use-NGROUPS-MAX-instead-of-constant-for-curpag-getgroups-call-20011110
[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
65 sigsetmask(int mask)
66 {
67         assert(0);
68 }
69 #endif  /* AFS_HPUX110_ENV */
70
71 /* converts string to integer */
72
73 char *cv2string(ttp, aval)
74     register char *ttp;
75     register unsigned long aval;
76 {
77     register char *tp = ttp;
78     register int  i;
79     int any = 0;
80
81     *(--tp) = 0;
82     while (aval != 0) {
83         i = aval % 10;
84         *(--tp) = '0' + i;
85         aval /= 10;
86         any = 1;
87     }
88     if (!any)
89         *(--tp) = '0';
90     return tp;
91 }
92
93 int do_klog(const char* user, const char* password, const char* lifetime)
94 {
95 pid_t   pid;
96 int     pipedes[2];
97 int     status;
98 char*   argv[32];
99 int     argc = 0;
100 char*   klog_prog;
101 int     ret = 1;
102
103 #if defined(AFS_KERBEROS_ENV) 
104    klog_prog = KLOGKRB;
105 #else
106    klog_prog = KLOG;
107 #endif
108    if (access(klog_prog, X_OK) != 0) {
109       syslog(LOG_ERR, "can not access klog program '%s'", KLOG);
110       goto out;
111    }
112 #if defined(AFS_KERBEROS_ENV) 
113    argv[argc++] = "klog.krb";
114
115 #else
116    argv[argc++] = "klog";
117 #endif
118    argv[argc++] = (char*)user;
119    argv[argc++] = "-silent";
120    argv[argc++] = "-pipe";
121    if (lifetime != NULL) {
122       argv[argc++] = "-lifetime";
123       argv[argc++] = (char*)lifetime;
124    }
125    argv[argc] = NULL;
126
127    if (pipe(pipedes) != 0) {
128       syslog(LOG_ERR, "can not open pipe: %s", strerror(errno));
129       goto out;
130    }
131    pid = fork();
132    switch(pid) {
133       case (-1): /* Error: fork failed */
134          syslog(LOG_ERR, "fork failed: %s", strerror(errno));
135          goto out;
136       case (0) : /* child */
137          close(0);
138          dup(pipedes[0]);
139          close(pipedes[0]);
140          close(1);
141          dup(pipedes[1]);
142          close(pipedes[1]);
143          execv(klog_prog, argv);
144          /* notreached */
145          syslog(LOG_ERR, "execv failed: %s", strerror(errno));
146          close(0);
147          close(1);
148          goto out;
149       default :
150          write(pipedes[1], password, strlen(password));
151          write(pipedes[1], "\n", 1);
152          close(pipedes[0]);
153          close(pipedes[1]);
154          if (pid != wait(&status)) return(0);
155          if (WIFEXITED(status)) {
156             ret = WEXITSTATUS(status);
157             goto out;
158          }
159          syslog(LOG_NOTICE, "%s for %s failed", klog_prog, user) ;
160    }
161 out:
162    /*   syslog(LOG_DEBUG, "do_klog returns %d", ret); */
163    return(ret);
164 }
165
166 /* get the current AFS pag for the calling process */
167 static afs_int32 curpag()
168 {
169    gid_t groups[NGROUPS_MAX];
170    afs_uint32 g0, g1;
171    afs_uint32 h, l, ret;
172       
173    if (getgroups(sizeof groups/sizeof groups[0], groups) < 2) return 0;
174          
175    g0 = groups[0]  & 0xffff;
176    g1 = groups[1]  & 0xffff;
177    g0 -= 0x3f00;
178    g1 -= 0x3f00;
179    if (g0 < 0xc000 && g1 < 0xc000) {
180       l = ((g0 & 0x3fff) << 14) | (g1 & 0x3fff);
181       h = (g0 >> 14);
182       h = (g1 >> 14) + h + h + h;
183       ret = ((h << 28) | l);
184       /* Additional testing */
185       if (((ret >> 24) & 0xff) == 'A')
186          return ret;
187       else
188          return -1;
189      }
190    return -1;
191 }
192
193 /* Returns the AFS pag number, if any, otherwise return -1 */
194 afs_int32 getPAG()
195 {
196    afs_int32 pag;
197    
198    pag = curpag();
199    if (pag == 0 || pag == -1)
200       return -1;
201        
202    /* high order byte is always 'A'; actual pag value is low 24 bits */
203    return (pag & 0xFFFFFF);
204 }