summaryrefslogtreecommitdiff
path: root/source3/libsmb
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2009-02-05 16:39:28 +0100
committerJelmer Vernooij <jelmer@samba.org>2009-02-05 16:39:28 +0100
commit6d139ca4680abcbda5110f2f0886aa038ff62088 (patch)
tree7d61db40fb058bcbf08ccd8e0dadc365b819371b /source3/libsmb
parent4a9b3052caeb8bb144803b49dcfae82395172bc3 (diff)
parentafa960cbbcd609123d710c301e7a9a070c1fed70 (diff)
downloadsamba-6d139ca4680abcbda5110f2f0886aa038ff62088.tar.gz
samba-6d139ca4680abcbda5110f2f0886aa038ff62088.tar.bz2
samba-6d139ca4680abcbda5110f2f0886aa038ff62088.zip
Merge branch 'master' of ssh://git.samba.org/data/git/samba
Conflicts: librpc/ndr.pc.in
Diffstat (limited to 'source3/libsmb')
-rw-r--r--source3/libsmb/async_smb.c43
-rw-r--r--source3/libsmb/cliconnect.c348
-rw-r--r--source3/libsmb/clidfs.c9
-rw-r--r--source3/libsmb/clientgen.c41
-rw-r--r--source3/libsmb/clifile.c155
-rw-r--r--source3/libsmb/clireadwrite.c30
-rw-r--r--source3/libsmb/clitrans.c20
-rw-r--r--source3/libsmb/credentials.c2
-rw-r--r--source3/libsmb/libsmb_server.c17
-rw-r--r--source3/libsmb/namecache.c21
-rw-r--r--source3/libsmb/namequery.c2
-rw-r--r--source3/libsmb/passchange.c10
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;
}