Mercurial > pidgin.yaz
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; |