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.
33 #include <atalk/afp.h>
34 #include <atalk/uam.h>
38 #define CRYPTBUFLEN (KEYSIZE*2)
39 #define CRYPT2BUFLEN (KEYSIZE + PASSWDLEN)
41 /* hash a number to a 16-bit quantity */
42 #define dhxhash(a) ((((unsigned long) (a) >> 8) ^ \
43 (unsigned long) (a)) & 0xffff)
46 static CAST_KEY castkey;
47 static struct passwd *dhxpwd;
48 static u_int8_t randbuf[16];
51 static int passwd_login(void *obj, struct passwd **uam_pwd,
52 char *ibuf, int ibuflen,
53 char *rbuf, int *rbuflen)
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 };
62 BIGNUM *bn, *gbn, *pbn;
70 if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, (void *) &name, &i) < 0)
73 len = (unsigned char) *ibuf++;
75 return( AFPERR_PARAM );
78 memcpy(name, ibuf, len );
81 if ((unsigned long) ibuf & 1) /* padding */
84 if (( dhxpwd = uam_getname(name, i)) == NULL ) {
88 syslog( LOG_INFO, "dhx login: %s", name);
89 if (uam_checkuser(dhxpwd) < 0)
90 return AFPERR_NOTAUTH;
93 if (( sp = getspnam( dhxpwd->pw_name )) == NULL ) {
94 syslog( LOG_INFO, "no shadow passwd entry for %s", name);
95 return AFPERR_NOTAUTH;
97 dhxpwd->pw_passwd = sp->sp_pwdp;
100 if (!dhxpwd->pw_passwd)
101 return AFPERR_NOTAUTH;
103 /* get the client's public key */
104 if (!(bn = BN_bin2bn(ibuf, KEYSIZE, NULL))) {
109 if (!(gbn = BN_bin2bn(&g, sizeof(g), NULL))) {
114 if (!(pbn = BN_bin2bn(p, sizeof(p), NULL))) {
120 /* okay, we're ready */
121 if (!(dh = DH_new())) {
128 /* generate key and make sure we have enough space */
131 if (!DH_generate_key(dh) || (BN_num_bytes(dh->pub_key) > KEYSIZE)) {
135 /* figure out the key. use rbuf as a temporary buffer. */
136 i = DH_compute_key(rbuf, bn, dh);
139 CAST_set_key(&castkey, i, rbuf);
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);
147 /* send our public key */
148 BN_bn2bin(dh->pub_key, rbuf);
152 /* buffer to be encrypted */
154 if (uam_afpserver_option(obj, UAM_OPTION_RANDNUM, (void *) randbuf,
159 memcpy(rbuf, &randbuf, sizeof(randbuf));
162 /* get the signature. it's always 16 bytes. */
163 if (uam_afpserver_option(obj, UAM_OPTION_SIGNATURE,
164 (void *) &name, NULL) < 0) {
168 memcpy(rbuf + KEYSIZE, name, KEYSIZE);
170 memset(rbuf + KEYSIZE, 0, KEYSIZE);
173 /* encrypt using cast */
174 CAST_cbc_encrypt(rbuf, rbuf, CRYPTBUFLEN, &castkey, iv, CAST_ENCRYPT);
175 *rbuflen += CRYPTBUFLEN;
178 return AFPERR_AUTHCONT;
186 static int passwd_logincont(void *obj, struct passwd **uam_pwd,
187 char *ibuf, int ibuflen,
188 char *rbuf, int *rbuflen)
190 unsigned char iv[] = "LWallace";
191 BIGNUM *bn1, *bn2, *bn3;
197 /* check for session id */
198 memcpy(&sessid, ibuf, sizeof(sessid));
199 if (sessid != dhxhash(obj))
201 ibuf += sizeof(sessid);
203 /* use rbuf as scratch space */
204 CAST_cbc_encrypt(ibuf, rbuf, CRYPT2BUFLEN, &castkey,
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)))
212 if (!(bn2 = BN_bin2bn(randbuf, sizeof(randbuf), NULL))) {
217 /* zero out the random number */
218 memset(rbuf, 0, sizeof(randbuf));
219 memset(randbuf, 0, sizeof(randbuf));
222 if (!(bn3 = BN_new())) {
228 BN_sub(bn3, bn1, bn2);
232 /* okay. is it one more? */
233 if (!BN_is_one(bn3)) {
239 rbuf[PASSWDLEN] = '\0';
240 p = crypt( rbuf, dhxpwd->pw_passwd );
241 memset(rbuf, 0, PASSWDLEN);
242 if ( strcmp( p, dhxpwd->pw_passwd ) == 0 ) {
247 return AFPERR_NOTAUTH;
251 static int uam_setup(const char *path)
253 if (uam_register(UAM_SERVER_LOGIN, path, "DHCAST128",
254 passwd_login, passwd_logincont, NULL) < 0)
256 /*uam_register(UAM_SERVER_PRINTAUTH, path, "DHCAST128",
262 static void uam_cleanup(void)
264 uam_unregister(UAM_SERVER_LOGIN, "DHCAST128");
265 /*uam_unregister(UAM_SERVER_PRINTAUTH, "DHCAST128"); */
268 UAM_MODULE_EXPORT struct uam_export uams_dhx = {
271 uam_setup, uam_cleanup