1 /* sec_helper.cc: NT security helper functions
3 Copyright 2000, 2001, 2002 Red Hat, Inc.
5 Written by Corinna Vinschen <corinna@vinschen.de>
7 This file is part of Cygwin.
9 This software is a copyrighted work licensed under the terms of the
10 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
20 #include <sys/types.h>
28 #include "perprocess.h"
38 SID_IDENTIFIER_AUTHORITY sid_auth[] = {
39 {SECURITY_NULL_SID_AUTHORITY},
40 {SECURITY_WORLD_SID_AUTHORITY},
41 {SECURITY_LOCAL_SID_AUTHORITY},
42 {SECURITY_CREATOR_SID_AUTHORITY},
43 {SECURITY_NON_UNIQUE_AUTHORITY},
44 {SECURITY_NT_AUTHORITY}
47 cygsid well_known_null_sid ("S-1-0-0");
48 cygsid well_known_world_sid ("S-1-1-0");
49 cygsid well_known_local_sid ("S-1-2-0");
50 cygsid well_known_creator_owner_sid ("S-1-3-0");
51 cygsid well_known_dialup_sid ("S-1-5-1");
52 cygsid well_known_network_sid ("S-1-5-2");
53 cygsid well_known_batch_sid ("S-1-5-3");
54 cygsid well_known_interactive_sid ("S-1-5-4");
55 cygsid well_known_service_sid ("S-1-5-6");
56 cygsid well_known_authenticated_users_sid ("S-1-5-11");
57 cygsid well_known_system_sid ("S-1-5-18");
58 cygsid well_known_admins_sid ("S-1-5-32-544");
61 cygsid::string (char *nsidstr) const
66 if (!psid || !nsidstr)
68 strcpy (nsidstr, "S-1-");
69 __small_sprintf(t, "%u", GetSidIdentifierAuthority (psid)->Value[5]);
71 for (i = 0; i < *GetSidSubAuthorityCount (psid); ++i)
73 __small_sprintf(t, "-%lu", *GetSidSubAuthority (psid, i));
80 cygsid::get_sid (DWORD s, DWORD cnt, DWORD *r)
84 if (s > 5 || cnt < 1 || cnt > 8)
90 InitializeSid(psid, &sid_auth[s], cnt);
91 for (i = 0; i < cnt; ++i)
92 memcpy ((char *) psid + 8 + sizeof (DWORD) * i, &r[i], sizeof (DWORD));
97 cygsid::getfromstr (const char *nsidstr)
105 if (!nsidstr || strncmp (nsidstr, "S-1-", 4))
111 strcpy (sid_buf, nsidstr);
113 for (t = sid_buf + 4, i = 0;
114 cnt < 8 && (t = strtok_r (t, "-", &lasts));
117 s = strtoul (t, NULL, 10);
119 r[cnt++] = strtoul (t, NULL, 10);
121 return get_sid (s, cnt, r);
125 cygsid::getfrompw (const struct passwd *pw)
127 char *sp = (pw && pw->pw_gecos) ? strrchr (pw->pw_gecos, ',') : NULL;
128 return (*this = sp ? sp + 1 : "") != NULL;
132 cygsid::getfromgr (const struct __group16 *gr)
134 char *sp = (gr && gr->gr_passwd) ? gr->gr_passwd : NULL;
135 return (*this = sp ?: "") != NULL;
139 cygsid::get_id (BOOL search_grp, int *type)
146 if (!IsValidSid (psid))
149 small_printf ("IsValidSid failed with %E");
153 /* First try to get SID from passwd or group entry */
162 for (int pidx = 0; (pw = internal_getpwent (pidx)); ++pidx)
164 if (sid.getfrompw (pw) && sid == psid)
177 if (search_grp || type)
179 struct __group16 *gr;
180 for (int gidx = 0; (gr = internal_getgrent (gidx)); ++gidx)
182 if (sid.getfromgr (gr) && sid == psid)
197 /* We use the RID as default UID/GID */
198 int id = *GetSidSubAuthority(psid, *GetSidSubAuthorityCount(psid) - 1);
201 * The RID maybe -1 if accountname == computername.
202 * In this case we search for the accountname in the passwd and group files.
203 * If type is needed, we search in each case.
205 if (id == -1 || type)
207 char account[UNLEN + 1];
208 char domain[INTERNET_MAX_HOST_NAME_LENGTH + 1];
209 DWORD acc_len = UNLEN + 1;
210 DWORD dom_len = INTERNET_MAX_HOST_NAME_LENGTH + 1;
211 SID_NAME_USE acc_type;
213 if (!LookupAccountSid (NULL, psid, account, &acc_len,
214 domain, &dom_len, &acc_type))
224 case SidTypeWellKnownGroup:
229 struct __group16 *gr = getgrnam (account);
239 struct passwd *pw = getpwnam (account);
254 is_grp_member (__uid16_t uid, __gid16_t gid)
256 extern int getgroups (int, __gid16_t *, __gid16_t, const char *);
257 BOOL grp_member = TRUE;
259 struct passwd *pw = getpwuid (uid);
260 __gid16_t grps[NGROUPS_MAX];
261 int cnt = getgroups (NGROUPS_MAX, grps,
262 pw ? pw->pw_gid : myself->gid,
263 pw ? pw->pw_name : cygheap->user.name ());
265 for (i = 0; i < cnt; ++i)
268 grp_member = (i < cnt);
272 #define SIDLEN (sidlen = MAX_SID_LEN, &sidlen)
273 #define DOMLEN (domlen = INTERNET_MAX_HOST_NAME_LENGTH, &domlen)
276 lookup_name (const char *name, const char *logsrv, PSID ret_sid)
280 char domuser[INTERNET_MAX_HOST_NAME_LENGTH + UNLEN + 2];
281 char dom[INTERNET_MAX_HOST_NAME_LENGTH + 1];
283 SID_NAME_USE acc_type;
285 debug_printf ("name : %s", name ? name : "NULL");
290 if (cygheap->user.domain ())
292 strcat (strcat (strcpy (domuser, cygheap->user.domain ()), "\\"), name);
293 if (LookupAccountName (NULL, domuser, sid, SIDLEN, dom, DOMLEN, &acc_type)
294 && legal_sid_type (acc_type))
296 if (logsrv && *logsrv
297 && LookupAccountName (logsrv, domuser, sid, SIDLEN,
298 dom, DOMLEN, &acc_type)
299 && legal_sid_type (acc_type))
302 if (logsrv && *logsrv)
304 if (LookupAccountName (logsrv, name, sid, SIDLEN, dom, DOMLEN, &acc_type)
305 && legal_sid_type (acc_type))
307 if (acc_type == SidTypeDomain)
309 strcat (strcat (strcpy (domuser, dom), "\\"), name);
310 if (LookupAccountName (logsrv, domuser, sid, SIDLEN,
311 dom, DOMLEN, &acc_type))
315 if (LookupAccountName (NULL, name, sid, SIDLEN, dom, DOMLEN, &acc_type)
316 && legal_sid_type (acc_type))
318 if (acc_type == SidTypeDomain)
320 strcat (strcat (strcpy (domuser, dom), "\\"), name);
321 if (LookupAccountName (NULL, domuser, sid, SIDLEN, dom, DOMLEN,&acc_type))
324 debug_printf ("LookupAccountName(%s) %E", name);
329 debug_printf ("sid : [%d]", *GetSidSubAuthority((PSID) sid,
330 *GetSidSubAuthorityCount((PSID) sid) - 1));
333 memcpy (ret_sid, sid, sidlen);
342 set_process_privilege (const char *privilege, BOOL enable)
344 HANDLE hToken = NULL;
346 TOKEN_PRIVILEGES new_priv, orig_priv;
350 if (!OpenProcessToken (hMainProc, TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
357 if (!LookupPrivilegeValue (NULL, privilege, &restore_priv))
363 new_priv.PrivilegeCount = 1;
364 new_priv.Privileges[0].Luid = restore_priv;
365 new_priv.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0;
367 if (!AdjustTokenPrivileges (hToken, FALSE, &new_priv,
368 sizeof orig_priv, &orig_priv, &size))
373 /* AdjustTokenPrivileges returns TRUE even if the privilege could not
374 be enabled. GetLastError() returns an correct error code, though. */
375 if (enable && GetLastError () == ERROR_NOT_ALL_ASSIGNED)
377 debug_printf ("Privilege %s couldn't be assigned", privilege);
382 ret = orig_priv.Privileges[0].Attributes == SE_PRIVILEGE_ENABLED ? 1 : 0;
386 CloseHandle (hToken);
388 syscall_printf ("%d = set_process_privilege (%s, %d)",ret, privilege, enable);