Ignore:
Timestamp:
Nov 24, 2016, 1:14:11 PM (9 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: update vendor to version 4.4.3

File:
1 edited

Legend:

Unmodified
Added
Removed
  • vendor/current/source3/smbd/dir.c

    r919 r988  
    2525#include "libcli/security/security.h"
    2626#include "lib/util/bitmap.h"
     27#include "../lib/util/memcache.h"
     28#include "../librpc/gen_ndr/open_files.h"
    2729
    2830/*
     
    3537#define DOT_DOT_DIRECTORY_OFFSET ((long)0x80000000)
    3638
     39/* "Special" directory offsets in 32-bit wire format. */
     40#define WIRE_END_OF_DIRECTORY_OFFSET ((uint32_t)0xFFFFFFFF)
     41#define WIRE_START_OF_DIRECTORY_OFFSET ((uint32_t)0)
     42#define WIRE_DOT_DOT_DIRECTORY_OFFSET ((uint32_t)0x80000000)
     43
    3744/* Make directory handle internals available. */
    3845
     
    4451struct smb_Dir {
    4552        connection_struct *conn;
    46         SMB_STRUCT_DIR *dir;
     53        DIR *dir;
    4754        long offset;
    4855        char *dir_path;
     
    5865        struct dptr_struct *next, *prev;
    5966        int dnum;
    60         uint16 spid;
     67        uint16_t spid;
    6168        struct connection_struct *conn;
    6269        struct smb_Dir *dir_hnd;
    6370        bool expect_close;
    6471        char *wcard;
    65         uint32 attr;
     72        uint32_t attr;
    6673        char *path;
    6774        bool has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */
    6875        bool did_stat; /* Optimisation for non-wcard searches. */
     76        bool priv;     /* Directory handle opened with privilege. */
     77        uint32_t counter;
     78        struct memcache *dptr_cache;
    6979};
    7080
     
    7282                        files_struct *fsp,
    7383                        const char *mask,
    74                         uint32 attr);
     84                        uint32_t attr);
     85
     86static void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset);
    7587
    7688#define INVALID_DPTR_KEY (-3)
    77 
    78 /****************************************************************************
    79  Make a dir struct.
    80 ****************************************************************************/
    81 
    82 bool make_dir_struct(TALLOC_CTX *ctx,
    83                         char *buf,
    84                         const char *mask,
    85                         const char *fname,
    86                         SMB_OFF_T size,
    87                         uint32 mode,
    88                         time_t date,
    89                         bool uc)
    90 {
    91         char *p;
    92         char *mask2 = talloc_strdup(ctx, mask);
    93 
    94         if (!mask2) {
    95                 return False;
    96         }
    97 
    98         if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
    99                 size = 0;
    100         }
    101 
    102         memset(buf+1,' ',11);
    103         if ((p = strchr_m(mask2,'.')) != NULL) {
    104                 *p = 0;
    105                 push_ascii(buf+1,mask2,8, 0);
    106                 push_ascii(buf+9,p+1,3, 0);
    107                 *p = '.';
    108         } else {
    109                 push_ascii(buf+1,mask2,11, 0);
    110         }
    111 
    112         memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
    113         SCVAL(buf,21,mode);
    114         srv_put_dos_date(buf,22,date);
    115         SSVAL(buf,26,size & 0xFFFF);
    116         SSVAL(buf,28,(size >> 16)&0xFFFF);
    117         /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
    118            Strange, but verified on W2K3. Needed for OS/2. JRA. */
    119         push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
    120         DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
    121         return True;
    122 }
    12389
    12490/****************************************************************************
     
    151117                DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum));
    152118                TALLOC_FREE(dptr->dir_hnd);
     119                TALLOC_FREE(dptr->dptr_cache);
     120                dptr->counter = 0;
    153121        }
    154122}
     
    204172                                        DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr->path,
    205173                                                strerror(errno)));
    206                                         return False;
     174                                        return NULL;
    207175                                }
    208176                        }
     
    218186****************************************************************************/
    219187
    220 char *dptr_path(struct smbd_server_connection *sconn, int key)
     188const char *dptr_path(struct smbd_server_connection *sconn, int key)
    221189{
    222190        struct dptr_struct *dptr = dptr_get(sconn, key, false);
     
    230198****************************************************************************/
    231199
    232 char *dptr_wcard(struct smbd_server_connection *sconn, int key)
     200const char *dptr_wcard(struct smbd_server_connection *sconn, int key)
    233201{
    234202        struct dptr_struct *dptr = dptr_get(sconn, key, false);
     
    242210****************************************************************************/
    243211
    244 uint16 dptr_attr(struct smbd_server_connection *sconn, int key)
     212uint16_t dptr_attr(struct smbd_server_connection *sconn, int key)
    245213{
    246214        struct dptr_struct *dptr = dptr_get(sconn, key, false);
     
    284252done:
    285253        TALLOC_FREE(dptr->dir_hnd);
    286 
    287         /* Lanman 2 specific code */
    288         SAFE_FREE(dptr->wcard);
    289         SAFE_FREE(dptr->path);
    290         SAFE_FREE(dptr);
     254        TALLOC_FREE(dptr);
    291255}
    292256
     
    371335
    372336void dptr_closepath(struct smbd_server_connection *sconn,
    373                     char *path,uint16 spid)
     337                    char *path,uint16_t spid)
    374338{
    375339        struct dptr_struct *dptr, *next;
     
    416380                }
    417381        }
     382}
     383
     384/****************************************************************************
     385 Safely do an OpenDir as root, ensuring we're in the right place.
     386****************************************************************************/
     387
     388static struct smb_Dir *open_dir_with_privilege(connection_struct *conn,
     389                                        struct smb_request *req,
     390                                        const char *path,
     391                                        const char *wcard,
     392                                        uint32_t attr)
     393{
     394        struct smb_Dir *dir_hnd = NULL;
     395        struct smb_filename *smb_fname_cwd;
     396        char *saved_dir = vfs_GetWd(talloc_tos(), conn);
     397        struct privilege_paths *priv_paths = req->priv_paths;
     398        int ret;
     399
     400        if (saved_dir == NULL) {
     401                return NULL;
     402        }
     403
     404        if (vfs_ChDir(conn, path) == -1) {
     405                return NULL;
     406        }
     407
     408        /* Now check the stat value is the same. */
     409        smb_fname_cwd = synthetic_smb_fname(talloc_tos(), ".", NULL, NULL);
     410
     411        if (smb_fname_cwd == NULL) {
     412                goto out;
     413        }
     414        ret = SMB_VFS_STAT(conn, smb_fname_cwd);
     415        if (ret != 0) {
     416                goto out;
     417        }
     418
     419        if (!check_same_stat(&smb_fname_cwd->st, &priv_paths->parent_name.st)) {
     420                DEBUG(0,("open_dir_with_privilege: stat mismatch between %s "
     421                        "and %s\n",
     422                        path,
     423                        smb_fname_str_dbg(&priv_paths->parent_name)));
     424                goto out;
     425        }
     426
     427        dir_hnd = OpenDir(NULL, conn, ".", wcard, attr);
     428
     429  out:
     430
     431        vfs_ChDir(conn, saved_dir);
     432        return dir_hnd;
    418433}
    419434
     
    427442****************************************************************************/
    428443
    429 NTSTATUS dptr_create(connection_struct *conn, files_struct *fsp,
    430                 const char *path, bool old_handle, bool expect_close,uint16 spid,
    431                 const char *wcard, bool wcard_has_wild, uint32 attr, struct dptr_struct **dptr_ret)
     444NTSTATUS dptr_create(connection_struct *conn,
     445                struct smb_request *req,
     446                files_struct *fsp,
     447                const char *path, bool old_handle, bool expect_close,uint16_t spid,
     448                const char *wcard, bool wcard_has_wild, uint32_t attr, struct dptr_struct **dptr_ret)
    432449{
    433450        struct smbd_server_connection *sconn = conn->sconn;
    434451        struct dptr_struct *dptr = NULL;
    435452        struct smb_Dir *dir_hnd;
    436         NTSTATUS status;
    437453
    438454        if (fsp && fsp->is_directory && fsp->fh->fd != -1) {
     
    452468
    453469        if (fsp) {
     470                if (!(fsp->access_mask & SEC_DIR_LIST)) {
     471                        DEBUG(5,("dptr_create: directory %s "
     472                                "not open for LIST access\n",
     473                                path));
     474                        return NT_STATUS_ACCESS_DENIED;
     475                }
    454476                dir_hnd = OpenDir_fsp(NULL, conn, fsp, wcard, attr);
    455477        } else {
    456                 status = check_name(conn,path);
     478                int ret;
     479                bool backup_intent = (req && req->priv_paths);
     480                struct smb_filename *smb_dname;
     481                NTSTATUS status;
     482
     483                smb_dname = synthetic_smb_fname(talloc_tos(), path,
     484                                                NULL, NULL);
     485                if (smb_dname == NULL) {
     486                        return NT_STATUS_NO_MEMORY;
     487                }
     488                if (req != NULL && req->posix_pathnames) {
     489                        ret = SMB_VFS_LSTAT(conn, smb_dname);
     490                } else {
     491                        ret = SMB_VFS_STAT(conn, smb_dname);
     492                }
     493                if (ret == -1) {
     494                        return map_nt_error_from_unix(errno);
     495                }
     496                if (!S_ISDIR(smb_dname->st.st_ex_mode)) {
     497                        return NT_STATUS_NOT_A_DIRECTORY;
     498                }
     499                status = smbd_check_access_rights(conn,
     500                                                smb_dname,
     501                                                backup_intent,
     502                                                SEC_DIR_LIST);
    457503                if (!NT_STATUS_IS_OK(status)) {
    458504                        return status;
    459505                }
    460                 dir_hnd = OpenDir(NULL, conn, path, wcard, attr);
     506                if (backup_intent) {
     507                        dir_hnd = open_dir_with_privilege(conn,
     508                                                req,
     509                                                path,
     510                                                wcard,
     511                                                attr);
     512                } else {
     513                        dir_hnd = OpenDir(NULL, conn, path, wcard, attr);
     514                }
    461515        }
    462516
     
    469523        }
    470524
    471         dptr = SMB_MALLOC_P(struct dptr_struct);
     525        dptr = talloc_zero(NULL, struct dptr_struct);
    472526        if(!dptr) {
    473                 DEBUG(0,("malloc fail in dptr_create.\n"));
     527                DEBUG(0,("talloc fail in dptr_create.\n"));
    474528                TALLOC_FREE(dir_hnd);
    475529                return NT_STATUS_NO_MEMORY;
    476530        }
    477531
    478         ZERO_STRUCTP(dptr);
    479 
    480         dptr->path = SMB_STRDUP(path);
     532        dptr->path = talloc_strdup(dptr, path);
    481533        if (!dptr->path) {
    482                 SAFE_FREE(dptr);
     534                TALLOC_FREE(dptr);
    483535                TALLOC_FREE(dir_hnd);
    484536                return NT_STATUS_NO_MEMORY;
     
    488540        dptr->spid = spid;
    489541        dptr->expect_close = expect_close;
    490         dptr->wcard = SMB_STRDUP(wcard);
     542        dptr->wcard = talloc_strdup(dptr, wcard);
    491543        if (!dptr->wcard) {
    492                 SAFE_FREE(dptr->path);
    493                 SAFE_FREE(dptr);
     544                TALLOC_FREE(dptr);
    494545                TALLOC_FREE(dir_hnd);
    495546                return NT_STATUS_NO_MEMORY;
    496547        }
    497         if (lp_posix_pathnames() || (wcard[0] == '.' && wcard[1] == 0)) {
     548        if ((req != NULL && req->posix_pathnames) ||
     549                        (wcard[0] == '.' && wcard[1] == 0)) {
    498550                dptr->has_wild = True;
    499551        } else {
     
    530582                        if(dptr->dnum == -1 || dptr->dnum > 254) {
    531583                                DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum));
    532                                 SAFE_FREE(dptr->path);
    533                                 SAFE_FREE(dptr->wcard);
    534                                 SAFE_FREE(dptr);
     584                                TALLOC_FREE(dptr);
    535585                                TALLOC_FREE(dir_hnd);
    536586                                return NT_STATUS_TOO_MANY_OPENED_FILES;
     
    562612                        if(dptr->dnum == -1 || dptr->dnum < 255) {
    563613                                DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum));
    564                                 SAFE_FREE(dptr->path);
    565                                 SAFE_FREE(dptr->wcard);
    566                                 SAFE_FREE(dptr);
     614                                TALLOC_FREE(dptr);
    567615                                TALLOC_FREE(dir_hnd);
    568616                                return NT_STATUS_TOO_MANY_OPENED_FILES;
     
    624672}
    625673
     674bool dptr_get_priv(struct dptr_struct *dptr)
     675{
     676        return dptr->priv;
     677}
     678
     679void dptr_set_priv(struct dptr_struct *dptr)
     680{
     681        dptr->priv = true;
     682}
     683
    626684/****************************************************************************
    627685 Return the next visible file name, skipping veto'd and invisible files.
     
    651709****************************************************************************/
    652710
    653 char *dptr_ReadDirName(TALLOC_CTX *ctx,
    654                         struct dptr_struct *dptr,
    655                         long *poffset,
    656                         SMB_STRUCT_STAT *pst)
     711static char *dptr_ReadDirName(TALLOC_CTX *ctx,
     712                              struct dptr_struct *dptr,
     713                              long *poffset,
     714                              SMB_STRUCT_STAT *pst)
    657715{
    658716        struct smb_filename smb_fname_base;
     
    715773
    716774        /* Create an smb_filename with stream_name == NULL. */
    717         ZERO_STRUCT(smb_fname_base);
    718         smb_fname_base.base_name = pathreal;
     775        smb_fname_base = (struct smb_filename) { .base_name = pathreal };
    719776
    720777        if (SMB_VFS_STAT(dptr->conn, &smb_fname_base) == 0) {
     
    794851
    795852/****************************************************************************
    796  Add the name we're returning into the underlying cache.
    797 ****************************************************************************/
    798 
    799 void dptr_DirCacheAdd(struct dptr_struct *dptr, const char *name, long offset)
    800 {
    801         DirCacheAdd(dptr->dir_hnd, name, offset);
    802 }
    803 
    804 /****************************************************************************
    805853 Initialize variables & state data at the beginning of all search SMB requests.
    806854****************************************************************************/
     
    808856{
    809857        SMB_VFS_INIT_SEARCH_OP(dptr->conn, dptr->dir_hnd->dir);
     858}
     859
     860/****************************************************************************
     861 Map a native directory offset to a 32-bit cookie.
     862****************************************************************************/
     863
     864static uint32_t map_dir_offset_to_wire(struct dptr_struct *dptr, long offset)
     865{
     866        DATA_BLOB key;
     867        DATA_BLOB val;
     868
     869        if (offset == END_OF_DIRECTORY_OFFSET) {
     870                return WIRE_END_OF_DIRECTORY_OFFSET;
     871        } else if(offset == START_OF_DIRECTORY_OFFSET) {
     872                return WIRE_START_OF_DIRECTORY_OFFSET;
     873        } else if (offset == DOT_DOT_DIRECTORY_OFFSET) {
     874                return WIRE_DOT_DOT_DIRECTORY_OFFSET;
     875        }
     876        if (sizeof(long) == 4) {
     877                /* 32-bit machine. We can cheat... */
     878                return (uint32_t)offset;
     879        }
     880        if (dptr->dptr_cache == NULL) {
     881                /* Lazy initialize cache. */
     882                dptr->dptr_cache = memcache_init(dptr, 0);
     883                if (dptr->dptr_cache == NULL) {
     884                        return WIRE_END_OF_DIRECTORY_OFFSET;
     885                }
     886        } else {
     887                /* Have we seen this offset before ? */
     888                key.data = (void *)&offset;
     889                key.length = sizeof(offset);
     890                if (memcache_lookup(dptr->dptr_cache,
     891                                        SMB1_SEARCH_OFFSET_MAP,
     892                                        key,
     893                                        &val)) {
     894                        uint32_t wire_offset;
     895                        SMB_ASSERT(val.length == sizeof(wire_offset));
     896                        memcpy(&wire_offset, val.data, sizeof(wire_offset));
     897                        DEBUG(10,("found wire %u <-> offset %ld\n",
     898                                (unsigned int)wire_offset,
     899                                (long)offset));
     900                        return wire_offset;
     901                }
     902        }
     903        /* Allocate a new wire cookie. */
     904        do {
     905                dptr->counter++;
     906        } while (dptr->counter == WIRE_START_OF_DIRECTORY_OFFSET ||
     907                 dptr->counter == WIRE_END_OF_DIRECTORY_OFFSET ||
     908                 dptr->counter == WIRE_DOT_DOT_DIRECTORY_OFFSET);
     909        /* Store it in the cache. */
     910        key.data = (void *)&offset;
     911        key.length = sizeof(offset);
     912        val.data = (void *)&dptr->counter;
     913        val.length = sizeof(dptr->counter); /* MUST BE uint32_t ! */
     914        memcache_add(dptr->dptr_cache,
     915                        SMB1_SEARCH_OFFSET_MAP,
     916                        key,
     917                        val);
     918        /* And the reverse mapping for lookup from
     919           map_wire_to_dir_offset(). */
     920        memcache_add(dptr->dptr_cache,
     921                        SMB1_SEARCH_OFFSET_MAP,
     922                        val,
     923                        key);
     924        DEBUG(10,("stored wire %u <-> offset %ld\n",
     925                (unsigned int)dptr->counter,
     926                (long)offset));
     927        return dptr->counter;
    810928}
    811929
     
    819937        unsigned char *buf = (unsigned char *)buf1;
    820938        struct dptr_struct *dptr = dptr_get(sconn, key, false);
    821         uint32 offset;
     939        uint32_t wire_offset;
    822940        if (!dptr) {
    823941                DEBUG(1,("filling null dirptr %d\n",key));
    824942                return(False);
    825943        }
    826         offset = (uint32)TellDir(dptr->dir_hnd);
     944        wire_offset = map_dir_offset_to_wire(dptr,TellDir(dptr->dir_hnd));
    827945        DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key,
    828                 (long)dptr->dir_hnd,(int)offset));
     946                (long)dptr->dir_hnd,(int)wire_offset));
    829947        buf[0] = key;
    830         SIVAL(buf,1,offset);
     948        SIVAL(buf,1,wire_offset);
    831949        return(True);
     950}
     951
     952/****************************************************************************
     953 Map a 32-bit wire cookie to a native directory offset.
     954****************************************************************************/
     955
     956static long map_wire_to_dir_offset(struct dptr_struct *dptr, uint32_t wire_offset)
     957{
     958        DATA_BLOB key;
     959        DATA_BLOB val;
     960
     961        if (wire_offset == WIRE_END_OF_DIRECTORY_OFFSET) {
     962                return END_OF_DIRECTORY_OFFSET;
     963        } else if(wire_offset == WIRE_START_OF_DIRECTORY_OFFSET) {
     964                return START_OF_DIRECTORY_OFFSET;
     965        } else if (wire_offset == WIRE_DOT_DOT_DIRECTORY_OFFSET) {
     966                return DOT_DOT_DIRECTORY_OFFSET;
     967        }
     968        if (sizeof(long) == 4) {
     969                /* 32-bit machine. We can cheat... */
     970                return (long)wire_offset;
     971        }
     972        if (dptr->dptr_cache == NULL) {
     973                /* Logic error, cache should be initialized. */
     974                return END_OF_DIRECTORY_OFFSET;
     975        }
     976        key.data = (void *)&wire_offset;
     977        key.length = sizeof(wire_offset);
     978        if (memcache_lookup(dptr->dptr_cache,
     979                                SMB1_SEARCH_OFFSET_MAP,
     980                                key,
     981                                &val)) {
     982                /* Found mapping. */
     983                long offset;
     984                SMB_ASSERT(val.length == sizeof(offset));
     985                memcpy(&offset, val.data, sizeof(offset));
     986                DEBUG(10,("lookup wire %u <-> offset %ld\n",
     987                        (unsigned int)wire_offset,
     988                        (long)offset));
     989                return offset;
     990        }
     991        return END_OF_DIRECTORY_OFFSET;
    832992}
    833993
     
    8411001        unsigned int key = *(unsigned char *)buf;
    8421002        struct dptr_struct *dptr = dptr_get(sconn, key, false);
    843         uint32 offset;
     1003        uint32_t wire_offset;
    8441004        long seekoff;
    8451005
     
    8491009        }
    8501010        *num = key;
    851         offset = IVAL(buf,1);
    852         if (offset == (uint32)-1) {
    853                 seekoff = END_OF_DIRECTORY_OFFSET;
    854         } else {
    855                 seekoff = (long)offset;
    856         }
     1011        wire_offset = IVAL(buf,1);
     1012        seekoff = map_wire_to_dir_offset(dptr, wire_offset);
    8571013        SeekDir(dptr->dir_hnd,seekoff);
    8581014        DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
     
    8761032        DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr->path));
    8771033        return(dptr);
    878 }
    879 
    880 /****************************************************************************
    881  Check that a file matches a particular file type.
    882 ****************************************************************************/
    883 
    884 bool dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype)
    885 {
    886         uint32 mask;
    887 
    888         /* Check the "may have" search bits. */
    889         if (((mode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY)) != 0)
    890                 return False;
    891 
    892         /* Check the "must have" bits, which are the may have bits shifted eight */
    893         /* If must have bit is set, the file/dir can not be returned in search unless the matching
    894                 file attribute is set */
    895         mask = ((dirtype >> 8) & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)); /* & 0x37 */
    896         if(mask) {
    897                 if((mask & (mode & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM))) == mask)   /* check if matching attribute present */
    898                         return True;
    899                 else
    900                         return False;
    901         }
    902 
    903         return True;
    9041034}
    9051035
     
    9401070        size_t slashlen;
    9411071        size_t pathlen;
     1072        bool dirptr_path_is_dot = ISDOT(dirptr->path);
    9421073
    9431074        *_smb_fname = NULL;
     
    9501081                long cur_offset;
    9511082                long prev_offset;
    952                 SMB_STRUCT_STAT sbuf;
     1083                SMB_STRUCT_STAT sbuf = { 0 };
    9531084                char *dname = NULL;
    9541085                bool isdots;
     
    9581089                uint32_t mode = 0;
    9591090                bool ok;
    960                 NTSTATUS status;
    9611091
    9621092                cur_offset = dptr_TellDir(dirptr);
     
    10051135                }
    10061136
    1007                 memcpy(pathreal, dirptr->path, pathlen);
    1008                 pathreal[pathlen] = '/';
    1009                 memcpy(pathreal + slashlen + pathlen, dname,
    1010                        talloc_get_size(dname));
     1137                /*
     1138                 * We don't want to pass ./xxx to modules below us so don't
     1139                 * add the path if it is just . by itself.
     1140                 */
     1141                if (dirptr_path_is_dot) {
     1142                        memcpy(pathreal, dname, talloc_get_size(dname));
     1143                } else {
     1144                        memcpy(pathreal, dirptr->path, pathlen);
     1145                        pathreal[pathlen] = '/';
     1146                        memcpy(pathreal + slashlen + pathlen, dname,
     1147                               talloc_get_size(dname));
     1148                }
    10111149
    10121150                /* Create smb_fname with NULL stream_name. */
    1013                 ZERO_STRUCT(smb_fname);
    1014                 smb_fname.base_name = pathreal;
    1015                 smb_fname.st = sbuf;
     1151                smb_fname = (struct smb_filename) {
     1152                        .base_name = pathreal, .st = sbuf
     1153                };
    10161154
    10171155                ok = mode_fn(ctx, private_data, &smb_fname, &mode);
     
    10231161                }
    10241162
    1025                 if (!dir_check_ftype(conn, mode, dirtype)) {
     1163                if (!dir_check_ftype(mode, dirtype)) {
    10261164                        DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",
    10271165                                fname, (unsigned int)mode, (unsigned int)dirtype));
     
    10541192                TALLOC_FREE(dname);
    10551193
    1056                 status = copy_smb_filename(ctx, &smb_fname, _smb_fname);
     1194                *_smb_fname = cp_smb_filename(ctx, &smb_fname);
    10571195                TALLOC_FREE(pathreal);
    1058                 if (!NT_STATUS_IS_OK(status)) {
     1196                if (*_smb_fname == NULL) {
    10591197                        return false;
    10601198                }
     
    10861224                char mname[13];
    10871225                const char *fname;
     1226                /*
     1227                 * Ensure we can push the original name as UCS2. If
     1228                 * not, then just don't return this name.
     1229                 */
     1230                NTSTATUS status;
     1231                size_t ret_len = 0;
     1232                size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
     1233                uint8_t *tmp = talloc_array(talloc_tos(),
     1234                                        uint8_t,
     1235                                        len);
     1236
     1237                status = srvstr_push(NULL,
     1238                        FLAGS2_UNICODE_STRINGS,
     1239                        tmp,
     1240                        dname,
     1241                        len,
     1242                        STR_TERMINATE,
     1243                        &ret_len);
     1244
     1245                TALLOC_FREE(tmp);
     1246
     1247                if (!NT_STATUS_IS_OK(status)) {
     1248                        return false;
     1249                }
    10881250
    10891251                if (!mangle_is_8_3(dname, false, conn->params)) {
     
    11361298                uint32_t dirtype,
    11371299                char **_fname,
    1138                 SMB_OFF_T *_size,
     1300                off_t *_size,
    11391301                uint32_t *_mode,
    11401302                struct timespec *_date,
     
    11831345                               struct smb_filename *smb_fname)
    11841346{
     1347        NTSTATUS status;
     1348        uint32_t rejected_share_access = 0;
     1349        uint32_t rejected_mask = 0;
     1350        struct security_descriptor *sd = NULL;
     1351        uint32_t access_mask = FILE_READ_DATA|
     1352                                FILE_READ_EA|
     1353                                FILE_READ_ATTRIBUTES|
     1354                                SEC_STD_READ_CONTROL;
     1355
    11851356        /*
    11861357         * Never hide files from the root user.
     
    11931364        }
    11941365
    1195         return can_access_file_acl(conn, smb_fname, FILE_READ_DATA);
     1366        /*
     1367         * We can't directly use smbd_check_access_rights()
     1368         * here, as this implicitly grants FILE_READ_ATTRIBUTES
     1369         * which the Windows access-based-enumeration code
     1370         * explicitly checks for on the file security descriptor.
     1371         * See bug:
     1372         *
     1373         * https://bugzilla.samba.org/show_bug.cgi?id=10252
     1374         *
     1375         * and the smb2.acl2.ACCESSBASED test for details.
     1376         */
     1377
     1378        rejected_share_access = access_mask & ~(conn->share_access);
     1379        if (rejected_share_access) {
     1380                DEBUG(10, ("rejected share access 0x%x "
     1381                        "on %s (0x%x)\n",
     1382                        (unsigned int)access_mask,
     1383                        smb_fname_str_dbg(smb_fname),
     1384                        (unsigned int)rejected_share_access ));
     1385                return false;
     1386        }
     1387
     1388        status = SMB_VFS_GET_NT_ACL(conn,
     1389                        smb_fname->base_name,
     1390                        (SECINFO_OWNER |
     1391                         SECINFO_GROUP |
     1392                         SECINFO_DACL),
     1393                        talloc_tos(),
     1394                        &sd);
     1395
     1396        if (!NT_STATUS_IS_OK(status)) {
     1397                DEBUG(10, ("Could not get acl "
     1398                        "on %s: %s\n",
     1399                        smb_fname_str_dbg(smb_fname),
     1400                        nt_errstr(status)));
     1401                return false;
     1402        }
     1403
     1404        status = se_file_access_check(sd,
     1405                                get_current_nttok(conn),
     1406                                false,
     1407                                access_mask,
     1408                                &rejected_mask);
     1409
     1410        TALLOC_FREE(sd);
     1411
     1412        if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
     1413                DEBUG(10,("rejected bits 0x%x read access for %s\n",
     1414                        (unsigned int)rejected_mask,
     1415                        smb_fname_str_dbg(smb_fname) ));
     1416                return false;
     1417        }
     1418        return true;
    11961419}
    11971420
     
    12621485                     const char *name, SMB_STRUCT_STAT *pst, bool use_veto)
    12631486{
    1264         bool hide_unreadable = lp_hideunreadable(SNUM(conn));
    1265         bool hide_unwriteable = lp_hideunwriteable_files(SNUM(conn));
     1487        bool hide_unreadable = lp_hide_unreadable(SNUM(conn));
     1488        bool hide_unwriteable = lp_hide_unwriteable_files(SNUM(conn));
    12661489        bool hide_special = lp_hide_special_files(SNUM(conn));
    12671490        char *entry = NULL;
    12681491        struct smb_filename *smb_fname_base = NULL;
    1269         NTSTATUS status;
    12701492        bool ret = false;
    12711493
     
    12881510
    12891511                /* Create an smb_filename with stream_name == NULL. */
    1290                 status = create_synthetic_smb_fname(talloc_tos(), entry, NULL,
    1291                                                     pst, &smb_fname_base);
    1292                 if (!NT_STATUS_IS_OK(status)) {
     1512                smb_fname_base = synthetic_smb_fname(talloc_tos(), entry, NULL,
     1513                                                     pst);
     1514                if (smb_fname_base == NULL) {
    12931515                        ret = false;
    12941516                        goto out;
     
    13031525                                ret = true;
    13041526                                goto out;
    1305                         } else {
    1306                                 *pst = smb_fname_base->st;
    13071527                        }
     1528                        *pst = smb_fname_base->st;
    13081529                }
    13091530
     
    13711592                        const char *name,
    13721593                        const char *mask,
    1373                         uint32 attr)
    1374 {
    1375         struct smb_Dir *dirp = TALLOC_ZERO_P(mem_ctx, struct smb_Dir);
     1594                        uint32_t attr)
     1595{
     1596        struct smb_Dir *dirp = talloc_zero(mem_ctx, struct smb_Dir);
    13761597        struct smbd_server_connection *sconn = conn->sconn;
    13771598
     
    14151636                        files_struct *fsp,
    14161637                        const char *mask,
    1417                         uint32 attr)
    1418 {
    1419         struct smb_Dir *dirp = TALLOC_ZERO_P(mem_ctx, struct smb_Dir);
     1638                        uint32_t attr)
     1639{
     1640        struct smb_Dir *dirp = talloc_zero(mem_ctx, struct smb_Dir);
    14201641        struct smbd_server_connection *sconn = conn->sconn;
    14211642
     
    14991720                *ptalloced = NULL;
    15001721                return n;
    1501         } else if (*poffset == END_OF_DIRECTORY_OFFSET) {
     1722        }
     1723
     1724        if (*poffset == END_OF_DIRECTORY_OFFSET) {
    15021725                *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
    15031726                return NULL;
    1504         } else {
    1505                 /* A real offset, seek to it. */
    1506                 SeekDir(dirp, *poffset);
    1507         }
     1727        }
     1728
     1729        /* A real offset, seek to it. */
     1730        SeekDir(dirp, *poffset);
    15081731
    15091732        while ((n = vfs_readdirname(conn, dirp->dir, sbuf, &talloced))) {
     
    15831806********************************************************************/
    15841807
    1585 void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset)
     1808static void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset)
    15861809{
    15871810        struct name_cache_entry *e;
     
    15921815
    15931816        if (dirp->name_cache == NULL) {
    1594                 dirp->name_cache = TALLOC_ZERO_ARRAY(
     1817                dirp->name_cache = talloc_zero_array(
    15951818                        dirp, struct name_cache_entry, dirp->name_cache_size);
    15961819
     
    16541877}
    16551878
     1879struct files_below_forall_state {
     1880        char *dirpath;
     1881        size_t dirpath_len;
     1882        int (*fn)(struct file_id fid, const struct share_mode_data *data,
     1883                  void *private_data);
     1884        void *private_data;
     1885};
     1886
     1887static int files_below_forall_fn(struct file_id fid,
     1888                                 const struct share_mode_data *data,
     1889                                 void *private_data)
     1890{
     1891        struct files_below_forall_state *state = private_data;
     1892        char tmpbuf[PATH_MAX];
     1893        char *fullpath, *to_free;
     1894        size_t len;
     1895
     1896        len = full_path_tos(data->servicepath, data->base_name,
     1897                            tmpbuf, sizeof(tmpbuf),
     1898                            &fullpath, &to_free);
     1899        if (len == -1) {
     1900                return 0;
     1901        }
     1902        if (state->dirpath_len >= len) {
     1903                /*
     1904                 * Filter files above dirpath
     1905                 */
     1906                return 0;
     1907        }
     1908        if (fullpath[state->dirpath_len] != '/') {
     1909                /*
     1910                 * Filter file that don't have a path separator at the end of
     1911                 * dirpath's length
     1912                 */
     1913                return 0;
     1914        }
     1915
     1916        if (memcmp(state->dirpath, fullpath, state->dirpath_len) != 0) {
     1917                /*
     1918                 * Not a parent
     1919                 */
     1920                return 0;
     1921        }
     1922
     1923        return state->fn(fid, data, state->private_data);
     1924}
     1925
     1926static int files_below_forall(connection_struct *conn,
     1927                              const struct smb_filename *dir_name,
     1928                              int (*fn)(struct file_id fid,
     1929                                        const struct share_mode_data *data,
     1930                                        void *private_data),
     1931                              void *private_data)
     1932{
     1933        struct files_below_forall_state state = {
     1934                        .fn = fn,
     1935                        .private_data = private_data,
     1936        };
     1937        int ret;
     1938        char tmpbuf[PATH_MAX];
     1939        char *to_free;
     1940
     1941        state.dirpath_len = full_path_tos(conn->connectpath,
     1942                                          dir_name->base_name,
     1943                                          tmpbuf, sizeof(tmpbuf),
     1944                                          &state.dirpath, &to_free);
     1945        if (state.dirpath_len == -1) {
     1946                return -1;
     1947        }
     1948
     1949        ret = share_mode_forall(files_below_forall_fn, &state);
     1950        TALLOC_FREE(to_free);
     1951        return ret;
     1952}
     1953
     1954struct have_file_open_below_state {
     1955        bool found_one;
     1956};
     1957
     1958static int have_file_open_below_fn(struct file_id fid,
     1959                                   const struct share_mode_data *data,
     1960                                   void *private_data)
     1961{
     1962        struct have_file_open_below_state *state = private_data;
     1963        state->found_one = true;
     1964        return 1;
     1965}
     1966
     1967bool have_file_open_below(connection_struct *conn,
     1968                                 const struct smb_filename *name)
     1969{
     1970        struct have_file_open_below_state state = {
     1971                .found_one = false,
     1972        };
     1973        int ret;
     1974
     1975        if (!VALID_STAT(name->st)) {
     1976                return false;
     1977        }
     1978        if (!S_ISDIR(name->st.st_ex_mode)) {
     1979                return false;
     1980        }
     1981
     1982        ret = files_below_forall(conn, name, have_file_open_below_fn, &state);
     1983        if (ret == -1) {
     1984                return false;
     1985        }
     1986
     1987        return state.found_one;
     1988}
     1989
    16561990/*****************************************************************
    16571991 Is this directory empty ?
     
    16631997        long dirpos = 0;
    16641998        const char *dname = NULL;
     1999        const char *dirname = fsp->fsp_name->base_name;
    16652000        char *talloced = NULL;
    16662001        SMB_STRUCT_STAT st;
     
    16852020                }
    16862021
    1687                 if (!is_visible_file(conn, fsp->fsp_name->base_name, dname, &st, True)) {
     2022                if (!is_visible_file(conn, dirname, dname, &st, True)) {
    16882023                        TALLOC_FREE(talloced);
    16892024                        continue;
    16902025                }
    16912026
    1692                 DEBUG(10,("can_delete_directory_fsp: got name %s - can't delete\n",
     2027                DEBUG(10,("got name %s - can't delete\n",
    16932028                         dname ));
    16942029                status = NT_STATUS_DIRECTORY_NOT_EMPTY;
     
    16982033        TALLOC_FREE(dir_hnd);
    16992034
    1700         return status;
    1701 }
     2035        if (!NT_STATUS_IS_OK(status)) {
     2036                return status;
     2037        }
     2038
     2039        if (!(fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) &&
     2040            lp_strict_rename(SNUM(conn)) &&
     2041            have_file_open_below(fsp->conn, fsp->fsp_name))
     2042        {
     2043                return NT_STATUS_ACCESS_DENIED;
     2044        }
     2045
     2046        return NT_STATUS_OK;
     2047}
Note: See TracChangeset for help on using the changeset viewer.