From: Corinna Vinschen Date: Mon, 24 Feb 2014 10:51:42 +0000 (+0000) Subject: * mkgroup.c (domlist_t): Drop id_offset. X-Git-Tag: sid-snapshot-20140501~76 X-Git-Url: https://sourceware.org/git/?a=commitdiff_plain;h=16a976cff4ea5b905badbd39f921052a7b88d8c0;p=newlib-cygwin.git * mkgroup.c (domlist_t): Drop id_offset. (get_dcname): Remove. (current_group): Remove. (enum_unix_groups): Simplify. Change space to underscore in domain name. (enum_local_groups): Simplify to accommodate the fact that it's only called for foreign machines. (enum_groups): Ditto. (print_special_by_sid): Remove. (print_special_by_name): Remove. (usage): Align to new code. (fetch_primary_domain): Remove. (main): Use cygwin_internal CW_SETENT, CW_GETENT and CW_ENDENT method. Call enum_local_groups, enum_groups, and enum_unix_groups only for foreign machines. * mkpasswd.c (get_dcname): Remove. (current_user): Remove. (enum_unix_users): Simplify. Change space to underscore in domain name. (enum_users): Simplify to accommodate the fact that it's only called for foreign machines. (print_special_by_sid): Remove. (usage): Align to new code. (longopts): Add -b/--no-builtin option. (opts): Add -b option. (print_special_by_name): Remove. (enum_std_accounts): Remove. (fetch_primary_domain): Remove. (main): Use cygwin_internal CW_SETENT, CW_GETENT and CW_ENDENT method. Call enum_users and enum_unix_users only for foreign machines. * utils.xml (mkgroup): Align documentation to new usage. (mkpasswd): Ditto. --- diff --git a/winsup/utils/ChangeLog b/winsup/utils/ChangeLog index 63b5e953e..842814969 100644 --- a/winsup/utils/ChangeLog +++ b/winsup/utils/ChangeLog @@ -1,3 +1,37 @@ +2013-11-24 Corinna Vinschen + + * mkgroup.c (domlist_t): Drop id_offset. + (get_dcname): Remove. + (current_group): Remove. + (enum_unix_groups): Simplify. Change space to underscore in domain + name. + (enum_local_groups): Simplify to accommodate the fact that it's only + called for foreign machines. + (enum_groups): Ditto. + (print_special_by_sid): Remove. + (print_special_by_name): Remove. + (usage): Align to new code. + (fetch_primary_domain): Remove. + (main): Use cygwin_internal CW_SETENT, CW_GETENT and CW_ENDENT method. + Call enum_local_groups, enum_groups, and enum_unix_groups only for + foreign machines. + * mkpasswd.c (get_dcname): Remove. + (current_user): Remove. + (enum_unix_users): Simplify. Change space to underscore in domain name. + (enum_users): Simplify to accommodate the fact that it's only + called for foreign machines. + (print_special_by_sid): Remove. + (usage): Align to new code. + (longopts): Add -b/--no-builtin option. + (opts): Add -b option. + (print_special_by_name): Remove. + (enum_std_accounts): Remove. + (fetch_primary_domain): Remove. + (main): Use cygwin_internal CW_SETENT, CW_GETENT and CW_ENDENT method. + Call enum_users and enum_unix_users only for foreign machines. + * utils.xml (mkgroup): Align documentation to new usage. + (mkpasswd): Ditto. + 2014-02-23 Jon TURNEY * minidumper.cc (minidump): Fix -t option argument handling. diff --git a/winsup/utils/mkgroup.c b/winsup/utils/mkgroup.c index 05f5910b0..7b102ec99 100644 --- a/winsup/utils/mkgroup.c +++ b/winsup/utils/mkgroup.c @@ -1,7 +1,7 @@ /* mkgroup.c: Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, - 2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc. + 2008, 2009, 2010, 2011, 2012, 2013, 2014 Red Hat, Inc. This file is part of Cygwin. @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -29,9 +30,7 @@ #include #include #include -#include #include -#include "loadlib.h" #define print_win_error(x) _print_win_error(x, __LINE__) @@ -47,7 +46,6 @@ SID_IDENTIFIER_AUTHORITY sid_nt_auth = {SECURITY_NT_AUTHORITY}; typedef struct { char *str; - DWORD id_offset; BOOL domain; BOOL with_dom; } domlist_t; @@ -70,31 +68,6 @@ _print_win_error (DWORD code, int line) line, (unsigned int) code); } -static PWCHAR -get_dcname (char *domain) -{ - static WCHAR server[INTERNET_MAX_HOST_NAME_LENGTH + 1]; - DWORD rc; - WCHAR domain_name[MAX_DOMAIN_NAME_LEN + 1]; - PDOMAIN_CONTROLLER_INFOW pdci = NULL; - - if (domain) - { - mbstowcs (domain_name, domain, strlen (domain) + 1); - rc = DsGetDcNameW (NULL, domain_name, NULL, NULL, 0, &pdci); - } - else - rc = DsGetDcNameW (NULL, NULL, NULL, NULL, 0, &pdci); - if (rc != ERROR_SUCCESS) - { - print_win_error (rc); - return (PWCHAR) -1; - } - wcscpy (server, pdci->DomainControllerName); - NetApiBufferFree (pdci); - return server; -} - static char * put_sid (PSID psid) { @@ -149,40 +122,10 @@ fetch_current_pgrp_sid () } static void -current_group (const char *sep, DWORD id_offset) -{ - WCHAR grp[GNLEN + 1]; - WCHAR 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 (!curr_pgrp.psid - || !LookupAccountSidW (NULL, curr_pgrp.psid, grp, &glen, dom, &dlen, - &acc_type)) - { - print_win_error (GetLastError ()); - return; - } - gid = *GetSidSubAuthority (curr_pgrp.psid, - *GetSidSubAuthorityCount(curr_pgrp.psid) - 1); - printf ("%ls%s%ls:%s:%" PRIu32 ":\n", - sep ? dom : L"", - sep ?: "", - grp, - put_sid (curr_pgrp.psid), - (unsigned int) (id_offset + gid)); -} - -static void -enum_unix_groups (domlist_t *dom_or_machine, const char *sep, DWORD id_offset, +enum_unix_groups (domlist_t *mach, const char *sep, DWORD id_offset, char *unix_grp_list) { 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; SID_IDENTIFIER_AUTHORITY auth = { { 0, 0, 0, 0, 0, 22 } }; char *gstr, *grp_list; WCHAR grp[GNLEN + sizeof ("Unix Group\\") + 1]; @@ -192,17 +135,13 @@ enum_unix_groups (domlist_t *dom_or_machine, const char *sep, DWORD id_offset, char psid_buffer[MAX_SID_LEN]; SID_NAME_USE acc_type; - if (!d_or_m) - return; - - int ret = mbstowcs (machine, d_or_m, INTERNET_MAX_HOST_NAME_LENGTH + 1); + int ret = mbstowcs (machine, mach->str, 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", - program_invocation_short_name, d_or_m); + program_invocation_short_name, mach->str); return; } - servername = machine; if (!AllocateAndInitializeSid (&auth, 2, 2, 0, 0, 0, 0, 0, 0, 0, &psid)) return; @@ -222,15 +161,15 @@ enum_unix_groups (domlist_t *dom_or_machine, const char *sep, DWORD id_offset, if (ret < 1 || ret >= GNLEN + 1) fprintf (stderr, "%s: Invalid group name '%s'. Skipping...\n", program_invocation_short_name, gstr); - else if (LookupAccountNameW (servername, grp, + else if (LookupAccountNameW (machine, grp, psid = (PSID) psid_buffer, (sidlen = MAX_SID_LEN, &sidlen), dom, (dlen = MAX_DOMAIN_NAME_LEN + 1, &dlen), &acc_type)) printf ("%s%s%ls:%s:%" PRIu32 ":\n", - with_dom ? "Unix Group" : "", - with_dom ? sep : "", + mach->with_dom ? "Unix_Group" : "", + mach->with_dom ? sep : "", p, put_sid (psid), (unsigned int) (id_offset + @@ -259,15 +198,15 @@ enum_unix_groups (domlist_t *dom_or_machine, const char *sep, DWORD id_offset, { *GetSidSubAuthority (psid, *GetSidSubAuthorityCount(psid) - 1) = start; - if (LookupAccountSidW (servername, psid, + if (LookupAccountSidW (machine, psid, grp, (glen = GNLEN + 1, &glen), dom, (dlen = MAX_DOMAIN_NAME_LEN + 1, &dlen), &acc_type) && !iswdigit (grp[0])) printf ("%s%s%ls:%s:%" PRIu32 ":\n", - with_dom ? "Unix Group" : "", - with_dom ? sep : "", + mach->with_dom ? "Unix_Group" : "", + mach->with_dom ? sep : "", grp, put_sid (psid), (unsigned int) (id_offset + start)); @@ -280,14 +219,11 @@ enum_unix_groups (domlist_t *dom_or_machine, const char *sep, DWORD id_offset, } static int -enum_local_groups (BOOL domain, domlist_t *dom_or_machine, const char *sep, +enum_local_groups (domlist_t *mach, const char *sep, DWORD id_offset, char *disp_groupname, int print_builtin, int print_current) { 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; @@ -295,22 +231,12 @@ enum_local_groups (BOOL domain, domlist_t *dom_or_machine, const char *sep, 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, mach->str, INTERNET_MAX_HOST_NAME_LENGTH + 1); + if (ret < 1 || ret >= INTERNET_MAX_HOST_NAME_LENGTH + 1) { - 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", - program_invocation_short_name, d_or_m); - return 1; - } - servername = machine; + fprintf (stderr, "%s: Invalid machine name '%s'. Skipping...\n", + program_invocation_short_name, mach->str); + return 1; } do @@ -320,7 +246,7 @@ enum_local_groups (BOOL domain, domlist_t *dom_or_machine, const char *sep, if (disp_groupname) { mbstowcs (gname, disp_groupname, GNLEN + 1); - rc = NetLocalGroupGetInfo (servername, gname, 0, (void *) &buffer); + rc = NetLocalGroupGetInfo (machine, gname, 0, (void *) &buffer); if (rc == ERROR_SUCCESS) entriesread = 1; /* Allow further searching for the group and avoid annoying @@ -330,7 +256,7 @@ enum_local_groups (BOOL domain, domlist_t *dom_or_machine, const char *sep, return 0; } else - rc = NetLocalGroupEnum (servername, 0, (void *) &buffer, + rc = NetLocalGroupEnum (machine, 0, (void *) &buffer, MAX_PREFERRED_LENGTH, &entriesread, &totalentries, &resume_handle); switch (rc) @@ -360,7 +286,7 @@ enum_local_groups (BOOL domain, domlist_t *dom_or_machine, const char *sep, PDBGSID pdsid; BOOL is_builtin = FALSE; - if (!LookupAccountNameW (servername, buffer[i].lgrpi0_name, psid, + if (!LookupAccountNameW (machine, buffer[i].lgrpi0_name, psid, &sid_length, domain_name, &domname_len, &acc_type)) { @@ -377,7 +303,7 @@ enum_local_groups (BOOL domain, domlist_t *dom_or_machine, const char *sep, wcscat (domname, buffer[i].lgrpi0_name); sid_length = MAX_SID_LEN; domname_len = MAX_DOMAIN_NAME_LEN + 1; - if (!LookupAccountNameW (servername, domname, + if (!LookupAccountNameW (machine, domname, psid, &sid_length, domain_name, &domname_len, &acc_type)) @@ -415,8 +341,8 @@ enum_local_groups (BOOL domain, domlist_t *dom_or_machine, const char *sep, gid = *GetSidSubAuthority (psid, *GetSidSubAuthorityCount(psid) - 1); printf ("%ls%s%ls:%s:%" PRIu32 ":\n", - with_dom && !is_builtin ? domain_name : L"", - with_dom && !is_builtin ? sep : "", + mach->with_dom && !is_builtin ? domain_name : L"", + mach->with_dom || is_builtin ? sep : "", buffer[i].lgrpi0_name, put_sid (psid), (unsigned int) (gid + (is_builtin ? 0 : id_offset))); @@ -436,13 +362,10 @@ skip_group: } static void -enum_groups (BOOL domain, domlist_t *dom_or_machine, const char *sep, - DWORD id_offset, char *disp_groupname, int print_current) +enum_groups (domlist_t *mach, const char *sep, DWORD id_offset, + char *disp_groupname, int print_current) { 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; @@ -450,22 +373,12 @@ enum_groups (BOOL domain, domlist_t *dom_or_machine, const char *sep, 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, mach->str, INTERNET_MAX_HOST_NAME_LENGTH + 1); + if (ret < 1 || ret >= INTERNET_MAX_HOST_NAME_LENGTH + 1) { - 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", - program_invocation_short_name, d_or_m); - return; - } - servername = machine; + fprintf (stderr, "%s: Invalid machine name '%s'. Skipping...\n", + program_invocation_short_name, mach->str); + return; } do @@ -475,8 +388,7 @@ enum_groups (BOOL domain, domlist_t *dom_or_machine, const char *sep, if (disp_groupname != NULL) { mbstowcs (gname, disp_groupname, GNLEN + 1); - rc = NetGroupGetInfo (servername, (LPWSTR) & gname, 2, - (void *) &buffer); + rc = NetGroupGetInfo (machine, (LPWSTR) & gname, 2, (void *) &buffer); entriesread=1; /* Avoid annoying error messages just because the group hasn't been found. */ @@ -484,9 +396,8 @@ enum_groups (BOOL domain, domlist_t *dom_or_machine, const char *sep, return; } else - rc = NetGroupEnum (servername, 2, (void *) & buffer, - MAX_PREFERRED_LENGTH, &entriesread, &totalentries, - &resume_handle); + rc = NetGroupEnum (machine, 2, (void *) & buffer, MAX_PREFERRED_LENGTH, + &entriesread, &totalentries, &resume_handle); switch (rc) { case ERROR_ACCESS_DENIED: @@ -512,7 +423,7 @@ enum_groups (BOOL domain, domlist_t *dom_or_machine, const char *sep, SID_NAME_USE acc_type; int gid = buffer[i].grpi2_group_id; - if (!LookupAccountNameW (servername, buffer[i].grpi2_name, + if (!LookupAccountNameW (machine, buffer[i].grpi2_name, psid, &sid_length, domain_name, &domname_len, &acc_type)) @@ -525,16 +436,13 @@ enum_groups (BOOL domain, domlist_t *dom_or_machine, const char *sep, { WCHAR domname[MAX_DOMAIN_NAME_LEN + GNLEN + 2]; - wcscpy (domname, domain || !servername - ? domain_name : servername); + wcscpy (domname, machine); 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)) + if (!LookupAccountNameW (machine, domname, psid, &sid_length, + domain_name, &domname_len, &acc_type)) { print_win_error (GetLastError ()); fprintf(stderr, " (%ls)\n", domname); @@ -547,8 +455,8 @@ enum_groups (BOOL domain, domlist_t *dom_or_machine, const char *sep, got_curr_pgrp = TRUE; printf ("%ls%s%ls:%s:%" PRIu32 ":\n", - with_dom ? domain_name : L"", - with_dom ? sep : "", + mach->with_dom ? domain_name : L"", + mach->with_dom ? sep : "", buffer[i].grpi2_name, put_sid (psid), (unsigned int) (id_offset + gid)); @@ -560,107 +468,42 @@ enum_groups (BOOL domain, domlist_t *dom_or_machine, const char *sep, while (rc == ERROR_MORE_DATA); } -static void -print_special_by_sid (PSID_IDENTIFIER_AUTHORITY auth, BYTE cnt, - DWORD sub1, DWORD sub2, DWORD sub3, DWORD sub4, - DWORD sub5, DWORD sub6, DWORD sub7, DWORD sub8) -{ - WCHAR grp[GNLEN + 1], dom[MAX_DOMAIN_NAME_LEN + 1]; - DWORD glen, dlen, rid; - PSID psid; - SID_NAME_USE acc_type; - - if (AllocateAndInitializeSid (auth, cnt, sub1, sub2, sub3, sub4, - sub5, sub6, sub7, sub8, &psid)) - { - if (LookupAccountSidW (NULL, psid, - grp, (glen = GNLEN + 1, &glen), - dom, (dlen = MAX_DOMAIN_NAME_LEN + 1, &dlen), - &acc_type)) - { - if (sub8) - rid = sub8; - else if (sub7) - rid = sub7; - else if (sub6) - rid = sub6; - else if (sub5) - rid = sub5; - else if (sub4) - rid = sub4; - else if (sub3) - rid = sub3; - else if (sub2) - rid = sub2; - else - rid = sub1; - printf ("%ls:%s:%" PRIu32 ":\n", grp, put_sid (psid), - (unsigned int) rid); - } - FreeSid (psid); - } -} - -static void -print_special_by_name (PCWSTR name, gid_t gid) -{ - DWORD size = 256, dom_size = 256; - PSID sid = (PSID) alloca (size); - WCHAR dom[dom_size]; - SID_NAME_USE use; - - PWCHAR name_only = wcschr (name, L'\\'); - if (name_only) - ++name_only; - - if (LookupAccountNameW (NULL, name, sid, &size, dom, &dom_size, &use)) - printf ("%ls:%s:%lu:\n", - name_only ?: name, put_sid (sid), (unsigned long) gid); -} - static int usage (FILE * stream) { fprintf (stream, "Usage: %s [OPTION]...\n" "\n" -"Print /etc/group file to stdout\n" +"Write /etc/group-like output to stdout\n" "\n" "Options:\n" "\n" -" -l,--local [machine[,offset]]\n" -" print local groups with gid offset offset\n" +" -l,--local [machine] print local groups\n" " (from local machine if no machine specified)\n" -" -L,--Local [machine[,offset]]\n" -" ditto, but generate groupname with machine prefix\n" -" -d,--domain [domain[,offset]]\n" -" print domain groups with gid offset offset\n" +" -L,--Local machine ditto, but generate groupname with machine prefix\n" +" -d,--domain [domain] print domain groups\n" " (from current domain if no domain specified)\n" -" -D,--Domain [domain[,offset]]\n" -" 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" +" -S,--separator char for -l use character char as domain\\group\n" +" separator in groupname instead of default '%s'\n" +" -o,--id-offset offset change the default offset (0x10000) added to\n" +" gids of foreign machine accounts.\n" " -g,--group groupname only return information for the specified group\n" -" one of -l, -L, -d, -D must be specified, too\n" +" one of -l, -d must be specified, too\n" " -b,--no-builtin don't print BUILTIN groups\n" -" -U,--unix grouplist additionally print UNIX groups when using -l or -L\n" -" on a UNIX Samba server\n" -" grouplist is a comma-separated list of groupnames\n" -" or gid ranges (root,-25,50-100).\n" +" -U,--unix grouplist print UNIX groups when using -l on a UNIX Samba\n" +" server. grouplist is a comma-separated list of\n" +" groupnames or gid ranges (root,-25,50-100).\n" " (enumerating large ranges can take a long time!)\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" -"\n", program_invocation_short_name); +"groups on domain controllers and domain member machines.\n\n" +"Don't use this command to generate a local /etc/group file, unless you\n" +"really need one. See the Cygwin User's Guide for more information.\n" +"\n", program_invocation_short_name, + (const char *) cygwin_internal (CW_GETNSSSEP)); return 1; } @@ -699,44 +542,20 @@ print_version () strrchr (__DATE__, ' ') + 1); } -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 *) ((void *) &p_dom)); - LsaClose (lsa); - if (!NT_SUCCESS (status)) - return FALSE; - } - return !!p_dom->Sid; -} - int main (int argc, char **argv) { int print_domlist = 0; domlist_t domlist[32]; - char *opt, *p, *ep; + char *opt, *p; int print_current = 0; - int print_system = 0; int print_builtin = 1; char *print_unix = NULL; - const char *sep_char = "\\"; - DWORD id_offset = 10000, off; + const char *sep_char = (const char *) cygwin_internal (CW_GETNSSSEP); + DWORD id_offset = 0x10000, off; int c, i; char *disp_groupname = NULL; - BOOL in_domain; + //BOOL in_domain; int optional_args = 0; if (!isatty (1)) @@ -746,22 +565,21 @@ main (int argc, char **argv) setlocale (LC_CTYPE, ""); if (!strcmp (setlocale (LC_CTYPE, NULL), "C")) setlocale (LC_CTYPE, "en_US.UTF-8"); - in_domain = fetch_primary_domain (); fetch_current_pgrp_sid (); if (argc == 1) { - print_special_by_sid (&sid_nt_auth, 1, SECURITY_LOCAL_SYSTEM_RID, - 0, 0, 0, 0, 0, 0, 0); - if (in_domain) + int enums = ENUM_PRIMARY | ENUM_LOCAL | ENUM_BUILTIN; + uintptr_t ticket = cygwin_internal (CW_SETENT, TRUE, enums, NULL); + if (ticket) { - if (!enum_local_groups (TRUE, NULL, sep_char, id_offset, - disp_groupname, print_builtin, 0)) - enum_groups (TRUE, NULL, sep_char, id_offset, disp_groupname, 0); + struct group *grp; + + while ((grp = (struct group *) cygwin_internal (CW_GETENT, TRUE, + ticket))) + printf ("%s:%s:%u:\n", grp->gr_name, grp->gr_passwd, grp->gr_gid); + cygwin_internal (CW_ENDENT, TRUE, ticket); } - else if (!enum_local_groups (FALSE, NULL, sep_char, 0, disp_groupname, - print_builtin, 0)) - enum_groups (FALSE, NULL, sep_char, 0, disp_groupname, 0); return 0; } @@ -799,15 +617,10 @@ main (int argc, char **argv) domlist[i].str); goto skip; } - if (!(domlist[print_domlist].str = opt)) - print_system = 1; - domlist[print_domlist].id_offset = UINT32_MAX; + domlist[print_domlist].str = opt; if (opt && (p = strchr (opt, ','))) { - if (p == opt - || !isdigit ((unsigned char) p[1]) - || (domlist[print_domlist].id_offset = strtol (p + 1, &ep, 10) - , *ep)) + if (p == opt) { fprintf (stderr, "%s: Malformed machine,offset string '%s'. " "Skipping...\n", program_invocation_short_name, opt); @@ -815,15 +628,15 @@ main (int argc, char **argv) } *p = '\0'; } - domlist[print_domlist++].with_dom = (c == 'D' || c == 'L'); + domlist[print_domlist++].with_dom = (c == 'L'); skip: break; case 'S': sep_char = optarg; if (strlen (sep_char) > 1) { - fprintf (stderr, "%s: Only one character allowed as domain\\user " - "separator character.\n", + fprintf (stderr, "%s: Only one ASCII character allowed as " + "domain\\user separator character.\n", program_invocation_short_name); return 1; } @@ -838,8 +651,6 @@ skip: print_unix = optarg; break; case 'c': - sep_char = NULL; - /*FALLTHRU*/ case 'C': print_current = 1; break; @@ -876,34 +687,77 @@ skip: exit (1); } - /* Get 'system' group */ - if (!disp_groupname && print_system && print_builtin && print_domlist) + struct group *pgrp = NULL; + if (print_current) + pgrp = (struct group *) cygwin_internal (CW_GETGRSID, TRUE, curr_pgrp.psid); + + int enums = ENUM_NONE; + WCHAR tdoms[print_domlist * 258]; + PWCHAR t = tdoms; + if (!disp_groupname && print_builtin && print_domlist) + enums |= ENUM_BUILTIN; + for (i = 0; i < print_domlist; ++i) { - print_special_by_sid (&sid_nt_auth, 1, SECURITY_LOCAL_SYSTEM_RID, - 0, 0, 0, 0, 0, 0, 0); - print_special_by_name (L"NT SERVICE\\TrustedInstaller", -2); + if (domlist[i].domain) + { + if (domlist[i].str) + { + enums |= ENUM_TDOMS; + t += mbstowcs (t, domlist[i].str, 257); + *t++ = L'\0'; + } + else + enums |= ENUM_PRIMARY; + } + else if (!domlist[i].str) + enums |= ENUM_LOCAL; } + if (t > tdoms) + *t++ = L'\0'; + if (enums) + { + uintptr_t ticket = cygwin_internal (CW_SETENT, TRUE, enums, + t > tdoms ? tdoms : NULL); + if (ticket) + { + struct group *grp; + const char *nss_sep = (const char *) cygwin_internal (CW_GETNSSSEP); + + while ((grp = (struct group *) + cygwin_internal (CW_GETENT, TRUE, ticket))) + { + if (disp_groupname + && strcasecmp (disp_groupname, grp->gr_name) != 0 + && (!(p = strchr (grp->gr_name, nss_sep[0])) + || strcasecmp (disp_groupname, p + 1) != 0)) + continue; + printf ("%s:%s:%u:\n", grp->gr_name, grp->gr_passwd, + grp->gr_gid); + if (pgrp && !strcmp (grp->gr_passwd, pgrp->gr_passwd)) + got_curr_pgrp = TRUE; + } + cygwin_internal (CW_ENDENT, TRUE, ticket); + } + } + + if (print_current && !got_curr_pgrp) + printf ("%s:%s:%u:\n", pgrp->gr_name, pgrp->gr_passwd, pgrp->gr_gid); - off = id_offset; + off = 0xfd000000; for (i = 0; i < print_domlist; ++i) { - DWORD my_off = (domlist[i].domain || domlist[i].str) - ? domlist[i].id_offset != UINT_MAX - ? domlist[i].id_offset : off : 0; - if (!enum_local_groups (domlist[i].domain, domlist + i, sep_char, - my_off, disp_groupname, print_builtin, print_current)) + if (domlist[i].domain || !domlist[i].str) + continue; + if (!enum_local_groups (domlist + i, sep_char, off, disp_groupname, + print_builtin, print_current)) { + enum_groups (domlist + i, sep_char, off, disp_groupname, + print_current); if (!domlist[i].domain && domlist[i].str && print_unix) - enum_unix_groups (domlist + i, sep_char, my_off, print_unix); - enum_groups (domlist[i].domain, domlist + i, sep_char, my_off, - disp_groupname, print_current); - if (my_off) - off += id_offset; + enum_unix_groups (domlist + i, sep_char, 0xff000000, print_unix); + off += id_offset; } } - if (print_current && !got_curr_pgrp) - current_group (sep_char, off); - return 0; } diff --git a/winsup/utils/mkpasswd.c b/winsup/utils/mkpasswd.c index d080dbd70..a2c664ed1 100644 --- a/winsup/utils/mkpasswd.c +++ b/winsup/utils/mkpasswd.c @@ -1,7 +1,7 @@ /* mkpasswd.c: Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2008, 2009, - 2010, 2011, 2012, 2013 Red Hat, Inc. + 2010, 2011, 2012, 2013, 2014 Red Hat, Inc. This file is part of Cygwin. @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -31,7 +32,6 @@ #include #include #include -#include "loadlib.h" #define print_win_error(x) _print_win_error(x, __LINE__) @@ -47,7 +47,6 @@ SID_IDENTIFIER_AUTHORITY sid_nt_auth = {SECURITY_NT_AUTHORITY}; typedef struct { char *str; - DWORD id_offset; BOOL domain; BOOL with_dom; } domlist_t; @@ -70,31 +69,6 @@ _print_win_error(DWORD code, int line) line, (unsigned int) code); } -static PWCHAR -get_dcname (char *domain) -{ - static WCHAR server[INTERNET_MAX_HOST_NAME_LENGTH + 1]; - DWORD rc; - WCHAR domain_name[MAX_DOMAIN_NAME_LEN + 1]; - PDOMAIN_CONTROLLER_INFOW pdci = NULL; - - if (domain) - { - mbstowcs (domain_name, domain, strlen (domain) + 1); - rc = DsGetDcNameW (NULL, domain_name, NULL, NULL, 0, &pdci); - } - else - rc = DsGetDcNameW (NULL, NULL, NULL, NULL, 0, &pdci); - if (rc != ERROR_SUCCESS) - { - print_win_error (rc); - return (PWCHAR) -1; - } - wcscpy (server, pdci->DomainControllerName); - NetApiBufferFree (pdci); - return server; -} - static char * put_sid (PSID sid) { @@ -150,72 +124,10 @@ fetch_current_user_sid () } static void -current_user (const char *sep, const char *passed_home_path, DWORD id_offset, - const char *disp_username) -{ - WCHAR user[UNLEN + 1]; - WCHAR dom[MAX_DOMAIN_NAME_LEN + 1]; - DWORD ulen = UNLEN + 1; - DWORD dlen = MAX_DOMAIN_NAME_LEN + 1; - SID_NAME_USE acc_type; - int uid, gid; - char homedir_psx[PATH_MAX] = {0}; - - if (!curr_user.psid || !curr_pgrp.psid - || !LookupAccountSidW (NULL, curr_user.psid, user, &ulen, dom, &dlen, - &acc_type)) - { - print_win_error (GetLastError ()); - return; - } - - uid = *GetSidSubAuthority (curr_user.psid, - *GetSidSubAuthorityCount(curr_user.psid) - 1); - gid = *GetSidSubAuthority (curr_pgrp.psid, - *GetSidSubAuthorityCount(curr_pgrp.psid) - 1); - if (passed_home_path[0] == '\0') - { - char *envhome = getenv ("HOME"); - - /* If $HOME exists and is non-empty, just copy it over to homedir_psx. - Otherwise, generate a new path of the form "/home/$USER". */ - if (envhome && envhome[0] != '\0') - strncat (homedir_psx, envhome, sizeof (homedir_psx) - 1); - else - { - wcstombs (stpncpy (homedir_psx, "/home/", sizeof (homedir_psx)), - user, sizeof (homedir_psx) - 6); - homedir_psx[PATH_MAX - 1] = '\0'; - } - } - else - { - char *p = stpncpy (homedir_psx, passed_home_path, sizeof (homedir_psx)); - wcstombs (p, user, sizeof (homedir_psx) - (p - homedir_psx)); - homedir_psx[PATH_MAX - 1] = '\0'; - } - - printf ("%ls%s%ls:unused:%" PRIu32 ":%" PRIu32 - ":U-%ls\\%ls,%s:%s:/bin/bash\n", - sep ? dom : L"", - sep ?: "", - user, - (unsigned int) (id_offset + uid), - (unsigned int) (id_offset + gid), - dom, - user, - put_sid (curr_user.psid), - homedir_psx); -} - -static void -enum_unix_users (domlist_t *dom_or_machine, const char *sep, DWORD id_offset, +enum_unix_users (domlist_t *mach, const char *sep, DWORD id_offset, char *unix_user_list) { 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; SID_IDENTIFIER_AUTHORITY auth = { { 0, 0, 0, 0, 0, 22 } }; char *ustr, *user_list; WCHAR user[UNLEN + sizeof ("Unix User\\") + 1]; @@ -225,17 +137,13 @@ enum_unix_users (domlist_t *dom_or_machine, const char *sep, DWORD id_offset, char psid_buffer[MAX_SID_LEN]; SID_NAME_USE acc_type; - if (!d_or_m) - return; - - int ret = mbstowcs (machine, d_or_m, INTERNET_MAX_HOST_NAME_LENGTH + 1); + int ret = mbstowcs (machine, mach->str, 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", - program_invocation_short_name, d_or_m); + program_invocation_short_name, mach->str); return; } - servername = machine; if (!AllocateAndInitializeSid (&auth, 2, 1, 0, 0, 0, 0, 0, 0, 0, &psid)) return; @@ -255,15 +163,15 @@ enum_unix_users (domlist_t *dom_or_machine, const char *sep, DWORD id_offset, if (ret < 1 || ret >= UNLEN + 1) fprintf (stderr, "%s: Invalid user name '%s'. Skipping...\n", program_invocation_short_name, ustr); - else if (LookupAccountNameW (servername, user, + else if (LookupAccountNameW (machine, user, psid = (PSID) psid_buffer, (sidlen = MAX_SID_LEN, &sidlen), dom, (dlen = MAX_DOMAIN_NAME_LEN + 1, &dlen), &acc_type)) printf ("%s%s%ls:unused:%" PRIu32 ":99999:,%s::\n", - with_dom ? "Unix User" : "", - with_dom ? sep : "", + mach->with_dom ? "Unix_User" : "", + mach->with_dom ? sep : "", user + 10, (unsigned int) (id_offset + *GetSidSubAuthority (psid, @@ -292,15 +200,15 @@ enum_unix_users (domlist_t *dom_or_machine, const char *sep, DWORD id_offset, { *GetSidSubAuthority (psid, *GetSidSubAuthorityCount(psid) - 1) = start; - if (LookupAccountSidW (servername, psid, + if (LookupAccountSidW (machine, psid, user, (ulen = GNLEN + 1, &ulen), dom, (dlen = MAX_DOMAIN_NAME_LEN + 1, &dlen), &acc_type) && !iswdigit (user[0])) printf ("%s%s%ls:unused:%" PRIu32 ":99999:,%s::\n", - with_dom ? "Unix User" : "", - with_dom ? sep : "", + mach->with_dom ? "Unix_User" : "", + mach->with_dom ? sep : "", user, (unsigned int) (id_offset + start), put_sid (psid)); @@ -313,36 +221,23 @@ enum_unix_users (domlist_t *dom_or_machine, const char *sep, DWORD id_offset, } static int -enum_users (BOOL domain, domlist_t *dom_or_machine, const char *sep, - const char *passed_home_path, DWORD id_offset, char *disp_username, - int print_current) +enum_users (domlist_t *mach, const char *sep, const char *passed_home_path, + DWORD id_offset, char *disp_username, int print_current) { 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; USER_INFO_3 *buffer; DWORD entriesread = 0; DWORD totalentries = 0; DWORD resume_handle = 0; DWORD rc; WCHAR uni_name[UNLEN + 1]; - if (domain) - { - servername = get_dcname (d_or_m); - if (servername == (PWCHAR) -1) - return 1; - } - else if (d_or_m) + + int ret = mbstowcs (machine, mach->str, INTERNET_MAX_HOST_NAME_LENGTH + 1); + if (ret < 1 || ret >= INTERNET_MAX_HOST_NAME_LENGTH + 1) { - 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", - program_invocation_short_name, d_or_m); - return 1; - } - servername = machine; + fprintf (stderr, "%s: Invalid machine name '%s'. Skipping...\n", + program_invocation_short_name, mach->str); + return 1; } do @@ -352,7 +247,7 @@ enum_users (BOOL domain, domlist_t *dom_or_machine, const char *sep, if (disp_username != NULL) { mbstowcs (uni_name, disp_username, UNLEN + 1); - rc = NetUserGetInfo (servername, (LPWSTR) &uni_name, 3, + rc = NetUserGetInfo (machine, (LPWSTR) &uni_name, 3, (void *) &buffer); entriesread = 1; /* Avoid annoying error messages just because the user hasn't been @@ -361,7 +256,7 @@ enum_users (BOOL domain, domlist_t *dom_or_machine, const char *sep, return 0; } else - rc = NetUserEnum (servername, 3, FILTER_NORMAL_ACCOUNT, + rc = NetUserEnum (machine, 3, FILTER_NORMAL_ACCOUNT, (void *) &buffer, MAX_PREFERRED_LENGTH, &entriesread, &totalentries, &resume_handle); switch (rc) @@ -407,7 +302,7 @@ enum_users (BOOL domain, domlist_t *dom_or_machine, const char *sep, stpcpy (homedir_psx, passed_home_path), PATH_MAX - strlen (passed_home_path)); - if (!LookupAccountNameW (servername, buffer[i].usri3_name, + if (!LookupAccountNameW (machine, buffer[i].usri3_name, psid, &sid_length, domain_name, &domname_len, &acc_type)) { @@ -419,13 +314,12 @@ enum_users (BOOL domain, domlist_t *dom_or_machine, const char *sep, { WCHAR domname[MAX_DOMAIN_NAME_LEN + UNLEN + 2]; - wcscpy (domname, domain || !servername - ? domain_name : servername); + wcscpy (domname, machine); wcscat (domname, L"\\"); wcscat (domname, buffer[i].usri3_name); sid_length = MAX_SID_LEN; domname_len = sizeof (domname); - if (!LookupAccountNameW (servername, domname, psid, + if (!LookupAccountNameW (machine, domname, psid, &sid_length, domain_name, &domname_len, &acc_type)) { @@ -441,8 +335,8 @@ enum_users (BOOL domain, domlist_t *dom_or_machine, const char *sep, printf ("%ls%s%ls:unused:%" PRIu32 ":%" PRIu32 ":%ls%sU-%ls\\%ls,%s:%s:/bin/bash\n", - with_dom ? domain_name : L"", - with_dom ? sep : "", + mach->with_dom ? domain_name : L"", + mach->with_dom ? sep : "", buffer[i].usri3_name, (unsigned int) (id_offset + uid), (unsigned int) (id_offset + gid), @@ -463,98 +357,49 @@ enum_users (BOOL domain, domlist_t *dom_or_machine, const char *sep, return 0; } -static void -print_special_by_sid (PSID_IDENTIFIER_AUTHORITY auth, BYTE cnt, - DWORD sub1, DWORD sub2, DWORD sub3, DWORD sub4, - DWORD sub5, DWORD sub6, DWORD sub7, DWORD sub8) -{ - WCHAR user[UNLEN + 1], dom[MAX_DOMAIN_NAME_LEN + 1]; - DWORD len, len2, rid; - PSID sid; - SID_NAME_USE acc_type; - - if (AllocateAndInitializeSid (auth, cnt, sub1, sub2, sub3, sub4, - sub5, sub6, sub7, sub8, &sid)) - { - if (LookupAccountSidW (NULL, sid, - user, (len = UNLEN + 1, &len), - dom, (len2 = MAX_DOMAIN_NAME_LEN + 1, &len2), - &acc_type)) - { - if (sub8) - rid = sub8; - else if (sub7) - rid = sub7; - else if (sub6) - rid = sub6; - else if (sub5) - rid = sub5; - else if (sub4) - rid = sub4; - else if (sub3) - rid = sub3; - else if (sub2) - rid = sub2; - else - rid = sub1; - printf ("%ls:*:%" PRIu32 ":%" PRIu32 ":,%s::\n", - user, (unsigned int) rid, - (unsigned int) (rid == 18 ? 544 : rid), /* SYSTEM hack */ - put_sid (sid)); - } - FreeSid (sid); - } -} - static int usage (FILE * stream) { fprintf (stream, "Usage: %s [OPTIONS]...\n" "\n" -"Print /etc/passwd file to stdout\n" +"Write /etc/passwd-like output to stdout\n" "\n" "Options:\n" "\n" -" -l,--local [machine[,offset]]\n" -" print local user accounts with uid offset offset\n" +" -l,--local [machine] print local user accounts with uid offset offset\n" " (from local machine if no machine specified)\n" -" -L,--Local [machine[,offset]]\n" -" ditto, but generate username with machine prefix\n" -" -d,--domain [domain[,offset]]\n" -" print domain accounts with uid offset offset\n" +" -L,--Local machine ditto, but generate username with machine prefix\n" +" -d,--domain [domain] print domain accounts with uid offset offset\n" " (from current domain if no domain specified)\n" -" -D,--Domain [domain[,offset]]\n" -" ditto, but generate username with domain prefix\n" " -c,--current print current user\n" -" -C,--Current ditto, but generate username with machine or\n" -" domain prefix\n" -" -S,--separator char for -L, -D, -C use character char as domain\\user\n" -" separator in username instead of the default '\\'\n" -" -o,--id-offset offset change the default offset (10000) added to uids\n" +" -S,--separator char for -l use character char as domain\\user\n" +" separator in username instead of the default '%s'\n" +" -o,--id-offset offset change the default offset (0x10000) added to uids\n" " in domain or foreign server accounts.\n" " -u,--username username only return information for the specified user\n" -" one of -l, -L, -d, -D must be specified, too\n" +" one of -l, -d must be specified, too\n" +" -b,--no-builtin don't print BUILTIN users\n" " -p,--path-to-home path use specified path instead of user account home dir\n" " or /home prefix\n" -" -U,--unix userlist additionally print UNIX users when using -l or -L\n" -" on a UNIX Samba server\n" -" userlist is a comma-separated list of usernames\n" -" or uid ranges (root,-25,50-100).\n" +" -U,--unix userlist print UNIX users when using -l on a UNIX Samba\n" +" server. userlist is a comma-separated list of\n" +" usernames or uid ranges (root,-25,50-100).\n" " (enumerating large ranges can take a long time!)\n" -" -s,--no-sids (ignored)\n" -" -m,--no-mount (ignored)\n" -" -g,--local-groups (ignored)\n" " -h,--help displays this message\n" " -V,--version version information and exit\n" "\n" "Default is to print local accounts on stand-alone machines, domain accounts\n" -"on domain controllers and domain member machines.\n" -"\n", program_invocation_short_name); +"on domain controllers and domain member machines.\n\n" +"Don't use this command to generate a local /etc/passwd file, unless you\n" +"really need one. See the Cygwin User's Guide for more information.\n" +"\n", program_invocation_short_name, + (const char *) cygwin_internal (CW_GETNSSSEP)); return 1; } static struct option longopts[] = { + {"no-builtin", no_argument, NULL, 'b'}, {"current", no_argument, NULL, 'c'}, {"Current", no_argument, NULL, 'C'}, {"domain", optional_argument, NULL, 'd'}, @@ -574,7 +419,7 @@ static struct option longopts[] = { {0, no_argument, NULL, 0} }; -static char opts[] = "cCd::D::ghl::L::mo:sS:p:u:U:V"; +static char opts[] = "bcCd::D::ghl::L::mo:sS:p:u:U:V"; static void print_version () @@ -590,66 +435,6 @@ print_version () strrchr (__DATE__, ' ') + 1); } -static void -print_special_by_name (PCWSTR name, uid_t uid, gid_t gid) -{ - DWORD size = 256, dom_size = 256; - PSID sid = (PSID) alloca (size); - WCHAR dom[dom_size]; - SID_NAME_USE use; - - PWCHAR name_only = wcschr (name, L'\\'); - if (name_only) - ++name_only; - - if (LookupAccountNameW (NULL, name, sid, &size, dom, &dom_size, &use)) - printf ("%ls:*:%lu:%lu:U-%ls%s%ls,%s::\n", - name_only ?: name, - (unsigned long) uid, - (unsigned long) gid, - name_only ? dom : L"", - name_only ? "\\" : "", - name_only ?: name, - put_sid (sid)); -} - -static void -enum_std_accounts () -{ - /* Generate service starter account entries. */ - printf ("SYSTEM:*:18:544:,S-1-5-18::\n"); - printf ("LocalService:*:19:544:U-NT AUTHORITY\\LocalService,S-1-5-19::\n"); - printf ("NetworkService:*:20:544:U-NT AUTHORITY\\NetworkService,S-1-5-20::\n"); - /* Get 'administrators' group (has localized name). */ - print_special_by_sid (&sid_nt_auth, 2, SECURITY_BUILTIN_DOMAIN_RID, - DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0); - /* Fetch "TrustedInstaller" account starting with Vista. */ - print_special_by_name (L"NT SERVICE\\TrustedInstaller", -2, -2); -} - -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_VIEW_LOCAL_INFORMATION, &lsa); - if (!NT_SUCCESS (status)) - return FALSE; - status = LsaQueryInformationPolicy (lsa, PolicyPrimaryDomainInformation, - (PVOID *) ((void *) &p_dom)); - LsaClose (lsa); - if (!NT_SUCCESS (status)) - return FALSE; - } - return !!p_dom->Sid; -} - int main (int argc, char **argv) { @@ -657,13 +442,14 @@ main (int argc, char **argv) domlist_t domlist[32]; char *opt, *p, *ep; int print_current = 0; + int print_builtin = 1; char *print_unix = NULL; - const char *sep_char = "\\"; - DWORD id_offset = 10000, off; + const char *nss_sep = (const char *) cygwin_internal (CW_GETNSSSEP); + const char *sep_char = nss_sep; + DWORD id_offset = 0x10000, off; int c, i; char *disp_username = NULL; char passed_home_path[PATH_MAX]; - BOOL in_domain; int optional_args = 0; passed_home_path[0] = '\0'; @@ -674,18 +460,23 @@ main (int argc, char **argv) setlocale (LC_CTYPE, ""); if (!strcmp (setlocale (LC_CTYPE, NULL), "C")) setlocale (LC_CTYPE, "en_US.UTF-8"); - in_domain = fetch_primary_domain (); fetch_current_user_sid (); if (argc == 1) { - enum_std_accounts (); - if (in_domain) - enum_users (TRUE, NULL, sep_char, passed_home_path, 10000, - disp_username, 0); - else - enum_users (FALSE, NULL, sep_char, passed_home_path, 0, - disp_username, 0); + int enums = ENUM_PRIMARY | ENUM_LOCAL | ENUM_BUILTIN; + uintptr_t ticket = cygwin_internal (CW_SETENT, FALSE, enums, NULL); + if (ticket) + { + struct passwd *pwd; + + while ((pwd = (struct passwd *) cygwin_internal (CW_GETENT, FALSE, + ticket))) + printf ("%s:%s:%u:%u:%s:%s:%s\n", pwd->pw_name, pwd->pw_passwd, + pwd->pw_uid, pwd->pw_gid, pwd->pw_gecos, pwd->pw_dir, + pwd->pw_shell); + cygwin_internal (CW_ENDENT, FALSE, ticket); + } return 0; } @@ -724,13 +515,9 @@ main (int argc, char **argv) goto skip; } domlist[print_domlist].str = opt; - domlist[print_domlist].id_offset = UINT32_MAX; if (opt && (p = strchr (opt, ','))) { - if (p == opt - || !isdigit ((unsigned char) p[1]) - || (domlist[print_domlist].id_offset = strtol (p + 1, &ep, 10) - , *ep)) + if (p == opt) { fprintf (stderr, "%s: Malformed domain,offset string '%s'. " "Skipping...\n", program_invocation_short_name, opt); @@ -738,15 +525,15 @@ main (int argc, char **argv) } *p = '\0'; } - domlist[print_domlist++].with_dom = (c == 'D' || c == 'L'); + domlist[print_domlist++].with_dom = (c == 'L'); skip: break; case 'S': sep_char = optarg; if (strlen (sep_char) > 1) { - fprintf (stderr, "%s: Only one character allowed as domain\\user " - "separator character.\n", + fprintf (stderr, "%s: Only one ASCII character allowed as " + "domain\\user separator character.\n", program_invocation_short_name); return 1; } @@ -761,19 +548,14 @@ skip: print_unix = optarg; break; case 'c': - sep_char = NULL; - /*FALLTHRU*/ case 'C': print_current = 1; break; case 'o': id_offset = strtoul (optarg, &ep, 10); - if (*ep) - { - fprintf (stderr, "%s: Malformed offset '%s'. " - "Skipping...\n", program_invocation_short_name, optarg); - return 1; - } + break; + case 'b': + print_builtin = 0; break; case 'p': if (optarg[0] != '/') @@ -814,24 +596,91 @@ skip: exit (1); } - off = id_offset; + struct passwd *ppwd = NULL; + const char *ppwd_sid = NULL; + if (print_current) + { + ppwd = (struct passwd *) cygwin_internal (CW_GETPWSID, TRUE, + curr_user.psid); + if (ppwd) + ppwd_sid = strrchr (ppwd->pw_gecos, ','); + } + + int enums = ENUM_NONE; + WCHAR tdoms[print_domlist * 258]; + PWCHAR t = tdoms; + if (!disp_username && print_builtin && print_domlist) + enums |= ENUM_BUILTIN; for (i = 0; i < print_domlist; ++i) { - DWORD my_off = (domlist[i].domain || domlist[i].str) - ? domlist[i].id_offset != UINT_MAX - ? domlist[i].id_offset : off : 0; - if (!domlist[i].domain && domlist[i].str && print_unix) - enum_unix_users (domlist + i, sep_char, my_off, print_unix); - if (!my_off && !disp_username) - enum_std_accounts (); - enum_users (domlist[i].domain, domlist + i, sep_char, passed_home_path, - my_off, disp_username, print_current); - if (my_off) - off += id_offset; + if (domlist[i].domain) + { + if (domlist[i].str) + { + enums |= ENUM_TDOMS; + t += mbstowcs (t, domlist[i].str, 257); + *t++ = L'\0'; + } + else + enums |= ENUM_PRIMARY; + } + else if (!domlist[i].str) + enums |= ENUM_LOCAL; + } + if (t > tdoms) + *t++ = L'\0'; + if (enums) + { + uintptr_t ticket = cygwin_internal (CW_SETENT, FALSE, enums, + t > tdoms ? tdoms : NULL); + if (ticket) + { + struct passwd *pwd; + + while ((pwd = (struct passwd *) + cygwin_internal (CW_GETENT, FALSE, ticket))) + { + p = NULL; + if (disp_username + && strcasecmp (disp_username, pwd->pw_name) != 0 + && (!(p = strchr (pwd->pw_name, nss_sep[0])) + || strcasecmp (disp_username, p + 1) != 0)) + continue; + printf ("%s:%s:%u:%u:%s:%s%s:%s\n", pwd->pw_name, pwd->pw_passwd, + pwd->pw_uid, pwd->pw_gid, pwd->pw_gecos, + passed_home_path[0] ? passed_home_path : "", + passed_home_path[0] ? (p ? p + 1 : pwd->pw_name) + : pwd->pw_dir, + pwd->pw_shell); + const char *pwd_sid = strrchr (pwd->pw_gecos, ','); + if (ppwd && ppwd_sid && pwd_sid && !strcmp (pwd_sid, ppwd_sid)) + got_curr_user = TRUE; + } + cygwin_internal (CW_ENDENT, FALSE, ticket); + } } if (print_current && !got_curr_user) - current_user (sep_char, passed_home_path, off, disp_username); + { + p = strchr (ppwd->pw_name, nss_sep[0]); + printf ("%s:%s:%u:%u:%s:%s%s:%s\n", ppwd->pw_name, ppwd->pw_passwd, + ppwd->pw_uid, ppwd->pw_gid, ppwd->pw_gecos, + passed_home_path[0] ? passed_home_path : "", + passed_home_path[0] ? (p ? p + 1 : ppwd->pw_name) : ppwd->pw_dir, + ppwd->pw_shell); + } + + off = 0xfd000000; + for (i = 0; i < print_domlist; ++i) + { + if (domlist[i].domain || !domlist[i].str) + continue; + enum_users (domlist + i, sep_char, passed_home_path, off, disp_username, + print_current); + if (!domlist[i].domain && domlist[i].str && print_unix) + enum_unix_users (domlist + i, sep_char, 0xff000000, print_unix); + off += id_offset; + } return 0; } diff --git a/winsup/utils/utils.xml b/winsup/utils/utils.xml index b7e8ff81d..45c2dfb4b 100644 --- a/winsup/utils/utils.xml +++ b/winsup/utils/utils.xml @@ -875,89 +875,77 @@ Write minidump from WIN32PID to FILENAME.dmp Usage: mkgroup [OPTION]... -Print /etc/group file to stdout +Write /etc/group-like output to stdout Options: - -l,--local [machine[,offset]] - print local groups with gid offset offset + -l,--local [machine] print local groups (from local machine if no machine specified) - -L,--Local [machine[,offset]] - ditto, but generate groupname with machine prefix - -d,--domain [domain[,offset]] - print domain groups with gid offset offset + -L,--Local machine ditto, but generate groupname with machine prefix + -d,--domain [domain] print domain groups (from current domain if no domain specified) - -D,--Domain [domain[,offset]] - ditto, but generate groupname with machine prefix -c,--current print current group - -C,--Current ditto, but generate groupname with machine or - domain prefix - -S,--separator char for -L, -D, -C use character char as domain\group - separator in groupname instead of the default '\' - -o,--id-offset offset change the default offset (10000) added to gids - in domain or foreign server accounts. + -S,--separator char for -l use character char as domain\group + separator in groupname instead of default '+' + -o,--id-offset offset change the default offset (0x10000) added to + gids of foreign machine accounts. -g,--group groupname only return information for the specified group - one of -l, -L, -d, -D must be specified, too + one of -l, -d must be specified, too -b,--no-builtin don't print BUILTIN groups - -U,--unix grouplist additionally print UNIX groups when using -l or -L - on a UNIX Samba server - grouplist is a comma-separated list of groupnames - or gid ranges (root,-25,50-100). - (enumerating large ranges can take a long time!) - -s,--no-sids (ignored) - -u,--users (ignored) + -U,--unix grouplist print UNIX groups when using -l on a UNIX Samba + server. grouplist is a comma-separated list of + groupnames or gid ranges (root,-25,50-100). + (enumerating large ranges can take a long time!) -h,--help print this message - -V,--version print version information and exit + -v,--version print version information and exit Default is to print local groups on stand-alone machines, plus domain groups on domain controllers and domain member machines. + +Don't use this command to generate a local /etc/group file, unless you +really need one. See the Cygwin User's Guide for more information. - The mkgroup program can be used to help configure - Cygwin by creating a /etc/group file. Its use is - essential to include Windows security information. - - The command is initially called by setup.exe to - create a default /etc/group. This should be - sufficient in most circumstances. However, especially when working in a - multi-domain environment, you can use mkgroup manually - to create a more complete /etc/group file for all - domains. Especially when you have the same group name used on multiple - machines or in multiple domains, you can use the -D, - -L and -C options to create unique - domain\group style groupnames. - - Note that this information is static. If you change the group - information in your system, you'll need to regenerate the group file for - it to have the new information. - - The -d/-D and -l/-L options - allow you to specify where the information comes from, the local SAM of a - machine or from the domain, or both. With the -d/-D - options the program contacts a Domain Controller, which my be unreachable - or have restricted access. Comma-separated from the machine or domain, - you can specify an offset which is used as base added to the group's RID - to compute the gid (offset + RID = gid). This allows you to create the - same gids every time you re-run mkgroup. For very - simple needs, an entry for the current user's group can be created by - using the option -c or -C. If you - want to use one of the -D, -L or - -C options, but you don't like the backslash as - domain/group separator, you can specify another separator using the - -S option, for instance: + The mkgroup program can be used to create a local + /etc/group file. Cygwin doesn't need this file, + because it reads group information from the Windows account databases, + but you can add an /etc/group file for instance, if + your machine is often disconnected from its domain controller. + + + Note that this information is static, in contrast to the information + automatically gathered by Cygwin from the Windows account databases. If + you change the group information on your system, you'll need to regenerate + the group file for it to have the new information. + + By default, the information generated by mkgroup + is equivalent to the information generated by Cygwin itself. The + -d and -l/-L options allow you to + specify where the information comes from, some domain, or the local SAM + of a machine. Note that you can only enumerate accounts from trusted + domains. Any non-trusted domain will be ignored. Access-restrictions + of your current account apply. The -l/-L when used + with a machine name, tries to contact that machine to enumerate local + groups of other machines, typically outside of domains. This scenario + cannot be covered by Cygwin's account automatism. If you want to use + the -L option, but you don't like the default + domain/group separator from /etc/nsswitch.conf, + you can specify another separator using the -S option, + for instance: Setting up group entry for current user with different domain/group separator -$ mkgroup -C -S+ > /etc/group -$ cat /etc/group -DOMAIN+my_group:S-1-5-21-2913048732-1697188782-3448811101-1144:11144: +$ mkgroup -L server1 -S= > /etc/group - The -o option allows for special cases (such as - multiple domains) where the GIDs might match otherwise. The + For very simple needs, an entry for the current user's group can be + created by using the option -c. + + The -o option allows for (unlikely) special cases + with multiple machines where the GIDs might match otherwise. The -g option only prints the information for one group. The -U option allows you to enumerate the standard UNIX groups on a Samba machine. It's used together with -l @@ -973,81 +961,69 @@ DOMAIN+my_group:S-1-5-21-2913048732-1697188782-3448811101-1144:11144: Usage: mkpasswd [OPTIONS]... -Print /etc/passwd file to stdout +Write /etc/passwd-like output to stdout Options: - -l,--local [machine[,offset]] - print local user accounts with uid offset offset + -l,--local [machine] print local user accounts with uid offset offset (from local machine if no machine specified) - -L,--Local [machine[,offset]] - ditto, but generate username with machine prefix - -d,--domain [domain[,offset]] - print domain accounts with uid offset offset + -L,--Local machine ditto, but generate username with machine prefix + -d,--domain [domain] print domain accounts with uid offset offset (from current domain if no domain specified) - -D,--Domain [domain[,offset]] - ditto, but generate username with domain prefix -c,--current print current user - -C,--Current ditto, but generate username with machine or - domain prefix - -S,--separator char for -L, -D, -C use character char as domain\user - separator in username instead of the default '\' - -o,--id-offset offset change the default offset (10000) added to uids + -S,--separator char for -l use character char as domain\user + separator in username instead of the default '+' + -o,--id-offset offset change the default offset (0x10000) added to uids in domain or foreign server accounts. -u,--username username only return information for the specified user - one of -l, -L, -d, -D must be specified, too + one of -l, -d must be specified, too + -b,--no-builtin don't print BUILTIN users -p,--path-to-home path use specified path instead of user account home dir or /home prefix - -U,--unix userlist additionally print UNIX users when using -l or -L\ - on a UNIX Samba server - userlist is a comma-separated list of usernames - or uid ranges (root,-25,50-100). + -U,--unix userlist print UNIX users when using -l on a UNIX Samba + server. userlist is a comma-separated list of + usernames or uid ranges (root,-25,50-100). (enumerating large ranges can take a long time!) - -s,--no-sids (ignored) - -m,--no-mount (ignored) - -g,--local-groups (ignored) -h,--help displays this message -V,--version version information and exit Default is to print local accounts on stand-alone machines, domain accounts on domain controllers and domain member machines. + +Don't use this command to generate a local /etc/passwd file, unless you +really need one. See the Cygwin User's Guide for more information. - The mkpasswd program can be used to help configure - Cygwin by creating a /etc/passwd from your system - information. Its use is essential to include Windows security - information. However, the actual passwords are determined by Windows, not - by the content of /etc/passwd. - - The command is initially called by setup.exe to - create a default /etc/passwd. This should be - sufficient in most circumstances. However, especially when working in a - multi-domain environment, you can use mkpasswd - manually to create a more complete /etc/passwd file - for all domains. Especially when you have the same user name used on - multiple machines or in multiple domains, you can use the - -D, -L and -C - options to create unique domain\user style usernames. - - Note that this information is static. If you change the user - information in your system, you'll need to regenerate the passwd file for - it to have the new information. - - The -d/-D and -l/-L options - allow you to specify where the information comes from, the local machine - or the domain (default or given), or both. With the - -d/-D options the program contacts the Domain - Controller, which may be unreachable or have restricted access. - Comma-separated from the machine or domain, you can specify an offset - which is used as base added to the user's RID to compute the uid (offset - + RID = uid). This allows to create the same uids every time you re-run - mkpasswd. An entry for the current user can be created - by using the option -c or -C. If - you want to use one of the -D, -L - or -C options, but you don't like the backslash as - domain/group separator, you can specify another separator using the - -S option, similar to the mkgroup. - The -o option allows for special cases (such as + The mkpasswd program can be used to create a + /etc/passwd file. Cygwin doesn't need this file, + because it reads user information from the Windows account databases, + but you can add an /etc/group file for instance, if + your machine is often disconnected from its domain controller. + + Note that this information is static, in contrast to the information + automatically gathered by Cygwin from the Windows account databases. If + you change the user information on your system, you'll need to regenerate + the passwd file for it to have the new information. + + By default, the information generated by mkpasswd + is equivalent to the information generated by Cygwin itself. The + -d and -l/-L options allow you to + specify where the information comes from, some domain, or the local SAM + of a machine. Note that you can only enumerate accounts from trusted + domains. Any non-trusted domain will be ignored. Access-restrictions + of your current account apply. The -l/-L when used + with a machine name, tries to contact that machine to enumerate local + groups of other machines, typically outside of domains. This scenario + cannot be covered by Cygwin's account automatism. If you want to use + the -L option, but you don't like the default + domain/group separator from /etc/nsswitch.conf, + you can specify another separator using the -S option, + analog to mkgroup. + + For very simple needs, an entry for the current user can be created + by using the option -c. + + The -o option allows for special cases (such as multiple domains) where the UIDs might match otherwise. The -p option causes mkpasswd to use the specified prefix instead of the account home dir or /home/ @@ -1062,7 +1038,8 @@ on domain controllers and domain member machines. to enumerate the standard UNIX users on a Samba machine. It's used together with -l samba-server or -L samba-server. The normal UNIX users are usually not enumerated, - but they can show up as file owners in ls -l output. + but they can show up as file owners in ls -l output. +