diff options
Diffstat (limited to 'source3/libsmb/cliconnect.c')
-rw-r--r-- | source3/libsmb/cliconnect.c | 348 |
1 files changed, 259 insertions, 89 deletions
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index bc690f2e02..a39e035d2a 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -161,50 +161,79 @@ static uint32 cli_session_setup_capabilities(struct cli_state *cli) Do a NT1 guest session setup. ****************************************************************************/ -static NTSTATUS cli_session_setup_guest(struct cli_state *cli) +struct async_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli) { - char *p; - uint32 capabilities = cli_session_setup_capabilities(cli); + struct async_req *result; + uint16_t vwv[13]; + uint8_t *bytes; - 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); - SSVAL(cli->outbuf,smb_vwv4,cli->pid); - SIVAL(cli->outbuf,smb_vwv5,cli->sesskey); - SSVAL(cli->outbuf,smb_vwv7,0); - SSVAL(cli->outbuf,smb_vwv8,0); - SIVAL(cli->outbuf,smb_vwv11,capabilities); - p = smb_buf(cli->outbuf); - p += clistr_push(cli, p, "", -1, STR_TERMINATE); /* username */ - p += clistr_push(cli, p, "", -1, STR_TERMINATE); /* workgroup */ - p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE); - p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE); - cli_setup_bcc(cli, p); + SCVAL(vwv+0, 0, 0xFF); + SCVAL(vwv+0, 1, 0); + SSVAL(vwv+1, 0, 0); + SSVAL(vwv+2, 0, CLI_BUFFER_SIZE); + SSVAL(vwv+3, 0, 2); + SSVAL(vwv+4, 0, cli->pid); + SIVAL(vwv+5, 0, cli->sesskey); + SSVAL(vwv+7, 0, 0); + SSVAL(vwv+8, 0, 0); + SSVAL(vwv+9, 0, 0); + SSVAL(vwv+10, 0, 0); + SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli)); + + bytes = talloc_array(talloc_tos(), uint8_t, 0); + + bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* username */ + NULL); + bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */ + NULL); + bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", + strlen("Unix")+1, NULL); + bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", + strlen("Samba")+1, NULL); + + if (bytes == NULL) { + return NULL; + } + + result = cli_request_send(mem_ctx, ev, cli, SMBsesssetupX, 0, + 13, vwv, 0, talloc_get_size(bytes), bytes); + TALLOC_FREE(bytes); + return result; +} - if (!cli_send_smb(cli) || !cli_receive_smb(cli)) { - return cli_nt_error(cli); +NTSTATUS cli_session_setup_guest_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; + uint8_t *p; + NTSTATUS status; + + if (async_req_is_nterror(req, &status)) { + return status; } - - show_msg(cli->inbuf); - - if (cli_is_error(cli)) { - return cli_nt_error(cli); + + status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes); + if (!NT_STATUS_IS_OK(status)) { + return status; } - cli->vuid = SVAL(cli->inbuf,smb_uid); + p = bytes; - p = smb_buf(cli->inbuf); - p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring), - -1, STR_TERMINATE); - p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring), - -1, STR_TERMINATE); - p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring), - -1, STR_TERMINATE); + cli->vuid = SVAL(cli_req->inbuf, smb_uid); + + p += clistr_pull(cli_req->inbuf, cli->server_os, (char *)p, + sizeof(fstring), bytes+num_bytes-p, STR_TERMINATE); + p += clistr_pull(cli_req->inbuf, cli->server_type, (char *)p, + sizeof(fstring), bytes+num_bytes-p, STR_TERMINATE); + p += clistr_pull(cli_req->inbuf, cli->server_domain, (char *)p, + sizeof(fstring), bytes+num_bytes-p, STR_TERMINATE); if (strstr(cli->server_type, "Samba")) { cli->is_samba = True; @@ -215,6 +244,43 @@ static NTSTATUS cli_session_setup_guest(struct cli_state *cli) return NT_STATUS_OK; } +static NTSTATUS cli_session_setup_guest(struct cli_state *cli) +{ + 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_session_setup_guest_send(frame, ev, cli); + if (req == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + while (req->state < ASYNC_REQ_DONE) { + event_loop_once(ev); + } + + status = cli_session_setup_guest_recv(req); + fail: + TALLOC_FREE(frame); + return status; +} + /**************************************************************************** Do a NT1 plaintext session setup. ****************************************************************************/ @@ -1107,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); @@ -1121,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) && @@ -1132,28 +1203,36 @@ 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); + if (passlen == -1) { + DEBUG(1, ("clistr_push(pword) failed\n")); + goto access_denied; + } } else { if (passlen) { memcpy(pword, pass, passlen); @@ -1161,52 +1240,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_ntstatus(result, ev, NT_STATUS_ACCESS_DENIED)) { + return result; + } + TALLOC_FREE(result); + return NULL; +} + +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 (async_req_is_nterror(req, &status)) { + return status; + } - clistr_pull(cli->inbuf, cli->dev, smb_buf(cli->inbuf), sizeof(fstring), - -1, STR_TERMINATE|STR_ASCII); + 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 && - smb_buflen(cli->inbuf) == 3) { + 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; - 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; + if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) { + cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0); + } - cli->cnum = SVAL(cli->inbuf,smb_tid); - return True; + 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; } /**************************************************************************** @@ -1294,7 +1460,10 @@ struct async_req *cli_negprot_send(TALLOC_CTX *mem_ctx, if (bytes == NULL) { return NULL; } - bytes = smb_bytes_push_str(bytes, false, prots[numprots].name); + bytes = smb_bytes_push_str(bytes, false, + prots[numprots].name, + strlen(prots[numprots].name)+1, + NULL); if (bytes == NULL) { return NULL; } @@ -1318,7 +1487,7 @@ NTSTATUS cli_negprot_recv(struct async_req *req) NTSTATUS status; uint16_t protnum; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } @@ -1887,8 +2056,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)) { |