aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b>2008-09-12 20:37:18 +0000
committertilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b>2008-09-12 20:37:18 +0000
commit3d74fe145cd118d1e92a9306dc15f32da3b91401 (patch)
tree2f1e7e04964e16dc1ca328f9113917b28345b23a
parentd7fe1556d7d7afb6918941cc7c2f2d66887ecedf (diff)
Create rules for disallowing contacts at certain addresses, which may
improve the security of various installations. As this does not change any default behavior, it is not classified as a direct security fix for anything within Asterisk, but may help PBX admins better secure their SIP servers. (closes issue #11776) Reported by: ibc Patches: 20080829__bug11776.diff.txt uploaded by Corydon76 (license 14) Tested by: Corydon76, blitzrage git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@142865 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--channels/chan_sip.c44
-rw-r--r--configs/sip.conf.sample14
2 files changed, 51 insertions, 7 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 6f205a381..0ff45af6a 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -574,6 +574,10 @@ static int global_matchexterniplocally; /*!< Match externip/externhost setting a
/*! \brief Codecs that we support by default: */
static int global_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263;
+/*! \brief Global list of addresses dynamic peers are not allowed to use */
+static struct ast_ha *global_contact_ha = NULL;
+static int global_dynamic_exclude_static = 0;
+
/* Object counters */
static int suserobjs = 0; /*!< Static users */
static int ruserobjs = 0; /*!< Realtime users */
@@ -1132,6 +1136,7 @@ struct sip_peer {
struct sockaddr_in defaddr; /*!< Default IP address, used until registration */
struct ast_ha *ha; /*!< Access control list */
+ struct ast_ha *contactha; /*!< Restrict what IPs are allowed in the Contact header (for registration) */
struct ast_variable *chanvars; /*!< Variables to set for channel created by user */
struct sip_pvt *mwipvt; /*!< Subscription for MWI */
int lastmsg;
@@ -8174,7 +8179,7 @@ static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, st
const char *useragent;
struct hostent *hp;
struct ast_hostent ahp;
- struct sockaddr_in oldsin;
+ struct sockaddr_in oldsin, testsin;
ast_copy_string(contact, get_header(req, "Contact"), sizeof(contact));
@@ -8255,13 +8260,26 @@ static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, st
} else
port = STANDARD_SIP_PORT;
oldsin = peer->addr;
+
+ /* Check that they're allowed to register at this IP */
+ /* XXX This could block for a long time XXX */
+ hp = ast_gethostbyname(n, &ahp);
+ if (!hp) {
+ ast_log(LOG_WARNING, "Invalid host '%s'\n", n);
+ *peer->fullcontact = '\0';
+ ast_string_field_set(pvt, our_contact, "");
+ return PARSE_REGISTER_FAILED;
+ }
+ memcpy(&testsin.sin_addr, hp->h_addr, sizeof(testsin.sin_addr));
+ if ( ast_apply_ha(global_contact_ha, &testsin) != AST_SENSE_ALLOW ||
+ ast_apply_ha(peer->contactha, &testsin) != AST_SENSE_ALLOW) {
+ ast_log(LOG_WARNING, "Host '%s' disallowed by rule\n", n);
+ *peer->fullcontact = '\0';
+ ast_string_field_set(pvt, our_contact, "");
+ return PARSE_REGISTER_FAILED;
+ }
+
if (!ast_test_flag(&peer->flags[0], SIP_NAT_ROUTE)) {
- /* XXX This could block for a long time XXX */
- hp = ast_gethostbyname(n, &ahp);
- if (!hp) {
- ast_log(LOG_WARNING, "Invalid host '%s'\n", n);
- return PARSE_REGISTER_FAILED;
- }
peer->addr.sin_family = AF_INET;
memcpy(&peer->addr.sin_addr, hp->h_addr, sizeof(peer->addr.sin_addr));
peer->addr.sin_port = htons(port);
@@ -17158,6 +17176,9 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
if (!peer->addr.sin_port)
peer->addr.sin_port = htons(STANDARD_SIP_PORT);
}
+ if (global_dynamic_exclude_static) {
+ global_contact_ha = ast_append_ha("deny", (char *)ast_inet_ntoa(peer->addr.sin_addr), global_contact_ha);
+ }
}
} else if (!strcasecmp(v->name, "defaultip")) {
if (ast_get_ip(&peer->defaddr, v->value)) {
@@ -17166,6 +17187,8 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
}
} else if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny")) {
peer->ha = ast_append_ha(v->name, v->value, peer->ha);
+ } else if (!strcasecmp(v->name, "contactpermit") || !strcasecmp(v->name, "contactdeny")) {
+ peer->contactha = ast_append_ha(v->name + 7, v->value, peer->contactha);
} else if (!strcasecmp(v->name, "port")) {
if (!realtime && ast_test_flag(&peer->flags[1], SIP_PAGE2_DYNAMIC))
peer->defaddr.sin_port = htons(atoi(v->value));
@@ -17333,6 +17356,9 @@ static int reload_config(enum channelreloadreason reason)
clear_sip_domains();
authl = NULL;
+ ast_free_ha(global_contact_ha);
+ global_contact_ha = NULL;
+
/* First, destroy all outstanding registry calls */
/* This is needed, since otherwise active registry entries will not be destroyed */
ASTOBJ_CONTAINER_TRAVERSE(&regl, 1, do {
@@ -17483,6 +17509,10 @@ static int reload_config(enum channelreloadreason reason)
ast_set2_flag(&global_flags[1], ast_true(v->value), SIP_PAGE2_IGNOREREGEXPIRE);
} else if (!strcasecmp(v->name, "t1min")) {
global_t1min = atoi(v->value);
+ } else if (!strcasecmp(v->name, "dynamic_exclude_static") || !strcasecmp(v->name, "dynamic_excludes_static")) {
+ global_dynamic_exclude_static = ast_true(v->value);
+ } else if (!strcasecmp(v->name, "contactpermit") || !strcasecmp(v->name, "contactdeny")) {
+ global_contact_ha = ast_append_ha(v->name + 7, v->value, global_contact_ha);
} else if (!strcasecmp(v->name, "rtautoclear")) {
int i = atoi(v->value);
if (i > 0)
diff --git a/configs/sip.conf.sample b/configs/sip.conf.sample
index eab1dcf6d..25bbb7735 100644
--- a/configs/sip.conf.sample
+++ b/configs/sip.conf.sample
@@ -136,6 +136,16 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
; your localnet setting. Unless you have some sort of strange network
; setup you will not need to enable this.
+;dynamic_exclude_static = yes ; Disallow all dynamic hosts from registering
+ ; as any IP address used for staticly defined
+ ; hosts. This helps avoid the configuration
+ ; error of allowing your users to register at
+ ; the same address as a SIP provider.
+
+;contactdeny=0.0.0.0/0.0.0.0 ; Use contactpermit and contactdeny to
+;contactpermit=172.16.0.0/255.255.0.0 ; restrict at what IPs your users may
+ ; register their phones.
+
;
; If regcontext is specified, Asterisk will dynamically create and destroy a
; NoOp priority 1 extension for a given peer who registers or unregisters with
@@ -501,6 +511,10 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
; outboundproxy
; rfc2833compensate
; t38pt_usertpsource
+; contactpermit ; Limit what a host may register as (a neat trick
+; contactdeny ; is to register at the same IP as a SIP provider,
+; ; then call oneself, and get redirected to that
+; ; same location).
;[sip_proxy]
; For incoming calls only. Example: FWD (Free World Dialup)