From 0c1b4c232135ebdef58bb5e697dfc60ddbb358bc Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 2 Jan 2012 15:38:38 +1100 Subject: s3-librpc Call SPENGO/GSSAPI via the auth_generic layer and gensec This simplifies a lot of code, as we know we are always dealing with a struct gensec_security, and allows the gensec module being used to implement GSSAPI to be swapped for AD-server operation. Andrew Bartlett Signed-off-by: Stefan Metzmacher --- source3/librpc/crypto/cli_spnego.c | 98 ++++++------------------------------- source3/librpc/crypto/spnego.h | 14 ++---- source3/librpc/rpc/dcerpc_helpers.c | 27 +--------- source3/rpc_client/cli_pipe.c | 16 +++--- source3/rpc_server/dcesrv_spnego.c | 58 ++++++++-------------- source3/rpc_server/srv_pipe.c | 71 ++------------------------- 6 files changed, 53 insertions(+), 231 deletions(-) (limited to 'source3') diff --git a/source3/librpc/crypto/cli_spnego.c b/source3/librpc/crypto/cli_spnego.c index 97e6a8152b..0a4bd18b22 100644 --- a/source3/librpc/crypto/cli_spnego.c +++ b/source3/librpc/crypto/cli_spnego.c @@ -46,44 +46,6 @@ static NTSTATUS spnego_context_init(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } -NTSTATUS spnego_gssapi_init_client(TALLOC_CTX *mem_ctx, - bool do_sign, bool do_seal, - bool is_dcerpc, - const char *ccache_name, - const char *server, - const char *service, - const char *username, - const char *password, - struct spnego_context **spnego_ctx) -{ - struct spnego_context *sp_ctx = NULL; - uint32_t add_gss_c_flags = 0; - NTSTATUS status; - - status = spnego_context_init(mem_ctx, do_sign, do_seal, &sp_ctx); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - sp_ctx->mech = SPNEGO_KRB5; - - if (is_dcerpc) { - add_gss_c_flags = GSS_C_DCE_STYLE; - } - - status = gse_init_client(sp_ctx, - do_sign, do_seal, - ccache_name, server, service, - username, password, add_gss_c_flags, - &sp_ctx->mech_ctx.gssapi_state); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(sp_ctx); - return status; - } - - *spnego_ctx = sp_ctx; - return NT_STATUS_OK; -} - NTSTATUS spnego_generic_init_client(TALLOC_CTX *mem_ctx, const char *oid, bool do_sign, bool do_seal, @@ -181,7 +143,6 @@ NTSTATUS spnego_get_client_auth_token(TALLOC_CTX *mem_ctx, DATA_BLOB *spnego_in, DATA_BLOB *spnego_out) { - struct gse_context *gse_ctx; struct gensec_security *gensec_security; struct spnego_data sp_in, sp_out; DATA_BLOB token_in = data_blob_null; @@ -190,7 +151,6 @@ NTSTATUS spnego_get_client_auth_token(TALLOC_CTX *mem_ctx, char *principal = NULL; ssize_t len_in = 0; ssize_t len_out = 0; - bool mech_wants_more = false; NTSTATUS status; if (!spnego_in->length) { @@ -228,33 +188,11 @@ NTSTATUS spnego_get_client_auth_token(TALLOC_CTX *mem_ctx, switch (sp_ctx->mech) { case SPNEGO_KRB5: - - gse_ctx = sp_ctx->mech_ctx.gssapi_state; - status = gse_get_client_auth_token(mem_ctx, gse_ctx, - &token_in, &token_out); - if (!NT_STATUS_IS_OK(status)) { - goto done; - } - mech_oids[0] = OID_KERBEROS5; - mech_wants_more = gse_require_more_processing(gse_ctx); - break; case SPNEGO_NTLMSSP: - - gensec_security = sp_ctx->mech_ctx.gensec_security; - status = gensec_update(gensec_security, mem_ctx, NULL, - 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: @@ -262,6 +200,17 @@ NTSTATUS spnego_get_client_auth_token(TALLOC_CTX *mem_ctx, goto done; } + gensec_security = sp_ctx->mech_ctx.gensec_security; + status = gensec_update(gensec_security, mem_ctx, NULL, + token_in, &token_out); + sp_ctx->more_processing = false; + if (NT_STATUS_EQUAL(status, + NT_STATUS_MORE_PROCESSING_REQUIRED)) { + sp_ctx->more_processing = true; + } else if (!NT_STATUS_IS_OK(status)) { + goto done; + } + switch (sp_ctx->state) { case SPNEGO_CONV_INIT: *spnego_out = spnego_gen_negTokenInit(mem_ctx, mech_oids, @@ -293,7 +242,7 @@ NTSTATUS spnego_get_client_auth_token(TALLOC_CTX *mem_ctx, goto done; } - if (!mech_wants_more) { + if (!sp_ctx->more_processing) { /* we still need to get an ack from the server */ sp_ctx->state = SPNEGO_CONV_AUTH_CONFIRM; } @@ -317,7 +266,6 @@ done: bool spnego_require_more_processing(struct spnego_context *sp_ctx) { - struct gse_context *gse_ctx; /* see if spnego processing itself requires more */ if (sp_ctx->state == SPNEGO_CONV_AUTH_MORE || @@ -328,10 +276,8 @@ bool spnego_require_more_processing(struct spnego_context *sp_ctx) /* otherwise see if underlying mechnism does */ switch (sp_ctx->mech) { case SPNEGO_KRB5: - gse_ctx = sp_ctx->mech_ctx.gssapi_state; - return gse_require_more_processing(gse_ctx); case SPNEGO_NTLMSSP: - return false; + return sp_ctx->more_processing; default: DEBUG(0, ("Unsupported type in request!\n")); return false; @@ -340,12 +286,10 @@ bool spnego_require_more_processing(struct spnego_context *sp_ctx) NTSTATUS spnego_get_negotiated_mech(struct spnego_context *sp_ctx, enum spnego_mech *type, - void **auth_context) + struct gensec_security **auth_context) { switch (sp_ctx->mech) { case SPNEGO_KRB5: - *auth_context = sp_ctx->mech_ctx.gssapi_state; - break; case SPNEGO_NTLMSSP: *auth_context = sp_ctx->mech_ctx.gensec_security; break; @@ -364,8 +308,6 @@ DATA_BLOB spnego_get_session_key(TALLOC_CTX *mem_ctx, NTSTATUS status; switch (sp_ctx->mech) { case SPNEGO_KRB5: - return gse_get_session_key(mem_ctx, - sp_ctx->mech_ctx.gssapi_state); case SPNEGO_NTLMSSP: status = gensec_session_key(sp_ctx->mech_ctx.gensec_security, mem_ctx, &sk); if (!NT_STATUS_IS_OK(status)) { @@ -385,9 +327,6 @@ NTSTATUS spnego_sign(TALLOC_CTX *mem_ctx, { switch(sp_ctx->mech) { case SPNEGO_KRB5: - return gse_sign(mem_ctx, - sp_ctx->mech_ctx.gssapi_state, - data, signature); case SPNEGO_NTLMSSP: return gensec_sign_packet( sp_ctx->mech_ctx.gensec_security, @@ -407,9 +346,6 @@ NTSTATUS spnego_sigcheck(TALLOC_CTX *mem_ctx, { switch(sp_ctx->mech) { case SPNEGO_KRB5: - return gse_sigcheck(mem_ctx, - sp_ctx->mech_ctx.gssapi_state, - data, signature); case SPNEGO_NTLMSSP: return gensec_check_packet( sp_ctx->mech_ctx.gensec_security, @@ -428,9 +364,6 @@ NTSTATUS spnego_seal(TALLOC_CTX *mem_ctx, { switch(sp_ctx->mech) { case SPNEGO_KRB5: - return gse_seal(mem_ctx, - sp_ctx->mech_ctx.gssapi_state, - data, signature); case SPNEGO_NTLMSSP: return gensec_seal_packet( sp_ctx->mech_ctx.gensec_security, @@ -450,9 +383,6 @@ NTSTATUS spnego_unseal(TALLOC_CTX *mem_ctx, { switch(sp_ctx->mech) { case SPNEGO_KRB5: - return gse_unseal(mem_ctx, - sp_ctx->mech_ctx.gssapi_state, - data, signature); case SPNEGO_NTLMSSP: return gensec_unseal_packet( sp_ctx->mech_ctx.gensec_security, diff --git a/source3/librpc/crypto/spnego.h b/source3/librpc/crypto/spnego.h index a31f997ab6..57396a63c5 100644 --- a/source3/librpc/crypto/spnego.h +++ b/source3/librpc/crypto/spnego.h @@ -31,7 +31,6 @@ struct spnego_context { union { struct gensec_security *gensec_security; - struct gse_context *gssapi_state; } mech_ctx; char *oid_list[ASN1_MAX_OIDS]; @@ -50,17 +49,10 @@ struct spnego_context { bool is_dcerpc; struct tsocket_address *remote_address; + + bool more_processing; /* Current mech state requires more processing */ }; -NTSTATUS spnego_gssapi_init_client(TALLOC_CTX *mem_ctx, - bool do_sign, bool do_seal, - bool is_dcerpc, - const char *ccache_name, - const char *server, - const char *service, - const char *username, - const char *password, - struct spnego_context **spengo_ctx); NTSTATUS spnego_generic_init_client(TALLOC_CTX *mem_ctx, const char *oid, bool do_sign, bool do_seal, @@ -81,7 +73,7 @@ bool spnego_require_more_processing(struct spnego_context *sp_ctx); NTSTATUS spnego_get_negotiated_mech(struct spnego_context *sp_ctx, enum spnego_mech *type, - void **auth_context); + struct gensec_security **auth_context); DATA_BLOB spnego_get_session_key(TALLOC_CTX *mem_ctx, struct spnego_context *sp_ctx); diff --git a/source3/librpc/rpc/dcerpc_helpers.c b/source3/librpc/rpc/dcerpc_helpers.c index 4cfe7933fe..ed0e0fe932 100644 --- a/source3/librpc/rpc/dcerpc_helpers.c +++ b/source3/librpc/rpc/dcerpc_helpers.c @@ -268,10 +268,7 @@ NTSTATUS dcerpc_guess_sizes(struct pipe_auth_data *auth, struct gensec_security *gensec_security; struct schannel_state *schannel_auth; struct spnego_context *spnego_ctx; - struct gse_context *gse_ctx; enum spnego_mech auth_type; - void *auth_ctx; - bool seal = false; NTSTATUS status; /* no auth token cases first */ @@ -287,7 +284,6 @@ NTSTATUS dcerpc_guess_sizes(struct pipe_auth_data *auth, return NT_STATUS_OK; case DCERPC_AUTH_LEVEL_PRIVACY: - seal = true; break; case DCERPC_AUTH_LEVEL_INTEGRITY: @@ -308,30 +304,11 @@ NTSTATUS dcerpc_guess_sizes(struct pipe_auth_data *auth, spnego_ctx = talloc_get_type_abort(auth->auth_ctx, struct spnego_context); status = spnego_get_negotiated_mech(spnego_ctx, - &auth_type, &auth_ctx); + &auth_type, &gensec_security); if (!NT_STATUS_IS_OK(status)) { return status; } - switch (auth_type) { - case SPNEGO_NTLMSSP: - gensec_security = talloc_get_type_abort(auth_ctx, - struct gensec_security); - *auth_len = gensec_sig_size(gensec_security, max_len); - break; - - case SPNEGO_KRB5: - gse_ctx = talloc_get_type_abort(auth_ctx, - struct gse_context); - if (!gse_ctx) { - return NT_STATUS_INVALID_PARAMETER; - } - *auth_len = gse_get_signature_length(gse_ctx, - seal, max_len); - break; - - default: - return NT_STATUS_INVALID_PARAMETER; - } + *auth_len = gensec_sig_size(gensec_security, max_len); break; case DCERPC_AUTH_TYPE_NTLMSSP: diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index ce8ab819c5..f3a334a052 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2939,6 +2939,7 @@ NTSTATUS cli_rpc_pipe_open_spnego_krb5(struct cli_state *cli, struct pipe_auth_data *auth; struct spnego_context *spnego_ctx; NTSTATUS status; + const char *target_service = "cifs"; /* TODO: Determine target service from the bindings or interface table */ status = cli_rpc_pipe_open(cli, transport, interface, &result); if (!NT_STATUS_IS_OK(status)) { @@ -2969,15 +2970,16 @@ NTSTATUS cli_rpc_pipe_open_spnego_krb5(struct cli_state *cli, goto err_out; } - status = spnego_gssapi_init_client(auth, - (auth->auth_level == + status = spnego_generic_init_client(auth, + GENSEC_OID_KERBEROS5, + (auth->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY), - (auth->auth_level == + (auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY), - true, - NULL, server, "cifs", - username, password, - &spnego_ctx); + true, + server, target_service, + auth->domain, auth->user_name, password, + &spnego_ctx); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("spnego_init_client returned %s\n", nt_errstr(status))); diff --git a/source3/rpc_server/dcesrv_spnego.c b/source3/rpc_server/dcesrv_spnego.c index e89563a9fb..1bea2321ef 100644 --- a/source3/rpc_server/dcesrv_spnego.c +++ b/source3/rpc_server/dcesrv_spnego.c @@ -23,6 +23,7 @@ #include "dcesrv_auth_generic.h" #include "dcesrv_gssapi.h" #include "dcesrv_spnego.h" +#include "auth/gensec/gensec.h" static NTSTATUS spnego_init_server(TALLOC_CTX *mem_ctx, bool do_sign, bool do_seal, @@ -55,51 +56,38 @@ static NTSTATUS spnego_server_mech_init(struct spnego_context *sp_ctx, DATA_BLOB *token_out) { struct gensec_security *gensec_security; - struct gse_context *gse_ctx; NTSTATUS status; + const char *oid; switch (sp_ctx->mech) { case SPNEGO_KRB5: - status = gssapi_server_auth_start(sp_ctx, - sp_ctx->do_sign, - sp_ctx->do_seal, - sp_ctx->is_dcerpc, - token_in, - token_out, - &gse_ctx); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("Failed to init gssapi server " - "(%s)\n", nt_errstr(status))); - return status; - } - - sp_ctx->mech_ctx.gssapi_state = gse_ctx; + oid = GENSEC_OID_KERBEROS5; break; - case SPNEGO_NTLMSSP: - status = auth_generic_server_start(sp_ctx, - OID_NTLMSSP, - sp_ctx->do_sign, - sp_ctx->do_seal, - sp_ctx->is_dcerpc, - token_in, - token_out, - sp_ctx->remote_address, - &gensec_security); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("Failed to init ntlmssp server " - "(%s)\n", nt_errstr(status))); - return status; - } - - sp_ctx->mech_ctx.gensec_security = gensec_security; + oid = GENSEC_OID_NTLMSSP; break; - default: DEBUG(3, ("No known mechanisms available\n")); return NT_STATUS_INVALID_PARAMETER; } + status = auth_generic_server_start(sp_ctx, + oid, + sp_ctx->do_sign, + sp_ctx->do_seal, + sp_ctx->is_dcerpc, + token_in, + token_out, + sp_ctx->remote_address, + &gensec_security); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("Failed to init ntlmssp server " + "(%s)\n", nt_errstr(status))); + return status; + } + + sp_ctx->mech_ctx.gensec_security = gensec_security; + return NT_STATUS_OK; } @@ -150,10 +138,6 @@ NTSTATUS spnego_server_step(struct spnego_context *sp_ctx, switch(sp_ctx->mech) { case SPNEGO_KRB5: - status = gssapi_server_step( - sp_ctx->mech_ctx.gssapi_state, - mem_ctx, &token_in, &token_out); - break; case SPNEGO_NTLMSSP: status = auth_generic_server_step( sp_ctx->mech_ctx.gensec_security, diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 605ed5420c..18389b42e0 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -676,52 +676,11 @@ static bool pipe_auth_generic_verify_final(TALLOC_CTX *mem_ctx, return true; } -static NTSTATUS pipe_gssapi_verify_final(TALLOC_CTX *mem_ctx, - struct gse_context *gse_ctx, - const struct tsocket_address *remote_address, - struct auth_session_info **session_info) -{ - NTSTATUS status; - bool bret; - - /* Finally - if the pipe negotiated integrity (sign) or privacy (seal) - ensure the underlying flags are also set. If not we should - refuse the bind. */ - - status = gssapi_server_check_flags(gse_ctx); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("Requested Security Layers not honored!\n")); - return status; - } - - status = gssapi_server_get_user_info(gse_ctx, mem_ctx, - remote_address, session_info); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, (__location__ ": failed to obtain the server info " - "for authenticated user: %s\n", nt_errstr(status))); - return status; - } - - /* - * We're an authenticated bind over smb, so the session key needs to - * be set to "SystemLibraryDTC". Weird, but this is what Windows - * does. See the RPC-SAMBA3SESSIONKEY. - */ - - bret = session_info_set_session_key((*session_info), generic_session_key()); - if (!bret) { - return NT_STATUS_ACCESS_DENIED; - } - - return NT_STATUS_OK; -} - static NTSTATUS pipe_auth_verify_final(struct pipes_struct *p) { enum spnego_mech auth_type; struct gensec_security *gensec_security; struct spnego_context *spnego_ctx; - struct gse_context *gse_ctx; void *mech_ctx; NTSTATUS status; @@ -740,37 +699,15 @@ static NTSTATUS pipe_auth_verify_final(struct pipes_struct *p) spnego_ctx = talloc_get_type_abort(p->auth.auth_ctx, struct spnego_context); status = spnego_get_negotiated_mech(spnego_ctx, - &auth_type, &mech_ctx); + &auth_type, &gensec_security); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Bad SPNEGO state (%s)\n", nt_errstr(status))); return status; } - switch(auth_type) { - case SPNEGO_KRB5: - gse_ctx = talloc_get_type_abort(mech_ctx, - struct gse_context); - status = pipe_gssapi_verify_final(p, gse_ctx, - p->remote_address, - &p->session_info); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("gssapi bind failed with: %s", - nt_errstr(status))); - return status; - } - break; - case SPNEGO_NTLMSSP: - gensec_security = talloc_get_type_abort(mech_ctx, - struct gensec_security); - if (!pipe_auth_generic_verify_final(p, gensec_security, - p->auth.auth_level, - &p->session_info)) { - return NT_STATUS_ACCESS_DENIED; - } - break; - default: - DEBUG(0, (__location__ ": incorrect spnego type " - "(%d).\n", auth_type)); + if (!pipe_auth_generic_verify_final(p, gensec_security, + p->auth.auth_level, + &p->session_info)) { return NT_STATUS_ACCESS_DENIED; } break; -- cgit