diff options
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 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; } /* |