1 /* uinfo.cc: user info (uid, gid, etc...)
3 Copyright 1996, 1997, 1998, 1999, 2000, 2001 Red Hat, Inc.
5 This file is part of Cygwin.
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
20 #include <sys/cygwin.h>
32 internal_getlogin (cygheap_user &user)
34 char username[UNLEN + 1];
35 DWORD username_len = UNLEN + 1;
36 struct passwd *pw = NULL;
38 if (!GetUserName (username, &username_len))
39 user.set_name ("unknown");
41 user.set_name (username);
42 debug_printf ("GetUserName() = %s", user.name ());
44 if (wincap.has_security ())
46 LPWKSTA_USER_INFO_1 wui;
51 user.set_logsrv (NULL);
52 /* First trying to get logon info from environment */
53 if ((env = getenv ("USERNAME")) != NULL)
55 if ((env = getenv ("USERDOMAIN")) != NULL)
56 user.set_domain (env);
57 if ((env = getenv ("LOGONSERVER")) != NULL)
58 user.set_logsrv (env + 2); /* filter leading double backslashes */
59 if (user.name () && user.domain ())
60 debug_printf ("User: %s, Domain: %s, Logon Server: %s",
61 user.name (), user.domain (), user.logsrv ());
62 else if (!(ret = NetWkstaUserGetInfo (NULL, 1, (LPBYTE *)&wui)))
64 sys_wcstombs (buf, wui->wkui1_username, UNLEN + 1);
66 sys_wcstombs (buf, wui->wkui1_logon_server,
67 INTERNET_MAX_HOST_NAME_LENGTH + 1);
68 user.set_logsrv (buf);
69 sys_wcstombs (buf, wui->wkui1_logon_domain,
70 INTERNET_MAX_HOST_NAME_LENGTH + 1);
71 user.set_domain (buf);
72 NetApiBufferFree (wui);
74 if (!user.logsrv () && get_logon_server_and_user_domain (buf, NULL))
76 user.set_logsrv (buf + 2);
77 setenv ("LOGONSERVER", buf, 1);
79 LPUSER_INFO_3 ui = NULL;
80 WCHAR wuser[UNLEN + 1];
81 WCHAR wlogsrv[INTERNET_MAX_HOST_NAME_LENGTH + 3];
83 /* HOMEDRIVE and HOMEPATH are wrong most of the time, too,
84 after changing user context! */
85 sys_mbstowcs (wuser, user.name (), UNLEN + 1);
89 strcat (strcpy (buf, "\\\\"), user.logsrv ());
90 sys_mbstowcs (wlogsrv, buf, INTERNET_MAX_HOST_NAME_LENGTH + 3);
92 if (!NetUserGetInfo (NULL, wuser, 3, (LPBYTE *)&ui)
93 || (wlogsrv[0] && !NetUserGetInfo (wlogsrv, wuser, 3,(LPBYTE *)&ui)))
95 sys_wcstombs (buf, ui->usri3_home_dir, MAX_PATH);
98 sys_wcstombs (buf, ui->usri3_home_dir_drive, MAX_PATH);
103 env = getenv ("SYSTEMDRIVE");
105 strcat (strcpy (buf, env), "\\");
107 GetSystemDirectoryA (buf, MAX_PATH);
110 setenv ("HOMEPATH", buf + 2, 1);
112 setenv ("HOMEDRIVE", buf, 1);
113 NetApiBufferFree (ui);
115 debug_printf ("Domain: %s, Logon Server: %s, Windows Username: %s",
116 user.domain (), user.logsrv (), user.name ());
120 HANDLE ptok = user.token; /* Which is INVALID_HANDLE_VALUE if no
121 impersonation took place. */
126 /* Try to get the SID either from already impersonated token
127 or from current process first. To differ that two cases is
128 important, because you can't rely on the user information
129 in a process token of a currently impersonated process. */
130 if (ptok == INVALID_HANDLE_VALUE
131 && !OpenProcessToken (GetCurrentProcess (),
132 TOKEN_ADJUST_DEFAULT | TOKEN_QUERY,
134 debug_printf ("OpenProcessToken(): %E\n");
135 else if (!GetTokenInformation (ptok, TokenUser, &tu, sizeof tu, &siz))
136 debug_printf ("GetTokenInformation(): %E");
137 else if (!(ret = user.set_sid (tu)))
138 debug_printf ("Couldn't retrieve SID from access token!");
139 /* If that failes, try to get the SID from localhost. This can only
140 be done if a domain is given because there's a chance that a local
141 and a domain user may have the same name. */
142 if (!ret && user.domain ())
144 /* Concat DOMAIN\USERNAME for the next lookup */
145 strcat (strcat (strcpy (buf, user.domain ()), "\\"), user.name ());
146 if (!(ret = lookup_name (buf, NULL, user.sid ())))
147 debug_printf ("Couldn't retrieve SID locally!");
150 /* If that fails, too, as a last resort try to get the SID from
152 if (!ret && !(ret = lookup_name (user.name (), user.logsrv (),
154 debug_printf ("Couldn't retrieve SID from '%s'!", user.logsrv ());
156 /* If we have a SID, try to get the corresponding Cygwin user name
157 which can be different from the Windows user name. */
158 cygsid gsid (NO_SID);
163 for (int pidx = 0; (pw = internal_getpwent (pidx)); ++pidx)
164 if (psid.getfrompw (pw) && EqualSid (user.sid (), psid))
166 user.set_name (pw->pw_name);
167 struct group *gr = getgrgid (pw->pw_gid);
169 if (!gsid.getfromgr (gr))
173 if (!strcasematch (user.name (), "SYSTEM")
174 && user.domain () && user.logsrv ())
176 if (get_registry_hive_path (user.sid (), buf))
177 setenv ("USERPROFILE", buf, 1);
179 unsetenv ("USERPROFILE");
183 /* If this process is started from a non Cygwin process,
184 set token owner to the same value as token user and
185 primary group to the group which is set as primary group
187 if (ptok != INVALID_HANDLE_VALUE && myself->ppid == 1)
189 if (!SetTokenInformation (ptok, TokenOwner, &tu, sizeof tu))
190 debug_printf ("SetTokenInformation(TokenOwner): %E");
191 if (gsid && !SetTokenInformation (ptok, TokenPrimaryGroup,
193 debug_printf ("SetTokenInformation(TokenPrimaryGroup): %E");
196 /* Close token only if it's a result from OpenProcessToken(). */
197 if (ptok != INVALID_HANDLE_VALUE
198 && user.token == INVALID_HANDLE_VALUE)
202 debug_printf ("Cygwins Username: %s", user.name ());
203 return pw ?: getpwnam(user.name ());
211 /* Initialize to non impersonated values.
212 Setting `impersonated' to TRUE seems to be wrong but it
213 isn't. Impersonated is thought as "Current User and `token'
214 are coincident". See seteuid() for the mechanism behind that. */
215 if (cygheap->user.token != INVALID_HANDLE_VALUE)
216 CloseHandle (cygheap->user.token);
217 cygheap->user.token = INVALID_HANDLE_VALUE;
218 cygheap->user.impersonated = TRUE;
220 /* If uid is USHRT_MAX, the process is started from a non cygwin
221 process or the user context was changed in spawn.cc */
222 if (myself->uid == USHRT_MAX)
223 if ((p = internal_getlogin (cygheap->user)) != NULL)
225 myself->uid = p->pw_uid;
226 /* Set primary group only if ntsec is off or the process has been
227 started from a non cygwin process. */
228 if (!allow_ntsec || myself->ppid == 1)
229 myself->gid = p->pw_gid;
233 myself->uid = DEFAULT_UID;
234 myself->gid = DEFAULT_GID;
236 /* Real and effective uid/gid are always identical on process start up.
237 This is at least true for NT/W2K. */
238 cygheap->user.orig_uid = cygheap->user.real_uid = myself->uid;
239 cygheap->user.orig_gid = cygheap->user.real_gid = myself->gid;
246 char *this_username=_reent_winsup ()->_username;
248 static NO_COPY char this_username[UNLEN + 1];
251 return strcpy (this_username, cygheap->user.name ());
257 return cygheap->user.real_uid;
263 return cygheap->user.real_gid;
278 /* Not quite right - cuserid can change, getlogin can't */
284 strcpy (src, getlogin ());