Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com Message-Id: <3.0.5.32.20020118194603.007db100@pop.ne.mediaone.net> X-Sender: phumblet AT pop DOT ne DOT mediaone DOT net (Unverified) X-Mailer: QUALCOMM Windows Eudora Pro Version 3.0.5 (32) Date: Fri, 18 Jan 2002 19:46:03 -0500 To: Corinna Vinschen From: "Pierre A. Humblet" Subject: Re: security.cc: bug report, question and suggestion In-Reply-To: <20011230183808.S27340@cygbert.vinschen.de> References: <3 DOT 0 DOT 5 DOT 32 DOT 20011230112615 DOT 00813e60 AT pop DOT ne DOT mediaone DOT net> <3 DOT 0 DOT 5 DOT 32 DOT 20011229152301 DOT 0083a1f0 AT pop DOT ne DOT mediaone DOT net> <3 DOT 0 DOT 5 DOT 32 DOT 20011229152301 DOT 0083a1f0 AT pop DOT ne DOT mediaone DOT net> <3 DOT 0 DOT 5 DOT 32 DOT 20011230112615 DOT 00813e60 AT pop DOT ne DOT mediaone DOT net> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=====================_1011419163==_" --=====================_1011419163==_ Content-Type: text/plain; charset="us-ascii" At 06:38 PM 12/30/01 +0100, Corinna Vinschen wrote: >On Sun, Dec 30, 2001 at 11:26:15AM -0500, Pierre A. Humblet wrote: >> At 11:15 PM 12/29/01 +0100, Corinna Vinschen wrote: >> While I am at it, here is another weird observation: >> base case above: prog reads some registry key. Succeeds. >> cases 1 and 2: prog reads some registry key. Access denied. >> But if xxx has admins privilege, prog can read the registry in >> cases 1 and 2... >> Can this be explained somehow? It's all on a standalone Win2000. > >Hmm, some debgging would help here, perhaps. > Hi Corinna Well, I had to learn a few things to track this one. Please cc me directly. Sorry about the length. What follows was observed on NT 4, it's somewhat different on Windows 2000. The keys are related to the perflib, e.g. "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib\\009" and others. Initially I thought that the error 5 ERROR_ACCESS_DENIED meant that, following setuid(), the user did not have query access to the key, even though he could open it without problems. This guess was wrong. The real problem is that following setuid(), the ACL (not default ACL) of the impersonation token (which is inherited from the default ACL of the process token) makes the impersonation token non-accessible by its user (normally the user has full access to its token, and it seems that setuid() should preserve that). ERROR_ACCESS_DENIED is thus generated when some Microsoft code tries to access the token while getting the key. This is demonstrated in the debug.out attachment where I print the impersonation token, try to access the key (fail), then clear the token ACL and succeed reading the key. I tried to patch security.cc, without success. In the attached diff file I set an acl (actually I reuse your default ACL) in a security descriptor "sd". sd is pointed to by your security attribute "sa", which is passed to DuplicateTokenEx() in create_token(). I also added a new call to SetKernelObjectSecurity(), for good measure. This runs without errors, but nothing happens. I have no idea why. Any help or suggestions will be appreciated. Here are four other things I noticed: 1) If setuid(gid) with a gid that doesn't exist, the system silently sets the gid to "administrators". That is not fail safe! The problem is that getgrgid() never fails. It should have a flag to tell it whether it should default or not. [The default is fine when specifying a SET_ACCESS ACE] 2) my_token isn't closed in create_token() 3) Why is it necessary to set the PrimaryGroup in the process token in setegid()? (That can fail silently). Is that field ever read? I thought that PrimaryGroup only needs to be set in impersonation tokens, so that seteuid() can decide if an existing token can be reused. 4) If in "cygrunsrv -u user ..." the Cygwin and Windows user names differ, then the process will have the wrong uid. Entry in passwd (note Cygwin name != Windows name) exim:unused_by_nt/2000/xp:1002:1005:daemon,U-PHumblet\Mail,S-1-5-21-21273915 03-1594901184-99485923-1002:/h ome/Mail:/bin/bash /> cygrunsrv -I test -u mail -e CYGWIN=ntsec -p /a.exe Enter password of user `.\mail': Reenter, please: /> cygrunsrv -S test /> head /var/log/test.log CYGWIN = ntsec USERNAME = UNDEF UID = 500 GID = 513 PID = 619 <==INCORRECT UID/GID /******************* Token Start ****************************/ /******************* Token User */ Mail PHumblet SidTypeUser <=== CORRECT USER S-1-5-21-2127391503-1594901184-99485923-1002 <=== CORRECT SID Changed entry in passwd mail:unused_by_nt/2000/xp:1002:1005:daemon,U-PHumblet\Mail,S-1-5-21-21273915 03-1594901184-99485923-1002:/home/Mail:/bin/bash /> cygrunsrv -S test /> head /var/log/test.log CYGWIN = ntsec USERNAME = UNDEF UID = 1002 GID = 1005 PID = 654 <== EVERYTHING OK /******************* Token Start ****************************/ /******************* Token User */ Mail PHumblet SidTypeUser S-1-5-21-2127391503-1594901184-99485923-1002 Pierre --=====================_1011419163==_ Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="security.diff" --- security.cc.in Wed Jan 9 20:35:04 2002 +++ security.cc Tue Jan 15 18:58:46 2002 @@ -696,6 +696,18 @@ return TRUE; } +static BOOL +get_sd (PSECURITY_DESCRIPTOR psd, PACL acl) +{ + if (!(InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION)= && + SetSecurityDescriptorDacl(psd, TRUE, acl, FALSE))) + { + __seterrno (); + return FALSE; + } + return TRUE; +} + HANDLE create_token (cygsid &usersid, cygsid &pgrpsid) { @@ -710,7 +722,8 @@ { sizeof sqos, SecurityImpersonation, SECURITY_STATIC_TRACKING, FALSE= }; OBJECT_ATTRIBUTES oa =3D { sizeof oa, 0, 0, 0, 0, &sqos }; - SECURITY_ATTRIBUTES sa =3D { sizeof sa, NULL, TRUE }; + SECURITY_DESCRIPTOR sd; + SECURITY_ATTRIBUTES sa =3D { sizeof sa, &sd, TRUE }; LUID auth_luid =3D SYSTEM_LUID; LARGE_INTEGER exp =3D { QuadPart:0x7fffffffffffffffLL }; @@ -813,10 +826,14 @@ goto out; dacl.DefaultDacl =3D (PACL) acl_buf; + /* Create security info */ + if (!get_sd (& sd, (PACL) acl_buf)) + goto out; + /* Let's be heroic... */ ret =3D NtCreateToken (&token, TOKEN_ALL_ACCESS, &oa,= TokenImpersonation, &auth_luid, &exp, &user, grps, privs, &owner, &pgrp, - &dacl, &source); + &dacl, &source); if (ret) set_errno (RtlNtStatusToDosError (ret)); else if (GetLastError () =3D=3D ERROR_PROC_NOT_FOUND) @@ -827,9 +844,18 @@ /* Convert to primary token. */ if (!DuplicateTokenEx (token, TOKEN_ALL_ACCESS, &sa, - SecurityImpersonation, TokenPrimary, - &primary_token)) - __seterrno (); + SecurityImpersonation, TokenPrimary, + &primary_token)) + { + __seterrno (); + debug_printf ("DuplicateTokenEx failed."); + } + /* Convert to primary token. */ + if (!SetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, &sd)) + { + __seterrno (); + debug_printf ("SetKernelObjectSecurity failed."); + } out: if (old_priv_state >=3D 0) --=====================_1011419163==_ Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="debug.out" ************************************************************************** Debug output demonstrating the token ACL problem NT= 4 ************************************************************************** 1) For reference, here is process token of a normal unprivileged user. The "SECURITY INFO" section shows that the user has full access to its token. Such a user has no problem reading the perflib registry key, even though it is non privileged. /******************* Token Start= ****************************/ /******************* Token User */ testuser PHumblet SidTypeUser /******************* Token Type */ TokenPrimary /******************* Token Source */ Token source User32 /******************* Token Security */ *************** SECURITY INFO START ************* Owner: testuser PHumblet SidTypeUser Group: None PHumblet SidTypeGroup ACL: 0 PHumblet\testuser (form=3D=3Dname) SET_ACCESS Inher 0 TRUSTEE_IS_USER TOKEN_ASSIGN_PRIMARY, TOKEN_DUPLICATE, TOKEN_IMPERSONATE, TOKEN_QUERY,= TOKEN_QUERY_SOURCE, TOKEN_ADJUST_PRIVILEGES, TOKEN_ADJUST_GROUPS,= TOKEN_ADJUST_DEFAULT, DELETE, READ_CONTROL, WRITE_DAC, WRITE_OWNER, 1 NT AUTHORITY\SYSTEM (form=3D=3Dname) SET_ACCESS Inher 0 TRUSTEE_IS_WELL_KNOWN_GROUP TOKEN_ASSIGN_PRIMARY, TOKEN_DUPLICATE, TOKEN_IMPERSONATE, TOKEN_QUERY,= TOKEN_QUERY_SOURCE, TOKEN_ADJUST_PRIVILEGES, TOKEN_ADJUST_GROUPS,= TOKEN_ADJUST_DEFAULT, DELETE, READ_CONTROL, WRITE_DAC, WRITE_OWNER,= *************** SECURITY INFO END ************* /******************* Token Groups */ None PHumblet SidTypeGroup SE_GROUP_ENABLED, SE_GROUP_ENABLED_BY_DEFAULT, SE_GROUP_MANDATORY, Everyone SidTypeWellKnownGroup SE_GROUP_ENABLED, SE_GROUP_ENABLED_BY_DEFAULT, SE_GROUP_MANDATORY, Users BUILTIN SidTypeAlias SE_GROUP_ENABLED, SE_GROUP_ENABLED_BY_DEFAULT, SE_GROUP_MANDATORY,= LookupAccountSid: error 1332 1 3 0 0 0 0 0 5 5 0 SE_GROUP_ENABLED, SE_GROUP_ENABLED_BY_DEFAULT, SE_GROUP_LOGON_ID,= SE_GROUP_MANDATORY, LOCAL SidTypeWellKnownGroup SE_GROUP_ENABLED, SE_GROUP_ENABLED_BY_DEFAULT, SE_GROUP_MANDATORY,= INTERACTIVE NT AUTHORITY SidTypeWellKnownGroup SE_GROUP_ENABLED, SE_GROUP_ENABLED_BY_DEFAULT, SE_GROUP_MANDATORY,= Authenticated Users NT AUTHORITY SidTypeWellKnownGroup SE_GROUP_ENABLED, SE_GROUP_ENABLED_BY_DEFAULT, SE_GROUP_MANDATORY,= /******************* Token restricted sids */ GetTokenInfo 87 300 172 <=3D=3D=3D No restricted SIDs /******************* Token privileges */ SeChangeNotifyPrivilege SE_PRIVILEGE_ENABLED,= SE_PRIVILEGE_ENABLED_BY_DEFAULT, SeShutdownPrivilege /******************* Token Owner */ testuser PHumblet SidTypeUser /******************* Token Primary group */ None PHumblet SidTypeGroup /******************* Token DACL */ 0 PHumblet\testuser (form=3D=3Dname) SET_ACCESS Inher 0 TRUSTEE_IS_USER 1 NT AUTHORITY\SYSTEM (form=3D=3Dname) SET_ACCESS Inher 0 TRUSTEE_IS_WELL_KNOWN_GROUP /******************* Token End ****************************/ 2) This is the impersonation token when both setgid(1005) and setuid(1004) have been called. Process was started by cygrunsrv under SYSTEM /******************* Token Start= ****************************/ /******************* Token User */ SYSTEM NT AUTHORITY SidTypeUser <=3D=3D=3D STRANGE= LookupAccountSid() S-1-5-21-2127391503-1594901184-99485923-1004 <=3D=3D=3D CORRECT SID= /******************* Token Type */ TokenImpersonation /******************* Token Source */ Token source Cygwin.1 /******************* Token Security */ *************** SECURITY INFO START ************* Owner: SYSTEM NT AUTHORITY SidTypeWellKnownGroup S-1-5-18 Group: mailgrp PHumblet SidTypeAlias <=3D=3D=3D CORRECT= GID S-1-5-21-2127391503-1594901184-99485923-1005 ACL: <=3D=3D=3D 1004 has no access 0 NT AUTHORITY\SYSTEM (form=3D=3Dname) SET_ACCESS Inher 0 TRUSTEE_IS_USER TOKEN_ASSIGN_PRIMARY, TOKEN_DUPLICATE, TOKEN_IMPERSONATE, TOKEN_QUERY,= TOKEN_QUERY_SOURCE, TOKEN_ADJUST_PRIVILEGES, TOKEN_ADJUST_GROUPS,= TOKEN_ADJUST_DEFAULT, DELETE, READ_CONTROL, WRITE_DAC, WRITE_OWNER, 1 BUILTIN\Administrators (form=3D=3Dname) SET_ACCESS Inher 0 TRUSTEE_IS_ALIAS TOKEN_QUERY, READ_CONTROL, *************** SECURITY INFO END ************* /******************* Token Groups */ Everyone SidTypeWellKnownGroup S-1-1-0 SE_GROUP_ENABLED, SE_GROUP_ENABLED_BY_DEFAULT, SE_GROUP_MANDATORY,= Authenticated Users NT AUTHORITY= SidTypeWellKnownGroup S-1-5-11 SE_GROUP_ENABLED, SE_GROUP_ENABLED_BY_DEFAULT, SE_GROUP_MANDATORY, Users BUILTIN SidTypeAlias S-1-5-32-545 SE_GROUP_ENABLED, SE_GROUP_ENABLED_BY_DEFAULT, SE_GROUP_MANDATORY, mailgrp PHumblet= SidTypeAlias S-1-5-21-2127391503-1594901184-99485923-1005 SE_GROUP_ENABLED, SE_GROUP_ENABLED_BY_DEFAULT, SE_GROUP_MANDATORY,= /******************* Token restricted sids */ GetTokenInfo 87 <=3D=3D=3D No restricted SIDs /******************* Token privileges */ SeChangeNotifyPrivilege SE_PRIVILEGE_ENABLED,= SE_PRIVILEGE_ENABLED_BY_DEFAULT, SeShutdownPrivilege SE_PRIVILEGE_ENABLED, SE_PRIVILEGE_ENABLED_BY_DEFAULT,= /******************* Token Owner */ SYSTEM NT AUTHORITY= SidTypeUser S-1-5-21-2127391503-1594901184-99485923-1004 /******************* Token Primary group */ mailgrp PHumblet= SidTypeAlias S-1-5-21-2127391503-1594901184-99485923-1005 /******************* Token DACL */ 0 NT AUTHORITY\SYSTEM (form=3D=3Dname) SET_ACCESS Inher 0 TRUSTEE_IS_USER 1 =EE=FE=EE=FE=EE=FE=EE=FE=EE=FE=EE=FE=EE=FE=EE=FE=EE=FE=EE=FE=EE=FE=EE=FE= =EE=FE=EE=FE=EE=FE=EE=FE=EE=FE=EE=FE=EE=FE=EE=FE=EE=FE=EE=FE=EE=FE=EE=FE=EE= =FE (form=3D=3Dname) <=3D=3D=3D NO IDEA WHY THIS IS GARBLED SET_ACCESS Inher 0 TRUSTEE_IS_USER <=3D=3D= =3D WILL LOOK AT IT NEXT WEEK /******************* Token End ****************************/ RegOpenKeyEx returned 0 <=3D=3D=3D=3D=3D=3D=3D Success RegQueryValueEx returned 5 <=3D=3D=3D=3D=3D=3D=3D FAILS 3) Impersonation token, after I clear its= ACL InitializeSecurityDescriptor(&sd,= SECURITY_DESCRIPTOR_REVISION); SetSecurityDescriptorDacl(&sd, TRUE, NULL,= FALSE); SetKernelObjectSecurity(ThreadHandle, DACL_SECURITY_INFORMATION, &sd); (I did this for simplicity, I should set the ACL to something. Putting such code in seteuid(0 [syscalls.c] should work) The thread is now able to read the registry key. UNFORTUNATELY, after a fork() the ACL goes back to its non-null value and the registry key can't be read again. (This is not shown here). /******************* Token Start= ****************************/ /******************* Token User */ SYSTEM NT AUTHORITY= SidTypeUser S-1-5-21-2127391503-1594901184-99485923-1004 /******************* Token Type */ TokenImpersonation /******************* Token Source */ Token source Cygwin.1 /******************* Token Security */ *************** SECURITY INFO START ************* Owner: SYSTEM NT AUTHORITY SidTypeWellKnownGroup S-1-5-18 Group: mailgrp PHumblet= SidTypeAlias S-1-5-21-2127391503-1594901184-99485923-1005 ACL: <=3D=3D=3D=3D=3D=3D ACL was cleared ACL is null *************** SECURITY INFO END ************* /******************* Token Groups */ Everyone SidTypeWellKnownGroup S-1-1-0 SE_GROUP_ENABLED, SE_GROUP_ENABLED_BY_DEFAULT, SE_GROUP_MANDATORY,= Authenticated Users NT AUTHORITY= SidTypeWellKnownGroup S-1-5-11 SE_GROUP_ENABLED, SE_GROUP_ENABLED_BY_DEFAULT, SE_GROUP_MANDATORY, Users BUILTIN SidTypeAlias S-1-5-32-545 SE_GROUP_ENABLED, SE_GROUP_ENABLED_BY_DEFAULT, SE_GROUP_MANDATORY, mailgrp PHumblet= SidTypeAlias S-1-5-21-2127391503-1594901184-99485923-1005 SE_GROUP_ENABLED, SE_GROUP_ENABLED_BY_DEFAULT, SE_GROUP_MANDATORY,= /******************* Token restricted sids */ GetTokenInfo 87 300 104 /******************* Token privileges */ SeChangeNotifyPrivilege SE_PRIVILEGE_ENABLED,= SE_PRIVILEGE_ENABLED_BY_DEFAULT, SeShutdownPrivilege SE_PRIVILEGE_ENABLED, SE_PRIVILEGE_ENABLED_BY_DEFAULT,= /******************* Token Owner */ SYSTEM NT AUTHORITY= SidTypeUser S-1-5-21-2127391503-1594901184-99485923-1004 /******************* Token Primary group */ mailgrp PHumblet= SidTypeAlias S-1-5-21-2127391503-1594901184-99485923-1005 /******************* Token DACL */ 0 NT AUTHORITY\SYSTEM (form=3D=3Dname) SET_ACCESS Inher 0 TRUSTEE_IS_USER 1 =EE=FE=EE=FE=EE=FE=EE=FE=EE=FE=EE=FE=EE=FE=EE=FE=EE=FE=EE=FE=EE=FE=EE=FE= =EE=FE=EE=FE=EE=FE=EE=FE=EE=FE=EE=FE=EE=FE=EE=FE=EE=FE=EE=FE=EE=FE=EE=FE=EE= =FE (form=3D=3Dname) SET_ACCESS Inher 0 TRUSTEE_IS_USER /******************* Token End ****************************/ RegOpenKeyEx returned 0 RegQueryValueEx returned 0 <=3D=3D=3D=3D IT WORKS 4) For reference, here is the SECURITY INFO of the= key "SOFTWARE\\Microsoft\\Windows= NT\\CurrentVersion\\Perflib\\009" *************** SECURITY INFO START ************* Owner: Administrators BUILTIN SidTypeAlias Group: LookupAccountSid: error 1332 1 5 0 0 0 0 0 5 15 0 ACL: 0 Everyone (form=3D=3Dname) SET_ACCESS Inher 2 TRUSTEE_IS_WELL_KNOWN_GROUP KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYS, KEY_NOTIFY, READ_CONTROL, 1 BUILTIN\Administrators (form=3D=3Dname) SET_ACCESS Inher 2 TRUSTEE_IS_ALIAS KEY_QUERY_VALUE, KEY_SET_VALUE, KEY_CREATE_SUB_KEY, KEY_ENUMERATE_SUB_KEYS,= KEY_NOTIFY, KEY_CREATE_LINK, DELETE, READ_CONTROL, WRITE_DAC, WRITE_OWNER,= 2 NT AUTHORITY\SYSTEM (form=3D=3Dname) SET_ACCESS Inher 2 TRUSTEE_IS_USER KEY_QUERY_VALUE, KEY_SET_VALUE, KEY_CREATE_SUB_KEY, KEY_ENUMERATE_SUB_KEYS,= KEY_NOTIFY, KEY_CREATE_LINK, DELETE, READ_CONTROL, WRITE_DAC, WRITE_OWNER,= 3 CREATOR OWNER (form=3D=3Dname) SET_ACCESS Inher 2 TRUSTEE_IS_WELL_KNOWN_GROUP KEY_QUERY_VALUE, KEY_SET_VALUE, KEY_CREATE_SUB_KEY, KEY_ENUMERATE_SUB_KEYS,= KEY_NOTIFY, KEY_CREATE_LINK, DELETE, READ_CONTROL, WRITE_DAC, WRITE_OWNER,= *************** SECURITY INFO END ************* --=====================_1011419163==_ Content-Type: text/plain; charset=us-ascii -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Bug reporting: http://cygwin.com/bugs.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/ --=====================_1011419163==_--