nsswitch/winbind_nss_linux.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003 
00004    Windows NT Domain nsswitch module
00005 
00006    Copyright (C) Tim Potter 2000
00007    
00008    This library is free software; you can redistribute it and/or
00009    modify it under the terms of the GNU Library General Public
00010    License as published by the Free Software Foundation; either
00011    version 2 of the License, or (at your option) any later version.
00012    
00013    This library is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016    Library General Public License for more details.
00017    
00018    You should have received a copy of the GNU Library General Public
00019    License along with this library; if not, write to the
00020    Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00021    Boston, MA  02111-1307, USA.   
00022 */
00023 
00024 #include "winbind_client.h"
00025 
00026 /* Maximum number of users to pass back over the unix domain socket
00027    per call. This is not a static limit on the total number of users 
00028    or groups returned in total. */
00029 
00030 #define MAX_GETPWENT_USERS 250
00031 #define MAX_GETGRENT_USERS 250
00032 
00033 NSS_STATUS _nss_winbind_setpwent(void);
00034 NSS_STATUS _nss_winbind_endpwent(void);
00035 NSS_STATUS _nss_winbind_getpwent_r(struct passwd *result, char *buffer, 
00036                                    size_t buflen, int *errnop);
00037 NSS_STATUS _nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, 
00038                                    char *buffer, size_t buflen, int *errnop);
00039 NSS_STATUS _nss_winbind_getpwnam_r(const char *name, struct passwd *result, 
00040                                    char *buffer, size_t buflen, int *errnop);
00041 NSS_STATUS _nss_winbind_setgrent(void);
00042 NSS_STATUS _nss_winbind_endgrent(void);
00043 NSS_STATUS _nss_winbind_getgrent_r(struct group *result, char *buffer, 
00044                                    size_t buflen, int *errnop);
00045 NSS_STATUS _nss_winbind_getgrlst_r(struct group *result, char *buffer, 
00046                                    size_t buflen, int *errnop);
00047 NSS_STATUS _nss_winbind_getgrnam_r(const char *name, struct group *result, 
00048                                    char *buffer, size_t buflen, int *errnop);
00049 NSS_STATUS _nss_winbind_getgrgid_r(gid_t gid, struct group *result, char *buffer, 
00050                                    size_t buflen, int *errnop);
00051 NSS_STATUS _nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start, 
00052                                        long int *size, gid_t **groups, 
00053                                        long int limit, int *errnop);
00054 NSS_STATUS _nss_winbind_getusersids(const char *user_sid, char **group_sids, 
00055                                     int *num_groups, char *buffer, size_t buf_size, 
00056                                     int *errnop);
00057 NSS_STATUS _nss_winbind_nametosid(const char *name, char **sid, char *buffer,
00058                                   size_t buflen, int *errnop);
00059 NSS_STATUS _nss_winbind_sidtoname(const char *sid, char **name, char *buffer, 
00060                                   size_t buflen, int *errnop);
00061 NSS_STATUS _nss_winbind_sidtouid(const char *sid, uid_t *uid, int *errnop);
00062 NSS_STATUS _nss_winbind_sidtogid(const char *sid, gid_t *gid, int *errnop);
00063 NSS_STATUS _nss_winbind_uidtosid(uid_t uid, char **sid, char *buffer, 
00064                                  size_t buflen, int *errnop);
00065 NSS_STATUS _nss_winbind_gidtosid(gid_t gid, char **sid, char *buffer, 
00066                                  size_t buflen, int *errnop);
00067 
00068 /* Prototypes from wb_common.c */
00069 
00070 extern int winbindd_fd;
00071 
00072 #ifdef DEBUG_NSS
00073 static const char *nss_err_str(NSS_STATUS ret) {
00074         switch (ret) {
00075                 case NSS_STATUS_TRYAGAIN:
00076                         return "NSS_STATUS_TRYAGAIN";
00077                 case NSS_STATUS_SUCCESS:
00078                         return "NSS_STATUS_SUCCESS";
00079                 case NSS_STATUS_NOTFOUND:
00080                         return "NSS_STATUS_NOTFOUND";
00081                 case NSS_STATUS_UNAVAIL:
00082                         return "NSS_STATUS_UNAVAIL";
00083                 case NSS_STATUS_RETURN:
00084                         return "NSS_STATUS_RETURN";
00085                 default:
00086                         return "UNKNOWN RETURN CODE!!!!!!!";
00087         }
00088 }
00089 #endif
00090 
00091 /* Allocate some space from the nss static buffer.  The buffer and buflen
00092    are the pointers passed in by the C library to the _nss_ntdom_*
00093    functions. */
00094 
00095 static char *get_static(char **buffer, size_t *buflen, size_t len)
00096 {
00097         char *result;
00098 
00099         /* Error check.  We return false if things aren't set up right, or
00100            there isn't enough buffer space left. */
00101         
00102         if ((buffer == NULL) || (buflen == NULL) || (*buflen < len)) {
00103                 return NULL;
00104         }
00105 
00106         /* Return an index into the static buffer */
00107 
00108         result = *buffer;
00109         *buffer += len;
00110         *buflen -= len;
00111 
00112         return result;
00113 }
00114 
00115 /* I've copied the strtok() replacement function next_token() from
00116    lib/util_str.c as I really don't want to have to link in any other
00117    objects if I can possibly avoid it. */
00118 
00119 static BOOL next_token(char **ptr,char *buff,const char *sep, size_t bufsize)
00120 {
00121         char *s;
00122         BOOL quoted;
00123         size_t len=1;
00124 
00125         if (!ptr) return(False);
00126 
00127         s = *ptr;
00128 
00129         /* default to simple separators */
00130         if (!sep) sep = " \t\n\r";
00131 
00132         /* find the first non sep char */
00133         while (*s && strchr(sep,*s)) s++;
00134         
00135         /* nothing left? */
00136         if (! *s) return(False);
00137         
00138         /* copy over the token */
00139         for (quoted = False; len < bufsize && *s && (quoted || !strchr(sep,*s)); s++) {
00140                 if (*s == '\"') {
00141                         quoted = !quoted;
00142                 } else {
00143                         len++;
00144                         *buff++ = *s;
00145                 }
00146         }
00147         
00148         *ptr = (*s) ? s+1 : s;  
00149         *buff = 0;
00150         
00151         return(True);
00152 }
00153 
00154 
00155 /* Fill a pwent structure from a winbindd_response structure.  We use
00156    the static data passed to us by libc to put strings and stuff in.
00157    Return NSS_STATUS_TRYAGAIN if we run out of memory. */
00158 
00159 static NSS_STATUS fill_pwent(struct passwd *result,
00160                                   struct winbindd_pw *pw,
00161                                   char **buffer, size_t *buflen)
00162 {
00163         /* User name */
00164 
00165         if ((result->pw_name = 
00166              get_static(buffer, buflen, strlen(pw->pw_name) + 1)) == NULL) {
00167 
00168                 /* Out of memory */
00169 
00170                 return NSS_STATUS_TRYAGAIN;
00171         }
00172 
00173         strcpy(result->pw_name, pw->pw_name);
00174 
00175         /* Password */
00176 
00177         if ((result->pw_passwd = 
00178              get_static(buffer, buflen, strlen(pw->pw_passwd) + 1)) == NULL) {
00179 
00180                 /* Out of memory */
00181 
00182                 return NSS_STATUS_TRYAGAIN;
00183         }
00184 
00185         strcpy(result->pw_passwd, pw->pw_passwd);
00186         
00187         /* [ug]id */
00188 
00189         result->pw_uid = pw->pw_uid;
00190         result->pw_gid = pw->pw_gid;
00191 
00192         /* GECOS */
00193 
00194         if ((result->pw_gecos = 
00195              get_static(buffer, buflen, strlen(pw->pw_gecos) + 1)) == NULL) {
00196 
00197                 /* Out of memory */
00198 
00199                 return NSS_STATUS_TRYAGAIN;
00200         }
00201 
00202         strcpy(result->pw_gecos, pw->pw_gecos);
00203         
00204         /* Home directory */
00205         
00206         if ((result->pw_dir = 
00207              get_static(buffer, buflen, strlen(pw->pw_dir) + 1)) == NULL) {
00208 
00209                 /* Out of memory */
00210 
00211                 return NSS_STATUS_TRYAGAIN;
00212         }
00213 
00214         strcpy(result->pw_dir, pw->pw_dir);
00215 
00216         /* Logon shell */
00217         
00218         if ((result->pw_shell = 
00219              get_static(buffer, buflen, strlen(pw->pw_shell) + 1)) == NULL) {
00220                 
00221                 /* Out of memory */
00222 
00223                 return NSS_STATUS_TRYAGAIN;
00224         }
00225 
00226         strcpy(result->pw_shell, pw->pw_shell);
00227 
00228         /* The struct passwd for Solaris has some extra fields which must
00229            be initialised or nscd crashes. */
00230 
00231 #if HAVE_PASSWD_PW_COMMENT
00232         result->pw_comment = "";
00233 #endif
00234 
00235 #if HAVE_PASSWD_PW_AGE
00236         result->pw_age = "";
00237 #endif
00238 
00239         return NSS_STATUS_SUCCESS;
00240 }
00241 
00242 /* Fill a grent structure from a winbindd_response structure.  We use
00243    the static data passed to us by libc to put strings and stuff in.
00244    Return NSS_STATUS_TRYAGAIN if we run out of memory. */
00245 
00246 static NSS_STATUS fill_grent(struct group *result, struct winbindd_gr *gr,
00247                       char *gr_mem, char **buffer, size_t *buflen)
00248 {
00249         fstring name;
00250         int i;
00251         char *tst;
00252 
00253         /* Group name */
00254 
00255         if ((result->gr_name =
00256              get_static(buffer, buflen, strlen(gr->gr_name) + 1)) == NULL) {
00257 
00258                 /* Out of memory */
00259 
00260                 return NSS_STATUS_TRYAGAIN;
00261         }
00262 
00263         strcpy(result->gr_name, gr->gr_name);
00264 
00265         /* Password */
00266 
00267         if ((result->gr_passwd =
00268              get_static(buffer, buflen, strlen(gr->gr_passwd) + 1)) == NULL) {
00269 
00270                 /* Out of memory */
00271                 
00272                 return NSS_STATUS_TRYAGAIN;
00273         }
00274 
00275         strcpy(result->gr_passwd, gr->gr_passwd);
00276 
00277         /* gid */
00278 
00279         result->gr_gid = gr->gr_gid;
00280 
00281         /* Group membership */
00282 
00283         if ((gr->num_gr_mem < 0) || !gr_mem) {
00284                 gr->num_gr_mem = 0;
00285         }
00286 
00287         /* this next value is a pointer to a pointer so let's align it */
00288 
00289         /* Calculate number of extra bytes needed to align on pointer size boundry */
00290         if ((i = (unsigned long)(*buffer) % sizeof(char*)) != 0)
00291                 i = sizeof(char*) - i;
00292         
00293         if ((tst = get_static(buffer, buflen, ((gr->num_gr_mem + 1) * 
00294                                  sizeof(char *)+i))) == NULL) {
00295 
00296                 /* Out of memory */
00297 
00298                 return NSS_STATUS_TRYAGAIN;
00299         }
00300         result->gr_mem = (char **)(tst + i);
00301 
00302         if (gr->num_gr_mem == 0) {
00303 
00304                 /* Group is empty */
00305 
00306                 *(result->gr_mem) = NULL;
00307                 return NSS_STATUS_SUCCESS;
00308         }
00309 
00310         /* Start looking at extra data */
00311 
00312         i = 0;
00313 
00314         while(next_token((char **)&gr_mem, name, ",", sizeof(fstring))) {
00315         
00316                 /* Allocate space for member */
00317         
00318                 if (((result->gr_mem)[i] = 
00319                      get_static(buffer, buflen, strlen(name) + 1)) == NULL) {
00320             
00321                         /* Out of memory */
00322             
00323                         return NSS_STATUS_TRYAGAIN;
00324                 }        
00325         
00326                 strcpy((result->gr_mem)[i], name);
00327                 i++;
00328         }
00329 
00330         /* Terminate list */
00331 
00332         (result->gr_mem)[i] = NULL;
00333 
00334         return NSS_STATUS_SUCCESS;
00335 }
00336 
00337 /*
00338  * NSS user functions
00339  */
00340 
00341 static struct winbindd_response getpwent_response;
00342 
00343 static int ndx_pw_cache;                 /* Current index into pwd cache */
00344 static int num_pw_cache;                 /* Current size of pwd cache */
00345 
00346 /* Rewind "file pointer" to start of ntdom password database */
00347 
00348 NSS_STATUS
00349 _nss_winbind_setpwent(void)
00350 {
00351         NSS_STATUS ret;
00352 #ifdef DEBUG_NSS
00353         fprintf(stderr, "[%5d]: setpwent\n", getpid());
00354 #endif
00355 
00356         if (num_pw_cache > 0) {
00357                 ndx_pw_cache = num_pw_cache = 0;
00358                 free_response(&getpwent_response);
00359         }
00360 
00361         ret = winbindd_request_response(WINBINDD_SETPWENT, NULL, NULL);
00362 #ifdef DEBUG_NSS
00363         fprintf(stderr, "[%5d]: setpwent returns %s (%d)\n", getpid(),
00364                 nss_err_str(ret), ret);
00365 #endif
00366         return ret;
00367 }
00368 
00369 /* Close ntdom password database "file pointer" */
00370 
00371 NSS_STATUS
00372 _nss_winbind_endpwent(void)
00373 {
00374         NSS_STATUS ret;
00375 #ifdef DEBUG_NSS
00376         fprintf(stderr, "[%5d]: endpwent\n", getpid());
00377 #endif
00378 
00379         if (num_pw_cache > 0) {
00380                 ndx_pw_cache = num_pw_cache = 0;
00381                 free_response(&getpwent_response);
00382         }
00383 
00384         ret = winbindd_request_response(WINBINDD_ENDPWENT, NULL, NULL);
00385 #ifdef DEBUG_NSS
00386         fprintf(stderr, "[%5d]: endpwent returns %s (%d)\n", getpid(),
00387                 nss_err_str(ret), ret);
00388 #endif
00389         return ret;
00390 }
00391 
00392 /* Fetch the next password entry from ntdom password database */
00393 
00394 NSS_STATUS
00395 _nss_winbind_getpwent_r(struct passwd *result, char *buffer, 
00396                         size_t buflen, int *errnop)
00397 {
00398         NSS_STATUS ret;
00399         struct winbindd_request request;
00400         static int called_again;
00401 
00402 #ifdef DEBUG_NSS
00403         fprintf(stderr, "[%5d]: getpwent\n", getpid());
00404 #endif
00405 
00406         /* Return an entry from the cache if we have one, or if we are
00407            called again because we exceeded our static buffer.  */
00408 
00409         if ((ndx_pw_cache < num_pw_cache) || called_again) {
00410                 goto return_result;
00411         }
00412 
00413         /* Else call winbindd to get a bunch of entries */
00414         
00415         if (num_pw_cache > 0) {
00416                 free_response(&getpwent_response);
00417         }
00418 
00419         ZERO_STRUCT(request);
00420         ZERO_STRUCT(getpwent_response);
00421 
00422         request.data.num_entries = MAX_GETPWENT_USERS;
00423 
00424         ret = winbindd_request_response(WINBINDD_GETPWENT, &request, 
00425                                &getpwent_response);
00426 
00427         if (ret == NSS_STATUS_SUCCESS) {
00428                 struct winbindd_pw *pw_cache;
00429 
00430                 /* Fill cache */
00431 
00432                 ndx_pw_cache = 0;
00433                 num_pw_cache = getpwent_response.data.num_entries;
00434 
00435                 /* Return a result */
00436 
00437         return_result:
00438 
00439                 pw_cache = (struct winbindd_pw *)
00440                         getpwent_response.extra_data.data;
00441 
00442                 /* Check data is valid */
00443 
00444                 if (pw_cache == NULL) {
00445                         ret = NSS_STATUS_NOTFOUND;
00446                         goto done;
00447                 }
00448 
00449                 ret = fill_pwent(result, &pw_cache[ndx_pw_cache],
00450                                  &buffer, &buflen);
00451                 
00452                 /* Out of memory - try again */
00453 
00454                 if (ret == NSS_STATUS_TRYAGAIN) {
00455                         called_again = True;
00456                         *errnop = errno = ERANGE;
00457                         goto done;
00458                 }
00459 
00460                 *errnop = errno = 0;
00461                 called_again = False;
00462                 ndx_pw_cache++;
00463 
00464                 /* If we've finished with this lot of results free cache */
00465 
00466                 if (ndx_pw_cache == num_pw_cache) {
00467                         ndx_pw_cache = num_pw_cache = 0;
00468                         free_response(&getpwent_response);
00469                 }
00470         }
00471         done:
00472 #ifdef DEBUG_NSS
00473         fprintf(stderr, "[%5d]: getpwent returns %s (%d)\n", getpid(),
00474                 nss_err_str(ret), ret);
00475 #endif
00476         return ret;
00477 }
00478 
00479 /* Return passwd struct from uid */
00480 
00481 NSS_STATUS
00482 _nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, char *buffer,
00483                         size_t buflen, int *errnop)
00484 {
00485         NSS_STATUS ret;
00486         static struct winbindd_response response;
00487         struct winbindd_request request;
00488         static int keep_response=0;
00489 
00490 #ifdef DEBUG_NSS
00491         fprintf(stderr, "[%5d]: getpwuid %d\n", getpid(), (unsigned int)uid);
00492 #endif
00493 
00494         /* If our static buffer needs to be expanded we are called again */
00495         if (!keep_response) {
00496 
00497                 /* Call for the first time */
00498 
00499                 ZERO_STRUCT(response);
00500                 ZERO_STRUCT(request);
00501 
00502                 request.data.uid = uid;
00503 
00504                 ret = winbindd_request_response(WINBINDD_GETPWUID, &request, &response);
00505 
00506                 if (ret == NSS_STATUS_SUCCESS) {
00507                         ret = fill_pwent(result, &response.data.pw, 
00508                                          &buffer, &buflen);
00509 
00510                         if (ret == NSS_STATUS_TRYAGAIN) {
00511                                 keep_response = True;
00512                                 *errnop = errno = ERANGE;
00513                                 goto done;
00514                         }
00515                 }
00516 
00517         } else {
00518 
00519                 /* We've been called again */
00520 
00521                 ret = fill_pwent(result, &response.data.pw, &buffer, &buflen);
00522 
00523                 if (ret == NSS_STATUS_TRYAGAIN) {
00524                         keep_response = True;
00525                         *errnop = errno = ERANGE;
00526                         goto done;
00527                 }
00528 
00529                 keep_response = False;
00530                 *errnop = errno = 0;
00531         }
00532 
00533         free_response(&response);
00534         done:
00535 
00536 #ifdef DEBUG_NSS
00537         fprintf(stderr, "[%5d]: getpwuid %d returns %s (%d)\n", getpid(),
00538                 (unsigned int)uid, nss_err_str(ret), ret);
00539 #endif
00540         return ret;
00541 }
00542 
00543 /* Return passwd struct from username */
00544 NSS_STATUS
00545 _nss_winbind_getpwnam_r(const char *name, struct passwd *result, char *buffer,
00546                         size_t buflen, int *errnop)
00547 {
00548         NSS_STATUS ret;
00549         static struct winbindd_response response;
00550         struct winbindd_request request;
00551         static int keep_response;
00552 
00553 #ifdef DEBUG_NSS
00554         fprintf(stderr, "[%5d]: getpwnam %s\n", getpid(), name);
00555 #endif
00556 
00557         /* If our static buffer needs to be expanded we are called again */
00558 
00559         if (!keep_response) {
00560 
00561                 /* Call for the first time */
00562 
00563                 ZERO_STRUCT(response);
00564                 ZERO_STRUCT(request);
00565 
00566                 strncpy(request.data.username, name, 
00567                         sizeof(request.data.username) - 1);
00568                 request.data.username
00569                         [sizeof(request.data.username) - 1] = '\0';
00570 
00571                 ret = winbindd_request_response(WINBINDD_GETPWNAM, &request, &response);
00572 
00573                 if (ret == NSS_STATUS_SUCCESS) {
00574                         ret = fill_pwent(result, &response.data.pw, &buffer,
00575                                          &buflen);
00576 
00577                         if (ret == NSS_STATUS_TRYAGAIN) {
00578                                 keep_response = True;
00579                                 *errnop = errno = ERANGE;
00580                                 goto done;
00581                         }
00582                 }
00583 
00584         } else {
00585 
00586                 /* We've been called again */
00587 
00588                 ret = fill_pwent(result, &response.data.pw, &buffer, &buflen);
00589 
00590                 if (ret == NSS_STATUS_TRYAGAIN) {
00591                         keep_response = True;
00592                         *errnop = errno = ERANGE;
00593                         goto done;
00594                 }
00595 
00596                 keep_response = False;
00597                 *errnop = errno = 0;
00598         }
00599 
00600         free_response(&response);
00601         done:
00602 #ifdef DEBUG_NSS
00603         fprintf(stderr, "[%5d]: getpwnam %s returns %s (%d)\n", getpid(),
00604                 name, nss_err_str(ret), ret);
00605 #endif
00606         return ret;
00607 }
00608 
00609 /*
00610  * NSS group functions
00611  */
00612 
00613 static struct winbindd_response getgrent_response;
00614 
00615 static int ndx_gr_cache;                 /* Current index into grp cache */
00616 static int num_gr_cache;                 /* Current size of grp cache */
00617 
00618 /* Rewind "file pointer" to start of ntdom group database */
00619 
00620 NSS_STATUS
00621 _nss_winbind_setgrent(void)
00622 {
00623         NSS_STATUS ret;
00624 #ifdef DEBUG_NSS
00625         fprintf(stderr, "[%5d]: setgrent\n", getpid());
00626 #endif
00627 
00628         if (num_gr_cache > 0) {
00629                 ndx_gr_cache = num_gr_cache = 0;
00630                 free_response(&getgrent_response);
00631         }
00632 
00633         ret = winbindd_request_response(WINBINDD_SETGRENT, NULL, NULL);
00634 #ifdef DEBUG_NSS
00635         fprintf(stderr, "[%5d]: setgrent returns %s (%d)\n", getpid(),
00636                 nss_err_str(ret), ret);
00637 #endif
00638         return ret;
00639 }
00640 
00641 /* Close "file pointer" for ntdom group database */
00642 
00643 NSS_STATUS
00644 _nss_winbind_endgrent(void)
00645 {
00646         NSS_STATUS ret;
00647 #ifdef DEBUG_NSS
00648         fprintf(stderr, "[%5d]: endgrent\n", getpid());
00649 #endif
00650 
00651         if (num_gr_cache > 0) {
00652                 ndx_gr_cache = num_gr_cache = 0;
00653                 free_response(&getgrent_response);
00654         }
00655 
00656         ret = winbindd_request_response(WINBINDD_ENDGRENT, NULL, NULL);
00657 #ifdef DEBUG_NSS
00658         fprintf(stderr, "[%5d]: endgrent returns %s (%d)\n", getpid(),
00659                 nss_err_str(ret), ret);
00660 #endif
00661         return ret;
00662 }
00663 
00664 /* Get next entry from ntdom group database */
00665 
00666 static NSS_STATUS
00667 winbind_getgrent(enum winbindd_cmd cmd,
00668                  struct group *result,
00669                  char *buffer, size_t buflen, int *errnop)
00670 {
00671         NSS_STATUS ret;
00672         static struct winbindd_request request;
00673         static int called_again;
00674         
00675 
00676 #ifdef DEBUG_NSS
00677         fprintf(stderr, "[%5d]: getgrent\n", getpid());
00678 #endif
00679 
00680         /* Return an entry from the cache if we have one, or if we are
00681            called again because we exceeded our static buffer.  */
00682 
00683         if ((ndx_gr_cache < num_gr_cache) || called_again) {
00684                 goto return_result;
00685         }
00686 
00687         /* Else call winbindd to get a bunch of entries */
00688         
00689         if (num_gr_cache > 0) {
00690                 free_response(&getgrent_response);
00691         }
00692 
00693         ZERO_STRUCT(request);
00694         ZERO_STRUCT(getgrent_response);
00695 
00696         request.data.num_entries = MAX_GETGRENT_USERS;
00697 
00698         ret = winbindd_request_response(cmd, &request, 
00699                                &getgrent_response);
00700 
00701         if (ret == NSS_STATUS_SUCCESS) {
00702                 struct winbindd_gr *gr_cache;
00703                 int mem_ofs;
00704 
00705                 /* Fill cache */
00706 
00707                 ndx_gr_cache = 0;
00708                 num_gr_cache = getgrent_response.data.num_entries;
00709 
00710                 /* Return a result */
00711 
00712         return_result:
00713 
00714                 gr_cache = (struct winbindd_gr *)
00715                         getgrent_response.extra_data.data;
00716 
00717                 /* Check data is valid */
00718 
00719                 if (gr_cache == NULL) {
00720                         ret = NSS_STATUS_NOTFOUND;
00721                         goto done;
00722                 }
00723 
00724                 /* Fill group membership.  The offset into the extra data
00725                    for the group membership is the reported offset plus the
00726                    size of all the winbindd_gr records returned. */
00727 
00728                 mem_ofs = gr_cache[ndx_gr_cache].gr_mem_ofs +
00729                         num_gr_cache * sizeof(struct winbindd_gr);
00730 
00731                 ret = fill_grent(result, &gr_cache[ndx_gr_cache],
00732                                  ((char *)getgrent_response.extra_data.data)+mem_ofs,
00733                                  &buffer, &buflen);
00734                 
00735                 /* Out of memory - try again */
00736 
00737                 if (ret == NSS_STATUS_TRYAGAIN) {
00738                         called_again = True;
00739                         *errnop = errno = ERANGE;
00740                         goto done;
00741                 }
00742 
00743                 *errnop = 0;
00744                 called_again = False;
00745                 ndx_gr_cache++;
00746 
00747                 /* If we've finished with this lot of results free cache */
00748 
00749                 if (ndx_gr_cache == num_gr_cache) {
00750                         ndx_gr_cache = num_gr_cache = 0;
00751                         free_response(&getgrent_response);
00752                 }
00753         }
00754         done:
00755 #ifdef DEBUG_NSS
00756         fprintf(stderr, "[%5d]: getgrent returns %s (%d)\n", getpid(),
00757                 nss_err_str(ret), ret);
00758 #endif
00759         return ret;
00760 }
00761 
00762 
00763 NSS_STATUS
00764 _nss_winbind_getgrent_r(struct group *result,
00765                         char *buffer, size_t buflen, int *errnop)
00766 {
00767         return winbind_getgrent(WINBINDD_GETGRENT, result, buffer, buflen, errnop);
00768 }
00769 
00770 NSS_STATUS
00771 _nss_winbind_getgrlst_r(struct group *result,
00772                         char *buffer, size_t buflen, int *errnop)
00773 {
00774         return winbind_getgrent(WINBINDD_GETGRLST, result, buffer, buflen, errnop);
00775 }
00776 
00777 /* Return group struct from group name */
00778 
00779 NSS_STATUS
00780 _nss_winbind_getgrnam_r(const char *name,
00781                         struct group *result, char *buffer,
00782                         size_t buflen, int *errnop)
00783 {
00784         NSS_STATUS ret;
00785         static struct winbindd_response response;
00786         struct winbindd_request request;
00787         static int keep_response;
00788         
00789 #ifdef DEBUG_NSS
00790         fprintf(stderr, "[%5d]: getgrnam %s\n", getpid(), name);
00791 #endif
00792 
00793         /* If our static buffer needs to be expanded we are called again */
00794         
00795         if (!keep_response) {
00796 
00797                 /* Call for the first time */
00798 
00799                 ZERO_STRUCT(request);
00800                 ZERO_STRUCT(response);
00801 
00802                 strncpy(request.data.groupname, name, 
00803                         sizeof(request.data.groupname));
00804                 request.data.groupname
00805                         [sizeof(request.data.groupname) - 1] = '\0';
00806 
00807                 ret = winbindd_request_response(WINBINDD_GETGRNAM, &request, &response);
00808 
00809                 if (ret == NSS_STATUS_SUCCESS) {
00810                         ret = fill_grent(result, &response.data.gr, 
00811                                          (char *)response.extra_data.data,
00812                                          &buffer, &buflen);
00813 
00814                         if (ret == NSS_STATUS_TRYAGAIN) {
00815                                 keep_response = True;
00816                                 *errnop = errno = ERANGE;
00817                                 goto done;
00818                         }
00819                 }
00820 
00821         } else {
00822                 
00823                 /* We've been called again */
00824                 
00825                 ret = fill_grent(result, &response.data.gr, 
00826                                  (char *)response.extra_data.data, &buffer,
00827                                  &buflen);
00828                 
00829                 if (ret == NSS_STATUS_TRYAGAIN) {
00830                         keep_response = True;
00831                         *errnop = errno = ERANGE;
00832                         goto done;
00833                 }
00834 
00835                 keep_response = False;
00836                 *errnop = 0;
00837         }
00838 
00839         free_response(&response);
00840         done:
00841 #ifdef DEBUG_NSS
00842         fprintf(stderr, "[%5d]: getgrnam %s returns %s (%d)\n", getpid(),
00843                 name, nss_err_str(ret), ret);
00844 #endif
00845         return ret;
00846 }
00847 
00848 /* Return group struct from gid */
00849 
00850 NSS_STATUS
00851 _nss_winbind_getgrgid_r(gid_t gid,
00852                         struct group *result, char *buffer,
00853                         size_t buflen, int *errnop)
00854 {
00855         NSS_STATUS ret;
00856         static struct winbindd_response response;
00857         struct winbindd_request request;
00858         static int keep_response;
00859 
00860 #ifdef DEBUG_NSS
00861         fprintf(stderr, "[%5d]: getgrgid %d\n", getpid(), gid);
00862 #endif
00863 
00864         /* If our static buffer needs to be expanded we are called again */
00865 
00866         if (!keep_response) {
00867 
00868                 /* Call for the first time */
00869 
00870                 ZERO_STRUCT(request);
00871                 ZERO_STRUCT(response);
00872 
00873                 request.data.gid = gid;
00874 
00875                 ret = winbindd_request_response(WINBINDD_GETGRGID, &request, &response);
00876 
00877                 if (ret == NSS_STATUS_SUCCESS) {
00878 
00879                         ret = fill_grent(result, &response.data.gr, 
00880                                          (char *)response.extra_data.data, 
00881                                          &buffer, &buflen);
00882 
00883                         if (ret == NSS_STATUS_TRYAGAIN) {
00884                                 keep_response = True;
00885                                 *errnop = errno = ERANGE;
00886                                 goto done;
00887                         }
00888                 }
00889 
00890         } else {
00891 
00892                 /* We've been called again */
00893 
00894                 ret = fill_grent(result, &response.data.gr, 
00895                                  (char *)response.extra_data.data, &buffer,
00896                                  &buflen);
00897 
00898                 if (ret == NSS_STATUS_TRYAGAIN) {
00899                         keep_response = True;
00900                         *errnop = errno = ERANGE;
00901                         goto done;
00902                 }
00903 
00904                 keep_response = False;
00905                 *errnop = 0;
00906         }
00907 
00908         free_response(&response);
00909         done:
00910 #ifdef DEBUG_NSS
00911         fprintf(stderr, "[%5d]: getgrgid %d returns %s (%d)\n", getpid(),
00912                 (unsigned int)gid, nss_err_str(ret), ret);
00913 #endif
00914         return ret;
00915 }
00916 
00917 /* Initialise supplementary groups */
00918 
00919 NSS_STATUS
00920 _nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start,
00921                             long int *size, gid_t **groups, long int limit,
00922                             int *errnop)
00923 {
00924         NSS_STATUS ret;
00925         struct winbindd_request request;
00926         struct winbindd_response response;
00927         int i;
00928 
00929 #ifdef DEBUG_NSS
00930         fprintf(stderr, "[%5d]: initgroups %s (%d)\n", getpid(),
00931                 user, group);
00932 #endif
00933 
00934         ZERO_STRUCT(request);
00935         ZERO_STRUCT(response);
00936 
00937         strncpy(request.data.username, user,
00938                 sizeof(request.data.username) - 1);
00939 
00940         ret = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response);
00941 
00942         if (ret == NSS_STATUS_SUCCESS) {
00943                 int num_gids = response.data.num_entries;
00944                 gid_t *gid_list = (gid_t *)response.extra_data.data;
00945 
00946 #ifdef DEBUG_NSS
00947                 fprintf(stderr, "[%5d]: initgroups %s: got NSS_STATUS_SUCCESS "
00948                                 "and %d gids\n", getpid(),
00949                                 user, num_gids);
00950 #endif
00951                 if (gid_list == NULL) {
00952                         ret = NSS_STATUS_NOTFOUND;
00953                         goto done;
00954                 }
00955 
00956                 /* Copy group list to client */
00957 
00958                 for (i = 0; i < num_gids; i++) {
00959 
00960 #ifdef DEBUG_NSS
00961                         fprintf(stderr, "[%5d]: initgroups %s (%d): "
00962                                         "processing gid %d \n", getpid(),
00963                                         user, group, gid_list[i]);
00964 #endif
00965 
00966                         /* Skip primary group */
00967 
00968                         if (gid_list[i] == group) {
00969                                 continue;
00970                         }
00971 
00972                         /* Filled buffer ? If so, resize. */
00973 
00974                         if (*start == *size) {
00975                                 long int newsize;
00976                                 gid_t *newgroups;
00977 
00978                                 newsize = 2 * (*size);
00979                                 if (limit > 0) {
00980                                         if (*size == limit) {
00981                                                 goto done;
00982                                         }
00983                                         if (newsize > limit) {
00984                                                 newsize = limit;
00985                                         }
00986                                 }
00987 
00988                                 newgroups = (gid_t *)
00989                                         realloc((*groups),
00990                                                 newsize * sizeof(**groups));
00991                                 if (!newgroups) {
00992                                         *errnop = ENOMEM;
00993                                         ret = NSS_STATUS_NOTFOUND;
00994                                         goto done;
00995                                 }
00996                                 *groups = newgroups;
00997                                 *size = newsize;
00998                         }
00999 
01000                         /* Add to buffer */
01001 
01002                         (*groups)[*start] = gid_list[i];
01003                         *start += 1;
01004                 }
01005         }
01006         
01007         /* Back to your regularly scheduled programming */
01008 
01009  done:
01010 #ifdef DEBUG_NSS
01011         fprintf(stderr, "[%5d]: initgroups %s returns %s (%d)\n", getpid(),
01012                 user, nss_err_str(ret), ret);
01013 #endif
01014         return ret;
01015 }
01016 
01017 
01018 /* return a list of group SIDs for a user SID */
01019 NSS_STATUS
01020 _nss_winbind_getusersids(const char *user_sid, char **group_sids,
01021                          int *num_groups,
01022                          char *buffer, size_t buf_size, int *errnop)
01023 {
01024         NSS_STATUS ret;
01025         struct winbindd_request request;
01026         struct winbindd_response response;
01027 
01028 #ifdef DEBUG_NSS
01029         fprintf(stderr, "[%5d]: getusersids %s\n", getpid(), user_sid);
01030 #endif
01031 
01032         ZERO_STRUCT(request);
01033         ZERO_STRUCT(response);
01034 
01035         strncpy(request.data.sid, user_sid,sizeof(request.data.sid) - 1);
01036         request.data.sid[sizeof(request.data.sid) - 1] = '\0';
01037 
01038         ret = winbindd_request_response(WINBINDD_GETUSERSIDS, &request, &response);
01039 
01040         if (ret != NSS_STATUS_SUCCESS) {
01041                 goto done;
01042         }
01043 
01044         if (buf_size < response.length - sizeof(response)) {
01045                 ret = NSS_STATUS_TRYAGAIN;
01046                 errno = *errnop = ERANGE;
01047                 goto done;
01048         }
01049 
01050         *num_groups = response.data.num_entries;
01051         *group_sids = buffer;
01052         memcpy(buffer, response.extra_data.data, response.length - sizeof(response));
01053         errno = *errnop = 0;
01054         
01055  done:
01056         free_response(&response);
01057         return ret;
01058 }
01059 
01060 
01061 /* map a user or group name to a SID string */
01062 NSS_STATUS
01063 _nss_winbind_nametosid(const char *name, char **sid, char *buffer,
01064                        size_t buflen, int *errnop)
01065 {
01066         NSS_STATUS ret;
01067         struct winbindd_response response;
01068         struct winbindd_request request;
01069 
01070 #ifdef DEBUG_NSS
01071         fprintf(stderr, "[%5d]: nametosid %s\n", getpid(), name);
01072 #endif
01073 
01074         ZERO_STRUCT(response);
01075         ZERO_STRUCT(request);
01076 
01077         strncpy(request.data.name.name, name, 
01078                 sizeof(request.data.name.name) - 1);
01079         request.data.name.name[sizeof(request.data.name.name) - 1] = '\0';
01080 
01081         ret = winbindd_request_response(WINBINDD_LOOKUPNAME, &request, &response);
01082         if (ret != NSS_STATUS_SUCCESS) {
01083                 *errnop = errno = EINVAL;
01084                 goto failed;
01085         }
01086 
01087         if (buflen < strlen(response.data.sid.sid)+1) {
01088                 ret = NSS_STATUS_TRYAGAIN;
01089                 *errnop = errno = ERANGE;
01090                 goto failed;
01091         }
01092 
01093         *errnop = errno = 0;
01094         *sid = buffer;
01095         strcpy(*sid, response.data.sid.sid);
01096 
01097 failed:
01098         free_response(&response);
01099         return ret;
01100 }
01101 
01102 /* map a sid string to a user or group name */
01103 NSS_STATUS
01104 _nss_winbind_sidtoname(const char *sid, char **name, char *buffer,
01105                        size_t buflen, int *errnop)
01106 {
01107         NSS_STATUS ret;
01108         struct winbindd_response response;
01109         struct winbindd_request request;
01110         static char sep_char;
01111         unsigned needed;
01112 
01113 #ifdef DEBUG_NSS
01114         fprintf(stderr, "[%5d]: sidtoname %s\n", getpid(), sid);
01115 #endif
01116 
01117         ZERO_STRUCT(response);
01118         ZERO_STRUCT(request);
01119 
01120         /* we need to fetch the separator first time through */
01121         if (!sep_char) {
01122                 ret = winbindd_request_response(WINBINDD_INFO, &request, &response);
01123                 if (ret != NSS_STATUS_SUCCESS) {
01124                         *errnop = errno = EINVAL;
01125                         goto failed;
01126                 }
01127 
01128                 sep_char = response.data.info.winbind_separator;
01129                 free_response(&response);
01130         }
01131 
01132 
01133         strncpy(request.data.sid, sid, 
01134                 sizeof(request.data.sid) - 1);
01135         request.data.sid[sizeof(request.data.sid) - 1] = '\0';
01136 
01137         ret = winbindd_request_response(WINBINDD_LOOKUPSID, &request, &response);
01138         if (ret != NSS_STATUS_SUCCESS) {
01139                 *errnop = errno = EINVAL;
01140                 goto failed;
01141         }
01142 
01143         needed = 
01144                 strlen(response.data.name.dom_name) +
01145                 strlen(response.data.name.name) + 2;
01146 
01147         if (buflen < needed) {
01148                 ret = NSS_STATUS_TRYAGAIN;
01149                 *errnop = errno = ERANGE;
01150                 goto failed;
01151         }
01152 
01153         snprintf(buffer, needed, "%s%c%s", 
01154                  response.data.name.dom_name,
01155                  sep_char,
01156                  response.data.name.name);
01157 
01158         *name = buffer;
01159         *errnop = errno = 0;
01160 
01161 failed:
01162         free_response(&response);
01163         return ret;
01164 }
01165 
01166 /* map a sid to a uid */
01167 NSS_STATUS
01168 _nss_winbind_sidtouid(const char *sid, uid_t *uid, int *errnop)
01169 {
01170         NSS_STATUS ret;
01171         struct winbindd_response response;
01172         struct winbindd_request request;
01173 
01174 #ifdef DEBUG_NSS
01175         fprintf(stderr, "[%5d]: sidtouid %s\n", getpid(), sid);
01176 #endif
01177 
01178         ZERO_STRUCT(request);
01179         ZERO_STRUCT(response);
01180 
01181         strncpy(request.data.sid, sid, sizeof(request.data.sid) - 1);
01182         request.data.sid[sizeof(request.data.sid) - 1] = '\0';
01183 
01184         ret = winbindd_request_response(WINBINDD_SID_TO_UID, &request, &response);
01185         if (ret != NSS_STATUS_SUCCESS) {
01186                 *errnop = errno = EINVAL;
01187                 goto failed;
01188         }
01189 
01190         *uid = response.data.uid;
01191 
01192 failed:
01193         return ret;
01194 }
01195 
01196 /* map a sid to a gid */
01197 NSS_STATUS
01198 _nss_winbind_sidtogid(const char *sid, gid_t *gid, int *errnop)
01199 {
01200         NSS_STATUS ret;
01201         struct winbindd_response response;
01202         struct winbindd_request request;
01203 
01204 #ifdef DEBUG_NSS
01205         fprintf(stderr, "[%5d]: sidtogid %s\n", getpid(), sid);
01206 #endif
01207 
01208         ZERO_STRUCT(request);
01209         ZERO_STRUCT(response);
01210 
01211         strncpy(request.data.sid, sid, sizeof(request.data.sid) - 1);
01212         request.data.sid[sizeof(request.data.sid) - 1] = '\0';
01213 
01214         ret = winbindd_request_response(WINBINDD_SID_TO_GID, &request, &response);
01215         if (ret != NSS_STATUS_SUCCESS) {
01216                 *errnop = errno = EINVAL;
01217                 goto failed;
01218         }
01219 
01220         *gid = response.data.gid;
01221 
01222 failed:
01223         return ret;
01224 }
01225 
01226 /* map a uid to a SID string */
01227 NSS_STATUS
01228 _nss_winbind_uidtosid(uid_t uid, char **sid, char *buffer,
01229                       size_t buflen, int *errnop)
01230 {
01231         NSS_STATUS ret;
01232         struct winbindd_response response;
01233         struct winbindd_request request;
01234 
01235 #ifdef DEBUG_NSS
01236         fprintf(stderr, "[%5u]: uidtosid %u\n", (unsigned int)getpid(), (unsigned int)uid);
01237 #endif
01238 
01239         ZERO_STRUCT(response);
01240         ZERO_STRUCT(request);
01241 
01242         request.data.uid = uid;
01243 
01244         ret = winbindd_request_response(WINBINDD_UID_TO_SID, &request, &response);
01245         if (ret != NSS_STATUS_SUCCESS) {
01246                 *errnop = errno = EINVAL;
01247                 goto failed;
01248         }
01249 
01250         if (buflen < strlen(response.data.sid.sid)+1) {
01251                 ret = NSS_STATUS_TRYAGAIN;
01252                 *errnop = errno = ERANGE;
01253                 goto failed;
01254         }
01255 
01256         *errnop = errno = 0;
01257         *sid = buffer;
01258         strcpy(*sid, response.data.sid.sid);
01259 
01260 failed:
01261         free_response(&response);
01262         return ret;
01263 }
01264 
01265 /* map a gid to a SID string */
01266 NSS_STATUS
01267 _nss_winbind_gidtosid(gid_t gid, char **sid, char *buffer,
01268                       size_t buflen, int *errnop)
01269 {
01270         NSS_STATUS ret;
01271         struct winbindd_response response;
01272         struct winbindd_request request;
01273 
01274 #ifdef DEBUG_NSS
01275         fprintf(stderr, "[%5u]: gidtosid %u\n", (unsigned int)getpid(), (unsigned int)gid);
01276 #endif
01277 
01278         ZERO_STRUCT(response);
01279         ZERO_STRUCT(request);
01280 
01281         request.data.gid = gid;
01282 
01283         ret = winbindd_request_response(WINBINDD_GID_TO_SID, &request, &response);
01284         if (ret != NSS_STATUS_SUCCESS) {
01285                 *errnop = errno = EINVAL;
01286                 goto failed;
01287         }
01288 
01289         if (buflen < strlen(response.data.sid.sid)+1) {
01290                 ret = NSS_STATUS_TRYAGAIN;
01291                 *errnop = errno = ERANGE;
01292                 goto failed;
01293         }
01294 
01295         *errnop = errno = 0;
01296         *sid = buffer;
01297         strcpy(*sid, response.data.sid.sid);
01298 
01299 failed:
01300         free_response(&response);
01301         return ret;
01302 }

Sambaに対してSat Aug 29 21:23:09 2009に生成されました。  doxygen 1.4.7