]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
Revert "Make use of rpccli_xxx_bind_data"
authorVolker Lendecke <vl@samba.org>
Fri, 25 Apr 2008 14:31:08 +0000 (16:31 +0200)
committerVolker Lendecke <vl@samba.org>
Fri, 25 Apr 2008 14:31:08 +0000 (16:31 +0200)
This reverts commit f9bc336affd2ce21a3c62880ecea2622f35653d1.

source/include/client.h
source/rpc_client/cli_pipe.c

index 5ab457a2abf17932478d10d0923406295b7ca516..3459ae20d0439f2c98058128743de5b0fbb2dca6 100644 (file)
@@ -58,6 +58,7 @@ struct cli_pipe_auth_data {
                NTLMSSP_STATE *ntlmssp_state;
                struct kerberos_auth_struct *kerberos_auth;
        } a_u;
+       void (*cli_auth_data_free_func)(struct cli_pipe_auth_data *);
 };
 
 struct rpc_pipe_client {
index 1897cff18e8cac54e0b4106df112abbd0d90f75f..991029d2036bd781841575c73f8453e4f5c672e4 100644 (file)
@@ -1994,7 +1994,8 @@ static NTSTATUS rpc_finish_spnego_ntlmssp_bind(struct rpc_pipe_client *cli,
 ****************************************************************************/
 
 static NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
-                             struct cli_pipe_auth_data *auth)
+                       enum pipe_auth_type auth_type,
+                       enum pipe_auth_level auth_level)
 {
        RPC_HDR hdr;
        RPC_HDR_BA hdr_ba;
@@ -2006,10 +2007,8 @@ static NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
        DEBUG(5,("Bind RPC Pipe[%x]: %s auth_type %u, auth_level %u\n",
                (unsigned int)cli->fnum,
                cli->pipe_name,
-               (unsigned int)auth->auth_type,
-               (unsigned int)auth->auth_level ));
-
-       cli->auth = talloc_move(cli, &auth);
+               (unsigned int)auth_type,
+               (unsigned int)auth_level ));
 
        prs_init_empty(&rpc_out, talloc_tos(), MARSHALL);
 
@@ -2019,8 +2018,8 @@ static NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
        status = create_rpc_bind_req(cli, &rpc_out, rpc_call_id,
                                cli->abstract_syntax,
                                cli->transfer_syntax,
-                               cli->auth->auth_type,
-                               cli->auth->auth_level);
+                               auth_type,
+                               auth_level);
 
        if (!NT_STATUS_IS_OK(status)) {
                prs_mem_free(&rpc_out);
@@ -2068,7 +2067,7 @@ static NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
        cli->max_recv_frag = hdr_ba.bba.max_rsize;
 
        /* For authenticated binds we may need to do 3 or 4 leg binds. */
-       switch(cli->auth->auth_type) {
+       switch(auth_type) {
 
                case PIPE_AUTH_TYPE_NONE:
                case PIPE_AUTH_TYPE_SCHANNEL:
@@ -2077,10 +2076,8 @@ static NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
 
                case PIPE_AUTH_TYPE_NTLMSSP:
                        /* Need to send AUTH3 packet - no reply. */
-                       status = rpc_finish_auth3_bind(
-                               cli, &hdr, &rbuf, rpc_call_id,
-                               cli->auth->auth_type,
-                               cli->auth->auth_level);
+                       status = rpc_finish_auth3_bind(cli, &hdr, &rbuf, rpc_call_id,
+                                               auth_type, auth_level);
                        if (!NT_STATUS_IS_OK(status)) {
                                prs_mem_free(&rbuf);
                                return status;
@@ -2089,10 +2086,10 @@ static NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
 
                case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
                        /* Need to send alter context request and reply. */
-                       status = rpc_finish_spnego_ntlmssp_bind(
-                               cli, &hdr, &rbuf, rpc_call_id,
-                               cli->abstract_syntax, cli->transfer_syntax,
-                               cli->auth->auth_type, cli->auth->auth_level);
+                       status = rpc_finish_spnego_ntlmssp_bind(cli, &hdr, &rbuf, rpc_call_id,
+                                               cli->abstract_syntax,
+                                               cli->transfer_syntax,
+                                               auth_type, auth_level);
                        if (!NT_STATUS_IS_OK(status)) {
                                prs_mem_free(&rbuf);
                                return status;
@@ -2103,23 +2100,22 @@ static NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
                        /* */
 
                default:
-                       DEBUG(0,("cli_finish_bind_auth: unknown auth type "
-                                "%u\n", (unsigned int)cli->auth->auth_type));
+                       DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
+                               (unsigned int)auth_type ));
                        prs_mem_free(&rbuf);
                        return NT_STATUS_INVALID_INFO_CLASS;
        }
 
        /* For NTLMSSP ensure the server gave us the auth_level we wanted. */
-       if (cli->auth->auth_type == PIPE_AUTH_TYPE_NTLMSSP
-           || cli->auth->auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP) {
-               if (cli->auth->auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
+       if (auth_type == PIPE_AUTH_TYPE_NTLMSSP || auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP) {
+               if (auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
                        if (!(cli->auth->a_u.ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN)) {
                                DEBUG(0,("cli_finish_bind_auth: requested NTLMSSSP signing and server refused.\n"));
                                prs_mem_free(&rbuf);
                                return NT_STATUS_INVALID_PARAMETER;
                        }
                }
-               if (cli->auth->auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
+               if (auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
                        if (!(cli->auth->a_u.ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL)) {
                                DEBUG(0,("cli_finish_bind_auth: requested NTLMSSSP sealing and server refused.\n"));
                                prs_mem_free(&rbuf);
@@ -2128,6 +2124,11 @@ static NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
                }
        }
 
+       /* Pipe is bound - set up auth_type and auth_level data. */
+
+       cli->auth->auth_type = auth_type;
+       cli->auth->auth_level = auth_level;
+
        prs_mem_free(&rbuf);
        return NT_STATUS_OK;
 }
@@ -2172,6 +2173,10 @@ static int rpc_pipe_destructor(struct rpc_pipe_client *p)
                          p->desthost, cli_errstr(p->cli)));
        }
 
+       if (p->auth->cli_auth_data_free_func) {
+               (*p->auth->cli_auth_data_free_func)(p->auth);
+       }
+
        DEBUG(10, ("rpc_pipe_destructor: closed pipe %s to machine %s\n",
                   p->pipe_name, p->desthost ));
 
@@ -2323,12 +2328,12 @@ static int cli_auth_kerberos_data_destructor(struct kerberos_auth_struct *auth)
        return 0;
 }
 
-NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx,
-                                  enum pipe_auth_level auth_level,
-                                  const char *service_princ,
-                                  const char *username,
-                                  const char *password,
-                                  struct cli_pipe_auth_data **presult)
+NTSTATUS rpccli_krb5_bind_data(TALLOC_CTX *mem_ctx,
+                              enum pipe_auth_level auth_level,
+                              const char *service_princ,
+                              const char *username,
+                              const char *password,
+                              struct cli_pipe_auth_data **presult)
 {
        struct cli_pipe_auth_data *result;
 
@@ -2414,16 +2419,31 @@ static struct rpc_pipe_client *cli_rpc_pipe_open(struct cli_state *cli, int pipe
                return NULL;
        }
 
+       result->auth = TALLOC_ZERO_P(result, struct cli_pipe_auth_data);
+       if (result->auth == NULL) {
+               *perr = NT_STATUS_NO_MEMORY;
+               TALLOC_FREE(result);
+               return NULL;
+       }
+
        result->pipe_name = cli_get_pipe_name(pipe_idx);
 
        result->cli = cli;
        result->abstract_syntax = pipe_names[pipe_idx].abstr_syntax;
        result->transfer_syntax = pipe_names[pipe_idx].trans_syntax;
+       result->auth->auth_type = PIPE_AUTH_TYPE_NONE;
+       result->auth->auth_level = PIPE_AUTH_LEVEL_NONE;
+
+       result->auth->domain = talloc_strdup(result, cli->domain);
+       result->auth->user_name = talloc_strdup(result, cli->user_name);
        result->desthost = talloc_strdup(result, cli->desthost);
        result->srv_name_slash = talloc_asprintf_strupper_m(
                result, "\\\\%s", result->desthost);
 
-       if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
+       if ((result->auth->domain == NULL)
+           || (result->auth->user_name == NULL)
+           || (result->desthost == NULL)
+           || (result->srv_name_slash == NULL)) {
                *perr = NT_STATUS_NO_MEMORY;
                TALLOC_FREE(result);
                return NULL;
@@ -2467,22 +2487,13 @@ static struct rpc_pipe_client *cli_rpc_pipe_open(struct cli_state *cli, int pipe
 struct rpc_pipe_client *cli_rpc_pipe_open_noauth(struct cli_state *cli, int pipe_idx, NTSTATUS *perr)
 {
        struct rpc_pipe_client *result;
-       struct cli_pipe_auth_data *auth;
 
        result = cli_rpc_pipe_open(cli, pipe_idx, perr);
        if (result == NULL) {
                return NULL;
        }
 
-       *perr = rpccli_anon_bind_data(result, &auth);
-       if (!NT_STATUS_IS_OK(*perr)) {
-               DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
-                         nt_errstr(*perr)));
-               TALLOC_FREE(result);
-               return NULL;
-       }
-
-       *perr = rpc_pipe_bind(result, auth);
+       *perr = rpc_pipe_bind(result, PIPE_AUTH_TYPE_NONE, PIPE_AUTH_LEVEL_NONE);
        if (!NT_STATUS_IS_OK(*perr)) {
                int lvl = 0;
                if (rpccli_is_pipe_idx(result, PI_DSSETUP)) {
@@ -2502,6 +2513,18 @@ struct rpc_pipe_client *cli_rpc_pipe_open_noauth(struct cli_state *cli, int pipe
        return result;
 }
 
+/****************************************************************************
+ Free function for NTLMSSP auth.
+ ****************************************************************************/
+
+static void cli_ntlmssp_auth_free(struct cli_pipe_auth_data *auth)
+{
+       if (auth->a_u.ntlmssp_state) {
+               ntlmssp_end(&auth->a_u.ntlmssp_state);
+               auth->a_u.ntlmssp_state = NULL;
+       }
+}
+
 /****************************************************************************
  Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
  ****************************************************************************/
@@ -2516,24 +2539,66 @@ static struct rpc_pipe_client *cli_rpc_pipe_open_ntlmssp_internal(struct cli_sta
                                                NTSTATUS *perr)
 {
        struct rpc_pipe_client *result;
-       struct cli_pipe_auth_data *auth;
+       NTLMSSP_STATE *ntlmssp_state = NULL;
 
        result = cli_rpc_pipe_open(cli, pipe_idx, perr);
        if (result == NULL) {
                return NULL;
        }
 
-       *perr = rpccli_ntlmssp_bind_data(
-               result, auth_type, auth_level, domain, username,
-               cli->pwd.null_pwd ? NULL : password, &auth);
+       result->auth->cli_auth_data_free_func = cli_ntlmssp_auth_free;
+
+       TALLOC_FREE(result->auth->domain);
+       TALLOC_FREE(result->auth->user_name);
+
+       result->auth->domain = talloc_strdup(result, domain);
+       result->auth->user_name = talloc_strdup(result, username);
+
+       if ((result->auth->domain == NULL)
+           || (result->auth->user_name == NULL)) {
+               *perr = NT_STATUS_NO_MEMORY;
+               goto err;
+       }
+
+       *perr = ntlmssp_client_start(&ntlmssp_state);
        if (!NT_STATUS_IS_OK(*perr)) {
-               DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
-                         nt_errstr(*perr)));
-               TALLOC_FREE(result);
-               return NULL;
+               goto err;
+       }
+
+       result->auth->a_u.ntlmssp_state = ntlmssp_state;
+
+       *perr = ntlmssp_set_username(ntlmssp_state, username);
+       if (!NT_STATUS_IS_OK(*perr)) {
+               goto err;
+       }
+
+       *perr = ntlmssp_set_domain(ntlmssp_state, domain);
+       if (!NT_STATUS_IS_OK(*perr)) {
+               goto err;
+       }
+
+       if (cli->pwd.null_pwd) {
+               *perr = ntlmssp_set_password(ntlmssp_state, NULL);
+               if (!NT_STATUS_IS_OK(*perr)) {
+                       goto err;
+               }
+       } else {
+               *perr = ntlmssp_set_password(ntlmssp_state, password);
+               if (!NT_STATUS_IS_OK(*perr)) {
+                       goto err;
+               }
+       }
+
+       /* Turn off sign+seal to allow selected auth level to turn it back on. */
+       ntlmssp_state->neg_flags &= ~(NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL);
+
+       if (auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
+               ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
+       } else if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) {
+               ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN;
        }
 
-       *perr = rpc_pipe_bind(result, auth);
+       *perr = rpc_pipe_bind(result, auth_type, auth_level);
        if (!NT_STATUS_IS_OK(*perr)) {
                DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
                        nt_errstr(*perr) ));
@@ -2691,23 +2756,31 @@ struct rpc_pipe_client *cli_rpc_pipe_open_schannel_with_key(struct cli_state *cl
                                        NTSTATUS *perr)
 {
        struct rpc_pipe_client *result;
-       struct cli_pipe_auth_data *auth;
 
        result = cli_rpc_pipe_open(cli, pipe_idx, perr);
        if (result == NULL) {
                return NULL;
        }
 
-       *perr = rpccli_schannel_bind_data(result, domain, auth_level,
-                                         pdc, &auth);
-       if (!NT_STATUS_IS_OK(*perr)) {
-               DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
-                         nt_errstr(*perr)));
+       result->auth->a_u.schannel_auth = TALLOC_ZERO_P(
+               result, struct schannel_auth_struct);
+       if (!result->auth->a_u.schannel_auth) {
                TALLOC_FREE(result);
+               *perr = NT_STATUS_NO_MEMORY;
                return NULL;
        }
 
-       *perr = rpc_pipe_bind(result, auth);
+       TALLOC_FREE(result->auth->domain);
+       result->auth->domain = talloc_strdup(result, domain);
+       if (result->auth->domain == NULL) {
+               TALLOC_FREE(result);
+               *perr = NT_STATUS_NO_MEMORY;
+               return NULL;
+       }
+
+       memcpy(result->auth->a_u.schannel_auth->sess_key, pdc->sess_key, 16);
+
+       *perr = rpc_pipe_bind(result, PIPE_AUTH_TYPE_SCHANNEL, auth_level);
        if (!NT_STATUS_IS_OK(*perr)) {
                DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: cli_rpc_pipe_bind failed with error %s\n",
                        nt_errstr(*perr) ));
@@ -2828,6 +2901,19 @@ struct rpc_pipe_client *cli_rpc_pipe_open_schannel(struct cli_state *cli,
        return result;
 }
 
+#ifdef HAVE_KRB5
+
+/****************************************************************************
+ Free function for the kerberos spcific data.
+ ****************************************************************************/
+
+static void kerberos_auth_struct_free(struct cli_pipe_auth_data *a)
+{
+       data_blob_free(&a->a_u.kerberos_auth->session_key);
+}
+
+#endif
+
 /****************************************************************************
  Open a named pipe to an SMB server and bind using krb5 (bind type 16).
  The idea is this can be called with service_princ, username and password all
@@ -2844,23 +2930,43 @@ struct rpc_pipe_client *cli_rpc_pipe_open_krb5(struct cli_state *cli,
 {
 #ifdef HAVE_KRB5
        struct rpc_pipe_client *result;
-       struct cli_pipe_auth_data *auth;
 
        result = cli_rpc_pipe_open(cli, pipe_idx, perr);
        if (result == NULL) {
                return NULL;
        }
 
-       *perr = rpccli_kerberos_bind_data(result, auth_level, service_princ,
-                                         username, password, &auth);
-       if (!NT_STATUS_IS_OK(*perr)) {
-               DEBUG(0, ("rpccli_kerberos_bind_data returned %s\n",
-                         nt_errstr(*perr)));
+       /* Default service principal is "desthost$@realm" */
+       if (!service_princ) {
+               service_princ = talloc_asprintf(result, "%s$@%s",
+                                               cli->desthost, lp_realm() );
+               if (!service_princ) {
+                       TALLOC_FREE(result);
+                       return NULL;
+               }
+       }
+
+       /* Only get a new TGT if username/password are given. */
+       if (username && password) {
+               int ret = kerberos_kinit_password(username, password, 0, NULL);
+               if (ret) {
+                       TALLOC_FREE(result);
+                       return NULL;
+               }
+       }
+
+       result->auth->a_u.kerberos_auth = TALLOC_ZERO_P(
+               result, struct kerberos_auth_struct);
+       if (!result->auth->a_u.kerberos_auth) {
                TALLOC_FREE(result);
+               *perr = NT_STATUS_NO_MEMORY;
                return NULL;
        }
 
-       *perr = rpc_pipe_bind(result, auth);
+       result->auth->a_u.kerberos_auth->service_principal = service_princ;
+       result->auth->cli_auth_data_free_func = kerberos_auth_struct_free;
+
+       *perr = rpc_pipe_bind(result, PIPE_AUTH_TYPE_KRB5, auth_level);
        if (!NT_STATUS_IS_OK(*perr)) {
                DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed with error %s\n",
                        nt_errstr(*perr) ));