From 1d26beb7084efdfcadb4a1cebe5a0d7cdcd2b454 Mon Sep 17 00:00:00 2001 From: Ephi Dror Date: Wed, 27 Aug 2008 17:28:34 -0700 Subject: Correct the netsamlogon_clear_cached_user function. (This used to be commit bb13312d9d53b1e048b3a0bfeeca088f9db84cd3) --- source3/libsmb/samlogon_cache.c | 54 ++++++++++++++--------------------------- 1 file changed, 18 insertions(+), 36 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/samlogon_cache.c b/source3/libsmb/samlogon_cache.c index 2d2588f70c..4abe5bb6de 100644 --- a/source3/libsmb/samlogon_cache.c +++ b/source3/libsmb/samlogon_cache.c @@ -59,48 +59,30 @@ bool netsamlogon_cache_shutdown(void) Clear cache getpwnam and getgroups entries from the winbindd cache ***********************************************************************/ -void netsamlogon_clear_cached_user(TDB_CONTEXT *tdb, struct netr_SamInfo3 *info3) +void netsamlogon_clear_cached_user(struct netr_SamInfo3 *info3) { - bool got_tdb = false; - DOM_SID sid; - fstring key_str, sid_string; - - /* We may need to call this function from smbd which will not have - winbindd_cache.tdb open. Open the tdb if a NULL is passed. */ - - if (!tdb) { - tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), - WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE, - TDB_DEFAULT, O_RDWR, 0600); - if (!tdb) { - DEBUG(5, ("netsamlogon_clear_cached_user: failed to open cache\n")); - return; - } - got_tdb = true; - } - - sid_copy(&sid, info3->base.domain_sid); - sid_append_rid(&sid, info3->base.rid); - - /* Clear U/SID cache entry */ - - fstr_sprintf(key_str, "U/%s", sid_to_fstring(sid_string, &sid)); - - DEBUG(10, ("netsamlogon_clear_cached_user: clearing %s\n", key_str)); - - tdb_delete(tdb, string_tdb_data(key_str)); + DOM_SID user_sid; + fstring keystr, tmp; - /* Clear UG/SID cache entry */ + if (!info3) { + return; + } - fstr_sprintf(key_str, "UG/%s", sid_to_fstring(sid_string, &sid)); + if (!netsamlogon_cache_init()) { + DEBUG(0,("netsamlogon_clear_cached_user: cannot open " + "%s for write!\n", + NETSAMLOGON_TDB)); + return; + } + sid_copy(&user_sid, info3->base.domain_sid); + sid_append_rid(&user_sid, info3->base.rid); - DEBUG(10, ("netsamlogon_clear_cached_user: clearing %s\n", key_str)); + /* Prepare key as DOMAIN-SID/USER-RID string */ + slprintf(keystr, sizeof(keystr), "%s", sid_to_fstring(tmp, &user_sid)); - tdb_delete(tdb, string_tdb_data(key_str)); + DEBUG(10,("netsamlogon_clear_cached_user: SID [%s]\n", keystr)); - if (got_tdb) { - tdb_close(tdb); - } + tdb_delete_bystring(netsamlogon_tdb, keystr); } /*********************************************************************** -- cgit From 58aa97c0d9db06588d1aba4f06a3c98ed2098d8f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 1 Aug 2008 23:14:51 +0200 Subject: Refactoring: Add the routine cli_request_send() cli_request_send() is supposed to bundle all generic SMB-header handling. This makes cli_request_new static to async_smb.c. (This used to be commit 7e73dd4e7622db64d30d48ba106892e0895fc188) --- source3/libsmb/async_smb.c | 62 ++++++++++++++++++++++++++++++++++--- source3/libsmb/clireadwrite.c | 71 +++++++++++++++---------------------------- 2 files changed, 82 insertions(+), 51 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c index 58bba2bfc7..454bd8169b 100644 --- a/source3/libsmb/async_smb.c +++ b/source3/libsmb/async_smb.c @@ -114,11 +114,11 @@ static int cli_request_destructor(struct cli_request *req) * Create a fresh async smb request */ -struct async_req *cli_request_new(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct cli_state *cli, - uint8_t num_words, size_t num_bytes, - struct cli_request **preq) +static struct async_req *cli_request_new(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + uint8_t num_words, size_t num_bytes, + struct cli_request **preq) { struct async_req *result; struct cli_request *cli_req; @@ -160,6 +160,58 @@ struct async_req *cli_request_new(TALLOC_CTX *mem_ctx, return result; } +/* + * Ship a new smb request to the server + */ +struct async_req *cli_request_send(TALLOC_CTX *mem_ctx, struct cli_state *cli, + uint8_t smb_command, + uint8_t additional_flags, + uint8_t wct, const uint16_t *vwv, + uint16_t num_bytes, const uint8_t *bytes) +{ + struct async_req *result; + struct cli_request *req; + + result = cli_request_new(mem_ctx, cli->event_ctx, cli, wct, num_bytes, + &req); + if (result == NULL) { + DEBUG(0, ("cli_request_new failed\n")); + return NULL; + } + + cli_set_message(req->outbuf, wct, num_bytes, false); + SCVAL(req->outbuf, smb_com, smb_command); + SSVAL(req->outbuf, smb_tid, cli->cnum); + cli_setup_packet_buf(cli, req->outbuf); + + memcpy(req->outbuf + smb_vwv0, vwv, sizeof(uint16_t) * wct); + memcpy(smb_buf(req->outbuf), bytes, num_bytes); + SSVAL(req->outbuf, smb_mid, req->mid); + SCVAL(cli->outbuf, smb_flg, + CVAL(cli->outbuf,smb_flg) | additional_flags); + + cli_calculate_sign_mac(cli, req->outbuf); + + if (cli_encryption_on(cli)) { + NTSTATUS status; + char *enc_buf; + + status = cli_encrypt_message(cli, req->outbuf, &enc_buf); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("Error in encrypting client message. " + "Error %s\n", nt_errstr(status))); + TALLOC_FREE(req); + return NULL; + } + req->outbuf = enc_buf; + req->enc_state = cli->trans_enc_state; + } + + event_fd_set_writeable(cli->fd_event); + + return result; +} + /* * Convenience function to get the SMB part out of an async_req */ diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index a57f1e0785..2b34fce5bd 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -47,7 +47,9 @@ struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx, struct async_req *result; struct cli_request *req; bool bigoffset = False; - char *enc_buf; + + uint16_t vwv[12]; + uint8_t wct = 10; if (size > cli_read_max_bufsize(cli)) { DEBUG(0, ("cli_read_andx_send got size=%d, can only handle " @@ -56,60 +58,37 @@ struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx, return NULL; } - result = cli_request_new(mem_ctx, cli->event_ctx, cli, 12, 0, &req); + SCVAL(vwv + 0, 0, 0xFF); + SCVAL(vwv + 0, 1, 0); + SSVAL(vwv + 1, 0, 0); + SSVAL(vwv + 2, 0, fnum); + SIVAL(vwv + 3, 0, offset); + SSVAL(vwv + 5, 0, size); + SSVAL(vwv + 6, 0, size); + SSVAL(vwv + 7, 0, (size >> 16)); + SSVAL(vwv + 8, 0, 0); + SSVAL(vwv + 9, 0, 0); + + if ((SMB_BIG_UINT)offset >> 32) { + bigoffset = True; + SIVAL(vwv + 10, 0, + (((SMB_BIG_UINT)offset)>>32) & 0xffffffff); + wct += 2; + } + + result = cli_request_send(mem_ctx, cli, SMBreadX, 0, wct, vwv, + 0, NULL); if (result == NULL) { - DEBUG(0, ("cli_request_new failed\n")); return NULL; } + req = cli_request_get(result); + req->data.read.ofs = offset; req->data.read.size = size; req->data.read.received = 0; req->data.read.rcvbuf = NULL; - if ((SMB_BIG_UINT)offset >> 32) - bigoffset = True; - - cli_set_message(req->outbuf, bigoffset ? 12 : 10, 0, False); - - SCVAL(req->outbuf,smb_com,SMBreadX); - SSVAL(req->outbuf,smb_tid,cli->cnum); - cli_setup_packet_buf(cli, req->outbuf); - - SCVAL(req->outbuf,smb_vwv0,0xFF); - SCVAL(req->outbuf,smb_vwv0+1,0); - SSVAL(req->outbuf,smb_vwv1,0); - SSVAL(req->outbuf,smb_vwv2,fnum); - SIVAL(req->outbuf,smb_vwv3,offset); - SSVAL(req->outbuf,smb_vwv5,size); - SSVAL(req->outbuf,smb_vwv6,size); - SSVAL(req->outbuf,smb_vwv7,(size >> 16)); - SSVAL(req->outbuf,smb_vwv8,0); - SSVAL(req->outbuf,smb_vwv9,0); - SSVAL(req->outbuf,smb_mid,req->mid); - - if (bigoffset) { - SIVAL(req->outbuf, smb_vwv10, - (((SMB_BIG_UINT)offset)>>32) & 0xffffffff); - } - - cli_calculate_sign_mac(cli, req->outbuf); - - event_fd_set_writeable(cli->fd_event); - - if (cli_encryption_on(cli)) { - NTSTATUS status; - status = cli_encrypt_message(cli, req->outbuf, &enc_buf); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("Error in encrypting client message. " - "Error %s\n", nt_errstr(status))); - TALLOC_FREE(req); - return NULL; - } - req->outbuf = enc_buf; - req->enc_state = cli->trans_enc_state; - } - return result; } -- cgit From 8f408a676eb1d2bac665d8212d727dafeecd386e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 1 Aug 2008 23:18:15 +0200 Subject: Add async cli_close (This used to be commit f84a2b5dbf8a072a9e356fa39523f65d042a2643) --- source3/libsmb/clifile.c | 51 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 13 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c index 12b10ba0a0..20357bbec0 100644 --- a/source3/libsmb/clifile.c +++ b/source3/libsmb/clifile.c @@ -865,28 +865,53 @@ int cli_open(struct cli_state *cli, const char *fname, int flags, int share_mode Close a file. ****************************************************************************/ -bool cli_close(struct cli_state *cli, int fnum) +struct async_req *cli_close_send(TALLOC_CTX *mem_ctx, struct cli_state *cli, + int fnum) { - memset(cli->outbuf,'\0',smb_size); - memset(cli->inbuf,'\0',smb_size); + uint16_t vwv[3]; - cli_set_message(cli->outbuf,3,0,True); + SSVAL(vwv+0, 0, fnum); + SIVALS(vwv+1, 0, -1); - SCVAL(cli->outbuf,smb_com,SMBclose); - SSVAL(cli->outbuf,smb_tid,cli->cnum); - cli_setup_packet(cli); + return cli_request_send(mem_ctx, cli, SMBclose, 0, 3, vwv, 0, NULL); +} - SSVAL(cli->outbuf,smb_vwv0,fnum); - SIVALS(cli->outbuf,smb_vwv1,-1); +NTSTATUS cli_close_recv(struct async_req *req) +{ + struct cli_request *cli_req = cli_request_get(req); - cli_send_smb(cli); - if (!cli_receive_smb(cli)) { - return False; + SMB_ASSERT(req->state >= ASYNC_REQ_DONE); + if (req->state == ASYNC_REQ_ERROR) { + return req->status; } - return !cli_is_error(cli); + return cli_pull_error(cli_req->inbuf); } +bool cli_close(struct cli_state *cli, int fnum) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct async_req *req; + bool result = false; + + if (cli_tmp_event_ctx(frame, cli) == NULL) { + goto fail; + } + + req = cli_close_send(frame, cli, fnum); + if (req == NULL) { + goto fail; + } + + while (req->state < ASYNC_REQ_DONE) { + event_loop_once(cli->event_ctx); + } + + result = NT_STATUS_IS_OK(cli_close_recv(req)); + fail: + TALLOC_FREE(frame); + return result; +} /**************************************************************************** Truncate a file to a specified size -- cgit From de9fcfc79504fbca0350a99269b4a3423e5f2561 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 2 Aug 2008 18:44:39 +0200 Subject: Add async open&x (This used to be commit faf353edd60967efac4d5c222db14fa730866273) --- source3/libsmb/clifile.c | 150 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 117 insertions(+), 33 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c index 20357bbec0..d5157877bf 100644 --- a/source3/libsmb/clifile.c +++ b/source3/libsmb/clifile.c @@ -781,19 +781,61 @@ int cli_nt_create(struct cli_state *cli, const char *fname, uint32 DesiredAccess FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0); } +static uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2, const char *str) +{ + size_t buflen = talloc_get_size(buf); + char *converted; + size_t converted_size; + + /* + * We're pushing into an SMB buffer, align odd + */ + if (ucs2 && (buflen % 2 == 0)) { + buf = TALLOC_REALLOC_ARRAY(NULL, buf, uint8_t, buflen + 1); + if (buf == NULL) { + return NULL; + } + buf[buflen] = '\0'; + buflen += 1; + } + + if (!convert_string_allocate(talloc_tos(), CH_UNIX, + ucs2 ? CH_UTF16LE : CH_DOS, + str, strlen(str)+1, &converted, + &converted_size, true)) { + return NULL; + } + + buf = TALLOC_REALLOC_ARRAY(NULL, buf, uint8_t, + buflen + converted_size); + if (buf == NULL) { + return NULL; + } + + memcpy(buf + buflen, converted, converted_size); + + TALLOC_FREE(converted); + return buf; +} + /**************************************************************************** Open a file WARNING: if you open with O_WRONLY then getattrE won't work! ****************************************************************************/ -int cli_open(struct cli_state *cli, const char *fname, int flags, int share_mode) +struct async_req *cli_open_send(TALLOC_CTX *mem_ctx, struct cli_state *cli, + const char *fname, int flags, int share_mode) { - char *p; - unsigned openfn=0; - unsigned accessmode=0; + unsigned openfn = 0; + unsigned accessmode = 0; + uint8_t additional_flags = 0; + uint8_t *bytes; + uint16_t vwv[15]; + struct async_req *result; - if (flags & O_CREAT) + if (flags & O_CREAT) { openfn |= (1<<4); + } if (!(flags & O_EXCL)) { if (flags & O_TRUNC) openfn |= (1<<1); @@ -819,46 +861,88 @@ int cli_open(struct cli_state *cli, const char *fname, int flags, int share_mode accessmode = 0xFF; } - memset(cli->outbuf,'\0',smb_size); - memset(cli->inbuf,'\0',smb_size); - - cli_set_message(cli->outbuf,15,0, true); - - SCVAL(cli->outbuf,smb_com,SMBopenX); - SSVAL(cli->outbuf,smb_tid,cli->cnum); - cli_setup_packet(cli); - - SSVAL(cli->outbuf,smb_vwv0,0xFF); - SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */ - SSVAL(cli->outbuf,smb_vwv3,accessmode); - SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN); - SSVAL(cli->outbuf,smb_vwv5,0); - SSVAL(cli->outbuf,smb_vwv8,openfn); + SCVAL(vwv + 0, 0, 0xFF); + SCVAL(vwv + 0, 1, 0); + SSVAL(vwv + 1, 0, 0); + SSVAL(vwv + 2, 0, 0); /* no additional info */ + SSVAL(vwv + 3, 0, accessmode); + SSVAL(vwv + 4, 0, aSYSTEM | aHIDDEN); + SSVAL(vwv + 5, 0, 0); + SIVAL(vwv + 6, 0, 0); + SSVAL(vwv + 8, 0, openfn); + SIVAL(vwv + 9, 0, 0); + SIVAL(vwv + 11, 0, 0); + SIVAL(vwv + 13, 0, 0); if (cli->use_oplocks) { /* if using oplocks then ask for a batch oplock via core and extended methods */ - SCVAL(cli->outbuf,smb_flg, CVAL(cli->outbuf,smb_flg)| - FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK); - SSVAL(cli->outbuf,smb_vwv2,SVAL(cli->outbuf,smb_vwv2) | 6); + additional_flags = + FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK; + SSVAL(vwv+2, 0, SVAL(vwv+2, 0) | 6); } - p = smb_buf(cli->outbuf); - p += clistr_push(cli, p, fname, - cli->bufsize - PTR_DIFF(p,cli->outbuf), STR_TERMINATE); + bytes = talloc_array(talloc_tos(), uint8_t, 0); + if (bytes == NULL) { + return NULL; + } - cli_setup_bcc(cli, p); + bytes = smb_bytes_push_str( + bytes, (cli->capabilities & CAP_UNICODE) != 0, fname); + if (bytes == NULL) { + return NULL; + } - cli_send_smb(cli); - if (!cli_receive_smb(cli)) { - return -1; + result = cli_request_send(mem_ctx, cli, SMBopenX, additional_flags, + 15, vwv, talloc_get_size(bytes), bytes); + TALLOC_FREE(bytes); + return result; +} + +NTSTATUS cli_open_recv(struct async_req *req, int *fnum) +{ + struct cli_request *cli_req = cli_request_get(req); + NTSTATUS status; + + SMB_ASSERT(req->state >= ASYNC_REQ_DONE); + if (req->state == ASYNC_REQ_ERROR) { + return req->status; } - if (cli_is_error(cli)) { - return -1; + status = cli_pull_error(cli_req->inbuf); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + *fnum = SVAL(cli_req->inbuf, smb_vwv2); + + return NT_STATUS_OK; +} + +int cli_open(struct cli_state *cli, const char *fname, int flags, + int share_mode) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct async_req *req; + int result = -1; + + if (cli_tmp_event_ctx(frame, cli) == NULL) { + goto fail; + } + + req = cli_open_send(frame, cli, fname, flags, share_mode); + if (req == NULL) { + goto fail; + } + + while (req->state < ASYNC_REQ_DONE) { + event_loop_once(cli->event_ctx); } - return SVAL(cli->inbuf,smb_vwv2); + cli_open_recv(req, &result); + fail: + TALLOC_FREE(frame); + return result; } /**************************************************************************** -- cgit From 2650207d4adbfd68974fc2b342dd2af079a2552c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 24 Aug 2008 14:17:43 +0200 Subject: Remove cli->event_ctx, pass it explicitly Storing the event_context as permanent state in struct cli_state creates more complex code than necessary IMO. (This used to be commit debb37f703075008e5ea7d34d214cfa4d0f8f916) --- source3/libsmb/async_smb.c | 94 +++++++++++-------------------------------- source3/libsmb/clifile.c | 44 +++++++++++++++----- source3/libsmb/clireadwrite.c | 33 ++++++++++----- 3 files changed, 81 insertions(+), 90 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c index 454bd8169b..e58b753da2 100644 --- a/source3/libsmb/async_smb.c +++ b/source3/libsmb/async_smb.c @@ -19,6 +19,9 @@ #include "includes.h" +static void cli_state_handler(struct event_context *event_ctx, + struct fd_event *event, uint16 flags, void *p); + /* * Fetch an error out of a NBT packet */ @@ -107,6 +110,9 @@ static int cli_request_destructor(struct cli_request *req) common_free_enc_buffer(req->enc_state, req->outbuf); } DLIST_REMOVE(req->cli->outstanding_requests, req); + if (req->cli->outstanding_requests == NULL) { + TALLOC_FREE(req->cli->fd_event); + } return 0; } @@ -163,7 +169,9 @@ static struct async_req *cli_request_new(TALLOC_CTX *mem_ctx, /* * Ship a new smb request to the server */ -struct async_req *cli_request_send(TALLOC_CTX *mem_ctx, struct cli_state *cli, +struct async_req *cli_request_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, uint8_t smb_command, uint8_t additional_flags, uint8_t wct, const uint16_t *vwv, @@ -172,10 +180,20 @@ struct async_req *cli_request_send(TALLOC_CTX *mem_ctx, struct cli_state *cli, struct async_req *result; struct cli_request *req; - result = cli_request_new(mem_ctx, cli->event_ctx, cli, wct, num_bytes, - &req); + if (cli->fd_event == NULL) { + SMB_ASSERT(cli->outstanding_requests == NULL); + cli->fd_event = event_add_fd(ev, cli, cli->fd, + EVENT_FD_READ, + cli_state_handler, cli); + if (cli->fd_event == NULL) { + return NULL; + } + } + + result = cli_request_new(mem_ctx, ev, cli, wct, num_bytes, &req); if (result == NULL) { DEBUG(0, ("cli_request_new failed\n")); + TALLOC_FREE(cli->fd_event); return NULL; } @@ -446,7 +464,9 @@ static void cli_state_handler(struct event_context *event_ctx, } if (req == NULL) { - event_fd_set_not_writeable(event); + if (cli->fd_event != NULL) { + event_fd_set_not_writeable(cli->fd_event); + } return; } @@ -474,69 +494,3 @@ static void cli_state_handler(struct event_context *event_ctx, close(cli->fd); cli->fd = -1; } - -/* - * Holder for a talloc_destructor, we need to zero out the pointers in cli - * when deleting - */ -struct cli_tmp_event { - struct cli_state *cli; -}; - -static int cli_tmp_event_destructor(struct cli_tmp_event *e) -{ - TALLOC_FREE(e->cli->fd_event); - TALLOC_FREE(e->cli->event_ctx); - return 0; -} - -/* - * Create a temporary event context for use in the sync helper functions - */ - -struct cli_tmp_event *cli_tmp_event_ctx(TALLOC_CTX *mem_ctx, - struct cli_state *cli) -{ - struct cli_tmp_event *state; - - if (cli->event_ctx != NULL) { - return NULL; - } - - state = talloc(mem_ctx, struct cli_tmp_event); - if (state == NULL) { - return NULL; - } - state->cli = cli; - talloc_set_destructor(state, cli_tmp_event_destructor); - - cli->event_ctx = event_context_init(state); - if (cli->event_ctx == NULL) { - TALLOC_FREE(state); - return NULL; - } - - cli->fd_event = event_add_fd(cli->event_ctx, state, cli->fd, - EVENT_FD_READ, cli_state_handler, cli); - if (cli->fd_event == NULL) { - TALLOC_FREE(state); - return NULL; - } - return state; -} - -/* - * Attach an event context permanently to a cli_struct - */ - -NTSTATUS cli_add_event_ctx(struct cli_state *cli, - struct event_context *event_ctx) -{ - cli->event_ctx = event_ctx; - cli->fd_event = event_add_fd(event_ctx, cli, cli->fd, EVENT_FD_READ, - cli_state_handler, cli); - if (cli->fd_event == NULL) { - return NT_STATUS_NO_MEMORY; - } - return NT_STATUS_OK; -} diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c index d5157877bf..dfb0ce8c11 100644 --- a/source3/libsmb/clifile.c +++ b/source3/libsmb/clifile.c @@ -823,7 +823,8 @@ static uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2, const char *str) WARNING: if you open with O_WRONLY then getattrE won't work! ****************************************************************************/ -struct async_req *cli_open_send(TALLOC_CTX *mem_ctx, struct cli_state *cli, +struct async_req *cli_open_send(TALLOC_CTX *mem_ctx, struct event_context *ev, + struct cli_state *cli, const char *fname, int flags, int share_mode) { unsigned openfn = 0; @@ -893,7 +894,7 @@ struct async_req *cli_open_send(TALLOC_CTX *mem_ctx, struct cli_state *cli, return NULL; } - result = cli_request_send(mem_ctx, cli, SMBopenX, additional_flags, + result = cli_request_send(mem_ctx, ev, cli, SMBopenX, additional_flags, 15, vwv, talloc_get_size(bytes), bytes); TALLOC_FREE(bytes); return result; @@ -923,20 +924,30 @@ int cli_open(struct cli_state *cli, const char *fname, int flags, int share_mode) { TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev; struct async_req *req; int result = -1; - if (cli_tmp_event_ctx(frame, cli) == NULL) { + if (cli->fd_event != NULL) { + /* + * Can't use sync call while an async call is in flight + */ + cli_set_error(cli, NT_STATUS_INVALID_PARAMETER); goto fail; } - req = cli_open_send(frame, cli, fname, flags, share_mode); + ev = event_context_init(frame); + if (ev == NULL) { + goto fail; + } + + req = cli_open_send(frame, ev, cli, fname, flags, share_mode); if (req == NULL) { goto fail; } while (req->state < ASYNC_REQ_DONE) { - event_loop_once(cli->event_ctx); + event_loop_once(ev); } cli_open_recv(req, &result); @@ -949,15 +960,16 @@ int cli_open(struct cli_state *cli, const char *fname, int flags, Close a file. ****************************************************************************/ -struct async_req *cli_close_send(TALLOC_CTX *mem_ctx, struct cli_state *cli, - int fnum) +struct async_req *cli_close_send(TALLOC_CTX *mem_ctx, struct event_context *ev, + struct cli_state *cli, int fnum) { uint16_t vwv[3]; SSVAL(vwv+0, 0, fnum); SIVALS(vwv+1, 0, -1); - return cli_request_send(mem_ctx, cli, SMBclose, 0, 3, vwv, 0, NULL); + return cli_request_send(mem_ctx, ev, cli, SMBclose, 0, 3, vwv, + 0, NULL); } NTSTATUS cli_close_recv(struct async_req *req) @@ -975,20 +987,30 @@ NTSTATUS cli_close_recv(struct async_req *req) bool cli_close(struct cli_state *cli, int fnum) { TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev; struct async_req *req; bool result = false; - if (cli_tmp_event_ctx(frame, cli) == NULL) { + if (cli->fd_event != NULL) { + /* + * Can't use sync call while an async call is in flight + */ + cli_set_error(cli, NT_STATUS_INVALID_PARAMETER); + goto fail; + } + + ev = event_context_init(frame); + if (ev == NULL) { goto fail; } - req = cli_close_send(frame, cli, fnum); + req = cli_close_send(frame, ev, cli, fnum); if (req == NULL) { goto fail; } while (req->state < ASYNC_REQ_DONE) { - event_loop_once(cli->event_ctx); + event_loop_once(ev); } result = NT_STATUS_IS_OK(cli_close_recv(req)); diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 2b34fce5bd..d2c8f3c1ba 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -41,6 +41,7 @@ static size_t cli_read_max_bufsize(struct cli_state *cli) */ struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, struct cli_state *cli, int fnum, off_t offset, size_t size) { @@ -76,7 +77,7 @@ struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx, wct += 2; } - result = cli_request_send(mem_ctx, cli, SMBreadX, 0, wct, vwv, + result = cli_request_send(mem_ctx, ev, cli, SMBreadX, 0, wct, vwv, 0, NULL); if (result == NULL) { return NULL; @@ -144,6 +145,7 @@ NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received, struct cli_pull_state { struct async_req *req; + struct event_context *ev; struct cli_state *cli; uint16_t fnum; off_t start_offset; @@ -202,7 +204,9 @@ static void cli_pull_read_done(struct async_req *read_req); * Prepare an async pull request */ -struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, struct cli_state *cli, +struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, uint16_t fnum, off_t start_offset, SMB_OFF_T size, size_t window_size, NTSTATUS (*sink)(char *buf, size_t n, @@ -213,7 +217,7 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, struct cli_state *cli, struct cli_pull_state *state; int i; - result = async_req_new(mem_ctx, cli->event_ctx); + result = async_req_new(mem_ctx, ev); if (result == NULL) { goto failed; } @@ -226,6 +230,7 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, struct cli_state *cli, state->req = result; state->cli = cli; + state->ev = ev; state->fnum = fnum; state->start_offset = start_offset; state->size = size; @@ -268,7 +273,7 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, struct cli_state *cli, request_thistime = MIN(size_left, state->chunk_size); state->reqs[i] = cli_read_andx_send( - state->reqs, cli, fnum, + state->reqs, ev, cli, fnum, state->start_offset + state->requested, request_thistime); @@ -363,7 +368,8 @@ static void cli_pull_read_done(struct async_req *read_req) state->top_req)); new_req = cli_read_andx_send( - state->reqs, state->cli, state->fnum, + state->reqs, state->ev, state->cli, + state->fnum, state->start_offset + state->requested, request_thistime); @@ -403,21 +409,30 @@ NTSTATUS cli_pull(struct cli_state *cli, uint16_t fnum, void *priv, SMB_OFF_T *received) { TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev; struct async_req *req; NTSTATUS result = NT_STATUS_NO_MEMORY; - if (cli_tmp_event_ctx(frame, cli) == NULL) { + if (cli->fd_event != NULL) { + /* + * Can't use sync call while an async call is in flight + */ + return NT_STATUS_INVALID_PARAMETER; + } + + ev = event_context_init(frame); + if (ev == NULL) { goto nomem; } - req = cli_pull_send(frame, cli, fnum, start_offset, size, window_size, - sink, priv); + req = cli_pull_send(frame, ev, cli, fnum, start_offset, size, + window_size, sink, priv); if (req == NULL) { goto nomem; } while (req->state < ASYNC_REQ_DONE) { - event_loop_once(cli->event_ctx); + event_loop_once(ev); } result = cli_pull_recv(req, received); -- cgit From 128524930d490fb5ea637d99bffb36157c80869b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 25 Aug 2008 13:33:41 +0200 Subject: Add cli_pull_reply Along the lines of cli_request_send this abstracts away the smb-level buffer handling when parsing replies we got from the server. (This used to be commit 253134d3aaa359fdfb665709dd5686f69af7f8fd) --- source3/libsmb/async_smb.c | 54 +++++++++++++++++++++++++++++++++++++++++++ source3/libsmb/clifile.c | 20 ++++++++++++---- source3/libsmb/clireadwrite.c | 17 ++++++++++---- 3 files changed, 81 insertions(+), 10 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c index e58b753da2..32f0e8abd6 100644 --- a/source3/libsmb/async_smb.c +++ b/source3/libsmb/async_smb.c @@ -230,6 +230,60 @@ struct async_req *cli_request_send(TALLOC_CTX *mem_ctx, return result; } +/** + * @brief Pull reply data out of a request + * @param[in] req The request that we just received a reply for + * @param[out] pwct How many words did the server send? + * @param[out] pvwv The words themselves + * @param[out] pnum_bytes How many bytes did the server send? + * @param[out] pbytes The bytes themselves + * @retval Was the reply formally correct? + */ + +NTSTATUS cli_pull_reply(struct async_req *req, + uint8_t *pwct, uint16_t **pvwv, + uint16_t *pnum_bytes, uint8_t **pbytes) +{ + struct cli_request *cli_req = cli_request_get(req); + uint8_t wct, cmd; + uint16_t num_bytes; + size_t wct_ofs, bytes_offset; + NTSTATUS status; + + status = cli_pull_error(cli_req->inbuf); + + if (NT_STATUS_IS_ERR(status)) { + cli_set_error(cli_req->cli, status); + return status; + } + + cmd = CVAL(cli_req->inbuf, smb_com); + wct_ofs = smb_wct; + + wct = CVAL(cli_req->inbuf, wct_ofs); + + bytes_offset = wct_ofs + 1 + wct * sizeof(uint16_t); + num_bytes = SVAL(cli_req->inbuf, bytes_offset); + + /* + * wct_ofs is a 16-bit value plus 4, wct is a 8-bit value, num_bytes + * is a 16-bit value. So bytes_offset being size_t should be far from + * wrapping. + */ + + if ((bytes_offset + 2 > talloc_get_size(cli_req->inbuf)) + || (bytes_offset > 0xffff)) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + + *pwct = wct; + *pvwv = (uint16_t *)(cli_req->inbuf + wct_ofs + 1); + *pnum_bytes = num_bytes; + *pbytes = (uint8_t *)cli_req->inbuf + bytes_offset + 2; + + return NT_STATUS_OK; +} + /* * Convenience function to get the SMB part out of an async_req */ diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c index dfb0ce8c11..b3032a08eb 100644 --- a/source3/libsmb/clifile.c +++ b/source3/libsmb/clifile.c @@ -902,7 +902,10 @@ struct async_req *cli_open_send(TALLOC_CTX *mem_ctx, struct event_context *ev, NTSTATUS cli_open_recv(struct async_req *req, int *fnum) { - struct cli_request *cli_req = cli_request_get(req); + uint8_t wct; + uint16_t *vwv; + uint16_t num_bytes; + uint8_t *bytes; NTSTATUS status; SMB_ASSERT(req->state >= ASYNC_REQ_DONE); @@ -910,12 +913,16 @@ NTSTATUS cli_open_recv(struct async_req *req, int *fnum) return req->status; } - status = cli_pull_error(cli_req->inbuf); + status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes); if (!NT_STATUS_IS_OK(status)) { return status; } - *fnum = SVAL(cli_req->inbuf, smb_vwv2); + if (wct < 3) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + + *fnum = SVAL(vwv+2, 0); return NT_STATUS_OK; } @@ -974,14 +981,17 @@ struct async_req *cli_close_send(TALLOC_CTX *mem_ctx, struct event_context *ev, NTSTATUS cli_close_recv(struct async_req *req) { - struct cli_request *cli_req = cli_request_get(req); + uint8_t wct; + uint16_t *vwv; + uint16_t num_bytes; + uint8_t *bytes; SMB_ASSERT(req->state >= ASYNC_REQ_DONE); if (req->state == ASYNC_REQ_ERROR) { return req->status; } - return cli_pull_error(cli_req->inbuf); + return cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes); } bool cli_close(struct cli_state *cli, int fnum) diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index d2c8f3c1ba..b64a4c68f3 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -104,6 +104,10 @@ NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received, uint8_t **rcvbuf) { struct cli_request *cli_req = cli_request_get(req); + uint8_t wct; + uint16_t *vwv; + uint16_t num_bytes; + uint8_t *bytes; NTSTATUS status; size_t size; @@ -112,24 +116,27 @@ NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received, return req->status; } - status = cli_pull_error(cli_req->inbuf); + status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes); if (NT_STATUS_IS_ERR(status)) { return status; } + if (wct < 12) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + /* size is the number of bytes the server returned. * Might be zero. */ - size = SVAL(cli_req->inbuf, smb_vwv5); - size |= (((unsigned int)(SVAL(cli_req->inbuf, smb_vwv7))) << 16); + size = SVAL(vwv + 5, 0); + size |= (((unsigned int)SVAL(vwv + 7, 0)) << 16); if (size > cli_req->data.read.size) { DEBUG(5,("server returned more than we wanted!\n")); return NT_STATUS_UNEXPECTED_IO_ERROR; } - *rcvbuf = (uint8_t *) - (smb_base(cli_req->inbuf) + SVAL(cli_req->inbuf, smb_vwv6)); + *rcvbuf = (uint8_t *)(smb_base(cli_req->inbuf) + SVAL(vwv + 6, 0)); *received = size; return NT_STATUS_OK; } -- cgit From 77d1b29e25512982a1f912adac46bb954ee3d19f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 25 Aug 2008 14:40:15 +0200 Subject: Move "struct cli_request" from client.h to async_smb.h Also add some comments (This used to be commit 2ecc311f785317caf5b60051147dcd085c80d64f) --- source3/libsmb/async_smb.c | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c index 32f0e8abd6..e36e514a16 100644 --- a/source3/libsmb/async_smb.c +++ b/source3/libsmb/async_smb.c @@ -22,8 +22,10 @@ static void cli_state_handler(struct event_context *event_ctx, struct fd_event *event, uint16 flags, void *p); -/* +/** * Fetch an error out of a NBT packet + * @param[in] buf The SMB packet + * @retval The error, converted to NTSTATUS */ NTSTATUS cli_pull_error(char *buf) @@ -43,8 +45,10 @@ NTSTATUS cli_pull_error(char *buf) return NT_STATUS_DOS(CVAL(buf, smb_rcls), SVAL(buf,smb_err)); } -/* +/** * Compatibility helper for the sync APIs: Fake NTSTATUS in cli->inbuf + * @param[in] cli The client connection that just received an error + * @param[in] status The error to set on "cli" */ void cli_set_error(struct cli_state *cli, NTSTATUS status) @@ -64,8 +68,10 @@ void cli_set_error(struct cli_state *cli, NTSTATUS status) return; } -/* +/** * Allocate a new mid + * @param[in] cli The client connection + * @retval The new, unused mid */ static uint16_t cli_new_mid(struct cli_state *cli) @@ -91,6 +97,13 @@ static uint16_t cli_new_mid(struct cli_state *cli) } } +/** + * Print an async req that happens to be a cli_request + * @param[in] mem_ctx The TALLOC_CTX to put the result on + * @param[in] req The request to print + * @retval The string representation of "req" + */ + static char *cli_request_print(TALLOC_CTX *mem_ctx, struct async_req *req) { char *result = async_req_print(mem_ctx, req); @@ -104,6 +117,12 @@ static char *cli_request_print(TALLOC_CTX *mem_ctx, struct async_req *req) result, "mid=%d\n", cli_req->mid); } +/** + * Destroy a cli_request + * @param[in] req The cli_request to kill + * @retval Can't fail + */ + static int cli_request_destructor(struct cli_request *req) { if (req->enc_state != NULL) { @@ -284,8 +303,10 @@ NTSTATUS cli_pull_reply(struct async_req *req, return NT_STATUS_OK; } -/* +/** * Convenience function to get the SMB part out of an async_req + * @param[in] req The request to look at + * @retval The private_data as struct cli_request */ struct cli_request *cli_request_get(struct async_req *req) @@ -296,8 +317,9 @@ struct cli_request *cli_request_get(struct async_req *req) return talloc_get_type_abort(req->private_data, struct cli_request); } -/* +/** * A PDU has arrived on cli->evt_inbuf + * @param[in] cli The cli_state that received something */ static void handle_incoming_pdu(struct cli_state *cli) @@ -434,8 +456,12 @@ static void handle_incoming_pdu(struct cli_state *cli) return; } -/* +/** * fd event callback. This is the basic connection to the socket + * @param[in] event_ctx The event context that called us + * @param[in] event The event that fired + * @param[in] flags EVENT_FD_READ | EVENT_FD_WRITE + * @param[in] p private_data, in this case the cli_state */ static void cli_state_handler(struct event_context *event_ctx, -- cgit From 65dcdf9c32e8ac43344b23db528206c02fcb967c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 25 Aug 2008 15:56:26 +0200 Subject: This adds the code to allow chained requests in libsmb/ This is not compiled yet, but it makes the patches much easier to read if it is add in bulk. (This used to be commit b4c539ba041bab8856c83816f08a35b5f5b21740) --- source3/libsmb/async_smb.c | 534 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 534 insertions(+) (limited to 'source3/libsmb') diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c index e36e514a16..e764147432 100644 --- a/source3/libsmb/async_smb.c +++ b/source3/libsmb/async_smb.c @@ -135,6 +135,540 @@ static int cli_request_destructor(struct cli_request *req) return 0; } +#if 0 + +/** + * 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? + * + * While chaining requests, the "next" request we're looking at needs to put + * its SMB_Command before the data the previous request already built up added + * to the chain. Find the offset to the place where we have to put our cmd. + */ + +static bool find_andx_cmd_ofs(char *buf, size_t *pofs) +{ + uint8_t cmd; + size_t ofs; + + cmd = CVAL(buf, smb_com); + + SMB_ASSERT(is_andx_req(cmd)); + + ofs = smb_vwv0; + + while (CVAL(buf, ofs) != 0xff) { + + if (!is_andx_req(CVAL(buf, ofs))) { + return false; + } + + /* + * ofs is from start of smb header, so add the 4 length + * bytes. The next cmd is right after the wct field. + */ + ofs = SVAL(buf, ofs+2) + 4 + 1; + + SMB_ASSERT(ofs+4 < talloc_get_size(buf)); + } + + *pofs = ofs; + return true; +} + +/** + * @brief Destroy an async_req that is the visible part of a cli_request + * @param[in] req The request to kill + * @retval Return 0 to make talloc happy + * + * This destructor is a bit tricky: Because a cli_request can host more than + * one async_req for chained requests, we need to make sure that the + * "cli_request" that we were part of is correctly destroyed at the right + * time. This is done by NULLing out ourself from the "async" member of our + * "cli_request". If there is none left, then also TALLOC_FREE() the + * cli_request, which was a talloc child of the client connection cli_state. + */ + +static int cli_async_req_destructor(struct async_req *req) +{ + struct cli_request *cli_req = cli_request_get(req); + int i, pending; + bool found = false; + + pending = 0; + + for (i=0; inum_async; i++) { + if (cli_req->async[i] == req) { + cli_req->async[i] = NULL; + found = true; + } + if (cli_req->async[i] != NULL) { + pending += 1; + } + } + + SMB_ASSERT(found); + + if (pending == 0) { + TALLOC_FREE(cli_req); + } + + return 0; +} + +/** + * @brief Chain up a request + * @param[in] mem_ctx The TALLOC_CTX for the result + * @param[in] ev The event context that will call us back + * @param[in] cli The cli_state we queue the request up for + * @param[in] smb_command The command that we want to issue + * @param[in] additional_flags open_and_x wants to add oplock header flags + * @param[in] wct How many words? + * @param[in] vwv The words, already in network order + * @param[in] num_bytes How many bytes? + * @param[in] bytes The data the request ships + * + * cli_request_chain() is the core of the SMB request marshalling routine. It + * will create a new async_req structure in the cli->chain_accumulator->async + * array and marshall the smb_cmd, the vwv array and the bytes into + * cli->chain_accumulator->outbuf. + */ + +static struct async_req *cli_request_chain(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + uint8_t smb_command, + uint8_t additional_flags, + uint8_t wct, const uint16_t *vwv, + uint16_t num_bytes, + const uint8_t *bytes) +{ + struct async_req **tmp_reqs; + char *tmp_buf; + struct cli_request *req; + size_t old_size, new_size; + size_t ofs; + + req = cli->chain_accumulator; + + tmp_reqs = TALLOC_REALLOC_ARRAY(req, req->async, struct async_req *, + req->num_async + 1); + if (tmp_reqs == NULL) { + DEBUG(0, ("talloc failed\n")); + return NULL; + } + req->async = tmp_reqs; + req->num_async += 1; + + req->async[req->num_async-1] = async_req_new(mem_ctx, ev); + if (req->async[req->num_async-1] == NULL) { + DEBUG(0, ("async_req_new failed\n")); + req->num_async -= 1; + return NULL; + } + req->async[req->num_async-1]->private_data = req; + req->async[req->num_async-1]->print = cli_request_print; + talloc_set_destructor(req->async[req->num_async-1], + cli_async_req_destructor); + + old_size = talloc_get_size(req->outbuf); + + /* + * We need space for the wct field, the words, the byte count field + * and the bytes themselves. + */ + new_size = old_size + 1 + wct * sizeof(uint16_t) + 2 + num_bytes; + + if (new_size > 0xffff) { + DEBUG(1, ("cli_request_chain: %u bytes won't fit\n", + (unsigned)new_size)); + goto fail; + } + + tmp_buf = TALLOC_REALLOC_ARRAY(NULL, req->outbuf, char, new_size); + if (tmp_buf == NULL) { + DEBUG(0, ("talloc failed\n")); + goto fail; + } + req->outbuf = tmp_buf; + + if (old_size == smb_wct) { + SCVAL(req->outbuf, smb_com, smb_command); + } else { + size_t andx_cmd_ofs; + if (!find_andx_cmd_ofs(req->outbuf, &andx_cmd_ofs)) { + DEBUG(1, ("invalid command chain\n")); + goto fail; + } + SCVAL(req->outbuf, andx_cmd_ofs, smb_command); + SSVAL(req->outbuf, andx_cmd_ofs + 2, old_size - 4); + } + + ofs = old_size; + + SCVAL(req->outbuf, ofs, wct); + ofs += 1; + + memcpy(req->outbuf + ofs, vwv, sizeof(uint16_t) * wct); + ofs += sizeof(uint16_t) * wct; + + SSVAL(req->outbuf, ofs, num_bytes); + ofs += sizeof(uint16_t); + + memcpy(req->outbuf + ofs, bytes, num_bytes); + + return req->async[req->num_async-1]; + + fail: + TALLOC_FREE(req->async[req->num_async-1]); + req->num_async -= 1; + return NULL; +} + +/** + * @brief prepare a cli_state to accept a chain of requests + * @param[in] cli The cli_state we want to queue up in + * @param[in] ev The event_context that will call us back for the socket + * @param[in] size_hint How many bytes are expected, just an optimization + * @retval Did we have enough memory? + * + * cli_chain_cork() sets up a new cli_request in cli->chain_accumulator. If + * cli is used in an async fashion, i.e. if we have outstanding requests, then + * we do not have to create a fd event. If cli is used only with the sync + * helpers, we need to create the fd_event here. + * + * If you want to issue a chained request to the server, do a + * cli_chain_cork(), then do you cli_open_send(), cli_read_and_x_send(), + * cli_close_send() and so on. The async requests that come out of + * cli_xxx_send() are normal async requests with the difference that they + * won't be shipped individually. But the event_context will still trigger the + * req->async.fn to be called on every single request. + * + * You have to take care yourself that you only issue chainable requests in + * the middle of the chain. + */ + +bool cli_chain_cork(struct cli_state *cli, struct event_context *ev, + size_t size_hint) +{ + struct cli_request *req = NULL; + + SMB_ASSERT(cli->chain_accumulator == NULL); + + if (cli->fd_event == NULL) { + SMB_ASSERT(cli->outstanding_requests == NULL); + cli->fd_event = event_add_fd(ev, cli, cli->fd, + EVENT_FD_READ, + cli_state_handler, cli); + if (cli->fd_event == NULL) { + return false; + } + } + + req = talloc(cli, struct cli_request); + if (req == NULL) { + goto fail; + } + req->cli = cli; + + if (size_hint == 0) { + size_hint = 100; + } + req->outbuf = talloc_array(req, char, smb_wct + size_hint); + if (req->outbuf == NULL) { + goto fail; + } + req->outbuf = TALLOC_REALLOC_ARRAY(NULL, req->outbuf, char, smb_wct); + + req->num_async = 0; + req->async = NULL; + + req->enc_state = NULL; + + SSVAL(req->outbuf, smb_tid, cli->cnum); + cli_setup_packet_buf(cli, req->outbuf); + + req->mid = cli_new_mid(cli); + SSVAL(req->outbuf, smb_mid, req->mid); + + cli->chain_accumulator = req; + + DEBUG(10, ("cli_chain_cork: mid=%d\n", req->mid)); + + return true; + fail: + TALLOC_FREE(req); + if (cli->outstanding_requests == NULL) { + TALLOC_FREE(cli->fd_event); + } + return false; +} + +/** + * Ship a request queued up via cli_request_chain() + * @param[in] cl The connection + */ + +void cli_chain_uncork(struct cli_state *cli) +{ + struct cli_request *req = cli->chain_accumulator; + + SMB_ASSERT(req != NULL); + + DLIST_ADD_END(cli->outstanding_requests, req, struct cli_request *); + talloc_set_destructor(req, cli_request_destructor); + + cli->chain_accumulator = NULL; + + smb_setlen(req->outbuf, talloc_get_size(req->outbuf) - 4); + + cli_calculate_sign_mac(cli, req->outbuf); + + if (cli_encryption_on(cli)) { + NTSTATUS status; + char *enc_buf; + + status = cli_encrypt_message(cli, req->outbuf, &enc_buf); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("Error in encrypting client message. " + "Error %s\n", nt_errstr(status))); + TALLOC_FREE(req); + return; + } + req->outbuf = enc_buf; + req->enc_state = cli->trans_enc_state; + } + + req->sent = 0; + + event_fd_set_writeable(cli->fd_event); +} + +/** + * @brief Send a request to the server + * @param[in] mem_ctx The TALLOC_CTX for the result + * @param[in] ev The event context that will call us back + * @param[in] cli The cli_state we queue the request up for + * @param[in] smb_command The command that we want to issue + * @param[in] additional_flags open_and_x wants to add oplock header flags + * @param[in] wct How many words? + * @param[in] vwv The words, already in network order + * @param[in] num_bytes How many bytes? + * @param[in] bytes The data the request ships + * + * This is the generic routine to be used by the cli_xxx_send routines. + */ + +struct async_req *cli_request_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + uint8_t smb_command, + uint8_t additional_flags, + uint8_t wct, const uint16_t *vwv, + uint16_t num_bytes, const uint8_t *bytes) +{ + struct async_req *result; + bool uncork = false; + + if (cli->chain_accumulator == NULL) { + if (!cli_chain_cork(cli, ev, + wct * sizeof(uint16_t) + num_bytes + 3)) { + DEBUG(1, ("cli_chain_cork failed\n")); + return NULL; + } + uncork = true; + } + + result = cli_request_chain(mem_ctx, ev, cli, smb_command, + additional_flags, wct, vwv, + num_bytes, bytes); + + if (result == NULL) { + DEBUG(1, ("cli_request_chain failed\n")); + } + + if (uncork) { + cli_chain_uncork(cli); + } + + return result; +} + +/** + * Figure out if there is an andx command behind the current one + * @param[in] buf The smb buffer to look at + * @param[in] ofs The offset to the wct field that is followed by the cmd + * @retval Is there a command following? + */ + +static bool have_andx_command(const char *buf, uint16_t ofs) +{ + uint8_t wct; + size_t buflen = talloc_get_size(buf); + + if ((ofs == buflen-1) || (ofs == buflen)) { + return false; + } + + wct = CVAL(buf, ofs); + if (wct < 2) { + /* + * Not enough space for the command and a following pointer + */ + return false; + } + return (CVAL(buf, ofs+1) != 0xff); +} + +/** + * @brief Pull reply data out of a request + * @param[in] req The request that we just received a reply for + * @param[out] pwct How many words did the server send? + * @param[out] pvwv The words themselves + * @param[out] pnum_bytes How many bytes did the server send? + * @param[out] pbytes The bytes themselves + * @retval Was the reply formally correct? + */ + +NTSTATUS cli_pull_reply(struct async_req *req, + uint8_t *pwct, uint16_t **pvwv, + uint16_t *pnum_bytes, uint8_t **pbytes) +{ + struct cli_request *cli_req = cli_request_get(req); + uint8_t wct, cmd; + uint16_t num_bytes; + size_t wct_ofs, bytes_offset; + int i, j; + NTSTATUS status; + + for (i = 0; i < cli_req->num_async; i++) { + if (req == cli_req->async[i]) { + break; + } + } + + if (i == cli_req->num_async) { + cli_set_error(cli_req->cli, NT_STATUS_INVALID_PARAMETER); + return NT_STATUS_INVALID_PARAMETER; + } + + /** + * The status we pull here is only relevant for the last reply in the + * chain. + */ + + status = cli_pull_error(cli_req->inbuf); + + if (i == 0) { + if (NT_STATUS_IS_ERR(status) + && !have_andx_command(cli_req->inbuf, smb_wct)) { + cli_set_error(cli_req->cli, status); + return status; + } + wct_ofs = smb_wct; + goto done; + } + + cmd = CVAL(cli_req->inbuf, smb_com); + wct_ofs = smb_wct; + + for (j = 0; j < i; j++) { + if (j < i-1) { + if (cmd == 0xff) { + return NT_STATUS_REQUEST_ABORTED; + } + if (!is_andx_req(cmd)) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + } + + if (!have_andx_command(cli_req->inbuf, wct_ofs)) { + /* + * This request was not completed because a previous + * request in the chain had received an error. + */ + return NT_STATUS_REQUEST_ABORTED; + } + + wct_ofs = SVAL(cli_req->inbuf, wct_ofs + 3); + + /* + * Skip the all-present length field. No overflow, we've just + * put a 16-bit value into a size_t. + */ + wct_ofs += 4; + + if (wct_ofs+2 > talloc_get_size(cli_req->inbuf)) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + + cmd = CVAL(cli_req->inbuf, wct_ofs + 1); + } + + if (!have_andx_command(cli_req->inbuf, wct_ofs) + && NT_STATUS_IS_ERR(status)) { + /* + * The last command takes the error code. All further commands + * down the requested chain will get a + * NT_STATUS_REQUEST_ABORTED. + */ + return status; + } + + done: + wct = CVAL(cli_req->inbuf, wct_ofs); + + bytes_offset = wct_ofs + 1 + wct * sizeof(uint16_t); + num_bytes = SVAL(cli_req->inbuf, bytes_offset); + + /* + * wct_ofs is a 16-bit value plus 4, wct is a 8-bit value, num_bytes + * is a 16-bit value. So bytes_offset being size_t should be far from + * wrapping. + */ + + if ((bytes_offset + 2 > talloc_get_size(cli_req->inbuf)) + || (bytes_offset > 0xffff)) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + + *pwct = wct; + *pvwv = (uint16_t *)(cli_req->inbuf + wct_ofs + 1); + *pnum_bytes = num_bytes; + *pbytes = (uint8_t *)cli_req->inbuf + bytes_offset + 2; + + return NT_STATUS_OK; +} + +#endif + /* * Create a fresh async smb request */ -- cgit From b054f14111337c826548d7728dc2b0a66ab5beae Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 25 Aug 2008 15:59:36 +0200 Subject: Activate code to enable chained requests Add the CHAIN1 torture test (This used to be commit 82992d74a99b056bbfe90e1b79190e0b7c0bf2bd) --- source3/libsmb/async_smb.c | 203 ++++++--------------------------------------- 1 file changed, 27 insertions(+), 176 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c index e764147432..4d6c32edfa 100644 --- a/source3/libsmb/async_smb.c +++ b/source3/libsmb/async_smb.c @@ -135,8 +135,6 @@ static int cli_request_destructor(struct cli_request *req) return 0; } -#if 0 - /** * Is the SMB command able to hold an AND_X successor * @param[in] cmd The SMB command in question @@ -667,176 +665,6 @@ NTSTATUS cli_pull_reply(struct async_req *req, return NT_STATUS_OK; } -#endif - -/* - * Create a fresh async smb request - */ - -static struct async_req *cli_request_new(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct cli_state *cli, - uint8_t num_words, size_t num_bytes, - struct cli_request **preq) -{ - struct async_req *result; - struct cli_request *cli_req; - size_t bufsize = smb_size + num_words * 2 + num_bytes; - - result = async_req_new(mem_ctx, ev); - if (result == NULL) { - return NULL; - } - - cli_req = (struct cli_request *)talloc_size( - result, sizeof(*cli_req) + bufsize); - if (cli_req == NULL) { - TALLOC_FREE(result); - return NULL; - } - talloc_set_name_const(cli_req, "struct cli_request"); - result->private_data = cli_req; - result->print = cli_request_print; - - cli_req->async = result; - cli_req->cli = cli; - cli_req->outbuf = ((char *)cli_req + sizeof(*cli_req)); - cli_req->sent = 0; - cli_req->mid = cli_new_mid(cli); - cli_req->inbuf = NULL; - cli_req->enc_state = NULL; - - SCVAL(cli_req->outbuf, smb_wct, num_words); - SSVAL(cli_req->outbuf, smb_vwv + num_words * 2, num_bytes); - - DLIST_ADD_END(cli->outstanding_requests, cli_req, - struct cli_request *); - talloc_set_destructor(cli_req, cli_request_destructor); - - DEBUG(10, ("cli_request_new: mid=%d\n", cli_req->mid)); - - *preq = cli_req; - return result; -} - -/* - * Ship a new smb request to the server - */ -struct async_req *cli_request_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - struct cli_state *cli, - uint8_t smb_command, - uint8_t additional_flags, - uint8_t wct, const uint16_t *vwv, - uint16_t num_bytes, const uint8_t *bytes) -{ - struct async_req *result; - struct cli_request *req; - - if (cli->fd_event == NULL) { - SMB_ASSERT(cli->outstanding_requests == NULL); - cli->fd_event = event_add_fd(ev, cli, cli->fd, - EVENT_FD_READ, - cli_state_handler, cli); - if (cli->fd_event == NULL) { - return NULL; - } - } - - result = cli_request_new(mem_ctx, ev, cli, wct, num_bytes, &req); - if (result == NULL) { - DEBUG(0, ("cli_request_new failed\n")); - TALLOC_FREE(cli->fd_event); - return NULL; - } - - cli_set_message(req->outbuf, wct, num_bytes, false); - SCVAL(req->outbuf, smb_com, smb_command); - SSVAL(req->outbuf, smb_tid, cli->cnum); - cli_setup_packet_buf(cli, req->outbuf); - - memcpy(req->outbuf + smb_vwv0, vwv, sizeof(uint16_t) * wct); - memcpy(smb_buf(req->outbuf), bytes, num_bytes); - SSVAL(req->outbuf, smb_mid, req->mid); - SCVAL(cli->outbuf, smb_flg, - CVAL(cli->outbuf,smb_flg) | additional_flags); - - cli_calculate_sign_mac(cli, req->outbuf); - - if (cli_encryption_on(cli)) { - NTSTATUS status; - char *enc_buf; - - status = cli_encrypt_message(cli, req->outbuf, &enc_buf); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("Error in encrypting client message. " - "Error %s\n", nt_errstr(status))); - TALLOC_FREE(req); - return NULL; - } - req->outbuf = enc_buf; - req->enc_state = cli->trans_enc_state; - } - - event_fd_set_writeable(cli->fd_event); - - return result; -} - -/** - * @brief Pull reply data out of a request - * @param[in] req The request that we just received a reply for - * @param[out] pwct How many words did the server send? - * @param[out] pvwv The words themselves - * @param[out] pnum_bytes How many bytes did the server send? - * @param[out] pbytes The bytes themselves - * @retval Was the reply formally correct? - */ - -NTSTATUS cli_pull_reply(struct async_req *req, - uint8_t *pwct, uint16_t **pvwv, - uint16_t *pnum_bytes, uint8_t **pbytes) -{ - struct cli_request *cli_req = cli_request_get(req); - uint8_t wct, cmd; - uint16_t num_bytes; - size_t wct_ofs, bytes_offset; - NTSTATUS status; - - status = cli_pull_error(cli_req->inbuf); - - if (NT_STATUS_IS_ERR(status)) { - cli_set_error(cli_req->cli, status); - return status; - } - - cmd = CVAL(cli_req->inbuf, smb_com); - wct_ofs = smb_wct; - - wct = CVAL(cli_req->inbuf, wct_ofs); - - bytes_offset = wct_ofs + 1 + wct * sizeof(uint16_t); - num_bytes = SVAL(cli_req->inbuf, bytes_offset); - - /* - * wct_ofs is a 16-bit value plus 4, wct is a 8-bit value, num_bytes - * is a 16-bit value. So bytes_offset being size_t should be far from - * wrapping. - */ - - if ((bytes_offset + 2 > talloc_get_size(cli_req->inbuf)) - || (bytes_offset > 0xffff)) { - return NT_STATUS_INVALID_NETWORK_RESPONSE; - } - - *pwct = wct; - *pvwv = (uint16_t *)(cli_req->inbuf + wct_ofs + 1); - *pnum_bytes = num_bytes; - *pbytes = (uint8_t *)cli_req->inbuf + bytes_offset + 2; - - return NT_STATUS_OK; -} - /** * Convenience function to get the SMB part out of an async_req * @param[in] req The request to look at @@ -862,8 +690,11 @@ static void handle_incoming_pdu(struct cli_state *cli) uint16_t mid; size_t raw_pdu_len, buf_len, pdu_len, rest_len; char *pdu; + int i; NTSTATUS status; + int num_async; + /* * The encrypted PDU len might differ from the unencrypted one */ @@ -976,7 +807,24 @@ static void handle_incoming_pdu(struct cli_state *cli) req->inbuf = talloc_move(req, &pdu); - async_req_done(req->async); + /* + * Freeing the last async_req will free the req (see + * cli_async_req_destructor). So make a copy of req->num_async, we + * can't reference it in the last round. + */ + + num_async = req->num_async; + + for (i=0; iasync via its + * destructor cli_async_req_destructor(). + */ + if (req->async[i] != NULL) { + async_req_done(req->async[i]); + } + } return; invalidate_requests: @@ -985,7 +833,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, status); + async_req_error(req->async[0], status); } return; } @@ -1101,8 +949,11 @@ static void cli_state_handler(struct event_context *event_ctx, sock_error: for (req = cli->outstanding_requests; req; req = req->next) { - req->async->state = ASYNC_REQ_ERROR; - req->async->status = map_nt_error_from_unix(errno); + int i; + for (i=0; inum_async; i++) { + req->async[i]->state = ASYNC_REQ_ERROR; + req->async[i]->status = map_nt_error_from_unix(errno); + } } TALLOC_FREE(cli->fd_event); close(cli->fd); -- cgit From bb0fc9cfceab7e961eaa9049d111121609ff8174 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 27 Aug 2008 19:26:40 +0200 Subject: Add cli_request->recv_helper Necessary for requests with multiple replies (This used to be commit cb2e338eb33dfb4627f9b43456af0c86d7d268c6) --- source3/libsmb/async_smb.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c index 4d6c32edfa..b5fa9c44b1 100644 --- a/source3/libsmb/async_smb.c +++ b/source3/libsmb/async_smb.c @@ -409,6 +409,7 @@ bool cli_chain_cork(struct cli_state *cli, struct event_context *ev, req->async = NULL; req->enc_state = NULL; + req->recv_helper.fn = NULL; SSVAL(req->outbuf, smb_tid, cli->cnum); cli_setup_packet_buf(cli, req->outbuf); @@ -822,7 +823,11 @@ static void handle_incoming_pdu(struct cli_state *cli) * destructor cli_async_req_destructor(). */ if (req->async[i] != NULL) { - async_req_done(req->async[i]); + if (req->recv_helper.fn != NULL) { + req->recv_helper.fn(req->async[i]); + } else { + async_req_done(req->async[i]); + } } } return; -- cgit From 228a12681bc7e6eb5bddb75b3b97a74c5eef1c3a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 27 Aug 2008 19:30:57 +0200 Subject: Add async smbecho client support (This used to be commit c1d645fbe39433541d8bfe6b818c855cee318dc5) --- source3/libsmb/clientgen.c | 166 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 139 insertions(+), 27 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index 2c0950de03..239ba470a9 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -637,41 +637,153 @@ bool cli_send_keepalive(struct cli_state *cli) return true; } -/**************************************************************************** - Send/receive a SMBecho command: ping the server -****************************************************************************/ +/** + * @brief: Collect a echo reply + * @param[in] req The corresponding async request + * + * There might be more than one echo reply. This helper pulls the reply out of + * the data stream. If all expected replies have arrived, declare the + * async_req done. + */ + +static void cli_echo_recv_helper(struct async_req *req) +{ + struct cli_request *cli_req; + uint8_t wct; + uint16_t *vwv; + uint16_t num_bytes; + uint8_t *bytes; + NTSTATUS status; + + status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + cli_req = cli_request_get(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); + return; + } + + cli_req->data.echo.num_echos -= 1; -bool cli_echo(struct cli_state *cli, uint16 num_echos, - unsigned char *data, size_t length) + if (cli_req->data.echo.num_echos == 0) { + client_set_trans_sign_state_off(cli_req->cli, cli_req->mid); + async_req_done(req); + return; + } + + return; +} + +/** + * @brief Send SMBEcho requests + * @param[in] mem_ctx The memory context to put the async_req on + * @param[in] ev The event context that will call us back + * @param[in] cli The connection to send the echo to + * @param[in] num_echos How many times do we want to get the reply? + * @param[in] data The data we want to get back + * @retval The async request + */ + +struct async_req *cli_echo_send(TALLOC_CTX *mem_ctx, struct event_context *ev, + struct cli_state *cli, uint16_t num_echos, + DATA_BLOB data) { - char *p; - int i; + uint16_t vwv[1]; + uint8_t *data_copy; + struct async_req *result; + struct cli_request *req; - SMB_ASSERT(length < 1024); + SSVAL(vwv, 0, num_echos); - memset(cli->outbuf,'\0',smb_size); - cli_set_message(cli->outbuf,1,length,true); - SCVAL(cli->outbuf,smb_com,SMBecho); - SSVAL(cli->outbuf,smb_tid,65535); - SSVAL(cli->outbuf,smb_vwv0,num_echos); - cli_setup_packet(cli); - p = smb_buf(cli->outbuf); - memcpy(p, data, length); - p += length; + data_copy = (uint8_t *)talloc_memdup(mem_ctx, data.data, data.length); + if (data_copy == NULL) { + return NULL; + } - cli_setup_bcc(cli, p); + result = cli_request_send(mem_ctx, ev, cli, SMBecho, 0, 1, vwv, + data.length, data.data); + if (result == NULL) { + TALLOC_FREE(data_copy); + return NULL; + } + req = cli_request_get(result); - cli_send_smb(cli); + client_set_trans_sign_state_on(cli, req->mid); - for (i=0; idata.echo.num_echos = num_echos; + req->data.echo.data.data = talloc_move(req, &data_copy); + req->data.echo.data.length = data.length; - if (cli_is_error(cli)) { - return false; - } + req->recv_helper.fn = cli_echo_recv_helper; + + return result; +} + +/** + * Get the result out from an echo request + * @param[in] req The async_req from cli_echo_send + * @retval Did the server reply correctly? + */ + +NTSTATUS cli_echo_recv(struct async_req *req) +{ + SMB_ASSERT(req->state >= ASYNC_REQ_DONE); + if (req->state == ASYNC_REQ_ERROR) { + return req->status; } - return true; + return NT_STATUS_OK; +} + +/** + * @brief Send/Receive SMBEcho requests + * @param[in] mem_ctx The memory context to put the async_req on + * @param[in] ev The event context that will call us back + * @param[in] cli The connection to send the echo to + * @param[in] num_echos How many times do we want to get the reply? + * @param[in] data The data we want to get back + * @retval Did the server reply correctly? + */ + +NTSTATUS cli_echo(struct cli_state *cli, uint16_t num_echos, DATA_BLOB data) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev; + struct async_req *req; + NTSTATUS status = NT_STATUS_NO_MEMORY; + + if (cli->fd_event != NULL) { + /* + * Can't use sync call while an async call is in flight + */ + cli_set_error(cli, NT_STATUS_INVALID_PARAMETER); + goto fail; + } + + ev = event_context_init(frame); + if (ev == NULL) { + goto fail; + } + + req = cli_echo_send(frame, ev, cli, num_echos, data); + if (req == NULL) { + goto fail; + } + + while (req->state < ASYNC_REQ_DONE) { + event_loop_once(ev); + } + + status = cli_echo_recv(req); + + fail: + TALLOC_FREE(frame); + return status; } -- cgit From f294f51bf0d136208fee1be343684ea890a499d0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 28 Aug 2008 15:44:14 +0200 Subject: Remove cli_request_get() req->private_data==NULL at this point is definitely a bug. (This used to be commit ce3dc9f616cafc1289a94ac7cae0beca967d836e) --- source3/libsmb/async_smb.c | 23 ++++++----------------- source3/libsmb/clientgen.c | 4 ++-- source3/libsmb/clireadwrite.c | 12 ++++++++---- 3 files changed, 16 insertions(+), 23 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c index b5fa9c44b1..79a924b9db 100644 --- a/source3/libsmb/async_smb.c +++ b/source3/libsmb/async_smb.c @@ -107,7 +107,8 @@ static uint16_t cli_new_mid(struct cli_state *cli) static char *cli_request_print(TALLOC_CTX *mem_ctx, struct async_req *req) { char *result = async_req_print(mem_ctx, req); - struct cli_request *cli_req = cli_request_get(req); + struct cli_request *cli_req = talloc_get_type_abort( + req->private_data, struct cli_request); if (result == NULL) { return NULL; @@ -216,7 +217,8 @@ static bool find_andx_cmd_ofs(char *buf, size_t *pofs) static int cli_async_req_destructor(struct async_req *req) { - struct cli_request *cli_req = cli_request_get(req); + struct cli_request *cli_req = talloc_get_type_abort( + req->private_data, struct cli_request); int i, pending; bool found = false; @@ -560,7 +562,8 @@ NTSTATUS cli_pull_reply(struct async_req *req, uint8_t *pwct, uint16_t **pvwv, uint16_t *pnum_bytes, uint8_t **pbytes) { - struct cli_request *cli_req = cli_request_get(req); + struct cli_request *cli_req = talloc_get_type_abort( + req->private_data, struct cli_request); uint8_t wct, cmd; uint16_t num_bytes; size_t wct_ofs, bytes_offset; @@ -666,20 +669,6 @@ NTSTATUS cli_pull_reply(struct async_req *req, return NT_STATUS_OK; } -/** - * Convenience function to get the SMB part out of an async_req - * @param[in] req The request to look at - * @retval The private_data as struct cli_request - */ - -struct cli_request *cli_request_get(struct async_req *req) -{ - if (req == NULL) { - return NULL; - } - return talloc_get_type_abort(req->private_data, struct cli_request); -} - /** * A PDU has arrived on cli->evt_inbuf * @param[in] cli The cli_state that received something diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index 239ba470a9..9d65fb4e94 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -661,7 +661,7 @@ static void cli_echo_recv_helper(struct async_req *req) return; } - cli_req = cli_request_get(req); + cli_req = talloc_get_type_abort(req->private_data, struct cli_request); if ((num_bytes != cli_req->data.echo.data.length) || (memcmp(cli_req->data.echo.data.data, bytes, @@ -713,7 +713,7 @@ struct async_req *cli_echo_send(TALLOC_CTX *mem_ctx, struct event_context *ev, TALLOC_FREE(data_copy); return NULL; } - req = cli_request_get(result); + req = talloc_get_type_abort(result->private_data, struct cli_request); client_set_trans_sign_state_on(cli, req->mid); diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index b64a4c68f3..ec63281630 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -83,7 +83,7 @@ struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx, return NULL; } - req = cli_request_get(result); + req = talloc_get_type_abort(result->private_data, struct cli_request); req->data.read.ofs = offset; req->data.read.size = size; @@ -103,7 +103,8 @@ struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx, NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received, uint8_t **rcvbuf) { - struct cli_request *cli_req = cli_request_get(req); + struct cli_request *cli_req = talloc_get_type_abort( + req->private_data, struct cli_request); uint8_t wct; uint16_t *vwv; uint16_t num_bytes; @@ -311,7 +312,8 @@ static void cli_pull_read_done(struct async_req *read_req) read_req->async.priv, struct async_req); struct cli_pull_state *state = talloc_get_type_abort( pull_req->private_data, struct cli_pull_state); - struct cli_request *read_state = cli_request_get(read_req); + struct cli_request *read_state = talloc_get_type_abort( + read_req->private_data, struct cli_request); NTSTATUS status; status = cli_read_andx_recv(read_req, &read_state->data.read.received, @@ -342,7 +344,9 @@ static void cli_pull_read_done(struct async_req *read_req) return; } - top_read = cli_request_get(state->reqs[state->top_req]); + top_read = talloc_get_type_abort( + state->reqs[state->top_req]->private_data, + struct cli_request); DEBUG(10, ("cli_pull_read_done: Pushing %d bytes, %d already " "pushed\n", (int)top_read->data.read.received, -- cgit From 0380fe9d823d6219441050a9b7298bf039b20742 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 22 Aug 2008 16:08:00 +0200 Subject: kerberos: move the KRB5_KEY* macros to header file. Guenther (This used to be commit c28fa17ffffee3e6fd4897c9c6b4937388a19600) --- source3/libsmb/clikrb5.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clikrb5.c b/source3/libsmb/clikrb5.c index fa21ad3467..b6fb7cf050 100644 --- a/source3/libsmb/clikrb5.c +++ b/source3/libsmb/clikrb5.c @@ -27,18 +27,6 @@ #ifdef HAVE_KRB5 -#ifdef HAVE_KRB5_KEYBLOCK_KEYVALUE /* Heimdal */ -#define KRB5_KEY_TYPE(k) ((k)->keytype) -#define KRB5_KEY_LENGTH(k) ((k)->keyvalue.length) -#define KRB5_KEY_DATA(k) ((k)->keyvalue.data) -#define KRB5_KEY_DATA_CAST void -#else /* MIT */ -#define KRB5_KEY_TYPE(k) ((k)->enctype) -#define KRB5_KEY_LENGTH(k) ((k)->length) -#define KRB5_KEY_DATA(k) ((k)->contents) -#define KRB5_KEY_DATA_CAST krb5_octet -#endif /* HAVE_KRB5_KEYBLOCK_KEYVALUE */ - #define GSSAPI_CHECKSUM 0x8003 /* Checksum type value for Kerberos */ #define GSSAPI_BNDLENGTH 16 /* Bind Length (rfc-1964 pg.3) */ #define GSSAPI_CHECKSUM_SIZE (12+GSSAPI_BNDLENGTH) -- cgit From bff20e14c38d7139033127182b76aa24e471b581 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 22 Aug 2008 14:58:01 +0200 Subject: kerberos: use KRB5_KT_KEY macro where appropriate. Guenther (This used to be commit a042dffd7121bda3dbc9509f69fcfae06ed4cc22) --- source3/libsmb/clikrb5.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clikrb5.c b/source3/libsmb/clikrb5.c index b6fb7cf050..bedd7d7aee 100644 --- a/source3/libsmb/clikrb5.c +++ b/source3/libsmb/clikrb5.c @@ -1045,6 +1045,7 @@ get_key_from_keytab(krb5_context context, krb5_error_code ret; krb5_keytab keytab; char *name = NULL; + krb5_keyblock *keyp; /* We have to open a new keytab handle here, as MIT does an implicit open/getnext/close on krb5_kt_get_entry. We @@ -1077,14 +1078,9 @@ get_key_from_keytab(krb5_context context, goto out; } -#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK /* Heimdal */ - ret = krb5_copy_keyblock(context, &entry.keyblock, out_key); -#elif defined(HAVE_KRB5_KEYTAB_ENTRY_KEY) /* MIT */ - ret = krb5_copy_keyblock(context, &entry.key, out_key); -#else -#error UNKNOWN_KRB5_KEYTAB_ENTRY_FORMAT -#endif + keyp = KRB5_KT_KEY(&entry); + ret = krb5_copy_keyblock(context, keyp, out_key); if (ret) { DEBUG(0,("get_key_from_keytab: failed to copy key: %s\n", error_message(ret))); goto out; @@ -1572,15 +1568,9 @@ done: #endif /* HAVE_KRB5_GET_INIT_CREDS_OPT_FREE */ } - krb5_enctype smb_get_enctype_from_kt_entry(const krb5_keytab_entry *kt_entry) + krb5_enctype smb_get_enctype_from_kt_entry(krb5_keytab_entry *kt_entry) { -#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEY /* MIT */ - return kt_entry->key.enctype; -#elif defined(HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK) /* Heimdal */ - return kt_entry->keyblock.keytype; -#else -#error UNKNOWN_KRB5_KEYTAB_ENTRY_KEYBLOCK_FORMAT -#endif + return KRB5_KEY_TYPE(KRB5_KT_KEY(kt_entry)); } -- cgit From 06dd647fe04535474eab85d110d409781544e7a7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 31 Aug 2008 11:45:12 +0200 Subject: Remove a duplicate retval check Jeremy, please check! (This used to be commit 6579005e6490f1a99b3860627ba51decaeb864bd) --- source3/libsmb/clikrb5.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clikrb5.c b/source3/libsmb/clikrb5.c index bedd7d7aee..f940081072 100644 --- a/source3/libsmb/clikrb5.c +++ b/source3/libsmb/clikrb5.c @@ -749,16 +749,10 @@ static krb5_error_code ads_krb5_mk_req(krb5_context context, ccache, &in_data ); if (retval) { - DEBUG( 1, ("ads_krb5_get_fwd_ticket failed (%s)\n", error_message( retval ) ) ); + DEBUG( 1, ("ads_krb5_get_fwd_ticket failed (%s)\n", + error_message( retval ) ) ); goto cleanup_creds; } - - if (retval) { - DEBUG( 1, ("krb5_auth_con_set_req_cksumtype failed (%s)\n", - error_message( retval ) ) ); - goto cleanup_creds; - } - } #endif -- cgit From cad04676ca07d5ae812c7dce26684870788c7535 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 1 Sep 2008 16:22:04 +0200 Subject: Fix typo (This used to be commit 544d1fd19a7e85af5f522c5b6b4b68c6beb093a6) --- source3/libsmb/clifile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c index b3032a08eb..a8b3440513 100644 --- a/source3/libsmb/clifile.c +++ b/source3/libsmb/clifile.c @@ -1892,7 +1892,7 @@ bool cli_set_ea_fnum(struct cli_state *cli, int fnum, const char *ea_name, const } /********************************************************* - Get an extended attribute list tility fn. + Get an extended attribute list utility fn. *********************************************************/ static bool cli_get_ea_list(struct cli_state *cli, -- cgit From 767130ebec474f16e951d1c450cca27e434e9b47 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 1 Sep 2008 21:28:57 +0200 Subject: Fix some nonempty blank lines (This used to be commit 9336cd1c5e5b5d113cd4912d4479dfe609fe261e) --- source3/libsmb/passchange.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/passchange.c b/source3/libsmb/passchange.c index c8a4406949..4c76234e0c 100644 --- a/source3/libsmb/passchange.c +++ b/source3/libsmb/passchange.c @@ -42,7 +42,7 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam "%s.\n", remote_machine); return NT_STATUS_UNSUCCESSFUL; } - + cli = cli_initialise(); if (!cli) { return NT_STATUS_NO_MEMORY; @@ -56,10 +56,10 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam cli_shutdown(cli); return result; } - + make_nmb_name(&calling, global_myname() , 0x0); make_nmb_name(&called , remote_machine, 0x20); - + if (!cli_session_request(cli, &calling, &called)) { asprintf(err_str, "machine %s rejected the session setup. " "Error was : %s.\n", @@ -68,7 +68,7 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam cli_shutdown(cli); return result; } - + cli->protocol = PROTOCOL_NT1; if (!cli_negprot(cli)) { @@ -79,7 +79,7 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam cli_shutdown(cli); return result; } - + /* Given things like SMB signing, restrict anonymous and the like, try an authenticated connection first */ result = cli_session_setup(cli, user_name, @@ -188,7 +188,7 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam } else if (!(NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL))) { /* it failed, but for reasons such as wrong password, too short etc ... */ - + asprintf(err_str, "machine %s rejected the password change: " "Error was : %s.\n", remote_machine, get_friendly_nt_error_msg(result)); @@ -198,12 +198,12 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam /* OK, that failed, so try again... */ TALLOC_FREE(pipe_hnd); - + /* Try anonymous NTLMSSP... */ cli_init_creds(cli, "", "", NULL); - + result = NT_STATUS_UNSUCCESSFUL; - + /* OK, this is ugly, but... try an anonymous pipe. */ result = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id, &pipe_hnd); @@ -227,10 +227,10 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam cli_shutdown(cli); return result; } - + /* We have failed to change the user's password, and we think the server just might not support SAMR password changes, so fall back */ - + if (lp_client_lanman_auth()) { /* Use the old RAP method. */ if (cli_oem_change_password(cli, user_name, new_passwd, old_passwd)) { -- cgit From 087a992b973466079f033c55bc5a1f522dc235fd Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 1 Sep 2008 17:07:33 +0200 Subject: doserr: add WERR_WRONG_PASSWORD. Guenther (This used to be commit 977fec76b77639403ba9ab7bb00c57601e23493d) --- source3/libsmb/doserr.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/libsmb') diff --git a/source3/libsmb/doserr.c b/source3/libsmb/doserr.c index 50b5b2238c..c62918e214 100644 --- a/source3/libsmb/doserr.c +++ b/source3/libsmb/doserr.c @@ -91,6 +91,7 @@ werror_code_struct dos_errs[] = { "WERR_DEFAULT_JOIN_REQUIRED", WERR_DEFAULT_JOIN_REQUIRED }, { "WERR_DEVICE_NOT_AVAILABLE", WERR_DEVICE_NOT_AVAILABLE }, { "WERR_LOGON_FAILURE", WERR_LOGON_FAILURE }, + { "WERR_WRONG_PASSWORD", WERR_WRONG_PASSWORD }, { "WERR_PASSWORD_RESTRICTION", WERR_PASSWORD_RESTRICTION }, { "WERR_NO_SUCH_DOMAIN", WERR_NO_SUCH_DOMAIN }, { "WERR_NONE_MAPPED", WERR_NONE_MAPPED }, @@ -150,6 +151,7 @@ werror_str_struct dos_err_strs[] = { { WERR_GROUP_EXISTS, "Group already exists" }, { WERR_DS_DRA_BAD_DN, "An invalid distinguished name was specified for this replication" }, { WERR_DS_DRA_BAD_NC, "An invalid naming context was specified for this replication operation" }, + { WERR_WRONG_PASSWORD, "The current password is incorrect" } }; /***************************************************************************** -- cgit