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/filename.c

    r860 r988  
    2929#include "fake_file.h"
    3030#include "smbd/smbd.h"
     31#include "smbd/globals.h"
    3132
    3233static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
    3334                                  connection_struct *conn,
    34                                   const char *orig_path,
    3535                                  struct smb_filename *smb_fname);
    3636
     
    5656
    5757static NTSTATUS determine_path_error(const char *name,
    58                         bool allow_wcard_last_component)
     58                        bool allow_wcard_last_component,
     59                        bool posix_pathnames)
    5960{
    6061        const char *p;
     62        bool name_has_wild = false;
    6163
    6264        if (!allow_wcard_last_component) {
     
    7577        p = strchr(name, '/');
    7678
    77         if (!p && (ms_has_wild(name) || ISDOT(name))) {
     79        if (!posix_pathnames) {
     80                name_has_wild = ms_has_wild(name);
     81        }
     82
     83        if (!p && (name_has_wild || ISDOT(name))) {
    7884                /* Error code at the end of a pathname. */
    7985                return NT_STATUS_OBJECT_NAME_INVALID;
     
    123129        NTSTATUS status;
    124130        int ret;
     131        bool parent_fname_has_wild = false;
    125132
    126133        ZERO_STRUCT(parent_fname);
     
    131138        }
    132139
     140        if (!posix_pathnames) {
     141                parent_fname_has_wild = ms_has_wild(parent_fname.base_name);
     142        }
     143
    133144        /*
    134145         * If there was no parent component in
     
    138149         */
    139150        if ((smb_fname->base_name == last_component) ||
    140                         ms_has_wild(parent_fname.base_name)) {
     151                        parent_fname_has_wild) {
    141152                return NT_STATUS_OK;
    142153        }
     
    161172
    162173        /* Parent exists - set "start" to be the
    163          * last compnent to shorten the tree walk. */
    164 
    165         /*
    166          * Safe to use CONST_DISCARD
     174         * last component to shorten the tree walk. */
     175
     176        /*
     177         * Safe to use discard_const_p
    167178         * here as last_component points
    168179         * into our smb_fname->base_name.
    169180         */
    170         *pp_start = CONST_DISCARD(char *,last_component);
     181        *pp_start = discard_const_p(char, last_component);
    171182
    172183        /* Update dirpath. */
     
    225236{
    226237        struct smb_filename *smb_fname = NULL;
    227         char *start, *end;
     238
     239        /*
     240         * This looks strange. But we need "start" initialized to "" here but
     241         * it can't be a const char *, so 'char *start = "";' does not work.
     242         */
     243        char cnull = '\0';
     244        char *start = &cnull;
     245
     246        char *end;
    228247        char *dirpath = NULL;
    229248        char *stream = NULL;
    230249        bool component_was_mangled = False;
    231250        bool name_has_wildcard = False;
    232         bool posix_pathnames = false;
     251        bool posix_pathnames = (ucf_flags & UCF_POSIX_PATHNAMES);
    233252        bool allow_wcard_last_component =
    234253            (ucf_flags & UCF_ALWAYS_ALLOW_WCARD_LCOMP);
     
    300319                } else {
    301320                        status =determine_path_error(&orig_path[2],
    302                             allow_wcard_last_component);
     321                            allow_wcard_last_component,
     322                            posix_pathnames);
    303323                }
    304324                goto err;
     
    323343        if (conn->case_sensitive && !conn->case_preserve &&
    324344                        !conn->short_case_preserve) {
    325                 strnorm(smb_fname->base_name, lp_defaultcase(SNUM(conn)));
     345                if (!strnorm(smb_fname->base_name, lp_default_case(SNUM(conn)))) {
     346                        DEBUG(0, ("strnorm %s failed\n", smb_fname->base_name));
     347                        status = NT_STATUS_INVALID_PARAMETER;
     348                        goto err;
     349                }
    326350        }
    327351
     
    344368                }
    345369        }
    346 
    347         posix_pathnames = (lp_posix_pathnames() ||
    348                                 (ucf_flags & UCF_POSIX_PATHNAMES));
    349370
    350371        /*
     
    367388                        *stream = '\0';
    368389                        stream = tmp;
     390
     391                        if (smb_fname->base_name[0] == '\0') {
     392                                /*
     393                                 * orig_name was just a stream name.
     394                                 * This is a stream on the root of
     395                                 * the share. Replace base_name with
     396                                 * a "."
     397                                 */
     398                                smb_fname->base_name =
     399                                        talloc_strdup(smb_fname, ".");
     400                                if (smb_fname->base_name == NULL) {
     401                                        status = NT_STATUS_NO_MEMORY;
     402                                        goto err;
     403                                }
     404                                if (SMB_VFS_STAT(conn, smb_fname) != 0) {
     405                                        status = map_nt_error_from_unix(errno);
     406                                        goto err;
     407                                }
     408                                /* dirpath must exist. */
     409                                dirpath = talloc_strdup(ctx,"");
     410                                if (dirpath == NULL) {
     411                                        status = NT_STATUS_NO_MEMORY;
     412                                        goto err;
     413                                }
     414                                DEBUG(5, ("conversion finished %s -> %s\n",
     415                                        orig_path,
     416                                        smb_fname->base_name));
     417                                goto done;
     418                        }
    369419                }
    370420        }
     
    406456         */
    407457
    408         name_has_wildcard = ms_has_wild(smb_fname->base_name);
    409         if (name_has_wildcard && !allow_wcard_last_component) {
    410                 /* Wildcard not valid anywhere. */
    411                 status = NT_STATUS_OBJECT_NAME_INVALID;
    412                 goto fail;
     458        if (!posix_pathnames) {
     459                /* POSIX pathnames have no wildcards. */
     460                name_has_wildcard = ms_has_wild(smb_fname->base_name);
     461                if (name_has_wildcard && !allow_wcard_last_component) {
     462                        /* Wildcard not valid anywhere. */
     463                        status = NT_STATUS_OBJECT_NAME_INVALID;
     464                        goto fail;
     465                }
    413466        }
    414467
     
    596649                        } else {
    597650                                status = determine_path_error(end+1,
    598                                                 allow_wcard_last_component);
     651                                                allow_wcard_last_component,
     652                                                posix_pathnames);
    599653                        }
    600654                        goto fail;
     
    604658                   the last component. */
    605659
    606                 name_has_wildcard = ms_has_wild(start);
     660                if (!posix_pathnames) {
     661                        name_has_wildcard = ms_has_wild(start);
     662                }
    607663
    608664                /* Wildcards never valid within a pathname. */
     
    716772                                 * here.
    717773                                 */
     774
    718775                                if (errno == EACCES) {
    719                                         if (ucf_flags & UCF_CREATING_FILE) {
     776                                        if ((ucf_flags & UCF_PREP_CREATEFILE) == 0) {
     777                                                status = NT_STATUS_ACCESS_DENIED;
     778                                                goto fail;
     779                                        } else {
    720780                                                /*
    721781                                                 * This is the dropbox
     
    729789                                                 * users creating a file.
    730790                                                 */
    731                                                 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
    732                                         } else {
    733                                                 status = NT_STATUS_ACCESS_DENIED;
     791                                                errno = 0;
    734792                                        }
    735                                         goto fail;
    736793                                }
    737794
     
    764821                                                   conn->params) &&
    765822                                                 !conn->short_case_preserve)) {
    766                                         strnorm(start,
    767                                                 lp_defaultcase(SNUM(conn)));
     823                                        if (!strnorm(start,
     824                                                        lp_default_case(SNUM(conn)))) {
     825                                                DEBUG(0, ("strnorm %s failed\n",
     826                                                        start));
     827                                                status = NT_STATUS_INVALID_PARAMETER;
     828                                                goto err;
     829                                        }
    768830                                }
    769831
     
    9711033
    9721034                /* Check path now that the base_name has been converted. */
    973                 status = build_stream_path(ctx, conn, orig_path, smb_fname);
     1035                status = build_stream_path(ctx, conn, smb_fname);
    9741036                if (!NT_STATUS_IS_OK(status)) {
    9751037                        goto fail;
     
    9811043 fail:
    9821044        DEBUG(10, ("dirpath = [%s] start = [%s]\n", dirpath, start));
    983         if (*dirpath != '\0') {
     1045        if (dirpath && *dirpath != '\0') {
    9841046                smb_fname->base_name = talloc_asprintf(smb_fname, "%s/%s",
    9851047                                                       dirpath, start);
     
    10021064
    10031065/****************************************************************************
    1004  Ensure a path is not vetod.
     1066 Ensure a path is not vetoed.
    10051067****************************************************************************/
    10061068
    1007 NTSTATUS check_veto_path(connection_struct *conn, const char *name)
     1069static NTSTATUS check_veto_path(connection_struct *conn, const char *name)
    10081070{
    10091071        if (IS_VETO_PATH(conn, name))  {
     
    10331095        }
    10341096
    1035         if (!lp_widelinks(SNUM(conn)) || !lp_symlinks(SNUM(conn))) {
     1097        if (!lp_widelinks(SNUM(conn)) || !lp_follow_symlinks(SNUM(conn))) {
    10361098                status = check_reduced_name(conn,name);
    10371099                if (!NT_STATUS_IS_OK(status)) {
     
    10431105
    10441106        return NT_STATUS_OK;
     1107}
     1108
     1109/****************************************************************************
     1110 Must be called as root. Creates the struct privilege_paths
     1111 attached to the struct smb_request if this call is successful.
     1112****************************************************************************/
     1113
     1114static NTSTATUS check_name_with_privilege(connection_struct *conn,
     1115                struct smb_request *smbreq,
     1116                const char *name)
     1117{
     1118        NTSTATUS status = check_veto_path(conn, name);
     1119
     1120        if (!NT_STATUS_IS_OK(status)) {
     1121                return status;
     1122        }
     1123        return check_reduced_name_with_privilege(conn,
     1124                        name,
     1125                        smbreq);
    10451126}
    10461127
     
    12041285static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
    12051286                                  connection_struct *conn,
    1206                                   const char *orig_path,
    12071287                                  struct smb_filename *smb_fname)
    12081288{
     
    12821362 * @param conn          connection struct for vfs calls.
    12831363 * @param dfs_path      Whether this path requires dfs resolution.
     1364 * @param smbreq        SMB request if we're using privileges.
    12841365 * @param name_in       The unconverted name.
    12851366 * @param ucf_flags     flags to pass through to unix_convert().
     
    12951376 *         error otherwise.
    12961377 */
     1378static NTSTATUS filename_convert_internal(TALLOC_CTX *ctx,
     1379                                connection_struct *conn,
     1380                                bool dfs_path,
     1381                                struct smb_request *smbreq,
     1382                                const char *name_in,
     1383                                uint32_t ucf_flags,
     1384                                bool *ppath_contains_wcard,
     1385                                struct smb_filename **pp_smb_fname)
     1386{
     1387        NTSTATUS status;
     1388        bool allow_wcards = (ucf_flags & (UCF_COND_ALLOW_WCARD_LCOMP|UCF_ALWAYS_ALLOW_WCARD_LCOMP));
     1389        char *fname = NULL;
     1390
     1391        *pp_smb_fname = NULL;
     1392
     1393        status = resolve_dfspath_wcard(ctx, conn,
     1394                                dfs_path,
     1395                                name_in,
     1396                                allow_wcards,
     1397                                !conn->sconn->using_smb2,
     1398                                &fname,
     1399                                ppath_contains_wcard);
     1400        if (!NT_STATUS_IS_OK(status)) {
     1401                DEBUG(10,("filename_convert_internal: resolve_dfspath failed "
     1402                        "for name %s with %s\n",
     1403                        name_in,
     1404                        nt_errstr(status) ));
     1405                return status;
     1406        }
     1407
     1408        if (is_fake_file_path(name_in)) {
     1409                SMB_STRUCT_STAT st;
     1410                ZERO_STRUCT(st);
     1411                st.st_ex_nlink = 1;
     1412                *pp_smb_fname = synthetic_smb_fname_split(ctx,
     1413                                                          name_in,
     1414                                                          &st);
     1415                if (*pp_smb_fname == NULL) {
     1416                        return NT_STATUS_NO_MEMORY;
     1417                }
     1418                return NT_STATUS_OK;
     1419        }
     1420
     1421        /*
     1422         * If the caller conditionally allows wildcard lookups, only add the
     1423         * always allow if the path actually does contain a wildcard.
     1424         */
     1425        if (ucf_flags & UCF_COND_ALLOW_WCARD_LCOMP &&
     1426            ppath_contains_wcard != NULL && *ppath_contains_wcard) {
     1427                ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
     1428        }
     1429
     1430        status = unix_convert(ctx, conn, fname, pp_smb_fname, ucf_flags);
     1431        if (!NT_STATUS_IS_OK(status)) {
     1432                DEBUG(10,("filename_convert_internal: unix_convert failed "
     1433                        "for name %s with %s\n",
     1434                        fname,
     1435                        nt_errstr(status) ));
     1436                return status;
     1437        }
     1438
     1439        if ((ucf_flags & UCF_UNIX_NAME_LOOKUP) &&
     1440                        VALID_STAT((*pp_smb_fname)->st) &&
     1441                        S_ISLNK((*pp_smb_fname)->st.st_ex_mode)) {
     1442                return check_veto_path(conn, (*pp_smb_fname)->base_name);
     1443        }
     1444
     1445        if (!smbreq) {
     1446                status = check_name(conn, (*pp_smb_fname)->base_name);
     1447        } else {
     1448                status = check_name_with_privilege(conn, smbreq, (*pp_smb_fname)->base_name);
     1449        }
     1450        if (!NT_STATUS_IS_OK(status)) {
     1451                DEBUG(3,("filename_convert_internal: check_name failed "
     1452                        "for name %s with %s\n",
     1453                        smb_fname_str_dbg(*pp_smb_fname),
     1454                        nt_errstr(status) ));
     1455                TALLOC_FREE(*pp_smb_fname);
     1456                return status;
     1457        }
     1458
     1459        return status;
     1460}
     1461
     1462/*
     1463 * Go through all the steps to validate a filename.
     1464 * Non-root version.
     1465 */
     1466
    12971467NTSTATUS filename_convert(TALLOC_CTX *ctx,
    12981468                                connection_struct *conn,
     
    13031473                                struct smb_filename **pp_smb_fname)
    13041474{
    1305         NTSTATUS status;
    1306         bool allow_wcards = (ucf_flags & (UCF_COND_ALLOW_WCARD_LCOMP|UCF_ALWAYS_ALLOW_WCARD_LCOMP));
    1307         char *fname = NULL;
    1308 
    1309         *pp_smb_fname = NULL;
    1310 
    1311         status = resolve_dfspath_wcard(ctx, conn,
    1312                                 dfs_path,
    1313                                 name_in,
    1314                                 allow_wcards,
    1315                                 &fname,
    1316                                 ppath_contains_wcard);
    1317         if (!NT_STATUS_IS_OK(status)) {
    1318                 DEBUG(10,("filename_convert: resolve_dfspath failed "
    1319                         "for name %s with %s\n",
    1320                         name_in,
    1321                         nt_errstr(status) ));
    1322                 return status;
    1323         }
    1324 
    1325         if (is_fake_file_path(name_in)) {
    1326                 SMB_STRUCT_STAT st;
    1327                 ZERO_STRUCT(st);
    1328                 st.st_ex_nlink = 1;
    1329                 status = create_synthetic_smb_fname_split(ctx,
    1330                                                           name_in,
    1331                                                           &st,
    1332                                                           pp_smb_fname);
    1333                 return status;
    1334         }
    1335 
    1336         /*
    1337          * If the caller conditionally allows wildcard lookups, only add the
    1338          * always allow if the path actually does contain a wildcard.
    1339          */
    1340         if (ucf_flags & UCF_COND_ALLOW_WCARD_LCOMP &&
    1341             ppath_contains_wcard != NULL && *ppath_contains_wcard) {
    1342                 ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
    1343         }
    1344 
    1345         status = unix_convert(ctx, conn, fname, pp_smb_fname, ucf_flags);
    1346         if (!NT_STATUS_IS_OK(status)) {
    1347                 DEBUG(10,("filename_convert: unix_convert failed "
    1348                         "for name %s with %s\n",
    1349                         fname,
    1350                         nt_errstr(status) ));
    1351                 return status;
    1352         }
    1353 
    1354         if ((ucf_flags & UCF_UNIX_NAME_LOOKUP) &&
    1355                         VALID_STAT((*pp_smb_fname)->st) &&
    1356                         S_ISLNK((*pp_smb_fname)->st.st_ex_mode)) {
    1357                 return check_veto_path(conn, (*pp_smb_fname)->base_name);
    1358         }
    1359 
    1360         status = check_name(conn, (*pp_smb_fname)->base_name);
    1361         if (!NT_STATUS_IS_OK(status)) {
    1362                 DEBUG(3,("filename_convert: check_name failed "
    1363                         "for name %s with %s\n",
    1364                         smb_fname_str_dbg(*pp_smb_fname),
    1365                         nt_errstr(status) ));
    1366                 TALLOC_FREE(*pp_smb_fname);
    1367                 return status;
    1368         }
    1369 
    1370         return status;
     1475        return filename_convert_internal(ctx,
     1476                                        conn,
     1477                                        dfs_path,
     1478                                        NULL,
     1479                                        name_in,
     1480                                        ucf_flags,
     1481                                        ppath_contains_wcard,
     1482                                        pp_smb_fname);
    13711483}
     1484
     1485/*
     1486 * Go through all the steps to validate a filename.
     1487 * root (privileged) version.
     1488 */
     1489
     1490NTSTATUS filename_convert_with_privilege(TALLOC_CTX *ctx,
     1491                                connection_struct *conn,
     1492                                struct smb_request *smbreq,
     1493                                const char *name_in,
     1494                                uint32_t ucf_flags,
     1495                                bool *ppath_contains_wcard,
     1496                                struct smb_filename **pp_smb_fname)
     1497{
     1498        return filename_convert_internal(ctx,
     1499                                        conn,
     1500                                        smbreq->flags2 & FLAGS2_DFS_PATHNAMES,
     1501                                        smbreq,
     1502                                        name_in,
     1503                                        ucf_flags,
     1504                                        ppath_contains_wcard,
     1505                                        pp_smb_fname);
     1506}
Note: See TracChangeset for help on using the changeset viewer.