Enumerating Unix users and groups from Windows
Corinna Vinschen
corinna at vinschen.de
Fri Jul 25 15:11:16 GMT 2008
On Jul 25 16:28, Volker Lendecke wrote:
> On Thu, Jul 24, 2008 at 10:54:36AM +0200, Corinna Vinschen wrote:
> > For instance, when you call NetLocalGroupEnum on a Windows machine, you
> > get a list which contains accounts from different "domains" and with
> > different base SIDs, too. Calling LookupAccountName afterwards shows
> > that clearly:
> >
> > NetLocalGroupEnum (MACHINE); LookupAccountName (Name)
> >
> > Name RID Domain SID
> > ----------------- ---- ------- -------------------------------
> > Administrators 544 BUILTIN S-1-5-32-544
> > Backup Operators 551 BUILTIN S-1-5-32-551
> > Guests 546 BUILTIN S-1-5-32-546
> > [...]
> > Users 545 BUILTIN S-1-5-32-545
> > HelpServicesGroup 1001 MACHINE S-1-5-21-12345-67890-76543-1001
> >
> > So it enumerates BUILTIN accounts as well as MACHINE accounts.
> >
> > Samba could return the unix groups as local groups as well:
>
> Well, not quite. Windows always has its SAM (the
> S-1-5-21-12345-6... thingy), and S-1-5-32-xx. Samba does
> this as well, so you should see the same output from a Samba
> box.
That's not what I see. The NetLocalGroupEnum function returns with
success but with an empty group list when called on a Samba server.
This is with 3.0.30.
> Those two domains are expected by the Win32 client API,
> not more. We could try to experiment what Windows says when
> we expand the samr_EnumDomains RPC call. What's the easiest
> way to call the NetEnumUsers API call? Some vbs script? :-)
Sorry, but I'm Windows scripting illiterate. What about just installing
Cygwin and building the below code with
gcc -o nlge nlge.c -lnetapi32
Corinna
=== SNIP ===
#include <stdio.h>
#include <windows.h>
#include <lm.h>
char *
put_sid (PSID psid)
{
static char s[256];
char t[32];
DWORD i;
strcpy (s, "S-1-");
sprintf (t, "%u", GetSidIdentifierAuthority (psid)->Value[5]);
strcat (s, t);
for (i = 0; i < *GetSidSubAuthorityCount (psid); ++i)
{
sprintf(t, "-%lu", *GetSidSubAuthority (psid, i));
strcat (s, t);
}
return s;
}
void
enum_local_groups (char *server)
{
WCHAR servername[256];
LOCALGROUP_INFO_0 *buffer;
DWORD entriesread = 0;
DWORD totalentries = 0;
DWORD resume_handle = 0;
DWORD rc, i;
if (!server)
return;
mbstowcs (servername, server, 256);
do
{
rc = NetLocalGroupEnum (servername, 0, (void *) &buffer,
MAX_PREFERRED_LENGTH, &entriesread,
&totalentries, &resume_handle);
if (rc != ERROR_MORE_DATA && rc != ERROR_SUCCESS)
{
fprintf (stderr, "NetLocalGroupEnum error %lu\n", rc);
break;
}
for (i = 0; i < entriesread; i++)
{
WCHAR domain_name[256];
DWORD domname_len = 256;
char psid_buffer[40];
PSID psid = (PSID) psid_buffer;
DWORD sid_length = 40;
SID_NAME_USE acc_type;
if (!LookupAccountNameW (servername, buffer[i].lgrpi0_name, psid,
&sid_length, domain_name, &domname_len,
&acc_type))
{
fprintf (stderr, "LookupAccountNameW (%ls) error %lu\n",
buffer[i].lgrpi0_name, GetLastError ());
continue;
}
else if (acc_type == SidTypeDomain)
{
WCHAR domname[512];
wcscpy (domname, domain_name);
wcscat (domname, L"\\");
wcscat (domname, buffer[i].lgrpi0_name);
sid_length = 40;
domname_len = 256;
if (!LookupAccountNameW (servername, domname,
psid, &sid_length,
domain_name, &domname_len,
&acc_type))
{
fprintf (stderr, "LookupAccountNameW (%ls) error %lu\n",
domname, GetLastError ());
continue;
}
}
printf ("%ls\\%ls == %s\n", domain_name, buffer[i].lgrpi0_name,
put_sid (psid));
}
NetApiBufferFree (buffer);
}
while (rc == ERROR_MORE_DATA);
}
int
main (int argc, char **argv)
{
if (argc != 2)
{
fprintf (stderr, "usage: %s server\n", argv[0]);
return 1;
}
enum_local_groups (argv[1]);
return 0;
}
More information about the samba-technical
mailing list