--- a/src/protocols/msn/nexus.c Thu Jun 22 08:33:54 2006 +0000 +++ b/src/protocols/msn/nexus.c Sat Jun 24 12:04:32 2006 +0000 @@ -68,19 +68,25 @@ msn_ssl_read(MsnNexus *nexus) { gssize len; + gssize total_len = 0; char temp_buf[4096]; - if ((len = gaim_ssl_read(nexus->gsc, temp_buf, + if((len = gaim_ssl_read(nexus->gsc, temp_buf, sizeof(temp_buf))) > 0) { +#if 0 + g_string_append(nexus->read_buf,temp_buf); +#else + total_len += len; nexus->read_buf = g_realloc(nexus->read_buf, nexus->read_len + len + 1); strncpy(nexus->read_buf + nexus->read_len, temp_buf, len); nexus->read_len += len; nexus->read_buf[nexus->read_len] = '\0'; +#endif } - - return len; +// gaim_debug_info("MaYuan","nexus ssl read:{%s}\n",nexus->read_buf); + return total_len; } static void @@ -91,6 +97,10 @@ total_len = strlen(nexus->write_buf); + /* + * write the content to SSL server, + * We use SOAP to request Windows Live ID authentication + */ len = gaim_ssl_write(nexus->gsc, nexus->write_buf + nexus->written_len, total_len - nexus->written_len); @@ -157,12 +167,11 @@ nexus->input_handler = gaim_input_add(nexus->gsc->fd, GAIM_INPUT_READ, nexus_login_written_cb, nexus); - + /*read the request header*/ len = msn_ssl_read(nexus); - - if (len < 0 && errno == EAGAIN) + if (len < 0 && errno == EAGAIN){ return; - else if (len < 0) { + }else if (len < 0) { gaim_input_remove(nexus->input_handler); nexus->input_handler = -1; g_free(nexus->read_buf); @@ -172,20 +181,22 @@ return; } + if(nexus->read_buf == NULL){ + return; + } if (g_strstr_len(nexus->read_buf, nexus->read_len, - "\r\n\r\n") == NULL) + "</S:Envelope>") == NULL){ return; + } gaim_input_remove(nexus->input_handler); nexus->input_handler = -1; - gaim_ssl_close(nexus->gsc); nexus->gsc = NULL; - gaim_debug_misc("msn", "ssl buffer: {%s}", nexus->read_buf); +// gaim_debug_misc("msn", "TWN Server Reply: {%s}", nexus->read_buf); - if (strstr(nexus->read_buf, "HTTP/1.1 302") != NULL) - { + if (strstr(nexus->read_buf, "HTTP/1.1 302") != NULL){ /* Redirect. */ char *location, *c; @@ -221,15 +232,11 @@ gaim_ssl_connect(session->account, nexus->login_host, GAIM_SSL_DEFAULT_PORT, login_connect_cb, login_error_cb, nexus); - } - else if (strstr(nexus->read_buf, "HTTP/1.1 401 Unauthorized") != NULL) - { + }else if (strstr(nexus->read_buf, "HTTP/1.1 401 Unauthorized") != NULL){ const char *error; - if ((error = strstr(nexus->read_buf, "WWW-Authenticate")) != NULL) - { - if ((error = strstr(error, "cbtxt=")) != NULL) - { + if ((error = strstr(nexus->read_buf, "WWW-Authenticate")) != NULL) { + if ((error = strstr(error, "cbtxt=")) != NULL){ const char *c; char *temp; @@ -243,45 +250,60 @@ g_free(temp); } } - msn_session_set_error(session, MSN_ERROR_AUTH, error); - } - else if (strstr(nexus->read_buf, "HTTP/1.1 200 OK")) - { + }else if (strstr(nexus->read_buf, "HTTP/1.1 200 OK")){ + /*reply OK, we should process the SOAP body*/ char *base, *c; char *login_params; - -#if 0 - /* All your base are belong to us. */ - base = buffer; + char *length_start,*length_end,*body_len; - /* For great cookie! */ - while ((base = strstr(base, "Set-Cookie: ")) != NULL) - { - base += strlen("Set-Cookie: "); - - c = strchr(base, ';'); + char **elems, **cur, **tokens; + const char * cert_str; - session->login_cookies = - g_list_append(session->login_cookies, - g_strndup(base, c - base)); - } -#endif + gaim_debug_info("MaYuan","Receive 200\n"); +#if 0 + length_start = strstr(nexus->read_buf, "Content-Length: "); + length_start += strlen("Content-Length: "); + length_end = strstr(length_start, "\r\n"); + body_len = g_strndup(length_start,length_end - length_start); +// gaim_debug_info("MaYuan","body length is :%s\n",body_len); - base = strstr(nexus->read_buf, "Authentication-Info: "); - - g_return_if_fail(base != NULL); - - base = strstr(base, "from-PP='"); - base += strlen("from-PP='"); - c = strchr(base, '\''); - + g_free(body_len); +// g_return_if_fail(body_len != NULL); +#endif + //TODO: we should parse it using XML + base = strstr(base, TWN_START_TOKEN); + base += strlen(TWN_START_TOKEN); +// gaim_debug_info("MaYuan","base is :%s\n",base); + c = strstr(base, TWN_END_TOKEN); +// gaim_debug_info("MaYuan","c is :%s\n",c); +// gaim_debug_info("MaYuan","len is :%d\n",c-base); login_params = g_strndup(base, c - base); - msn_got_login_params(session, login_params); + gaim_debug_info("msn", "TWN Cert: {%s}\n", login_params); + + /* Parse the challenge data. */ + elems = g_strsplit(login_params, "&", 0); + + for (cur = elems; *cur != NULL; cur++){ + tokens = g_strsplit(*cur, "=", 2); + g_hash_table_insert(session->nexus->challenge_data, tokens[0], tokens[1]); + /* Don't free each of the tokens, only the array. */ + g_free(tokens); + } + g_strfreev(elems); + + cert_str = g_strdup_printf("t=%s&p=%s", + (char *)g_hash_table_lookup(nexus->challenge_data, "t"), + (char *)g_hash_table_lookup(nexus->challenge_data, "p") + ); + msn_got_login_params(session, cert_str); + + g_free(cert_str); +// g_free(body_len); g_free(login_params); - +// return; msn_nexus_destroy(nexus); session->nexus = NULL; return; @@ -290,7 +312,6 @@ g_free(nexus->read_buf); nexus->read_buf = NULL; nexus->read_len = 0; - } @@ -301,10 +322,11 @@ MsnNexus *nexus; MsnSession *session; char *username, *password; - char *request_str, *head, *tail; + char *request_str, *head, *tail,*challenge_str; char *buffer = NULL; guint32 ctint; + gaim_debug_info("MaYuan","starting Windows Live ID authentication\n"); nexus = data; g_return_if_fail(nexus != NULL); @@ -315,44 +337,44 @@ msn_session_set_login_step(session, MSN_LOGIN_STEP_GET_COOKIE); - username = - g_strdup(gaim_url_encode(gaim_account_get_username(session->account))); - - password = - g_strdup(gaim_url_encode(gaim_connection_get_password(session->account->gc))); - - ctint = strtoul((char *)g_hash_table_lookup(nexus->challenge_data, "ct"), NULL, 10) + 200; + username = g_strdup(gaim_account_get_username(session->account)); - head = g_strdup_printf( - "GET %s HTTP/1.1\r\n" - "Authorization: Passport1.4 OrgVerb=GET,OrgURL=%s,sign-in=%s", - nexus->login_path, - (char *)g_hash_table_lookup(nexus->challenge_data, "ru"), - username); + password = g_strdup(gaim_connection_get_password(session->account->gc)); +// g_strdup(gaim_url_encode(gaim_connection_get_password(session->account->gc))); - tail = g_strdup_printf( - "lc=%s,id=%s,tw=%s,fs=%s,ru=%s,ct=%" G_GUINT32_FORMAT ",kpp=%s,kv=%s,ver=%s,tpf=%s\r\n" - "User-Agent: MSMSGS\r\n" - "Host: %s\r\n" - "Connection: Keep-Alive\r\n" - "Cache-Control: no-cache\r\n", + challenge_str = g_strdup_printf( + "lc=%s&id=%s&tw=%s&fs=%s&ru=%s&ct=%s&kpp=%s&kv=%s&ver=%s&rn=%s&tpf=%s\r\n", (char *)g_hash_table_lookup(nexus->challenge_data, "lc"), (char *)g_hash_table_lookup(nexus->challenge_data, "id"), (char *)g_hash_table_lookup(nexus->challenge_data, "tw"), (char *)g_hash_table_lookup(nexus->challenge_data, "fs"), (char *)g_hash_table_lookup(nexus->challenge_data, "ru"), - ctint, + (char *)g_hash_table_lookup(nexus->challenge_data, "ct"), (char *)g_hash_table_lookup(nexus->challenge_data, "kpp"), (char *)g_hash_table_lookup(nexus->challenge_data, "kv"), (char *)g_hash_table_lookup(nexus->challenge_data, "ver"), - (char *)g_hash_table_lookup(nexus->challenge_data, "tpf"), - nexus->login_host); + (char *)g_hash_table_lookup(nexus->challenge_data, "rn"), + (char *)g_hash_table_lookup(nexus->challenge_data, "tpf") + ); + + /*build the SOAP windows Live ID XML body */ + tail = g_strdup_printf(TWN_ENVELOP_TEMPLATE,username,password,challenge_str ); - buffer = g_strdup_printf("%s,pwd=XXXXXXXX,%s\r\n", head, tail); - request_str = g_strdup_printf("%s,pwd=%s,%s\r\n", head, password, tail); + nexus->login_path = g_strdup(TWN_POST_URL); + head = g_strdup_printf( + "POST %s HTTP/1.1\r\n" + "Accept: text/*\r\n" + "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n" + "Host: %s\r\n" + "Content-Length: %d\r\n" + "Connection: Keep-Alive\r\n" + "Cache-Control: no-cache\r\n\r\n", + nexus->login_path,nexus->login_host,strlen(tail)); - gaim_debug_misc("msn", "Sending: {%s}\n", buffer); + request_str = g_strdup_printf("%s%s", head,tail); +// gaim_debug_misc("msn", "TWN Sending: {%s}\n", request_str); +// g_free(nexus->login_path); g_free(buffer); g_free(head); g_free(tail); @@ -372,123 +394,18 @@ nexus_write_cb(nexus, gsc->fd, GAIM_INPUT_WRITE); return; - - } -static void -nexus_connect_written_cb(gpointer data, gint source, GaimInputCondition cond) +/************************************************************************** + * Connect + **************************************************************************/ +void +msn_nexus_connect(MsnNexus *nexus) { - MsnNexus *nexus = data; - int len; - char *da_login; - char *base, *c; - - if (nexus->input_handler == -1) - nexus->input_handler = gaim_input_add(nexus->gsc->fd, - GAIM_INPUT_READ, nexus_connect_written_cb, nexus); - - /* Get the PassportURLs line. */ - len = msn_ssl_read(nexus); - - if (len < 0 && errno == EAGAIN) - return; - else if (len < 0) { - gaim_input_remove(nexus->input_handler); - nexus->input_handler = -1; - g_free(nexus->read_buf); - nexus->read_buf = NULL; - nexus->read_len = 0; - /* TODO: error handling */ - return; - } - - if (g_strstr_len(nexus->read_buf, nexus->read_len, - "\r\n\r\n") == NULL) - return; - - gaim_input_remove(nexus->input_handler); - nexus->input_handler = -1; - - base = strstr(nexus->read_buf, "PassportURLs"); - - if (base == NULL) - { - g_free(nexus->read_buf); - nexus->read_buf = NULL; - nexus->read_len = 0; - return; - } - - if ((da_login = strstr(base, "DALogin=")) != NULL) - { - if ((da_login = strchr(da_login, '=')) != NULL) - da_login++; - - if ((c = strchr(da_login, ',')) != NULL) - *c = '\0'; - - if ((c = strchr(da_login, '/')) != NULL) - { - nexus->login_path = g_strdup(c); - *c = '\0'; - } - - nexus->login_host = g_strdup(da_login); - } - - g_free(nexus->read_buf); - nexus->read_buf = NULL; - nexus->read_len = 0; - - gaim_ssl_close(nexus->gsc); - nexus->gsc = NULL; - - /* Now begin the connection to the login server. */ + /* Authenticate via Windows Live ID. */ + gaim_debug_info("MaYuan","msn_nexus_connect...\n"); + nexus->login_host = g_strdup(TWN_SERVER); gaim_ssl_connect(nexus->session->account, nexus->login_host, GAIM_SSL_DEFAULT_PORT, login_connect_cb, login_error_cb, nexus); } - - -/************************************************************************** - * Connect - **************************************************************************/ - -static void -nexus_connect_cb(gpointer data, GaimSslConnection *gsc, - GaimInputCondition cond) -{ - MsnNexus *nexus; - MsnSession *session; - - nexus = data; - g_return_if_fail(nexus != NULL); - - session = nexus->session; - g_return_if_fail(session != NULL); - - nexus->gsc = gsc; - - msn_session_set_login_step(session, MSN_LOGIN_STEP_AUTH); - - nexus->write_buf = g_strdup("GET /rdr/pprdr.asp\r\n\r\n"); - nexus->written_len = 0; - - nexus->read_len = 0; - - nexus->written_cb = nexus_connect_written_cb; - - nexus->input_handler = gaim_input_add(gsc->fd, GAIM_INPUT_WRITE, - nexus_write_cb, nexus); - - nexus_write_cb(nexus, gsc->fd, GAIM_INPUT_WRITE); -} - -void -msn_nexus_connect(MsnNexus *nexus) -{ - gaim_ssl_connect(nexus->session->account, "nexus.passport.com", - GAIM_SSL_DEFAULT_PORT, nexus_connect_cb, - login_error_cb, nexus); -}