s3-librpc Call SPENGO/GSSAPI via the auth_generic layer and gensec
authorAndrew Bartlett <abartlet@samba.org>
Mon, 2 Jan 2012 04:38:38 +0000 (15:38 +1100)
committerStefan Metzmacher <metze@samba.org>
Wed, 18 Jan 2012 15:23:22 +0000 (16:23 +0100)
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 <metze@samba.org>
source3/librpc/crypto/cli_spnego.c
source3/librpc/crypto/spnego.h
source3/librpc/rpc/dcerpc_helpers.c
source3/rpc_client/cli_pipe.c
source3/rpc_server/dcesrv_spnego.c
source3/rpc_server/srv_pipe.c

index 97e6a8152bef6654fe719cb65558aaf3655502be..0a4bd18b22605cee16146f5ea1abfe7b14525cf6 100644 (file)
@@ -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,
index a31f997ab6da130f003ecab00e385cd4fa737832..57396a63c5d09479b3d1b8496893652614a6cf53 100644 (file)
@@ -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);
index 4cfe7933fe0c95002008aa6e9e6178ca52b306d3..ed0e0fe9325fa618353fc3821aa9f5d274fe75aa 100644 (file)
@@ -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:
index ce8ab819c53843d04b59a4b98e5c0723c7558703..f3a334a05247b14e2e2f2869cc1555d856643a81 100644 (file)
@@ -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)));
index e89563a9fb08882e571d800f3acfd350bc18fb15..1bea2321efccd9f13f824efcc29aa48c52c48c7e 100644 (file)
@@ -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,
index 605ed5420cd0e59e9ed9c89636cb4e4abb660d40..18389b42e0f99c1adf48060e3714c332ac7fcdbd 100644 (file)
@@ -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;