diff options
Diffstat (limited to 'source3/libsmb')
-rw-r--r-- | source3/libsmb/async_smb.c | 43 | ||||
-rw-r--r-- | source3/libsmb/cliconnect.c | 348 | ||||
-rw-r--r-- | source3/libsmb/clidfs.c | 9 | ||||
-rw-r--r-- | source3/libsmb/clientgen.c | 41 | ||||
-rw-r--r-- | source3/libsmb/clifile.c | 155 | ||||
-rw-r--r-- | source3/libsmb/clireadwrite.c | 30 | ||||
-rw-r--r-- | source3/libsmb/clitrans.c | 20 | ||||
-rw-r--r-- | source3/libsmb/credentials.c | 2 | ||||
-rw-r--r-- | source3/libsmb/libsmb_server.c | 17 | ||||
-rw-r--r-- | source3/libsmb/namecache.c | 21 | ||||
-rw-r--r-- | source3/libsmb/namequery.c | 2 | ||||
-rw-r--r-- | source3/libsmb/passchange.c | 10 |
12 files changed, 499 insertions, 199 deletions
diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c index a1fcf8eb07..e579d1c9f0 100644 --- a/source3/libsmb/async_smb.c +++ b/source3/libsmb/async_smb.c @@ -152,32 +152,6 @@ bool cli_in_chain(struct cli_state *cli) } /** - * Is the SMB command able to hold an AND_X successor - * @param[in] cmd The SMB command in question - * @retval Can we add a chained request after "cmd"? - */ - -static bool is_andx_req(uint8_t cmd) -{ - switch (cmd) { - case SMBtconX: - case SMBlockingX: - case SMBopenX: - case SMBreadX: - case SMBwriteX: - case SMBsesssetupX: - case SMBulogoffX: - case SMBntcreateX: - return true; - break; - default: - break; - } - - return false; -} - -/** * @brief Find the smb_cmd offset of the last command pushed * @param[in] buf The buffer we're building up * @retval Where can we put our next andx cmd? @@ -1005,7 +979,7 @@ static void handle_incoming_pdu(struct cli_state *cli) nt_errstr(status))); for (req = cli->outstanding_requests; req; req = req->next) { - async_req_error(req->async[0], status); + async_req_nterror(req->async[0], status); } return; } @@ -1022,7 +996,7 @@ static void cli_state_handler(struct event_context *event_ctx, struct fd_event *event, uint16 flags, void *p) { struct cli_state *cli = (struct cli_state *)p; - struct cli_request *req; + struct cli_request *req, *next; NTSTATUS status; DEBUG(11, ("cli_state_handler called with flags %d\n", flags)); @@ -1128,10 +1102,15 @@ static void cli_state_handler(struct event_context *event_ctx, return; sock_error: - for (req = cli->outstanding_requests; req; req = req->next) { - int i; - for (i=0; i<req->num_async; i++) { - async_req_error(req->async[i], status); + + for (req = cli->outstanding_requests; req; req = next) { + int i, num_async; + + next = req->next; + num_async = req->num_async; + + for (i=0; i<num_async; i++) { + async_req_nterror(req->async[i], status); } } TALLOC_FREE(cli->fd_event); 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)) { diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c index f853e4e670..e642f169f9 100644 --- a/source3/libsmb/clidfs.c +++ b/source3/libsmb/clidfs.c @@ -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; } diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index 0bec24202c..0382ef5fae 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -56,6 +56,16 @@ void cli_set_port(struct cli_state *cli, int port) } /**************************************************************************** + convenience routine to find if we negotiated ucs2 +****************************************************************************/ + +bool cli_ucs2(struct cli_state *cli) +{ + return ((cli->capabilities & CAP_UNICODE) != 0); +} + + +/**************************************************************************** Read an smb from a fd ignoring all keepalive packets. The timeout is in milliseconds @@ -640,7 +650,7 @@ static void cli_echo_recv_helper(struct async_req *req) status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -649,7 +659,7 @@ static void cli_echo_recv_helper(struct async_req *req) if ((num_bytes != cli_req->data.echo.data.length) || (memcmp(cli_req->data.echo.data.data, bytes, num_bytes) != 0)) { - async_req_error(req, NT_STATUS_INVALID_NETWORK_RESPONSE); + async_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); return; } @@ -717,7 +727,7 @@ struct async_req *cli_echo_send(TALLOC_CTX *mem_ctx, struct event_context *ev, NTSTATUS cli_echo_recv(struct async_req *req) { - return async_req_simple_recv(req); + return async_req_simple_recv_ntstatus(req); } /** @@ -765,3 +775,28 @@ NTSTATUS cli_echo(struct cli_state *cli, uint16_t num_echos, DATA_BLOB data) TALLOC_FREE(frame); return status; } + +/** + * Is the SMB command able to hold an AND_X successor + * @param[in] cmd The SMB command in question + * @retval Can we add a chained request after "cmd"? + */ +bool is_andx_req(uint8_t cmd) +{ + switch (cmd) { + case SMBtconX: + case SMBlockingX: + case SMBopenX: + case SMBreadX: + case SMBwriteX: + case SMBsesssetupX: + case SMBulogoffX: + case SMBntcreateX: + return true; + break; + default: + break; + } + + return false; +} diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c index 02cd2108bf..0703f04c5f 100644 --- a/source3/libsmb/clifile.c +++ b/source3/libsmb/clifile.c @@ -771,6 +771,138 @@ int cli_nt_create_full(struct cli_state *cli, const char *fname, return SVAL(cli->inbuf,smb_vwv2 + 1); } +struct async_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const char *fname, + uint32_t CreatFlags, + uint32_t DesiredAccess, + uint32_t FileAttributes, + uint32_t ShareAccess, + uint32_t CreateDisposition, + uint32_t CreateOptions, + uint8_t SecurityFlags) +{ + struct async_req *result; + uint8_t *bytes; + size_t converted_len; + uint16_t vwv[24]; + + SCVAL(vwv+0, 0, 0xFF); + SCVAL(vwv+0, 1, 0); + SSVAL(vwv+1, 0, 0); + SCVAL(vwv+2, 0, 0); + + if (cli->use_oplocks) { + CreatFlags |= (REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK); + } + SIVAL(vwv+3, 1, CreatFlags); + SIVAL(vwv+5, 1, 0x0); /* RootDirectoryFid */ + SIVAL(vwv+7, 1, DesiredAccess); + SIVAL(vwv+9, 1, 0x0); /* AllocationSize */ + SIVAL(vwv+11, 1, 0x0); /* AllocationSize */ + SIVAL(vwv+13, 1, FileAttributes); + SIVAL(vwv+15, 1, ShareAccess); + SIVAL(vwv+17, 1, CreateDisposition); + SIVAL(vwv+19, 1, CreateOptions); + SIVAL(vwv+21, 1, 0x02); /* ImpersonationLevel */ + SCVAL(vwv+23, 1, SecurityFlags); + + bytes = talloc_array(talloc_tos(), uint8_t, 0); + bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), + fname, strlen(fname)+1, + &converted_len); + + /* sigh. this copes with broken netapp filer behaviour */ + bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, NULL); + + if (bytes == NULL) { + return NULL; + } + + SIVAL(vwv+2, 1, converted_len); + + result = cli_request_send(mem_ctx, ev, cli, SMBntcreateX, 0, + 24, vwv, 0, talloc_get_size(bytes), bytes); + TALLOC_FREE(bytes); + return result; +} + +NTSTATUS cli_ntcreate_recv(struct async_req *req, uint16_t *pfnum) +{ + uint8_t wct; + uint16_t *vwv; + uint16_t num_bytes; + uint8_t *bytes; + NTSTATUS status; + + if (async_req_is_nterror(req, &status)) { + return status; + } + + status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + if (wct < 3) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + + *pfnum = SVAL(vwv+2, 1); + + return NT_STATUS_OK; +} + +NTSTATUS cli_ntcreate(struct cli_state *cli, + const char *fname, + uint32_t CreatFlags, + uint32_t DesiredAccess, + uint32_t FileAttributes, + uint32_t ShareAccess, + uint32_t CreateDisposition, + uint32_t CreateOptions, + uint8_t SecurityFlags, + uint16_t *pfid) +{ + 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_ntcreate_send(frame, ev, cli, fname, CreatFlags, + DesiredAccess, FileAttributes, ShareAccess, + CreateDisposition, CreateOptions, + SecurityFlags); + if (req == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + while (req->state < ASYNC_REQ_DONE) { + event_loop_once(ev); + } + + status = cli_ntcreate_recv(req, pfid); + fail: + TALLOC_FREE(frame); + return status; +} + /**************************************************************************** Open a file. ****************************************************************************/ @@ -781,7 +913,9 @@ int cli_nt_create(struct cli_state *cli, const char *fname, uint32 DesiredAccess FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0); } -uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2, const char *str) +uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2, + const char *str, size_t str_len, + size_t *pconverted_size) { size_t buflen; char *converted; @@ -806,7 +940,7 @@ uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2, const char *str) if (!convert_string_allocate(talloc_tos(), CH_UNIX, ucs2 ? CH_UTF16LE : CH_DOS, - str, strlen(str)+1, &converted, + str, str_len, &converted, &converted_size, true)) { return NULL; } @@ -821,6 +955,11 @@ uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2, const char *str) memcpy(buf + buflen, converted, converted_size); TALLOC_FREE(converted); + + if (pconverted_size) { + *pconverted_size = converted_size; + } + return buf; } @@ -890,12 +1029,8 @@ struct async_req *cli_open_send(TALLOC_CTX *mem_ctx, struct event_context *ev, } bytes = talloc_array(talloc_tos(), uint8_t, 0); - if (bytes == NULL) { - return NULL; - } - - bytes = smb_bytes_push_str( - bytes, (cli->capabilities & CAP_UNICODE) != 0, fname); + bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname, + strlen(fname)+1, NULL); if (bytes == NULL) { return NULL; } @@ -914,7 +1049,7 @@ NTSTATUS cli_open_recv(struct async_req *req, int *fnum) uint8_t *bytes; NTSTATUS status; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } @@ -992,7 +1127,7 @@ NTSTATUS cli_close_recv(struct async_req *req) uint8_t *bytes; NTSTATUS status; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 1ba93d827d..9d17ff86a5 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -148,7 +148,7 @@ NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received, NTSTATUS status; size_t size; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } @@ -297,7 +297,7 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, state->top_req = 0; if (size == 0) { - if (!async_post_status(result, ev, NT_STATUS_OK)) { + if (!async_post_ntstatus(result, ev, NT_STATUS_OK)) { goto failed; } return result; @@ -367,7 +367,7 @@ static void cli_pull_read_done(struct async_req *read_req) status = cli_read_andx_recv(read_req, &read_state->data.read.received, &read_state->data.read.rcvbuf); if (!NT_STATUS_IS_OK(status)) { - async_req_error(state->req, status); + async_req_nterror(state->req, status); return; } @@ -404,7 +404,7 @@ static void cli_pull_read_done(struct async_req *read_req) top_read->data.read.received, state->priv); if (!NT_STATUS_IS_OK(status)) { - async_req_error(state->req, status); + async_req_nterror(state->req, status); return; } state->pushed += top_read->data.read.received; @@ -455,7 +455,7 @@ NTSTATUS cli_pull_recv(struct async_req *req, SMB_OFF_T *received) req->private_data, struct cli_pull_state); NTSTATUS status; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } *received = state->pushed; @@ -792,7 +792,7 @@ NTSTATUS cli_write_andx_recv(struct async_req *req, size_t *pwritten) NTSTATUS status; size_t written; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } @@ -879,14 +879,14 @@ static void cli_writeall_written(struct async_req *subreq) status = cli_write_andx_recv(subreq, &written); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } state->written += written; if (state->written > state->size) { - async_req_error(req, NT_STATUS_INVALID_NETWORK_RESPONSE); + async_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); return; } @@ -902,7 +902,7 @@ static void cli_writeall_written(struct async_req *subreq) state->buf + state->written, state->offset + state->written, to_write); if (subreq == NULL) { - async_req_error(req, NT_STATUS_NO_MEMORY); + async_req_nterror(req, NT_STATUS_NO_MEMORY); return; } @@ -912,7 +912,7 @@ static void cli_writeall_written(struct async_req *subreq) static NTSTATUS cli_writeall_recv(struct async_req *req) { - return async_req_simple_recv(req); + return async_req_simple_recv_ntstatus(req); } struct cli_push_state { @@ -1018,7 +1018,7 @@ struct async_req *cli_push_send(TALLOC_CTX *mem_ctx, struct event_context *ev, } if (i == 0) { - if (!async_post_status(result, ev, NT_STATUS_OK)) { + if (!async_post_ntstatus(result, ev, NT_STATUS_OK)) { goto failed; } return result; @@ -1047,7 +1047,7 @@ static void cli_push_written(struct async_req *req) } if (i == state->num_reqs) { - async_req_error(state->req, NT_STATUS_INTERNAL_ERROR); + async_req_nterror(state->req, NT_STATUS_INTERNAL_ERROR); return; } @@ -1055,7 +1055,7 @@ static void cli_push_written(struct async_req *req) TALLOC_FREE(state->reqs[i]); req = NULL; if (!NT_STATUS_IS_OK(status)) { - async_req_error(state->req, status); + async_req_nterror(state->req, status); return; } @@ -1081,7 +1081,7 @@ static void cli_push_written(struct async_req *req) state->reqs, state->ev, state->cli, state->fnum, state->mode, buf, state->start_offset + state->sent, to_write); if (state->reqs[i] == NULL) { - async_req_error(state->req, NT_STATUS_NO_MEMORY); + async_req_nterror(state->req, NT_STATUS_NO_MEMORY); return; } @@ -1094,7 +1094,7 @@ static void cli_push_written(struct async_req *req) NTSTATUS cli_push_recv(struct async_req *req) { - return async_req_simple_recv(req); + return async_req_simple_recv_ntstatus(req); } NTSTATUS cli_push(struct cli_state *cli, uint16_t fnum, uint16_t mode, diff --git a/source3/libsmb/clitrans.c b/source3/libsmb/clitrans.c index baa73aeb14..69e2be3af7 100644 --- a/source3/libsmb/clitrans.c +++ b/source3/libsmb/clitrans.c @@ -765,9 +765,9 @@ static struct async_req *cli_ship_trans(TALLOC_CTX *mem_ctx, if (bytes == NULL) { goto fail; } - bytes = smb_bytes_push_str( - bytes, (state->cli->capabilities & CAP_UNICODE) != 0, - state->pipe_name); + bytes = smb_bytes_push_str(bytes, cli_ucs2(state->cli), + state->pipe_name, + strlen(state->pipe_name)+1, NULL); if (bytes == NULL) { goto fail; } @@ -962,7 +962,7 @@ static void cli_trans_ship_rest(struct async_req *req, { state->secondary_request_ctx = talloc_new(state); if (state->secondary_request_ctx == NULL) { - async_req_error(req, NT_STATUS_NO_MEMORY); + async_req_nterror(req, NT_STATUS_NO_MEMORY); return; } @@ -972,7 +972,7 @@ static void cli_trans_ship_rest(struct async_req *req, cli_req = cli_ship_trans(state->secondary_request_ctx, state); if (cli_req == NULL) { - async_req_error(req, NT_STATUS_NO_MEMORY); + async_req_nterror(req, NT_STATUS_NO_MEMORY); return; } } @@ -1133,7 +1133,7 @@ static void cli_trans_recv_helper(struct async_req *req) */ if (NT_STATUS_IS_ERR(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -1154,7 +1154,7 @@ static void cli_trans_recv_helper(struct async_req *req) state->rsetup = (uint16_t *)TALLOC_MEMDUP( state, setup, sizeof(uint16_t) * num_setup); if (state->rsetup == NULL) { - async_req_error(req, NT_STATUS_NO_MEMORY); + async_req_nterror(req, NT_STATUS_NO_MEMORY); return; } } @@ -1165,7 +1165,7 @@ static void cli_trans_recv_helper(struct async_req *req) if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("Pulling params failed: %s\n", nt_errstr(status))); - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -1175,7 +1175,7 @@ static void cli_trans_recv_helper(struct async_req *req) if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("Pulling data failed: %s\n", nt_errstr(status))); - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -1318,7 +1318,7 @@ NTSTATUS cli_trans_recv(struct async_req *req, TALLOC_CTX *mem_ctx, cli_req->recv_helper.priv, struct cli_trans_state); NTSTATUS status; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } diff --git a/source3/libsmb/credentials.c b/source3/libsmb/credentials.c index 9d33e6d93d..9ba460f869 100644 --- a/source3/libsmb/credentials.c +++ b/source3/libsmb/credentials.c @@ -146,7 +146,7 @@ static void creds_init_64(struct dcinfo *dc, static void creds_step(struct dcinfo *dc) { - DOM_CHAL time_chal; + struct netr_Credential time_chal; DEBUG(5,("\tsequence = 0x%x\n", (unsigned int)dc->sequence )); diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c index 0ece5bb649..6d7a86241a 100644 --- a/source3/libsmb/libsmb_server.c +++ b/source3/libsmb/libsmb_server.c @@ -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; } diff --git a/source3/libsmb/namecache.c b/source3/libsmb/namecache.c index ba706e5ee2..d3230cffef 100644 --- a/source3/libsmb/namecache.c +++ b/source3/libsmb/namecache.c @@ -62,27 +62,6 @@ bool namecache_enable(void) } /** - * Shutdown namecache. Routine calls gencache close function - * to safely close gencache file. - * - * @return true upon successful shutdown of the cache or - * false on failure - **/ - -bool namecache_shutdown(void) -{ - if (!gencache_shutdown()) { - DEBUG(2, ("namecache_shutdown: " - "Couldn't close namecache on top of gencache.\n")); - return False; - } - - DEBUG(5, ("namecache_shutdown: " - "netbios namecache closed successfully.\n")); - return True; -} - -/** * Generates a key for netbios name lookups on basis of * netbios name and type. * The caller must free returned key string when finished. diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c index 05679570d4..ac38d40271 100644 --- a/source3/libsmb/namequery.c +++ b/source3/libsmb/namequery.c @@ -1502,7 +1502,7 @@ NTSTATUS internal_resolve_name(const char *name, *return_count = 0; DEBUG(10, ("internal_resolve_name: looking up %s#%x (sitename %s)\n", - name, name_type, sitename ? sitename : NULL)); + name, name_type, sitename ? sitename : "(null)")); if (is_ipaddress(name)) { if ((*return_iplist = SMB_MALLOC_P(struct ip_service)) == diff --git a/source3/libsmb/passchange.c b/source3/libsmb/passchange.c index 76b06088d6..f9ff4b3191 100644 --- a/source3/libsmb/passchange.c +++ b/source3/libsmb/passchange.c @@ -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; } |