diff options
Diffstat (limited to 'source3/librpc/rpc/dcerpc_spnego.c')
-rw-r--r-- | source3/librpc/rpc/dcerpc_spnego.c | 108 |
1 files changed, 104 insertions, 4 deletions
diff --git a/source3/librpc/rpc/dcerpc_spnego.c b/source3/librpc/rpc/dcerpc_spnego.c index e733469ac3..a0832ce09f 100644 --- a/source3/librpc/rpc/dcerpc_spnego.c +++ b/source3/librpc/rpc/dcerpc_spnego.c @@ -19,6 +19,8 @@ #include "includes.h" #include "../libcli/auth/spnego.h" +#include "include/ntlmssp_wrap.h" +#include "librpc/gen_ndr/ntlmssp.h" #include "dcerpc_spnego.h" #include "dcerpc_gssapi.h" @@ -26,7 +28,7 @@ struct spnego_context { enum dcerpc_AuthType auth_type; union { - struct auth_ntlmssp_state *auth_ntlmssp_state; + struct auth_ntlmssp_state *ntlmssp_state; struct gse_context *gssapi_state; } mech_ctx; @@ -88,12 +90,80 @@ NTSTATUS spnego_gssapi_init_client(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } +NTSTATUS spnego_ntlmssp_init_client(TALLOC_CTX *mem_ctx, + enum dcerpc_AuthLevel auth_level, + const char *domain, + const char *username, + const char *password, + struct spnego_context **spnego_ctx) +{ + struct spnego_context *sp_ctx; + NTSTATUS status; + + status = spnego_context_init(mem_ctx, + DCERPC_AUTH_TYPE_NTLMSSP, &sp_ctx); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + status = auth_ntlmssp_client_start(sp_ctx, + global_myname(), + lp_workgroup(), + lp_client_ntlmv2_auth(), + &sp_ctx->mech_ctx.ntlmssp_state); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(sp_ctx); + return status; + } + + status = auth_ntlmssp_set_username(sp_ctx->mech_ctx.ntlmssp_state, + username); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(sp_ctx); + return status; + } + + status = auth_ntlmssp_set_domain(sp_ctx->mech_ctx.ntlmssp_state, + domain); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(sp_ctx); + return status; + } + + status = auth_ntlmssp_set_password(sp_ctx->mech_ctx.ntlmssp_state, + password); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(sp_ctx); + return status; + } + + /* + * Turn off sign+seal to allow selected auth level to turn it back on. + */ + auth_ntlmssp_and_flags(sp_ctx->mech_ctx.ntlmssp_state, + ~(NTLMSSP_NEGOTIATE_SIGN | + NTLMSSP_NEGOTIATE_SEAL)); + + if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) { + auth_ntlmssp_or_flags(sp_ctx->mech_ctx.ntlmssp_state, + NTLMSSP_NEGOTIATE_SIGN); + } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) { + auth_ntlmssp_or_flags(sp_ctx->mech_ctx.ntlmssp_state, + NTLMSSP_NEGOTIATE_SEAL | + NTLMSSP_NEGOTIATE_SIGN); + } + + *spnego_ctx = sp_ctx; + return NT_STATUS_OK; +} + NTSTATUS spnego_get_client_auth_token(TALLOC_CTX *mem_ctx, struct spnego_context *sp_ctx, DATA_BLOB *spnego_in, DATA_BLOB *spnego_out) { struct gse_context *gse_ctx; + struct auth_ntlmssp_state *ntlmssp_ctx; struct spnego_data sp_in, sp_out; DATA_BLOB token_in = data_blob_null; DATA_BLOB token_out = data_blob_null; @@ -129,6 +199,7 @@ NTSTATUS spnego_get_client_auth_token(TALLOC_CTX *mem_ctx, if (sp_ctx->state == SPNEGO_CONV_AUTH_CONFIRM) { if (sp_in.negTokenTarg.negResult == SPNEGO_ACCEPT_COMPLETED) { sp_ctx->state = SPNEGO_CONV_AUTH_DONE; + *spnego_out = data_blob_null; status = NT_STATUS_OK; } else { status = NT_STATUS_ACCESS_DENIED; @@ -152,8 +223,21 @@ NTSTATUS spnego_get_client_auth_token(TALLOC_CTX *mem_ctx, break; case DCERPC_AUTH_TYPE_NTLMSSP: - status = NT_STATUS_NOT_IMPLEMENTED; - goto done; + + ntlmssp_ctx = sp_ctx->mech_ctx.ntlmssp_state; + status = auth_ntlmssp_update(ntlmssp_ctx, + token_in, &token_out); + if (NT_STATUS_EQUAL(status, + NT_STATUS_MORE_PROCESSING_REQUIRED)) { + mech_wants_more = true; + } else if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + mech_oids[0] = OID_NTLMSSP; + + break; + default: status = NT_STATUS_INTERNAL_ERROR; goto done; @@ -227,6 +311,8 @@ bool spnego_require_more_processing(struct spnego_context *sp_ctx) case DCERPC_AUTH_TYPE_KRB5: gse_ctx = sp_ctx->mech_ctx.gssapi_state; return gse_require_more_processing(gse_ctx); + case DCERPC_AUTH_TYPE_NTLMSSP: + return false; default: DEBUG(0, ("Unsupported type in request!\n")); return false; @@ -242,7 +328,7 @@ NTSTATUS spnego_get_negotiated_mech(struct spnego_context *sp_ctx, *auth_context = sp_ctx->mech_ctx.gssapi_state; break; case DCERPC_AUTH_TYPE_NTLMSSP: - *auth_context = sp_ctx->mech_ctx.auth_ntlmssp_state; + *auth_context = sp_ctx->mech_ctx.ntlmssp_state; break; default: return NT_STATUS_INTERNAL_ERROR; @@ -252,3 +338,17 @@ NTSTATUS spnego_get_negotiated_mech(struct spnego_context *sp_ctx, return NT_STATUS_OK; } +DATA_BLOB spnego_get_session_key(struct spnego_context *sp_ctx) +{ + switch (sp_ctx->auth_type) { + case DCERPC_AUTH_TYPE_KRB5: + return gse_get_session_key(sp_ctx->mech_ctx.gssapi_state); + case DCERPC_AUTH_TYPE_NTLMSSP: + return auth_ntlmssp_get_session_key( + sp_ctx->mech_ctx.ntlmssp_state); + default: + DEBUG(0, ("Unsupported type in request!\n")); + return data_blob_null; + } +} + |