diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2009-04-09 09:19:03 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2009-04-09 09:19:03 +0000 |
commit | 2d647173bb2056dfd87a184ac2b6e5ded660a466 (patch) | |
tree | cc84ef1e8f66f8ecae0c889e1ea16e3ba8e9430c /winsup/cygwin | |
parent | 9b26525ec38243245b9736272e58ee1a0d492959 (diff) | |
download | newlib-2d647173bb2056dfd87a184ac2b6e5ded660a466.zip newlib-2d647173bb2056dfd87a184ac2b6e5ded660a466.tar.gz newlib-2d647173bb2056dfd87a184ac2b6e5ded660a466.tar.bz2 |
* fhandler_disk_file.cc (fhandler_disk_file::fchown): Catch an
error when changing the user account on a standalone Samba server.
Explain why.
* sec_acl.cc (setacl): Accommodate additional parameter to set_file_sd.
* sec_helper.cc (SECURITY_SAMBA_UNIX_AUTHORITY): Define.
(well_known_samba_unix_user_fake_sid): Define.
* security.cc (set_file_sd): Take additional parameter if ownership
should be changed. Restrict requested permissions accordingly.
(set_file_attribute): Accommodate additional parameter to set_file_sd.
* security.h (well_known_samba_unix_user_fake_sid): Declare.
(set_file_sd): Align declaration to above change.
Diffstat (limited to 'winsup/cygwin')
-rw-r--r-- | winsup/cygwin/ChangeLog | 14 | ||||
-rw-r--r-- | winsup/cygwin/fhandler_disk_file.cc | 27 | ||||
-rw-r--r-- | winsup/cygwin/sec_acl.cc | 2 | ||||
-rw-r--r-- | winsup/cygwin/sec_helper.cc | 4 | ||||
-rw-r--r-- | winsup/cygwin/security.cc | 13 | ||||
-rw-r--r-- | winsup/cygwin/security.h | 4 |
6 files changed, 56 insertions, 8 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 594efbd..76564cd 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,17 @@ +2009-04-09 Corinna Vinschen <corinna@vinschen.de> + + * fhandler_disk_file.cc (fhandler_disk_file::fchown): Catch an + error when changing the user account on a standalone Samba server. + Explain why. + * sec_acl.cc (setacl): Accommodate additional parameter to set_file_sd. + * sec_helper.cc (SECURITY_SAMBA_UNIX_AUTHORITY): Define. + (well_known_samba_unix_user_fake_sid): Define. + * security.cc (set_file_sd): Take additional parameter if ownership + should be changed. Restrict requested permissions accordingly. + (set_file_attribute): Accommodate additional parameter to set_file_sd. + * security.h (well_known_samba_unix_user_fake_sid): Declare. + (set_file_sd): Align declaration to above change. + 2009-04-07 Corinna Vinschen <corinna@vinschen.de> * include/stdint.h (int_least32_t): Define as int. diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc index 0ac4ed4..c4c36cc 100644 --- a/winsup/cygwin/fhandler_disk_file.cc +++ b/winsup/cygwin/fhandler_disk_file.cc @@ -24,6 +24,7 @@ details. */ #include "ntdll.h" #include "tls_pbuf.h" #include "nfs.h" +#include "pwdgrp.h" #include <winioctl.h> #define _COMPILING_NEWLIB @@ -870,7 +871,8 @@ fhandler_disk_file::fchown (__uid32_t uid, __gid32_t gid) mode_t attrib = 0; if (pc.isdir ()) attrib |= S_IFDIR; - int res = get_file_attribute (get_handle (), pc, &attrib, NULL, NULL); + __uid32_t old_uid; + int res = get_file_attribute (get_handle (), pc, &attrib, &old_uid, NULL); if (!res) { /* Typical Windows default ACLs can contain permissions for one @@ -883,6 +885,29 @@ fhandler_disk_file::fchown (__uid32_t uid, __gid32_t gid) if (pc.issymlink ()) attrib = S_IFLNK | STD_RBITS | STD_WBITS; res = set_file_attribute (get_handle (), pc, uid, gid, attrib); + /* If you're running a Samba server which has no winbidd running, the + uid<->SID mapping is disfunctional. Even trying to chown to your + own account fails since the account used on the server is the UNIX + account which gets used for the standard user mapping. This is a + default mechanism which doesn't know your real Windows SID. + There are two possible error codes in different Samba releases for + this situation, one of them is unfortunately the not very significant + STATUS_ACCESS_DENIED. Instead of relying on the error codes, we're + using the below very simple heuristic. If set_file_attribute failed, + and the original user account was either already unknown, or one of + the standard UNIX accounts, we're faking success. */ + if (res == -1 && pc.fs_is_samba ()) + { + cygsid sid; + + if (old_uid == ILLEGAL_UID + || (sid.getfrompw (internal_getpwuid (old_uid)) + && EqualPrefixSid (sid, well_known_samba_unix_user_fake_sid))) + { + debug_printf ("Faking chown worked on standalone Samba"); + res = 0; + } + } } if (oret) close_fs (); diff --git a/winsup/cygwin/sec_acl.cc b/winsup/cygwin/sec_acl.cc index 2496ce0..2a9b4fc 100644 --- a/winsup/cygwin/sec_acl.cc +++ b/winsup/cygwin/sec_acl.cc @@ -225,7 +225,7 @@ setacl (HANDLE handle, path_conv &pc, int nentries, __aclent32_t *aclbufp, return -1; } debug_printf ("Created SD-Size: %d", sd_ret.size ()); - return set_file_sd (handle, pc, sd_ret); + return set_file_sd (handle, pc, sd_ret, false); } /* Temporary access denied bits */ diff --git a/winsup/cygwin/sec_helper.cc b/winsup/cygwin/sec_helper.cc index 1e1657e..63be25c 100644 --- a/winsup/cygwin/sec_helper.cc +++ b/winsup/cygwin/sec_helper.cc @@ -67,6 +67,10 @@ MKSID (mandatory_high_integrity_sid, "S-1-16-12288", SECURITY_MANDATORY_LABEL_AUTHORITY, 1, SECURITY_MANDATORY_HIGH_RID); MKSID (mandatory_system_integrity_sid, "S-1-16-16384", SECURITY_MANDATORY_LABEL_AUTHORITY, 1, SECURITY_MANDATORY_SYSTEM_RID); +/* UNIX accounts on a Samba server have the SID prefix "S-1-22-1" */ +#define SECURITY_SAMBA_UNIX_AUTHORITY {0,0,0,0,0,22} +MKSID (well_known_samba_unix_user_fake_sid, "S-1-22-1-0", + SECURITY_SAMBA_UNIX_AUTHORITY, 2, 1, 0); bool cygpsid::operator== (const char *nsidstr) const diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc index c9de92b..a7d4a56 100644 --- a/winsup/cygwin/security.cc +++ b/winsup/cygwin/security.cc @@ -83,7 +83,7 @@ get_file_sd (HANDLE fh, path_conv &pc, security_descriptor &sd) } LONG -set_file_sd (HANDLE fh, path_conv &pc, security_descriptor &sd) +set_file_sd (HANDLE fh, path_conv &pc, security_descriptor &sd, bool is_chown) { NTSTATUS status = STATUS_SUCCESS; int retry = 0; @@ -93,7 +93,10 @@ set_file_sd (HANDLE fh, path_conv &pc, security_descriptor &sd) { if (fh) { - status = NtSetSecurityObject (fh, ALL_SECURITY_INFORMATION, sd); + status = NtSetSecurityObject (fh, + is_chown ? ALL_SECURITY_INFORMATION + : DACL_SECURITY_INFORMATION, + sd); if (NT_SUCCESS (status)) { res = 0; @@ -104,8 +107,7 @@ set_file_sd (HANDLE fh, path_conv &pc, security_descriptor &sd) { OBJECT_ATTRIBUTES attr; IO_STATUS_BLOCK io; - - status = NtOpenFile (&fh, WRITE_OWNER | WRITE_DAC, + status = NtOpenFile (&fh, (is_chown ? WRITE_OWNER : 0) | WRITE_DAC, pc.get_object_attr (attr, sec_none_nih), &io, FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT @@ -712,7 +714,8 @@ set_file_attribute (HANDLE handle, path_conv &pc, if (!get_file_sd (handle, pc, sd) && alloc_sd (pc, uid, gid, attribute, sd)) - ret = set_file_sd (handle, pc, sd); + ret = set_file_sd (handle, pc, sd, + uid != ILLEGAL_UID || gid != ILLEGAL_GID); } else ret = 0; diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h index f186597..9d306fe 100644 --- a/winsup/cygwin/security.h +++ b/winsup/cygwin/security.h @@ -327,6 +327,7 @@ extern cygpsid fake_logon_sid; extern cygpsid mandatory_medium_integrity_sid; extern cygpsid mandatory_high_integrity_sid; extern cygpsid mandatory_system_integrity_sid; +extern cygpsid well_known_samba_unix_user_fake_sid; bool privilege_luid (const PWCHAR pname, LUID *luid); @@ -345,7 +346,8 @@ int __stdcall set_file_attribute (HANDLE, path_conv &, __uid32_t, __gid32_t, int); int __stdcall get_reg_attribute (HKEY hkey, mode_t *, __uid32_t *, __gid32_t *); LONG __stdcall get_file_sd (HANDLE fh, path_conv &, security_descriptor &sd); -LONG __stdcall set_file_sd (HANDLE fh, path_conv &, security_descriptor &sd); +LONG __stdcall set_file_sd (HANDLE fh, path_conv &, security_descriptor &sd, + bool is_chown); bool __stdcall add_access_allowed_ace (PACL acl, int offset, DWORD attributes, PSID sid, size_t &len_add, DWORD inherit); bool __stdcall add_access_denied_ace (PACL acl, int offset, DWORD attributes, PSID sid, size_t &len_add, DWORD inherit); int __stdcall check_file_access (path_conv &, int); |