* 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.
This commit is contained in:
Corinna Vinschen 2014-02-24 10:51:42 +00:00
parent bdcad00bdf
commit 16a976cff4
4 changed files with 411 additions and 697 deletions

View File

@ -1,3 +1,37 @@
2013-11-24 Corinna Vinschen <corinna@vinschen.de>
* 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 <jon.turney@dronecode.org.uk>
* minidumper.cc (minidump): Fix -t option argument handling.

View File

@ -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 <inttypes.h>
#include <getopt.h>
#include <io.h>
#include <grp.h>
#include <sys/fcntl.h>
#include <sys/cygwin.h>
#include <cygwin/version.h>
@ -29,9 +30,7 @@
#include <wininet.h>
#include <iptypes.h>
#include <ntsecapi.h>
#include <dsgetdc.h>
#include <ntdef.h>
#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)
int ret = mbstowcs (machine, mach->str, INTERNET_MAX_HOST_NAME_LENGTH + 1);
if (ret < 1 || ret >= INTERNET_MAX_HOST_NAME_LENGTH + 1)
{
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",
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)
int ret = mbstowcs (machine, mach->str, INTERNET_MAX_HOST_NAME_LENGTH + 1);
if (ret < 1 || ret >= INTERNET_MAX_HOST_NAME_LENGTH + 1)
{
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",
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)
{
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);
}
struct group *pgrp = NULL;
if (print_current)
pgrp = (struct group *) cygwin_internal (CW_GETGRSID, TRUE, curr_pgrp.psid);
off = id_offset;
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)
{
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)
{
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;
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)
current_group (sep_char, off);
printf ("%s:%s:%u:\n", pgrp->gr_name, pgrp->gr_passwd, pgrp->gr_gid);
off = 0xfd000000;
for (i = 0; i < print_domlist; ++i)
{
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, 0xff000000, print_unix);
off += id_offset;
}
}
return 0;
}

View File

@ -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 <inttypes.h>
#include <getopt.h>
#include <io.h>
#include <pwd.h>
#include <sys/fcntl.h>
#include <sys/cygwin.h>
#include <cygwin/version.h>
@ -31,7 +32,6 @@
#include <ntsecapi.h>
#include <dsgetdc.h>
#include <ntdef.h>
#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)
int ret = mbstowcs (machine, mach->str, INTERNET_MAX_HOST_NAME_LENGTH + 1);
if (ret < 1 || ret >= INTERNET_MAX_HOST_NAME_LENGTH + 1)
{
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",
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;
}

View File

@ -875,89 +875,77 @@ Write minidump from WIN32PID to FILENAME.dmp
<screen>
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.
</screen>
<para>The <command>mkgroup</command> program can be used to help configure
Cygwin by creating a <filename>/etc/group</filename> file. Its use is
essential to include Windows security information.</para>
<para>The <command>mkgroup</command> program can be used to create a local
<filename>/etc/group</filename> file. Cygwin doesn't need this file,
because it reads group information from the Windows account databases,
but you can add an <filename>/etc/group</filename> file for instance, if
your machine is often disconnected from its domain controller.
</para>
<para>The command is initially called by <command>setup.exe</command> to
create a default <filename>/etc/group</filename>. This should be
sufficient in most circumstances. However, especially when working in a
multi-domain environment, you can use <command>mkgroup</command> manually
to create a more complete <filename>/etc/group</filename> file for all
domains. Especially when you have the same group name used on multiple
machines or in multiple domains, you can use the <literal>-D</literal>,
<literal>-L</literal> and <literal>-C</literal> options to create unique
domain\group style groupnames.</para>
<para>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.</para>
<para>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.</para>
<para>The <literal>-d/-D</literal> and <literal>-l/-L</literal> options
allow you to specify where the information comes from, the local SAM of a
machine or from the domain, or both. With the <literal>-d/-D</literal>
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 <command>mkgroup</command>. For very
simple needs, an entry for the current user's group can be created by
using the option <literal>-c</literal> or <literal>-C</literal>. If you
want to use one of the <literal>-D</literal>, <literal>-L</literal> or
<literal>-C</literal> options, but you don't like the backslash as
domain/group separator, you can specify another separator using the
<literal>-S</literal> option, for instance:</para>
<para>By default, the information generated by <command>mkgroup</command>
is equivalent to the information generated by Cygwin itself. The
<literal>-d</literal> and <literal>-l/-L</literal> 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 <literal>-l/-L</literal> 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 <literal>-L</literal> option, but you don't like the default
domain/group separator from <filename>/etc/nsswitch.conf</filename>,
you can specify another separator using the <literal>-S</literal> option,
for instance:</para>
<example id="utils-mkgroup-ex">
<title>Setting up group entry for current user with different
domain/group separator</title>
<screen>
<prompt>$</prompt> <userinput>mkgroup -C -S+ &gt; /etc/group</userinput>
<prompt>$</prompt> <userinput>cat /etc/group</userinput>
DOMAIN+my_group:S-1-5-21-2913048732-1697188782-3448811101-1144:11144:
<prompt>$</prompt> <userinput>mkgroup -L server1 -S= &gt; /etc/group</userinput>
</screen>
</example>
<para>The <literal>-o</literal> option allows for special cases (such as
multiple domains) where the GIDs might match otherwise. The
<para>For very simple needs, an entry for the current user's group can be
created by using the option <literal>-c</literal>.</para>
<para>The <literal>-o</literal> option allows for (unlikely) special cases
with multiple machines where the GIDs might match otherwise. The
<literal>-g</literal> option only prints the information for one group.
The <literal>-U</literal> option allows you to enumerate the standard
UNIX groups on a Samba machine. It's used together with <literal>-l
@ -973,81 +961,69 @@ DOMAIN+my_group:S-1-5-21-2913048732-1697188782-3448811101-1144:11144:
<screen>
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.
</screen>
<para>The <command>mkpasswd</command> program can be used to help configure
Cygwin by creating a <filename>/etc/passwd</filename> 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 <filename>/etc/passwd</filename>.</para>
<para>The <command>mkpasswd</command> program can be used to create a
<filename>/etc/passwd</filename> file. Cygwin doesn't need this file,
because it reads user information from the Windows account databases,
but you can add an <filename>/etc/group</filename> file for instance, if
your machine is often disconnected from its domain controller.</para>
<para>The command is initially called by <command>setup.exe</command> to
create a default <filename>/etc/passwd</filename>. This should be
sufficient in most circumstances. However, especially when working in a
multi-domain environment, you can use <command>mkpasswd</command>
manually to create a more complete <filename>/etc/passwd</filename> file
for all domains. Especially when you have the same user name used on
multiple machines or in multiple domains, you can use the
<literal>-D</literal>, <literal>-L</literal> and <literal>-C</literal>
options to create unique domain\user style usernames.</para>
<para>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.</para>
<para>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.</para>
<para>By default, the information generated by <command>mkpasswd</command>
is equivalent to the information generated by Cygwin itself. The
<literal>-d</literal> and <literal>-l/-L</literal> 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 <literal>-l/-L</literal> 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 <literal>-L</literal> option, but you don't like the default
domain/group separator from <filename>/etc/nsswitch.conf</filename>,
you can specify another separator using the <literal>-S</literal> option,
analog to <command>mkgroup</command>.</para>
<para>The <literal>-d/-D</literal> and <literal>-l/-L</literal> options
allow you to specify where the information comes from, the local machine
or the domain (default or given), or both. With the
<literal>-d/-D</literal> 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
<command>mkpasswd</command>. An entry for the current user can be created
by using the option <literal>-c</literal> or <literal>-C</literal>. If
you want to use one of the <literal>-D</literal>, <literal>-L</literal>
or <literal>-C</literal> options, but you don't like the backslash as
domain/group separator, you can specify another separator using the
<literal>-S</literal> option, similar to the <command>mkgroup</command>.
The <literal>-o</literal> option allows for special cases (such as
<para>For very simple needs, an entry for the current user can be created
by using the option <literal>-c</literal>.</para>
<para>The <literal>-o</literal> option allows for special cases (such as
multiple domains) where the UIDs might match otherwise. The
<literal>-p</literal> option causes <command>mkpasswd</command> to use
the specified prefix instead of the account home dir or <literal>/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 <literal>-l samba-server</literal> or <literal>-L
samba-server</literal>. The normal UNIX users are usually not enumerated,
but they can show up as file owners in <command>ls -l</command> output. </para>
but they can show up as file owners in <command>ls -l</command> output.
</para>
</sect2>