source: vendor/current/nsswitch/winbind_nss_aix.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

File size: 22.9 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3
4 AIX loadable authentication module, providing identification and
5 authentication routines against Samba winbind/Windows NT Domain
6
7 Copyright (C) Tim Potter 2003
8 Copyright (C) Steve Roylance 2003
9 Copyright (C) Andrew Tridgell 2003-2004
10
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.
15
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.
20
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/>.
23*/
24
25/*
26
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
29
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.
33
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
37
38 Many thanks to Julianne Haugh for explaining some of the finer
39 details of this interface.
40
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
43
44*/
45
46#include "winbind_client.h"
47#include <usersec.h>
48
49/* enable this to log which entry points have not been
50 completed yet */
51#define LOG_UNIMPLEMENTED_CALLS 0
52
53
54#define WB_AIX_ENCODED '_'
55
56static int debug_enabled;
57
58
59static void logit(const char *format, ...)
60{
61 va_list ap;
62 FILE *f;
63 if (!debug_enabled) {
64 return;
65 }
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);
72}
73
74
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)
84
85#define STRCPY_RET(dest, src) \
86do { \
87 if (strlen(src)+1 > sizeof(dest)) { errno = EINVAL; return -1; } \
88 strcpy(dest, src); \
89} while (0)
90
91#define STRCPY_RETNULL(dest, src) \
92do { \
93 if (strlen(src)+1 > sizeof(dest)) { errno = EINVAL; return NULL; } \
94 strcpy(dest, src); \
95} while (0)
96
97
98/* free a passwd structure */
99static void free_pwd(struct passwd *pwd)
100{
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);
107}
108
109/* free a group structure */
110static void free_grp(struct group *grp)
111{
112 int i;
113
114 free(grp->gr_name);
115 free(grp->gr_passwd);
116
117 if (!grp->gr_mem) {
118 free(grp);
119 return;
120 }
121
122 for (i=0; grp->gr_mem[i]; i++) {
123 free(grp->gr_mem[i]);
124 }
125
126 free(grp->gr_mem);
127 free(grp);
128}
129
130
131/* replace commas with nulls, and null terminate */
132static void replace_commas(char *s)
133{
134 char *p, *p0=s;
135 for (p=strchr(s, ','); p; p = strchr(p+1, ',')) {
136 *p=0;
137 p0 = p+1;
138 }
139
140 p0[strlen(p0)+1] = 0;
141}
142
143
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'.
149
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
152*/
153static unsigned decode_id(const char *name)
154{
155 unsigned id;
156 sscanf(name+1, "%u", &id);
157 return id;
158}
159
160static struct passwd *wb_aix_getpwuid(uid_t uid);
161
162static char *decode_user(const char *name)
163{
164 struct passwd *pwd;
165 unsigned id;
166 char *ret;
167
168 sscanf(name+1, "%u", &id);
169 pwd = wb_aix_getpwuid(id);
170 if (!pwd) {
171 return NULL;
172 }
173 ret = strdup(pwd->pw_name);
174
175 free_pwd(pwd);
176
177 logit("decoded '%s' -> '%s'\n", name, ret);
178
179 return ret;
180}
181
182
183/*
184 fill a struct passwd from a winbindd_pw struct, allocating as a single block
185*/
186static struct passwd *fill_pwent(struct winbindd_pw *pw)
187{
188 struct passwd *result;
189
190 result = calloc(1, sizeof(struct passwd));
191 if (!result) {
192 errno = ENOMEM;
193 return NULL;
194 }
195
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);
203
204 return result;
205}
206
207
208/*
209 fill a struct group from a winbindd_pw struct, allocating as a single block
210*/
211static struct group *fill_grent(struct winbindd_gr *gr, char *gr_mem)
212{
213 int i;
214 struct group *result;
215 char *p, *name;
216
217 result = calloc(1, sizeof(struct group));
218 if (!result) {
219 errno = ENOMEM;
220 return NULL;
221 }
222
223 result->gr_gid = gr->gr_gid;
224
225 result->gr_name = strdup(gr->gr_name);
226 result->gr_passwd = strdup(gr->gr_passwd);
227
228 /* Group membership */
229 if ((gr->num_gr_mem < 0) || !gr_mem) {
230 gr->num_gr_mem = 0;
231 }
232
233 if (gr->num_gr_mem == 0) {
234 /* Group is empty */
235 return result;
236 }
237
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;
245 }
246
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;
254 }
255 result->gr_mem[i] = strdup(name);
256 i++;
257 }
258
259 /* Terminate list */
260 result->gr_mem[i] = NULL;
261
262 return result;
263}
264
265
266
267/* take a group id and return a filled struct group */
268static struct group *wb_aix_getgrgid(gid_t gid)
269{
270 struct winbindd_response response;
271 struct winbindd_request request;
272 struct group *grp;
273 NSS_STATUS ret;
274
275 logit("getgrgid %d\n", gid);
276
277 ZERO_STRUCT(response);
278 ZERO_STRUCT(request);
279
280 request.data.gid = gid;
281
282 ret = winbindd_request_response(NULL, WINBINDD_GETGRGID,
283 &request, &response);
284
285 logit("getgrgid ret=%d\n", ret);
286
287 HANDLE_ERRORS(ret);
288
289 grp = fill_grent(&response.data.gr, response.extra_data.data);
290
291 winbindd_free_response(&response);
292
293 return grp;
294}
295
296/* take a group name and return a filled struct group */
297static struct group *wb_aix_getgrnam(const char *name)
298{
299 struct winbindd_response response;
300 struct winbindd_request request;
301 NSS_STATUS ret;
302 struct group *grp;
303
304 if (*name == WB_AIX_ENCODED) {
305 return wb_aix_getgrgid(decode_id(name));
306 }
307
308 logit("getgrnam '%s'\n", name);
309
310 ZERO_STRUCT(response);
311 ZERO_STRUCT(request);
312
313 STRCPY_RETNULL(request.data.groupname, name);
314
315 ret = winbindd_request_response(NULL, WINBINDD_GETGRNAM,
316 &request, &response);
317
318 HANDLE_ERRORS(ret);
319
320 grp = fill_grent(&response.data.gr, response.extra_data.data);
321
322 winbindd_free_response(&response);
323
324 return grp;
325}
326
327
328/* this call doesn't have to fill in the gr_mem, but we do anyway
329 for simplicity */
330static struct group *wb_aix_getgracct(void *id, int type)
331{
332 if (type == 1) {
333 return wb_aix_getgrnam((char *)id);
334 }
335 if (type == 0) {
336 return wb_aix_getgrgid(*(int *)id);
337 }
338 errno = EINVAL;
339 return NULL;
340}
341
342
343/* take a username and return a string containing a comma-separated
344 list of group id numbers to which the user belongs */
345static char *wb_aix_getgrset(char *user)
346{
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;
355
356 if (*user == WB_AIX_ENCODED) {
357 r_user = decode_user(r_user);
358 if (!r_user) {
359 errno = ENOENT;
360 return NULL;
361 }
362 }
363
364 logit("getgrset '%s'\n", r_user);
365
366 ZERO_STRUCT(response);
367 ZERO_STRUCT(request);
368
369 STRCPY_RETNULL(request.data.username, r_user);
370
371 if (*user == WB_AIX_ENCODED) {
372 free(r_user);
373 }
374
375 ret = winbindd_request_response(NULL, WINBINDD_GETGROUPS,
376 &request, &response);
377
378 HANDLE_ERRORS(ret);
379
380 num_gids = response.data.num_entries;
381 gid_list = (gid_t *)response.extra_data.data;
382
383 /* allocate a space large enough to contruct the string */
384 tmpbuf = malloc(num_gids*12);
385 if (!tmpbuf) {
386 return NULL;
387 }
388
389 for (idx=i=0; i < num_gids-1; i++) {
390 idx += sprintf(tmpbuf+idx, "%u,", gid_list[i]);
391 }
392 idx += sprintf(tmpbuf+idx, "%u", gid_list[i]);
393
394 winbindd_free_response(&response);
395
396 return tmpbuf;
397}
398
399
400/* take a uid and return a filled struct passwd */
401static struct passwd *wb_aix_getpwuid(uid_t uid)
402{
403 struct winbindd_response response;
404 struct winbindd_request request;
405 NSS_STATUS ret;
406 struct passwd *pwd;
407
408 logit("getpwuid '%d'\n", uid);
409
410 ZERO_STRUCT(response);
411 ZERO_STRUCT(request);
412
413 request.data.uid = uid;
414
415 ret = winbindd_request_response(NULL, WINBINDD_GETPWUID,
416 &request, &response);
417
418 HANDLE_ERRORS(ret);
419
420 pwd = fill_pwent(&response.data.pw);
421
422 winbindd_free_response(&response);
423
424 logit("getpwuid gave ptr %p\n", pwd);
425
426 return pwd;
427}
428
429
430/* take a username and return a filled struct passwd */
431static struct passwd *wb_aix_getpwnam(const char *name)
432{
433 struct winbindd_response response;
434 struct winbindd_request request;
435 NSS_STATUS ret;
436 struct passwd *pwd;
437
438 if (*name == WB_AIX_ENCODED) {
439 return wb_aix_getpwuid(decode_id(name));
440 }
441
442 logit("getpwnam '%s'\n", name);
443
444 ZERO_STRUCT(response);
445 ZERO_STRUCT(request);
446
447 STRCPY_RETNULL(request.data.username, name);
448
449 ret = winbindd_request_response(NULL, WINBINDD_GETPWNAM,
450 &request, &response);
451
452 HANDLE_ERRORS(ret);
453
454 pwd = fill_pwent(&response.data.pw);
455
456 winbindd_free_response(&response);
457
458 logit("getpwnam gave ptr %p\n", pwd);
459
460 return pwd;
461}
462
463/*
464 list users
465*/
466static int wb_aix_lsuser(char *attributes[], attrval_t results[], int size)
467{
468 NSS_STATUS ret;
469 struct winbindd_request request;
470 struct winbindd_response response;
471 int len;
472 char *s;
473
474 if (size != 1 || strcmp(attributes[0], S_USERS) != 0) {
475 logit("invalid lsuser op\n");
476 errno = EINVAL;
477 return -1;
478 }
479
480 ZERO_STRUCT(request);
481 ZERO_STRUCT(response);
482
483 ret = winbindd_request_response(NULL, WINBINDD_LIST_USERS,
484 &request, &response);
485 if (ret != 0) {
486 errno = EINVAL;
487 return -1;
488 }
489
490 len = strlen(response.extra_data.data);
491
492 s = malloc(len+2);
493 if (!s) {
494 winbindd_free_response(&response);
495 errno = ENOMEM;
496 return -1;
497 }
498
499 memcpy(s, response.extra_data.data, len+1);
500
501 replace_commas(s);
502
503 results[0].attr_un.au_char = s;
504 results[0].attr_flag = 0;
505
506 winbindd_free_response(&response);
507
508 return 0;
509}
510
511
512/*
513 list groups
514*/
515static int wb_aix_lsgroup(char *attributes[], attrval_t results[], int size)
516{
517 NSS_STATUS ret;
518 struct winbindd_request request;
519 struct winbindd_response response;
520 int len;
521 char *s;
522
523 if (size != 1 || strcmp(attributes[0], S_GROUPS) != 0) {
524 logit("invalid lsgroup op\n");
525 errno = EINVAL;
526 return -1;
527 }
528
529 ZERO_STRUCT(request);
530 ZERO_STRUCT(response);
531
532 ret = winbindd_request_response(NULL, WINBINDD_LIST_GROUPS,
533 &request, &response);
534 if (ret != 0) {
535 errno = EINVAL;
536 return -1;
537 }
538
539 len = strlen(response.extra_data.data);
540
541 s = malloc(len+2);
542 if (!s) {
543 winbindd_free_response(&response);
544 errno = ENOMEM;
545 return -1;
546 }
547
548 memcpy(s, response.extra_data.data, len+1);
549
550 replace_commas(s);
551
552 results[0].attr_un.au_char = s;
553 results[0].attr_flag = 0;
554
555 winbindd_free_response(&response);
556
557 return 0;
558}
559
560
561static attrval_t pwd_to_group(struct passwd *pwd)
562{
563 attrval_t r;
564 struct group *grp = wb_aix_getgrgid(pwd->pw_gid);
565
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);
572 }
573
574 return r;
575}
576
577static attrval_t pwd_to_groupsids(struct passwd *pwd)
578{
579 attrval_t r;
580 char *s, *p;
581
582 if ( (s = wb_aix_getgrset(pwd->pw_name)) == NULL ) {
583 r.attr_flag = EINVAL;
584 return r;
585 }
586
587 if ( (p = malloc(strlen(s)+2)) == NULL ) {
588 r.attr_flag = ENOMEM;
589 return r;
590 }
591
592 strcpy(p, s);
593 replace_commas(p);
594 free(s);
595
596 r.attr_un.au_char = p;
597
598 return r;
599}
600
601static attrval_t pwd_to_sid(struct passwd *pwd)
602{
603 struct winbindd_request request;
604 struct winbindd_response response;
605 attrval_t r;
606
607 ZERO_STRUCT(request);
608 ZERO_STRUCT(response);
609
610 request.data.uid = pwd->pw_uid;
611
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);
619 }
620
621 return r;
622}
623
624static int wb_aix_user_attrib(const char *key, char *attributes[],
625 attrval_t results[], int size)
626{
627 struct passwd *pwd;
628 int i;
629
630 pwd = wb_aix_getpwnam(key);
631 if (!pwd) {
632 errno = ENOENT;
633 return -1;
634 }
635
636 for (i=0;i<size;i++) {
637 results[i].attr_flag = 0;
638
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;
664 }
665 }
666
667 free_pwd(pwd);
668
669 return 0;
670}
671
672static int wb_aix_group_attrib(const char *key, char *attributes[],
673 attrval_t results[], int size)
674{
675 struct group *grp;
676 int i;
677
678 grp = wb_aix_getgrnam(key);
679 if (!grp) {
680 errno = ENOENT;
681 return -1;
682 }
683
684 for (i=0;i<size;i++) {
685 results[i].attr_flag = 0;
686
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;
694 }
695 }
696
697 free_grp(grp);
698
699 return 0;
700}
701
702
703/*
704 called for user/group enumerations
705*/
706static int wb_aix_getentry(char *key, char *table, char *attributes[],
707 attrval_t results[], int size)
708{
709 logit("Got getentry with key='%s' table='%s' size=%d attributes[0]='%s'\n",
710 key, table, size, attributes[0]);
711
712 if (strcmp(key, "ALL") == 0 &&
713 strcmp(table, "user") == 0) {
714 return wb_aix_lsuser(attributes, results, size);
715 }
716
717 if (strcmp(key, "ALL") == 0 &&
718 strcmp(table, "group") == 0) {
719 return wb_aix_lsgroup(attributes, results, size);
720 }
721
722 if (strcmp(table, "user") == 0) {
723 return wb_aix_user_attrib(key, attributes, results, size);
724 }
725
726 if (strcmp(table, "group") == 0) {
727 return wb_aix_group_attrib(key, attributes, results, size);
728 }
729
730 logit("Unknown getentry operation key='%s' table='%s'\n", key, table);
731
732 errno = ENOSYS;
733 return -1;
734}
735
736
737
738/*
739 called to start the backend
740*/
741static void *wb_aix_open(const char *name, const char *domain, int mode, char *options)
742{
743 if (strstr(options, "debug")) {
744 debug_enabled = 1;
745 }
746 logit("open name='%s' mode=%d domain='%s' options='%s'\n", name, domain,
747 mode, options);
748 return NULL;
749}
750
751static void wb_aix_close(void *token)
752{
753 logit("close\n");
754 return;
755}
756
757#ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_ATTRLIST
758/*
759 return a list of additional attributes supported by the backend
760*/
761static attrlist_t **wb_aix_attrlist(void)
762{
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. */
766
767 attrlist_t **ret = NULL;
768 attrlist_t *offset = NULL;
769 int i;
770 int n;
771 size_t size;
772
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},
791
792 /* group attributes */
793 {S_ID, AL_GROUPATTR, SEC_INT}
794 };
795
796 logit("method attrlist called\n");
797
798 n = sizeof(attr_list) / sizeof(struct attr_types);
799 size = (n*sizeof(attrlist_t *));
800
801 if ( (ret = malloc( size )) == NULL ) {
802 errno = ENOMEM;
803 return NULL;
804 }
805
806 /* offset to where the structures start in the buffer */
807
808 offset = (attrlist_t *)(ret + n);
809
810 /* now loop over the user_attr_list[] array and add
811 all the members */
812
813 for ( i=0; i<n; i++ ) {
814 attrlist_t *a = malloc(sizeof(attrlist_t));
815
816 if ( !a ) {
817 /* this is bad. Just bail */
818 return NULL;
819 }
820
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;
824
825 ret[i] = a;
826 }
827 ret[n] = NULL;
828
829 return ret;
830}
831#endif
832
833
834/*
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
837*/
838static int wb_aix_normalize(char *longname, char *shortname)
839{
840 struct passwd *pwd;
841
842 logit("normalize '%s'\n", longname);
843
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;
849 }
850
851 pwd = wb_aix_getpwnam(longname);
852 if (!pwd) {
853 errno = ENOENT;
854 return 0;
855 }
856
857 sprintf(shortname, "%c%07u", WB_AIX_ENCODED, pwd->pw_uid);
858
859 free_pwd(pwd);
860
861 return 1;
862}
863
864
865/*
866 authenticate a user
867 */
868static int wb_aix_authenticate(char *user, char *pass,
869 int *reenter, char **message)
870{
871 struct winbindd_request request;
872 struct winbindd_response response;
873 NSS_STATUS result;
874 char *r_user = user;
875
876 logit("authenticate '%s' response='%s'\n", user, pass);
877
878 *reenter = 0;
879 *message = NULL;
880
881 /* Send off request */
882 ZERO_STRUCT(request);
883 ZERO_STRUCT(response);
884
885 if (*user == WB_AIX_ENCODED) {
886 r_user = decode_user(r_user);
887 if (!r_user) {
888 return AUTH_NOTFOUND;
889 }
890 }
891
892 STRCPY_RET(request.data.auth.user, r_user);
893 STRCPY_RET(request.data.auth.pass, pass);
894
895 if (*user == WB_AIX_ENCODED) {
896 free(r_user);
897 }
898
899 result = winbindd_request_response(NULL, WINBINDD_PAM_AUTH,
900 &request, &response);
901
902 winbindd_free_response(&response);
903
904 logit("auth result %d for '%s'\n", result, user);
905
906 if (result == NSS_STATUS_SUCCESS) {
907 errno = 0;
908 return AUTH_SUCCESS;
909 }
910
911 return AUTH_FAILURE;
912}
913
914
915/*
916 change a user password
917*/
918static int wb_aix_chpass(char *user, char *oldpass, char *newpass, char **message)
919{
920 struct winbindd_request request;
921 struct winbindd_response response;
922 NSS_STATUS result;
923 char *r_user = user;
924
925 if (*user == WB_AIX_ENCODED) {
926 r_user = decode_user(r_user);
927 if (!r_user) {
928 errno = ENOENT;
929 return -1;
930 }
931 }
932
933 logit("chpass '%s' old='%s' new='%s'\n", r_user, oldpass, newpass);
934
935 *message = NULL;
936
937 /* Send off request */
938 ZERO_STRUCT(request);
939 ZERO_STRUCT(response);
940
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);
944
945 if (*user == WB_AIX_ENCODED) {
946 free(r_user);
947 }
948
949 result = winbindd_request_response(NULL, WINBINDD_PAM_CHAUTHTOK,
950 &request, &response);
951
952 winbindd_free_response(&response);
953
954 if (result == NSS_STATUS_SUCCESS) {
955 errno = 0;
956 return 0;
957 }
958
959 errno = EINVAL;
960 return -1;
961}
962
963/*
964 don't do any password strength testing for now
965*/
966static int wb_aix_passwdrestrictions(char *user, char *newpass, char *oldpass,
967 char **message)
968{
969 logit("passwdresrictions called for '%s'\n", user);
970 return 0;
971}
972
973
974static int wb_aix_passwdexpired(char *user, char **message)
975{
976 logit("passwdexpired '%s'\n", user);
977 /* we should check the account bits here */
978 return 0;
979}
980
981
982/*
983 we can't return a crypt() password
984*/
985static char *wb_aix_getpasswd(char *user)
986{
987 logit("getpasswd '%s'\n", user);
988 errno = ENOSYS;
989 return NULL;
990}
991
992/*
993 this is called to update things like the last login time. We don't
994 currently pass this onto the DC
995*/
996static int wb_aix_putentry(char *key, char *table, char *attributes[],
997 attrval_t values[], int size)
998{
999 logit("putentry key='%s' table='%s' attrib='%s'\n",
1000 key, table, size>=1?attributes[0]:"<null>");
1001 errno = ENOSYS;
1002 return -1;
1003}
1004
1005static int wb_aix_commit(char *key, char *table)
1006{
1007 logit("commit key='%s' table='%s'\n");
1008 errno = ENOSYS;
1009 return -1;
1010}
1011
1012static int wb_aix_getgrusers(char *group, void *result, int type, int *size)
1013{
1014 logit("getgrusers group='%s'\n", group);
1015 errno = ENOSYS;
1016 return -1;
1017}
1018
1019
1020#define DECL_METHOD(x) \
1021int method_ ## x(void) \
1022{ \
1023 logit("UNIMPLEMENTED METHOD '%s'\n", #x); \
1024 errno = EINVAL; \
1025 return -1; \
1026}
1027
1028#if LOG_UNIMPLEMENTED_CALLS
1029DECL_METHOD(delgroup);
1030DECL_METHOD(deluser);
1031DECL_METHOD(newgroup);
1032DECL_METHOD(newuser);
1033DECL_METHOD(putgrent);
1034DECL_METHOD(putgrusers);
1035DECL_METHOD(putpwent);
1036DECL_METHOD(lock);
1037DECL_METHOD(unlock);
1038DECL_METHOD(getcred);
1039DECL_METHOD(setcred);
1040DECL_METHOD(deletecred);
1041#endif
1042
1043int wb_aix_init(struct secmethod_table *methods)
1044{
1045 ZERO_STRUCTP(methods);
1046
1047#ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_VERSION
1048 methods->method_version = SECMETHOD_VERSION_520;
1049#endif
1050
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
1072
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
1087
1088 return AUTH_SUCCESS;
1089}
Note: See TracBrowser for help on using the repository browser.