2 * $Id: uams_dhx_passwd.c,v 1.22 2003-06-14 16:40:54 srittau Exp $
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.
9 #define _XOPEN_SOURCE /* for crypt() */
13 #endif /* HAVE_CONFIG_H */
20 #endif /* HAVE_UNISTD_H */
23 #endif /* ! NO_CRYPT_H */
25 #include <atalk/logger.h>
31 #include <atalk/afp.h>
32 #include <atalk/uam.h>
36 #define CRYPTBUFLEN (KEYSIZE*2)
37 #define CRYPT2BUFLEN (KEYSIZE + PASSWDLEN)
39 /* hash a number to a 16-bit quantity */
40 #define dhxhash(a) ((((unsigned long) (a) >> 8) ^ \
41 (unsigned long) (a)) & 0xffff)
44 static struct passwd *dhxpwd;
45 static u_int8_t randbuf[16];
51 static char *clientname;
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)
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 };
75 #if defined(TRU64) && !defined(HAVE_GCRYPT)
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) */
85 if( uam_afpserver_option( obj, UAM_OPTION_CLIENTNAME,
86 (void *) &clientname, NULL ) < 0 )
90 if (( dhxpwd = uam_getname(username, ulen)) == NULL ) {
94 LOG(log_info, logtype_uams, "dhx login: %s", username);
95 if (uam_checkuser(dhxpwd) < 0)
96 return AFPERR_NOTAUTH;
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;
103 dhxpwd->pw_passwd = sp->sp_pwdp;
104 #endif /* SHADOWPW */
106 if (!dhxpwd->pw_passwd)
107 return AFPERR_NOTAUTH;
109 castkey = atalk_cast_key(ibuf, KEYSIZE);
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);
119 /* send our public key */
120 BN_bn2bin(dh->pub_key, rbuf);
124 /* buffer to be encrypted */
126 if (uam_afpserver_option(obj, UAM_OPTION_RANDNUM, (void *) randbuf,
131 memcpy(rbuf, &randbuf, sizeof(randbuf));
134 /* get the signature. it's always 16 bytes. */
135 if (uam_afpserver_option(obj, UAM_OPTION_SIGNATURE,
136 (void *) &name, NULL) < 0) {
140 memcpy(rbuf + KEYSIZE, name, KEYSIZE);
142 memset(rbuf + KEYSIZE, 0, KEYSIZE);
145 /* encrypt using cast */
146 CAST_cbc_encrypt(rbuf, rbuf, CRYPTBUFLEN, &castkey, iv, CAST_ENCRYPT);
147 *rbuflen += CRYPTBUFLEN;
150 return AFPERR_AUTHCONT;
159 static int passwd_login(void *obj, struct passwd **uam_pwd,
160 char *ibuf, int ibuflen,
161 char *rbuf, int *rbuflen)
168 if (uam_afpserver_option(obj, UAM_OPTION_USERNAME,
169 (void *) &username, &ulen) < 0)
173 return( AFPERR_PARAM );
176 len = (unsigned char) *ibuf++;
178 if (!len || len > ibuflen || len > ulen ) {
179 return( AFPERR_PARAM );
181 memcpy(username, ibuf, len );
184 username[ len ] = '\0';
186 if ((unsigned long) ibuf & 1) { /* pad character */
190 return (pwd_login(obj, username, ulen, uam_pwd, ibuf, ibuflen, rbuf, rbuflen));
194 /* cleartxt login ext
197 2 bytes len (network order)
198 len bytes unicode name
200 static int passwd_login_ext(void *obj, char *uname, struct passwd **uam_pwd,
201 char *ibuf, int ibuflen,
202 char *rbuf, int *rbuflen)
210 if (uam_afpserver_option(obj, UAM_OPTION_USERNAME,
211 (void *) &username, &ulen) < 0)
217 memcpy(&temp16, uname, sizeof(temp16));
219 if (!len || len > ulen ) {
220 return( AFPERR_PARAM );
222 memcpy(username, uname +2, len );
223 username[ len ] = '\0';
224 return (pwd_login(obj, username, ulen, uam_pwd, ibuf, ibuflen, rbuf, rbuflen));
227 static int passwd_logincont(void *obj, struct passwd **uam_pwd,
228 char *ibuf, int ibuflen,
229 char *rbuf, int *rbuflen)
231 unsigned char iv[] = "LWallace";
232 BIGNUM *bn1, *bn2, *bn3;
238 /* check for session id */
239 memcpy(&sessid, ibuf, sizeof(sessid));
240 if (sessid != dhxhash(obj))
242 ibuf += sizeof(sessid);
244 /* use rbuf as scratch space */
245 CAST_cbc_encrypt(ibuf, rbuf, CRYPT2BUFLEN, &castkey,
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)))
253 if (!(bn2 = BN_bin2bn(randbuf, sizeof(randbuf), NULL))) {
258 /* zero out the random number */
259 memset(rbuf, 0, sizeof(randbuf));
260 memset(randbuf, 0, sizeof(randbuf));
263 if (!(bn3 = BN_new())) {
269 BN_sub(bn3, bn1, bn2);
273 /* okay. is it one more? */
274 if (!BN_is_one(bn3)) {
280 rbuf[PASSWDLEN] = '\0';
287 uam_afp_getcmdline( &ac, &av );
288 sprintf( hostname, "%s@%s", dhxpwd->pw_name, clientname );
290 if( uam_sia_validate_user( NULL, ac, av, hostname, dhxpwd->pw_name,
291 NULL, FALSE, NULL, rbuf ) != SIASUCCESS )
292 return AFPERR_NOTAUTH;
294 memset( rbuf, 0, PASSWDLEN );
299 p = crypt( rbuf, dhxpwd->pw_passwd );
300 memset(rbuf, 0, PASSWDLEN);
301 if ( strcmp( p, dhxpwd->pw_passwd ) == 0 ) {
307 return AFPERR_NOTAUTH;
311 static int uam_setup(const char *path)
313 if (uam_register(UAM_SERVER_LOGIN_EXT, path, "DHCAST128",
314 passwd_login, passwd_logincont, NULL, passwd_login_ext) < 0)
316 /*uam_register(UAM_SERVER_PRINTAUTH, path, "DHCAST128",
322 static void uam_cleanup(void)
324 uam_unregister(UAM_SERVER_LOGIN, "DHCAST128");
325 /*uam_unregister(UAM_SERVER_PRINTAUTH, "DHCAST128"); */
328 UAM_MODULE_EXPORT struct uam_export uams_dhx = {
331 uam_setup, uam_cleanup