Mercurial > pidgin.yaz
comparison src/cipher.c @ 12382:cfc808463763
[gaim-migrate @ 14688]
Reimplement HTTP Digest Authentication (RFC 2617) as part of the Cipher API
committer: Tailor Script <tailor@pidgin.im>
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Wed, 07 Dec 2005 04:50:36 +0000 |
parents | 8004885fabbe |
children | 4e045668b9d0 |
comparison
equal
deleted
inserted
replaced
12381:29e237c4141b | 12382:cfc808463763 |
---|---|
1778 gaim_cipher_context_get_data(GaimCipherContext *context) { | 1778 gaim_cipher_context_get_data(GaimCipherContext *context) { |
1779 g_return_val_if_fail(context, NULL); | 1779 g_return_val_if_fail(context, NULL); |
1780 | 1780 |
1781 return context->data; | 1781 return context->data; |
1782 } | 1782 } |
1783 | |
1784 gchar *gaim_cipher_http_digest_calculate_session_key( | |
1785 const gchar *algorithm, | |
1786 const gchar *username, | |
1787 const gchar *realm, | |
1788 const gchar *password, | |
1789 const gchar *nonce, | |
1790 const gchar *client_nonce) | |
1791 { | |
1792 GaimCipher *cipher; | |
1793 GaimCipherContext *context; | |
1794 gchar hash[32]; /* We only support MD5. */ | |
1795 | |
1796 g_return_val_if_fail(username != NULL, NULL); | |
1797 g_return_val_if_fail(realm != NULL, NULL); | |
1798 g_return_val_if_fail(password != NULL, NULL); | |
1799 g_return_val_if_fail(nonce != NULL, NULL); | |
1800 | |
1801 /* Check for a supported algorithm. */ | |
1802 g_return_val_if_fail(algorithm == NULL || | |
1803 *algorithm == '\0' || | |
1804 strcasecmp(algorithm, "MD5") || | |
1805 strcasecmp(algorithm, "MD5-sess"), NULL); | |
1806 | |
1807 cipher = gaim_ciphers_find_cipher("md5"); | |
1808 g_return_val_if_fail(cipher != NULL, NULL); | |
1809 | |
1810 context = gaim_cipher_context_new(cipher, NULL); | |
1811 | |
1812 gaim_cipher_context_append(context, (guchar *)username, strlen(username)); | |
1813 gaim_cipher_context_append(context, (guchar *)":", 1); | |
1814 gaim_cipher_context_append(context, (guchar *)realm, strlen(realm)); | |
1815 gaim_cipher_context_append(context, (guchar *)":", 1); | |
1816 gaim_cipher_context_append(context, (guchar *)password, strlen(password)); | |
1817 | |
1818 if (algorithm != NULL && !strcasecmp(algorithm, "MD5-sess")) | |
1819 { | |
1820 guchar digest[16]; | |
1821 | |
1822 if (client_nonce == NULL) | |
1823 { | |
1824 gaim_cipher_context_destroy(context); | |
1825 gaim_debug_error("cipher", "Required client_nonce missing for MD5-sess digest calculation."); | |
1826 return NULL; | |
1827 } | |
1828 | |
1829 gaim_cipher_context_digest(context, sizeof(digest), digest, NULL); | |
1830 gaim_cipher_context_destroy(context); | |
1831 | |
1832 context = gaim_cipher_context_new(cipher, NULL); | |
1833 gaim_cipher_context_append(context, digest, sizeof(digest)); | |
1834 gaim_cipher_context_append(context, (guchar *)":", 1); | |
1835 gaim_cipher_context_append(context, (guchar *)nonce, strlen(nonce)); | |
1836 gaim_cipher_context_append(context, (guchar *)":", 1); | |
1837 gaim_cipher_context_append(context, (guchar *)client_nonce, strlen(client_nonce)); | |
1838 } | |
1839 | |
1840 gaim_cipher_context_digest_to_str(context, sizeof(hash), hash, NULL); | |
1841 gaim_cipher_context_destroy(context); | |
1842 | |
1843 return g_strdup(hash); | |
1844 } | |
1845 | |
1846 gchar *gaim_cipher_http_digest_calculate_response( | |
1847 const gchar *algorithm, | |
1848 const gchar *method, | |
1849 const gchar *digest_uri, | |
1850 const gchar *qop, | |
1851 const gchar *hashed_entity, | |
1852 size_t hashed_entity_len, | |
1853 const gchar *nonce, | |
1854 const gchar *nonce_count, | |
1855 const gchar *client_nonce, | |
1856 const gchar *session_key) | |
1857 { | |
1858 GaimCipher *cipher; | |
1859 GaimCipherContext *context; | |
1860 gchar hash2[32]; /* We only support MD5. */ | |
1861 | |
1862 g_return_val_if_fail(method != NULL, NULL); | |
1863 g_return_val_if_fail(digest_uri != NULL, NULL); | |
1864 g_return_val_if_fail(nonce != NULL, NULL); | |
1865 g_return_val_if_fail(session_key != NULL, NULL); | |
1866 | |
1867 /* Check for a supported algorithm. */ | |
1868 g_return_val_if_fail(algorithm == NULL || | |
1869 *algorithm == '\0' || | |
1870 strcasecmp(algorithm, "MD5") || | |
1871 strcasecmp(algorithm, "MD5-sess"), NULL); | |
1872 | |
1873 /* Check for a supported "quality of protection". */ | |
1874 g_return_val_if_fail(qop == NULL || | |
1875 *qop == '\0' || | |
1876 strcasecmp(qop, "auth") || | |
1877 strcasecmp(qop, "auth-int"), NULL); | |
1878 | |
1879 cipher = gaim_ciphers_find_cipher("md5"); | |
1880 g_return_val_if_fail(cipher != NULL, NULL); | |
1881 | |
1882 context = gaim_cipher_context_new(cipher, NULL); | |
1883 | |
1884 gaim_cipher_context_append(context, (guchar *)method, strlen(method)); | |
1885 gaim_cipher_context_append(context, (guchar *)":", 1); | |
1886 gaim_cipher_context_append(context, (guchar *)digest_uri, strlen(digest_uri)); | |
1887 | |
1888 if (qop != NULL && !strcasecmp(qop, "auth-int")) | |
1889 { | |
1890 if (hashed_entity == NULL) | |
1891 { | |
1892 gaim_cipher_context_destroy(context); | |
1893 gaim_debug_error("cipher", "Required hashed_entity missing for auth-int digest calculation."); | |
1894 return NULL; | |
1895 } | |
1896 | |
1897 gaim_cipher_context_append(context, (guchar *)":", 1); | |
1898 gaim_cipher_context_append(context, (guchar *)hashed_entity, hashed_entity_len); | |
1899 } | |
1900 | |
1901 gaim_cipher_context_digest_to_str(context, sizeof(hash2), hash2, NULL); | |
1902 gaim_cipher_context_destroy(context); | |
1903 | |
1904 context = gaim_cipher_context_new(cipher, NULL); | |
1905 gaim_cipher_context_append(context, (guchar *)session_key, strlen(session_key)); | |
1906 gaim_cipher_context_append(context, (guchar *)":", 1); | |
1907 gaim_cipher_context_append(context, (guchar *)nonce, strlen(nonce)); | |
1908 gaim_cipher_context_append(context, (guchar *)":", 1); | |
1909 | |
1910 if (qop != NULL && *qop != '\0') | |
1911 { | |
1912 if (nonce_count == NULL) | |
1913 { | |
1914 gaim_cipher_context_destroy(context); | |
1915 gaim_debug_error("cipher", "Required nonce_count missing for digest calculation."); | |
1916 return NULL; | |
1917 } | |
1918 | |
1919 if (client_nonce == NULL) | |
1920 { | |
1921 gaim_cipher_context_destroy(context); | |
1922 gaim_debug_error("cipher", "Required client_nonce missing for digest calculation."); | |
1923 return NULL; | |
1924 } | |
1925 | |
1926 gaim_cipher_context_append(context, (guchar *)nonce_count, strlen(nonce_count)); | |
1927 gaim_cipher_context_append(context, (guchar *)":", 1); | |
1928 gaim_cipher_context_append(context, (guchar *)client_nonce, strlen(client_nonce)); | |
1929 gaim_cipher_context_append(context, (guchar *)":", 1); | |
1930 | |
1931 if (qop != NULL) | |
1932 gaim_cipher_context_append(context, (guchar *)qop, strlen(qop)); | |
1933 else | |
1934 gaim_cipher_context_append(context, (guchar *)"", 0); | |
1935 | |
1936 gaim_cipher_context_append(context, (guchar *)":", 1); | |
1937 } | |
1938 | |
1939 gaim_cipher_context_append(context, (guchar *)hash2, strlen(hash2)); | |
1940 gaim_cipher_context_digest_to_str(context, sizeof(hash2), hash2, NULL); | |
1941 gaim_cipher_context_destroy(context); | |
1942 | |
1943 return g_strdup(hash2); | |
1944 } |