s4-libnet: Improve debugging of libnet_BecomeDC LDAP errors
[Samba.git] / nsswitch / winbind_nss_aix.c
blob66200f35629808278aad9762086bd1ed599f96f8
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 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
32 module.
34 see
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"
47 #include <usersec.h>
49 /* enable this to log which entry points have not been
50 completed yet */
51 #define LOG_UNIMPLEMENTED_CALLS 0
54 #define WB_AIX_ENCODED '_'
56 static int debug_enabled;
59 static void logit(const char *format, ...)
61 va_list ap;
62 FILE *f;
63 if (!debug_enabled) {
64 return;
66 f = fopen("/tmp/WINBIND_DEBUG.log", "a");
67 if (!f) return;
68 va_start(ap, format);
69 vfprintf(f, format, ap);
70 va_end(ap);
71 fclose(f);
75 #define HANDLE_ERRORS(ret) do { \
76 if ((ret) == NSS_STATUS_NOTFOUND) { \
77 errno = ENOENT; \
78 return NULL; \
79 } else if ((ret) != NSS_STATUS_SUCCESS) { \
80 errno = EIO; \
81 return NULL; \
82 } \
83 } while (0)
85 #define STRCPY_RET(dest, src) \
86 do { \
87 if (strlen(src)+1 > sizeof(dest)) { errno = EINVAL; return -1; } \
88 strcpy(dest, src); \
89 } while (0)
91 #define STRCPY_RETNULL(dest, src) \
92 do { \
93 if (strlen(src)+1 > sizeof(dest)) { errno = EINVAL; return NULL; } \
94 strcpy(dest, src); \
95 } while (0)
98 /* free a passwd structure */
99 static void free_pwd(struct passwd *pwd)
101 free(pwd->pw_name);
102 free(pwd->pw_passwd);
103 free(pwd->pw_gecos);
104 free(pwd->pw_dir);
105 free(pwd->pw_shell);
106 free(pwd);
109 /* free a group structure */
110 static void free_grp(struct group *grp)
112 int i;
114 free(grp->gr_name);
115 free(grp->gr_passwd);
117 if (!grp->gr_mem) {
118 free(grp);
119 return;
122 for (i=0; grp->gr_mem[i]; i++) {
123 free(grp->gr_mem[i]);
126 free(grp->gr_mem);
127 free(grp);
131 /* replace commas with nulls, and null terminate */
132 static void replace_commas(char *s)
134 char *p, *p0=s;
135 for (p=strchr(s, ','); p; p = strchr(p+1, ',')) {
136 *p=0;
137 p0 = 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'
148 or '_GID'.
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)
155 unsigned id;
156 sscanf(name+1, "%u", &id);
157 return id;
160 static struct passwd *wb_aix_getpwuid(uid_t uid);
162 static char *decode_user(const char *name)
164 struct passwd *pwd;
165 unsigned id;
166 char *ret;
168 sscanf(name+1, "%u", &id);
169 pwd = wb_aix_getpwuid(id);
170 if (!pwd) {
171 return NULL;
173 ret = strdup(pwd->pw_name);
175 free_pwd(pwd);
177 logit("decoded '%s' -> '%s'\n", name, ret);
179 return 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));
191 if (!result) {
192 errno = ENOMEM;
193 return NULL;
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);
204 return result;
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)
213 int i;
214 struct group *result;
215 char *p, *name;
217 result = calloc(1, sizeof(struct group));
218 if (!result) {
219 errno = ENOMEM;
220 return NULL;
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) {
230 gr->num_gr_mem = 0;
233 if (gr->num_gr_mem == 0) {
234 /* Group is empty */
235 return result;
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);
242 free(result);
243 errno = ENOMEM;
244 return NULL;
247 /* Start looking at extra data */
248 i=0;
249 for (name = strtok_r(gr_mem, ",", &p);
250 name;
251 name = strtok_r(NULL, ",", &p)) {
252 if (i == gr->num_gr_mem) {
253 break;
255 result->gr_mem[i] = strdup(name);
256 i++;
259 /* Terminate list */
260 result->gr_mem[i] = NULL;
262 return result;
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;
272 struct group *grp;
273 NSS_STATUS ret;
275 logit("getgrgid %d\n", gid);
277 ZERO_STRUCT(response);
278 ZERO_STRUCT(request);
280 request.data.gid = gid;
282 ret = winbindd_request_response(WINBINDD_GETGRGID, &request, &response);
284 logit("getgrgid ret=%d\n", ret);
286 HANDLE_ERRORS(ret);
288 grp = fill_grent(&response.data.gr, response.extra_data.data);
290 winbindd_free_response(&response);
292 return grp;
295 /* take a group name and return a filled struct group */
296 static struct group *wb_aix_getgrnam(const char *name)
298 struct winbindd_response response;
299 struct winbindd_request request;
300 NSS_STATUS ret;
301 struct group *grp;
303 if (*name == WB_AIX_ENCODED) {
304 return wb_aix_getgrgid(decode_id(name));
307 logit("getgrnam '%s'\n", name);
309 ZERO_STRUCT(response);
310 ZERO_STRUCT(request);
312 STRCPY_RETNULL(request.data.groupname, name);
314 ret = winbindd_request_response(WINBINDD_GETGRNAM, &request, &response);
316 HANDLE_ERRORS(ret);
318 grp = fill_grent(&response.data.gr, response.extra_data.data);
320 winbindd_free_response(&response);
322 return grp;
326 /* this call doesn't have to fill in the gr_mem, but we do anyway
327 for simplicity */
328 static struct group *wb_aix_getgracct(void *id, int type)
330 if (type == 1) {
331 return wb_aix_getgrnam((char *)id);
333 if (type == 0) {
334 return wb_aix_getgrgid(*(int *)id);
336 errno = EINVAL;
337 return NULL;
341 /* take a username and return a string containing a comma-separated
342 list of group id numbers to which the user belongs */
343 static char *wb_aix_getgrset(char *user)
345 struct winbindd_response response;
346 struct winbindd_request request;
347 NSS_STATUS ret;
348 int i, idx;
349 char *tmpbuf;
350 int num_gids;
351 gid_t *gid_list;
352 char *r_user = user;
354 if (*user == WB_AIX_ENCODED) {
355 r_user = decode_user(r_user);
356 if (!r_user) {
357 errno = ENOENT;
358 return NULL;
362 logit("getgrset '%s'\n", r_user);
364 ZERO_STRUCT(response);
365 ZERO_STRUCT(request);
367 STRCPY_RETNULL(request.data.username, r_user);
369 if (*user == WB_AIX_ENCODED) {
370 free(r_user);
373 ret = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response);
375 HANDLE_ERRORS(ret);
377 num_gids = response.data.num_entries;
378 gid_list = (gid_t *)response.extra_data.data;
380 /* allocate a space large enough to contruct the string */
381 tmpbuf = malloc(num_gids*12);
382 if (!tmpbuf) {
383 return NULL;
386 for (idx=i=0; i < num_gids-1; i++) {
387 idx += sprintf(tmpbuf+idx, "%u,", gid_list[i]);
389 idx += sprintf(tmpbuf+idx, "%u", gid_list[i]);
391 winbindd_free_response(&response);
393 return tmpbuf;
397 /* take a uid and return a filled struct passwd */
398 static struct passwd *wb_aix_getpwuid(uid_t uid)
400 struct winbindd_response response;
401 struct winbindd_request request;
402 NSS_STATUS ret;
403 struct passwd *pwd;
405 logit("getpwuid '%d'\n", uid);
407 ZERO_STRUCT(response);
408 ZERO_STRUCT(request);
410 request.data.uid = uid;
412 ret = winbindd_request_response(WINBINDD_GETPWUID, &request, &response);
414 HANDLE_ERRORS(ret);
416 pwd = fill_pwent(&response.data.pw);
418 winbindd_free_response(&response);
420 logit("getpwuid gave ptr %p\n", pwd);
422 return pwd;
426 /* take a username and return a filled struct passwd */
427 static struct passwd *wb_aix_getpwnam(const char *name)
429 struct winbindd_response response;
430 struct winbindd_request request;
431 NSS_STATUS ret;
432 struct passwd *pwd;
434 if (*name == WB_AIX_ENCODED) {
435 return wb_aix_getpwuid(decode_id(name));
438 logit("getpwnam '%s'\n", name);
440 ZERO_STRUCT(response);
441 ZERO_STRUCT(request);
443 STRCPY_RETNULL(request.data.username, name);
445 ret = winbindd_request_response(WINBINDD_GETPWNAM, &request, &response);
447 HANDLE_ERRORS(ret);
449 pwd = fill_pwent(&response.data.pw);
451 winbindd_free_response(&response);
453 logit("getpwnam gave ptr %p\n", pwd);
455 return pwd;
459 list users
461 static int wb_aix_lsuser(char *attributes[], attrval_t results[], int size)
463 NSS_STATUS ret;
464 struct winbindd_request request;
465 struct winbindd_response response;
466 int len;
467 char *s;
469 if (size != 1 || strcmp(attributes[0], S_USERS) != 0) {
470 logit("invalid lsuser op\n");
471 errno = EINVAL;
472 return -1;
475 ZERO_STRUCT(request);
476 ZERO_STRUCT(response);
478 ret = winbindd_request_response(WINBINDD_LIST_USERS, &request, &response);
479 if (ret != 0) {
480 errno = EINVAL;
481 return -1;
484 len = strlen(response.extra_data.data);
486 s = malloc(len+2);
487 if (!s) {
488 winbindd_free_response(&response);
489 errno = ENOMEM;
490 return -1;
493 memcpy(s, response.extra_data.data, len+1);
495 replace_commas(s);
497 results[0].attr_un.au_char = s;
498 results[0].attr_flag = 0;
500 winbindd_free_response(&response);
502 return 0;
507 list groups
509 static int wb_aix_lsgroup(char *attributes[], attrval_t results[], int size)
511 NSS_STATUS ret;
512 struct winbindd_request request;
513 struct winbindd_response response;
514 int len;
515 char *s;
517 if (size != 1 || strcmp(attributes[0], S_GROUPS) != 0) {
518 logit("invalid lsgroup op\n");
519 errno = EINVAL;
520 return -1;
523 ZERO_STRUCT(request);
524 ZERO_STRUCT(response);
526 ret = winbindd_request_response(WINBINDD_LIST_GROUPS, &request, &response);
527 if (ret != 0) {
528 errno = EINVAL;
529 return -1;
532 len = strlen(response.extra_data.data);
534 s = malloc(len+2);
535 if (!s) {
536 winbindd_free_response(&response);
537 errno = ENOMEM;
538 return -1;
541 memcpy(s, response.extra_data.data, len+1);
543 replace_commas(s);
545 results[0].attr_un.au_char = s;
546 results[0].attr_flag = 0;
548 winbindd_free_response(&response);
550 return 0;
554 static attrval_t pwd_to_group(struct passwd *pwd)
556 attrval_t r;
557 struct group *grp = wb_aix_getgrgid(pwd->pw_gid);
559 if (!grp) {
560 r.attr_flag = EINVAL;
561 } else {
562 r.attr_flag = 0;
563 r.attr_un.au_char = strdup(grp->gr_name);
564 free_grp(grp);
567 return r;
570 static attrval_t pwd_to_groupsids(struct passwd *pwd)
572 attrval_t r;
573 char *s, *p;
575 if ( (s = wb_aix_getgrset(pwd->pw_name)) == NULL ) {
576 r.attr_flag = EINVAL;
577 return r;
580 if ( (p = malloc(strlen(s)+2)) == NULL ) {
581 r.attr_flag = ENOMEM;
582 return r;
585 strcpy(p, s);
586 replace_commas(p);
587 free(s);
589 r.attr_un.au_char = p;
591 return r;
594 static attrval_t pwd_to_sid(struct passwd *pwd)
596 struct winbindd_request request;
597 struct winbindd_response response;
598 attrval_t r;
600 ZERO_STRUCT(request);
601 ZERO_STRUCT(response);
603 request.data.uid = pwd->pw_uid;
605 if (winbindd_request_response(WINBINDD_UID_TO_SID, &request, &response) !=
606 NSS_STATUS_SUCCESS) {
607 r.attr_flag = ENOENT;
608 } else {
609 r.attr_flag = 0;
610 r.attr_un.au_char = strdup(response.data.sid.sid);
613 return r;
616 static int wb_aix_user_attrib(const char *key, char *attributes[],
617 attrval_t results[], int size)
619 struct passwd *pwd;
620 int i;
622 pwd = wb_aix_getpwnam(key);
623 if (!pwd) {
624 errno = ENOENT;
625 return -1;
628 for (i=0;i<size;i++) {
629 results[i].attr_flag = 0;
631 if (strcmp(attributes[i], S_ID) == 0) {
632 results[i].attr_un.au_int = pwd->pw_uid;
633 #ifdef _AIXVERSION_530
634 } else if (strcmp(attributes[i], S_PGID) == 0) {
635 results[i].attr_un.au_int = pwd->pw_gid;
636 #endif
637 } else if (strcmp(attributes[i], S_PWD) == 0) {
638 results[i].attr_un.au_char = strdup(pwd->pw_passwd);
639 } else if (strcmp(attributes[i], S_HOME) == 0) {
640 results[i].attr_un.au_char = strdup(pwd->pw_dir);
641 } else if (strcmp(attributes[i], S_SHELL) == 0) {
642 results[i].attr_un.au_char = strdup(pwd->pw_shell);
643 } else if (strcmp(attributes[i], S_REGISTRY) == 0) {
644 results[i].attr_un.au_char = strdup("WINBIND");
645 } else if (strcmp(attributes[i], S_GECOS) == 0) {
646 results[i].attr_un.au_char = strdup(pwd->pw_gecos);
647 } else if (strcmp(attributes[i], S_PGRP) == 0) {
648 results[i] = pwd_to_group(pwd);
649 } else if (strcmp(attributes[i], S_GROUPS) == 0) {
650 results[i] = pwd_to_groupsids(pwd);
651 } else if (strcmp(attributes[i], "SID") == 0) {
652 results[i] = pwd_to_sid(pwd);
653 } else {
654 logit("Unknown user attribute '%s'\n", attributes[i]);
655 results[i].attr_flag = EINVAL;
659 free_pwd(pwd);
661 return 0;
664 static int wb_aix_group_attrib(const char *key, char *attributes[],
665 attrval_t results[], int size)
667 struct group *grp;
668 int i;
670 grp = wb_aix_getgrnam(key);
671 if (!grp) {
672 errno = ENOENT;
673 return -1;
676 for (i=0;i<size;i++) {
677 results[i].attr_flag = 0;
679 if (strcmp(attributes[i], S_PWD) == 0) {
680 results[i].attr_un.au_char = strdup(grp->gr_passwd);
681 } else if (strcmp(attributes[i], S_ID) == 0) {
682 results[i].attr_un.au_int = grp->gr_gid;
683 } else {
684 logit("Unknown group attribute '%s'\n", attributes[i]);
685 results[i].attr_flag = EINVAL;
689 free_grp(grp);
691 return 0;
696 called for user/group enumerations
698 static int wb_aix_getentry(char *key, char *table, char *attributes[],
699 attrval_t results[], int size)
701 logit("Got getentry with key='%s' table='%s' size=%d attributes[0]='%s'\n",
702 key, table, size, attributes[0]);
704 if (strcmp(key, "ALL") == 0 &&
705 strcmp(table, "user") == 0) {
706 return wb_aix_lsuser(attributes, results, size);
709 if (strcmp(key, "ALL") == 0 &&
710 strcmp(table, "group") == 0) {
711 return wb_aix_lsgroup(attributes, results, size);
714 if (strcmp(table, "user") == 0) {
715 return wb_aix_user_attrib(key, attributes, results, size);
718 if (strcmp(table, "group") == 0) {
719 return wb_aix_group_attrib(key, attributes, results, size);
722 logit("Unknown getentry operation key='%s' table='%s'\n", key, table);
724 errno = ENOSYS;
725 return -1;
731 called to start the backend
733 static void *wb_aix_open(const char *name, const char *domain, int mode, char *options)
735 if (strstr(options, "debug")) {
736 debug_enabled = 1;
738 logit("open name='%s' mode=%d domain='%s' options='%s'\n", name, domain,
739 mode, options);
740 return NULL;
743 static void wb_aix_close(void *token)
745 logit("close\n");
746 return;
749 #ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_ATTRLIST
751 return a list of additional attributes supported by the backend
753 static attrlist_t **wb_aix_attrlist(void)
755 /* pretty confusing but we are allocating the array of pointers
756 and the structures we'll be pointing to all at once. So
757 you need N+1 pointers and N structures. */
759 attrlist_t **ret = NULL;
760 attrlist_t *offset = NULL;
761 int i;
762 int n;
763 size_t size;
765 struct attr_types {
766 const char *name;
767 int flags;
768 int type;
769 } attr_list[] = {
770 /* user attributes */
771 {S_ID, AL_USERATTR, SEC_INT},
772 {S_PGRP, AL_USERATTR, SEC_CHAR},
773 {S_HOME, AL_USERATTR, SEC_CHAR},
774 {S_SHELL, AL_USERATTR, SEC_CHAR},
775 #ifdef _AIXVERSION_530
776 {S_PGID, AL_USERATTR, SEC_INT},
777 #endif
778 {S_GECOS, AL_USERATTR, SEC_CHAR},
779 {S_SHELL, AL_USERATTR, SEC_CHAR},
780 {S_PGRP, AL_USERATTR, SEC_CHAR},
781 {S_GROUPS, AL_USERATTR, SEC_LIST},
782 {"SID", AL_USERATTR, SEC_CHAR},
784 /* group attributes */
785 {S_ID, AL_GROUPATTR, SEC_INT}
788 logit("method attrlist called\n");
790 n = sizeof(attr_list) / sizeof(struct attr_types);
791 size = (n*sizeof(attrlist_t *));
793 if ( (ret = malloc( size )) == NULL ) {
794 errno = ENOMEM;
795 return NULL;
798 /* offset to where the structures start in the buffer */
800 offset = (attrlist_t *)(ret + n);
802 /* now loop over the user_attr_list[] array and add
803 all the members */
805 for ( i=0; i<n; i++ ) {
806 attrlist_t *a = malloc(sizeof(attrlist_t));
808 if ( !a ) {
809 /* this is bad. Just bail */
810 return NULL;
813 a->al_name = strdup(attr_list[i].name);
814 a->al_flags = attr_list[i].flags;
815 a->al_type = attr_list[i].type;
817 ret[i] = a;
819 ret[n] = NULL;
821 return ret;
823 #endif
827 turn a long username into a short one. Needed to cope with the 8 char
828 username limit in AIX 5.2 and below
830 static int wb_aix_normalize(char *longname, char *shortname)
832 struct passwd *pwd;
834 logit("normalize '%s'\n", longname);
836 /* automatically cope with AIX 5.3 with longer usernames
837 when it comes out */
838 if (S_NAMELEN > strlen(longname)) {
839 strcpy(shortname, longname);
840 return 1;
843 pwd = wb_aix_getpwnam(longname);
844 if (!pwd) {
845 errno = ENOENT;
846 return 0;
849 sprintf(shortname, "%c%07u", WB_AIX_ENCODED, pwd->pw_uid);
851 free_pwd(pwd);
853 return 1;
858 authenticate a user
860 static int wb_aix_authenticate(char *user, char *pass,
861 int *reenter, char **message)
863 struct winbindd_request request;
864 struct winbindd_response response;
865 NSS_STATUS result;
866 char *r_user = user;
868 logit("authenticate '%s' response='%s'\n", user, pass);
870 *reenter = 0;
871 *message = NULL;
873 /* Send off request */
874 ZERO_STRUCT(request);
875 ZERO_STRUCT(response);
877 if (*user == WB_AIX_ENCODED) {
878 r_user = decode_user(r_user);
879 if (!r_user) {
880 return AUTH_NOTFOUND;
884 STRCPY_RET(request.data.auth.user, r_user);
885 STRCPY_RET(request.data.auth.pass, pass);
887 if (*user == WB_AIX_ENCODED) {
888 free(r_user);
891 result = winbindd_request_response(WINBINDD_PAM_AUTH, &request, &response);
893 winbindd_free_response(&response);
895 logit("auth result %d for '%s'\n", result, user);
897 if (result == NSS_STATUS_SUCCESS) {
898 errno = 0;
899 return AUTH_SUCCESS;
902 return AUTH_FAILURE;
907 change a user password
909 static int wb_aix_chpass(char *user, char *oldpass, char *newpass, char **message)
911 struct winbindd_request request;
912 struct winbindd_response response;
913 NSS_STATUS result;
914 char *r_user = user;
916 if (*user == WB_AIX_ENCODED) {
917 r_user = decode_user(r_user);
918 if (!r_user) {
919 errno = ENOENT;
920 return -1;
924 logit("chpass '%s' old='%s' new='%s'\n", r_user, oldpass, newpass);
926 *message = NULL;
928 /* Send off request */
929 ZERO_STRUCT(request);
930 ZERO_STRUCT(response);
932 STRCPY_RET(request.data.chauthtok.user, r_user);
933 STRCPY_RET(request.data.chauthtok.oldpass, oldpass);
934 STRCPY_RET(request.data.chauthtok.newpass, newpass);
936 if (*user == WB_AIX_ENCODED) {
937 free(r_user);
940 result = winbindd_request_response(WINBINDD_PAM_CHAUTHTOK, &request, &response);
942 winbindd_free_response(&response);
944 if (result == NSS_STATUS_SUCCESS) {
945 errno = 0;
946 return 0;
949 errno = EINVAL;
950 return -1;
954 don't do any password strength testing for now
956 static int wb_aix_passwdrestrictions(char *user, char *newpass, char *oldpass,
957 char **message)
959 logit("passwdresrictions called for '%s'\n", user);
960 return 0;
964 static int wb_aix_passwdexpired(char *user, char **message)
966 logit("passwdexpired '%s'\n", user);
967 /* we should check the account bits here */
968 return 0;
973 we can't return a crypt() password
975 static char *wb_aix_getpasswd(char *user)
977 logit("getpasswd '%s'\n", user);
978 errno = ENOSYS;
979 return NULL;
983 this is called to update things like the last login time. We don't
984 currently pass this onto the DC
986 static int wb_aix_putentry(char *key, char *table, char *attributes[],
987 attrval_t values[], int size)
989 logit("putentry key='%s' table='%s' attrib='%s'\n",
990 key, table, size>=1?attributes[0]:"<null>");
991 errno = ENOSYS;
992 return -1;
995 static int wb_aix_commit(char *key, char *table)
997 logit("commit key='%s' table='%s'\n");
998 errno = ENOSYS;
999 return -1;
1002 static int wb_aix_getgrusers(char *group, void *result, int type, int *size)
1004 logit("getgrusers group='%s'\n", group);
1005 errno = ENOSYS;
1006 return -1;
1010 #define DECL_METHOD(x) \
1011 int method_ ## x(void) \
1013 logit("UNIMPLEMENTED METHOD '%s'\n", #x); \
1014 errno = EINVAL; \
1015 return -1; \
1018 #if LOG_UNIMPLEMENTED_CALLS
1019 DECL_METHOD(delgroup);
1020 DECL_METHOD(deluser);
1021 DECL_METHOD(newgroup);
1022 DECL_METHOD(newuser);
1023 DECL_METHOD(putgrent);
1024 DECL_METHOD(putgrusers);
1025 DECL_METHOD(putpwent);
1026 DECL_METHOD(lock);
1027 DECL_METHOD(unlock);
1028 DECL_METHOD(getcred);
1029 DECL_METHOD(setcred);
1030 DECL_METHOD(deletecred);
1031 #endif
1033 int wb_aix_init(struct secmethod_table *methods)
1035 ZERO_STRUCTP(methods);
1037 #ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_VERSION
1038 methods->method_version = SECMETHOD_VERSION_520;
1039 #endif
1041 methods->method_getgrgid = wb_aix_getgrgid;
1042 methods->method_getgrnam = wb_aix_getgrnam;
1043 methods->method_getgrset = wb_aix_getgrset;
1044 methods->method_getpwnam = wb_aix_getpwnam;
1045 methods->method_getpwuid = wb_aix_getpwuid;
1046 methods->method_getentry = wb_aix_getentry;
1047 methods->method_open = wb_aix_open;
1048 methods->method_close = wb_aix_close;
1049 methods->method_normalize = wb_aix_normalize;
1050 methods->method_passwdexpired = wb_aix_passwdexpired;
1051 methods->method_putentry = wb_aix_putentry;
1052 methods->method_getpasswd = wb_aix_getpasswd;
1053 methods->method_authenticate = wb_aix_authenticate;
1054 methods->method_commit = wb_aix_commit;
1055 methods->method_chpass = wb_aix_chpass;
1056 methods->method_passwdrestrictions = wb_aix_passwdrestrictions;
1057 methods->method_getgracct = wb_aix_getgracct;
1058 methods->method_getgrusers = wb_aix_getgrusers;
1059 #ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_ATTRLIST
1060 methods->method_attrlist = wb_aix_attrlist;
1061 #endif
1063 #if LOG_UNIMPLEMENTED_CALLS
1064 methods->method_delgroup = method_delgroup;
1065 methods->method_deluser = method_deluser;
1066 methods->method_newgroup = method_newgroup;
1067 methods->method_newuser = method_newuser;
1068 methods->method_putgrent = method_putgrent;
1069 methods->method_putgrusers = method_putgrusers;
1070 methods->method_putpwent = method_putpwent;
1071 methods->method_lock = method_lock;
1072 methods->method_unlock = method_unlock;
1073 methods->method_getcred = method_getcred;
1074 methods->method_setcred = method_setcred;
1075 methods->method_deletecred = method_deletecred;
1076 #endif
1078 return AUTH_SUCCESS;