Changeset 988 for vendor/current/source3/smbd/dir.c
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source3/smbd/dir.c
r919 r988 25 25 #include "libcli/security/security.h" 26 26 #include "lib/util/bitmap.h" 27 #include "../lib/util/memcache.h" 28 #include "../librpc/gen_ndr/open_files.h" 27 29 28 30 /* … … 35 37 #define DOT_DOT_DIRECTORY_OFFSET ((long)0x80000000) 36 38 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 37 44 /* Make directory handle internals available. */ 38 45 … … 44 51 struct smb_Dir { 45 52 connection_struct *conn; 46 SMB_STRUCT_DIR *dir;53 DIR *dir; 47 54 long offset; 48 55 char *dir_path; … … 58 65 struct dptr_struct *next, *prev; 59 66 int dnum; 60 uint16 spid;67 uint16_t spid; 61 68 struct connection_struct *conn; 62 69 struct smb_Dir *dir_hnd; 63 70 bool expect_close; 64 71 char *wcard; 65 uint32 attr;72 uint32_t attr; 66 73 char *path; 67 74 bool has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */ 68 75 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; 69 79 }; 70 80 … … 72 82 files_struct *fsp, 73 83 const char *mask, 74 uint32 attr); 84 uint32_t attr); 85 86 static void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset); 75 87 76 88 #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 }123 89 124 90 /**************************************************************************** … … 151 117 DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum)); 152 118 TALLOC_FREE(dptr->dir_hnd); 119 TALLOC_FREE(dptr->dptr_cache); 120 dptr->counter = 0; 153 121 } 154 122 } … … 204 172 DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr->path, 205 173 strerror(errno))); 206 return False;174 return NULL; 207 175 } 208 176 } … … 218 186 ****************************************************************************/ 219 187 220 c har *dptr_path(struct smbd_server_connection *sconn, int key)188 const char *dptr_path(struct smbd_server_connection *sconn, int key) 221 189 { 222 190 struct dptr_struct *dptr = dptr_get(sconn, key, false); … … 230 198 ****************************************************************************/ 231 199 232 c har *dptr_wcard(struct smbd_server_connection *sconn, int key)200 const char *dptr_wcard(struct smbd_server_connection *sconn, int key) 233 201 { 234 202 struct dptr_struct *dptr = dptr_get(sconn, key, false); … … 242 210 ****************************************************************************/ 243 211 244 uint16 dptr_attr(struct smbd_server_connection *sconn, int key)212 uint16_t dptr_attr(struct smbd_server_connection *sconn, int key) 245 213 { 246 214 struct dptr_struct *dptr = dptr_get(sconn, key, false); … … 284 252 done: 285 253 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); 291 255 } 292 256 … … 371 335 372 336 void dptr_closepath(struct smbd_server_connection *sconn, 373 char *path,uint16 spid)337 char *path,uint16_t spid) 374 338 { 375 339 struct dptr_struct *dptr, *next; … … 416 380 } 417 381 } 382 } 383 384 /**************************************************************************** 385 Safely do an OpenDir as root, ensuring we're in the right place. 386 ****************************************************************************/ 387 388 static 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; 418 433 } 419 434 … … 427 442 ****************************************************************************/ 428 443 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) 444 NTSTATUS 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) 432 449 { 433 450 struct smbd_server_connection *sconn = conn->sconn; 434 451 struct dptr_struct *dptr = NULL; 435 452 struct smb_Dir *dir_hnd; 436 NTSTATUS status;437 453 438 454 if (fsp && fsp->is_directory && fsp->fh->fd != -1) { … … 452 468 453 469 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 } 454 476 dir_hnd = OpenDir_fsp(NULL, conn, fsp, wcard, attr); 455 477 } 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); 457 503 if (!NT_STATUS_IS_OK(status)) { 458 504 return status; 459 505 } 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 } 461 515 } 462 516 … … 469 523 } 470 524 471 dptr = SMB_MALLOC_P(struct dptr_struct);525 dptr = talloc_zero(NULL, struct dptr_struct); 472 526 if(!dptr) { 473 DEBUG(0,(" malloc fail in dptr_create.\n"));527 DEBUG(0,("talloc fail in dptr_create.\n")); 474 528 TALLOC_FREE(dir_hnd); 475 529 return NT_STATUS_NO_MEMORY; 476 530 } 477 531 478 ZERO_STRUCTP(dptr); 479 480 dptr->path = SMB_STRDUP(path); 532 dptr->path = talloc_strdup(dptr, path); 481 533 if (!dptr->path) { 482 SAFE_FREE(dptr);534 TALLOC_FREE(dptr); 483 535 TALLOC_FREE(dir_hnd); 484 536 return NT_STATUS_NO_MEMORY; … … 488 540 dptr->spid = spid; 489 541 dptr->expect_close = expect_close; 490 dptr->wcard = SMB_STRDUP(wcard);542 dptr->wcard = talloc_strdup(dptr, wcard); 491 543 if (!dptr->wcard) { 492 SAFE_FREE(dptr->path); 493 SAFE_FREE(dptr); 544 TALLOC_FREE(dptr); 494 545 TALLOC_FREE(dir_hnd); 495 546 return NT_STATUS_NO_MEMORY; 496 547 } 497 if (lp_posix_pathnames() || (wcard[0] == '.' && wcard[1] == 0)) { 548 if ((req != NULL && req->posix_pathnames) || 549 (wcard[0] == '.' && wcard[1] == 0)) { 498 550 dptr->has_wild = True; 499 551 } else { … … 530 582 if(dptr->dnum == -1 || dptr->dnum > 254) { 531 583 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); 535 585 TALLOC_FREE(dir_hnd); 536 586 return NT_STATUS_TOO_MANY_OPENED_FILES; … … 562 612 if(dptr->dnum == -1 || dptr->dnum < 255) { 563 613 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); 567 615 TALLOC_FREE(dir_hnd); 568 616 return NT_STATUS_TOO_MANY_OPENED_FILES; … … 624 672 } 625 673 674 bool dptr_get_priv(struct dptr_struct *dptr) 675 { 676 return dptr->priv; 677 } 678 679 void dptr_set_priv(struct dptr_struct *dptr) 680 { 681 dptr->priv = true; 682 } 683 626 684 /**************************************************************************** 627 685 Return the next visible file name, skipping veto'd and invisible files. … … 651 709 ****************************************************************************/ 652 710 653 char *dptr_ReadDirName(TALLOC_CTX *ctx,654 struct dptr_struct *dptr,655 long *poffset,656 SMB_STRUCT_STAT *pst)711 static char *dptr_ReadDirName(TALLOC_CTX *ctx, 712 struct dptr_struct *dptr, 713 long *poffset, 714 SMB_STRUCT_STAT *pst) 657 715 { 658 716 struct smb_filename smb_fname_base; … … 715 773 716 774 /* 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 }; 719 776 720 777 if (SMB_VFS_STAT(dptr->conn, &smb_fname_base) == 0) { … … 794 851 795 852 /**************************************************************************** 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 /****************************************************************************805 853 Initialize variables & state data at the beginning of all search SMB requests. 806 854 ****************************************************************************/ … … 808 856 { 809 857 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 864 static 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; 810 928 } 811 929 … … 819 937 unsigned char *buf = (unsigned char *)buf1; 820 938 struct dptr_struct *dptr = dptr_get(sconn, key, false); 821 uint32 939 uint32_t wire_offset; 822 940 if (!dptr) { 823 941 DEBUG(1,("filling null dirptr %d\n",key)); 824 942 return(False); 825 943 } 826 offset = (uint32)TellDir(dptr->dir_hnd);944 wire_offset = map_dir_offset_to_wire(dptr,TellDir(dptr->dir_hnd)); 827 945 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)); 829 947 buf[0] = key; 830 SIVAL(buf,1, offset);948 SIVAL(buf,1,wire_offset); 831 949 return(True); 950 } 951 952 /**************************************************************************** 953 Map a 32-bit wire cookie to a native directory offset. 954 ****************************************************************************/ 955 956 static 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; 832 992 } 833 993 … … 841 1001 unsigned int key = *(unsigned char *)buf; 842 1002 struct dptr_struct *dptr = dptr_get(sconn, key, false); 843 uint32 1003 uint32_t wire_offset; 844 1004 long seekoff; 845 1005 … … 849 1009 } 850 1010 *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); 857 1013 SeekDir(dptr->dir_hnd,seekoff); 858 1014 DEBUG(3,("fetching dirptr %d for path %s at offset %d\n", … … 876 1032 DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr->path)); 877 1033 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 matching894 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 else900 return False;901 }902 903 return True;904 1034 } 905 1035 … … 940 1070 size_t slashlen; 941 1071 size_t pathlen; 1072 bool dirptr_path_is_dot = ISDOT(dirptr->path); 942 1073 943 1074 *_smb_fname = NULL; … … 950 1081 long cur_offset; 951 1082 long prev_offset; 952 SMB_STRUCT_STAT sbuf ;1083 SMB_STRUCT_STAT sbuf = { 0 }; 953 1084 char *dname = NULL; 954 1085 bool isdots; … … 958 1089 uint32_t mode = 0; 959 1090 bool ok; 960 NTSTATUS status;961 1091 962 1092 cur_offset = dptr_TellDir(dirptr); … … 1005 1135 } 1006 1136 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 } 1011 1149 1012 1150 /* 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 }; 1016 1154 1017 1155 ok = mode_fn(ctx, private_data, &smb_fname, &mode); … … 1023 1161 } 1024 1162 1025 if (!dir_check_ftype( conn,mode, dirtype)) {1163 if (!dir_check_ftype(mode, dirtype)) { 1026 1164 DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n", 1027 1165 fname, (unsigned int)mode, (unsigned int)dirtype)); … … 1054 1192 TALLOC_FREE(dname); 1055 1193 1056 status = copy_smb_filename(ctx, &smb_fname, _smb_fname);1194 *_smb_fname = cp_smb_filename(ctx, &smb_fname); 1057 1195 TALLOC_FREE(pathreal); 1058 if ( !NT_STATUS_IS_OK(status)) {1196 if (*_smb_fname == NULL) { 1059 1197 return false; 1060 1198 } … … 1086 1224 char mname[13]; 1087 1225 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 } 1088 1250 1089 1251 if (!mangle_is_8_3(dname, false, conn->params)) { … … 1136 1298 uint32_t dirtype, 1137 1299 char **_fname, 1138 SMB_OFF_T*_size,1300 off_t *_size, 1139 1301 uint32_t *_mode, 1140 1302 struct timespec *_date, … … 1183 1345 struct smb_filename *smb_fname) 1184 1346 { 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 1185 1356 /* 1186 1357 * Never hide files from the root user. … … 1193 1364 } 1194 1365 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; 1196 1419 } 1197 1420 … … 1262 1485 const char *name, SMB_STRUCT_STAT *pst, bool use_veto) 1263 1486 { 1264 bool hide_unreadable = lp_hide unreadable(SNUM(conn));1265 bool hide_unwriteable = lp_hide unwriteable_files(SNUM(conn));1487 bool hide_unreadable = lp_hide_unreadable(SNUM(conn)); 1488 bool hide_unwriteable = lp_hide_unwriteable_files(SNUM(conn)); 1266 1489 bool hide_special = lp_hide_special_files(SNUM(conn)); 1267 1490 char *entry = NULL; 1268 1491 struct smb_filename *smb_fname_base = NULL; 1269 NTSTATUS status;1270 1492 bool ret = false; 1271 1493 … … 1288 1510 1289 1511 /* Create an smb_filename with stream_name == NULL. */ 1290 s tatus = 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) { 1293 1515 ret = false; 1294 1516 goto out; … … 1303 1525 ret = true; 1304 1526 goto out; 1305 } else {1306 *pst = smb_fname_base->st;1307 1527 } 1528 *pst = smb_fname_base->st; 1308 1529 } 1309 1530 … … 1371 1592 const char *name, 1372 1593 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); 1376 1597 struct smbd_server_connection *sconn = conn->sconn; 1377 1598 … … 1415 1636 files_struct *fsp, 1416 1637 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); 1420 1641 struct smbd_server_connection *sconn = conn->sconn; 1421 1642 … … 1499 1720 *ptalloced = NULL; 1500 1721 return n; 1501 } else if (*poffset == END_OF_DIRECTORY_OFFSET) { 1722 } 1723 1724 if (*poffset == END_OF_DIRECTORY_OFFSET) { 1502 1725 *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET; 1503 1726 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); 1508 1731 1509 1732 while ((n = vfs_readdirname(conn, dirp->dir, sbuf, &talloced))) { … … 1583 1806 ********************************************************************/ 1584 1807 1585 void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset)1808 static void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset) 1586 1809 { 1587 1810 struct name_cache_entry *e; … … 1592 1815 1593 1816 if (dirp->name_cache == NULL) { 1594 dirp->name_cache = TALLOC_ZERO_ARRAY(1817 dirp->name_cache = talloc_zero_array( 1595 1818 dirp, struct name_cache_entry, dirp->name_cache_size); 1596 1819 … … 1654 1877 } 1655 1878 1879 struct 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 1887 static 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 1926 static 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 1954 struct have_file_open_below_state { 1955 bool found_one; 1956 }; 1957 1958 static 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 1967 bool 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 1656 1990 /***************************************************************** 1657 1991 Is this directory empty ? … … 1663 1997 long dirpos = 0; 1664 1998 const char *dname = NULL; 1999 const char *dirname = fsp->fsp_name->base_name; 1665 2000 char *talloced = NULL; 1666 2001 SMB_STRUCT_STAT st; … … 1685 2020 } 1686 2021 1687 if (!is_visible_file(conn, fsp->fsp_name->base_name, dname, &st, True)) {2022 if (!is_visible_file(conn, dirname, dname, &st, True)) { 1688 2023 TALLOC_FREE(talloced); 1689 2024 continue; 1690 2025 } 1691 2026 1692 DEBUG(10,(" can_delete_directory_fsp:got name %s - can't delete\n",2027 DEBUG(10,("got name %s - can't delete\n", 1693 2028 dname )); 1694 2029 status = NT_STATUS_DIRECTORY_NOT_EMPTY; … … 1698 2033 TALLOC_FREE(dir_hnd); 1699 2034 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.