X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=source3%2Flibsmb%2Fclilist.c;h=41f84db5149142d9b6b1128291e2f9d639cdd3c6;hb=3005dc18f8668239442ffdbeaa3d6270ef7fef18;hp=280f876ba74f90d2d0ce670b633f14a1bd99adff;hpb=c7fe04abc791dd1b3c5272a96fb5f26f6ce5c252;p=obnox%2Fsamba%2Fsamba-obnox.git diff --git a/source3/libsmb/clilist.c b/source3/libsmb/clilist.c index 280f876ba74..41f84db5149 100644 --- a/source3/libsmb/clilist.c +++ b/source3/libsmb/clilist.c @@ -18,7 +18,11 @@ */ #include "includes.h" +#include "libsmb/libsmb.h" +#include "../lib/util/tevent_ntstatus.h" #include "async_smb.h" +#include "trans2.h" +#include "../libcli/smb/smbXcli_base.h" /**************************************************************************** Calculate a safe next_entry_offset. @@ -74,16 +78,18 @@ static size_t interpret_long_filename(TALLOC_CTX *ctx, return pdata_end - base; } finfo->ctime_ts = convert_time_t_to_timespec( - make_unix_date2(p+4, cli->serverzone)); + make_unix_date2(p+4, smb1cli_conn_server_time_zone(cli->conn))); finfo->atime_ts = convert_time_t_to_timespec( - make_unix_date2(p+8, cli->serverzone)); + make_unix_date2(p+8, smb1cli_conn_server_time_zone(cli->conn))); finfo->mtime_ts = convert_time_t_to_timespec( - make_unix_date2(p+12, cli->serverzone)); + make_unix_date2(p+12, smb1cli_conn_server_time_zone(cli->conn))); finfo->size = IVAL(p,16); finfo->mode = CVAL(p,24); len = CVAL(p, 26); p += 27; - p += align_string(base_ptr, p, 0); + if (recv_flags2 & FLAGS2_UNICODE_STRINGS) { + p += ucs2_align(base_ptr, p, STR_UNICODE); + } /* We can safely use len here (which is required by OS/2) * and the NAS-BASIC server instead of +2 or +1 as the @@ -123,11 +129,11 @@ static size_t interpret_long_filename(TALLOC_CTX *ctx, return pdata_end - base; } finfo->ctime_ts = convert_time_t_to_timespec( - make_unix_date2(p+4, cli->serverzone)); + make_unix_date2(p+4, smb1cli_conn_server_time_zone(cli->conn))); finfo->atime_ts = convert_time_t_to_timespec( - make_unix_date2(p+8, cli->serverzone)); + make_unix_date2(p+8, smb1cli_conn_server_time_zone(cli->conn))); finfo->mtime_ts = convert_time_t_to_timespec( - make_unix_date2(p+12, cli->serverzone)); + make_unix_date2(p+12, smb1cli_conn_server_time_zone(cli->conn))); finfo->size = IVAL(p,16); finfo->mode = CVAL(p,24); len = CVAL(p, 30); @@ -186,13 +192,15 @@ static size_t interpret_long_filename(TALLOC_CTX *ctx, return pdata_end - base; } p += 2; - { - /* stupid NT bugs. grr */ - int flags = 0; - if (p[1] == 0 && namelen > 1) flags |= STR_UNICODE; - clistr_pull(base_ptr, finfo->short_name, p, - sizeof(finfo->short_name), - slen, flags); + ret = clistr_pull_talloc(ctx, + base_ptr, + recv_flags2, + &finfo->short_name, + p, + slen, + STR_UNICODE); + if (ret == (size_t)-1) { + return pdata_end - base; } p += 24; /* short name? */ if (p + namelen < p || p + namelen > pdata_end) { @@ -243,14 +251,14 @@ static bool interpret_short_filename(TALLOC_CTX *ctx, finfo->mode = CVAL(p,21); /* this date is converted to GMT by make_unix_date */ - finfo->ctime_ts.tv_sec = make_unix_date(p+22, cli->serverzone); + finfo->ctime_ts.tv_sec = make_unix_date(p+22, smb1cli_conn_server_time_zone(cli->conn)); finfo->ctime_ts.tv_nsec = 0; finfo->mtime_ts.tv_sec = finfo->atime_ts.tv_sec = finfo->ctime_ts.tv_sec; finfo->mtime_ts.tv_nsec = finfo->atime_ts.tv_nsec = 0; finfo->size = IVAL(p,26); ret = clistr_pull_talloc(ctx, - cli->inbuf, - SVAL(cli->inbuf, smb_flg2), + NULL, + 0, &finfo->name, p+30, 12, @@ -260,9 +268,10 @@ static bool interpret_short_filename(TALLOC_CTX *ctx, } if (finfo->name) { - strlcpy(finfo->short_name, - finfo->name, - sizeof(finfo->short_name)); + finfo->short_name = talloc_strdup(ctx, finfo->name); + if (finfo->short_name == NULL) { + return false; + } } return true; } @@ -292,6 +301,7 @@ static struct tevent_req *cli_list_old_send(TALLOC_CTX *mem_ctx, struct cli_list_old_state *state; uint8_t *bytes; static const uint16_t zero = 0; + uint32_t usable_space; req = tevent_req_create(mem_ctx, &state, struct cli_list_old_state); if (req == NULL) { @@ -305,7 +315,8 @@ static struct tevent_req *cli_list_old_send(TALLOC_CTX *mem_ctx, if (tevent_req_nomem(state->mask, req)) { return tevent_req_post(req, ev); } - state->num_asked = (cli->max_xmit - 100) / DIR_STRUCT_SIZE; + usable_space = cli_state_available_size(cli, 100); + state->num_asked = usable_space / DIR_STRUCT_SIZE; SSVAL(state->vwv + 0, 0, state->num_asked); SSVAL(state->vwv + 1, 0, state->attribute); @@ -315,10 +326,10 @@ static struct tevent_req *cli_list_old_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } bytes[0] = 4; - bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), mask, + bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), mask, strlen(mask)+1, NULL); - bytes = smb_bytes_push_bytes(bytes, 5, (uint8_t *)&zero, 2); + bytes = smb_bytes_push_bytes(bytes, 5, (const uint8_t *)&zero, 2); if (tevent_req_nomem(bytes, req)) { return tevent_req_post(req, ev); } @@ -384,7 +395,7 @@ static void cli_list_old_done(struct tevent_req *subreq) dirlist_len = talloc_get_size(state->dirlist); - tmp = TALLOC_REALLOC_ARRAY( + tmp = talloc_realloc( state, state->dirlist, uint8_t, dirlist_len + received * DIR_STRUCT_SIZE); if (tevent_req_nomem(tmp, req)) { @@ -419,7 +430,7 @@ static void cli_list_old_done(struct tevent_req *subreq) return; } bytes[0] = 4; - bytes = smb_bytes_push_str(bytes, cli_ucs2(state->cli), "", + bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(state->cli->conn), "", 1, NULL); bytes = smb_bytes_push_bytes(bytes, 5, state->search_status, sizeof(state->search_status)); @@ -449,7 +460,7 @@ static NTSTATUS cli_list_old_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, num_received = talloc_array_length(state->dirlist) / DIR_STRUCT_SIZE; - finfo = TALLOC_ARRAY(mem_ctx, struct file_info, num_received); + finfo = talloc_array(mem_ctx, struct file_info, num_received); if (finfo == NULL) { return NT_STATUS_NO_MEMORY; } @@ -469,24 +480,24 @@ static NTSTATUS cli_list_old_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, NTSTATUS cli_list_old(struct cli_state *cli, const char *mask, uint16 attribute, - void (*fn)(const char *, struct file_info *, + NTSTATUS (*fn)(const char *, struct file_info *, const char *, void *), void *state) { TALLOC_CTX *frame = talloc_stackframe(); - struct event_context *ev; + struct tevent_context *ev; struct tevent_req *req; NTSTATUS status = NT_STATUS_NO_MEMORY; struct file_info *finfo; size_t i, num_finfo; - if (cli_has_async_calls(cli)) { + if (smbXcli_conn_has_async_calls(cli->conn)) { /* * Can't use sync call while an async call is in flight */ status = NT_STATUS_INVALID_PARAMETER; goto fail; } - ev = event_context_init(frame); + ev = samba_tevent_context_init(frame); if (ev == NULL) { goto fail; } @@ -504,13 +515,13 @@ NTSTATUS cli_list_old(struct cli_state *cli, const char *mask, } num_finfo = talloc_array_length(finfo); for (i=0; idfs_mountpoint, &finfo[i], mask, state); + status = fn(cli->dfs_mountpoint, &finfo[i], mask, state); + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } } fail: TALLOC_FREE(frame); - if (!NT_STATUS_IS_OK(status)) { - cli_set_error(cli, status); - } return status; } @@ -546,8 +557,7 @@ static struct tevent_req *cli_list_trans_send(TALLOC_CTX *mem_ctx, { struct tevent_req *req, *subreq; struct cli_list_trans_state *state; - size_t nlen, param_len; - char *p; + size_t param_len; req = tevent_req_create(mem_ctx, &state, struct cli_list_trans_state); @@ -567,10 +577,9 @@ static struct tevent_req *cli_list_trans_send(TALLOC_CTX *mem_ctx, state->max_matches = 1366; /* Match W2k */ - state->setup[0] = TRANSACT2_FINDFIRST; + SSVAL(&state->setup[0], 0, TRANSACT2_FINDFIRST); - nlen = 2*(strlen(mask)+1); - state->param = TALLOC_ARRAY(state, uint8_t, 12+nlen+2); + state->param = talloc_array(state, uint8_t, 12); if (tevent_req_nomem(state->param, req)) { return tevent_req_post(req, ev); } @@ -579,20 +588,24 @@ static struct tevent_req *cli_list_trans_send(TALLOC_CTX *mem_ctx, SSVAL(state->param, 2, state->max_matches); SSVAL(state->param, 4, FLAG_TRANS2_FIND_REQUIRE_RESUME - |FLAG_TRANS2_FIND_CLOSE_IF_END); + |FLAG_TRANS2_FIND_CLOSE_IF_END + |(cli->backup_intent ? FLAG_TRANS2_FIND_BACKUP_INTENT : 0)); SSVAL(state->param, 6, state->info_level); SIVAL(state->param, 8, 0); - p = ((char *)state->param)+12; - p += clistr_push(state->cli, p, state->mask, nlen, - STR_TERMINATE); - param_len = PTR_DIFF(p, state->param); + state->param = trans2_bytes_push_str(state->param, smbXcli_conn_use_unicode(cli->conn), + state->mask, strlen(state->mask)+1, + NULL); + if (tevent_req_nomem(state->param, req)) { + return tevent_req_post(req, ev); + } + param_len = talloc_get_size(state->param); subreq = cli_trans_send(state, state->ev, state->cli, SMBtrans2, NULL, -1, 0, 0, state->setup, 1, 0, state->param, param_len, 10, - NULL, 0, cli->max_xmit); + NULL, 0, CLI_BUFFER_SIZE); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } @@ -623,7 +636,7 @@ static void cli_list_trans_done(struct tevent_req *subreq) int i; DATA_BLOB last_name_raw; struct file_info *finfo = NULL; - size_t nlen, param_len; + size_t param_len; min_param = (state->first ? 6 : 4); @@ -651,7 +664,7 @@ static void cli_list_trans_done(struct tevent_req *subreq) old_num_finfo = talloc_array_length(state->finfo); - tmp = TALLOC_REALLOC_ARRAY(state, state->finfo, struct file_info, + tmp = talloc_realloc(state, state->finfo, struct file_info, old_num_finfo + ff_searchcount); if (tevent_req_nomem(tmp, req)) { return; @@ -708,7 +721,7 @@ static void cli_list_trans_done(struct tevent_req *subreq) /* * Shrink state->finfo to the real length we received */ - tmp = TALLOC_REALLOC_ARRAY(state, state->finfo, struct file_info, + tmp = talloc_realloc(state, state->finfo, struct file_info, old_num_finfo + i); if (tevent_req_nomem(tmp, req)) { return; @@ -729,12 +742,9 @@ static void cli_list_trans_done(struct tevent_req *subreq) return; } - state->setup[0] = TRANSACT2_FINDNEXT; + SSVAL(&state->setup[0], 0, TRANSACT2_FINDNEXT); - nlen = 2*(strlen(state->mask) + 1); - - param = TALLOC_REALLOC_ARRAY(state, state->param, uint8_t, - 12 + nlen + last_name_raw.length + 2); + param = talloc_realloc(state, state->param, uint8_t, 12); if (tevent_req_nomem(param, req)) { return; } @@ -754,24 +764,33 @@ static void cli_list_trans_done(struct tevent_req *subreq) * continue instead. JRA */ SSVAL(param, 10, (FLAG_TRANS2_FIND_REQUIRE_RESUME - |FLAG_TRANS2_FIND_CLOSE_IF_END)); - p = ((char *)param)+12; + |FLAG_TRANS2_FIND_CLOSE_IF_END + |(state->cli->backup_intent ? FLAG_TRANS2_FIND_BACKUP_INTENT : 0))); if (last_name_raw.length) { - memcpy(p, last_name_raw.data, last_name_raw.length); - p += last_name_raw.length; + state->param = trans2_bytes_push_bytes(state->param, + last_name_raw.data, + last_name_raw.length); + if (tevent_req_nomem(state->param, req)) { + return; + } data_blob_free(&last_name_raw); } else { - p += clistr_push(state->cli, p, state->mask, nlen, - STR_TERMINATE); + state->param = trans2_bytes_push_str(state->param, + smbXcli_conn_use_unicode(state->cli->conn), + state->mask, + strlen(state->mask)+1, + NULL); + if (tevent_req_nomem(state->param, req)) { + return; + } } - - param_len = PTR_DIFF(p, param); + param_len = talloc_get_size(state->param); subreq = cli_trans_send(state, state->ev, state->cli, SMBtrans2, NULL, -1, 0, 0, state->setup, 1, 0, state->param, param_len, 10, - NULL, 0, state->cli->max_xmit); + NULL, 0, CLI_BUFFER_SIZE); if (tevent_req_nomem(subreq, req)) { return; } @@ -795,25 +814,25 @@ static NTSTATUS cli_list_trans_recv(struct tevent_req *req, NTSTATUS cli_list_trans(struct cli_state *cli, const char *mask, uint16_t attribute, int info_level, - void (*fn)(const char *mnt, struct file_info *finfo, + NTSTATUS (*fn)(const char *mnt, struct file_info *finfo, const char *mask, void *private_data), void *private_data) { TALLOC_CTX *frame = talloc_stackframe(); - struct event_context *ev; + struct tevent_context *ev; struct tevent_req *req; int i, num_finfo; struct file_info *finfo = NULL; NTSTATUS status = NT_STATUS_NO_MEMORY; - if (cli_has_async_calls(cli)) { + if (smbXcli_conn_has_async_calls(cli->conn)) { /* * Can't use sync call while an async call is in flight */ status = NT_STATUS_INVALID_PARAMETER; goto fail; } - ev = event_context_init(frame); + ev = samba_tevent_context_init(frame); if (ev == NULL) { goto fail; } @@ -830,13 +849,13 @@ NTSTATUS cli_list_trans(struct cli_state *cli, const char *mask, } num_finfo = talloc_array_length(finfo); for (i=0; idfs_mountpoint, &finfo[i], mask, private_data); + status = fn(cli->dfs_mountpoint, &finfo[i], mask, private_data); + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } } fail: TALLOC_FREE(frame); - if (!NT_STATUS_IS_OK(status)) { - cli_set_error(cli, status); - } return status; } @@ -863,7 +882,7 @@ struct tevent_req *cli_list_send(TALLOC_CTX *mem_ctx, return NULL; } - if (cli->protocol <= PROTOCOL_LANMAN1) { + if (smbXcli_conn_protocol(cli->conn) <= PROTOCOL_LANMAN1) { subreq = cli_list_old_send(state, ev, cli, mask, attribute); state->recv_fn = cli_list_old_recv; } else { @@ -911,30 +930,30 @@ NTSTATUS cli_list_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, } NTSTATUS cli_list(struct cli_state *cli, const char *mask, uint16 attribute, - void (*fn)(const char *, struct file_info *, const char *, + NTSTATUS (*fn)(const char *, struct file_info *, const char *, void *), void *state) { TALLOC_CTX *frame = talloc_stackframe(); - struct event_context *ev; + struct tevent_context *ev; struct tevent_req *req; NTSTATUS status = NT_STATUS_NO_MEMORY; struct file_info *finfo; size_t i, num_finfo; uint16_t info_level; - if (cli_has_async_calls(cli)) { + if (smbXcli_conn_has_async_calls(cli->conn)) { /* * Can't use sync call while an async call is in flight */ status = NT_STATUS_INVALID_PARAMETER; goto fail; } - ev = event_context_init(frame); + ev = samba_tevent_context_init(frame); if (ev == NULL) { goto fail; } - info_level = (cli->capabilities & CAP_NT_SMBS) + info_level = smbXcli_conn_nt_smbs_supported(cli->conn) ? SMB_FIND_FILE_BOTH_DIRECTORY_INFO : SMB_FIND_INFO_STANDARD; req = cli_list_send(frame, ev, cli, mask, attribute, info_level); @@ -952,12 +971,12 @@ NTSTATUS cli_list(struct cli_state *cli, const char *mask, uint16 attribute, } for (i=0; idfs_mountpoint, &finfo[i], mask, state); + status = fn(cli->dfs_mountpoint, &finfo[i], mask, state); + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } } fail: TALLOC_FREE(frame); - if (!NT_STATUS_IS_OK(status)) { - cli_set_error(cli, status); - } return status; }