From d66150c14def46711a15a35b4734e8f438b6dad6 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 9 Feb 2011 14:22:16 +1100 Subject: libcli/named_pipe_auth Change from 'info3' to auth_session_info_transport This changes the structure being used to convey the current user state from the netlogon-derived 'netr_SamInfo3' structure to a purpose-built structure that matches the internals of the Samba auth subsystem and contains the final group list, as well as the final privilege set and session key. These previously had to be re-created on the server side of the pipe each time. Andrew Bartlett Signed-off-by: Andrew Tridgell --- libcli/named_pipe_auth/npa_tstream.c | 120 ++++++++++++---------------- libcli/named_pipe_auth/npa_tstream.h | 32 ++++---- librpc/idl/named_pipe_auth.idl | 17 ++-- librpc/wscript_build | 7 +- source3/Makefile.in | 3 +- source3/rpc_server/rpc_ncacn_np.c | 45 +++++++---- source3/rpc_server/rpc_server.c | 49 ++++++++++-- source4/auth/session.c | 147 +++++++++++++++++++++++++++++++++++ source4/auth/session.h | 10 +++ source4/ntvfs/ipc/vfs_ipc.c | 56 ++----------- 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 _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; } /* -- cgit