diff options
-rw-r--r-- | libcli/named_pipe_auth/npa_tstream.c | 120 | ||||
-rw-r--r-- | libcli/named_pipe_auth/npa_tstream.h | 32 | ||||
-rw-r--r-- | librpc/idl/named_pipe_auth.idl | 17 | ||||
-rw-r--r-- | librpc/wscript_build | 7 | ||||
-rw-r--r-- | source3/Makefile.in | 3 | ||||
-rw-r--r-- | source3/rpc_server/rpc_ncacn_np.c | 45 | ||||
-rw-r--r-- | source3/rpc_server/rpc_server.c | 49 | ||||
-rw-r--r-- | source4/auth/session.c | 147 | ||||
-rw-r--r-- | source4/auth/session.h | 10 | ||||
-rw-r--r-- | source4/ntvfs/ipc/vfs_ipc.c | 56 | ||||
-rw-r--r-- | source4/smbd/service_named_pipe.c | 138 |
11 files changed, 323 insertions, 301 deletions
diff --git a/libcli/named_pipe_auth/npa_tstream.c b/libcli/named_pipe_auth/npa_tstream.c index ace90d6664..2aeea5b0d3 100644 --- a/libcli/named_pipe_auth/npa_tstream.c +++ b/libcli/named_pipe_auth/npa_tstream.c @@ -59,16 +59,14 @@ struct tstream_npa_connect_state { static void tstream_npa_connect_unix_done(struct tevent_req *subreq); struct tevent_req *tstream_npa_connect_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - const char *directory, - const char *npipe, - const struct tsocket_address *client, - const char *client_name_in, - const struct tsocket_address *server, - const char *server_name, - const struct netr_SamInfo3 *sam_info3, - DATA_BLOB session_key, - DATA_BLOB delegated_creds) + struct tevent_context *ev, + const char *directory, + const char *npipe, + const struct tsocket_address *client, + const char *client_name_in, + const struct tsocket_address *server, + const char *server_name, + const struct auth_session_info_transport *session_info) { struct tevent_req *req; struct tstream_npa_connect_state *state; @@ -76,7 +74,7 @@ struct tevent_req *tstream_npa_connect_send(TALLOC_CTX *mem_ctx, int ret; enum ndr_err_code ndr_err; char *lower_case_npipe; - struct named_pipe_auth_req_info3 *info3; + struct named_pipe_auth_req_info4 *info4; req = tevent_req_create(mem_ctx, &state, struct tstream_npa_connect_state); @@ -122,37 +120,33 @@ struct tevent_req *tstream_npa_connect_send(TALLOC_CTX *mem_ctx, goto post; } - state->auth_req.level = 3; - info3 = &state->auth_req.info.info3; + state->auth_req.level = 4; + info4 = &state->auth_req.info.info4; - info3->client_name = client_name_in; - info3->client_addr = tsocket_address_inet_addr_string(client, state); - if (!info3->client_addr) { + info4->client_name = client_name_in; + info4->client_addr = tsocket_address_inet_addr_string(client, state); + if (!info4->client_addr) { /* errno might be EINVAL */ tevent_req_error(req, errno); goto post; } - info3->client_port = tsocket_address_inet_port(client); - if (!info3->client_name) { - info3->client_name = info3->client_addr; + info4->client_port = tsocket_address_inet_port(client); + if (!info4->client_name) { + info4->client_name = info4->client_addr; } - info3->server_addr = tsocket_address_inet_addr_string(server, state); - if (!info3->server_addr) { + info4->server_addr = tsocket_address_inet_addr_string(server, state); + if (!info4->server_addr) { /* errno might be EINVAL */ tevent_req_error(req, errno); goto post; } - info3->server_port = tsocket_address_inet_port(server); - if (!info3->server_name) { - info3->server_name = info3->server_addr; + info4->server_port = tsocket_address_inet_port(server); + if (!info4->server_name) { + info4->server_name = info4->server_addr; } - info3->sam_info3 = discard_const_p(struct netr_SamInfo3, sam_info3); - info3->session_key_length = session_key.length; - info3->session_key = session_key.data; - info3->gssapi_delegated_creds_length = delegated_creds.length; - info3->gssapi_delegated_creds = delegated_creds.data; + info4->session_info = discard_const_p(struct auth_session_info_transport, session_info); if (DEBUGLVL(10)) { NDR_PRINT_DEBUG(named_pipe_auth_req, &state->auth_req); @@ -422,10 +416,10 @@ int _tstream_npa_connect_recv(struct tevent_req *req, npas->unix_stream = talloc_move(stream, &state->unix_stream); switch (state->auth_rep.level) { - case 3: - npas->file_type = state->auth_rep.info.info3.file_type; - device_state = state->auth_rep.info.info3.device_state; - allocation_size = state->auth_rep.info.info3.allocation_size; + case 4: + npas->file_type = state->auth_rep.info.info4.file_type; + device_state = state->auth_rep.info.info4.device_state; + allocation_size = state->auth_rep.info.info4.allocation_size; break; } @@ -1086,9 +1080,7 @@ struct tstream_npa_accept_state { char *client_name; struct tsocket_address *server; char *server_name; - struct netr_SamInfo3 *info3; - DATA_BLOB session_key; - DATA_BLOB delegated_creds; + struct auth_session_info_transport *session_info; }; static int tstream_npa_accept_next_vector(struct tstream_context *unix_stream, @@ -1238,7 +1230,7 @@ static void tstream_npa_accept_existing_reply(struct tevent_req *subreq) tevent_req_data(req, struct tstream_npa_accept_state); struct named_pipe_auth_req *pipe_request; struct named_pipe_auth_rep pipe_reply; - struct named_pipe_auth_req_info3 i3; + struct named_pipe_auth_req_info4 i4; enum ndr_err_code ndr_err; DATA_BLOB out; int sys_errno; @@ -1283,70 +1275,62 @@ static void tstream_npa_accept_existing_reply(struct tevent_req *subreq) NDR_PRINT_DEBUG(named_pipe_auth_req, pipe_request); } - ZERO_STRUCT(i3); + ZERO_STRUCT(i4); - if (pipe_request->level != 3) { + if (pipe_request->level != 4) { DEBUG(0, ("Unknown level %u\n", pipe_request->level)); pipe_reply.level = 0; pipe_reply.status = NT_STATUS_INVALID_LEVEL; goto reply; } - pipe_reply.level = 3; + pipe_reply.level = 4; pipe_reply.status = NT_STATUS_OK; - pipe_reply.info.info3.file_type = state->file_type; - pipe_reply.info.info3.device_state = state->device_state; - pipe_reply.info.info3.allocation_size = state->alloc_size; + pipe_reply.info.info4.file_type = state->file_type; + pipe_reply.info.info4.device_state = state->device_state; + pipe_reply.info.info4.allocation_size = state->alloc_size; - i3 = pipe_request->info.info3; - if (i3.server_addr == NULL) { + i4 = pipe_request->info.info4; + if (i4.server_addr == NULL) { pipe_reply.status = NT_STATUS_INVALID_ADDRESS; DEBUG(2, ("Missing server address\n")); goto reply; } - if (i3.client_addr == NULL) { + if (i4.client_addr == NULL) { pipe_reply.status = NT_STATUS_INVALID_ADDRESS; DEBUG(2, ("Missing client address\n")); goto reply; } state->server_name = discard_const_p(char, - talloc_move(state, &i3.server_name)); + talloc_move(state, &i4.server_name)); ret = tsocket_address_inet_from_strings(state, "ip", - i3.server_addr, - i3.server_port, + i4.server_addr, + i4.server_port, &state->server); if (ret != 0) { DEBUG(2, ("Invalid server address[%s:%u] - %s\n", - i3.server_addr, i3.server_port, + i4.server_addr, i4.server_port, strerror(errno))); pipe_reply.status = NT_STATUS_INVALID_ADDRESS; goto reply; } state->client_name = discard_const_p(char, - talloc_move(state, &i3.client_name)); + talloc_move(state, &i4.client_name)); ret = tsocket_address_inet_from_strings(state, "ip", - i3.client_addr, - i3.client_port, + i4.client_addr, + i4.client_port, &state->client); if (ret != 0) { DEBUG(2, ("Invalid server address[%s:%u] - %s\n", - i3.client_addr, i3.client_port, + i4.client_addr, i4.client_port, strerror(errno))); pipe_reply.status = NT_STATUS_INVALID_ADDRESS; goto reply; } - state->info3 = talloc_move(state, &i3.sam_info3); - state->session_key.data = talloc_move(state, &i3.session_key); - state->session_key.length = i3.session_key_length; - - state->delegated_creds.data = - talloc_move(state, &i3.gssapi_delegated_creds); - state->delegated_creds.length = - i3.gssapi_delegated_creds_length; - + state->session_info = talloc_move(state, &i4.session_info); reply: /* create the output */ ndr_err = ndr_push_struct_blob(&out, state, &pipe_reply, @@ -1406,9 +1390,7 @@ int _tstream_npa_accept_existing_recv(struct tevent_req *req, char **_client_name, struct tsocket_address **server, char **server_name, - struct netr_SamInfo3 **info3, - DATA_BLOB *session_key, - DATA_BLOB *delegated_creds, + struct auth_session_info_transport **session_info, const char *location) { struct tstream_npa_accept_state *state = @@ -1457,11 +1439,7 @@ int _tstream_npa_accept_existing_recv(struct tevent_req *req, *_client_name = talloc_move(mem_ctx, &state->client_name); *server = talloc_move(mem_ctx, &state->server); *server_name = talloc_move(mem_ctx, &state->server_name); - *info3 = talloc_move(mem_ctx, &state->info3); - *session_key = state->session_key; - talloc_steal(mem_ctx, state->session_key.data); - *delegated_creds = state->delegated_creds; - talloc_steal(mem_ctx, state->delegated_creds.data); + *session_info = talloc_move(mem_ctx, &state->session_info); tevent_req_received(req); return 0; diff --git a/libcli/named_pipe_auth/npa_tstream.h b/libcli/named_pipe_auth/npa_tstream.h index 63845bed6a..f2223170f0 100644 --- a/libcli/named_pipe_auth/npa_tstream.h +++ b/libcli/named_pipe_auth/npa_tstream.h @@ -22,19 +22,17 @@ struct tevent_req; struct tevent_context; -struct netr_SamInfo3; +struct auth_session_info_transport; struct tevent_req *tstream_npa_connect_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - const char *directory, - const char *npipe, - const struct tsocket_address *client, - const char *client_name_in, - const struct tsocket_address *server, - const char *server_name, - const struct netr_SamInfo3 *info3, - DATA_BLOB session_key, - DATA_BLOB delegated_creds); + struct tevent_context *ev, + const char *directory, + const char *npipe, + const struct tsocket_address *client, + const char *client_name_in, + const struct tsocket_address *server, + const char *server_name, + const struct auth_session_info_transport *session_info); int _tstream_npa_connect_recv(struct tevent_req *req, int *perrno, TALLOC_CTX *mem_ctx, @@ -101,25 +99,21 @@ int _tstream_npa_accept_existing_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, struct tstream_context **stream, struct tsocket_address **client, - char **client_name, + char **_client_name, struct tsocket_address **server, char **server_name, - struct netr_SamInfo3 **info3, - DATA_BLOB *session_key, - DATA_BLOB *delegated_creds, + struct auth_session_info_transport **session_info, const char *location); #define tstream_npa_accept_existing_recv(req, perrno, \ mem_ctx, stream, \ client, client_name, \ server, server_name, \ - info3, session_key, \ - delegated_creds) \ + session_info) \ _tstream_npa_accept_existing_recv(req, perrno, \ mem_ctx, stream, \ client, client_name, \ server, server_name, \ - info3, session_key, \ - delegated_creds, \ + session_info, \ __location__) #endif /* NPA_TSTREAM_H */ diff --git a/librpc/idl/named_pipe_auth.idl b/librpc/idl/named_pipe_auth.idl index de89588664..721667eef9 100644 --- a/librpc/idl/named_pipe_auth.idl +++ b/librpc/idl/named_pipe_auth.idl @@ -3,7 +3,7 @@ miscellaneous IDL structures */ -import "netlogon.idl"; +import "netlogon.idl", "security.idl", "auth.idl"; [ pointer_default(unique) @@ -19,16 +19,11 @@ interface named_pipe_auth [charset(UTF8),string] uint8 *server_name; [charset(DOS),string] uint8 *server_addr; uint16 server_port; - netr_SamInfo3 *sam_info3; - uint32 session_key_length; - [size_is(session_key_length)] uint8 *session_key; - uint32 gssapi_delegated_creds_length; - [size_is(gssapi_delegated_creds_length)] - uint8 *gssapi_delegated_creds; - } named_pipe_auth_req_info3; + auth_session_info_transport *session_info; + } named_pipe_auth_req_info4; typedef [switch_type(uint32)] union { - [case(3)] named_pipe_auth_req_info3 info3; + [case(4)] named_pipe_auth_req_info4 info4; } named_pipe_auth_req_info; typedef [public,gensize] struct { @@ -44,10 +39,10 @@ interface named_pipe_auth uint16 file_type; uint16 device_state; hyper allocation_size; - } named_pipe_auth_rep_info3; + } named_pipe_auth_rep_info4; typedef [switch_type(uint32)] union { - [case(3)] named_pipe_auth_rep_info3 info3; + [case(4)] named_pipe_auth_rep_info4 info4; } named_pipe_auth_rep_info; typedef [public,gensize] struct { diff --git a/librpc/wscript_build b/librpc/wscript_build index d15e8b225d..706977c45d 100644 --- a/librpc/wscript_build +++ b/librpc/wscript_build @@ -8,9 +8,14 @@ bld.SAMBA_SUBSYSTEM('NDR_AUDIOSRV', public_deps='ndr' ) +bld.SAMBA_SUBSYSTEM('NDR_AUTH', + source='gen_ndr/ndr_auth.c', + public_deps='ndr NDR_SECURITY' + ) + bld.SAMBA_SUBSYSTEM('NDR_NAMED_PIPE_AUTH', source='gen_ndr/ndr_named_pipe_auth.c', - public_deps='ndr' + public_deps='ndr NDR_AUTH' ) bld.SAMBA_SUBSYSTEM('NDR_DNSSERVER', diff --git a/source3/Makefile.in b/source3/Makefile.in index 15d854eb15..3012caa7d3 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -709,7 +709,8 @@ RPC_EVENTLOG_OBJ = rpc_server/srv_eventlog_nt.o \ $(LIB_EVENTLOG_OBJ) librpc/gen_ndr/srv_eventlog.o NPA_TSTREAM_OBJ = ../libcli/named_pipe_auth/npa_tstream.o \ - librpc/gen_ndr/ndr_named_pipe_auth.o + librpc/gen_ndr/ndr_named_pipe_auth.o \ + ../auth/auth_sam_reply.o librpc/gen_ndr/ndr_auth.o RPC_NCACN_NP = rpc_server/srv_pipe_register.o rpc_server/rpc_ncacn_np.o \ rpc_server/rpc_handles.o diff --git a/source3/rpc_server/rpc_ncacn_np.c b/source3/rpc_server/rpc_ncacn_np.c index af21ec2aad..c35fa847ad 100644 --- a/source3/rpc_server/rpc_ncacn_np.c +++ b/source3/rpc_server/rpc_ncacn_np.c @@ -26,6 +26,8 @@ #include "../libcli/named_pipe_auth/npa_tstream.h" #include "rpc_server/rpc_ncacn_np.h" #include "librpc/gen_ndr/netlogon.h" +#include "librpc/gen_ndr/auth.h" +#include "../auth/auth_sam_reply.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_SRV @@ -594,7 +596,9 @@ struct np_proxy_state *make_external_rpc_pipe_p(TALLOC_CTX *mem_ctx, const char *socket_dir; struct tevent_context *ev; struct tevent_req *subreq; - struct netr_SamInfo3 *info3; + struct auth_session_info_transport *session_info; + struct auth_user_info_dc *user_info_dc; + union netr_Validation val; NTSTATUS status; bool ok; int ret; @@ -637,20 +641,31 @@ struct np_proxy_state *make_external_rpc_pipe_p(TALLOC_CTX *mem_ctx, goto fail; } - info3 = talloc_zero(talloc_tos(), struct netr_SamInfo3); - if (info3 == NULL) { + session_info = talloc_zero(talloc_tos(), struct auth_session_info_transport); + if (session_info == NULL) { DEBUG(0, ("talloc failed\n")); goto fail; } - status = serverinfo_to_SamInfo3(server_info, NULL, 0, info3); + /* Send the named_pipe_auth server the user's full token */ + session_info->security_token = server_info->ptok; + session_info->session_key = server_info->user_session_key; + + val.sam3 = server_info->info3; + + /* Convert into something we can build a struct + * auth_session_info_transport from. Most of the work here + * will be to convert the SIDS, which we will then ignore, but + * this is the easier way to handle it */ + status = make_user_info_dc_netlogon_validation(talloc_tos(), "", 3, &val, &user_info_dc); if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(info3); - DEBUG(0, ("serverinfo_to_SamInfo3 failed: %s\n", - nt_errstr(status))); + DEBUG(0, ("conversion of info3 into user_info_dc failed!\n")); goto fail; } + session_info->info = talloc_move(session_info, &user_info_dc->info); + talloc_free(user_info_dc); + become_root(); subreq = tstream_npa_connect_send(talloc_tos(), ev, socket_np_dir, @@ -659,15 +674,13 @@ struct np_proxy_state *make_external_rpc_pipe_p(TALLOC_CTX *mem_ctx, NULL, /* client_name */ local_address, /* server_addr */ NULL, /* server_name */ - info3, - server_info->user_session_key, - data_blob_null /* delegated_creds */); + session_info); if (subreq == NULL) { unbecome_root(); DEBUG(0, ("tstream_npa_connect_send to %s for pipe %s and " "user %s\\%s failed\n", - socket_np_dir, pipe_name, info3->base.domain.string, - info3->base.account_name.string)); + socket_np_dir, pipe_name, session_info->info->domain_name, + session_info->info->account_name)); goto fail; } ok = tevent_req_poll(subreq, ev); @@ -675,8 +688,8 @@ struct np_proxy_state *make_external_rpc_pipe_p(TALLOC_CTX *mem_ctx, if (!ok) { DEBUG(0, ("tevent_req_poll to %s for pipe %s and user %s\\%s " "failed for tstream_npa_connect: %s\n", - socket_np_dir, pipe_name, info3->base.domain.string, - info3->base.account_name.string, + socket_np_dir, pipe_name, session_info->info->domain_name, + session_info->info->account_name, strerror(errno))); goto fail; @@ -691,8 +704,8 @@ struct np_proxy_state *make_external_rpc_pipe_p(TALLOC_CTX *mem_ctx, if (ret != 0) { DEBUG(0, ("tstream_npa_connect_recv to %s for pipe %s and " "user %s\\%s failed: %s\n", - socket_np_dir, pipe_name, info3->base.domain.string, - info3->base.account_name.string, + socket_np_dir, pipe_name, session_info->info->domain_name, + session_info->info->account_name, strerror(sys_errno))); goto fail; } diff --git a/source3/rpc_server/rpc_server.c b/source3/rpc_server/rpc_server.c index 229096e463..a0da354fd3 100644 --- a/source3/rpc_server/rpc_server.c +++ b/source3/rpc_server/rpc_server.c @@ -21,9 +21,11 @@ #include "rpc_server/rpc_server.h" #include "rpc_dce.h" #include "librpc/gen_ndr/netlogon.h" +#include "librpc/gen_ndr/auth.h" #include "registry/reg_parse_prs.h" #include "lib/tsocket/tsocket.h" #include "libcli/named_pipe_auth/npa_tstream.h" +#include "../auth/auth_sam_reply.h" /* Creates a pipes_struct and initializes it with the information * sent from the client */ @@ -31,10 +33,12 @@ static int make_server_pipes_struct(TALLOC_CTX *mem_ctx, const char *pipe_name, const struct ndr_syntax_id id, const char *client_address, - struct netr_SamInfo3 *info3, + struct auth_session_info_transport *session_info, struct pipes_struct **_p, int *perrno) { + struct netr_SamInfo3 *info3; + struct auth_user_info_dc *auth_user_info_dc; struct pipes_struct *p; NTSTATUS status; bool ok; @@ -67,6 +71,30 @@ static int make_server_pipes_struct(TALLOC_CTX *mem_ctx, p->endian = RPC_LITTLE_ENDIAN; + /* Fake up an auth_user_info_dc for now, to make an info3, to make the server_info structure */ + auth_user_info_dc = talloc_zero(p, struct auth_user_info_dc); + if (!auth_user_info_dc) { + TALLOC_FREE(p); + *perrno = ENOMEM; + return -1; + } + + auth_user_info_dc->num_sids = session_info->security_token->num_sids; + auth_user_info_dc->sids = session_info->security_token->sids; + auth_user_info_dc->info = session_info->info; + auth_user_info_dc->user_session_key = session_info->session_key; + + /* This creates the input structure that make_server_info_info3 is looking for */ + status = auth_convert_user_info_dc_saminfo3(p, auth_user_info_dc, + &info3); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("Failed to convert auth_user_info_dc into netr_SamInfo3\n")); + TALLOC_FREE(p); + *perrno = EINVAL; + return -1; + } + status = make_server_info_info3(p, info3->base.account_name.string, info3->base.domain.string, @@ -90,6 +118,15 @@ static int make_server_pipes_struct(TALLOC_CTX *mem_ctx, return -1; } + /* Now override the server_info->ptok with the exact + * security_token we were given from the other side, + * regardless of what we just calculated */ + p->server_info->ptok = talloc_move(p->server_info, &session_info->security_token); + + /* Also set the session key to the correct value */ + p->server_info->user_session_key = session_info->session_key; + p->server_info->user_session_key.data = talloc_move(p->server_info, &session_info->session_key.data); + p->client_id = talloc_zero(p, struct client_address); if (!p->client_id) { TALLOC_FREE(p); @@ -318,9 +355,7 @@ struct named_pipe_client { char *client_name; struct tsocket_address *server; char *server_name; - struct netr_SamInfo3 *info3; - DATA_BLOB session_key; - DATA_BLOB delegated_creds; + struct auth_session_info_transport *session_info; struct pipes_struct *p; @@ -410,9 +445,7 @@ static void named_pipe_accept_done(struct tevent_req *subreq) &npc->client_name, &npc->server, &npc->server_name, - &npc->info3, - &npc->session_key, - &npc->delegated_creds); + &npc->session_info); TALLOC_FREE(subreq); if (ret != 0) { DEBUG(2, ("Failed to accept named pipe connection! (%s)\n", @@ -434,7 +467,7 @@ static void named_pipe_accept_done(struct tevent_req *subreq) ret = make_server_pipes_struct(npc, npc->pipe_name, npc->pipe_id, - cli_addr, npc->info3, + cli_addr, npc->session_info, &npc->p, &error); if (ret != 0) { DEBUG(2, ("Failed to create pipes_struct! (%s)\n", diff --git a/source4/auth/session.c b/source4/auth/session.c index a6b8b2688c..cf5514cbf7 100644 --- a/source4/auth/session.c +++ b/source4/auth/session.c @@ -24,10 +24,14 @@ #include "includes.h" #include "auth/auth.h" #include "auth/auth_sam.h" +#include "auth/credentials/credentials.h" +#include "auth/credentials/credentials_krb5.h" #include "libcli/security/security.h" #include "libcli/auth/libcli_auth.h" #include "dsdb/samdb/samdb.h" #include "auth/session_proto.h" +#include "system/kerberos.h" +#include <gssapi/gssapi.h> _PUBLIC_ struct auth_session_info *anonymous_session(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx) @@ -151,6 +155,149 @@ _PUBLIC_ NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } +/* Create a session_info structure from the + * auth_session_info_transport we were forwarded over named pipe + * forwarding. + * + * NOTE: The stucture members of session_info_transport are stolen + * with talloc_move() into auth_session_info for long term use + */ +struct auth_session_info *auth_session_info_from_transport(TALLOC_CTX *mem_ctx, + struct auth_session_info_transport *session_info_transport, + struct loadparm_context *lp_ctx, + const char **reason) +{ + struct auth_session_info *session_info; + session_info = talloc_zero(mem_ctx, struct auth_session_info); + if (!session_info) { + *reason = "failed to allocate session_info"; + return NULL; + } + + session_info->security_token = talloc_move(session_info, &session_info_transport->security_token); + session_info->info = talloc_move(session_info, &session_info_transport->info); + session_info->session_key = session_info_transport->session_key; + session_info->session_key.data = talloc_move(session_info, &session_info_transport->session_key.data); + + if (session_info_transport->exported_gssapi_credentials.length) { + struct cli_credentials *creds; + OM_uint32 minor_status; + gss_buffer_desc cred_token; + gss_cred_id_t cred_handle; + const char *error_string; + int ret; + + DEBUG(10, ("Delegated credentials supplied by client\n")); + + cred_token.value = session_info_transport->exported_gssapi_credentials.data; + cred_token.length = session_info_transport->exported_gssapi_credentials.length; + + ret = gss_import_cred(&minor_status, + &cred_token, + &cred_handle); + if (ret != GSS_S_COMPLETE) { + *reason = "Internal error in gss_import_cred()"; + return NULL; + } + + creds = cli_credentials_init(session_info); + if (!creds) { + *reason = "Out of memory in cli_credentials_init()"; + return NULL; + } + session_info->credentials = creds; + + cli_credentials_set_conf(creds, lp_ctx); + /* Just so we don't segfault trying to get at a username */ + cli_credentials_set_anonymous(creds); + + ret = cli_credentials_set_client_gss_creds(creds, + lp_ctx, + cred_handle, + CRED_SPECIFIED, + &error_string); + if (ret) { + *reason = talloc_asprintf(mem_ctx, + "Failed to set pipe forwarded" + "creds: %s\n", error_string); + return NULL; + } + + /* This credential handle isn't useful for password + * authentication, so ensure nobody tries to do that */ + cli_credentials_set_kerberos_state(creds, + CRED_MUST_USE_KERBEROS); + + } + + return session_info; +} + + +/* Create a auth_session_info_transport from an auth_session_info. + * + * NOTE: Members of the auth_session_info_transport structure are not talloc_referenced, but simply assigned. They are only valid for the lifetime of the struct auth_session_info + * + * This isn't normally an issue, as the auth_session_info has a very long typical life + */ +NTSTATUS auth_session_info_transport_from_session(TALLOC_CTX *mem_ctx, + struct auth_session_info *session_info, + struct tevent_context *event_ctx, + struct loadparm_context *lp_ctx, + struct auth_session_info_transport **transport_out) +{ + + struct auth_session_info_transport *session_info_transport = talloc_zero(mem_ctx, struct auth_session_info_transport); + session_info_transport->security_token = talloc_reference(session_info, session_info->security_token); + NT_STATUS_HAVE_NO_MEMORY(session_info_transport->security_token); + + session_info_transport->info = talloc_reference(session_info, session_info->info); + NT_STATUS_HAVE_NO_MEMORY(session_info_transport->info); + + session_info_transport->session_key = session_info->session_key; + session_info_transport->session_key.data = talloc_reference(session_info, session_info->session_key.data); + if (!session_info_transport->session_key.data && session_info->session_key.length) { + return NT_STATUS_NO_MEMORY; + } + + if (session_info->credentials) { + struct gssapi_creds_container *gcc; + OM_uint32 gret; + OM_uint32 minor_status; + gss_buffer_desc cred_token; + const char *error_string; + int ret; + + ret = cli_credentials_get_client_gss_creds(session_info->credentials, + event_ctx, + lp_ctx, + &gcc, &error_string); + if (ret != 0) { + *transport_out = session_info_transport; + return NT_STATUS_OK; + } + + gret = gss_export_cred(&minor_status, + gcc->creds, + &cred_token); + if (gret != GSS_S_COMPLETE) { + return NT_STATUS_INTERNAL_ERROR; + } + + if (cred_token.length) { + session_info_transport->exported_gssapi_credentials + = data_blob_talloc(session_info_transport, + cred_token.value, + cred_token.length); + gss_release_buffer(&minor_status, &cred_token); + NT_STATUS_HAVE_NO_MEMORY(session_info_transport->exported_gssapi_credentials.data); + } + } + *transport_out = session_info_transport; + return NT_STATUS_OK; +} + + /* Produce a session_info for an arbitary DN or principal in the local * DB, assuming the local DB holds all the groups * diff --git a/source4/auth/session.h b/source4/auth/session.h index d8c00a39a4..795497ea8f 100644 --- a/source4/auth/session.h +++ b/source4/auth/session.h @@ -52,6 +52,16 @@ NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx, NTSTATUS auth_anonymous_session_info(TALLOC_CTX *parent_ctx, struct loadparm_context *lp_ctx, struct auth_session_info **session_info); +struct auth_session_info *auth_session_info_from_transport(TALLOC_CTX *mem_ctx, + struct auth_session_info_transport *session_info_transport, + struct loadparm_context *lp_ctx, + const char **reason); +NTSTATUS auth_session_info_transport_from_session(TALLOC_CTX *mem_ctx, + struct auth_session_info *session_info, + struct tevent_context *event_ctx, + struct loadparm_context *lp_ctx, + struct auth_session_info_transport **transport_out); + /* Produce a session_info for an arbitary DN or principal in the local * DB, assuming the local DB holds all the groups * diff --git a/source4/ntvfs/ipc/vfs_ipc.c b/source4/ntvfs/ipc/vfs_ipc.c index 19127a29bc..185e72cfb0 100644 --- a/source4/ntvfs/ipc/vfs_ipc.c +++ b/source4/ntvfs/ipc/vfs_ipc.c @@ -217,7 +217,7 @@ struct ipc_open_state { struct pipe_state *p; struct ntvfs_request *req; union smb_open *oi; - struct netr_SamInfo3 *info3; + struct auth_session_info_transport *session_info_transport; }; static void ipc_open_done(struct tevent_req *subreq); @@ -253,9 +253,6 @@ static NTSTATUS ipc_open(struct ntvfs_module_context *ntvfs, const char *directory; const struct tsocket_address *client_addr; const struct tsocket_address *server_addr; - int ret; - DATA_BLOB delegated_creds = data_blob_null; - struct auth_user_info_dc user_info_dc; switch (oi->generic.level) { case RAW_OPEN_NTCREATEX: @@ -310,54 +307,17 @@ static NTSTATUS ipc_open(struct ntvfs_module_context *ntvfs, state->req = req; state->oi = oi; - /* Disgusting hack to recreate the user_info_dc that should - * not be used that this layer in this way */ - ZERO_STRUCT(user_info_dc); - user_info_dc.info = req->session_info->info; - user_info_dc.num_sids = req->session_info->torture->num_dc_sids; - user_info_dc.sids = req->session_info->torture->dc_sids; + status = auth_session_info_transport_from_session(state, + req->session_info, + ipriv->ntvfs->ctx->event_ctx, + ipriv->ntvfs->ctx->lp_ctx, + &state->session_info_transport); - status = auth_convert_user_info_dc_saminfo3(state, - &user_info_dc, - &state->info3); NT_STATUS_NOT_OK_RETURN(status); client_addr = ntvfs_get_local_address(ipriv->ntvfs); server_addr = ntvfs_get_remote_address(ipriv->ntvfs); - if (req->session_info->credentials) { - struct gssapi_creds_container *gcc; - OM_uint32 gret; - OM_uint32 minor_status; - gss_buffer_desc cred_token; - const char *error_string; - - ret = cli_credentials_get_client_gss_creds(req->session_info->credentials, - ipriv->ntvfs->ctx->event_ctx, - ipriv->ntvfs->ctx->lp_ctx, - &gcc, &error_string); - if (ret) { - goto skip; - } - - gret = gss_export_cred(&minor_status, - gcc->creds, - &cred_token); - if (gret != GSS_S_COMPLETE) { - return NT_STATUS_INTERNAL_ERROR; - } - - if (cred_token.length) { - delegated_creds = data_blob_talloc(req, - cred_token.value, - cred_token.length); - gss_release_buffer(&minor_status, &cred_token); - NT_STATUS_HAVE_NO_MEMORY(delegated_creds.data); - } - } - -skip: - subreq = tstream_npa_connect_send(p, ipriv->ntvfs->ctx->event_ctx, directory, @@ -366,9 +326,7 @@ skip: NULL, server_addr, NULL, - state->info3, - req->session_info->session_key, - delegated_creds); + state->session_info_transport); NT_STATUS_HAVE_NO_MEMORY(subreq); tevent_req_set_callback(subreq, ipc_open_done, state); diff --git a/source4/smbd/service_named_pipe.c b/source4/smbd/service_named_pipe.c index 148d4fdf80..086a037b69 100644 --- a/source4/smbd/service_named_pipe.c +++ b/source4/smbd/service_named_pipe.c @@ -33,8 +33,7 @@ #include "system/passwd.h" #include "system/network.h" #include "libcli/raw/smb.h" -#include "auth/credentials/credentials.h" -#include "auth/credentials/credentials_krb5.h" +#include "auth/session.h" #include "libcli/security/security.h" #include "libcli/named_pipe_auth/npa_tstream.h" @@ -93,18 +92,9 @@ static void named_pipe_accept_done(struct tevent_req *subreq) char *client_name; struct tsocket_address *server; char *server_name; - struct netr_SamInfo3 *info3; - DATA_BLOB session_key; - DATA_BLOB delegated_creds; - - union netr_Validation val; - struct auth_user_info_dc *user_info_dc; - struct auth_context *auth_context; - uint32_t session_flags = 0; - struct dom_sid *anonymous_sid; + struct auth_session_info_transport *session_info_transport; const char *reason = NULL; TALLOC_CTX *tmp_ctx; - NTSTATUS status; int error; int ret; @@ -115,14 +105,12 @@ static void named_pipe_accept_done(struct tevent_req *subreq) } ret = tstream_npa_accept_existing_recv(subreq, &error, tmp_ctx, - &conn->tstream, - &client, - &client_name, - &server, - &server_name, - &info3, - &session_key, - &delegated_creds); + &conn->tstream, + &client, + &client_name, + &server, + &server_name, + &session_info_transport); TALLOC_FREE(subreq); if (ret != 0) { reason = talloc_asprintf(conn, @@ -137,111 +125,11 @@ static void named_pipe_accept_done(struct tevent_req *subreq) client_name, tsocket_address_string(client, tmp_ctx), server_name, tsocket_address_string(server, tmp_ctx))); - if (info3) { - val.sam3 = info3; - - status = make_user_info_dc_netlogon_validation(conn, - val.sam3->base.account_name.string, - 3, &val, &user_info_dc); - if (!NT_STATUS_IS_OK(status)) { - reason = talloc_asprintf(conn, - "make_user_info_dc_netlogon_validation " - "returned: %s", nt_errstr(status)); - goto out; - } - - status = auth_context_create(conn, conn->event.ctx, - conn->msg_ctx, conn->lp_ctx, - &auth_context); - if (!NT_STATUS_IS_OK(status)) { - reason = talloc_asprintf(conn, - "auth_context_create returned: %s", - nt_errstr(status)); - goto out; - } - - anonymous_sid = dom_sid_parse_talloc(auth_context, - SID_NT_ANONYMOUS); - if (anonymous_sid == NULL) { - talloc_free(auth_context); - reason = "Failed to parse Anonymous SID "; - goto out; - } - - session_flags = AUTH_SESSION_INFO_DEFAULT_GROUPS; - if (user_info_dc->num_sids > 1 && !dom_sid_equal(anonymous_sid, &user_info_dc->sids[0])) { - session_flags |= AUTH_SESSION_INFO_AUTHENTICATED; - } - - - /* setup the session_info on the connection */ - status = auth_context->generate_session_info(conn, - auth_context, - user_info_dc, - session_flags, - &conn->session_info); - talloc_free(auth_context); - if (!NT_STATUS_IS_OK(status)) { - reason = talloc_asprintf(conn, - "auth_generate_session_info " - "returned: %s", nt_errstr(status)); - goto out; - } - } - - if (session_key.length) { - conn->session_info->session_key = session_key; - talloc_steal(conn->session_info, session_key.data); - } - - if (delegated_creds.length) { - struct cli_credentials *creds; - OM_uint32 minor_status; - gss_buffer_desc cred_token; - gss_cred_id_t cred_handle; - const char *error_string; - - DEBUG(10, ("Delegated credentials supplied by client\n")); - - cred_token.value = delegated_creds.data; - cred_token.length = delegated_creds.length; - - ret = gss_import_cred(&minor_status, - &cred_token, - &cred_handle); - if (ret != GSS_S_COMPLETE) { - reason = "Internal error in gss_import_cred()"; - goto out; - } - - creds = cli_credentials_init(conn->session_info); - if (!creds) { - reason = "Out of memory in cli_credentials_init()"; - goto out; - } - conn->session_info->credentials = creds; - - cli_credentials_set_conf(creds, conn->lp_ctx); - /* Just so we don't segfault trying to get at a username */ - cli_credentials_set_anonymous(creds); - - ret = cli_credentials_set_client_gss_creds(creds, - conn->lp_ctx, - cred_handle, - CRED_SPECIFIED, - &error_string); - if (ret) { - reason = talloc_asprintf(conn, - "Failed to set pipe forwarded" - "creds: %s\n", error_string); - goto out; - } - - /* This credential handle isn't useful for password - * authentication, so ensure nobody tries to do that */ - cli_credentials_set_kerberos_state(creds, - CRED_MUST_USE_KERBEROS); - + conn->session_info = auth_session_info_from_transport(conn, session_info_transport, + conn->lp_ctx, + &reason); + if (!conn->session_info) { + goto out; } /* |