Changeset 988 for vendor/current/source3/smbd/filename.c
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source3/smbd/filename.c
r860 r988 29 29 #include "fake_file.h" 30 30 #include "smbd/smbd.h" 31 #include "smbd/globals.h" 31 32 32 33 static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx, 33 34 connection_struct *conn, 34 const char *orig_path,35 35 struct smb_filename *smb_fname); 36 36 … … 56 56 57 57 static NTSTATUS determine_path_error(const char *name, 58 bool allow_wcard_last_component) 58 bool allow_wcard_last_component, 59 bool posix_pathnames) 59 60 { 60 61 const char *p; 62 bool name_has_wild = false; 61 63 62 64 if (!allow_wcard_last_component) { … … 75 77 p = strchr(name, '/'); 76 78 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))) { 78 84 /* Error code at the end of a pathname. */ 79 85 return NT_STATUS_OBJECT_NAME_INVALID; … … 123 129 NTSTATUS status; 124 130 int ret; 131 bool parent_fname_has_wild = false; 125 132 126 133 ZERO_STRUCT(parent_fname); … … 131 138 } 132 139 140 if (!posix_pathnames) { 141 parent_fname_has_wild = ms_has_wild(parent_fname.base_name); 142 } 143 133 144 /* 134 145 * If there was no parent component in … … 138 149 */ 139 150 if ((smb_fname->base_name == last_component) || 140 ms_has_wild(parent_fname.base_name)) {151 parent_fname_has_wild) { 141 152 return NT_STATUS_OK; 142 153 } … … 161 172 162 173 /* Parent exists - set "start" to be the 163 * last comp nent to shorten the tree walk. */164 165 /* 166 * Safe to use CONST_DISCARD174 * last component to shorten the tree walk. */ 175 176 /* 177 * Safe to use discard_const_p 167 178 * here as last_component points 168 179 * into our smb_fname->base_name. 169 180 */ 170 *pp_start = CONST_DISCARD(char *,last_component);181 *pp_start = discard_const_p(char, last_component); 171 182 172 183 /* Update dirpath. */ … … 225 236 { 226 237 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; 228 247 char *dirpath = NULL; 229 248 char *stream = NULL; 230 249 bool component_was_mangled = False; 231 250 bool name_has_wildcard = False; 232 bool posix_pathnames = false;251 bool posix_pathnames = (ucf_flags & UCF_POSIX_PATHNAMES); 233 252 bool allow_wcard_last_component = 234 253 (ucf_flags & UCF_ALWAYS_ALLOW_WCARD_LCOMP); … … 300 319 } else { 301 320 status =determine_path_error(&orig_path[2], 302 allow_wcard_last_component); 321 allow_wcard_last_component, 322 posix_pathnames); 303 323 } 304 324 goto err; … … 323 343 if (conn->case_sensitive && !conn->case_preserve && 324 344 !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 } 326 350 } 327 351 … … 344 368 } 345 369 } 346 347 posix_pathnames = (lp_posix_pathnames() ||348 (ucf_flags & UCF_POSIX_PATHNAMES));349 370 350 371 /* … … 367 388 *stream = '\0'; 368 389 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 } 369 419 } 370 420 } … … 406 456 */ 407 457 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 } 413 466 } 414 467 … … 596 649 } else { 597 650 status = determine_path_error(end+1, 598 allow_wcard_last_component); 651 allow_wcard_last_component, 652 posix_pathnames); 599 653 } 600 654 goto fail; … … 604 658 the last component. */ 605 659 606 name_has_wildcard = ms_has_wild(start); 660 if (!posix_pathnames) { 661 name_has_wildcard = ms_has_wild(start); 662 } 607 663 608 664 /* Wildcards never valid within a pathname. */ … … 716 772 * here. 717 773 */ 774 718 775 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 { 720 780 /* 721 781 * This is the dropbox … … 729 789 * users creating a file. 730 790 */ 731 status = NT_STATUS_OBJECT_PATH_NOT_FOUND; 732 } else { 733 status = NT_STATUS_ACCESS_DENIED; 791 errno = 0; 734 792 } 735 goto fail;736 793 } 737 794 … … 764 821 conn->params) && 765 822 !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 } 768 830 } 769 831 … … 971 1033 972 1034 /* 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); 974 1036 if (!NT_STATUS_IS_OK(status)) { 975 1037 goto fail; … … 981 1043 fail: 982 1044 DEBUG(10, ("dirpath = [%s] start = [%s]\n", dirpath, start)); 983 if ( *dirpath != '\0') {1045 if (dirpath && *dirpath != '\0') { 984 1046 smb_fname->base_name = talloc_asprintf(smb_fname, "%s/%s", 985 1047 dirpath, start); … … 1002 1064 1003 1065 /**************************************************************************** 1004 Ensure a path is not veto d.1066 Ensure a path is not vetoed. 1005 1067 ****************************************************************************/ 1006 1068 1007 NTSTATUS check_veto_path(connection_struct *conn, const char *name)1069 static NTSTATUS check_veto_path(connection_struct *conn, const char *name) 1008 1070 { 1009 1071 if (IS_VETO_PATH(conn, name)) { … … 1033 1095 } 1034 1096 1035 if (!lp_widelinks(SNUM(conn)) || !lp_ symlinks(SNUM(conn))) {1097 if (!lp_widelinks(SNUM(conn)) || !lp_follow_symlinks(SNUM(conn))) { 1036 1098 status = check_reduced_name(conn,name); 1037 1099 if (!NT_STATUS_IS_OK(status)) { … … 1043 1105 1044 1106 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 1114 static 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); 1045 1126 } 1046 1127 … … 1204 1285 static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx, 1205 1286 connection_struct *conn, 1206 const char *orig_path,1207 1287 struct smb_filename *smb_fname) 1208 1288 { … … 1282 1362 * @param conn connection struct for vfs calls. 1283 1363 * @param dfs_path Whether this path requires dfs resolution. 1364 * @param smbreq SMB request if we're using privileges. 1284 1365 * @param name_in The unconverted name. 1285 1366 * @param ucf_flags flags to pass through to unix_convert(). … … 1295 1376 * error otherwise. 1296 1377 */ 1378 static 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 1297 1467 NTSTATUS filename_convert(TALLOC_CTX *ctx, 1298 1468 connection_struct *conn, … … 1303 1473 struct smb_filename **pp_smb_fname) 1304 1474 { 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); 1371 1483 } 1484 1485 /* 1486 * Go through all the steps to validate a filename. 1487 * root (privileged) version. 1488 */ 1489 1490 NTSTATUS 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.