Make cli_tcon_andx async
authorVolker Lendecke <vl@samba.org>
Mon, 26 Jan 2009 07:37:13 +0000 (08:37 +0100)
committerVolker Lendecke <vl@samba.org>
Fri, 30 Jan 2009 11:47:59 +0000 (12:47 +0100)
13 files changed:
source3/client/smbspool.c
source3/include/proto.h
source3/libsmb/cliconnect.c
source3/libsmb/clidfs.c
source3/libsmb/libsmb_server.c
source3/libsmb/passchange.c
source3/nmbd/nmbd_synclists.c
source3/torture/locktest.c
source3/torture/masktest.c
source3/torture/torture.c
source3/utils/net_rpc.c
source3/utils/smbcacls.c
source3/winbindd/winbindd_cm.c

index 1910ccd4feefd2d0a8c81602f4333ba48ad8f4cf..7943cf582822fc5f9fdb01900938eb014d2062bd 100644 (file)
@@ -432,10 +432,13 @@ smb_complete_connection(const char *myname,
                return NULL;
        }
 
-       if (!cli_send_tconX(cli, share, "?????", password, strlen(password) + 1)) {
-               fprintf(stderr, "ERROR: Tree connect failed (%s)\n", cli_errstr(cli));
+       nt_status = cli_tcon_andx(cli, share, "?????", password,
+                                 strlen(password) + 1);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               fprintf(stderr, "ERROR: Tree connect failed (%s)\n",
+                       nt_errstr(nt_status));
 
-               if (get_exit_code(cli, cli_nt_error(cli)) == 2) {
+               if (get_exit_code(cli, nt_status) == 2) {
                        *need_auth = true;
                }
 
index 943ab5e3f173f1641f6caa6cd7236d5418d87eee..b06d8d67584ab659d00f74b2f9ef428d6d020c34 100644 (file)
@@ -2328,8 +2328,14 @@ struct async_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
                                               struct cli_state *cli);
 NTSTATUS cli_session_setup_guest_recv(struct async_req *req);
 bool cli_ulogoff(struct cli_state *cli);
-bool cli_send_tconX(struct cli_state *cli, 
-                   const char *share, const char *dev, const char *pass, int passlen);
+struct async_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
+                                    struct event_context *ev,
+                                    struct cli_state *cli,
+                                    const char *share, const char *dev,
+                                    const char *pass, int passlen);
+NTSTATUS cli_tcon_andx_recv(struct async_req *req);
+NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
+                      const char *dev, const char *pass, int passlen);
 bool cli_tdis(struct cli_state *cli);
 void cli_negprot_sendsync(struct cli_state *cli);
 NTSTATUS cli_negprot(struct cli_state *cli);
index e1bba90329fe00d7356ec9d5e72759a32a997d91..ed5adc5694847850dcaa30931e12dd93a7ae2edf 100644 (file)
@@ -1173,13 +1173,17 @@ bool cli_ulogoff(struct cli_state *cli)
  Send a tconX.
 ****************************************************************************/
 
-bool cli_send_tconX(struct cli_state *cli, 
-                   const char *share, const char *dev, const char *pass, int passlen)
+struct async_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
+                                    struct event_context *ev,
+                                    struct cli_state *cli,
+                                    const char *share, const char *dev,
+                                    const char *pass, int passlen)
 {
-       fstring fullshare, pword;
-       char *p;
-       memset(cli->outbuf,'\0',smb_size);
-       memset(cli->inbuf,'\0',smb_size);
+       fstring pword;
+       char *tmp = NULL;
+       struct async_req *result;
+       uint16_t vwv[4];
+       uint8_t *bytes;
 
        fstrcpy(cli->share, share);
 
@@ -1187,9 +1191,10 @@ bool cli_send_tconX(struct cli_state *cli,
        if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
                passlen = 1;
                pass = "";
-       } else if (!pass) {
-               DEBUG(1, ("Server not using user level security and no password supplied.\n"));
-               return False;
+       } else if (pass == NULL) {
+               DEBUG(1, ("Server not using user level security and no "
+                         "password supplied.\n"));
+               goto access_denied;
        }
 
        if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
@@ -1198,28 +1203,32 @@ bool cli_send_tconX(struct cli_state *cli,
                        DEBUG(1, ("Server requested LANMAN password "
                                  "(share-level security) but "
                                  "'client lanman auth' is disabled\n"));
-                       return False;
+                       goto access_denied;
                }
 
                /*
-                * Non-encrypted passwords - convert to DOS codepage before encryption.
+                * Non-encrypted passwords - convert to DOS codepage before
+                * encryption.
                 */
                passlen = 24;
-               SMBencrypt(pass,cli->secblob.data,(uchar *)pword);
+               SMBencrypt(pass, cli->secblob.data, (uchar *)pword);
        } else {
-               if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL|NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)) == 0) {
+               if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
+                                    |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
+                  == 0) {
                        if (!lp_client_plaintext_auth() && (*pass)) {
                                DEBUG(1, ("Server requested plaintext "
                                          "password but 'client plaintext "
                                          "auth' is disabled\n"));
-                               return False;
+                               goto access_denied;
                        }
 
                        /*
-                        * Non-encrypted passwords - convert to DOS codepage before using.
+                        * Non-encrypted passwords - convert to DOS codepage
+                        * before using.
                         */
-                       passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
-
+                       passlen = clistr_push(cli, pword, pass, sizeof(pword),
+                                             STR_TERMINATE);
                } else {
                        if (passlen) {
                                memcpy(pword, pass, passlen);
@@ -1227,52 +1236,139 @@ bool cli_send_tconX(struct cli_state *cli,
                }
        }
 
-       slprintf(fullshare, sizeof(fullshare)-1,
-                "\\\\%s\\%s", cli->desthost, share);
+       SCVAL(vwv+0, 0, 0xFF);
+       SCVAL(vwv+0, 1, 0);
+       SSVAL(vwv+1, 0, 0);
+       SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
+       SSVAL(vwv+3, 0, passlen);
 
-       cli_set_message(cli->outbuf,4, 0, True);
-       SCVAL(cli->outbuf,smb_com,SMBtconX);
-       cli_setup_packet(cli);
+       if (passlen) {
+               bytes = (uint8_t *)talloc_memdup(talloc_tos(), pword, passlen);
+       } else {
+               bytes = talloc_array(talloc_tos(), uint8_t, 0);
+       }
 
-       SSVAL(cli->outbuf,smb_vwv0,0xFF);
-       SSVAL(cli->outbuf,smb_vwv2,TCONX_FLAG_EXTENDED_RESPONSE);
-       SSVAL(cli->outbuf,smb_vwv3,passlen);
+       /*
+        * Add the sharename
+        */
+       tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
+                                        cli->desthost, share);
+       if (tmp == NULL) {
+               TALLOC_FREE(bytes);
+               return NULL;
+       }
+       bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
+                                  NULL);
+       TALLOC_FREE(tmp);
 
-       p = smb_buf(cli->outbuf);
-       if (passlen) {
-               memcpy(p,pword,passlen);
+       /*
+        * Add the devicetype
+        */
+       tmp = talloc_strdup_upper(talloc_tos(), dev);
+       if (tmp == NULL) {
+               TALLOC_FREE(bytes);
+               return NULL;
        }
-       p += passlen;
-       p += clistr_push(cli, p, fullshare, -1, STR_TERMINATE |STR_UPPER);
-       p += clistr_push(cli, p, dev, -1, STR_TERMINATE |STR_UPPER | STR_ASCII);
+       bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
+       TALLOC_FREE(tmp);
 
-       cli_setup_bcc(cli, p);
+       if (bytes == NULL) {
+               return NULL;
+       }
 
-       cli_send_smb(cli);
-       if (!cli_receive_smb(cli))
-               return False;
+       result = cli_request_send(mem_ctx, ev, cli, SMBtconX, 0,
+                                 4, vwv, 0, talloc_get_size(bytes), bytes);
+       TALLOC_FREE(bytes);
+       return result;
 
-       if (cli_is_error(cli))
-               return False;
+ access_denied:
+       result = async_req_new(mem_ctx);
+       if (async_post_status(result, ev, NT_STATUS_ACCESS_DENIED)) {
+               return result;
+       }
+       TALLOC_FREE(result);
+       return NULL;
+}
 
-       clistr_pull(cli->inbuf, cli->dev, smb_buf(cli->inbuf), sizeof(fstring),
-                   -1, STR_TERMINATE|STR_ASCII);
+NTSTATUS cli_tcon_andx_recv(struct async_req *req)
+{
+       struct cli_request *cli_req = talloc_get_type_abort(
+               req->private_data, struct cli_request);
+       struct cli_state *cli = cli_req->cli;
+       uint8_t wct;
+       uint16_t *vwv;
+       uint16_t num_bytes;
+       uint8_t *bytes;
+       NTSTATUS status;
 
-       if (cli->protocol >= PROTOCOL_NT1 &&
-           smb_buflen(cli->inbuf) == 3) {
+       if (async_req_is_error(req, &status)) {
+               return status;
+       }
+
+       status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       clistr_pull(cli_req->inbuf, cli->dev, bytes, sizeof(fstring),
+                   num_bytes, STR_TERMINATE|STR_ASCII);
+
+       if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
                /* almost certainly win95 - enable bug fixes */
                cli->win95 = True;
        }
 
-       /* Make sure that we have the optional support 16-bit field.  WCT > 2 */
-       /* Avoids issues when connecting to Win9x boxes sharing files */
+       /*
+        * Make sure that we have the optional support 16-bit field. WCT > 2.
+        * Avoids issues when connecting to Win9x boxes sharing files
+        */
 
-       cli->dfsroot = False;
-       if ( (CVAL(cli->inbuf, smb_wct))>2 && cli->protocol >= PROTOCOL_LANMAN2 )
-               cli->dfsroot = (SVAL( cli->inbuf, smb_vwv2 ) & SMB_SHARE_IN_DFS) ? True : False;
+       cli->dfsroot = false;
 
-       cli->cnum = SVAL(cli->inbuf,smb_tid);
-       return True;
+       if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
+               cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
+       }
+
+       cli->cnum = SVAL(cli_req->inbuf,smb_tid);
+       return NT_STATUS_OK;
+}
+
+NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
+                      const char *dev, const char *pass, int passlen)
+{
+       TALLOC_CTX *frame = talloc_stackframe();
+       struct event_context *ev;
+       struct async_req *req;
+       NTSTATUS status;
+
+       if (cli->fd_event != NULL) {
+               /*
+                * Can't use sync call while an async call is in flight
+                */
+               status = NT_STATUS_INVALID_PARAMETER;
+               goto fail;
+       }
+
+       ev = event_context_init(frame);
+       if (ev == NULL) {
+               status = NT_STATUS_NO_MEMORY;
+               goto fail;
+       }
+
+       req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
+       if (req == NULL) {
+               status = NT_STATUS_NO_MEMORY;
+               goto fail;
+       }
+
+       while (req->state < ASYNC_REQ_DONE) {
+               event_loop_once(ev);
+       }
+
+       status = cli_tcon_andx_recv(req);
+ fail:
+       TALLOC_FREE(frame);
+       return status;
 }
 
 /****************************************************************************
@@ -1956,8 +2052,9 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli,
        }
 
        if (service) {
-               if (!cli_send_tconX(cli, service, service_type, password, pw_len)) {
-                       nt_status = cli_nt_error(cli);
+               nt_status = cli_tcon_andx(cli, service, service_type, password,
+                                         pw_len);
+               if (!NT_STATUS_IS_OK(nt_status)) {
                        DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
                        cli_shutdown(cli);
                        if (NT_STATUS_IS_OK(nt_status)) {
index f853e4e6701f6b062e1a90c6108d6b6902ec6d6f..e642f169f974eebf442d2adf3b2efd8504c9594a 100644 (file)
@@ -275,9 +275,10 @@ static struct cli_state *do_connect(TALLOC_CTX *ctx,
 
        /* must be a normal share */
 
-       if (!cli_send_tconX(c, sharename, "?????",
-                               password, strlen(password)+1)) {
-               d_printf("tree connect failed: %s\n", cli_errstr(c));
+       status = cli_tcon_andx(c, sharename, "?????",
+                              password, strlen(password)+1);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_printf("tree connect failed: %s\n", nt_errstr(status));
                cli_shutdown(c);
                return NULL;
        }
@@ -1077,7 +1078,7 @@ static bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
 
        /* check for the referral */
 
-       if (!cli_send_tconX(cli, "IPC$", "IPC", NULL, 0)) {
+       if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, "IPC$", "IPC", NULL, 0))) {
                return false;
        }
 
index 0ece5bb649e194b60055812683d98c5b7c9c6a83..6d7a86241a8cc5c3b3284b21c73c2f18b292f7d7 100644 (file)
@@ -300,11 +300,11 @@ SMBC_server(TALLOC_CTX *ctx,
                         * tid.
                         */
 
-                       if (!cli_send_tconX(srv->cli, share, "?????",
-                                            *pp_password,
-                                            strlen(*pp_password)+1)) {
-
-                                errno = SMBC_errno(context, srv->cli);
+                       status = cli_tcon_andx(srv->cli, share, "?????",
+                                              *pp_password,
+                                              strlen(*pp_password)+1);
+                       if (!NT_STATUS_IS_OK(status)) {
+                                errno = map_errno_from_nt_status(status);
                                 cli_shutdown(srv->cli);
                                srv->cli = NULL;
                                 smbc_getFunctionRemoveCachedServer(context)(context,
@@ -501,9 +501,10 @@ again:
 
        DEBUG(4,(" session setup ok\n"));
 
-       if (!cli_send_tconX(c, share, "?????",
-                           *pp_password, strlen(*pp_password)+1)) {
-               errno = SMBC_errno(context, c);
+       status = cli_tcon_andx(c, share, "?????", *pp_password,
+                              strlen(*pp_password)+1);
+       if (!NT_STATUS_IS_OK(status)) {
+               errno = map_errno_from_nt_status(status);
                cli_shutdown(c);
                return NULL;
        }
index 76b06088d68e2f4084ae7f0f878721867de7a1b1..f9ff4b3191ec83a43e4c5b030995501142fa0356 100644 (file)
@@ -138,13 +138,13 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam
                cli_init_creds(cli, user_name, "", old_passwd);
        }
 
-       if (!cli_send_tconX(cli, "IPC$", "IPC", "", 1)) {
-               if (asprintf(err_str, "machine %s rejected the tconX on the IPC$ "
-                        "share. Error was : %s.\n",
-                        remote_machine, cli_errstr(cli)) == -1) {
+       result = cli_tcon_andx(cli, "IPC$", "IPC", "", 1);
+       if (!NT_STATUS_IS_OK(result)) {
+               if (asprintf(err_str, "machine %s rejected the tconX on the "
+                            "IPC$ share. Error was : %s.\n",
+                            remote_machine, nt_errstr(result))) {
                        *err_str = NULL;
                }
-               result = cli_nt_error(cli);
                cli_shutdown(cli);
                return result;
        }
index 3e672aef252abd3baeaf18f76afdbe92f5066d60..5da0da81e5c717a9d0103980f1420237487430b9 100644 (file)
@@ -109,7 +109,7 @@ static void sync_child(char *name, int nm_type,
                return;
        }
 
-       if (!cli_send_tconX(cli, "IPC$", "IPC", "", 1)) {
+       if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, "IPC$", "IPC", "", 1))) {
                cli_shutdown(cli);
                return;
        }
index 1bff95f4f3a950176511a74cf1d19fcdb4e933e3..4e8dcdd09aa5cfbb4483a6a635ba454ea12a9fb6 100644 (file)
@@ -257,9 +257,10 @@ static struct cli_state *connect_one(char *share, int snum)
        
        DEBUG(4,(" session setup ok\n"));
 
-       if (!cli_send_tconX(c, share, "?????",
-                           password[snum], strlen(password[snum])+1)) {
-               DEBUG(0,("tree connect failed: %s\n", cli_errstr(c)));
+       status = cli_tcon_andx(c, share, "?????", password[snum],
+                              strlen(password[snum])+1);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("tree connect failed: %s\n", nt_errstr(status)));
                cli_shutdown(c);
                return NULL;
        }
index 2c3bda1d436a2155613210cf014aef22cb1ce649..fb562c80755d396cb9d51ed5eff2da21dbf6d90b 100644 (file)
@@ -249,9 +249,10 @@ static struct cli_state *connect_one(char *share)
 
        DEBUG(4,(" session setup ok\n"));
 
-       if (!cli_send_tconX(c, share, "?????",
-                           password, strlen(password)+1)) {
-               DEBUG(0,("tree connect failed: %s\n", cli_errstr(c)));
+       status = cli_tcon_andx(c, share, "?????", password,
+                              strlen(password)+1);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("tree connect failed: %s\n", nt_errstr(status)));
                cli_shutdown(c);
                return NULL;
        }
index 85233bc0ae6b95c4cba30c1f003436a78e2115bb..1210a36a392714774e5ccaa1c3d0431afa42a25d 100644 (file)
@@ -1101,6 +1101,7 @@ static bool run_tcon_test(int dummy)
        uint16 vuid1, vuid2;
        char buf[4];
        bool ret = True;
+       NTSTATUS status;
 
        memset(buf, '\0', sizeof(buf));
 
@@ -1127,10 +1128,11 @@ static bool run_tcon_test(int dummy)
                return False;
        }
 
-       if (!cli_send_tconX(cli, share, "?????",
-                           password, strlen(password)+1)) {
+       status = cli_tcon_andx(cli, share, "?????",
+                              password, strlen(password)+1);
+       if (!NT_STATUS_IS_OK(status)) {
                printf("%s refused 2nd tree connect (%s)\n", host,
-                          cli_errstr(cli));
+                      nt_errstr(status));
                cli_shutdown(cli);
                return False;
        }
@@ -1239,14 +1241,14 @@ static bool tcon_devtest(struct cli_state *cli,
                         const char *return_devtype,
                         NTSTATUS expected_error)
 {
-       bool status;
+       NTSTATUS status;
        bool ret;
 
-       status = cli_send_tconX(cli, myshare, devtype,
-                               password, strlen(password)+1);
+       status = cli_tcon_andx(cli, myshare, devtype,
+                              password, strlen(password)+1);
 
        if (NT_STATUS_IS_OK(expected_error)) {
-               if (status) {
+               if (NT_STATUS_IS_OK(status)) {
                        if (strcmp(cli->dev, return_devtype) == 0) {
                                ret = True;
                        } else { 
@@ -1264,7 +1266,7 @@ static bool tcon_devtest(struct cli_state *cli,
                }
                cli_tdis(cli);
        } else {
-               if (status) {
+               if (NT_STATUS_IS_OK(status)) {
                        printf("tconx to share %s with type %s "
                               "should have failed but succeeded\n",
                               myshare, devtype);
@@ -2157,7 +2159,7 @@ static bool run_fdsesstest(int dummy)
                return False;
 
        saved_cnum = cli->cnum;
-       if (!cli_send_tconX(cli, share, "?????", "", 1))
+       if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, share, "?????", "", 1)))
                return False;
        new_cnum = cli->cnum;
        cli->cnum = saved_cnum;
index 0f59f027462b7d03155a830664af8e1216222842..a37bbbd56671eb03fc142ab9aec4a9bf5a7e3881 100644 (file)
@@ -3022,7 +3022,7 @@ static int rpc_share_list(struct net_context *c, int argc, const char **argv)
 
 static bool check_share_availability(struct cli_state *cli, const char *netname)
 {
-       if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
+       if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, netname, "A:", "", 0))) {
                d_printf("skipping   [%s]: not a file share.\n", netname);
                return false;
        }
@@ -4281,7 +4281,7 @@ static void show_userlist(struct rpc_pipe_client *pipe_hnd,
 
        cnum = cli->cnum;
 
-       if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
+       if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, netname, "A:", "", 0))) {
                return;
        }
 
index f07b5011c8ac10c09d9f9c29f7e87420b8502f61..c12778f8c71f820c1badf1af1828bb771e76739d 100644 (file)
@@ -76,8 +76,9 @@ static NTSTATUS cli_lsa_lookup_sid(struct cli_state *cli,
        char **domains;
        char **names;
 
-       if (!cli_send_tconX(cli, "IPC$", "?????", "", 0)) {
-               return cli_nt_error(cli);
+       status = cli_tcon_andx(cli, "IPC$", "?????", "", 0);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
        status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
@@ -124,8 +125,9 @@ static NTSTATUS cli_lsa_lookup_name(struct cli_state *cli,
        DOM_SID *sids;
        enum lsa_SidType *types;
 
-       if (!cli_send_tconX(cli, "IPC$", "?????", "", 0)) {
-               return cli_nt_error(cli);
+       status = cli_tcon_andx(cli, "IPC$", "?????", "", 0);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
        status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
index ab1218c560cc470dc5f4b98f01cd4f8bb1f137e4..35768fe7f2492c21fcd28be01b88fb818d6c8650 100644 (file)
@@ -961,15 +961,10 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
 
        winbindd_set_locator_kdc_envs(domain);
 
-       if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
-
-               result = cli_nt_error(*cli);
+       result = cli_tcon_andx(*cli, "IPC$", "IPC", "", 0);
 
+       if (!NT_STATUS_IS_OK(result)) {
                DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
-
-               if (NT_STATUS_IS_OK(result))
-                       result = NT_STATUS_UNSUCCESSFUL;
-
                goto done;
        }