s3-dcerpc: use common spengo wrapper code for client SPNEGO/NTLMSSP
authorSimo Sorce <idra@samba.org>
Thu, 29 Jul 2010 23:55:44 +0000 (19:55 -0400)
committerSimo Sorce <idra@samba.org>
Fri, 30 Jul 2010 18:55:27 +0000 (14:55 -0400)
source3/include/ntdomain.h
source3/librpc/rpc/dcerpc_helpers.c
source3/librpc/rpc/dcerpc_spnego.c
source3/librpc/rpc/dcerpc_spnego.h
source3/rpc_client/cli_pipe.c

index 98f2df944511fc364f24c02a072d6bd7cf4b8fa4..f42ff587ffa498103e0ef8f36d3893c4f3aaac36 100644 (file)
@@ -105,7 +105,7 @@ struct gse_context;
 
 struct pipe_auth_data {
        enum dcerpc_AuthType auth_type;
-       enum pipe_auth_type_spnego spnego_type;
+       enum pipe_auth_type_spnego spnego_type; /* used by server only */
        enum dcerpc_AuthLevel auth_level;
 
        union {
index 592832bdd8085d127cda0e434d752d1fd7f3fcf1..26b44de5ea2c3ce870d27432054e72430f3adae9 100644 (file)
@@ -524,6 +524,7 @@ static NTSTATUS add_spnego_auth_footer(struct spnego_context *spnego_ctx,
 {
        enum dcerpc_AuthType auth_type;
        struct gse_context *gse_ctx;
+       struct auth_ntlmssp_state *ntlmssp_ctx;
        void *auth_ctx;
        NTSTATUS status;
 
@@ -548,8 +549,15 @@ static NTSTATUS add_spnego_auth_footer(struct spnego_context *spnego_ctx,
                                                auth_level, rpc_out);
                break;
 
-       case DCERPC_AUTH_LEVEL_INTEGRITY:
-               status = NT_STATUS_NOT_IMPLEMENTED;
+       case DCERPC_AUTH_TYPE_NTLMSSP:
+               ntlmssp_ctx = talloc_get_type(auth_ctx,
+                                               struct auth_ntlmssp_state);
+               if (!ntlmssp_ctx) {
+                       status = NT_STATUS_INTERNAL_ERROR;
+                       break;
+               }
+               status = add_ntlmssp_auth_footer(ntlmssp_ctx,
+                                                auth_level, rpc_out);
                break;
 
        default:
@@ -560,6 +568,55 @@ static NTSTATUS add_spnego_auth_footer(struct spnego_context *spnego_ctx,
        return status;
 }
 
+static NTSTATUS get_spnego_auth_footer(TALLOC_CTX *mem_ctx,
+                                       struct spnego_context *sp_ctx,
+                                       enum dcerpc_AuthLevel auth_level,
+                                       DATA_BLOB *data, DATA_BLOB *full_pkt,
+                                       DATA_BLOB *auth_token)
+{
+       enum dcerpc_AuthType auth_type;
+       struct auth_ntlmssp_state *ntlmssp_ctx;
+       struct gse_context *gse_ctx;
+       void *auth_ctx;
+       NTSTATUS status;
+
+       status = spnego_get_negotiated_mech(sp_ctx, &auth_type, &auth_ctx);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       switch (auth_type) {
+       case DCERPC_AUTH_TYPE_KRB5:
+               gse_ctx = talloc_get_type(auth_ctx,
+                                         struct gse_context);
+               if (!gse_ctx) {
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+
+               DEBUG(10, ("KRB5 auth\n"));
+
+               return get_gssapi_auth_footer(mem_ctx, gse_ctx,
+                                               auth_level,
+                                               data, full_pkt,
+                                               auth_token);
+       case DCERPC_AUTH_TYPE_NTLMSSP:
+               ntlmssp_ctx = talloc_get_type(auth_ctx,
+                                         struct auth_ntlmssp_state);
+               if (!ntlmssp_ctx) {
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+
+               DEBUG(10, ("NTLMSSP auth\n"));
+
+               return get_ntlmssp_auth_footer(ntlmssp_ctx,
+                                               auth_level,
+                                               data, full_pkt,
+                                               auth_token);
+       default:
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+}
+
 /**
 * @brief   Append an auth footer according to what is the current mechanism
 *
@@ -618,12 +675,16 @@ NTSTATUS dcerpc_add_auth_footer(struct pipe_auth_data *auth,
                status = NT_STATUS_OK;
                break;
        case DCERPC_AUTH_TYPE_SPNEGO:
-               if (auth->spnego_type != PIPE_AUTH_TYPE_SPNEGO_NTLMSSP) {
-                       return add_spnego_auth_footer(auth->a_u.spnego_state,
-                                                     auth->auth_level,
-                                                     rpc_out);
+               if (auth->spnego_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP) {
+                       /* compat for server code */
+                       return add_ntlmssp_auth_footer(
+                                               auth->a_u.auth_ntlmssp_state,
+                                               auth->auth_level,
+                                               rpc_out);
                }
-               /* fall thorugh */
+               status = add_spnego_auth_footer(auth->a_u.spnego_state,
+                                               auth->auth_level, rpc_out);
+               break;
        case DCERPC_AUTH_TYPE_NTLMSSP:
                status = add_ntlmssp_auth_footer(auth->a_u.auth_ntlmssp_state,
                                                 auth->auth_level,
@@ -731,26 +792,12 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth,
                return NT_STATUS_OK;
 
        case DCERPC_AUTH_TYPE_SPNEGO:
-               if (auth->spnego_type != PIPE_AUTH_TYPE_SPNEGO_NTLMSSP) {
-                       enum dcerpc_AuthType auth_type;
-                       struct gse_context *gse_ctx;
-                       void *auth_ctx;
-
-                       status = spnego_get_negotiated_mech(
-                                               auth->a_u.spnego_state,
-                                               &auth_type, &auth_ctx);
-                       if (!NT_STATUS_IS_OK(status)) {
-                               return status;
-                       }
-                       gse_ctx = talloc_get_type(auth_ctx,
-                                                 struct gse_context);
-                       if (!gse_ctx) {
-                               return NT_STATUS_INVALID_PARAMETER;
-                       }
+               if (auth->spnego_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP) {
+                       /* compat for server code */
+                       DEBUG(10, ("NTLMSSP auth\n"));
 
-                       DEBUG(10, ("KRB5 auth\n"));
-
-                       status = get_gssapi_auth_footer(pkt, gse_ctx,
+                       status = get_ntlmssp_auth_footer(
+                                               auth->a_u.auth_ntlmssp_state,
                                                auth->auth_level,
                                                &data, &full_pkt,
                                                &auth_info.credentials);
@@ -759,7 +806,16 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth,
                        }
                        break;
                }
-               /* fall through */
+
+               status = get_spnego_auth_footer(pkt, auth->a_u.spnego_state,
+                                               auth->auth_level,
+                                               &data, &full_pkt,
+                                               &auth_info.credentials);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+               break;
+
        case DCERPC_AUTH_TYPE_NTLMSSP:
 
                DEBUG(10, ("NTLMSSP auth\n"));
index e733469ac32dbe5c339f682b2062085f0ce8cd57..a0832ce09ff7631b4bf8c5cfb20067f523be7081 100644 (file)
@@ -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;
+       }
+}
+
index 08458b246f74a8960d4553d1c958ee24bf9db8ea..58363fd07234bdc920cba499397c4b9e3dcb7297 100644 (file)
@@ -31,6 +31,12 @@ NTSTATUS spnego_gssapi_init_client(TALLOC_CTX *mem_ctx,
                                   const char *password,
                                   uint32_t add_gss_c_flags,
                                   struct spnego_context **spengo_ctx);
+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);
 
 NTSTATUS spnego_get_client_auth_token(TALLOC_CTX *mem_ctx,
                                      struct spnego_context *sp_ctx,
@@ -43,4 +49,5 @@ NTSTATUS spnego_get_negotiated_mech(struct spnego_context *sp_ctx,
                                    enum dcerpc_AuthType *auth_type,
                                    void **auth_context);
 
+DATA_BLOB spnego_get_session_key(struct spnego_context *sp_ctx);
 #endif /* _DCERPC_SPENGO_H_ */
index e41966f6fb6f64bbc35c0205cce4873d6ca4d08c..5fdfb6374ef0d90f411ee874b7be064da6743f87 100644 (file)
@@ -1247,20 +1247,7 @@ static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
                break;
 
        case DCERPC_AUTH_TYPE_SPNEGO:
-               switch (auth->spnego_type) {
-               case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
-                       ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli,
-                                                       auth->auth_level,
-                                                       &auth_info);
-                       break;
-
-               case PIPE_AUTH_TYPE_SPNEGO_KRB5:
-                       ret = create_spnego_auth_bind_req(cli, auth,
-                                                         &auth_info);
-                       break;
-               default:
-                       return NT_STATUS_INTERNAL_ERROR;
-               }
+               ret = create_spnego_auth_bind_req(cli, auth, &auth_info);
                if (!NT_STATUS_IS_OK(ret)) {
                        return ret;
                }
@@ -1331,17 +1318,17 @@ static NTSTATUS calculate_data_len_tosend(struct rpc_pipe_client *cli,
                /* Treat the same for all authenticated rpc requests. */
                switch(cli->auth->auth_type) {
                case DCERPC_AUTH_TYPE_SPNEGO:
-                       switch (cli->auth->spnego_type) {
-                       case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
+                       status = spnego_get_negotiated_mech(
+                                       cli->auth->a_u.spnego_state,
+                                       &auth_type, &auth_ctx);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
+                       switch (auth_type) {
+                       case DCERPC_AUTH_TYPE_NTLMSSP:
                                *p_auth_len = NTLMSSP_SIG_SIZE;
                                break;
-                       case PIPE_AUTH_TYPE_SPNEGO_KRB5:
-                               status = spnego_get_negotiated_mech(
-                                               cli->auth->a_u.spnego_state,
-                                               &auth_type, &auth_ctx);
-                               if (!NT_STATUS_IS_OK(status)) {
-                                       return status;
-                               }
+                       case DCERPC_AUTH_TYPE_KRB5:
                                gse_ctx = talloc_get_type(auth_ctx,
                                                          struct gse_context);
                                if (!gse_ctx) {
@@ -1986,36 +1973,24 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
                break;
 
        case DCERPC_AUTH_TYPE_SPNEGO:
-               switch (pauth->spnego_type) {
-               case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
-                       /* Need to send alter context request and reply. */
-                       status = rpc_finish_spnego_ntlmssp_bind_send(req,
-                                               state, &auth.credentials);
-                       break;
-
-               case PIPE_AUTH_TYPE_SPNEGO_KRB5:
-                       status = spnego_get_client_auth_token(state,
+               status = spnego_get_client_auth_token(state,
                                                pauth->a_u.spnego_state,
                                                &auth.credentials,
                                                &auth_token);
-                       if (!NT_STATUS_IS_OK(status)) {
-                               break;
-                       }
-                       if (auth_token.length == 0) {
-                               /* Bind complete. */
-                               tevent_req_done(req);
-                               return;
-                       }
-                       if (spnego_require_more_processing(pauth->a_u.spnego_state)) {
-                               status = rpc_bind_next_send(req, state,
-                                                               &auth_token);
-                       } else {
-                               status = rpc_bind_finish_send(req, state,
-                                                               &auth_token);
-                       }
+               if (!NT_STATUS_IS_OK(status)) {
                        break;
-               default:
-                       status = NT_STATUS_INTERNAL_ERROR;
+               }
+               if (auth_token.length == 0) {
+                       /* Bind complete. */
+                       tevent_req_done(req);
+                       return;
+               }
+               if (spnego_require_more_processing(pauth->a_u.spnego_state)) {
+                       status = rpc_bind_next_send(req, state,
+                                                       &auth_token);
+               } else {
+                       status = rpc_bind_finish_send(req, state,
+                                                       &auth_token);
                }
                break;
 
@@ -2358,12 +2333,31 @@ bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
 
 bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16])
 {
+       struct auth_ntlmssp_state *a = NULL;
        struct cli_state *cli;
 
-       if ((rpc_cli->auth->auth_type == DCERPC_AUTH_TYPE_NTLMSSP)
-           || ((rpc_cli->auth->auth_type == DCERPC_AUTH_TYPE_SPNEGO
-                && rpc_cli->auth->spnego_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP))) {
-               memcpy(nt_hash, auth_ntlmssp_get_nt_hash(rpc_cli->auth->a_u.auth_ntlmssp_state), 16);
+       if (rpc_cli->auth->auth_type == DCERPC_AUTH_TYPE_NTLMSSP) {
+               a = rpc_cli->auth->a_u.auth_ntlmssp_state;
+       } else if (rpc_cli->auth->auth_type == DCERPC_AUTH_TYPE_SPNEGO) {
+               enum dcerpc_AuthType auth_type;
+               void *auth_ctx;
+               NTSTATUS status;
+
+               status = spnego_get_negotiated_mech(
+                                       rpc_cli->auth->a_u.spnego_state,
+                                       &auth_type, &auth_ctx);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return false;
+               }
+
+               if (auth_type == DCERPC_AUTH_TYPE_NTLMSSP) {
+                       a = talloc_get_type(auth_ctx,
+                                           struct auth_ntlmssp_state);
+               }
+       }
+
+       if (a) {
+               memcpy(nt_hash, auth_ntlmssp_get_nt_hash(a), 16);
                return true;
        }
 
@@ -2408,7 +2402,6 @@ static int cli_auth_ntlmssp_data_destructor(struct pipe_auth_data *auth)
 
 static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
                                  enum dcerpc_AuthType auth_type,
-                                 enum pipe_auth_type_spnego spnego_type,
                                  enum dcerpc_AuthLevel auth_level,
                                  const char *domain,
                                  const char *username,
@@ -2424,7 +2417,6 @@ static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
        }
 
        result->auth_type = auth_type;
-       result->spnego_type = spnego_type;
        result->auth_level = auth_level;
 
        result->user_name = talloc_strdup(result, username);
@@ -3056,20 +3048,18 @@ NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
  Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
  ****************************************************************************/
 
-static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
-                                                  const struct ndr_syntax_id *interface,
-                                                  enum dcerpc_transport_t transport,
-                                                  bool use_spnego,
-                                                  enum dcerpc_AuthLevel auth_level,
-                                                  const char *domain,
-                                                  const char *username,
-                                                  const char *password,
-                                                  struct rpc_pipe_client **presult)
+NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
+                                  const struct ndr_syntax_id *interface,
+                                  enum dcerpc_transport_t transport,
+                                  enum dcerpc_AuthLevel auth_level,
+                                  const char *domain,
+                                  const char *username,
+                                  const char *password,
+                                  struct rpc_pipe_client **presult)
 {
        struct rpc_pipe_client *result;
        struct pipe_auth_data *auth;
        enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
-       enum pipe_auth_type_spnego spnego_type = PIPE_AUTH_TYPE_SPNEGO_NONE;
        NTSTATUS status;
 
        status = cli_rpc_pipe_open(cli, transport, interface, &result);
@@ -3077,13 +3067,8 @@ static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
                return status;
        }
 
-       if (use_spnego) {
-               auth_type = DCERPC_AUTH_TYPE_SPNEGO;
-               spnego_type = PIPE_AUTH_TYPE_SPNEGO_NTLMSSP;
-       }
-
        status = rpccli_ntlmssp_bind_data(result,
-                                         auth_type, spnego_type, auth_level,
+                                         auth_type, auth_level,
                                          domain, username, password,
                                          &auth);
        if (!NT_STATUS_IS_OK(status)) {
@@ -3113,56 +3098,6 @@ static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
        return status;
 }
 
-/****************************************************************************
- External interface.
- Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10)
- ****************************************************************************/
-
-NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
-                                  const struct ndr_syntax_id *interface,
-                                  enum dcerpc_transport_t transport,
-                                  enum dcerpc_AuthLevel auth_level,
-                                  const char *domain,
-                                  const char *username,
-                                  const char *password,
-                                  struct rpc_pipe_client **presult)
-{
-       return cli_rpc_pipe_open_ntlmssp_internal(cli,
-                                               interface,
-                                               transport,
-                                               false,
-                                               auth_level,
-                                               domain,
-                                               username,
-                                               password,
-                                               presult);
-}
-
-/****************************************************************************
- External interface.
- Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9)
- ****************************************************************************/
-
-NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
-                                         const struct ndr_syntax_id *interface,
-                                         enum dcerpc_transport_t transport,
-                                         enum dcerpc_AuthLevel auth_level,
-                                         const char *domain,
-                                         const char *username,
-                                         const char *password,
-                                         struct rpc_pipe_client **presult)
-{
-       return cli_rpc_pipe_open_ntlmssp_internal(cli,
-                                               interface,
-                                               transport,
-                                               true,
-                                               auth_level,
-                                               domain,
-                                               username,
-                                               password,
-                                               presult);
-}
-
 /****************************************************************************
   Get a the schannel session key out of an already opened netlogon pipe.
  ****************************************************************************/
@@ -3562,6 +3497,74 @@ err_out:
        return status;
 }
 
+NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
+                                         const struct ndr_syntax_id *interface,
+                                         enum dcerpc_transport_t transport,
+                                         enum dcerpc_AuthLevel auth_level,
+                                         const char *domain,
+                                         const char *username,
+                                         const char *password,
+                                         struct rpc_pipe_client **presult)
+{
+       struct rpc_pipe_client *result;
+       struct pipe_auth_data *auth;
+       NTSTATUS status;
+
+       status = cli_rpc_pipe_open(cli, transport, interface, &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       auth = talloc(result, struct pipe_auth_data);
+       if (auth == NULL) {
+               status = NT_STATUS_NO_MEMORY;
+               goto err_out;
+       }
+       auth->auth_type = DCERPC_AUTH_TYPE_SPNEGO;
+       auth->auth_level = auth_level;
+
+       if (!username) {
+               username = "";
+       }
+       auth->user_name = talloc_strdup(auth, username);
+       if (!auth->user_name) {
+               status = NT_STATUS_NO_MEMORY;
+               goto err_out;
+       }
+
+       if (!domain) {
+               domain = "";
+       }
+       auth->domain = talloc_strdup(auth, domain);
+       if (!auth->domain) {
+               status = NT_STATUS_NO_MEMORY;
+               goto err_out;
+       }
+
+       status = spnego_ntlmssp_init_client(auth, auth->auth_level,
+                                           domain, username, password,
+                                           &auth->a_u.spnego_state);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("spnego_init_client returned %s\n",
+                         nt_errstr(status)));
+               goto err_out;
+       }
+
+       status = rpc_pipe_bind(result, auth);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("cli_rpc_pipe_bind failed with error %s\n",
+                         nt_errstr(status)));
+               goto err_out;
+       }
+
+       *presult = result;
+       return NT_STATUS_OK;
+
+err_out:
+       TALLOC_FREE(result);
+       return status;
+}
+
 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
                             struct rpc_pipe_client *cli,
                             DATA_BLOB *session_key)
@@ -3583,15 +3586,8 @@ NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
                                     16);
                break;
        case DCERPC_AUTH_TYPE_SPNEGO:
-               switch (cli->auth->spnego_type) {
-               case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
-                       sk = auth_ntlmssp_get_session_key(
-                                               a->a_u.auth_ntlmssp_state);
-                       break;
-               case PIPE_AUTH_TYPE_SPNEGO_KRB5:
-                       sk = gse_get_session_key(a->a_u.gssapi_state);
-                       break;
-               default:
+               sk = spnego_get_session_key(a->a_u.spnego_state);
+               if (sk.length == 0) {
                        return NT_STATUS_NO_USER_SESSION_KEY;
                }
                break;