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
) {
244 /* Start looking at extra data */
246 for (name
= strtok_r(gr_mem
, ",", &p
);
248 name
= strtok_r(NULL
, ",", &p
)) {
249 if (i
== gr
->num_gr_mem
) {
252 result
->gr_mem
[i
] = strdup(name
);
257 result
->gr_mem
[i
] = NULL
;
264 /* take a group id and return a filled struct group */
265 static struct group
*wb_aix_getgrgid(gid_t gid
)
267 struct winbindd_response response
;
268 struct winbindd_request request
;
272 logit("getgrgid %d\n", gid
);
274 ZERO_STRUCT(response
);
275 ZERO_STRUCT(request
);
277 request
.data
.gid
= gid
;
279 ret
= winbindd_request_response(WINBINDD_GETGRGID
, &request
, &response
);
281 logit("getgrgid ret=%d\n", ret
);
285 grp
= fill_grent(&response
.data
.gr
, response
.extra_data
.data
);
287 winbindd_free_response(&response
);
292 /* take a group name and return a filled struct group */
293 static struct group
*wb_aix_getgrnam(const char *name
)
295 struct winbindd_response response
;
296 struct winbindd_request request
;
300 if (*name
== WB_AIX_ENCODED
) {
301 return wb_aix_getgrgid(decode_id(name
));
304 logit("getgrnam '%s'\n", name
);
306 ZERO_STRUCT(response
);
307 ZERO_STRUCT(request
);
309 STRCPY_RETNULL(request
.data
.groupname
, name
);
311 ret
= winbindd_request_response(WINBINDD_GETGRNAM
, &request
, &response
);
315 grp
= fill_grent(&response
.data
.gr
, response
.extra_data
.data
);
317 winbindd_free_response(&response
);
323 /* this call doesn't have to fill in the gr_mem, but we do anyway
325 static struct group
*wb_aix_getgracct(void *id
, int type
)
328 return wb_aix_getgrnam((char *)id
);
331 return wb_aix_getgrgid(*(int *)id
);
338 /* take a username and return a string containing a comma-separated
339 list of group id numbers to which the user belongs */
340 static char *wb_aix_getgrset(char *user
)
342 struct winbindd_response response
;
343 struct winbindd_request request
;
351 if (*user
== WB_AIX_ENCODED
) {
352 r_user
= decode_user(r_user
);
359 logit("getgrset '%s'\n", r_user
);
361 ZERO_STRUCT(response
);
362 ZERO_STRUCT(request
);
364 STRCPY_RETNULL(request
.data
.username
, r_user
);
366 if (*user
== WB_AIX_ENCODED
) {
370 ret
= winbindd_request_response(WINBINDD_GETGROUPS
, &request
, &response
);
374 num_gids
= response
.data
.num_entries
;
375 gid_list
= (gid_t
*)response
.extra_data
.data
;
377 /* allocate a space large enough to contruct the string */
378 tmpbuf
= malloc(num_gids
*12);
383 for (idx
=i
=0; i
< num_gids
-1; i
++) {
384 idx
+= sprintf(tmpbuf
+idx
, "%u,", gid_list
[i
]);
386 idx
+= sprintf(tmpbuf
+idx
, "%u", gid_list
[i
]);
388 winbindd_free_response(&response
);
394 /* take a uid and return a filled struct passwd */
395 static struct passwd
*wb_aix_getpwuid(uid_t uid
)
397 struct winbindd_response response
;
398 struct winbindd_request request
;
402 logit("getpwuid '%d'\n", uid
);
404 ZERO_STRUCT(response
);
405 ZERO_STRUCT(request
);
407 request
.data
.uid
= uid
;
409 ret
= winbindd_request_response(WINBINDD_GETPWUID
, &request
, &response
);
413 pwd
= fill_pwent(&response
.data
.pw
);
415 winbindd_free_response(&response
);
417 logit("getpwuid gave ptr %p\n", pwd
);
423 /* take a username and return a filled struct passwd */
424 static struct passwd
*wb_aix_getpwnam(const char *name
)
426 struct winbindd_response response
;
427 struct winbindd_request request
;
431 if (*name
== WB_AIX_ENCODED
) {
432 return wb_aix_getpwuid(decode_id(name
));
435 logit("getpwnam '%s'\n", name
);
437 ZERO_STRUCT(response
);
438 ZERO_STRUCT(request
);
440 STRCPY_RETNULL(request
.data
.username
, name
);
442 ret
= winbindd_request_response(WINBINDD_GETPWNAM
, &request
, &response
);
446 pwd
= fill_pwent(&response
.data
.pw
);
448 winbindd_free_response(&response
);
450 logit("getpwnam gave ptr %p\n", pwd
);
458 static int wb_aix_lsuser(char *attributes
[], attrval_t results
[], int size
)
461 struct winbindd_request request
;
462 struct winbindd_response response
;
466 if (size
!= 1 || strcmp(attributes
[0], S_USERS
) != 0) {
467 logit("invalid lsuser op\n");
472 ZERO_STRUCT(request
);
473 ZERO_STRUCT(response
);
475 ret
= winbindd_request_response(WINBINDD_LIST_USERS
, &request
, &response
);
481 len
= strlen(response
.extra_data
.data
);
485 winbindd_free_response(&response
);
490 memcpy(s
, response
.extra_data
.data
, len
+1);
494 results
[0].attr_un
.au_char
= s
;
495 results
[0].attr_flag
= 0;
497 winbindd_free_response(&response
);
506 static int wb_aix_lsgroup(char *attributes
[], attrval_t results
[], int size
)
509 struct winbindd_request request
;
510 struct winbindd_response response
;
514 if (size
!= 1 || strcmp(attributes
[0], S_GROUPS
) != 0) {
515 logit("invalid lsgroup op\n");
520 ZERO_STRUCT(request
);
521 ZERO_STRUCT(response
);
523 ret
= winbindd_request_response(WINBINDD_LIST_GROUPS
, &request
, &response
);
529 len
= strlen(response
.extra_data
.data
);
533 winbindd_free_response(&response
);
538 memcpy(s
, response
.extra_data
.data
, len
+1);
542 results
[0].attr_un
.au_char
= s
;
543 results
[0].attr_flag
= 0;
545 winbindd_free_response(&response
);
551 static attrval_t
pwd_to_group(struct passwd
*pwd
)
554 struct group
*grp
= wb_aix_getgrgid(pwd
->pw_gid
);
557 r
.attr_flag
= EINVAL
;
560 r
.attr_un
.au_char
= strdup(grp
->gr_name
);
567 static attrval_t
pwd_to_groupsids(struct passwd
*pwd
)
572 if ( (s
= wb_aix_getgrset(pwd
->pw_name
)) == NULL
) {
573 r
.attr_flag
= EINVAL
;
577 if ( (p
= malloc(strlen(s
)+2)) == NULL
) {
578 r
.attr_flag
= ENOMEM
;
586 r
.attr_un
.au_char
= p
;
591 static attrval_t
pwd_to_sid(struct passwd
*pwd
)
593 struct winbindd_request request
;
594 struct winbindd_response response
;
597 ZERO_STRUCT(request
);
598 ZERO_STRUCT(response
);
600 request
.data
.uid
= pwd
->pw_uid
;
602 if (winbindd_request_response(WINBINDD_UID_TO_SID
, &request
, &response
) !=
603 NSS_STATUS_SUCCESS
) {
604 r
.attr_flag
= ENOENT
;
607 r
.attr_un
.au_char
= strdup(response
.data
.sid
.sid
);
613 static int wb_aix_user_attrib(const char *key
, char *attributes
[],
614 attrval_t results
[], int size
)
619 pwd
= wb_aix_getpwnam(key
);
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 #ifdef _AIXVERSION_530
631 } else if (strcmp(attributes
[i
], S_PGID
) == 0) {
632 results
[i
].attr_un
.au_int
= pwd
->pw_gid
;
634 } else if (strcmp(attributes
[i
], S_PWD
) == 0) {
635 results
[i
].attr_un
.au_char
= strdup(pwd
->pw_passwd
);
636 } else if (strcmp(attributes
[i
], S_HOME
) == 0) {
637 results
[i
].attr_un
.au_char
= strdup(pwd
->pw_dir
);
638 } else if (strcmp(attributes
[i
], S_SHELL
) == 0) {
639 results
[i
].attr_un
.au_char
= strdup(pwd
->pw_shell
);
640 } else if (strcmp(attributes
[i
], S_REGISTRY
) == 0) {
641 results
[i
].attr_un
.au_char
= strdup("WINBIND");
642 } else if (strcmp(attributes
[i
], S_GECOS
) == 0) {
643 results
[i
].attr_un
.au_char
= strdup(pwd
->pw_gecos
);
644 } else if (strcmp(attributes
[i
], S_PGRP
) == 0) {
645 results
[i
] = pwd_to_group(pwd
);
646 } else if (strcmp(attributes
[i
], S_GROUPS
) == 0) {
647 results
[i
] = pwd_to_groupsids(pwd
);
648 } else if (strcmp(attributes
[i
], "SID") == 0) {
649 results
[i
] = pwd_to_sid(pwd
);
651 logit("Unknown user attribute '%s'\n", attributes
[i
]);
652 results
[i
].attr_flag
= EINVAL
;
661 static int wb_aix_group_attrib(const char *key
, char *attributes
[],
662 attrval_t results
[], int size
)
667 grp
= wb_aix_getgrnam(key
);
673 for (i
=0;i
<size
;i
++) {
674 results
[i
].attr_flag
= 0;
676 if (strcmp(attributes
[i
], S_PWD
) == 0) {
677 results
[i
].attr_un
.au_char
= strdup(grp
->gr_passwd
);
678 } else if (strcmp(attributes
[i
], S_ID
) == 0) {
679 results
[i
].attr_un
.au_int
= grp
->gr_gid
;
681 logit("Unknown group attribute '%s'\n", attributes
[i
]);
682 results
[i
].attr_flag
= EINVAL
;
693 called for user/group enumerations
695 static int wb_aix_getentry(char *key
, char *table
, char *attributes
[],
696 attrval_t results
[], int size
)
698 logit("Got getentry with key='%s' table='%s' size=%d attributes[0]='%s'\n",
699 key
, table
, size
, attributes
[0]);
701 if (strcmp(key
, "ALL") == 0 &&
702 strcmp(table
, "user") == 0) {
703 return wb_aix_lsuser(attributes
, results
, size
);
706 if (strcmp(key
, "ALL") == 0 &&
707 strcmp(table
, "group") == 0) {
708 return wb_aix_lsgroup(attributes
, results
, size
);
711 if (strcmp(table
, "user") == 0) {
712 return wb_aix_user_attrib(key
, attributes
, results
, size
);
715 if (strcmp(table
, "group") == 0) {
716 return wb_aix_group_attrib(key
, attributes
, results
, size
);
719 logit("Unknown getentry operation key='%s' table='%s'\n", key
, table
);
728 called to start the backend
730 static void *wb_aix_open(const char *name
, const char *domain
, int mode
, char *options
)
732 if (strstr(options
, "debug")) {
735 logit("open name='%s' mode=%d domain='%s' options='%s'\n", name
, domain
,
740 static void wb_aix_close(void *token
)
746 #ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_ATTRLIST
748 return a list of additional attributes supported by the backend
750 static attrlist_t
**wb_aix_attrlist(void)
752 /* pretty confusing but we are allocating the array of pointers
753 and the structures we'll be pointing to all at once. So
754 you need N+1 pointers and N structures. */
756 attrlist_t
**ret
= NULL
;
757 attrlist_t
*offset
= NULL
;
767 /* user attributes */
768 {S_ID
, AL_USERATTR
, SEC_INT
},
769 {S_PGRP
, AL_USERATTR
, SEC_CHAR
},
770 {S_HOME
, AL_USERATTR
, SEC_CHAR
},
771 {S_SHELL
, AL_USERATTR
, SEC_CHAR
},
772 #ifdef _AIXVERSION_530
773 {S_PGID
, AL_USERATTR
, SEC_INT
},
775 {S_GECOS
, AL_USERATTR
, SEC_CHAR
},
776 {S_SHELL
, AL_USERATTR
, SEC_CHAR
},
777 {S_PGRP
, AL_USERATTR
, SEC_CHAR
},
778 {S_GROUPS
, AL_USERATTR
, SEC_LIST
},
779 {"SID", AL_USERATTR
, SEC_CHAR
},
781 /* group attributes */
782 {S_ID
, AL_GROUPATTR
, SEC_INT
}
785 logit("method attrlist called\n");
787 n
= sizeof(attr_list
) / sizeof(struct attr_types
);
788 size
= (n
*sizeof(attrlist_t
*));
790 if ( (ret
= malloc( size
)) == NULL
) {
795 /* offset to where the structures start in the buffer */
797 offset
= (attrlist_t
*)(ret
+ n
);
799 /* now loop over the user_attr_list[] array and add
802 for ( i
=0; i
<n
; i
++ ) {
803 attrlist_t
*a
= malloc(sizeof(attrlist_t
));
806 /* this is bad. Just bail */
810 a
->al_name
= strdup(attr_list
[i
].name
);
811 a
->al_flags
= attr_list
[i
].flags
;
812 a
->al_type
= attr_list
[i
].type
;
824 turn a long username into a short one. Needed to cope with the 8 char
825 username limit in AIX 5.2 and below
827 static int wb_aix_normalize(char *longname
, char *shortname
)
831 logit("normalize '%s'\n", longname
);
833 /* automatically cope with AIX 5.3 with longer usernames
835 if (S_NAMELEN
> strlen(longname
)) {
836 strcpy(shortname
, longname
);
840 pwd
= wb_aix_getpwnam(longname
);
846 sprintf(shortname
, "%c%07u", WB_AIX_ENCODED
, pwd
->pw_uid
);
857 static int wb_aix_authenticate(char *user
, char *pass
,
858 int *reenter
, char **message
)
860 struct winbindd_request request
;
861 struct winbindd_response response
;
865 logit("authenticate '%s' response='%s'\n", user
, pass
);
870 /* Send off request */
871 ZERO_STRUCT(request
);
872 ZERO_STRUCT(response
);
874 if (*user
== WB_AIX_ENCODED
) {
875 r_user
= decode_user(r_user
);
877 return AUTH_NOTFOUND
;
881 STRCPY_RET(request
.data
.auth
.user
, r_user
);
882 STRCPY_RET(request
.data
.auth
.pass
, pass
);
884 if (*user
== WB_AIX_ENCODED
) {
888 result
= winbindd_request_response(WINBINDD_PAM_AUTH
, &request
, &response
);
890 winbindd_free_response(&response
);
892 logit("auth result %d for '%s'\n", result
, user
);
894 if (result
== NSS_STATUS_SUCCESS
) {
904 change a user password
906 static int wb_aix_chpass(char *user
, char *oldpass
, char *newpass
, char **message
)
908 struct winbindd_request request
;
909 struct winbindd_response response
;
913 if (*user
== WB_AIX_ENCODED
) {
914 r_user
= decode_user(r_user
);
921 logit("chpass '%s' old='%s' new='%s'\n", r_user
, oldpass
, newpass
);
925 /* Send off request */
926 ZERO_STRUCT(request
);
927 ZERO_STRUCT(response
);
929 STRCPY_RET(request
.data
.chauthtok
.user
, r_user
);
930 STRCPY_RET(request
.data
.chauthtok
.oldpass
, oldpass
);
931 STRCPY_RET(request
.data
.chauthtok
.newpass
, newpass
);
933 if (*user
== WB_AIX_ENCODED
) {
937 result
= winbindd_request_response(WINBINDD_PAM_CHAUTHTOK
, &request
, &response
);
939 winbindd_free_response(&response
);
941 if (result
== NSS_STATUS_SUCCESS
) {
951 don't do any password strength testing for now
953 static int wb_aix_passwdrestrictions(char *user
, char *newpass
, char *oldpass
,
956 logit("passwdresrictions called for '%s'\n", user
);
961 static int wb_aix_passwdexpired(char *user
, char **message
)
963 logit("passwdexpired '%s'\n", user
);
964 /* we should check the account bits here */
970 we can't return a crypt() password
972 static char *wb_aix_getpasswd(char *user
)
974 logit("getpasswd '%s'\n", user
);
980 this is called to update things like the last login time. We don't
981 currently pass this onto the DC
983 static int wb_aix_putentry(char *key
, char *table
, char *attributes
[],
984 attrval_t values
[], int size
)
986 logit("putentry key='%s' table='%s' attrib='%s'\n",
987 key
, table
, size
>=1?attributes
[0]:"<null>");
992 static int wb_aix_commit(char *key
, char *table
)
994 logit("commit key='%s' table='%s'\n");
999 static int wb_aix_getgrusers(char *group
, void *result
, int type
, int *size
)
1001 logit("getgrusers group='%s'\n", group
);
1007 #define DECL_METHOD(x) \
1008 int method_ ## x(void) \
1010 logit("UNIMPLEMENTED METHOD '%s'\n", #x); \
1015 #if LOG_UNIMPLEMENTED_CALLS
1016 DECL_METHOD(delgroup
);
1017 DECL_METHOD(deluser
);
1018 DECL_METHOD(newgroup
);
1019 DECL_METHOD(newuser
);
1020 DECL_METHOD(putgrent
);
1021 DECL_METHOD(putgrusers
);
1022 DECL_METHOD(putpwent
);
1024 DECL_METHOD(unlock
);
1025 DECL_METHOD(getcred
);
1026 DECL_METHOD(setcred
);
1027 DECL_METHOD(deletecred
);
1030 int wb_aix_init(struct secmethod_table
*methods
)
1032 ZERO_STRUCTP(methods
);
1034 #ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_VERSION
1035 methods
->method_version
= SECMETHOD_VERSION_520
;
1038 methods
->method_getgrgid
= wb_aix_getgrgid
;
1039 methods
->method_getgrnam
= wb_aix_getgrnam
;
1040 methods
->method_getgrset
= wb_aix_getgrset
;
1041 methods
->method_getpwnam
= wb_aix_getpwnam
;
1042 methods
->method_getpwuid
= wb_aix_getpwuid
;
1043 methods
->method_getentry
= wb_aix_getentry
;
1044 methods
->method_open
= wb_aix_open
;
1045 methods
->method_close
= wb_aix_close
;
1046 methods
->method_normalize
= wb_aix_normalize
;
1047 methods
->method_passwdexpired
= wb_aix_passwdexpired
;
1048 methods
->method_putentry
= wb_aix_putentry
;
1049 methods
->method_getpasswd
= wb_aix_getpasswd
;
1050 methods
->method_authenticate
= wb_aix_authenticate
;
1051 methods
->method_commit
= wb_aix_commit
;
1052 methods
->method_chpass
= wb_aix_chpass
;
1053 methods
->method_passwdrestrictions
= wb_aix_passwdrestrictions
;
1054 methods
->method_getgracct
= wb_aix_getgracct
;
1055 methods
->method_getgrusers
= wb_aix_getgrusers
;
1056 #ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_ATTRLIST
1057 methods
->method_attrlist
= wb_aix_attrlist
;
1060 #if LOG_UNIMPLEMENTED_CALLS
1061 methods
->method_delgroup
= method_delgroup
;
1062 methods
->method_deluser
= method_deluser
;
1063 methods
->method_newgroup
= method_newgroup
;
1064 methods
->method_newuser
= method_newuser
;
1065 methods
->method_putgrent
= method_putgrent
;
1066 methods
->method_putgrusers
= method_putgrusers
;
1067 methods
->method_putpwent
= method_putpwent
;
1068 methods
->method_lock
= method_lock
;
1069 methods
->method_unlock
= method_unlock
;
1070 methods
->method_getcred
= method_getcred
;
1071 methods
->method_setcred
= method_setcred
;
1072 methods
->method_deletecred
= method_deletecred
;
1075 return AUTH_SUCCESS
;