source: branches/samba-3.0/source/nsswitch/winbind_nss_aix.c

Last change on this file was 165, checked in by Paul Smedley, 17 years ago

Add 'missing' 3.0.34 diffs

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