From: corinna DOT vinschen AT cityweb DOT de (Corinna Vinschen) Subject: Patch: UNIX-like permissions on objects 22 Jan 1999 05:21:07 -0800 Message-ID: <36A877AA.9ABB8AD1.cygnus.cygwin32.developers@cityweb.de> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit To: cygwin32-developers AT cygnus DOT com Hi all, I have created two new functions, which give permissions to objects so, that not only the owner, but the administrator or administrator group too, has all permissions on the object. The functions are able, to substitute the global variables `sec_none' and `sec_none_nih'. Using this functions for example `in sigproc::getsem()' enables admin, to kill processes of every user and to kill processes, started via SRVANY, which have done a setsid(), e.g. if the service database starts `inetd' without option `-d'. This wasn't possible 'til now. The SECURITY_ATTRIBUTES, which are needed twice for every user, (inheritable and not inheritable) are generated only once, when a user process calls this functions the first time. They are not duplicated on process creation, but `static NO_COPY' in the DLL, to save time and memory. To get the administrators or administrators group SID, the /etc/group and /etc/passwd files are searched for 1st: gid 544, if not found 2nd: uid 544, if not found 3rd: uid 500, if not found 4th: try the fixed string "administrator". I have done this, because the name of the administrators group is not the same in the different native language versions of WinNT. It shouldn't be unmentioned that the above method, for getting the admins group name, is a security leak! I have created this, because I wished to login as another user than admin, but want to have their permissions so far as it affects cygwin. The code would be easy to shorten, if this is not acceptable. The used structure `sa_user' saves the name of the user, for later checks. Another facility would be, to save the uid instead of the name, to speed up the initial `for'-loop. This would be easy to do. The patch affects only shared.cc and shared.h, but for testing purposes, I have changed the call to CreateSemaphore() in `sigproc.cc:getsem()', too. I have attached it. Nevertheless, the functions `sec_user()' and `sec_user_nih()' would be usefull on any windows-object creation. I would be glad, to here your opinions about this patch. BTW: The patch is against winsup-19990101, but this should be all one, because it's not affecting existing code. Regards, Corinna ChangeLog: ========== 21 Jan 12:30:00 1999 Corinna Vinschen * sigproc.cc (getsem): CreateSemaphore calls sec_user_nih() instead of using sec_none_nih. * shared.h: Prototypes for the above functions. * shared.cc: New functions `sec_user()' and `sec_user_nih()'. New function `get_admin_sid()' as static helper function. Index: sigproc.cc =================================================================== RCS file: /src/cvsroot/winsup-981230/sigproc.cc,v retrieving revision 1.2 diff -u -p -b -1 -r1.2 sigproc.cc --- sigproc.cc 1998/12/31 13:27:54 1.2 +++ sigproc.cc 1999/01/22 12:23:38 @@ -1070,3 +1070,3 @@ getsem (pinfo *p, const char *str, int i DWORD winpid = GetCurrentProcessId (); - h = CreateSemaphore (&sec_none_nih, init, max, str = shared_name (str, winpid)); + h = CreateSemaphore (sec_user_nih (), init, max, str = shared_name (str, winpid)); p = myself; Index: shared.h =================================================================== RCS file: /src/cvsroot/winsup-981230/shared.h,v retrieving revision 1.1.1.1 diff -u -p -b -1 -r1.1.1.1 shared.h --- shared.h 1998/12/30 23:01:58 1.1.1.1 +++ shared.h 1999/01/22 12:06:16 @@ -395,2 +395,4 @@ public: extern SECURITY_ATTRIBUTES sec_none, sec_none_nih, sec_all, sec_all_nih; +extern SECURITY_ATTRIBUTES *sec_user (BOOL inherit = TRUE); +extern SECURITY_ATTRIBUTES *sec_user_nih (); Index: shared.cc =================================================================== RCS file: /src/cvsroot/winsup-981230/shared.cc,v retrieving revision 1.1.1.1 diff -u -p -b -1 -r1.1.1.1 shared.cc --- shared.cc 1998/12/30 23:01:58 1.1.1.1 +++ shared.cc 1999/01/22 12:06:58 @@ -12,2 +12,5 @@ details. */ #include +#include +#include +#include #include "winsup.h" @@ -187,2 +190,154 @@ SECURITY_DESCRIPTOR *get_null_sd () return null_sdp; +} + +static PSID +get_admin_sid () +{ + static NO_COPY PSID sidBuf; + + if (! sidBuf) + { + struct group *gr_ptr; + struct passwd *pw_ptr; + char user[32], dom[100]; + DWORD sidlen, domlen; + SID_NAME_USE acc_type; + + sidBuf = (PSID) malloc (1024); + + // Get name of administrator group from /etc/group + + if ((gr_ptr = getgrgid (544)) != NULL + && strcmp (gr_ptr->gr_name, "everyone")) + strcpy (user, gr_ptr->gr_name); + + // else get name of administrator group from /etc/passwd + + else if ((pw_ptr = getpwuid (544)) != NULL) + strcpy (user, pw_ptr->pw_name); + + // else get name of administrator from /etc/passwd + + else if ((pw_ptr = getpwuid (500)) != NULL) + strcpy (user, pw_ptr->pw_name); + + // else try "administrator" + + else + strcpy (user, "administrator"); + + if (! LookupAccountName (NULL, user, + sidBuf, (sidlen = 1024, &sidlen), + dom, (domlen = 100, &domlen), + &acc_type)) + { + free (sidBuf); + sidBuf = NULL; + } + else + sidBuf = (PSID) realloc (sidBuf, sidlen + 1); + } + return sidBuf; +} + +struct user_sa { + char user[32]; + SECURITY_ATTRIBUTES sa; + SECURITY_ATTRIBUTES sa_nih; + SECURITY_DESCRIPTOR sd; + PACL acl; +}; + +static NO_COPY int sa_cnt = 0; +static NO_COPY user_sa *sa_list; + +SECURITY_ATTRIBUTES * +sec_user (BOOL inherit) +{ + for (int i = 0; i < sa_cnt; ++i) + if (! strcmp (sa_list[i].user, getlogin ())) + return inherit ? &sa_list[i].sa_nih : &sa_list[i].sa; + + PSID sidBuf; + + sidBuf = (PSID) malloc (1024); + if (! sidBuf) + return inherit ? &sec_none_nih : &sec_none; + + DWORD sidlen, domlen; + char dom[100]; + SID_NAME_USE acc_type; + + if (! LookupAccountName (NULL, getlogin (), + sidBuf, (sidlen = 1024, &sidlen), + dom, (domlen = 100, &domlen), + &acc_type)) + { + free (sidBuf); + return inherit ? &sec_none_nih : &sec_none; + } + else if (acc_type != SidTypeUser) + { + char domuser[356]; + strcpy (domuser, dom); + strcat (domuser, "\\"); + strcpy (domuser, getlogin ()); + if (! LookupAccountName (NULL, domuser, + sidBuf, (sidlen = 1024, &sidlen), + dom, (domlen = 100, &domlen), + &acc_type)) + { + free (sidBuf); + return inherit ? &sec_none_nih : &sec_none; + } + } + sidBuf = (PSID) realloc (sidBuf, sidlen + 1); + + size_t acl_len = sizeof (ACL) + + 2 * (sizeof (ACCESS_ALLOWED_ACE) - sizeof (DWORD)) + + GetLengthSid (sidBuf) + + GetLengthSid (get_admin_sid ()); + PACL acl = (PACL) malloc (acl_len); + if (! acl) + { + free (sidBuf); + return inherit ? &sec_none_nih : &sec_none; + } + InitializeAcl (acl, acl_len, ACL_REVISION); + AddAccessAllowedAce (acl, ACL_REVISION, + SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL, + sidBuf); + AddAccessAllowedAce (acl, ACL_REVISION, + SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL, + get_admin_sid ()); + + user_sa *tmp_sa_list = (user_sa *) realloc (sa_list, + (sa_cnt + 1) * sizeof (user_sa)); + if (! tmp_sa_list) + { + free (acl); + free (sidBuf); + return inherit ? &sec_none_nih : &sec_none; + } + sa_list = tmp_sa_list; + + sa_list[sa_cnt].acl = acl; + InitializeSecurityDescriptor (&sa_list[sa_cnt].sd, + SECURITY_DESCRIPTOR_REVISION); + SetSecurityDescriptorDacl (&sa_list[sa_cnt].sd, TRUE, acl, FALSE); + sa_list[sa_cnt].sa.nLength = + sa_list[sa_cnt].sa_nih.nLength = sizeof (SECURITY_ATTRIBUTES); + sa_list[sa_cnt].sa.lpSecurityDescriptor = + sa_list[sa_cnt].sa_nih.lpSecurityDescriptor = &sa_list[sa_cnt].sd; + sa_list[sa_cnt].sa.bInheritHandle = TRUE; + sa_list[sa_cnt].sa_nih.bInheritHandle = FALSE; + strcpy (sa_list[sa_cnt].user, getlogin ()); + ++sa_cnt; + return inherit ? &sa_list[sa_cnt - 1].sa : &sa_list[sa_cnt - 1].sa_nih; +} + +SECURITY_ATTRIBUTES * +sec_user_nih () +{ + return sec_user (FALSE); }