updated the head branch as well
[Samba.git] / source / nsswitch / winbind_nss_aix.c
blob3e00e54e5c416021518dc17059457438bba7e319
1 /*
2 Unix SMB/CIFS implementation.
4 AIX loadable authentication module, providing identification and
5 authentication routines against Samba winbind/Windows NT Domain
7 Copyright (C) Tim Potter 2003
8 Copyright (C) Steve Roylance 2003
9 Copyright (C) Andrew Tridgell 2003-2004
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Library General Public
13 License as published by the Free Software Foundation; either
14 version 2 of the License, or (at your option) any later version.
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Library General Public License for more details.
21 You should have received a copy of the GNU Library General Public
22 License along with this library; if not, write to the
23 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 Boston, MA 02111-1307, USA.
29 To install this module copy nsswitch/WINBIND to /usr/lib/security and add
30 "WINBIND" in /usr/lib/security/methods.cfg and /etc/security/user
32 Note that this module also provides authentication and password
33 changing routines, so you do not need to install the winbind PAM
34 module.
36 see
37 http://publib16.boulder.ibm.com/doc_link/en_US/a_doc_lib/aixprggd/kernextc/sec_load_mod.htm
38 for some information in the interface that this module implements
40 Many thanks to Julianne Haugh for explaining some of the finer
41 details of this interface.
43 To debug this module use uess_test.c (which you can get from tridge)
44 or set "options=debug" in /usr/lib/security/methods.cfg
48 #include <stdlib.h>
49 #include <string.h>
50 #include <usersec.h>
51 #include <errno.h>
52 #include <stdarg.h>
54 #include "winbind_client.h"
56 #define WB_AIX_ENCODED '_'
58 static int debug_enabled;
61 static void logit(const char *format, ...)
63 va_list ap;
64 FILE *f;
65 if (!debug_enabled) {
66 return;
68 f = fopen("/tmp/WINBIND_DEBUG.log", "a");
69 if (!f) return;
70 va_start(ap, format);
71 vfprintf(f, format, ap);
72 va_end(ap);
73 fclose(f);
77 #define HANDLE_ERRORS(ret) do { \
78 if ((ret) == NSS_STATUS_NOTFOUND) { \
79 errno = ENOENT; \
80 return NULL; \
81 } else if ((ret) != NSS_STATUS_SUCCESS) { \
82 errno = EIO; \
83 return NULL; \
84 } \
85 } while (0)
87 #define STRCPY_RET(dest, src) \
88 do { \
89 if (strlen(src)+1 > sizeof(dest)) { errno = EINVAL; return -1; } \
90 strcpy(dest, src); \
91 } while (0)
93 #define STRCPY_RETNULL(dest, src) \
94 do { \
95 if (strlen(src)+1 > sizeof(dest)) { errno = EINVAL; return NULL; } \
96 strcpy(dest, src); \
97 } while (0)
100 /* free a passwd structure */
101 static void free_pwd(struct passwd *pwd)
103 free(pwd->pw_name);
104 free(pwd->pw_passwd);
105 free(pwd->pw_gecos);
106 free(pwd->pw_dir);
107 free(pwd->pw_shell);
108 free(pwd);
111 /* free a group structure */
112 static void free_grp(struct group *grp)
114 int i;
116 free(grp->gr_name);
117 free(grp->gr_passwd);
119 if (!grp->gr_mem) {
120 free(grp);
121 return;
124 for (i=0; grp->gr_mem[i]; i++) {
125 free(grp->gr_mem[i]);
128 free(grp->gr_mem);
129 free(grp);
133 /* replace commas with nulls, and null terminate */
134 static void replace_commas(char *s)
136 char *p, *p0=s;
137 for (p=strchr(s, ','); p; p = strchr(p+1, ',')) {
138 *p=0;
139 p0 = p+1;
142 p0[strlen(p0)+1] = 0;
146 /* the decode_*() routines are used to cope with the fact that AIX 5.2
147 and below cannot handle user or group names longer than 8
148 characters in some interfaces. We use the normalize method to
149 provide a mapping to a username that fits, by using the form '_UID'
150 or '_GID'.
152 this only works if you can guarantee that the WB_AIX_ENCODED char
153 is not used as the first char of any other username
155 static unsigned decode_id(const char *name)
157 unsigned id;
158 sscanf(name+1, "%u", &id);
159 return id;
162 static char *decode_user(const char *name)
164 struct passwd *pwd;
165 unsigned id;
166 char *ret;
167 static struct passwd *wb_aix_getpwuid(uid_t uid);
169 sscanf(name+1, "%u", &id);
170 pwd = wb_aix_getpwuid(id);
171 if (!pwd) {
172 return NULL;
174 ret = strdup(pwd->pw_name);
176 free_pwd(pwd);
178 logit("decoded '%s' -> '%s'\n", name, ret);
180 return ret;
185 fill a struct passwd from a winbindd_pw struct, allocating as a single block
187 static struct passwd *fill_pwent(struct winbindd_pw *pw)
189 struct passwd *result;
191 result = calloc(1, sizeof(struct passwd));
192 if (!result) {
193 errno = ENOMEM;
194 return NULL;
197 result->pw_uid = pw->pw_uid;
198 result->pw_gid = pw->pw_gid;
199 result->pw_name = strdup(pw->pw_name);
200 result->pw_passwd = strdup(pw->pw_passwd);
201 result->pw_gecos = strdup(pw->pw_gecos);
202 result->pw_dir = strdup(pw->pw_dir);
203 result->pw_shell = strdup(pw->pw_shell);
205 return result;
210 fill a struct group from a winbindd_pw struct, allocating as a single block
212 static struct group *fill_grent(struct winbindd_gr *gr, char *gr_mem)
214 int i;
215 struct group *result;
216 char *p, *name;
218 result = calloc(1, sizeof(struct group));
219 if (!result) {
220 errno = ENOMEM;
221 return NULL;
224 result->gr_gid = gr->gr_gid;
226 result->gr_name = strdup(gr->gr_name);
227 result->gr_passwd = strdup(gr->gr_passwd);
229 /* Group membership */
230 if ((gr->num_gr_mem < 0) || !gr_mem) {
231 gr->num_gr_mem = 0;
234 if (gr->num_gr_mem == 0) {
235 /* Group is empty */
236 return result;
239 result->gr_mem = (char **)malloc(sizeof(char *) * (gr->num_gr_mem+1));
240 if (!result->gr_mem) {
241 errno = ENOMEM;
242 return NULL;
245 /* Start looking at extra data */
246 i=0;
247 for (name = strtok_r(gr_mem, ",", &p);
248 name;
249 name = strtok_r(NULL, ",", &p)) {
250 if (i == gr->num_gr_mem) {
251 break;
253 result->gr_mem[i] = strdup(name);
254 i++;
257 /* Terminate list */
258 result->gr_mem[i] = NULL;
260 return result;
265 /* take a group id and return a filled struct group */
266 static struct group *wb_aix_getgrgid(gid_t gid)
268 struct winbindd_response response;
269 struct winbindd_request request;
270 struct group *grp;
271 NSS_STATUS ret;
273 logit("getgrgid %d\n", gid);
275 ZERO_STRUCT(response);
276 ZERO_STRUCT(request);
278 request.data.gid = gid;
280 ret = winbindd_request(WINBINDD_GETGRGID, &request, &response);
282 logit("getgrgid ret=%d\n", ret);
284 HANDLE_ERRORS(ret);
286 grp = fill_grent(&response.data.gr, response.extra_data);
288 free_response(&response);
290 return grp;
293 /* take a group name and return a filled struct group */
294 static struct group *wb_aix_getgrnam(const char *name)
296 struct winbindd_response response;
297 struct winbindd_request request;
298 NSS_STATUS ret;
299 struct group *grp;
301 if (*name == WB_AIX_ENCODED) {
302 return wb_aix_getgrgid(decode_id(name));
305 logit("getgrnam '%s'\n", name);
307 ZERO_STRUCT(response);
308 ZERO_STRUCT(request);
310 STRCPY_RETNULL(request.data.groupname, name);
312 ret = winbindd_request(WINBINDD_GETGRNAM, &request, &response);
314 HANDLE_ERRORS(ret);
316 grp = fill_grent(&response.data.gr, response.extra_data);
318 free_response(&response);
320 return grp;
324 /* this call doesn't have to fill in the gr_mem, but we do anyway
325 for simplicity */
326 static struct group *wb_aix_getgracct(void *id, int type)
328 if (type == 1) {
329 return wb_aix_getgrnam((char *)id);
331 if (type == 0) {
332 return wb_aix_getgrgid(*(int *)id);
334 errno = EINVAL;
335 return NULL;
339 /* take a username and return a string containing a comma-separated
340 list of group id numbers to which the user belongs */
341 static char *wb_aix_getgrset(char *user)
343 struct winbindd_response response;
344 struct winbindd_request request;
345 NSS_STATUS ret;
346 int i, idx;
347 char *tmpbuf;
348 int num_gids;
349 gid_t *gid_list;
350 char *r_user = user;
352 if (*user == WB_AIX_ENCODED) {
353 r_user = decode_user(r_user);
354 if (!r_user) {
355 errno = ENOENT;
356 return NULL;
360 logit("getgrset '%s'\n", r_user);
362 STRCPY_RETNULL(request.data.username, r_user);
364 if (*user == WB_AIX_ENCODED) {
365 free(r_user);
368 ret = winbindd_request(WINBINDD_GETGROUPS, &request, &response);
370 HANDLE_ERRORS(ret);
372 num_gids = response.data.num_entries;
373 gid_list = (gid_t *)response.extra_data;
375 /* allocate a space large enough to contruct the string */
376 tmpbuf = malloc(num_gids*12);
377 if (!tmpbuf) {
378 return NULL;
381 for (idx=i=0; i < num_gids-1; i++) {
382 idx += sprintf(tmpbuf+idx, "%u,", gid_list[i]);
384 idx += sprintf(tmpbuf+idx, "%u", gid_list[i]);
386 free_response(&response);
388 return tmpbuf;
392 /* take a uid and return a filled struct passwd */
393 static struct passwd *wb_aix_getpwuid(uid_t uid)
395 struct winbindd_response response;
396 struct winbindd_request request;
397 NSS_STATUS ret;
398 struct passwd *pwd;
400 logit("getpwuid '%d'\n", uid);
402 ZERO_STRUCT(response);
403 ZERO_STRUCT(request);
405 request.data.uid = uid;
407 ret = winbindd_request(WINBINDD_GETPWUID, &request, &response);
409 HANDLE_ERRORS(ret);
411 pwd = fill_pwent(&response.data.pw);
413 free_response(&response);
415 logit("getpwuid gave ptr %p\n", pwd);
417 return pwd;
421 /* take a username and return a filled struct passwd */
422 static struct passwd *wb_aix_getpwnam(const char *name)
424 struct winbindd_response response;
425 struct winbindd_request request;
426 NSS_STATUS ret;
427 struct passwd *pwd;
429 if (*name == WB_AIX_ENCODED) {
430 return wb_aix_getpwuid(decode_id(name));
433 logit("getpwnam '%s'\n", name);
435 ZERO_STRUCT(response);
436 ZERO_STRUCT(request);
438 STRCPY_RETNULL(request.data.username, name);
440 ret = winbindd_request(WINBINDD_GETPWNAM, &request, &response);
442 HANDLE_ERRORS(ret);
444 pwd = fill_pwent(&response.data.pw);
446 free_response(&response);
448 logit("getpwnam gave ptr %p\n", pwd);
450 return pwd;
454 list users
456 static int wb_aix_lsuser(char *attributes[], attrval_t results[], int size)
458 NSS_STATUS ret;
459 struct winbindd_request request;
460 struct winbindd_response response;
461 int len;
462 char *s;
464 if (size != 1 || strcmp(attributes[0], S_USERS) != 0) {
465 logit("invalid lsuser op\n");
466 errno = EINVAL;
467 return -1;
470 ZERO_STRUCT(request);
471 ZERO_STRUCT(response);
473 ret = winbindd_request(WINBINDD_LIST_USERS, &request, &response);
474 if (ret != 0) {
475 errno = EINVAL;
476 return -1;
479 len = strlen(response.extra_data);
481 s = malloc(len+2);
482 if (!s) {
483 free_response(&response);
484 errno = ENOMEM;
485 return -1;
488 memcpy(s, response.extra_data, len+1);
490 replace_commas(s);
492 results[0].attr_un.au_char = s;
493 results[0].attr_flag = 0;
495 free_response(&response);
497 return 0;
502 list groups
504 static int wb_aix_lsgroup(char *attributes[], attrval_t results[], int size)
506 NSS_STATUS ret;
507 struct winbindd_request request;
508 struct winbindd_response response;
509 int len;
510 char *s;
512 if (size != 1 || strcmp(attributes[0], S_GROUPS) != 0) {
513 logit("invalid lsgroup op\n");
514 errno = EINVAL;
515 return -1;
518 ZERO_STRUCT(request);
519 ZERO_STRUCT(response);
521 ret = winbindd_request(WINBINDD_LIST_GROUPS, &request, &response);
522 if (ret != 0) {
523 errno = EINVAL;
524 return -1;
527 len = strlen(response.extra_data);
529 s = malloc(len+2);
530 if (!s) {
531 free_response(&response);
532 errno = ENOMEM;
533 return -1;
536 memcpy(s, response.extra_data, len+1);
538 replace_commas(s);
540 results[0].attr_un.au_char = s;
541 results[0].attr_flag = 0;
543 free_response(&response);
545 return 0;
549 static attrval_t pwd_to_group(struct passwd *pwd)
551 attrval_t r;
552 struct group *grp = wb_aix_getgrgid(pwd->pw_gid);
554 if (!grp) {
555 r.attr_flag = EINVAL;
556 } else {
557 r.attr_flag = 0;
558 r.attr_un.au_char = strdup(grp->gr_name);
559 free_grp(grp);
562 return r;
565 static attrval_t pwd_to_groupsids(struct passwd *pwd)
567 attrval_t r;
568 char *s, *p;
570 s = wb_aix_getgrset(pwd->pw_name);
571 if (!s) {
572 r.attr_flag = EINVAL;
573 return r;
576 p = malloc(strlen(s)+2);
577 if (!p) {
578 r.attr_flag = ENOMEM;
579 return r;
582 strcpy(p, s);
583 replace_commas(p);
584 free(s);
586 r.attr_un.au_char = p;
588 return r;
591 static attrval_t pwd_to_sid(struct passwd *pwd)
593 struct winbindd_request request;
594 struct winbindd_response response;
595 attrval_t r;
597 ZERO_STRUCT(request);
598 ZERO_STRUCT(response);
600 request.data.uid = pwd->pw_uid;
602 if (winbindd_request(WINBINDD_UID_TO_SID, &request, &response) !=
603 NSS_STATUS_SUCCESS) {
604 r.attr_flag = ENOENT;
605 } else {
606 r.attr_flag = 0;
607 r.attr_un.au_char = strdup(response.data.sid.sid);
610 return r;
613 static int wb_aix_user_attrib(const char *key, char *attributes[],
614 attrval_t results[], int size)
616 struct passwd *pwd;
617 int i;
619 pwd = wb_aix_getpwnam(key);
620 if (!pwd) {
621 errno = ENOENT;
622 return -1;
625 for (i=0;i<size;i++) {
626 results[i].attr_flag = 0;
628 if (strcmp(attributes[i], S_ID) == 0) {
629 results[i].attr_un.au_int = pwd->pw_uid;
630 } else if (strcmp(attributes[i], S_PWD) == 0) {
631 results[i].attr_un.au_char = strdup(pwd->pw_passwd);
632 } else if (strcmp(attributes[i], S_HOME) == 0) {
633 results[i].attr_un.au_char = strdup(pwd->pw_dir);
634 } else if (strcmp(attributes[0], S_SHELL) == 0) {
635 results[i].attr_un.au_char = strdup(pwd->pw_shell);
636 } else if (strcmp(attributes[0], S_REGISTRY) == 0) {
637 results[i].attr_un.au_char = strdup("WINBIND");
638 } else if (strcmp(attributes[0], S_GECOS) == 0) {
639 results[i].attr_un.au_char = strdup(pwd->pw_gecos);
640 } else if (strcmp(attributes[0], S_PGRP) == 0) {
641 results[i] = pwd_to_group(pwd);
642 } else if (strcmp(attributes[0], S_GECOS) == 0) {
643 results[i].attr_un.au_char = strdup(pwd->pw_gecos);
644 } else if (strcmp(attributes[0], S_GROUPSIDS) == 0) {
645 results[i] = pwd_to_groupsids(pwd);
646 } else if (strcmp(attributes[0], "SID") == 0) {
647 results[i] = pwd_to_sid(pwd);
648 } else {
649 logit("Unknown user attribute '%s'\n", attributes[i]);
650 results[i].attr_flag = EINVAL;
654 free_pwd(pwd);
656 return 0;
659 static int wb_aix_group_attrib(const char *key, char *attributes[],
660 attrval_t results[], int size)
662 struct group *grp;
663 int i;
665 grp = wb_aix_getgrnam(key);
666 if (!grp) {
667 errno = ENOENT;
668 return -1;
671 for (i=0;i<size;i++) {
672 results[i].attr_flag = 0;
674 if (strcmp(attributes[i], S_PWD) == 0) {
675 results[i].attr_un.au_char = strdup(grp->gr_passwd);
676 } else if (strcmp(attributes[i], S_ID) == 0) {
677 results[i].attr_un.au_int = grp->gr_gid;
678 } else {
679 logit("Unknown group attribute '%s'\n", attributes[i]);
680 results[i].attr_flag = EINVAL;
684 free_grp(grp);
686 return 0;
691 called for user/group enumerations
693 static int wb_aix_getentry(char *key, char *table, char *attributes[],
694 attrval_t results[], int size)
696 logit("Got getentry with key='%s' table='%s' size=%d attributes[0]='%s'\n",
697 key, table, size, attributes[0]);
699 if (strcmp(key, "ALL") == 0 &&
700 strcmp(table, "user") == 0) {
701 return wb_aix_lsuser(attributes, results, size);
704 if (strcmp(key, "ALL") == 0 &&
705 strcmp(table, "group") == 0) {
706 return wb_aix_lsgroup(attributes, results, size);
709 if (strcmp(table, "user") == 0) {
710 return wb_aix_user_attrib(key, attributes, results, size);
713 if (strcmp(table, "group") == 0) {
714 return wb_aix_group_attrib(key, attributes, results, size);
717 logit("Unknown getentry operation key='%s' table='%s'\n", key, table);
719 errno = ENOSYS;
720 return -1;
726 called to start the backend
728 static void *wb_aix_open(const char *name, const char *domain, int mode, char *options)
730 if (strstr(options, "debug")) {
731 debug_enabled = 1;
733 logit("open name='%s' mode=%d domain='%s' options='%s'\n", name, domain,
734 mode, options);
735 return NULL;
738 static void wb_aix_close(void *token)
740 logit("close\n");
741 return;
745 return a list of additional attributes supported by the backend
747 static attrlist_t **wb_aix_attrlist(void)
749 attrlist_t **ret;
750 logit("method attrlist called\n");
751 ret = malloc(2*sizeof(attrlist_t *) + sizeof(attrlist_t));
752 if (!ret) {
753 errno = ENOMEM;
754 return NULL;
757 ret[0] = (attrlist_t *)(ret+2);
759 /* just one extra attribute - the windows SID */
760 ret[0]->al_name = strdup("SID");
761 ret[0]->al_flags = AL_USERATTR;
762 ret[0]->al_type = SEC_CHAR;
763 ret[1] = NULL;
765 return ret;
770 turn a long username into a short one. Needed to cope with the 8 char
771 username limit in AIX 5.2 and below
773 static int wb_aix_normalize(char *longname, char *shortname)
775 struct passwd *pwd;
777 logit("normalize '%s'\n", longname);
779 /* automatically cope with AIX 5.3 with longer usernames
780 when it comes out */
781 if (S_NAMELEN > strlen(longname)) {
782 strcpy(shortname, longname);
783 return 1;
786 pwd = wb_aix_getpwnam(longname);
787 if (!pwd) {
788 errno = ENOENT;
789 return 0;
792 sprintf(shortname, "%c%07u", WB_AIX_ENCODED, pwd->pw_uid);
794 free_pwd(pwd);
796 return 1;
801 authenticate a user
803 static int wb_aix_authenticate(char *user, char *pass,
804 int *reenter, char **message)
806 struct winbindd_request request;
807 struct winbindd_response response;
808 NSS_STATUS result;
809 char *r_user = user;
811 logit("authenticate '%s' response='%s'\n", user, pass);
813 *reenter = 0;
814 *message = NULL;
816 /* Send off request */
817 ZERO_STRUCT(request);
818 ZERO_STRUCT(response);
820 if (*user == WB_AIX_ENCODED) {
821 r_user = decode_user(r_user);
822 if (!r_user) {
823 return AUTH_NOTFOUND;
827 STRCPY_RET(request.data.auth.user, r_user);
828 STRCPY_RET(request.data.auth.pass, pass);
830 if (*user == WB_AIX_ENCODED) {
831 free(r_user);
834 result = winbindd_request(WINBINDD_PAM_AUTH, &request, &response);
836 free_response(&response);
838 logit("auth result %d for '%s'\n", result, user);
840 if (result == NSS_STATUS_SUCCESS) {
841 errno = 0;
842 return AUTH_SUCCESS;
845 return AUTH_FAILURE;
850 change a user password
852 static int wb_aix_chpass(char *user, char *oldpass, char *newpass, char **message)
854 struct winbindd_request request;
855 struct winbindd_response response;
856 NSS_STATUS result;
857 char *r_user = user;
859 if (*user == WB_AIX_ENCODED) {
860 r_user = decode_user(r_user);
861 if (!r_user) {
862 errno = ENOENT;
863 return -1;
867 logit("chpass '%s' old='%s' new='%s'\n", r_user, oldpass, newpass);
869 *message = NULL;
871 /* Send off request */
872 ZERO_STRUCT(request);
873 ZERO_STRUCT(response);
875 STRCPY_RET(request.data.chauthtok.user, r_user);
876 STRCPY_RET(request.data.chauthtok.oldpass, oldpass);
877 STRCPY_RET(request.data.chauthtok.newpass, newpass);
879 if (*user == WB_AIX_ENCODED) {
880 free(r_user);
883 result = winbindd_request(WINBINDD_PAM_CHAUTHTOK, &request, &response);
885 free_response(&response);
887 if (result == NSS_STATUS_SUCCESS) {
888 errno = 0;
889 return 0;
892 errno = EINVAL;
893 return -1;
897 don't do any password strength testing for now
899 static int wb_aix_passwdrestrictions(char *user, char *newpass, char *oldpass,
900 char **message)
902 logit("passwdresrictions called for '%s'\n", user);
903 return 0;
907 static int wb_aix_passwdexpired(char *user, char **message)
909 logit("passwdexpired '%s'\n", user);
910 /* we should check the account bits here */
911 return 0;
916 we can't return a crypt() password
918 static char *wb_aix_getpasswd(char *user)
920 logit("getpasswd '%s'\n", user);
921 errno = ENOSYS;
922 return NULL;
926 this is called to update things like the last login time. We don't
927 currently pass this onto the DC
929 static int wb_aix_putentry(char *key, char *table, char *attributes[],
930 attrval_t values[], int size)
932 logit("putentry key='%s' table='%s' attrib='%s'\n",
933 key, table, size>=1?attributes[0]:"<null>");
934 errno = ENOSYS;
935 return -1;
938 static int wb_aix_commit(char *key, char *table)
940 logit("commit key='%s' table='%s'\n");
941 errno = ENOSYS;
942 return -1;
945 static int wb_aix_getgrusers(char *group, void *result, int type, int *size)
947 logit("getgrusers group='%s'\n", group);
948 errno = ENOSYS;
949 return -1;
953 #define DECL_METHOD(x) \
954 int method_ ## x(void) \
956 logit("UNIMPLEMENTED METHOD '%s'\n", #x); \
957 errno = EINVAL; \
958 return -1; \
961 #if LOG_UNIMPLEMENTED_CALLS
962 DECL_METHOD(delgroup);
963 DECL_METHOD(deluser);
964 DECL_METHOD(newgroup);
965 DECL_METHOD(newuser);
966 DECL_METHOD(putgrent);
967 DECL_METHOD(putgrusers);
968 DECL_METHOD(putpwent);
969 DECL_METHOD(lock);
970 DECL_METHOD(unlock);
971 DECL_METHOD(getcred);
972 DECL_METHOD(setcred);
973 DECL_METHOD(deletecred);
974 #endif
976 int wb_aix_init(struct secmethod_table *methods)
978 ZERO_STRUCTP(methods);
980 methods->method_version = SECMETHOD_VERSION_520;
982 methods->method_getgrgid = wb_aix_getgrgid;
983 methods->method_getgrnam = wb_aix_getgrnam;
984 methods->method_getgrset = wb_aix_getgrset;
985 methods->method_getpwnam = wb_aix_getpwnam;
986 methods->method_getpwuid = wb_aix_getpwuid;
987 methods->method_getentry = wb_aix_getentry;
988 methods->method_open = wb_aix_open;
989 methods->method_close = wb_aix_close;
990 methods->method_normalize = wb_aix_normalize;
991 methods->method_passwdexpired = wb_aix_passwdexpired;
992 methods->method_putentry = wb_aix_putentry;
993 methods->method_getpasswd = wb_aix_getpasswd;
994 methods->method_authenticate = wb_aix_authenticate;
995 methods->method_commit = wb_aix_commit;
996 methods->method_chpass = wb_aix_chpass;
997 methods->method_passwdrestrictions = wb_aix_passwdrestrictions;
998 methods->method_getgracct = wb_aix_getgracct;
999 methods->method_getgrusers = wb_aix_getgrusers;
1000 methods->method_attrlist = wb_aix_attrlist;
1002 #if LOG_UNIMPLEMENTED_CALLS
1003 methods->method_delgroup = method_delgroup;
1004 methods->method_deluser = method_deluser;
1005 methods->method_newgroup = method_newgroup;
1006 methods->method_newuser = method_newuser;
1007 methods->method_putgrent = method_putgrent;
1008 methods->method_putgrusers = method_putgrusers;
1009 methods->method_putpwent = method_putpwent;
1010 methods->method_lock = method_lock;
1011 methods->method_unlock = method_unlock;
1012 methods->method_getcred = method_getcred;
1013 methods->method_setcred = method_setcred;
1014 methods->method_deletecred = method_deletecred;
1015 #endif
1017 return AUTH_SUCCESS;