⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 winbind_nss_linux.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    Unix SMB/CIFS implementation.   Windows NT Domain nsswitch module   Copyright (C) Tim Potter 2000      This library is free software; you can redistribute it and/or   modify it under the terms of the GNU Lesser General Public   License as published by the Free Software Foundation; either   version 3 of the License, or (at your option) any later version.      This library 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   Library General Public License for more details.      You should have received a copy of the GNU Lesser General Public License   along with this program.  If not, see <http://www.gnu.org/licenses/>.*/#include "winbind_client.h"/* Maximum number of users to pass back over the unix domain socket   per call. This is not a static limit on the total number of users    or groups returned in total. */#define MAX_GETPWENT_USERS 250#define MAX_GETGRENT_USERS 250NSS_STATUS _nss_winbind_setpwent(void);NSS_STATUS _nss_winbind_endpwent(void);NSS_STATUS _nss_winbind_getpwent_r(struct passwd *result, char *buffer, 				   size_t buflen, int *errnop);NSS_STATUS _nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, 				   char *buffer, size_t buflen, int *errnop);NSS_STATUS _nss_winbind_getpwnam_r(const char *name, struct passwd *result, 				   char *buffer, size_t buflen, int *errnop);NSS_STATUS _nss_winbind_setgrent(void);NSS_STATUS _nss_winbind_endgrent(void);NSS_STATUS _nss_winbind_getgrent_r(struct group *result, char *buffer, 				   size_t buflen, int *errnop);NSS_STATUS _nss_winbind_getgrlst_r(struct group *result, char *buffer, 				   size_t buflen, int *errnop);NSS_STATUS _nss_winbind_getgrnam_r(const char *name, struct group *result, 				   char *buffer, size_t buflen, int *errnop);NSS_STATUS _nss_winbind_getgrgid_r(gid_t gid, struct group *result, char *buffer, 				   size_t buflen, int *errnop);NSS_STATUS _nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start, 				       long int *size, gid_t **groups, 				       long int limit, int *errnop);NSS_STATUS _nss_winbind_getusersids(const char *user_sid, char **group_sids, 				    int *num_groups, char *buffer, size_t buf_size, 				    int *errnop);NSS_STATUS _nss_winbind_nametosid(const char *name, char **sid, char *buffer,				  size_t buflen, int *errnop);NSS_STATUS _nss_winbind_sidtoname(const char *sid, char **name, char *buffer, 				  size_t buflen, int *errnop);NSS_STATUS _nss_winbind_sidtouid(const char *sid, uid_t *uid, int *errnop);NSS_STATUS _nss_winbind_sidtogid(const char *sid, gid_t *gid, int *errnop);NSS_STATUS _nss_winbind_uidtosid(uid_t uid, char **sid, char *buffer, 				 size_t buflen, int *errnop);NSS_STATUS _nss_winbind_gidtosid(gid_t gid, char **sid, char *buffer, 				 size_t buflen, int *errnop);/* Prototypes from wb_common.c */extern int winbindd_fd;/* Allocate some space from the nss static buffer.  The buffer and buflen   are the pointers passed in by the C library to the _nss_ntdom_*   functions. */static char *get_static(char **buffer, size_t *buflen, size_t len){	char *result;	/* Error check.  We return false if things aren't set up right, or	   there isn't enough buffer space left. */		if ((buffer == NULL) || (buflen == NULL) || (*buflen < len)) {		return NULL;	}	/* Return an index into the static buffer */	result = *buffer;	*buffer += len;	*buflen -= len;	return result;}/* I've copied the strtok() replacement function next_token() from   lib/util_str.c as I really don't want to have to link in any other   objects if I can possibly avoid it. */static bool next_token(char **ptr,char *buff,const char *sep, size_t bufsize){	char *s;	bool quoted;	size_t len=1;	if (!ptr) return false;	s = *ptr;	/* default to simple separators */	if (!sep) sep = " \t\n\r";	/* find the first non sep char */	while (*s && strchr(sep,*s)) s++;		/* nothing left? */	if (! *s) return false;		/* copy over the token */	for (quoted = false; len < bufsize && *s && (quoted || !strchr(sep,*s)); s++) {		if (*s == '\"') {			quoted = !quoted;		} else {			len++;			*buff++ = *s;		}	}		*ptr = (*s) ? s+1 : s;  	*buff = 0;		return true;}/* Fill a pwent structure from a winbindd_response structure.  We use   the static data passed to us by libc to put strings and stuff in.   Return NSS_STATUS_TRYAGAIN if we run out of memory. */static NSS_STATUS fill_pwent(struct passwd *result,				  struct winbindd_pw *pw,				  char **buffer, size_t *buflen){	/* User name */	if ((result->pw_name = 	     get_static(buffer, buflen, strlen(pw->pw_name) + 1)) == NULL) {		/* Out of memory */		return NSS_STATUS_TRYAGAIN;	}	strcpy(result->pw_name, pw->pw_name);	/* Password */	if ((result->pw_passwd = 	     get_static(buffer, buflen, strlen(pw->pw_passwd) + 1)) == NULL) {		/* Out of memory */		return NSS_STATUS_TRYAGAIN;	}	strcpy(result->pw_passwd, pw->pw_passwd);        	/* [ug]id */	result->pw_uid = pw->pw_uid;	result->pw_gid = pw->pw_gid;	/* GECOS */	if ((result->pw_gecos = 	     get_static(buffer, buflen, strlen(pw->pw_gecos) + 1)) == NULL) {		/* Out of memory */		return NSS_STATUS_TRYAGAIN;	}	strcpy(result->pw_gecos, pw->pw_gecos);		/* Home directory */		if ((result->pw_dir = 	     get_static(buffer, buflen, strlen(pw->pw_dir) + 1)) == NULL) {		/* Out of memory */		return NSS_STATUS_TRYAGAIN;	}	strcpy(result->pw_dir, pw->pw_dir);	/* Logon shell */		if ((result->pw_shell = 	     get_static(buffer, buflen, strlen(pw->pw_shell) + 1)) == NULL) {				/* Out of memory */		return NSS_STATUS_TRYAGAIN;	}	strcpy(result->pw_shell, pw->pw_shell);	/* The struct passwd for Solaris has some extra fields which must	   be initialised or nscd crashes. */#if HAVE_PASSWD_PW_COMMENT	result->pw_comment = "";#endif#if HAVE_PASSWD_PW_AGE	result->pw_age = "";#endif	return NSS_STATUS_SUCCESS;}/* Fill a grent structure from a winbindd_response structure.  We use   the static data passed to us by libc to put strings and stuff in.   Return NSS_STATUS_TRYAGAIN if we run out of memory. */static NSS_STATUS fill_grent(struct group *result, struct winbindd_gr *gr,		      char *gr_mem, char **buffer, size_t *buflen){	fstring name;	int i;	char *tst;	/* Group name */	if ((result->gr_name =	     get_static(buffer, buflen, strlen(gr->gr_name) + 1)) == NULL) {		/* Out of memory */		return NSS_STATUS_TRYAGAIN;	}	strcpy(result->gr_name, gr->gr_name);	/* Password */	if ((result->gr_passwd =	     get_static(buffer, buflen, strlen(gr->gr_passwd) + 1)) == NULL) {		/* Out of memory */				return NSS_STATUS_TRYAGAIN;	}	strcpy(result->gr_passwd, gr->gr_passwd);	/* gid */	result->gr_gid = gr->gr_gid;	/* Group membership */	if ((gr->num_gr_mem < 0) || !gr_mem) {		gr->num_gr_mem = 0;	}	/* this next value is a pointer to a pointer so let's align it */	/* Calculate number of extra bytes needed to align on pointer size boundry */	if ((i = (unsigned long)(*buffer) % sizeof(char*)) != 0)		i = sizeof(char*) - i;		if ((tst = get_static(buffer, buflen, ((gr->num_gr_mem + 1) * 				 sizeof(char *)+i))) == NULL) {		/* Out of memory */		return NSS_STATUS_TRYAGAIN;	}	result->gr_mem = (char **)(tst + i);	if (gr->num_gr_mem == 0) {		/* Group is empty */		*(result->gr_mem) = NULL;		return NSS_STATUS_SUCCESS;	}	/* Start looking at extra data */	i = 0;	while(next_token((char **)&gr_mem, name, ",", sizeof(fstring))) {        		/* Allocate space for member */        		if (((result->gr_mem)[i] = 		     get_static(buffer, buflen, strlen(name) + 1)) == NULL) {            			/* Out of memory */            			return NSS_STATUS_TRYAGAIN;		}                		strcpy((result->gr_mem)[i], name);		i++;	}	/* Terminate list */	(result->gr_mem)[i] = NULL;	return NSS_STATUS_SUCCESS;}/* * NSS user functions */static struct winbindd_response getpwent_response;static int ndx_pw_cache;                 /* Current index into pwd cache */static int num_pw_cache;                 /* Current size of pwd cache *//* Rewind "file pointer" to start of ntdom password database */NSS_STATUS_nss_winbind_setpwent(void){	NSS_STATUS ret;#ifdef DEBUG_NSS	fprintf(stderr, "[%5d]: setpwent\n", getpid());#endif	if (num_pw_cache > 0) {		ndx_pw_cache = num_pw_cache = 0;		winbindd_free_response(&getpwent_response);	}	ret = winbindd_request_response(WINBINDD_SETPWENT, NULL, NULL);#ifdef DEBUG_NSS	fprintf(stderr, "[%5d]: setpwent returns %s (%d)\n", getpid(),		nss_err_str(ret), ret);#endif	return ret;}/* Close ntdom password database "file pointer" */NSS_STATUS_nss_winbind_endpwent(void){	NSS_STATUS ret;#ifdef DEBUG_NSS	fprintf(stderr, "[%5d]: endpwent\n", getpid());#endif	if (num_pw_cache > 0) {		ndx_pw_cache = num_pw_cache = 0;		winbindd_free_response(&getpwent_response);	}	ret = winbindd_request_response(WINBINDD_ENDPWENT, NULL, NULL);#ifdef DEBUG_NSS	fprintf(stderr, "[%5d]: endpwent returns %s (%d)\n", getpid(),		nss_err_str(ret), ret);#endif	return ret;}/* Fetch the next password entry from ntdom password database */NSS_STATUS_nss_winbind_getpwent_r(struct passwd *result, char *buffer, 			size_t buflen, int *errnop){	NSS_STATUS ret;	struct winbindd_request request;	static int called_again;#ifdef DEBUG_NSS	fprintf(stderr, "[%5d]: getpwent\n", getpid());#endif	/* Return an entry from the cache if we have one, or if we are	   called again because we exceeded our static buffer.  */	if ((ndx_pw_cache < num_pw_cache) || called_again) {		goto return_result;	}	/* Else call winbindd to get a bunch of entries */		if (num_pw_cache > 0) {		winbindd_free_response(&getpwent_response);	}	ZERO_STRUCT(request);	ZERO_STRUCT(getpwent_response);	request.data.num_entries = MAX_GETPWENT_USERS;	ret = winbindd_request_response(WINBINDD_GETPWENT, &request, 			       &getpwent_response);	if (ret == NSS_STATUS_SUCCESS) {		struct winbindd_pw *pw_cache;		/* Fill cache */		ndx_pw_cache = 0;		num_pw_cache = getpwent_response.data.num_entries;		/* Return a result */	return_result:		pw_cache = (struct winbindd_pw *)			getpwent_response.extra_data.data;		/* Check data is valid */		if (pw_cache == NULL) {			ret = NSS_STATUS_NOTFOUND;			goto done;		}		ret = fill_pwent(result, &pw_cache[ndx_pw_cache],				 &buffer, &buflen);				/* Out of memory - try again */		if (ret == NSS_STATUS_TRYAGAIN) {			called_again = true;			*errnop = errno = ERANGE;			goto done;		}		*errnop = errno = 0;		called_again = false;		ndx_pw_cache++;		/* If we've finished with this lot of results free cache */		if (ndx_pw_cache == num_pw_cache) {			ndx_pw_cache = num_pw_cache = 0;			winbindd_free_response(&getpwent_response);		}	}	done:#ifdef DEBUG_NSS	fprintf(stderr, "[%5d]: getpwent returns %s (%d)\n", getpid(),		nss_err_str(ret), ret);#endif	return ret;}/* Return passwd struct from uid */NSS_STATUS_nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, char *buffer,			size_t buflen, int *errnop){	NSS_STATUS ret;	static struct winbindd_response response;	struct winbindd_request request;	static int keep_response=0;#ifdef DEBUG_NSS	fprintf(stderr, "[%5d]: getpwuid %d\n", getpid(), (unsigned int)uid);#endif	/* If our static buffer needs to be expanded we are called again */	if (!keep_response) {		/* Call for the first time */		ZERO_STRUCT(response);		ZERO_STRUCT(request);		request.data.uid = uid;		ret = winbindd_request_response(WINBINDD_GETPWUID, &request, &response);		if (ret == NSS_STATUS_SUCCESS) {			ret = fill_pwent(result, &response.data.pw, 					 &buffer, &buflen);			if (ret == NSS_STATUS_TRYAGAIN) {				keep_response = true;				*errnop = errno = ERANGE;				goto done;			}		}	} else {		/* We've been called again */		ret = fill_pwent(result, &response.data.pw, &buffer, &buflen);		if (ret == NSS_STATUS_TRYAGAIN) {			keep_response = true;			*errnop = errno = ERANGE;			goto done;		}		keep_response = false;		*errnop = errno = 0;	}	winbindd_free_response(&response);	done:#ifdef DEBUG_NSS	fprintf(stderr, "[%5d]: getpwuid %d returns %s (%d)\n", getpid(),		(unsigned int)uid, nss_err_str(ret), ret);#endif	return ret;}/* Return passwd struct from username */NSS_STATUS_nss_winbind_getpwnam_r(const char *name, struct passwd *result, char *buffer,			size_t buflen, int *errnop){	NSS_STATUS ret;	static struct winbindd_response response;	struct winbindd_request request;	static int keep_response;#ifdef DEBUG_NSS	fprintf(stderr, "[%5d]: getpwnam %s\n", getpid(), name);#endif	/* If our static buffer needs to be expanded we are called again */	if (!keep_response) {		/* Call for the first time */		ZERO_STRUCT(response);		ZERO_STRUCT(request);		strncpy(request.data.username, name, 			sizeof(request.data.username) - 1);		request.data.username			[sizeof(request.data.username) - 1] = '\0';		ret = winbindd_request_response(WINBINDD_GETPWNAM, &request, &response);		if (ret == NSS_STATUS_SUCCESS) {			ret = fill_pwent(result, &response.data.pw, &buffer,					 &buflen);			if (ret == NSS_STATUS_TRYAGAIN) {				keep_response = true;				*errnop = errno = ERANGE;				goto done;			}		}	} else {		/* We've been called again */		ret = fill_pwent(result, &response.data.pw, &buffer, &buflen);		if (ret == NSS_STATUS_TRYAGAIN) {			keep_response = true;			*errnop = errno = ERANGE;			goto done;		}		keep_response = false;		*errnop = errno = 0;	}	winbindd_free_response(&response);	done:#ifdef DEBUG_NSS	fprintf(stderr, "[%5d]: getpwnam %s returns %s (%d)\n", getpid(),		name, nss_err_str(ret), ret);#endif	return ret;}/* * NSS group functions */static struct winbindd_response getgrent_response;static int ndx_gr_cache;                 /* Current index into grp cache */static int num_gr_cache;                 /* Current size of grp cache *//* Rewind "file pointer" to start of ntdom group database */NSS_STATUS_nss_winbind_setgrent(void){	NSS_STATUS ret;#ifdef DEBUG_NSS	fprintf(stderr, "[%5d]: setgrent\n", getpid());#endif	if (num_gr_cache > 0) {		ndx_gr_cache = num_gr_cache = 0;		winbindd_free_response(&getgrent_response);	}	ret = winbindd_request_response(WINBINDD_SETGRENT, NULL, NULL);#ifdef DEBUG_NSS	fprintf(stderr, "[%5d]: setgrent returns %s (%d)\n", getpid(),		nss_err_str(ret), ret);#endif	return ret;}/* Close "file pointer" for ntdom group database */NSS_STATUS_nss_winbind_endgrent(void){	NSS_STATUS ret;#ifdef DEBUG_NSS	fprintf(stderr, "[%5d]: endgrent\n", getpid());#endif	if (num_gr_cache > 0) {		ndx_gr_cache = num_gr_cache = 0;		winbindd_free_response(&getgrent_response);	}	ret = winbindd_request_response(WINBINDD_ENDGRENT, NULL, NULL);#ifdef DEBUG_NSS	fprintf(stderr, "[%5d]: endgrent returns %s (%d)\n", getpid(),		nss_err_str(ret), ret);#endif	return ret;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -