File: | mkpasswd.c |
Location: | line 476, column 15 |
Description: | Value stored to 'len2' is never read |
1 | /* mkpasswd.c: |
2 | |
3 | Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, |
4 | 2008, 2009, 2010, 2011, 2012 Red Hat, Inc. |
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 | |
12 | #define _WIN32_WINNT0x0600 0x0600 |
13 | #include <errno(*__errno()).h> |
14 | #include <ctype.h> |
15 | #include <stdlib.h> |
16 | #include <wchar.h> |
17 | #include <wctype.h> |
18 | #include <locale.h> |
19 | #include <stdio.h> |
20 | #include <unistd.h> |
21 | #include <getopt.h> |
22 | #include <io.h> |
23 | #include <sys/fcntl.h> |
24 | #include <sys/cygwin.h> |
25 | #include <cygwin/version.h> |
26 | #include <windows.h> |
27 | #include <lm.h> |
28 | #include <iptypes.h> |
29 | #include <wininet.h> |
30 | #include <ntsecapi.h> |
31 | #include <dsgetdc.h> |
32 | #include <ntdef.h> |
33 | #include "loadlib.h" |
34 | |
35 | #define print_win_error(x)_print_win_error(x, 35) _print_win_error(x, __LINE__35) |
36 | |
37 | #define MAX_SID_LEN40 40 |
38 | |
39 | SID_IDENTIFIER_AUTHORITY sid_world_auth = {SECURITY_WORLD_SID_AUTHORITY{0,0,0,0,0,1}}; |
40 | SID_IDENTIFIER_AUTHORITY sid_nt_auth = {SECURITY_NT_AUTHORITY{0,0,0,0,0,5}}; |
41 | |
42 | #ifndef min |
43 | #define min(a,b)((a)<(b)?(a):(b)) (((a)<(b))?(a):(b)) |
44 | #endif |
45 | |
46 | typedef struct |
47 | { |
48 | char *str; |
49 | DWORD id_offset; |
50 | BOOL domain; |
51 | BOOL with_dom; |
52 | } domlist_t; |
53 | |
54 | static void |
55 | _print_win_error(DWORD code, int line) |
56 | { |
57 | char buf[4096]; |
58 | |
59 | if (FormatMessageFormatMessageA (FORMAT_MESSAGE_FROM_SYSTEM4096 |
60 | | FORMAT_MESSAGE_IGNORE_INSERTS512, |
61 | NULL((void*)0), |
62 | code, |
63 | MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT)((((WORD)(0x01))<<10)|(WORD)(0x00)), |
64 | (LPTSTR) buf, sizeof (buf), NULL((void*)0))) |
65 | fprintf (stderr((__getreent())->_stderr), "mkpasswd (%d): [%lu] %s", line, code, buf); |
66 | else |
67 | fprintf (stderr((__getreent())->_stderr), "mkpasswd (%d): error %lu", line, code); |
68 | } |
69 | |
70 | static PWCHAR |
71 | get_dcname (char *domain) |
72 | { |
73 | static WCHAR server[INTERNET_MAX_HOST_NAME_LENGTH256 + 1]; |
74 | DWORD rc; |
75 | WCHAR domain_name[MAX_DOMAIN_NAME_LEN128 + 1]; |
76 | PDOMAIN_CONTROLLER_INFOW pdci = NULL((void*)0); |
77 | |
78 | if (domain) |
79 | { |
80 | mbstowcs (domain_name, domain, strlen (domain) + 1); |
81 | rc = DsGetDcNameW (NULL((void*)0), domain_name, NULL((void*)0), NULL((void*)0), 0, &pdci); |
82 | } |
83 | else |
84 | rc = DsGetDcNameW (NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), 0, &pdci); |
85 | if (rc != ERROR_SUCCESS0L) |
86 | { |
87 | print_win_error (rc)_print_win_error(rc, 87); |
88 | return (PWCHAR) -1; |
89 | } |
90 | wcscpy (server, pdci->DomainControllerName); |
91 | NetApiBufferFree (pdci); |
92 | return server; |
93 | } |
94 | |
95 | static char * |
96 | put_sid (PSID sid) |
97 | { |
98 | static char s[512]; |
99 | char t[32]; |
100 | DWORD i; |
101 | |
102 | strcpy (s, "S-1-"); |
103 | sprintf(t, "%u", GetSidIdentifierAuthority (sid)->Value[5]); |
104 | strcat (s, t); |
105 | for (i = 0; i < *GetSidSubAuthorityCount (sid); ++i) |
106 | { |
107 | sprintf(t, "-%lu", *GetSidSubAuthority (sid, i)); |
108 | strcat (s, t); |
109 | } |
110 | return s; |
111 | } |
112 | |
113 | static void |
114 | uni2ansi (LPWSTR wcs, char *mbs, int size) |
115 | { |
116 | if (wcs) |
117 | wcstombs (mbs, wcs, size); |
118 | else |
119 | *mbs = '\0'; |
120 | } |
121 | |
122 | typedef struct { |
123 | PSID psid; |
124 | int buffer[10]; |
125 | } sidbuf; |
126 | |
127 | static sidbuf curr_user; |
128 | static sidbuf curr_pgrp; |
129 | static BOOL got_curr_user = FALSE0; |
130 | |
131 | static void |
132 | fetch_current_user_sid () |
133 | { |
134 | DWORD len; |
135 | HANDLE ptok; |
136 | |
137 | if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY(0x0008), &ptok) |
138 | || !GetTokenInformation (ptok, TokenUser, &curr_user, sizeof curr_user, |
139 | &len) |
140 | || !GetTokenInformation (ptok, TokenPrimaryGroup, &curr_pgrp, |
141 | sizeof curr_pgrp, &len) |
142 | || !CloseHandle (ptok)) |
143 | { |
144 | print_win_error (GetLastError ())_print_win_error(GetLastError (), 144); |
145 | return; |
146 | } |
147 | } |
148 | |
149 | static void |
150 | current_user (const char *sep, const char *passed_home_path, DWORD id_offset, |
151 | const char *disp_username) |
152 | { |
153 | WCHAR user[UNLEN256 + 1]; |
154 | WCHAR dom[MAX_DOMAIN_NAME_LEN128 + 1]; |
155 | DWORD ulen = UNLEN256 + 1; |
156 | DWORD dlen = MAX_DOMAIN_NAME_LEN128 + 1; |
157 | SID_NAME_USE acc_type; |
158 | int uid, gid; |
159 | char homedir_psx[PATH_MAX4096] = {0}; |
160 | |
161 | if (!curr_user.psid || !curr_pgrp.psid |
162 | || !LookupAccountSidW (NULL((void*)0), curr_user.psid, user, &ulen, dom, &dlen, |
163 | &acc_type)) |
164 | { |
165 | print_win_error (GetLastError ())_print_win_error(GetLastError (), 165); |
166 | return; |
167 | } |
168 | |
169 | uid = *GetSidSubAuthority (curr_user.psid, |
170 | *GetSidSubAuthorityCount(curr_user.psid) - 1); |
171 | gid = *GetSidSubAuthority (curr_pgrp.psid, |
172 | *GetSidSubAuthorityCount(curr_pgrp.psid) - 1); |
173 | if (passed_home_path[0] == '\0') |
174 | { |
175 | char *envhome = getenv ("HOME"); |
176 | |
177 | /* If $HOME exists and is non-empty, just copy it over to homedir_psx. |
178 | Otherwise, generate a new path of the form "/home/$USER". */ |
179 | if (envhome && envhome[0] != '\0') |
180 | strncat (homedir_psx, envhome, sizeof (homedir_psx) - 1); |
181 | else |
182 | { |
183 | wcstombs (stpncpy (homedir_psx, "/home/", sizeof (homedir_psx)), |
184 | user, sizeof (homedir_psx) - 6); |
185 | homedir_psx[PATH_MAX4096 - 1] = '\0'; |
186 | } |
187 | } |
188 | else |
189 | { |
190 | char *p = stpncpy (homedir_psx, passed_home_path, sizeof (homedir_psx)); |
191 | wcstombs (p, user, sizeof (homedir_psx) - (p - homedir_psx)); |
192 | homedir_psx[PATH_MAX4096 - 1] = '\0'; |
193 | } |
194 | |
195 | printf ("%ls%s%ls:unused:%lu:%lu:U-%ls\\%ls,%s:%s:/bin/bash\n", |
196 | sep ? dom : L"", |
197 | sep ?: "", |
198 | user, |
199 | id_offset + uid, |
200 | id_offset + gid, |
201 | dom, |
202 | user, |
203 | put_sid (curr_user.psid), |
204 | homedir_psx); |
205 | } |
206 | |
207 | static void |
208 | enum_unix_users (domlist_t *dom_or_machine, const char *sep, DWORD id_offset, |
209 | char *unix_user_list) |
210 | { |
211 | WCHAR machine[INTERNET_MAX_HOST_NAME_LENGTH256 + 1]; |
212 | PWCHAR servername = NULL((void*)0); |
213 | char *d_or_m = dom_or_machine ? dom_or_machine->str : NULL((void*)0); |
214 | BOOL with_dom = dom_or_machine ? dom_or_machine->with_dom : FALSE0; |
215 | SID_IDENTIFIER_AUTHORITY auth = { { 0, 0, 0, 0, 0, 22 } }; |
216 | char *ustr, *user_list; |
217 | WCHAR user[UNLEN256 + sizeof ("Unix User\\") + 1]; |
218 | WCHAR dom[MAX_DOMAIN_NAME_LEN128 + 1]; |
219 | DWORD ulen, dlen, sidlen; |
220 | PSID psid; |
221 | char psid_buffer[MAX_SID_LEN40]; |
222 | SID_NAME_USE acc_type; |
223 | |
224 | if (!d_or_m) |
225 | return; |
226 | |
227 | int ret = mbstowcs (machine, d_or_m, INTERNET_MAX_HOST_NAME_LENGTH256 + 1); |
228 | if (ret < 1 || ret >= INTERNET_MAX_HOST_NAME_LENGTH256 + 1) |
229 | { |
230 | fprintf (stderr((__getreent())->_stderr), "%s: Invalid machine name '%s'. Skipping...\n", |
231 | program_invocation_short_name, d_or_m); |
232 | return; |
233 | } |
234 | servername = machine; |
235 | |
236 | if (!AllocateAndInitializeSid (&auth, 2, 1, 0, 0, 0, 0, 0, 0, 0, &psid)) |
237 | return; |
238 | |
239 | if (!(user_list = strdup (unix_user_list))) |
240 | { |
241 | FreeSid (psid); |
242 | return; |
243 | } |
244 | |
245 | for (ustr = strtok (user_list, ","); ustr; ustr = strtok (NULL((void*)0), ",")) |
246 | { |
247 | if (!isdigit ((unsigned char) ustr[0])(((__ctype_ptr__+sizeof(""[(unsigned char) ustr[0]]))[(int)(( unsigned char) ustr[0])])&04) && ustr[0] != '-') |
248 | { |
249 | PWCHAR p = wcpcpy (user, L"Unix User\\"); |
250 | ret = mbstowcs (p, ustr, UNLEN256 + 1); |
251 | if (ret < 1 || ret >= UNLEN256 + 1) |
252 | fprintf (stderr((__getreent())->_stderr), "%s: Invalid user name '%s'. Skipping...\n", |
253 | program_invocation_short_name, ustr); |
254 | else if (LookupAccountNameW (servername, user, |
255 | psid = (PSID) psid_buffer, |
256 | (sidlen = MAX_SID_LEN40, &sidlen), |
257 | dom, |
258 | (dlen = MAX_DOMAIN_NAME_LEN128 + 1, &dlen), |
259 | &acc_type)) |
260 | printf ("%s%s%ls:unused:%lu:99999:,%s::\n", |
261 | with_dom ? "Unix User" : "", |
262 | with_dom ? sep : "", |
263 | user + 10, |
264 | id_offset + |
265 | *GetSidSubAuthority (psid, |
266 | *GetSidSubAuthorityCount(psid) - 1), |
267 | put_sid (psid)); |
268 | } |
269 | else |
270 | { |
271 | DWORD start, stop; |
272 | char *p = ustr; |
273 | if (*p == '-') |
274 | start = 0; |
275 | else |
276 | start = strtol (p, &p, 10); |
277 | if (!*p) |
278 | stop = start; |
279 | else if (*p++ != '-' || !isdigit ((unsigned char) *p)(((__ctype_ptr__+sizeof(""[(unsigned char) *p]))[(int)((unsigned char) *p)])&04) |
280 | || (stop = strtol (p, &p, 10)) < start || *p) |
281 | { |
282 | fprintf (stderr((__getreent())->_stderr), "%s: Malformed unix user list entry '%s'. " |
283 | "Skipping...\n", |
284 | program_invocation_short_name, ustr); |
285 | continue; |
286 | } |
287 | for (; start <= stop; ++ start) |
288 | { |
289 | *GetSidSubAuthority (psid, *GetSidSubAuthorityCount(psid) - 1) |
290 | = start; |
291 | if (LookupAccountSidW (servername, psid, |
292 | user, (ulen = GNLEN256 + 1, &ulen), |
293 | dom, |
294 | (dlen = MAX_DOMAIN_NAME_LEN128 + 1, &dlen), |
295 | &acc_type) |
296 | && !iswdigit (user[0])) |
297 | printf ("%s%s%ls:unused:%lu:99999:,%s::\n", |
298 | with_dom ? "Unix User" : "", |
299 | with_dom ? sep : "", |
300 | user, |
301 | id_offset + start, |
302 | put_sid (psid)); |
303 | } |
304 | } |
305 | } |
306 | |
307 | free (user_list); |
308 | FreeSid (psid); |
309 | } |
310 | |
311 | static int |
312 | enum_users (BOOL domain, domlist_t *dom_or_machine, const char *sep, |
313 | const char *passed_home_path, DWORD id_offset, char *disp_username, |
314 | int print_current) |
315 | { |
316 | WCHAR machine[INTERNET_MAX_HOST_NAME_LENGTH256 + 1]; |
317 | PWCHAR servername = NULL((void*)0); |
318 | char *d_or_m = dom_or_machine ? dom_or_machine->str : NULL((void*)0); |
319 | BOOL with_dom = dom_or_machine ? dom_or_machine->with_dom : FALSE0; |
320 | USER_INFO_3 *buffer; |
321 | DWORD entriesread = 0; |
322 | DWORD totalentries = 0; |
323 | DWORD resume_handle = 0; |
324 | DWORD rc; |
325 | WCHAR uni_name[UNLEN256 + 1]; |
326 | if (domain) |
327 | { |
328 | servername = get_dcname (d_or_m); |
329 | if (servername == (PWCHAR) -1) |
330 | return 1; |
331 | } |
332 | else if (d_or_m) |
333 | { |
334 | int ret = mbstowcs (machine, d_or_m, INTERNET_MAX_HOST_NAME_LENGTH256 + 1); |
335 | if (ret < 1 || ret >= INTERNET_MAX_HOST_NAME_LENGTH256 + 1) |
336 | { |
337 | fprintf (stderr((__getreent())->_stderr), "%s: Invalid machine name '%s'. Skipping...\n", |
338 | program_invocation_short_name, d_or_m); |
339 | return 1; |
340 | } |
341 | servername = machine; |
342 | } |
343 | |
344 | do |
345 | { |
346 | DWORD i; |
347 | |
348 | if (disp_username != NULL((void*)0)) |
349 | { |
350 | mbstowcs (uni_name, disp_username, UNLEN256 + 1); |
351 | rc = NetUserGetInfo (servername, (LPWSTR) &uni_name, 3, |
352 | (void *) &buffer); |
353 | entriesread = 1; |
354 | /* Avoid annoying error messages just because the user hasn't been |
355 | found. */ |
356 | if (rc == NERR_UserNotFound(2100 +121)) |
357 | return 0; |
358 | } |
359 | else |
360 | rc = NetUserEnum (servername, 3, FILTER_NORMAL_ACCOUNT2, |
361 | (void *) &buffer, MAX_PREFERRED_LENGTH((DWORD)-1), |
362 | &entriesread, &totalentries, &resume_handle); |
363 | switch (rc) |
364 | { |
365 | case ERROR_ACCESS_DENIED5L: |
366 | print_win_error(rc)_print_win_error(rc, 366); |
367 | return 1; |
368 | |
369 | case ERROR_MORE_DATA234L: |
370 | case ERROR_SUCCESS0L: |
371 | break; |
372 | |
373 | default: |
374 | print_win_error(rc)_print_win_error(rc, 374); |
375 | return 1; |
376 | } |
377 | |
378 | for (i = 0; i < entriesread; i++) |
379 | { |
380 | char homedir_psx[PATH_MAX4096]; |
381 | WCHAR domain_name[MAX_DOMAIN_NAME_LEN128 + 1]; |
382 | DWORD domname_len = MAX_DOMAIN_NAME_LEN128 + 1; |
383 | char psid_buffer[MAX_SID_LEN40]; |
384 | PSID psid = (PSID) psid_buffer; |
385 | DWORD sid_length = MAX_SID_LEN40; |
386 | SID_NAME_USE acc_type; |
387 | |
388 | int uid = buffer[i].usri3_user_id; |
389 | int gid = buffer[i].usri3_primary_group_id; |
390 | homedir_psx[0] = '\0'; |
391 | if (passed_home_path[0] == '\0') |
392 | { |
393 | if (buffer[i].usri3_home_dir[0] != L'\0') |
394 | cygwin_conv_path (CCP_WIN_W_TO_POSIX | CCP_ABSOLUTE, |
395 | buffer[i].usri3_home_dir, homedir_psx, |
396 | PATH_MAX4096); |
397 | else |
398 | uni2ansi (buffer[i].usri3_name, |
399 | stpcpy (homedir_psx, "/home/"), PATH_MAX4096 - 6); |
400 | } |
401 | else |
402 | uni2ansi (buffer[i].usri3_name, |
403 | stpcpy (homedir_psx, passed_home_path), |
404 | PATH_MAX4096 - strlen (passed_home_path)); |
405 | |
406 | if (!LookupAccountNameW (servername, buffer[i].usri3_name, |
407 | psid, &sid_length, domain_name, |
408 | &domname_len, &acc_type)) |
409 | { |
410 | print_win_error(GetLastError ())_print_win_error(GetLastError (), 410); |
411 | fprintf(stderr((__getreent())->_stderr), " (%ls)\n", buffer[i].usri3_name); |
412 | continue; |
413 | } |
414 | else if (acc_type == SidTypeDomain) |
415 | { |
416 | WCHAR domname[MAX_DOMAIN_NAME_LEN128 + UNLEN256 + 2]; |
417 | |
418 | wcscpy (domname, domain || !servername |
419 | ? domain_name : servername); |
420 | wcscat (domname, L"\\"); |
421 | wcscat (domname, buffer[i].usri3_name); |
422 | sid_length = MAX_SID_LEN40; |
423 | domname_len = sizeof (domname); |
424 | if (!LookupAccountNameW (servername, domname, psid, |
425 | &sid_length, domain_name, |
426 | &domname_len, &acc_type)) |
427 | { |
428 | print_win_error(GetLastError ())_print_win_error(GetLastError (), 428); |
429 | fprintf(stderr((__getreent())->_stderr), " (%ls)\n", domname); |
430 | continue; |
431 | } |
432 | } |
433 | if (!print_current) |
434 | /* fall through */; |
435 | else if (EqualSid (curr_user.psid, psid)) |
436 | got_curr_user = TRUE1; |
437 | |
438 | printf ("%ls%s%ls:unused:%lu:%lu:%ls%sU-%ls\\%ls,%s:%s:/bin/bash\n", |
439 | with_dom ? domain_name : L"", |
440 | with_dom ? sep : "", |
441 | buffer[i].usri3_name, |
442 | id_offset + uid, |
443 | id_offset + gid, |
444 | buffer[i].usri3_full_name ?: L"", |
445 | buffer[i].usri3_full_name |
446 | && buffer[i].usri3_full_name[0] ? "," : "", |
447 | domain_name, |
448 | buffer[i].usri3_name, |
449 | put_sid (psid), |
450 | homedir_psx); |
451 | } |
452 | |
453 | NetApiBufferFree (buffer); |
454 | |
455 | } |
456 | while (rc == ERROR_MORE_DATA234L); |
457 | |
458 | return 0; |
459 | } |
460 | |
461 | static void |
462 | print_special_by_sid (PSID_IDENTIFIER_AUTHORITY auth, BYTE cnt, |
463 | DWORD sub1, DWORD sub2, DWORD sub3, DWORD sub4, |
464 | DWORD sub5, DWORD sub6, DWORD sub7, DWORD sub8) |
465 | { |
466 | WCHAR user[UNLEN256 + 1], dom[MAX_DOMAIN_NAME_LEN128 + 1]; |
467 | DWORD len, len2, rid; |
468 | PSID sid; |
469 | SID_NAME_USE acc_type; |
470 | |
471 | if (AllocateAndInitializeSid (auth, cnt, sub1, sub2, sub3, sub4, |
472 | sub5, sub6, sub7, sub8, &sid)) |
473 | { |
474 | if (LookupAccountSidW (NULL((void*)0), sid, |
475 | user, (len = UNLEN256 + 1, &len), |
476 | dom, (len2 = MAX_DOMAIN_NAME_LEN128 + 1, &len), |
Value stored to 'len2' is never read | |
477 | &acc_type)) |
478 | { |
479 | if (sub8) |
480 | rid = sub8; |
481 | else if (sub7) |
482 | rid = sub7; |
483 | else if (sub6) |
484 | rid = sub6; |
485 | else if (sub5) |
486 | rid = sub5; |
487 | else if (sub4) |
488 | rid = sub4; |
489 | else if (sub3) |
490 | rid = sub3; |
491 | else if (sub2) |
492 | rid = sub2; |
493 | else |
494 | rid = sub1; |
495 | printf ("%ls:*:%lu:%lu:,%s::\n", |
496 | user, rid, rid == 18 ? 544 : rid, /* SYSTEM hack */ |
497 | put_sid (sid)); |
498 | } |
499 | FreeSid (sid); |
500 | } |
501 | } |
502 | |
503 | static int |
504 | usage (FILE * stream) |
505 | { |
506 | fprintf (stream, |
507 | "Usage: %s [OPTIONS]...\n" |
508 | "\n" |
509 | "Print /etc/passwd file to stdout\n" |
510 | "\n" |
511 | "Options:\n" |
512 | "\n" |
513 | " -l,--local [machine[,offset]]\n" |
514 | " print local user accounts with uid offset offset\n" |
515 | " (from local machine if no machine specified)\n" |
516 | " -L,--Local [machine[,offset]]\n" |
517 | " ditto, but generate username with machine prefix\n" |
518 | " -d,--domain [domain[,offset]]\n" |
519 | " print domain accounts with uid offset offset\n" |
520 | " (from current domain if no domain specified)\n" |
521 | " -D,--Domain [domain[,offset]]\n" |
522 | " ditto, but generate username with domain prefix\n" |
523 | " -c,--current print current user\n" |
524 | " -C,--Current ditto, but generate username with machine or\n" |
525 | " domain prefix\n" |
526 | " -S,--separator char for -L, -D, -C use character char as domain\\user\n" |
527 | " separator in username instead of the default '\\'\n" |
528 | " -o,--id-offset offset change the default offset (10000) added to uids\n" |
529 | " in domain or foreign server accounts.\n" |
530 | " -u,--username username only return information for the specified user\n" |
531 | " one of -l, -L, -d, -D must be specified, too\n" |
532 | " -p,--path-to-home path use specified path instead of user account home dir\n" |
533 | " or /home prefix\n" |
534 | " -U,--unix userlist additionally print UNIX users when using -l or -L\n" |
535 | " on a UNIX Samba server\n" |
536 | " userlist is a comma-separated list of usernames\n" |
537 | " or uid ranges (root,-25,50-100).\n" |
538 | " (enumerating large ranges can take a long time!)\n" |
539 | " -s,--no-sids (ignored)\n" |
540 | " -m,--no-mount (ignored)\n" |
541 | " -g,--local-groups (ignored)\n" |
542 | " -h,--help displays this message\n" |
543 | " -V,--version version information and exit\n" |
544 | "\n" |
545 | "Default is to print local accounts on stand-alone machines, domain accounts\n" |
546 | "on domain controllers and domain member machines.\n" |
547 | "\n", program_invocation_short_name); |
548 | return 1; |
549 | } |
550 | |
551 | static struct option longopts[] = { |
552 | {"current", no_argument0, NULL((void*)0), 'c'}, |
553 | {"Current", no_argument0, NULL((void*)0), 'C'}, |
554 | {"domain", optional_argument2, NULL((void*)0), 'd'}, |
555 | {"Domain", optional_argument2, NULL((void*)0), 'D'}, |
556 | {"local-groups", no_argument0, NULL((void*)0), 'g'}, |
557 | {"help", no_argument0, NULL((void*)0), 'h'}, |
558 | {"local", optional_argument2, NULL((void*)0), 'l'}, |
559 | {"Local", optional_argument2, NULL((void*)0), 'L'}, |
560 | {"no-mount", no_argument0, NULL((void*)0), 'm'}, |
561 | {"id-offset", required_argument1, NULL((void*)0), 'o'}, |
562 | {"path-to-home", required_argument1, NULL((void*)0), 'p'}, |
563 | {"no-sids", no_argument0, NULL((void*)0), 's'}, |
564 | {"separator", required_argument1, NULL((void*)0), 'S'}, |
565 | {"username", required_argument1, NULL((void*)0), 'u'}, |
566 | {"unix", required_argument1, NULL((void*)0), 'U'}, |
567 | {"version", no_argument0, NULL((void*)0), 'V'}, |
568 | {0, no_argument0, NULL((void*)0), 0} |
569 | }; |
570 | |
571 | static char opts[] = "cCd::D::ghl::L::mo:sS:p:u:U:V"; |
572 | |
573 | static void |
574 | print_version () |
575 | { |
576 | printf ("mkpasswd (cygwin) %d.%d.%d\n" |
577 | "Passwd File Generator\n" |
578 | "Copyright (C) 1997 - %s Red Hat, Inc.\n" |
579 | "This is free software; see the source for copying conditions. There is NO\n" |
580 | "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n", |
581 | CYGWIN_VERSION_DLL_MAJOR1007 / 1000, |
582 | CYGWIN_VERSION_DLL_MAJOR1007 % 1000, |
583 | CYGWIN_VERSION_DLL_MINOR16, |
584 | strrchr (__DATE__"Jul 3 2012", ' ') + 1); |
585 | } |
586 | |
587 | static void |
588 | print_special_by_name (PCWSTR name, uid_t uid, gid_t gid) |
589 | { |
590 | DWORD size = 256, dom_size = 256; |
591 | PSID sid = (PSID) alloca (size)__builtin_alloca(size); |
592 | WCHAR dom[dom_size]; |
593 | SID_NAME_USE use; |
594 | |
595 | PWCHAR name_only = wcschr (name, L'\\'); |
596 | if (name_only) |
597 | ++name_only; |
598 | |
599 | if (LookupAccountNameW (NULL((void*)0), name, sid, &size, dom, &dom_size, &use)) |
600 | printf ("%ls:*:%lu:%lu:U-%ls%s%ls,%s::\n", |
601 | name_only ?: name, |
602 | (unsigned long) uid, |
603 | (unsigned long) gid, |
604 | name_only ? dom : L"", |
605 | name_only ? "\\" : "", |
606 | name_only ?: name, |
607 | put_sid (sid)); |
608 | } |
609 | |
610 | static void |
611 | enum_std_accounts () |
612 | { |
613 | /* Generate service starter account entries. */ |
614 | printf ("SYSTEM:*:18:544:,S-1-5-18::\n"); |
615 | printf ("LocalService:*:19:544:U-NT AUTHORITY\\LocalService,S-1-5-19::\n"); |
616 | printf ("NetworkService:*:20:544:U-NT AUTHORITY\\NetworkService,S-1-5-20::\n"); |
617 | /* Get 'administrators' group (has localized name). */ |
618 | print_special_by_sid (&sid_nt_auth, 2, SECURITY_BUILTIN_DOMAIN_RID32, |
619 | DOMAIN_ALIAS_RID_ADMINS0x220L, 0, 0, 0, 0, 0, 0); |
620 | /* Fetch "TrustedInstaller" account starting with Vista. */ |
621 | print_special_by_name (L"NT SERVICE\\TrustedInstaller", -2, -2); |
622 | } |
623 | |
624 | static PPOLICY_PRIMARY_DOMAIN_INFO p_dom; |
625 | |
626 | static BOOL |
627 | fetch_primary_domain () |
628 | { |
629 | NTSTATUS status; |
630 | LSA_OBJECT_ATTRIBUTES oa = { 0, 0, 0, 0, 0, 0 }; |
631 | LSA_HANDLE lsa; |
632 | |
633 | if (!p_dom) |
634 | { |
635 | status = LsaOpenPolicy (NULL((void*)0), &oa, POLICY_VIEW_LOCAL_INFORMATION1, &lsa); |
636 | if (!NT_SUCCESS (status)((status)>=0)) |
637 | return FALSE0; |
638 | status = LsaQueryInformationPolicy (lsa, PolicyPrimaryDomainInformation, |
639 | (PVOID *) ((void *) &p_dom)); |
640 | LsaClose (lsa); |
641 | if (!NT_SUCCESS (status)((status)>=0)) |
642 | return FALSE0; |
643 | } |
644 | return !!p_dom->Sid; |
645 | } |
646 | |
647 | int |
648 | main (int argc, char **argv) |
649 | { |
650 | int print_domlist = 0; |
651 | domlist_t domlist[32]; |
652 | char *opt, *p, *ep; |
653 | int print_current = 0; |
654 | char *print_unix = NULL((void*)0); |
655 | const char *sep_char = "\\"; |
656 | DWORD id_offset = 10000, off; |
657 | int c, i; |
658 | char *disp_username = NULL((void*)0); |
659 | char passed_home_path[PATH_MAX4096]; |
660 | BOOL in_domain; |
661 | int optional_args = 0; |
662 | |
663 | passed_home_path[0] = '\0'; |
664 | if (!isatty (1)) |
665 | setmode (1, O_BINARY0x10000); |
666 | |
667 | /* Use locale from environment. If not set or set to "C", use UTF-8. */ |
668 | setlocale (LC_CTYPE2, ""); |
669 | if (!strcmp (setlocale (LC_CTYPE2, NULL((void*)0)), "C")) |
670 | setlocale (LC_CTYPE2, "en_US.UTF-8"); |
671 | in_domain = fetch_primary_domain (); |
672 | fetch_current_user_sid (); |
673 | |
674 | if (argc == 1) |
675 | { |
676 | enum_std_accounts (); |
677 | if (in_domain) |
678 | enum_users (TRUE1, NULL((void*)0), sep_char, passed_home_path, 10000, |
679 | disp_username, 0); |
680 | else |
681 | enum_users (FALSE0, NULL((void*)0), sep_char, passed_home_path, 0, |
682 | disp_username, 0); |
683 | return 0; |
684 | } |
685 | |
686 | unsetenv ("POSIXLY_CORRECT"); /* To get optional arg processing right. */ |
687 | while ((c = getopt_long (argc, argv, opts, longopts, NULL((void*)0))) != EOF(-1)) |
688 | switch (c) |
689 | { |
690 | case 'd': |
691 | case 'D': |
692 | case 'l': |
693 | case 'L': |
694 | if (print_domlist >= 32) |
695 | { |
696 | fprintf (stderr((__getreent())->_stderr), "%s: Can not enumerate from more than 32 " |
697 | "domains and machines.\n", |
698 | program_invocation_short_name); |
699 | return 1; |
700 | } |
701 | domlist[print_domlist].domain = (c == 'd' || c == 'D'); |
702 | opt = optarg ?: |
703 | argv[optind] && argv[optind][0] != '-' ? argv[optind] : NULL((void*)0); |
704 | if (argv[optind] && opt == argv[optind]) |
705 | ++optional_args; |
706 | for (i = 0; i < print_domlist; ++i) |
707 | if (domlist[i].domain == domlist[print_domlist].domain |
708 | && ((!domlist[i].str && !opt) |
709 | || (domlist[i].str && opt |
710 | && (off = strlen (domlist[i].str)) |
711 | && !strncmp (domlist[i].str, opt, off) |
712 | && (!opt[off] || opt[off] == ',')))) |
713 | { |
714 | fprintf (stderr((__getreent())->_stderr), "%s: Duplicate %s '%s'. Skipping...\n", |
715 | program_invocation_short_name, |
716 | domlist[i].domain ? "domain" : "machine", |
717 | domlist[i].str); |
718 | goto skip; |
719 | } |
720 | domlist[print_domlist].str = opt; |
721 | domlist[print_domlist].id_offset = ULONG_MAX(2147483647L * 2UL + 1); |
722 | if (opt && (p = strchr (opt, ','))) |
723 | { |
724 | if (p == opt |
725 | || !isdigit ((unsigned char) p[1])(((__ctype_ptr__+sizeof(""[(unsigned char) p[1]]))[(int)((unsigned char) p[1])])&04) |
726 | || (domlist[print_domlist].id_offset = strtol (p + 1, &ep, 10) |
727 | , *ep)) |
728 | { |
729 | fprintf (stderr((__getreent())->_stderr), "%s: Malformed domain,offset string '%s'. " |
730 | "Skipping...\n", program_invocation_short_name, opt); |
731 | break; |
732 | } |
733 | *p = '\0'; |
734 | } |
735 | domlist[print_domlist++].with_dom = (c == 'D' || c == 'L'); |
736 | skip: |
737 | break; |
738 | case 'S': |
739 | sep_char = optarg; |
740 | if (strlen (sep_char) > 1) |
741 | { |
742 | fprintf (stderr((__getreent())->_stderr), "%s: Only one character allowed as domain\\user " |
743 | "separator character.\n", |
744 | program_invocation_short_name); |
745 | return 1; |
746 | } |
747 | if (*sep_char == ':') |
748 | { |
749 | fprintf (stderr((__getreent())->_stderr), "%s: Colon not allowed as domain\\user separator " |
750 | "character.\n", program_invocation_short_name); |
751 | return 1; |
752 | } |
753 | break; |
754 | case 'U': |
755 | print_unix = optarg; |
756 | break; |
757 | case 'c': |
758 | sep_char = NULL((void*)0); |
759 | /*FALLTHRU*/ |
760 | case 'C': |
761 | print_current = 1; |
762 | break; |
763 | case 'o': |
764 | id_offset = strtoul (optarg, &ep, 10); |
765 | if (*ep) |
766 | { |
767 | fprintf (stderr((__getreent())->_stderr), "%s: Malformed offset '%s'. " |
768 | "Skipping...\n", program_invocation_short_name, optarg); |
769 | return 1; |
770 | } |
771 | break; |
772 | case 'p': |
773 | if (optarg[0] != '/') |
774 | { |
775 | fprintf (stderr((__getreent())->_stderr), "%s: '%s' is not a fully qualified path.\n", |
776 | program_invocation_short_name, optarg); |
777 | return 1; |
778 | } |
779 | strcpy (passed_home_path, optarg); |
780 | if (optarg[strlen (optarg)-1] != '/') |
781 | strcat (passed_home_path, "/"); |
782 | break; |
783 | case 'u': |
784 | disp_username = optarg; |
785 | break; |
786 | case 'h': |
787 | usage (stdout((__getreent())->_stdout)); |
788 | return 0; |
789 | case 'V': |
790 | print_version (); |
791 | return 0; |
792 | case 'g': /* deprecated */ |
793 | case 's': /* deprecated */ |
794 | case 'm': /* deprecated */ |
795 | break; |
796 | default: |
797 | fprintf (stderr((__getreent())->_stderr), "Try `%s --help' for more information.\n", |
798 | program_invocation_short_name); |
799 | return 1; |
800 | } |
801 | |
802 | optind += optional_args; |
803 | if (argv[optind]) |
804 | { |
805 | fprintf (stderr((__getreent())->_stderr), |
806 | "mkpasswd: non-option command line argument `%s' is not allowed.\n" |
807 | "Try `mkpasswd --help' for more information.\n", argv[optind]); |
808 | exit (1); |
809 | } |
810 | |
811 | off = id_offset; |
812 | for (i = 0; i < print_domlist; ++i) |
813 | { |
814 | DWORD my_off = (domlist[i].domain || domlist[i].str) |
815 | ? domlist[i].id_offset != ULONG_MAX(2147483647L * 2UL + 1) |
816 | ? domlist[i].id_offset : off : 0; |
817 | if (!domlist[i].domain && domlist[i].str && print_unix) |
818 | enum_unix_users (domlist + i, sep_char, my_off, print_unix); |
819 | if (!my_off && !disp_username) |
820 | enum_std_accounts (); |
821 | enum_users (domlist[i].domain, domlist + i, sep_char, passed_home_path, |
822 | my_off, disp_username, print_current); |
823 | if (my_off) |
824 | off += id_offset; |
825 | } |
826 | |
827 | if (print_current && !got_curr_user) |
828 | current_user (sep_char, passed_home_path, off, disp_username); |
829 | |
830 | return 0; |
831 | } |