/* * idmap_rid: static map between Active Directory/NT RIDs and RFC 2307 accounts * Copyright (C) Guenther Deschner, 2004 * Copyright (C) Sumit Bose, 2004 * * 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 2 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, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include "includes.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_IDMAP NTSTATUS init_module(void); struct dom_entry { fstring name; fstring sid; uint32 min_id; uint32 max_id; }; typedef struct trust_dom_array { int number; struct dom_entry *dom; } trust_dom_array; static trust_dom_array trust; static NTSTATUS rid_idmap_parse(const char *init_param, uint32 num_domains, fstring *domain_names, DOM_SID *domain_sids, uid_t u_low, uid_t u_high) { const char *p; int i; trust.number = 0; fstring sid_str; BOOL known_domain = False; p = init_param; fstring tok; /* falling back to automatic mapping when there were no options given */ if (!*init_param) { DEBUG(3,("rid_idmap_parse: no domain list given or trusted domain-support deactivated, falling back to automatic mapping for own domain:\n")); sid_to_string(sid_str, &domain_sids[0]); fstrcpy(trust.dom[0].name, domain_names[0]); fstrcpy(trust.dom[0].sid, sid_str); trust.dom[0].min_id = u_low; trust.dom[0].max_id = u_high; trust.number = 1; DEBUGADD(3,("rid_idmap_parse:\tdomain: [%s], sid: [%s], range=[%d-%d]\n", trust.dom[0].name, trust.dom[0].sid, trust.dom[0].min_id, trust.dom[0].max_id)); return NT_STATUS_OK; } /* scan through the init_param-list */ while (next_token(&init_param, tok, LIST_SEP, sizeof(tok))) { p = tok; DEBUG(3,("rid_idmap_parse: parsing entry: %d\n", trust.number)); /* reinit sizes */ trust.dom = (struct dom_entry *) realloc(trust.dom, sizeof(struct dom_entry)*(trust.number+1)); if ( trust.dom == NULL ) { return NT_STATUS_NO_MEMORY; } if (!next_token(&p, tok, "=", sizeof(tok))) { DEBUG(0, ("rid_idmap_parse: no '=' sign found in domain list [%s]\n", init_param)); return NT_STATUS_UNSUCCESSFUL; } /* add the name */ fstrcpy(trust.dom[trust.number].name, tok); DEBUGADD(3,("rid_idmap_parse:\tentry %d has name: [%s]\n", trust.number, trust.dom[trust.number].name)); /* add the domain-sid */ for (i=0; i trust.dom[i].max_id) { DEBUG(0, ("rid_idmap_init: min_id (%d) has to be smaller than max_id (%d) for domain [%s]\n", trust.dom[i].min_id, trust.dom[i].max_id, trust.dom[i].name)); goto out; } if (trust.dom[i].min_id < u_low || trust.dom[i].max_id > u_high) { DEBUG(0, ("rid_idmap_init: mapping of domain [%s] (%d-%d) has to fit into global idmap range (%d-%d).\n", trust.dom[i].name, trust.dom[i].min_id, trust.dom[i].max_id, u_low, u_high)); goto out; } } /* check for overlaps */ for (i=0; i= unid.uid ) break; } if (i == trust.number) { DEBUG(0,("rid_idmap_get_sid_from_id: no suitable range available for id: %d\n", unid.uid)); return NT_STATUS_INVALID_PARAMETER; } /* use lower-end of idmap-range as offset for users and groups*/ unid.uid -= trust.dom[i].min_id; if (!trust.dom[i].sid) return NT_STATUS_INVALID_PARAMETER; string_to_sid(&sidstr, trust.dom[i].sid); sid_copy(sid, &sidstr); if (!sid_append_rid( sid, (unsigned long)unid.uid )) { DEBUG(0,("rid_idmap_get_sid_from_id: could not append rid to domain sid\n")); return NT_STATUS_NO_MEMORY; } DEBUG(3, ("rid_idmap_get_sid_from_id: mapped POSIX %s %d to SID [%s]\n", (id_type == ID_GROUPID) ? "GID" : "UID", unid.uid, sid_to_string(sid_string, sid))); return NT_STATUS_OK; } static NTSTATUS rid_idmap_get_id_from_sid(unid_t *unid, int *id_type, const DOM_SID *sid) { fstring sid_string; int i; uint32 rid; DOM_SID sidstr; /* check if we have a mapping for the sid */ for (i=0; iuid = rid + trust.dom[i].min_id; if (unid->uid > trust.dom[i].max_id) { DEBUG(0,("rid_idmap_get_id_from_sid: rid: %d (%s: %d) too high for mapping of domain: %s (%d-%d)\n", rid, (*id_type == ID_GROUPID) ? "GID" : "UID", unid->uid, trust.dom[i].name, trust.dom[i].min_id, trust.dom[i].max_id)); return NT_STATUS_INVALID_PARAMETER; } if (unid->uid < trust.dom[i].min_id) { DEBUG(0,("rid_idmap_get_id_from_sid: rid: %d (%s: %d) too low for mapping of domain: %s (%d-%d)\n", rid, (*id_type == ID_GROUPID) ? "GID" : "UID", unid->uid, trust.dom[i].name, trust.dom[i].min_id, trust.dom[i].max_id)); return NT_STATUS_INVALID_PARAMETER; } DEBUG(3,("rid_idmap_get_id_from_sid: mapped SID [%s] to POSIX %s %d\n", sid_to_string(sid_string, sid), (*id_type == ID_GROUPID) ? "GID" : "UID", unid->uid)); return NT_STATUS_OK; } static NTSTATUS rid_idmap_set_mapping(const DOM_SID *sid, unid_t id, int id_type) { return NT_STATUS_NOT_IMPLEMENTED; } static NTSTATUS rid_idmap_close(void) { SAFE_FREE(trust.dom); return NT_STATUS_OK; } static NTSTATUS rid_idmap_allocate_rid(uint32 *rid, int rid_type) { return NT_STATUS_NOT_IMPLEMENTED; } static NTSTATUS rid_idmap_allocate_id(unid_t *id, int id_type) { return NT_STATUS_NOT_IMPLEMENTED; } static void rid_idmap_status(void) { DEBUG(0, ("RID IDMAP Status not available\n")); } static struct idmap_methods rid_methods = { rid_idmap_init, rid_idmap_allocate_rid, rid_idmap_allocate_id, rid_idmap_get_sid_from_id, rid_idmap_get_id_from_sid, rid_idmap_set_mapping, rid_idmap_close, rid_idmap_status }; NTSTATUS init_module(void) { return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "idmap_rid", &rid_methods); }