source: branches/samba-3.3.x/source/nsswitch/winbind_nss_aix.c

Last change on this file was 206, checked in by Herwig Bauernfeind, 16 years ago

Import Samba 3.3 branch at 3.0.0 level (psmedley's port)

File size: 22.8 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 errno = ENOMEM;
241 return NULL;
242 }
243
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;
251 }
252 result->gr_mem[i] = strdup(name);
253 i++;
254 }
255
256 /* Terminate list */
257 result->gr_mem[i] = NULL;
258
259 return result;
260}
261
262
263
264/* take a group id and return a filled struct group */
265static struct group *wb_aix_getgrgid(gid_t gid)
266{
267 struct winbindd_response response;
268 struct winbindd_request request;
269 struct group *grp;
270 NSS_STATUS ret;
271
272 logit("getgrgid %d\n", gid);
273
274 ZERO_STRUCT(response);
275 ZERO_STRUCT(request);
276
277 request.data.gid = gid;
278
279 ret = winbindd_request_response(WINBINDD_GETGRGID, &request, &response);
280
281 logit("getgrgid ret=%d\n", ret);
282
283 HANDLE_ERRORS(ret);
284
285 grp = fill_grent(&response.data.gr, response.extra_data.data);
286
287 winbindd_free_response(&response);
288
289 return grp;
290}
291
292/* take a group name and return a filled struct group */
293static struct group *wb_aix_getgrnam(const char *name)
294{
295 struct winbindd_response response;
296 struct winbindd_request request;
297 NSS_STATUS ret;
298 struct group *grp;
299
300 if (*name == WB_AIX_ENCODED) {
301 return wb_aix_getgrgid(decode_id(name));
302 }
303
304 logit("getgrnam '%s'\n", name);
305
306 ZERO_STRUCT(response);
307 ZERO_STRUCT(request);
308
309 STRCPY_RETNULL(request.data.groupname, name);
310
311 ret = winbindd_request_response(WINBINDD_GETGRNAM, &request, &response);
312
313 HANDLE_ERRORS(ret);
314
315 grp = fill_grent(&response.data.gr, response.extra_data.data);
316
317 winbindd_free_response(&response);
318
319 return grp;
320}
321
322
323/* this call doesn't have to fill in the gr_mem, but we do anyway
324 for simplicity */
325static struct group *wb_aix_getgracct(void *id, int type)
326{
327 if (type == 1) {
328 return wb_aix_getgrnam((char *)id);
329 }
330 if (type == 0) {
331 return wb_aix_getgrgid(*(int *)id);
332 }
333 errno = EINVAL;
334 return NULL;
335}
336
337
338/* take a username and return a string containing a comma-separated
339 list of group id numbers to which the user belongs */
340static char *wb_aix_getgrset(char *user)
341{
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;
350
351 if (*user == WB_AIX_ENCODED) {
352 r_user = decode_user(r_user);
353 if (!r_user) {
354 errno = ENOENT;
355 return NULL;
356 }
357 }
358
359 logit("getgrset '%s'\n", r_user);
360
361 ZERO_STRUCT(response);
362 ZERO_STRUCT(request);
363
364 STRCPY_RETNULL(request.data.username, r_user);
365
366 if (*user == WB_AIX_ENCODED) {
367 free(r_user);
368 }
369
370 ret = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response);
371
372 HANDLE_ERRORS(ret);
373
374 num_gids = response.data.num_entries;
375 gid_list = (gid_t *)response.extra_data.data;
376
377 /* allocate a space large enough to contruct the string */
378 tmpbuf = malloc(num_gids*12);
379 if (!tmpbuf) {
380 return NULL;
381 }
382
383 for (idx=i=0; i < num_gids-1; i++) {
384 idx += sprintf(tmpbuf+idx, "%u,", gid_list[i]);
385 }
386 idx += sprintf(tmpbuf+idx, "%u", gid_list[i]);
387
388 winbindd_free_response(&response);
389
390 return tmpbuf;
391}
392
393
394/* take a uid and return a filled struct passwd */
395static struct passwd *wb_aix_getpwuid(uid_t uid)
396{
397 struct winbindd_response response;
398 struct winbindd_request request;
399 NSS_STATUS ret;
400 struct passwd *pwd;
401
402 logit("getpwuid '%d'\n", uid);
403
404 ZERO_STRUCT(response);
405 ZERO_STRUCT(request);
406
407 request.data.uid = uid;
408
409 ret = winbindd_request_response(WINBINDD_GETPWUID, &request, &response);
410
411 HANDLE_ERRORS(ret);
412
413 pwd = fill_pwent(&response.data.pw);
414
415 winbindd_free_response(&response);
416
417 logit("getpwuid gave ptr %p\n", pwd);
418
419 return pwd;
420}
421
422
423/* take a username and return a filled struct passwd */
424static struct passwd *wb_aix_getpwnam(const char *name)
425{
426 struct winbindd_response response;
427 struct winbindd_request request;
428 NSS_STATUS ret;
429 struct passwd *pwd;
430
431 if (*name == WB_AIX_ENCODED) {
432 return wb_aix_getpwuid(decode_id(name));
433 }
434
435 logit("getpwnam '%s'\n", name);
436
437 ZERO_STRUCT(response);
438 ZERO_STRUCT(request);
439
440 STRCPY_RETNULL(request.data.username, name);
441
442 ret = winbindd_request_response(WINBINDD_GETPWNAM, &request, &response);
443
444 HANDLE_ERRORS(ret);
445
446 pwd = fill_pwent(&response.data.pw);
447
448 winbindd_free_response(&response);
449
450 logit("getpwnam gave ptr %p\n", pwd);
451
452 return pwd;
453}
454
455/*
456 list users
457*/
458static int wb_aix_lsuser(char *attributes[], attrval_t results[], int size)
459{
460 NSS_STATUS ret;
461 struct winbindd_request request;
462 struct winbindd_response response;
463 int len;
464 char *s;
465
466 if (size != 1 || strcmp(attributes[0], S_USERS) != 0) {
467 logit("invalid lsuser op\n");
468 errno = EINVAL;
469 return -1;
470 }
471
472 ZERO_STRUCT(request);
473 ZERO_STRUCT(response);
474
475 ret = winbindd_request_response(WINBINDD_LIST_USERS, &request, &response);
476 if (ret != 0) {
477 errno = EINVAL;
478 return -1;
479 }
480
481 len = strlen(response.extra_data.data);
482
483 s = malloc(len+2);
484 if (!s) {
485 winbindd_free_response(&response);
486 errno = ENOMEM;
487 return -1;
488 }
489
490 memcpy(s, response.extra_data.data, len+1);
491
492 replace_commas(s);
493
494 results[0].attr_un.au_char = s;
495 results[0].attr_flag = 0;
496
497 winbindd_free_response(&response);
498
499 return 0;
500}
501
502
503/*
504 list groups
505*/
506static int wb_aix_lsgroup(char *attributes[], attrval_t results[], int size)
507{
508 NSS_STATUS ret;
509 struct winbindd_request request;
510 struct winbindd_response response;
511 int len;
512 char *s;
513
514 if (size != 1 || strcmp(attributes[0], S_GROUPS) != 0) {
515 logit("invalid lsgroup op\n");
516 errno = EINVAL;
517 return -1;
518 }
519
520 ZERO_STRUCT(request);
521 ZERO_STRUCT(response);
522
523 ret = winbindd_request_response(WINBINDD_LIST_GROUPS, &request, &response);
524 if (ret != 0) {
525 errno = EINVAL;
526 return -1;
527 }
528
529 len = strlen(response.extra_data.data);
530
531 s = malloc(len+2);
532 if (!s) {
533 winbindd_free_response(&response);
534 errno = ENOMEM;
535 return -1;
536 }
537
538 memcpy(s, response.extra_data.data, len+1);
539
540 replace_commas(s);
541
542 results[0].attr_un.au_char = s;
543 results[0].attr_flag = 0;
544
545 winbindd_free_response(&response);
546
547 return 0;
548}
549
550
551static attrval_t pwd_to_group(struct passwd *pwd)
552{
553 attrval_t r;
554 struct group *grp = wb_aix_getgrgid(pwd->pw_gid);
555
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);
562 }
563
564 return r;
565}
566
567static attrval_t pwd_to_groupsids(struct passwd *pwd)
568{
569 attrval_t r;
570 char *s, *p;
571
572 if ( (s = wb_aix_getgrset(pwd->pw_name)) == NULL ) {
573 r.attr_flag = EINVAL;
574 return r;
575 }
576
577 if ( (p = malloc(strlen(s)+2)) == NULL ) {
578 r.attr_flag = ENOMEM;
579 return r;
580 }
581
582 strcpy(p, s);
583 replace_commas(p);
584 free(s);
585
586 r.attr_un.au_char = p;
587
588 return r;
589}
590
591static attrval_t pwd_to_sid(struct passwd *pwd)
592{
593 struct winbindd_request request;
594 struct winbindd_response response;
595 attrval_t r;
596
597 ZERO_STRUCT(request);
598 ZERO_STRUCT(response);
599
600 request.data.uid = pwd->pw_uid;
601
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);
608 }
609
610 return r;
611}
612
613static int wb_aix_user_attrib(const char *key, char *attributes[],
614 attrval_t results[], int size)
615{
616 struct passwd *pwd;
617 int i;
618
619 pwd = wb_aix_getpwnam(key);
620 if (!pwd) {
621 errno = ENOENT;
622 return -1;
623 }
624
625 for (i=0;i<size;i++) {
626 results[i].attr_flag = 0;
627
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;
653 }
654 }
655
656 free_pwd(pwd);
657
658 return 0;
659}
660
661static int wb_aix_group_attrib(const char *key, char *attributes[],
662 attrval_t results[], int size)
663{
664 struct group *grp;
665 int i;
666
667 grp = wb_aix_getgrnam(key);
668 if (!grp) {
669 errno = ENOENT;
670 return -1;
671 }
672
673 for (i=0;i<size;i++) {
674 results[i].attr_flag = 0;
675
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;
683 }
684 }
685
686 free_grp(grp);
687
688 return 0;
689}
690
691
692/*
693 called for user/group enumerations
694*/
695static int wb_aix_getentry(char *key, char *table, char *attributes[],
696 attrval_t results[], int size)
697{
698 logit("Got getentry with key='%s' table='%s' size=%d attributes[0]='%s'\n",
699 key, table, size, attributes[0]);
700
701 if (strcmp(key, "ALL") == 0 &&
702 strcmp(table, "user") == 0) {
703 return wb_aix_lsuser(attributes, results, size);
704 }
705
706 if (strcmp(key, "ALL") == 0 &&
707 strcmp(table, "group") == 0) {
708 return wb_aix_lsgroup(attributes, results, size);
709 }
710
711 if (strcmp(table, "user") == 0) {
712 return wb_aix_user_attrib(key, attributes, results, size);
713 }
714
715 if (strcmp(table, "group") == 0) {
716 return wb_aix_group_attrib(key, attributes, results, size);
717 }
718
719 logit("Unknown getentry operation key='%s' table='%s'\n", key, table);
720
721 errno = ENOSYS;
722 return -1;
723}
724
725
726
727/*
728 called to start the backend
729*/
730static void *wb_aix_open(const char *name, const char *domain, int mode, char *options)
731{
732 if (strstr(options, "debug")) {
733 debug_enabled = 1;
734 }
735 logit("open name='%s' mode=%d domain='%s' options='%s'\n", name, domain,
736 mode, options);
737 return NULL;
738}
739
740static void wb_aix_close(void *token)
741{
742 logit("close\n");
743 return;
744}
745
746#ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_ATTRLIST
747/*
748 return a list of additional attributes supported by the backend
749*/
750static attrlist_t **wb_aix_attrlist(void)
751{
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. */
755
756 attrlist_t **ret = NULL;
757 attrlist_t *offset = NULL;
758 int i;
759 int n;
760 size_t size;
761
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},
780
781 /* group attributes */
782 {S_ID, AL_GROUPATTR, SEC_INT}
783 };
784
785 logit("method attrlist called\n");
786
787 n = sizeof(attr_list) / sizeof(struct attr_types);
788 size = (n*sizeof(attrlist_t *));
789
790 if ( (ret = malloc( size )) == NULL ) {
791 errno = ENOMEM;
792 return NULL;
793 }
794
795 /* offset to where the structures start in the buffer */
796
797 offset = (attrlist_t *)(ret + n);
798
799 /* now loop over the user_attr_list[] array and add
800 all the members */
801
802 for ( i=0; i<n; i++ ) {
803 attrlist_t *a = malloc(sizeof(attrlist_t));
804
805 if ( !a ) {
806 /* this is bad. Just bail */
807 return NULL;
808 }
809
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;
813
814 ret[i] = a;
815 }
816 ret[n] = NULL;
817
818 return ret;
819}
820#endif
821
822
823/*
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
826*/
827static int wb_aix_normalize(char *longname, char *shortname)
828{
829 struct passwd *pwd;
830
831 logit("normalize '%s'\n", longname);
832
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;
838 }
839
840 pwd = wb_aix_getpwnam(longname);
841 if (!pwd) {
842 errno = ENOENT;
843 return 0;
844 }
845
846 sprintf(shortname, "%c%07u", WB_AIX_ENCODED, pwd->pw_uid);
847
848 free_pwd(pwd);
849
850 return 1;
851}
852
853
854/*
855 authenticate a user
856 */
857static int wb_aix_authenticate(char *user, char *pass,
858 int *reenter, char **message)
859{
860 struct winbindd_request request;
861 struct winbindd_response response;
862 NSS_STATUS result;
863 char *r_user = user;
864
865 logit("authenticate '%s' response='%s'\n", user, pass);
866
867 *reenter = 0;
868 *message = NULL;
869
870 /* Send off request */
871 ZERO_STRUCT(request);
872 ZERO_STRUCT(response);
873
874 if (*user == WB_AIX_ENCODED) {
875 r_user = decode_user(r_user);
876 if (!r_user) {
877 return AUTH_NOTFOUND;
878 }
879 }
880
881 STRCPY_RET(request.data.auth.user, r_user);
882 STRCPY_RET(request.data.auth.pass, pass);
883
884 if (*user == WB_AIX_ENCODED) {
885 free(r_user);
886 }
887
888 result = winbindd_request_response(WINBINDD_PAM_AUTH, &request, &response);
889
890 winbindd_free_response(&response);
891
892 logit("auth result %d for '%s'\n", result, user);
893
894 if (result == NSS_STATUS_SUCCESS) {
895 errno = 0;
896 return AUTH_SUCCESS;
897 }
898
899 return AUTH_FAILURE;
900}
901
902
903/*
904 change a user password
905*/
906static int wb_aix_chpass(char *user, char *oldpass, char *newpass, char **message)
907{
908 struct winbindd_request request;
909 struct winbindd_response response;
910 NSS_STATUS result;
911 char *r_user = user;
912
913 if (*user == WB_AIX_ENCODED) {
914 r_user = decode_user(r_user);
915 if (!r_user) {
916 errno = ENOENT;
917 return -1;
918 }
919 }
920
921 logit("chpass '%s' old='%s' new='%s'\n", r_user, oldpass, newpass);
922
923 *message = NULL;
924
925 /* Send off request */
926 ZERO_STRUCT(request);
927 ZERO_STRUCT(response);
928
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);
932
933 if (*user == WB_AIX_ENCODED) {
934 free(r_user);
935 }
936
937 result = winbindd_request_response(WINBINDD_PAM_CHAUTHTOK, &request, &response);
938
939 winbindd_free_response(&response);
940
941 if (result == NSS_STATUS_SUCCESS) {
942 errno = 0;
943 return 0;
944 }
945
946 errno = EINVAL;
947 return -1;
948}
949
950/*
951 don't do any password strength testing for now
952*/
953static int wb_aix_passwdrestrictions(char *user, char *newpass, char *oldpass,
954 char **message)
955{
956 logit("passwdresrictions called for '%s'\n", user);
957 return 0;
958}
959
960
961static int wb_aix_passwdexpired(char *user, char **message)
962{
963 logit("passwdexpired '%s'\n", user);
964 /* we should check the account bits here */
965 return 0;
966}
967
968
969/*
970 we can't return a crypt() password
971*/
972static char *wb_aix_getpasswd(char *user)
973{
974 logit("getpasswd '%s'\n", user);
975 errno = ENOSYS;
976 return NULL;
977}
978
979/*
980 this is called to update things like the last login time. We don't
981 currently pass this onto the DC
982*/
983static int wb_aix_putentry(char *key, char *table, char *attributes[],
984 attrval_t values[], int size)
985{
986 logit("putentry key='%s' table='%s' attrib='%s'\n",
987 key, table, size>=1?attributes[0]:"<null>");
988 errno = ENOSYS;
989 return -1;
990}
991
992static int wb_aix_commit(char *key, char *table)
993{
994 logit("commit key='%s' table='%s'\n");
995 errno = ENOSYS;
996 return -1;
997}
998
999static int wb_aix_getgrusers(char *group, void *result, int type, int *size)
1000{
1001 logit("getgrusers group='%s'\n", group);
1002 errno = ENOSYS;
1003 return -1;
1004}
1005
1006
1007#define DECL_METHOD(x) \
1008int method_ ## x(void) \
1009{ \
1010 logit("UNIMPLEMENTED METHOD '%s'\n", #x); \
1011 errno = EINVAL; \
1012 return -1; \
1013}
1014
1015#if LOG_UNIMPLEMENTED_CALLS
1016DECL_METHOD(delgroup);
1017DECL_METHOD(deluser);
1018DECL_METHOD(newgroup);
1019DECL_METHOD(newuser);
1020DECL_METHOD(putgrent);
1021DECL_METHOD(putgrusers);
1022DECL_METHOD(putpwent);
1023DECL_METHOD(lock);
1024DECL_METHOD(unlock);
1025DECL_METHOD(getcred);
1026DECL_METHOD(setcred);
1027DECL_METHOD(deletecred);
1028#endif
1029
1030int wb_aix_init(struct secmethod_table *methods)
1031{
1032 ZERO_STRUCTP(methods);
1033
1034#ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_VERSION
1035 methods->method_version = SECMETHOD_VERSION_520;
1036#endif
1037
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
1059
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
1074
1075 return AUTH_SUCCESS;
1076}
1077
Note: See TracBrowser for help on using the repository browser.