reindent-20030715
[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 #ifdef HAVE_STRING_H
21 #include <string.h>
22 #else
23 #ifdef HAVE_STRINGS_H
24 #include <strings.h>
25 #endif
26 #endif
27 #include <stdlib.h>
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     gid_t groups[NGROUPS_MAX];
184     afs_uint32 g0, g1;
185     afs_uint32 h, l, ret;
186
187     if (getgroups(sizeof groups / sizeof groups[0], groups) < 2)
188         return 0;
189
190     g0 = groups[0] & 0xffff;
191     g1 = groups[1] & 0xffff;
192     g0 -= 0x3f00;
193     g1 -= 0x3f00;
194     if (g0 < 0xc000 && g1 < 0xc000) {
195         l = ((g0 & 0x3fff) << 14) | (g1 & 0x3fff);
196         h = (g0 >> 14);
197         h = (g1 >> 14) + h + h + h;
198         ret = ((h << 28) | l);
199         /* Additional testing */
200         if (((ret >> 24) & 0xff) == 'A')
201             return ret;
202         else
203             return -1;
204     }
205     return -1;
206 }
207
208 /* Returns the AFS pag number, if any, otherwise return -1 */
209 afs_int32
210 getPAG(void)
211 {
212     afs_int32 pag;
213
214     pag = curpag();
215     if (pag == 0 || pag == -1)
216         return -1;
217
218     /* high order byte is always 'A'; actual pag value is low 24 bits */
219     return (pag & 0xFFFFFF);
220 }