ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/modules/saslserv/dh-blowfish.C
Revision: 1.8
Committed: Sat Sep 22 14:27:30 2007 UTC (16 years, 8 months ago) by pippijn
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.7: +3 -3 lines
Log Message:
split up ermyth into ermyth-modules, libermyth (currently just ermyth-util) and ermyth-core

File Contents

# Content
1 /**
2 * dh.C: DH-BLOWFISH mechanism provider
3 *
4 * Copyright © 2007 Pippijn van Steenhoven / The Ermyth Team
5 * Rights to this code are as documented in COPYING.
6 *
7 *
8 * Portions of this file were derived from sources bearing the following license:
9 * Copyright © 2006 Atheme Development Group
10 * Rights to this code are as documented in doc/pod/license.pod.
11 *
12 * $Id: dh-blowfish.C,v 1.7 2007-09-16 18:54:44 pippijn Exp $
13 */
14
15 #include "atheme.h"
16 #include <ermyth/module.h>
17 #include <account/myuser.h>
18 #include <sasl.h>
19
20 #ifdef HAVE_OPENSSL
21
22 #include <openssl/bn.h>
23 #include <openssl/dh.h>
24 #include <openssl/blowfish.h>
25 #include <arpa/inet.h>
26
27 static char const rcsid[] = "$Id: dh-blowfish.C,v 1.7 2007-09-16 18:54:44 pippijn Exp $";
28
29 REGISTER_MODULE ("saslserv/dh-blowfish", false, "The Ermyth Team <http://ermyth.xinutec.org>");
30
31 E list_t sasl_mechanisms;
32 static node_t *mnode;
33
34 static int mech_start (sasl_session_t *p, char **out, int *out_len);
35 static int mech_step (sasl_session_t *p, char *message, int len, char **out, int *out_len);
36 static void mech_finish (sasl_session_t *p);
37 static sasl_mechanism_t mech ("DH-BLOWFISH", &mech_start, &mech_step, &mech_finish);
38
39 bool
40 _modinit (module *m)
41 {
42 mnode = node_create ();
43 node_add (&mech, mnode, &sasl_mechanisms);
44
45 return true;
46 }
47
48 void
49 _moddeinit ()
50 {
51 node_del (mnode, &sasl_mechanisms);
52 node_free (mnode);
53 }
54
55 static int
56 mech_start (sasl_session_t *p, char **out, int *out_len)
57 {
58 DH *dh;
59 char *ptr;
60
61 if ((dh = DH_generate_parameters (256, 5, NULL, NULL)) == NULL)
62 return ASASL_FAIL;
63
64 if (!DH_generate_key (dh))
65 {
66 DH_free (dh);
67 return ASASL_FAIL;
68 }
69
70 /* Serialize p, g, and pub_key */
71 *out = salloc<char> (BN_num_bytes (dh->p) + BN_num_bytes (dh->g) + BN_num_bytes (dh->pub_key) + 6);
72 *out_len = BN_num_bytes (dh->p) + BN_num_bytes (dh->g) + BN_num_bytes (dh->pub_key) + 6;
73 ptr = *out;
74
75 /* p */
76 *((unsigned int *) ptr) = htons (BN_num_bytes (dh->p));
77 BN_bn2bin (dh->p, (unsigned char *) ptr + 2);
78 ptr += 2 + BN_num_bytes (dh->p);
79
80 /* g */
81 *((unsigned int *) ptr) = htons (BN_num_bytes (dh->g));
82 BN_bn2bin (dh->g, (unsigned char *) ptr + 2);
83 ptr += 2 + BN_num_bytes (dh->g);
84
85 /* pub_key */
86 *((unsigned int *) ptr) = htons (BN_num_bytes (dh->pub_key));
87 BN_bn2bin (dh->pub_key, (unsigned char *) ptr + 2);
88 ptr += 2 + BN_num_bytes (dh->pub_key);
89
90 p->mechdata = dh;
91 return ASASL_MORE;
92 }
93
94 static int
95 mech_step (sasl_session_t *p, char *message, int len, char **out, int *out_len)
96 {
97 DH *dh = NULL;
98 BF_KEY key;
99 BIGNUM *their_key = NULL;
100 myuser_t *mu;
101 char *ptr, *secret = NULL, *password = NULL;
102 int size, ret = ASASL_FAIL;
103
104 if (!p->mechdata)
105 return ASASL_FAIL;
106 dh = (DH *) p->mechdata;
107
108 /* Their pub_key */
109 if (len < 2)
110 goto end;
111 size = ntohs (*(unsigned int *) message);
112 message += 2;
113 len -= 2;
114 if (size > len)
115 goto end;
116 if ((their_key = BN_bin2bn ((unsigned char *) message, size, NULL)) == NULL)
117 goto end;
118 message += size;
119 len -= size;
120
121 /* Username */
122 size = strlen (message);
123 if (size >= NICKLEN) /* our base64 routines null-terminate - how polite */
124 goto end;
125 p->username = strdup (message);
126 message += size + 1;
127 len -= size + 1;
128 if ((mu = myuser_t::find (p->username)) == NULL)
129 goto end;
130 /* AES-encrypted password remains */
131
132 /* Compute shared secret */
133 secret = salloc<char> (DH_size (dh));
134 if ((size = DH_compute_key ((unsigned char *) secret, their_key, dh)) == -1)
135 goto end;
136
137 /* Data must be multiple of block size, and let's be reasonable about size */
138 if (len == 0 || len % 8 || len > 128)
139 goto end;
140
141 /* Decrypt! */
142 BF_set_key (&key, size, (unsigned char *) secret);
143 ptr = password = salloc<char> (len + 1);
144 password[len] = '\0';
145 while (len)
146 {
147 BF_ecb_encrypt ((unsigned char *) message, (unsigned char *) ptr, &key, BF_DECRYPT);
148 message += 8;
149 ptr += 8;
150 len -= 8;
151 }
152
153 if (mu->verify_password (password))
154 ret = ASASL_DONE;
155
156 end:
157 if (their_key)
158 BN_free (their_key);
159 sfree (secret);
160 sfree (password);
161 return ret;
162 }
163
164 static void
165 mech_finish (sasl_session_t *p)
166 {
167 if (p && p->mechdata)
168 {
169 DH_free ((DH *) p->mechdata);
170 p->mechdata = NULL;
171 }
172 }
173
174 #endif /* HAVE_OPENSSL */