aix51-pag-header-20090320
[openafs.git] / src / pam / afs_util.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <stdio.h>
11 #include <assert.h>
12 #include <unistd.h>
13 #include <errno.h>
14 #include <syslog.h>
15 #include <security/pam_appl.h>
16 #include <afsconfig.h>
17 #include <afs/param.h>
18 #include <sys/wait.h>
19 #include <limits.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #ifdef AFS_AIX51_ENV
23 #include <sys/cred.h>
24 #ifdef HAVE_SYS_PAG_H
25 #include <sys/pag.h>
26 #endif
27 #endif
28
29 RCSID
30     ("$Header$");
31
32 #include "afs_util.h"
33
34
35 char *pam_afs_ident = "pam_afs";
36 char *pam_afs_lh = "OPENAFS_PAM_AFS_AUTH_login_handle";
37
38
39 void
40 lc_cleanup(pam_handle_t * pamh, void *data, int pam_end_status)
41 {
42     if (data) {
43         memset(data, 0, strlen(data));
44         free(data);
45     }
46 }
47
48
49 void
50 nil_cleanup(pam_handle_t * pamh, void *data, int pam_end_status)
51 {
52     return;
53 }
54
55 /* The PAM module needs to be free from libucb dependency. Otherwise, 
56 dynamic linking is a problem, the AFS PAM library refuses to coexist
57 with the DCE library. The sigvec() and sigsetmask() are the only two
58 calls that neccesiate the inclusion of libucb.a.  There are used by
59 the lwp library to support premeptive threads and signalling between 
60 threads. Since the lwp support used by the PAM module uses none of 
61 these facilities, we can safely define these to be null functions */
62
63 #if !defined(AFS_HPUX110_ENV)
64 /* For HP 11.0, this function is in util/hputil.c */
65 int
66 sigvec(int sig, const struct sigvec *vec, struct sigvec *ovec)
67 {
68     assert(0);
69 }
70
71 int
72 sigsetmask(int mask)
73 {
74     assert(0);
75 }
76 #endif /* AFS_HPUX110_ENV */
77
78 /* converts string to integer */
79
80 char *
81 cv2string(register char *ttp, register unsigned long aval)
82 {
83     register char *tp = ttp;
84     register int i;
85     int any = 0;
86
87     *(--tp) = 0;
88     while (aval != 0) {
89         i = aval % 10;
90         *(--tp) = '0' + i;
91         aval /= 10;
92         any = 1;
93     }
94     if (!any)
95         *(--tp) = '0';
96     return tp;
97 }
98
99 int
100 do_klog(const char *user, const char *password, const char *lifetime,
101         const char *cell_name)
102 {
103     pid_t pid;
104     int pipedes[2];
105     int status;
106     char *argv[32];
107     int argc = 0;
108     char *klog_prog;
109     int ret = 1;
110
111 #if defined(AFS_KERBEROS_ENV)
112     klog_prog = KLOGKRB;
113 #else
114     klog_prog = KLOG;
115 #endif
116     if (access(klog_prog, X_OK) != 0) {
117         syslog(LOG_ERR, "can not access klog program '%s'", KLOG);
118         goto out;
119     }
120 #if defined(AFS_KERBEROS_ENV)
121     argv[argc++] = "klog.krb";
122
123 #else
124     argv[argc++] = "klog";
125 #endif
126     argv[argc++] = (char *)user;
127     if (cell_name) {
128         argv[argc++] = "-cell";
129         argv[argc++] = (char *)cell_name;
130     }
131     argv[argc++] = "-silent";
132     argv[argc++] = "-pipe";
133     if (lifetime != NULL) {
134         argv[argc++] = "-lifetime";
135         argv[argc++] = (char *)lifetime;
136     }
137     argv[argc] = NULL;
138
139     if (pipe(pipedes) != 0) {
140         syslog(LOG_ERR, "can not open pipe: %s", strerror(errno));
141         goto out;
142     }
143     pid = fork();
144     switch (pid) {
145     case (-1):                  /* Error: fork failed */
146         syslog(LOG_ERR, "fork failed: %s", strerror(errno));
147         goto out;
148     case (0):                   /* child */
149         close(0);
150         dup(pipedes[0]);
151         close(pipedes[0]);
152         close(1);
153         dup(pipedes[1]);
154         close(pipedes[1]);
155         execv(klog_prog, argv);
156         /* notreached */
157         syslog(LOG_ERR, "execv failed: %s", strerror(errno));
158         close(0);
159         close(1);
160         goto out;
161     default:
162         write(pipedes[1], password, strlen(password));
163         write(pipedes[1], "\n", 1);
164         close(pipedes[0]);
165         close(pipedes[1]);
166         if (pid != wait(&status))
167             return (0);
168         if (WIFEXITED(status)) {
169             ret = WEXITSTATUS(status);
170             goto out;
171         }
172         syslog(LOG_NOTICE, "%s for %s failed", klog_prog, user);
173     }
174   out:
175     /*   syslog(LOG_DEBUG, "do_klog returns %d", ret); */
176     return (ret);
177 }
178
179 /* get the current AFS pag for the calling process */
180 static afs_int32
181 curpag(void)
182 {
183 #if defined(AFS_AIX51_ENV)
184     int code = getpagvalue("afs");
185     if (code < 0 && errno == EINVAL)
186         code = 0;
187     return code;
188 #else
189     gid_t groups[NGROUPS_MAX];
190     afs_uint32 g0, g1;
191     afs_uint32 h, l, ret;
192
193     if (getgroups(sizeof groups / sizeof groups[0], groups) < 2)
194         return 0;
195
196     g0 = groups[0] & 0xffff;
197     g1 = groups[1] & 0xffff;
198     g0 -= 0x3f00;
199     g1 -= 0x3f00;
200     if (g0 < 0xc000 && g1 < 0xc000) {
201         l = ((g0 & 0x3fff) << 14) | (g1 & 0x3fff);
202         h = (g0 >> 14);
203         h = (g1 >> 14) + h + h + h;
204         ret = ((h << 28) | l);
205         /* Additional testing */
206         if (((ret >> 24) & 0xff) == 'A')
207             return ret;
208         else
209             return -1;
210     }
211     return -1;
212 #endif
213 }
214
215 /* Returns the AFS pag number, if any, otherwise return -1 */
216 afs_int32
217 getPAG(void)
218 {
219     afs_int32 pag;
220
221     pag = curpag();
222     if (pag == 0 || pag == -1)
223         return -1;
224
225     /* high order byte is always 'A'; actual pag value is low 24 bits */
226     return (pag & 0xFFFFFF);
227 }