3 * Copyright (c) 1990,1993 Regents of The University of Michigan.
4 * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu)
5 * All Rights Reserved. See COPYRIGHT.
10 #endif /* HAVE_CONFIG_H */
14 #include <atalk/standards.h>
21 #endif /* HAVE_UNISTD_H */
24 #endif /* HAVE_CRYPT_H */
26 #include <atalk/logger.h>
28 #if defined(GNUTLS_DHX)
29 #include <gnutls/openssl.h>
30 #elif defined(OPENSSL_DHX)
31 #include <openssl/bn.h>
32 #include <openssl/dh.h>
33 #include <openssl/cast.h>
34 #else /* OPENSSL_DHX */
38 #endif /* OPENSSL_DHX */
40 #include <atalk/afp.h>
41 #include <atalk/uam.h>
45 #define CRYPTBUFLEN (KEYSIZE*2)
46 #define CRYPT2BUFLEN (KEYSIZE + PASSWDLEN)
48 /* hash a number to a 16-bit quantity */
49 #define pgphash(a) ((((unsigned long) (a) >> 8) ^ \
50 (unsigned long) (a)) & 0xffff)
53 static struct passwd *pgppwd;
54 static CAST_KEY castkey;
55 static uint8_t randbuf[16];
58 static int pgp_login(void *obj, struct passwd **uam_pwd,
59 char *ibuf, size_t ibuflen,
60 char *rbuf, size_t *rbuflen)
67 if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, (void *) &name, &i) < 0)
70 len = (unsigned char) *ibuf++;
72 return( AFPERR_PARAM );
75 memcpy(name, ibuf, len );
78 if ((unsigned long) ibuf & 1) /* padding */
81 if (( pgppwd = uam_getname(obj, name, i)) == NULL ) {
85 LOG(log_info, logtype_uams, "pgp login: %s", name);
86 if (uam_checkuser(pgppwd) < 0)
87 return AFPERR_NOTAUTH;
89 /* get the challenge */
90 len = (unsigned char) *ibuf++;
93 /* get the signature. it's always 16 bytes. */
94 if (uam_afpserver_option(obj, UAM_OPTION_SIGNATURE,
95 (void *) &name, NULL) < 0) {
99 memcpy(rbuf + KEYSIZE, name, KEYSIZE);
105 static int pgp_logincont(void *obj, struct passwd **uam_pwd,
106 char *ibuf, size_t ibuflen,
107 char *rbuf, size_t *rbuflen)
109 unsigned char iv[] = "RJscorat";
110 BIGNUM *bn1, *bn2, *bn3;
116 /* check for session id */
117 memcpy(&sessid, ibuf, sizeof(sessid));
118 if (sessid != pgphash(obj))
120 ibuf += sizeof(sessid);
122 /* use rbuf as scratch space */
123 CAST_cbc_encrypt(ibuf, rbuf, CRYPT2BUFLEN, &castkey,
126 /* check to make sure that the random number is the same. we
127 * get sent back an incremented random number. */
128 if (!(bn1 = BN_bin2bn(rbuf, KEYSIZE, NULL)))
131 if (!(bn2 = BN_bin2bn(randbuf, sizeof(randbuf), NULL))) {
136 /* zero out the random number */
137 memset(rbuf, 0, sizeof(randbuf));
138 memset(randbuf, 0, sizeof(randbuf));
141 if (!(bn3 = BN_new())) {
147 BN_sub(bn3, bn1, bn2);
151 /* okay. is it one more? */
152 if (!BN_is_one(bn3)) {
159 if ( kcheckuser(*uam_pwd, rbuf) == 0) {
165 rbuf[PASSWDLEN] = '\0';
166 p = crypt( rbuf, pgppwd->pw_passwd );
167 memset(rbuf, 0, PASSWDLEN);
168 if ( strcmp( p, pgppwd->pw_passwd ) == 0 ) {
173 return AFPERR_NOTAUTH;
177 static int uam_setup(const char *path)
179 if (uam_register(UAM_SERVER_LOGIN, path, "PGPuam 1.0",
180 pgp_login, pgp_logincont, NULL) < 0)
186 static void uam_cleanup(void)
188 uam_unregister(UAM_SERVER_LOGIN, "PGPuam 1.0");
191 UAM_MODULE_EXPORT struct uam_export uams_pgp = {
194 uam_setup, uam_cleanup