From 9653a1073898b9e78b579b12adedadb669ae2b94 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 10 Mar 2020 11:51:09 -0700 Subject: libsmbclient: Put it back to a known, well-working state For adapting unix extensions in our client libraries, we need a fresh start with additional APIs. We can't change existing application behaviour. Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- source3/libsmb/clifile.c | 122 +++++++++++++++++------------------------ source3/libsmb/clilist.c | 69 +---------------------- source3/libsmb/libsmb_dir.c | 64 ++++++++------------- source3/libsmb/libsmb_file.c | 44 ++++++--------- source3/libsmb/libsmb_misc.c | 15 ++--- source3/libsmb/libsmb_server.c | 1 + source3/libsmb/libsmb_stat.c | 2 +- source3/libsmb/proto.h | 8 +-- 8 files changed, 102 insertions(+), 223 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c index 164be11386c..dd08b0e30f3 100644 --- a/source3/libsmb/clifile.c +++ b/source3/libsmb/clifile.c @@ -736,65 +736,12 @@ NTSTATUS cli_posix_setacl(struct cli_state *cli, return status; } -static void fetch_file_unix_basic_info( - const uint8_t data[100], SMB_STRUCT_STAT *sbuf) -{ - ZERO_STRUCTP(sbuf); - - /* total size, in bytes */ - sbuf->st_ex_size = IVAL2_TO_SMB_BIG_UINT(data, 0); - - /* number of blocks allocated */ - sbuf->st_ex_blocks = IVAL2_TO_SMB_BIG_UINT(data,8); -#if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE) - sbuf->st_ex_blocks /= STAT_ST_BLOCKSIZE; -#else - /* assume 512 byte blocks */ - sbuf->st_ex_blocks /= 512; -#endif - /* time of last change */ - sbuf->st_ex_ctime = interpret_long_date((const char *)(data + 16)); - - /* time of last access */ - sbuf->st_ex_atime = interpret_long_date((const char *)(data + 24)); - - /* time of last modification */ - sbuf->st_ex_mtime = interpret_long_date((const char *)(data + 32)); - - sbuf->st_ex_uid = (uid_t) IVAL(data, 40); /* user ID of owner */ - sbuf->st_ex_gid = (gid_t) IVAL(data, 48); /* group ID of owner */ - sbuf->st_ex_mode = unix_filetype_from_wire(IVAL(data, 56)); - -#if defined(HAVE_MAKEDEV) - { - uint32_t dev_major = IVAL(data,60); - uint32_t dev_minor = IVAL(data,68); - sbuf->st_ex_rdev = makedev(dev_major, dev_minor); - } -#endif - /* inode */ - sbuf->st_ex_ino = (SMB_INO_T)IVAL2_TO_SMB_BIG_UINT(data, 76); - - /* protection */ - sbuf->st_ex_mode |= wire_perms_to_unix(IVAL(data, 84)); - - /* number of hard links */ - sbuf->st_ex_nlink = BIG_UINT(data, 92); -} - -void fetch_file_unix_basic_info2( - const uint8_t data[116], SMB_STRUCT_STAT *sbuf) -{ - fetch_file_unix_basic_info(data, sbuf); - sbuf->st_ex_btime = interpret_long_date((const char *)(data + 100)); -} - /**************************************************************************** Stat a file (UNIX extensions). ****************************************************************************/ struct stat_state { - SMB_STRUCT_STAT sbuf; + SMB_STRUCT_STAT *sbuf; }; static void cli_posix_stat_done(struct tevent_req *subreq); @@ -802,7 +749,8 @@ static void cli_posix_stat_done(struct tevent_req *subreq); struct tevent_req *cli_posix_stat_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli, - const char *fname) + const char *fname, + SMB_STRUCT_STAT *sbuf) { struct tevent_req *req = NULL, *subreq = NULL; struct stat_state *state = NULL; @@ -811,6 +759,7 @@ struct tevent_req *cli_posix_stat_send(TALLOC_CTX *mem_ctx, if (req == NULL) { return NULL; } + state->sbuf = sbuf; subreq = cli_qpathinfo_send(state, ev, cli, fname, SMB_QUERY_FILE_UNIX_BASIC, 100, 100); @@ -826,7 +775,7 @@ static void cli_posix_stat_done(struct tevent_req *subreq) struct tevent_req *req = tevent_req_callback_data( subreq, struct tevent_req); struct stat_state *state = tevent_req_data(req, struct stat_state); - SMB_STRUCT_STAT *sbuf = &state->sbuf; + SMB_STRUCT_STAT *sbuf = state->sbuf; uint8_t *data; uint32_t num_data = 0; NTSTATUS status; @@ -846,25 +795,54 @@ static void cli_posix_stat_done(struct tevent_req *subreq) return; } - fetch_file_unix_basic_info(data, sbuf); + *sbuf = (SMB_STRUCT_STAT) { 0 }; + + /* total size, in bytes */ + sbuf->st_ex_size = IVAL2_TO_SMB_BIG_UINT(data, 0); + + /* number of blocks allocated */ + sbuf->st_ex_blocks = IVAL2_TO_SMB_BIG_UINT(data,8); +#if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE) + sbuf->st_ex_blocks /= STAT_ST_BLOCKSIZE; +#else + /* assume 512 byte blocks */ + sbuf->st_ex_blocks /= 512; +#endif + /* time of last change */ + sbuf->st_ex_ctime = interpret_long_date((char *)(data + 16)); + + /* time of last access */ + sbuf->st_ex_atime = interpret_long_date((char *)(data + 24)); + + /* time of last modification */ + sbuf->st_ex_mtime = interpret_long_date((char *)(data + 32)); + + sbuf->st_ex_uid = (uid_t) IVAL(data, 40); /* user ID of owner */ + sbuf->st_ex_gid = (gid_t) IVAL(data, 48); /* group ID of owner */ + sbuf->st_ex_mode = unix_filetype_from_wire(IVAL(data, 56)); + +#if defined(HAVE_MAKEDEV) + { + uint32_t dev_major = IVAL(data,60); + uint32_t dev_minor = IVAL(data,68); + sbuf->st_ex_rdev = makedev(dev_major, dev_minor); + } +#endif + /* inode */ + sbuf->st_ex_ino = (SMB_INO_T)IVAL2_TO_SMB_BIG_UINT(data, 76); + + /* protection */ + sbuf->st_ex_mode |= wire_perms_to_unix(IVAL(data, 84)); + + /* number of hard links */ + sbuf->st_ex_nlink = BIG_UINT(data, 92); tevent_req_done(req); } -NTSTATUS cli_posix_stat_recv(struct tevent_req *req, - SMB_STRUCT_STAT *sbuf) +NTSTATUS cli_posix_stat_recv(struct tevent_req *req) { - struct stat_state *state = tevent_req_data(req, struct stat_state); - NTSTATUS status; - - if (tevent_req_is_nterror(req, &status)) { - return status; - } - if (sbuf != NULL) { - *sbuf = state->sbuf; - } - tevent_req_received(req); - return NT_STATUS_OK; + return tevent_req_simple_recv_ntstatus(req); } NTSTATUS cli_posix_stat(struct cli_state *cli, @@ -890,7 +868,7 @@ NTSTATUS cli_posix_stat(struct cli_state *cli, goto fail; } - req = cli_posix_stat_send(frame, ev, cli, fname); + req = cli_posix_stat_send(frame, ev, cli, fname, sbuf); if (req == NULL) { status = NT_STATUS_NO_MEMORY; goto fail; @@ -900,7 +878,7 @@ NTSTATUS cli_posix_stat(struct cli_state *cli, goto fail; } - status = cli_posix_stat_recv(req, sbuf); + status = cli_posix_stat_recv(req); fail: TALLOC_FREE(frame); diff --git a/source3/libsmb/clilist.c b/source3/libsmb/clilist.c index ca6d8b53129..f868e72a239 100644 --- a/source3/libsmb/clilist.c +++ b/source3/libsmb/clilist.c @@ -305,63 +305,6 @@ static size_t interpret_long_filename(TALLOC_CTX *ctx, } return calc_next_entry_offset(base, pdata_end); } - case SMB_FIND_FILE_UNIX_INFO2: - { - SMB_STRUCT_STAT *sbuf = &finfo->posix_sbuf; - size_t namelen; - - if (pdata_end - base < 128) { - return pdata_end - base; - } - - p += 4; /* next entry offset */ - - if (p_resume_key) { - *p_resume_key = IVAL(p,0); - } - p += 4; /* fileindex */ - - fetch_file_unix_basic_info2((const uint8_t *)p, sbuf); - p += 116; - - finfo->mode = S_ISDIR(sbuf->st_ex_mode) ? - FILE_ATTRIBUTE_DIRECTORY : - FILE_ATTRIBUTE_NORMAL; - if (sbuf->st_ex_mode & S_IXUSR) { - finfo->mode |= FILE_ATTRIBUTE_ARCHIVE; - } - - finfo->size = sbuf->st_ex_size; - finfo->allocated_size = - sbuf->st_ex_blksize * sbuf->st_ex_blocks; - finfo->uid = sbuf->st_ex_uid; - finfo->gid = sbuf->st_ex_gid; - finfo->ino = sbuf->st_ex_ino; - finfo->btime_ts = sbuf->st_ex_btime; - finfo->mtime_ts = sbuf->st_ex_mtime; - finfo->atime_ts = sbuf->st_ex_atime; - finfo->ctime_ts = sbuf->st_ex_ctime; - - namelen = IVAL(p, 0); - p += 4; - - if (namelen > (pdata_end - p)) { - return pdata_end - base; - } - - ret = clistr_pull_talloc( - ctx, - base_ptr, - recv_flags2, - &finfo->name, - p, - namelen, - 0); - if (ret == (size_t)-1) { - return pdata_end - base; - } - return calc_next_entry_offset(base, pdata_end); - } } DEBUG(1,("Unknown long filename format %d\n",level)); @@ -1100,7 +1043,6 @@ NTSTATUS cli_list(struct cli_state *cli, const char *mask, uint16_t attribute, NTSTATUS status = NT_STATUS_NO_MEMORY; struct file_info *finfo; size_t i, num_finfo = 0; - uint32_t caps; uint16_t info_level; if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { @@ -1121,15 +1063,8 @@ NTSTATUS cli_list(struct cli_state *cli, const char *mask, uint16_t attribute, goto fail; } - caps = smb1cli_conn_capabilities(cli->conn); - - if (caps & CAP_UNIX) { - info_level = SMB_FIND_FILE_UNIX_INFO2; - } else if (caps & CAP_NT_SMBS) { - info_level = SMB_FIND_FILE_BOTH_DIRECTORY_INFO; - } else { - info_level = SMB_FIND_INFO_STANDARD; - } + info_level = (smb1cli_conn_capabilities(cli->conn) & CAP_NT_SMBS) + ? SMB_FIND_FILE_BOTH_DIRECTORY_INFO : SMB_FIND_INFO_STANDARD; req = cli_list_send(frame, ev, cli, mask, attribute, info_level); if (req == NULL) { diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c index 801d556f53b..00d2a878e84 100644 --- a/source3/libsmb/libsmb_dir.c +++ b/source3/libsmb/libsmb_dir.c @@ -49,7 +49,6 @@ static void remove_dirplus(SMBCFILE *dir) struct smbc_dirplus_list *f = d; d = d->next; - SAFE_FREE(f->posix_sbuf); SAFE_FREE(f->smb_finfo->short_name); SAFE_FREE(f->smb_finfo->name); SAFE_FREE(f->smb_finfo); @@ -213,20 +212,6 @@ static int add_dirplus(SMBCFILE *dir, struct file_info *finfo) } new_entry->smb_finfo = info; - if (finfo->posix_sbuf.st_ex_nlink != 0) { - new_entry->posix_sbuf = SMB_MALLOC_P(SMB_STRUCT_STAT); - if (new_entry->posix_sbuf == NULL) { - SAFE_FREE(info->short_name); - SAFE_FREE(info->name); - SAFE_FREE(info); - SAFE_FREE(new_entry); - dir->dir_error = ENOMEM; - return -1; - } - *new_entry->posix_sbuf = finfo->posix_sbuf; - new_entry->posix_sbuf->st_ex_dev = dir->srv->dev; - } - /* Now add to the list. */ if (dir->dirplus_list == NULL) { /* Empty list - point everything at new_entry. */ @@ -561,12 +546,6 @@ SMBC_opendir_ctx(SMBCCTX *context, dir->cli_fd = 0; dir->fname = SMB_STRDUP(fname); - if (dir->fname == NULL) { - SAFE_FREE(dir); - TALLOC_FREE(frame); - errno = ENOMEM; - return NULL; - } dir->srv = NULL; dir->offset = 0; dir->file = False; @@ -1055,7 +1034,7 @@ SMBC_closedir_ctx(SMBCCTX *context, return -1; } - if (!SMBC_dlist_contains(context->internal->files, dir)) { + if (!dir || !SMBC_dlist_contains(context->internal->files, dir)) { errno = EBADF; TALLOC_FREE(frame); return -1; @@ -1168,7 +1147,7 @@ SMBC_readdir_ctx(SMBCCTX *context, } - if (!SMBC_dlist_contains(context->internal->files, dir)) { + if (!dir || !SMBC_dlist_contains(context->internal->files, dir)) { errno = EBADF; DEBUG(0, ("Invalid dir in SMBC_readdir_ctx()\n")); @@ -1247,7 +1226,9 @@ SMBC_readdirplus_ctx(SMBCCTX *context, return NULL; } - if (!SMBC_dlist_contains(context->internal->files, dir)) { + if (dir == NULL || + SMBC_dlist_contains(context->internal->files, + dir) == 0) { DBG_ERR("Invalid dir in SMBC_readdirplus_ctx()\n"); TALLOC_FREE(frame); errno = EBADF; @@ -1326,7 +1307,10 @@ const struct libsmb_file_info *SMBC_readdirplus2_ctx(SMBCCTX *context, return NULL; } - if (!SMBC_dlist_contains(context->internal->files, dir)) { + if (dir == NULL || + SMBC_dlist_contains(context->internal->files, + dir) == 0) + { DBG_ERR("Invalid dir in SMBC_readdirplus2_ctx()\n"); TALLOC_FREE(frame); errno = EBADF; @@ -1375,20 +1359,15 @@ const struct libsmb_file_info *SMBC_readdirplus2_ctx(SMBCCTX *context, return NULL; } - if (dp_list->posix_sbuf != NULL) { - setup_stat_from_stat_ex(dp_list->posix_sbuf, path, st); - } else { - setup_stat( - st, - path, - smb_finfo->size, - smb_finfo->attrs, - ino, - dir->srv->dev, - smb_finfo->atime_ts, - smb_finfo->ctime_ts, - smb_finfo->mtime_ts); - } + setup_stat(st, + path, + smb_finfo->size, + smb_finfo->attrs, + ino, + dir->srv->dev, + smb_finfo->atime_ts, + smb_finfo->ctime_ts, + smb_finfo->mtime_ts); TALLOC_FREE(full_pathname); @@ -1436,7 +1415,7 @@ SMBC_getdents_ctx(SMBCCTX *context, } - if (!SMBC_dlist_contains(context->internal->files, dir)) { + if (!dir || !SMBC_dlist_contains(context->internal->files, dir)) { errno = EBADF; TALLOC_FREE(frame); @@ -1803,7 +1782,7 @@ SMBC_telldir_ctx(SMBCCTX *context, } - if (!SMBC_dlist_contains(context->internal->files, dir)) { + if (!dir || !SMBC_dlist_contains(context->internal->files, dir)) { errno = EBADF; TALLOC_FREE(frame); @@ -2651,7 +2630,8 @@ SMBC_notify_ctx(SMBCCTX *context, SMBCFILE *dir, smbc_bool recursive, errno = EINVAL; return -1; } - if (!SMBC_dlist_contains(context->internal->files, dir)) { + if ((dir == NULL) || + !SMBC_dlist_contains(context->internal->files, dir)) { TALLOC_FREE(frame); errno = EBADF; return -1; diff --git a/source3/libsmb/libsmb_file.c b/source3/libsmb/libsmb_file.c index 512827e134d..1577010e490 100644 --- a/source3/libsmb/libsmb_file.c +++ b/source3/libsmb/libsmb_file.c @@ -125,21 +125,8 @@ SMBC_open_ctx(SMBCCTX *context, } /*d_printf(">>>open: resolved %s as %s\n", path, targetpath);*/ - if (srv->try_posixinfo) { - status = cli_posix_open( - targetcli, - targetpath, - flags, - mode, - &fd); - } else { - status = cli_open( - targetcli, - targetpath, - flags, - context->internal->share_mode, - &fd); - } + status = cli_open(targetcli, targetpath, flags, + context->internal->share_mode, &fd); if (!NT_STATUS_IS_OK(status)) { /* Handle the error ... */ @@ -269,9 +256,9 @@ SMBC_read_ctx(SMBCCTX *context, return -1; } - DEBUG(4, ("smbc_read(%p, %zu)\n", file, count)); + DEBUG(4, ("smbc_read(%p, %d)\n", file, (int)count)); - if (!SMBC_dlist_contains(context->internal->files, file)) { + if (!file || !SMBC_dlist_contains(context->internal->files, file)) { errno = EBADF; TALLOC_FREE(frame); return -1; @@ -297,7 +284,7 @@ SMBC_read_ctx(SMBCCTX *context, file->offset += ret; - DEBUG(4, (" --> %zu\n", ret)); + DEBUG(4, (" --> %ld\n", (unsigned long)ret)); TALLOC_FREE(frame); return ret; /* Success, ret bytes of data ... */ @@ -321,13 +308,17 @@ SMBC_splice_ctx(SMBCCTX *context, return -1; } - if (!SMBC_dlist_contains(context->internal->files, srcfile)) { + if (!srcfile || + !SMBC_dlist_contains(context->internal->files, srcfile)) + { errno = EBADF; TALLOC_FREE(frame); return -1; } - if (!SMBC_dlist_contains(context->internal->files, dstfile)) { + if (!dstfile || + !SMBC_dlist_contains(context->internal->files, dstfile)) + { errno = EBADF; TALLOC_FREE(frame); return -1; @@ -372,7 +363,7 @@ SMBC_write_ctx(SMBCCTX *context, return -1; } - if (!SMBC_dlist_contains(context->internal->files, file)) { + if (!file || !SMBC_dlist_contains(context->internal->files, file)) { errno = EBADF; TALLOC_FREE(frame); return -1; @@ -418,7 +409,7 @@ SMBC_close_ctx(SMBCCTX *context, return -1; } - if (!SMBC_dlist_contains(context->internal->files, file)) { + if (!file || !SMBC_dlist_contains(context->internal->files, file)) { errno = EBADF; TALLOC_FREE(frame); return -1; @@ -484,7 +475,7 @@ SMBC_getatr(SMBCCTX * context, } /* path fixup for . and .. */ - if (ISDOT(path) || ISDOTDOT(path)) { + if (strequal(path, ".") || strequal(path, "..")) { fixedpath = talloc_strdup(frame, "\\"); if (!fixedpath) { errno = ENOMEM; @@ -516,9 +507,8 @@ SMBC_getatr(SMBCCTX * context, if (srv->try_posixinfo) { SMB_STRUCT_STAT sbuf; - status = cli_posix_stat(targetcli, targetpath, &sbuf); + status = cli_posix_stat(targetcli, frame, &sbuf); if (NT_STATUS_IS_OK(status)) { - sbuf.st_ex_dev = srv->dev; setup_stat_from_stat_ex(&sbuf, path, sb); TALLOC_FREE(frame); @@ -711,7 +701,7 @@ SMBC_lseek_ctx(SMBCCTX *context, return -1; } - if (!SMBC_dlist_contains(context->internal->files, file)) { + if (!file || !SMBC_dlist_contains(context->internal->files, file)) { errno = EBADF; TALLOC_FREE(frame); return -1; @@ -774,7 +764,7 @@ SMBC_ftruncate_ctx(SMBCCTX *context, return -1; } - if (!SMBC_dlist_contains(context->internal->files, file)) { + if (!file || !SMBC_dlist_contains(context->internal->files, file)) { errno = EBADF; TALLOC_FREE(frame); return -1; diff --git a/source3/libsmb/libsmb_misc.c b/source3/libsmb/libsmb_misc.c index 28e2ca842cf..1d874c74cd8 100644 --- a/source3/libsmb/libsmb_misc.c +++ b/source3/libsmb/libsmb_misc.c @@ -31,18 +31,15 @@ /* * check if an element is part of the list. */ -bool SMBC_dlist_contains(SMBCFILE * list, SMBCFILE *p) +int +SMBC_dlist_contains(SMBCFILE * list, SMBCFILE *p) { - if ((p == NULL) || (list == NULL)) { - return false; - } + if (!p || !list) return False; do { - if (p == list) { - return true; - } + if (p == list) return True; list = list->next; - } while (list != NULL); - return false; + } while (list); + return False; } diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c index 104a04a6fc8..d4f71d8c8b7 100644 --- a/source3/libsmb/libsmb_server.c +++ b/source3/libsmb/libsmb_server.c @@ -296,6 +296,7 @@ SMBC_server_internal(TALLOC_CTX *ctx, bool use_ccache = false; bool pw_nt_hash = false; + ZERO_STRUCT(c); *in_cache = false; if (server[0] == 0) { diff --git a/source3/libsmb/libsmb_stat.c b/source3/libsmb/libsmb_stat.c index a4aaf6c327f..f20f79579e2 100644 --- a/source3/libsmb/libsmb_stat.c +++ b/source3/libsmb/libsmb_stat.c @@ -251,7 +251,7 @@ SMBC_fstat_ctx(SMBCCTX *context, return -1; } - if (!SMBC_dlist_contains(context->internal->files, file)) { + if (!file || !SMBC_dlist_contains(context->internal->files, file)) { errno = EBADF; TALLOC_FREE(frame); return -1; diff --git a/source3/libsmb/proto.h b/source3/libsmb/proto.h index 07c22a696fe..0e2c1adb4ae 100644 --- a/source3/libsmb/proto.h +++ b/source3/libsmb/proto.h @@ -283,8 +283,6 @@ NTSTATUS cli_posix_hardlink(struct cli_state *cli, const char *newname); uint32_t unix_perms_to_wire(mode_t perms); mode_t wire_perms_to_unix(uint32_t perms); -void fetch_file_unix_basic_info2( - const uint8_t data[116], SMB_STRUCT_STAT *sbuf); struct tevent_req *cli_posix_getacl_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli, @@ -312,9 +310,9 @@ NTSTATUS cli_posix_setacl(struct cli_state *cli, struct tevent_req *cli_posix_stat_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli, - const char *fname); -NTSTATUS cli_posix_stat_recv(struct tevent_req *req, - SMB_STRUCT_STAT *sbuf); + const char *fname, + SMB_STRUCT_STAT *sbuf); +NTSTATUS cli_posix_stat_recv(struct tevent_req *req); NTSTATUS cli_posix_stat(struct cli_state *cli, const char *fname, SMB_STRUCT_STAT *sbuf); -- cgit v1.2.1