comparison libpurple/protocols/oscar/clientlogin.c @ 31085:4297feb30ad1

Merged everything related to ICQ server changes. applied changes from b6d7712e90b68610df3bd2d8cbaf46d94c8b3794 through d849dc2a852a4ffdd345a150f0b88ab37de36e36 applied changes from 7aedaac3ed815cab16d758474a829d5ec5a59e4b through d849dc2a852a4ffdd345a150f0b88ab37de36e36
author ivan.komarov@soc.pidgin.im
date Sat, 30 Oct 2010 21:36:34 +0000
parents 943fce8ef142
children d9e21370fca0
comparison
equal deleted inserted replaced
31084:a61147460879 31085:4297feb30ad1
40 #include "oscarcommon.h" 40 #include "oscarcommon.h"
41 41
42 #include "cipher.h" 42 #include "cipher.h"
43 #include "core.h" 43 #include "core.h"
44 44
45 #define URL_CLIENT_LOGIN "https://api.screenname.aol.com/auth/clientLogin" 45 #define AIM_LOGIN_HOST "api.screenname.aol.com"
46 #define URL_START_OSCAR_SESSION "https://api.oscar.aol.com/aim/startOSCARSession" 46 #define ICQ_LOGIN_HOST "api.login.icq.net"
47
48 #define AIM_API_HOST "api.oscar.aol.com"
49 #define ICQ_API_HOST "api.icq.net"
50
51 #define CLIENT_LOGIN_PAGE "/auth/clientLogin"
52 #define START_OSCAR_SESSION_PAGE "/aim/startOSCARSession"
53
54 #define HTTPS_FORMAT_URL(host, page) "https://" host page
55
56 static const gchar *client_login_urls[] = {
57 HTTPS_FORMAT_URL(AIM_LOGIN_HOST, CLIENT_LOGIN_PAGE),
58 HTTPS_FORMAT_URL(ICQ_LOGIN_HOST, CLIENT_LOGIN_PAGE),
59 };
60
61 static const gchar *start_oscar_session_urls[] = {
62 HTTPS_FORMAT_URL(AIM_API_HOST, START_OSCAR_SESSION_PAGE),
63 HTTPS_FORMAT_URL(ICQ_API_HOST, START_OSCAR_SESSION_PAGE),
64 };
65
66 static const gchar *get_client_login_url(OscarData *od)
67 {
68 return client_login_urls[od->icq];
69 }
70
71 static const gchar *get_start_oscar_session_url(OscarData *od)
72 {
73 return start_oscar_session_urls[od->icq];
74 }
47 75
48 /* 76 /*
49 * Using clientLogin requires a developer ID. This key is for libpurple. 77 * Using clientLogin requires a developer ID. This key is for libpurple.
50 * It is the default key for all libpurple-based clients. AOL encourages 78 * It is the default key for all libpurple-based clients. AOL encourages
51 * UIs (especially ones with lots of users) to override this with their 79 * UIs (especially ones with lots of users) to override this with their
123 return signature; 151 return signature;
124 } 152 }
125 153
126 static gboolean parse_start_oscar_session_response(PurpleConnection *gc, const gchar *response, gsize response_len, char **host, unsigned short *port, char **cookie, char **tls_certname) 154 static gboolean parse_start_oscar_session_response(PurpleConnection *gc, const gchar *response, gsize response_len, char **host, unsigned short *port, char **cookie, char **tls_certname)
127 { 155 {
156 OscarData *od = purple_connection_get_protocol_data(gc);
128 xmlnode *response_node, *tmp_node, *data_node; 157 xmlnode *response_node, *tmp_node, *data_node;
129 xmlnode *host_node = NULL, *port_node = NULL, *cookie_node = NULL, *tls_node = NULL; 158 xmlnode *host_node = NULL, *port_node = NULL, *cookie_node = NULL, *tls_node = NULL;
130 gboolean use_tls; 159 gboolean use_tls;
131 char *tmp; 160 char *tmp;
132 guint code; 161 guint code;
140 char *msg; 169 char *msg;
141 purple_debug_error("oscar", "startOSCARSession could not parse " 170 purple_debug_error("oscar", "startOSCARSession could not parse "
142 "response as XML: %s\n", response); 171 "response as XML: %s\n", response);
143 /* Note to translators: %s in this string is a URL */ 172 /* Note to translators: %s in this string is a URL */
144 msg = generate_error_message(response_node, 173 msg = generate_error_message(response_node,
145 URL_START_OSCAR_SESSION); 174 get_start_oscar_session_url(od));
146 purple_connection_error_reason(gc, 175 purple_connection_error_reason(gc,
147 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); 176 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
148 g_free(msg); 177 g_free(msg);
149 return FALSE; 178 return FALSE;
150 } 179 }
163 if (tmp_node == NULL || (tmp = xmlnode_get_data_unescaped(tmp_node)) == NULL) { 192 if (tmp_node == NULL || (tmp = xmlnode_get_data_unescaped(tmp_node)) == NULL) {
164 char *msg; 193 char *msg;
165 purple_debug_error("oscar", "startOSCARSession response was " 194 purple_debug_error("oscar", "startOSCARSession response was "
166 "missing statusCode: %s\n", response); 195 "missing statusCode: %s\n", response);
167 msg = generate_error_message(response_node, 196 msg = generate_error_message(response_node,
168 URL_START_OSCAR_SESSION); 197 get_start_oscar_session_url(od));
169 purple_connection_error_reason(gc, 198 purple_connection_error_reason(gc,
170 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); 199 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
171 g_free(msg); 200 g_free(msg);
172 xmlnode_free(response_node); 201 xmlnode_free(response_node);
173 return FALSE; 202 return FALSE;
201 "you continue to try, you will need to wait even " 230 "you continue to try, you will need to wait even "
202 "longer.")); 231 "longer."));
203 else { 232 else {
204 char *msg; 233 char *msg;
205 msg = generate_error_message(response_node, 234 msg = generate_error_message(response_node,
206 URL_START_OSCAR_SESSION); 235 get_start_oscar_session_url(od));
207 purple_connection_error_reason(gc, 236 purple_connection_error_reason(gc,
208 PURPLE_CONNECTION_ERROR_OTHER_ERROR, msg); 237 PURPLE_CONNECTION_ERROR_OTHER_ERROR, msg);
209 g_free(msg); 238 g_free(msg);
210 } 239 }
211 240
214 return FALSE; 243 return FALSE;
215 } 244 }
216 g_free(tmp); 245 g_free(tmp);
217 246
218 /* Make sure we have everything else */ 247 /* Make sure we have everything else */
219 if (data_node == NULL || host_node == NULL || 248 if (data_node == NULL || host_node == NULL || port_node == NULL || cookie_node == NULL)
220 port_node == NULL || cookie_node == NULL ||
221 (use_tls && tls_node == NULL))
222 { 249 {
223 char *msg; 250 char *msg;
224 purple_debug_error("oscar", "startOSCARSession response was missing " 251 purple_debug_error("oscar", "startOSCARSession response was missing "
225 "something: %s\n", response); 252 "something: %s\n", response);
226 msg = generate_error_message(response_node, 253 msg = generate_error_message(response_node,
227 URL_START_OSCAR_SESSION); 254 get_start_oscar_session_url(od));
228 purple_connection_error_reason(gc, 255 purple_connection_error_reason(gc,
229 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); 256 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
230 g_free(msg); 257 g_free(msg);
231 xmlnode_free(response_node); 258 xmlnode_free(response_node);
232 return FALSE; 259 return FALSE;
235 /* Extract data from the XML */ 262 /* Extract data from the XML */
236 *host = xmlnode_get_data_unescaped(host_node); 263 *host = xmlnode_get_data_unescaped(host_node);
237 tmp = xmlnode_get_data_unescaped(port_node); 264 tmp = xmlnode_get_data_unescaped(port_node);
238 *cookie = xmlnode_get_data_unescaped(cookie_node); 265 *cookie = xmlnode_get_data_unescaped(cookie_node);
239 266
240 if (use_tls) 267 if (use_tls) {
241 *tls_certname = xmlnode_get_data_unescaped(tls_node); 268 if (tls_node != NULL) {
242 269 *tls_certname = xmlnode_get_data_unescaped(tls_node);
243 if (*host == NULL || **host == '\0' || tmp == NULL || *tmp == '\0' || *cookie == NULL || **cookie == '\0' || 270 } else {
244 (use_tls && (*tls_certname == NULL || **tls_certname == '\0'))) 271 purple_debug_warning("oscar", "useTls was 1, but we haven't received a tlsCertName to use. We will not do SSL to BOS.\n");
272 }
273 }
274
275 if (*host == NULL || **host == '\0' || tmp == NULL || *tmp == '\0' || *cookie == NULL || **cookie == '\0')
245 { 276 {
246 char *msg; 277 char *msg;
247 purple_debug_error("oscar", "startOSCARSession response was missing " 278 purple_debug_error("oscar", "startOSCARSession response was missing "
248 "something: %s\n", response); 279 "something: %s\n", response);
249 msg = generate_error_message(response_node, 280 msg = generate_error_message(response_node,
250 URL_START_OSCAR_SESSION); 281 get_start_oscar_session_url(od));
251 purple_connection_error_reason(gc, 282 purple_connection_error_reason(gc,
252 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); 283 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
253 g_free(msg); 284 g_free(msg);
254 g_free(*host); 285 g_free(*host);
255 g_free(tmp); 286 g_free(tmp);
282 if (error_message != NULL || len == 0) { 313 if (error_message != NULL || len == 0) {
283 gchar *tmp; 314 gchar *tmp;
284 /* Note to translators: The first %s is a URL, the second is an 315 /* Note to translators: The first %s is a URL, the second is an
285 error message. */ 316 error message. */
286 tmp = g_strdup_printf(_("Error requesting %s: %s"), 317 tmp = g_strdup_printf(_("Error requesting %s: %s"),
287 URL_START_OSCAR_SESSION, error_message); 318 get_start_oscar_session_url(od), error_message);
288 purple_connection_error_reason(gc, 319 purple_connection_error_reason(gc,
289 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); 320 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
290 g_free(tmp); 321 g_free(tmp);
291 return; 322 return;
292 } 323 }
324 "&useTLS=%d", 355 "&useTLS=%d",
325 purple_url_encode(token), 356 purple_url_encode(token),
326 oscar_get_ui_info_int(od->icq ? "prpl-icq-distid" 357 oscar_get_ui_info_int(od->icq ? "prpl-icq-distid"
327 : "prpl-aim-distid", 0x00000611), 358 : "prpl-aim-distid", 0x00000611),
328 get_client_key(od), hosttime, use_tls); 359 get_client_key(od), hosttime, use_tls);
329 signature = generate_signature("GET", URL_START_OSCAR_SESSION, 360 signature = generate_signature("GET", get_start_oscar_session_url(od),
330 query_string, session_key); 361 query_string, session_key);
331 url = g_strdup_printf(URL_START_OSCAR_SESSION "?%s&sig_sha256=%s", 362 url = g_strdup_printf("%s?%s&sig_sha256=%s", get_start_oscar_session_url(od),
332 query_string, signature); 363 query_string, signature);
333 g_free(query_string); 364 g_free(query_string);
334 g_free(signature); 365 g_free(signature);
335 366
336 /* Make the request */ 367 /* Make the request */
365 * @return TRUE if the request was successful and we were able to 396 * @return TRUE if the request was successful and we were able to
366 * extract all info we need. Otherwise FALSE. 397 * extract all info we need. Otherwise FALSE.
367 */ 398 */
368 static gboolean parse_client_login_response(PurpleConnection *gc, const gchar *response, gsize response_len, char **token, char **secret, time_t *hosttime) 399 static gboolean parse_client_login_response(PurpleConnection *gc, const gchar *response, gsize response_len, char **token, char **secret, time_t *hosttime)
369 { 400 {
401 OscarData *od = purple_connection_get_protocol_data(gc);
370 xmlnode *response_node, *tmp_node, *data_node; 402 xmlnode *response_node, *tmp_node, *data_node;
371 xmlnode *secret_node = NULL, *hosttime_node = NULL, *token_node = NULL, *tokena_node = NULL; 403 xmlnode *secret_node = NULL, *hosttime_node = NULL, *token_node = NULL, *tokena_node = NULL;
372 char *tmp; 404 char *tmp;
373 405
374 /* Parse the response as XML */ 406 /* Parse the response as XML */
377 { 409 {
378 char *msg; 410 char *msg;
379 purple_debug_error("oscar", "clientLogin could not parse " 411 purple_debug_error("oscar", "clientLogin could not parse "
380 "response as XML: %s\n", response); 412 "response as XML: %s\n", response);
381 msg = generate_error_message(response_node, 413 msg = generate_error_message(response_node,
382 URL_CLIENT_LOGIN); 414 get_client_login_url(od));
383 purple_connection_error_reason(gc, 415 purple_connection_error_reason(gc,
384 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); 416 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
385 g_free(msg); 417 g_free(msg);
386 return FALSE; 418 return FALSE;
387 } 419 }
401 if (tmp_node == NULL || (tmp = xmlnode_get_data_unescaped(tmp_node)) == NULL) { 433 if (tmp_node == NULL || (tmp = xmlnode_get_data_unescaped(tmp_node)) == NULL) {
402 char *msg; 434 char *msg;
403 purple_debug_error("oscar", "clientLogin response was " 435 purple_debug_error("oscar", "clientLogin response was "
404 "missing statusCode: %s\n", response); 436 "missing statusCode: %s\n", response);
405 msg = generate_error_message(response_node, 437 msg = generate_error_message(response_node,
406 URL_CLIENT_LOGIN); 438 get_client_login_url(od));
407 purple_connection_error_reason(gc, 439 purple_connection_error_reason(gc,
408 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); 440 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
409 g_free(msg); 441 g_free(msg);
410 xmlnode_free(response_node); 442 xmlnode_free(response_node);
411 return FALSE; 443 return FALSE;
444 PURPLE_CONNECTION_ERROR_OTHER_ERROR, 476 PURPLE_CONNECTION_ERROR_OTHER_ERROR,
445 _("AOL does not allow your screen name to authenticate here")); 477 _("AOL does not allow your screen name to authenticate here"));
446 } else { 478 } else {
447 char *msg; 479 char *msg;
448 msg = generate_error_message(response_node, 480 msg = generate_error_message(response_node,
449 URL_CLIENT_LOGIN); 481 get_client_login_url(od));
450 purple_connection_error_reason(gc, 482 purple_connection_error_reason(gc,
451 PURPLE_CONNECTION_ERROR_OTHER_ERROR, msg); 483 PURPLE_CONNECTION_ERROR_OTHER_ERROR, msg);
452 g_free(msg); 484 g_free(msg);
453 } 485 }
454 486
463 { 495 {
464 char *msg; 496 char *msg;
465 purple_debug_error("oscar", "clientLogin response was missing " 497 purple_debug_error("oscar", "clientLogin response was missing "
466 "something: %s\n", response); 498 "something: %s\n", response);
467 msg = generate_error_message(response_node, 499 msg = generate_error_message(response_node,
468 URL_CLIENT_LOGIN); 500 get_client_login_url(od));
469 purple_connection_error_reason(gc, 501 purple_connection_error_reason(gc,
470 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); 502 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
471 g_free(msg); 503 g_free(msg);
472 xmlnode_free(response_node); 504 xmlnode_free(response_node);
473 return FALSE; 505 return FALSE;
481 { 513 {
482 char *msg; 514 char *msg;
483 purple_debug_error("oscar", "clientLogin response was missing " 515 purple_debug_error("oscar", "clientLogin response was missing "
484 "something: %s\n", response); 516 "something: %s\n", response);
485 msg = generate_error_message(response_node, 517 msg = generate_error_message(response_node,
486 URL_CLIENT_LOGIN); 518 get_client_login_url(od));
487 purple_connection_error_reason(gc, 519 purple_connection_error_reason(gc,
488 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); 520 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
489 g_free(msg); 521 g_free(msg);
490 g_free(*token); 522 g_free(*token);
491 g_free(*secret); 523 g_free(*secret);
518 550
519 if (error_message != NULL || len == 0) { 551 if (error_message != NULL || len == 0) {
520 gchar *tmp; 552 gchar *tmp;
521 if (error_message != NULL) 553 if (error_message != NULL)
522 tmp = g_strdup_printf(_("Error requesting %s: %s"), 554 tmp = g_strdup_printf(_("Error requesting %s: %s"),
523 URL_CLIENT_LOGIN, error_message); 555 get_client_login_url(od), error_message);
524 else 556 else
525 tmp = g_strdup_printf(_("Error requesting %s"), 557 tmp = g_strdup_printf(_("Error requesting %s"),
526 URL_CLIENT_LOGIN); 558 get_client_login_url(od));
527 purple_connection_error_reason(gc, 559 purple_connection_error_reason(gc,
528 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); 560 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
529 g_free(tmp); 561 g_free(tmp);
530 return; 562 return;
531 } 563 }
597 g_string_append_len(request, body->str, body->len); 629 g_string_append_len(request, body->str, body->len);
598 g_string_free(body, TRUE); 630 g_string_free(body, TRUE);
599 631
600 /* Send the POST request */ 632 /* Send the POST request */
601 od->url_data = purple_util_fetch_url_request_len_with_account( 633 od->url_data = purple_util_fetch_url_request_len_with_account(
602 purple_connection_get_account(gc), URL_CLIENT_LOGIN, 634 purple_connection_get_account(gc), get_client_login_url(od),
603 TRUE, NULL, FALSE, request->str, FALSE, -1, 635 TRUE, NULL, FALSE, request->str, FALSE, -1,
604 client_login_cb, od); 636 client_login_cb, od);
605 g_string_free(request, TRUE); 637 g_string_free(request, TRUE);
606 } 638 }