]> sourceware.org Git - newlib-cygwin.git/blob - winsup/utils/mkpasswd.c
* mkpasswd.c (enum_users): Change to unconditionally use
[newlib-cygwin.git] / winsup / utils / mkpasswd.c
1 /* mkpasswd.c:
2
3 Copyright 1997, 1998, 1999, 2000, 2001 Red Hat, Inc.
4
5 This file is part of Cygwin.
6
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
9 details. */
10
11 #include <ctype.h>
12 #include <stdlib.h>
13 #include <wchar.h>
14 #include <stdio.h>
15 #include <windows.h>
16 #include <io.h>
17 #include <sys/cygwin.h>
18 #include <getopt.h>
19 #include <lmaccess.h>
20 #include <lmapibuf.h>
21 #include <sys/fcntl.h>
22 #include <lmerr.h>
23
24 SID_IDENTIFIER_AUTHORITY sid_world_auth = {SECURITY_WORLD_SID_AUTHORITY};
25 SID_IDENTIFIER_AUTHORITY sid_nt_auth = {SECURITY_NT_AUTHORITY};
26
27 NET_API_STATUS WINAPI (*netapibufferfree)(PVOID);
28 NET_API_STATUS WINAPI (*netuserenum)(LPWSTR,DWORD,DWORD,PBYTE*,DWORD,PDWORD,PDWORD,PDWORD);
29 NET_API_STATUS WINAPI (*netlocalgroupenum)(LPWSTR,DWORD,PBYTE*,DWORD,PDWORD,PDWORD,PDWORD);
30 NET_API_STATUS WINAPI (*netgetdcname)(LPWSTR,LPWSTR,PBYTE*);
31 NET_API_STATUS WINAPI (*netusergetinfo)(LPWSTR,LPWSTR,DWORD,PBYTE*);
32
33 #ifndef min
34 #define min(a,b) (((a)<(b))?(a):(b))
35 #endif
36
37 BOOL
38 load_netapi ()
39 {
40 HANDLE h = LoadLibrary ("netapi32.dll");
41
42 if (!h)
43 return FALSE;
44
45 if (!(netapibufferfree = (void *) GetProcAddress (h, "NetApiBufferFree")))
46 return FALSE;
47 if (!(netuserenum = (void *) GetProcAddress (h, "NetUserEnum")))
48 return FALSE;
49 if (!(netlocalgroupenum = (void *) GetProcAddress (h, "NetLocalGroupEnum")))
50 return FALSE;
51 if (!(netgetdcname = (void *) GetProcAddress (h, "NetGetDCName")))
52 return FALSE;
53 if (!(netusergetinfo = (void *) GetProcAddress (h, "NetUserGetInfo")))
54 return FALSE;
55
56 return TRUE;
57 }
58
59 char *
60 put_sid (PSID sid)
61 {
62 static char s[512];
63 char t[32];
64 DWORD i;
65
66 strcpy (s, "S-1-");
67 sprintf(t, "%u", GetSidIdentifierAuthority (sid)->Value[5]);
68 strcat (s, t);
69 for (i = 0; i < *GetSidSubAuthorityCount (sid); ++i)
70 {
71 sprintf(t, "-%lu", *GetSidSubAuthority (sid, i));
72 strcat (s, t);
73 }
74 return s;
75 }
76
77 void
78 psx_dir (char *in, char *out)
79 {
80 if (isalpha (in[0]) && in[1] == ':')
81 {
82 sprintf (out, "/cygdrive/%c", in[0]);
83 in += 2;
84 out += strlen (out);
85 }
86
87 while (*in)
88 {
89 if (*in == '\\')
90 *out = '/';
91 else
92 *out = *in;
93 in++;
94 out++;
95 }
96
97 *out = '\0';
98 }
99
100 void
101 uni2ansi (LPWSTR wcs, char *mbs, int size)
102 {
103 if (wcs)
104 WideCharToMultiByte (CP_ACP, 0, wcs, -1, mbs, size, NULL, NULL);
105 else
106 *mbs = '\0';
107 }
108
109 int
110 enum_users (LPWSTR servername, int print_sids, int print_cygpath,
111 const char * passed_home_path, int id_offset, char *disp_username)
112 {
113 USER_INFO_3 *buffer;
114 DWORD entriesread = 0;
115 DWORD totalentries = 0;
116 DWORD resume_handle = 0;
117 DWORD rc;
118 char ansi_srvname[256];
119 WCHAR uni_name[512];
120
121 if (servername)
122 uni2ansi (servername, ansi_srvname, sizeof (ansi_srvname));
123
124 do
125 {
126 DWORD i;
127
128 if (disp_username != NULL)
129 {
130 MultiByteToWideChar (CP_ACP, 0, disp_username, -1, uni_name, 512 );
131 rc = netusergetinfo(servername, (LPWSTR) & uni_name, 3,
132 (LPBYTE *) &buffer );
133 entriesread=1;
134 }
135 else
136 rc = netuserenum (servername, 3, FILTER_NORMAL_ACCOUNT,
137 (LPBYTE *) & buffer, 1024,
138 &entriesread, &totalentries, &resume_handle);
139 switch (rc)
140 {
141 case ERROR_ACCESS_DENIED:
142 fprintf (stderr, "Access denied\n");
143 exit (1);
144
145 case ERROR_MORE_DATA:
146 case ERROR_SUCCESS:
147 break;
148
149 default:
150 fprintf (stderr, "NetUserEnum() failed with error %ld.\n", rc);
151 if (rc == NERR_UserNotFound)
152 fprintf (stderr, "That user doesn't exist.\n");
153 exit (1);
154 }
155
156 for (i = 0; i < entriesread; i++)
157 {
158 char username[100];
159 char fullname[100];
160 char homedir_psx[MAX_PATH];
161 char homedir_w32[MAX_PATH];
162 char domain_name[100];
163 DWORD domname_len = 100;
164 char psid_buffer[1024];
165 PSID psid = (PSID) psid_buffer;
166 DWORD sid_length = 1024;
167 SID_NAME_USE acc_type;
168
169 int uid = buffer[i].usri3_user_id;
170 int gid = buffer[i].usri3_primary_group_id;
171 uni2ansi (buffer[i].usri3_name, username, sizeof (username));
172 uni2ansi (buffer[i].usri3_full_name, fullname, sizeof (fullname));
173 homedir_w32[0] = homedir_psx[0] = '\0';
174 if (passed_home_path[0] == '\0')
175 {
176 uni2ansi (buffer[i].usri3_home_dir, homedir_w32,
177 sizeof (homedir_w32));
178 if (homedir_w32[0] != '\0')
179 {
180 if (print_cygpath)
181 cygwin_conv_to_posix_path (homedir_w32, homedir_psx);
182 else
183 psx_dir (homedir_w32, homedir_psx);
184 }
185 else
186 {
187 strcpy (homedir_psx, "/home/");
188 strcat (homedir_psx, username);
189 }
190 }
191 else
192 {
193 strcpy (homedir_psx, passed_home_path);
194 strcat (homedir_psx, username);
195 }
196
197 if (print_sids)
198 {
199 if (!LookupAccountName (servername ? ansi_srvname : NULL,
200 username,
201 psid, &sid_length,
202 domain_name, &domname_len,
203 &acc_type))
204 {
205 fprintf (stderr,
206 "LookupAccountName(%s,%s) failed with error %ld\n",
207 servername ? ansi_srvname : "NULL",
208 username,
209 GetLastError ());
210 continue;
211 }
212 else if (acc_type == SidTypeDomain)
213 {
214 char domname[356];
215
216 strcpy (domname, domain_name);
217 strcat (domname, "\\");
218 strcat (domname, username);
219 sid_length = 1024;
220 domname_len = 100;
221 if (!LookupAccountName (servername ? ansi_srvname : NULL,
222 domname,
223 psid, &sid_length,
224 domain_name, &domname_len,
225 &acc_type))
226 {
227 fprintf (stderr,
228 "LookupAccountName(%s,%s) failed with error %ld\n",
229 servername ? ansi_srvname : "NULL",
230 domname,
231 GetLastError ());
232 continue;
233 }
234 }
235 }
236 printf ("%s:unused_by_nt/2000/xp:%d:%d:%s%s%s%s%s%s%s%s:%s:/bin/bash\n",
237 username,
238 uid + id_offset,
239 gid + id_offset,
240 fullname,
241 print_sids && fullname[0] ? "," : "",
242 print_sids ? "U-" : "",
243 print_sids ? domain_name : "",
244 print_sids && domain_name[0] ? "\\" : "",
245 print_sids ? username : "",
246 print_sids ? "," : "",
247 print_sids ? put_sid (psid) : "",
248 homedir_psx);
249 }
250
251 netapibufferfree (buffer);
252
253 }
254 while (rc == ERROR_MORE_DATA);
255
256 if (servername)
257 netapibufferfree (servername);
258
259 return 0;
260 }
261
262 int
263 enum_local_groups (int print_sids)
264 {
265 LOCALGROUP_INFO_0 *buffer;
266 DWORD entriesread = 0;
267 DWORD totalentries = 0;
268 DWORD resume_handle = 0;
269 DWORD rc ;
270
271 do
272 {
273 DWORD i;
274
275 rc = netlocalgroupenum (NULL, 0, (LPBYTE *) & buffer, 1024,
276 &entriesread, &totalentries, &resume_handle);
277 switch (rc)
278 {
279 case ERROR_ACCESS_DENIED:
280 fprintf (stderr, "Access denied\n");
281 exit (1);
282
283 case ERROR_MORE_DATA:
284 case ERROR_SUCCESS:
285 break;
286
287 default:
288 fprintf (stderr, "NetLocalGroupEnum() failed with %ld\n", rc);
289 exit (1);
290 }
291
292 for (i = 0; i < entriesread; i++)
293 {
294 char localgroup_name[100];
295 char domain_name[100];
296 DWORD domname_len = 100;
297 char psid_buffer[1024];
298 PSID psid = (PSID) psid_buffer;
299 DWORD sid_length = 1024;
300 DWORD gid;
301 SID_NAME_USE acc_type;
302 uni2ansi (buffer[i].lgrpi0_name, localgroup_name, sizeof (localgroup_name));
303
304 if (!LookupAccountName (NULL, localgroup_name, psid,
305 &sid_length, domain_name, &domname_len,
306 &acc_type))
307 {
308 fprintf (stderr, "LookupAccountName(%s) failed with %ld\n",
309 localgroup_name, GetLastError ());
310 continue;
311 }
312 else if (acc_type == SidTypeDomain)
313 {
314 char domname[356];
315
316 strcpy (domname, domain_name);
317 strcat (domname, "\\");
318 strcat (domname, localgroup_name);
319 sid_length = 1024;
320 domname_len = 100;
321 if (!LookupAccountName (NULL, domname,
322 psid, &sid_length,
323 domain_name, &domname_len,
324 &acc_type))
325 {
326 fprintf (stderr,
327 "LookupAccountName(%s) failed with error %ld\n",
328 localgroup_name, GetLastError ());
329 continue;
330 }
331 }
332
333 gid = *GetSidSubAuthority (psid, *GetSidSubAuthorityCount(psid) - 1);
334
335 printf ("%s:*:%ld:%ld:%s%s::\n", localgroup_name, gid, gid,
336 print_sids ? "," : "",
337 print_sids ? put_sid (psid) : "");
338 }
339
340 netapibufferfree (buffer);
341
342 }
343 while (rc == ERROR_MORE_DATA);
344
345 return 0;
346 }
347
348 void
349 print_special (int print_sids,
350 PSID_IDENTIFIER_AUTHORITY auth, BYTE cnt,
351 DWORD sub1, DWORD sub2, DWORD sub3, DWORD sub4,
352 DWORD sub5, DWORD sub6, DWORD sub7, DWORD sub8)
353 {
354 char name[256], dom[256];
355 DWORD len, len2, rid;
356 PSID sid;
357 SID_NAME_USE use;
358
359 if (AllocateAndInitializeSid (auth, cnt, sub1, sub2, sub3, sub4,
360 sub5, sub6, sub7, sub8, &sid))
361 {
362 if (LookupAccountSid (NULL, sid,
363 name, (len = 256, &len),
364 dom, (len2 = 256, &len),
365 &use))
366 {
367 if (sub8)
368 rid = sub8;
369 else if (sub7)
370 rid = sub7;
371 else if (sub6)
372 rid = sub6;
373 else if (sub5)
374 rid = sub5;
375 else if (sub4)
376 rid = sub4;
377 else if (sub3)
378 rid = sub3;
379 else if (sub2)
380 rid = sub2;
381 else
382 rid = sub1;
383 printf ("%s:*:%lu:%lu:%s%s::\n",
384 name, rid, rid,
385 print_sids ? "," : "",
386 print_sids ? put_sid (sid) : "");
387 }
388 FreeSid (sid);
389 }
390 }
391
392 int
393 usage ()
394 {
395 fprintf (stderr, "Usage: mkpasswd [OPTION]... [domain]\n\n");
396 fprintf (stderr, "This program prints a /etc/passwd file to stdout\n\n");
397 fprintf (stderr, "Options:\n");
398 fprintf (stderr, " -l,--local print local user accounts\n");
399 fprintf (stderr, " -d,--domain print domain accounts (from current domain\n");
400 fprintf (stderr, " if no domain specified)\n");
401 fprintf (stderr, " -o,--id-offset offset change the default offset (10000) added to uids\n");
402 fprintf (stderr, " in domain accounts.\n");
403 fprintf (stderr, " -g,--local-groups print local group information too\n");
404 fprintf (stderr, " if no domain specified\n");
405 fprintf (stderr, " -m,--no-mount don't use mount points for home dir\n");
406 fprintf (stderr, " -s,--no-sids don't print SIDs in GCOS field\n");
407 fprintf (stderr, " (this affects ntsec)\n");
408 fprintf (stderr, " -p,--path-to-home path use specified path instead of user account home dir\n");
409 fprintf (stderr, " -u,--username username only return information for the specified user\n");
410 fprintf (stderr, " -?,--help displays this message\n\n");
411 fprintf (stderr, "One of `-l', `-d' or `-g' must be given on NT/W2K.\n");
412 return 1;
413 }
414
415 struct option longopts[] = {
416 {"local", no_argument, NULL, 'l'},
417 {"domain", no_argument, NULL, 'd'},
418 {"id-offset", required_argument, NULL, 'o'},
419 {"local-groups", no_argument, NULL, 'g'},
420 {"no-mount", no_argument, NULL, 'm'},
421 {"no-sids", no_argument, NULL, 's'},
422 {"path-to-home", required_argument, NULL, 'p'},
423 {"username", required_argument, NULL, 'u'},
424 {"help", no_argument, NULL, 'h'},
425 {0, no_argument, NULL, 0}
426 };
427
428 char opts[] = "ldo:gsmhp:u:";
429
430 int
431 main (int argc, char **argv)
432 {
433 LPWSTR servername = NULL;
434 DWORD rc = ERROR_SUCCESS;
435 WCHAR domain_name[200];
436 int print_local = 0;
437 int print_domain = 0;
438 int print_local_groups = 0;
439 int domain_name_specified = 0;
440 int print_sids = 1;
441 int print_cygpath = 1;
442 int id_offset = 10000;
443 int i;
444 char *disp_username = NULL;
445
446 char name[256], passed_home_path[MAX_PATH];
447 DWORD len;
448
449 passed_home_path[0] = '\0';
450 setmode (1, O_BINARY);
451
452 if (GetVersion () < 0x80000000)
453 {
454 if (argc == 1)
455 return usage ();
456 else
457 {
458 while ((i = getopt_long (argc, argv, opts, longopts, NULL)) != EOF)
459 switch (i)
460 {
461 case 'l':
462 print_local = 1;
463 break;
464 case 'd':
465 print_domain = 1;
466 break;
467 case 'o':
468 id_offset = strtol (optarg, NULL, 10);
469 break;
470 case 'g':
471 print_local_groups = 1;
472 break;
473 case 's':
474 print_sids = 0;
475 break;
476 case 'm':
477 print_cygpath = 0;
478 break;
479 case 'p':
480 if (optarg[0] != '/')
481 {
482 fprintf (stderr, "%s: `%s' is not a fully qualified path.\n",
483 argv[0], optarg);
484 return 1;
485 }
486 strcpy (passed_home_path, optarg);
487 if (optarg[strlen (optarg)-1] != '/')
488 strcat (passed_home_path, "/");
489 break;
490 case 'u':
491 disp_username = optarg;
492 break;
493 case 'h':
494 return usage ();
495 default:
496 fprintf (stderr, "Try `%s --help' for more information.\n", argv[0]);
497 return 1;
498 }
499 if (!print_local && !print_domain && !print_local_groups)
500 {
501 fprintf (stderr, "%s: Specify one of `-l', `-d' or `-g'\n", argv[0]);
502 return 1;
503 }
504 if (optind < argc)
505 {
506 if (!print_domain)
507 {
508 fprintf (stderr, "%s: A domain name is only accepted "
509 "when `-d' is given.\n", argv[0]);
510 return 1;
511 }
512 mbstowcs (domain_name, argv[optind], (strlen (argv[optind]) + 1));
513 domain_name_specified = 1;
514 }
515 }
516 }
517
518 /* This takes Windows 9x/ME into account. */
519 if (GetVersion () >= 0x80000000)
520 {
521 /* Same behaviour as in cygwin/uinfo.cc (internal_getlogin). */
522 if (!GetUserName (name, (len = 256, &len)))
523 strcpy (name, "unknown");
524
525 printf ("%s::%ld:%ld::%s%s:/bin/bash\n", name,
526 DOMAIN_USER_RID_ADMIN,
527 DOMAIN_ALIAS_RID_ADMINS,
528 passed_home_path,
529 name);
530
531 return 0;
532 }
533
534 if (!load_netapi ())
535 {
536 fprintf (stderr, "Failed loading symbols from netapi32.dll "
537 "with error %lu\n", GetLastError ());
538 return 1;
539 }
540
541 /*
542 * Get `Everyone' group
543 */
544 if (disp_username == NULL)
545 {
546 print_special (print_sids, &sid_world_auth, 1, SECURITY_WORLD_RID,
547 0, 0, 0, 0, 0, 0, 0);
548 /*
549 * Get `system' group
550 */
551 print_special (print_sids, &sid_nt_auth, 1, SECURITY_LOCAL_SYSTEM_RID,
552 0, 0, 0, 0, 0, 0, 0);
553 /*
554 * Get `administrators' group
555 */
556 if (!print_local_groups)
557 print_special (print_sids, &sid_nt_auth, 2, SECURITY_BUILTIN_DOMAIN_RID,
558 DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0);
559
560 if (print_local_groups)
561 enum_local_groups (print_sids);
562 }
563
564 if (print_domain)
565 {
566 if (domain_name_specified)
567 rc = netgetdcname (NULL, domain_name, (LPBYTE *) & servername);
568
569 else
570 rc = netgetdcname (NULL, NULL, (LPBYTE *) & servername);
571
572 if (rc != ERROR_SUCCESS)
573 {
574 fprintf (stderr, "Cannot get DC, code = %ld\n", rc);
575 exit (1);
576 }
577
578 enum_users (servername, print_sids, print_cygpath, passed_home_path,
579 id_offset, disp_username);
580 }
581
582 if (print_local)
583 enum_users (NULL, print_sids, print_cygpath, passed_home_path, 0,
584 disp_username);
585
586 if (servername)
587 netapibufferfree (servername);
588
589 return 0;
590 }
This page took 0.058852 seconds and 6 git commands to generate.