From 1f0f8e127c6a6fd7520ebc08eb2f479507247d5f Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Wed, 15 Nov 2000 00:13:09 +0000 Subject: [PATCH] * cygheap.cc (cygheap_root::cygheap_root): New function. (cygheap_root::~cygheap_root): Ditto. (cygheap_root::operator=): Ditto. (cygheap_user::~cygheap_user): Ditto. (cygheap_user::set_name): Ditto. (cygheap_user::set_logsrv): Ditto. (cygheap_user::set_domain): Ditto. (cygheap_user::set_sid): Ditto. * cygheap.h (cygheap_root): New class. (cygheap_user): Ditto. (init_cygheap): Change type of `root' member to cygheap_root. Add `user' member. * dir.cc (opendir): Use new `cygheap_root' class. * dcrt0.cc (dll_crt0_1): Use new `cygheap_user' class. * fork.cc (fork_parent): Ditto. * grp.cc (getgroups): Ditto. * passwd.cc (search_for): Ditto. * path.cc: Use new `cygheap_root' class throughout. * pinfo.h (_pinfo): Remove `use_psid'. Move `username', `psid', `logsrv', `domain', `orig_{uid,gid}' and `real_{uid,gid}' to cygheap_user class. * security.cc: Use new `cygheap_user' class throughout. * shared.cc (sec_user): Ditto. * sigproc.cc (proc_subproc): Remove copy statements for user related information moved to `cygheap_user' class. * spawn.cc (spawn_guts): Invalidate current chroot settings when creating Windows environment. Use new `cygheap_user' class. * syscalls.cc: Use new `cygheap_user' class throughout. * uinfo.cc: Ditto. * uinfo.cc (internal_getlogin): Change parameters to reflect the move of user information to cygheap. --- winsup/cygwin/ChangeLog | 34 ++++++++++++++ winsup/cygwin/cygheap.cc | 90 +++++++++++++++++++++++++++++++++++ winsup/cygwin/cygheap.h | 59 +++++++++++++++++++++-- winsup/cygwin/dcrt0.cc | 2 +- winsup/cygwin/dir.cc | 2 +- winsup/cygwin/fork.cc | 3 +- winsup/cygwin/grp.cc | 10 +--- winsup/cygwin/passwd.cc | 3 +- winsup/cygwin/path.cc | 34 +++++++------- winsup/cygwin/pinfo.h | 13 ------ winsup/cygwin/security.cc | 9 ++-- winsup/cygwin/shared.cc | 7 +-- winsup/cygwin/sigproc.cc | 11 ----- winsup/cygwin/spawn.cc | 10 ++-- winsup/cygwin/syscalls.cc | 40 +++++++--------- winsup/cygwin/uinfo.cc | 98 +++++++++++++++++++++------------------ 16 files changed, 287 insertions(+), 138 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 58e6e67c4..623570261 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,37 @@ +Wed Nov 15 0:51:00 2000 Corinna Vinschen + + * cygheap.cc (cygheap_root::cygheap_root): New function. + (cygheap_root::~cygheap_root): Ditto. + (cygheap_root::operator=): Ditto. + (cygheap_user::~cygheap_user): Ditto. + (cygheap_user::set_name): Ditto. + (cygheap_user::set_logsrv): Ditto. + (cygheap_user::set_domain): Ditto. + (cygheap_user::set_sid): Ditto. + * cygheap.h (cygheap_root): New class. + (cygheap_user): Ditto. + (init_cygheap): Change type of `root' member to cygheap_root. + Add `user' member. + * dir.cc (opendir): Use new `cygheap_root' class. + * dcrt0.cc (dll_crt0_1): Use new `cygheap_user' class. + * fork.cc (fork_parent): Ditto. + * grp.cc (getgroups): Ditto. + * passwd.cc (search_for): Ditto. + * path.cc: Use new `cygheap_root' class throughout. + * pinfo.h (_pinfo): Remove `use_psid'. Move `username', `psid', + `logsrv', `domain', `orig_{uid,gid}' and `real_{uid,gid}' to + cygheap_user class. + * security.cc: Use new `cygheap_user' class throughout. + * shared.cc (sec_user): Ditto. + * sigproc.cc (proc_subproc): Remove copy statements for user + related information moved to `cygheap_user' class. + * spawn.cc (spawn_guts): Invalidate current chroot settings + when creating Windows environment. Use new `cygheap_user' class. + * syscalls.cc: Use new `cygheap_user' class throughout. + * uinfo.cc: Ditto. + * uinfo.cc (internal_getlogin): Change parameters to reflect the + move of user information to cygheap. + Tue Nov 14 17:05:00 2000 Eric Fifer * dir.cc (rewinddir): Always set __d_position = 0, so next diff --git a/winsup/cygwin/cygheap.cc b/winsup/cygwin/cygheap.cc index 15c2667c0..0d720e9d5 100644 --- a/winsup/cygwin/cygheap.cc +++ b/winsup/cygwin/cygheap.cc @@ -279,3 +279,93 @@ cstrdup1 (const char *s) MALLOC_CHECK; return p; } + +cygheap_root::cygheap_root (cygheap_root &nroot) +{ + rootlen = nroot.rootlen; + root = nroot.root ? cstrdup (nroot.root) : NULL; +} + +cygheap_root::~cygheap_root () +{ + if (root) + cfree (root); +} + +char * +cygheap_root::operator =(const char *new_root) +{ + if (root) + { + cfree (root); + root = NULL; + } + rootlen = 0; + if (new_root && *new_root) + { + root = cstrdup (new_root); + rootlen = strlen (root); + if (rootlen > 1 && root[rootlen - 1] == '/') + root[--rootlen] = '\0'; + if (!rootlen) + { + cfree (root); + root = NULL; + } + } + return root; +} + +cygheap_user::~cygheap_user () +{ + if (pname) + cfree (pname); + if (plogsrv) + cfree (plogsrv); + if (pdomain) + cfree (pdomain); + if (psid) + cfree (psid); +} + +void +cygheap_user::set_name (const char *new_name) +{ + if (pname) + cfree (pname); + pname = cstrdup (new_name ? new_name : ""); +} + +void +cygheap_user::set_logsrv (const char *new_logsrv) +{ + if (plogsrv) + cfree (plogsrv); + plogsrv = (new_logsrv && *new_logsrv) ? cstrdup (new_logsrv) : NULL; +} + +void +cygheap_user::set_domain (const char *new_domain) +{ + if (pdomain) + cfree (pdomain); + pdomain = (new_domain && *new_domain) ? cstrdup (new_domain) : NULL; +} + +BOOL +cygheap_user::set_sid (PSID new_sid) +{ + if (!new_sid) + { + if (psid) + cfree (psid); + psid = NULL; + return TRUE; + } + else + { + if (!psid) + psid = cmalloc (HEAP_STR, MAX_SID_LEN); + return CopySid (MAX_SID_LEN, psid, new_sid); + } +} diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h index faa50bf12..779df67d3 100644 --- a/winsup/cygwin/cygheap.h +++ b/winsup/cygwin/cygheap.h @@ -39,15 +39,64 @@ struct _cmalloc_entry char data[0]; }; +class cygheap_root +{ + /* Root directory information. + This is used after a chroot is called. */ + size_t rootlen; + char *root; +public: + cygheap_root (cygheap_root &nroot); + ~cygheap_root (); + char *operator =(const char *new_root); + size_t length () const { return rootlen; } + const char *path () const { return root; } +}; + +class cygheap_user { + /* Extendend user information. + The information is derived from the internal_getlogin call + when on a NT system. */ + char *pname; /* user's name */ + char *plogsrv; /* Logon server, may be FQDN */ + char *pdomain; /* Logon domain of the user */ + PSID psid; /* buffer for user's SID */ + +public: + uid_t orig_uid; /* Remains intact even after impersonation */ + uid_t orig_gid; /* Ditto */ + uid_t real_uid; /* Remains intact on seteuid, replaced by setuid */ + gid_t real_gid; /* Ditto */ + + cygheap_user () : pname (NULL), plogsrv (NULL), pdomain (NULL), psid (NULL) {} + ~cygheap_user (); + + void set_name (const char *new_name); + const char *name () const { return pname; } + + void set_logsrv (const char *new_logsrv); + const char *logsrv () const { return plogsrv; } + + void set_domain (const char *new_domain); + const char *domain () const { return pdomain; } + + BOOL set_sid (PSID new_sid); + PSID sid () const { return psid; } + + void operator =(cygheap_user &user) + { + set_name (user.name ()); + set_logsrv (user.logsrv ()); + set_domain (user.domain ()); + set_sid (user.sid ()); + } +}; struct init_cygheap { _cmalloc_entry *chain; - struct - { - size_t rootlen; - char *root; - }; + cygheap_root root; + cygheap_user user; mode_t umask; }; diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index 7f75eca8f..c0a9f50d3 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -711,7 +711,7 @@ dll_crt0_1 () ProtectHandle (child_proc_info->subproc_ready); myself->uid = spawn_info->moreinfo->uid; if (myself->uid == USHRT_MAX) - myself->use_psid = 0; + cygheap->user.set_sid (NULL); break; } } diff --git a/winsup/cygwin/dir.cc b/winsup/cygwin/dir.cc index ee7d2a967..a14b44f8f 100644 --- a/winsup/cygwin/dir.cc +++ b/winsup/cygwin/dir.cc @@ -76,7 +76,7 @@ opendir (const char *dirname) goto failed; } - if (stat (cygheap->rootlen ? dirname : real_dirname.get_win32 (), + if (stat (cygheap->root.length () ? dirname : real_dirname.get_win32 (), &statbuf) == -1) goto failed; diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc index c5536e2b7..10c20040e 100644 --- a/winsup/cygwin/fork.cc +++ b/winsup/cygwin/fork.cc @@ -402,7 +402,7 @@ fork_parent (void *stack_here, HANDLE& hParent, dll *&first_dll, bool& load_dlls uid_t uid; uid = geteuid(); if (myself->impersonated && myself->token != INVALID_HANDLE_VALUE) - seteuid (myself->orig_uid); + seteuid (cygheap->user.orig_uid); ch.parent = hParent; ch.cygheap = cygheap; @@ -474,7 +474,6 @@ fork_parent (void *stack_here, HANDLE& hParent, dll *&first_dll, bool& load_dlls forked->hProcess = pi.hProcess; forked->dwProcessId = pi.dwProcessId; forked->copysigs(myself); - memcpy (forked->username, myself->username, MAX_USER_NAME); set_child_mmap_ptr (forked); forked.remember (); diff --git a/winsup/cygwin/grp.cc b/winsup/cygwin/grp.cc index 0469c0217..737c50595 100644 --- a/winsup/cygwin/grp.cc +++ b/winsup/cygwin/grp.cc @@ -19,6 +19,7 @@ details. */ #include "sync.h" #include "sigproc.h" #include "pinfo.h" +#include "cygheap.h" #include "cygerrno.h" /* Read /etc/group only once for better performance. This is done @@ -273,14 +274,7 @@ extern "C" int getgroups (int gidsetsize, gid_t *grouplist) { -#if 0 - if (gidsetsize <= 0) - return 0; - grouplist[0] = myself->gid; - return 1; -#else - return getgroups (gidsetsize, grouplist, myself->gid, myself->username); -#endif + return getgroups (gidsetsize, grouplist, myself->gid, cygheap->user.name ()); } extern "C" diff --git a/winsup/cygwin/passwd.cc b/winsup/cygwin/passwd.cc index 62b2955a0..797fb5375 100644 --- a/winsup/cygwin/passwd.cc +++ b/winsup/cygwin/passwd.cc @@ -19,6 +19,7 @@ details. */ #include "sync.h" #include "sigproc.h" #include "pinfo.h" +#include "cygheap.h" #include /* Read /etc/passwd only once for better performance. This is done @@ -179,7 +180,7 @@ search_for (uid_t uid, const char *name) request for the current user. */ if (passwd_state != loaded || (!name && uid == myself->uid) - || (name && strcasematch(name, myself->username))) + || (name && strcasematch(name, cygheap->user.name ()))) return default_pw; return NULL; diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index b415afa5a..b878920f7 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -109,10 +109,11 @@ cwdstuff cygcwd; /* The current working directory. */ (isdirsep(path[cygwin_shared->mount.cygdrive_len + 1]) || \ !path[cygwin_shared->mount.cygdrive_len + 1])) -#define ischrootpath(path) \ - (cygheap->rootlen && \ - strncasematch (cygheap->root, path, cygheap->rootlen) && \ - (path[cygheap->rootlen] == '/' || path[cygheap->rootlen] == '\0')) +#define ischrootpath(p) \ + (cygheap->root.length () && \ + strncasematch (cygheap->root.path (), p, cygheap->root.length ()) && \ + (p[cygheap->root.length ()] == '/' \ + || p[cygheap->root.length ()] == '\0')) /* Return non-zero if PATH1 is a prefix of PATH2. Both are assumed to be of the same path style and / vs \ usage. @@ -615,7 +616,7 @@ normalize_posix_path (const char *src, char *dst) /* Two leading /'s? If so, preserve them. */ else if (isslash (src[1])) { - if (cygheap->rootlen) + if (cygheap->root.length ()) { debug_printf ("ENOENT = normalize_posix_path (%s)", src); return ENOENT; @@ -631,10 +632,10 @@ normalize_posix_path (const char *src, char *dst) } } /* Exactly one leading slash. Absolute path. Check for chroot. */ - else if (cygheap->rootlen) + else if (cygheap->root.length ()) { - strcpy (dst, cygheap->root); - dst += cygheap->rootlen; + strcpy (dst, cygheap->root.path ()); + dst += cygheap->root.length (); } while (*src) @@ -669,7 +670,7 @@ normalize_posix_path (const char *src, char *dst) else { if (!ischrootpath (dst_start) || - dst - dst_start != (int) cygheap->rootlen) + dst - dst_start != (int) cygheap->root.length ()) while (dst > dst_start && !isslash (*--dst)) continue; src++; @@ -718,7 +719,7 @@ normalize_win32_path (const char *src, char *dst) /* Two leading \'s? If so, preserve them. */ else if (SLASH_P (src[0]) && SLASH_P (src[1])) { - if (cygheap->rootlen) + if (cygheap->root.length ()) { debug_printf ("ENOENT = normalize_win32_path (%s)", src); return ENOENT; @@ -727,13 +728,13 @@ normalize_win32_path (const char *src, char *dst) ++src; } /* If absolute path, care for chroot. */ - else if (SLASH_P (src[0]) && !SLASH_P (src[1]) && cygheap->rootlen) + else if (SLASH_P (src[0]) && !SLASH_P (src[1]) && cygheap->root.length ()) { - strcpy (dst, cygheap->root); + strcpy (dst, cygheap->root.path ()); char *c; while ((c = strchr (dst, '/')) != NULL) *c = '\\'; - dst += cygheap->rootlen; + dst += cygheap->root.length (); dst_root_start = dst; *dst++ = '\\'; } @@ -997,7 +998,7 @@ mount_info::conv_to_win32_path (const char *src_path, char *win32_path, } isrelpath = !isabspath (src_path); *flags = set_flags_from_win32_path (dst); - if (cygheap->rootlen && dst[0] && dst[1] == ':') + if (cygheap->root.length () && dst[0] && dst[1] == ':') { char posix_path[MAX_PATH + 1]; @@ -2939,9 +2940,10 @@ cwdstuff::get (char *buf, int need_posix, int with_chroot, unsigned ulen) tocopy = win32; else tocopy = with_chroot && ischrootpath(posix) ? - posix + cygheap->rootlen : posix; + posix + cygheap->root.length () : posix; - debug_printf("cygheap->root: %s, posix: %s", cygheap->root, posix); + debug_printf("cygheap->root: %s, posix: %s", + (const char *) cygheap->root.path (), posix); if (strlen (tocopy) >= ulen) { set_errno (ERANGE); diff --git a/winsup/cygwin/pinfo.h b/winsup/cygwin/pinfo.h index 74ceb95c5..0171a71b0 100644 --- a/winsup/cygwin/pinfo.h +++ b/winsup/cygwin/pinfo.h @@ -73,24 +73,11 @@ public: pid_t sid; /* Session ID */ int ctty; /* Control tty */ bool has_pgid_children;/* True if we've forked or spawned children with our GID. */ - char username[MAX_USER_NAME]; /* user's name */ - - /* Extendend user information. - The information is derived from the internal_getlogin call - when on a NT system. */ - int use_psid; /* TRUE if psid contains valid data */ - char psid[MAX_SID_LEN]; /* buffer for user's SID */ - char logsrv[MAX_HOST_NAME]; /* Logon server, may be FQDN */ - char domain[MAX_COMPUTERNAME_LENGTH+1]; /* Logon domain of the user */ /* token is needed if sexec should be called. It can be set by a call to `set_impersonation_token()'. */ HANDLE token; BOOL impersonated; - uid_t orig_uid; /* Remains intact also after impersonation */ - uid_t orig_gid; /* Ditto */ - uid_t real_uid; /* Remains intact on seteuid, replaced by setuid */ - gid_t real_gid; /* Ditto */ /* Resources used by process. */ long start_time; diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc index 6d0f5a6bc..35caf1d79 100644 --- a/winsup/cygwin/security.cc +++ b/winsup/cygwin/security.cc @@ -29,6 +29,7 @@ details. */ #include "sync.h" #include "sigproc.h" #include "pinfo.h" +#include "cygheap.h" #include "security.h" extern BOOL allow_ntea; @@ -326,7 +327,7 @@ is_grp_member (uid_t uid, gid_t gid) gid_t grps[NGROUPS_MAX]; int cnt = getgroups (NGROUPS_MAX, grps, pw ? pw->pw_gid : myself->gid, - pw ? pw->pw_name : myself->username); + pw ? pw->pw_name : cygheap->user.name ()); int i; for (i = 0; i < cnt; ++i) if (grps[i] == gid) @@ -352,9 +353,9 @@ lookup_name (const char *name, const char *logsrv, PSID ret_sid) if (! name) return FALSE; - if (*myself->domain) + if (cygheap->user.domain ()) { - strcat (strcat (strcpy (domuser, myself->domain), "\\"), name); + strcat (strcat (strcpy (domuser, cygheap->user.domain ()), "\\"), name); if (LookupAccountName (NULL, domuser, sid, (sidlen = MAX_SID_LEN, &sidlen), dom, (domlen = MAX_COMPUTERNAME_LENGTH, &domlen), @@ -1138,7 +1139,7 @@ set_file_attribute (int use_ntsec, const char *file, int attribute) { return set_file_attribute (use_ntsec, file, myself->uid, myself->gid, - attribute, myself->logsrv); + attribute, cygheap->user.logsrv ()); } static int diff --git a/winsup/cygwin/shared.cc b/winsup/cygwin/shared.cc index ee68c9b4a..fb023e725 100644 --- a/winsup/cygwin/shared.cc +++ b/winsup/cygwin/shared.cc @@ -17,6 +17,7 @@ details. */ #include "sync.h" #include "sigproc.h" #include "pinfo.h" +#include "cygheap.h" #include "shared_info.h" #include "registry.h" #include "cygwin_version.h" @@ -219,9 +220,9 @@ sec_user (PVOID sa_buf, PSID sid2, BOOL inherit) char sid_buf[MAX_SID_LEN]; PSID sid = (PSID) sid_buf; - if (myself->use_psid) - CopySid (MAX_SID_LEN, sid, myself->psid); - else if (! lookup_name (getlogin (), myself->logsrv, sid)) + if (cygheap->user.sid ()) + CopySid (MAX_SID_LEN, sid, (void *) cygheap->user.sid ()); + else if (! lookup_name (getlogin (), cygheap->user.logsrv (), sid)) return inherit ? &sec_none_nih : &sec_none; size_t acl_len = sizeof (ACL) diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index 999dc7319..472b101e8 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -263,18 +263,7 @@ proc_subproc (DWORD what, DWORD val) vchild->pgid = myself->pgid; vchild->sid = myself->sid; vchild->ctty = myself->ctty; - vchild->orig_uid = myself->orig_uid; - vchild->orig_gid = myself->orig_gid; - vchild->real_uid = myself->real_uid; - vchild->real_gid = myself->real_gid; vchild->impersonated = myself->impersonated; - if (myself->use_psid) - { - vchild->use_psid = 1; - memcpy (vchild->psid, myself->psid, MAX_SID_LEN); - } - memcpy (vchild->logsrv, myself->logsrv, MAX_HOST_NAME); - memcpy (vchild->domain, myself->domain, MAX_COMPUTERNAME_LENGTH+1); vchild->token = myself->token; vchild->process_state |= PID_INITIALIZING | (myself->process_state & PID_USETTY); diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc index e17541446..7dc193c48 100644 --- a/winsup/cygwin/spawn.cc +++ b/winsup/cygwin/spawn.cc @@ -554,7 +554,12 @@ skip_arg_parsing: if (real_path.iscygexec ()) envblock = NULL; else - envblock = winenv (envp, 0); + { + cygheap_root sav_root (cygheap->root); + cygheap->root = NULL; + envblock = winenv (envp, 0); + cygheap->root = sav_root; + } ciresrv.cygheap = cygheap; ciresrv.cygheap_max = cygheap_max; @@ -625,7 +630,7 @@ skip_arg_parsing: /* Remove impersonation */ uid_t uid = geteuid(); if (myself->impersonated && myself->token != INVALID_HANDLE_VALUE) - seteuid (myself->orig_uid); + seteuid (cygheap->user.orig_uid); /* Load users registry hive. */ load_registry_hive (sid); @@ -705,7 +710,6 @@ skip_arg_parsing: syscall_printf ("-1 = spawnve (), process table full"); return -1; } - child->username[0] = '\0'; child->progname[0] = '\0'; child->dwProcessId = pi.dwProcessId; child->hProcess = pi.hProcess; diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index 348a49b8b..90cc1b785 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -704,7 +704,7 @@ chown_worker (const char *name, unsigned fmode, uid_t uid, gid_t gid) res = set_file_attribute (win32_path.has_acls (), win32_path.get_win32 (), uid, gid, attrib, - myself->logsrv); + cygheap->user.logsrv ()); } if (res != 0 && get_errno () == ENOSYS) { @@ -815,7 +815,7 @@ chmod (const char *path, mode_t mode) if (! set_file_attribute (win32_path.has_acls (), win32_path.get_win32 (), uid, gid, - mode, myself->logsrv) + mode, cygheap->user.logsrv ()) && allow_ntsec) res = 0; @@ -1796,7 +1796,7 @@ setgid (gid_t gid) { int ret = setegid (gid); if (!ret) - myself->real_gid = myself->gid; + cygheap->user.real_gid = myself->gid; return ret; } @@ -1806,12 +1806,12 @@ setuid (uid_t uid) { int ret = seteuid (uid); if (!ret) - myself->real_uid = myself->uid; - debug_printf ("real: %d, effective: %d", myself->real_uid, myself->uid); + cygheap->user.real_uid = myself->uid; + debug_printf ("real: %d, effective: %d", cygheap->user.real_uid, myself->uid); return ret; } -extern char *internal_getlogin (_pinfo *pi); +extern const char *internal_getlogin (cygheap_user &user, HANDLE token); /* seteuid: standards? */ extern "C" int @@ -1830,7 +1830,7 @@ seteuid (uid_t uid) } if (uid != myself->uid) - if (uid == myself->orig_uid) + if (uid == cygheap->user.orig_uid) { debug_printf ("RevertToSelf() (uid == orig_uid, token=%d)", myself->token); @@ -1850,32 +1850,28 @@ seteuid (uid_t uid) myself->impersonated = TRUE; } - struct _pinfo pi; - /* pi.token is used in internal_getlogin() to determine if + cygheap_user user; + /* token is used in internal_getlogin() to determine if impersonation is active. If so, the token is used for retrieving user's SID. */ - pi.token = myself->impersonated ? myself->token - : INVALID_HANDLE_VALUE; - struct passwd *pw_cur = getpwnam (internal_getlogin (&pi)); + HANDLE token = myself->impersonated ? myself->token + : INVALID_HANDLE_VALUE; + struct passwd *pw_cur = getpwnam (internal_getlogin (user, token)); if (pw_cur != pw_new) { debug_printf ("Diffs!!! token: %d, cur: %d, new: %d, orig: %d", myself->token, pw_cur->pw_uid, - pw_new->pw_uid, myself->orig_uid); + pw_new->pw_uid, cygheap->user.orig_uid); set_errno (EPERM); return -1; } myself->uid = uid; - strcpy (myself->username, pi.username); - strcpy (myself->logsrv, pi.logsrv); - strcpy (myself->domain, pi.domain); - memcpy (myself->psid, pi.psid, MAX_SID_LEN); - myself->use_psid = 1; + cygheap->user = user; } } else set_errno (ENOSYS); - debug_printf ("real: %d, effective: %d", myself->real_uid, myself->uid); + debug_printf ("real: %d, effective: %d", cygheap->user.real_uid, myself->uid); return 0; } @@ -1930,11 +1926,7 @@ chroot (const char *newroot) set_errno (ret); goto done; } - cygheap->rootlen = strlen (cygheap->root); - if (cygheap->rootlen > 1 && buf[cygheap->rootlen - 1] == '/') - buf[--cygheap->rootlen] = '\0'; - cygheap->root = (char *) crealloc (cygheap->root, cygheap->rootlen + 1); - strcpy (cygheap->root, buf); + cygheap->root = buf; ret = 0; done: diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc index 45f3747c0..8a95fa349 100644 --- a/winsup/cygwin/uinfo.cc +++ b/winsup/cygwin/uinfo.cc @@ -20,18 +20,20 @@ details. */ #include "sync.h" #include "sigproc.h" #include "pinfo.h" +#include "cygheap.h" #include "registry.h" #include "security.h" -char * -internal_getlogin (_pinfo *pi) +const char * +internal_getlogin (cygheap_user &user, HANDLE token) { - if (! pi) - api_fatal ("pinfo pointer is NULL!\n"); - + char username[MAX_USER_NAME]; DWORD username_len = MAX_USER_NAME; - if (! GetUserName (pi->username, &username_len)) - strcpy (pi->username, "unknown"); + + if (! GetUserName (username, &username_len)) + user.set_name ("unknown"); + else + user.set_name (username); if (os_being_run == winNT) { LPWKSTA_USER_INFO_1 wui; @@ -42,31 +44,37 @@ internal_getlogin (_pinfo *pi) if ((env = getenv ("USERNAME")) != NULL) un = env; if ((env = getenv ("LOGONSERVER")) != NULL) - strcpy (pi->logsrv, env + 2); /* filter leading double backslashes */ + user.set_logsrv (env + 2); /* filter leading double backslashes */ if ((env = getenv ("USERDOMAIN")) != NULL) - strcpy (pi->domain, env); + user.set_domain (env); /* Trust only if usernames are identical */ - if (un && strcasematch (pi->username, un) - && pi->domain[0] && pi->logsrv[0]) - debug_printf ("Domain: %s, Logon Server: %s", pi->domain, pi->logsrv); + if (un && strcasematch (user.name (), un) + && user.domain () && user.logsrv ()) + debug_printf ("Domain: %s, Logon Server: %s", + user.domain (), user.logsrv ()); /* If that failed, try to get that info from NetBIOS */ else if (!NetWkstaUserGetInfo (NULL, 1, (LPBYTE *)&wui)) { - sys_wcstombs (pi->username, wui->wkui1_username, MAX_USER_NAME); - sys_wcstombs (pi->logsrv, wui->wkui1_logon_server, MAX_HOST_NAME); - sys_wcstombs (pi->domain, wui->wkui1_logon_domain, + char buf[512]; + + sys_wcstombs (buf, wui->wkui1_username, MAX_USER_NAME); + user.set_name (buf); + sys_wcstombs (buf, wui->wkui1_logon_server, MAX_HOST_NAME); + user.set_logsrv (buf); + sys_wcstombs (buf, wui->wkui1_logon_domain, MAX_COMPUTERNAME_LENGTH + 1); + user.set_domain (buf); /* Save values in environment */ - if (!strcasematch (pi->username, "SYSTEM") - && pi->domain[0] && pi->logsrv[0]) + if (!strcasematch (user.name (), "SYSTEM") + && user.domain () && user.logsrv ()) { LPUSER_INFO_3 ui = NULL; WCHAR wbuf[MAX_HOST_NAME + 2]; - strcat (strcpy (buf, "\\\\"), pi->logsrv); - setenv ("USERNAME", pi->username, 1); + strcat (strcpy (buf, "\\\\"), user.logsrv ()); + setenv ("USERNAME", user.name (), 1); setenv ("LOGONSERVER", buf, 1); - setenv ("USERDOMAIN", pi->domain, 1); + setenv ("USERDOMAIN", user.domain (), 1); /* HOMEDRIVE and HOMEPATH are wrong most of the time, too, after changing user context! */ sys_mbstowcs (wbuf, buf, MAX_HOST_NAME + 2); @@ -95,12 +103,12 @@ internal_getlogin (_pinfo *pi) } } debug_printf ("Domain: %s, Logon Server: %s, Windows Username: %s", - pi->domain, pi->logsrv, pi->username); + user.domain (), user.logsrv (), user.name ()); NetApiBufferFree (wui); } if (allow_ntsec) { - HANDLE ptok = pi->token; /* Which is INVALID_HANDLE_VALUE if no + HANDLE ptok = token; /* Which is INVALID_HANDLE_VALUE if no impersonation took place. */ DWORD siz; char tu[1024]; @@ -116,29 +124,28 @@ internal_getlogin (_pinfo *pi) else if (!GetTokenInformation (ptok, TokenUser, (LPVOID) &tu, sizeof tu, &siz)) debug_printf ("GetTokenInformation(): %E"); - else if (!(ret = CopySid (MAX_SID_LEN, (PSID) pi->psid, - ((TOKEN_USER *) &tu)->User.Sid))) + else if (!(ret = user.set_sid (((TOKEN_USER *) &tu)->User.Sid))) debug_printf ("Couldn't retrieve SID from access token!"); /* Close token only if it's a result from OpenProcessToken(). */ - if (ptok != INVALID_HANDLE_VALUE && pi->token == INVALID_HANDLE_VALUE) + if (ptok != INVALID_HANDLE_VALUE && token == INVALID_HANDLE_VALUE) CloseHandle (ptok); /* If that failes, try to get the SID from localhost. This can only be done if a domain is given because there's a chance that a local and a domain user may have the same name. */ - if (!ret && pi->domain[0]) + if (!ret && user.domain ()) { /* Concat DOMAIN\USERNAME for the next lookup */ - strcat (strcat (strcpy (buf, pi->domain), "\\"), pi->username); - if (!(ret = lookup_name (buf, NULL, (PSID) pi->psid))) + strcat (strcat (strcpy (buf, user.domain ()), "\\"), user.name ()); + if (!(ret = lookup_name (buf, NULL, user.sid ()))) debug_printf ("Couldn't retrieve SID locally!"); } /* If that failes, too, as a last resort try to get the SID from the logon server. */ - if (!ret && !(ret = lookup_name(pi->username, pi->logsrv, - (PSID)pi->psid))) - debug_printf ("Couldn't retrieve SID from '%s'!", pi->logsrv); + if (!ret && !(ret = lookup_name(user.name (), user.logsrv (), + user.sid ()))) + debug_printf ("Couldn't retrieve SID from '%s'!", user.logsrv ()); /* If we have a SID, try to get the corresponding Cygwin user name which can be different from the Windows user name. */ @@ -148,31 +155,29 @@ internal_getlogin (_pinfo *pi) char psidbuf[MAX_SID_LEN]; PSID psid = (PSID) psidbuf; - pi->use_psid = 1; - if (!strcasematch (pi->username, "SYSTEM") - && pi->domain[0] && pi->logsrv[0]) + if (!strcasematch (user.name (), "SYSTEM") + && user.domain () && user.logsrv ()) { - if (get_registry_hive_path (pi->psid, buf)) + if (get_registry_hive_path (user.sid (), buf)) setenv ("USERPROFILE", buf, 1); } while ((pw = getpwent ()) != NULL) - if (get_pw_sid (psid, pw) && EqualSid (pi->psid, psid)) + if (get_pw_sid (psid, pw) && EqualSid (user.sid (), psid)) { - strcpy (pi->username, pw->pw_name); + user.set_name (pw->pw_name); break; } endpwent (); } } } - debug_printf ("Cygwins Username: %s", pi->username); - return pi->username; + debug_printf ("Cygwins Username: %s", user.name ()); + return user.name (); } void uinfo_init () { - char *username; struct passwd *p; /* Initialize to non impersonated values. @@ -185,7 +190,8 @@ uinfo_init () /* If uid is USHRT_MAX, the process is started from a non cygwin process or the user context was changed in spawn.cc */ if (myself->uid == USHRT_MAX) - if ((p = getpwnam (username = internal_getlogin (myself))) != NULL) + if ((p = getpwnam (internal_getlogin (cygheap->user, + INVALID_HANDLE_VALUE))) != NULL) { myself->uid = p->pw_uid; myself->gid = p->pw_gid; @@ -197,8 +203,8 @@ uinfo_init () } /* Real and effective uid/gid are always identical on process start up. This is at least true for NT/W2K. */ - myself->orig_uid = myself->real_uid = myself->uid; - myself->orig_gid = myself->real_gid = myself->gid; + cygheap->user.orig_uid = cygheap->user.real_uid = myself->uid; + cygheap->user.orig_gid = cygheap->user.real_gid = myself->gid; } extern "C" char * @@ -210,19 +216,19 @@ getlogin (void) static NO_COPY char this_username[MAX_USER_NAME]; #endif - return strcpy (this_username, myself->username); + return strcpy (this_username, cygheap->user.name ()); } extern "C" uid_t getuid (void) { - return myself->real_uid; + return cygheap->user.real_uid; } extern "C" gid_t getgid (void) { - return myself->real_gid; + return cygheap->user.real_gid; } extern "C" uid_t