s3 torture: Prevent smbcli segfault when running smbtorture3 against an smbd with...
[samba.git] / source3 / libsmb / cliconnect.c
index a2409b69801242903e03fd55241cbbba9bcf0679..fa79ebcea362606919f4dc409af0061758fdaa2d 100644 (file)
@@ -3,17 +3,17 @@
    client connect/disconnect routines
    Copyright (C) Andrew Tridgell 1994-1998
    Copyright (C) Andrew Bartlett 2001-2003
-   
+
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -105,7 +105,7 @@ static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli,
        cli_set_message(cli->outbuf,10, 0, True);
        SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
        cli_setup_packet(cli);
-       
+
        SCVAL(cli->outbuf,smb_vwv0,0xFF);
        SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
        SSVAL(cli->outbuf,smb_vwv3,2);
@@ -131,7 +131,7 @@ static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli,
        if (cli_is_error(cli)) {
                return cli_nt_error(cli);
        }
-       
+
        /* use the returned vuid from now on */
        cli->vuid = SVAL(cli->inbuf,smb_uid);   
        status = cli_set_username(cli, user);
@@ -360,14 +360,14 @@ static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
        char *p;
        NTSTATUS status;
        fstring lanman;
-       
+
        fstr_sprintf( lanman, "Samba %s", samba_version_string());
 
        memset(cli->outbuf, '\0', smb_size);
        cli_set_message(cli->outbuf,13,0,True);
        SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
        cli_setup_packet(cli);
-                       
+
        SCVAL(cli->outbuf,smb_vwv0,0xFF);
        SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
        SSVAL(cli->outbuf,smb_vwv3,2);
@@ -376,9 +376,9 @@ static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
        SSVAL(cli->outbuf,smb_vwv8,0);
        SIVAL(cli->outbuf,smb_vwv11,capabilities); 
        p = smb_buf(cli->outbuf);
-       
+
        /* check wether to send the ASCII or UNICODE version of the password */
-       
+
        if ( (capabilities & CAP_UNICODE) == 0 ) {
                p += clistr_push(cli, p, pass, -1, STR_TERMINATE); /* password */
                SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf)));
@@ -394,7 +394,7 @@ static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
                p += clistr_push(cli, p, pass, -1, STR_UNICODE|STR_TERMINATE); /* unicode password */
                SSVAL(cli->outbuf,smb_vwv8,PTR_DIFF(p, smb_buf(cli->outbuf))-1);        
        }
-       
+
        p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */
        p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */
        p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
@@ -404,9 +404,9 @@ static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
        if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
                return cli_nt_error(cli);
        }
-       
+
        show_msg(cli->inbuf);
-       
+
        if (cli_is_error(cli)) {
                return cli_nt_error(cli);
        }
@@ -525,7 +525,7 @@ static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
        cli_set_message(cli->outbuf,13,0,True);
        SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
        cli_setup_packet(cli);
-                       
+
        SCVAL(cli->outbuf,smb_vwv0,0xFF);
        SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
        SSVAL(cli->outbuf,smb_vwv3,2);
@@ -575,7 +575,7 @@ static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
 
        /* use the returned vuid from now on */
        cli->vuid = SVAL(cli->inbuf,smb_uid);
-       
+
        p = smb_buf(cli->inbuf);
        p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
                         -1, STR_TERMINATE);
@@ -606,101 +606,6 @@ end:
        return result;
 }
 
-/****************************************************************************
- Send a extended security session setup blob
-****************************************************************************/
-
-static bool cli_session_setup_blob_send(struct cli_state *cli, DATA_BLOB blob)
-{
-       uint32 capabilities = cli_session_setup_capabilities(cli);
-       char *p;
-
-       capabilities |= CAP_EXTENDED_SECURITY;
-
-       /* send a session setup command */
-       memset(cli->outbuf,'\0',smb_size);
-
-       cli_set_message(cli->outbuf,12,0,True);
-       SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
-
-       cli_setup_packet(cli);
-
-       SCVAL(cli->outbuf,smb_vwv0,0xFF);
-       SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
-       SSVAL(cli->outbuf,smb_vwv3,2);
-       SSVAL(cli->outbuf,smb_vwv4,1);
-       SIVAL(cli->outbuf,smb_vwv5,0);
-       SSVAL(cli->outbuf,smb_vwv7,blob.length);
-       SIVAL(cli->outbuf,smb_vwv10,capabilities); 
-       p = smb_buf(cli->outbuf);
-       memcpy(p, blob.data, blob.length);
-       p += blob.length;
-       p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
-       p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
-       cli_setup_bcc(cli, p);
-       return cli_send_smb(cli);
-}
-
-/****************************************************************************
- Send a extended security session setup blob, returning a reply blob.
-****************************************************************************/
-
-static DATA_BLOB cli_session_setup_blob_receive(struct cli_state *cli)
-{
-       DATA_BLOB blob2 = data_blob_null;
-       char *p;
-       size_t len;
-
-       if (!cli_receive_smb(cli))
-               return blob2;
-
-       show_msg(cli->inbuf);
-
-       if (cli_is_error(cli) && !NT_STATUS_EQUAL(cli_nt_error(cli),
-                                                 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
-               return blob2;
-       }
-
-       /* use the returned vuid from now on */
-       cli->vuid = SVAL(cli->inbuf,smb_uid);
-
-       p = smb_buf(cli->inbuf);
-
-       blob2 = data_blob(p, SVAL(cli->inbuf, smb_vwv3));
-
-       p += blob2.length;
-       p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
-                        -1, STR_TERMINATE);
-
-       /* w2k with kerberos doesn't properly null terminate this field */
-       len = smb_bufrem(cli->inbuf, p);
-       if (p + len < cli->inbuf + cli->bufsize+SAFETY_MARGIN - 2) {
-               char *end_of_buf = p + len;
-
-               SSVAL(p, len, 0);
-               /* Now it's null terminated. */
-               p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
-                       -1, STR_TERMINATE);
-               /*
-                * See if there's another string. If so it's the
-                * server domain (part of the 'standard' Samba
-                * server signature).
-                */
-               if (p < end_of_buf) {
-                       p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
-                               -1, STR_TERMINATE);
-               }
-       } else {
-               /*
-                * No room to null terminate so we can't see if there
-                * is another string (server_domain) afterwards.
-                */
-               p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
-                                len, 0);
-       }
-       return blob2;
-}
-
 /* The following is calculated from :
  * (smb_size-4) = 35
  * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
@@ -1558,25 +1463,88 @@ NTSTATUS cli_session_setup(struct cli_state *cli,
  Send a uloggoff.
 *****************************************************************************/
 
-bool cli_ulogoff(struct cli_state *cli)
+struct cli_ulogoff_state {
+       struct cli_state *cli;
+       uint16_t vwv[2];
+};
+
+static void cli_ulogoff_done(struct tevent_req *subreq);
+
+struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
+                                   struct tevent_context *ev,
+                                   struct cli_state *cli)
 {
-       memset(cli->outbuf,'\0',smb_size);
-       cli_set_message(cli->outbuf,2,0,True);
-       SCVAL(cli->outbuf,smb_com,SMBulogoffX);
-       cli_setup_packet(cli);
-       SSVAL(cli->outbuf,smb_vwv0,0xFF);
-       SSVAL(cli->outbuf,smb_vwv2,0);  /* no additional info */
+       struct tevent_req *req, *subreq;
+       struct cli_ulogoff_state *state;
 
-       cli_send_smb(cli);
-       if (!cli_receive_smb(cli))
-               return False;
+       req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
+       if (req == NULL) {
+               return NULL;
+       }
+       state->cli = cli;
 
-       if (cli_is_error(cli)) {
-               return False;
+       SCVAL(state->vwv+0, 0, 0xFF);
+       SCVAL(state->vwv+1, 0, 0);
+       SSVAL(state->vwv+2, 0, 0);
+
+       subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
+                             0, NULL);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
        }
+       tevent_req_set_callback(subreq, cli_ulogoff_done, req);
+       return req;
+}
+
+static void cli_ulogoff_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct cli_ulogoff_state *state = tevent_req_data(
+               req, struct cli_ulogoff_state);
+       NTSTATUS status;
 
-        cli->vuid = -1;
-        return True;
+       status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               tevent_req_nterror(req, status);
+               return;
+       }
+       state->cli->vuid = -1;
+       tevent_req_done(req);
+}
+
+NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
+{
+       return tevent_req_simple_recv_ntstatus(req);
+}
+
+NTSTATUS cli_ulogoff(struct cli_state *cli)
+{
+       struct tevent_context *ev;
+       struct tevent_req *req;
+       NTSTATUS status = NT_STATUS_NO_MEMORY;
+
+       if (cli_has_async_calls(cli)) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+       ev = tevent_context_init(talloc_tos());
+       if (ev == NULL) {
+               goto fail;
+       }
+       req = cli_ulogoff_send(ev, ev, cli);
+       if (req == NULL) {
+               goto fail;
+       }
+       if (!tevent_req_poll_ntstatus(req, ev, &status)) {
+               goto fail;
+       }
+       status = cli_ulogoff_recv(req);
+fail:
+       TALLOC_FREE(ev);
+       if (!NT_STATUS_IS_OK(status)) {
+               cli_set_error(cli, status);
+       }
+       return status;
 }
 
 /****************************************************************************
@@ -1605,6 +1573,8 @@ struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
        char *tmp = NULL;
        uint8_t *bytes;
 
+       *psmbreq = NULL;
+
        req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
        if (req == NULL) {
                return NULL;
@@ -1740,6 +1710,9 @@ struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
        if (req == NULL) {
                return NULL;
        }
+       if (subreq == NULL) {
+               return req;
+       }
        status = cli_smb_req_send(subreq);
        if (!NT_STATUS_IS_OK(status)) {
                tevent_req_nterror(req, status);
@@ -1843,24 +1816,83 @@ NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
  Send a tree disconnect.
 ****************************************************************************/
 
-bool cli_tdis(struct cli_state *cli)
+struct cli_tdis_state {
+       struct cli_state *cli;
+};
+
+static void cli_tdis_done(struct tevent_req *subreq);
+
+struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
+                                struct tevent_context *ev,
+                                struct cli_state *cli)
 {
-       memset(cli->outbuf,'\0',smb_size);
-       cli_set_message(cli->outbuf,0,0,True);
-       SCVAL(cli->outbuf,smb_com,SMBtdis);
-       SSVAL(cli->outbuf,smb_tid,cli->cnum);
-       cli_setup_packet(cli);
+       struct tevent_req *req, *subreq;
+       struct cli_tdis_state *state;
 
-       cli_send_smb(cli);
-       if (!cli_receive_smb(cli))
-               return False;
+       req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
+       if (req == NULL) {
+               return NULL;
+       }
+       state->cli = cli;
 
-       if (cli_is_error(cli)) {
-               return False;
+       subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
        }
+       tevent_req_set_callback(subreq, cli_tdis_done, req);
+       return req;
+}
 
-       cli->cnum = -1;
-       return True;
+static void cli_tdis_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct cli_tdis_state *state = tevent_req_data(
+               req, struct cli_tdis_state);
+       NTSTATUS status;
+
+       status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
+       TALLOC_FREE(subreq);
+       if (!NT_STATUS_IS_OK(status)) {
+               tevent_req_nterror(req, status);
+               return;
+       }
+       state->cli->cnum = -1;
+       tevent_req_done(req);
+}
+
+NTSTATUS cli_tdis_recv(struct tevent_req *req)
+{
+       return tevent_req_simple_recv_ntstatus(req);
+}
+
+NTSTATUS cli_tdis(struct cli_state *cli)
+{
+       struct tevent_context *ev;
+       struct tevent_req *req;
+       NTSTATUS status = NT_STATUS_NO_MEMORY;
+
+       if (cli_has_async_calls(cli)) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+       ev = tevent_context_init(talloc_tos());
+       if (ev == NULL) {
+               goto fail;
+       }
+       req = cli_tdis_send(ev, ev, cli);
+       if (req == NULL) {
+               goto fail;
+       }
+       if (!tevent_req_poll_ntstatus(req, ev, &status)) {
+               goto fail;
+       }
+       status = cli_tdis_recv(req);
+fail:
+       TALLOC_FREE(ev);
+       if (!NT_STATUS_IS_OK(status)) {
+               cli_set_error(cli, status);
+       }
+       return status;
 }
 
 /****************************************************************************