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