[asterisk-commits] rizzo: branch rizzo/astobj2 r45988 -
/team/rizzo/astobj2/channels/chan_sip.c
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Mon Oct 23 09:44:13 MST 2006
Author: rizzo
Date: Mon Oct 23 11:44:12 2006
New Revision: 45988
URL: http://svn.digium.com/view/asterisk?rev=45988&view=rev
Log:
merge from trunk
Modified:
team/rizzo/astobj2/channels/chan_sip.c
Modified: team/rizzo/astobj2/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/rizzo/astobj2/channels/chan_sip.c?rev=45988&r1=45987&r2=45988&view=diff
==============================================================================
--- team/rizzo/astobj2/channels/chan_sip.c (original)
+++ team/rizzo/astobj2/channels/chan_sip.c Mon Oct 23 11:44:12 2006
@@ -317,11 +317,14 @@
/*! \brief Authentication result from check_auth* functions */
enum check_auth_result {
+ AUTH_DONT_KNOW = -100, /*!< no result, need to check further */
+ /* XXX maybe this is the same as AUTH_NOT_FOUND */
+
AUTH_SUCCESSFUL = 0,
AUTH_CHALLENGE_SENT = 1,
AUTH_SECRET_FAILED = -1,
AUTH_USERNAME_MISMATCH = -2,
- AUTH_NOT_FOUND = -3,
+ AUTH_NOT_FOUND = -3, /* returned by register_verify */
AUTH_FAKE_AUTH = -4,
AUTH_UNKNOWN_DOMAIN = -5,
};
@@ -516,6 +519,7 @@
static int srvlookup; /*!< SRV Lookup on or off. Default is off, RFC behavior is on */
static int pedanticsipchecking; /*!< Extra checking ? Default off */
static int autocreatepeer; /*!< Auto creation of peers at registration? Default off. */
+static int match_auth_username; /*!< Match auth username if available instead of From: Default off. */
static int global_relaxdtmf; /*!< Relax DTMF */
static int global_rtptimeout; /*!< Time out call if no RTP */
static int global_rtpholdtimeout;
@@ -908,6 +912,7 @@
AST_STRING_FIELD(cid_name); /*!< Caller*ID name */
AST_STRING_FIELD(via); /*!< Via: header */
AST_STRING_FIELD(fullcontact); /*!< The Contact: that the UA registers with us */
+ /* we only store the part in <brackets> in this field. */
AST_STRING_FIELD(our_contact); /*!< Our contact header */
AST_STRING_FIELD(rpid); /*!< Our RPID header */
AST_STRING_FIELD(rpid_from); /*!< Our RPID From header */
@@ -2228,6 +2233,75 @@
}
}
return tmp;
+}
+
+/*!
+ * parses a URI in its components.
+ * If scheme is specified, drop it from the top.
+ * If a component is not requested, do not split around it.
+ * This means that if we don't have domain, we cannot split
+ * name:pass and domain:port.
+ * It is safe to call with ret_name, pass, domain, port
+ * pointing all to the same place.
+ * Init pointers to empty string so we never get NULL dereferencing.
+ * Overwrites the string.
+ * return 0 on success, other values on error.
+ */
+static int parse_uri(char *uri, char *scheme,
+ char **ret_name, char **pass, char **domain, char **port, char **options)
+{
+ char *name = NULL;
+ int error = 0;
+
+ /* init field as required */
+ if (*pass)
+ *pass = "";
+ if (*port)
+ *port = "";
+ name = strsep(&uri, ";"); /* remove options */
+ if (scheme) {
+ int l = strlen(scheme);
+ if (!strncmp(name, scheme, l))
+ name += l;
+ else {
+ ast_log(LOG_NOTICE, "Missing scheme '%s' in '%s'\n", scheme, name);
+ error = -1;
+ }
+ }
+ if (!domain) {
+ /* if we don't want to split around domain, keep everything as a name,
+ * so we need to do nothing here, except remember why.
+ */
+ } else {
+ /* store the result in a temp. variable to avoid it being
+ * overwritten if arguments point to the same place.
+ */
+ char *c, *dom = "";
+
+ if ((c = strchr(name, '@')) == NULL) {
+ /* domain-only URI, according to the SIP RFC. */
+ dom = name;
+ name = "";
+ } else {
+ *c++ = '\0';
+ dom = c;
+ }
+ if (port && (c = strchr(dom, ':'))) { /* Remove :port */
+ *c++ = '\0';
+ *port = c;
+ }
+ if (pass && (c = strchr(name, ':'))) { /* user:password */
+ *c++ = '\0';
+ *pass = c;
+ }
+ *domain = dom;
+ }
+ if (ret_name) /* same as for domain, store the result only at the end */
+ *ret_name = name;
+ if (options)
+ *options = uri ? uri : "";
+
+ return error;
}
/*! \brief Send SIP MESSAGE text within a call
@@ -7517,7 +7591,7 @@
struct hostent *hp;
struct ast_hostent ahp;
int port;
- char *c, *host, *pt;
+ char *host, *pt;
char *contact;
@@ -7531,32 +7605,12 @@
/* Work on a copy */
contact = ast_strdupa(pvt->fullcontact);
-
- /* XXX this code is repeated all over */
- /* Make sure it's a SIP URL */
- if (strncasecmp(contact, "sip:", 4)) {
+ /* We have only the part in <brackets> here so we just need to parse a SIP URI.*/
+
+ if (parse_uri(contact, "sip:", &contact, NULL, &host, &pt, NULL))
ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip:) trying to use anyway\n", contact);
- } else
- contact += 4;
-
- /* Ditch arguments */
- /* XXX this code is replicated also shortly below */
- contact = strsep(&contact, ";"); /* trim ; and beyond */
-
- /* Grab host */
- host = strchr(contact, '@');
- if (!host) { /* No username part */
- host = contact;
- c = NULL;
- } else {
- *host++ = '\0';
- }
- pt = strchr(host, ':');
- if (pt) {
- *pt++ = '\0';
- port = atoi(pt);
- } else
- port = STANDARD_SIP_PORT;
+ port = !ast_strlen_zero(pt) ? atoi(pt) : STANDARD_SIP_PORT;
+ ast_verbose("--- set_address_from_contact host '%s'\n", host);
/* XXX This could block for a long time XXX */
/* We should only do this if it's a name, not an IP */
@@ -8072,6 +8126,24 @@
transmit_response_with_auth(p, "401 Unauthorized", req, p->randdata, reliable, "WWW-Authenticate", 0);
}
+/*!
+ * Terminate the uri at the first ';' or space.
+ * Technically we should ignore escaped space per RFC3261 (19.1.1 etc)
+ * but don't do it for the time being. Remember the uri format is:
+ *
+ * sip:user:password at host:port;uri-parameters?headers
+ * sips:user:password at host:port;uri-parameters?headers
+ *
+ */
+static char *terminate_uri(char *uri)
+{
+ char *t = uri;
+ while (*t && *t > ' ' && *t != ';')
+ t++;
+ *t = '\0';
+ return uri;
+}
+
/*! \brief Verify registration of user
- Registration is done in several steps, first a REGISTER without auth
to get a challenge (nonce) then a second one with auth
@@ -8084,15 +8156,10 @@
struct sip_peer *peer;
char tmp[256];
char *name, *c;
- char *t;
char *domain;
- /* Terminate URI */
- t = uri;
- while(*t && (*t > 32) && (*t != ';'))
- t++;
- *t = '\0';
-
+ terminate_uri(uri); /* warning, overwrite the string */
+
ast_copy_string(tmp, get_header(req, "To"), sizeof(tmp));
if (pedanticsipchecking)
ast_uri_decode(tmp);
@@ -8107,6 +8174,9 @@
ast_log(LOG_NOTICE, "Invalid to address: '%s' from %s (missing sip:) trying to use anyway...\n", c, ast_inet_ntoa(sin->sin_addr));
}
+ /* XXX here too we interpret a missing @domain as a name-only
+ * URI, whereas the RFC says this is a domain-only uri.
+ */
/* Strip off the domain name */
if ((c = strchr(name, '@'))) {
*c++ = '\0';
@@ -8679,13 +8749,13 @@
return -1;
}
c += 4;
+ if ((a = strchr(c, ';'))) /* Remove arguments */
+ *a = '\0';
+
if ((a = strchr(c, '@'))) { /* Separate Domain */
*a++ = '\0';
ast_copy_string(referdata->refer_to_domain, a, sizeof(referdata->refer_to_domain));
}
-
- if ((a = strchr(c, ';'))) /* Remove arguments */
- *a = '\0';
if (sip_debug_test_pvt(p))
ast_verbose("Looking for %s in %s\n", c, p->context);
@@ -8836,6 +8906,262 @@
return 0;
}
+/*!
+ * duplicate a list of channel variables, \return the copy.
+ */
+static struct ast_variable *copy_vars(struct ast_variable *src)
+{
+ struct ast_variable *res = NULL, *tmp, *v = NULL;
+
+ for (v = src ; v ; v = v->next) {
+ if ((tmp = ast_variable_new(v->name, v->value))) {
+ tmp->next = res;
+ res = tmp;
+ }
+ }
+ return res;
+}
+
+static enum check_auth_result check_user_ok(struct sip_pvt *p, char *of,
+ struct sip_request *req, int sipmethod, struct sockaddr_in *sin,
+ enum xmittype reliable,
+ char *rpid_num, char *calleridname, char *uri2)
+{
+ enum check_auth_result res;
+ struct sip_user *user = find_user(of, 1);
+ int debug=sip_debug_test_addr(sin);
+
+ /* Find user based on user name in the from header */
+ if (!user) {
+ if (debug)
+ ast_verbose("No user '%s' in SIP users list\n", of);
+ return AUTH_DONT_KNOW;
+ }
+ if (!ast_apply_ha(user->ha, sin)) {
+ if (debug)
+ ast_verbose("Found user '%s' for '%s', but fails host access\n",
+ user->name, of);
+ ASTOBJ_UNREF(user,sip_destroy_user);
+ return AUTH_DONT_KNOW;
+ }
+ if (debug)
+ ast_verbose("Found user '%s' for '%s'\n", user->name, of);
+
+ ast_copy_flags(&p->flags[0], &user->flags[0], SIP_FLAGS_TO_COPY);
+ ast_copy_flags(&p->flags[1], &user->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
+ /* copy channel vars */
+ p->chanvars = copy_vars(user->chanvars);
+ p->prefs = user->prefs;
+ /* Set Frame packetization */
+ if (p->rtp) {
+ ast_rtp_codec_setpref(p->rtp, &p->prefs);
+ p->autoframing = user->autoframing;
+ }
+ /* replace callerid if rpid found, and not restricted */
+ if (!ast_strlen_zero(rpid_num) && ast_test_flag(&p->flags[0], SIP_TRUSTRPID)) {
+ char *tmp;
+ if (*calleridname)
+ ast_string_field_set(p, cid_name, calleridname);
+ tmp = ast_strdupa(rpid_num);
+ if (ast_is_shrinkable_phonenumber(tmp))
+ ast_shrink_phone_number(tmp);
+ ast_string_field_set(p, cid_num, tmp);
+ }
+
+ do_setnat(p, ast_test_flag(&p->flags[0], SIP_NAT_ROUTE) );
+
+ if (!(res = check_auth(p, req, user->name, user->secret, user->md5secret, sipmethod, uri2, reliable, ast_test_flag(req, SIP_PKT_IGNORE)))) {
+ sip_cancel_destroy(p);
+ ast_copy_flags(&p->flags[0], &user->flags[0], SIP_FLAGS_TO_COPY);
+ ast_copy_flags(&p->flags[1], &user->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
+ /* Copy SIP extensions profile from INVITE */
+ if (p->sipoptions)
+ user->sipoptions = p->sipoptions;
+
+ /* If we have a call limit, set flag */
+ if (user->call_limit)
+ ast_set_flag(&p->flags[0], SIP_CALL_LIMIT);
+ if (!ast_strlen_zero(user->context))
+ ast_string_field_set(p, context, user->context);
+ if (!ast_strlen_zero(user->cid_num) && !ast_strlen_zero(p->cid_num)) {
+ char *tmp = ast_strdupa(user->cid_num);
+ if (ast_is_shrinkable_phonenumber(tmp))
+ ast_shrink_phone_number(tmp);
+ ast_string_field_set(p, cid_num, tmp);
+ }
+ if (!ast_strlen_zero(user->cid_name) && !ast_strlen_zero(p->cid_num))
+ ast_string_field_set(p, cid_name, user->cid_name);
+ ast_string_field_set(p, username, user->name);
+ ast_string_field_set(p, peername, user->name);
+ ast_string_field_set(p, peersecret, user->secret);
+ ast_string_field_set(p, peermd5secret, user->md5secret);
+ ast_string_field_set(p, subscribecontext, user->subscribecontext);
+ ast_string_field_set(p, accountcode, user->accountcode);
+ ast_string_field_set(p, language, user->language);
+ ast_string_field_set(p, mohsuggest, user->mohsuggest);
+ ast_string_field_set(p, mohinterpret, user->mohinterpret);
+ p->allowtransfer = user->allowtransfer;
+ p->amaflags = user->amaflags;
+ p->callgroup = user->callgroup;
+ p->pickupgroup = user->pickupgroup;
+ if (user->callingpres) /* User callingpres setting will override RPID header */
+ p->callingpres = user->callingpres;
+
+ /* Set default codec settings for this call */
+ p->capability = user->capability; /* User codec choice */
+ p->jointcapability = user->capability; /* Our codecs */
+ if (p->peercapability) /* AND with peer's codecs */
+ p->jointcapability &= p->peercapability;
+ if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) ||
+ (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO))
+ p->noncodeccapability |= AST_RTP_DTMF;
+ else
+ p->noncodeccapability &= ~AST_RTP_DTMF;
+ if (p->t38.peercapability)
+ p->t38.jointcapability &= p->t38.peercapability;
+ p->maxcallbitrate = user->maxcallbitrate;
+ /* If we do not support video, remove video from call structure */
+ if (!ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT) && p->vrtp) {
+ ast_rtp_destroy(p->vrtp);
+ p->vrtp = NULL;
+ }
+ }
+ ASTOBJ_UNREF(user, sip_destroy_user);
+ return res;
+}
+
+static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
+ struct sip_request *req, int sipmethod, struct sockaddr_in *sin,
+ struct sip_peer **authpeer,
+ enum xmittype reliable,
+ char *rpid_num, char *calleridname, char *uri2)
+{
+ enum check_auth_result res;
+ int debug=sip_debug_test_addr(sin);
+ struct sip_peer *peer;
+
+ if (sipmethod == SIP_SUBSCRIBE)
+ /* For subscribes, match on peer name only */
+ peer = find_peer(of, NULL, 1);
+ else
+ /* Look for peer based on the IP address we received data from */
+ /* If peer is registered from this IP address or have this as a default
+ IP address, this call is from the peer
+ */
+ peer = find_peer(NULL, &p->recv, 1);
+
+ if (!peer) {
+ if (debug)
+ ast_verbose("No matching peer for '%s' from '%s:%d'\n",
+ of, ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port));
+ return AUTH_DONT_KNOW;
+ }
+
+ if (debug)
+ ast_verbose("Found peer '%s' for '%s' from %s:%d\n",
+ peer->name, of, ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port));
+
+ /* XXX what about p->prefs = peer->prefs; ? */
+ /* Set Frame packetization */
+ if (p->rtp) {
+ ast_rtp_codec_setpref(p->rtp, &peer->prefs);
+ p->autoframing = peer->autoframing;
+ }
+
+ /* Take the peer */
+ ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY);
+ ast_copy_flags(&p->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
+
+ /* Copy SIP extensions profile to peer */
+ if (p->sipoptions)
+ peer->sipoptions = p->sipoptions;
+
+ /* replace callerid if rpid found, and not restricted */
+ if (!ast_strlen_zero(rpid_num) && ast_test_flag(&p->flags[0], SIP_TRUSTRPID)) {
+ char *tmp = ast_strdupa(rpid_num);
+ if (*calleridname)
+ ast_string_field_set(p, cid_name, calleridname);
+ if (ast_is_shrinkable_phonenumber(tmp))
+ ast_shrink_phone_number(tmp);
+ ast_string_field_set(p, cid_num, tmp);
+ }
+ do_setnat(p, ast_test_flag(&p->flags[0], SIP_NAT_ROUTE));
+
+ ast_string_field_set(p, peersecret, peer->secret);
+ ast_string_field_set(p, peermd5secret, peer->md5secret);
+ ast_string_field_set(p, subscribecontext, peer->subscribecontext);
+ ast_string_field_set(p, mohinterpret, peer->mohinterpret);
+ ast_string_field_set(p, mohsuggest, peer->mohsuggest);
+ if (peer->callingpres) /* Peer calling pres setting will override RPID */
+ p->callingpres = peer->callingpres;
+ if (peer->maxms && peer->lastms)
+ p->timer_t1 = peer->lastms;
+ if (ast_test_flag(&peer->flags[0], SIP_INSECURE_INVITE)) {
+ /* Pretend there is no required authentication */
+ ast_string_field_free(p, peersecret);
+ ast_string_field_free(p, peermd5secret);
+ }
+ if (!(res = check_auth(p, req, peer->name, p->peersecret, p->peermd5secret, sipmethod, uri2, reliable, ast_test_flag(req, SIP_PKT_IGNORE)))) {
+ ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY);
+ ast_copy_flags(&p->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
+ /* If we have a call limit, set flag */
+ if (peer->call_limit)
+ ast_set_flag(&p->flags[0], SIP_CALL_LIMIT);
+ ast_string_field_set(p, peername, peer->name);
+ ast_string_field_set(p, authname, peer->name);
+
+ /* copy channel vars */
+ p->chanvars = copy_vars(peer->chanvars);
+ if (authpeer) {
+ (*authpeer) = ASTOBJ_REF(peer); /* Add a ref to the object here, to keep it in memory a bit longer if it is realtime */
+ }
+
+ if (!ast_strlen_zero(peer->username)) {
+ ast_string_field_set(p, username, peer->username);
+ /* Use the default username for authentication on outbound calls */
+ /* XXX this takes the name from the caller... can we override ? */
+ ast_string_field_set(p, authname, peer->username);
+ }
+ if (!ast_strlen_zero(peer->cid_num) && !ast_strlen_zero(p->cid_num)) {
+ char *tmp = ast_strdupa(peer->cid_num);
+ if (ast_is_shrinkable_phonenumber(tmp))
+ ast_shrink_phone_number(tmp);
+ ast_string_field_set(p, cid_num, tmp);
+ }
+ if (!ast_strlen_zero(peer->cid_name) && !ast_strlen_zero(p->cid_name))
+ ast_string_field_set(p, cid_name, peer->cid_name);
+ ast_string_field_set(p, fullcontact, peer->fullcontact);
+ if (!ast_strlen_zero(peer->context))
+ ast_string_field_set(p, context, peer->context);
+ ast_string_field_set(p, peersecret, peer->secret);
+ ast_string_field_set(p, peermd5secret, peer->md5secret);
+ ast_string_field_set(p, language, peer->language);
+ ast_string_field_set(p, accountcode, peer->accountcode);
+ p->amaflags = peer->amaflags;
+ p->callgroup = peer->callgroup;
+ p->pickupgroup = peer->pickupgroup;
+ p->capability = peer->capability;
+ p->prefs = peer->prefs;
+ p->jointcapability = peer->capability;
+ if (p->peercapability)
+ p->jointcapability &= p->peercapability;
+ p->maxcallbitrate = peer->maxcallbitrate;
+ if (!ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT) && p->vrtp) {
+ ast_rtp_destroy(p->vrtp);
+ p->vrtp = NULL;
+ }
+ if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) ||
+ (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO))
+ p->noncodeccapability |= AST_RTP_DTMF;
+ else
+ p->noncodeccapability &= ~AST_RTP_DTMF;
+ if (p->t38.peercapability)
+ p->t38.jointcapability &= p->t38.peercapability;
+ }
+ ASTOBJ_UNREF(peer, sip_destroy_peer);
+ return res;
+}
+
/*! \brief Check if matching user or peer is defined
Match user on From: user name and peer on IP/port
@@ -8846,25 +9172,19 @@
int sipmethod, char *uri, enum xmittype reliable,
struct sockaddr_in *sin, struct sip_peer **authpeer)
{
- struct sip_user *user = NULL;
- struct sip_peer *peer;
- char from[256], *c;
+ char from[256];
+ char *dummy; /* dummy return value for parse_uri */
+ char *domain; /* dummy return value for parse_uri */
char *of;
char rpid_num[50];
const char *rpid;
- enum check_auth_result res = AUTH_SUCCESSFUL;
- char *t;
+ enum check_auth_result res;
char calleridname[50];
- int debug=sip_debug_test_addr(sin);
- struct ast_variable *tmpvar = NULL, *v = NULL;
char *uri2 = ast_strdupa(uri);
- /* Terminate URI */
- t = uri2;
- while (*t && *t > 32 && *t != ';')
- t++;
- *t = '\0';
- ast_copy_string(from, get_header(req, "From"), sizeof(from)); /* XXX bug in original code, overwrote string */
+ terminate_uri(uri2); /* trim extra stuff */
+
+ ast_copy_string(from, get_header(req, "From"), sizeof(from));
if (pedanticsipchecking)
ast_uri_decode(from);
/* XXX here tries to map the username for invite things */
@@ -8880,7 +9200,7 @@
of = get_in_brackets(from);
if (ast_strlen_zero(p->exten)) {
- t = uri2;
+ char *t = uri2;
if (!strncmp(t, "sip:", 4))
t+= 4;
ast_string_field_set(p, exten, t);
@@ -8892,17 +9212,22 @@
}
/* save the URI part of the From header */
ast_string_field_set(p, from, of);
- if (strncmp(of, "sip:", 4)) {
+
+ /* ignore all fields but name */
+ if (parse_uri(of, "sip:", &of, &dummy, &domain, &dummy, &dummy)) {
ast_log(LOG_NOTICE, "From address missing 'sip:', using it anyway\n");
- } else
- of += 4;
- /* Get just the username part */
- if ((c = strchr(of, '@'))) {
- char *tmp;
- *c = '\0';
- if ((c = strchr(of, ':')))
- *c = '\0';
- tmp = ast_strdupa(of);
+ }
+ if (ast_strlen_zero(of)) {
+ /* XXX note: the original code considered a missing @host
+ * as a username-only URI. The SIP RFC (19.1.1) says that
+ * this is wrong, and it should be considered as a domain-only URI.
+ * For backward compatibility, we keep this block, but it is
+ * really a mistake and should go away.
+ */
+ of = domain;
+ }
+ {
+ char *tmp = ast_strdupa(of);
if (ast_is_shrinkable_phonenumber(tmp))
ast_shrink_phone_number(tmp);
ast_string_field_set(p, cid_num, tmp);
@@ -8910,256 +9235,48 @@
if (ast_strlen_zero(of))
return AUTH_SUCCESSFUL;
- if (1) {
+ if (match_auth_username) {
/*
* XXX This is experimental code to grab the search key from the
* Auth header's username instead of the 'From' name, if available.
* Do not enable this block unless you understand the side effects (if any!)
* Note, the search for "username" should be done in a more robust way.
+ * Note2, at the moment we chech both fields, though maybe we should
+ * pick one or another depending on the request ? XXX
*/
- const char *hdr = (sipmethod == SIP_REGISTER || sipmethod == SIP_SUBSCRIBE) ?
- "Authorization" : "Proxy-Authorization";
- if ( (hdr = get_header(req, hdr)) && (hdr = strstr(hdr, "username=\"")) ) {
+ const char *hdr = get_header(req, "Authorization");
+ if (ast_strlen_zero(hdr))
+ hdr = get_header(req, "Proxy-Authorization");
+
+ if ( !ast_strlen_zero(hdr) && (hdr = strstr(hdr, "username=\"")) ) {
ast_copy_string(from, hdr + strlen("username=\""), sizeof(from));
of = from;
of = strsep(&of, "\"");
}
}
- if (!authpeer) /* If we are looking for a peer, don't check the user objects (or realtime) */
- user = find_user(of, 1);
-
- /* Find user based on user name in the from header */
- if (user && ast_apply_ha(user->ha, sin)) {
- ast_copy_flags(&p->flags[0], &user->flags[0], SIP_FLAGS_TO_COPY);
- ast_copy_flags(&p->flags[1], &user->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
- /* copy channel vars */
- for (v = user->chanvars ; v ; v = v->next) {
- if ((tmpvar = ast_variable_new(v->name, v->value))) {
- tmpvar->next = p->chanvars;
- p->chanvars = tmpvar;
- }
- }
- p->prefs = user->prefs;
- /* Set Frame packetization */
- if (p->rtp) {
- ast_rtp_codec_setpref(p->rtp, &p->prefs);
- p->autoframing = user->autoframing;
- }
- /* replace callerid if rpid found, and not restricted */
- if (!ast_strlen_zero(rpid_num) && ast_test_flag(&p->flags[0], SIP_TRUSTRPID)) {
- char *tmp;
- if (*calleridname)
- ast_string_field_set(p, cid_name, calleridname);
- tmp = ast_strdupa(rpid_num);
- if (ast_is_shrinkable_phonenumber(tmp))
- ast_shrink_phone_number(tmp);
- ast_string_field_set(p, cid_num, tmp);
- }
-
- do_setnat(p, ast_test_flag(&p->flags[0], SIP_NAT_ROUTE) );
-
- if (!(res = check_auth(p, req, user->name, user->secret, user->md5secret, sipmethod, uri2, reliable, ast_test_flag(req, SIP_PKT_IGNORE)))) {
- sip_cancel_destroy(p);
- ast_copy_flags(&p->flags[0], &user->flags[0], SIP_FLAGS_TO_COPY);
- ast_copy_flags(&p->flags[1], &user->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
- /* Copy SIP extensions profile from INVITE */
- if (p->sipoptions)
- user->sipoptions = p->sipoptions;
-
- /* If we have a call limit, set flag */
- if (user->call_limit)
- ast_set_flag(&p->flags[0], SIP_CALL_LIMIT);
- if (!ast_strlen_zero(user->context))
- ast_string_field_set(p, context, user->context);
- if (!ast_strlen_zero(user->cid_num) && !ast_strlen_zero(p->cid_num)) {
- char *tmp = ast_strdupa(user->cid_num);
- if (ast_is_shrinkable_phonenumber(tmp))
- ast_shrink_phone_number(tmp);
- ast_string_field_set(p, cid_num, tmp);
- }
- if (!ast_strlen_zero(user->cid_name) && !ast_strlen_zero(p->cid_num))
- ast_string_field_set(p, cid_name, user->cid_name);
- ast_string_field_set(p, username, user->name);
- ast_string_field_set(p, peername, user->name);
- ast_string_field_set(p, peersecret, user->secret);
- ast_string_field_set(p, peermd5secret, user->md5secret);
- ast_string_field_set(p, subscribecontext, user->subscribecontext);
- ast_string_field_set(p, accountcode, user->accountcode);
- ast_string_field_set(p, language, user->language);
- ast_string_field_set(p, mohsuggest, user->mohsuggest);
- ast_string_field_set(p, mohinterpret, user->mohinterpret);
- p->allowtransfer = user->allowtransfer;
- p->amaflags = user->amaflags;
- p->callgroup = user->callgroup;
- p->pickupgroup = user->pickupgroup;
- if (user->callingpres) /* User callingpres setting will override RPID header */
- p->callingpres = user->callingpres;
-
- /* Set default codec settings for this call */
- p->capability = user->capability; /* User codec choice */
- p->jointcapability = user->capability; /* Our codecs */
- if (p->peercapability) /* AND with peer's codecs */
- p->jointcapability &= p->peercapability;
- if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) ||
- (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO))
- p->noncodeccapability |= AST_RTP_DTMF;
- else
- p->noncodeccapability &= ~AST_RTP_DTMF;
- if (p->t38.peercapability)
- p->t38.jointcapability &= p->t38.peercapability;
- p->maxcallbitrate = user->maxcallbitrate;
- /* If we do not support video, remove video from call structure */
- if (!ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT) && p->vrtp) {
- ast_rtp_destroy(p->vrtp);
- p->vrtp = NULL;
- }
- }
- if (user && debug)
- ast_verbose("Found user '%s'\n", user->name);
- } else {
- if (user) {
- if (!authpeer && debug)
- ast_verbose("Found user '%s', but fails host access\n", user->name);
- ASTOBJ_UNREF(user,sip_destroy_user);
- }
- user = NULL;
- }
-
- if (!user) {
- /* If we didn't find a user match, check for peers */
- if (sipmethod == SIP_SUBSCRIBE)
- /* For subscribes, match on peer name only */
- peer = find_peer(of, NULL, 1);
- else
- /* Look for peer based on the IP address we received data from */
- /* If peer is registered from this IP address or have this as a default
- IP address, this call is from the peer
- */
- peer = find_peer(NULL, &p->recv, 1);
-
- if (peer) {
- /* Set Frame packetization */
- if (p->rtp) {
- ast_rtp_codec_setpref(p->rtp, &peer->prefs);
- p->autoframing = peer->autoframing;
- }
- if (debug)
- ast_verbose("Found peer '%s'\n", peer->name);
-
- /* Take the peer */
- ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY);
- ast_copy_flags(&p->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
-
- /* Copy SIP extensions profile to peer */
- if (p->sipoptions)
- peer->sipoptions = p->sipoptions;
-
- /* replace callerid if rpid found, and not restricted */
- if (!ast_strlen_zero(rpid_num) && ast_test_flag(&p->flags[0], SIP_TRUSTRPID)) {
- char *tmp = ast_strdupa(rpid_num);
- if (*calleridname)
- ast_string_field_set(p, cid_name, calleridname);
- if (ast_is_shrinkable_phonenumber(tmp))
- ast_shrink_phone_number(tmp);
- ast_string_field_set(p, cid_num, tmp);
- }
- do_setnat(p, ast_test_flag(&p->flags[0], SIP_NAT_ROUTE));
-
- ast_string_field_set(p, peersecret, peer->secret);
- ast_string_field_set(p, peermd5secret, peer->md5secret);
- ast_string_field_set(p, subscribecontext, peer->subscribecontext);
- ast_string_field_set(p, mohinterpret, peer->mohinterpret);
- ast_string_field_set(p, mohsuggest, peer->mohsuggest);
- if (peer->callingpres) /* Peer calling pres setting will override RPID */
- p->callingpres = peer->callingpres;
- if (peer->maxms && peer->lastms)
- p->timer_t1 = peer->lastms;
- if (ast_test_flag(&peer->flags[0], SIP_INSECURE_INVITE)) {
- /* Pretend there is no required authentication */
- ast_string_field_free(p, peersecret);
- ast_string_field_free(p, peermd5secret);
- }
- if (!(res = check_auth(p, req, peer->name, p->peersecret, p->peermd5secret, sipmethod, uri2, reliable, ast_test_flag(req, SIP_PKT_IGNORE)))) {
- ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY);
- ast_copy_flags(&p->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
- /* If we have a call limit, set flag */
- if (peer->call_limit)
- ast_set_flag(&p->flags[0], SIP_CALL_LIMIT);
- ast_string_field_set(p, peername, peer->name);
- ast_string_field_set(p, authname, peer->name);
-
- /* copy channel vars */
- for (v = peer->chanvars ; v ; v = v->next) {
- if ((tmpvar = ast_variable_new(v->name, v->value))) {
- tmpvar->next = p->chanvars;
- p->chanvars = tmpvar;
- }
- }
- if (authpeer) {
- (*authpeer) = ASTOBJ_REF(peer); /* Add a ref to the object here, to keep it in memory a bit longer if it is realtime */
- }
-
- if (!ast_strlen_zero(peer->username)) {
- ast_string_field_set(p, username, peer->username);
- /* Use the default username for authentication on outbound calls */
- /* XXX this takes the name from the caller... can we override ? */
- ast_string_field_set(p, authname, peer->username);
- }
- if (!ast_strlen_zero(peer->cid_num) && !ast_strlen_zero(p->cid_num)) {
- char *tmp = ast_strdupa(peer->cid_num);
- if (ast_is_shrinkable_phonenumber(tmp))
- ast_shrink_phone_number(tmp);
- ast_string_field_set(p, cid_num, tmp);
- }
- if (!ast_strlen_zero(peer->cid_name) && !ast_strlen_zero(p->cid_name))
- ast_string_field_set(p, cid_name, peer->cid_name);
- ast_string_field_set(p, fullcontact, peer->fullcontact);
- if (!ast_strlen_zero(peer->context))
- ast_string_field_set(p, context, peer->context);
- ast_string_field_set(p, peersecret, peer->secret);
- ast_string_field_set(p, peermd5secret, peer->md5secret);
- ast_string_field_set(p, language, peer->language);
- ast_string_field_set(p, accountcode, peer->accountcode);
- p->amaflags = peer->amaflags;
- p->callgroup = peer->callgroup;
- p->pickupgroup = peer->pickupgroup;
- p->capability = peer->capability;
- p->prefs = peer->prefs;
- p->jointcapability = peer->capability;
- if (p->peercapability)
- p->jointcapability &= p->peercapability;
- p->maxcallbitrate = peer->maxcallbitrate;
- if (!ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT) && p->vrtp) {
- ast_rtp_destroy(p->vrtp);
- p->vrtp = NULL;
- }
- if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) ||
- (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO))
- p->noncodeccapability |= AST_RTP_DTMF;
- else
- p->noncodeccapability &= ~AST_RTP_DTMF;
- if (p->t38.peercapability)
- p->t38.jointcapability &= p->t38.peercapability;
- }
- ASTOBJ_UNREF(peer, sip_destroy_peer);
- } else {
- if (debug)
- ast_verbose("Found no matching peer or user for '%s:%d'\n", ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port));
-
- /* do we allow guests? */
- if (!global_allowguest) {
- if (global_alwaysauthreject)
- res = AUTH_FAKE_AUTH; /* reject with fake authorization request */
- else
- res = AUTH_SECRET_FAILED; /* we don't want any guests, authentication will fail */
- }
- }
-
- }
-
- if (user)
- ASTOBJ_UNREF(user, sip_destroy_user);
+ if (!authpeer) {
+ /* If we are looking for a peer, don't check the
+ user objects (or realtime) */
+ res = check_user_ok(p, of, req, sipmethod, sin,
+ reliable, rpid_num, calleridname, uri2);
+ if (res != AUTH_DONT_KNOW)
+ return res;
+ }
+
+ res = check_peer_ok(p, of, req, sipmethod, sin,
+ authpeer, reliable, rpid_num, calleridname, uri2);
+ if (res != AUTH_DONT_KNOW)
+ return res;
+
+ /* Finally, apply the guest policy */
+ if (global_allowguest)
+ res = AUTH_SUCCESSFUL;
+ else if (global_alwaysauthreject)
+ res = AUTH_FAKE_AUTH; /* reject with fake authorization request */
+ else
+ res = AUTH_SECRET_FAILED; /* we don't want any guests, authentication will fail */
+
return res;
}
@@ -10176,6 +10293,7 @@
ast_cli(fd, " Bindaddress: %s\n", ast_inet_ntoa(bindaddr.sin_addr));
ast_cli(fd, " Videosupport: %s\n", ast_test_flag(&global_flags[1], SIP_PAGE2_VIDEOSUPPORT) ? "Yes" : "No");
ast_cli(fd, " AutoCreatePeer: %s\n", autocreatepeer ? "Yes" : "No");
+ ast_cli(fd, " MatchAuthUsername: %s\n", match_auth_username ? "Yes" : "No");
ast_cli(fd, " Allow unknown access: %s\n", global_allowguest ? "Yes" : "No");
ast_cli(fd, " Allow subscriptions: %s\n", ast_test_flag(&global_flags[1], SIP_PAGE2_ALLOWSUBSCRIBE) ? "Yes" : "No");
ast_cli(fd, " Allow overlap dialing: %s\n", ast_test_flag(&global_flags[1], SIP_PAGE2_ALLOWOVERLAP) ? "Yes" : "No");
@@ -15343,14 +15461,30 @@
return a;
}
+/*!
+ * implement the servar config line
+ */
+static struct ast_variable *add_var(const char *buf, struct ast_variable *list)
+{
+ struct ast_variable *tmpvar = NULL;
+ char *varname = ast_strdupa(buf), *varval = NULL;
+
+ if ((varval = strchr(varname,'='))) {
+ *varval++ = '\0';
+ if ((tmpvar = ast_variable_new(varname, varval))) {
+ tmpvar->next = list;
+ list = tmpvar;
+ }
+ }
+ return list;
+}
+
/*! \brief Initiate a SIP user structure from configuration (configuration or realtime) */
static struct sip_user *build_user(const char *name, struct ast_variable *v, int realtime)
{
struct sip_user *user;
int format;
struct ast_ha *oldha = NULL;
- char *varname = NULL, *varval = NULL;
- struct ast_variable *tmpvar = NULL;
struct ast_flags userflags[2] = {{(0)}};
struct ast_flags mask[2] = {{(0)}};
@@ -15383,14 +15517,7 @@
} else if (!strcasecmp(v->name, "subscribecontext")) {
ast_copy_string(user->subscribecontext, v->value, sizeof(user->subscribecontext));
} else if (!strcasecmp(v->name, "setvar")) {
- varname = ast_strdupa(v->value);
- if ((varval = strchr(varname,'='))) {
- *varval++ = '\0';
- if ((tmpvar = ast_variable_new(varname, varval))) {
- tmpvar->next = user->chanvars;
- user->chanvars = tmpvar;
- }
- }
+ user->chanvars = add_var(v->value, user->chanvars);
} else if (!strcasecmp(v->name, "permit") ||
!strcasecmp(v->name, "deny")) {
user->ha = ast_append_ha(v->name, v->value, user->ha);
@@ -15533,8 +15660,6 @@
int firstpass=1;
int format=0; /* Ama flags */
time_t regseconds = 0;
- char *varname = NULL, *varval = NULL;
- struct ast_variable *tmpvar = NULL;
struct ast_flags peerflags[2] = {{(0)}};
struct ast_flags mask[2] = {{(0)}};
char contact[256] = "";
@@ -15727,15 +15852,7 @@
peer->rtpkeepalive = global_rtpkeepalive;
}
} else if (!strcasecmp(v->name, "setvar")) {
- /* Set peer channel variable */
- varname = ast_strdupa(v->value);
- if ((varval = strchr(varname, '='))) {
- *varval++ = '\0';
- if ((tmpvar = ast_variable_new(varname, varval))) {
- tmpvar->next = peer->chanvars;
- peer->chanvars = tmpvar;
- }
- }
+ peer->chanvars = add_var(v->value, peer->chanvars);
} else if (!strcasecmp(v->name, "qualify")) {
if (!strcasecmp(v->value, "no")) {
peer->maxms = 0;
@@ -16007,6 +16124,8 @@
outboundproxyip.sin_port = htons(format);
} else if (!strcasecmp(v->name, "autocreatepeer")) {
autocreatepeer = ast_true(v->value);
+ } else if (!strcasecmp(v->name, "match_auth_username")) {
+ match_auth_username = ast_true(v->value);
} else if (!strcasecmp(v->name, "srvlookup")) {
srvlookup = ast_true(v->value);
} else if (!strcasecmp(v->name, "pedantic")) {
More information about the asterisk-commits
mailing list