2 * $Id: uams_pgp.c,v 1.10 2003-06-11 07:26:50 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.
11 #endif /* HAVE_CONFIG_H */
22 #endif /* HAVE_UNISTD_H */
24 #include <atalk/logger.h>
26 #if defined(GNUTLS_DHX)
27 #include <gnutls/openssl.h>
28 #elif defined(OPENSSL_DHX)
29 #include <openssl/bn.h>
30 #include <openssl/dh.h>
31 #include <openssl/cast.h>
32 #else /* OPENSSL_DHX */
36 #endif /* OPENSSL_DHX */
38 #include <atalk/afp.h>
39 #include <atalk/uam.h>
43 #define CRYPTBUFLEN (KEYSIZE*2)
44 #define CRYPT2BUFLEN (KEYSIZE + PASSWDLEN)
46 /* hash a number to a 16-bit quantity */
47 #define pgphash(a) ((((unsigned long) (a) >> 8) ^ \
48 (unsigned long) (a)) & 0xffff)
51 static struct passwd *pgppwd;
52 static CAST_KEY castkey;
53 static u_int8_t randbuf[16];
56 static int pgp_login(void *obj, struct passwd **uam_pwd,
57 char *ibuf, int ibuflen,
58 char *rbuf, int *rbuflen)
60 BIGNUM *bn, *gbn, *pbn;
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(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, int ibuflen,
107 char *rbuf, int *rbuflen)
109 unsigned char iv[] = "RJscorat";
111 GcryMPI *bn1, *bn2, *bn3;
112 #else /* HAVE_GCRYPT */
113 BIGNUM *bn1, *bn2, *bn3;
120 /* check for session id */
121 memcpy(&sessid, ibuf, sizeof(sessid));
122 if (sessid != pgphash(obj))
124 ibuf += sizeof(sessid);
130 handle = gcry_cipher_open(GCRY_CIPHER_CAST5,
131 GCRY_CIPHER_MODE_CBC, 0);
135 if (gcry_cipher_setkey(handle, &castkey, ) != 0) {
136 gcry_cipher_close(handle);
140 if (gcry_cipher_setiv(handle, iv, sizeof(iv)) != 0) {
141 gcry_cipher_close(handle);
145 if (gcry_cipher_decrypt(handle, rbuf, CRYPT2BUFLEN, ibuf, CRYPT2BUFLEN) != 0) {
146 gcry_cipher_close(handle);
150 gcry_cipher_close(handle);
152 #else /* HAVE_GCRYPT */
153 /* use rbuf as scratch space */
154 CAST_cbc_encrypt(ibuf, rbuf, CRYPT2BUFLEN, &castkey,
156 #endif /* HAVE_GCRYPT */
162 bn1 = gcry_mpi_snew(KEYSIZE * 8);
164 gcry_mpi_scan(bn1, GCRYMPI_FMT_STD, rbuf, &sz);
165 bn2 = gcry_mpi_snew(sizeof(randbuf) * 8);
166 sz = sizeof(randbuf);
167 gcry_mpi_scan(bn1, GCRYMPI_FMT_STD, randbuf. &sz);
169 #else /* HAVE_GCRYPT */
170 /* check to make sure that the random number is the same. we
171 * get sent back an incremented random number. */
172 if (!(bn1 = BN_bin2bn(rbuf, KEYSIZE, NULL)))
175 if (!(bn2 = BN_bin2bn(randbuf, sizeof(randbuf), NULL))) {
179 #endif /* HAVE_GCRYPT */
181 /* zero out the random number */
182 memset(rbuf, 0, sizeof(randbuf));
183 memset(randbuf, 0, sizeof(randbuf));
187 bn3 = gcry_mpi_snew(0);
188 gcry_mpi_sub(bn3, bn1, bn2);
189 gcry_mpi_release(bn2);
190 gcry_mpi_release(bn1);
192 if (gcry_mpi_cmp_ui(bn3, 1UL) != 0) {
193 gcry_mpi_release(bn3);
196 gcry_mpi_release(bn3);
197 #else /* HAVE_GCRYPT */
198 if (!(bn3 = BN_new())) {
204 BN_sub(bn3, bn1, bn2);
208 /* okay. is it one more? */
209 if (!BN_is_one(bn3)) {
214 #endif /* HAVE_GCRYPT */
217 if ( kcheckuser(*uam_pwd, rbuf) == 0) {
223 rbuf[PASSWDLEN] = '\0';
224 p = crypt( rbuf, pgppwd->pw_passwd );
225 memset(rbuf, 0, PASSWDLEN);
226 if ( strcmp( p, pgppwd->pw_passwd ) == 0 ) {
231 return AFPERR_NOTAUTH;
235 static int uam_setup(const char *path)
237 if (uam_register(UAM_SERVER_LOGIN, path, "PGPuam 1.0",
238 pgp_login, pgp_logincont, NULL) < 0)
244 static void uam_cleanup(void)
246 uam_unregister(UAM_SERVER_LOGIN, "PGPuam 1.0");
249 UAM_MODULE_EXPORT struct uam_export uams_pgp = {
252 uam_setup, uam_cleanup