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