@ -1809,6 +1809,7 @@ struct sip_pvt {
struct ast_variable * notify_headers ; /*!< Custom notify type */
struct ast_variable * notify_headers ; /*!< Custom notify type */
struct sip_auth * peerauth ; /*!< Realm authentication */
struct sip_auth * peerauth ; /*!< Realm authentication */
int noncecount ; /*!< Nonce-count */
int noncecount ; /*!< Nonce-count */
unsigned int stalenonce : 1 ; /*!< Marks the current nonce as responded too */
char lastmsg [ 256 ] ; /*!< Last Message sent/received */
char lastmsg [ 256 ] ; /*!< Last Message sent/received */
int amaflags ; /*!< AMA Flags */
int amaflags ; /*!< AMA Flags */
int pendinginvite ; /*!< Any pending INVITE or state NOTIFY (in subscribe pvt's) ? (seqno of this) */
int pendinginvite ; /*!< Any pending INVITE or state NOTIFY (in subscribe pvt's) ? (seqno of this) */
@ -12505,6 +12506,20 @@ static void build_route(struct sip_pvt *p, struct sip_request *req, int backward
list_route ( p - > route ) ;
list_route ( p - > route ) ;
}
}
/*! \brief builds the sip_pvt's randdata field which is used for the nonce
* challenge . When forceupdate is not set , the nonce is only updated if
* the current one is stale . In this case , a stalenonce is one which
* has already received a response , if a nonce has not received a response
* it is not always necessary or beneficial to create a new one . */
static void set_nonce_randdata ( struct sip_pvt * p , int forceupdate )
{
if ( p - > stalenonce | | forceupdate | | ast_strlen_zero ( p - > randdata ) ) {
ast_string_field_build ( p , randdata , " %08lx " , ast_random ( ) ) ; /* Create nonce for challenge */
p - > stalenonce = 0 ;
}
}
AST_THREADSTORAGE ( check_auth_buf ) ;
AST_THREADSTORAGE ( check_auth_buf ) ;
# define CHECK_AUTH_BUF_INITLEN 256
# define CHECK_AUTH_BUF_INITLEN 256
@ -12570,7 +12585,7 @@ static enum check_auth_result check_auth(struct sip_pvt *p, struct sip_request *
return AUTH_CHALLENGE_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 */
set_nonce_randdata( p , 1 ) ; /* 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 , DEFAULT_TRANS_TIMEOUT ) ;
sip_scheddestroy ( p , DEFAULT_TRANS_TIMEOUT ) ;
@ -12621,10 +12636,13 @@ static enum check_auth_result check_auth(struct sip_pvt *p, struct sip_request *
return AUTH_USERNAME_MISMATCH ;
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, and the nonce has not already been responded to.
if ( strcasecmp ( p - > randdata , keys [ K_NONCE ] . s ) ) { /* XXX it was 'n'casecmp ? */
* If this check fails , send 401 with new nonce */
if ( strcasecmp ( p - > randdata , keys [ K_NONCE ] . s ) | | p - > stalenonce ) { /* XXX it was 'n'casecmp ? */
wrongnonce = TRUE ;
wrongnonce = TRUE ;
usednonce = keys [ K_NONCE ] . s ;
usednonce = keys [ K_NONCE ] . s ;
} else {
p - > stalenonce = 1 ; /* now, since the nonce has a response, mark it as stale so it can't be sent or responded to again */
}
}
if ( ! ast_strlen_zero ( md5secret ) )
if ( ! ast_strlen_zero ( md5secret ) )
@ -12655,14 +12673,14 @@ static enum check_auth_result check_auth(struct sip_pvt *p, struct sip_request *
if ( sipdebug )
if ( sipdebug )
ast_log ( LOG_NOTICE , " Correct auth, but based on stale nonce received from '%s' \n " , get_header ( req , " To " ) ) ;
ast_log ( LOG_NOTICE , " Correct auth, but based on stale nonce received from '%s' \n " , get_header ( req , " To " ) ) ;
/* We got working auth token, based on stale nonce . */
/* We got working auth token, based on stale nonce . */
ast_string_field_build( p , randdata , " %08lx " , ast_random ( ) ) ;
set_nonce_randdata( p , 0 ) ;
transmit_response_with_auth ( p , response , req , p - > randdata , reliable , respheader , TRUE ) ;
transmit_response_with_auth ( p , response , req , p - > randdata , reliable , respheader , TRUE ) ;
} else {
} else {
/* Everything was wrong, so give the device one more try with a new challenge */
/* Everything was wrong, so give the device one more try with a new challenge */
if ( ! req - > ignore ) {
if ( ! req - > ignore ) {
if ( sipdebug )
if ( sipdebug )
ast_log ( LOG_NOTICE , " Bad authentication received from '%s' \n " , get_header ( req , " To " ) ) ;
ast_log ( LOG_NOTICE , " Bad authentication received from '%s' \n " , get_header ( req , " To " ) ) ;
ast_string_field_build( p , randdata , " %08lx " , ast_random ( ) ) ;
set_nonce_randdata( p , 1 ) ;
} else {
} else {
if ( sipdebug )
if ( sipdebug )
ast_log ( LOG_NOTICE , " Duplicate authentication received from '%s' \n " , get_header ( req , " To " ) ) ;
ast_log ( LOG_NOTICE , " Duplicate authentication received from '%s' \n " , get_header ( req , " To " ) ) ;
@ -12795,7 +12813,7 @@ static void transmit_fake_auth_response(struct sip_pvt *p, int sipmethod, struct
return ;
return ;
} 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 */
set_nonce_randdata( p , 1 ) ;
transmit_response_with_auth ( p , response , req , p - > randdata , 0 , respheader , 0 ) ;
transmit_response_with_auth ( p , response , req , p - > randdata , 0 , respheader , 0 ) ;
/* Schedule auto destroy in 32 seconds */
/* Schedule auto destroy in 32 seconds */
sip_scheddestroy ( p , DEFAULT_TRANS_TIMEOUT ) ;
sip_scheddestroy ( p , DEFAULT_TRANS_TIMEOUT ) ;
@ -12840,7 +12858,7 @@ static void transmit_fake_auth_response(struct sip_pvt *p, int sipmethod, struct
/* 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 */
if ( strcasecmp ( p - > randdata , keys [ K_NONCE ] . s ) ) {
if ( strcasecmp ( p - > randdata , keys [ K_NONCE ] . s ) ) {
if ( ! req - > ignore ) {
if ( ! req - > ignore ) {
ast_string_field_build( p , randdata , " %08lx " , ast_random ( ) ) ;
set_nonce_randdata( p , 1 ) ;
}
}
transmit_response_with_auth ( p , response , req , p - > randdata , reliable , respheader , FALSE ) ;
transmit_response_with_auth ( p , response , req , p - > randdata , reliable , respheader , FALSE ) ;