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