idmap_tdb.c
来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 677 行 · 第 1/2 页
C
677 行
/* Unix SMB/CIFS implementation. idmap TDB backend Copyright (C) Tim Potter 2000 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003 Copyright (C) Simo Sorce 2003 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/* High water mark keys */#define HWM_GROUP "GROUP HWM"#define HWM_USER "USER HWM"/* idmap version determines auto-conversion */#define IDMAP_VERSION 2/* Globals */static TDB_CONTEXT *idmap_tdb;static struct idmap_state { /* User and group id pool */ uid_t uid_low, uid_high; /* Range of uids to allocate */ gid_t gid_low, gid_high; /* Range of gids to allocate */} idmap_state;/********************************************************************** allocate a new RID; We don't care if is a user or group**********************************************************************/static NTSTATUS db_allocate_rid(uint32 *rid, int rid_type){ uint32 lowrid, highrid; uint32 tmp_rid; /* can't handle group rids right now. This is such a mess.... */ if ( rid_type == GROUP_RID_TYPE ) return NT_STATUS_UNSUCCESSFUL; /* cannot fail since idmap is only called winbindd */ get_free_rid_range( &lowrid, &highrid ); tmp_rid = lowrid; if ( !tdb_change_uint32_atomic(idmap_tdb, "RID_COUNTER", &tmp_rid, RID_MULTIPLIER) ) { DEBUG(3,("db_allocate_rid: Failed to locate next rid record in idmap db\n")); return NT_STATUS_UNSUCCESSFUL; } if ( tmp_rid > highrid ) { DEBUG(0, ("db_allocate_rid: no RIDs available!\n")); return NT_STATUS_UNSUCCESSFUL; } *rid = tmp_rid; return NT_STATUS_OK;}/********************************************************************** Allocate either a user or group id from the pool **********************************************************************/ static NTSTATUS db_allocate_id(unid_t *id, int id_type){ BOOL ret; int hwm; if (!id) return NT_STATUS_INVALID_PARAMETER; /* Get current high water mark */ switch (id_type & ID_TYPEMASK) { case ID_USERID: if ((hwm = tdb_fetch_int32(idmap_tdb, HWM_USER)) == -1) { return NT_STATUS_INTERNAL_DB_ERROR; } /* check it is in the range */ if (hwm > idmap_state.uid_high) { DEBUG(0, ("idmap Fatal Error: UID range full!! (max: %lu)\n", (unsigned long)idmap_state.uid_high)); return NT_STATUS_UNSUCCESSFUL; } /* fetch a new id and increment it */ ret = tdb_change_uint32_atomic(idmap_tdb, HWM_USER, (unsigned int *)&hwm, 1); if (!ret) { DEBUG(0, ("idmap_tdb: Fatal error while fetching a new id\n!")); return NT_STATUS_UNSUCCESSFUL; } /* recheck it is in the range */ if (hwm > idmap_state.uid_high) { DEBUG(0, ("idmap Fatal Error: UID range full!! (max: %lu)\n", (unsigned long)idmap_state.uid_high)); return NT_STATUS_UNSUCCESSFUL; } (*id).uid = hwm; DEBUG(10,("db_allocate_id: ID_USERID (*id).uid = %d\n", (unsigned int)hwm)); break; case ID_GROUPID: if ((hwm = tdb_fetch_int32(idmap_tdb, HWM_GROUP)) == -1) { return NT_STATUS_INTERNAL_DB_ERROR; } /* check it is in the range */ if (hwm > idmap_state.gid_high) { DEBUG(0, ("idmap Fatal Error: GID range full!! (max: %lu)\n", (unsigned long)idmap_state.gid_high)); return NT_STATUS_UNSUCCESSFUL; } /* fetch a new id and increment it */ ret = tdb_change_uint32_atomic(idmap_tdb, HWM_GROUP, (unsigned int *)&hwm, 1); if (!ret) { DEBUG(0, ("idmap_tdb: Fatal error while fetching a new id\n!")); return NT_STATUS_UNSUCCESSFUL; } /* recheck it is in the range */ if (hwm > idmap_state.gid_high) { DEBUG(0, ("idmap Fatal Error: GID range full!! (max: %lu)\n", (unsigned long)idmap_state.gid_high)); return NT_STATUS_UNSUCCESSFUL; } (*id).gid = hwm; DEBUG(10,("db_allocate_id: ID_GROUPID (*id).gid = %d\n", (unsigned int)hwm)); break; default: return NT_STATUS_INVALID_PARAMETER; } return NT_STATUS_OK;}/* Get a sid from an id */static NTSTATUS internal_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type){ TDB_DATA key, data; fstring keystr; NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; if (!sid) return NT_STATUS_INVALID_PARAMETER; switch (id_type & ID_TYPEMASK) { case ID_USERID: slprintf(keystr, sizeof(keystr), "UID %lu", (unsigned long)id.uid); break; case ID_GROUPID: slprintf(keystr, sizeof(keystr), "GID %lu", (unsigned long)id.gid); break; default: return NT_STATUS_UNSUCCESSFUL; } key.dptr = keystr; key.dsize = strlen(keystr) + 1; DEBUG(10,("internal_get_sid_from_id: fetching record %s\n", keystr )); data = tdb_fetch(idmap_tdb, key); if (data.dptr) { if (string_to_sid(sid, data.dptr)) { DEBUG(10,("internal_get_sid_from_id: fetching record %s -> %s\n", keystr, data.dptr )); ret = NT_STATUS_OK; } SAFE_FREE(data.dptr); } return ret;}/* Error codes for get_id_from_sid */enum getidfromsiderr { GET_ID_FROM_SID_OK = 0, GET_ID_FROM_SID_NOTFOUND, GET_ID_FROM_SID_WRONG_TYPE, GET_ID_FROM_SID_ERR };static enum getidfromsiderr internal_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid) { enum getidfromsiderr ret = GET_ID_FROM_SID_ERR; fstring keystr; TDB_DATA key, data; int type = *id_type & ID_TYPEMASK; /* Check if sid is present in database */ sid_to_string(keystr, sid); key.dptr = keystr; key.dsize = strlen(keystr) + 1; DEBUG(10,("internal_get_id_from_sid: fetching record %s of type 0x%x\n", keystr, type )); data = tdb_fetch(idmap_tdb, key); if (!data.dptr) { DEBUG(10,("internal_get_id_from_sid: record %s not found\n", keystr )); return GET_ID_FROM_SID_NOTFOUND; } else { DEBUG(10,("internal_get_id_from_sid: record %s -> %s\n", keystr, data.dptr )); } if (type == ID_EMPTY || type == ID_USERID) { fstring scanstr; /* Parse and return existing uid */ fstrcpy(scanstr, "UID %d"); if (sscanf(data.dptr, scanstr, &((*id).uid)) == 1) { /* uid ok? */ if (type == ID_EMPTY) { *id_type = ID_USERID; } DEBUG(10,("internal_get_id_from_sid: %s fetching record %s -> %s \n", (type == ID_EMPTY) ? "ID_EMPTY" : "ID_USERID", keystr, data.dptr )); ret = GET_ID_FROM_SID_OK; } else { ret = GET_ID_FROM_SID_WRONG_TYPE; } } if ((ret != GET_ID_FROM_SID_OK) && (type == ID_EMPTY || type == ID_GROUPID)) { fstring scanstr; /* Parse and return existing gid */ fstrcpy(scanstr, "GID %d"); if (sscanf(data.dptr, scanstr, &((*id).gid)) == 1) { /* gid ok? */ if (type == ID_EMPTY) { *id_type = ID_GROUPID; } DEBUG(10,("internal_get_id_from_sid: %s fetching record %s -> %s \n", (type == ID_EMPTY) ? "ID_EMPTY" : "ID_GROUPID", keystr, data.dptr )); ret = GET_ID_FROM_SID_OK; } else { ret = GET_ID_FROM_SID_WRONG_TYPE; } } SAFE_FREE(data.dptr); return ret;}/* Get a sid from an id */static NTSTATUS db_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type_in){ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; enum getidfromsiderr iderr; int id_type = id_type_in & ID_TYPEMASK; unid_t id_tmp = id; int id_type_tmp = id_type; DEBUG(10,("db_get_sid_from_id: id_type_in = 0x%x\n", id_type_in)); ret = internal_get_sid_from_id(sid, id, id_type); if (!NT_STATUS_IS_OK(ret)) { return ret; } iderr = internal_get_id_from_sid(&id_tmp, &id_type_tmp, sid); if (iderr != GET_ID_FROM_SID_OK) { return NT_STATUS_UNSUCCESSFUL; } if (id_type_tmp != id_type) { return NT_STATUS_UNSUCCESSFUL; } else if (id_type == ID_USERID) { if (id_tmp.uid != id.uid) { return NT_STATUS_UNSUCCESSFUL; } } else if (id_type == ID_GROUPID) { if (id_tmp.gid != id.gid) { return NT_STATUS_UNSUCCESSFUL; } } else { return NT_STATUS_UNSUCCESSFUL; } return ret;}/* Get an id from a sid */static NTSTATUS db_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid){ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; enum getidfromsiderr iderr; DEBUG(10,("db_get_id_from_sid\n")); if (!sid || !id || !id_type) return NT_STATUS_INVALID_PARAMETER; iderr = internal_get_id_from_sid(id, id_type, sid); if (iderr == GET_ID_FROM_SID_OK) { DOM_SID sid_tmp; ret = internal_get_sid_from_id(&sid_tmp, *id, *id_type); if (NT_STATUS_IS_OK(ret)) { if (!sid_equal(&sid_tmp, sid)) { return NT_STATUS_UNSUCCESSFUL; } } } else if (iderr == GET_ID_FROM_SID_WRONG_TYPE) { /* We found a record but not the type we wanted. * This is an error, not an opportunity to overwrite... * JRA. */ return NT_STATUS_UNSUCCESSFUL; } if (!(*id_type & ID_QUERY_ONLY) && (iderr != GET_ID_FROM_SID_OK) && (((*id_type & ID_TYPEMASK) == ID_USERID) || (*id_type & ID_TYPEMASK) == ID_GROUPID)) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?