From 0bdab5c8a91407ef2b4e5501378eef9bdca9fc55 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Wed, 23 Jul 2008 11:41:10 +0000 Subject: * mkgroup.c: Consolidate variable names. (enum_unix_groups): New function. (print_special): Use LookupAccountSidW instead of LookupAccountSidA. (current_group): Ditto. (usage): Add -U option. (longopts): Add --unix option. (opts): Add -U option. (main): Handle -U option. Call enum_unix_groups if set. * mkpasswd.c: Consolidate variable names. (current_user): Use LookupAccountSidW instead of LookupAccountSidA. (enum_unix_users): New function. (usage): Add -U option. (longopts): Add --unix option. (opts): Add -U option. (main): Handle -U option. Call enum_unix_groups if set. * utils.sgml: Add -U option text to mkgroup and mkpasswd description. --- winsup/utils/ChangeLog | 19 ++++++ winsup/utils/mkgroup.c | 165 +++++++++++++++++++++++++++++++++++++++++------- winsup/utils/mkpasswd.c | 160 ++++++++++++++++++++++++++++++++++++++++------ winsup/utils/utils.sgml | 23 ++++++- 4 files changed, 323 insertions(+), 44 deletions(-) diff --git a/winsup/utils/ChangeLog b/winsup/utils/ChangeLog index ce044e28a..d3e8336f1 100644 --- a/winsup/utils/ChangeLog +++ b/winsup/utils/ChangeLog @@ -1,3 +1,22 @@ +2008-07-23 Corinna Vinschen + + * mkgroup.c: Consolidate variable names. + (enum_unix_groups): New function. + (print_special): Use LookupAccountSidW instead of LookupAccountSidA. + (current_group): Ditto. + (usage): Add -U option. + (longopts): Add --unix option. + (opts): Add -U option. + (main): Handle -U option. Call enum_unix_groups if set. + * mkpasswd.c: Consolidate variable names. + (current_user): Use LookupAccountSidW instead of LookupAccountSidA. + (enum_unix_users): New function. + (usage): Add -U option. + (longopts): Add --unix option. + (opts): Add -U option. + (main): Handle -U option. Call enum_unix_groups if set. + * utils.sgml: Add -U option text to mkgroup and mkpasswd description. + 2008-07-22 Corinna Vinschen * mkgroup.c (enum_groups): Create full qualified groupname using diff --git a/winsup/utils/mkgroup.c b/winsup/utils/mkgroup.c index fc3f96585..a68e8d5e0 100644 --- a/winsup/utils/mkgroup.c +++ b/winsup/utils/mkgroup.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -122,18 +123,18 @@ get_dcname (char *domain) } char * -put_sid (PSID sid) +put_sid (PSID psid) { static char s[512]; char t[32]; DWORD i; strcpy (s, "S-1-"); - sprintf(t, "%u", GetSidIdentifierAuthority (sid)->Value[5]); + sprintf(t, "%u", GetSidIdentifierAuthority (psid)->Value[5]); strcat (s, t); - for (i = 0; i < *GetSidSubAuthorityCount (sid); ++i) + for (i = 0; i < *GetSidSubAuthorityCount (psid); ++i) { - sprintf(t, "-%lu", *GetSidSubAuthority (sid, i)); + sprintf(t, "-%lu", *GetSidSubAuthority (psid, i)); strcat (s, t); } return s; @@ -150,6 +151,109 @@ typedef struct { DBGSID builtin_sid_list[MAX_BUILTIN_SIDS]; DWORD builtin_sid_cnt; +void +enum_unix_groups (domlist_t *dom_or_machine, const char *sep, int 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]; + WCHAR dom[MAX_DOMAIN_NAME_LEN + 1]; + DWORD glen, dlen, sidlen; + PSID psid; + 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); + 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; + + if (!AllocateAndInitializeSid (&auth, 2, 2, 0, 0, 0, 0, 0, 0, 0, &psid)) + return; + + if (!(grp_list = strdup (unix_grp_list))) + { + FreeSid (psid); + return; + } + + for (gstr = strtok (grp_list, ","); gstr; gstr = strtok (NULL, ",")) + { + if (!isdigit (gstr[0]) && gstr[0] != '-') + { + PWCHAR p = wcpcpy (grp, L"Unix Group\\"); + ret = mbstowcs (p, gstr, GNLEN + 1); + if (ret < 1 || ret >= GNLEN + 1) + fprintf (stderr, "%s: Invalid group name '%s'. Skipping...\n", + __progname, gstr); + else if (LookupAccountNameW (servername, 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:%lu:\n", + with_dom ? "Unix Group" : "", + with_dom ? sep : "", + p, + put_sid (psid), + id_offset + + *GetSidSubAuthority (psid, + *GetSidSubAuthorityCount(psid) - 1)); + } + else + { + DWORD start, stop; + char *p = gstr; + if (*p == '-') + start = 0; + else + start = strtol (p, &p, 10); + if (!*p) + stop = start; + else if (*p++ != '-' || !isdigit (*p) + || (stop = strtol (p, &p, 10)) < start || *p) + { + fprintf (stderr, "%s: Malformed unix group list entry '%s'. " + "Skipping...\n", __progname, gstr); + continue; + } + for (; start <= stop; ++ start) + { + *GetSidSubAuthority (psid, *GetSidSubAuthorityCount(psid) - 1) + = start; + if (LookupAccountSidW (servername, psid, + grp, (glen = GNLEN + 1, &glen), + dom, + (dlen = MAX_DOMAIN_NAME_LEN + 1, &dlen), + &acc_type) + && !iswdigit (grp[0])) + printf ("%s%s%ls:%s:%lu:\n", + with_dom ? "Unix Group" : "", + with_dom ? sep : "", + grp, + put_sid (psid), + id_offset + start); + } + } + } + + free (grp_list); + FreeSid (psid); +} + int enum_local_groups (BOOL domain, domlist_t *dom_or_machine, const char *sep, int id_offset, char *disp_groupname) @@ -414,18 +518,18 @@ print_special (PSID_IDENTIFIER_AUTHORITY auth, BYTE cnt, DWORD sub1, DWORD sub2, DWORD sub3, DWORD sub4, DWORD sub5, DWORD sub6, DWORD sub7, DWORD sub8) { - char name[UNLEN + 1], dom[MAX_DOMAIN_NAME_LEN + 1]; - DWORD len, len2, rid; - PSID sid; - SID_NAME_USE use; + 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, &sid)) + sub5, sub6, sub7, sub8, &psid)) { - if (LookupAccountSid (NULL, sid, - name, (len = UNLEN + 1, &len), - dom, (len2 = MAX_DOMAIN_NAME_LEN + 1, &len), - &use)) + if (LookupAccountSidW (NULL, psid, + grp, (glen = GNLEN + 1, &glen), + dom, (dlen = MAX_DOMAIN_NAME_LEN + 1, &dlen), + &acc_type)) { if (sub8) rid = sub8; @@ -443,9 +547,9 @@ print_special (PSID_IDENTIFIER_AUTHORITY auth, BYTE cnt, rid = sub2; else rid = sub1; - printf ("%s:%s:%lu:\n", name, put_sid (sid), rid); + printf ("%ls:%s:%lu:\n", grp, put_sid (psid), rid); } - FreeSid (sid); + FreeSid (psid); } } @@ -458,8 +562,8 @@ current_group (const char *sep, int id_offset) PSID psid; char buffer[MAX_SID_LEN]; } tg; - char grp[GNLEN + 1]; - char dom[MAX_DOMAIN_NAME_LEN + 1]; + WCHAR grp[GNLEN + 1]; + WCHAR dom[MAX_DOMAIN_NAME_LEN + 1]; DWORD glen = GNLEN + 1; DWORD dlen = MAX_DOMAIN_NAME_LEN + 1; int gid; @@ -468,14 +572,14 @@ current_group (const char *sep, int id_offset) 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)) + || !LookupAccountSidW (NULL, tg.psid, grp, &glen, dom, &dlen, &acc_type)) { print_win_error (GetLastError ()); return; } gid = *GetSidSubAuthority (tg.psid, *GetSidSubAuthorityCount(tg.psid) - 1); - printf ("%s%s%s:%s:%u:\n", - sep ? dom : "", + printf ("%ls%s%ls:%s:%u:\n", + sep ? dom : L"", sep ?: "", grp, put_sid (tg.psid), @@ -505,6 +609,11 @@ usage (FILE * stream) " 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" +" -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" +" (enumerating large ranges can take a long time!)\n" " -s,--no-sids (ignored)\n" " -u,--users (ignored)\n" " -h,--help print this message\n" @@ -528,11 +637,12 @@ struct option longopts[] = { {"no-sids", no_argument, NULL, 's'}, {"separator", required_argument, NULL, 'S'}, {"users", no_argument, NULL, 'u'}, + {"unix", required_argument, NULL, 'U'}, {"version", no_argument, NULL, 'v'}, {0, no_argument, NULL, 0} }; -char opts[] = "cCd::D::g:hl::L::o:sS:uv"; +char opts[] = "cCd::D::g:hl::L::o:sS:uU:v"; void print_version () @@ -590,6 +700,7 @@ main (int argc, char **argv) char *opt; int print_current = 0; int print_system = 0; + char *print_unix = NULL; const char *sep_char = "\\"; int id_offset = 10000; int c, i, off; @@ -672,6 +783,9 @@ main (int argc, char **argv) return 1; } break; + case 'U': + print_unix = optarg; + break; case 'c': sep_char = NULL; /*FALLTHRU*/ @@ -714,8 +828,13 @@ main (int argc, char **argv) { 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); + { + if (print_unix) + enum_unix_groups (locals + i, sep_char, id_offset * off, + print_unix); + enum_groups (FALSE, locals + i, sep_char, id_offset * off++, + disp_groupname); + } } else if (!enum_local_groups (FALSE, locals + i, sep_char, 0, disp_groupname)) diff --git a/winsup/utils/mkpasswd.c b/winsup/utils/mkpasswd.c index c9031248a..54f2d9414 100644 --- a/winsup/utils/mkpasswd.c +++ b/winsup/utils/mkpasswd.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -182,8 +183,8 @@ current_user (int print_cygpath, const char *sep, const char *passed_home_path, PSID psid; int buffer[10]; } tu, tg; - char user[UNLEN + 1]; - char dom[MAX_DOMAIN_NAME_LEN + 1]; + 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; @@ -194,7 +195,7 @@ current_user (int print_cygpath, const char *sep, const char *passed_home_path, || !GetTokenInformation (ptok, TokenUser, &tu, sizeof tu, &len) || !GetTokenInformation (ptok, TokenPrimaryGroup, &tg, sizeof tg, &len) || !CloseHandle (ptok) - || !LookupAccountSidA (NULL, tu.psid, user, &ulen, dom, &dlen, &acc_type)) + || !LookupAccountSidW (NULL, tu.psid, user, &ulen, dom, &dlen, &acc_type)) { print_win_error (GetLastError ()); return; @@ -231,18 +232,20 @@ current_user (int print_cygpath, const char *sep, const char *passed_home_path, } else { - strlcpy (homedir_psx, "/home/", sizeof (homedir_psx)); - strlcat (homedir_psx, user, sizeof (homedir_psx)); + wcstombs (stpncpy (homedir_psx, "/home/", sizeof (homedir_psx)), + user, sizeof (homedir_psx) - 6); + homedir_psx[PATH_MAX - 1] = '\0'; } } else { - strlcpy (homedir_psx, passed_home_path, sizeof (homedir_psx)); - strlcat (homedir_psx, user, sizeof (homedir_psx)); + 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 ("%s%s%s:unused:%u:%u:U-%s\\%s,%s:%s:/bin/bash\n", - sep ? dom : "", + printf ("%ls%s%ls:unused:%u:%u:U-%ls\\%ls,%s:%s:/bin/bash\n", + sep ? dom : L"", sep ?: "", user, uid + id_offset, @@ -253,6 +256,109 @@ current_user (int print_cygpath, const char *sep, const char *passed_home_path, homedir_psx); } +void +enum_unix_users (domlist_t *dom_or_machine, const char *sep, int 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]; + WCHAR dom[MAX_DOMAIN_NAME_LEN + 1]; + DWORD ulen, dlen, sidlen; + PSID psid; + 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); + 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; + + if (!AllocateAndInitializeSid (&auth, 2, 1, 0, 0, 0, 0, 0, 0, 0, &psid)) + return; + + if (!(user_list = strdup (unix_user_list))) + { + FreeSid (psid); + return; + } + + for (ustr = strtok (user_list, ","); ustr; ustr = strtok (NULL, ",")) + { + if (!isdigit (ustr[0]) && ustr[0] != '-') + { + PWCHAR p = wcpcpy (user, L"Unix User\\"); + ret = mbstowcs (p, ustr, UNLEN + 1); + if (ret < 1 || ret >= UNLEN + 1) + fprintf (stderr, "%s: Invalid user name '%s'. Skipping...\n", + __progname, ustr); + else if (LookupAccountNameW (servername, 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:%lu:99999:,%s::\n", + with_dom ? "Unix User" : "", + with_dom ? sep : "", + user + 10, + id_offset + + *GetSidSubAuthority (psid, + *GetSidSubAuthorityCount(psid) - 1), + put_sid (psid)); + } + else + { + DWORD start, stop; + char *p = ustr; + if (*p == '-') + start = 0; + else + start = strtol (p, &p, 10); + if (!*p) + stop = start; + else if (*p++ != '-' || !isdigit (*p) + || (stop = strtol (p, &p, 10)) < start || *p) + { + fprintf (stderr, "%s: Malformed unix user list entry '%s'. " + "Skipping...\n", __progname, ustr); + continue; + } + for (; start <= stop; ++ start) + { + *GetSidSubAuthority (psid, *GetSidSubAuthorityCount(psid) - 1) + = start; + if (LookupAccountSidW (servername, psid, + user, (ulen = GNLEN + 1, &ulen), + dom, + (dlen = MAX_DOMAIN_NAME_LEN + 1, &dlen), + &acc_type) + && !iswdigit (user[0])) + printf ("%s%s%ls:unused:%lu:99999:,%s::\n", + with_dom ? "Unix User" : "", + with_dom ? sep : "", + user, + id_offset + start, + put_sid (psid)); + } + } + } + + free (user_list); + FreeSid (psid); +} + int enum_users (BOOL domain, domlist_t *dom_or_machine, const char *sep, int print_cygpath, const char *passed_home_path, int id_offset, @@ -408,18 +514,18 @@ print_special (PSID_IDENTIFIER_AUTHORITY auth, BYTE cnt, DWORD sub1, DWORD sub2, DWORD sub3, DWORD sub4, DWORD sub5, DWORD sub6, DWORD sub7, DWORD sub8) { - char name[UNLEN + 1], dom[MAX_DOMAIN_NAME_LEN + 1]; + WCHAR user[UNLEN + 1], dom[MAX_DOMAIN_NAME_LEN + 1]; DWORD len, len2, rid; PSID sid; - SID_NAME_USE use; + SID_NAME_USE acc_type; if (AllocateAndInitializeSid (auth, cnt, sub1, sub2, sub3, sub4, sub5, sub6, sub7, sub8, &sid)) { - if (LookupAccountSid (NULL, sid, - name, (len = UNLEN + 1, &len), - dom, (len2 = MAX_DOMAIN_NAME_LEN + 1, &len), - &use)) + if (LookupAccountSidW (NULL, sid, + user, (len = UNLEN + 1, &len), + dom, (len2 = MAX_DOMAIN_NAME_LEN + 1, &len), + &acc_type)) { if (sub8) rid = sub8; @@ -437,8 +543,8 @@ print_special (PSID_IDENTIFIER_AUTHORITY auth, BYTE cnt, rid = sub2; else rid = sub1; - printf ("%s:*:%lu:%lu:,%s::\n", - name, rid, rid == 18 ? 544 : rid, /* SYSTEM hack */ + printf ("%ls:*:%lu:%lu:,%s::\n", + user, rid, rid == 18 ? 544 : rid, /* SYSTEM hack */ put_sid (sid)); } FreeSid (sid); @@ -471,6 +577,11 @@ usage (FILE * stream) " -p,--path-to-home path use specified path instead of user account home dir\n" " or /home prefix\n" " -m,--no-mount don't use mount points for home dir\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" +" (enumerating large ranges can take a long time!)\n" " -s,--no-sids (ignored)\n" " -g,--local-groups (ignored)\n" " -h,--help displays this message\n" @@ -496,11 +607,12 @@ struct option longopts[] = { {"no-sids", no_argument, NULL, 's'}, {"separator", required_argument, NULL, 'S'}, {"username", required_argument, NULL, 'u'}, + {"unix", required_argument, NULL, 'U'}, {"version", no_argument, NULL, 'v'}, {0, no_argument, NULL, 0} }; -char opts[] = "cCd::D::ghl::L::mo:sS:p:u:v"; +char opts[] = "cCd::D::ghl::L::mo:sS:p:u:U:v"; static void print_version () @@ -570,6 +682,7 @@ main (int argc, char **argv) char *opt; int print_cygpath = 1; int print_current = 0; + char *print_unix = NULL; const char *sep_char = "\\"; int id_offset = 10000; int c, i, off; @@ -649,6 +762,9 @@ skip_domain: return 1; } break; + case 'U': + print_unix = optarg; + break; case 'c': sep_char = NULL; /*FALLTHRU*/ @@ -697,8 +813,12 @@ skip_domain: for (i = 0; i < print_local; ++i) { if (locals[i].str) - enum_users (FALSE, locals + i, sep_char, print_cygpath, - passed_home_path, id_offset * off++, disp_username); + { + if (print_unix) + enum_unix_users (locals + i, sep_char, id_offset * off, print_unix); + enum_users (FALSE, locals + i, sep_char, print_cygpath, + passed_home_path, id_offset * off++, disp_username); + } else { enum_std_accounts (); diff --git a/winsup/utils/utils.sgml b/winsup/utils/utils.sgml index 2cb391b3e..caacbd35c 100644 --- a/winsup/utils/utils.sgml +++ b/winsup/utils/utils.sgml @@ -524,6 +524,11 @@ Options: in domain or foreign server accounts. -g,--group groupname only return information for the specified group one of -l, -L, -d, -D must be specified, too + -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) -h,--help print this message @@ -574,6 +579,11 @@ DOMAIN+my_group:S-1-5-21-2913048732-1697188782-3448811101-1144:11144: The -o option allows for special cases (such as multiple domains) where the GIDs might match otherwise. The -g option only prints the information for one group. +The -U option allows to enumerate the standard UNIX +groups on a Samba machine. It's used together with +-l samba-server or -L samba-server. +The normal UNIX groups are usually not enumerated, but they can show +up as group in ls -l output. @@ -603,6 +613,11 @@ Options: -p,--path-to-home path use specified path instead of user account home dir or /home prefix -m,--no-mount don't use mount points for home dir + -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). + (enumerating large ranges can take a long time!) -s,--no-sids (ignored) -g,--local-groups (ignored) -h,--help displays this message @@ -662,7 +677,13 @@ use the specified prefix instead of the account home dir or /home/ would put local users' home directories in the Windows 'Profiles' directory. The -u option creates just an entry for -the specified user. +the specified user. +The -U option allows 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. + -- cgit v1.2.3