From a1e199034882ebf25918021d2d30962928e997d6 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Tue, 22 Jul 2008 14:40:05 +0000 Subject: * Makefile.in (cygcheck.exe): Link against ntdll. * bloda.cc: Use statically linked functions throughout. * cygpath.cc: Drop 9x considerations. * mkgroup.c: Revamp. Redefine -l and -d options to take optional machine and domain parameters. Redefine -c to work always, using token information. Add -L, -D, -C to create unique groupnames in domain\group syntax. Add -S option to define domain\group separator char. Ignore -u and -s options. * mkpasswd.c: Revamp. Redefine -l and -d options to take optional machine and domain parameters. Redefine -c to work always, using token information. Add -L, -D, -C to create unique usernames in domain\user syntax. Add -S option to define domain\user separator char. Ignore -g and -s options. Prefer to take homedir from $HOME over $HOMEDRIVE/$HOMEPATH. * path.cc (oopts): Add "acl", "noacl", "posix=0" and "posix=1" options. (getmntent): Accomodate throughout. * ps.cc: Fix copyright dates. * utils.sgml: Fix text for mkgroup and mkpasswd. --- winsup/utils/mkgroup.c | 795 +++++++++++++++++++++++++------------------------ 1 file changed, 400 insertions(+), 395 deletions(-) (limited to 'winsup/utils/mkgroup.c') diff --git a/winsup/utils/mkgroup.c b/winsup/utils/mkgroup.c index 63408cd8a..a82ae3b1b 100644 --- a/winsup/utils/mkgroup.c +++ b/winsup/utils/mkgroup.c @@ -9,37 +9,31 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for details. */ +#define _WIN32_WINNT 0x0600 #include #include #include #include -#include -#include +#include #include -#include -#include +#include +#include +#include +#include +#include #include #include #include +#include #include #define print_win_error(x) _print_win_error(x, __LINE__) -static const char version[] = "$Revision$"; - #define MAX_SID_LEN 40 -typedef struct { - LPWSTR DomainControllerName; - LPWSTR DomainControllerAddress; - ULONG DomainControllerAddressType; - GUID DomainGuid; - LPWSTR DomainName; - LPWSTR DnsForestName; - ULONG Flags; - LPWSTR DcSiteName; - LPWSTR ClientSiteName; -} *PDOMAIN_CONTROLLER_INFOW; +static const char version[] = "$Revision$"; + +extern char *__progname; SID_IDENTIFIER_AUTHORITY sid_world_auth = {SECURITY_WORLD_SID_AUTHORITY}; SID_IDENTIFIER_AUTHORITY sid_nt_auth = {SECURITY_NT_AUTHORITY}; @@ -50,14 +44,83 @@ NET_API_STATUS WINAPI (*dsgetdcname)(LPWSTR,LPWSTR,GUID*,LPWSTR,ULONG,PDOMAIN_CO #define min(a,b) (((a)<(b))?(a):(b)) #endif +typedef struct +{ + char *str; + BOOL with_dom; +} domlist_t; + +void +_print_win_error (DWORD code, int line) +{ + char buf[4096]; + + if (FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + code, + MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) buf, sizeof (buf), NULL)) + fprintf (stderr, "mkgroup (%d): [%lu] %s", line, code, buf); + else + fprintf (stderr, "mkgroup (%d): error %lu", line, code); +} + void -load_netapi () +load_dsgetdcname () { HANDLE h = LoadLibrary ("netapi32.dll"); if (h) dsgetdcname = (void *) GetProcAddress (h, "DsGetDcNameW"); } +static PWCHAR +get_dcname (char *domain) +{ + static WCHAR server[INTERNET_MAX_HOST_NAME_LENGTH + 1]; + DWORD rc; + PWCHAR servername; + WCHAR domain_name[MAX_DOMAIN_NAME_LEN + 1]; + PDOMAIN_CONTROLLER_INFOW pdci = NULL; + + if (dsgetdcname) + { + if (domain) + { + mbstowcs (domain_name, domain, strlen (domain) + 1); + rc = dsgetdcname (NULL, domain_name, NULL, NULL, 0, &pdci); + } + else + rc = dsgetdcname (NULL, NULL, NULL, NULL, 0, &pdci); + if (rc != ERROR_SUCCESS) + { + print_win_error (rc); + return (PWCHAR) -1; + } + wcscpy (server, pdci->DomainControllerName); + NetApiBufferFree (pdci); + } + else + { + rc = NetGetDCName (NULL, NULL, (void *) &servername); + if (rc == ERROR_SUCCESS && domain) + { + LPWSTR server = servername; + mbstowcs (domain_name, domain, strlen (domain) + 1); + rc = NetGetDCName (server, domain_name, (void *) &servername); + NetApiBufferFree (server); + } + if (rc != ERROR_SUCCESS) + { + print_win_error(rc); + return (PWCHAR) -1; + } + wcscpy (server, servername); + NetApiBufferFree ((PVOID) servername); + } + return server; +} + char * put_sid (PSID sid) { @@ -76,48 +139,6 @@ put_sid (PSID sid) return s; } -void -_print_win_error(DWORD code, int line) -{ - char buf[4096]; - - if (FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM - | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - code, - MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) buf, sizeof (buf), NULL)) - fprintf (stderr, "mkgroup (%d): [%lu] %s", line, code, buf); - else - fprintf (stderr, "mkgroup (%d): error %lu", line, code); -} - -void -enum_local_users (LPWSTR servername, LPWSTR groupname) -{ - LOCALGROUP_MEMBERS_INFO_1 *buf1; - DWORD entries = 0; - DWORD total = 0; - DWORD reshdl = 0; - - if (!NetLocalGroupGetMembers (servername, groupname, 1, (void *) &buf1, - MAX_PREFERRED_LENGTH, - &entries, &total, &reshdl)) - { - unsigned i, first = 1; - - for (i = 0; i < entries; ++i) - if (buf1[i].lgrmi1_sidusage == SidTypeUser) - { - if (!first) - printf (","); - first = 0; - printf ("%ls", buf1[i].lgrmi1_name); - } - NetApiBufferFree (buf1); - } -} - typedef struct { BYTE Revision; BYTE SubAuthorityCount; @@ -130,26 +151,48 @@ DBGSID builtin_sid_list[MAX_BUILTIN_SIDS]; DWORD builtin_sid_cnt; int -enum_local_groups (LPWSTR servername, int print_sids, int print_users, +enum_local_groups (BOOL domain, domlist_t *dom_or_machine, const char *sep, int id_offset, char *disp_groupname) { + WCHAR machine[INTERNET_MAX_HOST_NAME_LENGTH + 1]; + PWCHAR servername = NULL; + char *d_or_m = dom_or_machine ? dom_or_machine->str : NULL; + BOOL with_dom = dom_or_machine ? dom_or_machine->with_dom : FALSE; LOCALGROUP_INFO_0 *buffer; DWORD entriesread = 0; DWORD totalentries = 0; DWORD resume_handle = 0; - WCHAR uni_name[GNLEN + 1]; + WCHAR gname[GNLEN + 1]; DWORD rc; + if (domain) + { + servername = get_dcname (d_or_m); + if (servername == (PWCHAR) -1) + return 1; + } + else if (d_or_m) + { + int ret = mbstowcs (machine, d_or_m, INTERNET_MAX_HOST_NAME_LENGTH + 1); + if (ret < 1 || ret >= INTERNET_MAX_HOST_NAME_LENGTH + 1) + { + fprintf (stderr, "%s: Invalid machine name '%s'. Skipping...\n", + __progname, d_or_m); + return 1; + } + servername = machine; + } + do { DWORD i; if (disp_groupname != NULL) { - mbstowcs (uni_name, disp_groupname, GNLEN + 1); + mbstowcs (gname, disp_groupname, GNLEN + 1); rc = NetApiBufferAllocate (sizeof (LOCALGROUP_INFO_0), (void *) &buffer); - buffer[0].lgrpi0_name = uni_name; + buffer[0].lgrpi0_name = gname; entriesread = 1; } else @@ -159,16 +202,16 @@ enum_local_groups (LPWSTR servername, int print_sids, int print_users, switch (rc) { case ERROR_ACCESS_DENIED: - print_win_error(rc); - exit (1); + print_win_error (rc); + return 1; case ERROR_MORE_DATA: case ERROR_SUCCESS: break; default: - print_win_error(rc); - exit (1); + print_win_error (rc); + return 1; } for (i = 0; i < entriesread; i++) @@ -187,7 +230,7 @@ enum_local_groups (LPWSTR servername, int print_sids, int print_users, &sid_length, domain_name, &domname_len, &acc_type)) { - print_win_error(rc); + print_win_error (rc); fprintf (stderr, " (%ls)\n", buffer[i].lgrpi0_name); continue; } @@ -205,7 +248,7 @@ enum_local_groups (LPWSTR servername, int print_sids, int print_users, domain_name, &domname_len, &acc_type)) { - print_win_error(rc); + print_win_error (rc); fprintf(stderr, " (%ls)\n", domname); continue; } @@ -232,12 +275,12 @@ enum_local_groups (LPWSTR servername, int print_sids, int print_users, gid = *GetSidSubAuthority (psid, *GetSidSubAuthorityCount(psid) - 1); - printf ("%ls:%s:%ld:", buffer[i].lgrpi0_name, - print_sids ? put_sid (psid) : "", - gid + (is_builtin ? 0 : id_offset)); - if (print_users) - enum_local_users (servername, buffer[i].lgrpi0_name); - printf ("\n"); + printf ("%ls%s%ls:%s:%ld:\n", + with_dom ? domain_name : L"", + with_dom ? sep : "", + buffer[i].lgrpi0_name, + put_sid (psid), + gid + (is_builtin ? 0 : id_offset)); skip_group: ; } @@ -251,48 +294,46 @@ skip_group: } void -enum_users (LPWSTR servername, LPWSTR groupname) -{ - GROUP_USERS_INFO_0 *buf1; - DWORD entries = 0; - DWORD total = 0; - DWORD reshdl = 0; - - if (!NetGroupGetUsers (servername, groupname, 0, (void *) &buf1, - MAX_PREFERRED_LENGTH, &entries, &total, &reshdl)) - { - unsigned i, first = 1; - - for (i = 0; i < entries; ++i) - { - if (!first) - printf (","); - first = 0; - printf ("%ls", buf1[i].grui0_name); - } - NetApiBufferFree (buf1); - } -} - -void -enum_groups (LPWSTR servername, int print_sids, int print_users, int id_offset, - char *disp_groupname) +enum_groups (BOOL domain, domlist_t *dom_or_machine, const char *sep, + int id_offset, char *disp_groupname) { + WCHAR machine[INTERNET_MAX_HOST_NAME_LENGTH + 1]; + PWCHAR servername = NULL; + char *d_or_m = dom_or_machine ? dom_or_machine->str : NULL; + BOOL with_dom = dom_or_machine ? dom_or_machine->with_dom : FALSE; GROUP_INFO_2 *buffer; DWORD entriesread = 0; DWORD totalentries = 0; DWORD resume_handle = 0; - WCHAR uni_name[GNLEN + 1]; + WCHAR gname[GNLEN + 1]; DWORD rc; + if (domain) + { + servername = get_dcname (d_or_m); + if (servername == (PWCHAR) -1) + return; + } + else if (d_or_m) + { + int ret = mbstowcs (machine, d_or_m, INTERNET_MAX_HOST_NAME_LENGTH + 1); + if (ret < 1 || ret >= INTERNET_MAX_HOST_NAME_LENGTH + 1) + { + fprintf (stderr, "%s: Invalid machine name '%s'. Skipping...\n", + __progname, d_or_m); + return; + } + servername = machine; + } + do { DWORD i; if (disp_groupname != NULL) { - mbstowcs (uni_name, disp_groupname, GNLEN + 1); - rc = NetGroupGetInfo (servername, (LPWSTR) & uni_name, 2, + mbstowcs (gname, disp_groupname, GNLEN + 1); + rc = NetGroupGetInfo (servername, (LPWSTR) & gname, 2, (void *) &buffer); entriesread=1; } @@ -303,16 +344,16 @@ enum_groups (LPWSTR servername, int print_sids, int print_users, int id_offset, switch (rc) { case ERROR_ACCESS_DENIED: - print_win_error(rc); - exit (1); + print_win_error (rc); + return; case ERROR_MORE_DATA: case ERROR_SUCCESS: break; default: - print_win_error(rc); - exit (1); + print_win_error (rc); + return; } for (i = 0; i < entriesread; i++) @@ -325,43 +366,40 @@ enum_groups (LPWSTR servername, int print_sids, int print_users, int id_offset, SID_NAME_USE acc_type; int gid = buffer[i].grpi2_group_id; - if (print_sids) - { - if (!LookupAccountNameW (servername, buffer[i].grpi2_name, - psid, &sid_length, - domain_name, &domname_len, - &acc_type)) - { - print_win_error(rc); - fprintf(stderr, " (%ls)\n", buffer[i].grpi2_name); - continue; - } - else if (acc_type == SidTypeDomain) - { - WCHAR domname[MAX_DOMAIN_NAME_LEN + GNLEN + 2]; - - wcscpy (domname, domain_name); - wcscat (domname, L"\\"); - wcscat (domname, buffer[i].grpi2_name); - sid_length = MAX_SID_LEN; - domname_len = MAX_DOMAIN_NAME_LEN + 1; - if (!LookupAccountNameW (servername, domname, - psid, &sid_length, - domain_name, &domname_len, - &acc_type)) - { - print_win_error(rc); - fprintf(stderr, " (%ls)\n", domname); - continue; - } - } - } - printf ("%ls:%s:%u:", buffer[i].grpi2_name, - print_sids ? put_sid (psid) : "", - gid + id_offset); - if (print_users) - enum_users (servername, buffer[i].grpi2_name); - printf ("\n"); + if (!LookupAccountNameW (servername, buffer[i].grpi2_name, + psid, &sid_length, + domain_name, &domname_len, + &acc_type)) + { + print_win_error (rc); + fprintf(stderr, " (%ls)\n", buffer[i].grpi2_name); + continue; + } + else if (acc_type == SidTypeDomain) + { + WCHAR domname[MAX_DOMAIN_NAME_LEN + GNLEN + 2]; + + wcscpy (domname, domain_name); + wcscat (domname, L"\\"); + wcscat (domname, buffer[i].grpi2_name); + sid_length = MAX_SID_LEN; + domname_len = MAX_DOMAIN_NAME_LEN + 1; + if (!LookupAccountNameW (servername, domname, + psid, &sid_length, + domain_name, &domname_len, + &acc_type)) + { + print_win_error (rc); + fprintf(stderr, " (%ls)\n", domname); + continue; + } + } + printf ("%ls%s%ls:%s:%u:\n", + with_dom ? domain_name : L"", + with_dom ? sep : "", + buffer[i].grpi2_name, + put_sid (psid), + gid + id_offset); } NetApiBufferFree (buffer); @@ -371,8 +409,7 @@ enum_groups (LPWSTR servername, int print_sids, int print_users, int id_offset, } void -print_special (int print_sids, - PSID_IDENTIFIER_AUTHORITY auth, BYTE cnt, +print_special (PSID_IDENTIFIER_AUTHORITY auth, BYTE cnt, DWORD sub1, DWORD sub2, DWORD sub3, DWORD sub4, DWORD sub5, DWORD sub6, DWORD sub7, DWORD sub8) { @@ -405,97 +442,96 @@ print_special (int print_sids, rid = sub2; else rid = sub1; - printf ("%s:%s:%lu:\n", name, - print_sids ? put_sid (sid) : "", - rid); + printf ("%s:%s:%lu:\n", name, put_sid (sid), rid); } FreeSid (sid); } } void -current_group (int print_sids, int print_users, int id_offset) +current_group (const char *sep, int id_offset) { - char name[UNLEN + 1], *envname, *envdomain; DWORD len; HANDLE ptok; - int errpos = 0; struct { PSID psid; char buffer[MAX_SID_LEN]; } tg; - - - if ((!GetUserName (name, (len = sizeof (name), &len)) && (errpos = __LINE__)) - || !name[0] - || !(envname = getenv("USERNAME")) - || strcasecmp (envname, name) - || (!GetComputerName (name, (len = sizeof (name), &len)) - && (errpos = __LINE__)) - || !(envdomain = getenv("USERDOMAIN")) - || !envdomain[0] - || !strcasecmp (envdomain, name) - || (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &ptok) - && (errpos = __LINE__)) - || (!GetTokenInformation (ptok, TokenPrimaryGroup, &tg, sizeof tg, &len) - && (errpos = __LINE__)) - || (!CloseHandle (ptok) && (errpos = __LINE__))) + char grp[GNLEN + 1]; + char dom[MAX_DOMAIN_NAME_LEN + 1]; + DWORD glen = GNLEN + 1; + DWORD dlen = MAX_DOMAIN_NAME_LEN + 1; + int gid; + SID_NAME_USE acc_type; + + if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &ptok) + || !GetTokenInformation (ptok, TokenPrimaryGroup, &tg, sizeof tg, &len) + || !CloseHandle (ptok) + || !LookupAccountSidA (NULL, tg.psid, grp, &glen, dom, &dlen, &acc_type)) { - if (errpos) - { - print_win_error (GetLastError ()); - } + print_win_error (GetLastError ()); return; } - - int gid = *GetSidSubAuthority (tg.psid, *GetSidSubAuthorityCount(tg.psid) - 1); - - printf ("mkgroup_l_d:%s:%u:", print_sids ? put_sid (tg.psid) : "", - gid + id_offset); - if (print_users) - printf("%s", envname); - printf ("\n"); + gid = *GetSidSubAuthority (tg.psid, *GetSidSubAuthorityCount(tg.psid) - 1); + printf ("%s%s%s:%s:%u:\n", + sep ? dom : "", + sep ?: "", + grp, + put_sid (tg.psid), + gid + id_offset); } int -usage (FILE * stream, int isNT) +usage (FILE * stream) { - fprintf (stream, "Usage: mkgroup [OPTION]... [domain]...\n" - "Print /etc/group file to stdout\n\n" - "Options:\n"); - if (isNT) - fprintf (stream, " -l,--local print machine local group information\n" - " -c,--current print current group, if a domain account\n" - " -d,--domain print domain group information (from current\n" - " domain if no domains specified)\n" - " -o,--id-offset offset change the default offset (10000) added to gids\n" - " in domain accounts.\n" - " -s,--no-sids don't print SIDs in pwd field\n" - " (this affects ntsec)\n" - " -u,--users print user list in gr_mem field\n" - " -g,--group groupname only return information for the specified group\n"); - fprintf (stream, " -h,--help print this message\n" - " -v,--version print version information and exit\n\n"); - if (isNT) - fprintf (stream, "One of '-l' or '-d' must be given.\n"); - + fprintf (stream, +"Usage: mkgroup [OPTION]...\n" +"Print /etc/group file to stdout\n" +"\n" +"Options:\n" +" -l,--local [machine] print local groups (from local machine if no\n" +" machine specified)\n" +" -L,--Local [machine] ditto, but generate groupname with machine prefix\n" +" -d,--domain [domain] print domain groups (from current domain if no\n" +" domain specified)\n" +" -D,--Domain [domain] ditto, but generate groupname with machine prefix\n" +" -c,--current print current group\n" +" -C,--Current ditto, but generate groupname with machine or\n" +" domain prefix\n" +" -S,--separator char for -L, -D, -C use character char as domain\\group\n" +" separator in groupname instead of the default '\\'\n" +" -o,--id-offset offset change the default offset (10000) added to gids\n" +" in domain or foreign server accounts.\n" +" -g,--group groupname only return information for the specified group\n" +" one of -l, -L, -d, -D must be specified, too\n" +" -s,--no-sids (ignored)\n" +" -u,--users (ignored)\n" +" -h,--help print this message\n" +" -v,--version print version information and exit\n" +"\n" +"Default is to print local groups on stand-alone machines, plus domain\n" +"groups on domain controllers and domain member machines.\n"); return 1; } struct option longopts[] = { - {"local", no_argument, NULL, 'l'}, {"current", no_argument, NULL, 'c'}, - {"domain", no_argument, NULL, 'd'}, + {"Current", no_argument, NULL, 'C'}, + {"domain", optional_argument, NULL, 'd'}, + {"Domain", optional_argument, NULL, 'D'}, + {"group", required_argument, NULL, 'g'}, + {"help", no_argument, NULL, 'h'}, + {"local", optional_argument, NULL, 'l'}, + {"Local", optional_argument, NULL, 'L'}, {"id-offset", required_argument, NULL, 'o'}, {"no-sids", no_argument, NULL, 's'}, + {"separator", required_argument, NULL, 'S'}, {"users", no_argument, NULL, 'u'}, - {"group", required_argument, NULL, 'g'}, - {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'v'}, {0, no_argument, NULL, 0} }; -char opts[] = "lcdo:sug:hv"; +char opts[] = "cCd::D::g:hl::L::o:sS:uv"; void print_version () @@ -520,219 +556,188 @@ Compiled on %s\n\ ", len, v, __DATE__); } +static PPOLICY_PRIMARY_DOMAIN_INFO p_dom; + +static BOOL +fetch_primary_domain () +{ + NTSTATUS status; + LSA_OBJECT_ATTRIBUTES oa = { 0, 0, 0, 0, 0, 0 }; + LSA_HANDLE lsa; + + if (!p_dom) + { + status = LsaOpenPolicy (NULL, &oa, POLICY_EXECUTE, &lsa); + if (!NT_SUCCESS (status)) + return FALSE; + status = LsaQueryInformationPolicy (lsa, PolicyPrimaryDomainInformation, + (PVOID *) &p_dom); + LsaClose (lsa); + if (!NT_SUCCESS (status)) + return FALSE; + } + return !!p_dom->Sid; +} + int main (int argc, char **argv) { - LPWSTR servername; - DWORD rc = ERROR_SUCCESS; - WCHAR domain_name[MAX_DOMAIN_NAME_LEN + 1]; int print_local = 0; - int print_current = 0; + domlist_t locals[16]; int print_domain = 0; - int print_sids = 1; - int print_users = 0; - int domain_specified = 0; + domlist_t domains[16]; + char *opt; + int print_current = 0; + const char *sep_char = "\\"; int id_offset = 10000; + int c, i, off; char *disp_groupname = NULL; int isRoot = 0; - int isNT; - int i; - - char dom[MAX_DOMAIN_NAME_LEN + 1]; - DWORD len, len2; - PSID psid = NULL; - SID_NAME_USE use; - - LSA_OBJECT_ATTRIBUTES oa = { 0, 0, 0, 0, 0, 0 }; - LSA_HANDLE lsa = INVALID_HANDLE_VALUE; - NTSTATUS ret; - PPOLICY_PRIMARY_DOMAIN_INFO pdi; + BOOL in_domain; - isNT = (GetVersion () < 0x80000000); + if (!isatty (1)) + setmode (1, O_BINARY); - if (isNT && argc == 1) - return usage(stderr, isNT); - else + load_dsgetdcname (); + in_domain = fetch_primary_domain (); + if (argc == 1) { - while ((i = getopt_long (argc, argv, opts, longopts, NULL)) != EOF) - switch (i) + print_special (&sid_nt_auth, 1, SECURITY_LOCAL_SYSTEM_RID, + 0, 0, 0, 0, 0, 0, 0); + if (in_domain) { - case 'l': - print_local = 1; - break; - case 'c': - print_current = 1; - break; - case 'd': - print_domain = 1; - break; - case 'o': - id_offset = strtol (optarg, NULL, 10); - break; - case 's': - print_sids = 0; - break; - case 'u': - print_users = 1; - break; - case 'g': - disp_groupname = optarg; - isRoot = !strcmp(disp_groupname, "root"); - break; - case 'h': - usage (stdout, isNT); - return 0; - case 'v': - print_version (); - return 0; - default: - fprintf (stderr, "Try '%s --help' for more information.\n", argv[0]); - return 1; + if (!enum_local_groups (TRUE, NULL, sep_char, id_offset, + disp_groupname)) + enum_groups (TRUE, NULL, sep_char, id_offset, disp_groupname); } - } - - /* This takes Windows 9x/ME into account. */ - if (!isNT) - { - printf ("all::%ld:\n", DOMAIN_ALIAS_RID_ADMINS); + else if (!enum_local_groups (FALSE, NULL, sep_char, 0, disp_groupname)) + enum_groups (FALSE, NULL, sep_char, 0, disp_groupname); return 0; } - if (!print_local && !print_domain) - { - fprintf (stderr, "%s: Specify one of '-l' or '-d'\n", argv[0]); - return 1; - } - if (optind < argc) - { - if (!print_domain) - { - fprintf (stderr, "%s: A domain name is only accepted " - "when '-d' is given.\n", argv[0]); - return 1; - } - domain_specified = 1; - } - load_netapi (); + while ((c = getopt_long (argc, argv, opts, longopts, NULL)) != EOF) + switch (c) + { + case 'l': + case 'L': + if (print_local >= 16) + { + fprintf (stderr, "%s: Can not enumerate from more than 16 " + "servers.\n", __progname); + return 1; + } + opt = optarg ?: + argv[optind] && argv[optind][0] != '-' ? argv[optind] : NULL; + for (i = 0; i < print_local; ++i) + if ((!locals[i].str && !opt) + || (locals[i].str && opt && !strcmp (locals[i].str, opt))) + goto skip_local; + locals[print_local].str = opt; + locals[print_local++].with_dom = c == 'L'; + skip_local: + break; + case 'd': + case 'D': + if (print_domain >= 16) + { + fprintf (stderr, "%s: Can not enumerate from more than 16 " + "domains.\n", __progname); + return 1; + } + opt = optarg ?: + argv[optind] && argv[optind][0] != '-' ? argv[optind] : NULL; + for (i = 0; i < print_domain; ++i) + if ((!domains[i].str && !opt) + || (domains[i].str && opt && !strcmp (domains[i].str, opt))) + goto skip_domain; + domains[print_domain].str = opt; + domains[print_domain++].with_dom = c == 'D'; + skip_domain: + break; + case 'S': + sep_char = optarg; + if (strlen (sep_char) > 1) + { + fprintf (stderr, "%s: Only one character allowed as domain\\user " + "separator character.\n", __progname); + return 1; + } + if (*sep_char == ':') + { + fprintf (stderr, "%s: Colon not allowed as domain\\user separator " + "character.\n", __progname); + return 1; + } + break; + case 'c': + sep_char = NULL; + /*FALLTHRU*/ + case 'C': + print_current = 1; + break; + case 'o': + id_offset = strtol (optarg, NULL, 10); + break; + case 's': + break; + case 'u': + break; + case 'g': + disp_groupname = optarg; + isRoot = !strcmp(disp_groupname, "root"); + break; + case 'h': + usage (stdout); + return 0; + case 'v': + print_version (); + return 0; + default: + fprintf (stderr, "Try '%s --help' for more information.\n", argv[0]); + return 1; + } - if (print_local) - { - char machine[INTERNET_MAX_HOST_NAME_LENGTH + 1]; - char sid[MAX_SID_LEN]; - - if (isRoot) - { - /* - * Very special feature for the oncoming future: - * Create a "root" group account, being actually the local - * Administrators group. Since user name, sid and gid are - * fixed, there's no need to call print_special() for this. - */ - printf ("root:S-1-5-32-544:0:\n"); - } + if (optind < argc - 1) + usage (stdout); - if (disp_groupname == NULL) - { - /* - * Get 'system' group - */ - print_special (print_sids, &sid_nt_auth, 1, SECURITY_LOCAL_SYSTEM_RID, - 0, 0, 0, 0, 0, 0, 0); - /* - * Get 'None' group - */ - len = INTERNET_MAX_HOST_NAME_LENGTH + 1; - GetComputerName (machine, &len); - len = MAX_SID_LEN; - len2 = MAX_DOMAIN_NAME_LEN + 1; - if (LookupAccountName (NULL, machine, (PSID) sid, &len, dom, &len2, &use)) - psid = (PSID) sid; - else - { - ret = LsaOpenPolicy (NULL, &oa, POLICY_VIEW_LOCAL_INFORMATION, &lsa); - if (ret == STATUS_SUCCESS && lsa != INVALID_HANDLE_VALUE) - { - ret = LsaQueryInformationPolicy (lsa, - PolicyPrimaryDomainInformation, - (void *) &pdi); - if (ret == STATUS_SUCCESS) - { - if (pdi->Sid) - { - CopySid (MAX_SID_LEN, (PSID) sid, pdi->Sid); - psid = (PSID) sid; - } - LsaFreeMemory (pdi); - } - LsaClose (lsa); - } - } - if (!psid) - fprintf (stderr, - "WARNING: Machine local group 513 couldn't get retrieved. Try mkgroup -d\n"); - else - print_special (print_sids, GetSidIdentifierAuthority (psid), 5, - *GetSidSubAuthority (psid, 0), - *GetSidSubAuthority (psid, 1), - *GetSidSubAuthority (psid, 2), - *GetSidSubAuthority (psid, 3), - 513, - 0, - 0, - 0); - } + /* Get 'system' group */ + if (!disp_groupname && (print_local > 0 || print_domain > 0)) + print_special (&sid_nt_auth, 1, SECURITY_LOCAL_SYSTEM_RID, + 0, 0, 0, 0, 0, 0, 0); - if (!isRoot) - enum_local_groups (NULL, print_sids, print_users, 0, disp_groupname); + off = 1; + if (isRoot) + { + /* Very special feature for the oncoming future: + Create a "root" group being actually the local Administrators group. + Printing root disables printing any other "real" local group. */ + printf ("root:S-1-5-32-544:0:\n"); } - i = 1; - if (print_domain) - do + else + for (i = 0; i < print_local; ++i) { - PDOMAIN_CONTROLLER_INFOW pdci = NULL; - - if (dsgetdcname) + if (locals[i].str) { - if (domain_specified) - { - mbstowcs (domain_name, argv[optind], strlen (argv[optind]) + 1); - rc = dsgetdcname (NULL, domain_name, NULL, NULL, 0, &pdci); - } - else - rc = dsgetdcname (NULL, NULL, NULL, NULL, 0, &pdci); - if (rc != ERROR_SUCCESS) - { - print_win_error(rc); - return 1; - } - servername = pdci->DomainControllerName; - } - else - { - rc = NetGetDCName (NULL, NULL, (void *) &servername); - if (rc == ERROR_SUCCESS && domain_specified) - { - LPWSTR server = servername; - mbstowcs (domain_name, argv[optind], strlen (argv[optind]) + 1); - rc = NetGetDCName (NULL, domain_name, (void *) &servername); - NetApiBufferFree (server); - } - if (rc != ERROR_SUCCESS) - { - print_win_error(rc); - return 1; - } - } - enum_groups (servername, print_sids, print_users, id_offset * i, - disp_groupname); - enum_local_groups (servername, print_sids, print_users, id_offset * i++, + if (!enum_local_groups (FALSE, locals + i, sep_char, + id_offset * off, disp_groupname)) + enum_groups (FALSE, locals + i, sep_char, id_offset * off++, disp_groupname); - NetApiBufferFree (pdci ? (PVOID) pdci : (PVOID) servername); + } + else if (!enum_local_groups (FALSE, locals + i, sep_char, 0, + disp_groupname)) + enum_groups (FALSE, locals + i, sep_char, 0, disp_groupname); } - while (++optind < argc); - if (print_current && !print_domain) - current_group (print_sids, print_users, id_offset); + for (i = 0; i < print_domain; ++i) + { + if (!enum_local_groups (TRUE, domains + i, sep_char, id_offset * off, + disp_groupname)) + enum_groups (TRUE, domains + i, sep_char, id_offset * off++, + disp_groupname); + } + + if (print_current) + current_group (sep_char, id_offset); return 0; } -- cgit v1.2.3