comparison src/protocols/yahoo/yahoo.c @ 7134:67f9b43c402a

[gaim-migrate @ 7701] I think this is the fifth Yahoo authentication method Gaim's seen in its days. Please tell me if anything stops working. committer: Tailor Script <tailor@pidgin.im>
author Sean Egan <seanegan@gmail.com>
date Fri, 03 Oct 2003 23:01:13 +0000
parents 8246bd3141ae
children f189f8ccaa98
comparison
equal deleted inserted replaced
7133:28dd20b5f4cf 7134:67f9b43c402a
37 #include "sha.h" 37 #include "sha.h"
38 #include "yahoo.h" 38 #include "yahoo.h"
39 #include "yahoochat.h" 39 #include "yahoochat.h"
40 #include "md5.h" 40 #include "md5.h"
41 41
42 #define YAHOO_WEBMESSENGER
43
42 extern char *yahoo_crypt(const char *, const char *); 44 extern char *yahoo_crypt(const char *, const char *);
43 45
44 typedef struct 46 typedef struct
45 { 47 {
46 GaimConnection *gc; 48 GaimConnection *gc;
54 56
55 #define YAHOO_PAGER_HOST "scs.yahoo.com" 57 #define YAHOO_PAGER_HOST "scs.yahoo.com"
56 #define YAHOO_PAGER_PORT 5050 58 #define YAHOO_PAGER_PORT 5050
57 #define YAHOO_PROFILE_URL "http://profiles.yahoo.com/" 59 #define YAHOO_PROFILE_URL "http://profiles.yahoo.com/"
58 60
61 #ifdef YAHOO_WEBMESSENGER
62 #define YAHOO_PROTO_VER 0x0065
63 #else
59 #define YAHOO_PROTO_VER 0x000b 64 #define YAHOO_PROTO_VER 0x000b
65 #endif
60 66
61 #define YAHOO_PACKET_HDRLEN (4 + 2 + 2 + 2 + 2 + 4 + 4) 67 #define YAHOO_PACKET_HDRLEN (4 + 2 + 2 + 2 + 2 + 4 + 4)
62 68
63 static void yahoo_add_buddy(GaimConnection *gc, const char *who, GaimGroup *); 69 static void yahoo_add_buddy(GaimConnection *gc, const char *who, GaimGroup *);
64 70
1488 msg = _("Incorrect password."); 1494 msg = _("Incorrect password.");
1489 break; 1495 break;
1490 default: 1496 default:
1491 msg = _("Unknown error."); 1497 msg = _("Unknown error.");
1492 } 1498 }
1493
1494 gaim_connection_error(gc, msg); 1499 gaim_connection_error(gc, msg);
1495 } 1500 }
1496 1501
1497 static void yahoo_process_addbuddy(GaimConnection *gc, struct yahoo_packet *pkt) 1502 static void yahoo_process_addbuddy(GaimConnection *gc, struct yahoo_packet *pkt)
1498 { 1503 {
1723 yahoo_packet_free(pkt); 1728 yahoo_packet_free(pkt);
1724 1729
1725 gc->inpa = gaim_input_add(yd->fd, GAIM_INPUT_READ, yahoo_pending, gc); 1730 gc->inpa = gaim_input_add(yd->fd, GAIM_INPUT_READ, yahoo_pending, gc);
1726 } 1731 }
1727 1732
1733 #ifdef YAHOO_WEBMESSENGER
1734 static void yahoo_got_web_connected(gpointer data, gint source, GaimInputCondition cond)
1735 {
1736 GaimConnection *gc = data;
1737 struct yahoo_data *yd;
1738 struct yahoo_packet *pkt;
1739
1740 if (!g_list_find(gaim_connections_get_all(), gc)) {
1741 close(source);
1742 return;
1743 }
1744
1745 if (source < 0) {
1746 gaim_connection_error(gc, _("Unable to connect"));
1747 return;
1748 }
1749
1750 yd = gc->proto_data;
1751 yd->fd = source;
1752
1753 pkt = yahoo_packet_new(YAHOO_SERVICE_WEBLOGIN, YAHOO_STATUS_WEBLOGIN, 0);
1754
1755 yahoo_packet_hash(pkt, 0, gaim_normalize(gaim_account_get_username(gaim_connection_get_account(gc))));
1756 yahoo_packet_hash(pkt, 1, gaim_normalize(gaim_account_get_username(gaim_connection_get_account(gc))));
1757 yahoo_packet_hash(pkt, 6, yd->auth);
1758 yahoo_send_packet(yd, pkt);
1759
1760 yahoo_packet_free(pkt);
1761 g_free(yd->auth);
1762 gc->inpa = gaim_input_add(yd->fd, GAIM_INPUT_READ, yahoo_pending, gc);
1763 }
1764
1765 static void yahoo_web_pending(gpointer data, gint source, GaimInputCondition cond)
1766 {
1767 GaimConnection *gc = data;
1768 GaimAccount *account = gaim_connection_get_account(gc);
1769 struct yahoo_data *yd = gc->proto_data;
1770 char buf[1024], buf2[256], *i = buf, *r = buf2;
1771 int len, o = 0;
1772
1773 len = read(source, buf, sizeof(buf));
1774
1775 if (len <= 0 || strncmp(buf, "HTTP/1.0 302", strlen("HTTP/1.0 302"))) {
1776 gaim_connection_error(gc, _("Unable to read"));
1777 return;
1778 }
1779
1780 while ((i = strstr(i, "Set-Cookie: ")) && 0 < 2) {
1781 i += strlen("Set-Cookie: ");
1782 for (;*i != ';'; r++, i++) {
1783 *r = *i;
1784 }
1785 *r=';';
1786 r++;
1787 *r=' ';
1788 r++;
1789 o++;
1790 }
1791 /* Get rid of that "; " */
1792 *(r-2) = '\0';
1793 yd->auth = g_strdup(buf2);
1794 gaim_input_remove(gc->inpa);
1795 close(source);
1796
1797 /* Now we have our cookies to login with. I'll go get the milk. */
1798 if (gaim_proxy_connect(account, "wcs1.msg.sc5.yahoo.com",
1799 gaim_account_get_int(account, "port", YAHOO_PAGER_PORT),
1800 yahoo_got_web_connected, gc) != 0) {
1801 gaim_connection_error(gc, _("Connection problem"));
1802 return;
1803 }
1804 }
1805
1806 static void yahoo_got_cookies(gpointer data, gint source, GaimInputCondition cond)
1807 {
1808 GaimConnection *gc = data;
1809 struct yahoo_data *yd = gc->proto_data;
1810 if (source < 0) {
1811 gaim_connection_error(gc, _("Unable to connect"));
1812 return;
1813 }
1814 write(source, yd->auth, strlen(yd->auth));
1815 g_free(yd->auth);
1816 gc->inpa = gaim_input_add(source, GAIM_INPUT_READ, yahoo_web_pending, gc);
1817 }
1818
1819 static void yahoo_login_page_hash_iter(const char *key, const char *val, GString *url)
1820 {
1821 if (!strcmp(key, "passwd"))
1822 return;
1823 url = g_string_append_c(url, '&');
1824 url = g_string_append(url, key);
1825 url = g_string_append_c(url, '=');
1826 if (!strcmp(key, ".save") || !strcmp(key, ".js"))
1827 url = g_string_append_c(url, '1');
1828 else if (!strcmp(key, ".challenge"))
1829 url = g_string_append(url, val);
1830 else
1831 url = g_string_append(url, gaim_url_encode(val));
1832 }
1833
1834 static GHashTable *yahoo_login_page_hash(const char *buf, size_t len)
1835 {
1836 GHashTable *hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
1837 const char *c = buf, *d;
1838 char name[64], value[64];
1839 while ((c < (buf + len)) && (c = strstr(c, "<input "))) {
1840 c = strstr(c, "name=\"") + strlen("name=\"");
1841 for (d = name; *c!='"'; c++, d++)
1842 *d = *c;
1843 *d = '\0';
1844 d = strstr(c, "value=\"") + strlen("value=\"");
1845 if (strchr(c, '>') < d)
1846 break;
1847 for (c = d, d = value; *c!='"'; c++, d++)
1848 *d = *c;
1849 *d = '\0';
1850 g_hash_table_insert(hash, g_strdup(name), g_strdup(value));
1851 }
1852 return hash;
1853 }
1854
1855 static void yahoo_login_page_cb(GaimConnection *gc, const char *buf, size_t len)
1856 {
1857 GaimAccount *account = gaim_connection_get_account(gc);
1858 struct yahoo_data *yd = gc->proto_data;
1859 const char *sn = gaim_account_get_username(account);
1860 const char *pass = gaim_account_get_password(account);
1861
1862 GHashTable *hash = yahoo_login_page_hash(buf, len);
1863 GString *url = g_string_new("GET /config/login?login=");
1864 url = g_string_append(url, sn);
1865 url = g_string_append(url, "&passwd=");
1866
1867 char md5[33], *hashp = md5, *chal;
1868 int i;
1869 md5_byte_t result[16];
1870 md5_state_t ctx;
1871 md5_init(&ctx);
1872 md5_append(&ctx, pass, strlen(pass));
1873 md5_finish(&ctx, result);
1874 for (i = 0; i < 16; ++i) {
1875 g_snprintf(hashp, 3, "%02x", result[i]);
1876 hashp += 2;
1877 }
1878 chal = g_strconcat(md5, g_hash_table_lookup(hash, ".challenge"), NULL);
1879 md5_init(&ctx);
1880 md5_append(&ctx, chal, strlen(chal));
1881 md5_finish(&ctx, result);
1882 hashp = md5;
1883 for (i = 0; i < 16; ++i) {
1884 g_snprintf(hashp, 3, "%02x", result[i]);
1885 hashp += 2;
1886 }
1887 /*
1888 md5_init(&ctx);
1889 md5_append(&ctx, md5, strlen(md5));
1890 md5_finish(&ctx, result);
1891 hashp = md5;
1892 for (i = 0; i < 16; ++i) {
1893 g_snprintf(hashp, 3, "%02x", result[i]);
1894 hashp += 2;
1895 }
1896 */
1897 g_free(chal);
1898
1899 url = g_string_append(url, md5);
1900 g_hash_table_foreach(hash, yahoo_login_page_hash_iter, url);
1901
1902 url = g_string_append(url, "&.hash=1&.md5=1 HTTP/1.1\r\n"
1903 "Host: login.yahoo.com\r\n\r\n");
1904 g_hash_table_destroy(hash);
1905
1906 yd->auth = g_string_free(url, FALSE);
1907 if (gaim_proxy_connect(account, "login.yahoo.com", 80, yahoo_got_cookies, gc) != 0) {
1908 gaim_connection_error(gc, _("Connection problem"));
1909 return;
1910 }
1911 }
1912
1913 #endif /* YAHOO_WEBMESSENGER */
1914
1728 static void yahoo_login(GaimAccount *account) { 1915 static void yahoo_login(GaimAccount *account) {
1729 GaimConnection *gc = gaim_account_get_connection(account); 1916 GaimConnection *gc = gaim_account_get_connection(account);
1730 struct yahoo_data *yd = gc->proto_data = g_new0(struct yahoo_data, 1); 1917 struct yahoo_data *yd = gc->proto_data = g_new0(struct yahoo_data, 1);
1731 1918
1732 gc->flags |= GAIM_CONNECTION_HTML | GAIM_CONNECTION_NO_BGCOLOR; 1919 gc->flags |= GAIM_CONNECTION_HTML | GAIM_CONNECTION_NO_BGCOLOR;
1736 yd->fd = -1; 1923 yd->fd = -1;
1737 yd->friends = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, yahoo_friend_free); 1924 yd->friends = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, yahoo_friend_free);
1738 yd->confs = NULL; 1925 yd->confs = NULL;
1739 yd->conf_id = 2; 1926 yd->conf_id = 2;
1740 1927
1928 #ifndef YAHOO_WEBMESSENGER
1741 if (gaim_proxy_connect(account, gaim_account_get_string(account, "server", YAHOO_PAGER_HOST), 1929 if (gaim_proxy_connect(account, gaim_account_get_string(account, "server", YAHOO_PAGER_HOST),
1742 gaim_account_get_int(account, "port", YAHOO_PAGER_PORT), 1930 gaim_account_get_int(account, "port", YAHOO_PAGER_PORT),
1743 yahoo_got_connected, gc) != 0) { 1931 yahoo_got_connected, gc) != 0) {
1744 gaim_connection_error(gc, _("Connection problem")); 1932 gaim_connection_error(gc, _("Connection problem"));
1745 return; 1933 return;
1746 } 1934 }
1935 #else
1936 gaim_url_fetch(WEBMESSENGER_URL, TRUE, "Gaim/" VERSION, FALSE, yahoo_login_page_cb, gc);
1937 #endif
1747 1938
1748 } 1939 }
1749 1940
1750 static void yahoo_close(GaimConnection *gc) { 1941 static void yahoo_close(GaimConnection *gc) {
1751 struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data; 1942 struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;