winbind_nss_linux.c

来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 1,165 行 · 第 1/2 页

C
1,165
字号
/*    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 Library General Public   License as published by the Free Software Foundation; either   version 2 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 Library General Public   License along with this library; if not, write to the   Free Software Foundation, Inc., 59 Temple Place - Suite 330,   Boston, MA  02111-1307, USA.   */#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 250/* 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. */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){#ifdef DEBUG_NSS	fprintf(stderr, "[%5d]: setpwent\n", getpid());#endif	if (num_pw_cache > 0) {		ndx_pw_cache = num_pw_cache = 0;		free_response(&getpwent_response);	}	return winbindd_request_response(WINBINDD_SETPWENT, NULL, NULL);}/* Close ntdom password database "file pointer" */NSS_STATUS_nss_winbind_endpwent(void){#ifdef DEBUG_NSS	fprintf(stderr, "[%5d]: endpwent\n", getpid());#endif	if (num_pw_cache > 0) {		ndx_pw_cache = num_pw_cache = 0;		free_response(&getpwent_response);	}	return winbindd_request_response(WINBINDD_ENDPWENT, NULL, NULL);}/* 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) {		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 = getpwent_response.extra_data;		/* Check data is valid */		if (pw_cache == NULL) {			return NSS_STATUS_NOTFOUND;		}		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;			return ret;		}		*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;			free_response(&getpwent_response);		}	}	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;	/* 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;				return ret;			}		}	} 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;			return ret;		}		keep_response = False;		*errnop = errno = 0;	}	free_response(&response);	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;				return ret;			}		}	} 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;			return ret;		}		keep_response = False;		*errnop = errno = 0;	}	free_response(&response);	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){#ifdef DEBUG_NSS	fprintf(stderr, "[%5d]: setgrent\n", getpid());#endif	if (num_gr_cache > 0) {		ndx_gr_cache = num_gr_cache = 0;		free_response(&getgrent_response);	}	return winbindd_request_response(WINBINDD_SETGRENT, NULL, NULL);}/* Close "file pointer" for ntdom group database */NSS_STATUS_nss_winbind_endgrent(void){#ifdef DEBUG_NSS	fprintf(stderr, "[%5d]: endgrent\n", getpid());#endif	if (num_gr_cache > 0) {		ndx_gr_cache = num_gr_cache = 0;		free_response(&getgrent_response);	}	return winbindd_request_response(WINBINDD_ENDGRENT, NULL, NULL);}/* Get next entry from ntdom group database */static NSS_STATUSwinbind_getgrent(enum winbindd_cmd cmd,		 struct group *result,		 char *buffer, size_t buflen, int *errnop){	NSS_STATUS ret;	static struct winbindd_request request;	static int called_again;	#ifdef DEBUG_NSS	fprintf(stderr, "[%5d]: getgrent\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.  */

⌨️ 快捷键说明

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