mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-12 15:45:18 +00:00
res_pjsip_outbound_authenticator_digest: Be tolerant of RFC8760 UASs
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
This commit is contained in:
committed by
Friendly Automation
parent
83c2a16b2e
commit
655ee680cd
@@ -2499,11 +2499,47 @@ int ast_sip_retrieve_auths(const struct ast_sip_auth_vector *auths, struct ast_s
|
||||
* Call this function once you have completed operating on auths
|
||||
* retrieved from \ref ast_sip_retrieve_auths
|
||||
*
|
||||
* \param auths An vector of auth structures to clean up
|
||||
* \param num_auths The number of auths in the vector
|
||||
* \param auths An array of auth object pointers to clean up
|
||||
* \param num_auths The number of auths in the array
|
||||
*/
|
||||
void ast_sip_cleanup_auths(struct ast_sip_auth *auths[], size_t num_auths);
|
||||
|
||||
/*!
|
||||
* \brief Retrieve relevant SIP auth structures from sorcery as a vector
|
||||
*
|
||||
* \param auth_ids Vector of sorcery IDs of auth credentials to retrieve
|
||||
* \param[out] auth_objects A pointer ast_sip_auth_objects_vector to hold the objects
|
||||
*
|
||||
* \retval 0 Success
|
||||
* \retval -1 Number of auth objects found is less than the number of names supplied.
|
||||
*
|
||||
* \WARNING The number of auth objects retrieved may be less than the
|
||||
* number of auth ids supplied if auth objects couldn't be found for
|
||||
* some of them.
|
||||
*
|
||||
* \NOTE Since the ref count on all auith objects returned has been
|
||||
* bumped, you must call ast_sip_cleanup_auth_objects_vector() to decrement
|
||||
* the ref count on all of the auth objects in the vector,
|
||||
* then call AST_VECTOR_FREE() on the vector itself.
|
||||
*
|
||||
*/
|
||||
AST_VECTOR(ast_sip_auth_objects_vector, struct ast_sip_auth *);
|
||||
int ast_sip_retrieve_auths_vector(const struct ast_sip_auth_vector *auth_ids,
|
||||
struct ast_sip_auth_objects_vector *auth_objects);
|
||||
|
||||
/*!
|
||||
* \brief Clean up retrieved auth objects in vector
|
||||
*
|
||||
* Call this function once you have completed operating on auths
|
||||
* retrieved from \ref ast_sip_retrieve_auths_vector. All
|
||||
* auth objects will have their reference counts decremented and
|
||||
* the vector size will be reset to 0. You must still call
|
||||
* AST_VECTOR_FREE() on the vector itself.
|
||||
*
|
||||
* \param auth_objects A vector of auth structures to clean up
|
||||
*/
|
||||
#define ast_sip_cleanup_auth_objects_vector(auth_objects) AST_VECTOR_RESET(auth_objects, ao2_cleanup)
|
||||
|
||||
/*!
|
||||
* \brief Checks if the given content type matches type/subtype.
|
||||
*
|
||||
|
Reference in New Issue
Block a user