diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 4f11f3df7..d82f63974 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,14 @@ +2006-10-21 Corinna Vinschen + + * fhandler.cc (fhandler_base::fhaccess): Call check_registry_access + for registry keys/values if ntsec is on. + * security.cc (check_access): New static function derived from + check_file_access, but object type agnostic. + (check_file_access): Only do file specific stuff. Call check_access. + (check_registry_access): New access check function for registry keys/ + values. + * security.h (check_registry_access): Declare. + 2006-10-21 Corinna Vinschen * fhandler_registry.cc (fhandler_registry::fstat): Set restrictive diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index 672b434e5..2933a1712 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -388,6 +388,12 @@ fhandler_base::fhaccess (int flags) res = check_file_access (get_win32_name (), flags); goto done; } + else if (get_device () == FH_REGISTRY && allow_ntsec && open (O_RDONLY, 0)) + { + res = check_registry_access (get_handle (), flags); + close (); + return res; + } struct __stat64 st; if (fstat (&st)) diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc index 5484b7028..dceb5b571 100644 --- a/winsup/cygwin/security.cc +++ b/winsup/cygwin/security.cc @@ -1944,38 +1944,19 @@ set_file_attribute (bool use_ntsec, HANDLE handle, const char *file, myself->uid, myself->gid, attribute); } -int -check_file_access (const char *fn, int flags) +static int +check_access (security_descriptor &sd, GENERIC_MAPPING &mapping, + DWORD desired, int flags) { int ret = -1; - - security_descriptor sd; - - HANDLE hToken; BOOL status; - DWORD desired = 0, granted; - DWORD plength = sizeof (PRIVILEGE_SET) + 3 * sizeof (LUID_AND_ATTRIBUTES); - PPRIVILEGE_SET pset = (PPRIVILEGE_SET) alloca (plength); - static GENERIC_MAPPING NO_COPY mapping = { FILE_GENERIC_READ, - FILE_GENERIC_WRITE, - FILE_GENERIC_EXECUTE, - FILE_ALL_ACCESS }; - if (read_sd (fn, sd) <= 0) - goto done; + DWORD granted; + DWORD plen = sizeof (PRIVILEGE_SET) + 3 * sizeof (LUID_AND_ATTRIBUTES); + PPRIVILEGE_SET pset = (PPRIVILEGE_SET) alloca (plen); + HANDLE tok = cygheap->user.issetuid () ? cygheap->user.token () + : hProcImpToken; - if (cygheap->user.issetuid ()) - hToken = cygheap->user.token (); - else - hToken = hProcImpToken; - - if (flags & R_OK) - desired |= FILE_READ_DATA; - if (flags & W_OK) - desired |= FILE_WRITE_DATA; - if (flags & X_OK) - desired |= FILE_EXECUTE; - if (!AccessCheck (sd, hToken, desired, &mapping, - pset, &plength, &granted, &status)) + if (!AccessCheck (sd, tok, desired, &mapping, pset, &plen, &granted, &status)) __seterrno (); else if (!status) { @@ -1993,31 +1974,73 @@ check_file_access (const char *fn, int flags) backup/restore privileges has to be made. Sigh. */ int granted_flags = 0; if (flags & R_OK) - { + { pset->PrivilegeCount = 1; pset->Control = 0; pset->Privilege[0].Luid = *privilege_luid (SE_BACKUP_PRIV); pset->Privilege[0].Attributes = 0; - if (PrivilegeCheck (hToken, pset, &status) && status) + if (PrivilegeCheck (tok, pset, &status) && status) granted_flags |= R_OK; } if (flags & W_OK) - { + { pset->PrivilegeCount = 1; pset->Control = 0; pset->Privilege[0].Luid = *privilege_luid (SE_RESTORE_PRIV); pset->Privilege[0].Attributes = 0; - if (PrivilegeCheck (hToken, pset, &status) && status) + if (PrivilegeCheck (tok, pset, &status) && status) granted_flags |= W_OK; } if (granted_flags == flags) - ret = 0; + ret = 0; else set_errno (EACCES); } else ret = 0; - done: + return ret; +} + +int +check_file_access (const char *fn, int flags) +{ + security_descriptor sd; + int ret = -1; + static GENERIC_MAPPING NO_COPY mapping = { FILE_GENERIC_READ, + FILE_GENERIC_WRITE, + FILE_GENERIC_EXECUTE, + FILE_ALL_ACCESS }; + DWORD desired = 0; + if (flags & R_OK) + desired |= FILE_READ_DATA; + if (flags & W_OK) + desired |= FILE_WRITE_DATA; + if (flags & X_OK) + desired |= FILE_EXECUTE; + if (read_sd (fn, sd) > 0) + ret = check_access (sd, mapping, desired, flags); + debug_printf ("flags %x, ret %d", flags, ret); + return ret; +} + +int +check_registry_access (HANDLE hdl, int flags) +{ + security_descriptor sd; + int ret = -1; + static GENERIC_MAPPING NO_COPY mapping = { KEY_READ, + KEY_WRITE, + KEY_EXECUTE, + KEY_ALL_ACCESS }; + DWORD desired = 0; + if (flags & R_OK) + desired |= KEY_ENUMERATE_SUB_KEYS; + if (flags & W_OK) + desired |= KEY_SET_VALUE; + if (flags & X_OK) + desired |= KEY_QUERY_VALUE; + if (!get_reg_security (hdl, sd)) + ret = check_access (sd, mapping, desired, flags); debug_printf ("flags %x, ret %d", flags, ret); return ret; } diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h index ef0871fdd..94e3cc3f5 100644 --- a/winsup/cygwin/security.h +++ b/winsup/cygwin/security.h @@ -302,6 +302,7 @@ LONG __stdcall write_sd (HANDLE fh, const char *file, security_descriptor &sd); 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 (const char *, int); +int __stdcall check_registry_access (HANDLE, int); void set_security_attribute (int attribute, PSECURITY_ATTRIBUTES psa, security_descriptor &sd_buf);