* 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>
* 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);
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,
attr = tdom_attr, 0, &tv, &msg)) != LDAP_SUCCESS)
{

View File

@ -777,22 +777,32 @@ cygheap_domain_info::init ()
{
/* Copy... */
tdom[idx].NetbiosDomainName = cwcsdup (td[idx].NetbiosDomainName);
tdom[idx].DnsDomainName = cwcsdup (td[idx].DnsDomainName);
ULONG len = RtlLengthSid (td[idx].DomainSid);
tdom[idx].DomainSid = cmalloc_abort(HEAP_BUF, len);
RtlCopySid (len, tdom[idx].DomainSid, td[idx].DomainSid);
/* 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);
tdom[idx].DomainSid = cmalloc_abort(HEAP_BUF, len);
RtlCopySid (len, tdom[idx].DomainSid, td[idx].DomainSid);
}
/* ...and set PosixOffset to 0. This */
tdom[idx].PosixOffset = 0;
}
NetApiBufferFree (td);
tdom_count = tdom_cnt;
}
/* If we have NFS installed, we make use of a name mapping server. This
can be either Active Directory to map uids/gids directly to Windows SIDs,
or an AD LDS or other RFC 2307 compatible identity store. The name of
the mapping domain can be fetched from the registry key created by the
NFS client installation and entered by the user via nfsadmin or the
"Services For NFS" MMC snap-in.
/* If we have Microsoft Client for NFS installed, we make use of a name
mapping server. This can be either Active Directory to map uids/gids
directly to Windows SIDs, or an AD LDS or other RFC 2307 compatible
identity store. The name of the mapping domain can be fetched from the
registry key created by the NFS client installation and entered by the
user via nfsadmin or the "Services For NFS" MMC snap-in.
Reference:
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;
tmp_pathbuf tp;
char *buf = tp.c_get ();
char *str = tp.c_get ();
char str[128];
char *ret = NULL;
/* Create search string. */
@ -1066,6 +1076,34 @@ pwdgrp::fetch_account_from_file (fetch_user_arg_t &arg)
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 *
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:
sid = *arg.sid;
ret = LookupAccountSidW (NULL, sid, name, &nlen, dom, &dlen, &acc_type);
if (!ret)
debug_printf ("LookupAccountSid(%W), %E", sid.string (sidstr));
break;
case NAME_arg:
/* 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)
{
/* If we don't have the PosixOffset of the domain, fetch it.
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;
}
}
fetch_posix_offset (td, ldap_open, cldap);
if (td->PosixOffset > posix_offset && td->PosixOffset <= arg.id)
posix_offset = td->PosixOffset;
}
@ -1344,36 +1368,13 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group)
for (ULONG idx = 0;
(td = cygheap->dom.trusted_domain (idx));
++idx)
{
if (wcscmp (dom, td->NetbiosDomainName))
continue;
domain = td->DnsDomainName;
posix_offset = td->PosixOffset;
/* If we don't have the PosixOffset of the domain,
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;
}
if (!wcscmp (dom, td->NetbiosDomainName))
{
domain = td->DnsDomainName;
posix_offset =
fetch_posix_offset (td, ldap_open, cldap);
break;
}
if (!domain)
{
@ -1640,8 +1641,36 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group)
}
else
{
wcpcpy (dom, L"Unknown");
wcpcpy (name = namebuf, group ? L"Group" : L"User");
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
{
wcpcpy (dom, L"Unknown");
wcpcpy (name = namebuf, group ? L"Group" : L"User");
}
name_style = fully_qualified;
}