[svn-commits] mmichelson: branch group/pimp_my_sip r381346 - in /team/group/pimp_my_sip: in...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Wed Feb 13 09:50:16 CST 2013


Author: mmichelson
Date: Wed Feb 13 09:50:12 2013
New Revision: 381346

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=381346
Log:
Add authentication support for SIP.

This changes the original authentication and authenticator APIs
to be more flexible and not try to force digest authentication onto
authenticators.

This also introduces res_sip_authenticator_digest.c, an MD5 digest
authenticator. Authentication information is retrieved from sorcery.
Asterisk sends digest challenges to endpoints that have authentication
configured. Asterisk can then verify credentials on subsequent requests.
Asterisk can also detect stale nonces in authentication requests and
rechallenge if necessary.

(closes issue ASTERISK-20953)
Reported by Matt Jordan


Added:
    team/group/pimp_my_sip/res/res_sip/config_auth.c
      - copied unchanged from r381345, team/mmichelson/authenticate/res/res_sip/config_auth.c
    team/group/pimp_my_sip/res/res_sip_authenticator_digest.c
      - copied unchanged from r381345, team/mmichelson/authenticate/res/res_sip_authenticator_digest.c
Modified:
    team/group/pimp_my_sip/include/asterisk/res_sip.h
    team/group/pimp_my_sip/include/asterisk/sorcery.h
    team/group/pimp_my_sip/main/astobj2.c
    team/group/pimp_my_sip/main/sorcery.c
    team/group/pimp_my_sip/res/res_sip.c
    team/group/pimp_my_sip/res/res_sip/config_transport.c
    team/group/pimp_my_sip/res/res_sip/sip_configuration.c
    team/group/pimp_my_sip/res/res_sip_session.c
    team/group/pimp_my_sip/tests/test_sorcery.c

Modified: team/group/pimp_my_sip/include/asterisk/res_sip.h
URL: http://svnview.digium.com/svn/asterisk/team/group/pimp_my_sip/include/asterisk/res_sip.h?view=diff&rev=381346&r1=381345&r2=381346
==============================================================================
--- team/group/pimp_my_sip/include/asterisk/res_sip.h (original)
+++ team/group/pimp_my_sip/include/asterisk/res_sip.h Wed Feb 13 09:50:12 2013
@@ -174,6 +174,41 @@
 };
 
 /*!
+ * \brief Methods of storing SIP digest authentication credentials.
+ *
+ * Note that both methods result in MD5 digest authentication being
+ * used. The two methods simply alter how Asterisk determines the
+ * credentials for a SIP authentication
+ */
+enum ast_sip_auth_type {
+	/*! Credentials stored as a username and password combination */
+	AST_SIP_AUTH_TYPE_USER_PASS,
+	/*! Credentials stored as an MD5 sum */
+	AST_SIP_AUTH_TYPE_MD5,
+};
+
+#define SIP_SORCERY_AUTH_TYPE "auth"
+
+struct ast_sip_auth {
+	/* Sorcery ID of the auth is its name */
+	SORCERY_OBJECT(details);
+	AST_DECLARE_STRING_FIELDS(
+		/* Identification for these credentials */
+		AST_STRING_FIELD(realm);
+		/* Authentication username */
+		AST_STRING_FIELD(auth_user);
+		/* Authentication password */
+		AST_STRING_FIELD(auth_pass);
+		/* Authentication credentials in MD5 format (hash of user:realm:pass) */
+		AST_STRING_FIELD(md5_creds);
+	);
+	/* The time period (in seconds) that a nonce may be reused */
+	unsigned int nonce_lifetime;
+	/* Used to determine what to use when authenticating */
+	enum ast_sip_auth_type type;
+};
+
+/*!
  * \brief An entity with which Asterisk communicates
  */
 struct ast_sip_endpoint {
@@ -181,8 +216,8 @@
 	AST_DECLARE_STRING_FIELDS(
 		/*! Context to send incoming calls to */
 		AST_STRING_FIELD(context);
-                /*! Name of an explicit transport to use */
-                AST_STRING_FIELD(transport);
+		/*! Name of an explicit transport to use */
+		AST_STRING_FIELD(transport);
 	);
 	/*! Identification information for this endpoint */
 	struct ast_party_id id;
@@ -194,6 +229,10 @@
 	struct ast_codec_pref prefs;
 	/*! Configured codecs */
 	struct ast_format_cap *codecs;
+	/*! Names of authentication credentials */
+	const char **sip_auths;
+	/*! Number of configured auths */
+	size_t num_auths;
 	/*! DTMF mode to use with this endpoint */
 	enum ast_sip_dtmf_mode dtmf;
 	/*! Enabled SIP extensions */
@@ -234,60 +273,19 @@
 struct ast_sip_endpoint *ast_sip_get_endpoint_from_location(const char *addr);
  
 /*!
- * \brief Data used for creating authentication challenges.
- * 
- * This data gets populated by an authenticator's get_authentication_credentials() callback.
- */
-struct ast_sip_digest_challenge_data {
-    /*!
-     * The realm to which the user is authenticating. An authenticator MUST fill this in.
-     */
-    const char *realm;
-    /*!
-     * Indicates whether the username and password are in plaintext or encoded as MD5.
-     * If this is non-zero, then the data is an MD5 sum. Otherwise, the username and password are plaintext.
-     * Authenticators MUST set this.
-     */
-    int is_md5;
-    /*!
-     * This is the actual username and secret. The is_md5 field is used to determine which member
-     * of the union is to be used when creating the authentication challenge. In other words, if
-     * is_md5 is non-zero, then we will use the md5 field of the auth union. Otherwise, we will
-     * use the plain struct in the auth union.
-     * Authenticators MUST fill in the appropriate field of the union.
-     */
-    union {
-        /*!
-         * Structure containing the username and password to encode in a digest authentication challenge.
-         */
-        struct {
-            const char *username;
-            const char *password;
-        } plain;
-        /*!
-         * An MD5-encoded string that incorporates the username and password.
-         */
-        const char *md5;
-    } auth;
-    /*!
-     * Domain for which the authentication challenge is being sent. This corresponds to the "domain=" portion of
-     * a digest authentication.
-     *
-     * Authenticators do not have to fill in this field since it is an optional part of a digest.
-     */
-    const char *domain;
-    /*!
-     * Opaque string for digest challenge. This corresponds to the "opaque=" portion of a digest authentication.
-     * Authenticators do not have to fill in this field. If an authenticator does not fill it in, Asterisk will provide one.
-     */
-    const char *opaque;
-    /*!
-     * Nonce string for digest challenge. This corresponds to the "nonce=" portion of a digest authentication.
-     * Authenticators do not have to fill in this field. If an authenticator does not fill it in, Asterisk will provide one.
-     */
-    const char *nonce;
-};
- 
+ * \brief Possible returns from ast_sip_check_authentication
+ */
+enum ast_sip_check_auth_result {
+    /*! Authentication needs to be challenged */
+    AST_SIP_AUTHENTICATION_CHALLENGE,
+    /*! Authentication succeeded */
+    AST_SIP_AUTHENTICATION_SUCCESS,
+    /*! Authentication failed */
+    AST_SIP_AUTHENTICATION_FAILED,
+    /*! Authentication encountered some internal error */
+    AST_SIP_AUTHENTICATION_ERROR,
+};
+
 /*!
  * \brief An interchangeable way of handling digest authentication for SIP.
  * 
@@ -301,16 +299,17 @@
      * See ast_sip_requires_authentication for more details
      */
     int (*requires_authentication)(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata);
-    /*!
-     * \brief Attempt to authenticate the incoming request
-     * See ast_sip_authenticate_request for more details
-     */
-    int (*authenticate_request)(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata);
-    /*!
-     * \brief Get digest authentication details
-     * See ast_sip_get_authentication_credentials for more details
-    */
-    int (*get_authentication_credentials)(struct ast_sip_endpoint *endpoint, struct ast_sip_digest_challenge_data *challenge);
+	/*!
+	 * \brief Check that an incoming request passes authentication.
+	 *
+	 * The tdata parameter is useful for adding information such as digest challenges.
+	 *
+	 * \param endpoint The endpoint sending the incoming request
+	 * \param rdata The incoming request
+	 * \param tdata Tentative outgoing request.
+	 */
+	enum ast_sip_check_auth_result (*check_authentication)(struct ast_sip_endpoint *endpoint,
+			pjsip_rx_data *rdata, pjsip_tx_data *tdata);
 };
  
 /*!
@@ -446,6 +445,16 @@
  * \retval 0 success
  */
 int ast_sip_initialize_sorcery_transport(struct ast_sorcery *sorcery);
+
+/*!
+ * \brief Initialize authentication support on a sorcery instance
+ *
+ * \param sorcery The sorcery instance
+ *
+ * \retval -1 failure
+ * \retval 0 success
+ */
+int ast_sip_initialize_sorcery_auth(struct ast_sorcery *sorcery);
 
 /*!
  * \brief Create a new SIP work structure
@@ -536,71 +545,20 @@
 int ast_sip_requires_authentication(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata);
  
 /*!
- * \brief Authenticate an inbound SIP request
- *
- * This calls into the registered authenticator's authenticate_request callback
- * in order to determine if the request contains proper credentials as to be
- * authenticated.
- *
- * If there is no registered authenticator, then the request will assumed to be
- * authenticated properly.
- *
- * \param endpoint The endpoint from which the request originates
- * \param rdata The incoming SIP request
- * \retval 0 Successfully authenticated
- * \retval nonzero Failure to authenticate
- */
-int ast_sip_authenticate_request(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata);
- 
-/*!
- * \brief Get authentication credentials in order to challenge a request
- *
- * This calls into the registered authenticator's get_authentication_credentials
- * callback in order to get credentials required for challenging a request.
- *
- * \param endpoint The endpoint whose credentials are being gathered
- * \param[out] challenge The necessary data in order to be able to challenge a request
- * \retval 0 Success
- * \retval -1 Failure
- */
-int ast_sip_get_authentication_credentials(struct ast_sip_endpoint *endpoint, struct ast_sip_digest_challenge_data *challenge);
- 
-/*!
- * \brief Possible returns from ast_sip_check_authentication
- */
-enum ast_sip_check_auth_result {
-    /*! Authentication challenge sent */
-    AST_SIP_AUTHENTICATION_CHALLENGE_SENT,
-    /*! Authentication succeeded */
-    AST_SIP_AUTHENTICATION_SUCCESS,
-    /*! Authentication failed */
-    AST_SIP_AUTHENTICATION_FAILED,
-    /*! Authentication not required */
-    AST_SIP_AUTHENTICATION_NOT_REQUIRED,
-};
- 
-/*!
- * \brief Shortcut routine to check for authentication of an incoming request
- *
- * This is a wrapper that will call into a registered authenticator to see if a request
- * should be authenticated. Then if it should be, will attempt to authenticate. If the
- * request cannot be authenticated, then a challenge will be sent. Calling this can be
- * a suitable substitute for calling ast_sip_requires_authentication(),
- * ast_sip_authenticate_request(), and ast_sip_get_authentication_credentials()
+ * \brief Method to determine authentication status of an incoming request
+ *
+ * This will call into a registered authenticator. The registered authenticator will
+ * do what is necessary to determine whether the incoming request passes authentication.
+ * A tentative response is passed into this function so that if, say, a digest authentication
+ * challenge should be sent in the ensuing response, it can be added to the response.
  *
  * \param endpoint The endpoint from the request was sent
  * \param rdata The request to potentially authenticate
+ * \param tdata Tentative response to the request
  * \return The result of checking authentication.
  */
-enum ast_sip_check_auth_result ast_sip_check_authentication(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata);
- 
-/*!
- * \brief Add digest information to an authentication challenge
- *
- * \param challenge Details to help in constructing a WWW-Authenticate header
- * \param tdata The challenge to add the digest to
- */
-void ast_sip_add_digest_to_challenge(struct ast_sip_digest_challenge_data *challenge, pjsip_tx_data *tdata);
+enum ast_sip_check_auth_result ast_sip_check_authentication(struct ast_sip_endpoint *endpoint,
+		pjsip_rx_data *rdata, pjsip_tx_data *tdata);
  
 /*!
  * \brief Determine the endpoint that has sent a SIP message

Modified: team/group/pimp_my_sip/include/asterisk/sorcery.h
URL: http://svnview.digium.com/svn/asterisk/team/group/pimp_my_sip/include/asterisk/sorcery.h?view=diff&rev=381346&r1=381345&r2=381346
==============================================================================
--- team/group/pimp_my_sip/include/asterisk/sorcery.h (original)
+++ team/group/pimp_my_sip/include/asterisk/sorcery.h Wed Feb 13 09:50:12 2013
@@ -146,10 +146,15 @@
 /*!
  * \brief A callback function for when an object set is successfully applied to an object
  *
+ * \note On a failure return, the state of the object is left undefined. It is a bad
+ * idea to try to use this object.
+ *
  * \param sorcery Sorcery structure in use
  * \param obj The object itself
- */
-typedef void (*sorcery_apply_handler)(const struct ast_sorcery *sorcery, void *obj);
+ * \retval 0 Success
+ * \retval non-zero Failure
+ */
+typedef int (*sorcery_apply_handler)(const struct ast_sorcery *sorcery, void *obj);
 
 /*!
  * \brief A callback function for copying the contents of one object to another

Modified: team/group/pimp_my_sip/main/astobj2.c
URL: http://svnview.digium.com/svn/asterisk/team/group/pimp_my_sip/main/astobj2.c?view=diff&rev=381346&r1=381345&r2=381346
==============================================================================
--- team/group/pimp_my_sip/main/astobj2.c (original)
+++ team/group/pimp_my_sip/main/astobj2.c Wed Feb 13 09:50:12 2013
@@ -525,6 +525,7 @@
 	struct astobj2 *obj = INTERNAL_OBJ(user_data);
 
 	if (obj == NULL) {
+		ast_backtrace();
 		ast_assert(0);
 		return -1;
 	}

Modified: team/group/pimp_my_sip/main/sorcery.c
URL: http://svnview.digium.com/svn/asterisk/team/group/pimp_my_sip/main/sorcery.c?view=diff&rev=381346&r1=381345&r2=381346
==============================================================================
--- team/group/pimp_my_sip/main/sorcery.c (original)
+++ team/group/pimp_my_sip/main/sorcery.c Wed Feb 13 09:50:12 2013
@@ -717,7 +717,7 @@
 	}
 
 	if (!res && object_type->apply) {
-		object_type->apply(sorcery, object);
+		res = object_type->apply(sorcery, object);
 	}
 
 	return res;

Modified: team/group/pimp_my_sip/res/res_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/group/pimp_my_sip/res/res_sip.c?view=diff&rev=381346&r1=381345&r2=381346
==============================================================================
--- team/group/pimp_my_sip/res/res_sip.c (original)
+++ team/group/pimp_my_sip/res/res_sip.c Wed Feb 13 09:50:12 2013
@@ -71,16 +71,15 @@
 	ast_debug(1, "Unregistered SIP service %.*s\n", (int) pj_strlen(&module->name), pj_strbuf(&module->name));
 }
 
-AO2_GLOBAL_OBJ_STATIC(registered_authenticator);
+static struct ast_sip_authenticator *registered_authenticator;
 
 int ast_sip_register_authenticator(struct ast_sip_authenticator *auth)
 {
-	RAII_VAR(struct ast_sip_authenticator *, reg, ao2_global_obj_ref(registered_authenticator), ao2_cleanup);
-	if (reg) {
-		ast_log(LOG_WARNING, "Authenticator %p is already registered. Cannot register a new one\n", reg);
-		return -1;
-	}
-	ao2_global_obj_replace_unref(registered_authenticator, auth);
+	if (registered_authenticator) {
+		ast_log(LOG_WARNING, "Authenticator %p is already registered. Cannot register a new one\n", registered_authenticator);
+		return -1;
+	}
+	registered_authenticator = auth;
 	ast_debug(1, "Registered SIP authenticator module %p\n", auth);
 	ast_module_ref(ast_module_info->self);
 	return 0;
@@ -88,80 +87,34 @@
 
 void ast_sip_unregister_authenticator(struct ast_sip_authenticator *auth)
 {
-	RAII_VAR(struct ast_sip_authenticator *, reg, ao2_global_obj_ref(registered_authenticator), ao2_cleanup);
-	if (auth != reg) {
+	if (registered_authenticator != auth) {
 		ast_log(LOG_WARNING, "Trying to unregister authenticator %p but authenticator %p registered\n",
-				auth, reg);
+				auth, registered_authenticator);
 		return;
 	}
-	ao2_global_obj_release(registered_authenticator);
+	registered_authenticator = NULL;
 	ast_debug(1, "Unregistered SIP authenticator %p\n", auth);
 	ast_module_unref(ast_module_info->self);
 }
 
 int ast_sip_requires_authentication(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
 {
-	RAII_VAR(struct ast_sip_authenticator *, reg, ao2_global_obj_ref(registered_authenticator), ao2_cleanup);
-	if (!reg) {
+	if (!registered_authenticator) {
 		ast_log(LOG_WARNING, "No SIP authenticator registered. Assuming authentication is not required\n");
 		return 0;
 	}
 
-	return reg->requires_authentication(endpoint, rdata);
-}
-
-int ast_sip_authenticate_request(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
-{
-	RAII_VAR(struct ast_sip_authenticator *, reg, ao2_global_obj_ref(registered_authenticator), ao2_cleanup);
-	if (!reg) {
-		ast_log(LOG_WARNING, "No SIP authenticator registered. Assuming request authenticated properly\n");
+	return registered_authenticator->requires_authentication(endpoint, rdata);
+}
+
+enum ast_sip_check_auth_result ast_sip_check_authentication(struct ast_sip_endpoint *endpoint,
+		pjsip_rx_data *rdata, pjsip_tx_data *tdata)
+{
+	if (!registered_authenticator) {
+		ast_log(LOG_WARNING, "No SIP authenticator registered. Assuming authentication is successful\n");
 		return 0;
 	}
-
-	return reg->authenticate_request(endpoint, rdata);
-}
-
-int ast_sip_get_authentication_credentials(struct ast_sip_endpoint *endpoint,
-		struct ast_sip_digest_challenge_data *challenge)
-{
-	RAII_VAR(struct ast_sip_authenticator *, reg, ao2_global_obj_ref(registered_authenticator), ao2_cleanup);
-	if (!reg) {
-		ast_log(LOG_WARNING, "No SIP authenticator registered. Assuming no authentication credentials\n");
-		return -1;
-	}
-
-	return reg->get_authentication_credentials(endpoint, challenge);
-}
-
-void ast_sip_add_digest_to_challenge(struct ast_sip_digest_challenge_data *challenge, pjsip_tx_data *tdata)
-{
-	pjsip_auth_srv auth_server;
-	pj_str_t realm;
-	pj_str_t nonce;
-	pj_str_t *nonce_ptr = NULL;
-	pj_str_t qop;
-	pj_str_t opaque;
-	pj_str_t *opaque_ptr = NULL;
-
-	pj_cstr(&realm, challenge->realm);
-	pj_cstr(&qop, "auth");
-	if (!ast_strlen_zero(challenge->opaque)) {
-		pj_cstr(&opaque, challenge->opaque);
-		opaque_ptr = &opaque;
-	}
-	if (!ast_strlen_zero(challenge->nonce)) {
-		pj_cstr(&nonce, challenge->nonce);
-		nonce_ptr = &nonce;
-	}
-
-	pjsip_auth_srv_init(tdata->pool, &auth_server, &realm, NULL, 0);
-	pjsip_auth_srv_challenge(&auth_server, &qop, nonce_ptr, opaque_ptr, PJ_FALSE, tdata);
-}
-
-enum ast_sip_check_auth_result ast_sip_check_authentication(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
-{
-	/* XXX Stub */
-	return AST_SIP_AUTHENTICATION_SUCCESS;
+	return registered_authenticator->check_authentication(endpoint, rdata, tdata);
 }
 
 struct endpoint_identifier_list {

Modified: team/group/pimp_my_sip/res/res_sip/config_transport.c
URL: http://svnview.digium.com/svn/asterisk/team/group/pimp_my_sip/res/res_sip/config_transport.c?view=diff&rev=381346&r1=381345&r2=381346
==============================================================================
--- team/group/pimp_my_sip/res/res_sip/config_transport.c (original)
+++ team/group/pimp_my_sip/res/res_sip/config_transport.c Wed Feb 13 09:50:12 2013
@@ -68,7 +68,7 @@
 }
 
 /*! \brief Apply handler for transports */
-static void transport_apply(const struct ast_sorcery *sorcery, void *obj)
+static int transport_apply(const struct ast_sorcery *sorcery, void *obj)
 {
 	struct ast_sip_transport *transport = obj;
 	RAII_VAR(struct ast_sip_transport *, existing, ast_sorcery_retrieve_by_id(sorcery, "transport", ast_sorcery_object_get_id(obj)), ao2_cleanup);
@@ -77,7 +77,7 @@
 	if (!existing || !existing->state) {
 		if (!(transport->state = ao2_alloc(sizeof(*transport->state), transport_state_destroy))) {
 			ast_log(LOG_ERROR, "Transport state for '%s' could not be allocated\n", ast_sorcery_object_get_id(obj));
-			return;
+			return -1;
 		}
 	} else {
 		transport->state = existing->state;
@@ -86,7 +86,7 @@
 
 	/* Once active a transport can not be reconfigured */
 	if (transport->state->transport || transport->state->factory) {
-		return;
+		return -1;
 	}
 
 	/* Set default port if not present */
@@ -121,7 +121,9 @@
 
 		pjsip_strerror(res, msg, sizeof(msg));
 		ast_log(LOG_ERROR, "Transport '%s' could not be started: %s\n", ast_sorcery_object_get_id(obj), msg);
-	}
+		return -1;
+	}
+	return 0;
 }
 
 /*! \brief Custom handler for turning a string protocol into an enum */

Modified: team/group/pimp_my_sip/res/res_sip/sip_configuration.c
URL: http://svnview.digium.com/svn/asterisk/team/group/pimp_my_sip/res/res_sip/sip_configuration.c?view=diff&rev=381346&r1=381345&r2=381346
==============================================================================
--- team/group/pimp_my_sip/res/res_sip/sip_configuration.c (original)
+++ team/group/pimp_my_sip/res/res_sip/sip_configuration.c Wed Feb 13 09:50:12 2013
@@ -193,6 +193,47 @@
 	return 0;
 }
 
+static void destroy_endpoint_auths(const struct ast_sip_endpoint *endpoint)
+{
+	int i;
+	for (i = 0; i < endpoint->num_auths; ++i) {
+		ast_free((char *) endpoint->sip_auths[i]);
+	}
+	ast_free(endpoint->sip_auths);
+}
+
+#define AUTH_INCREMENT 4
+
+static int auth_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
+{
+	char *auths = ast_strdupa(var->value);
+	char *val;
+	struct ast_sip_endpoint *endpoint = obj;
+	int num_alloced = 0;
+
+	while ((val = strsep(&auths, ","))) {
+		if (endpoint->num_auths >= num_alloced) {
+			size_t size;
+			num_alloced += AUTH_INCREMENT;
+			size = num_alloced * sizeof(char *);
+			endpoint->sip_auths = ast_realloc(endpoint->sip_auths, size);
+			if (!endpoint->sip_auths) {
+				goto failure;
+			}
+		}
+		endpoint->sip_auths[endpoint->num_auths] = ast_strdup(val);
+		if (!endpoint->sip_auths[endpoint->num_auths]) {
+			goto failure;
+		}
+		++endpoint->num_auths;
+	}
+	return 0;
+
+failure:
+	destroy_endpoint_auths(endpoint);
+	return -1;
+}
+
 int ast_res_sip_initialize_configuration(void)
 {
 	if (ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands))) {
@@ -205,6 +246,14 @@
 	}
 
 	ast_sorcery_apply_config(sip_sorcery, "res_sip");
+
+	if (ast_sip_initialize_sorcery_auth(sip_sorcery)) {
+		ast_log(LOG_ERROR, "Failed to register SIP authentication support\n");
+		ast_sorcery_unref(sip_sorcery);
+		sip_sorcery = NULL;
+		return -1;
+	}
+
 	ast_sorcery_apply_default(sip_sorcery, "endpoint", "config", "res_sip.conf,criteria=type=endpoint");
 
 	ast_sorcery_apply_default(sip_sorcery, "location_to_endpoint", "memory", NULL);
@@ -232,6 +281,7 @@
 	ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "timers", "yes", timers_handler, NULL, 0, 0);
 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "timers_min_se", "90", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, min_se));
 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "timers_sess_expires", "1800", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, sess_expires));
+	ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "auth", "", auth_handler, NULL, 0, 0);
 
 	if (ast_sip_initialize_sorcery_transport(sip_sorcery)) {
 		ast_log(LOG_ERROR, "Failed to register SIP transport support with sorcery\n");
@@ -268,10 +318,7 @@
 	if (endpoint->codecs) {
 		ast_format_cap_destroy(endpoint->codecs);
 	}
-
-	/* XXX Will likely need to destroy a bunch
-	 * more other endpoint data too.
-	 */
+	destroy_endpoint_auths(endpoint);
 }
 
 void *ast_sip_endpoint_alloc(const char *name)

Modified: team/group/pimp_my_sip/res/res_sip_session.c
URL: http://svnview.digium.com/svn/asterisk/team/group/pimp_my_sip/res/res_sip_session.c?view=diff&rev=381346&r1=381345&r2=381346
==============================================================================
--- team/group/pimp_my_sip/res/res_sip_session.c (original)
+++ team/group/pimp_my_sip/res/res_sip_session.c Wed Feb 13 09:50:12 2013
@@ -734,23 +734,21 @@
 	 */
 
 	if (ast_sip_requires_authentication(endpoint, rdata)) {
-		if (ast_sip_authenticate_request(endpoint, rdata)) {
-			struct ast_sip_digest_challenge_data challenge_data;
-			if (pjsip_inv_initial_answer(inv_session, rdata, 401, NULL, NULL, &tdata) != PJ_SUCCESS) {
-				pjsip_inv_terminate(inv_session, 500, PJ_TRUE);
-				return;
-			}
-			memset(&challenge_data, 0, sizeof(challenge_data));
-			if (ast_sip_get_authentication_credentials(endpoint, &challenge_data)) {
-				if (pjsip_inv_answer(inv_session, 500, NULL, NULL, &tdata) != PJ_SUCCESS) {
-					ast_sip_session_send_response(session, tdata);
-				} else {
-					pjsip_inv_terminate(inv_session, 500, PJ_TRUE);
-				}
-				return;
-			}
-			ast_sip_add_digest_to_challenge(&challenge_data, tdata);
-			ast_sip_session_send_response(session, tdata);
+		pjsip_inv_initial_answer(inv_session, rdata, 401, NULL, NULL, &tdata);
+		switch (ast_sip_check_authentication(endpoint, rdata, tdata)) {
+		case AST_SIP_AUTHENTICATION_CHALLENGE:
+			/* Send the 401 we created for them */
+			pjsip_inv_send_msg(inv_session, tdata);
+			return;
+		case AST_SIP_AUTHENTICATION_SUCCESS:
+			break;
+		case AST_SIP_AUTHENTICATION_FAILED:
+			pjsip_inv_answer(inv_session, 403, NULL, NULL, &tdata);
+			pjsip_inv_send_msg(inv_session, tdata);
+			return;
+		case AST_SIP_AUTHENTICATION_ERROR:
+			pjsip_inv_answer(inv_session, 500, NULL, NULL, &tdata);
+			pjsip_inv_send_msg(inv_session, tdata);
 			return;
 		}
 	}

Modified: team/group/pimp_my_sip/tests/test_sorcery.c
URL: http://svnview.digium.com/svn/asterisk/team/group/pimp_my_sip/tests/test_sorcery.c?view=diff&rev=381346&r1=381345&r2=381346
==============================================================================
--- team/group/pimp_my_sip/tests/test_sorcery.c (original)
+++ team/group/pimp_my_sip/tests/test_sorcery.c Wed Feb 13 09:50:12 2013
@@ -112,9 +112,10 @@
 static int apply_handler_called;
 
 /*! \brief Simple apply handler which sets global scope integer to 1 if called */
-static void test_apply_handler(const struct ast_sorcery *sorcery, void *obj)
+static int test_apply_handler(const struct ast_sorcery *sorcery, void *obj)
 {
 	apply_handler_called = 1;
+	return 0;
 }
 
 /*! \brief Global scope caching structure for testing */




More information about the svn-commits mailing list