@ -317,6 +317,9 @@ enum sip_auth_type {
/*! \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 ,
@ -516,6 +519,7 @@ static int global_alwaysauthreject; /*!< Send 401 Unauthorized for all failing r
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 ;
@ -8852,89 +8856,31 @@ static struct ast_variable *copy_vars(struct ast_variable *src)
return res ;
}
/*! \brief Check if matching user or peer is defined
Match user on From : user name and peer on IP / port
This is used on first invite ( not re - invites ) and subscribe requests
\ return 0 on success , non - zero on failure
*/
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 )
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 )
{
struct sip_user * user = NULL ;
struct sip_peer * peer ;
char from [ 256 ] , * c ;
char * of ;
char rpid_num [ 50 ] ;
const char * rpid ;
enum check_auth_result res ;
char * t ;
char calleridname [ 50 ] ;
struct sip_user * user = find_user ( of , 1 ) ;
int debug = sip_debug_test_addr ( sin ) ;
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 */
if ( pedanticsipchecking )
ast_uri_decode ( from ) ;
/* XXX here tries to map the username for invite things */
memset ( calleridname , 0 , sizeof ( calleridname ) ) ;
get_calleridname ( from , calleridname , sizeof ( calleridname ) ) ;
if ( calleridname [ 0 ] )
ast_string_field_set ( p , cid_name , 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 = uri2 ;
if ( ! strncmp ( t , " sip: " , 4 ) )
t + = 4 ;
ast_string_field_set ( p , exten , t ) ;
t = strchr ( p - > exten , ' @ ' ) ;
if ( t )
* t = ' \0 ' ;
if ( ast_strlen_zero ( p - > our_contact ) )
build_contact ( p ) ;
}
/* save the URI part of the From header */
ast_string_field_set ( p , from , of ) ;
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 , ' @ ' ) ) ) {
char * tmp ;
* c = ' \0 ' ;
if ( ( c = strchr ( of , ' : ' ) ) )
* c = ' \0 ' ;
tmp = ast_strdupa ( of ) ;
if ( ast_is_shrinkable_phonenumber ( tmp ) )
ast_shrink_phone_number ( tmp ) ;
ast_string_field_set ( p , cid_num , tmp ) ;
}
if ( ast_strlen_zero ( of ) )
return AUTH_SUCCESSFUL ;
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 ) ) {
if ( ! authpeer & & debug )
ast_verbose ( " Found user '%s', but fails host access \n " , user - > name ) ;
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 ) ;
user = NULL ;
return AUTH_DONT_KNOW ;
}
if ( user ) {
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 */
@ -9014,15 +8960,20 @@ static enum check_auth_result check_user_full(struct sip_pvt *p, struct sip_requ
p - > vrtp = NULL ;
}
}
if ( debug )
ast_verbose ( " Found user '%s' \n " , user - > name ) ;
ASTOBJ_UNREF ( user , sip_destroy_user ) ;
return res ;
}
}
/* XXX need to reindent the next block */
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 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 ) ;
@ -9035,16 +8986,21 @@ static enum check_auth_result check_user_full(struct sip_pvt *p, struct sip_requ
if ( ! peer ) {
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 ) ) ;
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 ;
}
} else {
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 ;
}
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 ) ;
@ -9138,8 +9094,112 @@ static enum check_auth_result check_user_full(struct sip_pvt *p, struct sip_requ
}
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
This is used on first invite ( not re - invites ) and subscribe requests
\ return 0 on success , non - zero on failure
*/
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 )
{
char from [ 256 ] , * c ;
char * of ;
char rpid_num [ 50 ] ;
const char * rpid ;
enum check_auth_result res ;
char * t ;
char calleridname [ 50 ] ;
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 */
if ( pedanticsipchecking )
ast_uri_decode ( from ) ;
/* XXX here tries to map the username for invite things */
memset ( calleridname , 0 , sizeof ( calleridname ) ) ;
get_calleridname ( from , calleridname , sizeof ( calleridname ) ) ;
if ( calleridname [ 0 ] )
ast_string_field_set ( p , cid_name , 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 = uri2 ;
if ( ! strncmp ( t , " sip: " , 4 ) )
t + = 4 ;
ast_string_field_set ( p , exten , t ) ;
t = strchr ( p - > exten , ' @ ' ) ;
if ( t )
* t = ' \0 ' ;
if ( ast_strlen_zero ( p - > our_contact ) )
build_contact ( p ) ;
}
/* save the URI part of the From header */
ast_string_field_set ( p , from , of ) ;
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 , ' @ ' ) ) ) {
char * tmp ;
* c = ' \0 ' ;
if ( ( c = strchr ( of , ' : ' ) ) )
* c = ' \0 ' ;
tmp = ast_strdupa ( of ) ;
if ( ast_is_shrinkable_phonenumber ( tmp ) )
ast_shrink_phone_number ( tmp ) ;
ast_string_field_set ( p , cid_num , tmp ) ;
}
if ( ast_strlen_zero ( of ) )
return AUTH_SUCCESSFUL ;
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 = 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 ) */
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 ;
@ -10164,6 +10224,7 @@ static int sip_show_settings(int fd, int argc, char *argv[])
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 " ) ;
@ -15994,6 +16055,8 @@ static int reload_config(enum channelreloadreason reason)
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 " ) ) {