diff options
Diffstat (limited to 'source3/auth/auth_ntlmssp.c')
-rw-r--r-- | source3/auth/auth_ntlmssp.c | 311 |
1 files changed, 227 insertions, 84 deletions
diff --git a/source3/auth/auth_ntlmssp.c b/source3/auth/auth_ntlmssp.c index b4bc9f9c15c..9f29ce28015 100644 --- a/source3/auth/auth_ntlmssp.c +++ b/source3/auth/auth_ntlmssp.c @@ -25,34 +25,63 @@ #include "../auth/ntlmssp/ntlmssp.h" #include "ntlmssp_wrap.h" #include "../librpc/gen_ndr/netlogon.h" +#include "../librpc/gen_ndr/dcerpc.h" #include "../lib/tsocket/tsocket.h" #include "auth/gensec/gensec.h" #include "librpc/rpc/dcerpc.h" +#include "lib/param/param.h" NTSTATUS auth_ntlmssp_session_info(TALLOC_CTX *mem_ctx, struct auth_ntlmssp_state *auth_ntlmssp_state, struct auth_session_info **session_info) { NTSTATUS nt_status; - if (auth_ntlmssp_state->gensec_security) { + nt_status = gensec_session_info(auth_ntlmssp_state->gensec_security, + mem_ctx, + session_info); + return nt_status; +} - nt_status = gensec_session_info(auth_ntlmssp_state->gensec_security, - mem_ctx, - session_info); - return nt_status; - } +static NTSTATUS gensec_ntlmssp3_server_session_info(struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx, + struct auth_session_info **session_info) +{ + struct gensec_ntlmssp_context *gensec_ntlmssp = + talloc_get_type_abort(gensec_security->private_data, + struct gensec_ntlmssp_context); + NTSTATUS nt_status; nt_status = create_local_token(mem_ctx, - auth_ntlmssp_state->server_info, - &auth_ntlmssp_state->ntlmssp_state->session_key, - auth_ntlmssp_state->ntlmssp_state->user, + gensec_ntlmssp->server_info, + &gensec_ntlmssp->ntlmssp_state->session_key, + gensec_ntlmssp->ntlmssp_state->user, session_info); - if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(10, ("create_local_token failed: %s\n", nt_errstr(nt_status))); + return nt_status; } - return nt_status; + + return NT_STATUS_OK; +} + +static NTSTATUS gensec_ntlmssp3_server_update(struct gensec_security *gensec_security, + TALLOC_CTX *out_mem_ctx, + const DATA_BLOB request, + DATA_BLOB *reply) +{ + NTSTATUS status; + struct gensec_ntlmssp_context *gensec_ntlmssp = + talloc_get_type_abort(gensec_security->private_data, + struct gensec_ntlmssp_context); + + status = ntlmssp_update(gensec_ntlmssp->ntlmssp_state, request, reply); + if (NT_STATUS_IS_OK(status) || + NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + talloc_steal(out_mem_ctx, reply->data); + } + + return status; } /** @@ -63,10 +92,10 @@ NTSTATUS auth_ntlmssp_session_info(TALLOC_CTX *mem_ctx, static NTSTATUS auth_ntlmssp_get_challenge(const struct ntlmssp_state *ntlmssp_state, uint8_t chal[8]) { - struct auth_ntlmssp_state *auth_ntlmssp_state = - (struct auth_ntlmssp_state *)ntlmssp_state->callback_private; - auth_ntlmssp_state->auth_context->get_ntlm_challenge( - auth_ntlmssp_state->auth_context, chal); + struct gensec_ntlmssp_context *gensec_ntlmssp = + (struct gensec_ntlmssp_context *)ntlmssp_state->callback_private; + gensec_ntlmssp->auth_context->get_ntlm_challenge( + gensec_ntlmssp->auth_context, chal); return NT_STATUS_OK; } @@ -77,9 +106,9 @@ static NTSTATUS auth_ntlmssp_get_challenge(const struct ntlmssp_state *ntlmssp_s */ static bool auth_ntlmssp_may_set_challenge(const struct ntlmssp_state *ntlmssp_state) { - struct auth_ntlmssp_state *auth_ntlmssp_state = - (struct auth_ntlmssp_state *)ntlmssp_state->callback_private; - struct auth_context *auth_context = auth_ntlmssp_state->auth_context; + struct gensec_ntlmssp_context *gensec_ntlmssp = + (struct gensec_ntlmssp_context *)ntlmssp_state->callback_private; + struct auth_context *auth_context = gensec_ntlmssp->auth_context; return auth_context->challenge_may_be_modified; } @@ -90,9 +119,9 @@ static bool auth_ntlmssp_may_set_challenge(const struct ntlmssp_state *ntlmssp_s */ static NTSTATUS auth_ntlmssp_set_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *challenge) { - struct auth_ntlmssp_state *auth_ntlmssp_state = - (struct auth_ntlmssp_state *)ntlmssp_state->callback_private; - struct auth_context *auth_context = auth_ntlmssp_state->auth_context; + struct gensec_ntlmssp_context *gensec_ntlmssp = + (struct gensec_ntlmssp_context *)ntlmssp_state->callback_private; + struct auth_context *auth_context = gensec_ntlmssp->auth_context; SMB_ASSERT(challenge->length == 8); @@ -116,8 +145,8 @@ static NTSTATUS auth_ntlmssp_set_challenge(struct ntlmssp_state *ntlmssp_state, static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, TALLOC_CTX *mem_ctx, DATA_BLOB *session_key, DATA_BLOB *lm_session_key) { - struct auth_ntlmssp_state *auth_ntlmssp_state = - (struct auth_ntlmssp_state *)ntlmssp_state->callback_private; + struct gensec_ntlmssp_context *gensec_ntlmssp = + (struct gensec_ntlmssp_context *)ntlmssp_state->callback_private; struct auth_usersupplied_info *user_info = NULL; NTSTATUS nt_status; bool username_was_mapped; @@ -125,21 +154,21 @@ static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, /* the client has given us its machine name (which we otherwise would not get on port 445). we need to possibly reload smb.conf if smb.conf includes depend on the machine name */ - set_remote_machine_name(auth_ntlmssp_state->ntlmssp_state->client.netbios_name, True); + set_remote_machine_name(gensec_ntlmssp->ntlmssp_state->client.netbios_name, True); /* setup the string used by %U */ /* sub_set_smb_name checks for weird internally */ - sub_set_smb_name(auth_ntlmssp_state->ntlmssp_state->user); + sub_set_smb_name(gensec_ntlmssp->ntlmssp_state->user); lp_load(get_dyn_CONFIGFILE(), false, false, true, true); nt_status = make_user_info_map(&user_info, - auth_ntlmssp_state->ntlmssp_state->user, - auth_ntlmssp_state->ntlmssp_state->domain, - auth_ntlmssp_state->ntlmssp_state->client.netbios_name, - auth_ntlmssp_state->remote_address, - auth_ntlmssp_state->ntlmssp_state->lm_resp.data ? &auth_ntlmssp_state->ntlmssp_state->lm_resp : NULL, - auth_ntlmssp_state->ntlmssp_state->nt_resp.data ? &auth_ntlmssp_state->ntlmssp_state->nt_resp : NULL, + gensec_ntlmssp->ntlmssp_state->user, + gensec_ntlmssp->ntlmssp_state->domain, + gensec_ntlmssp->ntlmssp_state->client.netbios_name, + gensec_get_remote_address(gensec_ntlmssp->gensec_security), + gensec_ntlmssp->ntlmssp_state->lm_resp.data ? &gensec_ntlmssp->ntlmssp_state->lm_resp : NULL, + gensec_ntlmssp->ntlmssp_state->nt_resp.data ? &gensec_ntlmssp->ntlmssp_state->nt_resp : NULL, NULL, NULL, NULL, AUTH_PASSWORD_RESPONSE); @@ -149,8 +178,8 @@ static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, user_info->logon_parameters = MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT | MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT; - nt_status = auth_ntlmssp_state->auth_context->check_ntlm_password(auth_ntlmssp_state->auth_context, - user_info, &auth_ntlmssp_state->server_info); + nt_status = gensec_ntlmssp->auth_context->check_ntlm_password(gensec_ntlmssp->auth_context, + user_info, &gensec_ntlmssp->server_info); username_was_mapped = user_info->was_mapped; @@ -158,36 +187,35 @@ static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, if (!NT_STATUS_IS_OK(nt_status)) { nt_status = do_map_to_guest_server_info(nt_status, - &auth_ntlmssp_state->server_info, - auth_ntlmssp_state->ntlmssp_state->user, - auth_ntlmssp_state->ntlmssp_state->domain); + &gensec_ntlmssp->server_info, + gensec_ntlmssp->ntlmssp_state->user, + gensec_ntlmssp->ntlmssp_state->domain); + return nt_status; } if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } - talloc_steal(auth_ntlmssp_state, auth_ntlmssp_state->server_info); - - auth_ntlmssp_state->server_info->nss_token |= username_was_mapped; + gensec_ntlmssp->server_info->nss_token |= username_was_mapped; /* Clear out the session keys, and pass them to the caller. * They will not be used in this form again - instead the * NTLMSSP code will decide on the final correct session key, * and supply it to create_local_token() */ - if (auth_ntlmssp_state->server_info->session_key.length) { + if (gensec_ntlmssp->server_info->session_key.length) { DEBUG(10, ("Got NT session key of length %u\n", - (unsigned int)auth_ntlmssp_state->server_info->session_key.length)); - *session_key = auth_ntlmssp_state->server_info->session_key; - talloc_steal(mem_ctx, auth_ntlmssp_state->server_info->session_key.data); - auth_ntlmssp_state->server_info->session_key = data_blob_null; + (unsigned int)gensec_ntlmssp->server_info->session_key.length)); + *session_key = gensec_ntlmssp->server_info->session_key; + talloc_steal(mem_ctx, gensec_ntlmssp->server_info->session_key.data); + gensec_ntlmssp->server_info->session_key = data_blob_null; } - if (auth_ntlmssp_state->server_info->lm_session_key.length) { + if (gensec_ntlmssp->server_info->lm_session_key.length) { DEBUG(10, ("Got LM session key of length %u\n", - (unsigned int)auth_ntlmssp_state->server_info->lm_session_key.length)); - *lm_session_key = auth_ntlmssp_state->server_info->lm_session_key; - talloc_steal(mem_ctx, auth_ntlmssp_state->server_info->lm_session_key.data); - auth_ntlmssp_state->server_info->lm_session_key = data_blob_null; + (unsigned int)gensec_ntlmssp->server_info->lm_session_key.length)); + *lm_session_key = gensec_ntlmssp->server_info->lm_session_key; + talloc_steal(mem_ctx, gensec_ntlmssp->server_info->lm_session_key.data); + gensec_ntlmssp->server_info->lm_session_key = data_blob_null; } return nt_status; } @@ -195,14 +223,9 @@ static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, NTSTATUS auth_ntlmssp_prepare(const struct tsocket_address *remote_address, struct auth_ntlmssp_state **auth_ntlmssp_state) { - NTSTATUS nt_status; - bool is_standalone; - const char *netbios_name; - const char *netbios_domain; - const char *dns_name; - char *dns_domain; - struct auth_ntlmssp_state *ans; struct auth_context *auth_context; + struct auth_ntlmssp_state *ans; + NTSTATUS nt_status; ans = talloc_zero(NULL, struct auth_ntlmssp_state); if (!ans) { @@ -219,15 +242,64 @@ NTSTATUS auth_ntlmssp_prepare(const struct tsocket_address *remote_address, ans->auth_context = talloc_steal(ans, auth_context); if (auth_context->prepare_gensec) { - nt_status = auth_context->prepare_gensec(ans, &ans->gensec_security); + nt_status = auth_context->prepare_gensec(ans, + &ans->gensec_security); if (!NT_STATUS_IS_OK(nt_status)) { TALLOC_FREE(ans); return nt_status; } *auth_ntlmssp_state = ans; return NT_STATUS_OK; + } else { + struct gensec_settings *gensec_settings; + struct loadparm_context *lp_ctx; + + lp_ctx = loadparm_init_s3(ans, loadparm_s3_context()); + if (lp_ctx == NULL) { + DEBUG(10, ("loadparm_init_s3 failed\n")); + TALLOC_FREE(ans); + return NT_STATUS_INVALID_SERVER_STATE; + } + + gensec_settings = lpcfg_gensec_settings(ans, lp_ctx); + if (lp_ctx == NULL) { + DEBUG(10, ("lpcfg_gensec_settings failed\n")); + TALLOC_FREE(ans); + return NT_STATUS_NO_MEMORY; + } + + nt_status = gensec_server_start(ans, NULL, gensec_settings, + NULL, &ans->gensec_security); + + if (!NT_STATUS_IS_OK(nt_status)) { + TALLOC_FREE(ans); + return nt_status; + } + talloc_unlink(ans, lp_ctx); + talloc_unlink(ans, gensec_settings); } + nt_status = gensec_set_remote_address(ans->gensec_security, + remote_address); + if (!NT_STATUS_IS_OK(nt_status)) { + TALLOC_FREE(ans); + return nt_status; + } + + *auth_ntlmssp_state = ans; + return NT_STATUS_OK; +} + +static NTSTATUS gensec_ntlmssp3_server_start(struct gensec_security *gensec_security) +{ + NTSTATUS nt_status; + bool is_standalone; + const char *netbios_name; + const char *netbios_domain; + const char *dns_name; + char *dns_domain; + struct gensec_ntlmssp_context *gensec_ntlmssp; + if ((enum server_role)lp_server_role() == ROLE_STANDALONE) { is_standalone = true; } else { @@ -243,59 +315,111 @@ NTSTATUS auth_ntlmssp_prepare(const struct tsocket_address *remote_address, } dns_name = get_mydnsfullname(); - ans->remote_address = tsocket_address_copy(remote_address, ans); - if (ans->remote_address == NULL) { - DEBUG(0,("auth_ntlmssp_start: talloc failed!\n")); - return NT_STATUS_NO_MEMORY; - } + nt_status = gensec_ntlmssp_start(gensec_security); + NT_STATUS_NOT_OK_RETURN(nt_status); + + gensec_ntlmssp = + talloc_get_type_abort(gensec_security->private_data, + struct gensec_ntlmssp_context); - nt_status = ntlmssp_server_start(ans, + nt_status = ntlmssp_server_start(gensec_ntlmssp, is_standalone, netbios_name, netbios_domain, dns_name, dns_domain, - &ans->ntlmssp_state); + &gensec_ntlmssp->ntlmssp_state); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } - ans->ntlmssp_state->callback_private = ans; - ans->ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge; - ans->ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge; - ans->ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge; - ans->ntlmssp_state->check_password = auth_ntlmssp_check_password; + gensec_ntlmssp->ntlmssp_state->callback_private = gensec_ntlmssp; + + gensec_ntlmssp->ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge; + gensec_ntlmssp->ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge; + gensec_ntlmssp->ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge; + gensec_ntlmssp->ntlmssp_state->check_password = auth_ntlmssp_check_password; + + if (gensec_ntlmssp->gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) { + gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; + } + if (gensec_ntlmssp->gensec_security->want_features & GENSEC_FEATURE_SIGN) { + gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; + } + if (gensec_ntlmssp->gensec_security->want_features & GENSEC_FEATURE_SEAL) { + gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; + gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL; + } - *auth_ntlmssp_state = ans; return NT_STATUS_OK; } +static const char *gensec_ntlmssp3_server_oids[] = { + GENSEC_OID_NTLMSSP, + NULL +}; + +static const struct gensec_security_ops gensec_ntlmssp3_server_ops = { + .name = "ntlmssp3_server", + .sasl_name = GENSEC_SASL_NAME_NTLMSSP, /* "NTLM" */ + .auth_type = DCERPC_AUTH_TYPE_NTLMSSP, + .oid = gensec_ntlmssp3_server_oids, + .server_start = gensec_ntlmssp3_server_start, + .magic = gensec_ntlmssp_magic, + .update = gensec_ntlmssp3_server_update, + .sig_size = gensec_ntlmssp_sig_size, + .sign_packet = gensec_ntlmssp_sign_packet, + .check_packet = gensec_ntlmssp_check_packet, + .seal_packet = gensec_ntlmssp_seal_packet, + .unseal_packet = gensec_ntlmssp_unseal_packet, + .wrap = gensec_ntlmssp_wrap, + .unwrap = gensec_ntlmssp_unwrap, + .session_key = gensec_ntlmssp_session_key, + .session_info = gensec_ntlmssp3_server_session_info, + .have_feature = gensec_ntlmssp_have_feature, + .enabled = true, + .priority = GENSEC_NTLMSSP +}; + NTSTATUS auth_generic_start(struct auth_ntlmssp_state *auth_ntlmssp_state, const char *oid) { + struct gensec_ntlmssp_context *gensec_ntlmssp; + NTSTATUS status; + if (auth_ntlmssp_state->auth_context->gensec_start_mech_by_oid) { - return auth_ntlmssp_state->auth_context->gensec_start_mech_by_oid(auth_ntlmssp_state->gensec_security, oid); + return auth_ntlmssp_state->auth_context->gensec_start_mech_by_oid( + auth_ntlmssp_state->gensec_security, oid); } if (strcmp(oid, GENSEC_OID_NTLMSSP) != 0) { - /* The caller will then free the auth_ntlmssp_state, - * undoing what was done in auth_ntlmssp_prepare(). - * - * We can't do that logic here, as - * auth_ntlmssp_want_feature() may have been called in - * between. - */ return NT_STATUS_NOT_IMPLEMENTED; } + status = gensec_start_mech_by_ops(auth_ntlmssp_state->gensec_security, + &gensec_ntlmssp3_server_ops); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + gensec_ntlmssp = + talloc_get_type_abort(auth_ntlmssp_state->gensec_security->private_data, + struct gensec_ntlmssp_context); + + gensec_ntlmssp->auth_context = auth_ntlmssp_state->auth_context; + return NT_STATUS_OK; } -NTSTATUS auth_generic_authtype_start(struct auth_ntlmssp_state *auth_ntlmssp_state, +NTSTATUS auth_generic_authtype_start(struct auth_ntlmssp_state *auth_ntlmssp_state, uint8_t auth_type, uint8_t auth_level) { + struct gensec_ntlmssp_context *gensec_ntlmssp; + NTSTATUS status; + if (auth_ntlmssp_state->auth_context->gensec_start_mech_by_authtype) { - return auth_ntlmssp_state->auth_context->gensec_start_mech_by_authtype(auth_ntlmssp_state->gensec_security, - auth_type, auth_level); + return auth_ntlmssp_state->auth_context->gensec_start_mech_by_authtype( + auth_ntlmssp_state->gensec_security, + auth_type, auth_level); } if (auth_type != DCERPC_AUTH_TYPE_NTLMSSP) { @@ -309,11 +433,18 @@ NTSTATUS auth_generic_authtype_start(struct auth_ntlmssp_state *auth_ntlmssp_sta return NT_STATUS_NOT_IMPLEMENTED; } + gensec_want_feature(auth_ntlmssp_state->gensec_security, + GENSEC_FEATURE_DCE_STYLE); + gensec_want_feature(auth_ntlmssp_state->gensec_security, + GENSEC_FEATURE_ASYNC_REPLIES); if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) { - auth_ntlmssp_want_feature(auth_ntlmssp_state, NTLMSSP_FEATURE_SIGN); + gensec_want_feature(auth_ntlmssp_state->gensec_security, + GENSEC_FEATURE_SIGN); } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) { - /* Always implies both sign and seal for ntlmssp */ - auth_ntlmssp_want_feature(auth_ntlmssp_state, NTLMSSP_FEATURE_SEAL); + gensec_want_feature(auth_ntlmssp_state->gensec_security, + GENSEC_FEATURE_SIGN); + gensec_want_feature(auth_ntlmssp_state->gensec_security, + GENSEC_FEATURE_SEAL); } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) { /* Default features */ } else { @@ -322,6 +453,18 @@ NTSTATUS auth_generic_authtype_start(struct auth_ntlmssp_state *auth_ntlmssp_sta return NT_STATUS_INVALID_PARAMETER; } + status = gensec_start_mech_by_ops(auth_ntlmssp_state->gensec_security, + &gensec_ntlmssp3_server_ops); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + gensec_ntlmssp = + talloc_get_type_abort(auth_ntlmssp_state->gensec_security->private_data, + struct gensec_ntlmssp_context); + + gensec_ntlmssp->auth_context = auth_ntlmssp_state->auth_context; + return NT_STATUS_OK; } |