ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/ermyth/modules/saslserv/crypt.C
Revision: 1.3
Committed: Sat Jul 21 13:23:21 2007 UTC (19 years, 2 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.2: +2 -2 lines
Log Message:
- added rcsid to some files
- more documentation tweaks
- made most protocol commands local to phandler.C
- added ircd metadata (inspircd only for now)
- added inspircd swhois support

File Contents

# User Rev Content
1 pippijn 1.1 /*
2     * 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.3 * $Id: crypt.C,v 1.2 2007-07-21 01:29:10 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     #include <account/myuser.h>
19    
20 pippijn 1.3 static char const rcsid[] = "$Id$";
21 pippijn 1.1
22     struct ss_crypt_listeners : callback::has_listeners
23     {
24     };
25    
26     ss_crypt_listeners listeners;
27    
28     DECLARE_MODULE_V1 ("saslserv/crypt", false, _modinit, _moddeinit, rcsid, "The Ermyth Team <http://ermyth.schmorp.de>");
29    
30     list_t *mechanisms;
31     node_t *mnode;
32     static int mech_start (sasl_session_t *p, char **out, int *out_len);
33     static int mech_step (sasl_session_t *p, char *message, int len, char **out, int *out_len);
34     static void mech_finish (sasl_session_t *p);
35     sasl_mechanism_t mech = { "CRYPT", &mech_start, &mech_step, &mech_finish };
36    
37     struct crypt_status
38     {
39     unsigned char client_data[16];
40     unsigned char server_data[16];
41     unsigned char *password;
42     unsigned char stage;
43     };
44    
45     void
46     _modinit (module_t *m)
47     {
48     MODULE_USE_SYMBOL (mechanisms, "saslserv/main", "sasl_mechanisms");
49     mnode = node_create ();
50     node_add (&mech, mnode, mechanisms);
51     }
52    
53     void
54     _moddeinit ()
55     {
56     node_del (mnode, mechanisms);
57     }
58    
59     /* Protocol synopsis;
60     * S -> C: 16 random bytes
61     * C -> S: 16 random bytes(different from server's random bytes) + username
62     * S -> C: salt from user's pass(possibly generated on the spot)
63     * C -> S: raw MD5 of (server's data + client's data + crypted pass)
64     *
65     * WARNING: this allows the client to log in given just the encrypted password
66     */
67    
68     static int
69     mech_start (sasl_session_t *p, char **out, int *out_len)
70     {
71     struct crypt_status *s;
72     int i;
73    
74     /* Allocate session structure for our crap */
75     p->mechdata = malloc (sizeof (struct crypt_status));
76     s = (struct crypt_status *) p->mechdata;
77     s->stage = 0;
78     s->password = NULL;
79    
80     /* Generate server's random data */
81     for (i = 0; i < 16; i++)
82     s->server_data[i] = (unsigned char) (arc4random () % 256);
83    
84     /* Send data to client */
85     *out = static_cast<char *> (smalloc (16));
86     memcpy (*out, s->server_data, 16);
87     *out_len = 16;
88    
89     return ASASL_MORE;
90     }
91    
92     static int
93     mech_step (sasl_session_t *p, char *message, int len, char **out, int *out_len)
94     {
95     struct crypt_status *s = (struct crypt_status *) p->mechdata;
96     myuser_t *mu;
97     s->stage++;
98    
99     if (s->stage == 1) /* C -> S: username + 16 bytes random data */
100     {
101     char user[64];
102    
103     if (len < 17)
104     return ASASL_FAIL;
105    
106     /* Store client's random data & skip to username */
107     memcpy (s->client_data, message, 16);
108     message += 16;
109     len -= 16;
110    
111     /* Sanitize and check if user exists */
112     strlcpy (user, message, len > 63 ? 64 : len + 1);
113     if (!(mu = myuser_find (user)))
114     return ASASL_FAIL;
115     p->username = strdup (user);
116    
117     /* Send salt from password to client, generating one if necessary */
118     if (mu->flags & MU_CRYPTPASS)
119     {
120     if (strlen (mu->pass) == 13) /* original DES type */
121     {
122     *out_len = 2;
123     *out = static_cast<char *> (smalloc (2));
124     memcpy (*out, mu->pass, 2);
125     }
126     else if (*(mu->pass) == '$') /* FreeBSD MD5 type */
127     {
128     *out_len = strlen (mu->pass) - 22;
129     *out = static_cast<char *> (smalloc (*out_len));
130     memcpy (*out, mu->pass, *out_len);
131     (*out)[(*out_len) - 1] = '$';
132     }
133     s->password = (unsigned char *) strdup (mu->pass);
134     }
135     else
136     {
137     s->password = (unsigned char *) strdup (crypt (mu->pass, gen_salt ()));
138     *out_len = 10;
139     *out = strdup ((char *) s->password);
140     }
141     return ASASL_MORE;
142     }
143     else if (s->stage == 2) /* C -> S: raw MD5 of server random data + client random data + crypted password */
144     {
145     MD5Context ctx;
146     char hash[16];
147    
148     if (len != 16)
149     return ASASL_FAIL;
150    
151     MD5Init (&ctx);
152     MD5Update (&ctx, s->server_data, 16);
153     MD5Update (&ctx, s->client_data, 16);
154     MD5Update (&ctx, s->password, strlen ((char *) s->password));
155     MD5Final ((unsigned char *) hash, &ctx);
156    
157     if (!memcmp (message, hash, 16))
158     return ASASL_DONE;
159     else
160     return ASASL_FAIL;
161     }
162     else /* wtf? */
163     return ASASL_FAIL;
164     }
165    
166     static void
167     mech_finish (sasl_session_t *p)
168     {
169     if (p->mechdata)
170     {
171     struct crypt_status *s = (struct crypt_status *) p->mechdata;
172     free (s->password);
173     free (p->mechdata);
174     }
175     }
176    
177     /* vim:cinoptions=>s,e0,n0,f0,{0,}0,^0,=s,ps,t0,c3,+s,(2s,us,)20,*30,gs,hs
178     * vim:ts=8
179     * vim:sw=8
180     * vim:noexpandtab
181     */