diff options
Diffstat (limited to 'source3/winbindd/idmap_nss.c')
-rw-r--r-- | source3/winbindd/idmap_nss.c | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/source3/winbindd/idmap_nss.c b/source3/winbindd/idmap_nss.c new file mode 100644 index 0000000..2729a0d --- /dev/null +++ b/source3/winbindd/idmap_nss.c @@ -0,0 +1,227 @@ +/* + Unix SMB/CIFS implementation. + + idmap NSS backend + + Copyright (C) Simo Sorce 2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "system/passwd.h" +#include "winbindd.h" +#include "nsswitch/winbind_client.h" +#include "idmap.h" +#include "lib/winbind_util.h" +#include "libcli/security/dom_sid.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_IDMAP + +/***************************** + Initialise idmap database. +*****************************/ + +static NTSTATUS idmap_nss_int_init(struct idmap_domain *dom) +{ + return NT_STATUS_OK; +} + +/********************************** + lookup a set of unix ids. +**********************************/ + +static NTSTATUS idmap_nss_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids) +{ + int i; + + /* initialize the status to avoid suprise */ + for (i = 0; ids[i]; i++) { + ids[i]->status = ID_UNKNOWN; + } + + for (i = 0; ids[i]; i++) { + struct passwd *pw; + struct group *gr; + const char *name; + struct dom_sid sid; + enum lsa_SidType type; + bool ret; + + switch (ids[i]->xid.type) { + case ID_TYPE_UID: + pw = getpwuid((uid_t)ids[i]->xid.id); + + if (!pw) { + ids[i]->status = ID_UNMAPPED; + continue; + } + name = pw->pw_name; + break; + case ID_TYPE_GID: + gr = getgrgid((gid_t)ids[i]->xid.id); + + if (!gr) { + ids[i]->status = ID_UNMAPPED; + continue; + } + name = gr->gr_name; + break; + default: /* ?? */ + ids[i]->status = ID_UNKNOWN; + continue; + } + + /* by default calls to winbindd are disabled + the following call will not recurse so this is safe */ + (void)winbind_on(); + /* Lookup name from PDC using lsa_lookup_names() */ + ret = winbind_lookup_name(dom->name, name, &sid, &type); + (void)winbind_off(); + + if (!ret) { + /* TODO: how do we know if the name is really not mapped, + * or something just failed ? */ + ids[i]->status = ID_UNMAPPED; + continue; + } + + switch (type) { + case SID_NAME_USER: + if (ids[i]->xid.type == ID_TYPE_UID) { + sid_copy(ids[i]->sid, &sid); + ids[i]->status = ID_MAPPED; + } + break; + + case SID_NAME_DOM_GRP: + case SID_NAME_ALIAS: + case SID_NAME_WKN_GRP: + if (ids[i]->xid.type == ID_TYPE_GID) { + sid_copy(ids[i]->sid, &sid); + ids[i]->status = ID_MAPPED; + } + break; + + default: + ids[i]->status = ID_UNKNOWN; + break; + } + } + return NT_STATUS_OK; +} + +/********************************** + lookup a set of sids. +**********************************/ + +static NTSTATUS idmap_nss_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids) +{ + int i; + + /* initialize the status to avoid suprise */ + for (i = 0; ids[i]; i++) { + ids[i]->status = ID_UNKNOWN; + } + + for (i = 0; ids[i]; i++) { + struct group *gr; + enum lsa_SidType type; + const char *_domain = NULL; + const char *_name = NULL; + char *domain = NULL; + char *name = NULL; + bool ret; + + /* by default calls to winbindd are disabled + the following call will not recurse so this is safe */ + (void)winbind_on(); + ret = winbind_lookup_sid(talloc_tos(), + ids[i]->sid, + &_domain, + &_name, + &type); + (void)winbind_off(); + if (!ret) { + /* TODO: how do we know if the name is really not mapped, + * or something just failed ? */ + ids[i]->status = ID_UNMAPPED; + continue; + } + + domain = discard_const_p(char, _domain); + name = discard_const_p(char, _name); + + if (!strequal(domain, dom->name)) { + struct dom_sid_buf buf; + DBG_ERR("DOMAIN[%s] ignoring SID[%s] belongs to %s [%s\\%s]\n", + dom->name, dom_sid_str_buf(ids[i]->sid, &buf), + sid_type_lookup(type), domain, name); + ids[i]->status = ID_UNMAPPED; + continue; + } + + switch (type) { + case SID_NAME_USER: { + struct passwd *pw; + + /* this will find also all lower case name and use username level */ + + pw = Get_Pwnam_alloc(talloc_tos(), name); + if (pw) { + ids[i]->xid.id = pw->pw_uid; + ids[i]->xid.type = ID_TYPE_UID; + ids[i]->status = ID_MAPPED; + } + TALLOC_FREE(pw); + break; + } + + case SID_NAME_DOM_GRP: + case SID_NAME_ALIAS: + case SID_NAME_WKN_GRP: + + gr = getgrnam(name); + if (gr) { + ids[i]->xid.id = gr->gr_gid; + ids[i]->xid.type = ID_TYPE_GID; + ids[i]->status = ID_MAPPED; + } + break; + + default: + ids[i]->status = ID_UNKNOWN; + break; + } + TALLOC_FREE(domain); + TALLOC_FREE(name); + } + return NT_STATUS_OK; +} + +/********************************** + Close the idmap tdb instance +**********************************/ + +static const struct idmap_methods nss_methods = { + .init = idmap_nss_int_init, + .unixids_to_sids = idmap_nss_unixids_to_sids, + .sids_to_unixids = idmap_nss_sids_to_unixids, +}; + +NTSTATUS idmap_nss_init(TALLOC_CTX *mem_ctx) +{ + return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "nss", &nss_methods); +} |