diff options
Diffstat (limited to 'source3/nsswitch')
-rw-r--r-- | source3/nsswitch/winbindd_sid.c | 240 |
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; |