Ignore:
Timestamp:
Feb 26, 2007 10:31:06 PM (17 years ago)
Author:
bennylp
Message:

Finishing up STUN server side authentication

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib-util/src/pjlib-util/stun_msg.c

    r1002 r1003  
    2222#include <pjlib-util/hmac_sha1.h> 
    2323#include <pjlib-util/md5.h> 
     24#include <pjlib-util/sha1.h> 
    2425#include <pj/assert.h> 
    2526#include <pj/log.h> 
     
    15601561    unsigned uattr_cnt; 
    15611562    const pj_uint8_t *start_pdu = pdu; 
     1563    pj_bool_t has_msg_int = PJ_FALSE; 
     1564    pj_bool_t has_fingerprint = PJ_FALSE; 
    15621565    pj_status_t status; 
    15631566 
     
    15871590 
    15881591    pdu += sizeof(pj_stun_msg_hdr); 
    1589     pdu_len -= sizeof(pj_stun_msg_hdr); 
     1592    /* pdu_len -= sizeof(pj_stun_msg_hdr); */ 
     1593    pdu_len = msg->hdr.length; 
    15901594 
    15911595    /* No need to create response if this is not a request */ 
     
    16881692                return status; 
    16891693            } 
    1690              
     1694 
     1695            if (attr_type == PJ_STUN_ATTR_MESSAGE_INTEGRITY &&  
     1696                !has_fingerprint)  
     1697            { 
     1698                if (has_msg_int) { 
     1699                    /* Already has MESSAGE-INTEGRITY */ 
     1700                    if (p_response) { 
     1701                        pj_str_t e; 
     1702                        e = pj_str("MESSAGE-INTEGRITY already present"); 
     1703                        pj_stun_msg_create_response(pool, msg, 
     1704                                                    PJ_STUN_STATUS_BAD_REQUEST, 
     1705                                                    NULL, p_response); 
     1706                    } 
     1707                    return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_STATUS_BAD_REQUEST); 
     1708                } 
     1709                has_msg_int = PJ_TRUE; 
     1710 
     1711            } else if (attr_type == PJ_STUN_ATTR_FINGERPRINT) { 
     1712                if (has_fingerprint) { 
     1713                    /* Already has FINGERPRINT */ 
     1714                    if (p_response) { 
     1715                        pj_str_t e; 
     1716                        e = pj_str("FINGERPRINT already present"); 
     1717                        pj_stun_msg_create_response(pool, msg, 
     1718                                                    PJ_STUN_STATUS_BAD_REQUEST, 
     1719                                                    NULL, p_response); 
     1720                    } 
     1721                    return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_STATUS_BAD_REQUEST); 
     1722                } 
     1723                has_fingerprint = PJ_TRUE; 
     1724            } else { 
     1725                if (has_msg_int || has_fingerprint) { 
     1726                    /* Another attribute is found which is not FINGERPRINT 
     1727                     * after FINGERPRINT or MESSAGE-INTEGRITY */ 
     1728                    if (p_response) { 
     1729                        pj_str_t e; 
     1730                        e = pj_str("Invalid attribute order"); 
     1731                        pj_stun_msg_create_response(pool, msg, 
     1732                                                    PJ_STUN_STATUS_BAD_REQUEST, 
     1733                                                    NULL, p_response); 
     1734                    } 
     1735                    return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_STATUS_BAD_REQUEST); 
     1736                } 
     1737            } 
     1738 
    16911739            /* Make sure we have rooms for the new attribute */ 
    16921740            if (msg->attr_count >= PJ_STUN_MAX_ATTR) { 
     
    17161764 
    17171765    return PJ_SUCCESS; 
     1766} 
     1767 
     1768/* Calculate HMAC-SHA1 key for long term credential, by getting 
     1769 * MD5 digest of username, realm, and password.  
     1770 */ 
     1771static void calc_md5_key(pj_uint8_t digest[16], 
     1772                         const pj_str_t *realm, 
     1773                         const pj_str_t *username, 
     1774                         const pj_str_t *passwd) 
     1775{ 
     1776    /* The 16-byte key for MESSAGE-INTEGRITY HMAC is formed by taking 
     1777     * the MD5 hash of the result of concatenating the following five 
     1778     * fields: (1) The username, with any quotes and trailing nulls 
     1779     * removed, (2) A single colon, (3) The realm, with any quotes and 
     1780     * trailing nulls removed, (4) A single colon, and (5) The  
     1781     * password, with any trailing nulls removed. 
     1782     */ 
     1783    pj_md5_context ctx; 
     1784    pj_str_t s; 
     1785 
     1786    pj_md5_init(&ctx); 
     1787 
     1788#define REMOVE_QUOTE(s) if (s.slen && *s.ptr=='"') \ 
     1789                    s.ptr++, s.slen--; \ 
     1790                if (s.slen && s.ptr[s.slen-1]=='"') \ 
     1791                    s.slen--; 
     1792 
     1793    /* Add username */ 
     1794    s = *username; 
     1795    REMOVE_QUOTE(s); 
     1796    pj_md5_update(&ctx, (pj_uint8_t*)s.ptr, s.slen); 
     1797 
     1798    /* Add single colon */ 
     1799    pj_md5_update(&ctx, (pj_uint8_t*)":", 1); 
     1800 
     1801    /* Add realm */ 
     1802    s = *realm; 
     1803    REMOVE_QUOTE(s); 
     1804    pj_md5_update(&ctx, (pj_uint8_t*)s.ptr, s.slen); 
     1805 
     1806#undef REMOVE_QUOTE 
     1807 
     1808    /* Another colon */ 
     1809    pj_md5_update(&ctx, (pj_uint8_t*)":", 1); 
     1810 
     1811    /* Add password */ 
     1812    pj_md5_update(&ctx, (pj_uint8_t*)passwd->ptr, passwd->slen); 
     1813 
     1814    /* Done */ 
     1815    pj_md5_final(&ctx, digest); 
    17181816} 
    17191817 
     
    17961894    } 
    17971895 
     1896    /* We MUST update the message length in the header NOW before 
     1897     * calculating MESSAGE-INTEGRITY and FINGERPRINT.  
     1898     * Note that length is not including the 20 bytes header. 
     1899     */ 
     1900    if (amsg_integrity && afingerprint) { 
     1901        length = (pj_uint16_t)((buf - start) - 20 + 24 + 8); 
     1902    } else if (amsg_integrity) { 
     1903        length = (pj_uint16_t)((buf - start) - 20 + 24); 
     1904    } else if (afingerprint) { 
     1905        length = (pj_uint16_t)((buf - start) - 20 + 8); 
     1906    } else { 
     1907        length = (pj_uint16_t)((buf - start) - 20); 
     1908    } 
     1909 
     1910    /* hdr->length = pj_htons(length); */ 
     1911    *(buf+2) = (pj_uint8_t)((length >> 8) & 0x00FF); 
     1912    *(buf+3) = (pj_uint8_t)(length & 0x00FF); 
     1913 
    17981914    /* Calculate message integrity, if present */ 
    17991915    if (amsg_integrity != NULL) { 
     
    18361952 
    18371953        } else { 
    1838             /* The 16-byte key for MESSAGE-INTEGRITY HMAC is formed by taking 
    1839              * the MD5 hash of the result of concatenating the following five 
    1840              * fields: (1) The username, with any quotes and trailing nulls 
    1841              * removed, (2) A single colon, (3) The realm, with any quotes and 
    1842              * trailing nulls removed, (4) A single colon, and (5) The  
    1843              * password, with any trailing nulls removed. 
    1844              */ 
    1845             pj_md5_context ctx; 
    1846             pj_str_t s; 
    1847  
    1848             pj_md5_init(&ctx); 
    1849  
    1850 #define REMOVE_QUOTE(s) if (s.slen && *s.ptr=='"') \ 
    1851                             s.ptr++, s.slen--; \ 
    1852                         if (s.slen && s.ptr[s.slen-1]=='"') \ 
    1853                             s.slen--; 
    1854  
    1855             /* Add username */ 
    1856             s = auname->value; 
    1857             REMOVE_QUOTE(s); 
    1858             pj_md5_update(&ctx, (pj_uint8_t*)s.ptr, s.slen); 
    1859  
    1860             /* Add single colon */ 
    1861             pj_md5_update(&ctx, (pj_uint8_t*)":", 1); 
    1862  
    1863             /* Add realm */ 
    1864             s = arealm->value; 
    1865             REMOVE_QUOTE(s); 
    1866             pj_md5_update(&ctx, (pj_uint8_t*)s.ptr, s.slen); 
    1867  
    1868 #undef REMOVE_QUOTE 
    1869  
    1870             /* Another colon */ 
    1871             pj_md5_update(&ctx, (pj_uint8_t*)":", 1); 
    1872  
    1873             /* Add password */ 
    1874             pj_md5_update(&ctx, (pj_uint8_t*)password->ptr, password->slen); 
    1875  
    1876             /* Done */ 
    1877             pj_md5_final(&ctx, md5_key_buf); 
     1954            calc_md5_key(md5_key_buf, &arealm->value, &auname->value,  
     1955                         password); 
    18781956            key.ptr = (char*) md5_key_buf; 
    18791957            key.slen = 16; 
     
    19101988    } 
    19111989 
    1912     /* Update the message length in the header.  
    1913      * Note that length is not including the 20 bytes header. 
    1914      */ 
    1915     length = (pj_uint16_t)((buf - start) - 20); 
    1916     /* hdr->length = pj_htons(length); */ 
    1917     *(buf+2) = (pj_uint8_t)((length >> 8) & 0x00FF); 
    1918     *(buf+3) = (pj_uint8_t)(length & 0x00FF); 
    1919  
    1920  
    19211990    /* Done */ 
    19221991    if (p_msg_len) 
     
    19462015 
    19472016 
     2017/**************************************************************************/ 
     2018/* 
     2019 * Authentication 
     2020 */ 
     2021 
     2022 
     2023/* Send 401 response */ 
     2024static pj_status_t create_challenge(pj_pool_t *pool, 
     2025                                    const pj_stun_msg *msg, 
     2026                                    int err_code, 
     2027                                    const pj_str_t *err_msg, 
     2028                                    const pj_str_t *realm, 
     2029                                    const pj_str_t *nonce, 
     2030                                    pj_stun_msg **p_response) 
     2031{ 
     2032    pj_stun_msg *response; 
     2033    pj_status_t rc; 
     2034 
     2035    rc = pj_stun_msg_create_response(pool, msg,  
     2036                                     err_code,  err_msg, &response); 
     2037    if (rc != PJ_SUCCESS) 
     2038        return rc; 
     2039 
     2040 
     2041    if (realm && realm->slen) { 
     2042        rc = pj_stun_msg_add_generic_string_attr(pool, response, 
     2043                                                 PJ_STUN_ATTR_REALM,  
     2044                                                 realm); 
     2045        if (rc != PJ_SUCCESS) 
     2046            return rc; 
     2047    } 
     2048 
     2049    if (nonce && nonce->slen) { 
     2050        rc = pj_stun_msg_add_generic_string_attr(pool, response, 
     2051                                                 PJ_STUN_ATTR_NONCE,  
     2052                                                 nonce); 
     2053        if (rc != PJ_SUCCESS) 
     2054            return rc; 
     2055    } 
     2056 
     2057    *p_response = response; 
     2058 
     2059    return PJ_SUCCESS; 
     2060} 
     2061 
    19482062/* Verify credential */ 
    1949 PJ_DEF(pj_status_t) pj_stun_verify_credential( const pj_stun_msg *msg, 
    1950                                                const pj_str_t *realm, 
    1951                                                const pj_str_t *username, 
    1952                                                const pj_str_t *password, 
    1953                                                unsigned options, 
     2063PJ_DEF(pj_status_t) pj_stun_verify_credential( const pj_uint8_t *pkt, 
     2064                                               unsigned pkt_len, 
     2065                                               const pj_stun_msg *msg, 
     2066                                               pj_stun_auth_policy *pol, 
    19542067                                               pj_pool_t *pool, 
    19552068                                               pj_stun_msg **p_response) 
    19562069{ 
     2070    pj_str_t realm, nonce, password; 
    19572071    const pj_stun_msg_integrity_attr *amsgi; 
     2072    unsigned amsgi_pos; 
    19582073    const pj_stun_username_attr *auser; 
     2074    pj_bool_t username_ok; 
    19592075    const pj_stun_realm_attr *arealm; 
    1960  
    1961     PJ_ASSERT_RETURN(msg && password, PJ_EINVAL); 
    1962     PJ_ASSERT_RETURN(options==0, PJ_EINVAL); 
    1963     PJ_UNUSED_ARG(options); 
     2076    const pj_stun_realm_attr *anonce; 
     2077    pj_uint8_t digest[PJ_SHA1_DIGEST_SIZE]; 
     2078    pj_uint8_t md5_digest[16]; 
     2079    pj_str_t key; 
     2080    pj_status_t status; 
     2081 
     2082    /* msg and policy MUST be specified */ 
     2083    PJ_ASSERT_RETURN(pkt && pkt_len && msg && pol, PJ_EINVAL); 
     2084 
     2085    /* If p_response is specified, pool MUST be specified. */ 
     2086    PJ_ASSERT_RETURN(!p_response || pool, PJ_EINVAL); 
    19642087 
    19652088    if (p_response) 
    19662089        *p_response = NULL; 
     2090 
     2091    if (PJ_STUN_IS_REQUEST(msg->hdr.type)) 
     2092        p_response = NULL; 
     2093 
     2094    /* Get realm and nonce */ 
     2095    realm.slen = nonce.slen = 0; 
     2096    if (pol->type == PJ_STUN_POLICY_STATIC_SHORT_TERM) { 
     2097        realm.slen = 0; 
     2098        nonce = pol->data.static_short_term.nonce; 
     2099    } else if (pol->type == PJ_STUN_POLICY_STATIC_LONG_TERM) { 
     2100        realm = pol->data.static_long_term.realm; 
     2101        nonce = pol->data.static_long_term.nonce; 
     2102    } else if (pol->type == PJ_STUN_POLICY_DYNAMIC) { 
     2103        status = pol->data.dynamic.get_auth(pol->user_data, pool,  
     2104                                            &realm, &nonce); 
     2105        if (status != PJ_SUCCESS) 
     2106            return status; 
     2107    } else { 
     2108        pj_assert(!"Unexpected"); 
     2109        return PJ_EBUG; 
     2110    } 
    19672111 
    19682112    /* First check that MESSAGE-INTEGRITY is present */ 
     
    19702114            pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_MESSAGE_INTEGRITY, 0); 
    19712115    if (amsgi == NULL) { 
    1972         if (pool && p_response) { 
    1973             pj_status_t rc; 
    1974  
    1975             rc = pj_stun_msg_create_response(pool, msg,  
    1976                                              PJ_STUN_STATUS_UNAUTHORIZED,  
    1977                                              NULL, p_response); 
    1978             if (rc==PJ_SUCCESS && realm) { 
    1979                 pj_stun_msg_add_generic_string_attr(pool, *p_response, 
    1980                                                     PJ_STUN_ATTR_REALM,  
    1981                                                     realm); 
    1982             } 
     2116        if (p_response) { 
     2117            create_challenge(pool, msg, PJ_STUN_STATUS_UNAUTHORIZED, NULL, 
     2118                             &realm, &nonce, p_response); 
    19832119        } 
    19842120        return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_STATUS_UNAUTHORIZED); 
     
    19892125            pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_USERNAME, 0); 
    19902126    if (auser == NULL) { 
    1991         if (pool && p_response) { 
    1992             pj_status_t rc; 
    1993  
    1994             rc = pj_stun_msg_create_response(pool, msg,  
    1995                                              PJ_STUN_STATUS_MISSING_USERNAME,  
    1996                                              NULL, p_response); 
    1997             if (rc==PJ_SUCCESS && realm) { 
    1998                 pj_stun_msg_add_generic_string_attr(pool, *p_response, 
    1999                                                     PJ_STUN_ATTR_REALM,  
    2000                                                     realm); 
    2001             } 
     2127        if (p_response) { 
     2128            create_challenge(pool, msg, PJ_STUN_STATUS_MISSING_USERNAME, NULL, 
     2129                             &realm, &nonce, p_response); 
    20022130        } 
    20032131        return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_STATUS_MISSING_USERNAME); 
    20042132    } 
    20052133 
    2006     /* Check if username match */ 
    2007     if (username && pj_stricmp(&auser->value, username) != 0) { 
    2008         /* Username mismatch */ 
    2009         if (pool && p_response) { 
    2010             pj_status_t rc; 
    2011  
    2012             rc = pj_stun_msg_create_response(pool, msg,  
    2013                                              PJ_STUN_STATUS_WRONG_USERNAME,  
    2014                                              NULL, p_response); 
    2015             if (rc==PJ_SUCCESS && realm) { 
    2016                 pj_stun_msg_add_generic_string_attr(pool, *p_response, 
    2017                                                     PJ_STUN_ATTR_REALM,  
    2018                                                     realm); 
    2019             } 
    2020         } 
    2021         return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_STATUS_WRONG_USERNAME); 
    2022     } 
    2023  
    2024     /* Next check that REALM is present */ 
     2134    /* Get REALM, if any */ 
    20252135    arealm = (const pj_stun_realm_attr*) 
    20262136             pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_REALM, 0); 
    2027     if (realm != NULL && arealm == NULL) { 
    2028         /* Long term credential is required */ 
    2029         if (pool && p_response) { 
    2030             pj_status_t rc; 
    2031  
    2032             rc = pj_stun_msg_create_response(pool, msg,  
    2033                                              PJ_STUN_STATUS_MISSING_REALM,  
    2034                                              NULL, p_response); 
    2035             if (rc==PJ_SUCCESS) { 
    2036                 pj_stun_msg_add_generic_string_attr(pool, *p_response, 
    2037                                                     PJ_STUN_ATTR_REALM,  
    2038                                                     realm); 
    2039             } 
     2137 
     2138    /* Check if username match */ 
     2139    if (pol->type == PJ_STUN_POLICY_STATIC_SHORT_TERM) { 
     2140        username_ok = !pj_strcmp(&auser->value,  
     2141                                 &pol->data.static_short_term.username); 
     2142        password = pol->data.static_short_term.password; 
     2143    } else if (pol->type == PJ_STUN_POLICY_STATIC_LONG_TERM) { 
     2144        username_ok = !pj_strcmp(&auser->value,  
     2145                                 &pol->data.static_long_term.username); 
     2146        password = pol->data.static_long_term.password; 
     2147    } else if (pol->type == PJ_STUN_POLICY_DYNAMIC) { 
     2148        pj_status_t rc; 
     2149        rc = pol->data.dynamic.get_password(pol->user_data,  
     2150                                            (arealm?&arealm->value:NULL), 
     2151                                            &auser->value, pool, 
     2152                                            &password); 
     2153        username_ok = (rc == PJ_SUCCESS); 
     2154    } else { 
     2155        username_ok = PJ_TRUE; 
     2156        password.slen = 0; 
     2157    } 
     2158 
     2159    if (!username_ok) { 
     2160        /* Username mismatch */ 
     2161        if (p_response) { 
     2162            create_challenge(pool, msg, PJ_STUN_STATUS_UNKNOWN_USERNAME, NULL, 
     2163                             &realm, &nonce, p_response); 
     2164        } 
     2165        return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_STATUS_UNKNOWN_USERNAME); 
     2166    } 
     2167 
     2168 
     2169    /* Get NONCE attribute */ 
     2170    anonce = (pj_stun_nonce_attr*) 
     2171             pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_NONCE, 0); 
     2172 
     2173    /* Check for long term/short term requirements. */ 
     2174    if (realm.slen != 0 && arealm == NULL) { 
     2175        /* Long term credential is required and REALM is not present */ 
     2176        if (p_response) { 
     2177            create_challenge(pool, msg, PJ_STUN_STATUS_MISSING_REALM, NULL, 
     2178                             &realm, &nonce, p_response); 
    20402179        } 
    20412180        return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_STATUS_MISSING_REALM); 
    20422181 
    2043     } else if (realm != NULL && arealm != NULL) { 
    2044  
    2045  
    2046     } else if (realm == NULL && arealm != NULL) { 
     2182    } else if (realm.slen != 0 && arealm != NULL) { 
     2183        /* We want long term, and REALM is present */ 
     2184 
     2185        /* NONCE must be present. */ 
     2186        if (anonce == NULL) { 
     2187            if (p_response) { 
     2188                create_challenge(pool, msg, PJ_STUN_STATUS_MISSING_NONCE,  
     2189                                 NULL, &realm, &nonce, p_response); 
     2190            } 
     2191            return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_STATUS_MISSING_NONCE); 
     2192        } 
     2193 
     2194        /* Verify REALM matches */ 
     2195        if (pj_stricmp(&arealm->value, &realm)) { 
     2196            /* REALM doesn't match */ 
     2197            if (p_response) { 
     2198                create_challenge(pool, msg, PJ_STUN_STATUS_MISSING_REALM,  
     2199                                 NULL, &realm, &nonce, p_response); 
     2200            } 
     2201            return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_STATUS_MISSING_REALM); 
     2202        } 
     2203 
     2204        /* Valid case, will validate the message integrity later */ 
     2205 
     2206    } else if (realm.slen == 0 && arealm != NULL) { 
    20472207        /* We want to use short term credential, but client uses long 
    20482208         * term credential. The draft doesn't mention anything about 
    20492209         * switching between long term and short term. 
    20502210         */ 
    2051         PJ_TODO(SWITCHING_BETWEEN_SHORT_TERM_AND_LONG_TERM); 
    2052     } 
    2053  
    2054     PJ_TODO(CONTINUE_IMPLEMENTATION); 
    2055  
    2056     return PJ_SUCCESS; 
    2057 } 
    2058  
    2059  
     2211         
     2212        /* For now just accept the credential, anyway it will probably 
     2213         * cause wrong message integrity value later. 
     2214         */ 
     2215    } else if (realm.slen==0 && arealm == NULL) { 
     2216        /* Short term authentication is wanted, and one is supplied */ 
     2217 
     2218        /* Application MAY request NONCE to be supplied */ 
     2219        if (nonce.slen != 0) { 
     2220            if (p_response) { 
     2221                create_challenge(pool, msg, PJ_STUN_STATUS_MISSING_NONCE,  
     2222                                 NULL, &realm, &nonce, p_response); 
     2223            } 
     2224            return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_STATUS_MISSING_NONCE); 
     2225        } 
     2226    } 
     2227 
     2228    /* If NONCE is present, validate it */ 
     2229    if (anonce) { 
     2230        pj_bool_t ok; 
     2231 
     2232        if (pol->type == PJ_STUN_POLICY_DYNAMIC) { 
     2233            ok = pol->data.dynamic.verify_nonce(pol->user_data, 
     2234                                                (arealm?&arealm->value:NULL), 
     2235                                                &auser->value, 
     2236                                                &anonce->value); 
     2237        } else { 
     2238            if (nonce.slen) { 
     2239                ok = !pj_strcmp(&anonce->value, &nonce); 
     2240            } else { 
     2241                ok = PJ_TRUE; 
     2242            } 
     2243        } 
     2244 
     2245        if (!ok) { 
     2246            if (p_response) { 
     2247                create_challenge(pool, msg, PJ_STUN_STATUS_STALE_NONCE,  
     2248                                 NULL, &realm, &nonce, p_response); 
     2249            } 
     2250            return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_STATUS_STALE_NONCE); 
     2251        } 
     2252    } 
     2253 
     2254    /* Get the position of MESSAGE-INTEGRITY in the packet */ 
     2255    amsgi_pos = 20+msg->hdr.length-22; 
     2256    if (GET_VAL16(pkt, amsgi_pos) == PJ_STUN_ATTR_MESSAGE_INTEGRITY) { 
     2257        /* Found MESSAGE-INTEGRITY as the last attribute */ 
     2258    } else { 
     2259        amsgi_pos = 0; 
     2260    } 
     2261     
     2262    if (amsgi_pos==0) { 
     2263        amsgi_pos = 20+msg->hdr.length-8-22; 
     2264        if (GET_VAL16(pkt, amsgi_pos) == PJ_STUN_ATTR_MESSAGE_INTEGRITY) { 
     2265            /* Found MESSAGE-INTEGRITY before FINGERPRINT */ 
     2266        } else { 
     2267            amsgi_pos = 0; 
     2268        } 
     2269    } 
     2270 
     2271    if (amsgi_pos==0) { 
     2272        pj_assert(!"Unable to find MESSAGE-INTEGRITY in the message!"); 
     2273        return PJ_EBUG; 
     2274    } 
     2275 
     2276    /* Determine which key to use */ 
     2277    if (realm.slen) { 
     2278        calc_md5_key(md5_digest, &realm, &auser->value, &password); 
     2279        key.ptr = (char*)md5_digest; 
     2280        key.slen = 16; 
     2281    } else { 
     2282        key = password; 
     2283    } 
     2284 
     2285    /* Now calculate HMAC of the message */ 
     2286    pj_hmac_sha1(pkt, amsgi_pos, (pj_uint8_t*)key.ptr, key.slen, digest); 
     2287 
     2288    /* Compare HMACs */ 
     2289    if (pj_memcmp(amsgi->hmac, digest, 20)) { 
     2290        /* HMAC value mismatch */ 
     2291        if (p_response) { 
     2292            create_challenge(pool, msg, PJ_STUN_STATUS_INTEGRITY_CHECK_FAILURE, 
     2293                             NULL, &realm, &nonce, p_response); 
     2294        } 
     2295        return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_STATUS_INTEGRITY_CHECK_FAILURE); 
     2296    } 
     2297 
     2298    /* Everything looks okay! */ 
     2299    return PJ_SUCCESS; 
     2300} 
     2301 
     2302 
Note: See TracChangeset for help on using the changeset viewer.