summaryrefslogtreecommitdiff
path: root/source3/nsswitch
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2003-11-07 14:39:47 +0000
committerGerald Carter <jerry@samba.org>2003-11-07 14:39:47 +0000
commit84ca7ad00cdc831e0f887ca424db41af01d5e2fd (patch)
treeeddb31d6b550f9951146c92cfeb0f8f8519ac385 /source3/nsswitch
parent9db332645b81dc34bcb043c2401b3c56cf7a38a0 (diff)
downloadsamba-84ca7ad00cdc831e0f887ca424db41af01d5e2fd.tar.gz
samba-84ca7ad00cdc831e0f887ca424db41af01d5e2fd.tar.bz2
samba-84ca7ad00cdc831e0f887ca424db41af01d5e2fd.zip
fix for bug 680 (heads up). This gist is to map the
UNIX entity foo to DOMAIN\foo instead of SERVER\foo on members of a Samba domain when all UNIX accounts are shared via NIS, et. al. * allow winbindd to match local accounts to domain SID when 'winbind trusted domains only = yes' * remove code in idmap_ldap that searches the user suffix and group suffix. It's not needed and provides inconsistent functionality from the tdb backend. This has been tested. I'm still waiting on some more feedback but This needs to be in 3.0.1pre2 for widespread use. (This used to be commit ee272414e9965d7d550ba91d4e83997134dd51e6)
Diffstat (limited to 'source3/nsswitch')
-rw-r--r--source3/nsswitch/winbindd_sid.c240
1 files changed, 215 insertions, 25 deletions
diff --git a/source3/nsswitch/winbindd_sid.c b/source3/nsswitch/winbindd_sid.c
index ac1ee11555..0faeec5636 100644
--- a/source3/nsswitch/winbindd_sid.c
+++ b/source3/nsswitch/winbindd_sid.c
@@ -130,16 +130,75 @@ enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state)
DEBUG(3, ("[%5lu]: sid to uid %s\n", (unsigned long)state->pid,
state->request.data.sid));
- /* Split sid into domain sid and user rid */
if (!string_to_sid(&sid, state->request.data.sid)) {
DEBUG(1, ("Could not get convert sid %s from string\n", state->request.data.sid));
return WINBINDD_ERROR;
}
+ /* This gets a little tricky. If we assume that usernames are syncd between
+ /etc/passwd and the windows domain (such as a member of a Samba domain),
+ the we need to get the uid from the OS and not alocate one ourselves */
+
+ if ( lp_winbind_trusted_domains_only() ) {
+ struct winbindd_domain *domain = NULL;
+ DOM_SID sid2;
+ uint32 rid;
+
+ domain = find_domain_from_name( lp_workgroup() );
+ if ( !domain ) {
+ DEBUG(0,("winbindd_sid_to_uid: can't find my own domain!\n"));
+ return WINBINDD_ERROR;
+ }
+
+ sid_copy( &sid2, &sid );
+ sid_split_rid( &sid2, &rid );
+
+ if ( sid_equal( &sid2, &domain->sid ) ) {
+
+ fstring domain_name;
+ fstring user;
+ enum SID_NAME_USE type;
+ struct passwd *pw = NULL;
+ unid_t id;
+
+ /* ok...here's we know that we are dealing with our
+ own domain (the one to which we are joined). And
+ we know that there must be a UNIX account for this user.
+ So we lookup the sid and the call getpwnam().*/
+
+
+ /* But first check and see if we don't already have a mapping */
+
+ flags = ID_QUERY_ONLY;
+ if ( NT_STATUS_IS_OK(idmap_sid_to_uid(&sid, &(state->response.data.uid), flags)) )
+ return WINBINDD_OK;
+
+ /* now fall back to the hard way */
+
+ if ( !winbindd_lookup_name_by_sid(&sid, domain_name, user, &type) )
+ return WINBINDD_ERROR;
+
+ if ( !(pw = getpwnam(user)) ) {
+ DEBUG(0,("winbindd_sid_to_uid: 'winbind trusted domains only' is "
+ "set but this user [%s] doesn't exist!\n", user));
+ return WINBINDD_ERROR;
+ }
+
+ state->response.data.uid = pw->pw_uid;
+
+ id.uid = pw->pw_uid;
+ idmap_set_mapping( &sid, id, ID_USERID );
+
+ return WINBINDD_OK;
+ }
+
+ }
+
if ( state->request.flags & WBFLAG_QUERY_ONLY )
flags = ID_QUERY_ONLY;
/* Find uid for this sid and return it */
+
if ( !NT_STATUS_IS_OK(idmap_sid_to_uid(&sid, &(state->response.data.uid), flags)) ) {
DEBUG(1, ("Could not get uid for sid %s\n", state->request.data.sid));
return WINBINDD_ERROR;
@@ -167,6 +226,64 @@ enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state)
return WINBINDD_ERROR;
}
+ /* This gets a little tricky. If we assume that usernames are syncd between
+ /etc/passwd and the windows domain (such as a member of a Samba domain),
+ the we need to get the uid from the OS and not alocate one ourselves */
+
+ if ( lp_winbind_trusted_domains_only() ) {
+ struct winbindd_domain *domain = NULL;
+ DOM_SID sid2;
+ uint32 rid;
+ unid_t id;
+
+ domain = find_domain_from_name( lp_workgroup() );
+ if ( !domain ) {
+ DEBUG(0,("winbindd_sid_to_uid: can't find my own domain!\n"));
+ return WINBINDD_ERROR;
+ }
+
+ sid_copy( &sid2, &sid );
+ sid_split_rid( &sid2, &rid );
+
+ if ( sid_equal( &sid2, &domain->sid ) ) {
+
+ fstring domain_name;
+ fstring group;
+ enum SID_NAME_USE type;
+ struct group *grp = NULL;
+
+ /* ok...here's we know that we are dealing with our
+ own domain (the one to which we are joined). And
+ we know that there must be a UNIX account for this group.
+ So we lookup the sid and the call getpwnam().*/
+
+ /* But first check and see if we don't already have a mapping */
+
+ flags = ID_QUERY_ONLY;
+ if ( NT_STATUS_IS_OK(idmap_sid_to_gid(&sid, &(state->response.data.gid), flags)) )
+ return WINBINDD_OK;
+
+ /* now fall back to the hard way */
+
+ if ( !winbindd_lookup_name_by_sid(&sid, domain_name, group, &type) )
+ return WINBINDD_ERROR;
+
+ if ( !(grp = getgrnam(group)) ) {
+ DEBUG(0,("winbindd_sid_to_uid: 'winbind trusted domains only' is "
+ "set but this group [%s] doesn't exist!\n", group));
+ return WINBINDD_ERROR;
+ }
+
+ state->response.data.gid = grp->gr_gid;
+
+ id.gid = grp->gr_gid;
+ idmap_set_mapping( &sid, id, ID_GROUPID );
+
+ return WINBINDD_OK;
+ }
+
+ }
+
if ( state->request.flags & WBFLAG_QUERY_ONLY )
flags = ID_QUERY_ONLY;
@@ -185,28 +302,65 @@ enum winbindd_result winbindd_uid_to_sid(struct winbindd_cli_state *state)
{
DOM_SID sid;
-#if 0 /* JERRY */
- /* we cannot do this check this anymore since a domain member of
- a Samba domain may share unix accounts via NIS or LDAP. In this
- case the uid/gid will be out of winbindd's range but still might
- be resolved to a SID via an ldap idmap backend */
-
- if ((state->request.data.uid < server_state.uid_low ) ||
- (state->request.data.uid > server_state.uid_high)) {
- return WINBINDD_ERROR;
- }
-#endif
-
DEBUG(3, ("[%5lu]: uid to sid %lu\n", (unsigned long)state->pid,
(unsigned long)state->request.data.uid));
+ if ( (state->request.data.uid < server_state.uid_low )
+ || (state->request.data.uid > server_state.uid_high) )
+ {
+ struct passwd *pw = NULL;
+ enum SID_NAME_USE type;
+ unid_t id;
+ struct winbindd_domain *domain;
+
+ /* SPECIAL CASE FOR MEMBERS OF SAMBA DOMAINS */
+
+ /* if we don't trust /etc/password then when can't know
+ anything about this uid */
+
+ if ( !lp_winbind_trusted_domains_only() )
+ return WINBINDD_ERROR;
+
+
+ /* look for an idmap entry first */
+
+ if ( NT_STATUS_IS_OK(idmap_uid_to_sid(&sid, state->request.data.uid)) )
+ goto done;
+
+ /* if users exist in /etc/passwd, we should try to
+ use that uid. Get the username and the lookup the SID */
+
+ if ( !(pw = getpwuid(state->request.data.uid)) )
+ return WINBINDD_ERROR;
+
+ if ( !(domain = find_domain_from_name(lp_workgroup())) ) {
+ DEBUG(0,("winbindd_uid_to_sid: can't find my own domain!\n"));
+ return WINBINDD_ERROR;
+ }
+
+ if ( !winbindd_lookup_sid_by_name(domain, pw->pw_name, &sid, &type) )
+ return WINBINDD_ERROR;
+
+ if ( type != SID_NAME_USER )
+ return WINBINDD_ERROR;
+
+ /* don't fail if we can't store it */
+
+ id.uid = pw->pw_uid;
+ idmap_set_mapping( &sid, id, ID_USERID );
+
+ goto done;
+ }
+
/* Lookup rid for this uid */
+
if (!NT_STATUS_IS_OK(idmap_uid_to_sid(&sid, state->request.data.uid))) {
DEBUG(1, ("Could not convert uid %lu to rid\n",
(unsigned long)state->request.data.uid));
return WINBINDD_ERROR;
}
+done:
sid_to_string(state->response.data.sid.sid, &sid);
state->response.data.sid.type = SID_NAME_USER;
@@ -219,28 +373,64 @@ enum winbindd_result winbindd_gid_to_sid(struct winbindd_cli_state *state)
{
DOM_SID sid;
-#if 0 /* JERRY */
- /* we cannot do this check this anymore since a domain member of
- a Samba domain may share unix accounts via NIS or LDAP. In this
- case the uid/gid will be out of winbindd's range but still might
- be resolved to a SID via an ldap idmap backend */
-
- if ((state->request.data.gid < server_state.gid_low) ||
- (state->request.data.gid > server_state.gid_high)) {
- return WINBINDD_ERROR;
- }
-#endif
-
DEBUG(3, ("[%5lu]: gid to sid %lu\n", (unsigned long)state->pid,
(unsigned long)state->request.data.gid));
+
+ if ( (state->request.data.gid < server_state.gid_low)
+ || (state->request.data.gid > server_state.gid_high) )
+ {
+ struct group *grp = NULL;
+ enum SID_NAME_USE type;
+ unid_t id;
+ struct winbindd_domain *domain;
+
+ /* SPECIAL CASE FOR MEMBERS OF SAMBA DOMAINS */
+
+ /* if we don't trust /etc/group then when can't know
+ anything about this gid */
+
+ if ( !lp_winbind_trusted_domains_only() )
+ return WINBINDD_ERROR;
+
+ /* look for an idmap entry first */
+
+ if ( NT_STATUS_IS_OK(idmap_gid_to_sid(&sid, state->request.data.gid)) )
+ goto done;
+
+ /* if users exist in /etc/group, we should try to
+ use that gid. Get the username and the lookup the SID */
+
+ if ( !(grp = getgrgid(state->request.data.gid)) )
+ return WINBINDD_ERROR;
+
+ if ( !(domain = find_domain_from_name(lp_workgroup())) ) {
+ DEBUG(0,("winbindd_uid_to_sid: can't find my own domain!\n"));
+ return WINBINDD_ERROR;
+ }
+
+ if ( !winbindd_lookup_sid_by_name(domain, grp->gr_name, &sid, &type) )
+ return WINBINDD_ERROR;
+
+ if ( type!=SID_NAME_DOM_GRP && type!=SID_NAME_ALIAS )
+ return WINBINDD_ERROR;
+
+ /* don't fail if we can't store it */
+
+ id.gid = grp->gr_gid;
+ idmap_set_mapping( &sid, id, ID_GROUPID );
+
+ goto done;
+ }
/* Lookup sid for this uid */
+
if (!NT_STATUS_IS_OK(idmap_gid_to_sid(&sid, state->request.data.gid))) {
DEBUG(1, ("Could not convert gid %lu to sid\n",
(unsigned long)state->request.data.gid));
return WINBINDD_ERROR;
}
+done:
/* Construct sid and return it */
sid_to_string(state->response.data.sid.sid, &sid);
state->response.data.sid.type = SID_NAME_DOM_GRP;