* autoload.cc (NtCreateFile): Add.
* dir.cc (mkdir): Change set_file_attribute call to indicate that NT security isn't used. * fhandler.cc (fhandler_base::open_9x): New method, created from fhandler_base::open. (fhandler_base::open): Rearrange to use NtCreateFile instead of CreateFile. * fhandler.h (enum query_state): Redefine query_null_access to query_stat_control. query_null_access isn't allowed in NtCreateFile. (fhandler_base::open_9x): Declare. * fhandler_disk_file.cc (fhandler_base::fstat_fs): Use query_stat_control first, query_read_control if that fails. (fhandler_disk_file::fchmod): Call enable_restore_privilege before trying to open for query_write_control. Don't fall back to opening for query_read_control. (fhandler_disk_file::fchown): Ditto. (fhandler_disk_file::facl): Only request restore privilege and query access necessary for given cmd. * fhandler_raw.cc (fhandler_dev_raw::open): Call fhandler_base::open instead of opening device here. * ntdll.h (NtCreateFile): Declare. * path.cc (symlink_worker): Change set_file_attribute call to indicate that NT security isn't used. * sec_acl.cc (getacl): Fix bracketing. * sec_helper.cc (enable_restore_privilege): New function. * security.cc (str2buf2uni_cat): New function. (write_sd): Don't request restore permission here. * security.h (set_process_privileges): Drop stale declaration. (str2buf2uni): Declare. (str2buf2uni_cat): Declare. (enable_restore_privilege): Declare. * syscalls.cc (fchown32): Return immediate success on 9x.
This commit is contained in:
		
							parent
							
								
									e2c248c18b
								
							
						
					
					
						commit
						e859706578
					
				|  | @ -1,3 +1,38 @@ | |||
| 2004-04-16  Corinna Vinschen  <corinna@vinschen.de> | ||||
| 
 | ||||
| 	* autoload.cc (NtCreateFile): Add. | ||||
| 	* dir.cc (mkdir): Change set_file_attribute call to indicate that | ||||
| 	NT security isn't used. | ||||
| 	* fhandler.cc (fhandler_base::open_9x): New method, created from | ||||
| 	fhandler_base::open. | ||||
| 	(fhandler_base::open): Rearrange to use NtCreateFile instead of | ||||
| 	CreateFile. | ||||
| 	* fhandler.h (enum query_state): Redefine query_null_access to | ||||
| 	query_stat_control.  query_null_access isn't allowed in NtCreateFile. | ||||
| 	(fhandler_base::open_9x): Declare. | ||||
| 	* fhandler_disk_file.cc (fhandler_base::fstat_fs): Use | ||||
| 	query_stat_control first, query_read_control if that fails. | ||||
| 	(fhandler_disk_file::fchmod): Call enable_restore_privilege before | ||||
| 	trying to open for query_write_control.  Don't fall back to | ||||
| 	opening for query_read_control. | ||||
| 	(fhandler_disk_file::fchown): Ditto. | ||||
| 	(fhandler_disk_file::facl):  Only request restore privilege and query | ||||
| 	access necessary for given cmd. | ||||
| 	* fhandler_raw.cc (fhandler_dev_raw::open): Call fhandler_base::open | ||||
| 	instead of opening device here. | ||||
| 	* ntdll.h (NtCreateFile): Declare. | ||||
| 	* path.cc (symlink_worker): Change set_file_attribute call to indicate | ||||
| 	that NT security isn't used. | ||||
| 	* sec_acl.cc (getacl): Fix bracketing. | ||||
| 	* sec_helper.cc (enable_restore_privilege): New function. | ||||
| 	* security.cc (str2buf2uni_cat): New function. | ||||
| 	(write_sd): Don't request restore permission here. | ||||
| 	* security.h (set_process_privileges): Drop stale declaration. | ||||
| 	(str2buf2uni): Declare. | ||||
| 	(str2buf2uni_cat): Declare. | ||||
| 	(enable_restore_privilege): Declare. | ||||
| 	* syscalls.cc (fchown32): Return immediate success on 9x. | ||||
| 
 | ||||
| 2004-04-15  Christopher Faylor  <cgf@alum.bu.edu> | ||||
| 
 | ||||
| 	* autoload.cc (dll_chain1): Rename to dll_chain.  Remove old dll_chain | ||||
|  |  | |||
|  | @ -375,6 +375,7 @@ LoadDLLfunc (NetUserGetGroups, 28, netapi32) | |||
| LoadDLLfunc (NetUserGetInfo, 16, netapi32) | ||||
| LoadDLLfunc (NetWkstaUserGetInfo, 12, netapi32) | ||||
| 
 | ||||
| LoadDLLfuncEx (NtCreateFile, 44, ntdll, 1) | ||||
| LoadDLLfuncEx (NtCreateToken, 52, ntdll, 1) | ||||
| LoadDLLfuncEx (NtMapViewOfSection, 40, ntdll, 1) | ||||
| LoadDLLfuncEx (NtOpenFile, 24, ntdll, 1) | ||||
|  |  | |||
|  | @ -284,7 +284,7 @@ mkdir (const char *dir, mode_t mode) | |||
|   if (CreateDirectoryA (real_dir.get_win32 (), &sa)) | ||||
|     { | ||||
|       if (!allow_ntsec && allow_ntea) | ||||
| 	set_file_attribute (real_dir.has_acls (), NULL, real_dir.get_win32 (), | ||||
| 	set_file_attribute (false, NULL, real_dir.get_win32 (), | ||||
| 			    S_IFDIR | ((mode & 07777) & ~cygheap->umask)); | ||||
| #ifdef HIDDEN_DOT_FILES | ||||
|       char *c = strrchr (real_dir.get_win32 (), '\\'); | ||||
|  |  | |||
|  | @ -28,6 +28,8 @@ details. */ | |||
| #include <assert.h> | ||||
| #include <limits.h> | ||||
| #include <winioctl.h> | ||||
| #include <ntdef.h> | ||||
| #include "ntdll.h" | ||||
| 
 | ||||
| static NO_COPY const int CHUNK_SIZE = 1024; /* Used for crlf conversions */ | ||||
| 
 | ||||
|  | @ -425,7 +427,7 @@ done: | |||
| 
 | ||||
| /* Open system call handler function. */ | ||||
| int | ||||
| fhandler_base::open (int flags, mode_t mode) | ||||
| fhandler_base::open_9x (int flags, mode_t mode) | ||||
| { | ||||
|   int res = 0; | ||||
|   HANDLE x; | ||||
|  | @ -435,7 +437,7 @@ fhandler_base::open (int flags, mode_t mode) | |||
|   SECURITY_ATTRIBUTES sa = sec_none; | ||||
|   security_descriptor sd; | ||||
| 
 | ||||
|   syscall_printf ("(%s, %p) query_open %d", get_win32_name (), flags, query_open ()); | ||||
|   syscall_printf ("(%s, %p)", get_win32_name (), flags); | ||||
| 
 | ||||
|   if (get_win32_name () == NULL) | ||||
|     { | ||||
|  | @ -443,34 +445,12 @@ fhandler_base::open (int flags, mode_t mode) | |||
|       goto done; | ||||
|     } | ||||
| 
 | ||||
|   switch (query_open ()) | ||||
|     { | ||||
|       case query_null_access: | ||||
| 	access = 0; | ||||
| 	break; | ||||
|       case query_read_control: | ||||
| 	access = READ_CONTROL; | ||||
| 	break; | ||||
|       case query_write_control: | ||||
| 	access = READ_CONTROL | WRITE_OWNER | WRITE_DAC; | ||||
| 	break; | ||||
|       default: | ||||
| 	if (get_major () == DEV_TAPE_MAJOR) | ||||
| 	  access = GENERIC_READ | GENERIC_WRITE; | ||||
| 	else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDONLY) | ||||
| 	  access = GENERIC_READ; | ||||
| 	else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY) | ||||
| 	  access = GENERIC_WRITE; | ||||
| 	else | ||||
| 	  access = GENERIC_READ | GENERIC_WRITE; | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|   /* Allow reliable lseek on disk devices. */ | ||||
|   if (get_major () == DEV_FLOPPY_MAJOR) | ||||
|     access |= GENERIC_READ; | ||||
| 
 | ||||
|   /* FIXME: O_EXCL handling?  */ | ||||
|   if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDONLY) | ||||
|     access = GENERIC_READ; | ||||
|   else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY) | ||||
|     access = GENERIC_WRITE; | ||||
|   else | ||||
|     access = GENERIC_READ | GENERIC_WRITE; | ||||
| 
 | ||||
|   if ((flags & O_TRUNC) && ((flags & O_ACCMODE) != O_RDONLY)) | ||||
|     { | ||||
|  | @ -508,16 +488,6 @@ fhandler_base::open (int flags, mode_t mode) | |||
|     } | ||||
| #endif | ||||
| 
 | ||||
|   /* CreateFile() with dwDesiredAccess == 0 when called on remote
 | ||||
|      share returns some handle, even if file doesn't exist. This code | ||||
|      works around this bug. */ | ||||
|   if (query_open () && isremote () && | ||||
|       creation_distribution == OPEN_EXISTING && !pc.exists ()) | ||||
|     { | ||||
|       set_errno (ENOENT); | ||||
|       goto done; | ||||
|     } | ||||
| 
 | ||||
|   /* If mode has no write bits set, we set the R/O attribute. */ | ||||
|   if (!(mode & (S_IWUSR | S_IWGRP | S_IWOTH))) | ||||
|     file_attributes |= FILE_ATTRIBUTE_READONLY; | ||||
|  | @ -564,6 +534,162 @@ done: | |||
|   return res; | ||||
| } | ||||
| 
 | ||||
| /* Open system call handler function. */ | ||||
| int | ||||
| fhandler_base::open (int flags, mode_t mode) | ||||
| { | ||||
|   if (!wincap.is_winnt ()) | ||||
|     return fhandler_base::open_9x (flags, mode); | ||||
| 
 | ||||
|   int res = 0; | ||||
|   HANDLE x; | ||||
|   ULONG file_attributes = 0; | ||||
|   ULONG shared = wincap.shared (); | ||||
|   ULONG create_disposition; | ||||
|   ULONG create_options; | ||||
|   SECURITY_ATTRIBUTES sa = sec_none; | ||||
|   security_descriptor sd; | ||||
|   UNICODE_STRING upath; | ||||
|   WCHAR wpath[CYG_MAX_PATH + 10]; | ||||
|   OBJECT_ATTRIBUTES attr; | ||||
|   IO_STATUS_BLOCK io; | ||||
|   NTSTATUS status; | ||||
| 
 | ||||
|   syscall_printf ("(%s, %p)", get_win32_name (), flags); | ||||
|   if (get_win32_name () == NULL) | ||||
|     { | ||||
|       set_errno (ENOENT); | ||||
|       goto done; | ||||
|     } | ||||
|   if (get_win32_name ()[0] == '\\') | ||||
|     { | ||||
|       if (get_win32_name ()[1] == '\\') | ||||
|         { | ||||
| 	  str2buf2uni (upath, wpath, "\\??\\UNC"); | ||||
| 	  str2buf2uni_cat (upath, get_win32_name () + 1); | ||||
| 	} | ||||
|       else | ||||
| 	str2buf2uni (upath, wpath, get_win32_name ()); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       str2buf2uni (upath, wpath, "\\??\\"); | ||||
|       str2buf2uni_cat (upath, get_win32_name ()); | ||||
|     } | ||||
|   InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE | OBJ_INHERIT, | ||||
| 			      sa.lpSecurityDescriptor, NULL); | ||||
| 
 | ||||
|   switch (query_open ()) | ||||
|     { | ||||
|       case query_read_control: | ||||
|         access = READ_CONTROL; | ||||
|         create_options = FILE_OPEN_FOR_BACKUP_INTENT; | ||||
|         break; | ||||
|       case query_stat_control: | ||||
|         access = READ_CONTROL | FILE_READ_ATTRIBUTES; | ||||
|         create_options = FILE_OPEN_FOR_BACKUP_INTENT; | ||||
|         break; | ||||
|       case query_write_control: | ||||
|         access = READ_CONTROL | WRITE_OWNER | WRITE_DAC; | ||||
|         create_options = FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_FOR_RECOVERY; | ||||
|         break; | ||||
|       default: | ||||
|         create_options = 0; | ||||
| 	if (get_major () == DEV_TAPE_MAJOR && (flags & O_TEXT)) | ||||
| 	  { | ||||
| 	    /* O_TEXT is used to indicate write-through on tape devices */ | ||||
| 	    create_options |= FILE_WRITE_THROUGH; | ||||
| 	    flags &= ~O_TEXT; | ||||
| 	  } | ||||
| 	if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDONLY) | ||||
| 	  access = GENERIC_READ; | ||||
| 	else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY) | ||||
| 	  access = GENERIC_WRITE; | ||||
| 	else | ||||
| 	  access = GENERIC_READ | GENERIC_WRITE; | ||||
| 	/* Allow reliable lseek on disk devices. */ | ||||
| 	if (get_major () == DEV_FLOPPY_MAJOR) | ||||
| 	  access |= GENERIC_READ; | ||||
| 	else if (get_major () != DEV_SERIAL_MAJOR) | ||||
| 	  { | ||||
| 	    create_options |= FILE_SYNCHRONOUS_IO_NONALERT; | ||||
| 	    access |= SYNCHRONIZE; | ||||
| 	  } | ||||
| 	break; | ||||
|     } | ||||
| 
 | ||||
|   if ((flags & O_TRUNC) && ((flags & O_ACCMODE) != O_RDONLY)) | ||||
|     { | ||||
|       if (flags & O_CREAT) | ||||
| 	create_disposition = FILE_SUPERSEDE; | ||||
|       else | ||||
| 	create_disposition = FILE_OVERWRITE; | ||||
|     } | ||||
|   else if (flags & O_CREAT) | ||||
|     create_disposition = FILE_OPEN_IF; | ||||
|   else | ||||
|     create_disposition = FILE_OPEN; | ||||
| 
 | ||||
|   if ((flags & O_EXCL) && (flags & O_CREAT)) | ||||
|     create_disposition = FILE_CREATE; | ||||
| 
 | ||||
|   if (flags & O_APPEND) | ||||
|     append_mode (true); | ||||
| 
 | ||||
|   if (flags & O_CREAT && get_device () == FH_FS) | ||||
|     { | ||||
|       file_attributes = FILE_ATTRIBUTE_NORMAL; | ||||
|       /* If mode has no write bits set, we set the R/O attribute. */ | ||||
|       if (!(mode & (S_IWUSR | S_IWGRP | S_IWOTH))) | ||||
| 	file_attributes |= FILE_ATTRIBUTE_READONLY; | ||||
| #ifdef HIDDEN_DOT_FILES | ||||
|       char *c = strrchr (get_win32_name (), '\\'); | ||||
|       if ((c && c[1] == '.') || *get_win32_name () == '.') | ||||
| 	file_attributes |= FILE_ATTRIBUTE_HIDDEN; | ||||
| #endif | ||||
|       /* If the file should actually be created and ntsec is on,
 | ||||
| 	 set files attributes. */ | ||||
|       if (allow_ntsec && has_acls ()) | ||||
| 	{ | ||||
| 	  set_security_attribute (mode, &sa, sd); | ||||
| 	  attr.SecurityDescriptor = sa.lpSecurityDescriptor; | ||||
| 	} | ||||
|     } | ||||
| 
 | ||||
|   status = NtCreateFile (&x, access, &attr, &io, NULL, file_attributes, shared, | ||||
|   			 create_disposition, create_options, NULL, 0); | ||||
|   if (!NT_SUCCESS (status)) | ||||
|     { | ||||
|       if (!wincap.can_open_directories () && pc.isdir ()) | ||||
| 	{ | ||||
| 	  if (flags & (O_CREAT | O_EXCL) == (O_CREAT | O_EXCL)) | ||||
| 	    set_errno (EEXIST); | ||||
| 	  else if (flags & (O_WRONLY | O_RDWR)) | ||||
| 	    set_errno (EISDIR); | ||||
| 	  else | ||||
| 	    nohandle (true); | ||||
| 	} | ||||
|       __seterrno_from_win_error (RtlNtStatusToDosError (status)); | ||||
|       if (!nohandle ()) | ||||
| 	goto done; | ||||
|    } | ||||
| 
 | ||||
|   syscall_printf ("%x = NtCreateFile " | ||||
|   		  "(%p, %x, %s, io, NULL, %x, %x, %x, %x, NULL, 0)", | ||||
| 		  status, x, access, get_win32_name (), file_attributes, shared, | ||||
| 		  create_disposition, create_options); | ||||
| 
 | ||||
|   set_io_handle (x); | ||||
|   set_flags (flags, pc.binmode ()); | ||||
| 
 | ||||
|   res = 1; | ||||
|   set_open_status (); | ||||
| done: | ||||
|   syscall_printf ("%d = fhandler_base::open (%s, %p)", res, get_win32_name (), | ||||
| 		  flags); | ||||
|   return res; | ||||
| } | ||||
| 
 | ||||
| /* states:
 | ||||
|    open buffer in binary mode?  Just do the read. | ||||
| 
 | ||||
|  |  | |||
|  | @ -63,8 +63,8 @@ enum bg_check_types | |||
| 
 | ||||
| enum query_state { | ||||
|   no_query = 0, | ||||
|   query_null_access = 1, | ||||
|   query_read_control = 2, | ||||
|   query_read_control = 1, | ||||
|   query_stat_control = 2, | ||||
|   query_write_control = 3 | ||||
| }; | ||||
| 
 | ||||
|  | @ -226,6 +226,7 @@ class fhandler_base | |||
|   void fork_fixup (HANDLE parent, HANDLE &h, const char *name); | ||||
|   virtual bool need_fixup_before () const {return false;} | ||||
| 
 | ||||
|   int open_9x (int flags, mode_t mode = 0); | ||||
|   virtual int open (int flags, mode_t mode = 0); | ||||
|   int open_fs (int flags, mode_t mode = 0); | ||||
|   virtual int close (); | ||||
|  |  | |||
|  | @ -174,16 +174,16 @@ fhandler_base::fstat_fs (struct __stat64 *buf) | |||
|      then just do a "query open" as it is apparently much faster. */ | ||||
|   if (pc.exec_state () != dont_know_if_executable) | ||||
|     { | ||||
|       query_open (query_read_control); | ||||
|       if (pc.fs_is_fat () && !strpbrk (get_win32_name (), "?*|<>")) | ||||
| 	return fstat_by_name (buf); | ||||
|       query_open (query_stat_control); | ||||
|     } | ||||
|   if (!(oret = open_fs (open_flags, 0)) && get_errno () == EACCES) | ||||
|     { | ||||
|       /* If we couldn't open the file, try a query open with no permissions.
 | ||||
| 	 This allows us to determine *some* things about the file, at least. */ | ||||
|       pc.set_exec (0); | ||||
|       query_open (query_null_access); | ||||
|       query_open (query_read_control); | ||||
|       oret = open_fs (open_flags, 0); | ||||
|     } | ||||
| 
 | ||||
|  | @ -378,15 +378,15 @@ fhandler_disk_file::fchmod (mode_t mode) | |||
|   if (pc.is_fs_special ()) | ||||
|     return chmod_device (pc, mode); | ||||
| 
 | ||||
|   if (!get_io_handle ()) | ||||
|   if (wincap.has_security ()) | ||||
|     { | ||||
|       query_open (query_write_control); | ||||
|       if (!(oret = open_fs (O_BINARY, 0))) | ||||
|         { | ||||
| 	  query_open (query_read_control); | ||||
|       enable_restore_privilege (); | ||||
|       if (!get_io_handle ()) | ||||
| 	{ | ||||
| 	  query_open (query_write_control); | ||||
| 	  if (!(oret = open_fs (O_BINARY, 0))) | ||||
| 	    return -1; | ||||
|         } | ||||
| 	} | ||||
|     } | ||||
| 
 | ||||
|   if (!allow_ntsec && allow_ntea) /* Not necessary when manipulating SD. */ | ||||
|  | @ -423,15 +423,13 @@ int __stdcall | |||
| fhandler_disk_file::fchown (__uid32_t uid, __gid32_t gid) | ||||
| { | ||||
|   int oret = 0; | ||||
| 
 | ||||
|   enable_restore_privilege (); | ||||
|   if (!get_io_handle ()) | ||||
|     { | ||||
|       query_open (query_write_control); | ||||
|       if (!(oret = open_fs (O_BINARY, 0))) | ||||
|         { | ||||
| 	  query_open (query_read_control); | ||||
| 	  if (!(oret = open_fs (O_BINARY, 0))) | ||||
| 	    return -1; | ||||
|         } | ||||
| 	return -1; | ||||
|     } | ||||
| 
 | ||||
|   mode_t attrib = 0; | ||||
|  | @ -460,17 +458,6 @@ fhandler_disk_file::facl (int cmd, int nentries, __aclent32_t *aclbufp) | |||
|   int res = -1; | ||||
|   int oret = 0; | ||||
| 
 | ||||
|   if (!get_io_handle ()) | ||||
|     { | ||||
|       query_open (query_write_control); | ||||
|       if (!(oret = open_fs (O_BINARY, 0))) | ||||
|         { | ||||
| 	  query_open (query_read_control); | ||||
| 	  if (!(oret = open_fs (O_BINARY, 0))) | ||||
| 	    return -1; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|   if (!pc.has_acls () || !allow_ntsec) | ||||
|     { | ||||
|       switch (cmd) | ||||
|  | @ -485,30 +472,50 @@ fhandler_disk_file::facl (int cmd, int nentries, __aclent32_t *aclbufp) | |||
| 	      set_errno(EFAULT); | ||||
| 	    else if (nentries < MIN_ACL_ENTRIES) | ||||
| 	      set_errno (ENOSPC); | ||||
| 	    else if (!fstat_by_handle (&st)) | ||||
| 	    else | ||||
| 	      { | ||||
| 		aclbufp[0].a_type = USER_OBJ; | ||||
| 		aclbufp[0].a_id = st.st_uid; | ||||
| 		aclbufp[0].a_perm = (st.st_mode & S_IRWXU) >> 6; | ||||
| 		aclbufp[1].a_type = GROUP_OBJ; | ||||
| 		aclbufp[1].a_id = st.st_gid; | ||||
| 		aclbufp[1].a_perm = (st.st_mode & S_IRWXG) >> 3; | ||||
| 		aclbufp[2].a_type = OTHER_OBJ; | ||||
| 		aclbufp[2].a_id = ILLEGAL_GID; | ||||
| 		aclbufp[2].a_perm = st.st_mode & S_IRWXO; | ||||
| 		aclbufp[3].a_type = CLASS_OBJ;  | ||||
| 		aclbufp[3].a_id = ILLEGAL_GID; | ||||
| 		aclbufp[3].a_perm = S_IRWXU | S_IRWXG | S_IRWXO; | ||||
| 		res = MIN_ACL_ENTRIES; | ||||
| 		if (!get_io_handle ()) | ||||
| 		  { | ||||
| 		    query_open (query_read_control); | ||||
| 		    if (!(oret = open_fs (O_BINARY, 0))) | ||||
| 		      return -1; | ||||
| 		  } | ||||
| 	        if (!fstat_by_handle (&st)) | ||||
| 		  { | ||||
| 		    aclbufp[0].a_type = USER_OBJ; | ||||
| 		    aclbufp[0].a_id = st.st_uid; | ||||
| 		    aclbufp[0].a_perm = (st.st_mode & S_IRWXU) >> 6; | ||||
| 		    aclbufp[1].a_type = GROUP_OBJ; | ||||
| 		    aclbufp[1].a_id = st.st_gid; | ||||
| 		    aclbufp[1].a_perm = (st.st_mode & S_IRWXG) >> 3; | ||||
| 		    aclbufp[2].a_type = OTHER_OBJ; | ||||
| 		    aclbufp[2].a_id = ILLEGAL_GID; | ||||
| 		    aclbufp[2].a_perm = st.st_mode & S_IRWXO; | ||||
| 		    aclbufp[3].a_type = CLASS_OBJ;  | ||||
| 		    aclbufp[3].a_id = ILLEGAL_GID; | ||||
| 		    aclbufp[3].a_perm = S_IRWXU | S_IRWXG | S_IRWXO; | ||||
| 		    res = MIN_ACL_ENTRIES; | ||||
| 		  } | ||||
| 	      } | ||||
| 	    break; | ||||
| 	  case GETACLCNT: | ||||
| 	    res = MIN_ACL_ENTRIES; | ||||
| 	    break; | ||||
| 	  default: | ||||
| 	    set_errno (EINVAL); | ||||
| 	    break; | ||||
| 	} | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       if (cmd == SETACL) | ||||
| 	enable_restore_privilege (); | ||||
|       if (!get_io_handle ()) | ||||
| 	{ | ||||
| 	  query_open (cmd == SETACL ? query_write_control : query_read_control); | ||||
| 	  if (!(oret = open_fs (O_BINARY, 0))) | ||||
| 	    return -1; | ||||
| 	} | ||||
|       switch (cmd) | ||||
| 	{ | ||||
| 	  case SETACL: | ||||
|  |  | |||
|  | @ -144,41 +144,16 @@ fhandler_dev_raw::open (int flags, mode_t) | |||
|   flags &= ~(O_CREAT | O_TRUNC); | ||||
|   flags |= O_BINARY; | ||||
| 
 | ||||
|   DWORD access = GENERIC_READ | SYNCHRONIZE; | ||||
|   if (get_major () == DEV_TAPE_MAJOR | ||||
|       || (flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY | ||||
|       || (flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDWR) | ||||
|     access |= GENERIC_WRITE; | ||||
|     flags = ((flags & ~(O_WRONLY | O_RDWR)) | O_RDWR); | ||||
| 
 | ||||
|   extern void str2buf2uni (UNICODE_STRING &, WCHAR *, const char *); | ||||
|   UNICODE_STRING dev; | ||||
|   WCHAR devname[CYG_MAX_PATH + 1]; | ||||
|   str2buf2uni (dev, devname, get_win32_name ()); | ||||
|   OBJECT_ATTRIBUTES attr; | ||||
|   ULONG options = FILE_SYNCHRONOUS_IO_NONALERT; | ||||
|   /* The O_TEXT flag is used to indicate write-through on tape devices */ | ||||
|   if (get_major () == DEV_TAPE_MAJOR && (flags & O_TEXT)) | ||||
|     options |= FILE_WRITE_THROUGH; | ||||
|   flags &= ~O_TEXT; | ||||
|   InitializeObjectAttributes (&attr, &dev, OBJ_CASE_INSENSITIVE, NULL, NULL); | ||||
| 
 | ||||
|   HANDLE h; | ||||
|   IO_STATUS_BLOCK io; | ||||
|   NTSTATUS status = NtOpenFile (&h, access, &attr, &io, 0 /* excl. access */, | ||||
| 				options); | ||||
|   if (!NT_SUCCESS (status)) | ||||
|     { | ||||
|       __seterrno_from_win_error (RtlNtStatusToDosError (status)); | ||||
|       return 0; | ||||
|     } | ||||
| 
 | ||||
|   set_io_handle (h); | ||||
|   set_flags ((flags & ~O_TEXT) | O_BINARY); | ||||
| 
 | ||||
|   if (devbufsiz > 1L) | ||||
|   int res = fhandler_base::open (flags, 0); | ||||
|   if (res && devbufsiz > 1L) | ||||
|     devbuf = new char [devbufsiz]; | ||||
| 
 | ||||
|   return 1; | ||||
|   return res; | ||||
| } | ||||
| 
 | ||||
| int | ||||
|  |  | |||
|  | @ -389,6 +389,9 @@ typedef struct _OBJECT_NAME_INFORMATION | |||
|    standard Win32 header.  */ | ||||
| extern "C" | ||||
| { | ||||
|   NTSTATUS NTAPI NtCreateFile (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, | ||||
| 			     PIO_STATUS_BLOCK, PLARGE_INTEGER, ULONG, ULONG, | ||||
| 			     ULONG, ULONG, PVOID, ULONG); | ||||
|   NTSTATUS NTAPI NtCreateToken (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, | ||||
| 				TOKEN_TYPE, PLUID, PLARGE_INTEGER, PTOKEN_USER, | ||||
| 				PTOKEN_GROUPS, PTOKEN_PRIVILEGES, PTOKEN_OWNER, | ||||
|  |  | |||
|  | @ -2648,8 +2648,7 @@ symlink_worker (const char *topath, const char *frompath, bool use_winsym, | |||
| 	{ | ||||
| 	  CloseHandle (h); | ||||
| 	  if (!allow_ntsec && allow_ntea) | ||||
| 	    set_file_attribute (win32_path.has_acls (), NULL, | ||||
| 				win32_path.get_win32 (), | ||||
| 	    set_file_attribute (false, NULL, win32_path.get_win32 (), | ||||
| 				S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO); | ||||
| 
 | ||||
| 	  DWORD attr = use_winsym ? FILE_ATTRIBUTE_READONLY | ||||
|  |  | |||
|  | @ -261,7 +261,7 @@ getacl (HANDLE handle, const char *file, DWORD attr, int nentries, | |||
| { | ||||
|   security_descriptor sd; | ||||
| 
 | ||||
|   if (!handle || get_nt_object_security (handle, SE_FILE_OBJECT, sd) | ||||
|   if ((!handle || get_nt_object_security (handle, SE_FILE_OBJECT, sd)) | ||||
|       && read_sd (file, sd) <= 0) | ||||
|     { | ||||
|       debug_printf ("read_sd %E"); | ||||
|  |  | |||
|  | @ -375,6 +375,20 @@ out: | |||
|   return ret; | ||||
| } | ||||
| 
 | ||||
| /* Helper function to set the SE_RESTORE_NAME privilege once. */ | ||||
| void | ||||
| enable_restore_privilege () | ||||
| { | ||||
|   static int NO_COPY saved_res; | ||||
|   bool issetuid = cygheap->user.issetuid (); | ||||
|   if (!saved_res || issetuid) | ||||
|     { | ||||
|       int res = 2 + set_process_privilege (SE_RESTORE_NAME, true, issetuid); | ||||
|       if (!issetuid) | ||||
|         saved_res = res; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Function to return a common SECURITY_DESCRIPTOR * that | ||||
|  * allows all access. | ||||
|  |  | |||
|  | @ -165,6 +165,16 @@ str2buf2uni (UNICODE_STRING &tgt, WCHAR *buf, const char *srcstr) | |||
|   sys_mbstowcs (buf, srcstr, tgt.MaximumLength); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| str2buf2uni_cat (UNICODE_STRING &tgt, const char *srcstr) | ||||
| { | ||||
|   DWORD len = strlen (srcstr) * sizeof (WCHAR); | ||||
|   sys_mbstowcs (tgt.Buffer + tgt.Length / sizeof (WCHAR), srcstr, | ||||
| 		len + tgt.MaximumLength); | ||||
|   tgt.Length += len; | ||||
|   tgt.MaximumLength += len; | ||||
| } | ||||
| 
 | ||||
| #if 0				/* unused */
 | ||||
| static void | ||||
| lsa2wchar (WCHAR *tgt, LSA_UNICODE_STRING &src, int size) | ||||
|  | @ -1119,38 +1129,9 @@ read_sd (const char *file, security_descriptor &sd) | |||
| LONG | ||||
| write_sd (HANDLE fh, const char *file, security_descriptor &sd) | ||||
| { | ||||
|   /* Try turning privilege on, may not have WRITE_OWNER or WRITE_DAC access.
 | ||||
|      Must have privilege to set different owner, else BackupWrite misbehaves */ | ||||
|   static int NO_COPY saved_res; /* 0: never, 1: failed, 2 & 3: OK */ | ||||
|   int res; | ||||
|   if (!saved_res || cygheap->user.issetuid ()) | ||||
|     { | ||||
|       res = 2 + set_process_privilege (SE_RESTORE_NAME, true, | ||||
| 				       cygheap->user.issetuid ()); | ||||
|       if (!cygheap->user.issetuid ()) | ||||
| 	saved_res = res; | ||||
|     } | ||||
|   else | ||||
|     res = saved_res; | ||||
|   if (res == 1) | ||||
|     { | ||||
|       BOOL dummy; | ||||
|       cygpsid owner; | ||||
| 
 | ||||
|       if (!GetSecurityDescriptorOwner (sd, (PSID *) &owner, &dummy)) | ||||
| 	{ | ||||
| 	  __seterrno (); | ||||
| 	  return -1; | ||||
| 	} | ||||
|       if (owner != cygheap->user.sid ()) | ||||
| 	{ | ||||
| 	  set_errno (EPERM); | ||||
| 	  return -1; | ||||
| 	} | ||||
|     } | ||||
|   NTSTATUS ret = STATUS_SUCCESS; | ||||
|   int retry = 0; | ||||
|   res = -1; | ||||
|   int res = -1; | ||||
|   for (; retry < 2; ++retry) | ||||
|     { | ||||
|       if (retry && (fh = CreateFile (file, WRITE_OWNER | WRITE_DAC, | ||||
|  |  | |||
|  | @ -248,7 +248,6 @@ extern bool allow_ntsec; | |||
| extern bool allow_smbntsec; | ||||
| 
 | ||||
| /* File manipulation */ | ||||
| int __stdcall set_process_privileges (); | ||||
| int __stdcall get_file_attribute (int, HANDLE, const char *, mode_t *, | ||||
| 				  __uid32_t * = NULL, __gid32_t * = NULL); | ||||
| int __stdcall set_file_attribute (bool, HANDLE, const char *, int); | ||||
|  | @ -275,6 +274,10 @@ extern "C" int acl32 (const char *, int, int, __acl32 *); | |||
| int getacl (HANDLE, const char *, DWORD, int, __acl32 *); | ||||
| int setacl (HANDLE, const char *, int, __acl32 *); | ||||
| 
 | ||||
| struct _UNICODE_STRING; | ||||
| void __stdcall str2buf2uni (_UNICODE_STRING &, WCHAR *, const char *) __attribute__ ((regparm (3))); | ||||
| void __stdcall str2buf2uni_cat (_UNICODE_STRING &, const char *) __attribute__ ((regparm (2))); | ||||
| 
 | ||||
| /* Try a subauthentication. */ | ||||
| HANDLE subauth (struct passwd *pw); | ||||
| /* Try creating a token directly. */ | ||||
|  | @ -289,6 +292,7 @@ bool get_logon_server (const char * domain, char * server, WCHAR *wserver = NULL | |||
| 
 | ||||
| /* sec_helper.cc: Security helper functions. */ | ||||
| int set_process_privilege (const char *privilege, bool enable = true, bool use_thread = false); | ||||
| void enable_restore_privilege (void); | ||||
| 
 | ||||
| /* shared.cc: */ | ||||
| /* Retrieve a security descriptor that allows all access */ | ||||
|  |  | |||
|  | @ -872,6 +872,9 @@ lchown (const char * name, __uid16_t uid, __gid16_t gid) | |||
| extern "C" int | ||||
| fchown32 (int fd, __uid32_t uid, __gid32_t gid) | ||||
| { | ||||
|   if (!wincap.has_security ())  // real chown only works on NT
 | ||||
|     return 0;			// return zero (and do nothing) under Windows 9x
 | ||||
| 
 | ||||
|   cygheap_fdget cfd (fd); | ||||
|   if (cfd < 0) | ||||
|     { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue