]> sourceware.org Git - newlib-cygwin.git/blob - winsup/utils/mkgroup.c
* mkgroup.c (usage): Use one just fprintf + string concatenation for output
[newlib-cygwin.git] / winsup / utils / mkgroup.c
1 /* mkgroup.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 <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 "This program prints a /etc/group file to stdout\n\n"
411 "Options:\n"
412 " -l,--local print local group information\n"
413 " -d,--domain print global group information from the domain\n"
414 " specified (or from the current domain if there is\n"
415 " no domain specified)\n"
416 " -o,--id-offset offset change the default offset (10000) added to uids\n"
417 " in domain accounts.\n"
418 " -s,--no-sids don't print SIDs in pwd field\n"
419 " (this affects ntsec)\n"
420 " -u,--users print user list in gr_mem field\n"
421 " -h,--help print this message\n\n"
422 " -v,--version print version information and exit\n\n"
423 "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 void
441 print_version ()
442 {
443 const char *v = strchr (version, ':');
444 int len;
445 if (!v)
446 {
447 v = "?";
448 len = 1;
449 }
450 else
451 {
452 v += 2;
453 len = strchr (v, ' ') - v;
454 }
455 printf ("\
456 mkgroup (cygwin) %.*s\n\
457 group File Generator\n\
458 Copyright 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.\n\
459 Compiled on %s", len, v, __DATE__);
460 }
461
462 int
463 main (int argc, char **argv)
464 {
465 LPWSTR servername;
466 DWORD rc = ERROR_SUCCESS;
467 WCHAR domain_name[100];
468 int print_local = 0;
469 int print_domain = 0;
470 int print_sids = 1;
471 int print_users = 0;
472 int domain_specified = 0;
473 int id_offset = 10000;
474 int i;
475
476 char name[256], dom[256];
477 DWORD len, len2;
478 char buf[1024];
479 PSID psid = NULL;
480 SID_NAME_USE use;
481
482 LSA_OBJECT_ATTRIBUTES oa = { 0, 0, 0, 0, 0, 0 };
483 LSA_HANDLE lsa = INVALID_HANDLE_VALUE;
484 NTSTATUS ret;
485 PPOLICY_PRIMARY_DOMAIN_INFO pdi;
486
487 if (GetVersion () < 0x80000000)
488 {
489 if (argc == 1)
490 return usage(stderr, 1);
491 else
492 {
493 while ((i = getopt_long (argc, argv, opts, longopts, NULL)) != EOF)
494 switch (i)
495 {
496 case 'l':
497 print_local = 1;
498 break;
499 case 'd':
500 print_domain = 1;
501 break;
502 case 'o':
503 id_offset = strtol (optarg, NULL, 10);
504 break;
505 case 's':
506 print_sids = 0;
507 break;
508 case 'u':
509 print_users = 1;
510 break;
511 case 'h':
512 return usage (stdout, 0);
513 case 'v':
514 print_version ();
515 exit (0);
516 default:
517 fprintf (stderr, "Try `%s --help' for more information.\n", argv[0]);
518 return 1;
519 }
520 if (!print_local && !print_domain)
521 {
522 fprintf (stderr, "%s: Specify one of `-l' or `-d'\n", argv[0]);
523 return 1;
524 }
525 if (optind < argc)
526 {
527 if (!print_domain)
528 {
529 fprintf (stderr, "%s: A domain name is only accepted "
530 "when `-d' is given.\n", argv[0]);
531 return 1;
532 }
533 mbstowcs (domain_name, argv[optind], (strlen (argv[optind]) + 1));
534 domain_specified = 1;
535 }
536 }
537 }
538
539 /* This takes Windows 9x/ME into account. */
540 if (GetVersion () >= 0x80000000)
541 {
542 printf ("unknown::%ld:\n", DOMAIN_ALIAS_RID_ADMINS);
543 return 0;
544 }
545
546 if (!load_netapi ())
547 {
548 fprintf (stderr, "Failed loading symbols from netapi32.dll "
549 "with error %lu\n", GetLastError ());
550 return 1;
551 }
552
553 /*
554 * Get `Everyone' group
555 */
556 print_special (print_sids, &sid_world_auth, 1, SECURITY_WORLD_RID,
557 0, 0, 0, 0, 0, 0, 0);
558 /*
559 * Get `system' group
560 */
561 print_special (print_sids, &sid_nt_auth, 1, SECURITY_LOCAL_SYSTEM_RID,
562 0, 0, 0, 0, 0, 0, 0);
563 if (print_local)
564 {
565 /*
566 * Get `None' group
567 */
568 len = 256;
569 GetComputerName (name, &len);
570 len = 1024;
571 len2 = 256;
572 if (LookupAccountName (NULL, name, (PSID) buf, &len, dom, &len, &use))
573 psid = (PSID) buf;
574 else
575 {
576 ret = LsaOpenPolicy(NULL, &oa, POLICY_VIEW_LOCAL_INFORMATION, &lsa);
577 if (ret == STATUS_SUCCESS && lsa != INVALID_HANDLE_VALUE)
578 {
579 ret = LsaQueryInformationPolicy (lsa,
580 PolicyPrimaryDomainInformation,
581 (PVOID *) &pdi);
582 if (ret == STATUS_SUCCESS)
583 {
584 if (pdi->Sid)
585 {
586 CopySid (1024, (PSID) buf, pdi->Sid);
587 psid = (PSID) buf;
588 }
589 LsaFreeMemory (pdi);
590 }
591 LsaClose (lsa);
592 }
593 }
594 if (!psid)
595 fprintf (stderr,
596 "WARNING: Group 513 couldn't get retrieved. Try mkgroup -d\n");
597 else
598 print_special (print_sids, GetSidIdentifierAuthority (psid), 5,
599 *GetSidSubAuthority (psid, 0),
600 *GetSidSubAuthority (psid, 1),
601 *GetSidSubAuthority (psid, 2),
602 *GetSidSubAuthority (psid, 3),
603 513,
604 0,
605 0,
606 0);
607 }
608
609 if (print_domain)
610 {
611 if (domain_specified)
612 rc = netgetdcname (NULL, domain_name, (LPBYTE *) & servername);
613
614 else
615 rc = netgetdcname (NULL, NULL, (LPBYTE *) & servername);
616
617 if (rc != ERROR_SUCCESS)
618 {
619 fprintf (stderr, "Cannot get PDC, code = %ld\n", rc);
620 exit (1);
621 }
622
623 enum_groups (servername, print_sids, print_users, id_offset);
624 }
625
626 if (print_local)
627 enum_local_groups (print_sids, print_users);
628
629 return 0;
630 }
This page took 0.066418 seconds and 6 git commands to generate.