]>
Commit | Line | Data |
---|---|---|
1fd5e000 CF |
1 | /* uinfo.cc: user info (uid, gid, etc...) |
2 | ||
bc837d22 CF |
3 | Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, |
4 | 2007, 2008, 2009, 2010, 2011, 2012 Red Hat, Inc. | |
1fd5e000 CF |
5 | |
6 | This file is part of Cygwin. | |
7 | ||
8 | This software is a copyrighted work licensed under the terms of the | |
9 | Cygwin license. Please consult the file "CYGWIN_LICENSE" for | |
10 | details. */ | |
11 | ||
1fd5e000 | 12 | #include "winsup.h" |
84c7d409 | 13 | #include <unistd.h> |
17db1105 | 14 | #include <wininet.h> |
1fd5e000 | 15 | #include <stdlib.h> |
520fcc97 | 16 | #include <wchar.h> |
1fd5e000 | 17 | #include <lm.h> |
9a512577 | 18 | #include <iptypes.h> |
eb79d041 | 19 | #include <sys/cygwin.h> |
169c465a | 20 | #include "cygerrno.h" |
e2ebe117 | 21 | #include "pinfo.h" |
47063f00 | 22 | #include "path.h" |
7ac61736 | 23 | #include "fhandler.h" |
0381fec6 | 24 | #include "dtable.h" |
1f0f8e12 | 25 | #include "cygheap.h" |
520fcc97 | 26 | #include "shared_info.h" |
f0338f54 | 27 | #include "registry.h" |
9a771b29 | 28 | #include "child_info.h" |
094d5193 | 29 | #include "environ.h" |
d6ffc075 | 30 | #include "pwdgrp.h" |
edab6053 | 31 | #include "tls_pbuf.h" |
5f9c8e2a | 32 | #include "ntdll.h" |
1fd5e000 | 33 | |
0efafbfb CF |
34 | /* Initialize the part of cygheap_user that does not depend on files. |
35 | The information is used in shared.cc for the user shared. | |
36 | Final initialization occurs in uinfo_init */ | |
9a771b29 | 37 | void |
9a4d574b | 38 | cygheap_user::init () |
1fd5e000 | 39 | { |
ebdc75d9 | 40 | WCHAR user_name[UNLEN + 1]; |
2a9b4b7a | 41 | DWORD user_name_len = UNLEN + 1; |
0efafbfb | 42 | |
3f74d8d5 CV |
43 | /* This code is only run if a Cygwin process gets started by a native |
44 | Win32 process. We try to get the username from the environment, | |
45 | first USERNAME (Win32), then USER (POSIX). If that fails (which is | |
46 | very unlikely), it only has an impact if we don't have an entry in | |
47 | /etc/passwd for this user either. In that case the username sticks | |
48 | to "unknown". Since this is called early in initialization, and | |
49 | since we don't want pull in a dependency to any other DLL except | |
50 | ntdll and kernel32 at this early stage, don't call GetUserName, | |
51 | GetUserNameEx, NetWkstaUserGetInfo, etc. */ | |
52 | if (GetEnvironmentVariableW (L"USERNAME", user_name, user_name_len) | |
53 | || GetEnvironmentVariableW (L"USER", user_name, user_name_len)) | |
54 | { | |
55 | char mb_user_name[user_name_len = sys_wcstombs (NULL, 0, user_name)]; | |
56 | sys_wcstombs (mb_user_name, user_name_len, user_name); | |
57 | set_name (mb_user_name); | |
58 | } | |
59 | else | |
60 | set_name ("unknown"); | |
1f0f8e12 | 61 | |
12eac211 CV |
62 | NTSTATUS status; |
63 | ULONG size; | |
043878df | 64 | PSECURITY_DESCRIPTOR psd; |
6806a8b5 | 65 | |
12eac211 CV |
66 | status = NtQueryInformationToken (hProcToken, TokenPrimaryGroup, |
67 | &groups.pgsid, sizeof (cygsid), &size); | |
68 | if (!NT_SUCCESS (status)) | |
61522196 | 69 | system_printf ("NtQueryInformationToken (TokenPrimaryGroup), %y", status); |
6806a8b5 PH |
70 | |
71 | /* Get the SID from current process and store it in effec_cygsid */ | |
12eac211 CV |
72 | status = NtQueryInformationToken (hProcToken, TokenUser, &effec_cygsid, |
73 | sizeof (cygsid), &size); | |
74 | if (!NT_SUCCESS (status)) | |
6806a8b5 | 75 | { |
61522196 | 76 | system_printf ("NtQueryInformationToken (TokenUser), %y", status); |
f4a1f8a1 | 77 | return; |
6806a8b5 PH |
78 | } |
79 | ||
80 | /* Set token owner to the same value as token user */ | |
12eac211 CV |
81 | status = NtSetInformationToken (hProcToken, TokenOwner, &effec_cygsid, |
82 | sizeof (cygsid)); | |
83 | if (!NT_SUCCESS (status)) | |
61522196 | 84 | debug_printf ("NtSetInformationToken(TokenOwner), %y", status); |
6806a8b5 | 85 | |
043878df | 86 | /* Standard way to build a security descriptor with the usual DACL */ |
7311cc1f | 87 | PSECURITY_ATTRIBUTES sa_buf = (PSECURITY_ATTRIBUTES) alloca (1024); |
f4a1f8a1 | 88 | psd = (PSECURITY_DESCRIPTOR) |
b86f999a | 89 | (sec_user_nih (sa_buf, sid()))->lpSecurityDescriptor; |
6806a8b5 | 90 | |
1838d97b | 91 | BOOLEAN acl_exists, dummy; |
043878df | 92 | TOKEN_DEFAULT_DACL dacl; |
1838d97b CV |
93 | |
94 | status = RtlGetDaclSecurityDescriptor (psd, &acl_exists, &dacl.DefaultDacl, | |
95 | &dummy); | |
96 | if (NT_SUCCESS (status) && acl_exists && dacl.DefaultDacl) | |
043878df | 97 | { |
5f9c8e2a | 98 | |
043878df | 99 | /* Set the default DACL and the process DACL */ |
12eac211 CV |
100 | status = NtSetInformationToken (hProcToken, TokenDefaultDacl, &dacl, |
101 | sizeof (dacl)); | |
102 | if (!NT_SUCCESS (status)) | |
61522196 | 103 | system_printf ("NtSetInformationToken (TokenDefaultDacl), %y", status); |
f16706de CV |
104 | if ((status = NtSetSecurityObject (NtCurrentProcess (), |
105 | DACL_SECURITY_INFORMATION, psd))) | |
61522196 | 106 | system_printf ("NtSetSecurityObject, %y", status); |
0efafbfb | 107 | } |
043878df | 108 | else |
0cd9f74f | 109 | system_printf("Cannot get dacl, %E"); |
0efafbfb CF |
110 | } |
111 | ||
112 | void | |
113 | internal_getlogin (cygheap_user &user) | |
114 | { | |
115 | struct passwd *pw = NULL; | |
116 | ||
2a9b4b7a CV |
117 | cygpsid psid = user.sid (); |
118 | pw = internal_getpwsid (psid); | |
39b553b8 | 119 | |
2a9b4b7a | 120 | if (!pw && !(pw = internal_getpwnam (user.name ())) |
d6ffc075 | 121 | && !(pw = internal_getpwuid (DEFAULT_UID))) |
9a4d574b | 122 | debug_printf ("user not found in augmented /etc/passwd"); |
647b92a7 | 123 | else |
9a771b29 | 124 | { |
a76877e9 CV |
125 | cygsid gsid; |
126 | ||
1fd072b6 CV |
127 | myself->uid = pw->pw_uid; |
128 | myself->gid = pw->pw_gid; | |
efcaf042 | 129 | user.set_name (pw->pw_name); |
a76877e9 | 130 | if (gsid.getfromgr (internal_getgrgid (pw->pw_gid))) |
eb6d2e2f | 131 | { |
a76877e9 | 132 | if (gsid != user.groups.pgsid) |
647b92a7 | 133 | { |
a76877e9 | 134 | /* Set primary group to the group in /etc/passwd. */ |
12eac211 CV |
135 | NTSTATUS status = NtSetInformationToken (hProcToken, |
136 | TokenPrimaryGroup, | |
137 | &gsid, sizeof gsid); | |
138 | if (!NT_SUCCESS (status)) | |
61522196 | 139 | debug_printf ("NtSetInformationToken (TokenPrimaryGroup), %y", |
12eac211 | 140 | status); |
a76877e9 CV |
141 | else |
142 | user.groups.pgsid = gsid; | |
143 | clear_procimptoken (); | |
647b92a7 | 144 | } |
647b92a7 | 145 | } |
a76877e9 CV |
146 | else |
147 | debug_printf ("gsid not found in augmented /etc/group"); | |
9a771b29 | 148 | } |
0c55f6ed | 149 | cygheap->user.ontherange (CH_HOME, pw); |
1fd5e000 CF |
150 | } |
151 | ||
152 | void | |
153 | uinfo_init () | |
154 | { | |
70249d56 | 155 | if (child_proc_info && !cygheap->user.has_impersonation_tokens ()) |
271c1935 CV |
156 | return; |
157 | ||
158 | if (!child_proc_info) | |
159 | internal_getlogin (cygheap->user); /* Set the cygheap->user. */ | |
160 | /* Conditions must match those in spawn to allow starting child | |
161 | processes with ruid != euid and rgid != egid. */ | |
162 | else if (cygheap->user.issetuid () | |
e3778517 | 163 | && cygheap->user.saved_uid == cygheap->user.real_uid |
1498189c | 164 | && cygheap->user.saved_gid == cygheap->user.real_gid |
0191627a CV |
165 | && !cygheap->user.groups.issetgroups () |
166 | && !cygheap->user.setuid_to_restricted) | |
4f7e12dd | 167 | { |
70249d56 | 168 | cygheap->user.reimpersonate (); |
271c1935 | 169 | return; |
4f7e12dd | 170 | } |
271c1935 | 171 | else |
70249d56 | 172 | cygheap->user.close_impersonation_tokens (); |
271c1935 | 173 | |
1498189c CV |
174 | cygheap->user.saved_uid = cygheap->user.real_uid = myself->uid; |
175 | cygheap->user.saved_gid = cygheap->user.real_gid = myself->gid; | |
53197923 PH |
176 | cygheap->user.external_token = NO_IMPERSONATION; |
177 | cygheap->user.internal_token = NO_IMPERSONATION; | |
f4a1f8a1 | 178 | cygheap->user.curr_primary_token = NO_IMPERSONATION; |
77ee8805 | 179 | cygheap->user.curr_imp_token = NO_IMPERSONATION; |
0191627a CV |
180 | cygheap->user.ext_token_is_restricted = false; |
181 | cygheap->user.curr_token_is_restricted = false; | |
182 | cygheap->user.setuid_to_restricted = false; | |
1498189c | 183 | cygheap->user.set_saved_sid (); /* Update the original sid */ |
a6f3658d | 184 | cygheap->user.deimpersonate (); |
1fd5e000 CF |
185 | } |
186 | ||
68509b30 CV |
187 | extern "C" int |
188 | getlogin_r (char *name, size_t namesize) | |
189 | { | |
553f0805 | 190 | const char *login = cygheap->user.name (); |
68509b30 CV |
191 | size_t len = strlen (login) + 1; |
192 | if (len > namesize) | |
193 | return ERANGE; | |
893ac8e0 CF |
194 | myfault efault; |
195 | if (efault.faulted ()) | |
196 | return EFAULT; | |
68509b30 CV |
197 | strncpy (name, login, len); |
198 | return 0; | |
199 | } | |
200 | ||
1fd5e000 CF |
201 | extern "C" char * |
202 | getlogin (void) | |
203 | { | |
553f0805 CV |
204 | static char username[UNLEN]; |
205 | int ret = getlogin_r (username, UNLEN); | |
206 | if (ret) | |
207 | { | |
208 | set_errno (ret); | |
209 | return NULL; | |
210 | } | |
211 | return username; | |
1fd5e000 CF |
212 | } |
213 | ||
61522196 | 214 | extern "C" uid_t |
a8d7ae61 CV |
215 | getuid32 (void) |
216 | { | |
217 | return cygheap->user.real_uid; | |
218 | } | |
219 | ||
61522196 CV |
220 | #ifdef __x86_64__ |
221 | EXPORT_ALIAS (getuid32, getuid) | |
222 | #else | |
de4e0d30 | 223 | extern "C" __uid16_t |
1fd5e000 CF |
224 | getuid (void) |
225 | { | |
1f0f8e12 | 226 | return cygheap->user.real_uid; |
1fd5e000 | 227 | } |
61522196 | 228 | #endif |
1fd5e000 | 229 | |
61522196 | 230 | extern "C" gid_t |
57196405 CV |
231 | getgid32 (void) |
232 | { | |
233 | return cygheap->user.real_gid; | |
234 | } | |
235 | ||
61522196 CV |
236 | #ifdef __x86_64__ |
237 | EXPORT_ALIAS (getgid32, getgid) | |
238 | #else | |
de4e0d30 | 239 | extern "C" __gid16_t |
1fd5e000 CF |
240 | getgid (void) |
241 | { | |
1f0f8e12 | 242 | return cygheap->user.real_gid; |
1fd5e000 | 243 | } |
61522196 | 244 | #endif |
1fd5e000 | 245 | |
61522196 | 246 | extern "C" uid_t |
a8d7ae61 CV |
247 | geteuid32 (void) |
248 | { | |
249 | return myself->uid; | |
250 | } | |
251 | ||
61522196 CV |
252 | #ifdef __x86_64__ |
253 | EXPORT_ALIAS (geteuid32, geteuid) | |
254 | #else | |
255 | extern "C" uid_t | |
1fd5e000 CF |
256 | geteuid (void) |
257 | { | |
64b30629 | 258 | return myself->uid; |
1fd5e000 | 259 | } |
61522196 | 260 | #endif |
1fd5e000 | 261 | |
61522196 | 262 | extern "C" gid_t |
57196405 CV |
263 | getegid32 (void) |
264 | { | |
265 | return myself->gid; | |
266 | } | |
267 | ||
61522196 CV |
268 | #ifdef __x86_64__ |
269 | EXPORT_ALIAS (getegid32, getegid) | |
270 | #else | |
de4e0d30 | 271 | extern "C" __gid16_t |
1fd5e000 CF |
272 | getegid (void) |
273 | { | |
64b30629 | 274 | return myself->gid; |
1fd5e000 | 275 | } |
61522196 | 276 | #endif |
1fd5e000 CF |
277 | |
278 | /* Not quite right - cuserid can change, getlogin can't */ | |
279 | extern "C" char * | |
280 | cuserid (char *src) | |
281 | { | |
da086d02 CF |
282 | if (!src) |
283 | return getlogin (); | |
284 | ||
285 | strcpy (src, getlogin ()); | |
286 | return src; | |
287 | } | |
288 | ||
289 | const char * | |
290 | cygheap_user::ontherange (homebodies what, struct passwd *pw) | |
291 | { | |
da086d02 CF |
292 | LPUSER_INFO_3 ui = NULL; |
293 | WCHAR wuser[UNLEN + 1]; | |
294 | NET_API_STATUS ret; | |
179cae11 CF |
295 | char homedrive_env_buf[3]; |
296 | char *newhomedrive = NULL; | |
297 | char *newhomepath = NULL; | |
edab6053 | 298 | tmp_pathbuf tp; |
da086d02 | 299 | |
094d5193 | 300 | debug_printf ("what %d, pw %p", what, pw); |
da086d02 CF |
301 | if (what == CH_HOME) |
302 | { | |
303 | char *p; | |
5f25e1d1 | 304 | |
da086d02 CF |
305 | if ((p = getenv ("HOME"))) |
306 | debug_printf ("HOME is already in the environment %s", p); | |
307 | else | |
308 | { | |
da086d02 CF |
309 | if (pw && pw->pw_dir && *pw->pw_dir) |
310 | { | |
da086d02 | 311 | debug_printf ("Set HOME (from /etc/passwd) to %s", pw->pw_dir); |
8297bda0 | 312 | setenv ("HOME", pw->pw_dir, 1); |
da086d02 | 313 | } |
8297bda0 | 314 | else |
da086d02 | 315 | { |
764d88e4 CV |
316 | char home[strlen (name ()) + 8]; |
317 | ||
318 | debug_printf ("Set HOME to default /home/USER"); | |
319 | __small_sprintf (home, "/home/%s", name ()); | |
8297bda0 | 320 | setenv ("HOME", home, 1); |
da086d02 CF |
321 | } |
322 | } | |
323 | } | |
324 | ||
094d5193 | 325 | if (what != CH_HOME && homepath == NULL && newhomepath == NULL) |
1fd5e000 | 326 | { |
edab6053 | 327 | char *homepath_env_buf = tp.c_get (); |
da086d02 | 328 | if (!pw) |
d6ffc075 | 329 | pw = internal_getpwnam (name ()); |
da086d02 | 330 | if (pw && pw->pw_dir && *pw->pw_dir) |
edab6053 CV |
331 | cygwin_conv_path (CCP_POSIX_TO_WIN_A, pw->pw_dir, homepath_env_buf, |
332 | NT_MAX_PATH); | |
da086d02 CF |
333 | else |
334 | { | |
179cae11 | 335 | homepath_env_buf[0] = homepath_env_buf[1] = '\0'; |
094d5193 | 336 | if (logsrv ()) |
da086d02 | 337 | { |
834224ab | 338 | WCHAR wlogsrv[INTERNET_MAX_HOST_NAME_LENGTH + 3]; |
5ab0b5cf CV |
339 | sys_mbstowcs (wlogsrv, sizeof (wlogsrv) / sizeof (*wlogsrv), |
340 | logsrv ()); | |
341 | sys_mbstowcs (wuser, sizeof (wuser) / sizeof (*wuser), winname ()); | |
9a4d574b | 342 | if (!(ret = NetUserGetInfo (wlogsrv, wuser, 3, (LPBYTE *) &ui))) |
da086d02 | 343 | { |
edab6053 | 344 | sys_wcstombs (homepath_env_buf, NT_MAX_PATH, |
b86f999a | 345 | ui->usri3_home_dir); |
834224ab CV |
346 | if (!homepath_env_buf[0]) |
347 | { | |
edab6053 | 348 | sys_wcstombs (homepath_env_buf, NT_MAX_PATH, |
03a49a00 | 349 | ui->usri3_home_dir_drive); |
834224ab CV |
350 | if (homepath_env_buf[0]) |
351 | strcat (homepath_env_buf, "\\"); | |
db57a363 | 352 | else |
edab6053 CV |
353 | cygwin_conv_path (CCP_POSIX_TO_WIN_A | CCP_ABSOLUTE, |
354 | "/", homepath_env_buf, NT_MAX_PATH); | |
834224ab | 355 | } |
da086d02 CF |
356 | } |
357 | } | |
358 | if (ui) | |
359 | NetApiBufferFree (ui); | |
360 | } | |
361 | ||
a77d35f7 | 362 | if (homepath_env_buf[1] != ':') |
da086d02 | 363 | { |
179cae11 CF |
364 | newhomedrive = almost_null; |
365 | newhomepath = homepath_env_buf; | |
da086d02 CF |
366 | } |
367 | else | |
368 | { | |
a77d35f7 CF |
369 | homedrive_env_buf[0] = homepath_env_buf[0]; |
370 | homedrive_env_buf[1] = homepath_env_buf[1]; | |
179cae11 CF |
371 | homedrive_env_buf[2] = '\0'; |
372 | newhomedrive = homedrive_env_buf; | |
373 | newhomepath = homepath_env_buf + 2; | |
da086d02 | 374 | } |
1fd5e000 | 375 | } |
da086d02 | 376 | |
8297bda0 | 377 | if (newhomedrive && newhomedrive != homedrive) |
179cae11 | 378 | cfree_and_set (homedrive, (newhomedrive == almost_null) |
5bf785a0 | 379 | ? almost_null : cstrdup (newhomedrive)); |
179cae11 | 380 | |
8297bda0 | 381 | if (newhomepath && newhomepath != homepath) |
179cae11 CF |
382 | cfree_and_set (homepath, cstrdup (newhomepath)); |
383 | ||
da086d02 | 384 | switch (what) |
1fd5e000 | 385 | { |
da086d02 CF |
386 | case CH_HOMEDRIVE: |
387 | return homedrive; | |
388 | case CH_HOMEPATH: | |
389 | return homepath; | |
390 | default: | |
391 | return homepath; | |
1fd5e000 CF |
392 | } |
393 | } | |
da086d02 CF |
394 | |
395 | const char * | |
094d5193 | 396 | cygheap_user::test_uid (char *&what, const char *name, size_t namelen) |
da086d02 | 397 | { |
8297bda0 | 398 | if (!what && !issetuid ()) |
38bc1196 | 399 | what = getwinenveq (name, namelen, HEAP_STR); |
094d5193 CF |
400 | return what; |
401 | } | |
402 | ||
403 | const char * | |
404 | cygheap_user::env_logsrv (const char *name, size_t namelen) | |
405 | { | |
406 | if (test_uid (plogsrv, name, namelen)) | |
9a771b29 | 407 | return plogsrv; |
da086d02 | 408 | |
efc1575e CF |
409 | const char *mydomain = domain (); |
410 | const char *myname = winname (); | |
c69d873f | 411 | if (!mydomain || ascii_strcasematch (myname, "SYSTEM")) |
e97962b9 | 412 | return almost_null; |
5f25e1d1 | 413 | |
9a512577 | 414 | WCHAR wdomain[MAX_DOMAIN_NAME_LEN + 1]; |
5558de95 | 415 | WCHAR wlogsrv[INTERNET_MAX_HOST_NAME_LENGTH + 3]; |
9a512577 | 416 | sys_mbstowcs (wdomain, MAX_DOMAIN_NAME_LEN + 1, mydomain); |
179cae11 | 417 | cfree_and_set (plogsrv, almost_null); |
5558de95 CV |
418 | if (get_logon_server (wdomain, wlogsrv, false)) |
419 | sys_wcstombs_alloc (&plogsrv, HEAP_STR, wlogsrv); | |
179cae11 | 420 | return plogsrv; |
9a771b29 CF |
421 | } |
422 | ||
423 | const char * | |
094d5193 | 424 | cygheap_user::env_domain (const char *name, size_t namelen) |
9a771b29 | 425 | { |
38bc1196 | 426 | if (pwinname && test_uid (pdomain, name, namelen)) |
9a771b29 CF |
427 | return pdomain; |
428 | ||
91d30570 CV |
429 | DWORD ulen = UNLEN + 1; |
430 | WCHAR username[ulen]; | |
3f74d8d5 | 431 | DWORD dlen = MAX_DOMAIN_NAME_LEN + 1; |
91d30570 | 432 | WCHAR userdomain[dlen]; |
9a771b29 CF |
433 | SID_NAME_USE use; |
434 | ||
094d5193 | 435 | cfree_and_set (pwinname, almost_null); |
179cae11 | 436 | cfree_and_set (pdomain, almost_null); |
91d30570 CV |
437 | if (!LookupAccountSidW (NULL, sid (), username, &ulen, |
438 | userdomain, &dlen, &use)) | |
179cae11 CF |
439 | __seterrno (); |
440 | else | |
9a771b29 | 441 | { |
91d30570 CV |
442 | sys_wcstombs_alloc (&pwinname, HEAP_STR, username); |
443 | sys_wcstombs_alloc (&pdomain, HEAP_STR, userdomain); | |
9a771b29 | 444 | } |
179cae11 | 445 | return pdomain; |
da086d02 CF |
446 | } |
447 | ||
448 | const char * | |
094d5193 | 449 | cygheap_user::env_userprofile (const char *name, size_t namelen) |
da086d02 | 450 | { |
094d5193 CF |
451 | if (test_uid (puserprof, name, namelen)) |
452 | return puserprof; | |
453 | ||
793371f5 CV |
454 | /* User hive path is never longer than MAX_PATH. */ |
455 | WCHAR userprofile_env_buf[MAX_PATH]; | |
7b4b41ab | 456 | WCHAR win_id[UNLEN + 1]; /* Large enough for SID */ |
e70bea19 | 457 | |
179cae11 | 458 | cfree_and_set (puserprof, almost_null); |
e70bea19 | 459 | if (get_registry_hive_path (get_windows_id (win_id), userprofile_env_buf)) |
793371f5 | 460 | sys_wcstombs_alloc (&puserprof, HEAP_STR, userprofile_env_buf); |
5f25e1d1 | 461 | |
179cae11 | 462 | return puserprof; |
da086d02 CF |
463 | } |
464 | ||
465 | const char * | |
094d5193 | 466 | cygheap_user::env_homepath (const char *name, size_t namelen) |
da086d02 CF |
467 | { |
468 | return ontherange (CH_HOMEPATH); | |
469 | } | |
470 | ||
471 | const char * | |
094d5193 | 472 | cygheap_user::env_homedrive (const char *name, size_t namelen) |
da086d02 CF |
473 | { |
474 | return ontherange (CH_HOMEDRIVE); | |
475 | } | |
9a771b29 CF |
476 | |
477 | const char * | |
094d5193 | 478 | cygheap_user::env_name (const char *name, size_t namelen) |
9a771b29 | 479 | { |
094d5193 | 480 | if (!test_uid (pwinname, name, namelen)) |
0c55f6ed | 481 | domain (); |
094d5193 | 482 | return pwinname; |
9a771b29 | 483 | } |
14ea5029 | 484 | |
60cb120f CV |
485 | const char * |
486 | cygheap_user::env_systemroot (const char *name, size_t namelen) | |
487 | { | |
488 | if (!psystemroot) | |
489 | { | |
ba6aad1d | 490 | int size = GetSystemWindowsDirectoryW (NULL, 0); |
60cb120f | 491 | if (size > 0) |
05726ddd | 492 | { |
ba6aad1d CV |
493 | WCHAR wsystemroot[size]; |
494 | size = GetSystemWindowsDirectoryW (wsystemroot, size); | |
495 | if (size > 0) | |
496 | sys_wcstombs_alloc (&psystemroot, HEAP_STR, wsystemroot); | |
60cb120f CV |
497 | } |
498 | if (size <= 0) | |
ba6aad1d | 499 | debug_printf ("GetSystemWindowsDirectoryW(), %E"); |
60cb120f CV |
500 | } |
501 | return psystemroot; | |
502 | } | |
503 | ||
7905c4f1 | 504 | char * |
ac413374 | 505 | pwdgrp::next_str (char c) |
14ea5029 | 506 | { |
ac413374 | 507 | char *res = lptr; |
f71f133b | 508 | lptr = strchrnul (lptr, c); |
fea48988 CF |
509 | if (*lptr) |
510 | *lptr++ = '\0'; | |
ac413374 | 511 | return res; |
7905c4f1 | 512 | } |
14ea5029 | 513 | |
65037056 CF |
514 | bool |
515 | pwdgrp::next_num (unsigned long& n) | |
ac413374 | 516 | { |
fea48988 | 517 | char *p = next_str (':'); |
ac413374 | 518 | char *cp; |
65037056 CF |
519 | n = strtoul (p, &cp, 10); |
520 | return p != cp && !*cp; | |
ac413374 CF |
521 | } |
522 | ||
523 | char * | |
524 | pwdgrp::add_line (char *eptr) | |
7905c4f1 | 525 | { |
ac413374 | 526 | if (eptr) |
7905c4f1 | 527 | { |
ac413374 | 528 | lptr = eptr; |
03dba1de CF |
529 | eptr = strchr (lptr, '\n'); |
530 | if (eptr) | |
ac413374 CF |
531 | { |
532 | if (eptr > lptr && eptr[-1] == '\r') | |
fea48988 CF |
533 | eptr[-1] = '\0'; |
534 | else | |
535 | *eptr = '\0'; | |
ac413374 CF |
536 | eptr++; |
537 | } | |
538 | if (curr_lines >= max_lines) | |
539 | { | |
540 | max_lines += 10; | |
541 | *pwdgrp_buf = realloc (*pwdgrp_buf, max_lines * pwdgrp_buf_elem_size); | |
542 | } | |
65037056 CF |
543 | if ((this->*parse) ()) |
544 | curr_lines++; | |
7905c4f1 | 545 | } |
ac413374 | 546 | return eptr; |
14ea5029 CF |
547 | } |
548 | ||
65037056 | 549 | void |
520fcc97 | 550 | pwdgrp::load (const wchar_t *rel_path) |
14ea5029 | 551 | { |
65037056 CF |
552 | static const char failed[] = "failed"; |
553 | static const char succeeded[] = "succeeded"; | |
e1e4b104 CV |
554 | const char *res = failed; |
555 | HANDLE fh = NULL; | |
e1e4b104 CV |
556 | |
557 | NTSTATUS status; | |
558 | OBJECT_ATTRIBUTES attr; | |
559 | IO_STATUS_BLOCK io; | |
560 | FILE_STANDARD_INFORMATION fsi; | |
65037056 | 561 | |
7905c4f1 CF |
562 | if (buf) |
563 | free (buf); | |
564 | buf = NULL; | |
981f9625 | 565 | curr_lines = 0; |
7905c4f1 | 566 | |
520fcc97 | 567 | if (!path && |
8895d962 | 568 | !(path = (PWCHAR) malloc ((wcslen (cygheap->installation_root) |
520fcc97 | 569 | + wcslen (rel_path) + 1) * sizeof (WCHAR)))) |
65037056 | 570 | { |
520fcc97 | 571 | paranoid_printf ("malloc (%W) failed", rel_path); |
e1e4b104 | 572 | goto out; |
65037056 | 573 | } |
8895d962 | 574 | wcpcpy (wcpcpy (path, cygheap->installation_root), rel_path); |
520fcc97 CV |
575 | RtlInitUnicodeString (&upath, path); |
576 | ||
577 | InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE, NULL, NULL); | |
578 | etc_ix = etc::init (etc_ix, &attr); | |
579 | ||
580 | paranoid_printf ("%S", &upath); | |
581 | ||
e9982f2a | 582 | status = NtOpenFile (&fh, SYNCHRONIZE | FILE_READ_DATA, &attr, &io, |
93e88498 CV |
583 | FILE_SHARE_VALID_FLAGS, |
584 | FILE_SYNCHRONOUS_IO_NONALERT | |
585 | | FILE_OPEN_FOR_BACKUP_INTENT); | |
e1e4b104 | 586 | if (!NT_SUCCESS (status)) |
7905c4f1 | 587 | { |
61522196 | 588 | paranoid_printf ("NtOpenFile(%S) failed, status %y", &upath, status); |
e1e4b104 | 589 | goto out; |
14ea5029 | 590 | } |
e1e4b104 CV |
591 | status = NtQueryInformationFile (fh, &io, &fsi, sizeof fsi, |
592 | FileStandardInformation); | |
593 | if (!NT_SUCCESS (status)) | |
594 | { | |
61522196 | 595 | paranoid_printf ("NtQueryInformationFile(%S) failed, status %y", |
520fcc97 | 596 | &upath, status); |
e1e4b104 CV |
597 | goto out; |
598 | } | |
599 | /* FIXME: Should we test for HighPart set? If so, the | |
600 | passwd or group file is way beyond what we can handle. */ | |
601 | /* FIXME 2: It's still ugly that we keep the file in memory. | |
602 | Big organizations have naturally large passwd files. */ | |
603 | buf = (char *) malloc (fsi.EndOfFile.LowPart + 1); | |
604 | if (!buf) | |
605 | { | |
61522196 | 606 | paranoid_printf ("malloc (%u) failed", fsi.EndOfFile.LowPart); |
e1e4b104 CV |
607 | goto out; |
608 | } | |
e9982f2a CV |
609 | status = NtReadFile (fh, NULL, NULL, NULL, &io, buf, fsi.EndOfFile.LowPart, |
610 | NULL, NULL); | |
e1e4b104 CV |
611 | if (!NT_SUCCESS (status)) |
612 | { | |
61522196 | 613 | paranoid_printf ("NtReadFile(%S) failed, status %y", &upath, status); |
e1e4b104 CV |
614 | free (buf); |
615 | goto out; | |
616 | } | |
617 | buf[fsi.EndOfFile.LowPart] = '\0'; | |
7b9e380f | 618 | for (char *eptr = buf; (eptr = add_line (eptr)); ) |
e1e4b104 | 619 | continue; |
520fcc97 | 620 | debug_printf ("%W curr_lines %d", rel_path, curr_lines); |
e1e4b104 CV |
621 | res = succeeded; |
622 | ||
623 | out: | |
624 | if (fh) | |
625 | NtClose (fh); | |
520fcc97 | 626 | debug_printf ("%W load %s", rel_path, res); |
57394495 | 627 | initialized = true; |
14ea5029 | 628 | } |