diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2001-04-20 13:02:32 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2001-04-20 13:02:32 +0000 |
commit | c0d1968a18c75ffb160c840c474b9b1e095cd541 (patch) | |
tree | 99ad46ce44b67c9c6c175bb8b61ca46e18d57336 /winsup/cygwin/sec_helper.cc | |
parent | 125261f738b1ae42ac89c50d06478b6955be1d73 (diff) | |
download | cygnal-c0d1968a18c75ffb160c840c474b9b1e095cd541.tar.gz cygnal-c0d1968a18c75ffb160c840c474b9b1e095cd541.tar.bz2 cygnal-c0d1968a18c75ffb160c840c474b9b1e095cd541.zip |
* Makefile.in: Add object files `sec_helper.cc' and `sec_acl.cc'.
* security.cc: Swap out several functions.
* sec_acl.cc: New file. Move Sun compatibel ACL functions from
`security.cc' to here.
* sec_helper.cc: New file. Move security helper functions from
`security.cc' to here.
* security.h: Changed to accomodate the above changes.
* grp.cc: Replace `group_in_memory_p' by `group_state'.
Eliminate group_sem throughout.
(enum grp_state): New enumeration type.
(read_etc_group): Make race safe.
* security.cc: Eliminate group_sem throughout.
Diffstat (limited to 'winsup/cygwin/sec_helper.cc')
-rw-r--r-- | winsup/cygwin/sec_helper.cc | 399 |
1 files changed, 399 insertions, 0 deletions
diff --git a/winsup/cygwin/sec_helper.cc b/winsup/cygwin/sec_helper.cc new file mode 100644 index 000000000..1771d934c --- /dev/null +++ b/winsup/cygwin/sec_helper.cc @@ -0,0 +1,399 @@ +/* sec_helper.cc: NT security helper functions + + Copyright 2000, 2001 Cygnus Solutions. + + Written by Corinna Vinschen <corinna@vinschen.de> + +This file is part of Cygwin. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +#include "winsup.h" +#include <grp.h> +#include <pwd.h> +#include <unistd.h> +#include <stdlib.h> +#include <errno.h> +#include <limits.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/acl.h> +#include <ctype.h> +#include <wingdi.h> +#include <winuser.h> +#include "cygerrno.h" +#include "perprocess.h" +#include "fhandler.h" +#include "path.h" +#include "dtable.h" +#include "sync.h" +#include "sigproc.h" +#include "pinfo.h" +#include "cygheap.h" +#include "security.h" + +SID_IDENTIFIER_AUTHORITY sid_auth[] = { + {SECURITY_NULL_SID_AUTHORITY}, + {SECURITY_WORLD_SID_AUTHORITY}, + {SECURITY_LOCAL_SID_AUTHORITY}, + {SECURITY_CREATOR_SID_AUTHORITY}, + {SECURITY_NON_UNIQUE_AUTHORITY}, + {SECURITY_NT_AUTHORITY} +}; + +char * +convert_sid_to_string_sid (PSID psid, char *sid_str) +{ + char t[32]; + DWORD i; + + if (!psid || !sid_str) + return NULL; + strcpy (sid_str, "S-1-"); + __small_sprintf(t, "%u", GetSidIdentifierAuthority (psid)->Value[5]); + strcat (sid_str, t); + for (i = 0; i < *GetSidSubAuthorityCount (psid); ++i) + { + __small_sprintf(t, "-%lu", *GetSidSubAuthority (psid, i)); + strcat (sid_str, t); + } + return sid_str; +} + +PSID +get_sid (PSID psid, DWORD s, DWORD cnt, DWORD *r) +{ + DWORD i; + + if (!psid || s > 5 || cnt < 1 || cnt > 8) + return NULL; + + InitializeSid(psid, &sid_auth[s], cnt); + for (i = 0; i < cnt; ++i) + memcpy ((char *) psid + 8 + sizeof (DWORD) * i, &r[i], sizeof (DWORD)); + return psid; +} + +PSID +convert_string_sid_to_sid (PSID psid, const char *sid_str) +{ + char sid_buf[256]; + char *t, *lasts; + DWORD cnt = 0; + DWORD s = 0; + DWORD i, r[8]; + + if (!sid_str || strncmp (sid_str, "S-1-", 4)) + return NULL; + + strcpy (sid_buf, sid_str); + + for (t = sid_buf + 4, i = 0; + cnt < 8 && (t = strtok_r (t, "-", &lasts)); + t = NULL, ++i) + if (i == 0) + s = strtoul (t, NULL, 10); + else + r[cnt++] = strtoul (t, NULL, 10); + + return get_sid (psid, s, cnt, r); +} + +BOOL +get_pw_sid (PSID sid, struct passwd *pw) +{ + char *sp = pw->pw_gecos ? strrchr (pw->pw_gecos, ',') : NULL; + + if (!sp) + return FALSE; + return convert_string_sid_to_sid (sid, ++sp) != NULL; +} + +BOOL +get_gr_sid (PSID sid, struct group *gr) +{ + return convert_string_sid_to_sid (sid, gr->gr_passwd) != NULL; +} + +PSID +get_admin_sid () +{ + static NO_COPY char admin_sid_buf[MAX_SID_LEN]; + static NO_COPY PSID admin_sid = NULL; + + if (!admin_sid) + { + admin_sid = (PSID) admin_sid_buf; + convert_string_sid_to_sid (admin_sid, "S-1-5-32-544"); + } + return admin_sid; +} + +PSID +get_system_sid () +{ + static NO_COPY char system_sid_buf[MAX_SID_LEN]; + static NO_COPY PSID system_sid = NULL; + + if (!system_sid) + { + system_sid = (PSID) system_sid_buf; + convert_string_sid_to_sid (system_sid, "S-1-5-18"); + } + return system_sid; +} + +PSID +get_creator_owner_sid () +{ + static NO_COPY char owner_sid_buf[MAX_SID_LEN]; + static NO_COPY PSID owner_sid = NULL; + + if (!owner_sid) + { + owner_sid = (PSID) owner_sid_buf; + convert_string_sid_to_sid (owner_sid, "S-1-3-0"); + } + return owner_sid; +} + +PSID +get_world_sid () +{ + static NO_COPY char world_sid_buf[MAX_SID_LEN]; + static NO_COPY PSID world_sid = NULL; + + if (!world_sid) + { + world_sid = (PSID) world_sid_buf; + convert_string_sid_to_sid (world_sid, "S-1-1-0"); + } + return world_sid; +} + +int +get_id_from_sid (PSID psid, BOOL search_grp, int *type) +{ + if (!IsValidSid (psid)) + { + __seterrno (); + small_printf ("IsValidSid failed with %E"); + return -1; + } + + /* First try to get SID from passwd or group entry */ + if (allow_ntsec) + { + char sidbuf[MAX_SID_LEN]; + PSID sid = (PSID) sidbuf; + int id = -1; + + if (!search_grp) + { + struct passwd *pw; + while ((pw = getpwent ()) != NULL) + { + if (get_pw_sid (sid, pw) && EqualSid (psid, sid)) + { + id = pw->pw_uid; + break; + } + } + endpwent (); + if (id >= 0) + { + if (type) + *type = USER; + return id; + } + } + if (search_grp || type) + { + struct group *gr; + while ((gr = getgrent ()) != NULL) + { + if (get_gr_sid (sid, gr) && EqualSid (psid, sid)) + { + id = gr->gr_gid; + break; + } + } + endgrent (); + if (id >= 0) + { + if (type) + *type = GROUP; + return id; + } + } + } + + /* We use the RID as default UID/GID */ + int id = *GetSidSubAuthority(psid, *GetSidSubAuthorityCount(psid) - 1); + + /* + * The RID maybe -1 if accountname == computername. + * In this case we search for the accountname in the passwd and group files. + * If type is needed, we search in each case. + */ + if (id == -1 || type) + { + char account[MAX_USER_NAME]; + char domain[MAX_COMPUTERNAME_LENGTH+1]; + DWORD acc_len = MAX_USER_NAME; + DWORD dom_len = MAX_COMPUTERNAME_LENGTH+1; + SID_NAME_USE acc_type; + + if (!LookupAccountSid (NULL, psid, account, &acc_len, + domain, &dom_len, &acc_type)) + { + __seterrno (); + return -1; + } + + switch (acc_type) + { + case SidTypeGroup: + case SidTypeAlias: + case SidTypeWellKnownGroup: + if (type) + *type = GROUP; + if (id == -1) + { + struct group *gr = getgrnam (account); + if (gr) + id = gr->gr_gid; + } + break; + case SidTypeUser: + if (type) + *type = USER; + if (id == -1) + { + struct passwd *pw = getpwnam (account); + if (pw) + id = pw->pw_uid; + } + break; + default: + break; + } + } + if (id == -1) + id = getuid (); + return id; +} + +int +get_id_from_sid (PSID psid, BOOL search_grp) +{ + return get_id_from_sid (psid, search_grp, NULL); +} + +BOOL +legal_sid_type (SID_NAME_USE type) +{ + return type == SidTypeUser || type == SidTypeGroup + || SidTypeAlias || SidTypeWellKnownGroup; +} + +BOOL +is_grp_member (uid_t uid, gid_t gid) +{ + extern int getgroups (int, gid_t *, gid_t, const char *); + BOOL grp_member = TRUE; + + struct passwd *pw = getpwuid (uid); + gid_t grps[NGROUPS_MAX]; + int cnt = getgroups (NGROUPS_MAX, grps, + pw ? pw->pw_gid : myself->gid, + pw ? pw->pw_name : cygheap->user.name ()); + int i; + for (i = 0; i < cnt; ++i) + if (grps[i] == gid) + break; + grp_member = (i < cnt); + return grp_member; +} + +BOOL +lookup_name (const char *name, const char *logsrv, PSID ret_sid) +{ + char sidbuf[MAX_SID_LEN]; + PSID sid = (PSID) sidbuf; + DWORD sidlen; + char domuser[MAX_COMPUTERNAME_LENGTH+MAX_USER_NAME+1]; + char dom[MAX_COMPUTERNAME_LENGTH+1]; + DWORD domlen; + SID_NAME_USE acc_type; + + debug_printf ("name : %s", name ? name : "NULL"); + + if (!name) + return FALSE; + + if (cygheap->user.domain ()) + { + strcat (strcat (strcpy (domuser, cygheap->user.domain ()), "\\"), name); + if (LookupAccountName (NULL, domuser, + sid, (sidlen = MAX_SID_LEN, &sidlen), + dom, (domlen = MAX_COMPUTERNAME_LENGTH, &domlen), + &acc_type) + && legal_sid_type (acc_type)) + goto got_it; + if (logsrv && *logsrv + && LookupAccountName (logsrv, domuser, + sid, (sidlen = MAX_SID_LEN, &sidlen), + dom, (domlen = MAX_COMPUTERNAME_LENGTH,&domlen), + &acc_type) + && legal_sid_type (acc_type)) + goto got_it; + } + if (logsrv && *logsrv) + { + if (LookupAccountName (logsrv, name, + sid, (sidlen = MAX_SID_LEN, &sidlen), + dom, (domlen = MAX_COMPUTERNAME_LENGTH, &domlen), + &acc_type) + && legal_sid_type (acc_type)) + goto got_it; + if (acc_type == SidTypeDomain) + { + strcat (strcat (strcpy (domuser, dom), "\\"), name); + if (LookupAccountName (logsrv, domuser, + sid,(sidlen = MAX_SID_LEN, &sidlen), + dom,(domlen = MAX_COMPUTERNAME_LENGTH,&domlen), + &acc_type)) + goto got_it; + } + } + if (LookupAccountName (NULL, name, + sid, (sidlen = MAX_SID_LEN, &sidlen), + dom, (domlen = 100, &domlen), + &acc_type) + && legal_sid_type (acc_type)) + goto got_it; + if (acc_type == SidTypeDomain) + { + strcat (strcat (strcpy (domuser, dom), "\\"), name); + if (LookupAccountName (NULL, domuser, + sid, (sidlen = MAX_SID_LEN, &sidlen), + dom, (domlen = MAX_COMPUTERNAME_LENGTH, &domlen), + &acc_type)) + goto got_it; + } + debug_printf ("LookupAccountName(%s) %E", name); + __seterrno (); + return FALSE; + +got_it: + debug_printf ("sid : [%d]", *GetSidSubAuthority((PSID) sid, + *GetSidSubAuthorityCount((PSID) sid) - 1)); + + if (ret_sid) + memcpy (ret_sid, sid, sidlen); + + return TRUE; +} |