]> arthur.barton.de Git - netatalk.git/blob - etc/uams/uams_dhx_passwd.c
Tru64 SIA fixes and Eddie and Burkhard.
[netatalk.git] / etc / uams / uams_dhx_passwd.c
1 /*
2  * $Id: uams_dhx_passwd.c,v 1.15 2002-02-13 16:44:59 srittau Exp $
3  *
4  * Copyright (c) 1990,1993 Regents of The University of Michigan.
5  * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu) 
6  * All Rights Reserved.  See COPYRIGHT.
7  */
8
9 #ifdef HAVE_CONFIG_H
10 #include "config.h"
11 #endif /* HAVE_CONFIG_H */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #ifdef HAVE_UNISTD_H
17 #include <unistd.h>
18 #endif /* HAVE_UNISTD_H */
19 #ifndef NO_CRYPT_H
20 #include <crypt.h>
21 #endif /* ! NO_CRYPT_H */
22 #include <pwd.h>
23 #include <atalk/logger.h>
24
25 #ifdef SHADOWPW
26 #include <shadow.h>
27 #endif /* SHADOWPW */
28
29 #ifdef OPENSSL_DHX
30 #include <openssl/bn.h>
31 #include <openssl/dh.h>
32 #include <openssl/cast.h>
33 #else /* OPENSSL_DHX */
34 #include <bn.h>
35 #include <dh.h>
36 #include <cast.h>
37 #endif /* OPENSSL_DHX */
38
39 #include <atalk/afp.h>
40 #include <atalk/uam.h>
41
42 #define KEYSIZE 16
43 #define PASSWDLEN 64
44 #define CRYPTBUFLEN  (KEYSIZE*2)
45 #define CRYPT2BUFLEN (KEYSIZE + PASSWDLEN)
46
47 /* hash a number to a 16-bit quantity */
48 #define dhxhash(a) ((((unsigned long) (a) >> 8) ^ \
49                      (unsigned long) (a)) & 0xffff)
50
51 /* the secret key */
52 static CAST_KEY castkey;
53 static struct passwd *dhxpwd;
54 static u_int8_t randbuf[16];
55
56 #ifdef TRU64
57 #include <sia.h>
58 #include <siad.h>
59
60 static char *clientname;
61 #endif /* TRU64 */
62
63 /* dhx passwd */
64 static int passwd_login(void *obj, struct passwd **uam_pwd,
65                         char *ibuf, int ibuflen,
66                         char *rbuf, int *rbuflen)
67 {
68     unsigned char iv[] = "CJalbert";
69     u_int8_t p[] = {0xBA, 0x28, 0x73, 0xDF, 0xB0, 0x60, 0x57, 0xD4,
70                     0x3F, 0x20, 0x24, 0x74, 0x4C, 0xEE, 0xE7, 0x5B };
71     u_int8_t g = 0x07;
72 #ifdef SHADOWPW
73     struct spwd *sp;
74 #endif /* SHADOWPW */
75     BIGNUM *bn, *gbn, *pbn;
76     u_int16_t sessid;
77     int len, i;
78     char *name;
79     DH *dh;
80
81 #ifdef TRU64
82     static const char rnd_seed[] = "string to make the random number generator think it has entropy";
83     RAND_seed(rnd_seed, sizeof rnd_seed);
84 #endif /* TRU64 */
85
86     *rbuflen = 0;
87
88     if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, (void *) &name, &i) < 0)
89       return AFPERR_PARAM;
90
91 #ifdef TRU64
92     if( uam_afpserver_option( obj, UAM_OPTION_CLIENTNAME,
93                               (void *) &clientname, NULL ) < 0 )
94         return AFPERR_PARAM;
95 #endif /* TRU64 */
96
97     len = (unsigned char) *ibuf++;
98     if ( len + 1 > i ) {
99         return( AFPERR_PARAM );
100     }
101
102     memcpy(name, ibuf, len );
103     ibuf += len;
104     name[ len ] = '\0';
105     if ((unsigned long) ibuf & 1) /* padding */
106       ++ibuf;
107
108     if (( dhxpwd = uam_getname(name, i)) == NULL ) {
109       return AFPERR_PARAM;
110     }
111
112     LOG(log_info, logtype_default, "dhx login: %s", name);
113     if (uam_checkuser(dhxpwd) < 0)
114       return AFPERR_NOTAUTH;
115
116 #ifdef SHADOWPW
117     if (( sp = getspnam( dhxpwd->pw_name )) == NULL ) {
118         LOG(log_info, logtype_default, "no shadow passwd entry for %s", name);
119         return AFPERR_NOTAUTH;
120     }
121     dhxpwd->pw_passwd = sp->sp_pwdp;
122 #endif /* SHADOWPW */
123
124     if (!dhxpwd->pw_passwd)
125       return AFPERR_NOTAUTH;
126
127     /* get the client's public key */
128     if (!(bn = BN_bin2bn(ibuf, KEYSIZE, NULL))) {
129       return AFPERR_PARAM;
130     }
131
132     /* get our primes */
133     if (!(gbn = BN_bin2bn(&g, sizeof(g), NULL))) {
134       BN_free(bn);
135       return AFPERR_PARAM;
136     }
137
138     if (!(pbn = BN_bin2bn(p, sizeof(p), NULL))) {
139       BN_free(gbn);
140       BN_free(bn);
141       return AFPERR_PARAM;
142     }
143
144     /* okay, we're ready */
145     if (!(dh = DH_new())) {
146       BN_free(pbn);
147       BN_free(gbn);
148       BN_free(bn);
149       return AFPERR_PARAM;
150     }
151
152     /* generate key and make sure we have enough space */
153     dh->p = pbn;
154     dh->g = gbn;
155     if (!DH_generate_key(dh) || (BN_num_bytes(dh->pub_key) > KEYSIZE)) {
156       goto passwd_fail;
157     }
158
159     /* figure out the key. use rbuf as a temporary buffer. */
160     i = DH_compute_key(rbuf, bn, dh);
161     
162     /* set the key */
163     CAST_set_key(&castkey, i, rbuf);
164     
165     /* session id. it's just a hashed version of the object pointer. */
166     sessid = dhxhash(obj);
167     memcpy(rbuf, &sessid, sizeof(sessid));
168     rbuf += sizeof(sessid);
169     *rbuflen += sizeof(sessid);
170     
171     /* send our public key */
172     BN_bn2bin(dh->pub_key, rbuf); 
173     rbuf += KEYSIZE;
174     *rbuflen += KEYSIZE;
175
176     /* buffer to be encrypted */
177     i = sizeof(randbuf);
178     if (uam_afpserver_option(obj, UAM_OPTION_RANDNUM, (void *) randbuf,
179                              &i) < 0) {
180       *rbuflen = 0;
181       goto passwd_fail;
182     }    
183     memcpy(rbuf, &randbuf, sizeof(randbuf));
184
185 #if 0
186     /* get the signature. it's always 16 bytes. */
187     if (uam_afpserver_option(obj, UAM_OPTION_SIGNATURE, 
188                              (void *) &name, NULL) < 0) {
189       *rbuflen = 0;
190       goto passwd_fail;
191     }
192     memcpy(rbuf + KEYSIZE, name, KEYSIZE); 
193 #else /* 0 */
194     memset(rbuf + KEYSIZE, 0, KEYSIZE);
195 #endif /* 0 */
196
197     /* encrypt using cast */
198     CAST_cbc_encrypt(rbuf, rbuf, CRYPTBUFLEN, &castkey, iv, CAST_ENCRYPT);
199     *rbuflen += CRYPTBUFLEN;
200     BN_free(bn);
201     DH_free(dh);
202     return AFPERR_AUTHCONT;
203
204 passwd_fail:
205     BN_free(bn);
206     DH_free(dh);
207     return AFPERR_PARAM;
208 }
209
210 static int passwd_logincont(void *obj, struct passwd **uam_pwd,
211                             char *ibuf, int ibuflen, 
212                             char *rbuf, int *rbuflen)
213 {
214     unsigned char iv[] = "LWallace";
215     BIGNUM *bn1, *bn2, *bn3;
216     u_int16_t sessid;
217     char *p;
218
219     *rbuflen = 0;
220
221     /* check for session id */
222     memcpy(&sessid, ibuf, sizeof(sessid));
223     if (sessid != dhxhash(obj))
224       return AFPERR_PARAM;
225     ibuf += sizeof(sessid);
226    
227     /* use rbuf as scratch space */
228     CAST_cbc_encrypt(ibuf, rbuf, CRYPT2BUFLEN, &castkey,
229                      iv, CAST_DECRYPT);
230     
231     /* check to make sure that the random number is the same. we
232      * get sent back an incremented random number. */
233     if (!(bn1 = BN_bin2bn(rbuf, KEYSIZE, NULL)))
234       return AFPERR_PARAM;
235
236     if (!(bn2 = BN_bin2bn(randbuf, sizeof(randbuf), NULL))) {
237       BN_free(bn1);
238       return AFPERR_PARAM;
239     }
240       
241     /* zero out the random number */
242     memset(rbuf, 0, sizeof(randbuf));
243     memset(randbuf, 0, sizeof(randbuf));
244     rbuf += KEYSIZE;
245
246     if (!(bn3 = BN_new())) {
247       BN_free(bn2);
248       BN_free(bn1);
249       return AFPERR_PARAM;
250     }
251
252     BN_sub(bn3, bn1, bn2);
253     BN_free(bn2);
254     BN_free(bn1);
255
256     /* okay. is it one more? */
257     if (!BN_is_one(bn3)) {
258       BN_free(bn3);
259       return AFPERR_PARAM;
260     }
261     BN_free(bn3);
262
263     rbuf[PASSWDLEN] = '\0';
264 #ifdef TRU64
265     {
266         int ac;
267         char **av;
268         char hostname[256];
269
270         uam_afp_getcmdline( &ac, &av );
271         sprintf( hostname, "%s@%s", dhxpwd->pw_name, clientname );
272
273         if( uam_sia_validate_user( NULL, ac, av, hostname, dhxpwd->pw_name,
274                                    NULL, FALSE, NULL, rbuf ) != SIASUCCESS )
275             return AFPERR_NOTAUTH;
276
277         memset( rbuf, 0, PASSWDLEN );
278         *uam_pwd = dhxpwd;
279         return AFP_OK;
280     }
281 #else /* TRU64 */
282     p = crypt( rbuf, dhxpwd->pw_passwd );
283     memset(rbuf, 0, PASSWDLEN);
284     if ( strcmp( p, dhxpwd->pw_passwd ) == 0 ) {
285       *uam_pwd = dhxpwd;
286       return AFP_OK;
287     }
288 #endif /* TRU64 */
289
290     return AFPERR_NOTAUTH;
291 }
292
293
294 static int uam_setup(const char *path)
295 {
296   if (uam_register(UAM_SERVER_LOGIN, path, "DHCAST128",
297                    passwd_login, passwd_logincont, NULL) < 0)
298     return -1;
299   /*uam_register(UAM_SERVER_PRINTAUTH, path, "DHCAST128",
300     passwd_printer);*/
301
302   return 0;
303 }
304
305 static void uam_cleanup(void)
306 {
307   uam_unregister(UAM_SERVER_LOGIN, "DHCAST128");
308   /*uam_unregister(UAM_SERVER_PRINTAUTH, "DHCAST128"); */
309 }
310
311 UAM_MODULE_EXPORT struct uam_export uams_dhx = {
312   UAM_MODULE_SERVER,
313   UAM_MODULE_VERSION,
314   uam_setup, uam_cleanup
315 };