comparison src/protocols/jabber/auth.c @ 8397:b63debdf5a92

[gaim-migrate @ 9126] be more user-friendly about the whole unencrypted plaintext password thing committer: Tailor Script <tailor@pidgin.im>
author Nathan Walp <nwalp@pidgin.im>
date Fri, 05 Mar 2004 16:14:22 +0000
parents dd6fe7d965aa
children c13a4913a071
comparison
equal deleted inserted replaced
8396:387ba791d5f9 8397:b63debdf5a92
29 29
30 #include "debug.h" 30 #include "debug.h"
31 #include "md5.h" 31 #include "md5.h"
32 #include "util.h" 32 #include "util.h"
33 #include "sslconn.h" 33 #include "sslconn.h"
34 #include "request.h"
35
36 static void auth_old_result_cb(JabberStream *js, xmlnode *packet,
37 gpointer data);
34 38
35 gboolean 39 gboolean
36 jabber_process_starttls(JabberStream *js, xmlnode *packet) 40 jabber_process_starttls(JabberStream *js, xmlnode *packet)
37 { 41 {
38 xmlnode *starttls; 42 xmlnode *starttls;
50 } 54 }
51 55
52 return FALSE; 56 return FALSE;
53 } 57 }
54 58
59 static void finish_plaintext_authentication(JabberStream *js)
60 {
61 if(js->auth_type == JABBER_AUTH_PLAIN) {
62 xmlnode *auth;
63 GString *response;
64 char *enc_out;
65
66 auth = xmlnode_new("auth");
67 xmlnode_set_attrib(auth, "xmlns", "urn:ietf:params:xml:ns:xmpp-sasl");
68
69 response = g_string_new("");
70 response = g_string_append_len(response, "\0", 1);
71 response = g_string_append(response, js->user->node);
72 response = g_string_append_len(response, "\0", 1);
73 response = g_string_append(response,
74 gaim_account_get_password(js->gc->account));
75
76 enc_out = gaim_base64_encode(response->str, response->len);
77
78 xmlnode_set_attrib(auth, "mechanism", "PLAIN");
79 xmlnode_insert_data(auth, enc_out, -1);
80 g_free(enc_out);
81 g_string_free(response, TRUE);
82
83 jabber_send(js, auth);
84 xmlnode_free(auth);
85 } else if(js->auth_type == JABBER_AUTH_IQ_AUTH) {
86 JabberIq *iq;
87 xmlnode *query, *x;
88
89 iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:auth");
90 query = xmlnode_get_child(iq->node, "query");
91 x = xmlnode_new_child(query, "username");
92 xmlnode_insert_data(x, js->user->node, -1);
93 x = xmlnode_new_child(query, "resource");
94 xmlnode_insert_data(x, js->user->resource, -1);
95 x = xmlnode_new_child(query, "password");
96 xmlnode_insert_data(x, gaim_account_get_password(js->gc->account), -1);
97 jabber_iq_set_callback(iq, auth_old_result_cb, NULL);
98 jabber_iq_send(iq);
99 }
100 }
101
102 static void allow_plaintext_auth(GaimAccount *account)
103 {
104 gaim_account_set_bool(account, "auth_plain_in_clear", TRUE);
105
106 finish_plaintext_authentication(account->gc->proto_data);
107 }
108
109 static void disallow_plaintext_auth(GaimAccount *account)
110 {
111 gaim_connection_error(account->gc, _("Server requires plaintext authentication over an unencrypted stream"));
112 }
113
55 void 114 void
56 jabber_auth_start(JabberStream *js, xmlnode *packet) 115 jabber_auth_start(JabberStream *js, xmlnode *packet)
57 { 116 {
58 xmlnode *mechs, *mechnode; 117 xmlnode *mechs, *mechnode;
59 xmlnode *auth;
60 118
61 gboolean digest_md5 = FALSE, plain=FALSE; 119 gboolean digest_md5 = FALSE, plain=FALSE;
62 120
63 121
64 if(js->registration) { 122 if(js->registration) {
82 else if(mech_name && !strcmp(mech_name, "PLAIN")) 140 else if(mech_name && !strcmp(mech_name, "PLAIN"))
83 plain = TRUE; 141 plain = TRUE;
84 g_free(mech_name); 142 g_free(mech_name);
85 } 143 }
86 144
87 auth = xmlnode_new("auth");
88 xmlnode_set_attrib(auth, "xmlns", "urn:ietf:params:xml:ns:xmpp-sasl");
89 145
90 if(digest_md5) { 146 if(digest_md5) {
147 xmlnode *auth;
148
149 js->auth_type = JABBER_AUTH_DIGEST_MD5;
150 auth = xmlnode_new("auth");
151 xmlnode_set_attrib(auth, "xmlns", "urn:ietf:params:xml:ns:xmpp-sasl");
91 xmlnode_set_attrib(auth, "mechanism", "DIGEST-MD5"); 152 xmlnode_set_attrib(auth, "mechanism", "DIGEST-MD5");
92 js->auth_type = JABBER_AUTH_DIGEST_MD5; 153
154 jabber_send(js, auth);
155 xmlnode_free(auth);
93 } else if(plain) { 156 } else if(plain) {
94 GString *response; 157 js->auth_type = JABBER_AUTH_PLAIN;
95 char *enc_out;
96 158
97 if(js->gsc == NULL && !gaim_account_get_bool(js->gc->account, "auth_plain_in_clear", FALSE)) { 159 if(js->gsc == NULL && !gaim_account_get_bool(js->gc->account, "auth_plain_in_clear", FALSE)) {
98 /* XXX: later, make this yes/no so they can just click to enable it */ 160 gaim_request_yes_no(js->gc, _("Plaintext Authentication"),
99 gaim_connection_error(js->gc, 161 _("Plaintext Authentication"),
100 _("Server requires plaintext authentication over an unencrypted stream")); 162 _("This server requires plaintext authentication over an unencrypted connection. Allow this and continue authentication?"),
101 xmlnode_free(auth); 163 2, js->gc->account, allow_plaintext_auth,
164 disallow_plaintext_auth);
102 return; 165 return;
103 } 166 }
104 167 finish_plaintext_authentication(js);
105 response = g_string_new("");
106 response = g_string_append_len(response, "\0", 1);
107 response = g_string_append(response, js->user->node);
108 response = g_string_append_len(response, "\0", 1);
109 response = g_string_append(response,
110 gaim_account_get_password(js->gc->account));
111
112 enc_out = gaim_base64_encode(response->str, response->len);
113
114 xmlnode_set_attrib(auth, "mechanism", "PLAIN");
115 xmlnode_insert_data(auth, enc_out, -1);
116 g_free(enc_out);
117 g_string_free(response, TRUE);
118
119 js->auth_type = JABBER_AUTH_PLAIN;
120 } else { 168 } else {
121 gaim_connection_error(js->gc, 169 gaim_connection_error(js->gc,
122 _("Server does not use any supported authentication method")); 170 _("Server does not use any supported authentication method"));
123 xmlnode_free(auth); 171 }
124 return;
125 }
126
127 jabber_send(js, auth);
128 xmlnode_free(auth);
129 } 172 }
130 173
131 static void auth_old_result_cb(JabberStream *js, xmlnode *packet, gpointer data) 174 static void auth_old_result_cb(JabberStream *js, xmlnode *packet, gpointer data)
132 { 175 {
133 const char *type = xmlnode_get_attrib(packet, "type"); 176 const char *type = xmlnode_get_attrib(packet, "type");
164 207
165 static void auth_old_cb(JabberStream *js, xmlnode *packet, gpointer data) 208 static void auth_old_cb(JabberStream *js, xmlnode *packet, gpointer data)
166 { 209 {
167 JabberIq *iq; 210 JabberIq *iq;
168 xmlnode *query, *x; 211 xmlnode *query, *x;
169 gboolean digest = FALSE;
170 const char *type = xmlnode_get_attrib(packet, "type"); 212 const char *type = xmlnode_get_attrib(packet, "type");
171 const char *pw = gaim_account_get_password(js->gc->account); 213 const char *pw = gaim_account_get_password(js->gc->account);
172 214
173 if(!type) { 215 if(!type) {
174 gaim_connection_error(js->gc, _("Invalid response from server.")); 216 gaim_connection_error(js->gc, _("Invalid response from server."));
189 g_free(err_txt); 231 g_free(err_txt);
190 g_free(buf); 232 g_free(buf);
191 } else if(!strcmp(type, "result")) { 233 } else if(!strcmp(type, "result")) {
192 query = xmlnode_get_child(packet, "query"); 234 query = xmlnode_get_child(packet, "query");
193 if(js->stream_id && xmlnode_get_child(query, "digest")) { 235 if(js->stream_id && xmlnode_get_child(query, "digest")) {
194 digest = TRUE;
195 } else if(xmlnode_get_child(query, "password")) {
196 if(js->gsc == NULL && !gaim_account_get_bool(js->gc->account,
197 "auth_plain_in_clear", FALSE)) {
198 /* XXX: later, make this yes/no so they can just click to enable it */
199 gaim_connection_error(js->gc,
200 _("Server requires plaintext authentication over an unencrypted stream"));
201 return;
202 }
203 } else {
204 gaim_connection_error(js->gc,
205 _("Server does not use any supported authentication method"));
206 return;
207 }
208
209 iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:auth");
210 query = xmlnode_get_child(iq->node, "query");
211 x = xmlnode_new_child(query, "username");
212 xmlnode_insert_data(x, js->user->node, -1);
213 x = xmlnode_new_child(query, "resource");
214 xmlnode_insert_data(x, js->user->resource, -1);
215
216 if(digest) {
217 unsigned char hashval[20]; 236 unsigned char hashval[20];
218 char *s, h[41], *p; 237 char *s, h[41], *p;
219 int i; 238 int i;
239
240 iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:auth");
241 query = xmlnode_get_child(iq->node, "query");
242 x = xmlnode_new_child(query, "username");
243 xmlnode_insert_data(x, js->user->node, -1);
244 x = xmlnode_new_child(query, "resource");
245 xmlnode_insert_data(x, js->user->resource, -1);
220 246
221 x = xmlnode_new_child(query, "digest"); 247 x = xmlnode_new_child(query, "digest");
222 s = g_strdup_printf("%s%s", js->stream_id, pw); 248 s = g_strdup_printf("%s%s", js->stream_id, pw);
223 shaBlock((unsigned char *)s, strlen(s), hashval); 249 shaBlock((unsigned char *)s, strlen(s), hashval);
224 p = h; 250 p = h;
225 for(i=0; i<20; i++, p+=2) 251 for(i=0; i<20; i++, p+=2)
226 snprintf(p, 3, "%02x", hashval[i]); 252 snprintf(p, 3, "%02x", hashval[i]);
227 xmlnode_insert_data(x, h, -1); 253 xmlnode_insert_data(x, h, -1);
228 g_free(s); 254 g_free(s);
255 jabber_iq_set_callback(iq, auth_old_result_cb, NULL);
256 jabber_iq_send(iq);
257
258 } else if(xmlnode_get_child(query, "password")) {
259 if(js->gsc == NULL && !gaim_account_get_bool(js->gc->account,
260 "auth_plain_in_clear", FALSE)) {
261 gaim_request_yes_no(js->gc, _("Plaintext Authentication"),
262 _("Plaintext Authentication"),
263 _("This server requires plaintext authentication over an unencrypted connection. Allow this and continue authentication?"),
264 2, js->gc->account, allow_plaintext_auth,
265 disallow_plaintext_auth);
266 return;
267 }
268 finish_plaintext_authentication(js);
229 } else { 269 } else {
230 x = xmlnode_new_child(query, "password"); 270 gaim_connection_error(js->gc,
231 xmlnode_insert_data(x, pw, -1); 271 _("Server does not use any supported authentication method"));
232 } 272 return;
233 273 }
234 jabber_iq_set_callback(iq, auth_old_result_cb, NULL);
235
236 jabber_iq_send(iq);
237 } 274 }
238 } 275 }
239 276
240 void jabber_auth_start_old(JabberStream *js) 277 void jabber_auth_start_old(JabberStream *js)
241 { 278 {