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