Skip to content
Snippets Groups Projects
  • George Joseph's avatar
    655ee680
    res_pjsip_outbound_authenticator_digest: Be tolerant of RFC8760 UASs · 655ee680
    George Joseph authored
    RFC7616 and RFC8760 allow more than one WWW-Authenticate or
    Proxy-Authenticate header per realm, each with different digest
    algorithms (including new ones like SHA-256 and SHA-512-256).
    Thankfully however a UAS can NOT send back multiple Authenticate
    headers for the same realm with the same digest algorithm.  The
    UAS is also supposed to send the headers in order of preference
    with the first one being the most preferred.  We're supposed to
    send an Authorization header for the first one we encounter for a
    realm that we can support.
    
    The UAS can also send multiple realms, especially when it's a
    proxy that has forked the request in which case the proxy will
    aggregate all of the Authenticate headers and then send them all
    back to the UAC.
    
    It doesn't stop there though... Each realm can require a
    different username from the others.  There's also nothing
    preventing each digest algorithm from having a unique password
    although I'm not sure if that adds any benefit.
    
    So now... For each Authenticate header we encounter, we have to
    determine if we support the digest algorithm and, if not, just
    skip the header.  We then have to find an auth object that
    matches the realm AND the digest algorithm or find a wildcard
    object that matches the digest algorithm. If we find one, we add
    it to the results vector and read the next Authenticate header.
    If the next header is for the same realm AND we already added an
    auth object for that realm, we skip the header. Otherwise we
    repeat the process for the next header.
    
    In the end, we'll have accumulated a list of credentials we can
    pass to pjproject that it can use to add Authentication headers
    to a request.
    
    NOTE: Neither we nor pjproject can currently handle digest
    algorithms other than MD5.  We don't even have a place for it in
    the ast_sip_auth object. For this reason, we just skip processing
    any Authenticate header that's not MD5.  When we support the
    others, we'll move the check into the loop that searches the
    objects.
    
    Changes:
    
     * Added a new API ast_sip_retrieve_auths_vector() that takes in
       a vector of auth ids (usually supplied on a call to
       ast_sip_create_request_with_auth()) and populates another
       vector with the actual objects.
    
     * Refactored res_pjsip_outbound_authenticator_digest to handle
       multiple Authenticate headers and set the stage for handling
       additional digest algorithms.
    
     * Added a pjproject patch that allows them to ignore digest
       algorithms they don't support.  This patch has already been
       merged upstream.
    
     * Updated documentation for auth objects in the XML and
       in pjsip.conf.sample.
    
     * Although res_pjsip_authenticator_digest isn't affected
       by this change, some debugging and a testsuite AMI event
       was added to facilitate testing.
    
    Discovered during OpenSIPit 2021.
    
    ASTERISK-29397
    
    Change-Id: I3aef5ce4fe1d27e48d61268520f284d15d650281
    655ee680
    History
    res_pjsip_outbound_authenticator_digest: Be tolerant of RFC8760 UASs
    George Joseph authored
    RFC7616 and RFC8760 allow more than one WWW-Authenticate or
    Proxy-Authenticate header per realm, each with different digest
    algorithms (including new ones like SHA-256 and SHA-512-256).
    Thankfully however a UAS can NOT send back multiple Authenticate
    headers for the same realm with the same digest algorithm.  The
    UAS is also supposed to send the headers in order of preference
    with the first one being the most preferred.  We're supposed to
    send an Authorization header for the first one we encounter for a
    realm that we can support.
    
    The UAS can also send multiple realms, especially when it's a
    proxy that has forked the request in which case the proxy will
    aggregate all of the Authenticate headers and then send them all
    back to the UAC.
    
    It doesn't stop there though... Each realm can require a
    different username from the others.  There's also nothing
    preventing each digest algorithm from having a unique password
    although I'm not sure if that adds any benefit.
    
    So now... For each Authenticate header we encounter, we have to
    determine if we support the digest algorithm and, if not, just
    skip the header.  We then have to find an auth object that
    matches the realm AND the digest algorithm or find a wildcard
    object that matches the digest algorithm. If we find one, we add
    it to the results vector and read the next Authenticate header.
    If the next header is for the same realm AND we already added an
    auth object for that realm, we skip the header. Otherwise we
    repeat the process for the next header.
    
    In the end, we'll have accumulated a list of credentials we can
    pass to pjproject that it can use to add Authentication headers
    to a request.
    
    NOTE: Neither we nor pjproject can currently handle digest
    algorithms other than MD5.  We don't even have a place for it in
    the ast_sip_auth object. For this reason, we just skip processing
    any Authenticate header that's not MD5.  When we support the
    others, we'll move the check into the loop that searches the
    objects.
    
    Changes:
    
     * Added a new API ast_sip_retrieve_auths_vector() that takes in
       a vector of auth ids (usually supplied on a call to
       ast_sip_create_request_with_auth()) and populates another
       vector with the actual objects.
    
     * Refactored res_pjsip_outbound_authenticator_digest to handle
       multiple Authenticate headers and set the stage for handling
       additional digest algorithms.
    
     * Added a pjproject patch that allows them to ignore digest
       algorithms they don't support.  This patch has already been
       merged upstream.
    
     * Updated documentation for auth objects in the XML and
       in pjsip.conf.sample.
    
     * Although res_pjsip_authenticator_digest isn't affected
       by this change, some debugging and a testsuite AMI event
       was added to facilitate testing.
    
    Discovered during OpenSIPit 2021.
    
    ASTERISK-29397
    
    Change-Id: I3aef5ce4fe1d27e48d61268520f284d15d650281