nsswitch/winbind_nss_aix.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003 
00004    AIX loadable authentication module, providing identification and
00005    authentication routines against Samba winbind/Windows NT Domain
00006 
00007    Copyright (C) Tim Potter 2003
00008    Copyright (C) Steve Roylance 2003
00009    Copyright (C) Andrew Tridgell 2003-2004
00010    
00011    This library is free software; you can redistribute it and/or
00012    modify it under the terms of the GNU Library General Public
00013    License as published by the Free Software Foundation; either
00014    version 2 of the License, or (at your option) any later version.
00015    
00016    This library is distributed in the hope that it will be useful,
00017    but WITHOUT ANY WARRANTY; without even the implied warranty of
00018    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019    Library General Public License for more details.
00020    
00021    You should have received a copy of the GNU Library General Public
00022    License along with this library; if not, write to the
00023    Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00024    Boston, MA  02111-1307, USA.   
00025 */
00026 
00027 /*
00028 
00029   To install this module copy nsswitch/WINBIND to /usr/lib/security and add
00030   "WINBIND" in /usr/lib/security/methods.cfg and /etc/security/user
00031 
00032   Note that this module also provides authentication and password
00033   changing routines, so you do not need to install the winbind PAM
00034   module.
00035 
00036   see 
00037   http://publib16.boulder.ibm.com/doc_link/en_US/a_doc_lib/aixprggd/kernextc/sec_load_mod.htm
00038   for some information in the interface that this module implements
00039 
00040   Many thanks to Julianne Haugh for explaining some of the finer
00041   details of this interface.
00042 
00043   To debug this module use uess_test.c (which you can get from tridge)
00044   or set "options=debug" in /usr/lib/security/methods.cfg
00045 
00046 */
00047 
00048 #include "winbind_client.h"
00049 #include <usersec.h>
00050 
00051 /* enable this to log which entry points have not been
00052   completed yet */
00053 #define LOG_UNIMPLEMENTED_CALLS 0
00054 
00055 
00056 #define WB_AIX_ENCODED '_'
00057 
00058 static int debug_enabled;
00059 
00060 
00061 static void logit(const char *format, ...)
00062 {
00063         va_list ap;
00064         FILE *f;
00065         if (!debug_enabled) {
00066                 return;
00067         }
00068         f = fopen("/tmp/WINBIND_DEBUG.log", "a");
00069         if (!f) return;
00070         va_start(ap, format);
00071         vfprintf(f, format, ap);
00072         va_end(ap);
00073         fclose(f);
00074 }
00075 
00076 
00077 #define HANDLE_ERRORS(ret) do { \
00078         if ((ret) == NSS_STATUS_NOTFOUND) { \
00079                 errno = ENOENT; \
00080                 return NULL; \
00081         } else if ((ret) != NSS_STATUS_SUCCESS) { \
00082                 errno = EIO; \
00083                 return NULL; \
00084         } \
00085 } while (0)
00086 
00087 #define STRCPY_RET(dest, src) \
00088 do { \
00089         if (strlen(src)+1 > sizeof(dest)) { errno = EINVAL; return -1; } \
00090         strcpy(dest, src); \
00091 } while (0)
00092 
00093 #define STRCPY_RETNULL(dest, src) \
00094 do { \
00095         if (strlen(src)+1 > sizeof(dest)) { errno = EINVAL; return NULL; } \
00096         strcpy(dest, src); \
00097 } while (0)
00098 
00099 
00100 /* free a passwd structure */
00101 static void free_pwd(struct passwd *pwd)
00102 {
00103         free(pwd->pw_name);
00104         free(pwd->pw_passwd);
00105         free(pwd->pw_gecos);
00106         free(pwd->pw_dir);
00107         free(pwd->pw_shell);
00108         free(pwd);
00109 }
00110 
00111 /* free a group structure */
00112 static void free_grp(struct group *grp)
00113 {
00114         int i;
00115 
00116         free(grp->gr_name);
00117         free(grp->gr_passwd);
00118         
00119         if (!grp->gr_mem) {
00120                 free(grp);
00121                 return;
00122         }
00123         
00124         for (i=0; grp->gr_mem[i]; i++) {
00125                 free(grp->gr_mem[i]);
00126         }
00127 
00128         free(grp->gr_mem);
00129         free(grp);
00130 }
00131 
00132 
00133 /* replace commas with nulls, and null terminate */
00134 static void replace_commas(char *s)
00135 {
00136         char *p, *p0=s;
00137         for (p=strchr(s, ','); p; p = strchr(p+1, ',')) {
00138                 *p=0;
00139                 p0 = p+1;
00140         }
00141 
00142         p0[strlen(p0)+1] = 0;
00143 }
00144 
00145 
00146 /* the decode_*() routines are used to cope with the fact that AIX 5.2
00147    and below cannot handle user or group names longer than 8
00148    characters in some interfaces. We use the normalize method to
00149    provide a mapping to a username that fits, by using the form '_UID'
00150    or '_GID'.
00151 
00152    this only works if you can guarantee that the WB_AIX_ENCODED char
00153    is not used as the first char of any other username
00154 */
00155 static unsigned decode_id(const char *name)
00156 {
00157         unsigned id;
00158         sscanf(name+1, "%u", &id);
00159         return id;
00160 }
00161 
00162 static struct passwd *wb_aix_getpwuid(uid_t uid);
00163 
00164 static char *decode_user(const char *name)
00165 {
00166         struct passwd *pwd;
00167         unsigned id;
00168         char *ret;
00169 
00170         sscanf(name+1, "%u", &id);
00171         pwd = wb_aix_getpwuid(id);
00172         if (!pwd) {
00173                 return NULL;
00174         }
00175         ret = strdup(pwd->pw_name);
00176 
00177         free_pwd(pwd);
00178 
00179         logit("decoded '%s' -> '%s'\n", name, ret);
00180 
00181         return ret;
00182 }
00183 
00184 
00185 /*
00186   fill a struct passwd from a winbindd_pw struct, allocating as a single block
00187 */
00188 static struct passwd *fill_pwent(struct winbindd_pw *pw)
00189 {
00190         struct passwd *result;
00191 
00192         result = calloc(1, sizeof(struct passwd));
00193         if (!result) {
00194                 errno = ENOMEM;
00195                 return NULL;
00196         }
00197 
00198         result->pw_uid = pw->pw_uid;
00199         result->pw_gid = pw->pw_gid;
00200         result->pw_name   = strdup(pw->pw_name);
00201         result->pw_passwd = strdup(pw->pw_passwd);
00202         result->pw_gecos  = strdup(pw->pw_gecos);
00203         result->pw_dir    = strdup(pw->pw_dir);
00204         result->pw_shell  = strdup(pw->pw_shell);
00205         
00206         return result;
00207 }
00208 
00209 
00210 /*
00211   fill a struct group from a winbindd_pw struct, allocating as a single block
00212 */
00213 static struct group *fill_grent(struct winbindd_gr *gr, char *gr_mem)
00214 {
00215         int i;
00216         struct group *result;
00217         char *p, *name;
00218 
00219         result = calloc(1, sizeof(struct group));
00220         if (!result) {
00221                 errno = ENOMEM;
00222                 return NULL;
00223         }
00224 
00225         result->gr_gid = gr->gr_gid;
00226 
00227         result->gr_name   = strdup(gr->gr_name);
00228         result->gr_passwd = strdup(gr->gr_passwd);
00229 
00230         /* Group membership */
00231         if ((gr->num_gr_mem < 0) || !gr_mem) {
00232                 gr->num_gr_mem = 0;
00233         }
00234         
00235         if (gr->num_gr_mem == 0) {
00236                 /* Group is empty */            
00237                 return result;
00238         }
00239         
00240         result->gr_mem = (char **)malloc(sizeof(char *) * (gr->num_gr_mem+1));
00241         if (!result->gr_mem) {
00242                 errno = ENOMEM;
00243                 return NULL;
00244         }
00245 
00246         /* Start looking at extra data */
00247         i=0;
00248         for (name = strtok_r(gr_mem, ",", &p); 
00249              name; 
00250              name = strtok_r(NULL, ",", &p)) {
00251                 if (i == gr->num_gr_mem) {
00252                         break;
00253                 }
00254                 result->gr_mem[i] = strdup(name);
00255                 i++;
00256         }
00257 
00258         /* Terminate list */
00259         result->gr_mem[i] = NULL;
00260 
00261         return result;
00262 }
00263 
00264 
00265 
00266 /* take a group id and return a filled struct group */  
00267 static struct group *wb_aix_getgrgid(gid_t gid)
00268 {
00269         struct winbindd_response response;
00270         struct winbindd_request request;
00271         struct group *grp;
00272         NSS_STATUS ret;
00273 
00274         logit("getgrgid %d\n", gid);
00275 
00276         ZERO_STRUCT(response);
00277         ZERO_STRUCT(request);
00278         
00279         request.data.gid = gid;
00280 
00281         ret = winbindd_request_response(WINBINDD_GETGRGID, &request, &response);
00282 
00283         logit("getgrgid ret=%d\n", ret);
00284 
00285         HANDLE_ERRORS(ret);
00286 
00287         grp = fill_grent(&response.data.gr, response.extra_data.data);
00288 
00289         free_response(&response);
00290 
00291         return grp;
00292 }
00293 
00294 /* take a group name and return a filled struct group */
00295 static struct group *wb_aix_getgrnam(const char *name)
00296 {
00297         struct winbindd_response response;
00298         struct winbindd_request request;
00299         NSS_STATUS ret;
00300         struct group *grp;
00301 
00302         if (*name == WB_AIX_ENCODED) {
00303                 return wb_aix_getgrgid(decode_id(name));
00304         }
00305 
00306         logit("getgrnam '%s'\n", name);
00307 
00308         ZERO_STRUCT(response);
00309         ZERO_STRUCT(request);
00310 
00311         STRCPY_RETNULL(request.data.groupname, name);
00312 
00313         ret = winbindd_request_response(WINBINDD_GETGRNAM, &request, &response);
00314         
00315         HANDLE_ERRORS(ret);
00316 
00317         grp = fill_grent(&response.data.gr, response.extra_data.data);
00318 
00319         free_response(&response);
00320 
00321         return grp;
00322 }
00323 
00324 
00325 /* this call doesn't have to fill in the gr_mem, but we do anyway
00326    for simplicity */
00327 static struct group *wb_aix_getgracct(void *id, int type)
00328 {
00329         if (type == 1) {
00330                 return wb_aix_getgrnam((char *)id);
00331         }
00332         if (type == 0) {
00333                 return wb_aix_getgrgid(*(int *)id);
00334         }
00335         errno = EINVAL;
00336         return NULL;
00337 }
00338 
00339 
00340 /* take a username and return a string containing a comma-separated
00341    list of group id numbers to which the user belongs */
00342 static char *wb_aix_getgrset(char *user)
00343 {
00344         struct winbindd_response response;
00345         struct winbindd_request request;
00346         NSS_STATUS ret;
00347         int i, idx;
00348         char *tmpbuf;
00349         int num_gids;
00350         gid_t *gid_list;
00351         char *r_user = user;
00352 
00353         if (*user == WB_AIX_ENCODED) {
00354                 r_user = decode_user(r_user);
00355                 if (!r_user) {
00356                         errno = ENOENT;
00357                         return NULL;
00358                 }
00359         }
00360 
00361         logit("getgrset '%s'\n", r_user);
00362 
00363         ZERO_STRUCT(response);
00364         ZERO_STRUCT(request);
00365 
00366         STRCPY_RETNULL(request.data.username, r_user);
00367 
00368         if (*user == WB_AIX_ENCODED) {
00369                 free(r_user);
00370         }
00371 
00372         ret = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response);
00373 
00374         HANDLE_ERRORS(ret);
00375 
00376         num_gids = response.data.num_entries;
00377         gid_list = (gid_t *)response.extra_data.data;
00378                 
00379         /* allocate a space large enough to contruct the string */
00380         tmpbuf = malloc(num_gids*12);
00381         if (!tmpbuf) {
00382                 return NULL;
00383         }
00384 
00385         for (idx=i=0; i < num_gids-1; i++) {
00386                 idx += sprintf(tmpbuf+idx, "%u,", gid_list[i]); 
00387         }
00388         idx += sprintf(tmpbuf+idx, "%u", gid_list[i]);  
00389 
00390         free_response(&response);
00391 
00392         return tmpbuf;
00393 }
00394 
00395 
00396 /* take a uid and return a filled struct passwd */      
00397 static struct passwd *wb_aix_getpwuid(uid_t uid)
00398 {
00399         struct winbindd_response response;
00400         struct winbindd_request request;
00401         NSS_STATUS ret;
00402         struct passwd *pwd;
00403 
00404         logit("getpwuid '%d'\n", uid);
00405 
00406         ZERO_STRUCT(response);
00407         ZERO_STRUCT(request);
00408                 
00409         request.data.uid = uid;
00410         
00411         ret = winbindd_request_response(WINBINDD_GETPWUID, &request, &response);
00412 
00413         HANDLE_ERRORS(ret);
00414 
00415         pwd = fill_pwent(&response.data.pw);
00416 
00417         free_response(&response);
00418 
00419         logit("getpwuid gave ptr %p\n", pwd);
00420 
00421         return pwd;
00422 }
00423 
00424 
00425 /* take a username and return a filled struct passwd */
00426 static struct passwd *wb_aix_getpwnam(const char *name)
00427 {
00428         struct winbindd_response response;
00429         struct winbindd_request request;
00430         NSS_STATUS ret;
00431         struct passwd *pwd;
00432 
00433         if (*name == WB_AIX_ENCODED) {
00434                 return wb_aix_getpwuid(decode_id(name));
00435         }
00436 
00437         logit("getpwnam '%s'\n", name);
00438 
00439         ZERO_STRUCT(response);
00440         ZERO_STRUCT(request);
00441 
00442         STRCPY_RETNULL(request.data.username, name);
00443 
00444         ret = winbindd_request_response(WINBINDD_GETPWNAM, &request, &response);
00445 
00446         HANDLE_ERRORS(ret);
00447         
00448         pwd = fill_pwent(&response.data.pw);
00449 
00450         free_response(&response);
00451 
00452         logit("getpwnam gave ptr %p\n", pwd);
00453 
00454         return pwd;
00455 }
00456 
00457 /*
00458   list users
00459 */
00460 static int wb_aix_lsuser(char *attributes[], attrval_t results[], int size)
00461 {
00462         NSS_STATUS ret;
00463         struct winbindd_request request;
00464         struct winbindd_response response;
00465         int len;
00466         char *s;
00467 
00468         if (size != 1 || strcmp(attributes[0], S_USERS) != 0) {
00469                 logit("invalid lsuser op\n");
00470                 errno = EINVAL;
00471                 return -1;
00472         }
00473 
00474         ZERO_STRUCT(request);
00475         ZERO_STRUCT(response);
00476         
00477         ret = winbindd_request_response(WINBINDD_LIST_USERS, &request, &response);
00478         if (ret != 0) {
00479                 errno = EINVAL;
00480                 return -1;
00481         }
00482 
00483         len = strlen(response.extra_data.data);
00484 
00485         s = malloc(len+2);
00486         if (!s) {
00487                 free_response(&response);
00488                 errno = ENOMEM;
00489                 return -1;
00490         }
00491         
00492         memcpy(s, response.extra_data.data, len+1);
00493 
00494         replace_commas(s);
00495 
00496         results[0].attr_un.au_char = s;
00497         results[0].attr_flag = 0;
00498 
00499         free_response(&response);
00500         
00501         return 0;
00502 }
00503 
00504 
00505 /*
00506   list groups
00507 */
00508 static int wb_aix_lsgroup(char *attributes[], attrval_t results[], int size)
00509 {
00510         NSS_STATUS ret;
00511         struct winbindd_request request;
00512         struct winbindd_response response;
00513         int len;
00514         char *s;
00515 
00516         if (size != 1 || strcmp(attributes[0], S_GROUPS) != 0) {
00517                 logit("invalid lsgroup op\n");
00518                 errno = EINVAL;
00519                 return -1;
00520         }
00521 
00522         ZERO_STRUCT(request);
00523         ZERO_STRUCT(response);
00524         
00525         ret = winbindd_request_response(WINBINDD_LIST_GROUPS, &request, &response);
00526         if (ret != 0) {
00527                 errno = EINVAL;
00528                 return -1;
00529         }
00530 
00531         len = strlen(response.extra_data.data);
00532 
00533         s = malloc(len+2);
00534         if (!s) {
00535                 free_response(&response);
00536                 errno = ENOMEM;
00537                 return -1;
00538         }
00539         
00540         memcpy(s, response.extra_data.data, len+1);
00541 
00542         replace_commas(s);
00543 
00544         results[0].attr_un.au_char = s;
00545         results[0].attr_flag = 0;
00546 
00547         free_response(&response);
00548         
00549         return 0;
00550 }
00551 
00552 
00553 static attrval_t pwd_to_group(struct passwd *pwd)
00554 {
00555         attrval_t r;
00556         struct group *grp = wb_aix_getgrgid(pwd->pw_gid);
00557         
00558         if (!grp) {
00559                 r.attr_flag = EINVAL;                           
00560         } else {
00561                 r.attr_flag = 0;
00562                 r.attr_un.au_char = strdup(grp->gr_name);
00563                 free_grp(grp);
00564         }
00565 
00566         return r;
00567 }
00568 
00569 static attrval_t pwd_to_groupsids(struct passwd *pwd)
00570 {
00571         attrval_t r;
00572         char *s, *p;
00573 
00574         if ( (s = wb_aix_getgrset(pwd->pw_name)) == NULL ) {
00575                 r.attr_flag = EINVAL;
00576                 return r;
00577         }
00578 
00579         if ( (p = malloc(strlen(s)+2)) == NULL ) {
00580                 r.attr_flag = ENOMEM;
00581                 return r;
00582         }
00583 
00584         strcpy(p, s);
00585         replace_commas(p);
00586         free(s);
00587 
00588         r.attr_un.au_char = p;
00589 
00590         return r;
00591 }
00592 
00593 static attrval_t pwd_to_sid(struct passwd *pwd)
00594 {
00595         struct winbindd_request request;
00596         struct winbindd_response response;
00597         attrval_t r;
00598 
00599         ZERO_STRUCT(request);
00600         ZERO_STRUCT(response);
00601 
00602         request.data.uid = pwd->pw_uid;
00603 
00604         if (winbindd_request_response(WINBINDD_UID_TO_SID, &request, &response) !=
00605             NSS_STATUS_SUCCESS) {
00606                 r.attr_flag = ENOENT;
00607         } else {
00608                 r.attr_flag = 0;
00609                 r.attr_un.au_char = strdup(response.data.sid.sid);
00610         }
00611 
00612         return r;
00613 }
00614 
00615 static int wb_aix_user_attrib(const char *key, char *attributes[],
00616                               attrval_t results[], int size)
00617 {
00618         struct passwd *pwd;
00619         int i;
00620 
00621         pwd = wb_aix_getpwnam(key);
00622         if (!pwd) {
00623                 errno = ENOENT;
00624                 return -1;
00625         }
00626 
00627         for (i=0;i<size;i++) {
00628                 results[i].attr_flag = 0;
00629 
00630                 if (strcmp(attributes[i], S_ID) == 0) {
00631                         results[i].attr_un.au_int = pwd->pw_uid;
00632 #ifdef _AIXVERSION_530
00633                 } else if (strcmp(attributes[i], S_PGID) == 0) {
00634                         results[i].attr_un.au_int = pwd->pw_gid;
00635 #endif
00636                 } else if (strcmp(attributes[i], S_PWD) == 0) {
00637                         results[i].attr_un.au_char = strdup(pwd->pw_passwd);
00638                 } else if (strcmp(attributes[i], S_HOME) == 0) {
00639                         results[i].attr_un.au_char = strdup(pwd->pw_dir);
00640                 } else if (strcmp(attributes[i], S_SHELL) == 0) {
00641                         results[i].attr_un.au_char = strdup(pwd->pw_shell);
00642                 } else if (strcmp(attributes[i], S_REGISTRY) == 0) {
00643                         results[i].attr_un.au_char = strdup("WINBIND");
00644                 } else if (strcmp(attributes[i], S_GECOS) == 0) {
00645                         results[i].attr_un.au_char = strdup(pwd->pw_gecos);
00646                 } else if (strcmp(attributes[i], S_PGRP) == 0) {
00647                         results[i] = pwd_to_group(pwd);
00648                 } else if (strcmp(attributes[i], S_GROUPS) == 0) {
00649                         results[i] = pwd_to_groupsids(pwd);
00650                 } else if (strcmp(attributes[i], "SID") == 0) {
00651                         results[i] = pwd_to_sid(pwd);
00652                 } else {
00653                         logit("Unknown user attribute '%s'\n", attributes[i]);
00654                         results[i].attr_flag = EINVAL;
00655                 }
00656         }
00657 
00658         free_pwd(pwd);
00659 
00660         return 0;
00661 }
00662 
00663 static int wb_aix_group_attrib(const char *key, char *attributes[],
00664                                attrval_t results[], int size)
00665 {
00666         struct group *grp;
00667         int i;
00668 
00669         grp = wb_aix_getgrnam(key);
00670         if (!grp) {
00671                 errno = ENOENT;
00672                 return -1;
00673         }
00674 
00675         for (i=0;i<size;i++) {
00676                 results[i].attr_flag = 0;
00677 
00678                 if (strcmp(attributes[i], S_PWD) == 0) {
00679                         results[i].attr_un.au_char = strdup(grp->gr_passwd);
00680                 } else if (strcmp(attributes[i], S_ID) == 0) {
00681                         results[i].attr_un.au_int = grp->gr_gid;
00682                 } else {
00683                         logit("Unknown group attribute '%s'\n", attributes[i]);
00684                         results[i].attr_flag = EINVAL;
00685                 }
00686         }
00687 
00688         free_grp(grp);
00689 
00690         return 0;
00691 }
00692 
00693 
00694 /*
00695   called for user/group enumerations
00696 */
00697 static int wb_aix_getentry(char *key, char *table, char *attributes[], 
00698                            attrval_t results[], int size)
00699 {
00700         logit("Got getentry with key='%s' table='%s' size=%d attributes[0]='%s'\n", 
00701               key, table, size, attributes[0]);
00702 
00703         if (strcmp(key, "ALL") == 0 && 
00704             strcmp(table, "user") == 0) {
00705                 return wb_aix_lsuser(attributes, results, size);
00706         }
00707 
00708         if (strcmp(key, "ALL") == 0 && 
00709             strcmp(table, "group") == 0) {
00710                 return wb_aix_lsgroup(attributes, results, size);
00711         }
00712 
00713         if (strcmp(table, "user") == 0) {
00714                 return wb_aix_user_attrib(key, attributes, results, size);
00715         }
00716 
00717         if (strcmp(table, "group") == 0) {
00718                 return wb_aix_group_attrib(key, attributes, results, size);
00719         }
00720 
00721         logit("Unknown getentry operation key='%s' table='%s'\n", key, table);
00722 
00723         errno = ENOSYS;
00724         return -1;
00725 }
00726 
00727 
00728 
00729 /*
00730   called to start the backend
00731 */
00732 static void *wb_aix_open(const char *name, const char *domain, int mode, char *options)
00733 {
00734         if (strstr(options, "debug")) {
00735                 debug_enabled = 1;
00736         }
00737         logit("open name='%s' mode=%d domain='%s' options='%s'\n", name, domain, 
00738               mode, options);
00739         return NULL;
00740 }
00741 
00742 static void wb_aix_close(void *token)
00743 {
00744         logit("close\n");
00745         return;
00746 }
00747 
00748 #ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_ATTRLIST
00749 /* 
00750    return a list of additional attributes supported by the backend 
00751 */
00752 static attrlist_t **wb_aix_attrlist(void)
00753 {
00754         /* pretty confusing but we are allocating the array of pointers
00755            and the structures we'll be pointing to all at once.  So
00756            you need N+1 pointers and N structures. */
00757 
00758         attrlist_t **ret = NULL;
00759         attrlist_t *offset = NULL;
00760         int i;
00761         int n;
00762         size_t size;
00763 
00764         struct attr_types {
00765                 const char *name;
00766                 int flags;
00767                 int type;
00768         } attr_list[] = {
00769                 /* user attributes */
00770                 {S_ID,          AL_USERATTR,    SEC_INT},
00771                 {S_PGRP,        AL_USERATTR,    SEC_CHAR},
00772                 {S_HOME,        AL_USERATTR,    SEC_CHAR},
00773                 {S_SHELL,       AL_USERATTR,    SEC_CHAR},
00774 #ifdef _AIXVERSION_530
00775                 {S_PGID,        AL_USERATTR,    SEC_INT},
00776 #endif
00777                 {S_GECOS,       AL_USERATTR,    SEC_CHAR},
00778                 {S_SHELL,       AL_USERATTR,    SEC_CHAR},
00779                 {S_PGRP,        AL_USERATTR,    SEC_CHAR},
00780                 {S_GROUPS,      AL_USERATTR,    SEC_LIST},
00781                 {"SID",         AL_USERATTR,    SEC_CHAR},
00782 
00783                 /* group attributes */
00784                 {S_ID,          AL_GROUPATTR,   SEC_INT}
00785         };
00786 
00787         logit("method attrlist called\n");
00788 
00789         n = sizeof(attr_list) / sizeof(struct attr_types);
00790         size = (n*sizeof(attrlist_t *));
00791 
00792         if ( (ret = malloc( size )) == NULL ) {
00793                 errno = ENOMEM;
00794                 return NULL;
00795         }
00796 
00797         /* offset to where the structures start in the buffer */
00798 
00799         offset = (attrlist_t *)(ret + n);
00800 
00801         /* now loop over the user_attr_list[] array and add
00802            all the members */
00803 
00804         for ( i=0; i<n; i++ ) {
00805                 attrlist_t *a = malloc(sizeof(attrlist_t));
00806 
00807                 if ( !a ) {
00808                         /* this is bad.  Just bail */
00809                         return NULL;
00810                 }
00811 
00812                 a->al_name  = strdup(attr_list[i].name);
00813                 a->al_flags = attr_list[i].flags;
00814                 a->al_type  = attr_list[i].type;
00815 
00816                 ret[i] = a;
00817         }
00818         ret[n] = NULL;
00819 
00820         return ret;
00821 }
00822 #endif
00823 
00824 
00825 /*
00826   turn a long username into a short one. Needed to cope with the 8 char 
00827   username limit in AIX 5.2 and below
00828 */
00829 static int wb_aix_normalize(char *longname, char *shortname)
00830 {
00831         struct passwd *pwd;
00832 
00833         logit("normalize '%s'\n", longname);
00834 
00835         /* automatically cope with AIX 5.3 with longer usernames
00836            when it comes out */
00837         if (S_NAMELEN > strlen(longname)) {
00838                 strcpy(shortname, longname);
00839                 return 1;
00840         }
00841 
00842         pwd = wb_aix_getpwnam(longname);
00843         if (!pwd) {
00844                 errno = ENOENT;
00845                 return 0;
00846         }
00847 
00848         sprintf(shortname, "%c%07u", WB_AIX_ENCODED, pwd->pw_uid);
00849 
00850         free_pwd(pwd);
00851 
00852         return 1;
00853 }
00854 
00855 
00856 /*
00857   authenticate a user
00858  */
00859 static int wb_aix_authenticate(char *user, char *pass, 
00860                                int *reenter, char **message)
00861 {
00862         struct winbindd_request request;
00863         struct winbindd_response response;
00864         NSS_STATUS result;
00865         char *r_user = user;
00866 
00867         logit("authenticate '%s' response='%s'\n", user, pass);
00868 
00869         *reenter = 0;
00870         *message = NULL;
00871 
00872         /* Send off request */
00873         ZERO_STRUCT(request);
00874         ZERO_STRUCT(response);
00875 
00876         if (*user == WB_AIX_ENCODED) {
00877                 r_user = decode_user(r_user);
00878                 if (!r_user) {
00879                         return AUTH_NOTFOUND;
00880                 }
00881         }
00882 
00883         STRCPY_RET(request.data.auth.user, r_user);
00884         STRCPY_RET(request.data.auth.pass, pass);
00885 
00886         if (*user == WB_AIX_ENCODED) {
00887                 free(r_user);
00888         }
00889 
00890         result = winbindd_request_response(WINBINDD_PAM_AUTH, &request, &response);
00891 
00892         free_response(&response);
00893 
00894         logit("auth result %d for '%s'\n", result, user);
00895 
00896         if (result == NSS_STATUS_SUCCESS) {
00897                 errno = 0;
00898                 return AUTH_SUCCESS;
00899         }
00900 
00901         return AUTH_FAILURE;
00902 }
00903 
00904 
00905 /*
00906   change a user password
00907 */
00908 static int wb_aix_chpass(char *user, char *oldpass, char *newpass, char **message)
00909 {
00910         struct winbindd_request request;
00911         struct winbindd_response response;
00912         NSS_STATUS result;
00913         char *r_user = user;
00914 
00915         if (*user == WB_AIX_ENCODED) {
00916                 r_user = decode_user(r_user);
00917                 if (!r_user) {
00918                         errno = ENOENT;
00919                         return -1;
00920                 }
00921         }
00922 
00923         logit("chpass '%s' old='%s' new='%s'\n", r_user, oldpass, newpass);
00924 
00925         *message = NULL;
00926 
00927         /* Send off request */
00928         ZERO_STRUCT(request);
00929         ZERO_STRUCT(response);
00930 
00931         STRCPY_RET(request.data.chauthtok.user, r_user);
00932         STRCPY_RET(request.data.chauthtok.oldpass, oldpass);
00933         STRCPY_RET(request.data.chauthtok.newpass, newpass);
00934 
00935         if (*user == WB_AIX_ENCODED) {
00936                 free(r_user);
00937         }
00938 
00939         result = winbindd_request_response(WINBINDD_PAM_CHAUTHTOK, &request, &response);
00940 
00941         free_response(&response);
00942 
00943         if (result == NSS_STATUS_SUCCESS) {
00944                 errno = 0;
00945                 return 0;
00946         }
00947 
00948         errno = EINVAL;
00949         return -1;
00950 }
00951 
00952 /*
00953   don't do any password strength testing for now
00954 */
00955 static int wb_aix_passwdrestrictions(char *user, char *newpass, char *oldpass, 
00956                                      char **message)
00957 {
00958         logit("passwdresrictions called for '%s'\n", user);
00959         return 0;
00960 }
00961 
00962 
00963 static int wb_aix_passwdexpired(char *user, char **message)
00964 {
00965         logit("passwdexpired '%s'\n", user);
00966         /* we should check the account bits here */
00967         return 0;
00968 }
00969 
00970 
00971 /*
00972   we can't return a crypt() password
00973 */
00974 static char *wb_aix_getpasswd(char *user)
00975 {
00976         logit("getpasswd '%s'\n", user);
00977         errno = ENOSYS;
00978         return NULL;
00979 }
00980 
00981 /*
00982   this is called to update things like the last login time. We don't 
00983   currently pass this onto the DC
00984 */
00985 static int wb_aix_putentry(char *key, char *table, char *attributes[], 
00986                            attrval_t values[], int size)
00987 {
00988         logit("putentry key='%s' table='%s' attrib='%s'\n", 
00989               key, table, size>=1?attributes[0]:"<null>");
00990         errno = ENOSYS;
00991         return -1;
00992 }
00993 
00994 static int wb_aix_commit(char *key, char *table)
00995 {
00996         logit("commit key='%s' table='%s'\n");
00997         errno = ENOSYS;
00998         return -1;
00999 }
01000 
01001 static int wb_aix_getgrusers(char *group, void *result, int type, int *size)
01002 {
01003         logit("getgrusers group='%s'\n", group);
01004         errno = ENOSYS;
01005         return -1;
01006 }
01007 
01008 
01009 #define DECL_METHOD(x) \
01010 int method_ ## x(void) \
01011 { \
01012         logit("UNIMPLEMENTED METHOD '%s'\n", #x); \
01013         errno = EINVAL; \
01014         return -1; \
01015 }
01016 
01017 #if LOG_UNIMPLEMENTED_CALLS
01018 DECL_METHOD(delgroup);
01019 DECL_METHOD(deluser);
01020 DECL_METHOD(newgroup);
01021 DECL_METHOD(newuser);
01022 DECL_METHOD(putgrent);
01023 DECL_METHOD(putgrusers);
01024 DECL_METHOD(putpwent);
01025 DECL_METHOD(lock);
01026 DECL_METHOD(unlock);
01027 DECL_METHOD(getcred);
01028 DECL_METHOD(setcred);
01029 DECL_METHOD(deletecred);
01030 #endif
01031 
01032 int wb_aix_init(struct secmethod_table *methods)
01033 {
01034         ZERO_STRUCTP(methods);
01035 
01036 #ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_VERSION
01037         methods->method_version = SECMETHOD_VERSION_520;
01038 #endif
01039 
01040         methods->method_getgrgid           = wb_aix_getgrgid;
01041         methods->method_getgrnam           = wb_aix_getgrnam;
01042         methods->method_getgrset           = wb_aix_getgrset;
01043         methods->method_getpwnam           = wb_aix_getpwnam;
01044         methods->method_getpwuid           = wb_aix_getpwuid;
01045         methods->method_getentry           = wb_aix_getentry;
01046         methods->method_open               = wb_aix_open;
01047         methods->method_close              = wb_aix_close;
01048         methods->method_normalize          = wb_aix_normalize;
01049         methods->method_passwdexpired      = wb_aix_passwdexpired;
01050         methods->method_putentry           = wb_aix_putentry;
01051         methods->method_getpasswd          = wb_aix_getpasswd;
01052         methods->method_authenticate       = wb_aix_authenticate;       
01053         methods->method_commit             = wb_aix_commit;
01054         methods->method_chpass             = wb_aix_chpass;
01055         methods->method_passwdrestrictions = wb_aix_passwdrestrictions;
01056         methods->method_getgracct          = wb_aix_getgracct;
01057         methods->method_getgrusers         = wb_aix_getgrusers;
01058 #ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_ATTRLIST
01059         methods->method_attrlist           = wb_aix_attrlist;
01060 #endif
01061 
01062 #if LOG_UNIMPLEMENTED_CALLS
01063         methods->method_delgroup      = method_delgroup;
01064         methods->method_deluser       = method_deluser;
01065         methods->method_newgroup      = method_newgroup;
01066         methods->method_newuser       = method_newuser;
01067         methods->method_putgrent      = method_putgrent;
01068         methods->method_putgrusers    = method_putgrusers;
01069         methods->method_putpwent      = method_putpwent;
01070         methods->method_lock          = method_lock;
01071         methods->method_unlock        = method_unlock;
01072         methods->method_getcred       = method_getcred;
01073         methods->method_setcred       = method_setcred;
01074         methods->method_deletecred    = method_deletecred;
01075 #endif
01076 
01077         return AUTH_SUCCESS;
01078 }
01079 

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