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 }