aboutsummaryrefslogtreecommitdiffstats
path: root/channels/chan_sip.c
diff options
context:
space:
mode:
authordvossel <dvossel@f38db490-d61c-443f-a65b-d21fe96a405b>2010-09-03 17:30:04 +0000
committerdvossel <dvossel@f38db490-d61c-443f-a65b-d21fe96a405b>2010-09-03 17:30:04 +0000
commit984a550f3b56279c523083d35fcd68fbad98c107 (patch)
treeae877db98730ef1aea61c65fe27489149231d46e /channels/chan_sip.c
parent92fefe352cf93ef172be7aa9a5c17c96ec7187c3 (diff)
Merged revisions 284950 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r284950 | dvossel | 2010-09-03 12:29:02 -0500 (Fri, 03 Sep 2010) | 14 lines authenticate OPTIONS requests just like we would an INVITE OPTIONS requests should be treated the same as an INVITE This includes authentication. This patch adds the ability for incoming out of dialog OPTION requests to be authenticated before providing a response indicating whether an extension is available or not. The authentication routine works the exact same way as it does for incoming INVITEs. This means that if a peer has 'insecure=invite' in their peer definition, the same will be true for the processing of the OPTIONS request. Review: https://reviewboard.asterisk.org/r/881/ ........ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@284951 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels/chan_sip.c')
-rw-r--r--channels/chan_sip.c49
1 files changed, 35 insertions, 14 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 7254bf736..8d0b51971 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -1512,7 +1512,7 @@ static int handle_request_cancel(struct sip_pvt *p, struct sip_request *req);
static int handle_request_message(struct sip_pvt *p, struct sip_request *req);
static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, int seqno, const char *e);
static void handle_request_info(struct sip_pvt *p, struct sip_request *req);
-static int handle_request_options(struct sip_pvt *p, struct sip_request *req);
+static int handle_request_options(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e);
static int handle_invite_replaces(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, struct ast_sockaddr *addr, int *nounlock);
static int handle_request_notify(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, int seqno, const char *e);
static int local_attended_transfer(struct sip_pvt *transferer, struct sip_dual *current, struct sip_request *req, int seqno, int *nounlock);
@@ -7054,6 +7054,7 @@ struct sip_pvt *sip_alloc(ast_string_field callid, struct ast_sockaddr *addr,
char *sent_by, *branch;
const char *cseq = get_header(req, "Cseq");
unsigned int seqno;
+
/* get branch parameter from initial Request that started this dialog */
get_viabranch(ast_strdupa(get_header(req, "Via")), &sent_by, &branch);
/* only store the branch if it begins with the magic prefix "z9hG4bK", otherwise
@@ -7068,7 +7069,8 @@ struct sip_pvt *sip_alloc(ast_string_field callid, struct ast_sockaddr *addr,
if (!ast_strlen_zero(cseq) && (sscanf(cseq, "%30u", &seqno) == 1)) {
p->init_icseq = seqno;
}
- set_socket_transport(&p->socket, req->socket.type); /* Later in ast_sip_ouraddrfor we need this to choose the right ip and port for the specific transport */
+ /* Later in ast_sip_ouraddrfor we need this to choose the right ip and port for the specific transport */
+ set_socket_transport(&p->socket, req->socket.type);
} else {
set_socket_transport(&p->socket, SIP_TRANSPORT_UDP);
}
@@ -20500,19 +20502,10 @@ static int handle_request_notify(struct sip_pvt *p, struct sip_request *req, str
/*! \brief Handle incoming OPTIONS request
An OPTIONS request should be answered like an INVITE from the same UA, including SDP
*/
-static int handle_request_options(struct sip_pvt *p, struct sip_request *req)
+static int handle_request_options(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e)
{
int res;
-
- /*! XXX get_destination assumes we're already authenticated. This means that a request from
- a known device (peer) will end up in the wrong context if this is out-of-dialog.
- However, we want to handle OPTIONS as light as possible, so we might want to have
- a configuration option whether we care or not. Some devices use this for testing
- capabilities, which means that we need to match device to answer with proper
- capabilities (including SDP).
- \todo Fix handle_request_options device handling with optional authentication
- (this needs to be fixed in 1.4 as well)
- */
+ struct sip_peer *authpeer = NULL; /* Matching Peer */
if (p->lastinvite) {
/* if this is a request in an active dialog, just confirm that the dialog exists. */
@@ -20520,6 +20513,29 @@ static int handle_request_options(struct sip_pvt *p, struct sip_request *req)
return 0;
}
+ if (sip_cfg.auth_options_requests) {
+ /* Do authentication if this OPTIONS request began the dialog */
+ copy_request(&p->initreq, req);
+ set_pvt_allowed_methods(p, req);
+ res = check_user_full(p, req, SIP_OPTIONS, e, XMIT_UNRELIABLE, addr, &authpeer);
+ if (res == AUTH_CHALLENGE_SENT) {
+ sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
+ return 0;
+ }
+ if (res < 0) { /* Something failed in authentication */
+ if (res == AUTH_FAKE_AUTH) {
+ ast_log(LOG_NOTICE, "Sending fake auth rejection for device %s\n", get_header(req, "From"));
+ transmit_fake_auth_response(p, SIP_OPTIONS, req, XMIT_UNRELIABLE);
+ } else {
+ ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", get_header(req, "From"));
+ transmit_response(p, "403 Forbidden", req);
+ }
+ sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
+ return 0;
+ }
+ }
+
+ /* must go through authentication before getting here */
res = (get_destination(p, req, NULL) == SIP_GET_DEST_EXTEN_FOUND ? 0 : -1);
build_contact(p);
@@ -23546,7 +23562,7 @@ static int handle_incoming(struct sip_pvt *p, struct sip_request *req, struct as
/* Handle various incoming SIP methods in requests */
switch (p->method) {
case SIP_OPTIONS:
- res = handle_request_options(p, req);
+ res = handle_request_options(p, req, addr, e);
break;
case SIP_INVITE:
res = handle_request_invite(p, req, debug, seqno, addr, recount, e, nounlock);
@@ -26390,6 +26406,7 @@ static int reload_config(enum channelreloadreason reason)
sip_cfg.notifyhold = FALSE; /*!< Keep track of hold status for a peer */
sip_cfg.directrtpsetup = FALSE; /* Experimental feature, disabled by default */
sip_cfg.alwaysauthreject = DEFAULT_ALWAYSAUTHREJECT;
+ sip_cfg.auth_options_requests = 1;
sip_cfg.allowsubscribe = FALSE;
sip_cfg.disallowed_methods = SIP_UNKNOWN;
sip_cfg.contact_ha = NULL; /* Reset the contact ACL */
@@ -26630,6 +26647,10 @@ static int reload_config(enum channelreloadreason reason)
}
} else if (!strcasecmp(v->name, "alwaysauthreject")) {
sip_cfg.alwaysauthreject = ast_true(v->value);
+ } else if (!strcasecmp(v->name, "auth_options_requests")) {
+ if (ast_false(v->value)) {
+ sip_cfg.auth_options_requests = 0;
+ }
} else if (!strcasecmp(v->name, "mohinterpret")) {
ast_copy_string(default_mohinterpret, v->value, sizeof(default_mohinterpret));
} else if (!strcasecmp(v->name, "mohsuggest")) {