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