ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/ermyth/modules/saslserv/crypt.C
Revision: 1.7
Committed: Sun Sep 16 18:54:44 2007 UTC (19 years ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.6: +10 -5 lines
Log Message:
#defines to enum

File Contents

# User Rev Content
1 pippijn 1.7 /**
2     * crypt.C: CRYPT 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 pippijn 1.4 * Copyright © 2006 Atheme Development Group
10 pippijn 1.2 * Rights to this code are as documented in doc/pod/license.pod.
11 pippijn 1.1 *
12 pippijn 1.7 * $Id: crypt.C,v 1.6 2007-08-30 19:56:24 pippijn Exp $
13 pippijn 1.1 */
14    
15     /******************************* WARNING ******************************************
16     * This mechanism presents a vulnerability that allows any user to be logged in *
17     * providing their crytped password is known. This allows attackers with a stolen *
18     * DB or crypted password to instantly log in using only the crypted password and *
19     * without cracking or brute-forcing. If you use this, guard your DB closely! *
20     **********************************************************************************/
21    
22     #include "atheme.h"
23 pippijn 1.4 #include <ermyth/crypto.h>
24     #include <ermyth/module.h>
25 pippijn 1.1 #include <account/myuser.h>
26 pippijn 1.4 #include <common/random.h>
27     #include <sasl.h>
28 pippijn 1.1
29 pippijn 1.7 static char const rcsid[] = "$Id: crypt.C,v 1.6 2007-08-30 19:56:24 pippijn Exp $";
30 pippijn 1.1
31 pippijn 1.4 REGISTER_MODULE ("saslserv/crypt", false, "The Ermyth Team <http://ermyth.schmorp.de>");
32 pippijn 1.1
33 pippijn 1.4 E list_t sasl_mechanisms;
34     static node_t *mnode;
35 pippijn 1.1 static int mech_start (sasl_session_t *p, char **out, int *out_len);
36     static int mech_step (sasl_session_t *p, char *message, int len, char **out, int *out_len);
37     static void mech_finish (sasl_session_t *p);
38 pippijn 1.4 static sasl_mechanism_t mech ("CRYPT", &mech_start, &mech_step, &mech_finish);
39 pippijn 1.1
40     struct crypt_status
41     {
42     unsigned char client_data[16];
43     unsigned char server_data[16];
44     unsigned char *password;
45     unsigned char stage;
46     };
47    
48 pippijn 1.4 bool
49     _modinit (module *m)
50 pippijn 1.1 {
51     mnode = node_create ();
52 pippijn 1.4 node_add (&mech, mnode, &sasl_mechanisms);
53    
54     return true;
55 pippijn 1.1 }
56    
57     void
58     _moddeinit ()
59     {
60 pippijn 1.4 node_del (mnode, &sasl_mechanisms);
61 pippijn 1.1 }
62    
63     /* Protocol synopsis;
64     * S -> C: 16 random bytes
65     * C -> S: 16 random bytes(different from server's random bytes) + username
66     * S -> C: salt from user's pass(possibly generated on the spot)
67     * C -> S: raw MD5 of (server's data + client's data + crypted pass)
68     *
69     * WARNING: this allows the client to log in given just the encrypted password
70     */
71    
72     static int
73     mech_start (sasl_session_t *p, char **out, int *out_len)
74     {
75     struct crypt_status *s;
76     int i;
77    
78     /* Allocate session structure for our crap */
79 pippijn 1.4 p->mechdata = new crypt_status;
80 pippijn 1.1 s = (struct crypt_status *) p->mechdata;
81     s->stage = 0;
82     s->password = NULL;
83    
84     /* Generate server's random data */
85     for (i = 0; i < 16; i++)
86 pippijn 1.4 s->server_data[i] = (unsigned char) (gen_rand32 () % 256);
87 pippijn 1.1
88     /* Send data to client */
89 pippijn 1.6 *out = salloc<char> (16);
90 pippijn 1.1 memcpy (*out, s->server_data, 16);
91     *out_len = 16;
92    
93     return ASASL_MORE;
94     }
95    
96     static int
97     mech_step (sasl_session_t *p, char *message, int len, char **out, int *out_len)
98     {
99     struct crypt_status *s = (struct crypt_status *) p->mechdata;
100     myuser_t *mu;
101     s->stage++;
102    
103     if (s->stage == 1) /* C -> S: username + 16 bytes random data */
104     {
105     char user[64];
106    
107     if (len < 17)
108     return ASASL_FAIL;
109    
110     /* Store client's random data & skip to username */
111     memcpy (s->client_data, message, 16);
112     message += 16;
113     len -= 16;
114    
115     /* Sanitize and check if user exists */
116     strlcpy (user, message, len > 63 ? 64 : len + 1);
117 pippijn 1.5 if (!(mu = myuser_t::find (user)))
118 pippijn 1.1 return ASASL_FAIL;
119     p->username = strdup (user);
120    
121     /* Send salt from password to client, generating one if necessary */
122     if (mu->flags & MU_CRYPTPASS)
123     {
124     if (strlen (mu->pass) == 13) /* original DES type */
125     {
126     *out_len = 2;
127 pippijn 1.6 *out = salloc<char> (2);
128 pippijn 1.1 memcpy (*out, mu->pass, 2);
129     }
130     else if (*(mu->pass) == '$') /* FreeBSD MD5 type */
131     {
132     *out_len = strlen (mu->pass) - 22;
133 pippijn 1.6 *out = salloc<char> (*out_len);
134 pippijn 1.1 memcpy (*out, mu->pass, *out_len);
135     (*out)[(*out_len) - 1] = '$';
136     }
137     s->password = (unsigned char *) strdup (mu->pass);
138     }
139     else
140     {
141 pippijn 1.4 s->password = (unsigned char *) strdup (crypt (mu->pass, crypto::gen_salt ()));
142 pippijn 1.1 *out_len = 10;
143     *out = strdup ((char *) s->password);
144     }
145     return ASASL_MORE;
146     }
147     else if (s->stage == 2) /* C -> S: raw MD5 of server random data + client random data + crypted password */
148     {
149     MD5Context ctx;
150     char hash[16];
151    
152     if (len != 16)
153     return ASASL_FAIL;
154    
155     MD5Init (&ctx);
156     MD5Update (&ctx, s->server_data, 16);
157     MD5Update (&ctx, s->client_data, 16);
158     MD5Update (&ctx, s->password, strlen ((char *) s->password));
159     MD5Final ((unsigned char *) hash, &ctx);
160    
161     if (!memcmp (message, hash, 16))
162     return ASASL_DONE;
163     else
164     return ASASL_FAIL;
165     }
166     else /* wtf? */
167     return ASASL_FAIL;
168     }
169    
170     static void
171     mech_finish (sasl_session_t *p)
172     {
173     if (p->mechdata)
174     {
175     struct crypt_status *s = (struct crypt_status *) p->mechdata;
176 pippijn 1.4 sfree (s->password);
177     sfree (p->mechdata);
178 pippijn 1.1 }
179     }