e0a8daed144b4ecd323a78826fd0f0a4bb38506c
[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
20 RCSID("$Header$");
21
22 #include "afs_util.h"
23
24
25 char    *pam_afs_ident          = "pam_afs";
26 char    *pam_afs_lh             = "TRANSARC_PAM_AFS_AUTH_login_handle";
27
28
29 void lc_cleanup(
30         pam_handle_t    *pamh,
31         void            *data,
32         int             pam_end_status)
33 {
34     if ( data )
35     {
36         memset(data, 0, strlen(data));
37         free(data);
38     }
39 }
40
41
42 void nil_cleanup(
43         pam_handle_t    *pamh,
44         void            *data,
45         int             pam_end_status)
46 {
47     return;
48 }
49
50 /* The PAM module needs to be free from libucb dependency. Otherwise, 
51 dynamic linking is a problem, the AFS PAM library refuses to coexist
52 with the DCE library. The sigvec() and sigsetmask() are the only two
53 calls that neccesiate the inclusion of libucb.a.  There are used by
54 the lwp library to support premeptive threads and signalling between 
55 threads. Since the lwp support used by the PAM module uses none of 
56 these facilities, we can safely define these to be null functions */
57
58 #if !defined(AFS_HPUX110_ENV)
59 /* For HP 11.0, this function is in util/hputil.c */
60 sigvec(int sig, const struct sigvec* vec, struct sigvec* ovec)
61 {
62         assert(0);
63 }
64 #endif  /* AFS_HPUX110_ENV */
65 sigsetmask(int mask)
66 {
67         assert(0);
68 }
69
70 /* converts string to integer */
71
72 char *cv2string(ttp, aval)
73     register char *ttp;
74     register unsigned long aval;
75 {
76     register char *tp = ttp;
77     register int  i;
78     int any = 0;
79
80     *(--tp) = 0;
81     while (aval != 0) {
82         i = aval % 10;
83         *(--tp) = '0' + i;
84         aval /= 10;
85         any = 1;
86     }
87     if (!any)
88         *(--tp) = '0';
89     return tp;
90 }
91
92 int do_klog(const char* user, const char* password, const char* lifetime)
93 {
94 pid_t   pid;
95 int     pipedes[2];
96 int     status;
97 char*   argv[32];
98 int     argc = 0;
99 char*   klog_prog;
100 int     ret = 1;
101
102 #if defined(AFS_KERBEROS_ENV) 
103    klog_prog = KLOGKRB;
104 #else
105    klog_prog = KLOG;
106 #endif
107    if (access(klog_prog, X_OK) != 0) {
108       syslog(LOG_ERR, "can not access klog program '%s'", KLOG);
109       goto out;
110    }
111 #if defined(AFS_KERBEROS_ENV) 
112    argv[argc++] = "klog.krb";
113
114 #else
115    argv[argc++] = "klog";
116 #endif
117    argv[argc++] = (char*)user;
118    argv[argc++] = "-silent";
119    argv[argc++] = "-pipe";
120    if (lifetime != NULL) {
121       argv[argc++] = "-lifetime";
122       argv[argc++] = (char*)lifetime;
123    }
124    argv[argc] = NULL;
125
126    if (pipe(pipedes) != 0) {
127       syslog(LOG_ERR, "can not open pipe: %s", strerror(errno));
128       goto out;
129    }
130    pid = fork();
131    switch(pid) {
132       case (-1): /* Error: fork failed */
133          syslog(LOG_ERR, "fork failed: %s", strerror(errno));
134          goto out;
135       case (0) : /* child */
136          close(0);
137          dup(pipedes[0]);
138          close(pipedes[0]);
139          close(1);
140          dup(pipedes[1]);
141          close(pipedes[1]);
142          execv(klog_prog, argv);
143          /* notreached */
144          syslog(LOG_ERR, "execv failed: %s", strerror(errno));
145          close(0);
146          close(1);
147          goto out;
148       default :
149          write(pipedes[1], password, strlen(password));
150          write(pipedes[1], "\n", 1);
151          close(pipedes[0]);
152          close(pipedes[1]);
153          if (pid != wait(&status)) return(0);
154          if (WIFEXITED(status)) {
155             ret = WEXITSTATUS(status);
156             goto out;
157          }
158          syslog(LOG_NOTICE, "%s for %s failed", klog_prog, user) ;
159    }
160 out:
161    /*   syslog(LOG_DEBUG, "do_klog returns %d", ret); */
162    return(ret);
163 }
164
165 /* get the current AFS pag for the calling process */
166 static afs_int32 curpag()
167 {
168    gid_t groups[30];
169    afs_uint32 g0, g1;
170    afs_uint32 h, l, ret;
171       
172    if (getgroups(sizeof groups/sizeof groups[0], groups) < 2) return 0;
173          
174    g0 = groups[0]  & 0xffff;
175    g1 = groups[1]  & 0xffff;
176    g0 -= 0x3f00;
177    g1 -= 0x3f00;
178    if (g0 < 0xc000 && g1 < 0xc000) {
179       l = ((g0 & 0x3fff) << 14) | (g1 & 0x3fff);
180       h = (g0 >> 14);
181       h = (g1 >> 14) + h + h + h;
182       ret = ((h << 28) | l);
183       /* Additional testing */
184       if (((ret >> 24) & 0xff) == 'A')
185          return ret;
186       else
187          return -1;
188      }
189    return -1;
190 }
191
192 /* Returns the AFS pag number, if any, otherwise return -1 */
193 afs_int32 getPAG()
194 {
195    afs_int32 pag;
196    
197    pag = curpag();
198    if (pag == 0 || pag == -1)
199       return -1;
200        
201    /* high order byte is always 'A'; actual pag value is low 24 bits */
202    return (pag & 0xFFFFFF);
203 }