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 Lesser General Public
13 License as published by the Free Software Foundation; either
14 version 3 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 Lesser General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 To install this module copy nsswitch/WINBIND to /usr/lib/security and add
28 "WINBIND" in /usr/lib/security/methods.cfg and /etc/security/user
30 Note that this module also provides authentication and password
31 changing routines, so you do not need to install the winbind PAM
35 http://publib16.boulder.ibm.com/doc_link/en_US/a_doc_lib/aixprggd/kernextc/sec_load_mod.htm
36 for some information in the interface that this module implements
38 Many thanks to Julianne Haugh for explaining some of the finer
39 details of this interface.
41 To debug this module use uess_test.c (which you can get from tridge)
42 or set "options=debug" in /usr/lib/security/methods.cfg
46 #include "winbind_client.h"
49 /* enable this to log which entry points have not been
51 #define LOG_UNIMPLEMENTED_CALLS 0
54 #define WB_AIX_ENCODED '_'
56 static int debug_enabled
;
59 static void logit(const char *format
, ...)
66 f
= fopen("/tmp/WINBIND_DEBUG.log", "a");
69 vfprintf(f
, format
, ap
);
75 #define HANDLE_ERRORS(ret) do { \
76 if ((ret) == NSS_STATUS_NOTFOUND) { \
79 } else if ((ret) != NSS_STATUS_SUCCESS) { \
85 #define STRCPY_RET(dest, src) \
87 if (strlen(src)+1 > sizeof(dest)) { errno = EINVAL; return -1; } \
91 #define STRCPY_RETNULL(dest, src) \
93 if (strlen(src)+1 > sizeof(dest)) { errno = EINVAL; return NULL; } \
98 /* free a passwd structure */
99 static void free_pwd(struct passwd
*pwd
)
102 free(pwd
->pw_passwd
);
109 /* free a group structure */
110 static void free_grp(struct group
*grp
)
115 free(grp
->gr_passwd
);
122 for (i
=0; grp
->gr_mem
[i
]; i
++) {
123 free(grp
->gr_mem
[i
]);
131 /* replace commas with nulls, and null terminate */
132 static void replace_commas(char *s
)
135 for (p
=strchr(s
, ','); p
; p
= strchr(p
+1, ',')) {
140 p0
[strlen(p0
)+1] = 0;
144 /* the decode_*() routines are used to cope with the fact that AIX 5.2
145 and below cannot handle user or group names longer than 8
146 characters in some interfaces. We use the normalize method to
147 provide a mapping to a username that fits, by using the form '_UID'
150 this only works if you can guarantee that the WB_AIX_ENCODED char
151 is not used as the first char of any other username
153 static unsigned decode_id(const char *name
)
156 sscanf(name
+1, "%u", &id
);
160 static struct passwd
*wb_aix_getpwuid(uid_t uid
);
162 static char *decode_user(const char *name
)
168 sscanf(name
+1, "%u", &id
);
169 pwd
= wb_aix_getpwuid(id
);
173 ret
= strdup(pwd
->pw_name
);
177 logit("decoded '%s' -> '%s'\n", name
, ret
);
184 fill a struct passwd from a winbindd_pw struct, allocating as a single block
186 static struct passwd
*fill_pwent(struct winbindd_pw
*pw
)
188 struct passwd
*result
;
190 result
= calloc(1, sizeof(struct passwd
));
196 result
->pw_uid
= pw
->pw_uid
;
197 result
->pw_gid
= pw
->pw_gid
;
198 result
->pw_name
= strdup(pw
->pw_name
);
199 result
->pw_passwd
= strdup(pw
->pw_passwd
);
200 result
->pw_gecos
= strdup(pw
->pw_gecos
);
201 result
->pw_dir
= strdup(pw
->pw_dir
);
202 result
->pw_shell
= strdup(pw
->pw_shell
);
209 fill a struct group from a winbindd_pw struct, allocating as a single block
211 static struct group
*fill_grent(struct winbindd_gr
*gr
, char *gr_mem
)
214 struct group
*result
;
217 result
= calloc(1, sizeof(struct group
));
223 result
->gr_gid
= gr
->gr_gid
;
225 result
->gr_name
= strdup(gr
->gr_name
);
226 result
->gr_passwd
= strdup(gr
->gr_passwd
);
228 /* Group membership */
229 if ((gr
->num_gr_mem
< 0) || !gr_mem
) {
233 if (gr
->num_gr_mem
== 0) {
238 result
->gr_mem
= (char **)malloc(sizeof(char *) * (gr
->num_gr_mem
+1));
239 if (!result
->gr_mem
) {
240 free(result
->gr_name
);
241 free(result
->gr_passwd
);
247 /* Start looking at extra data */
249 for (name
= strtok_r(gr_mem
, ",", &p
);
251 name
= strtok_r(NULL
, ",", &p
)) {
252 if (i
== gr
->num_gr_mem
) {
255 result
->gr_mem
[i
] = strdup(name
);
260 result
->gr_mem
[i
] = NULL
;
267 /* take a group id and return a filled struct group */
268 static struct group
*wb_aix_getgrgid(gid_t gid
)
270 struct winbindd_response response
;
271 struct winbindd_request request
;
275 logit("getgrgid %d\n", gid
);
277 ZERO_STRUCT(response
);
278 ZERO_STRUCT(request
);
280 request
.data
.gid
= gid
;
282 ret
= winbindd_request_response(NULL
, WINBINDD_GETGRGID
,
283 &request
, &response
);
285 logit("getgrgid ret=%d\n", ret
);
289 grp
= fill_grent(&response
.data
.gr
, response
.extra_data
.data
);
291 winbindd_free_response(&response
);
296 /* take a group name and return a filled struct group */
297 static struct group
*wb_aix_getgrnam(const char *name
)
299 struct winbindd_response response
;
300 struct winbindd_request request
;
304 if (*name
== WB_AIX_ENCODED
) {
305 return wb_aix_getgrgid(decode_id(name
));
308 logit("getgrnam '%s'\n", name
);
310 ZERO_STRUCT(response
);
311 ZERO_STRUCT(request
);
313 STRCPY_RETNULL(request
.data
.groupname
, name
);
315 ret
= winbindd_request_response(NULL
, WINBINDD_GETGRNAM
,
316 &request
, &response
);
320 grp
= fill_grent(&response
.data
.gr
, response
.extra_data
.data
);
322 winbindd_free_response(&response
);
328 /* this call doesn't have to fill in the gr_mem, but we do anyway
330 static struct group
*wb_aix_getgracct(void *id
, int type
)
333 return wb_aix_getgrnam((char *)id
);
336 return wb_aix_getgrgid(*(int *)id
);
343 /* take a username and return a string containing a comma-separated
344 list of group id numbers to which the user belongs */
345 static char *wb_aix_getgrset(char *user
)
347 struct winbindd_response response
;
348 struct winbindd_request request
;
356 if (*user
== WB_AIX_ENCODED
) {
357 r_user
= decode_user(r_user
);
364 logit("getgrset '%s'\n", r_user
);
366 ZERO_STRUCT(response
);
367 ZERO_STRUCT(request
);
369 STRCPY_RETNULL(request
.data
.username
, r_user
);
371 if (*user
== WB_AIX_ENCODED
) {
375 ret
= winbindd_request_response(NULL
, WINBINDD_GETGROUPS
,
376 &request
, &response
);
380 num_gids
= response
.data
.num_entries
;
381 gid_list
= (gid_t
*)response
.extra_data
.data
;
383 /* allocate a space large enough to contruct the string */
384 tmpbuf
= malloc(num_gids
*12);
389 for (idx
=i
=0; i
< num_gids
-1; i
++) {
390 idx
+= sprintf(tmpbuf
+idx
, "%u,", gid_list
[i
]);
392 idx
+= sprintf(tmpbuf
+idx
, "%u", gid_list
[i
]);
394 winbindd_free_response(&response
);
400 /* take a uid and return a filled struct passwd */
401 static struct passwd
*wb_aix_getpwuid(uid_t uid
)
403 struct winbindd_response response
;
404 struct winbindd_request request
;
408 logit("getpwuid '%d'\n", uid
);
410 ZERO_STRUCT(response
);
411 ZERO_STRUCT(request
);
413 request
.data
.uid
= uid
;
415 ret
= winbindd_request_response(NULL
, WINBINDD_GETPWUID
,
416 &request
, &response
);
420 pwd
= fill_pwent(&response
.data
.pw
);
422 winbindd_free_response(&response
);
424 logit("getpwuid gave ptr %p\n", pwd
);
430 /* take a username and return a filled struct passwd */
431 static struct passwd
*wb_aix_getpwnam(const char *name
)
433 struct winbindd_response response
;
434 struct winbindd_request request
;
438 if (*name
== WB_AIX_ENCODED
) {
439 return wb_aix_getpwuid(decode_id(name
));
442 logit("getpwnam '%s'\n", name
);
444 ZERO_STRUCT(response
);
445 ZERO_STRUCT(request
);
447 STRCPY_RETNULL(request
.data
.username
, name
);
449 ret
= winbindd_request_response(NULL
, WINBINDD_GETPWNAM
,
450 &request
, &response
);
454 pwd
= fill_pwent(&response
.data
.pw
);
456 winbindd_free_response(&response
);
458 logit("getpwnam gave ptr %p\n", pwd
);
466 static int wb_aix_lsuser(char *attributes
[], attrval_t results
[], int size
)
469 struct winbindd_request request
;
470 struct winbindd_response response
;
474 if (size
!= 1 || strcmp(attributes
[0], S_USERS
) != 0) {
475 logit("invalid lsuser op\n");
480 ZERO_STRUCT(request
);
481 ZERO_STRUCT(response
);
483 ret
= winbindd_request_response(NULL
, WINBINDD_LIST_USERS
,
484 &request
, &response
);
490 len
= strlen(response
.extra_data
.data
);
494 winbindd_free_response(&response
);
499 memcpy(s
, response
.extra_data
.data
, len
+1);
503 results
[0].attr_un
.au_char
= s
;
504 results
[0].attr_flag
= 0;
506 winbindd_free_response(&response
);
515 static int wb_aix_lsgroup(char *attributes
[], attrval_t results
[], int size
)
518 struct winbindd_request request
;
519 struct winbindd_response response
;
523 if (size
!= 1 || strcmp(attributes
[0], S_GROUPS
) != 0) {
524 logit("invalid lsgroup op\n");
529 ZERO_STRUCT(request
);
530 ZERO_STRUCT(response
);
532 ret
= winbindd_request_response(NULL
, WINBINDD_LIST_GROUPS
,
533 &request
, &response
);
539 len
= strlen(response
.extra_data
.data
);
543 winbindd_free_response(&response
);
548 memcpy(s
, response
.extra_data
.data
, len
+1);
552 results
[0].attr_un
.au_char
= s
;
553 results
[0].attr_flag
= 0;
555 winbindd_free_response(&response
);
561 static attrval_t
pwd_to_group(struct passwd
*pwd
)
564 struct group
*grp
= wb_aix_getgrgid(pwd
->pw_gid
);
567 r
.attr_flag
= EINVAL
;
570 r
.attr_un
.au_char
= strdup(grp
->gr_name
);
577 static attrval_t
pwd_to_groupsids(struct passwd
*pwd
)
582 if ( (s
= wb_aix_getgrset(pwd
->pw_name
)) == NULL
) {
583 r
.attr_flag
= EINVAL
;
587 if ( (p
= malloc(strlen(s
)+2)) == NULL
) {
588 r
.attr_flag
= ENOMEM
;
596 r
.attr_un
.au_char
= p
;
601 static attrval_t
pwd_to_sid(struct passwd
*pwd
)
603 struct winbindd_request request
;
604 struct winbindd_response response
;
607 ZERO_STRUCT(request
);
608 ZERO_STRUCT(response
);
610 request
.data
.uid
= pwd
->pw_uid
;
612 if (winbindd_request_response(NULL
, WINBINDD_UID_TO_SID
,
613 &request
, &response
) !=
614 NSS_STATUS_SUCCESS
) {
615 r
.attr_flag
= ENOENT
;
618 r
.attr_un
.au_char
= strdup(response
.data
.sid
.sid
);
624 static int wb_aix_user_attrib(const char *key
, char *attributes
[],
625 attrval_t results
[], int size
)
630 pwd
= wb_aix_getpwnam(key
);
636 for (i
=0;i
<size
;i
++) {
637 results
[i
].attr_flag
= 0;
639 if (strcmp(attributes
[i
], S_ID
) == 0) {
640 results
[i
].attr_un
.au_int
= pwd
->pw_uid
;
641 #ifdef _AIXVERSION_530
642 } else if (strcmp(attributes
[i
], S_PGID
) == 0) {
643 results
[i
].attr_un
.au_int
= pwd
->pw_gid
;
645 } else if (strcmp(attributes
[i
], S_PWD
) == 0) {
646 results
[i
].attr_un
.au_char
= strdup(pwd
->pw_passwd
);
647 } else if (strcmp(attributes
[i
], S_HOME
) == 0) {
648 results
[i
].attr_un
.au_char
= strdup(pwd
->pw_dir
);
649 } else if (strcmp(attributes
[i
], S_SHELL
) == 0) {
650 results
[i
].attr_un
.au_char
= strdup(pwd
->pw_shell
);
651 } else if (strcmp(attributes
[i
], S_REGISTRY
) == 0) {
652 results
[i
].attr_un
.au_char
= strdup("WINBIND");
653 } else if (strcmp(attributes
[i
], S_GECOS
) == 0) {
654 results
[i
].attr_un
.au_char
= strdup(pwd
->pw_gecos
);
655 } else if (strcmp(attributes
[i
], S_PGRP
) == 0) {
656 results
[i
] = pwd_to_group(pwd
);
657 } else if (strcmp(attributes
[i
], S_GROUPS
) == 0) {
658 results
[i
] = pwd_to_groupsids(pwd
);
659 } else if (strcmp(attributes
[i
], "SID") == 0) {
660 results
[i
] = pwd_to_sid(pwd
);
662 logit("Unknown user attribute '%s'\n", attributes
[i
]);
663 results
[i
].attr_flag
= EINVAL
;
672 static int wb_aix_group_attrib(const char *key
, char *attributes
[],
673 attrval_t results
[], int size
)
678 grp
= wb_aix_getgrnam(key
);
684 for (i
=0;i
<size
;i
++) {
685 results
[i
].attr_flag
= 0;
687 if (strcmp(attributes
[i
], S_PWD
) == 0) {
688 results
[i
].attr_un
.au_char
= strdup(grp
->gr_passwd
);
689 } else if (strcmp(attributes
[i
], S_ID
) == 0) {
690 results
[i
].attr_un
.au_int
= grp
->gr_gid
;
692 logit("Unknown group attribute '%s'\n", attributes
[i
]);
693 results
[i
].attr_flag
= EINVAL
;
704 called for user/group enumerations
706 static int wb_aix_getentry(char *key
, char *table
, char *attributes
[],
707 attrval_t results
[], int size
)
709 logit("Got getentry with key='%s' table='%s' size=%d attributes[0]='%s'\n",
710 key
, table
, size
, attributes
[0]);
712 if (strcmp(key
, "ALL") == 0 &&
713 strcmp(table
, "user") == 0) {
714 return wb_aix_lsuser(attributes
, results
, size
);
717 if (strcmp(key
, "ALL") == 0 &&
718 strcmp(table
, "group") == 0) {
719 return wb_aix_lsgroup(attributes
, results
, size
);
722 if (strcmp(table
, "user") == 0) {
723 return wb_aix_user_attrib(key
, attributes
, results
, size
);
726 if (strcmp(table
, "group") == 0) {
727 return wb_aix_group_attrib(key
, attributes
, results
, size
);
730 logit("Unknown getentry operation key='%s' table='%s'\n", key
, table
);
739 called to start the backend
741 static void *wb_aix_open(const char *name
, const char *domain
, int mode
, char *options
)
743 if (strstr(options
, "debug")) {
746 logit("open name='%s' mode=%d domain='%s' options='%s'\n", name
, domain
,
751 static void wb_aix_close(void *token
)
757 #ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_ATTRLIST
759 return a list of additional attributes supported by the backend
761 static attrlist_t
**wb_aix_attrlist(void)
763 /* pretty confusing but we are allocating the array of pointers
764 and the structures we'll be pointing to all at once. So
765 you need N+1 pointers and N structures. */
767 attrlist_t
**ret
= NULL
;
768 attrlist_t
*offset
= NULL
;
778 /* user attributes */
779 {S_ID
, AL_USERATTR
, SEC_INT
},
780 {S_PGRP
, AL_USERATTR
, SEC_CHAR
},
781 {S_HOME
, AL_USERATTR
, SEC_CHAR
},
782 {S_SHELL
, AL_USERATTR
, SEC_CHAR
},
783 #ifdef _AIXVERSION_530
784 {S_PGID
, AL_USERATTR
, SEC_INT
},
786 {S_GECOS
, AL_USERATTR
, SEC_CHAR
},
787 {S_SHELL
, AL_USERATTR
, SEC_CHAR
},
788 {S_PGRP
, AL_USERATTR
, SEC_CHAR
},
789 {S_GROUPS
, AL_USERATTR
, SEC_LIST
},
790 {"SID", AL_USERATTR
, SEC_CHAR
},
792 /* group attributes */
793 {S_ID
, AL_GROUPATTR
, SEC_INT
}
796 logit("method attrlist called\n");
798 n
= sizeof(attr_list
) / sizeof(struct attr_types
);
799 size
= (n
*sizeof(attrlist_t
*));
801 if ( (ret
= malloc( size
)) == NULL
) {
806 /* offset to where the structures start in the buffer */
808 offset
= (attrlist_t
*)(ret
+ n
);
810 /* now loop over the user_attr_list[] array and add
813 for ( i
=0; i
<n
; i
++ ) {
814 attrlist_t
*a
= malloc(sizeof(attrlist_t
));
817 /* this is bad. Just bail */
821 a
->al_name
= strdup(attr_list
[i
].name
);
822 a
->al_flags
= attr_list
[i
].flags
;
823 a
->al_type
= attr_list
[i
].type
;
835 turn a long username into a short one. Needed to cope with the 8 char
836 username limit in AIX 5.2 and below
838 static int wb_aix_normalize(char *longname
, char *shortname
)
842 logit("normalize '%s'\n", longname
);
844 /* automatically cope with AIX 5.3 with longer usernames
846 if (S_NAMELEN
> strlen(longname
)) {
847 strcpy(shortname
, longname
);
851 pwd
= wb_aix_getpwnam(longname
);
857 sprintf(shortname
, "%c%07u", WB_AIX_ENCODED
, pwd
->pw_uid
);
868 static int wb_aix_authenticate(char *user
, char *pass
,
869 int *reenter
, char **message
)
871 struct winbindd_request request
;
872 struct winbindd_response response
;
876 logit("authenticate '%s' response='%s'\n", user
, pass
);
881 /* Send off request */
882 ZERO_STRUCT(request
);
883 ZERO_STRUCT(response
);
885 if (*user
== WB_AIX_ENCODED
) {
886 r_user
= decode_user(r_user
);
888 return AUTH_NOTFOUND
;
892 STRCPY_RET(request
.data
.auth
.user
, r_user
);
893 STRCPY_RET(request
.data
.auth
.pass
, pass
);
895 if (*user
== WB_AIX_ENCODED
) {
899 result
= winbindd_request_response(NULL
, WINBINDD_PAM_AUTH
,
900 &request
, &response
);
902 winbindd_free_response(&response
);
904 logit("auth result %d for '%s'\n", result
, user
);
906 if (result
== NSS_STATUS_SUCCESS
) {
916 change a user password
918 static int wb_aix_chpass(char *user
, char *oldpass
, char *newpass
, char **message
)
920 struct winbindd_request request
;
921 struct winbindd_response response
;
925 if (*user
== WB_AIX_ENCODED
) {
926 r_user
= decode_user(r_user
);
933 logit("chpass '%s' old='%s' new='%s'\n", r_user
, oldpass
, newpass
);
937 /* Send off request */
938 ZERO_STRUCT(request
);
939 ZERO_STRUCT(response
);
941 STRCPY_RET(request
.data
.chauthtok
.user
, r_user
);
942 STRCPY_RET(request
.data
.chauthtok
.oldpass
, oldpass
);
943 STRCPY_RET(request
.data
.chauthtok
.newpass
, newpass
);
945 if (*user
== WB_AIX_ENCODED
) {
949 result
= winbindd_request_response(NULL
, WINBINDD_PAM_CHAUTHTOK
,
950 &request
, &response
);
952 winbindd_free_response(&response
);
954 if (result
== NSS_STATUS_SUCCESS
) {
964 don't do any password strength testing for now
966 static int wb_aix_passwdrestrictions(char *user
, char *newpass
, char *oldpass
,
969 logit("passwdresrictions called for '%s'\n", user
);
974 static int wb_aix_passwdexpired(char *user
, char **message
)
976 logit("passwdexpired '%s'\n", user
);
977 /* we should check the account bits here */
983 we can't return a crypt() password
985 static char *wb_aix_getpasswd(char *user
)
987 logit("getpasswd '%s'\n", user
);
993 this is called to update things like the last login time. We don't
994 currently pass this onto the DC
996 static int wb_aix_putentry(char *key
, char *table
, char *attributes
[],
997 attrval_t values
[], int size
)
999 logit("putentry key='%s' table='%s' attrib='%s'\n",
1000 key
, table
, size
>=1?attributes
[0]:"<null>");
1005 static int wb_aix_commit(char *key
, char *table
)
1007 logit("commit key='%s' table='%s'\n");
1012 static int wb_aix_getgrusers(char *group
, void *result
, int type
, int *size
)
1014 logit("getgrusers group='%s'\n", group
);
1020 #define DECL_METHOD(x) \
1021 int method_ ## x(void) \
1023 logit("UNIMPLEMENTED METHOD '%s'\n", #x); \
1028 #if LOG_UNIMPLEMENTED_CALLS
1029 DECL_METHOD(delgroup
);
1030 DECL_METHOD(deluser
);
1031 DECL_METHOD(newgroup
);
1032 DECL_METHOD(newuser
);
1033 DECL_METHOD(putgrent
);
1034 DECL_METHOD(putgrusers
);
1035 DECL_METHOD(putpwent
);
1037 DECL_METHOD(unlock
);
1038 DECL_METHOD(getcred
);
1039 DECL_METHOD(setcred
);
1040 DECL_METHOD(deletecred
);
1043 int wb_aix_init(struct secmethod_table
*methods
)
1045 ZERO_STRUCTP(methods
);
1047 #ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_VERSION
1048 methods
->method_version
= SECMETHOD_VERSION_520
;
1051 methods
->method_getgrgid
= wb_aix_getgrgid
;
1052 methods
->method_getgrnam
= wb_aix_getgrnam
;
1053 methods
->method_getgrset
= wb_aix_getgrset
;
1054 methods
->method_getpwnam
= wb_aix_getpwnam
;
1055 methods
->method_getpwuid
= wb_aix_getpwuid
;
1056 methods
->method_getentry
= wb_aix_getentry
;
1057 methods
->method_open
= wb_aix_open
;
1058 methods
->method_close
= wb_aix_close
;
1059 methods
->method_normalize
= wb_aix_normalize
;
1060 methods
->method_passwdexpired
= wb_aix_passwdexpired
;
1061 methods
->method_putentry
= wb_aix_putentry
;
1062 methods
->method_getpasswd
= wb_aix_getpasswd
;
1063 methods
->method_authenticate
= wb_aix_authenticate
;
1064 methods
->method_commit
= wb_aix_commit
;
1065 methods
->method_chpass
= wb_aix_chpass
;
1066 methods
->method_passwdrestrictions
= wb_aix_passwdrestrictions
;
1067 methods
->method_getgracct
= wb_aix_getgracct
;
1068 methods
->method_getgrusers
= wb_aix_getgrusers
;
1069 #ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_ATTRLIST
1070 methods
->method_attrlist
= wb_aix_attrlist
;
1073 #if LOG_UNIMPLEMENTED_CALLS
1074 methods
->method_delgroup
= method_delgroup
;
1075 methods
->method_deluser
= method_deluser
;
1076 methods
->method_newgroup
= method_newgroup
;
1077 methods
->method_newuser
= method_newuser
;
1078 methods
->method_putgrent
= method_putgrent
;
1079 methods
->method_putgrusers
= method_putgrusers
;
1080 methods
->method_putpwent
= method_putpwent
;
1081 methods
->method_lock
= method_lock
;
1082 methods
->method_unlock
= method_unlock
;
1083 methods
->method_getcred
= method_getcred
;
1084 methods
->method_setcred
= method_setcred
;
1085 methods
->method_deletecred
= method_deletecred
;
1088 return AUTH_SUCCESS
;