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