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 + -
显示快捷键?