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