[svn-commits] mnicholson: trunk r211947 - in /trunk: channels/ configs/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Wed Aug 12 17:18:15 CDT 2009


Author: mnicholson
Date: Wed Aug 12 17:18:09 2009
New Revision: 211947

URL: http://svn.asterisk.org/svn-view/asterisk?view=rev&rev=211947
Log:
This patch adds support for choosing a realm based on the domain in the From or To header in the incoming request.  Eligible domains are taken from the domains list in the config file.  This functionality is enabled when domainsasrealm is enabled in the config file.

(closes issue #11361)
Reported by: arkadia
Patches:
      sip_realm_mnich_to_added_2.patch uploaded by arkadia (license 233)
Tested by: arkadia

Modified:
    trunk/channels/chan_sip.c
    trunk/configs/sip.conf.sample

Modified: trunk/channels/chan_sip.c
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/channels/chan_sip.c?view=diff&rev=211947&r1=211946&r2=211947
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Wed Aug 12 17:18:09 2009
@@ -1118,6 +1118,7 @@
 #define DEFAULT_COS_TEXT        5		/*!< Level 2 class of service for text media (T.140) */
 #define DEFAULT_ALLOW_EXT_DOM	TRUE		/*!< Allow external domains */
 #define DEFAULT_REALM		"asterisk"	/*!< Realm for HTTP digest authentication */
+#define DEFAULT_DOMAINSASREALM	FALSE		/*!< Use the domain option to guess the realm for registration and invite requests */
 #define DEFAULT_NOTIFYRINGING	TRUE		/*!< Notify devicestate system on ringing state */
 #define DEFAULT_NOTIFYCID		DISABLED	/*!< Include CID with ringing notifications */
 #define DEFAULT_PEDANTIC	FALSE		/*!< Avoid following SIP standards for dialog matching */
@@ -1195,6 +1196,7 @@
 	int allowsubscribe;	        /*!< Flag for disabling ALL subscriptions, this is FALSE only if all peers are FALSE 
 					    the global setting is in globals_flags[1] */
 	char realm[MAXHOSTNAMELEN]; 		/*!< Default realm */
+	int domainsasrealm;			/*!< Use domains lists as realms */
 	struct sip_proxy outboundproxy;	/*!< Outbound proxy */
 	char default_context[AST_MAX_CONTEXT];
 	char default_subscribecontext[AST_MAX_CONTEXT];
@@ -2637,6 +2639,8 @@
 static void update_connectedline(struct sip_pvt *p, const void *data, size_t datalen);
 static void update_redirecting(struct sip_pvt *p, const void *data, size_t datalen);
 static void change_redirecting_information(struct sip_pvt *p, struct sip_request *req, struct ast_party_redirecting *redirecting, int set_call_forward);
+static int get_domain(const char *str, char *domain, int len); 
+static void get_realm(struct sip_pvt *p, const struct sip_request *req);
 
 /*-- TCP connection handling ---*/
 static void *_sip_tcp_helper_thread(struct sip_pvt *pvt, struct ast_tcptls_session_instance *tcptls_session);
@@ -9479,14 +9483,91 @@
 		ast_log(LOG_WARNING, "Unable to determine sequence number from '%s'\n", get_header(req, "CSeq"));
 		return -1;
 	}
+	/* Choose Realm */
+	get_realm(p, req);
+
 	/* Stale means that they sent us correct authentication, but 
 	   based it on an old challenge (nonce) */
-	snprintf(tmp, sizeof(tmp), "Digest algorithm=MD5, realm=\"%s\", nonce=\"%s\"%s", sip_cfg.realm, randdata, stale ? ", stale=true" : "");
+	snprintf(tmp, sizeof(tmp), "Digest algorithm=MD5, realm=\"%s\", nonce=\"%s\"%s", p->realm, randdata, stale ? ", stale=true" : "");
 	respprep(&resp, p, msg, req);
 	add_header(&resp, header, tmp);
 	add_header_contentLength(&resp, 0);
 	append_history(p, "AuthChal", "Auth challenge sent for %s - nc %d", p->username, p->noncecount);
 	return send_response(p, &resp, reliable, seqno);
+}
+
+/*! 
+ \brief Extract domain from SIP To/From header
+ \return -1 on error, 1 if domain string is empty, 0 if domain was properly extracted
+ \note TODO: Such code is all over SIP channel, there is a sense to organize 
+      this patern in one function
+*/
+static int get_domain(const char *str, char *domain, int len)
+{
+	char tmpf[256];
+	char *a, *from;
+
+	*domain = '\0';
+	ast_copy_string(tmpf, str, sizeof(tmpf));
+	from = get_in_brackets(tmpf);
+	if (!ast_strlen_zero(from)) {
+		if (strncasecmp(from, "sip:", 4)) {
+			ast_log(LOG_WARNING, "Huh?  Not a SIP header (%s)?\n", from);
+			return -1;
+		}
+		from += 4;
+	} else
+		from = NULL;
+
+	if (from) {
+		/* Strip any params or options from user */
+		if ((a = strchr(from, ';')))
+			*a = '\0';
+		/* Strip port from domain if present */
+		if ((a = strchr(from, ':')))
+			*a = '\0';
+		if ((a = strchr(from, '@'))) {
+			*a = '\0';
+			ast_copy_string(domain, a + 1, len);
+		} else
+			ast_copy_string(domain, from, len);
+	}
+
+	return ast_strlen_zero(domain);
+}
+
+/*! 
+  \brief Choose realm based on From header and then To header or use globaly configured realm. 
+  Realm from From/To header should be listed among served domains in config file: domain=... 
+*/
+static void get_realm(struct sip_pvt *p, const struct sip_request *req)
+{
+	char domain[MAXHOSTNAMELEN];
+
+	if (!ast_strlen_zero(p->realm))
+		return;
+
+	if (sip_cfg.domainsasrealm &&
+	    !AST_LIST_EMPTY(&domain_list))
+	{
+		/* Check From header first */
+		if (!get_domain(get_header(req, "From"), domain, sizeof(domain))) {
+			if (check_sip_domain(domain, NULL, 0)) {
+				ast_string_field_set(p, realm, domain);
+				return;
+			}
+		}
+		/* Check To header */
+		if (!get_domain(get_header(req, "To"), domain, sizeof(domain))) {
+			if (check_sip_domain(domain, NULL, 0)) {
+				ast_string_field_set(p, realm, domain);
+				return;
+			}
+		}
+	}
+	
+	/* Use default realm from config file */
+	ast_string_field_set(p, realm, sip_cfg.realm);
 }
 
 /*! \brief Add text body to SIP message */
@@ -12561,7 +12642,7 @@
 		ast_copy_string(a1_hash, md5secret, sizeof(a1_hash));
 	else {
 		char a1[256];
-		snprintf(a1, sizeof(a1), "%s:%s:%s", username, sip_cfg.realm, secret);
+		snprintf(a1, sizeof(a1), "%s:%s:%s", username, p->realm, secret);
 		ast_md5_hash(a1_hash, a1);
 	}
 
@@ -15915,6 +15996,7 @@
 	ast_cli(a->fd, "  SIP domain support:     %s\n", cli_yesno(!AST_LIST_EMPTY(&domain_list)));
 	ast_cli(a->fd, "  Realm. auth:            %s\n", cli_yesno(authl != NULL));
 	ast_cli(a->fd, "  Our auth realm          %s\n", sip_cfg.realm);
+	ast_cli(a->fd, "  Use domains as realms:  %s\n", cli_yesno(sip_cfg.domainsasrealm));
 	ast_cli(a->fd, "  Call to non-local dom.: %s\n", cli_yesno(sip_cfg.allow_external_domains));
 	ast_cli(a->fd, "  URI user is phone no:   %s\n", cli_yesno(ast_test_flag(&global_flags[0], SIP_USEREQPHONE)));
  	ast_cli(a->fd, "  Always auth rejects:    %s\n", cli_yesno(sip_cfg.alwaysauthreject));
@@ -24559,6 +24641,7 @@
 	snprintf(global_sdpowner, sizeof(global_sdpowner), "%s", DEFAULT_SDPOWNER);
 	ast_copy_string(default_notifymime, DEFAULT_NOTIFYMIME, sizeof(default_notifymime));
 	ast_copy_string(sip_cfg.realm, S_OR(ast_config_AST_SYSTEM_NAME, DEFAULT_REALM), sizeof(sip_cfg.realm));
+	sip_cfg.domainsasrealm = DEFAULT_DOMAINSASREALM;
 	ast_copy_string(default_callerid, DEFAULT_CALLERID, sizeof(default_callerid));
 	ast_copy_string(default_mwi_from, DEFAULT_MWI_FROM, sizeof(default_mwi_from));
 	sip_cfg.compactheaders = DEFAULT_COMPACTHEADERS;
@@ -24651,6 +24734,8 @@
 			sip_cfg.allowguest = ast_true(v->value) ? 1 : 0;
 		} else if (!strcasecmp(v->name, "realm")) {
 			ast_copy_string(sip_cfg.realm, v->value, sizeof(sip_cfg.realm));
+  		} else if (!strcasecmp(v->name, "domainsasrealm")) {
+			sip_cfg.domainsasrealm = ast_true(v->value);
 		} else if (!strcasecmp(v->name, "useragent")) {
 			ast_copy_string(global_useragent, v->value, sizeof(global_useragent));
 			ast_debug(1, "Setting SIP channel User-Agent Name to %s\n", global_useragent);

Modified: trunk/configs/sip.conf.sample
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/configs/sip.conf.sample?view=diff&rev=211947&r1=211946&r2=211947
==============================================================================
--- trunk/configs/sip.conf.sample (original)
+++ trunk/configs/sip.conf.sample Wed Aug 12 17:18:09 2009
@@ -98,6 +98,12 @@
                                 ; asterisk.conf, it defaults to that system name
                                 ; Realms MUST be globally unique according to RFC 3261
                                 ; Set this to your host name or domain name
+;domainsasrealm=no              ; Use domans list as realms
+                                ; You can serve multiple Realms specifying several
+                                ; 'domain=...' directives (see below). 
+                                ; In this case Realm will be based on request 'From'/'To' header
+                                ; and should match one of domain names.
+                                ; Otherwise default 'realm=...' will be used.
 udpbindaddr=0.0.0.0             ; IP address to bind UDP listen socket to (0.0.0.0 binds to all)
                                 ; Optionally add a port number, 192.168.1.1:5062 (default is port 5060)
 




More information about the svn-commits mailing list