8171
|
1 #include "msn.h"
|
|
2 #include "nexus.h"
|
|
3 #include "notification.h"
|
|
4
|
|
5 /**************************************************************************
|
|
6 * Util
|
|
7 **************************************************************************/
|
|
8
|
|
9 static size_t
|
|
10 msn_ssl_read(GaimSslConnection *gsc, char **dest_buffer)
|
|
11 {
|
|
12 size_t size = 0, s;
|
|
13 char *buffer = NULL;
|
|
14 char temp_buf[4096];
|
|
15
|
|
16 while ((s = gaim_ssl_read(gsc, temp_buf, sizeof(temp_buf))) > 0)
|
|
17 {
|
|
18 buffer = g_realloc(buffer, size + s + 1);
|
|
19
|
|
20 strncpy(buffer + size, temp_buf, s);
|
|
21
|
|
22 buffer[size + s] = '\0';
|
|
23
|
|
24 size += s;
|
|
25 }
|
|
26
|
|
27 *dest_buffer = buffer;
|
|
28
|
|
29 return size;
|
|
30 }
|
|
31
|
|
32 /**************************************************************************
|
|
33 * Login
|
|
34 **************************************************************************/
|
|
35
|
|
36 static void
|
|
37 login_error_cb(GaimSslConnection *gsc, GaimSslErrorType error, void *data)
|
|
38 {
|
|
39 MsnNexus *nexus;
|
|
40 MsnSession *session;
|
|
41 GaimAccount *account;
|
|
42 GaimConnection *gc;
|
|
43
|
|
44 nexus = data;
|
|
45 g_return_if_fail(nexus != NULL);
|
|
46
|
|
47 session = nexus->session;
|
|
48 g_return_if_fail(session != NULL);
|
|
49
|
|
50 account = session->account;
|
|
51 g_return_if_fail(account != NULL);
|
|
52
|
|
53 gc = gaim_account_get_connection(account);
|
|
54 g_return_if_fail(gc != NULL);
|
|
55
|
|
56 gaim_connection_error(gc, _("Unable to connect to server"));
|
|
57
|
|
58 msn_nexus_destroy(nexus);
|
|
59 session->nexus = NULL;
|
|
60 }
|
|
61
|
|
62 static void
|
|
63 login_connect_cb(gpointer data, GaimSslConnection *gsc,
|
|
64 GaimInputCondition cond)
|
|
65 {
|
|
66 MsnNexus *nexus;
|
|
67 MsnSession *session;
|
|
68 GaimConnection *gc;
|
|
69 char *username, *password;
|
|
70 char *request_str;
|
|
71 char *buffer = NULL;
|
|
72 size_t s;
|
|
73
|
|
74 nexus = data;
|
|
75 g_return_if_fail(nexus != NULL);
|
|
76
|
|
77 session = nexus->session;
|
|
78 g_return_if_fail(session != NULL);
|
|
79
|
|
80 gc = gaim_account_get_connection(session->account);
|
|
81 g_return_if_fail(gc != NULL);
|
|
82
|
|
83 username =
|
|
84 g_strdup(gaim_url_encode(gaim_account_get_username(session->account)));
|
|
85
|
|
86 password =
|
|
87 g_strdup(gaim_url_encode(gaim_account_get_password(session->account)));
|
|
88
|
|
89 request_str = g_strdup_printf(
|
|
90 "GET %s HTTP/1.1\r\n"
|
|
91 "Authorization: Passport1.4 OrgVerb=GET,OrgURL=%s,sign-in=%s,pwd=%s,"
|
|
92 "lc=%s,id=%s,tw=%s,fs=%s,ru=%s,ct=%s,kpp=%s,kv=%s,ver=%s,tpf=%s\r\n"
|
|
93 "User-Agent: MSMSGS\r\n"
|
|
94 "Host: %s\r\n"
|
|
95 "Connection: Keep-Alive\r\n"
|
|
96 "Cache-Control: no-cache\r\n"
|
|
97 "\r\n",
|
|
98 nexus->login_path,
|
|
99 (char *)g_hash_table_lookup(nexus->challenge_data, "ru"),
|
|
100 username, password,
|
|
101 (char *)g_hash_table_lookup(nexus->challenge_data, "lc"),
|
|
102 (char *)g_hash_table_lookup(nexus->challenge_data, "id"),
|
|
103 (char *)g_hash_table_lookup(nexus->challenge_data, "tw"),
|
|
104 (char *)g_hash_table_lookup(nexus->challenge_data, "fs"),
|
|
105 (char *)g_hash_table_lookup(nexus->challenge_data, "ru"),
|
|
106 (char *)g_hash_table_lookup(nexus->challenge_data, "ct"),
|
|
107 (char *)g_hash_table_lookup(nexus->challenge_data, "kpp"),
|
|
108 (char *)g_hash_table_lookup(nexus->challenge_data, "kv"),
|
|
109 (char *)g_hash_table_lookup(nexus->challenge_data, "ver"),
|
|
110 (char *)g_hash_table_lookup(nexus->challenge_data, "tpf"),
|
|
111 nexus->login_host);
|
|
112
|
|
113 gaim_debug(GAIM_DEBUG_MISC, "msn", "Sending: {%s}\n", request_str);
|
|
114
|
|
115 g_free(username);
|
|
116 g_free(password);
|
|
117
|
|
118 if ((s = gaim_ssl_write(gsc, request_str, strlen(request_str))) <= 0)
|
|
119 {
|
|
120 g_free(request_str);
|
|
121 gaim_connection_error(gc, _("Unable to write to MSN Nexus server."));
|
|
122
|
|
123 return;
|
|
124 }
|
|
125
|
|
126 g_free(request_str);
|
|
127
|
|
128 if ((s = msn_ssl_read(gsc, &buffer)) <= 0)
|
|
129 {
|
|
130 gaim_connection_error(gc, _("Unable to write to MSN Nexus server."));
|
|
131 return;
|
|
132 }
|
|
133
|
|
134 gaim_ssl_close(gsc);
|
|
135
|
|
136 gaim_debug(GAIM_DEBUG_MISC, "msn", "ssl buffer: {%s}", buffer);
|
|
137
|
|
138 if (strstr(buffer, "HTTP/1.1 302") != NULL)
|
|
139 {
|
|
140 /* Redirect. */
|
|
141 char *location, *c;
|
|
142
|
|
143 location = strstr(buffer, "Location: ");
|
|
144 if (location == NULL)
|
|
145 {
|
|
146 gaim_connection_error(gc,
|
|
147 _("MSN Nexus server returned invalid redirect information."));
|
|
148
|
|
149 g_free(buffer);
|
|
150
|
|
151 return;
|
|
152 }
|
|
153
|
|
154 location = strchr(location, ' ') + 1;
|
|
155
|
|
156 if ((c = strchr(location, '\r')) != NULL)
|
|
157 *c = '\0';
|
|
158
|
|
159 /* Skip the http:// */
|
|
160 if ((c = strchr(location, '/')) != NULL)
|
|
161 location = c + 2;
|
|
162
|
|
163 if ((c = strchr(location, '/')) != NULL)
|
|
164 {
|
|
165 g_free(nexus->login_path);
|
|
166 nexus->login_path = g_strdup(c);
|
|
167
|
|
168 *c = '\0';
|
|
169 }
|
|
170
|
|
171 g_free(nexus->login_host);
|
|
172 nexus->login_host = g_strdup(location);
|
|
173
|
|
174 gaim_ssl_connect(session->account, nexus->login_host,
|
|
175 GAIM_SSL_DEFAULT_PORT, login_connect_cb,
|
|
176 login_error_cb, nexus);
|
|
177 }
|
|
178 else if (strstr(buffer, "HTTP/1.1 401 Unauthorized") != NULL)
|
|
179 {
|
|
180 GaimConnection *gc;
|
|
181 const char *error, *c;
|
|
182 char *temp;
|
|
183
|
|
184 if ((error = strstr(buffer, "WWW-Authenticate")) != NULL)
|
|
185 {
|
|
186 if ((error = strstr(error, "cbtxt=")) != NULL)
|
|
187 {
|
|
188 error += strlen("cbtxt=");
|
|
189
|
|
190 if ((c = strchr(error, '\n')) == NULL)
|
|
191 c = error + strlen(error);
|
|
192
|
|
193 temp = g_strndup(error, c - error);
|
|
194 error = gaim_url_decode(temp);
|
|
195 g_free(temp);
|
|
196 }
|
|
197 }
|
|
198
|
|
199 gc = gaim_account_get_connection(session->account);
|
|
200
|
|
201 if (error == NULL)
|
|
202 {
|
|
203 gaim_connection_error(gc,
|
|
204 _("Unknown error when attempting to authorize with "
|
|
205 "MSN login server."));
|
|
206 }
|
|
207 else
|
|
208 gaim_connection_error(gc, error);
|
|
209 }
|
|
210 else if (strstr(buffer, "HTTP/1.1 200 OK"))
|
|
211 {
|
|
212 char outparams[MSN_BUF_LEN];
|
|
213 char *base, *c;
|
|
214 char *login_params;
|
|
215
|
|
216 #if 0
|
|
217 /* All your base are belong to us. */
|
|
218 base = buffer;
|
|
219
|
|
220 /* For great cookie! */
|
|
221 while ((base = strstr(base, "Set-Cookie: ")) != NULL)
|
|
222 {
|
|
223 base += strlen("Set-Cookie: ");
|
|
224
|
|
225 c = strchr(base, ';');
|
|
226
|
|
227 session->login_cookies =
|
|
228 g_list_append(session->login_cookies,
|
|
229 g_strndup(base, c - base));
|
|
230 }
|
|
231 #endif
|
|
232
|
|
233 base = strstr(buffer, "Authentication-Info: ");
|
|
234
|
|
235 if(base == NULL)
|
|
236 {
|
|
237 gaim_debug(GAIM_DEBUG_ERROR, "msn",
|
|
238 "Authentication information was not found. This did "
|
|
239 "not just happen, but if it did, you're screwed. "
|
|
240 "Report this.\n");
|
|
241
|
|
242 return;
|
|
243 }
|
|
244
|
|
245 base = strstr(base, "from-PP='");
|
|
246 base += strlen("from-PP='");
|
|
247 c = strchr(base, '\'');
|
|
248
|
|
249 login_params = g_strndup(base, c - base);
|
|
250
|
|
251 g_snprintf(outparams, sizeof(outparams),
|
|
252 "TWN S %s", login_params);
|
|
253
|
|
254 msn_servconn_send_command(session->notification_conn, "USR",
|
|
255 outparams);
|
|
256
|
|
257 g_free(login_params);
|
|
258
|
|
259 msn_nexus_destroy(nexus);
|
|
260 session->nexus = NULL;
|
|
261 }
|
|
262
|
|
263 g_free(buffer);
|
|
264 }
|
|
265
|
|
266 static void
|
|
267 nexus_connect_cb(gpointer data, GaimSslConnection *gsc,
|
|
268 GaimInputCondition cond)
|
|
269 {
|
|
270 MsnNexus *nexus;
|
|
271 MsnSession *session;
|
|
272 char *request_str;
|
|
273 char *da_login;
|
|
274 char *base, *c;
|
|
275 char *buffer = NULL;
|
|
276 size_t s;
|
|
277
|
|
278 nexus = data;
|
|
279 g_return_if_fail(nexus != NULL);
|
|
280
|
|
281 session = nexus->session;
|
|
282 g_return_if_fail(session != NULL);
|
|
283
|
|
284 request_str = g_strdup_printf("GET /rdr/pprdr.asp\r\n\r\n");
|
|
285
|
|
286 if ((s = gaim_ssl_write(gsc, request_str, strlen(request_str))) <= 0)
|
|
287 {
|
|
288 g_free(request_str);
|
|
289 return;
|
|
290 }
|
|
291
|
|
292 g_free(request_str);
|
|
293
|
|
294 /* Get the PassportURLs line. */
|
|
295 if ((s = msn_ssl_read(gsc, &buffer)) <= 0)
|
|
296 return;
|
|
297
|
|
298 base = strstr(buffer, "PassportURLs");
|
|
299
|
|
300 if (base == NULL)
|
|
301 {
|
|
302 g_free(buffer);
|
|
303 return;
|
|
304 }
|
|
305
|
|
306 if ((da_login = strstr(base, "DALogin=")) != NULL)
|
|
307 {
|
|
308 if ((da_login = strchr(da_login, '=')) != NULL)
|
|
309 da_login++;
|
|
310
|
|
311 if ((c = strchr(da_login, ',')) != NULL)
|
|
312 *c = '\0';
|
|
313
|
|
314 if ((c = strchr(da_login, '/')) != NULL)
|
|
315 {
|
|
316 nexus->login_path = g_strdup(c);
|
|
317
|
|
318 *c = '\0';
|
|
319 }
|
|
320
|
|
321 nexus->login_host = g_strdup(da_login);
|
|
322 }
|
|
323
|
|
324 g_free(buffer);
|
|
325
|
|
326 gaim_ssl_close(gsc);
|
|
327
|
|
328 /* Now begin the connection to the login server. */
|
|
329 gaim_ssl_connect(session->account, nexus->login_host,
|
|
330 GAIM_SSL_DEFAULT_PORT, login_connect_cb,
|
|
331 login_error_cb, nexus);
|
|
332 }
|
|
333
|
|
334 /**************************************************************************
|
|
335 * Nexus
|
|
336 **************************************************************************/
|
|
337
|
|
338 MsnNexus *
|
|
339 msn_nexus_new(MsnSession *session)
|
|
340 {
|
|
341 MsnNexus *nexus;
|
|
342
|
|
343 nexus = g_new0(MsnNexus, 1);
|
|
344 nexus->session = session;
|
|
345 nexus->challenge_data = g_hash_table_new_full(g_str_hash, g_str_equal,
|
|
346 g_free, g_free);
|
|
347
|
|
348 return nexus;
|
|
349 }
|
|
350
|
|
351 void
|
|
352 msn_nexus_destroy(MsnNexus *nexus)
|
|
353 {
|
|
354 if (nexus->login_host != NULL)
|
|
355 g_free(nexus->login_host);
|
|
356
|
|
357 if (nexus->login_path != NULL)
|
|
358 g_free(nexus->login_path);
|
|
359
|
|
360 if (nexus->challenge_data != NULL)
|
|
361 g_hash_table_destroy(nexus->challenge_data);
|
|
362
|
|
363 g_free(nexus);
|
|
364 }
|
|
365
|
|
366 void
|
|
367 msn_nexus_connect(MsnNexus *nexus)
|
|
368 {
|
|
369 gaim_ssl_connect(nexus->session->account, "nexus.passport.com",
|
|
370 GAIM_SSL_DEFAULT_PORT, nexus_connect_cb,
|
|
371 login_error_cb, nexus);
|
|
372 }
|