ctdb-scripts: Move "ERROR:" prefix out of ctdb_check_rpc()
[Samba.git] / nsswitch / winbind_nss_aix.c
blob7a847b2344bc0dcb94597f258710363d54242787
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(NULL, WINBINDD_GETGRGID,
283 &request, &response);
285 logit("getgrgid ret=%d\n", ret);
287 HANDLE_ERRORS(ret);
289 grp = fill_grent(&response.data.gr, response.extra_data.data);
291 winbindd_free_response(&response);
293 return grp;
296 /* take a group name and return a filled struct group */
297 static struct group *wb_aix_getgrnam(const char *name)
299 struct winbindd_response response;
300 struct winbindd_request request;
301 NSS_STATUS ret;
302 struct group *grp;
304 if (*name == WB_AIX_ENCODED) {
305 return wb_aix_getgrgid(decode_id(name));
308 logit("getgrnam '%s'\n", name);
310 ZERO_STRUCT(response);
311 ZERO_STRUCT(request);
313 STRCPY_RETNULL(request.data.groupname, name);
315 ret = winbindd_request_response(NULL, WINBINDD_GETGRNAM,
316 &request, &response);
318 HANDLE_ERRORS(ret);
320 grp = fill_grent(&response.data.gr, response.extra_data.data);
322 winbindd_free_response(&response);
324 return grp;
328 /* this call doesn't have to fill in the gr_mem, but we do anyway
329 for simplicity */
330 static struct group *wb_aix_getgracct(void *id, int type)
332 if (type == 1) {
333 return wb_aix_getgrnam((char *)id);
335 if (type == 0) {
336 return wb_aix_getgrgid(*(int *)id);
338 errno = EINVAL;
339 return NULL;
343 /* take a username and return a string containing a comma-separated
344 list of group id numbers to which the user belongs */
345 static char *wb_aix_getgrset(char *user)
347 struct winbindd_response response;
348 struct winbindd_request request;
349 NSS_STATUS ret;
350 int i, idx;
351 char *tmpbuf;
352 int num_gids;
353 gid_t *gid_list;
354 char *r_user = user;
356 if (*user == WB_AIX_ENCODED) {
357 r_user = decode_user(r_user);
358 if (!r_user) {
359 errno = ENOENT;
360 return NULL;
364 logit("getgrset '%s'\n", r_user);
366 ZERO_STRUCT(response);
367 ZERO_STRUCT(request);
369 STRCPY_RETNULL(request.data.username, r_user);
371 if (*user == WB_AIX_ENCODED) {
372 free(r_user);
375 ret = winbindd_request_response(NULL, WINBINDD_GETGROUPS,
376 &request, &response);
378 HANDLE_ERRORS(ret);
380 num_gids = response.data.num_entries;
381 gid_list = (gid_t *)response.extra_data.data;
383 /* allocate a space large enough to contruct the string */
384 tmpbuf = malloc(num_gids*12);
385 if (!tmpbuf) {
386 return NULL;
389 for (idx=i=0; i < num_gids-1; i++) {
390 idx += sprintf(tmpbuf+idx, "%u,", gid_list[i]);
392 idx += sprintf(tmpbuf+idx, "%u", gid_list[i]);
394 winbindd_free_response(&response);
396 return tmpbuf;
400 /* take a uid and return a filled struct passwd */
401 static struct passwd *wb_aix_getpwuid(uid_t uid)
403 struct winbindd_response response;
404 struct winbindd_request request;
405 NSS_STATUS ret;
406 struct passwd *pwd;
408 logit("getpwuid '%d'\n", uid);
410 ZERO_STRUCT(response);
411 ZERO_STRUCT(request);
413 request.data.uid = uid;
415 ret = winbindd_request_response(NULL, WINBINDD_GETPWUID,
416 &request, &response);
418 HANDLE_ERRORS(ret);
420 pwd = fill_pwent(&response.data.pw);
422 winbindd_free_response(&response);
424 logit("getpwuid gave ptr %p\n", pwd);
426 return pwd;
430 /* take a username and return a filled struct passwd */
431 static struct passwd *wb_aix_getpwnam(const char *name)
433 struct winbindd_response response;
434 struct winbindd_request request;
435 NSS_STATUS ret;
436 struct passwd *pwd;
438 if (*name == WB_AIX_ENCODED) {
439 return wb_aix_getpwuid(decode_id(name));
442 logit("getpwnam '%s'\n", name);
444 ZERO_STRUCT(response);
445 ZERO_STRUCT(request);
447 STRCPY_RETNULL(request.data.username, name);
449 ret = winbindd_request_response(NULL, WINBINDD_GETPWNAM,
450 &request, &response);
452 HANDLE_ERRORS(ret);
454 pwd = fill_pwent(&response.data.pw);
456 winbindd_free_response(&response);
458 logit("getpwnam gave ptr %p\n", pwd);
460 return pwd;
464 list users
466 static int wb_aix_lsuser(char *attributes[], attrval_t results[], int size)
468 NSS_STATUS ret;
469 struct winbindd_request request;
470 struct winbindd_response response;
471 int len;
472 char *s;
474 if (size != 1 || strcmp(attributes[0], S_USERS) != 0) {
475 logit("invalid lsuser op\n");
476 errno = EINVAL;
477 return -1;
480 ZERO_STRUCT(request);
481 ZERO_STRUCT(response);
483 ret = winbindd_request_response(NULL, WINBINDD_LIST_USERS,
484 &request, &response);
485 if (ret != 0) {
486 errno = EINVAL;
487 return -1;
490 len = strlen(response.extra_data.data);
492 s = malloc(len+2);
493 if (!s) {
494 winbindd_free_response(&response);
495 errno = ENOMEM;
496 return -1;
499 memcpy(s, response.extra_data.data, len+1);
501 replace_commas(s);
503 results[0].attr_un.au_char = s;
504 results[0].attr_flag = 0;
506 winbindd_free_response(&response);
508 return 0;
513 list groups
515 static int wb_aix_lsgroup(char *attributes[], attrval_t results[], int size)
517 NSS_STATUS ret;
518 struct winbindd_request request;
519 struct winbindd_response response;
520 int len;
521 char *s;
523 if (size != 1 || strcmp(attributes[0], S_GROUPS) != 0) {
524 logit("invalid lsgroup op\n");
525 errno = EINVAL;
526 return -1;
529 ZERO_STRUCT(request);
530 ZERO_STRUCT(response);
532 ret = winbindd_request_response(NULL, WINBINDD_LIST_GROUPS,
533 &request, &response);
534 if (ret != 0) {
535 errno = EINVAL;
536 return -1;
539 len = strlen(response.extra_data.data);
541 s = malloc(len+2);
542 if (!s) {
543 winbindd_free_response(&response);
544 errno = ENOMEM;
545 return -1;
548 memcpy(s, response.extra_data.data, len+1);
550 replace_commas(s);
552 results[0].attr_un.au_char = s;
553 results[0].attr_flag = 0;
555 winbindd_free_response(&response);
557 return 0;
561 static attrval_t pwd_to_group(struct passwd *pwd)
563 attrval_t r;
564 struct group *grp = wb_aix_getgrgid(pwd->pw_gid);
566 if (!grp) {
567 r.attr_flag = EINVAL;
568 } else {
569 r.attr_flag = 0;
570 r.attr_un.au_char = strdup(grp->gr_name);
571 free_grp(grp);
574 return r;
577 static attrval_t pwd_to_groupsids(struct passwd *pwd)
579 attrval_t r;
580 char *s, *p;
582 if ( (s = wb_aix_getgrset(pwd->pw_name)) == NULL ) {
583 r.attr_flag = EINVAL;
584 return r;
587 if ( (p = malloc(strlen(s)+2)) == NULL ) {
588 r.attr_flag = ENOMEM;
589 return r;
592 strcpy(p, s);
593 replace_commas(p);
594 free(s);
596 r.attr_un.au_char = p;
598 return r;
601 static attrval_t pwd_to_sid(struct passwd *pwd)
603 struct winbindd_request request;
604 struct winbindd_response response;
605 attrval_t r;
607 ZERO_STRUCT(request);
608 ZERO_STRUCT(response);
610 request.data.uid = pwd->pw_uid;
612 if (winbindd_request_response(NULL, WINBINDD_UID_TO_SID,
613 &request, &response) !=
614 NSS_STATUS_SUCCESS) {
615 r.attr_flag = ENOENT;
616 } else {
617 r.attr_flag = 0;
618 r.attr_un.au_char = strdup(response.data.sid.sid);
621 return r;
624 static int wb_aix_user_attrib(const char *key, char *attributes[],
625 attrval_t results[], int size)
627 struct passwd *pwd;
628 int i;
630 pwd = wb_aix_getpwnam(key);
631 if (!pwd) {
632 errno = ENOENT;
633 return -1;
636 for (i=0;i<size;i++) {
637 results[i].attr_flag = 0;
639 if (strcmp(attributes[i], S_ID) == 0) {
640 results[i].attr_un.au_int = pwd->pw_uid;
641 #ifdef _AIXVERSION_530
642 } else if (strcmp(attributes[i], S_PGID) == 0) {
643 results[i].attr_un.au_int = pwd->pw_gid;
644 #endif
645 } else if (strcmp(attributes[i], S_PWD) == 0) {
646 results[i].attr_un.au_char = strdup(pwd->pw_passwd);
647 } else if (strcmp(attributes[i], S_HOME) == 0) {
648 results[i].attr_un.au_char = strdup(pwd->pw_dir);
649 } else if (strcmp(attributes[i], S_SHELL) == 0) {
650 results[i].attr_un.au_char = strdup(pwd->pw_shell);
651 } else if (strcmp(attributes[i], S_REGISTRY) == 0) {
652 results[i].attr_un.au_char = strdup("WINBIND");
653 } else if (strcmp(attributes[i], S_GECOS) == 0) {
654 results[i].attr_un.au_char = strdup(pwd->pw_gecos);
655 } else if (strcmp(attributes[i], S_PGRP) == 0) {
656 results[i] = pwd_to_group(pwd);
657 } else if (strcmp(attributes[i], S_GROUPS) == 0) {
658 results[i] = pwd_to_groupsids(pwd);
659 } else if (strcmp(attributes[i], "SID") == 0) {
660 results[i] = pwd_to_sid(pwd);
661 } else {
662 logit("Unknown user attribute '%s'\n", attributes[i]);
663 results[i].attr_flag = EINVAL;
667 free_pwd(pwd);
669 return 0;
672 static int wb_aix_group_attrib(const char *key, char *attributes[],
673 attrval_t results[], int size)
675 struct group *grp;
676 int i;
678 grp = wb_aix_getgrnam(key);
679 if (!grp) {
680 errno = ENOENT;
681 return -1;
684 for (i=0;i<size;i++) {
685 results[i].attr_flag = 0;
687 if (strcmp(attributes[i], S_PWD) == 0) {
688 results[i].attr_un.au_char = strdup(grp->gr_passwd);
689 } else if (strcmp(attributes[i], S_ID) == 0) {
690 results[i].attr_un.au_int = grp->gr_gid;
691 } else {
692 logit("Unknown group attribute '%s'\n", attributes[i]);
693 results[i].attr_flag = EINVAL;
697 free_grp(grp);
699 return 0;
704 called for user/group enumerations
706 static int wb_aix_getentry(char *key, char *table, char *attributes[],
707 attrval_t results[], int size)
709 logit("Got getentry with key='%s' table='%s' size=%d attributes[0]='%s'\n",
710 key, table, size, attributes[0]);
712 if (strcmp(key, "ALL") == 0 &&
713 strcmp(table, "user") == 0) {
714 return wb_aix_lsuser(attributes, results, size);
717 if (strcmp(key, "ALL") == 0 &&
718 strcmp(table, "group") == 0) {
719 return wb_aix_lsgroup(attributes, results, size);
722 if (strcmp(table, "user") == 0) {
723 return wb_aix_user_attrib(key, attributes, results, size);
726 if (strcmp(table, "group") == 0) {
727 return wb_aix_group_attrib(key, attributes, results, size);
730 logit("Unknown getentry operation key='%s' table='%s'\n", key, table);
732 errno = ENOSYS;
733 return -1;
739 called to start the backend
741 static void *wb_aix_open(const char *name, const char *domain, int mode, char *options)
743 if (strstr(options, "debug")) {
744 debug_enabled = 1;
746 logit("open name='%s' mode=%d domain='%s' options='%s'\n", name, domain,
747 mode, options);
748 return NULL;
751 static void wb_aix_close(void *token)
753 logit("close\n");
754 return;
757 #ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_ATTRLIST
759 return a list of additional attributes supported by the backend
761 static attrlist_t **wb_aix_attrlist(void)
763 /* pretty confusing but we are allocating the array of pointers
764 and the structures we'll be pointing to all at once. So
765 you need N+1 pointers and N structures. */
767 attrlist_t **ret = NULL;
768 attrlist_t *offset = NULL;
769 int i;
770 int n;
771 size_t size;
773 struct attr_types {
774 const char *name;
775 int flags;
776 int type;
777 } attr_list[] = {
778 /* user attributes */
779 {S_ID, AL_USERATTR, SEC_INT},
780 {S_PGRP, AL_USERATTR, SEC_CHAR},
781 {S_HOME, AL_USERATTR, SEC_CHAR},
782 {S_SHELL, AL_USERATTR, SEC_CHAR},
783 #ifdef _AIXVERSION_530
784 {S_PGID, AL_USERATTR, SEC_INT},
785 #endif
786 {S_GECOS, AL_USERATTR, SEC_CHAR},
787 {S_SHELL, AL_USERATTR, SEC_CHAR},
788 {S_PGRP, AL_USERATTR, SEC_CHAR},
789 {S_GROUPS, AL_USERATTR, SEC_LIST},
790 {"SID", AL_USERATTR, SEC_CHAR},
792 /* group attributes */
793 {S_ID, AL_GROUPATTR, SEC_INT}
796 logit("method attrlist called\n");
798 n = sizeof(attr_list) / sizeof(struct attr_types);
799 size = (n*sizeof(attrlist_t *));
801 if ( (ret = malloc( size )) == NULL ) {
802 errno = ENOMEM;
803 return NULL;
806 /* offset to where the structures start in the buffer */
808 offset = (attrlist_t *)(ret + n);
810 /* now loop over the user_attr_list[] array and add
811 all the members */
813 for ( i=0; i<n; i++ ) {
814 attrlist_t *a = malloc(sizeof(attrlist_t));
816 if ( !a ) {
817 /* this is bad. Just bail */
818 return NULL;
821 a->al_name = strdup(attr_list[i].name);
822 a->al_flags = attr_list[i].flags;
823 a->al_type = attr_list[i].type;
825 ret[i] = a;
827 ret[n] = NULL;
829 return ret;
831 #endif
835 turn a long username into a short one. Needed to cope with the 8 char
836 username limit in AIX 5.2 and below
838 static int wb_aix_normalize(char *longname, char *shortname)
840 struct passwd *pwd;
842 logit("normalize '%s'\n", longname);
844 /* automatically cope with AIX 5.3 with longer usernames
845 when it comes out */
846 if (S_NAMELEN > strlen(longname)) {
847 strcpy(shortname, longname);
848 return 1;
851 pwd = wb_aix_getpwnam(longname);
852 if (!pwd) {
853 errno = ENOENT;
854 return 0;
857 sprintf(shortname, "%c%07u", WB_AIX_ENCODED, pwd->pw_uid);
859 free_pwd(pwd);
861 return 1;
866 authenticate a user
868 static int wb_aix_authenticate(char *user, char *pass,
869 int *reenter, char **message)
871 struct winbindd_request request;
872 struct winbindd_response response;
873 NSS_STATUS result;
874 char *r_user = user;
876 logit("authenticate '%s' response='%s'\n", user, pass);
878 *reenter = 0;
879 *message = NULL;
881 /* Send off request */
882 ZERO_STRUCT(request);
883 ZERO_STRUCT(response);
885 if (*user == WB_AIX_ENCODED) {
886 r_user = decode_user(r_user);
887 if (!r_user) {
888 return AUTH_NOTFOUND;
892 STRCPY_RET(request.data.auth.user, r_user);
893 STRCPY_RET(request.data.auth.pass, pass);
895 if (*user == WB_AIX_ENCODED) {
896 free(r_user);
899 result = winbindd_request_response(NULL, WINBINDD_PAM_AUTH,
900 &request, &response);
902 winbindd_free_response(&response);
904 logit("auth result %d for '%s'\n", result, user);
906 if (result == NSS_STATUS_SUCCESS) {
907 errno = 0;
908 return AUTH_SUCCESS;
911 return AUTH_FAILURE;
916 change a user password
918 static int wb_aix_chpass(char *user, char *oldpass, char *newpass, char **message)
920 struct winbindd_request request;
921 struct winbindd_response response;
922 NSS_STATUS result;
923 char *r_user = user;
925 if (*user == WB_AIX_ENCODED) {
926 r_user = decode_user(r_user);
927 if (!r_user) {
928 errno = ENOENT;
929 return -1;
933 logit("chpass '%s' old='%s' new='%s'\n", r_user, oldpass, newpass);
935 *message = NULL;
937 /* Send off request */
938 ZERO_STRUCT(request);
939 ZERO_STRUCT(response);
941 STRCPY_RET(request.data.chauthtok.user, r_user);
942 STRCPY_RET(request.data.chauthtok.oldpass, oldpass);
943 STRCPY_RET(request.data.chauthtok.newpass, newpass);
945 if (*user == WB_AIX_ENCODED) {
946 free(r_user);
949 result = winbindd_request_response(NULL, WINBINDD_PAM_CHAUTHTOK,
950 &request, &response);
952 winbindd_free_response(&response);
954 if (result == NSS_STATUS_SUCCESS) {
955 errno = 0;
956 return 0;
959 errno = EINVAL;
960 return -1;
964 don't do any password strength testing for now
966 static int wb_aix_passwdrestrictions(char *user, char *newpass, char *oldpass,
967 char **message)
969 logit("passwdresrictions called for '%s'\n", user);
970 return 0;
974 static int wb_aix_passwdexpired(char *user, char **message)
976 logit("passwdexpired '%s'\n", user);
977 /* we should check the account bits here */
978 return 0;
983 we can't return a crypt() password
985 static char *wb_aix_getpasswd(char *user)
987 logit("getpasswd '%s'\n", user);
988 errno = ENOSYS;
989 return NULL;
993 this is called to update things like the last login time. We don't
994 currently pass this onto the DC
996 static int wb_aix_putentry(char *key, char *table, char *attributes[],
997 attrval_t values[], int size)
999 logit("putentry key='%s' table='%s' attrib='%s'\n",
1000 key, table, size>=1?attributes[0]:"<null>");
1001 errno = ENOSYS;
1002 return -1;
1005 static int wb_aix_commit(char *key, char *table)
1007 logit("commit key='%s' table='%s'\n");
1008 errno = ENOSYS;
1009 return -1;
1012 static int wb_aix_getgrusers(char *group, void *result, int type, int *size)
1014 logit("getgrusers group='%s'\n", group);
1015 errno = ENOSYS;
1016 return -1;
1020 #define DECL_METHOD(x) \
1021 int method_ ## x(void) \
1023 logit("UNIMPLEMENTED METHOD '%s'\n", #x); \
1024 errno = EINVAL; \
1025 return -1; \
1028 #if LOG_UNIMPLEMENTED_CALLS
1029 DECL_METHOD(delgroup);
1030 DECL_METHOD(deluser);
1031 DECL_METHOD(newgroup);
1032 DECL_METHOD(newuser);
1033 DECL_METHOD(putgrent);
1034 DECL_METHOD(putgrusers);
1035 DECL_METHOD(putpwent);
1036 DECL_METHOD(lock);
1037 DECL_METHOD(unlock);
1038 DECL_METHOD(getcred);
1039 DECL_METHOD(setcred);
1040 DECL_METHOD(deletecred);
1041 #endif
1043 int wb_aix_init(struct secmethod_table *methods)
1045 ZERO_STRUCTP(methods);
1047 #ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_VERSION
1048 methods->method_version = SECMETHOD_VERSION_520;
1049 #endif
1051 methods->method_getgrgid = wb_aix_getgrgid;
1052 methods->method_getgrnam = wb_aix_getgrnam;
1053 methods->method_getgrset = wb_aix_getgrset;
1054 methods->method_getpwnam = wb_aix_getpwnam;
1055 methods->method_getpwuid = wb_aix_getpwuid;
1056 methods->method_getentry = wb_aix_getentry;
1057 methods->method_open = wb_aix_open;
1058 methods->method_close = wb_aix_close;
1059 methods->method_normalize = wb_aix_normalize;
1060 methods->method_passwdexpired = wb_aix_passwdexpired;
1061 methods->method_putentry = wb_aix_putentry;
1062 methods->method_getpasswd = wb_aix_getpasswd;
1063 methods->method_authenticate = wb_aix_authenticate;
1064 methods->method_commit = wb_aix_commit;
1065 methods->method_chpass = wb_aix_chpass;
1066 methods->method_passwdrestrictions = wb_aix_passwdrestrictions;
1067 methods->method_getgracct = wb_aix_getgracct;
1068 methods->method_getgrusers = wb_aix_getgrusers;
1069 #ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_ATTRLIST
1070 methods->method_attrlist = wb_aix_attrlist;
1071 #endif
1073 #if LOG_UNIMPLEMENTED_CALLS
1074 methods->method_delgroup = method_delgroup;
1075 methods->method_deluser = method_deluser;
1076 methods->method_newgroup = method_newgroup;
1077 methods->method_newuser = method_newuser;
1078 methods->method_putgrent = method_putgrent;
1079 methods->method_putgrusers = method_putgrusers;
1080 methods->method_putpwent = method_putpwent;
1081 methods->method_lock = method_lock;
1082 methods->method_unlock = method_unlock;
1083 methods->method_getcred = method_getcred;
1084 methods->method_setcred = method_setcred;
1085 methods->method_deletecred = method_deletecred;
1086 #endif
1088 return AUTH_SUCCESS;