add a new option for 'obscuring' SIP user/peer names from fishers

use an enum for authentication results and clean up code
fix a bug where SUBSCRIBE for an unknown user/peer would not generate a response


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@29903 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.4
Kevin P. Fleming 19 years ago
parent 74cb39729b
commit 3e99be68d1

@ -444,6 +444,7 @@ static struct ast_codec_pref default_prefs; /*!< Default codec prefs */
/* Global settings only apply to the channel */ /* Global settings only apply to the channel */
static int global_rtautoclear; static int global_rtautoclear;
static int global_notifyringing; /*!< Send notifications on ringing */ static int global_notifyringing; /*!< Send notifications on ringing */
static int global_alwaysauthreject; /*!< Send 401 Unauthorized for all failing requests */
static int srvlookup; /*!< SRV Lookup on or off. Default is off, RFC behavior is on */ static int srvlookup; /*!< SRV Lookup on or off. Default is off, RFC behavior is on */
static int pedanticsipchecking; /*!< Extra checking ? Default off */ static int pedanticsipchecking; /*!< Extra checking ? Default off */
static int autocreatepeer; /*!< Auto creation of peers at registration? Default off. */ static int autocreatepeer; /*!< Auto creation of peers at registration? Default off. */
@ -1031,6 +1032,16 @@ static struct sockaddr_in debugaddr;
static struct ast_config *notify_types; /*!< The list of manual NOTIFY types we know how to send */ static struct ast_config *notify_types; /*!< The list of manual NOTIFY types we know how to send */
enum check_auth_result {
AUTH_SUCCESSFUL = 0,
AUTH_CHALLENGE_SENT = 1,
AUTH_SECRET_FAILED = -1,
AUTH_USERNAME_MISMATCH = -2,
AUTH_NOT_FOUND = -3,
AUTH_FAKE_AUTH = -4,
AUTH_UNKNOWN_DOMAIN = -5,
};
/*---------------------------- Forward declarations of functions in chan_sip.c */ /*---------------------------- Forward declarations of functions in chan_sip.c */
/*! \note Sorted up from start to build_rpid.... Will continue categorization in order to /*! \note Sorted up from start to build_rpid.... Will continue categorization in order to
split up chan_sip.c into several files */ split up chan_sip.c into several files */
@ -1114,7 +1125,7 @@ static int build_reply_digest(struct sip_pvt *p, int method, char *digest, int d
static int clear_realm_authentication(struct sip_auth *authlist); /* Clear realm authentication list (at reload) */ static int clear_realm_authentication(struct sip_auth *authlist); /* Clear realm authentication list (at reload) */
static struct sip_auth *add_realm_authentication(struct sip_auth *authlist, char *configuration, int lineno); /* Add realm authentication in list */ static struct sip_auth *add_realm_authentication(struct sip_auth *authlist, char *configuration, int lineno); /* Add realm authentication in list */
static struct sip_auth *find_realm_authentication(struct sip_auth *authlist, const char *realm); /* Find authentication for a specific realm */ static struct sip_auth *find_realm_authentication(struct sip_auth *authlist, const char *realm); /* Find authentication for a specific realm */
static int check_auth(struct sip_pvt *p, struct sip_request *req, const char *username, static enum check_auth_result check_auth(struct sip_pvt *p, struct sip_request *req, const char *username,
const char *secret, const char *md5secret, int sipmethod, const char *secret, const char *md5secret, int sipmethod,
char *uri, enum xmittype reliable, int ignore); char *uri, enum xmittype reliable, int ignore);
@ -6635,10 +6646,9 @@ static void build_route(struct sip_pvt *p, struct sip_request *req, int backward
/*! \brief Check user authorization from peer definition /*! \brief Check user authorization from peer definition
Some actions, like REGISTER and INVITEs from peers require Some actions, like REGISTER and INVITEs from peers require
authentication (if peer have secret set) authentication (if peer have secret set)
\return -1 on Error, 0 on success, 1 on challenge sent \return 0 on success, non-zero on error
*/ */
static int check_auth(struct sip_pvt *p, struct sip_request *req, const char *username, static enum check_auth_result check_auth(struct sip_pvt *p, struct sip_request *req, const char *username,
const char *secret, const char *md5secret, int sipmethod, const char *secret, const char *md5secret, int sipmethod,
char *uri, enum xmittype reliable, int ignore) char *uri, enum xmittype reliable, int ignore)
{ {
@ -6649,7 +6659,7 @@ static int check_auth(struct sip_pvt *p, struct sip_request *req, const char *us
/* Always OK if no secret */ /* Always OK if no secret */
if (ast_strlen_zero(secret) && ast_strlen_zero(md5secret)) if (ast_strlen_zero(secret) && ast_strlen_zero(md5secret))
return 0; return AUTH_SUCCESSFUL;
if (sipmethod == SIP_REGISTER || sipmethod == SIP_SUBSCRIBE) { if (sipmethod == SIP_REGISTER || sipmethod == SIP_SUBSCRIBE) {
/* On a REGISTER, we have to use 401 and its family of headers instead of 407 and its family /* On a REGISTER, we have to use 401 and its family of headers instead of 407 and its family
of headers -- GO SIP! Whoo hoo! Two things that do the same thing but are used in of headers -- GO SIP! Whoo hoo! Two things that do the same thing but are used in
@ -6669,14 +6679,14 @@ static int check_auth(struct sip_pvt *p, struct sip_request *req, const char *us
/* Schedule auto destroy in 32 seconds (according to RFC 3261) */ /* Schedule auto destroy in 32 seconds (according to RFC 3261) */
sip_scheddestroy(p, SIP_TRANS_TIMEOUT); sip_scheddestroy(p, SIP_TRANS_TIMEOUT);
} }
return 1; /* Auth sent */ return AUTH_CHALLENGE_SENT;
} else if (ast_strlen_zero(p->randdata) || ast_strlen_zero(authtoken)) { } else if (ast_strlen_zero(p->randdata) || ast_strlen_zero(authtoken)) {
/* We have no auth, so issue challenge and request authentication */ /* We have no auth, so issue challenge and request authentication */
ast_string_field_build(p, randdata, "%08lx", ast_random()); /* Create nonce for challenge */ ast_string_field_build(p, randdata, "%08lx", ast_random()); /* Create nonce for challenge */
transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 0); transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 0);
/* Schedule auto destroy in 32 seconds */ /* Schedule auto destroy in 32 seconds */
sip_scheddestroy(p, SIP_TRANS_TIMEOUT); sip_scheddestroy(p, SIP_TRANS_TIMEOUT);
return 1; /* Auth sent */ return AUTH_CHALLENGE_SENT;
} else { /* We have auth, so check it */ } else { /* We have auth, so check it */
/* Whoever came up with the authentication section of SIP can suck my %&#$&* for not putting /* Whoever came up with the authentication section of SIP can suck my %&#$&* for not putting
an example in the spec of just what it is you're doing a hash on. */ an example in the spec of just what it is you're doing a hash on. */
@ -6729,7 +6739,7 @@ static int check_auth(struct sip_pvt *p, struct sip_request *req, const char *us
ast_log(LOG_WARNING, "username mismatch, have <%s>, digest has <%s>\n", ast_log(LOG_WARNING, "username mismatch, have <%s>, digest has <%s>\n",
username, keys[K_USER].s); username, keys[K_USER].s);
/* Oops, we're trying something here */ /* Oops, we're trying something here */
return -2; return AUTH_USERNAME_MISMATCH;
} }
/* Verify nonce from request matches our nonce. If not, send 401 with new nonce */ /* Verify nonce from request matches our nonce. If not, send 401 with new nonce */
@ -6777,18 +6787,16 @@ static int check_auth(struct sip_pvt *p, struct sip_request *req, const char *us
/* Schedule auto destroy in 32 seconds */ /* Schedule auto destroy in 32 seconds */
sip_scheddestroy(p, SIP_TRANS_TIMEOUT); sip_scheddestroy(p, SIP_TRANS_TIMEOUT);
return 1; /* XXX should it be -1 ? */ return AUTH_CHALLENGE_SENT;
} }
if (good_response) /* Auth is OK */ if (good_response)
return 0; return AUTH_SUCCESSFUL;
/* XXX is this needed ? */
/* Ok, we have a bad username/secret pair */ /* Ok, we have a bad username/secret pair */
/* Challenge again, and again, and again */ /* Challenge again, and again, and again */
transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 0); transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 0);
sip_scheddestroy(p, SIP_TRANS_TIMEOUT); sip_scheddestroy(p, SIP_TRANS_TIMEOUT);
return 1; /* Challenge sent */ return AUTH_CHALLENGE_SENT;
} }
} }
@ -6821,10 +6829,20 @@ static int cb_extensionstate(char *context, char* exten, int state, void *data)
return 0; return 0;
} }
/*! \brief Send a fake 401 Unauthorized response when the administrator
wants to hide the names of local users/peers from fishers
*/
static void transmit_fake_auth_response(struct sip_pvt *p, struct sip_request *req, int reliable)
{
ast_string_field_build(p, randdata, "%08lx", ast_random()); /* Create nonce for challenge */
transmit_response_with_auth(p, "401 Unauthorized", req, p->randdata, reliable, "WWW-Authenticate", 0);
}
/*! \brief Verify registration of user */ /*! \brief Verify registration of user */
static int register_verify(struct sip_pvt *p, struct sockaddr_in *sin, struct sip_request *req, char *uri) static enum check_auth_result register_verify(struct sip_pvt *p, struct sockaddr_in *sin,
struct sip_request *req, char *uri)
{ {
int res = -3; enum check_auth_result res = AUTH_NOT_FOUND;
struct sip_peer *peer; struct sip_peer *peer;
char tmp[256]; char tmp[256];
char iabuf[INET_ADDRSTRLEN]; char iabuf[INET_ADDRSTRLEN];
@ -6861,7 +6879,7 @@ static int register_verify(struct sip_pvt *p, struct sockaddr_in *sin, struct si
if (!AST_LIST_EMPTY(&domain_list)) { if (!AST_LIST_EMPTY(&domain_list)) {
if (!check_sip_domain(domain, NULL, 0)) { if (!check_sip_domain(domain, NULL, 0)) {
transmit_response(p, "404 Not found (unknown domain)", &p->initreq); transmit_response(p, "404 Not found (unknown domain)", &p->initreq);
return -3; return AUTH_UNKNOWN_DOMAIN;
} }
} }
} }
@ -6938,28 +6956,46 @@ static int register_verify(struct sip_pvt *p, struct sockaddr_in *sin, struct si
} }
if (res < 0) { if (res < 0) {
switch (res) { switch (res) {
case -1: case AUTH_SECRET_FAILED:
/* Wrong password in authentication. Go away, don't try again until you fixed it */ /* Wrong password in authentication. Go away, don't try again until you fixed it */
transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq); transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq);
break; break;
case -2: case AUTH_USERNAME_MISMATCH:
/* Username and digest username does not match. /* Username and digest username does not match.
Asterisk uses the From: username for authentication. We need the Asterisk uses the From: username for authentication. We need the
users to use the same authentication user name until we support users to use the same authentication user name until we support
proper authentication by digest auth name */ proper authentication by digest auth name */
transmit_response(p, "403 Authentication user name does not match account name", &p->initreq); transmit_response(p, "403 Authentication user name does not match account name", &p->initreq);
break; break;
case -3: case AUTH_NOT_FOUND:
if (global_alwaysauthreject) {
transmit_fake_auth_response(p, &p->initreq, 1);
} else {
/* URI not found */ /* URI not found */
transmit_response(p, "404 Not found", &p->initreq); transmit_response(p, "404 Not found", &p->initreq);
/* Set res back to -2 because we don't want to return an invalid domain message. That check already happened up above. */ }
res = -2; break;
default:
break; break;
} }
if (option_debug > 1) { if (option_debug > 1) {
const char *reason = "";
switch (res) {
case AUTH_SECRET_FAILED:
reason = "Bad password";
break;
case AUTH_USERNAME_MISMATCH:
reason = "Bad digest user";
break;
case AUTH_NOT_FOUND:
reason = "Peer not found";
break;
default:
break;
}
ast_log(LOG_DEBUG, "SIP REGISTER attempt failed for %s : %s\n", ast_log(LOG_DEBUG, "SIP REGISTER attempt failed for %s : %s\n",
peer->name, peer->name, reason);
(res == -1) ? "Bad password" : ((res == -2 ) ? "Bad digest user" : "Peer not found"));
} }
} }
if (peer) if (peer)
@ -7455,10 +7491,11 @@ static int get_rpid_num(const char *input, char *output, int maxlen)
/*! \brief Check if matching user or peer is defined /*! \brief Check if matching user or peer is defined
Match user on From: user name and peer on IP/port Match user on From: user name and peer on IP/port
This is used on first invite (not re-invites) and subscribe requests This is used on first invite (not re-invites) and subscribe requests
\return 0 on success, -1 on failure, and 1 on challenge sent \return 0 on success, non-zero on failure
-2 on authentication error from chedck_auth()
*/ */
static int check_user_full(struct sip_pvt *p, struct sip_request *req, int sipmethod, char *uri, enum xmittype reliable, struct sockaddr_in *sin, struct sip_peer **authpeer) static enum check_auth_result check_user_full(struct sip_pvt *p, struct sip_request *req,
int sipmethod, char *uri, enum xmittype reliable,
struct sockaddr_in *sin, struct sip_peer **authpeer)
{ {
struct sip_user *user = NULL; struct sip_user *user = NULL;
struct sip_peer *peer; struct sip_peer *peer;
@ -7467,7 +7504,7 @@ static int check_user_full(struct sip_pvt *p, struct sip_request *req, int sipme
char rpid_num[50]; char rpid_num[50];
const char *rpid; const char *rpid;
char iabuf[INET_ADDRSTRLEN]; char iabuf[INET_ADDRSTRLEN];
int res = 0; enum check_auth_result res = AUTH_SUCCESSFUL;
char *t; char *t;
char calleridname[50]; char calleridname[50];
int debug=sip_debug_test_addr(sin); int debug=sip_debug_test_addr(sin);
@ -7523,7 +7560,7 @@ static int check_user_full(struct sip_pvt *p, struct sip_request *req, int sipme
ast_string_field_set(p, cid_num, tmp); ast_string_field_set(p, cid_num, tmp);
} }
if (ast_strlen_zero(of)) if (ast_strlen_zero(of))
return 0; return AUTH_SUCCESSFUL;
if (!authpeer) /* If we are looking for a peer, don't check the user objects (or realtime) */ if (!authpeer) /* If we are looking for a peer, don't check the user objects (or realtime) */
user = find_user(of, 1); user = find_user(of, 1);
@ -7551,7 +7588,6 @@ static int check_user_full(struct sip_pvt *p, struct sip_request *req, int sipme
ast_string_field_set(p, cid_num, tmp); ast_string_field_set(p, cid_num, tmp);
} }
usenatroute = ast_test_flag(&p->flags[0], SIP_NAT_ROUTE); usenatroute = ast_test_flag(&p->flags[0], SIP_NAT_ROUTE);
if (p->rtp) { if (p->rtp) {
@ -7742,8 +7778,12 @@ static int check_user_full(struct sip_pvt *p, struct sip_request *req, int sipme
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)); 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? */ /* do we allow guests? */
if (!global_allowguest) if (!global_allowguest) {
res = -1; /* we don't want any guests, authentication will fail */ 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 */
}
} }
} }
@ -8789,6 +8829,7 @@ static int sip_show_settings(int fd, int argc, char *argv[])
ast_cli(fd, " URI user is phone no: %s\n", ast_test_flag(&global_flags[0], SIP_USEREQPHONE) ? "Yes" : "No"); ast_cli(fd, " URI user is phone no: %s\n", ast_test_flag(&global_flags[0], SIP_USEREQPHONE) ? "Yes" : "No");
ast_cli(fd, " Our auth realm %s\n", global_realm); ast_cli(fd, " Our auth realm %s\n", global_realm);
ast_cli(fd, " Realm. auth: %s\n", authl ? "Yes": "No"); ast_cli(fd, " Realm. auth: %s\n", authl ? "Yes": "No");
ast_cli(fd, " Always auth rejects: %s\n", global_alwaysauthreject ? "Yes" : "No");
ast_cli(fd, " User Agent: %s\n", global_useragent); ast_cli(fd, " User Agent: %s\n", global_useragent);
ast_cli(fd, " MWI checking interval: %d secs\n", global_mwitime); ast_cli(fd, " MWI checking interval: %d secs\n", global_mwitime);
ast_cli(fd, " Reg. context: %s\n", S_OR(global_regcontext, "(not set)")); ast_cli(fd, " Reg. context: %s\n", S_OR(global_regcontext, "(not set)"));
@ -11248,11 +11289,16 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
/* Handle authentication if this is our first invite */ /* Handle authentication if this is our first invite */
res = check_user(p, req, SIP_INVITE, e, XMIT_RELIABLE, sin); res = check_user(p, req, SIP_INVITE, e, XMIT_RELIABLE, sin);
if (res > 0) /* We have challenged the user for auth */ if (res == AUTH_CHALLENGE_SENT)
return 0; return 0;
if (res < 0) { /* Something failed in authentication */ if (res < 0) { /* Something failed in authentication */
if (res == AUTH_FAKE_AUTH) {
ast_log(LOG_NOTICE, "Sending fake auth rejection for user %s\n", get_header(req, "From"));
transmit_fake_auth_response(p, req, 1);
} else {
ast_log(LOG_NOTICE, "Failed to authenticate user %s\n", get_header(req, "From")); ast_log(LOG_NOTICE, "Failed to authenticate user %s\n", get_header(req, "From"));
transmit_response_reliable(p, "403 Forbidden", req); transmit_response_reliable(p, "403 Forbidden", req);
}
ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
ast_string_field_free(p, theirtag); ast_string_field_free(p, theirtag);
return 0; return 0;
@ -11678,11 +11724,18 @@ static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req,
/* Handle authentication if this is our first subscribe */ /* Handle authentication if this is our first subscribe */
res = check_user_full(p, req, SIP_SUBSCRIBE, e, 0, sin, &authpeer); res = check_user_full(p, req, SIP_SUBSCRIBE, e, 0, sin, &authpeer);
if (res) { /* if an authentication response was sent, we are done here */
if (res == AUTH_CHALLENGE_SENT)
return 0;
if (res < 0) { if (res < 0) {
if (res == AUTH_FAKE_AUTH) {
ast_log(LOG_NOTICE, "Sending fake auth rejection for user %s\n", get_header(req, "From"));
transmit_fake_auth_response(p, req, 1);
} else {
ast_log(LOG_NOTICE, "Failed to authenticate user %s for SUBSCRIBE\n", get_header(req, "From")); ast_log(LOG_NOTICE, "Failed to authenticate user %s for SUBSCRIBE\n", get_header(req, "From"));
ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); transmit_response_reliable(p, "403 Forbidden", req);
} }
ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
return 0; return 0;
} }
@ -11856,7 +11909,7 @@ static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req,
/*! \brief Handle incoming REGISTER request */ /*! \brief Handle incoming REGISTER request */
static int handle_request_register(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, char *e) static int handle_request_register(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, char *e)
{ {
int res = 0; enum check_auth_result res;
char iabuf[INET_ADDRSTRLEN]; char iabuf[INET_ADDRSTRLEN];
/* Use this as the basis */ /* Use this as the basis */
@ -11864,12 +11917,33 @@ static int handle_request_register(struct sip_pvt *p, struct sip_request *req, s
ast_verbose("Using latest REGISTER request as basis request\n"); ast_verbose("Using latest REGISTER request as basis request\n");
copy_request(&p->initreq, req); copy_request(&p->initreq, req);
check_via(p, req); check_via(p, req);
if ((res = register_verify(p, sin, req, e)) < 0) if ((res = register_verify(p, sin, req, e)) < 0) {
ast_log(LOG_NOTICE, "Registration from '%s' failed for '%s' - %s\n", get_header(req, "To"), ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr), (res == -1) ? "Wrong password" : (res == -2 ? "Username/auth name mismatch" : "Not a local SIP domain")); const char *reason = "";
switch (res) {
case AUTH_SECRET_FAILED:
reason = "Wrong password";
break;
case AUTH_USERNAME_MISMATCH:
reason = "Username/auth name mismatch";
break;
case AUTH_NOT_FOUND:
reason = "No matching peer found";
break;
case AUTH_UNKNOWN_DOMAIN:
reason = "Not a local domain";
break;
default:
break;
}
ast_log(LOG_NOTICE, "Registration from '%s' failed for '%s' - %s\n",
get_header(req, "To"), ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr),
reason);
}
if (res < 1) { if (res < 1) {
/* Destroy the session, but keep us around for just a bit in case they don't /* Destroy the session, but keep us around for just a bit in case they don't
get our 200 OK */ get our 200 OK */
sip_scheddestroy(p, 15*1000); sip_scheddestroy(p, 15000);
} }
return res; return res;
} }
@ -13392,6 +13466,7 @@ static int reload_config(enum channelreloadreason reason)
global_regcontext[0] = '\0'; global_regcontext[0] = '\0';
expiry = DEFAULT_EXPIRY; expiry = DEFAULT_EXPIRY;
global_notifyringing = DEFAULT_NOTIFYRINGING; global_notifyringing = DEFAULT_NOTIFYRINGING;
global_alwaysauthreject = 0;
global_allowsubscribe = FALSE; global_allowsubscribe = FALSE;
ast_copy_string(global_useragent, DEFAULT_USERAGENT, sizeof(global_useragent)); ast_copy_string(global_useragent, DEFAULT_USERAGENT, sizeof(global_useragent));
ast_copy_string(default_notifymime, DEFAULT_NOTIFYMIME, sizeof(default_notifymime)); ast_copy_string(default_notifymime, DEFAULT_NOTIFYMIME, sizeof(default_notifymime));
@ -13503,6 +13578,8 @@ static int reload_config(enum channelreloadreason reason)
ast_copy_string(default_notifymime, v->value, sizeof(default_notifymime)); ast_copy_string(default_notifymime, v->value, sizeof(default_notifymime));
} else if (!strcasecmp(v->name, "notifyringing")) { } else if (!strcasecmp(v->name, "notifyringing")) {
global_notifyringing = ast_true(v->value); global_notifyringing = ast_true(v->value);
} else if (!strcasecmp(v->name, "alwaysauthreject")) {
global_alwaysauthreject = ast_true(v->value);
} else if (!strcasecmp(v->name, "musicclass") || !strcasecmp(v->name, "musiconhold")) { } else if (!strcasecmp(v->name, "musicclass") || !strcasecmp(v->name, "musiconhold")) {
ast_copy_string(default_musicclass, v->value, sizeof(default_musicclass)); ast_copy_string(default_musicclass, v->value, sizeof(default_musicclass));
} else if (!strcasecmp(v->name, "language")) { } else if (!strcasecmp(v->name, "language")) {

@ -136,6 +136,10 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
; Useful to limit subscriptions to local extensions ; Useful to limit subscriptions to local extensions
; Settable per peer/user also ; Settable per peer/user also
;notifyringing = yes ; Notify subscriptions on RINGING state ;notifyringing = yes ; Notify subscriptions on RINGING state
;alwaysauthreject = yes ; When an incoming INVITE or REGISTER is to be rejected,
; for any reason, always reject with '401 Unauthorized'
; instead of letting the requester know whether there was
; a matching user or peer for their request
; ;
; If regcontext is specified, Asterisk will dynamically create and destroy a ; If regcontext is specified, Asterisk will dynamically create and destroy a
; NoOp priority 1 extension for a given peer who registers or unregisters with ; NoOp priority 1 extension for a given peer who registers or unregisters with

Loading…
Cancel
Save