VERSION: Raise version number up to 3.0.36.
[Samba.git] / source / nsswitch / winbind_nss_aix.c
blob92d4bee005f1670e595e83ae96b7810b68bd6847
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 "winbind_client.h"
49 #include <usersec.h>
51 /* enable this to log which entry points have not been
52 completed yet */
53 #define LOG_UNIMPLEMENTED_CALLS 0
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 struct passwd *wb_aix_getpwuid(uid_t uid);
164 static char *decode_user(const char *name)
166 struct passwd *pwd;
167 unsigned id;
168 char *ret;
170 sscanf(name+1, "%u", &id);
171 pwd = wb_aix_getpwuid(id);
172 if (!pwd) {
173 return NULL;
175 ret = strdup(pwd->pw_name);
177 free_pwd(pwd);
179 logit("decoded '%s' -> '%s'\n", name, ret);
181 return ret;
186 fill a struct passwd from a winbindd_pw struct, allocating as a single block
188 static struct passwd *fill_pwent(struct winbindd_pw *pw)
190 struct passwd *result;
192 result = calloc(1, sizeof(struct passwd));
193 if (!result) {
194 errno = ENOMEM;
195 return NULL;
198 result->pw_uid = pw->pw_uid;
199 result->pw_gid = pw->pw_gid;
200 result->pw_name = strdup(pw->pw_name);
201 result->pw_passwd = strdup(pw->pw_passwd);
202 result->pw_gecos = strdup(pw->pw_gecos);
203 result->pw_dir = strdup(pw->pw_dir);
204 result->pw_shell = strdup(pw->pw_shell);
206 return result;
211 fill a struct group from a winbindd_pw struct, allocating as a single block
213 static struct group *fill_grent(struct winbindd_gr *gr, char *gr_mem)
215 int i;
216 struct group *result;
217 char *p, *name;
219 result = calloc(1, sizeof(struct group));
220 if (!result) {
221 errno = ENOMEM;
222 return NULL;
225 result->gr_gid = gr->gr_gid;
227 result->gr_name = strdup(gr->gr_name);
228 result->gr_passwd = strdup(gr->gr_passwd);
230 /* Group membership */
231 if ((gr->num_gr_mem < 0) || !gr_mem) {
232 gr->num_gr_mem = 0;
235 if (gr->num_gr_mem == 0) {
236 /* Group is empty */
237 return result;
240 result->gr_mem = (char **)malloc(sizeof(char *) * (gr->num_gr_mem+1));
241 if (!result->gr_mem) {
242 errno = ENOMEM;
243 return NULL;
246 /* Start looking at extra data */
247 i=0;
248 for (name = strtok_r(gr_mem, ",", &p);
249 name;
250 name = strtok_r(NULL, ",", &p)) {
251 if (i == gr->num_gr_mem) {
252 break;
254 result->gr_mem[i] = strdup(name);
255 i++;
258 /* Terminate list */
259 result->gr_mem[i] = NULL;
261 return result;
266 /* take a group id and return a filled struct group */
267 static struct group *wb_aix_getgrgid(gid_t gid)
269 struct winbindd_response response;
270 struct winbindd_request request;
271 struct group *grp;
272 NSS_STATUS ret;
274 logit("getgrgid %d\n", gid);
276 ZERO_STRUCT(response);
277 ZERO_STRUCT(request);
279 request.data.gid = gid;
281 ret = winbindd_request_response(WINBINDD_GETGRGID, &request, &response);
283 logit("getgrgid ret=%d\n", ret);
285 HANDLE_ERRORS(ret);
287 grp = fill_grent(&response.data.gr, response.extra_data.data);
289 free_response(&response);
291 return grp;
294 /* take a group name and return a filled struct group */
295 static struct group *wb_aix_getgrnam(const char *name)
297 struct winbindd_response response;
298 struct winbindd_request request;
299 NSS_STATUS ret;
300 struct group *grp;
302 if (*name == WB_AIX_ENCODED) {
303 return wb_aix_getgrgid(decode_id(name));
306 logit("getgrnam '%s'\n", name);
308 ZERO_STRUCT(response);
309 ZERO_STRUCT(request);
311 STRCPY_RETNULL(request.data.groupname, name);
313 ret = winbindd_request_response(WINBINDD_GETGRNAM, &request, &response);
315 HANDLE_ERRORS(ret);
317 grp = fill_grent(&response.data.gr, response.extra_data.data);
319 free_response(&response);
321 return grp;
325 /* this call doesn't have to fill in the gr_mem, but we do anyway
326 for simplicity */
327 static struct group *wb_aix_getgracct(void *id, int type)
329 if (type == 1) {
330 return wb_aix_getgrnam((char *)id);
332 if (type == 0) {
333 return wb_aix_getgrgid(*(int *)id);
335 errno = EINVAL;
336 return NULL;
340 /* take a username and return a string containing a comma-separated
341 list of group id numbers to which the user belongs */
342 static char *wb_aix_getgrset(char *user)
344 struct winbindd_response response;
345 struct winbindd_request request;
346 NSS_STATUS ret;
347 int i, idx;
348 char *tmpbuf;
349 int num_gids;
350 gid_t *gid_list;
351 char *r_user = user;
353 if (*user == WB_AIX_ENCODED) {
354 r_user = decode_user(r_user);
355 if (!r_user) {
356 errno = ENOENT;
357 return NULL;
361 logit("getgrset '%s'\n", r_user);
363 ZERO_STRUCT(response);
364 ZERO_STRUCT(request);
366 STRCPY_RETNULL(request.data.username, r_user);
368 if (*user == WB_AIX_ENCODED) {
369 free(r_user);
372 ret = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response);
374 HANDLE_ERRORS(ret);
376 num_gids = response.data.num_entries;
377 gid_list = (gid_t *)response.extra_data.data;
379 /* allocate a space large enough to contruct the string */
380 tmpbuf = malloc(num_gids*12);
381 if (!tmpbuf) {
382 return NULL;
385 for (idx=i=0; i < num_gids-1; i++) {
386 idx += sprintf(tmpbuf+idx, "%u,", gid_list[i]);
388 idx += sprintf(tmpbuf+idx, "%u", gid_list[i]);
390 free_response(&response);
392 return tmpbuf;
396 /* take a uid and return a filled struct passwd */
397 static struct passwd *wb_aix_getpwuid(uid_t uid)
399 struct winbindd_response response;
400 struct winbindd_request request;
401 NSS_STATUS ret;
402 struct passwd *pwd;
404 logit("getpwuid '%d'\n", uid);
406 ZERO_STRUCT(response);
407 ZERO_STRUCT(request);
409 request.data.uid = uid;
411 ret = winbindd_request_response(WINBINDD_GETPWUID, &request, &response);
413 HANDLE_ERRORS(ret);
415 pwd = fill_pwent(&response.data.pw);
417 free_response(&response);
419 logit("getpwuid gave ptr %p\n", pwd);
421 return pwd;
425 /* take a username and return a filled struct passwd */
426 static struct passwd *wb_aix_getpwnam(const char *name)
428 struct winbindd_response response;
429 struct winbindd_request request;
430 NSS_STATUS ret;
431 struct passwd *pwd;
433 if (*name == WB_AIX_ENCODED) {
434 return wb_aix_getpwuid(decode_id(name));
437 logit("getpwnam '%s'\n", name);
439 ZERO_STRUCT(response);
440 ZERO_STRUCT(request);
442 STRCPY_RETNULL(request.data.username, name);
444 ret = winbindd_request_response(WINBINDD_GETPWNAM, &request, &response);
446 HANDLE_ERRORS(ret);
448 pwd = fill_pwent(&response.data.pw);
450 free_response(&response);
452 logit("getpwnam gave ptr %p\n", pwd);
454 return pwd;
458 list users
460 static int wb_aix_lsuser(char *attributes[], attrval_t results[], int size)
462 NSS_STATUS ret;
463 struct winbindd_request request;
464 struct winbindd_response response;
465 int len;
466 char *s;
468 if (size != 1 || strcmp(attributes[0], S_USERS) != 0) {
469 logit("invalid lsuser op\n");
470 errno = EINVAL;
471 return -1;
474 ZERO_STRUCT(request);
475 ZERO_STRUCT(response);
477 ret = winbindd_request_response(WINBINDD_LIST_USERS, &request, &response);
478 if (ret != 0) {
479 errno = EINVAL;
480 return -1;
483 len = strlen(response.extra_data.data);
485 s = malloc(len+2);
486 if (!s) {
487 free_response(&response);
488 errno = ENOMEM;
489 return -1;
492 memcpy(s, response.extra_data.data, len+1);
494 replace_commas(s);
496 results[0].attr_un.au_char = s;
497 results[0].attr_flag = 0;
499 free_response(&response);
501 return 0;
506 list groups
508 static int wb_aix_lsgroup(char *attributes[], attrval_t results[], int size)
510 NSS_STATUS ret;
511 struct winbindd_request request;
512 struct winbindd_response response;
513 int len;
514 char *s;
516 if (size != 1 || strcmp(attributes[0], S_GROUPS) != 0) {
517 logit("invalid lsgroup op\n");
518 errno = EINVAL;
519 return -1;
522 ZERO_STRUCT(request);
523 ZERO_STRUCT(response);
525 ret = winbindd_request_response(WINBINDD_LIST_GROUPS, &request, &response);
526 if (ret != 0) {
527 errno = EINVAL;
528 return -1;
531 len = strlen(response.extra_data.data);
533 s = malloc(len+2);
534 if (!s) {
535 free_response(&response);
536 errno = ENOMEM;
537 return -1;
540 memcpy(s, response.extra_data.data, len+1);
542 replace_commas(s);
544 results[0].attr_un.au_char = s;
545 results[0].attr_flag = 0;
547 free_response(&response);
549 return 0;
553 static attrval_t pwd_to_group(struct passwd *pwd)
555 attrval_t r;
556 struct group *grp = wb_aix_getgrgid(pwd->pw_gid);
558 if (!grp) {
559 r.attr_flag = EINVAL;
560 } else {
561 r.attr_flag = 0;
562 r.attr_un.au_char = strdup(grp->gr_name);
563 free_grp(grp);
566 return r;
569 static attrval_t pwd_to_groupsids(struct passwd *pwd)
571 attrval_t r;
572 char *s, *p;
574 if ( (s = wb_aix_getgrset(pwd->pw_name)) == NULL ) {
575 r.attr_flag = EINVAL;
576 return r;
579 if ( (p = malloc(strlen(s)+2)) == NULL ) {
580 r.attr_flag = ENOMEM;
581 return r;
584 strcpy(p, s);
585 replace_commas(p);
586 free(s);
588 r.attr_un.au_char = p;
590 return r;
593 static attrval_t pwd_to_sid(struct passwd *pwd)
595 struct winbindd_request request;
596 struct winbindd_response response;
597 attrval_t r;
599 ZERO_STRUCT(request);
600 ZERO_STRUCT(response);
602 request.data.uid = pwd->pw_uid;
604 if (winbindd_request_response(WINBINDD_UID_TO_SID, &request, &response) !=
605 NSS_STATUS_SUCCESS) {
606 r.attr_flag = ENOENT;
607 } else {
608 r.attr_flag = 0;
609 r.attr_un.au_char = strdup(response.data.sid.sid);
612 return r;
615 static int wb_aix_user_attrib(const char *key, char *attributes[],
616 attrval_t results[], int size)
618 struct passwd *pwd;
619 int i;
621 pwd = wb_aix_getpwnam(key);
622 if (!pwd) {
623 errno = ENOENT;
624 return -1;
627 for (i=0;i<size;i++) {
628 results[i].attr_flag = 0;
630 if (strcmp(attributes[i], S_ID) == 0) {
631 results[i].attr_un.au_int = pwd->pw_uid;
632 #ifdef _AIXVERSION_530
633 } else if (strcmp(attributes[i], S_PGID) == 0) {
634 results[i].attr_un.au_int = pwd->pw_gid;
635 #endif
636 } else if (strcmp(attributes[i], S_PWD) == 0) {
637 results[i].attr_un.au_char = strdup(pwd->pw_passwd);
638 } else if (strcmp(attributes[i], S_HOME) == 0) {
639 results[i].attr_un.au_char = strdup(pwd->pw_dir);
640 } else if (strcmp(attributes[i], S_SHELL) == 0) {
641 results[i].attr_un.au_char = strdup(pwd->pw_shell);
642 } else if (strcmp(attributes[i], S_REGISTRY) == 0) {
643 results[i].attr_un.au_char = strdup("WINBIND");
644 } else if (strcmp(attributes[i], S_GECOS) == 0) {
645 results[i].attr_un.au_char = strdup(pwd->pw_gecos);
646 } else if (strcmp(attributes[i], S_PGRP) == 0) {
647 results[i] = pwd_to_group(pwd);
648 } else if (strcmp(attributes[i], S_GROUPS) == 0) {
649 results[i] = pwd_to_groupsids(pwd);
650 } else if (strcmp(attributes[i], "SID") == 0) {
651 results[i] = pwd_to_sid(pwd);
652 } else {
653 logit("Unknown user attribute '%s'\n", attributes[i]);
654 results[i].attr_flag = EINVAL;
658 free_pwd(pwd);
660 return 0;
663 static int wb_aix_group_attrib(const char *key, char *attributes[],
664 attrval_t results[], int size)
666 struct group *grp;
667 int i;
669 grp = wb_aix_getgrnam(key);
670 if (!grp) {
671 errno = ENOENT;
672 return -1;
675 for (i=0;i<size;i++) {
676 results[i].attr_flag = 0;
678 if (strcmp(attributes[i], S_PWD) == 0) {
679 results[i].attr_un.au_char = strdup(grp->gr_passwd);
680 } else if (strcmp(attributes[i], S_ID) == 0) {
681 results[i].attr_un.au_int = grp->gr_gid;
682 } else {
683 logit("Unknown group attribute '%s'\n", attributes[i]);
684 results[i].attr_flag = EINVAL;
688 free_grp(grp);
690 return 0;
695 called for user/group enumerations
697 static int wb_aix_getentry(char *key, char *table, char *attributes[],
698 attrval_t results[], int size)
700 logit("Got getentry with key='%s' table='%s' size=%d attributes[0]='%s'\n",
701 key, table, size, attributes[0]);
703 if (strcmp(key, "ALL") == 0 &&
704 strcmp(table, "user") == 0) {
705 return wb_aix_lsuser(attributes, results, size);
708 if (strcmp(key, "ALL") == 0 &&
709 strcmp(table, "group") == 0) {
710 return wb_aix_lsgroup(attributes, results, size);
713 if (strcmp(table, "user") == 0) {
714 return wb_aix_user_attrib(key, attributes, results, size);
717 if (strcmp(table, "group") == 0) {
718 return wb_aix_group_attrib(key, attributes, results, size);
721 logit("Unknown getentry operation key='%s' table='%s'\n", key, table);
723 errno = ENOSYS;
724 return -1;
730 called to start the backend
732 static void *wb_aix_open(const char *name, const char *domain, int mode, char *options)
734 if (strstr(options, "debug")) {
735 debug_enabled = 1;
737 logit("open name='%s' mode=%d domain='%s' options='%s'\n", name, domain,
738 mode, options);
739 return NULL;
742 static void wb_aix_close(void *token)
744 logit("close\n");
745 return;
748 #ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_ATTRLIST
750 return a list of additional attributes supported by the backend
752 static attrlist_t **wb_aix_attrlist(void)
754 /* pretty confusing but we are allocating the array of pointers
755 and the structures we'll be pointing to all at once. So
756 you need N+1 pointers and N structures. */
758 attrlist_t **ret = NULL;
759 attrlist_t *offset = NULL;
760 int i;
761 int n;
762 size_t size;
764 struct attr_types {
765 const char *name;
766 int flags;
767 int type;
768 } attr_list[] = {
769 /* user attributes */
770 {S_ID, AL_USERATTR, SEC_INT},
771 {S_PGRP, AL_USERATTR, SEC_CHAR},
772 {S_HOME, AL_USERATTR, SEC_CHAR},
773 {S_SHELL, AL_USERATTR, SEC_CHAR},
774 #ifdef _AIXVERSION_530
775 {S_PGID, AL_USERATTR, SEC_INT},
776 #endif
777 {S_GECOS, AL_USERATTR, SEC_CHAR},
778 {S_SHELL, AL_USERATTR, SEC_CHAR},
779 {S_PGRP, AL_USERATTR, SEC_CHAR},
780 {S_GROUPS, AL_USERATTR, SEC_LIST},
781 {"SID", AL_USERATTR, SEC_CHAR},
783 /* group attributes */
784 {S_ID, AL_GROUPATTR, SEC_INT}
787 logit("method attrlist called\n");
789 n = sizeof(attr_list) / sizeof(struct attr_types);
790 size = (n*sizeof(attrlist_t *));
792 if ( (ret = malloc( size )) == NULL ) {
793 errno = ENOMEM;
794 return NULL;
797 /* offset to where the structures start in the buffer */
799 offset = (attrlist_t *)(ret + n);
801 /* now loop over the user_attr_list[] array and add
802 all the members */
804 for ( i=0; i<n; i++ ) {
805 attrlist_t *a = malloc(sizeof(attrlist_t));
807 if ( !a ) {
808 /* this is bad. Just bail */
809 return NULL;
812 a->al_name = strdup(attr_list[i].name);
813 a->al_flags = attr_list[i].flags;
814 a->al_type = attr_list[i].type;
816 ret[i] = a;
818 ret[n] = NULL;
820 return ret;
822 #endif
826 turn a long username into a short one. Needed to cope with the 8 char
827 username limit in AIX 5.2 and below
829 static int wb_aix_normalize(char *longname, char *shortname)
831 struct passwd *pwd;
833 logit("normalize '%s'\n", longname);
835 /* automatically cope with AIX 5.3 with longer usernames
836 when it comes out */
837 if (S_NAMELEN > strlen(longname)) {
838 strcpy(shortname, longname);
839 return 1;
842 pwd = wb_aix_getpwnam(longname);
843 if (!pwd) {
844 errno = ENOENT;
845 return 0;
848 sprintf(shortname, "%c%07u", WB_AIX_ENCODED, pwd->pw_uid);
850 free_pwd(pwd);
852 return 1;
857 authenticate a user
859 static int wb_aix_authenticate(char *user, char *pass,
860 int *reenter, char **message)
862 struct winbindd_request request;
863 struct winbindd_response response;
864 NSS_STATUS result;
865 char *r_user = user;
867 logit("authenticate '%s' response='%s'\n", user, pass);
869 *reenter = 0;
870 *message = NULL;
872 /* Send off request */
873 ZERO_STRUCT(request);
874 ZERO_STRUCT(response);
876 if (*user == WB_AIX_ENCODED) {
877 r_user = decode_user(r_user);
878 if (!r_user) {
879 return AUTH_NOTFOUND;
883 STRCPY_RET(request.data.auth.user, r_user);
884 STRCPY_RET(request.data.auth.pass, pass);
886 if (*user == WB_AIX_ENCODED) {
887 free(r_user);
890 result = winbindd_request_response(WINBINDD_PAM_AUTH, &request, &response);
892 free_response(&response);
894 logit("auth result %d for '%s'\n", result, user);
896 if (result == NSS_STATUS_SUCCESS) {
897 errno = 0;
898 return AUTH_SUCCESS;
901 return AUTH_FAILURE;
906 change a user password
908 static int wb_aix_chpass(char *user, char *oldpass, char *newpass, char **message)
910 struct winbindd_request request;
911 struct winbindd_response response;
912 NSS_STATUS result;
913 char *r_user = user;
915 if (*user == WB_AIX_ENCODED) {
916 r_user = decode_user(r_user);
917 if (!r_user) {
918 errno = ENOENT;
919 return -1;
923 logit("chpass '%s' old='%s' new='%s'\n", r_user, oldpass, newpass);
925 *message = NULL;
927 /* Send off request */
928 ZERO_STRUCT(request);
929 ZERO_STRUCT(response);
931 STRCPY_RET(request.data.chauthtok.user, r_user);
932 STRCPY_RET(request.data.chauthtok.oldpass, oldpass);
933 STRCPY_RET(request.data.chauthtok.newpass, newpass);
935 if (*user == WB_AIX_ENCODED) {
936 free(r_user);
939 result = winbindd_request_response(WINBINDD_PAM_CHAUTHTOK, &request, &response);
941 free_response(&response);
943 if (result == NSS_STATUS_SUCCESS) {
944 errno = 0;
945 return 0;
948 errno = EINVAL;
949 return -1;
953 don't do any password strength testing for now
955 static int wb_aix_passwdrestrictions(char *user, char *newpass, char *oldpass,
956 char **message)
958 logit("passwdresrictions called for '%s'\n", user);
959 return 0;
963 static int wb_aix_passwdexpired(char *user, char **message)
965 logit("passwdexpired '%s'\n", user);
966 /* we should check the account bits here */
967 return 0;
972 we can't return a crypt() password
974 static char *wb_aix_getpasswd(char *user)
976 logit("getpasswd '%s'\n", user);
977 errno = ENOSYS;
978 return NULL;
982 this is called to update things like the last login time. We don't
983 currently pass this onto the DC
985 static int wb_aix_putentry(char *key, char *table, char *attributes[],
986 attrval_t values[], int size)
988 logit("putentry key='%s' table='%s' attrib='%s'\n",
989 key, table, size>=1?attributes[0]:"<null>");
990 errno = ENOSYS;
991 return -1;
994 static int wb_aix_commit(char *key, char *table)
996 logit("commit key='%s' table='%s'\n");
997 errno = ENOSYS;
998 return -1;
1001 static int wb_aix_getgrusers(char *group, void *result, int type, int *size)
1003 logit("getgrusers group='%s'\n", group);
1004 errno = ENOSYS;
1005 return -1;
1009 #define DECL_METHOD(x) \
1010 int method_ ## x(void) \
1012 logit("UNIMPLEMENTED METHOD '%s'\n", #x); \
1013 errno = EINVAL; \
1014 return -1; \
1017 #if LOG_UNIMPLEMENTED_CALLS
1018 DECL_METHOD(delgroup);
1019 DECL_METHOD(deluser);
1020 DECL_METHOD(newgroup);
1021 DECL_METHOD(newuser);
1022 DECL_METHOD(putgrent);
1023 DECL_METHOD(putgrusers);
1024 DECL_METHOD(putpwent);
1025 DECL_METHOD(lock);
1026 DECL_METHOD(unlock);
1027 DECL_METHOD(getcred);
1028 DECL_METHOD(setcred);
1029 DECL_METHOD(deletecred);
1030 #endif
1032 int wb_aix_init(struct secmethod_table *methods)
1034 ZERO_STRUCTP(methods);
1036 #ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_VERSION
1037 methods->method_version = SECMETHOD_VERSION_520;
1038 #endif
1040 methods->method_getgrgid = wb_aix_getgrgid;
1041 methods->method_getgrnam = wb_aix_getgrnam;
1042 methods->method_getgrset = wb_aix_getgrset;
1043 methods->method_getpwnam = wb_aix_getpwnam;
1044 methods->method_getpwuid = wb_aix_getpwuid;
1045 methods->method_getentry = wb_aix_getentry;
1046 methods->method_open = wb_aix_open;
1047 methods->method_close = wb_aix_close;
1048 methods->method_normalize = wb_aix_normalize;
1049 methods->method_passwdexpired = wb_aix_passwdexpired;
1050 methods->method_putentry = wb_aix_putentry;
1051 methods->method_getpasswd = wb_aix_getpasswd;
1052 methods->method_authenticate = wb_aix_authenticate;
1053 methods->method_commit = wb_aix_commit;
1054 methods->method_chpass = wb_aix_chpass;
1055 methods->method_passwdrestrictions = wb_aix_passwdrestrictions;
1056 methods->method_getgracct = wb_aix_getgracct;
1057 methods->method_getgrusers = wb_aix_getgrusers;
1058 #ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_ATTRLIST
1059 methods->method_attrlist = wb_aix_attrlist;
1060 #endif
1062 #if LOG_UNIMPLEMENTED_CALLS
1063 methods->method_delgroup = method_delgroup;
1064 methods->method_deluser = method_deluser;
1065 methods->method_newgroup = method_newgroup;
1066 methods->method_newuser = method_newuser;
1067 methods->method_putgrent = method_putgrent;
1068 methods->method_putgrusers = method_putgrusers;
1069 methods->method_putpwent = method_putpwent;
1070 methods->method_lock = method_lock;
1071 methods->method_unlock = method_unlock;
1072 methods->method_getcred = method_getcred;
1073 methods->method_setcred = method_setcred;
1074 methods->method_deletecred = method_deletecred;
1075 #endif
1077 return AUTH_SUCCESS;