--- channels/chan_sip.c 2005-08-08 11:25:52.000000000 -0700 +++ channels/chan_sip.c 2005-08-08 11:31:53.000000000 -0700 @@ -314,6 +314,8 @@ static int global_reg_timeout = DEFAULT_REGISTRATION_TIMEOUT; static int global_regattempts_max = DEFAULT_REGATTEMPTS_MAX; +static int matchpriority = 0; + /* Object counters */ static int suserobjs = 0; static int ruserobjs = 0; @@ -6182,8 +6184,295 @@ return 0; } +/*--- check_user: Check if matching user or peer is defined - priority to peer ---*/ +static int check_user_full_peer(struct sip_pvt *p, struct sip_request *req, + int sipmethod, char *uri, int reliable, + struct sockaddr_in *sin, int ignore, + char *mailbox, int mailboxlen) +{ + struct sip_user *user = NULL; + struct sip_peer *peer = NULL; + char *of, from[256] = "", *c; + char *rpid, rpid_num[50]; + char iabuf[INET_ADDRSTRLEN]; + int res = 0; + char *t; + char calleridname[50]; + int debug = sip_debug_test_addr(sin); + struct ast_variable *tmpvar = NULL, *v = NULL; + + /* Terminate URI */ + t = uri; + while (*t && (*t > 32) && (*t != ';')) + t++; + *t = '\0'; + of = get_header(req, "From"); + ast_copy_string(from, of, sizeof(from)); + memset(calleridname, 0, sizeof(calleridname)); + get_calleridname(from, calleridname, sizeof(calleridname)); + + rpid = get_header(req, "Remote-Party-ID"); + memset(rpid_num, 0, sizeof(rpid_num)); + if (!ast_strlen_zero(rpid)) + p->callingpres = get_rpid_num(rpid, rpid_num, sizeof(rpid_num)); + + of = get_in_brackets(from); + if (ast_strlen_zero(p->exten)) { + t = uri; + if (!strncmp(t, "sip:", 4)) + t += 4; + ast_copy_string(p->exten, t, sizeof(p->exten)); + t = strchr(p->exten, '@'); + if (t) + *t = '\0'; + if (ast_strlen_zero(p->our_contact)) + build_contact(p); + } + if (strncmp(of, "sip:", 4)) { + ast_log(LOG_NOTICE, "From address missing 'sip:', using it anyway\n"); + } else + of += 4; + /* Get just the username part */ + if ((c = strchr(of, '@'))) { + *c = '\0'; + if ((c = strchr(of, ':'))) + *c = '\0'; + ast_copy_string(p->cid_num, of, sizeof(p->cid_num)); + ast_shrink_phone_number(p->cid_num); + } + if (*calleridname) + ast_copy_string(p->cid_name, calleridname, sizeof(p->cid_name)); + if (ast_strlen_zero(of)) + return 0; + /* Now find them... with peer as priority */ + + peer = find_peer(NULL, &p->recv, 1); + if (peer) { + if (debug) + ast_verbose("Found peer '%s'\n", peer->name); + /* Take the peer */ + ast_copy_flags(p, peer, + SIP_TRUSTRPID | SIP_USECLIENTCODE | SIP_NAT | + SIP_PROG_INBAND | SIP_OSPAUTH); + + /* 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, SIP_TRUSTRPID)) { + if (*calleridname) + ast_copy_string(p->cid_name, calleridname, + sizeof(p->cid_name)); + ast_copy_string(p->cid_num, rpid_num, sizeof(p->cid_num)); + ast_shrink_phone_number(p->cid_num); + } + if (p->rtp) { + ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", + (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE)); + ast_rtp_setnat(p->rtp, + (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE)); + } + if (p->vrtp) { + ast_log(LOG_DEBUG, "Setting NAT on VRTP to %d\n", + (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE)); + ast_rtp_setnat(p->vrtp, + (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE)); + } + ast_copy_string(p->peersecret, peer->secret, sizeof(p->peersecret)); + p->peersecret[sizeof(p->peersecret) - 1] = '\0'; + ast_copy_string(p->peermd5secret, peer->md5secret, + sizeof(p->peermd5secret)); + p->peermd5secret[sizeof(p->peermd5secret) - 1] = '\0'; + p->callingpres = peer->callingpres; + if (ast_test_flag(peer, SIP_INSECURE_INVITE)) { + /* Pretend there is no required authentication */ + p->peersecret[0] = '\0'; + p->peermd5secret[0] = '\0'; + } + if (! + (res = + check_auth(p, req, p->randdata, sizeof(p->randdata), peer->name, + p->peersecret, p->peermd5secret, sipmethod, uri, + reliable, ignore))) { + ast_copy_flags(p, peer, + SIP_PROMISCREDIR | SIP_DTMF | SIP_REINVITE); + /* If we have a call limit, set flag */ + if (peer->incominglimit) + ast_set_flag(p, SIP_CALL_LIMIT); + ast_copy_string(p->peername, peer->name, sizeof(p->peername)); + ast_copy_string(p->authname, peer->name, sizeof(p->authname)); + /* 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 (mailbox) + snprintf(mailbox, mailboxlen, ",%s,", peer->mailbox); + if (!ast_strlen_zero(peer->username)) { + ast_copy_string(p->username, peer->username, + sizeof(p->username)); + /* Use the default username for authentication on outbound calls */ + ast_copy_string(p->authname, peer->username, + sizeof(p->authname)); + } + if (!ast_strlen_zero(peer->cid_num) + && !ast_strlen_zero(p->cid_num)) { + ast_copy_string(p->cid_num, peer->cid_num, + sizeof(p->cid_num)); + ast_shrink_phone_number(p->cid_num); + } + if (!ast_strlen_zero(peer->cid_name) + && !ast_strlen_zero(p->cid_name)) + ast_copy_string(p->cid_name, peer->cid_name, + sizeof(p->cid_name)); + ast_copy_string(p->fullcontact, peer->fullcontact, + sizeof(p->fullcontact)); + if (!ast_strlen_zero(peer->context)) + ast_copy_string(p->context, peer->context, + sizeof(p->context)); + ast_copy_string(p->peersecret, peer->secret, + sizeof(p->peersecret)); + ast_copy_string(p->peermd5secret, peer->md5secret, + sizeof(p->peermd5secret)); + ast_copy_string(p->language, peer->language, sizeof(p->language)); + ast_copy_string(p->accountcode, peer->accountcode, + sizeof(p->accountcode)); + p->amaflags = peer->amaflags; + p->callgroup = peer->callgroup; + p->pickupgroup = peer->pickupgroup; + p->capability = peer->capability; + p->jointcapability = peer->capability; + if (p->peercapability) + p->jointcapability &= p->peercapability; + if (ast_test_flag(p, SIP_DTMF) == SIP_DTMF_RFC2833) + p->noncodeccapability |= AST_RTP_DTMF; + else + p->noncodeccapability &= ~AST_RTP_DTMF; + } + ASTOBJ_UNREF(peer, sip_destroy_peer); + } else { + /* Try to match on user */ + user = find_user(of, 1); + /* Find user based on user name in the from header */ + if (!mailbox && user && ast_apply_ha(user->ha, sin)) { + ast_copy_flags(p, user, + SIP_TRUSTRPID | SIP_USECLIENTCODE | SIP_NAT | + SIP_PROG_INBAND | SIP_OSPAUTH); + /* 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; + /* replace callerid if rpid found, and not restricted */ + if (!ast_strlen_zero(rpid_num) && ast_test_flag(p, SIP_TRUSTRPID)) { + if (*calleridname) + ast_copy_string(p->cid_name, calleridname, + sizeof(p->cid_name)); + ast_copy_string(p->cid_num, rpid_num, sizeof(p->cid_num)); + ast_shrink_phone_number(p->cid_num); + } + + if (p->rtp) { + ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", + (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE)); + ast_rtp_setnat(p->rtp, + (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE)); + } + if (p->vrtp) { + ast_log(LOG_DEBUG, "Setting NAT on VRTP to %d\n", + (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE)); + ast_rtp_setnat(p->vrtp, + (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE)); + } + if (! + (res = + check_auth(p, req, p->randdata, sizeof(p->randdata), + user->name, user->secret, user->md5secret, + sipmethod, uri, reliable, ignore))) { + sip_cancel_destroy(p); + ast_copy_flags(p, user, + SIP_PROMISCREDIR | SIP_DTMF | SIP_REINVITE); + /* Copy SIP extensions profile from INVITE */ + if (p->sipoptions) + user->sipoptions = p->sipoptions; + + /* If we have a call limit, set flag */ + if (user->incominglimit) + ast_set_flag(p, SIP_CALL_LIMIT); + if (!ast_strlen_zero(user->context)) + ast_copy_string(p->context, user->context, + sizeof(p->context)); + if (!ast_strlen_zero(user->cid_num) + && !ast_strlen_zero(p->cid_num)) { + ast_copy_string(p->cid_num, user->cid_num, + sizeof(p->cid_num)); + ast_shrink_phone_number(p->cid_num); + } + if (!ast_strlen_zero(user->cid_name) + && !ast_strlen_zero(p->cid_num)) + ast_copy_string(p->cid_name, user->cid_name, + sizeof(p->cid_name)); + ast_copy_string(p->username, user->name, sizeof(p->username)); + ast_copy_string(p->peersecret, user->secret, + sizeof(p->peersecret)); + ast_copy_string(p->peermd5secret, user->md5secret, + sizeof(p->peermd5secret)); + ast_copy_string(p->accountcode, user->accountcode, + sizeof(p->accountcode)); + ast_copy_string(p->language, user->language, + sizeof(p->language)); + ast_copy_string(p->musicclass, user->musicclass, + sizeof(p->musicclass)); + p->amaflags = user->amaflags; + p->callgroup = user->callgroup; + p->pickupgroup = user->pickupgroup; + p->callingpres = user->callingpres; + p->capability = user->capability; + p->jointcapability = user->capability; + if (p->peercapability) + p->jointcapability &= p->peercapability; + if (ast_test_flag(p, SIP_DTMF) == SIP_DTMF_RFC2833) + p->noncodeccapability |= AST_RTP_DTMF; + else + p->noncodeccapability &= ~AST_RTP_DTMF; + } + if (user && debug) + ast_verbose("Found user '%s'\n", user->name); + } else { + if (debug) + ast_verbose("Found no matching peer or user for '%s:%d'\n", + ast_inet_ntoa(iabuf, sizeof(iabuf), + p->recv.sin_addr), + ntohs(p->recv.sin_port)); + + /* do we allow guests? */ + if (!global_allowguest) + res = -1; /* we don't want any guests, authentication will fail */ +#ifdef OSP_SUPPORT + else if (global_allowguest == 2) { + ast_copy_flags(p, &global_flags, SIP_OSPAUTH); + res = + check_auth(p, req, p->randdata, sizeof(p->randdata), "", + "", "", sipmethod, uri, reliable, ignore); + } +#endif + + user = NULL; + } + } + if (user) + ASTOBJ_UNREF(user, sip_destroy_user); + return res; +} -/*--- check_user: Check if matching user or peer is defined ---*/ + +/*--- check_user: Check if matching user or peer is defined -- priority to user ---*/ static int check_user_full(struct sip_pvt *p, struct sip_request *req, int sipmethod, char *uri, int reliable, struct sockaddr_in *sin, int ignore, char *mailbox, int mailboxlen) { struct sip_user *user; @@ -6430,7 +6719,10 @@ /*--- check_user: Find user ---*/ static int check_user(struct sip_pvt *p, struct sip_request *req, int sipmethod, char *uri, int reliable, struct sockaddr_in *sin, int ignore) { - return check_user_full(p, req, sipmethod, uri, reliable, sin, ignore, NULL, 0); + if (!matchpriority) + return check_user_full(p, req, sipmethod, uri, reliable, sin, ignore, NULL, 0); + else + return check_user_full_peer(p, req, sipmethod, uri, reliable, sin, ignore, NULL, 0); } /*--- get_msg_text: Get text out of a SIP MESSAGE packet ---*/ @@ -9426,7 +9718,10 @@ int found = 0; /* Handle authentication if this is our first subscribe */ - res = check_user_full(p, req, SIP_SUBSCRIBE, e, 0, sin, ignore, mailbox, sizeof(mailbox)); + if (!matchpriority) + res = check_user_full(p, req, SIP_SUBSCRIBE, e, 0, sin, ignore, mailbox, sizeof(mailbox)); + else + res = check_user_full_peer(p, req, SIP_SUBSCRIBE, e, 0, sin, ignore, mailbox, sizeof(mailbox)); if (res) { if (res < 0) { ast_log(LOG_NOTICE, "Failed to authenticate user %s for SUBSCRIBE\n", get_header(req, "From")); @@ -10869,6 +11164,7 @@ relaxdtmf = 0; callevents = 0; ourport = DEFAULT_SIP_PORT; + matchpriority = 0; global_rtptimeout = 0; global_rtpholdtimeout = 0; global_rtpkeepalive = 0; @@ -10969,6 +11265,11 @@ outboundproxyip.sin_port = htons(format); } else if (!strcasecmp(v->name, "autocreatepeer")) { autocreatepeer = ast_true(v->value); + } else if (!strcasecmp(v->name, "matchpriority")) { + if (!strcasecmp(v->value, "peer")) + matchpriority = 1; + else + matchpriority = 0; } else if (!strcasecmp(v->name, "srvlookup")) { srvlookup = ast_true(v->value); } else if (!strcasecmp(v->name, "pedantic")) {