* 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> 2014-02-23 Jon TURNEY <jon.turney@dronecode.org.uk>
* minidumper.cc (minidump): Fix -t option argument handling. * minidumper.cc (minidump): Fix -t option argument handling.

View File

@ -1,7 +1,7 @@
/* mkgroup.c: /* mkgroup.c:
Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 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. This file is part of Cygwin.
@ -21,6 +21,7 @@
#include <inttypes.h> #include <inttypes.h>
#include <getopt.h> #include <getopt.h>
#include <io.h> #include <io.h>
#include <grp.h>
#include <sys/fcntl.h> #include <sys/fcntl.h>
#include <sys/cygwin.h> #include <sys/cygwin.h>
#include <cygwin/version.h> #include <cygwin/version.h>
@ -29,9 +30,7 @@
#include <wininet.h> #include <wininet.h>
#include <iptypes.h> #include <iptypes.h>
#include <ntsecapi.h> #include <ntsecapi.h>
#include <dsgetdc.h>
#include <ntdef.h> #include <ntdef.h>
#include "loadlib.h"
#define print_win_error(x) _print_win_error(x, __LINE__) #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 typedef struct
{ {
char *str; char *str;
DWORD id_offset;
BOOL domain; BOOL domain;
BOOL with_dom; BOOL with_dom;
} domlist_t; } domlist_t;
@ -70,31 +68,6 @@ _print_win_error (DWORD code, int line)
line, (unsigned int) code); 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 * static char *
put_sid (PSID psid) put_sid (PSID psid)
{ {
@ -149,40 +122,10 @@ fetch_current_pgrp_sid ()
} }
static void static void
current_group (const char *sep, DWORD id_offset) enum_unix_groups (domlist_t *mach, 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,
char *unix_grp_list) char *unix_grp_list)
{ {
WCHAR machine[INTERNET_MAX_HOST_NAME_LENGTH + 1]; 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 } }; SID_IDENTIFIER_AUTHORITY auth = { { 0, 0, 0, 0, 0, 22 } };
char *gstr, *grp_list; char *gstr, *grp_list;
WCHAR grp[GNLEN + sizeof ("Unix Group\\") + 1]; 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]; char psid_buffer[MAX_SID_LEN];
SID_NAME_USE acc_type; SID_NAME_USE acc_type;
if (!d_or_m) int ret = mbstowcs (machine, mach->str, INTERNET_MAX_HOST_NAME_LENGTH + 1);
return;
int ret = mbstowcs (machine, d_or_m, INTERNET_MAX_HOST_NAME_LENGTH + 1);
if (ret < 1 || ret >= 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", fprintf (stderr, "%s: Invalid machine name '%s'. Skipping...\n",
program_invocation_short_name, d_or_m); program_invocation_short_name, mach->str);
return; return;
} }
servername = machine;
if (!AllocateAndInitializeSid (&auth, 2, 2, 0, 0, 0, 0, 0, 0, 0, &psid)) if (!AllocateAndInitializeSid (&auth, 2, 2, 0, 0, 0, 0, 0, 0, 0, &psid))
return; 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) if (ret < 1 || ret >= GNLEN + 1)
fprintf (stderr, "%s: Invalid group name '%s'. Skipping...\n", fprintf (stderr, "%s: Invalid group name '%s'. Skipping...\n",
program_invocation_short_name, gstr); program_invocation_short_name, gstr);
else if (LookupAccountNameW (servername, grp, else if (LookupAccountNameW (machine, grp,
psid = (PSID) psid_buffer, psid = (PSID) psid_buffer,
(sidlen = MAX_SID_LEN, &sidlen), (sidlen = MAX_SID_LEN, &sidlen),
dom, dom,
(dlen = MAX_DOMAIN_NAME_LEN + 1, &dlen), (dlen = MAX_DOMAIN_NAME_LEN + 1, &dlen),
&acc_type)) &acc_type))
printf ("%s%s%ls:%s:%" PRIu32 ":\n", printf ("%s%s%ls:%s:%" PRIu32 ":\n",
with_dom ? "Unix Group" : "", mach->with_dom ? "Unix_Group" : "",
with_dom ? sep : "", mach->with_dom ? sep : "",
p, p,
put_sid (psid), put_sid (psid),
(unsigned int) (id_offset + (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) *GetSidSubAuthority (psid, *GetSidSubAuthorityCount(psid) - 1)
= start; = start;
if (LookupAccountSidW (servername, psid, if (LookupAccountSidW (machine, psid,
grp, (glen = GNLEN + 1, &glen), grp, (glen = GNLEN + 1, &glen),
dom, dom,
(dlen = MAX_DOMAIN_NAME_LEN + 1, &dlen), (dlen = MAX_DOMAIN_NAME_LEN + 1, &dlen),
&acc_type) &acc_type)
&& !iswdigit (grp[0])) && !iswdigit (grp[0]))
printf ("%s%s%ls:%s:%" PRIu32 ":\n", printf ("%s%s%ls:%s:%" PRIu32 ":\n",
with_dom ? "Unix Group" : "", mach->with_dom ? "Unix_Group" : "",
with_dom ? sep : "", mach->with_dom ? sep : "",
grp, grp,
put_sid (psid), put_sid (psid),
(unsigned int) (id_offset + start)); (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 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, DWORD id_offset, char *disp_groupname, int print_builtin,
int print_current) int print_current)
{ {
WCHAR machine[INTERNET_MAX_HOST_NAME_LENGTH + 1]; 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; LOCALGROUP_INFO_0 *buffer;
DWORD entriesread = 0; DWORD entriesread = 0;
DWORD totalentries = 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]; WCHAR gname[GNLEN + 1];
DWORD rc; 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); fprintf (stderr, "%s: Invalid machine name '%s'. Skipping...\n",
if (servername == (PWCHAR) -1) program_invocation_short_name, mach->str);
return 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;
} }
do do
@ -320,7 +246,7 @@ enum_local_groups (BOOL domain, domlist_t *dom_or_machine, const char *sep,
if (disp_groupname) if (disp_groupname)
{ {
mbstowcs (gname, disp_groupname, GNLEN + 1); mbstowcs (gname, disp_groupname, GNLEN + 1);
rc = NetLocalGroupGetInfo (servername, gname, 0, (void *) &buffer); rc = NetLocalGroupGetInfo (machine, gname, 0, (void *) &buffer);
if (rc == ERROR_SUCCESS) if (rc == ERROR_SUCCESS)
entriesread = 1; entriesread = 1;
/* Allow further searching for the group and avoid annoying /* 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; return 0;
} }
else else
rc = NetLocalGroupEnum (servername, 0, (void *) &buffer, rc = NetLocalGroupEnum (machine, 0, (void *) &buffer,
MAX_PREFERRED_LENGTH, &entriesread, MAX_PREFERRED_LENGTH, &entriesread,
&totalentries, &resume_handle); &totalentries, &resume_handle);
switch (rc) switch (rc)
@ -360,7 +286,7 @@ enum_local_groups (BOOL domain, domlist_t *dom_or_machine, const char *sep,
PDBGSID pdsid; PDBGSID pdsid;
BOOL is_builtin = FALSE; 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, &sid_length, domain_name, &domname_len,
&acc_type)) &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); wcscat (domname, buffer[i].lgrpi0_name);
sid_length = MAX_SID_LEN; sid_length = MAX_SID_LEN;
domname_len = MAX_DOMAIN_NAME_LEN + 1; domname_len = MAX_DOMAIN_NAME_LEN + 1;
if (!LookupAccountNameW (servername, domname, if (!LookupAccountNameW (machine, domname,
psid, &sid_length, psid, &sid_length,
domain_name, &domname_len, domain_name, &domname_len,
&acc_type)) &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); gid = *GetSidSubAuthority (psid, *GetSidSubAuthorityCount(psid) - 1);
printf ("%ls%s%ls:%s:%" PRIu32 ":\n", printf ("%ls%s%ls:%s:%" PRIu32 ":\n",
with_dom && !is_builtin ? domain_name : L"", mach->with_dom && !is_builtin ? domain_name : L"",
with_dom && !is_builtin ? sep : "", mach->with_dom || is_builtin ? sep : "",
buffer[i].lgrpi0_name, buffer[i].lgrpi0_name,
put_sid (psid), put_sid (psid),
(unsigned int) (gid + (is_builtin ? 0 : id_offset))); (unsigned int) (gid + (is_builtin ? 0 : id_offset)));
@ -436,13 +362,10 @@ skip_group:
} }
static void static void
enum_groups (BOOL domain, domlist_t *dom_or_machine, const char *sep, enum_groups (domlist_t *mach, const char *sep, DWORD id_offset,
DWORD id_offset, char *disp_groupname, int print_current) char *disp_groupname, int print_current)
{ {
WCHAR machine[INTERNET_MAX_HOST_NAME_LENGTH + 1]; 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; GROUP_INFO_2 *buffer;
DWORD entriesread = 0; DWORD entriesread = 0;
DWORD totalentries = 0; DWORD totalentries = 0;
@ -450,22 +373,12 @@ enum_groups (BOOL domain, domlist_t *dom_or_machine, const char *sep,
WCHAR gname[GNLEN + 1]; WCHAR gname[GNLEN + 1];
DWORD rc; 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); fprintf (stderr, "%s: Invalid machine name '%s'. Skipping...\n",
if (servername == (PWCHAR) -1) program_invocation_short_name, mach->str);
return; 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;
} }
do do
@ -475,8 +388,7 @@ enum_groups (BOOL domain, domlist_t *dom_or_machine, const char *sep,
if (disp_groupname != NULL) if (disp_groupname != NULL)
{ {
mbstowcs (gname, disp_groupname, GNLEN + 1); mbstowcs (gname, disp_groupname, GNLEN + 1);
rc = NetGroupGetInfo (servername, (LPWSTR) & gname, 2, rc = NetGroupGetInfo (machine, (LPWSTR) & gname, 2, (void *) &buffer);
(void *) &buffer);
entriesread=1; entriesread=1;
/* Avoid annoying error messages just because the group hasn't been /* Avoid annoying error messages just because the group hasn't been
found. */ found. */
@ -484,9 +396,8 @@ enum_groups (BOOL domain, domlist_t *dom_or_machine, const char *sep,
return; return;
} }
else else
rc = NetGroupEnum (servername, 2, (void *) & buffer, rc = NetGroupEnum (machine, 2, (void *) & buffer, MAX_PREFERRED_LENGTH,
MAX_PREFERRED_LENGTH, &entriesread, &totalentries, &entriesread, &totalentries, &resume_handle);
&resume_handle);
switch (rc) switch (rc)
{ {
case ERROR_ACCESS_DENIED: 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; SID_NAME_USE acc_type;
int gid = buffer[i].grpi2_group_id; int gid = buffer[i].grpi2_group_id;
if (!LookupAccountNameW (servername, buffer[i].grpi2_name, if (!LookupAccountNameW (machine, buffer[i].grpi2_name,
psid, &sid_length, psid, &sid_length,
domain_name, &domname_len, domain_name, &domname_len,
&acc_type)) &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]; WCHAR domname[MAX_DOMAIN_NAME_LEN + GNLEN + 2];
wcscpy (domname, domain || !servername wcscpy (domname, machine);
? domain_name : servername);
wcscat (domname, L"\\"); wcscat (domname, L"\\");
wcscat (domname, buffer[i].grpi2_name); wcscat (domname, buffer[i].grpi2_name);
sid_length = MAX_SID_LEN; sid_length = MAX_SID_LEN;
domname_len = MAX_DOMAIN_NAME_LEN + 1; domname_len = MAX_DOMAIN_NAME_LEN + 1;
if (!LookupAccountNameW (servername, domname, if (!LookupAccountNameW (machine, domname, psid, &sid_length,
psid, &sid_length, domain_name, &domname_len, &acc_type))
domain_name, &domname_len,
&acc_type))
{ {
print_win_error (GetLastError ()); print_win_error (GetLastError ());
fprintf(stderr, " (%ls)\n", domname); 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; got_curr_pgrp = TRUE;
printf ("%ls%s%ls:%s:%" PRIu32 ":\n", printf ("%ls%s%ls:%s:%" PRIu32 ":\n",
with_dom ? domain_name : L"", mach->with_dom ? domain_name : L"",
with_dom ? sep : "", mach->with_dom ? sep : "",
buffer[i].grpi2_name, buffer[i].grpi2_name,
put_sid (psid), put_sid (psid),
(unsigned int) (id_offset + gid)); (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); 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 static int
usage (FILE * stream) usage (FILE * stream)
{ {
fprintf (stream, fprintf (stream,
"Usage: %s [OPTION]...\n" "Usage: %s [OPTION]...\n"
"\n" "\n"
"Print /etc/group file to stdout\n" "Write /etc/group-like output to stdout\n"
"\n" "\n"
"Options:\n" "Options:\n"
"\n" "\n"
" -l,--local [machine[,offset]]\n" " -l,--local [machine] print local groups\n"
" print local groups with gid offset offset\n"
" (from local machine if no machine specified)\n" " (from local machine if no machine specified)\n"
" -L,--Local [machine[,offset]]\n" " -L,--Local machine ditto, but generate groupname with machine prefix\n"
" ditto, but generate groupname with machine prefix\n" " -d,--domain [domain] print domain groups\n"
" -d,--domain [domain[,offset]]\n"
" print domain groups with gid offset offset\n"
" (from current domain if no domain specified)\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 print current group\n"
" -C,--Current ditto, but generate groupname with machine or\n" " -S,--separator char for -l use character char as domain\\group\n"
" domain prefix\n" " separator in groupname instead of default '%s'\n"
" -S,--separator char for -L, -D, -C use character char as domain\\group\n" " -o,--id-offset offset change the default offset (0x10000) added to\n"
" separator in groupname instead of the default '\\'\n" " gids of foreign machine accounts.\n"
" -o,--id-offset offset change the default offset (10000) added to gids\n"
" in domain or foreign server accounts.\n"
" -g,--group groupname only return information for the specified group\n" " -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" " -b,--no-builtin don't print BUILTIN groups\n"
" -U,--unix grouplist additionally print UNIX groups when using -l or -L\n" " -U,--unix grouplist print UNIX groups when using -l on a UNIX Samba\n"
" on a UNIX Samba server\n" " server. grouplist is a comma-separated list of\n"
" grouplist is a comma-separated list of groupnames\n" " groupnames or gid ranges (root,-25,50-100).\n"
" or gid ranges (root,-25,50-100).\n"
" (enumerating large ranges can take a long time!)\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" " -h,--help print this message\n"
" -v,--version print version information and exit\n" " -v,--version print version information and exit\n"
"\n" "\n"
"Default is to print local groups on stand-alone machines, plus domain\n" "Default is to print local groups on stand-alone machines, plus domain\n"
"groups on domain controllers and domain member machines.\n" "groups on domain controllers and domain member machines.\n\n"
"\n", program_invocation_short_name); "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; return 1;
} }
@ -699,44 +542,20 @@ print_version ()
strrchr (__DATE__, ' ') + 1); 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 int
main (int argc, char **argv) main (int argc, char **argv)
{ {
int print_domlist = 0; int print_domlist = 0;
domlist_t domlist[32]; domlist_t domlist[32];
char *opt, *p, *ep; char *opt, *p;
int print_current = 0; int print_current = 0;
int print_system = 0;
int print_builtin = 1; int print_builtin = 1;
char *print_unix = NULL; char *print_unix = NULL;
const char *sep_char = "\\"; const char *sep_char = (const char *) cygwin_internal (CW_GETNSSSEP);
DWORD id_offset = 10000, off; DWORD id_offset = 0x10000, off;
int c, i; int c, i;
char *disp_groupname = NULL; char *disp_groupname = NULL;
BOOL in_domain; //BOOL in_domain;
int optional_args = 0; int optional_args = 0;
if (!isatty (1)) if (!isatty (1))
@ -746,22 +565,21 @@ main (int argc, char **argv)
setlocale (LC_CTYPE, ""); setlocale (LC_CTYPE, "");
if (!strcmp (setlocale (LC_CTYPE, NULL), "C")) if (!strcmp (setlocale (LC_CTYPE, NULL), "C"))
setlocale (LC_CTYPE, "en_US.UTF-8"); setlocale (LC_CTYPE, "en_US.UTF-8");
in_domain = fetch_primary_domain ();
fetch_current_pgrp_sid (); fetch_current_pgrp_sid ();
if (argc == 1) if (argc == 1)
{ {
print_special_by_sid (&sid_nt_auth, 1, SECURITY_LOCAL_SYSTEM_RID, int enums = ENUM_PRIMARY | ENUM_LOCAL | ENUM_BUILTIN;
0, 0, 0, 0, 0, 0, 0); uintptr_t ticket = cygwin_internal (CW_SETENT, TRUE, enums, NULL);
if (in_domain) if (ticket)
{ {
if (!enum_local_groups (TRUE, NULL, sep_char, id_offset, struct group *grp;
disp_groupname, print_builtin, 0))
enum_groups (TRUE, NULL, sep_char, id_offset, disp_groupname, 0); 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; return 0;
} }
@ -799,15 +617,10 @@ main (int argc, char **argv)
domlist[i].str); domlist[i].str);
goto skip; goto skip;
} }
if (!(domlist[print_domlist].str = opt)) domlist[print_domlist].str = opt;
print_system = 1;
domlist[print_domlist].id_offset = UINT32_MAX;
if (opt && (p = strchr (opt, ','))) if (opt && (p = strchr (opt, ',')))
{ {
if (p == opt if (p == opt)
|| !isdigit ((unsigned char) p[1])
|| (domlist[print_domlist].id_offset = strtol (p + 1, &ep, 10)
, *ep))
{ {
fprintf (stderr, "%s: Malformed machine,offset string '%s'. " fprintf (stderr, "%s: Malformed machine,offset string '%s'. "
"Skipping...\n", program_invocation_short_name, opt); "Skipping...\n", program_invocation_short_name, opt);
@ -815,15 +628,15 @@ main (int argc, char **argv)
} }
*p = '\0'; *p = '\0';
} }
domlist[print_domlist++].with_dom = (c == 'D' || c == 'L'); domlist[print_domlist++].with_dom = (c == 'L');
skip: skip:
break; break;
case 'S': case 'S':
sep_char = optarg; sep_char = optarg;
if (strlen (sep_char) > 1) if (strlen (sep_char) > 1)
{ {
fprintf (stderr, "%s: Only one character allowed as domain\\user " fprintf (stderr, "%s: Only one ASCII character allowed as "
"separator character.\n", "domain\\user separator character.\n",
program_invocation_short_name); program_invocation_short_name);
return 1; return 1;
} }
@ -838,8 +651,6 @@ skip:
print_unix = optarg; print_unix = optarg;
break; break;
case 'c': case 'c':
sep_char = NULL;
/*FALLTHRU*/
case 'C': case 'C':
print_current = 1; print_current = 1;
break; break;
@ -876,34 +687,77 @@ skip:
exit (1); exit (1);
} }
/* Get 'system' group */ struct group *pgrp = NULL;
if (!disp_groupname && print_system && print_builtin && print_domlist) if (print_current)
{ pgrp = (struct group *) cygwin_internal (CW_GETGRSID, TRUE, curr_pgrp.psid);
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);
}
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) for (i = 0; i < print_domlist; ++i)
{ {
DWORD my_off = (domlist[i].domain || domlist[i].str) if (domlist[i].domain)
? 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 && print_unix) if (domlist[i].str)
enum_unix_groups (domlist + i, sep_char, my_off, print_unix); {
enum_groups (domlist[i].domain, domlist + i, sep_char, my_off, enums |= ENUM_TDOMS;
disp_groupname, print_current); t += mbstowcs (t, domlist[i].str, 257);
if (my_off) *t++ = L'\0';
off += id_offset; }
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) 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; return 0;
} }

View File

@ -1,7 +1,7 @@
/* mkpasswd.c: /* mkpasswd.c:
Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2008, 2009, 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. This file is part of Cygwin.
@ -21,6 +21,7 @@
#include <inttypes.h> #include <inttypes.h>
#include <getopt.h> #include <getopt.h>
#include <io.h> #include <io.h>
#include <pwd.h>
#include <sys/fcntl.h> #include <sys/fcntl.h>
#include <sys/cygwin.h> #include <sys/cygwin.h>
#include <cygwin/version.h> #include <cygwin/version.h>
@ -31,7 +32,6 @@
#include <ntsecapi.h> #include <ntsecapi.h>
#include <dsgetdc.h> #include <dsgetdc.h>
#include <ntdef.h> #include <ntdef.h>
#include "loadlib.h"
#define print_win_error(x) _print_win_error(x, __LINE__) #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 typedef struct
{ {
char *str; char *str;
DWORD id_offset;
BOOL domain; BOOL domain;
BOOL with_dom; BOOL with_dom;
} domlist_t; } domlist_t;
@ -70,31 +69,6 @@ _print_win_error(DWORD code, int line)
line, (unsigned int) code); 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 * static char *
put_sid (PSID sid) put_sid (PSID sid)
{ {
@ -150,72 +124,10 @@ fetch_current_user_sid ()
} }
static void static void
current_user (const char *sep, const char *passed_home_path, DWORD id_offset, enum_unix_users (domlist_t *mach, const char *sep, 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,
char *unix_user_list) char *unix_user_list)
{ {
WCHAR machine[INTERNET_MAX_HOST_NAME_LENGTH + 1]; 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 } }; SID_IDENTIFIER_AUTHORITY auth = { { 0, 0, 0, 0, 0, 22 } };
char *ustr, *user_list; char *ustr, *user_list;
WCHAR user[UNLEN + sizeof ("Unix User\\") + 1]; 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]; char psid_buffer[MAX_SID_LEN];
SID_NAME_USE acc_type; SID_NAME_USE acc_type;
if (!d_or_m) int ret = mbstowcs (machine, mach->str, INTERNET_MAX_HOST_NAME_LENGTH + 1);
return;
int ret = mbstowcs (machine, d_or_m, INTERNET_MAX_HOST_NAME_LENGTH + 1);
if (ret < 1 || ret >= 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", fprintf (stderr, "%s: Invalid machine name '%s'. Skipping...\n",
program_invocation_short_name, d_or_m); program_invocation_short_name, mach->str);
return; return;
} }
servername = machine;
if (!AllocateAndInitializeSid (&auth, 2, 1, 0, 0, 0, 0, 0, 0, 0, &psid)) if (!AllocateAndInitializeSid (&auth, 2, 1, 0, 0, 0, 0, 0, 0, 0, &psid))
return; 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) if (ret < 1 || ret >= UNLEN + 1)
fprintf (stderr, "%s: Invalid user name '%s'. Skipping...\n", fprintf (stderr, "%s: Invalid user name '%s'. Skipping...\n",
program_invocation_short_name, ustr); program_invocation_short_name, ustr);
else if (LookupAccountNameW (servername, user, else if (LookupAccountNameW (machine, user,
psid = (PSID) psid_buffer, psid = (PSID) psid_buffer,
(sidlen = MAX_SID_LEN, &sidlen), (sidlen = MAX_SID_LEN, &sidlen),
dom, dom,
(dlen = MAX_DOMAIN_NAME_LEN + 1, &dlen), (dlen = MAX_DOMAIN_NAME_LEN + 1, &dlen),
&acc_type)) &acc_type))
printf ("%s%s%ls:unused:%" PRIu32 ":99999:,%s::\n", printf ("%s%s%ls:unused:%" PRIu32 ":99999:,%s::\n",
with_dom ? "Unix User" : "", mach->with_dom ? "Unix_User" : "",
with_dom ? sep : "", mach->with_dom ? sep : "",
user + 10, user + 10,
(unsigned int) (id_offset + (unsigned int) (id_offset +
*GetSidSubAuthority (psid, *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) *GetSidSubAuthority (psid, *GetSidSubAuthorityCount(psid) - 1)
= start; = start;
if (LookupAccountSidW (servername, psid, if (LookupAccountSidW (machine, psid,
user, (ulen = GNLEN + 1, &ulen), user, (ulen = GNLEN + 1, &ulen),
dom, dom,
(dlen = MAX_DOMAIN_NAME_LEN + 1, &dlen), (dlen = MAX_DOMAIN_NAME_LEN + 1, &dlen),
&acc_type) &acc_type)
&& !iswdigit (user[0])) && !iswdigit (user[0]))
printf ("%s%s%ls:unused:%" PRIu32 ":99999:,%s::\n", printf ("%s%s%ls:unused:%" PRIu32 ":99999:,%s::\n",
with_dom ? "Unix User" : "", mach->with_dom ? "Unix_User" : "",
with_dom ? sep : "", mach->with_dom ? sep : "",
user, user,
(unsigned int) (id_offset + start), (unsigned int) (id_offset + start),
put_sid (psid)); put_sid (psid));
@ -313,36 +221,23 @@ enum_unix_users (domlist_t *dom_or_machine, const char *sep, DWORD id_offset,
} }
static int static int
enum_users (BOOL domain, domlist_t *dom_or_machine, const char *sep, enum_users (domlist_t *mach, const char *sep, const char *passed_home_path,
const char *passed_home_path, DWORD id_offset, char *disp_username, DWORD id_offset, char *disp_username, int print_current)
int print_current)
{ {
WCHAR machine[INTERNET_MAX_HOST_NAME_LENGTH + 1]; 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; USER_INFO_3 *buffer;
DWORD entriesread = 0; DWORD entriesread = 0;
DWORD totalentries = 0; DWORD totalentries = 0;
DWORD resume_handle = 0; DWORD resume_handle = 0;
DWORD rc; DWORD rc;
WCHAR uni_name[UNLEN + 1]; 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); fprintf (stderr, "%s: Invalid machine name '%s'. Skipping...\n",
if (servername == (PWCHAR) -1) program_invocation_short_name, mach->str);
return 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;
} }
do do
@ -352,7 +247,7 @@ enum_users (BOOL domain, domlist_t *dom_or_machine, const char *sep,
if (disp_username != NULL) if (disp_username != NULL)
{ {
mbstowcs (uni_name, disp_username, UNLEN + 1); mbstowcs (uni_name, disp_username, UNLEN + 1);
rc = NetUserGetInfo (servername, (LPWSTR) &uni_name, 3, rc = NetUserGetInfo (machine, (LPWSTR) &uni_name, 3,
(void *) &buffer); (void *) &buffer);
entriesread = 1; entriesread = 1;
/* Avoid annoying error messages just because the user hasn't been /* 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; return 0;
} }
else else
rc = NetUserEnum (servername, 3, FILTER_NORMAL_ACCOUNT, rc = NetUserEnum (machine, 3, FILTER_NORMAL_ACCOUNT,
(void *) &buffer, MAX_PREFERRED_LENGTH, (void *) &buffer, MAX_PREFERRED_LENGTH,
&entriesread, &totalentries, &resume_handle); &entriesread, &totalentries, &resume_handle);
switch (rc) switch (rc)
@ -407,7 +302,7 @@ enum_users (BOOL domain, domlist_t *dom_or_machine, const char *sep,
stpcpy (homedir_psx, passed_home_path), stpcpy (homedir_psx, passed_home_path),
PATH_MAX - strlen (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, psid, &sid_length, domain_name,
&domname_len, &acc_type)) &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]; WCHAR domname[MAX_DOMAIN_NAME_LEN + UNLEN + 2];
wcscpy (domname, domain || !servername wcscpy (domname, machine);
? domain_name : servername);
wcscat (domname, L"\\"); wcscat (domname, L"\\");
wcscat (domname, buffer[i].usri3_name); wcscat (domname, buffer[i].usri3_name);
sid_length = MAX_SID_LEN; sid_length = MAX_SID_LEN;
domname_len = sizeof (domname); domname_len = sizeof (domname);
if (!LookupAccountNameW (servername, domname, psid, if (!LookupAccountNameW (machine, domname, psid,
&sid_length, domain_name, &sid_length, domain_name,
&domname_len, &acc_type)) &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 printf ("%ls%s%ls:unused:%" PRIu32 ":%" PRIu32
":%ls%sU-%ls\\%ls,%s:%s:/bin/bash\n", ":%ls%sU-%ls\\%ls,%s:%s:/bin/bash\n",
with_dom ? domain_name : L"", mach->with_dom ? domain_name : L"",
with_dom ? sep : "", mach->with_dom ? sep : "",
buffer[i].usri3_name, buffer[i].usri3_name,
(unsigned int) (id_offset + uid), (unsigned int) (id_offset + uid),
(unsigned int) (id_offset + gid), (unsigned int) (id_offset + gid),
@ -463,98 +357,49 @@ enum_users (BOOL domain, domlist_t *dom_or_machine, const char *sep,
return 0; 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 static int
usage (FILE * stream) usage (FILE * stream)
{ {
fprintf (stream, fprintf (stream,
"Usage: %s [OPTIONS]...\n" "Usage: %s [OPTIONS]...\n"
"\n" "\n"
"Print /etc/passwd file to stdout\n" "Write /etc/passwd-like output to stdout\n"
"\n" "\n"
"Options:\n" "Options:\n"
"\n" "\n"
" -l,--local [machine[,offset]]\n" " -l,--local [machine] print local user accounts with uid offset offset\n"
" print local user accounts with uid offset offset\n"
" (from local machine if no machine specified)\n" " (from local machine if no machine specified)\n"
" -L,--Local [machine[,offset]]\n" " -L,--Local machine ditto, but generate username with machine prefix\n"
" ditto, but generate username with machine prefix\n" " -d,--domain [domain] print domain accounts with uid offset offset\n"
" -d,--domain [domain[,offset]]\n"
" print domain accounts with uid offset offset\n"
" (from current domain if no domain specified)\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 print current user\n"
" -C,--Current ditto, but generate username with machine or\n" " -S,--separator char for -l use character char as domain\\user\n"
" domain prefix\n" " separator in username instead of the default '%s'\n"
" -S,--separator char for -L, -D, -C use character char as domain\\user\n" " -o,--id-offset offset change the default offset (0x10000) added to uids\n"
" separator in username instead of the default '\\'\n"
" -o,--id-offset offset change the default offset (10000) added to uids\n"
" in domain or foreign server accounts.\n" " in domain or foreign server accounts.\n"
" -u,--username username only return information for the specified user\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" " -p,--path-to-home path use specified path instead of user account home dir\n"
" or /home prefix\n" " or /home prefix\n"
" -U,--unix userlist additionally print UNIX users when using -l or -L\n" " -U,--unix userlist print UNIX users when using -l on a UNIX Samba\n"
" on a UNIX Samba server\n" " server. userlist is a comma-separated list of\n"
" userlist is a comma-separated list of usernames\n" " usernames or uid ranges (root,-25,50-100).\n"
" or uid ranges (root,-25,50-100).\n"
" (enumerating large ranges can take a long time!)\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" " -h,--help displays this message\n"
" -V,--version version information and exit\n" " -V,--version version information and exit\n"
"\n" "\n"
"Default is to print local accounts on stand-alone machines, domain accounts\n" "Default is to print local accounts on stand-alone machines, domain accounts\n"
"on domain controllers and domain member machines.\n" "on domain controllers and domain member machines.\n\n"
"\n", program_invocation_short_name); "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; return 1;
} }
static struct option longopts[] = { static struct option longopts[] = {
{"no-builtin", no_argument, NULL, 'b'},
{"current", no_argument, NULL, 'c'}, {"current", no_argument, NULL, 'c'},
{"Current", no_argument, NULL, 'C'}, {"Current", no_argument, NULL, 'C'},
{"domain", optional_argument, NULL, 'd'}, {"domain", optional_argument, NULL, 'd'},
@ -574,7 +419,7 @@ static struct option longopts[] = {
{0, no_argument, NULL, 0} {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 static void
print_version () print_version ()
@ -590,66 +435,6 @@ print_version ()
strrchr (__DATE__, ' ') + 1); 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 int
main (int argc, char **argv) main (int argc, char **argv)
{ {
@ -657,13 +442,14 @@ main (int argc, char **argv)
domlist_t domlist[32]; domlist_t domlist[32];
char *opt, *p, *ep; char *opt, *p, *ep;
int print_current = 0; int print_current = 0;
int print_builtin = 1;
char *print_unix = NULL; char *print_unix = NULL;
const char *sep_char = "\\"; const char *nss_sep = (const char *) cygwin_internal (CW_GETNSSSEP);
DWORD id_offset = 10000, off; const char *sep_char = nss_sep;
DWORD id_offset = 0x10000, off;
int c, i; int c, i;
char *disp_username = NULL; char *disp_username = NULL;
char passed_home_path[PATH_MAX]; char passed_home_path[PATH_MAX];
BOOL in_domain;
int optional_args = 0; int optional_args = 0;
passed_home_path[0] = '\0'; passed_home_path[0] = '\0';
@ -674,18 +460,23 @@ main (int argc, char **argv)
setlocale (LC_CTYPE, ""); setlocale (LC_CTYPE, "");
if (!strcmp (setlocale (LC_CTYPE, NULL), "C")) if (!strcmp (setlocale (LC_CTYPE, NULL), "C"))
setlocale (LC_CTYPE, "en_US.UTF-8"); setlocale (LC_CTYPE, "en_US.UTF-8");
in_domain = fetch_primary_domain ();
fetch_current_user_sid (); fetch_current_user_sid ();
if (argc == 1) if (argc == 1)
{ {
enum_std_accounts (); int enums = ENUM_PRIMARY | ENUM_LOCAL | ENUM_BUILTIN;
if (in_domain) uintptr_t ticket = cygwin_internal (CW_SETENT, FALSE, enums, NULL);
enum_users (TRUE, NULL, sep_char, passed_home_path, 10000, if (ticket)
disp_username, 0); {
else struct passwd *pwd;
enum_users (FALSE, NULL, sep_char, passed_home_path, 0,
disp_username, 0); 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; return 0;
} }
@ -724,13 +515,9 @@ main (int argc, char **argv)
goto skip; goto skip;
} }
domlist[print_domlist].str = opt; domlist[print_domlist].str = opt;
domlist[print_domlist].id_offset = UINT32_MAX;
if (opt && (p = strchr (opt, ','))) if (opt && (p = strchr (opt, ',')))
{ {
if (p == opt if (p == opt)
|| !isdigit ((unsigned char) p[1])
|| (domlist[print_domlist].id_offset = strtol (p + 1, &ep, 10)
, *ep))
{ {
fprintf (stderr, "%s: Malformed domain,offset string '%s'. " fprintf (stderr, "%s: Malformed domain,offset string '%s'. "
"Skipping...\n", program_invocation_short_name, opt); "Skipping...\n", program_invocation_short_name, opt);
@ -738,15 +525,15 @@ main (int argc, char **argv)
} }
*p = '\0'; *p = '\0';
} }
domlist[print_domlist++].with_dom = (c == 'D' || c == 'L'); domlist[print_domlist++].with_dom = (c == 'L');
skip: skip:
break; break;
case 'S': case 'S':
sep_char = optarg; sep_char = optarg;
if (strlen (sep_char) > 1) if (strlen (sep_char) > 1)
{ {
fprintf (stderr, "%s: Only one character allowed as domain\\user " fprintf (stderr, "%s: Only one ASCII character allowed as "
"separator character.\n", "domain\\user separator character.\n",
program_invocation_short_name); program_invocation_short_name);
return 1; return 1;
} }
@ -761,19 +548,14 @@ skip:
print_unix = optarg; print_unix = optarg;
break; break;
case 'c': case 'c':
sep_char = NULL;
/*FALLTHRU*/
case 'C': case 'C':
print_current = 1; print_current = 1;
break; break;
case 'o': case 'o':
id_offset = strtoul (optarg, &ep, 10); id_offset = strtoul (optarg, &ep, 10);
if (*ep) break;
{ case 'b':
fprintf (stderr, "%s: Malformed offset '%s'. " print_builtin = 0;
"Skipping...\n", program_invocation_short_name, optarg);
return 1;
}
break; break;
case 'p': case 'p':
if (optarg[0] != '/') if (optarg[0] != '/')
@ -814,24 +596,91 @@ skip:
exit (1); 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) for (i = 0; i < print_domlist; ++i)
{ {
DWORD my_off = (domlist[i].domain || domlist[i].str) if (domlist[i].domain)
? domlist[i].id_offset != UINT_MAX {
? domlist[i].id_offset : off : 0; if (domlist[i].str)
if (!domlist[i].domain && domlist[i].str && print_unix) {
enum_unix_users (domlist + i, sep_char, my_off, print_unix); enums |= ENUM_TDOMS;
if (!my_off && !disp_username) t += mbstowcs (t, domlist[i].str, 257);
enum_std_accounts (); *t++ = L'\0';
enum_users (domlist[i].domain, domlist + i, sep_char, passed_home_path, }
my_off, disp_username, print_current); else
if (my_off) enums |= ENUM_PRIMARY;
off += id_offset; }
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) 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; return 0;
} }

View File

@ -875,89 +875,77 @@ Write minidump from WIN32PID to FILENAME.dmp
<screen> <screen>
Usage: mkgroup [OPTION]... Usage: mkgroup [OPTION]...
Print /etc/group file to stdout Write /etc/group-like output to stdout
Options: Options:
-l,--local [machine[,offset]] -l,--local [machine] print local groups
print local groups with gid offset offset
(from local machine if no machine specified) (from local machine if no machine specified)
-L,--Local [machine[,offset]] -L,--Local machine ditto, but generate groupname with machine prefix
ditto, but generate groupname with machine prefix -d,--domain [domain] print domain groups
-d,--domain [domain[,offset]]
print domain groups with gid offset offset
(from current domain if no domain specified) (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 print current group
-C,--Current ditto, but generate groupname with machine or -S,--separator char for -l use character char as domain\group
domain prefix separator in groupname instead of default '+'
-S,--separator char for -L, -D, -C use character char as domain\group -o,--id-offset offset change the default offset (0x10000) added to
separator in groupname instead of the default '\' gids of foreign machine accounts.
-o,--id-offset offset change the default offset (10000) added to gids
in domain or foreign server accounts.
-g,--group groupname only return information for the specified group -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 -b,--no-builtin don't print BUILTIN groups
-U,--unix grouplist additionally print UNIX groups when using -l or -L -U,--unix grouplist print UNIX groups when using -l on a UNIX Samba
on a UNIX Samba server server. grouplist is a comma-separated list of
grouplist is a comma-separated list of groupnames groupnames or gid ranges (root,-25,50-100).
or gid ranges (root,-25,50-100). (enumerating large ranges can take a long time!)
(enumerating large ranges can take a long time!)
-s,--no-sids (ignored)
-u,--users (ignored)
-h,--help print this message -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 Default is to print local groups on stand-alone machines, plus domain
groups on domain controllers and domain member machines. 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> </screen>
<para>The <command>mkgroup</command> program can be used to help configure <para>The <command>mkgroup</command> program can be used to create a local
Cygwin by creating a <filename>/etc/group</filename> file. Its use is <filename>/etc/group</filename> file. Cygwin doesn't need this file,
essential to include Windows security information.</para> 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 <para>Note that this information is static, in contrast to the information
create a default <filename>/etc/group</filename>. This should be automatically gathered by Cygwin from the Windows account databases. If
sufficient in most circumstances. However, especially when working in a you change the group information on your system, you'll need to regenerate
multi-domain environment, you can use <command>mkgroup</command> manually the group file for it to have the new information.</para>
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. If you change the group <para>By default, the information generated by <command>mkgroup</command>
information in your system, you'll need to regenerate the group file for is equivalent to the information generated by Cygwin itself. The
it to have the new information.</para> <literal>-d</literal> and <literal>-l/-L</literal> options allow you to
specify where the information comes from, some domain, or the local SAM
<para>The <literal>-d/-D</literal> and <literal>-l/-L</literal> options of a machine. Note that you can only enumerate accounts from trusted
allow you to specify where the information comes from, the local SAM of a domains. Any non-trusted domain will be ignored. Access-restrictions
machine or from the domain, or both. With the <literal>-d/-D</literal> of your current account apply. The <literal>-l/-L</literal> when used
options the program contacts a Domain Controller, which my be unreachable with a machine name, tries to contact that machine to enumerate local
or have restricted access. Comma-separated from the machine or domain, groups of other machines, typically outside of domains. This scenario
you can specify an offset which is used as base added to the group's RID cannot be covered by Cygwin's account automatism. If you want to use
to compute the gid (offset + RID = gid). This allows you to create the the <literal>-L</literal> option, but you don't like the default
same gids every time you re-run <command>mkgroup</command>. For very domain/group separator from <filename>/etc/nsswitch.conf</filename>,
simple needs, an entry for the current user's group can be created by you can specify another separator using the <literal>-S</literal> option,
using the option <literal>-c</literal> or <literal>-C</literal>. If you for instance:</para>
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>
<example id="utils-mkgroup-ex"> <example id="utils-mkgroup-ex">
<title>Setting up group entry for current user with different <title>Setting up group entry for current user with different
domain/group separator</title> domain/group separator</title>
<screen> <screen>
<prompt>$</prompt> <userinput>mkgroup -C -S+ &gt; /etc/group</userinput> <prompt>$</prompt> <userinput>mkgroup -L server1 -S= &gt; /etc/group</userinput>
<prompt>$</prompt> <userinput>cat /etc/group</userinput>
DOMAIN+my_group:S-1-5-21-2913048732-1697188782-3448811101-1144:11144:
</screen> </screen>
</example> </example>
<para>The <literal>-o</literal> option allows for special cases (such as <para>For very simple needs, an entry for the current user's group can be
multiple domains) where the GIDs might match otherwise. The 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. <literal>-g</literal> option only prints the information for one group.
The <literal>-U</literal> option allows you to enumerate the standard The <literal>-U</literal> option allows you to enumerate the standard
UNIX groups on a Samba machine. It's used together with <literal>-l 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> <screen>
Usage: mkpasswd [OPTIONS]... Usage: mkpasswd [OPTIONS]...
Print /etc/passwd file to stdout Write /etc/passwd-like output to stdout
Options: Options:
-l,--local [machine[,offset]] -l,--local [machine] print local user accounts with uid offset offset
print local user accounts with uid offset offset
(from local machine if no machine specified) (from local machine if no machine specified)
-L,--Local [machine[,offset]] -L,--Local machine ditto, but generate username with machine prefix
ditto, but generate username with machine prefix -d,--domain [domain] print domain accounts with uid offset offset
-d,--domain [domain[,offset]]
print domain accounts with uid offset offset
(from current domain if no domain specified) (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 print current user
-C,--Current ditto, but generate username with machine or -S,--separator char for -l use character char as domain\user
domain prefix separator in username instead of the default '+'
-S,--separator char for -L, -D, -C use character char as domain\user -o,--id-offset offset change the default offset (0x10000) added to uids
separator in username instead of the default '\'
-o,--id-offset offset change the default offset (10000) added to uids
in domain or foreign server accounts. in domain or foreign server accounts.
-u,--username username only return information for the specified user -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 -p,--path-to-home path use specified path instead of user account home dir
or /home prefix or /home prefix
-U,--unix userlist additionally print UNIX users when using -l or -L\ -U,--unix userlist print UNIX users when using -l on a UNIX Samba
on a UNIX Samba server server. userlist is a comma-separated list of
userlist is a comma-separated list of usernames usernames or uid ranges (root,-25,50-100).
or uid ranges (root,-25,50-100).
(enumerating large ranges can take a long time!) (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 -h,--help displays this message
-V,--version version information and exit -V,--version version information and exit
Default is to print local accounts on stand-alone machines, domain accounts Default is to print local accounts on stand-alone machines, domain accounts
on domain controllers and domain member machines. 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> </screen>
<para>The <command>mkpasswd</command> program can be used to help configure <para>The <command>mkpasswd</command> program can be used to create a
Cygwin by creating a <filename>/etc/passwd</filename> from your system <filename>/etc/passwd</filename> file. Cygwin doesn't need this file,
information. Its use is essential to include Windows security because it reads user information from the Windows account databases,
information. However, the actual passwords are determined by Windows, not but you can add an <filename>/etc/group</filename> file for instance, if
by the content of <filename>/etc/passwd</filename>.</para> your machine is often disconnected from its domain controller.</para>
<para>The command is initially called by <command>setup.exe</command> to <para>Note that this information is static, in contrast to the information
create a default <filename>/etc/passwd</filename>. This should be automatically gathered by Cygwin from the Windows account databases. If
sufficient in most circumstances. However, especially when working in a you change the user information on your system, you'll need to regenerate
multi-domain environment, you can use <command>mkpasswd</command> the passwd file for it to have the new information.</para>
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. If you change the user <para>By default, the information generated by <command>mkpasswd</command>
information in your system, you'll need to regenerate the passwd file for is equivalent to the information generated by Cygwin itself. The
it to have the new information.</para> <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 <para>For very simple needs, an entry for the current user can be created
allow you to specify where the information comes from, the local machine by using the option <literal>-c</literal>.</para>
or the domain (default or given), or both. With the
<literal>-d/-D</literal> options the program contacts the Domain <para>The <literal>-o</literal> option allows for special cases (such as
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
multiple domains) where the UIDs might match otherwise. The multiple domains) where the UIDs might match otherwise. The
<literal>-p</literal> option causes <command>mkpasswd</command> to use <literal>-p</literal> option causes <command>mkpasswd</command> to use
the specified prefix instead of the account home dir or <literal>/home/ 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 to enumerate the standard UNIX users on a Samba machine. It's used
together with <literal>-l samba-server</literal> or <literal>-L together with <literal>-l samba-server</literal> or <literal>-L
samba-server</literal>. The normal UNIX users are usually not enumerated, 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> </sect2>