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

Last change on this file was 414, checked in by Herwig Bauernfeind, 15 years ago

Samba 3.5.0: Initial import

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 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(WINBINDD_GETGRGID, &request, &response);
283
284 logit("getgrgid ret=%d\n", ret);
285
286 HANDLE_ERRORS(ret);
287
288 grp = fill_grent(&response.data.gr, response.extra_data.data);
289
290 winbindd_free_response(&response);
291
292 return grp;
293}
294
295/* take a group name and return a filled struct group */
296static struct group *wb_aix_getgrnam(const char *name)
297{
298 struct winbindd_response response;
299 struct winbindd_request request;
300 NSS_STATUS ret;
301 struct group *grp;
302
303 if (*name == WB_AIX_ENCODED) {
304 return wb_aix_getgrgid(decode_id(name));
305 }
306
307 logit("getgrnam '%s'\n", name);
308
309 ZERO_STRUCT(response);
310 ZERO_STRUCT(request);
311
312 STRCPY_RETNULL(request.data.groupname, name);
313
314 ret = winbindd_request_response(WINBINDD_GETGRNAM, &request, &response);
315
316 HANDLE_ERRORS(ret);
317
318 grp = fill_grent(&response.data.gr, response.extra_data.data);
319
320 winbindd_free_response(&response);
321
322 return grp;
323}
324
325
326/* this call doesn't have to fill in the gr_mem, but we do anyway
327 for simplicity */
328static struct group *wb_aix_getgracct(void *id, int type)
329{
330 if (type == 1) {
331 return wb_aix_getgrnam((char *)id);
332 }
333 if (type == 0) {
334 return wb_aix_getgrgid(*(int *)id);
335 }
336 errno = EINVAL;
337 return NULL;
338}
339
340
341/* take a username and return a string containing a comma-separated
342 list of group id numbers to which the user belongs */
343static char *wb_aix_getgrset(char *user)
344{
345 struct winbindd_response response;
346 struct winbindd_request request;
347 NSS_STATUS ret;
348 int i, idx;
349 char *tmpbuf;
350 int num_gids;
351 gid_t *gid_list;
352 char *r_user = user;
353
354 if (*user == WB_AIX_ENCODED) {
355 r_user = decode_user(r_user);
356 if (!r_user) {
357 errno = ENOENT;
358 return NULL;
359 }
360 }
361
362 logit("getgrset '%s'\n", r_user);
363
364 ZERO_STRUCT(response);
365 ZERO_STRUCT(request);
366
367 STRCPY_RETNULL(request.data.username, r_user);
368
369 if (*user == WB_AIX_ENCODED) {
370 free(r_user);
371 }
372
373 ret = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response);
374
375 HANDLE_ERRORS(ret);
376
377 num_gids = response.data.num_entries;
378 gid_list = (gid_t *)response.extra_data.data;
379
380 /* allocate a space large enough to contruct the string */
381 tmpbuf = malloc(num_gids*12);
382 if (!tmpbuf) {
383 return NULL;
384 }
385
386 for (idx=i=0; i < num_gids-1; i++) {
387 idx += sprintf(tmpbuf+idx, "%u,", gid_list[i]);
388 }
389 idx += sprintf(tmpbuf+idx, "%u", gid_list[i]);
390
391 winbindd_free_response(&response);
392
393 return tmpbuf;
394}
395
396
397/* take a uid and return a filled struct passwd */
398static struct passwd *wb_aix_getpwuid(uid_t uid)
399{
400 struct winbindd_response response;
401 struct winbindd_request request;
402 NSS_STATUS ret;
403 struct passwd *pwd;
404
405 logit("getpwuid '%d'\n", uid);
406
407 ZERO_STRUCT(response);
408 ZERO_STRUCT(request);
409
410 request.data.uid = uid;
411
412 ret = winbindd_request_response(WINBINDD_GETPWUID, &request, &response);
413
414 HANDLE_ERRORS(ret);
415
416 pwd = fill_pwent(&response.data.pw);
417
418 winbindd_free_response(&response);
419
420 logit("getpwuid gave ptr %p\n", pwd);
421
422 return pwd;
423}
424
425
426/* take a username and return a filled struct passwd */
427static struct passwd *wb_aix_getpwnam(const char *name)
428{
429 struct winbindd_response response;
430 struct winbindd_request request;
431 NSS_STATUS ret;
432 struct passwd *pwd;
433
434 if (*name == WB_AIX_ENCODED) {
435 return wb_aix_getpwuid(decode_id(name));
436 }
437
438 logit("getpwnam '%s'\n", name);
439
440 ZERO_STRUCT(response);
441 ZERO_STRUCT(request);
442
443 STRCPY_RETNULL(request.data.username, name);
444
445 ret = winbindd_request_response(WINBINDD_GETPWNAM, &request, &response);
446
447 HANDLE_ERRORS(ret);
448
449 pwd = fill_pwent(&response.data.pw);
450
451 winbindd_free_response(&response);
452
453 logit("getpwnam gave ptr %p\n", pwd);
454
455 return pwd;
456}
457
458/*
459 list users
460*/
461static int wb_aix_lsuser(char *attributes[], attrval_t results[], int size)
462{
463 NSS_STATUS ret;
464 struct winbindd_request request;
465 struct winbindd_response response;
466 int len;
467 char *s;
468
469 if (size != 1 || strcmp(attributes[0], S_USERS) != 0) {
470 logit("invalid lsuser op\n");
471 errno = EINVAL;
472 return -1;
473 }
474
475 ZERO_STRUCT(request);
476 ZERO_STRUCT(response);
477
478 ret = winbindd_request_response(WINBINDD_LIST_USERS, &request, &response);
479 if (ret != 0) {
480 errno = EINVAL;
481 return -1;
482 }
483
484 len = strlen(response.extra_data.data);
485
486 s = malloc(len+2);
487 if (!s) {
488 winbindd_free_response(&response);
489 errno = ENOMEM;
490 return -1;
491 }
492
493 memcpy(s, response.extra_data.data, len+1);
494
495 replace_commas(s);
496
497 results[0].attr_un.au_char = s;
498 results[0].attr_flag = 0;
499
500 winbindd_free_response(&response);
501
502 return 0;
503}
504
505
506/*
507 list groups
508*/
509static int wb_aix_lsgroup(char *attributes[], attrval_t results[], int size)
510{
511 NSS_STATUS ret;
512 struct winbindd_request request;
513 struct winbindd_response response;
514 int len;
515 char *s;
516
517 if (size != 1 || strcmp(attributes[0], S_GROUPS) != 0) {
518 logit("invalid lsgroup op\n");
519 errno = EINVAL;
520 return -1;
521 }
522
523 ZERO_STRUCT(request);
524 ZERO_STRUCT(response);
525
526 ret = winbindd_request_response(WINBINDD_LIST_GROUPS, &request, &response);
527 if (ret != 0) {
528 errno = EINVAL;
529 return -1;
530 }
531
532 len = strlen(response.extra_data.data);
533
534 s = malloc(len+2);
535 if (!s) {
536 winbindd_free_response(&response);
537 errno = ENOMEM;
538 return -1;
539 }
540
541 memcpy(s, response.extra_data.data, len+1);
542
543 replace_commas(s);
544
545 results[0].attr_un.au_char = s;
546 results[0].attr_flag = 0;
547
548 winbindd_free_response(&response);
549
550 return 0;
551}
552
553
554static attrval_t pwd_to_group(struct passwd *pwd)
555{
556 attrval_t r;
557 struct group *grp = wb_aix_getgrgid(pwd->pw_gid);
558
559 if (!grp) {
560 r.attr_flag = EINVAL;
561 } else {
562 r.attr_flag = 0;
563 r.attr_un.au_char = strdup(grp->gr_name);
564 free_grp(grp);
565 }
566
567 return r;
568}
569
570static attrval_t pwd_to_groupsids(struct passwd *pwd)
571{
572 attrval_t r;
573 char *s, *p;
574
575 if ( (s = wb_aix_getgrset(pwd->pw_name)) == NULL ) {
576 r.attr_flag = EINVAL;
577 return r;
578 }
579
580 if ( (p = malloc(strlen(s)+2)) == NULL ) {
581 r.attr_flag = ENOMEM;
582 return r;
583 }
584
585 strcpy(p, s);
586 replace_commas(p);
587 free(s);
588
589 r.attr_un.au_char = p;
590
591 return r;
592}
593
594static attrval_t pwd_to_sid(struct passwd *pwd)
595{
596 struct winbindd_request request;
597 struct winbindd_response response;
598 attrval_t r;
599
600 ZERO_STRUCT(request);
601 ZERO_STRUCT(response);
602
603 request.data.uid = pwd->pw_uid;
604
605 if (winbindd_request_response(WINBINDD_UID_TO_SID, &request, &response) !=
606 NSS_STATUS_SUCCESS) {
607 r.attr_flag = ENOENT;
608 } else {
609 r.attr_flag = 0;
610 r.attr_un.au_char = strdup(response.data.sid.sid);
611 }
612
613 return r;
614}
615
616static int wb_aix_user_attrib(const char *key, char *attributes[],
617 attrval_t results[], int size)
618{
619 struct passwd *pwd;
620 int i;
621
622 pwd = wb_aix_getpwnam(key);
623 if (!pwd) {
624 errno = ENOENT;
625 return -1;
626 }
627
628 for (i=0;i<size;i++) {
629 results[i].attr_flag = 0;
630
631 if (strcmp(attributes[i], S_ID) == 0) {
632 results[i].attr_un.au_int = pwd->pw_uid;
633#ifdef _AIXVERSION_530
634 } else if (strcmp(attributes[i], S_PGID) == 0) {
635 results[i].attr_un.au_int = pwd->pw_gid;
636#endif
637 } else if (strcmp(attributes[i], S_PWD) == 0) {
638 results[i].attr_un.au_char = strdup(pwd->pw_passwd);
639 } else if (strcmp(attributes[i], S_HOME) == 0) {
640 results[i].attr_un.au_char = strdup(pwd->pw_dir);
641 } else if (strcmp(attributes[i], S_SHELL) == 0) {
642 results[i].attr_un.au_char = strdup(pwd->pw_shell);
643 } else if (strcmp(attributes[i], S_REGISTRY) == 0) {
644 results[i].attr_un.au_char = strdup("WINBIND");
645 } else if (strcmp(attributes[i], S_GECOS) == 0) {
646 results[i].attr_un.au_char = strdup(pwd->pw_gecos);
647 } else if (strcmp(attributes[i], S_PGRP) == 0) {
648 results[i] = pwd_to_group(pwd);
649 } else if (strcmp(attributes[i], S_GROUPS) == 0) {
650 results[i] = pwd_to_groupsids(pwd);
651 } else if (strcmp(attributes[i], "SID") == 0) {
652 results[i] = pwd_to_sid(pwd);
653 } else {
654 logit("Unknown user attribute '%s'\n", attributes[i]);
655 results[i].attr_flag = EINVAL;
656 }
657 }
658
659 free_pwd(pwd);
660
661 return 0;
662}
663
664static int wb_aix_group_attrib(const char *key, char *attributes[],
665 attrval_t results[], int size)
666{
667 struct group *grp;
668 int i;
669
670 grp = wb_aix_getgrnam(key);
671 if (!grp) {
672 errno = ENOENT;
673 return -1;
674 }
675
676 for (i=0;i<size;i++) {
677 results[i].attr_flag = 0;
678
679 if (strcmp(attributes[i], S_PWD) == 0) {
680 results[i].attr_un.au_char = strdup(grp->gr_passwd);
681 } else if (strcmp(attributes[i], S_ID) == 0) {
682 results[i].attr_un.au_int = grp->gr_gid;
683 } else {
684 logit("Unknown group attribute '%s'\n", attributes[i]);
685 results[i].attr_flag = EINVAL;
686 }
687 }
688
689 free_grp(grp);
690
691 return 0;
692}
693
694
695/*
696 called for user/group enumerations
697*/
698static int wb_aix_getentry(char *key, char *table, char *attributes[],
699 attrval_t results[], int size)
700{
701 logit("Got getentry with key='%s' table='%s' size=%d attributes[0]='%s'\n",
702 key, table, size, attributes[0]);
703
704 if (strcmp(key, "ALL") == 0 &&
705 strcmp(table, "user") == 0) {
706 return wb_aix_lsuser(attributes, results, size);
707 }
708
709 if (strcmp(key, "ALL") == 0 &&
710 strcmp(table, "group") == 0) {
711 return wb_aix_lsgroup(attributes, results, size);
712 }
713
714 if (strcmp(table, "user") == 0) {
715 return wb_aix_user_attrib(key, attributes, results, size);
716 }
717
718 if (strcmp(table, "group") == 0) {
719 return wb_aix_group_attrib(key, attributes, results, size);
720 }
721
722 logit("Unknown getentry operation key='%s' table='%s'\n", key, table);
723
724 errno = ENOSYS;
725 return -1;
726}
727
728
729
730/*
731 called to start the backend
732*/
733static void *wb_aix_open(const char *name, const char *domain, int mode, char *options)
734{
735 if (strstr(options, "debug")) {
736 debug_enabled = 1;
737 }
738 logit("open name='%s' mode=%d domain='%s' options='%s'\n", name, domain,
739 mode, options);
740 return NULL;
741}
742
743static void wb_aix_close(void *token)
744{
745 logit("close\n");
746 return;
747}
748
749#ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_ATTRLIST
750/*
751 return a list of additional attributes supported by the backend
752*/
753static attrlist_t **wb_aix_attrlist(void)
754{
755 /* pretty confusing but we are allocating the array of pointers
756 and the structures we'll be pointing to all at once. So
757 you need N+1 pointers and N structures. */
758
759 attrlist_t **ret = NULL;
760 attrlist_t *offset = NULL;
761 int i;
762 int n;
763 size_t size;
764
765 struct attr_types {
766 const char *name;
767 int flags;
768 int type;
769 } attr_list[] = {
770 /* user attributes */
771 {S_ID, AL_USERATTR, SEC_INT},
772 {S_PGRP, AL_USERATTR, SEC_CHAR},
773 {S_HOME, AL_USERATTR, SEC_CHAR},
774 {S_SHELL, AL_USERATTR, SEC_CHAR},
775#ifdef _AIXVERSION_530
776 {S_PGID, AL_USERATTR, SEC_INT},
777#endif
778 {S_GECOS, AL_USERATTR, SEC_CHAR},
779 {S_SHELL, AL_USERATTR, SEC_CHAR},
780 {S_PGRP, AL_USERATTR, SEC_CHAR},
781 {S_GROUPS, AL_USERATTR, SEC_LIST},
782 {"SID", AL_USERATTR, SEC_CHAR},
783
784 /* group attributes */
785 {S_ID, AL_GROUPATTR, SEC_INT}
786 };
787
788 logit("method attrlist called\n");
789
790 n = sizeof(attr_list) / sizeof(struct attr_types);
791 size = (n*sizeof(attrlist_t *));
792
793 if ( (ret = malloc( size )) == NULL ) {
794 errno = ENOMEM;
795 return NULL;
796 }
797
798 /* offset to where the structures start in the buffer */
799
800 offset = (attrlist_t *)(ret + n);
801
802 /* now loop over the user_attr_list[] array and add
803 all the members */
804
805 for ( i=0; i<n; i++ ) {
806 attrlist_t *a = malloc(sizeof(attrlist_t));
807
808 if ( !a ) {
809 /* this is bad. Just bail */
810 return NULL;
811 }
812
813 a->al_name = strdup(attr_list[i].name);
814 a->al_flags = attr_list[i].flags;
815 a->al_type = attr_list[i].type;
816
817 ret[i] = a;
818 }
819 ret[n] = NULL;
820
821 return ret;
822}
823#endif
824
825
826/*
827 turn a long username into a short one. Needed to cope with the 8 char
828 username limit in AIX 5.2 and below
829*/
830static int wb_aix_normalize(char *longname, char *shortname)
831{
832 struct passwd *pwd;
833
834 logit("normalize '%s'\n", longname);
835
836 /* automatically cope with AIX 5.3 with longer usernames
837 when it comes out */
838 if (S_NAMELEN > strlen(longname)) {
839 strcpy(shortname, longname);
840 return 1;
841 }
842
843 pwd = wb_aix_getpwnam(longname);
844 if (!pwd) {
845 errno = ENOENT;
846 return 0;
847 }
848
849 sprintf(shortname, "%c%07u", WB_AIX_ENCODED, pwd->pw_uid);
850
851 free_pwd(pwd);
852
853 return 1;
854}
855
856
857/*
858 authenticate a user
859 */
860static int wb_aix_authenticate(char *user, char *pass,
861 int *reenter, char **message)
862{
863 struct winbindd_request request;
864 struct winbindd_response response;
865 NSS_STATUS result;
866 char *r_user = user;
867
868 logit("authenticate '%s' response='%s'\n", user, pass);
869
870 *reenter = 0;
871 *message = NULL;
872
873 /* Send off request */
874 ZERO_STRUCT(request);
875 ZERO_STRUCT(response);
876
877 if (*user == WB_AIX_ENCODED) {
878 r_user = decode_user(r_user);
879 if (!r_user) {
880 return AUTH_NOTFOUND;
881 }
882 }
883
884 STRCPY_RET(request.data.auth.user, r_user);
885 STRCPY_RET(request.data.auth.pass, pass);
886
887 if (*user == WB_AIX_ENCODED) {
888 free(r_user);
889 }
890
891 result = winbindd_request_response(WINBINDD_PAM_AUTH, &request, &response);
892
893 winbindd_free_response(&response);
894
895 logit("auth result %d for '%s'\n", result, user);
896
897 if (result == NSS_STATUS_SUCCESS) {
898 errno = 0;
899 return AUTH_SUCCESS;
900 }
901
902 return AUTH_FAILURE;
903}
904
905
906/*
907 change a user password
908*/
909static int wb_aix_chpass(char *user, char *oldpass, char *newpass, char **message)
910{
911 struct winbindd_request request;
912 struct winbindd_response response;
913 NSS_STATUS result;
914 char *r_user = user;
915
916 if (*user == WB_AIX_ENCODED) {
917 r_user = decode_user(r_user);
918 if (!r_user) {
919 errno = ENOENT;
920 return -1;
921 }
922 }
923
924 logit("chpass '%s' old='%s' new='%s'\n", r_user, oldpass, newpass);
925
926 *message = NULL;
927
928 /* Send off request */
929 ZERO_STRUCT(request);
930 ZERO_STRUCT(response);
931
932 STRCPY_RET(request.data.chauthtok.user, r_user);
933 STRCPY_RET(request.data.chauthtok.oldpass, oldpass);
934 STRCPY_RET(request.data.chauthtok.newpass, newpass);
935
936 if (*user == WB_AIX_ENCODED) {
937 free(r_user);
938 }
939
940 result = winbindd_request_response(WINBINDD_PAM_CHAUTHTOK, &request, &response);
941
942 winbindd_free_response(&response);
943
944 if (result == NSS_STATUS_SUCCESS) {
945 errno = 0;
946 return 0;
947 }
948
949 errno = EINVAL;
950 return -1;
951}
952
953/*
954 don't do any password strength testing for now
955*/
956static int wb_aix_passwdrestrictions(char *user, char *newpass, char *oldpass,
957 char **message)
958{
959 logit("passwdresrictions called for '%s'\n", user);
960 return 0;
961}
962
963
964static int wb_aix_passwdexpired(char *user, char **message)
965{
966 logit("passwdexpired '%s'\n", user);
967 /* we should check the account bits here */
968 return 0;
969}
970
971
972/*
973 we can't return a crypt() password
974*/
975static char *wb_aix_getpasswd(char *user)
976{
977 logit("getpasswd '%s'\n", user);
978 errno = ENOSYS;
979 return NULL;
980}
981
982/*
983 this is called to update things like the last login time. We don't
984 currently pass this onto the DC
985*/
986static int wb_aix_putentry(char *key, char *table, char *attributes[],
987 attrval_t values[], int size)
988{
989 logit("putentry key='%s' table='%s' attrib='%s'\n",
990 key, table, size>=1?attributes[0]:"<null>");
991 errno = ENOSYS;
992 return -1;
993}
994
995static int wb_aix_commit(char *key, char *table)
996{
997 logit("commit key='%s' table='%s'\n");
998 errno = ENOSYS;
999 return -1;
1000}
1001
1002static int wb_aix_getgrusers(char *group, void *result, int type, int *size)
1003{
1004 logit("getgrusers group='%s'\n", group);
1005 errno = ENOSYS;
1006 return -1;
1007}
1008
1009
1010#define DECL_METHOD(x) \
1011int method_ ## x(void) \
1012{ \
1013 logit("UNIMPLEMENTED METHOD '%s'\n", #x); \
1014 errno = EINVAL; \
1015 return -1; \
1016}
1017
1018#if LOG_UNIMPLEMENTED_CALLS
1019DECL_METHOD(delgroup);
1020DECL_METHOD(deluser);
1021DECL_METHOD(newgroup);
1022DECL_METHOD(newuser);
1023DECL_METHOD(putgrent);
1024DECL_METHOD(putgrusers);
1025DECL_METHOD(putpwent);
1026DECL_METHOD(lock);
1027DECL_METHOD(unlock);
1028DECL_METHOD(getcred);
1029DECL_METHOD(setcred);
1030DECL_METHOD(deletecred);
1031#endif
1032
1033int wb_aix_init(struct secmethod_table *methods)
1034{
1035 ZERO_STRUCTP(methods);
1036
1037#ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_VERSION
1038 methods->method_version = SECMETHOD_VERSION_520;
1039#endif
1040
1041 methods->method_getgrgid = wb_aix_getgrgid;
1042 methods->method_getgrnam = wb_aix_getgrnam;
1043 methods->method_getgrset = wb_aix_getgrset;
1044 methods->method_getpwnam = wb_aix_getpwnam;
1045 methods->method_getpwuid = wb_aix_getpwuid;
1046 methods->method_getentry = wb_aix_getentry;
1047 methods->method_open = wb_aix_open;
1048 methods->method_close = wb_aix_close;
1049 methods->method_normalize = wb_aix_normalize;
1050 methods->method_passwdexpired = wb_aix_passwdexpired;
1051 methods->method_putentry = wb_aix_putentry;
1052 methods->method_getpasswd = wb_aix_getpasswd;
1053 methods->method_authenticate = wb_aix_authenticate;
1054 methods->method_commit = wb_aix_commit;
1055 methods->method_chpass = wb_aix_chpass;
1056 methods->method_passwdrestrictions = wb_aix_passwdrestrictions;
1057 methods->method_getgracct = wb_aix_getgracct;
1058 methods->method_getgrusers = wb_aix_getgrusers;
1059#ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_ATTRLIST
1060 methods->method_attrlist = wb_aix_attrlist;
1061#endif
1062
1063#if LOG_UNIMPLEMENTED_CALLS
1064 methods->method_delgroup = method_delgroup;
1065 methods->method_deluser = method_deluser;
1066 methods->method_newgroup = method_newgroup;
1067 methods->method_newuser = method_newuser;
1068 methods->method_putgrent = method_putgrent;
1069 methods->method_putgrusers = method_putgrusers;
1070 methods->method_putpwent = method_putpwent;
1071 methods->method_lock = method_lock;
1072 methods->method_unlock = method_unlock;
1073 methods->method_getcred = method_getcred;
1074 methods->method_setcred = method_setcred;
1075 methods->method_deletecred = method_deletecred;
1076#endif
1077
1078 return AUTH_SUCCESS;
1079}
Note: See TracBrowser for help on using the repository browser.