* ldap.cc (cyg_ldap::fetch_posix_offset_for_domain): If domain name

has no dot, it's a Netbios name.  Change the search filter expression
	accordingly and filter by flatName.  Add comment.
	* uinfo.cc (cygheap_domain_info::init):  Gracefully handle NULL
	DnsDomainName and DomainSid members in DS_DOMAIN_TRUSTSW strutures.
	Add comment.  Fix comment preceeding fetching the mapping server
	from registry.
	(pwdgrp::fetch_account_from_file): Convert str to a local array.
	(fetch_posix_offset): New static function.
	(pwdgrp::fetch_account_from_windows): Add debug output in case
	LookupAccountSidW fails.  Simplify code by calling fetch_posix_offset
	where appropriate.  If LookupAccountSidW fails, check if the SID is
	one of the known trusted domains.  If so, create a more informative
	account entry.
This commit is contained in:
Corinna Vinschen 2014-02-13 14:04:03 +00:00
parent 5f51881a6d
commit 85b8256d2e
3 changed files with 110 additions and 61 deletions

View File

@ -1,3 +1,20 @@
2014-02-13 Corinna Vinschen <corinna@vinschen.de>
* ldap.cc (cyg_ldap::fetch_posix_offset_for_domain): If domain name
has no dot, it's a Netbios name. Change the search filter expression
accordingly and filter by flatName. Add comment.
* uinfo.cc (cygheap_domain_info::init): Gracefully handle NULL
DnsDomainName and DomainSid members in DS_DOMAIN_TRUSTSW strutures.
Add comment. Fix comment preceeding fetching the mapping server
from registry.
(pwdgrp::fetch_account_from_file): Convert str to a local array.
(fetch_posix_offset): New static function.
(pwdgrp::fetch_account_from_windows): Add debug output in case
LookupAccountSidW fails. Simplify code by calling fetch_posix_offset
where appropriate. If LookupAccountSidW fails, check if the SID is
one of the known trusted domains. If so, create a more informative
account entry.
2014-02-12 Corinna Vinschen <corinna@vinschen.de> 2014-02-12 Corinna Vinschen <corinna@vinschen.de>
* uinfo.cc (cygheap_pwdgrp::nss_init_line): Explicitely ignore a colon * uinfo.cc (cygheap_pwdgrp::nss_init_line): Explicitely ignore a colon

View File

@ -289,7 +289,10 @@ cyg_ldap::fetch_posix_offset_for_domain (PCWSTR domain)
ldap_value_freeW (val); ldap_value_freeW (val);
val = NULL; val = NULL;
} }
__small_swprintf (filter, L"(&(objectClass=trustedDomain)(name=%W))", domain); /* If domain name has no dot, it's a Netbios name. In that case, filter
by flatName rather than by name. */
__small_swprintf (filter, L"(&(objectClass=trustedDomain)(%W=%W))",
wcschr (domain, L'.') ? L"name" : L"flatName", domain);
if ((ret = ldap_search_stW (lh, rootdse, LDAP_SCOPE_SUBTREE, filter, if ((ret = ldap_search_stW (lh, rootdse, LDAP_SCOPE_SUBTREE, filter,
attr = tdom_attr, 0, &tv, &msg)) != LDAP_SUCCESS) attr = tdom_attr, 0, &tv, &msg)) != LDAP_SUCCESS)
{ {

View File

@ -777,22 +777,32 @@ cygheap_domain_info::init ()
{ {
/* Copy... */ /* Copy... */
tdom[idx].NetbiosDomainName = cwcsdup (td[idx].NetbiosDomainName); tdom[idx].NetbiosDomainName = cwcsdup (td[idx].NetbiosDomainName);
tdom[idx].DnsDomainName = cwcsdup (td[idx].DnsDomainName); /* DnsDomainName as well as DomainSid can be NULL. The reason is
usually a domain of type TRUST_TYPE_DOWNLEVEL. This can be an
old pre-AD domain, or a Netware domain, etc. If DnsDomainName
is NULL, just set it to NetbiosDomainName. This simplifies
subsequent code which doesn't have to check for a NULL pointer. */
tdom[idx].DnsDomainName = td[idx].DnsDomainName
? cwcsdup (td[idx].DnsDomainName)
: tdom[idx].NetbiosDomainName;
if (td[idx].DomainSid)
{
ULONG len = RtlLengthSid (td[idx].DomainSid); ULONG len = RtlLengthSid (td[idx].DomainSid);
tdom[idx].DomainSid = cmalloc_abort(HEAP_BUF, len); tdom[idx].DomainSid = cmalloc_abort(HEAP_BUF, len);
RtlCopySid (len, tdom[idx].DomainSid, td[idx].DomainSid); RtlCopySid (len, tdom[idx].DomainSid, td[idx].DomainSid);
}
/* ...and set PosixOffset to 0. This */ /* ...and set PosixOffset to 0. This */
tdom[idx].PosixOffset = 0; tdom[idx].PosixOffset = 0;
} }
NetApiBufferFree (td); NetApiBufferFree (td);
tdom_count = tdom_cnt; tdom_count = tdom_cnt;
} }
/* If we have NFS installed, we make use of a name mapping server. This /* If we have Microsoft Client for NFS installed, we make use of a name
can be either Active Directory to map uids/gids directly to Windows SIDs, mapping server. This can be either Active Directory to map uids/gids
or an AD LDS or other RFC 2307 compatible identity store. The name of directly to Windows SIDs, or an AD LDS or other RFC 2307 compatible
the mapping domain can be fetched from the registry key created by the identity store. The name of the mapping domain can be fetched from the
NFS client installation and entered by the user via nfsadmin or the registry key created by the NFS client installation and entered by the
"Services For NFS" MMC snap-in. user via nfsadmin or the "Services For NFS" MMC snap-in.
Reference: Reference:
http://blogs.technet.com/b/filecab/archive/2012/10/09/nfs-identity-mapping-in-windows-server-2012.aspx http://blogs.technet.com/b/filecab/archive/2012/10/09/nfs-identity-mapping-in-windows-server-2012.aspx
@ -1042,7 +1052,7 @@ pwdgrp::fetch_account_from_file (fetch_user_arg_t &arg)
NT_readline rl; NT_readline rl;
tmp_pathbuf tp; tmp_pathbuf tp;
char *buf = tp.c_get (); char *buf = tp.c_get ();
char *str = tp.c_get (); char str[128];
char *ret = NULL; char *ret = NULL;
/* Create search string. */ /* Create search string. */
@ -1066,6 +1076,34 @@ pwdgrp::fetch_account_from_file (fetch_user_arg_t &arg)
return NULL; return NULL;
} }
static ULONG
fetch_posix_offset (PDS_DOMAIN_TRUSTSW td, bool &ldap_open, cyg_ldap &cldap)
{
uint32_t id_val;
if (!td->PosixOffset && !(td->Flags & DS_DOMAIN_PRIMARY) && td->DomainSid)
{
if (!ldap_open && !(ldap_open = cldap.open (NULL)))
{
/* We're probably running under a local account, so we're not allowed
to fetch any information from AD beyond the most obvious. Never
mind, just fake a reasonable posix offset. */
id_val = cygheap->dom.lowest_tdo_posix_offset
- 0x01000000;
}
else
id_val = cldap.fetch_posix_offset_for_domain (td->DnsDomainName);
if (id_val)
{
td->PosixOffset = id_val;
if (id_val < cygheap->dom.lowest_tdo_posix_offset)
cygheap->dom.lowest_tdo_posix_offset = id_val;
}
}
return td->PosixOffset;
}
char * char *
pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group) pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group)
{ {
@ -1111,6 +1149,8 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group)
case SID_arg: case SID_arg:
sid = *arg.sid; sid = *arg.sid;
ret = LookupAccountSidW (NULL, sid, name, &nlen, dom, &dlen, &acc_type); ret = LookupAccountSidW (NULL, sid, name, &nlen, dom, &dlen, &acc_type);
if (!ret)
debug_printf ("LookupAccountSid(%W), %E", sid.string (sidstr));
break; break;
case NAME_arg: case NAME_arg:
/* Skip leading domain separator. This denotes an alias or well-known /* Skip leading domain separator. This denotes an alias or well-known
@ -1235,23 +1275,7 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group)
for (ULONG idx = 0; (td = cygheap->dom.trusted_domain (idx)); ++idx) for (ULONG idx = 0; (td = cygheap->dom.trusted_domain (idx)); ++idx)
{ {
/* If we don't have the PosixOffset of the domain, fetch it. fetch_posix_offset (td, ldap_open, cldap);
Skip primary domain. */
if (!td->PosixOffset && !(td->Flags & DS_DOMAIN_PRIMARY))
{
if (!ldap_open && !(ldap_open = cldap.open (NULL)))
id_val = cygheap->dom.lowest_tdo_posix_offset
- 0x01000000;
else
id_val =
cldap.fetch_posix_offset_for_domain (td->DnsDomainName);
if (id_val)
{
td->PosixOffset = id_val;
if (id_val < cygheap->dom.lowest_tdo_posix_offset)
cygheap->dom.lowest_tdo_posix_offset = id_val;
}
}
if (td->PosixOffset > posix_offset && td->PosixOffset <= arg.id) if (td->PosixOffset > posix_offset && td->PosixOffset <= arg.id)
posix_offset = td->PosixOffset; posix_offset = td->PosixOffset;
} }
@ -1344,34 +1368,11 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group)
for (ULONG idx = 0; for (ULONG idx = 0;
(td = cygheap->dom.trusted_domain (idx)); (td = cygheap->dom.trusted_domain (idx));
++idx) ++idx)
if (!wcscmp (dom, td->NetbiosDomainName))
{ {
if (wcscmp (dom, td->NetbiosDomainName))
continue;
domain = td->DnsDomainName; domain = td->DnsDomainName;
posix_offset = td->PosixOffset; posix_offset =
/* If we don't have the PosixOffset of the domain, fetch_posix_offset (td, ldap_open, cldap);
fetch it. */
if (!posix_offset)
{
if (!ldap_open && !(ldap_open = cldap.open (NULL)))
{
/* We're probably running under a local account,
so we're not allowed to fetch any information
from AD beyond the most obvious. Never mind,
just fake a reasonable posix offset. */
id_val = cygheap->dom.lowest_tdo_posix_offset
- 0x01000000;
}
else
id_val =
cldap.fetch_posix_offset_for_domain (domain);
if (id_val)
{
td->PosixOffset = posix_offset = id_val;
if (id_val < cygheap->dom.lowest_tdo_posix_offset)
cygheap->dom.lowest_tdo_posix_offset = id_val;
}
}
break; break;
} }
@ -1638,10 +1639,38 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group)
__small_swprintf (name = namebuf, L"%d", uid & UNIX_POSIX_MASK); __small_swprintf (name = namebuf, L"%d", uid & UNIX_POSIX_MASK);
name_style = fully_qualified; name_style = fully_qualified;
} }
else
{
if (sid_id_auth (sid) == 5 /* SECURITY_NT_AUTHORITY */
&& sid_sub_auth (sid, 0) == SECURITY_NT_NON_UNIQUE)
{
/* Check if we know the domain. If so, create a passwd/group
entry with domain prefix and RID as username. */
PDS_DOMAIN_TRUSTSW td = NULL;
sid_sub_auth_count (sid) = sid_sub_auth_count (sid) - 1;
for (ULONG idx = 0; (td = cygheap->dom.trusted_domain (idx)); ++idx)
if (td->DomainSid && RtlEqualSid (sid, td->DomainSid))
{
domain = td->NetbiosDomainName;
posix_offset = fetch_posix_offset (td, ldap_open, cldap);
break;
}
}
if (domain)
{
sid_sub_auth_count (sid) = sid_sub_auth_count (sid) + 1;
wcscpy (dom, domain);
__small_swprintf (name = namebuf, L"%W(%u)",
group ? L"Group" : L"User",
sid_sub_auth_rid (sid));
uid = posix_offset + sid_sub_auth_rid (sid);
}
else else
{ {
wcpcpy (dom, L"Unknown"); wcpcpy (dom, L"Unknown");
wcpcpy (name = namebuf, group ? L"Group" : L"User"); wcpcpy (name = namebuf, group ? L"Group" : L"User");
}
name_style = fully_qualified; name_style = fully_qualified;
} }