From fa1275610b3c7cad75b5b86ae4b32d8781d1acc0 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 18 Oct 2011 16:16:02 +1100 Subject: s3-libsmb Use a gensec module to provide the ntlmssp client in ntlmssp_wrap.c This removes the need to have if (ans->gensec_security) everywhere. Andrew Bartlett --- source3/include/ntlmssp_wrap.h | 8 +- source3/libsmb/ntlmssp_wrap.c | 275 +++++++++++++++++++++++++++++------------ 2 files changed, 198 insertions(+), 85 deletions(-) (limited to 'source3') diff --git a/source3/include/ntlmssp_wrap.h b/source3/include/ntlmssp_wrap.h index 7ee3d3d9d8..bfbfdebd26 100644 --- a/source3/include/ntlmssp_wrap.h +++ b/source3/include/ntlmssp_wrap.h @@ -26,10 +26,12 @@ struct gensec_security; struct auth_ntlmssp_state { /* used only by server implementation */ struct auth_context *auth_context; - struct gensec_security *gensec_security; - + /* used only by the client implementation */ - struct ntlmssp_state *ntlmssp_state; + struct cli_credentials *credentials; + + /* used by both */ + struct gensec_security *gensec_security; }; NTSTATUS auth_ntlmssp_sign_packet(struct auth_ntlmssp_state *ans, diff --git a/source3/libsmb/ntlmssp_wrap.c b/source3/libsmb/ntlmssp_wrap.c index 5f8e246398..3d1d099a58 100644 --- a/source3/libsmb/ntlmssp_wrap.c +++ b/source3/libsmb/ntlmssp_wrap.c @@ -22,6 +22,9 @@ #include "auth/ntlmssp/ntlmssp.h" #include "ntlmssp_wrap.h" #include "auth/gensec/gensec.h" +#include "auth/credentials/credentials.h" +#include "librpc/rpc/dcerpc.h" +#include "lib/param/param.h" NTSTATUS auth_ntlmssp_sign_packet(struct auth_ntlmssp_state *ans, TALLOC_CTX *sig_mem_ctx, @@ -31,15 +34,8 @@ NTSTATUS auth_ntlmssp_sign_packet(struct auth_ntlmssp_state *ans, size_t pdu_length, DATA_BLOB *sig) { - if (ans->gensec_security) { - return gensec_sign_packet(ans->gensec_security, - sig_mem_ctx, data, length, whole_pdu, pdu_length, sig); - } - return ntlmssp_sign_packet(ans->ntlmssp_state, - sig_mem_ctx, - data, length, - whole_pdu, pdu_length, - sig); + return gensec_sign_packet(ans->gensec_security, + sig_mem_ctx, data, length, whole_pdu, pdu_length, sig); } NTSTATUS auth_ntlmssp_check_packet(struct auth_ntlmssp_state *ans, @@ -49,14 +45,8 @@ NTSTATUS auth_ntlmssp_check_packet(struct auth_ntlmssp_state *ans, size_t pdu_length, const DATA_BLOB *sig) { - if (ans->gensec_security) { - return gensec_check_packet(ans->gensec_security, - data, length, whole_pdu, pdu_length, sig); - } - return ntlmssp_check_packet(ans->ntlmssp_state, - data, length, - whole_pdu, pdu_length, - sig); + return gensec_check_packet(ans->gensec_security, + data, length, whole_pdu, pdu_length, sig); } NTSTATUS auth_ntlmssp_seal_packet(struct auth_ntlmssp_state *ans, @@ -67,15 +57,8 @@ NTSTATUS auth_ntlmssp_seal_packet(struct auth_ntlmssp_state *ans, size_t pdu_length, DATA_BLOB *sig) { - if (ans->gensec_security) { - return gensec_seal_packet(ans->gensec_security, - sig_mem_ctx, data, length, whole_pdu, pdu_length, sig); - } - return ntlmssp_seal_packet(ans->ntlmssp_state, - sig_mem_ctx, - data, length, - whole_pdu, pdu_length, - sig); + return gensec_seal_packet(ans->gensec_security, + sig_mem_ctx, data, length, whole_pdu, pdu_length, sig); } NTSTATUS auth_ntlmssp_unseal_packet(struct auth_ntlmssp_state *ans, @@ -85,113 +68,225 @@ NTSTATUS auth_ntlmssp_unseal_packet(struct auth_ntlmssp_state *ans, size_t pdu_length, const DATA_BLOB *sig) { - if (ans->gensec_security) { - return gensec_unseal_packet(ans->gensec_security, - data, length, whole_pdu, pdu_length, sig); - } - return ntlmssp_unseal_packet(ans->ntlmssp_state, - data, length, - whole_pdu, pdu_length, - sig); + return gensec_unseal_packet(ans->gensec_security, + data, length, whole_pdu, pdu_length, sig); } bool auth_ntlmssp_negotiated_sign(struct auth_ntlmssp_state *ans) { - if (ans->gensec_security) { - return gensec_have_feature(ans->gensec_security, GENSEC_FEATURE_SIGN); - } - return ans->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN; + return gensec_have_feature(ans->gensec_security, GENSEC_FEATURE_SIGN); } bool auth_ntlmssp_negotiated_seal(struct auth_ntlmssp_state *ans) { - if (ans->gensec_security) { - return gensec_have_feature(ans->gensec_security, GENSEC_FEATURE_SEAL); - } - return ans->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL; + return gensec_have_feature(ans->gensec_security, GENSEC_FEATURE_SEAL); } NTSTATUS auth_ntlmssp_set_username(struct auth_ntlmssp_state *ans, const char *user) { - return ntlmssp_set_username(ans->ntlmssp_state, user); + cli_credentials_set_username(ans->credentials, user, CRED_SPECIFIED); + return NT_STATUS_OK; } NTSTATUS auth_ntlmssp_set_domain(struct auth_ntlmssp_state *ans, const char *domain) { - return ntlmssp_set_domain(ans->ntlmssp_state, domain); + cli_credentials_set_domain(ans->credentials, domain, CRED_SPECIFIED); + return NT_STATUS_OK; } NTSTATUS auth_ntlmssp_set_password(struct auth_ntlmssp_state *ans, const char *password) { - return ntlmssp_set_password(ans->ntlmssp_state, password); + cli_credentials_set_password(ans->credentials, password, CRED_SPECIFIED); + return NT_STATUS_OK; } void auth_ntlmssp_want_feature(struct auth_ntlmssp_state *ans, uint32_t feature) { - if (ans->gensec_security) { - if (feature & NTLMSSP_FEATURE_SESSION_KEY) { - gensec_want_feature(ans->gensec_security, GENSEC_FEATURE_SESSION_KEY); - } - if (feature & NTLMSSP_FEATURE_SIGN) { - gensec_want_feature(ans->gensec_security, GENSEC_FEATURE_SIGN); - } - if (feature & NTLMSSP_FEATURE_SEAL) { - gensec_want_feature(ans->gensec_security, GENSEC_FEATURE_SEAL); - } - } else { - ntlmssp_want_feature(ans->ntlmssp_state, feature); + if (feature & NTLMSSP_FEATURE_SESSION_KEY) { + gensec_want_feature(ans->gensec_security, GENSEC_FEATURE_SESSION_KEY); + } + if (feature & NTLMSSP_FEATURE_SIGN) { + gensec_want_feature(ans->gensec_security, GENSEC_FEATURE_SIGN); + } + if (feature & NTLMSSP_FEATURE_SEAL) { + gensec_want_feature(ans->gensec_security, GENSEC_FEATURE_SEAL); } } DATA_BLOB auth_ntlmssp_get_session_key(struct auth_ntlmssp_state *ans, TALLOC_CTX *mem_ctx) { - if (ans->gensec_security) { - DATA_BLOB session_key; - NTSTATUS status = gensec_session_key(ans->gensec_security, mem_ctx, &session_key); - if (NT_STATUS_IS_OK(status)) { - return session_key; - } else { - return data_blob_null; - } + DATA_BLOB session_key; + NTSTATUS status = gensec_session_key(ans->gensec_security, mem_ctx, &session_key); + if (NT_STATUS_IS_OK(status)) { + return session_key; + } else { + return data_blob_null; } - return data_blob_talloc(mem_ctx, ans->ntlmssp_state->session_key.data, ans->ntlmssp_state->session_key.length); } NTSTATUS auth_ntlmssp_update(struct auth_ntlmssp_state *ans, TALLOC_CTX *mem_ctx, const DATA_BLOB request, DATA_BLOB *reply) +{ + return gensec_update(ans->gensec_security, mem_ctx, NULL, request, reply); +} + +static NTSTATUS gensec_ntlmssp3_client_update(struct gensec_security *gensec_security, + TALLOC_CTX *out_mem_ctx, + struct tevent_context *ev, + const DATA_BLOB request, + DATA_BLOB *reply) { NTSTATUS status; - if (ans->gensec_security) { - return gensec_update(ans->gensec_security, mem_ctx, NULL, request, reply); - } - status = ntlmssp_update(ans->ntlmssp_state, request, reply); - if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - return 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); } - talloc_steal(mem_ctx, reply->data); + return status; } -NTSTATUS auth_ntlmssp_client_prepare(TALLOC_CTX *mem_ctx, - struct auth_ntlmssp_state **_ans) +static NTSTATUS gensec_ntlmssp3_client_start(struct gensec_security *gensec_security) +{ + NTSTATUS nt_status; + struct gensec_ntlmssp_context *gensec_ntlmssp; + const char *user, *domain; + const char *password; + + 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_client_start(gensec_ntlmssp, + lp_netbios_name(), lp_workgroup(), + lp_client_ntlmv2_auth(), &gensec_ntlmssp->ntlmssp_state); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } + + cli_credentials_get_ntlm_username_domain(gensec_security->credentials, gensec_ntlmssp, &user, &domain); + if (!user || !domain) { + return NT_STATUS_NO_MEMORY; + } + + nt_status = ntlmssp_set_username(gensec_ntlmssp->ntlmssp_state, user); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } + + nt_status = ntlmssp_set_domain(gensec_ntlmssp->ntlmssp_state, domain); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } + + password = cli_credentials_get_password(gensec_security->credentials); + if (!password) { + return NT_STATUS_NO_MEMORY; + } + + nt_status = ntlmssp_set_password(gensec_ntlmssp->ntlmssp_state, password); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } + + 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; + } + + return NT_STATUS_OK; +} + +static const char *gensec_ntlmssp3_client_oids[] = { + GENSEC_OID_NTLMSSP, + NULL +}; + +static const struct gensec_security_ops gensec_ntlmssp3_client_ops = { + .name = "ntlmssp3_client", + .sasl_name = GENSEC_SASL_NAME_NTLMSSP, /* "NTLM" */ + .auth_type = DCERPC_AUTH_TYPE_NTLMSSP, + .oid = gensec_ntlmssp3_client_oids, + .client_start = gensec_ntlmssp3_client_start, + .magic = gensec_ntlmssp_magic, + .update = gensec_ntlmssp3_client_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, + .have_feature = gensec_ntlmssp_have_feature, + .enabled = true, + .priority = GENSEC_NTLMSSP +}; + +NTSTATUS auth_ntlmssp_client_prepare(TALLOC_CTX *mem_ctx, struct auth_ntlmssp_state **auth_ntlmssp_state) { struct auth_ntlmssp_state *ans; - NTSTATUS status; + NTSTATUS nt_status; + + struct gensec_settings *gensec_settings; + struct loadparm_context *lp_ctx; ans = talloc_zero(mem_ctx, struct auth_ntlmssp_state); + if (!ans) { + DEBUG(0,("auth_ntlmssp_start: talloc failed!\n")); + return NT_STATUS_NO_MEMORY; + } - status = ntlmssp_client_start(ans, - lp_netbios_name(), lp_workgroup(), - lp_client_ntlmv2_auth(), &ans->ntlmssp_state); - if (!NT_STATUS_IS_OK(status)) { - return status; + 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_client_start(ans, &ans->gensec_security, gensec_settings); + + if (!NT_STATUS_IS_OK(nt_status)) { + TALLOC_FREE(ans); + return nt_status; } - *_ans = ans; + ans->credentials = cli_credentials_init(ans); + if (!ans->credentials) { + TALLOC_FREE(ans); + return NT_STATUS_NO_MEMORY; + } + + cli_credentials_guess(ans->credentials, lp_ctx); + + talloc_unlink(ans, lp_ctx); + talloc_unlink(ans, gensec_settings); + + *auth_ntlmssp_state = ans; return NT_STATUS_OK; } @@ -199,5 +294,21 @@ NTSTATUS auth_ntlmssp_client_start(struct auth_ntlmssp_state *ans) { NTSTATUS status; + /* Transfer the credentials to gensec */ + status = gensec_set_credentials(ans->gensec_security, ans->credentials); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("Failed to set GENSEC credentials: %s\n", + nt_errstr(status))); + return status; + } + talloc_unlink(ans, ans->credentials); + ans->credentials = NULL; + + status = gensec_start_mech_by_ops(ans->gensec_security, + &gensec_ntlmssp3_client_ops); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + return NT_STATUS_OK; } -- cgit