ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/ermyth/modules/saslserv/crypt.C
Revision: 1.4
Committed: Tue Aug 28 17:08:12 2007 UTC (19 years, 1 month ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.3: +25 -32 lines
Log Message:
- changed name
- updated the example config to the new system
- added more documentation
- enhanced documentation generators
- added a link to the pdf to the website
- added an RSS feed generator
- transitioned hooks to c++ callbacks
- did various merges with upstream along the way
- added const where appropriate
- removed the old block allocator
- fixed most memory leaks
- transitioned some dictionaries to std::map
- transitioned some lists to std::vector
- made some free functions members where appropriate
- renamed string to dynstr and added a static string ststr
- use NOW instead of time (NULL) if possible
- completely reworked database backends, crypto handlers and protocol handlers
  to use an object factory
- removed the old module system. ermyth does not do any dynamic loading anymore
- fixed most of the build system
- reworked how protocol commands work

File Contents

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