Add missing end tags
[Samba/bjacke.git] / source / nsswitch / winbind_nss_aix.c
blob9c84e5f8aa518d33bccaad057a560f4db3cd0f6a
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 errno = ENOMEM;
241 return NULL;
244 /* Start looking at extra data */
245 i=0;
246 for (name = strtok_r(gr_mem, ",", &p);
247 name;
248 name = strtok_r(NULL, ",", &p)) {
249 if (i == gr->num_gr_mem) {
250 break;
252 result->gr_mem[i] = strdup(name);
253 i++;
256 /* Terminate list */
257 result->gr_mem[i] = NULL;
259 return result;
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;
269 struct group *grp;
270 NSS_STATUS ret;
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);
283 HANDLE_ERRORS(ret);
285 grp = fill_grent(&response.data.gr, response.extra_data.data);
287 winbindd_free_response(&response);
289 return grp;
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;
297 NSS_STATUS ret;
298 struct group *grp;
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);
313 HANDLE_ERRORS(ret);
315 grp = fill_grent(&response.data.gr, response.extra_data.data);
317 winbindd_free_response(&response);
319 return grp;
323 /* this call doesn't have to fill in the gr_mem, but we do anyway
324 for simplicity */
325 static struct group *wb_aix_getgracct(void *id, int type)
327 if (type == 1) {
328 return wb_aix_getgrnam((char *)id);
330 if (type == 0) {
331 return wb_aix_getgrgid(*(int *)id);
333 errno = EINVAL;
334 return NULL;
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;
344 NSS_STATUS ret;
345 int i, idx;
346 char *tmpbuf;
347 int num_gids;
348 gid_t *gid_list;
349 char *r_user = user;
351 if (*user == WB_AIX_ENCODED) {
352 r_user = decode_user(r_user);
353 if (!r_user) {
354 errno = ENOENT;
355 return NULL;
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) {
367 free(r_user);
370 ret = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response);
372 HANDLE_ERRORS(ret);
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);
379 if (!tmpbuf) {
380 return NULL;
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);
390 return tmpbuf;
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;
399 NSS_STATUS ret;
400 struct passwd *pwd;
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);
411 HANDLE_ERRORS(ret);
413 pwd = fill_pwent(&response.data.pw);
415 winbindd_free_response(&response);
417 logit("getpwuid gave ptr %p\n", pwd);
419 return 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;
428 NSS_STATUS ret;
429 struct passwd *pwd;
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);
444 HANDLE_ERRORS(ret);
446 pwd = fill_pwent(&response.data.pw);
448 winbindd_free_response(&response);
450 logit("getpwnam gave ptr %p\n", pwd);
452 return pwd;
456 list users
458 static int wb_aix_lsuser(char *attributes[], attrval_t results[], int size)
460 NSS_STATUS ret;
461 struct winbindd_request request;
462 struct winbindd_response response;
463 int len;
464 char *s;
466 if (size != 1 || strcmp(attributes[0], S_USERS) != 0) {
467 logit("invalid lsuser op\n");
468 errno = EINVAL;
469 return -1;
472 ZERO_STRUCT(request);
473 ZERO_STRUCT(response);
475 ret = winbindd_request_response(WINBINDD_LIST_USERS, &request, &response);
476 if (ret != 0) {
477 errno = EINVAL;
478 return -1;
481 len = strlen(response.extra_data.data);
483 s = malloc(len+2);
484 if (!s) {
485 winbindd_free_response(&response);
486 errno = ENOMEM;
487 return -1;
490 memcpy(s, response.extra_data.data, len+1);
492 replace_commas(s);
494 results[0].attr_un.au_char = s;
495 results[0].attr_flag = 0;
497 winbindd_free_response(&response);
499 return 0;
504 list groups
506 static int wb_aix_lsgroup(char *attributes[], attrval_t results[], int size)
508 NSS_STATUS ret;
509 struct winbindd_request request;
510 struct winbindd_response response;
511 int len;
512 char *s;
514 if (size != 1 || strcmp(attributes[0], S_GROUPS) != 0) {
515 logit("invalid lsgroup op\n");
516 errno = EINVAL;
517 return -1;
520 ZERO_STRUCT(request);
521 ZERO_STRUCT(response);
523 ret = winbindd_request_response(WINBINDD_LIST_GROUPS, &request, &response);
524 if (ret != 0) {
525 errno = EINVAL;
526 return -1;
529 len = strlen(response.extra_data.data);
531 s = malloc(len+2);
532 if (!s) {
533 winbindd_free_response(&response);
534 errno = ENOMEM;
535 return -1;
538 memcpy(s, response.extra_data.data, len+1);
540 replace_commas(s);
542 results[0].attr_un.au_char = s;
543 results[0].attr_flag = 0;
545 winbindd_free_response(&response);
547 return 0;
551 static attrval_t pwd_to_group(struct passwd *pwd)
553 attrval_t r;
554 struct group *grp = wb_aix_getgrgid(pwd->pw_gid);
556 if (!grp) {
557 r.attr_flag = EINVAL;
558 } else {
559 r.attr_flag = 0;
560 r.attr_un.au_char = strdup(grp->gr_name);
561 free_grp(grp);
564 return r;
567 static attrval_t pwd_to_groupsids(struct passwd *pwd)
569 attrval_t r;
570 char *s, *p;
572 if ( (s = wb_aix_getgrset(pwd->pw_name)) == NULL ) {
573 r.attr_flag = EINVAL;
574 return r;
577 if ( (p = malloc(strlen(s)+2)) == NULL ) {
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_response(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 #ifdef _AIXVERSION_530
631 } else if (strcmp(attributes[i], S_PGID) == 0) {
632 results[i].attr_un.au_int = pwd->pw_gid;
633 #endif
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);
650 } else {
651 logit("Unknown user attribute '%s'\n", attributes[i]);
652 results[i].attr_flag = EINVAL;
656 free_pwd(pwd);
658 return 0;
661 static int wb_aix_group_attrib(const char *key, char *attributes[],
662 attrval_t results[], int size)
664 struct group *grp;
665 int i;
667 grp = wb_aix_getgrnam(key);
668 if (!grp) {
669 errno = ENOENT;
670 return -1;
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;
680 } else {
681 logit("Unknown group attribute '%s'\n", attributes[i]);
682 results[i].attr_flag = EINVAL;
686 free_grp(grp);
688 return 0;
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);
721 errno = ENOSYS;
722 return -1;
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")) {
733 debug_enabled = 1;
735 logit("open name='%s' mode=%d domain='%s' options='%s'\n", name, domain,
736 mode, options);
737 return NULL;
740 static void wb_aix_close(void *token)
742 logit("close\n");
743 return;
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;
758 int i;
759 int n;
760 size_t size;
762 struct attr_types {
763 const char *name;
764 int flags;
765 int type;
766 } attr_list[] = {
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},
774 #endif
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 ) {
791 errno = ENOMEM;
792 return 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
800 all the members */
802 for ( i=0; i<n; i++ ) {
803 attrlist_t *a = malloc(sizeof(attrlist_t));
805 if ( !a ) {
806 /* this is bad. Just bail */
807 return NULL;
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;
814 ret[i] = a;
816 ret[n] = NULL;
818 return ret;
820 #endif
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)
829 struct passwd *pwd;
831 logit("normalize '%s'\n", longname);
833 /* automatically cope with AIX 5.3 with longer usernames
834 when it comes out */
835 if (S_NAMELEN > strlen(longname)) {
836 strcpy(shortname, longname);
837 return 1;
840 pwd = wb_aix_getpwnam(longname);
841 if (!pwd) {
842 errno = ENOENT;
843 return 0;
846 sprintf(shortname, "%c%07u", WB_AIX_ENCODED, pwd->pw_uid);
848 free_pwd(pwd);
850 return 1;
855 authenticate a user
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;
862 NSS_STATUS result;
863 char *r_user = user;
865 logit("authenticate '%s' response='%s'\n", user, pass);
867 *reenter = 0;
868 *message = NULL;
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);
876 if (!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) {
885 free(r_user);
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) {
895 errno = 0;
896 return AUTH_SUCCESS;
899 return AUTH_FAILURE;
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;
910 NSS_STATUS result;
911 char *r_user = user;
913 if (*user == WB_AIX_ENCODED) {
914 r_user = decode_user(r_user);
915 if (!r_user) {
916 errno = ENOENT;
917 return -1;
921 logit("chpass '%s' old='%s' new='%s'\n", r_user, oldpass, newpass);
923 *message = NULL;
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) {
934 free(r_user);
937 result = winbindd_request_response(WINBINDD_PAM_CHAUTHTOK, &request, &response);
939 winbindd_free_response(&response);
941 if (result == NSS_STATUS_SUCCESS) {
942 errno = 0;
943 return 0;
946 errno = EINVAL;
947 return -1;
951 don't do any password strength testing for now
953 static int wb_aix_passwdrestrictions(char *user, char *newpass, char *oldpass,
954 char **message)
956 logit("passwdresrictions called for '%s'\n", user);
957 return 0;
961 static int wb_aix_passwdexpired(char *user, char **message)
963 logit("passwdexpired '%s'\n", user);
964 /* we should check the account bits here */
965 return 0;
970 we can't return a crypt() password
972 static char *wb_aix_getpasswd(char *user)
974 logit("getpasswd '%s'\n", user);
975 errno = ENOSYS;
976 return NULL;
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>");
988 errno = ENOSYS;
989 return -1;
992 static int wb_aix_commit(char *key, char *table)
994 logit("commit key='%s' table='%s'\n");
995 errno = ENOSYS;
996 return -1;
999 static int wb_aix_getgrusers(char *group, void *result, int type, int *size)
1001 logit("getgrusers group='%s'\n", group);
1002 errno = ENOSYS;
1003 return -1;
1007 #define DECL_METHOD(x) \
1008 int method_ ## x(void) \
1010 logit("UNIMPLEMENTED METHOD '%s'\n", #x); \
1011 errno = EINVAL; \
1012 return -1; \
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);
1023 DECL_METHOD(lock);
1024 DECL_METHOD(unlock);
1025 DECL_METHOD(getcred);
1026 DECL_METHOD(setcred);
1027 DECL_METHOD(deletecred);
1028 #endif
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;
1036 #endif
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;
1058 #endif
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;
1073 #endif
1075 return AUTH_SUCCESS;