Mercurial > pidgin
diff libpurple/protocols/msn/nexus.c @ 20408:14b8fb8d27b3
merge of 790a91b1bb6c10ada984951cbd2485e95e5159fd and
05f7badcad9471084218e698a5c011908d17af90
author | Ka-Hing Cheung <khc@hxbc.us> |
---|---|
date | Wed, 02 May 2007 06:06:56 +0000 |
parents | 6b4e778ee4b4 60bc06498746 |
children | 4403cecc7cd6 |
line wrap: on
line diff
--- a/libpurple/protocols/msn/nexus.c Mon Apr 23 17:19:11 2007 +0000 +++ b/libpurple/protocols/msn/nexus.c Wed May 02 06:06:56 2007 +0000 @@ -22,8 +22,13 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "msn.h" +#include "soap.h" #include "nexus.h" #include "notification.h" +#undef NEXUS_LOGIN_TWN + +/*Local Function Prototype*/ +static void nexus_login_connect_cb(gpointer data, PurpleSslConnection *gsc,PurpleInputCondition cond); /************************************************************************** * Main @@ -36,6 +41,9 @@ nexus = g_new0(MsnNexus, 1); nexus->session = session; + /*we must use SSL connection to do Windows Live ID authentication*/ + nexus->soapconn = msn_soap_new(session,nexus,1); + nexus->challenge_data = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); @@ -45,24 +53,14 @@ void msn_nexus_destroy(MsnNexus *nexus) { - if (nexus->gsc) - purple_ssl_close(nexus->gsc); - - g_free(nexus->login_host); - - g_free(nexus->login_path); - if (nexus->challenge_data != NULL) g_hash_table_destroy(nexus->challenge_data); - if (nexus->input_handler > 0) - purple_input_remove(nexus->input_handler); - g_free(nexus->write_buf); - g_free(nexus->read_buf); - + msn_soap_destroy(nexus->soapconn); g_free(nexus); } +#if 0 /* khc */ /************************************************************************** * Util **************************************************************************/ @@ -121,283 +119,242 @@ nexus->written_cb(nexus, source, 0); } +#endif /************************************************************************** * Login **************************************************************************/ - static void -login_connect_cb(gpointer data, PurpleSslConnection *gsc, - PurpleInputCondition cond); +nexus_login_error_cb(PurpleSslConnection *gsc, PurpleSslErrorType error, void *data) +{ + MsnSoapConn * soapconn = data; + MsnSession *session; + + session = soapconn->session; + g_return_if_fail(session != NULL); + + soapconn->gsc = NULL; + msn_session_set_error(session, MSN_ERROR_AUTH, _("Windows Live ID authentication:Unable to connect")); + /* the above line will result in nexus being destroyed, so we don't want + * to destroy it here, or we'd crash */ +} + +/*process the SOAP reply, get the Authentication Info*/ static void -login_error_cb(PurpleSslConnection *gsc, PurpleSslErrorType error, void *data) +nexus_login_read_cb(gpointer data, gint source, PurpleInputCondition cond) { + MsnSoapConn * soapconn = data; MsnNexus *nexus; MsnSession *session; - nexus = data; - g_return_if_fail(nexus != NULL); + char *base, *c; + char *msn_twn_t,*msn_twn_p; + char *login_params; + char **elems, **cur, **tokens; + char * cert_str; - nexus->gsc = NULL; - + nexus = soapconn->parent; + g_return_if_fail(nexus != NULL); session = nexus->session; g_return_if_fail(session != NULL); - msn_session_set_error(session, MSN_ERROR_AUTH, _("Unable to connect")); - /* the above line will result in nexus being destroyed, so we don't want - * to destroy it here, or we'd crash */ + purple_debug_misc("msn", "TWN Server Reply: {%s}\n", soapconn->read_buf); + + /*reply OK, we should process the SOAP body*/ + purple_debug_info("MaYuan","Windows Live ID Reply OK!\n"); + + //TODO: we should parse it using XML +#ifdef NEXUS_LOGIN_TWN + base = g_strstr_len(soapconn->read_buf, soapconn->read_len, TWN_START_TOKEN); + base += strlen(TWN_START_TOKEN); + c = g_strstr_len(soapconn->read_buf, soapconn->read_len, TWN_END_TOKEN); +#else + base = g_strstr_len(soapconn->read_buf, soapconn->read_len, TWN_LIVE_START_TOKEN); + base += strlen(TWN_LIVE_START_TOKEN); + c = g_strstr_len(soapconn->read_buf, soapconn->read_len, TWN_LIVE_END_TOKEN); +#endif + login_params = g_strndup(base, c - base); + + // purple_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(nexus->challenge_data, tokens[0], tokens[1]); + /* Don't free each of the tokens, only the array. */ + g_free(tokens); + } + + g_strfreev(elems); + + msn_twn_t = (char *)g_hash_table_lookup(nexus->challenge_data, "t"); + msn_twn_p = (char *)g_hash_table_lookup(nexus->challenge_data, "p"); + + /*setup the t and p parameter for session*/ + if (session->passport_info.t != NULL){ + g_free(session->passport_info.t); + } + session->passport_info.t = g_strdup(msn_twn_t); + + if (session->passport_info.p != NULL) + g_free(session->passport_info.p); + session->passport_info.p = g_strdup(msn_twn_p); + + cert_str = g_strdup_printf("t=%s&p=%s",msn_twn_t,msn_twn_p); + msn_got_login_params(session, cert_str); + + purple_debug_info("MaYuan","close nexus connection! \n"); + g_free(cert_str); + g_free(login_params); + msn_nexus_destroy(nexus); + session->nexus = NULL; + + return; } static void nexus_login_written_cb(gpointer data, gint source, PurpleInputCondition cond) { - MsnNexus *nexus = data; - MsnSession *session; - int len; + MsnSoapConn * soapconn = data; - session = nexus->session; - g_return_if_fail(session != NULL); - - if (nexus->input_handler == 0) - /* TODO: Use purple_ssl_input_add()? */ - nexus->input_handler = purple_input_add(nexus->gsc->fd, - PURPLE_INPUT_READ, nexus_login_written_cb, nexus); + soapconn->read_cb = nexus_login_read_cb; +// msn_soap_read_cb(data,source,cond); +} - len = msn_ssl_read(nexus); - - if (len < 0 && errno == EAGAIN) - return; - else if (len < 0) { - purple_input_remove(nexus->input_handler); - nexus->input_handler = 0; - 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; - - purple_input_remove(nexus->input_handler); - nexus->input_handler = 0; - - purple_ssl_close(nexus->gsc); - nexus->gsc = NULL; - - purple_debug_misc("msn", "ssl buffer: {%s}", nexus->read_buf); - - if (strstr(nexus->read_buf, "HTTP/1.1 302") != NULL) - { - /* Redirect. */ - char *location, *c; - - location = strstr(nexus->read_buf, "Location: "); - if (location == NULL) - { - g_free(nexus->read_buf); - nexus->read_buf = NULL; - nexus->read_len = 0; - - return; - } - location = strchr(location, ' ') + 1; - - if ((c = strchr(location, '\r')) != NULL) - *c = '\0'; - - /* Skip the http:// */ - if ((c = strchr(location, '/')) != NULL) - location = c + 2; - - if ((c = strchr(location, '/')) != NULL) - { - g_free(nexus->login_path); - nexus->login_path = g_strdup(c); - - *c = '\0'; - } - - g_free(nexus->login_host); - nexus->login_host = g_strdup(location); - - nexus->gsc = purple_ssl_connect(session->account, - nexus->login_host, PURPLE_SSL_DEFAULT_PORT, - login_connect_cb, login_error_cb, nexus); - } - 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) - { - const char *c; - char *temp; - - error += strlen("cbtxt="); - - if ((c = strchr(error, '\n')) == NULL) - c = error + strlen(error); - - temp = g_strndup(error, c - error); - error = purple_url_decode(temp); - g_free(temp); - } - } - - msn_session_set_error(session, MSN_ERROR_AUTH, error); - } - else if (strstr(nexus->read_buf, "HTTP/1.1 503 Service Unavailable")) - { - msn_session_set_error(session, MSN_ERROR_SERV_UNAVAILABLE, NULL); - } - else if (strstr(nexus->read_buf, "HTTP/1.1 200 OK")) - { - char *base, *c; - char *login_params; - -#if 0 - /* All your base are belong to us. */ - base = buffer; - - /* For great cookie! */ - while ((base = strstr(base, "Set-Cookie: ")) != NULL) - { - base += strlen("Set-Cookie: "); - - c = strchr(base, ';'); - - session->login_cookies = - g_list_append(session->login_cookies, - g_strndup(base, c - base)); - } +/*when connect, do the SOAP Style windows Live ID authentication */ +void +nexus_login_connect_cb(gpointer data, PurpleSslConnection *gsc, + PurpleInputCondition cond) +{ + MsnSoapConn *soapconn; + MsnNexus * nexus; + MsnSession *session; + char *ru,*lc,*id,*tw,*ct,*kpp,*kv,*ver,*rn,*tpf; + char *fs0,*fs; + char *username, *password; + char *request_str, *head, *tail; +#ifdef NEXUS_LOGIN_TWN + char *challenge_str; +#else + char *rst1_str,*rst2_str,*rst3_str; #endif - base = strstr(nexus->read_buf, "Authentication-Info: "); + purple_debug_info("MaYuan","starting Windows Live ID authentication\n"); + + soapconn = data; + g_return_if_fail(soapconn != NULL); + + nexus = soapconn->parent; + g_return_if_fail(nexus != NULL); - g_return_if_fail(base != NULL); + session = soapconn->session; + g_return_if_fail(session != NULL); + + msn_session_set_login_step(session, MSN_LOGIN_STEP_GET_COOKIE); + + /*prepare the Windows Live ID authentication token*/ + username = g_strdup(purple_account_get_username(session->account)); + password = g_strdup(purple_connection_get_password(session->account->gc)); - base = strstr(base, "from-PP='"); - base += strlen("from-PP='"); - c = strchr(base, '\''); + lc = (char *)g_hash_table_lookup(nexus->challenge_data, "lc"); + id = (char *)g_hash_table_lookup(nexus->challenge_data, "id"); + tw = (char *)g_hash_table_lookup(nexus->challenge_data, "tw"); + fs0= (char *)g_hash_table_lookup(nexus->challenge_data, "fs"); + ru = (char *)g_hash_table_lookup(nexus->challenge_data, "ru"); + ct = (char *)g_hash_table_lookup(nexus->challenge_data, "ct"); + kpp= (char *)g_hash_table_lookup(nexus->challenge_data, "kpp"); + kv = (char *)g_hash_table_lookup(nexus->challenge_data, "kv"); + ver= (char *)g_hash_table_lookup(nexus->challenge_data, "ver"); + rn = (char *)g_hash_table_lookup(nexus->challenge_data, "rn"); + tpf= (char *)g_hash_table_lookup(nexus->challenge_data, "tpf"); - login_params = g_strndup(base, c - base); - - msn_got_login_params(session, login_params); - - g_free(login_params); - + /* + * add some fail-safe code to avoid windows Purple Crash bug #1540454 + * If any of these string is NULL, will return Authentication Fail! + * for when windows g_strdup_printf() implementation get NULL point,It crashed! + */ + if(!(lc && id && tw && ru && ct && kpp && kv && ver && tpf)){ + purple_debug_error("MaYuan","WLM Authenticate Key Error!\n"); + msn_session_set_error(session, MSN_ERROR_AUTH, _("Windows Live ID authentication Failed")); + g_free(username); + g_free(password); + purple_ssl_close(gsc); msn_nexus_destroy(nexus); session->nexus = NULL; return; } - g_free(nexus->read_buf); - nexus->read_buf = NULL; - nexus->read_len = 0; - -} - -/* this guards against missing hash entries */ -static char * -nexus_challenge_data_lookup(GHashTable *challenge_data, const char *key) -{ - char *entry; - - return (entry = (char *)g_hash_table_lookup(challenge_data, key)) ? - entry : "(null)"; -} + /* + * in old MSN NS server's "USR TWN S" return,didn't include fs string + * so we use a default "1" for fs. + */ + if(fs0){ + fs = g_strdup(fs0); + }else{ + fs = g_strdup("1"); + } -void -login_connect_cb(gpointer data, PurpleSslConnection *gsc, - PurpleInputCondition cond) -{ - MsnNexus *nexus; - MsnSession *session; - char *username, *password; - char *request_str, *head, *tail; - char *buffer = NULL; - guint32 ctint; - - nexus = data; - g_return_if_fail(nexus != NULL); - - session = nexus->session; - g_return_if_fail(session != NULL); - - msn_session_set_login_step(session, MSN_LOGIN_STEP_GET_COOKIE); +#ifdef NEXUS_LOGIN_TWN + 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", + lc,id,tw,fs,ru,ct,kpp,kv,ver,rn,tpf + ); - username = - g_strdup(purple_url_encode(purple_account_get_username(session->account))); - - password = - g_strdup(purple_url_encode(purple_connection_get_password(session->account->gc))); - - ctint = strtoul((char *)g_hash_table_lookup(nexus->challenge_data, "ct"), NULL, 10) + 200; - - 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); + /*build the SOAP windows Live ID XML body */ + tail = g_strdup_printf(TWN_ENVELOP_TEMPLATE,username,password,challenge_str ); + g_free(challenge_str); +#else + rst1_str = g_strdup_printf( + "id=%s&tw=%s&fs=%s&kpp=%s&kv=%s&ver=%s&rn=%s", + id,tw,fs,kpp,kv,ver,rn + ); + rst2_str = g_strdup_printf( + "fs=%s&id=%s&kv=%s&rn=%s&tw=%s&ver=%s", + fs,id,kv,rn,tw,ver + ); + rst3_str = g_strdup_printf("id=%s",id); + tail = g_strdup_printf(TWN_LIVE_ENVELOP_TEMPLATE,username,password,rst1_str,rst2_str,rst3_str); + g_free(rst1_str); + g_free(rst2_str); + g_free(rst3_str); +#endif + g_free(fs); - 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", - nexus_challenge_data_lookup(nexus->challenge_data, "lc"), - nexus_challenge_data_lookup(nexus->challenge_data, "id"), - nexus_challenge_data_lookup(nexus->challenge_data, "tw"), - nexus_challenge_data_lookup(nexus->challenge_data, "fs"), - nexus_challenge_data_lookup(nexus->challenge_data, "ru"), - ctint, - nexus_challenge_data_lookup(nexus->challenge_data, "kpp"), - nexus_challenge_data_lookup(nexus->challenge_data, "kv"), - nexus_challenge_data_lookup(nexus->challenge_data, "ver"), - nexus_challenge_data_lookup(nexus->challenge_data, "tpf"), - nexus->login_host); + soapconn->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", + soapconn->login_path,soapconn->login_host,(int)strlen(tail)); - 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); + request_str = g_strdup_printf("%s%s", head,tail); + purple_debug_misc("msn", "TWN Sending: {%s}\n", request_str); - purple_debug_misc("msn", "Sending: {%s}\n", buffer); - - g_free(buffer); g_free(head); g_free(tail); g_free(username); g_free(password); - nexus->write_buf = request_str; - nexus->written_len = 0; - - nexus->read_len = 0; - - nexus->written_cb = nexus_login_written_cb; - - nexus->input_handler = purple_input_add(gsc->fd, PURPLE_INPUT_WRITE, - nexus_write_cb, nexus); - - nexus_write_cb(nexus, gsc->fd, PURPLE_INPUT_WRITE); + /*prepare to send the SOAP request*/ + msn_soap_write(soapconn,request_str,nexus_login_written_cb); return; - - } +#if 0 /* khc */ static void nexus_connect_written_cb(gpointer data, gint source, PurpleInputCondition cond) { MsnNexus *nexus = data; int len; + char *da_login; char *base, *c; @@ -406,6 +363,7 @@ nexus->input_handler = purple_input_add(nexus->gsc->fd, PURPLE_INPUT_READ, nexus_connect_written_cb, nexus); + /* Get the PassportURLs line. */ len = msn_ssl_read(nexus); @@ -468,10 +426,13 @@ } +#endif + /************************************************************************** * Connect **************************************************************************/ +#if 0 /* khc */ static void nexus_connect_cb(gpointer data, PurpleSslConnection *gsc, PurpleInputCondition cond) @@ -500,10 +461,13 @@ nexus_write_cb(nexus, gsc->fd, PURPLE_INPUT_WRITE); } +#endif + void msn_nexus_connect(MsnNexus *nexus) { - nexus->gsc = purple_ssl_connect(nexus->session->account, - "nexus.passport.com", PURPLE_SSL_DEFAULT_PORT, - nexus_connect_cb, login_error_cb, nexus); + /* Authenticate via Windows Live ID. */ + purple_debug_info("MaYuan","msn_nexus_connect...\n"); + msn_soap_init(nexus->soapconn,MSN_TWN_SERVER,1,nexus_login_connect_cb,nexus_login_error_cb); + msn_soap_connect(nexus->soapconn); }