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