diff options
author | Alexander Bokovoy <ab@samba.org> | 2009-08-08 08:07:24 +0300 |
---|---|---|
committer | Alexander Bokovoy <ab@samba.org> | 2009-08-08 08:07:24 +0300 |
commit | 8eac1896299d820fec0fd92b2b8b6a058ae39642 (patch) | |
tree | f97b0a2c21eb4f91aa51cb2af4381287c3525727 /source3/smbd | |
parent | 217e3086c74eb0b46fab512b5887d9a5a5b7ee9a (diff) | |
parent | d296c774c5981baa863c697782dba1b6280d632e (diff) | |
download | samba-8eac1896299d820fec0fd92b2b8b6a058ae39642.tar.gz samba-8eac1896299d820fec0fd92b2b8b6a058ae39642.tar.bz2 samba-8eac1896299d820fec0fd92b2b8b6a058ae39642.zip |
Merge branch 'master' of ssh://git.samba.org/data/git/samba
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/conn.c | 29 | ||||
-rw-r--r-- | source3/smbd/dir.c | 490 | ||||
-rw-r--r-- | source3/smbd/files.c | 25 | ||||
-rw-r--r-- | source3/smbd/globals.c | 4 | ||||
-rw-r--r-- | source3/smbd/globals.h | 32 | ||||
-rw-r--r-- | source3/smbd/ipc.c | 3 | ||||
-rw-r--r-- | source3/smbd/msdfs.c | 22 | ||||
-rw-r--r-- | source3/smbd/posix_acls.c | 10 | ||||
-rw-r--r-- | source3/smbd/process.c | 3 | ||||
-rw-r--r-- | source3/smbd/reply.c | 61 | ||||
-rw-r--r-- | source3/smbd/server.c | 2 | ||||
-rw-r--r-- | source3/smbd/service.c | 35 | ||||
-rw-r--r-- | source3/smbd/smb2_tcon.c | 2 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 1364 |
14 files changed, 1152 insertions, 930 deletions
diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index af6e0919a4..959fcd7754 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -101,6 +101,7 @@ connection_struct *conn_new(struct smbd_server_connection *sconn) TALLOC_FREE(conn); return NULL; } + conn->sconn = sconn; return conn; } @@ -154,6 +155,7 @@ find_again: TALLOC_FREE(conn); return NULL; } + conn->sconn = sconn; conn->cnum = i; conn->force_group_gid = (gid_t)-1; @@ -161,7 +163,6 @@ find_again: sconn->smb1.tcons.num_open++; - string_set(&conn->dirpath,""); string_set(&conn->connectpath,""); string_set(&conn->origpath,""); @@ -181,7 +182,7 @@ bool conn_close_all(struct smbd_server_connection *sconn) for (conn=sconn->smb1.tcons.Connections;conn;conn=next) { next=conn->next; set_current_service(conn, 0, True); - close_cnum(sconn, conn, conn->vuid); + close_cnum(conn, conn->vuid); ret = true; } return ret; @@ -255,9 +256,9 @@ void conn_clear_vuid_caches(struct smbd_server_connection *sconn,uint16_t vuid) Free a conn structure - internal part. ****************************************************************************/ -void conn_free_internal(connection_struct *conn) +static void conn_free_internal(connection_struct *conn) { - vfs_handle_struct *handle = NULL, *thandle = NULL; + vfs_handle_struct *handle = NULL, *thandle = NULL; struct trans_state *state = NULL; /* Free vfs_connection_struct */ @@ -282,7 +283,6 @@ void conn_free_internal(connection_struct *conn) free_namearray(conn->veto_oplock_list); free_namearray(conn->aio_write_behind_list); - string_free(&conn->dirpath); string_free(&conn->connectpath); string_free(&conn->origpath); @@ -294,19 +294,24 @@ void conn_free_internal(connection_struct *conn) Free a conn structure. ****************************************************************************/ -void conn_free(struct smbd_server_connection *sconn, connection_struct *conn) +void conn_free(connection_struct *conn) { - if (sconn->allow_smb2) { + if (conn->sconn == NULL) { + conn_free_internal(conn); + return; + } + + if (conn->sconn->allow_smb2) { conn_free_internal(conn); return; } - DLIST_REMOVE(sconn->smb1.tcons.Connections, conn); + DLIST_REMOVE(conn->sconn->smb1.tcons.Connections, conn); - bitmap_clear(sconn->smb1.tcons.bmap, conn->cnum); + bitmap_clear(conn->sconn->smb1.tcons.bmap, conn->cnum); - SMB_ASSERT(sconn->smb1.tcons.num_open > 0); - sconn->smb1.tcons.num_open--; + SMB_ASSERT(conn->sconn->smb1.tcons.num_open > 0); + conn->sconn->smb1.tcons.num_open--; conn_free_internal(conn); } @@ -340,7 +345,7 @@ void msg_force_tdis(struct messaging_context *msg, if (strequal(lp_servicename(SNUM(conn)), sharename)) { DEBUG(1,("Forcing close of share %s cnum=%d\n", sharename, conn->cnum)); - close_cnum(sconn, conn, (uint16)-1); + close_cnum(conn, (uint16)-1); } } } diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 642fb09362..73c4cbb3e7 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -115,15 +115,19 @@ bool make_dir_struct(TALLOC_CTX *ctx, Initialise the dir bitmap. ****************************************************************************/ -void init_dptrs(void) +bool init_dptrs(struct smbd_server_connection *sconn) { - if (dptr_bmap) - return; + if (sconn->smb1.searches.dptr_bmap) { + return true; + } + + sconn->smb1.searches.dptr_bmap = bitmap_allocate(MAX_DIRECTORY_HANDLES); - dptr_bmap = bitmap_allocate(MAX_DIRECTORY_HANDLES); + if (sconn->smb1.searches.dptr_bmap == NULL) { + return false; + } - if (!dptr_bmap) - exit_server("out of memory in init_dptrs"); + return true; } /**************************************************************************** @@ -142,14 +146,14 @@ static void dptr_idle(struct dptr_struct *dptr) Idle the oldest dptr. ****************************************************************************/ -static void dptr_idleoldest(void) +static void dptr_idleoldest(struct smbd_server_connection *sconn) { struct dptr_struct *dptr; /* * Go to the end of the list. */ - for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next) + for(dptr = sconn->smb1.searches.dirptrs; dptr && dptr->next; dptr = dptr->next) ; if(!dptr) { @@ -173,15 +177,16 @@ static void dptr_idleoldest(void) Get the struct dptr_struct for a dir index. ****************************************************************************/ -static struct dptr_struct *dptr_get(int key, bool forclose) +static struct dptr_struct *dptr_get(struct smbd_server_connection *sconn, + int key, bool forclose) { struct dptr_struct *dptr; - for(dptr = dirptrs; dptr; dptr = dptr->next) { + for(dptr = sconn->smb1.searches.dirptrs; dptr; dptr = dptr->next) { if(dptr->dnum == key) { if (!forclose && !dptr->dir_hnd) { - if (dirhandles_open >= MAX_OPEN_DIRECTORIES) - dptr_idleoldest(); + if (sconn->smb1.searches.dirhandles_open >= MAX_OPEN_DIRECTORIES) + dptr_idleoldest(sconn); DEBUG(4,("dptr_get: Reopening dptr key %d\n",key)); if (!(dptr->dir_hnd = OpenDir( NULL, dptr->conn, dptr->path, @@ -191,7 +196,7 @@ static struct dptr_struct *dptr_get(int key, bool forclose) return False; } } - DLIST_PROMOTE(dirptrs,dptr); + DLIST_PROMOTE(sconn->smb1.searches.dirptrs,dptr); return dptr; } } @@ -202,9 +207,9 @@ static struct dptr_struct *dptr_get(int key, bool forclose) Get the dir path for a dir index. ****************************************************************************/ -char *dptr_path(int key) +char *dptr_path(struct smbd_server_connection *sconn, int key) { - struct dptr_struct *dptr = dptr_get(key, False); + struct dptr_struct *dptr = dptr_get(sconn, key, false); if (dptr) return(dptr->path); return(NULL); @@ -214,9 +219,9 @@ char *dptr_path(int key) Get the dir wcard for a dir index. ****************************************************************************/ -char *dptr_wcard(int key) +char *dptr_wcard(struct smbd_server_connection *sconn, int key) { - struct dptr_struct *dptr = dptr_get(key, False); + struct dptr_struct *dptr = dptr_get(sconn, key, false); if (dptr) return(dptr->wcard); return(NULL); @@ -226,9 +231,9 @@ char *dptr_wcard(int key) Get the dir attrib for a dir index. ****************************************************************************/ -uint16 dptr_attr(int key) +uint16 dptr_attr(struct smbd_server_connection *sconn, int key) { - struct dptr_struct *dptr = dptr_get(key, False); + struct dptr_struct *dptr = dptr_get(sconn, key, false); if (dptr) return(dptr->attr); return(0); @@ -240,22 +245,29 @@ uint16 dptr_attr(int key) static void dptr_close_internal(struct dptr_struct *dptr) { + struct smbd_server_connection *sconn = dptr->conn->sconn; + DEBUG(4,("closing dptr key %d\n",dptr->dnum)); - DLIST_REMOVE(dirptrs, dptr); + if (sconn == NULL) { + goto done; + } + + DLIST_REMOVE(sconn->smb1.searches.dirptrs, dptr); /* * Free the dnum in the bitmap. Remember the dnum value is always * biased by one with respect to the bitmap. */ - if(bitmap_query( dptr_bmap, dptr->dnum - 1) != True) { + if(bitmap_query(sconn->smb1.searches.dptr_bmap, dptr->dnum - 1) != true) { DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n", dptr->dnum )); } - bitmap_clear(dptr_bmap, dptr->dnum - 1); + bitmap_clear(sconn->smb1.searches.dptr_bmap, dptr->dnum - 1); +done: TALLOC_FREE(dptr->dir_hnd); /* Lanman 2 specific code */ @@ -268,7 +280,7 @@ static void dptr_close_internal(struct dptr_struct *dptr) Close a dptr given a key. ****************************************************************************/ -void dptr_close(int *key) +void dptr_close(struct smbd_server_connection *sconn, int *key) { struct dptr_struct *dptr; @@ -278,7 +290,7 @@ void dptr_close(int *key) /* OS/2 seems to use -1 to indicate "close all directories" */ if (*key == -1) { struct dptr_struct *next; - for(dptr = dirptrs; dptr; dptr = next) { + for(dptr = sconn->smb1.searches.dirptrs; dptr; dptr = next) { next = dptr->next; dptr_close_internal(dptr); } @@ -286,7 +298,7 @@ void dptr_close(int *key) return; } - dptr = dptr_get(*key, True); + dptr = dptr_get(sconn, *key, true); if (!dptr) { DEBUG(0,("Invalid key %d given to dptr_close\n", *key)); @@ -305,10 +317,17 @@ void dptr_close(int *key) void dptr_closecnum(connection_struct *conn) { struct dptr_struct *dptr, *next; - for(dptr = dirptrs; dptr; dptr = next) { + struct smbd_server_connection *sconn = conn->sconn; + + if (sconn == NULL) { + return; + } + + for(dptr = sconn->smb1.searches.dirptrs; dptr; dptr = next) { next = dptr->next; - if (dptr->conn == conn) + if (dptr->conn == conn) { dptr_close_internal(dptr); + } } } @@ -319,9 +338,16 @@ void dptr_closecnum(connection_struct *conn) void dptr_idlecnum(connection_struct *conn) { struct dptr_struct *dptr; - for(dptr = dirptrs; dptr; dptr = dptr->next) { - if (dptr->conn == conn && dptr->dir_hnd) + struct smbd_server_connection *sconn = conn->sconn; + + if (sconn == NULL) { + return; + } + + for(dptr = sconn->smb1.searches.dirptrs; dptr; dptr = dptr->next) { + if (dptr->conn == conn && dptr->dir_hnd) { dptr_idle(dptr); + } } } @@ -329,10 +355,11 @@ void dptr_idlecnum(connection_struct *conn) Close a dptr that matches a given path, only if it matches the spid also. ****************************************************************************/ -void dptr_closepath(char *path,uint16 spid) +void dptr_closepath(struct smbd_server_connection *sconn, + char *path,uint16 spid) { struct dptr_struct *dptr, *next; - for(dptr = dirptrs; dptr; dptr = next) { + for(dptr = sconn->smb1.searches.dirptrs; dptr; dptr = next) { next = dptr->next; if (spid == dptr->spid && strequal(dptr->path,path)) dptr_close_internal(dptr); @@ -345,14 +372,15 @@ void dptr_closepath(char *path,uint16 spid) finished with that one. ****************************************************************************/ -static void dptr_close_oldest(bool old) +static void dptr_close_oldest(struct smbd_server_connection *sconn, + bool old) { struct dptr_struct *dptr; /* * Go to the end of the list. */ - for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next) + for(dptr = sconn->smb1.searches.dirptrs; dptr && dptr->next; dptr = dptr->next) ; if(!dptr) { @@ -387,12 +415,18 @@ static void dptr_close_oldest(bool old) NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, bool expect_close,uint16 spid, const char *wcard, bool wcard_has_wild, uint32 attr, struct dptr_struct **dptr_ret) { + struct smbd_server_connection *sconn = conn->sconn; struct dptr_struct *dptr = NULL; struct smb_Dir *dir_hnd; NTSTATUS status; DEBUG(5,("dptr_create dir=%s\n", path)); + if (sconn == NULL) { + DEBUG(0,("dptr_create: called with fake connection_struct\n")); + return NT_STATUS_INTERNAL_ERROR; + } + if (!wcard) { return NT_STATUS_INVALID_PARAMETER; } @@ -407,10 +441,8 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, return map_nt_error_from_unix(errno); } - string_set(&conn->dirpath,path); - - if (dirhandles_open >= MAX_OPEN_DIRECTORIES) { - dptr_idleoldest(); + if (sconn->smb1.searches.dirhandles_open >= MAX_OPEN_DIRECTORIES) { + dptr_idleoldest(sconn); } dptr = SMB_MALLOC_P(struct dptr_struct); @@ -429,7 +461,7 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, * value we return will fit in the range 1-255. */ - dptr->dnum = bitmap_find(dptr_bmap, 0); + dptr->dnum = bitmap_find(sconn->smb1.searches.dptr_bmap, 0); if(dptr->dnum == -1 || dptr->dnum > 254) { @@ -439,10 +471,10 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, * finished with that one. */ - dptr_close_oldest(True); + dptr_close_oldest(sconn, true); /* Now try again... */ - dptr->dnum = bitmap_find(dptr_bmap, 0); + dptr->dnum = bitmap_find(sconn->smb1.searches.dptr_bmap, 0); if(dptr->dnum == -1 || dptr->dnum > 254) { DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum)); SAFE_FREE(dptr); @@ -457,7 +489,7 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, * a range that will return 256 - MAX_DIRECTORY_HANDLES. */ - dptr->dnum = bitmap_find(dptr_bmap, 255); + dptr->dnum = bitmap_find(sconn->smb1.searches.dptr_bmap, 255); if(dptr->dnum == -1 || dptr->dnum < 255) { @@ -468,10 +500,10 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, * directory handles. */ - dptr_close_oldest(False); + dptr_close_oldest(sconn, false); /* Now try again... */ - dptr->dnum = bitmap_find(dptr_bmap, 255); + dptr->dnum = bitmap_find(sconn->smb1.searches.dptr_bmap, 255); if(dptr->dnum == -1 || dptr->dnum < 255) { DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum)); @@ -482,7 +514,7 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, } } - bitmap_set(dptr_bmap, dptr->dnum); + bitmap_set(sconn->smb1.searches.dptr_bmap, dptr->dnum); dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */ @@ -493,7 +525,7 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, dptr->expect_close = expect_close; dptr->wcard = SMB_STRDUP(wcard); if (!dptr->wcard) { - bitmap_clear(dptr_bmap, dptr->dnum - 1); + bitmap_clear(sconn->smb1.searches.dptr_bmap, dptr->dnum - 1); SAFE_FREE(dptr); TALLOC_FREE(dir_hnd); return NT_STATUS_NO_MEMORY; @@ -506,7 +538,7 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, dptr->attr = attr; - DLIST_ADD(dirptrs, dptr); + DLIST_ADD(sconn->smb1.searches.dirptrs, dptr); DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n", dptr->dnum,path,expect_close)); @@ -523,7 +555,8 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, int dptr_CloseDir(struct dptr_struct *dptr) { - DLIST_REMOVE(dirptrs, dptr); + struct smbd_server_connection *sconn = dptr->conn->sconn; + DLIST_REMOVE(sconn->smb1.searches.dirptrs, dptr); TALLOC_FREE(dptr->dir_hnd); return 0; } @@ -726,10 +759,11 @@ void dptr_init_search_op(struct dptr_struct *dptr) Fill the 5 byte server reserved dptr field. ****************************************************************************/ -bool dptr_fill(char *buf1,unsigned int key) +bool dptr_fill(struct smbd_server_connection *sconn, + char *buf1,unsigned int key) { unsigned char *buf = (unsigned char *)buf1; - struct dptr_struct *dptr = dptr_get(key, False); + struct dptr_struct *dptr = dptr_get(sconn, key, false); uint32 offset; if (!dptr) { DEBUG(1,("filling null dirptr %d\n",key)); @@ -747,10 +781,11 @@ bool dptr_fill(char *buf1,unsigned int key) Fetch the dir ptr and seek it given the 5 byte server field. ****************************************************************************/ -struct dptr_struct *dptr_fetch(char *buf,int *num) +struct dptr_struct *dptr_fetch(struct smbd_server_connection *sconn, + char *buf, int *num) { unsigned int key = *(unsigned char *)buf; - struct dptr_struct *dptr = dptr_get(key, False); + struct dptr_struct *dptr = dptr_get(sconn, key, false); uint32 offset; long seekoff; @@ -767,7 +802,7 @@ struct dptr_struct *dptr_fetch(char *buf,int *num) } SeekDir(dptr->dir_hnd,seekoff); DEBUG(3,("fetching dirptr %d for path %s at offset %d\n", - key,dptr_path(key),(int)seekoff)); + key, dptr->path, (int)seekoff)); return(dptr); } @@ -775,15 +810,16 @@ struct dptr_struct *dptr_fetch(char *buf,int *num) Fetch the dir ptr. ****************************************************************************/ -struct dptr_struct *dptr_fetch_lanman2(int dptr_num) +struct dptr_struct *dptr_fetch_lanman2(struct smbd_server_connection *sconn, + int dptr_num) { - struct dptr_struct *dptr = dptr_get(dptr_num, False); + struct dptr_struct *dptr = dptr_get(sconn, dptr_num, false); if (!dptr) { DEBUG(3,("fetched null dirptr %d\n",dptr_num)); return(NULL); } - DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num))); + DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr->path)); return(dptr); } @@ -825,156 +861,251 @@ static bool mangle_mask_match(connection_struct *conn, return mask_match_search(mname,mask,False); } -/**************************************************************************** - Get an 8.3 directory entry. -****************************************************************************/ - -bool get_dir_entry(TALLOC_CTX *ctx, - connection_struct *conn, - const char *mask, - uint32 dirtype, - char **pp_fname_out, - SMB_OFF_T *size, - uint32 *mode, - struct timespec *date, - bool check_descend, - bool ask_sharemode) +bool smbd_dirptr_get_entry(TALLOC_CTX *ctx, + struct dptr_struct *dirptr, + const char *mask, + uint32_t dirtype, + bool dont_descend, + bool ask_sharemode, + bool (*match_fn)(TALLOC_CTX *ctx, + void *private_data, + const char *dname, + const char *mask, + char **_fname), + bool (*mode_fn)(TALLOC_CTX *ctx, + void *private_data, + struct smb_filename *smb_fname, + uint32_t *_mode), + void *private_data, + char **_fname, + struct smb_filename **_smb_fname, + uint32_t *_mode, + long *_prev_offset) { - char *dname = NULL; - bool found = False; - SMB_STRUCT_STAT sbuf; - char *pathreal = NULL; - char *filename = NULL; + connection_struct *conn = dirptr->conn; bool needslash; - *pp_fname_out = NULL; + *_smb_fname = NULL; + *_mode = 0; - needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/'); + needslash = ( dirptr->path[strlen(dirptr->path) -1] != '/'); - if (!conn->dirptr) { - return(False); - } + while (true) { + long cur_offset; + long prev_offset; + SMB_STRUCT_STAT sbuf; + char *dname = NULL; + bool isdots; + char *fname = NULL; + char *pathreal = NULL; + struct smb_filename *smb_fname = NULL; + uint32_t mode = 0; + bool ok; + NTSTATUS status; - while (!found) { - long curoff = dptr_TellDir(conn->dirptr); - dname = dptr_ReadDirName(ctx, conn->dirptr, &curoff, &sbuf); + cur_offset = dptr_TellDir(dirptr); + prev_offset = cur_offset; + dname = dptr_ReadDirName(ctx, dirptr, &cur_offset, &sbuf); - DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n", - (long)conn->dirptr,TellDir(conn->dirptr->dir_hnd))); + DEBUG(6,("smbd_dirptr_get_entry: dirptr 0x%lx now at offset %ld\n", + (long)dirptr, cur_offset)); if (dname == NULL) { - return(False); + return false; } - filename = dname; - - /* notice the special *.* handling. This appears to be the only difference - between the wildcard handling in this routine and in the trans2 routines. - see masktest for a demo - */ - if ((strcmp(mask,"*.*") == 0) || - mask_match_search(filename,mask,False) || - mangle_mask_match(conn,filename,mask)) { - char mname[13]; - struct smb_filename *smb_fname = NULL; - NTSTATUS status; - - if (!mangle_is_8_3(filename, False, conn->params)) { - if (!name_to_8_3(filename,mname,False, - conn->params)) { - TALLOC_FREE(filename); - continue; - } - filename = talloc_strdup(ctx, mname); - if (!filename) { - return False; - } - } + isdots = (ISDOT(dname) || ISDOTDOT(dname)); + if (dont_descend && !isdots) { + TALLOC_FREE(dname); + continue; + } - if (needslash) { - pathreal = talloc_asprintf(ctx, - "%s/%s", - conn->dirpath, - dname); - } else { - pathreal = talloc_asprintf(ctx, - "%s%s", - conn->dirpath, - dname); - } - if (!pathreal) { - TALLOC_FREE(filename); - return False; - } + /* + * fname may get mangled, dname is never mangled. + * Whenever we're accessing the filesystem we use + * pathreal which is composed from dname. + */ - /* Create smb_fname with NULL stream_name. */ - status = create_synthetic_smb_fname(ctx, pathreal, - NULL, &sbuf, - &smb_fname); + ok = match_fn(ctx, private_data, dname, mask, &fname); + if (!ok) { + TALLOC_FREE(dname); + continue; + } - TALLOC_FREE(pathreal); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(filename); - return false; - } + pathreal = talloc_asprintf(ctx, "%s%s%s", + dirptr->path, + needslash?"/":"", + dname); + if (!pathreal) { + TALLOC_FREE(dname); + TALLOC_FREE(fname); + return false; + } - if (!VALID_STAT(smb_fname->st)) { - if ((SMB_VFS_STAT(conn, smb_fname)) != 0) { - DEBUG(5,("Couldn't stat 1 [%s]. Error " - "= %s\n", - smb_fname_str_dbg(smb_fname), - strerror(errno))); - TALLOC_FREE(smb_fname); - TALLOC_FREE(filename); - continue; - } - } + /* Create smb_fname with NULL stream_name. */ + status = create_synthetic_smb_fname(ctx, pathreal, + NULL, &sbuf, + &smb_fname); + TALLOC_FREE(pathreal); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(dname); + TALLOC_FREE(fname); + return false; + } - *mode = dos_mode(conn, smb_fname); + ok = mode_fn(ctx, private_data, smb_fname, &mode); + if (!ok) { + TALLOC_FREE(dname); + TALLOC_FREE(fname); + TALLOC_FREE(smb_fname); + continue; + } - if (!dir_check_ftype(conn,*mode,dirtype)) { - DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",filename,(unsigned int)*mode,(unsigned int)dirtype)); - TALLOC_FREE(smb_fname); - TALLOC_FREE(filename); - continue; + if (!dir_check_ftype(conn, mode, dirtype)) { + DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n", + fname, (unsigned int)mode, (unsigned int)dirtype)); + TALLOC_FREE(dname); + TALLOC_FREE(fname); + TALLOC_FREE(smb_fname); + continue; + } + + if (ask_sharemode) { + struct timespec write_time_ts; + struct file_id fileid; + + fileid = vfs_file_id_from_sbuf(conn, + &smb_fname->st); + get_file_infos(fileid, NULL, &write_time_ts); + if (!null_timespec(write_time_ts)) { + update_stat_ex_mtime(&smb_fname->st, + write_time_ts); } + } - *size = smb_fname->st.st_ex_size; - *date = smb_fname->st.st_ex_mtime; + DEBUG(3,("smbd_dirptr_get_entry mask=[%s] found %s " + "fname=%s (%s)\n", + mask, smb_fname_str_dbg(smb_fname), + dname, fname)); - if (ask_sharemode) { - struct timespec write_time_ts; - struct file_id fileid; + DirCacheAdd(dirptr->dir_hnd, dname, cur_offset); - fileid = vfs_file_id_from_sbuf(conn, - &smb_fname->st); - get_file_infos(fileid, NULL, &write_time_ts); - if (!null_timespec(write_time_ts)) { - *date = write_time_ts; - } + TALLOC_FREE(dname); + + *_fname = fname; + *_smb_fname = smb_fname; + *_mode = mode; + *_prev_offset = prev_offset; + + return true; + } + + return false; +} + +/**************************************************************************** + Get an 8.3 directory entry. +****************************************************************************/ + +static bool smbd_dirptr_8_3_match_fn(TALLOC_CTX *ctx, + void *private_data, + const char *dname, + const char *mask, + char **_fname) +{ + connection_struct *conn = (connection_struct *)private_data; + + if ((strcmp(mask,"*.*") == 0) || + mask_match_search(dname, mask, false) || + mangle_mask_match(conn, dname, mask)) { + char mname[13]; + const char *fname; + + if (!mangle_is_8_3(dname, false, conn->params)) { + bool ok = name_to_8_3(dname, mname, false, + conn->params); + if (!ok) { + return false; } + fname = mname; + } else { + fname = dname; + } - DEBUG(3,("get_dir_entry mask=[%s] found %s " - "fname=%s (%s)\n", - mask, - smb_fname_str_dbg(smb_fname), - dname, - filename)); + *_fname = talloc_strdup(ctx, fname); + if (*_fname == NULL) { + return false; + } - found = True; + return true; + } - SMB_ASSERT(filename != NULL); - *pp_fname_out = filename; + return false; +} - DirCacheAdd(conn->dirptr->dir_hnd, dname, curoff); - TALLOC_FREE(smb_fname); +static bool smbd_dirptr_8_3_mode_fn(TALLOC_CTX *ctx, + void *private_data, + struct smb_filename *smb_fname, + uint32_t *_mode) +{ + connection_struct *conn = (connection_struct *)private_data; + + if (!VALID_STAT(smb_fname->st)) { + if ((SMB_VFS_STAT(conn, smb_fname)) != 0) { + DEBUG(5,("smbd_dirptr_8_3_mode_fn: " + "Couldn't stat [%s]. Error " + "= %s\n", + smb_fname_str_dbg(smb_fname), + strerror(errno))); + return false; } + } + + *_mode = dos_mode(conn, smb_fname); + return true; +} - if (!found) - TALLOC_FREE(filename); +bool get_dir_entry(TALLOC_CTX *ctx, + struct dptr_struct *dirptr, + const char *mask, + uint32_t dirtype, + char **_fname, + SMB_OFF_T *_size, + uint32_t *_mode, + struct timespec *_date, + bool check_descend, + bool ask_sharemode) +{ + connection_struct *conn = dirptr->conn; + char *fname = NULL; + struct smb_filename *smb_fname = NULL; + uint32_t mode = 0; + long prev_offset; + bool ok; + + ok = smbd_dirptr_get_entry(ctx, + dirptr, + mask, + dirtype, + check_descend, + ask_sharemode, + smbd_dirptr_8_3_match_fn, + smbd_dirptr_8_3_mode_fn, + conn, + &fname, + &smb_fname, + &mode, + &prev_offset); + if (!ok) { + return false; } - return(found); + *_fname = talloc_move(ctx, &fname); + *_size = smb_fname->st.st_ex_size; + *_mode = mode; + *_date = smb_fname->st.st_ex_mtime; + TALLOC_FREE(smb_fname); + return true; } /******************************************************************* @@ -1152,7 +1283,9 @@ static int smb_Dir_destructor(struct smb_Dir *dirp) if (dirp->dir) { SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir); } - dirhandles_open--; + if (dirp->conn->sconn) { + dirp->conn->sconn->smb1.searches.dirhandles_open--; + } return 0; } @@ -1164,6 +1297,7 @@ struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn, const char *name, const char *mask, uint32 attr) { struct smb_Dir *dirp = TALLOC_ZERO_P(mem_ctx, struct smb_Dir); + struct smbd_server_connection *sconn = conn->sconn; if (!dirp) { return NULL; @@ -1178,7 +1312,9 @@ struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn, goto fail; } - dirhandles_open++; + if (sconn) { + sconn->smb1.searches.dirhandles_open++; + } talloc_set_destructor(dirp, smb_Dir_destructor); dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr); diff --git a/source3/smbd/files.c b/source3/smbd/files.c index a170f774fe..146d809738 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -404,14 +404,15 @@ bool file_find_subpath(files_struct *dir_fsp) { files_struct *fsp; size_t dlen; - char *d_fullname; + char *d_fullname = NULL; + bool ret = false; d_fullname = talloc_asprintf(talloc_tos(), "%s/%s", dir_fsp->conn->connectpath, dir_fsp->fsp_name->base_name); if (!d_fullname) { - return false; + goto out; } dlen = strlen(d_fullname); @@ -429,15 +430,27 @@ bool file_find_subpath(files_struct *dir_fsp) fsp->fsp_name->base_name); if (strnequal(d_fullname, d1_fullname, dlen)) { - TALLOC_FREE(d_fullname); + int d1_len = strlen(d1_fullname); + + /* + * If the open file is a second file handle to the + * same name or is a stream on the original file, then + * don't return true. + */ + if (d1_len == dlen) { + TALLOC_FREE(d1_fullname); + continue; + } + TALLOC_FREE(d1_fullname); - return true; + ret = true; + goto out; } TALLOC_FREE(d1_fullname); } - + out: TALLOC_FREE(d_fullname); - return false; + return ret; } /**************************************************************************** diff --git a/source3/smbd/globals.c b/source3/smbd/globals.c index 317304a86d..f680b76369 100644 --- a/source3/smbd/globals.c +++ b/source3/smbd/globals.c @@ -46,10 +46,6 @@ struct smbd_dmapi_context *dmapi_ctx = NULL; bool dfree_broken = false; -struct bitmap *dptr_bmap = NULL; -struct dptr_struct *dirptrs = NULL; -int dirhandles_open = 0; - /* how many write cache buffers have been allocated */ unsigned int allocated_write_caches = 0; diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 434204b60d..338398968a 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -44,11 +44,6 @@ extern struct smbd_dmapi_context *dmapi_ctx; extern bool dfree_broken; -extern struct bitmap *dptr_bmap; -//struct dptr_struct; -extern struct dptr_struct *dirptrs; -extern int dirhandles_open; - /* how many write cache buffers have been allocated */ extern unsigned int allocated_write_caches; @@ -218,6 +213,27 @@ NTSTATUS smbd_do_qfsinfo(connection_struct *conn, char **ppdata, int *ret_data_len); +bool smbd_dirptr_get_entry(TALLOC_CTX *ctx, + struct dptr_struct *dirptr, + const char *mask, + uint32_t dirtype, + bool dont_descend, + bool ask_sharemode, + bool (*match_fn)(TALLOC_CTX *ctx, + void *private_data, + const char *dname, + const char *mask, + char **_fname), + bool (*mode_fn)(TALLOC_CTX *ctx, + void *private_data, + struct smb_filename *smb_fname, + uint32_t *_mode), + void *private_data, + char **_fname, + struct smb_filename **_smb_fname, + uint32_t *_mode, + long *_prev_offset); + void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn, const char *reason, const char *location); @@ -432,6 +448,12 @@ struct smbd_server_connection { struct pending_auth_data *pd_list; struct notify_mid_map *notify_mid_maps; + + struct { + struct bitmap *dptr_bmap; + struct dptr_struct *dirptrs; + int dirhandles_open; + } searches; } smb1; struct { struct tevent_context *event_ctx; diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 96a411dd70..12d4922844 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -534,7 +534,6 @@ static void named_pipe(connection_struct *conn, uint16 vuid, static void handle_trans(connection_struct *conn, struct smb_request *req, struct trans_state *state) { - struct smbd_server_connection *sconn = smbd_server_conn; char *local_machine_name; int name_offset = 0; @@ -585,7 +584,7 @@ static void handle_trans(connection_struct *conn, struct smb_request *req, state->max_param_return); if (state->close_on_completion) { - close_cnum(sconn, conn,state->vuid); + close_cnum(conn,state->vuid); req->conn = NULL; } diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 22fb8c3ad6..767c8fe297 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -268,7 +268,7 @@ NTSTATUS create_conn_struct(TALLOC_CTX *ctx, if (!smbd_vfs_init(conn)) { NTSTATUS status = map_nt_error_from_unix(errno); DEBUG(0,("create_conn_struct: smbd_vfs_init failed.\n")); - conn_free_internal(conn); + conn_free(conn); return status; } @@ -284,7 +284,7 @@ NTSTATUS create_conn_struct(TALLOC_CTX *ctx, if (oldcwd == NULL) { NTSTATUS status = map_nt_error_from_unix(errno); DEBUG(3, ("vfs_GetWd failed: %s\n", strerror(errno))); - conn_free_internal(conn); + conn_free(conn); return status; } @@ -293,7 +293,7 @@ NTSTATUS create_conn_struct(TALLOC_CTX *ctx, DEBUG(3,("create_conn_struct: Can't ChDir to new conn path %s. " "Error was %s\n", conn->connectpath, strerror(errno) )); - conn_free_internal(conn); + conn_free(conn); return status; } @@ -939,7 +939,7 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, DEBUG(3,("get_referred_path: No valid referrals for path %s\n", dfs_path)); vfs_ChDir(conn, oldpath); - conn_free_internal(conn); + conn_free(conn); TALLOC_FREE(pdp); return status; } @@ -951,13 +951,13 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, DEBUG(3,("get_referred_path: failed to parse symlink " "target %s\n", targetpath )); vfs_ChDir(conn, oldpath); - conn_free_internal(conn); + conn_free(conn); TALLOC_FREE(pdp); return NT_STATUS_NOT_FOUND; } vfs_ChDir(conn, oldpath); - conn_free_internal(conn); + conn_free(conn); TALLOC_FREE(pdp); return NT_STATUS_OK; } @@ -1374,7 +1374,7 @@ static bool junction_to_local_path(const struct junction_map *jucn, jucn->volume_name); if (!*pp_path_out) { vfs_ChDir(*conn_out, *oldpath); - conn_free_internal(*conn_out); + conn_free(*conn_out); return False; } return True; @@ -1462,7 +1462,7 @@ bool create_msdfs_link(const struct junction_map *jucn) out: vfs_ChDir(conn, cwd); - conn_free_internal(conn); + conn_free(conn); return ret; } @@ -1493,7 +1493,7 @@ bool remove_msdfs_link(const struct junction_map *jucn) TALLOC_FREE(smb_fname); vfs_ChDir(conn, cwd); - conn_free_internal(conn); + conn_free(conn); return ret; } @@ -1554,7 +1554,7 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum) out: vfs_ChDir(conn, cwd); - conn_free_internal(conn); + conn_free(conn); return cnt; } @@ -1680,7 +1680,7 @@ out: } vfs_ChDir(conn, cwd); - conn_free_internal(conn); + conn_free(conn); return cnt; } diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 0a3b0dff75..b61421dc8f 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -4360,7 +4360,7 @@ static SMB_ACL_T create_posix_acl_from_wire(connection_struct *conn, uint16 num_ on the directory. ****************************************************************************/ -bool set_unix_posix_default_acl(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, +bool set_unix_posix_default_acl(connection_struct *conn, const char *fname, const SMB_STRUCT_STAT *psbuf, uint16 num_def_acls, const char *pdata) { SMB_ACL_T def_acl = NULL; @@ -4616,7 +4616,7 @@ SEC_DESC *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname) if (!smbd_vfs_init(conn)) { DEBUG(0,("get_nt_acl_no_snum: Unable to create a fake connection struct!\n")); - conn_free_internal( conn ); + conn_free(conn); return NULL; } @@ -4631,21 +4631,21 @@ SEC_DESC *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname) status = create_synthetic_smb_fname(talloc_tos(), fname, NULL, NULL, &finfo.fsp_name); if (!NT_STATUS_IS_OK(status)) { - conn_free_internal( conn ); + conn_free(conn); return NULL; } if (!NT_STATUS_IS_OK(SMB_VFS_FGET_NT_ACL( &finfo, DACL_SECURITY_INFORMATION, &psd))) { DEBUG(0,("get_nt_acl_no_snum: get_nt_acl returned zero.\n")); TALLOC_FREE(finfo.fsp_name); - conn_free_internal( conn ); + conn_free(conn); return NULL; } ret_sd = dup_sec_desc( ctx, psd ); TALLOC_FREE(finfo.fsp_name); - conn_free_internal( conn ); + conn_free(conn); return ret_sd; } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 99c862300d..6ec46071ff 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -2206,6 +2206,9 @@ void smbd_process(void) #endif conn_init(smbd_server_conn); + if (!init_dptrs(smbd_server_conn)) { + exit_server("init_dptrs() failed"); + } smbd_server_conn->smb1.fde = event_add_fd(smbd_event_context(), smbd_server_conn, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 77e122a90c..3498109f12 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -703,7 +703,7 @@ void reply_tcon_and_X(struct smb_request *req) /* we might have to close an old one */ if ((tcon_flags & 0x1) && conn) { - close_cnum(sconn, conn,req->vuid); + close_cnum(conn,req->vuid); req->conn = NULL; conn = NULL; } @@ -1366,6 +1366,8 @@ void reply_search(struct smb_request *req) bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False; TALLOC_CTX *ctx = talloc_tos(); bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true); + struct dptr_struct *dirptr = NULL; + struct smbd_server_connection *sconn = smbd_server_conn; START_PROFILE(SMBsearch); @@ -1446,14 +1448,15 @@ void reply_search(struct smb_request *req) mask, mask_contains_wcard, dirtype, - &conn->dirptr); + &dirptr); if (!NT_STATUS_IS_OK(nt_status)) { reply_nterror(req, nt_status); goto out; } - dptr_num = dptr_dnum(conn->dirptr); + dptr_num = dptr_dnum(dirptr); } else { int status_dirtype; + const char *dirpath; memcpy(status,p,21); status_dirtype = CVAL(status,0) & 0x1F; @@ -1461,12 +1464,18 @@ void reply_search(struct smb_request *req) dirtype = status_dirtype; } - conn->dirptr = dptr_fetch(status+12,&dptr_num); - if (!conn->dirptr) { + dirptr = dptr_fetch(sconn, status+12,&dptr_num); + if (!dirptr) { goto SearchEmpty; } - string_set(&conn->dirpath,dptr_path(dptr_num)); - mask = dptr_wcard(dptr_num); + dirpath = dptr_path(sconn, dptr_num); + directory = talloc_strdup(ctx, dirpath); + if (!directory) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + goto out; + } + + mask = dptr_wcard(sconn, dptr_num); if (!mask) { goto SearchEmpty; } @@ -1475,13 +1484,13 @@ void reply_search(struct smb_request *req) * check from the initial saved string. */ mask_contains_wcard = ms_has_wild(mask); - dirtype = dptr_attr(dptr_num); + dirtype = dptr_attr(sconn, dptr_num); } DEBUG(4,("dptr_num is %d\n",dptr_num)); /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */ - dptr_init_search_op(conn->dirptr); + dptr_init_search_op(dirptr); if ((dirtype&0x1F) == aVOLID) { char buf[DIR_STRUCT_SIZE]; @@ -1491,7 +1500,7 @@ void reply_search(struct smb_request *req) reply_nterror(req, NT_STATUS_NO_MEMORY); goto out; } - dptr_fill(buf+12,dptr_num); + dptr_fill(sconn, buf+12,dptr_num); if (dptr_zero(buf+12) && (status_len==0)) { numentries = 1; } else { @@ -1512,14 +1521,14 @@ void reply_search(struct smb_request *req) /DIR_STRUCT_SIZE)); DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", - conn->dirpath,lp_dontdescend(SNUM(conn)))); - if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) { + directory,lp_dontdescend(SNUM(conn)))); + if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) { check_descend = True; } for (i=numentries;(i<maxentries) && !finished;i++) { finished = !get_dir_entry(ctx, - conn, + dirptr, mask, dirtype, &fname, @@ -1542,7 +1551,7 @@ void reply_search(struct smb_request *req) reply_nterror(req, NT_STATUS_NO_MEMORY); goto out; } - if (!dptr_fill(buf+12,dptr_num)) { + if (!dptr_fill(sconn, buf+12,dptr_num)) { break; } if (message_push_blob(&req->outbuf, @@ -1563,15 +1572,15 @@ void reply_search(struct smb_request *req) (X/Open spec) */ if (numentries == 0) { - dptr_close(&dptr_num); + dptr_close(sconn, &dptr_num); } else if(expect_close && status_len == 0) { /* Close the dptr - we know it's gone */ - dptr_close(&dptr_num); + dptr_close(sconn, &dptr_num); } /* If we were called as SMBfunique, then we can close the dirptr now ! */ if(dptr_num >= 0 && req->cmd == SMBfunique) { - dptr_close(&dptr_num); + dptr_close(sconn, &dptr_num); } if ((numentries == 0) && !mask_contains_wcard) { @@ -1597,18 +1606,15 @@ void reply_search(struct smb_request *req) SSVAL(req->outbuf, smb_flg2, (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS))); - if (!directory) { - directory = dptr_path(dptr_num); - } - DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n", smb_fn_name(req->cmd), mask, - directory ? directory : "./", + directory, dirtype, numentries, maxentries )); out: + TALLOC_FREE(directory); TALLOC_FREE(smb_fname); END_PROFILE(SMBsearch); return; @@ -1628,6 +1634,7 @@ void reply_fclose(struct smb_request *req) NTSTATUS err; bool path_contains_wcard = False; TALLOC_CTX *ctx = talloc_tos(); + struct smbd_server_connection *sconn = smbd_server_conn; START_PROFILE(SMBfclose); @@ -1657,9 +1664,9 @@ void reply_fclose(struct smb_request *req) memcpy(status,p,21); - if(dptr_fetch(status+12,&dptr_num)) { + if(dptr_fetch(sconn, status+12,&dptr_num)) { /* Close the dptr - we know it's gone */ - dptr_close(&dptr_num); + dptr_close(sconn, &dptr_num); } reply_outbuf(req, 1, 0); @@ -4868,7 +4875,6 @@ void reply_unlock(struct smb_request *req) void reply_tdis(struct smb_request *req) { - struct smbd_server_connection *sconn = smbd_server_conn; connection_struct *conn = req->conn; START_PROFILE(SMBtdis); @@ -4881,7 +4887,7 @@ void reply_tdis(struct smb_request *req) conn->used = False; - close_cnum(sconn, conn,req->vuid); + close_cnum(conn,req->vuid); req->conn = NULL; reply_outbuf(req, 0, 0); @@ -5528,6 +5534,7 @@ void reply_rmdir(struct smb_request *req) char *directory = NULL; NTSTATUS status; TALLOC_CTX *ctx = talloc_tos(); + struct smbd_server_connection *sconn = smbd_server_conn; START_PROFILE(SMBrmdir); @@ -5559,7 +5566,7 @@ void reply_rmdir(struct smb_request *req) goto out; } - dptr_closepath(smb_dname->base_name, req->smbpid); + dptr_closepath(sconn, smb_dname->base_name, req->smbpid); status = rmdir_internals(ctx, conn, smb_dname); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 4b1c803d75..ace3124842 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -914,8 +914,6 @@ static bool init_structs(void ) file_init(); - init_dptrs(); - if (!secrets_init()) return False; diff --git a/source3/smbd/service.c b/source3/smbd/service.c index a043288bc9..fc56105adf 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -673,7 +673,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, DEBUG(1, ("create_connection_server_info failed: %s\n", nt_errstr(status))); *pstatus = status; - conn_free(sconn, conn); + conn_free(conn); return NULL; } @@ -692,7 +692,6 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, conn->printer = (strncmp(dev,"LPT",3) == 0); conn->ipc = ( (strncmp(dev,"IPC",3) == 0) || ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) ); - conn->dirptr = NULL; /* Case options for the share. */ if (lp_casesensitive(snum) == Auto) { @@ -712,7 +711,6 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, conn->hide_list = NULL; conn->veto_oplock_list = NULL; conn->aio_write_behind_list = NULL; - string_set(&conn->dirpath,""); conn->read_only = lp_readonly(SNUM(conn)); conn->admin_user = False; @@ -730,7 +728,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, fuser = talloc_string_sub(conn, lp_force_user(snum), "%S", lp_servicename(snum)); if (fuser == NULL) { - conn_free(sconn, conn); + conn_free(conn); *pstatus = NT_STATUS_NO_MEMORY; return NULL; } @@ -739,7 +737,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, conn, fuser, conn->server_info->guest, &forced_serverinfo); if (!NT_STATUS_IS_OK(status)) { - conn_free(sconn, conn); + conn_free(conn); *pstatus = status; return NULL; } @@ -764,7 +762,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, &conn->server_info->utok.gid); if (!NT_STATUS_IS_OK(status)) { - conn_free(sconn, conn); + conn_free(conn); *pstatus = status; return NULL; } @@ -790,14 +788,14 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, pdb_get_domain(conn->server_info->sam_account), lp_pathname(snum)); if (!s) { - conn_free(sconn, conn); + conn_free(conn); *pstatus = NT_STATUS_NO_MEMORY; return NULL; } if (!set_conn_connectpath(conn,s)) { TALLOC_FREE(s); - conn_free(sconn, conn); + conn_free(conn); *pstatus = NT_STATUS_NO_MEMORY; return NULL; } @@ -829,7 +827,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, "denied due to security " "descriptor.\n", lp_servicename(snum))); - conn_free(sconn, conn); + conn_free(conn); *pstatus = NT_STATUS_ACCESS_DENIED; return NULL; } else { @@ -842,7 +840,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, if (!smbd_vfs_init(conn)) { DEBUG(0, ("vfs_init failed for service %s\n", lp_servicename(snum))); - conn_free(sconn, conn); + conn_free(conn); *pstatus = NT_STATUS_BAD_NETWORK_NAME; return NULL; } @@ -860,7 +858,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, "for service %s, path %s\n", lp_servicename(snum), conn->connectpath)); - conn_free(sconn, conn); + conn_free(conn); *pstatus = NT_STATUS_BAD_NETWORK_NAME; return NULL; } @@ -884,7 +882,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, DEBUG(1, ("Max connections (%d) exceeded for %s\n", lp_max_connections(snum), lp_servicename(snum))); - conn_free(sconn, conn); + conn_free(conn); *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES; return NULL; } @@ -894,7 +892,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, */ if (!claim_connection(conn, lp_servicename(snum), 0)) { DEBUG(1, ("Could not store connections entry\n")); - conn_free(sconn, conn); + conn_free(conn); *pstatus = NT_STATUS_INTERNAL_DB_ERROR; return NULL; } @@ -918,7 +916,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, DEBUG(1,("root preexec gave %d - failing " "connection\n", ret)); yield_connection(conn, lp_servicename(snum)); - conn_free(sconn, conn); + conn_free(conn); *pstatus = NT_STATUS_ACCESS_DENIED; return NULL; } @@ -929,7 +927,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, /* No point continuing if they fail the basic checks */ DEBUG(0,("Can't become connected user!\n")); yield_connection(conn, lp_servicename(snum)); - conn_free(sconn, conn); + conn_free(conn); *pstatus = NT_STATUS_LOGON_FAILURE; return NULL; } @@ -1072,7 +1070,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, SMB_VFS_DISCONNECT(conn); } yield_connection(conn, lp_servicename(snum)); - conn_free(sconn, conn); + conn_free(conn); return NULL; } @@ -1219,8 +1217,7 @@ connection_struct *make_connection(struct smbd_server_connection *sconn, Close a cnum. ****************************************************************************/ -void close_cnum(struct smbd_server_connection *sconn, - connection_struct *conn, uint16 vuid) +void close_cnum(connection_struct *conn, uint16 vuid) { file_close_conn(conn); @@ -1274,5 +1271,5 @@ void close_cnum(struct smbd_server_connection *sconn, TALLOC_FREE(cmd); } - conn_free(sconn, conn); + conn_free(conn); } diff --git a/source3/smbd/smb2_tcon.c b/source3/smbd/smb2_tcon.c index 8c4b1f1b6f..090f9b7908 100644 --- a/source3/smbd/smb2_tcon.c +++ b/source3/smbd/smb2_tcon.c @@ -127,7 +127,7 @@ static int smbd_smb2_tcon_destructor(struct smbd_smb2_tcon *tcon) idr_remove(tcon->session->tcons.idtree, tcon->tid); DLIST_REMOVE(tcon->session->tcons.list, tcon); - conn_free(tcon->session->conn, tcon->compat_conn); + conn_free(tcon->compat_conn); tcon->compat_conn = NULL; tcon->tid = 0; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 184a858097..2e47eab4f0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1165,19 +1165,24 @@ static void call_trans2open(connection_struct *conn, Case can be significant or not. **********************************************************/ -static bool exact_match(connection_struct *conn, - const char *str, - const char *mask) +static bool exact_match(bool has_wild, + bool case_sensitive, + const char *str, + const char *mask) { - if (mask[0] == '.' && mask[1] == 0) - return False; - if (dptr_has_wild(conn->dirptr)) { - return False; + if (mask[0] == '.' && mask[1] == 0) { + return false; + } + + if (has_wild) { + return false; } - if (conn->case_sensitive) + + if (case_sensitive) { return strcmp(str,mask)==0; - else + } else { return StrCaseCmp(str,mask) == 0; + } } /**************************************************************************** @@ -1317,671 +1322,589 @@ static bool check_msdfs_link(connection_struct *conn, Get a level dependent lanman2 dir entry. ****************************************************************************/ -static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, - connection_struct *conn, - uint16 flags2, - const char *path_mask, - uint32 dirtype, - int info_level, - int requires_resume_key, - bool dont_descend, - bool ask_sharemode, - char **ppdata, - char *base_data, - char *end_data, - int space_remaining, - bool *out_of_space, - bool *got_exact_match, - int *last_entry_off, - struct ea_list *name_list) +struct smbd_dirptr_lanman2_state { + connection_struct *conn; + uint32_t info_level; + bool check_mangled_names; + bool has_wild; + bool got_exact_match; +}; + +static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx, + void *private_data, + const char *dname, + const char *mask, + char **_fname) { - char *dname; - bool found = False; - SMB_STRUCT_STAT sbuf; - const char *mask = NULL; - char *pathreal = NULL; - char *fname = NULL; - char *p, *q, *pdata = *ppdata; - uint32 reskey=0; - long prev_dirpos=0; - uint32 mode=0; - SMB_OFF_T file_size = 0; - uint64_t allocation_size = 0; - uint32 len; - struct timespec mdate_ts, adate_ts, create_date_ts; - time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0; - char *nameptr; - char *last_entry_ptr; - bool was_8_3; - uint32 nt_extmode; /* Used for NT connections instead of mode */ - bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/'); - bool check_mangled_names = lp_manglednames(conn->params); + struct smbd_dirptr_lanman2_state *state = + (struct smbd_dirptr_lanman2_state *)private_data; + bool ok; char mangled_name[13]; /* mangled 8.3 name. */ + bool got_match; + const char *fname; - *out_of_space = False; - *got_exact_match = False; - - ZERO_STRUCT(mdate_ts); - ZERO_STRUCT(adate_ts); - ZERO_STRUCT(create_date_ts); - - if (!conn->dirptr) { - return(False); - } - - p = strrchr_m(path_mask,'/'); - if(p != NULL) { - if(p[1] == '\0') { - mask = talloc_strdup(ctx,"*.*"); - } else { - mask = p+1; + /* Mangle fname if it's an illegal name. */ + if (mangle_must_mangle(dname, state->conn->params)) { + ok = name_to_8_3(dname, mangled_name, + true, state->conn->params); + if (!ok) { + return false; } + fname = mangled_name; } else { - mask = path_mask; + fname = dname; } - while (!found) { - bool got_match; - bool ms_dfs_link = False; - - /* Needed if we run out of space */ - long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr); - dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf); - - /* - * Due to bugs in NT client redirectors we are not using - * resume keys any more - set them to zero. - * Check out the related comments in findfirst/findnext. - * JRA. - */ - - reskey = 0; - - DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n", - (long)conn->dirptr,curr_dirpos)); - - if (!dname) { - return(False); - } + got_match = exact_match(state->has_wild, + state->conn->case_sensitive, + fname, mask); + state->got_exact_match = got_match; + if (!got_match) { + got_match = mask_match(fname, mask, + state->conn->case_sensitive); + } + if(!got_match && state->check_mangled_names && + !mangle_is_8_3(fname, false, state->conn->params)) { /* - * fname may get mangled, dname is never mangled. - * Whenever we're accessing the filesystem we use - * pathreal which is composed from dname. + * It turns out that NT matches wildcards against + * both long *and* short names. This may explain some + * of the wildcard wierdness from old DOS clients + * that some people have been seeing.... JRA. */ - - pathreal = NULL; - fname = dname; - - /* Mangle fname if it's an illegal name. */ - if (mangle_must_mangle(dname,conn->params)) { - if (!name_to_8_3(dname,mangled_name,True,conn->params)) { - TALLOC_FREE(fname); - continue; /* Error - couldn't mangle. */ - } - fname = talloc_strdup(ctx, mangled_name); - if (!fname) { - return False; - } + /* Force the mangling into 8.3. */ + ok = name_to_8_3(fname, mangled_name, + false, state->conn->params); + if (!ok) { + return false; } - if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) { - got_match = mask_match(fname, mask, conn->case_sensitive); + got_match = exact_match(state->has_wild, + state->conn->case_sensitive, + mangled_name, mask); + state->got_exact_match = got_match; + if (!got_match) { + got_match = mask_match(mangled_name, mask, + state->conn->case_sensitive); } + } - if(!got_match && check_mangled_names && - !mangle_is_8_3(fname, False, conn->params)) { - /* - * It turns out that NT matches wildcards against - * both long *and* short names. This may explain some - * of the wildcard wierdness from old DOS clients - * that some people have been seeing.... JRA. - */ - /* Force the mangling into 8.3. */ - if (!name_to_8_3( fname, mangled_name, False, conn->params)) { - TALLOC_FREE(fname); - continue; /* Error - couldn't mangle. */ - } - - if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) { - got_match = mask_match(mangled_name, mask, conn->case_sensitive); - } - } - - if (got_match) { - bool isdots = (ISDOT(dname) || ISDOTDOT(dname)); - struct smb_filename *smb_fname = NULL; - NTSTATUS status; - - if (dont_descend && !isdots) { - TALLOC_FREE(fname); - continue; - } - - if (needslash) { - pathreal = NULL; - pathreal = talloc_asprintf(ctx, - "%s/%s", - conn->dirpath, - dname); - } else { - pathreal = talloc_asprintf(ctx, - "%s%s", - conn->dirpath, - dname); - } - - if (!pathreal) { - TALLOC_FREE(fname); - return False; - } - - /* A dirent from dptr_ReadDirName isn't a stream. */ - status = create_synthetic_smb_fname(ctx, pathreal, - NULL, &sbuf, - &smb_fname); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(fname); - return false; - } + if (!got_match) { + return false; + } - if (INFO_LEVEL_IS_UNIX(info_level)) { - if (SMB_VFS_LSTAT(conn, smb_fname) != 0) { - DEBUG(5,("get_lanman2_dir_entry: " - "Couldn't lstat [%s] (%s)\n", - smb_fname_str_dbg(smb_fname), - strerror(errno))); - TALLOC_FREE(smb_fname); - TALLOC_FREE(pathreal); - TALLOC_FREE(fname); - continue; - } - } else if (!VALID_STAT(smb_fname->st) && - SMB_VFS_STAT(conn, smb_fname) != 0) { - /* Needed to show the msdfs symlinks as - * directories */ - - ms_dfs_link = - check_msdfs_link(conn, - smb_fname->base_name, - &smb_fname->st); - if (!ms_dfs_link) { - DEBUG(5,("get_lanman2_dir_entry: " - "Couldn't stat [%s] (%s)\n", - smb_fname_str_dbg(smb_fname), - strerror(errno))); - TALLOC_FREE(smb_fname); - TALLOC_FREE(pathreal); - TALLOC_FREE(fname); - continue; - } - } + *_fname = talloc_strdup(ctx, fname); + if (*_fname == NULL) { + return false; + } - if (ms_dfs_link) { - mode = dos_mode_msdfs(conn, smb_fname); - } else { - mode = dos_mode(conn, smb_fname); - } + return true; +} - if (!dir_check_ftype(conn,mode,dirtype)) { - DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype)); - TALLOC_FREE(smb_fname); - TALLOC_FREE(pathreal); - TALLOC_FREE(fname); - continue; - } +static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx, + void *private_data, + struct smb_filename *smb_fname, + uint32_t *_mode) +{ + struct smbd_dirptr_lanman2_state *state = + (struct smbd_dirptr_lanman2_state *)private_data; + bool ms_dfs_link = false; + uint32_t mode = 0; - if (!(mode & aDIR)) { - file_size = get_file_size_stat(&smb_fname->st); - } - allocation_size = - SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st); - - if (ask_sharemode) { - struct timespec write_time_ts; - struct file_id fileid; - - ZERO_STRUCT(write_time_ts); - fileid = vfs_file_id_from_sbuf(conn, - &smb_fname->st); - get_file_infos(fileid, NULL, &write_time_ts); - if (!null_timespec(write_time_ts)) { - update_stat_ex_mtime(&smb_fname->st, - write_time_ts); - } - } + if (INFO_LEVEL_IS_UNIX(state->info_level)) { + if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) { + DEBUG(5,("smbd_dirptr_lanman2_mode_fn: " + "Couldn't lstat [%s] (%s)\n", + smb_fname_str_dbg(smb_fname), + strerror(errno))); + return false; + } + } else if (!VALID_STAT(smb_fname->st) && + SMB_VFS_STAT(state->conn, smb_fname) != 0) { + /* Needed to show the msdfs symlinks as + * directories */ + + ms_dfs_link = check_msdfs_link(state->conn, + smb_fname->base_name, + &smb_fname->st); + if (!ms_dfs_link) { + DEBUG(5,("smbd_dirptr_lanman2_mode_fn: " + "Couldn't stat [%s] (%s)\n", + smb_fname_str_dbg(smb_fname), + strerror(errno))); + return false; + } + } - mdate_ts = smb_fname->st.st_ex_mtime; - adate_ts = smb_fname->st.st_ex_atime; - create_date_ts = smb_fname->st.st_ex_btime; + if (ms_dfs_link) { + mode = dos_mode_msdfs(state->conn, smb_fname); + } else { + mode = dos_mode(state->conn, smb_fname); + } - if (lp_dos_filetime_resolution(SNUM(conn))) { - dos_filetime_timespec(&create_date_ts); - dos_filetime_timespec(&mdate_ts); - dos_filetime_timespec(&adate_ts); - } + *_mode = mode; + return true; +} - create_date = convert_timespec_to_time_t(create_date_ts); - mdate = convert_timespec_to_time_t(mdate_ts); - adate = convert_timespec_to_time_t(adate_ts); +static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx, + connection_struct *conn, + uint16_t flags2, + uint32_t info_level, + struct ea_list *name_list, + bool check_mangled_names, + bool requires_resume_key, + uint32_t mode, + const char *fname, + const struct smb_filename *smb_fname, + uint64_t space_remaining, + char *base_data, + char **ppdata, + char *end_data, + bool *out_of_space, + uint64_t *last_entry_off) +{ + char *p, *q, *pdata = *ppdata; + uint32_t reskey=0; + uint64_t file_size = 0; + uint64_t allocation_size = 0; + uint32_t len; + struct timespec mdate_ts, adate_ts, create_date_ts; + time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0; + char *nameptr; + char *last_entry_ptr; + bool was_8_3; + uint32_t nt_extmode; /* Used for NT connections instead of mode */ - DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n", - smb_fname_str_dbg(smb_fname), fname)); + *out_of_space = false; - found = True; + ZERO_STRUCT(mdate_ts); + ZERO_STRUCT(adate_ts); + ZERO_STRUCT(create_date_ts); - dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos); - sbuf = smb_fname->st; + if (!(mode & aDIR)) { + file_size = get_file_size_stat(&smb_fname->st); + } + allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st); - TALLOC_FREE(smb_fname); - } + mdate_ts = smb_fname->st.st_ex_mtime; + adate_ts = smb_fname->st.st_ex_atime; + create_date_ts = smb_fname->st.st_ex_btime; - if (!found) - TALLOC_FREE(fname); + if (lp_dos_filetime_resolution(SNUM(conn))) { + dos_filetime_timespec(&create_date_ts); + dos_filetime_timespec(&mdate_ts); + dos_filetime_timespec(&adate_ts); } + create_date = convert_timespec_to_time_t(create_date_ts); + mdate = convert_timespec_to_time_t(mdate_ts); + adate = convert_timespec_to_time_t(adate_ts); + p = pdata; last_entry_ptr = p; nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL; switch (info_level) { - case SMB_FIND_INFO_STANDARD: - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n")); - if(requires_resume_key) { - SIVAL(p,0,reskey); - p += 4; - } - srv_put_dos_date2(p,0,create_date); - srv_put_dos_date2(p,4,adate); - srv_put_dos_date2(p,8,mdate); - SIVAL(p,12,(uint32)file_size); - SIVAL(p,16,(uint32)allocation_size); - SSVAL(p,20,mode); - p += 23; - nameptr = p; - if (flags2 & FLAGS2_UNICODE_STRINGS) { - p += ucs2_align(base_data, p, 0); - } - len = srvstr_push(base_data, flags2, p, - fname, PTR_DIFF(end_data, p), - STR_TERMINATE); - if (flags2 & FLAGS2_UNICODE_STRINGS) { - if (len > 2) { - SCVAL(nameptr, -1, len - 2); - } else { - SCVAL(nameptr, -1, 0); - } + case SMB_FIND_INFO_STANDARD: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n")); + if(requires_resume_key) { + SIVAL(p,0,reskey); + p += 4; + } + srv_put_dos_date2(p,0,create_date); + srv_put_dos_date2(p,4,adate); + srv_put_dos_date2(p,8,mdate); + SIVAL(p,12,(uint32)file_size); + SIVAL(p,16,(uint32)allocation_size); + SSVAL(p,20,mode); + p += 23; + nameptr = p; + if (flags2 & FLAGS2_UNICODE_STRINGS) { + p += ucs2_align(base_data, p, 0); + } + len = srvstr_push(base_data, flags2, p, + fname, PTR_DIFF(end_data, p), + STR_TERMINATE); + if (flags2 & FLAGS2_UNICODE_STRINGS) { + if (len > 2) { + SCVAL(nameptr, -1, len - 2); } else { - if (len > 1) { - SCVAL(nameptr, -1, len - 1); - } else { - SCVAL(nameptr, -1, 0); - } + SCVAL(nameptr, -1, 0); } - p += len; - break; - - case SMB_FIND_EA_SIZE: - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n")); - if(requires_resume_key) { - SIVAL(p,0,reskey); - p += 4; - } - srv_put_dos_date2(p,0,create_date); - srv_put_dos_date2(p,4,adate); - srv_put_dos_date2(p,8,mdate); - SIVAL(p,12,(uint32)file_size); - SIVAL(p,16,(uint32)allocation_size); - SSVAL(p,20,mode); - { - unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal); - SIVAL(p,22,ea_size); /* Extended attributes */ - } - p += 27; - nameptr = p - 1; - len = srvstr_push(base_data, flags2, - p, fname, PTR_DIFF(end_data, p), - STR_TERMINATE | STR_NOALIGN); - if (flags2 & FLAGS2_UNICODE_STRINGS) { - if (len > 2) { - len -= 2; - } else { - len = 0; - } + } else { + if (len > 1) { + SCVAL(nameptr, -1, len - 1); } else { - if (len > 1) { - len -= 1; - } else { - len = 0; - } + SCVAL(nameptr, -1, 0); } - SCVAL(nameptr,0,len); - p += len; - SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */ - break; + } + p += len; + break; - case SMB_FIND_EA_LIST: + case SMB_FIND_EA_SIZE: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n")); + if (requires_resume_key) { + SIVAL(p,0,reskey); + p += 4; + } + srv_put_dos_date2(p,0,create_date); + srv_put_dos_date2(p,4,adate); + srv_put_dos_date2(p,8,mdate); + SIVAL(p,12,(uint32)file_size); + SIVAL(p,16,(uint32)allocation_size); + SSVAL(p,20,mode); { - struct ea_list *file_list = NULL; - size_t ea_len = 0; - - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n")); - if (!name_list) { - return False; - } - if(requires_resume_key) { - SIVAL(p,0,reskey); - p += 4; - } - srv_put_dos_date2(p,0,create_date); - srv_put_dos_date2(p,4,adate); - srv_put_dos_date2(p,8,mdate); - SIVAL(p,12,(uint32)file_size); - SIVAL(p,16,(uint32)allocation_size); - SSVAL(p,20,mode); - p += 22; /* p now points to the EA area. */ - - file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len); - name_list = ea_list_union(name_list, file_list, &ea_len); - - /* We need to determine if this entry will fit in the space available. */ - /* Max string size is 255 bytes. */ - if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) { - /* Move the dirptr back to prev_dirpos */ - dptr_SeekDir(conn->dirptr, prev_dirpos); - *out_of_space = True; - DEBUG(9,("get_lanman2_dir_entry: out of space\n")); - return False; /* Not finished - just out of space */ + unsigned int ea_size = estimate_ea_size(conn, NULL, + smb_fname->base_name); + SIVAL(p,22,ea_size); /* Extended attributes */ + } + p += 27; + nameptr = p - 1; + len = srvstr_push(base_data, flags2, + p, fname, PTR_DIFF(end_data, p), + STR_TERMINATE | STR_NOALIGN); + if (flags2 & FLAGS2_UNICODE_STRINGS) { + if (len > 2) { + len -= 2; + } else { + len = 0; } - - /* Push the ea_data followed by the name. */ - p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list); - nameptr = p; - len = srvstr_push(base_data, flags2, - p + 1, fname, PTR_DIFF(end_data, p+1), - STR_TERMINATE | STR_NOALIGN); - if (flags2 & FLAGS2_UNICODE_STRINGS) { - if (len > 2) { - len -= 2; - } else { - len = 0; - } + } else { + if (len > 1) { + len -= 1; } else { - if (len > 1) { - len -= 1; - } else { - len = 0; - } + len = 0; } - SCVAL(nameptr,0,len); - p += len + 1; - SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */ - break; } + SCVAL(nameptr,0,len); + p += len; + SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */ + break; - case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n")); - was_8_3 = mangle_is_8_3(fname, True, conn->params); + case SMB_FIND_EA_LIST: + { + struct ea_list *file_list = NULL; + size_t ea_len = 0; + + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n")); + if (!name_list) { + return false; + } + if (requires_resume_key) { + SIVAL(p,0,reskey); p += 4; - SIVAL(p,0,reskey); p += 4; - put_long_date_timespec(p,create_date_ts); p += 8; - put_long_date_timespec(p,adate_ts); p += 8; - put_long_date_timespec(p,mdate_ts); p += 8; - put_long_date_timespec(p,mdate_ts); p += 8; - SOFF_T(p,0,file_size); p += 8; - SOFF_T(p,0,allocation_size); p += 8; - SIVAL(p,0,nt_extmode); p += 4; - q = p; p += 4; /* q is placeholder for name length. */ - { - unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal); - SIVAL(p,0,ea_size); /* Extended attributes */ - p += 4; + } + srv_put_dos_date2(p,0,create_date); + srv_put_dos_date2(p,4,adate); + srv_put_dos_date2(p,8,mdate); + SIVAL(p,12,(uint32)file_size); + SIVAL(p,16,(uint32)allocation_size); + SSVAL(p,20,mode); + p += 22; /* p now points to the EA area. */ + + file_list = get_ea_list_from_file(ctx, conn, NULL, + smb_fname->base_name, + &ea_len); + name_list = ea_list_union(name_list, file_list, &ea_len); + + /* We need to determine if this entry will fit in the space available. */ + /* Max string size is 255 bytes. */ + if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) { + *out_of_space = true; + DEBUG(9,("get_lanman2_dir_entry: out of space\n")); + return False; /* Not finished - just out of space */ + } + + /* Push the ea_data followed by the name. */ + p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list); + nameptr = p; + len = srvstr_push(base_data, flags2, + p + 1, fname, PTR_DIFF(end_data, p+1), + STR_TERMINATE | STR_NOALIGN); + if (flags2 & FLAGS2_UNICODE_STRINGS) { + if (len > 2) { + len -= 2; + } else { + len = 0; } - /* Clear the short name buffer. This is - * IMPORTANT as not doing so will trigger - * a Win2k client bug. JRA. - */ - if (!was_8_3 && check_mangled_names) { - if (!name_to_8_3(fname,mangled_name,True, - conn->params)) { - /* Error - mangle failed ! */ - memset(mangled_name,'\0',12); - } - mangled_name[12] = 0; - len = srvstr_push(base_data, flags2, - p+2, mangled_name, 24, - STR_UPPER|STR_UNICODE); - if (len < 24) { - memset(p + 2 + len,'\0',24 - len); - } - SSVAL(p, 0, len); + } else { + if (len > 1) { + len -= 1; } else { - memset(p,'\0',26); + len = 0; } - p += 2 + 24; - len = srvstr_push(base_data, flags2, p, - fname, PTR_DIFF(end_data, p), - STR_TERMINATE_ASCII); - SIVAL(q,0,len); - p += len; - SIVAL(p,0,0); /* Ensure any padding is null. */ - len = PTR_DIFF(p, pdata); - len = (len + 3) & ~3; - SIVAL(pdata,0,len); - p = pdata + len; - break; + } + SCVAL(nameptr,0,len); + p += len + 1; + SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */ + break; + } - case SMB_FIND_FILE_DIRECTORY_INFO: - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n")); + case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n")); + was_8_3 = mangle_is_8_3(fname, True, conn->params); + p += 4; + SIVAL(p,0,reskey); p += 4; + put_long_date_timespec(p,create_date_ts); p += 8; + put_long_date_timespec(p,adate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; + SOFF_T(p,0,file_size); p += 8; + SOFF_T(p,0,allocation_size); p += 8; + SIVAL(p,0,nt_extmode); p += 4; + q = p; p += 4; /* q is placeholder for name length. */ + { + unsigned int ea_size = estimate_ea_size(conn, NULL, + smb_fname->base_name); + SIVAL(p,0,ea_size); /* Extended attributes */ p += 4; - SIVAL(p,0,reskey); p += 4; - put_long_date_timespec(p,create_date_ts); p += 8; - put_long_date_timespec(p,adate_ts); p += 8; - put_long_date_timespec(p,mdate_ts); p += 8; - put_long_date_timespec(p,mdate_ts); p += 8; - SOFF_T(p,0,file_size); p += 8; - SOFF_T(p,0,allocation_size); p += 8; - SIVAL(p,0,nt_extmode); p += 4; + } + /* Clear the short name buffer. This is + * IMPORTANT as not doing so will trigger + * a Win2k client bug. JRA. + */ + if (!was_8_3 && check_mangled_names) { + char mangled_name[13]; /* mangled 8.3 name. */ + if (!name_to_8_3(fname,mangled_name,True, + conn->params)) { + /* Error - mangle failed ! */ + memset(mangled_name,'\0',12); + } + mangled_name[12] = 0; len = srvstr_push(base_data, flags2, - p + 4, fname, PTR_DIFF(end_data, p+4), - STR_TERMINATE_ASCII); - SIVAL(p,0,len); - p += 4 + len; - SIVAL(p,0,0); /* Ensure any padding is null. */ - len = PTR_DIFF(p, pdata); - len = (len + 3) & ~3; - SIVAL(pdata,0,len); - p = pdata + len; - break; - - case SMB_FIND_FILE_FULL_DIRECTORY_INFO: - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n")); - p += 4; - SIVAL(p,0,reskey); p += 4; - put_long_date_timespec(p,create_date_ts); p += 8; - put_long_date_timespec(p,adate_ts); p += 8; - put_long_date_timespec(p,mdate_ts); p += 8; - put_long_date_timespec(p,mdate_ts); p += 8; - SOFF_T(p,0,file_size); p += 8; - SOFF_T(p,0,allocation_size); p += 8; - SIVAL(p,0,nt_extmode); p += 4; - q = p; p += 4; /* q is placeholder for name length. */ - { - unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal); - SIVAL(p,0,ea_size); /* Extended attributes */ - p +=4; + p+2, mangled_name, 24, + STR_UPPER|STR_UNICODE); + if (len < 24) { + memset(p + 2 + len,'\0',24 - len); } - len = srvstr_push(base_data, flags2, p, - fname, PTR_DIFF(end_data, p), - STR_TERMINATE_ASCII); - SIVAL(q, 0, len); - p += len; + SSVAL(p, 0, len); + } else { + memset(p,'\0',26); + } + p += 2 + 24; + len = srvstr_push(base_data, flags2, p, + fname, PTR_DIFF(end_data, p), + STR_TERMINATE_ASCII); + SIVAL(q,0,len); + p += len; + SIVAL(p,0,0); /* Ensure any padding is null. */ + len = PTR_DIFF(p, pdata); + len = (len + 3) & ~3; + SIVAL(pdata,0,len); + p = pdata + len; + break; - SIVAL(p,0,0); /* Ensure any padding is null. */ - len = PTR_DIFF(p, pdata); - len = (len + 3) & ~3; - SIVAL(pdata,0,len); - p = pdata + len; - break; + case SMB_FIND_FILE_DIRECTORY_INFO: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n")); + p += 4; + SIVAL(p,0,reskey); p += 4; + put_long_date_timespec(p,create_date_ts); p += 8; + put_long_date_timespec(p,adate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; + SOFF_T(p,0,file_size); p += 8; + SOFF_T(p,0,allocation_size); p += 8; + SIVAL(p,0,nt_extmode); p += 4; + len = srvstr_push(base_data, flags2, + p + 4, fname, PTR_DIFF(end_data, p+4), + STR_TERMINATE_ASCII); + SIVAL(p,0,len); + p += 4 + len; + SIVAL(p,0,0); /* Ensure any padding is null. */ + len = PTR_DIFF(p, pdata); + len = (len + 3) & ~3; + SIVAL(pdata,0,len); + p = pdata + len; + break; - case SMB_FIND_FILE_NAMES_INFO: - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n")); - p += 4; - SIVAL(p,0,reskey); p += 4; - p += 4; - /* this must *not* be null terminated or w2k gets in a loop trying to set an - acl on a dir (tridge) */ - len = srvstr_push(base_data, flags2, p, - fname, PTR_DIFF(end_data, p), - STR_TERMINATE_ASCII); - SIVAL(p, -4, len); - p += len; - SIVAL(p,0,0); /* Ensure any padding is null. */ - len = PTR_DIFF(p, pdata); - len = (len + 3) & ~3; - SIVAL(pdata,0,len); - p = pdata + len; - break; + case SMB_FIND_FILE_FULL_DIRECTORY_INFO: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n")); + p += 4; + SIVAL(p,0,reskey); p += 4; + put_long_date_timespec(p,create_date_ts); p += 8; + put_long_date_timespec(p,adate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; + SOFF_T(p,0,file_size); p += 8; + SOFF_T(p,0,allocation_size); p += 8; + SIVAL(p,0,nt_extmode); p += 4; + q = p; p += 4; /* q is placeholder for name length. */ + { + unsigned int ea_size = estimate_ea_size(conn, NULL, + smb_fname->base_name); + SIVAL(p,0,ea_size); /* Extended attributes */ + p +=4; + } + len = srvstr_push(base_data, flags2, p, + fname, PTR_DIFF(end_data, p), + STR_TERMINATE_ASCII); + SIVAL(q, 0, len); + p += len; + + SIVAL(p,0,0); /* Ensure any padding is null. */ + len = PTR_DIFF(p, pdata); + len = (len + 3) & ~3; + SIVAL(pdata,0,len); + p = pdata + len; + break; - case SMB_FIND_ID_FULL_DIRECTORY_INFO: - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n")); - p += 4; - SIVAL(p,0,reskey); p += 4; - put_long_date_timespec(p,create_date_ts); p += 8; - put_long_date_timespec(p,adate_ts); p += 8; - put_long_date_timespec(p,mdate_ts); p += 8; - put_long_date_timespec(p,mdate_ts); p += 8; - SOFF_T(p,0,file_size); p += 8; - SOFF_T(p,0,allocation_size); p += 8; - SIVAL(p,0,nt_extmode); p += 4; - q = p; p += 4; /* q is placeholder for name length. */ - { - unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal); - SIVAL(p,0,ea_size); /* Extended attributes */ - p +=4; - } - SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */ - SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */ - SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */ - len = srvstr_push(base_data, flags2, p, - fname, PTR_DIFF(end_data, p), - STR_TERMINATE_ASCII); - SIVAL(q, 0, len); - p += len; - SIVAL(p,0,0); /* Ensure any padding is null. */ - len = PTR_DIFF(p, pdata); - len = (len + 3) & ~3; - SIVAL(pdata,0,len); - p = pdata + len; - break; + case SMB_FIND_FILE_NAMES_INFO: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n")); + p += 4; + SIVAL(p,0,reskey); p += 4; + p += 4; + /* this must *not* be null terminated or w2k gets in a loop trying to set an + acl on a dir (tridge) */ + len = srvstr_push(base_data, flags2, p, + fname, PTR_DIFF(end_data, p), + STR_TERMINATE_ASCII); + SIVAL(p, -4, len); + p += len; + SIVAL(p,0,0); /* Ensure any padding is null. */ + len = PTR_DIFF(p, pdata); + len = (len + 3) & ~3; + SIVAL(pdata,0,len); + p = pdata + len; + break; - case SMB_FIND_ID_BOTH_DIRECTORY_INFO: - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n")); - was_8_3 = mangle_is_8_3(fname, True, conn->params); - p += 4; - SIVAL(p,0,reskey); p += 4; - put_long_date_timespec(p,create_date_ts); p += 8; - put_long_date_timespec(p,adate_ts); p += 8; - put_long_date_timespec(p,mdate_ts); p += 8; - put_long_date_timespec(p,mdate_ts); p += 8; - SOFF_T(p,0,file_size); p += 8; - SOFF_T(p,0,allocation_size); p += 8; - SIVAL(p,0,nt_extmode); p += 4; - q = p; p += 4; /* q is placeholder for name length */ - { - unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal); - SIVAL(p,0,ea_size); /* Extended attributes */ - p +=4; - } - /* Clear the short name buffer. This is - * IMPORTANT as not doing so will trigger - * a Win2k client bug. JRA. - */ - if (!was_8_3 && check_mangled_names) { - if (!name_to_8_3(fname,mangled_name,True, - conn->params)) { - /* Error - mangle failed ! */ - memset(mangled_name,'\0',12); - } - mangled_name[12] = 0; - len = srvstr_push(base_data, flags2, - p+2, mangled_name, 24, - STR_UPPER|STR_UNICODE); - SSVAL(p, 0, len); - if (len < 24) { - memset(p + 2 + len,'\0',24 - len); - } - SSVAL(p, 0, len); - } else { - memset(p,'\0',26); + case SMB_FIND_ID_FULL_DIRECTORY_INFO: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n")); + p += 4; + SIVAL(p,0,reskey); p += 4; + put_long_date_timespec(p,create_date_ts); p += 8; + put_long_date_timespec(p,adate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; + SOFF_T(p,0,file_size); p += 8; + SOFF_T(p,0,allocation_size); p += 8; + SIVAL(p,0,nt_extmode); p += 4; + q = p; p += 4; /* q is placeholder for name length. */ + { + unsigned int ea_size = estimate_ea_size(conn, NULL, + smb_fname->base_name); + SIVAL(p,0,ea_size); /* Extended attributes */ + p +=4; + } + SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */ + SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */ + SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */ + len = srvstr_push(base_data, flags2, p, + fname, PTR_DIFF(end_data, p), + STR_TERMINATE_ASCII); + SIVAL(q, 0, len); + p += len; + SIVAL(p,0,0); /* Ensure any padding is null. */ + len = PTR_DIFF(p, pdata); + len = (len + 3) & ~3; + SIVAL(pdata,0,len); + p = pdata + len; + break; + + case SMB_FIND_ID_BOTH_DIRECTORY_INFO: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n")); + was_8_3 = mangle_is_8_3(fname, True, conn->params); + p += 4; + SIVAL(p,0,reskey); p += 4; + put_long_date_timespec(p,create_date_ts); p += 8; + put_long_date_timespec(p,adate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; + SOFF_T(p,0,file_size); p += 8; + SOFF_T(p,0,allocation_size); p += 8; + SIVAL(p,0,nt_extmode); p += 4; + q = p; p += 4; /* q is placeholder for name length */ + { + unsigned int ea_size = estimate_ea_size(conn, NULL, + smb_fname->base_name); + SIVAL(p,0,ea_size); /* Extended attributes */ + p +=4; + } + /* Clear the short name buffer. This is + * IMPORTANT as not doing so will trigger + * a Win2k client bug. JRA. + */ + if (!was_8_3 && check_mangled_names) { + char mangled_name[13]; /* mangled 8.3 name. */ + if (!name_to_8_3(fname,mangled_name,True, + conn->params)) { + /* Error - mangle failed ! */ + memset(mangled_name,'\0',12); + } + mangled_name[12] = 0; + len = srvstr_push(base_data, flags2, + p+2, mangled_name, 24, + STR_UPPER|STR_UNICODE); + SSVAL(p, 0, len); + if (len < 24) { + memset(p + 2 + len,'\0',24 - len); } - p += 26; - SSVAL(p,0,0); p += 2; /* Reserved ? */ - SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */ - SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */ - len = srvstr_push(base_data, flags2, p, - fname, PTR_DIFF(end_data, p), - STR_TERMINATE_ASCII); - SIVAL(q,0,len); - p += len; - SIVAL(p,0,0); /* Ensure any padding is null. */ - len = PTR_DIFF(p, pdata); - len = (len + 3) & ~3; - SIVAL(pdata,0,len); - p = pdata + len; - break; + SSVAL(p, 0, len); + } else { + memset(p,'\0',26); + } + p += 26; + SSVAL(p,0,0); p += 2; /* Reserved ? */ + SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */ + SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */ + len = srvstr_push(base_data, flags2, p, + fname, PTR_DIFF(end_data, p), + STR_TERMINATE_ASCII); + SIVAL(q,0,len); + p += len; + SIVAL(p,0,0); /* Ensure any padding is null. */ + len = PTR_DIFF(p, pdata); + len = (len + 3) & ~3; + SIVAL(pdata,0,len); + p = pdata + len; + break; - /* CIFS UNIX Extension. */ + /* CIFS UNIX Extension. */ - case SMB_FIND_FILE_UNIX: - case SMB_FIND_FILE_UNIX_INFO2: - p+= 4; - SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */ + case SMB_FIND_FILE_UNIX: + case SMB_FIND_FILE_UNIX_INFO2: + p+= 4; + SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */ - /* Begin of SMB_QUERY_FILE_UNIX_BASIC */ + /* Begin of SMB_QUERY_FILE_UNIX_BASIC */ - if (info_level == SMB_FIND_FILE_UNIX) { - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n")); - p = store_file_unix_basic(conn, p, - NULL, &sbuf); - len = srvstr_push(base_data, flags2, p, - fname, PTR_DIFF(end_data, p), - STR_TERMINATE); - } else { - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n")); - p = store_file_unix_basic_info2(conn, p, - NULL, &sbuf); - nameptr = p; - p += 4; - len = srvstr_push(base_data, flags2, p, fname, - PTR_DIFF(end_data, p), 0); - SIVAL(nameptr, 0, len); - } + if (info_level == SMB_FIND_FILE_UNIX) { + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n")); + p = store_file_unix_basic(conn, p, + NULL, &smb_fname->st); + len = srvstr_push(base_data, flags2, p, + fname, PTR_DIFF(end_data, p), + STR_TERMINATE); + } else { + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n")); + p = store_file_unix_basic_info2(conn, p, + NULL, &smb_fname->st); + nameptr = p; + p += 4; + len = srvstr_push(base_data, flags2, p, fname, + PTR_DIFF(end_data, p), 0); + SIVAL(nameptr, 0, len); + } - p += len; - SIVAL(p,0,0); /* Ensure any padding is null. */ + p += len; + SIVAL(p,0,0); /* Ensure any padding is null. */ - len = PTR_DIFF(p, pdata); - len = (len + 3) & ~3; - SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */ - p = pdata + len; - /* End of SMB_QUERY_FILE_UNIX_BASIC */ + len = PTR_DIFF(p, pdata); + len = (len + 3) & ~3; + SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */ + p = pdata + len; + /* End of SMB_QUERY_FILE_UNIX_BASIC */ - break; + break; - default: - TALLOC_FREE(fname); - return(False); + default: + return false; } - TALLOC_FREE(fname); if (PTR_DIFF(p,pdata) > space_remaining) { - /* Move the dirptr back to prev_dirpos */ - dptr_SeekDir(conn->dirptr, prev_dirpos); - *out_of_space = True; + *out_of_space = true; DEBUG(9,("get_lanman2_dir_entry: out of space\n")); - return False; /* Not finished - just out of space */ + return false; /* Not finished - just out of space */ } /* Setup the last entry pointer, as an offset from base_data */ @@ -1989,7 +1912,106 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, /* Advance the data pointer to the next slot */ *ppdata = p; - return(found); + return true; +} + +static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, + connection_struct *conn, + struct dptr_struct *dirptr, + uint16 flags2, + const char *path_mask, + uint32 dirtype, + int info_level, + int requires_resume_key, + bool dont_descend, + bool ask_sharemode, + char **ppdata, + char *base_data, + char *end_data, + int space_remaining, + bool *out_of_space, + bool *got_exact_match, + int *_last_entry_off, + struct ea_list *name_list) +{ + const char *p; + const char *mask = NULL; + long prev_dirpos = 0; + uint32_t mode = 0; + char *fname = NULL; + struct smb_filename *smb_fname = NULL; + struct smbd_dirptr_lanman2_state state; + bool ok; + uint64_t last_entry_off = 0; + + ZERO_STRUCT(state); + state.conn = conn; + state.info_level = info_level; + state.check_mangled_names = lp_manglednames(conn->params); + state.has_wild = dptr_has_wild(dirptr); + state.got_exact_match = false; + + *out_of_space = false; + *got_exact_match = false; + + p = strrchr_m(path_mask,'/'); + if(p != NULL) { + if(p[1] == '\0') { + mask = "*.*"; + } else { + mask = p+1; + } + } else { + mask = path_mask; + } + + ok = smbd_dirptr_get_entry(ctx, + dirptr, + mask, + dirtype, + dont_descend, + ask_sharemode, + smbd_dirptr_lanman2_match_fn, + smbd_dirptr_lanman2_mode_fn, + &state, + &fname, + &smb_fname, + &mode, + &prev_dirpos); + if (!ok) { + return false; + } + + *got_exact_match = state.got_exact_match; + + ok = smbd_marshall_dir_entry(ctx, + conn, + flags2, + info_level, + name_list, + state.check_mangled_names, + requires_resume_key, + mode, + fname, + smb_fname, + space_remaining, + base_data, + ppdata, + end_data, + out_of_space, + &last_entry_off); + TALLOC_FREE(fname); + TALLOC_FREE(smb_fname); + if (*out_of_space) { + dptr_SeekDir(dirptr, prev_dirpos); + return false; + } + if (!ok) { + return false; + } + + *_last_entry_off = last_entry_off; + return true; } /**************************************************************************** @@ -2034,6 +2056,8 @@ static void call_trans2findfirst(connection_struct *conn, NTSTATUS ntstatus = NT_STATUS_OK; bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true); TALLOC_CTX *ctx = talloc_tos(); + struct dptr_struct *dirptr = NULL; + struct smbd_server_connection *sconn = smbd_server_conn; if (total_params < 13) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); @@ -2191,24 +2215,25 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd mask, mask_contains_wcard, dirtype, - &conn->dirptr); + &dirptr); if (!NT_STATUS_IS_OK(ntstatus)) { reply_nterror(req, ntstatus); goto out; } - dptr_num = dptr_dnum(conn->dirptr); + dptr_num = dptr_dnum(dirptr); DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype)); /* Initialize per TRANS2_FIND_FIRST operation data */ - dptr_init_search_op(conn->dirptr); + dptr_init_search_op(dirptr); /* We don't need to check for VOL here as this is returned by a different TRANS2 call. */ - DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn)))); - if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive)) + DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", + directory,lp_dontdescend(SNUM(conn)))); + if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive)) dont_descend = True; p = pdata; @@ -2226,6 +2251,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } else { finished = !get_lanman2_dir_entry(ctx, conn, + dirptr, req->flags2, mask,dirtype,info_level, requires_resume_key,dont_descend, @@ -2264,7 +2290,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd /* Check if we can close the dirptr */ if(close_after_first || (finished && close_if_end)) { DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num)); - dptr_close(&dptr_num); + dptr_close(sconn, &dptr_num); } /* @@ -2275,7 +2301,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd */ if(numentries == 0) { - dptr_close(&dptr_num); + dptr_close(sconn, &dptr_num); if (Protocol < PROTOCOL_NT1) { reply_doserror(req, ERRDOS, ERRnofiles); goto out; @@ -2298,8 +2324,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes); - if ((! *directory) && dptr_path(dptr_num)) { - directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num)); + if ((! *directory) && dptr_path(sconn, dptr_num)) { + directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num)); if (!directory) { reply_nterror(req, NT_STATUS_NO_MEMORY); } @@ -2369,6 +2395,8 @@ static void call_trans2findnext(connection_struct *conn, NTSTATUS ntstatus = NT_STATUS_OK; bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true); TALLOC_CTX *ctx = talloc_tos(); + struct dptr_struct *dirptr; + struct smbd_server_connection *sconn = smbd_server_conn; if (total_params < 13) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); @@ -2490,39 +2518,39 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd params = *pparams; /* Check that the dptr is valid */ - if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) { + if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) { reply_doserror(req, ERRDOS, ERRnofiles); return; } - string_set(&conn->dirpath,dptr_path(dptr_num)); + directory = dptr_path(sconn, dptr_num); /* Get the wildcard mask from the dptr */ - if((p = dptr_wcard(dptr_num))== NULL) { + if((p = dptr_wcard(sconn, dptr_num))== NULL) { DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num)); reply_doserror(req, ERRDOS, ERRnofiles); return; } mask = p; - directory = conn->dirpath; /* Get the attr mask from the dptr */ - dirtype = dptr_attr(dptr_num); + dirtype = dptr_attr(sconn, dptr_num); DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n", dptr_num, mask, dirtype, - (long)conn->dirptr, - dptr_TellDir(conn->dirptr))); + (long)dirptr, + dptr_TellDir(dirptr))); /* Initialize per TRANS2_FIND_NEXT operation data */ - dptr_init_search_op(conn->dirptr); + dptr_init_search_op(dirptr); /* We don't need to check for VOL here as this is returned by a different TRANS2 call. */ - DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn)))); - if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive)) + DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", + directory,lp_dontdescend(SNUM(conn)))); + if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive)) dont_descend = True; p = pdata; @@ -2564,7 +2592,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd * should already be at the correct place. */ - finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st); + finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st); } /* end if resume_name && !continue_bit */ for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) { @@ -2578,6 +2606,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } else { finished = !get_lanman2_dir_entry(ctx, conn, + dirptr, req->flags2, mask,dirtype,info_level, requires_resume_key,dont_descend, @@ -2614,7 +2643,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd /* Check if we can close the dirptr */ if(close_after_request || (finished && close_if_end)) { DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num)); - dptr_close(&dptr_num); /* This frees up the saved mask */ + dptr_close(sconn, &dptr_num); /* This frees up the saved mask */ } /* Set up the return parameter block */ @@ -5193,9 +5222,8 @@ NTSTATUS smb_set_file_time(connection_struct *conn, struct smb_filename *smb_fname_base = NULL; uint32 action = FILE_NOTIFY_CHANGE_LAST_ACCESS - |FILE_NOTIFY_CHANGE_LAST_WRITE; - bool set_createtime = false; - bool set_ctime = false; + |FILE_NOTIFY_CHANGE_LAST_WRITE + |FILE_NOTIFY_CHANGE_CREATION; NTSTATUS status; if (!VALID_STAT(smb_fname->st)) { @@ -5204,24 +5232,14 @@ NTSTATUS smb_set_file_time(connection_struct *conn, /* get some defaults (no modifications) if any info is zero or -1. */ if (null_timespec(ft->create_time)) { - ft->create_time = smb_fname->st.st_ex_btime; - } else { - set_createtime = true; - } - - if (null_timespec(ft->ctime)) { - ft->ctime = smb_fname->st.st_ex_ctime; - } else { - set_ctime = true; + action &= ~FILE_NOTIFY_CHANGE_CREATION; } if (null_timespec(ft->atime)) { - ft->atime= smb_fname->st.st_ex_atime; action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS; } if (null_timespec(ft->mtime)) { - ft->mtime = smb_fname->st.st_ex_mtime; action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE; } @@ -5239,24 +5257,6 @@ NTSTATUS smb_set_file_time(connection_struct *conn, DEBUG(5,("smb_set_file_time: createtime: %s\n ", time_to_asc(convert_timespec_to_time_t(ft->create_time)))); - /* - * Try and set the times of this file if - * they are different from the current values. - */ - - { - struct timespec mts = smb_fname->st.st_ex_mtime; - struct timespec ats = smb_fname->st.st_ex_atime; - if ((timespec_compare(&ft->atime, &ats) == 0) && - (timespec_compare(&ft->mtime, &mts) == 0)) { - if (set_createtime || set_ctime) { - notify_fname(conn, NOTIFY_ACTION_MODIFIED, FILE_NOTIFY_CHANGE_LAST_WRITE, - smb_fname->base_name); - } - return NT_STATUS_OK; - } - } - if (setting_write_time) { /* * This was a Windows setfileinfo on an open file. @@ -6110,6 +6110,41 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn, } /**************************************************************************** + Deal with SMB_INFO_STANDARD. +****************************************************************************/ + +static NTSTATUS smb_set_info_standard(connection_struct *conn, + const char *pdata, + int total_data, + files_struct *fsp, + const struct smb_filename *smb_fname) +{ + struct smb_file_time ft; + + ZERO_STRUCT(ft); + + if (total_data < 12) { + return NT_STATUS_INVALID_PARAMETER; + } + + /* create time */ + ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata)); + /* access time */ + ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4)); + /* write time */ + ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8)); + + DEBUG(10,("smb_set_info_standard: file %s\n", + smb_fname_str_dbg(smb_fname))); + + return smb_set_file_time(conn, + fsp, + smb_fname, + &ft, + true); +} + +/**************************************************************************** Deal with SMB_SET_FILE_ALLOCATION_INFO. ****************************************************************************/ @@ -7086,6 +7121,16 @@ NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn, switch (info_level) { + case SMB_INFO_STANDARD: + { + status = smb_set_info_standard(conn, + pdata, + total_data, + fsp, + smb_fname); + break; + } + case SMB_INFO_SET_EA: { status = smb_info_set_ea(conn, @@ -7818,6 +7863,7 @@ static void call_trans2ioctl(connection_struct *conn, void reply_findclose(struct smb_request *req) { int dptr_num; + struct smbd_server_connection *sconn = smbd_server_conn; START_PROFILE(SMBfindclose); @@ -7831,7 +7877,7 @@ void reply_findclose(struct smb_request *req) DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num)); - dptr_close(&dptr_num); + dptr_close(sconn, &dptr_num); reply_outbuf(req, 0, 0); |