diff options
author | Andrew Bartlett <abartlet@samba.org> | 2011-02-09 14:22:16 +1100 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2011-02-10 06:51:06 +0100 |
commit | d66150c14def46711a15a35b4734e8f438b6dad6 (patch) | |
tree | 78aa50274367fd6af3f9647fbded3f9305a91d7a /source4 | |
parent | 248c8217803341aa48626f5b68cc939d28aea5ab (diff) | |
download | samba-d66150c14def46711a15a35b4734e8f438b6dad6.tar.gz samba-d66150c14def46711a15a35b4734e8f438b6dad6.tar.xz samba-d66150c14def46711a15a35b4734e8f438b6dad6.zip |
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 <tridge@samba.org>
Diffstat (limited to 'source4')
-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 |
4 files changed, 177 insertions, 174 deletions
diff --git a/source4/auth/session.c b/source4/auth/session.c index a6b8b2688ce..cf5514cbf7f 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 d8c00a39a4d..795497ea8fe 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 19127a29bce..185e72cfb0f 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 148d4fdf80f..086a037b69d 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; } /* |