Hi,
I added AKA SQN sync failure support to SIPp. I introduced a new
authentication parameter: aka_SQN=<SQN number in hexadecimal format
(0x[0-9A-Fa-f]{12})>.
Aka_SQN specifies the initial SQN value of SIPp. If SQN that had been
sent by HE was less that this, then SIPp would response sqn sync failure
message (corresponding auts parameter appears in Authorization header).
SIPp scenario example:
REGISTER sip:[domain] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];rport
From: [user] <sip:[EMAIL PROTECTED]>;tag=[call_id]
To: [user] <sip:[EMAIL PROTECTED]>
...
[authentication username="[EMAIL PROTECTED]"
aka_K=0x6c38a116ac280c454f59332ee35c8c4f
aka_OP=0x63bfa50ee6523365ff14c1f45f88737d aka_SQN=0x63bfa50ee652]
Example for SIP sync failure response message:
REGISTER sip:domain.com SIP/2.0
Via: SIP/2.0/UDP 127.0.0.1:5098;rport
...
Authorization: Digest username="[EMAIL PROTECTED]",...
response="d60f3655a7ada3e6b88b46d6d400889e",algorithm=AKAv1-MD5,auts="3KOC52grnTPNEPwruko="
The patch should be applied to sipp trunk, revision 424.
Cheers,
Gergo
--
Gergely Kovacs
http://www.iptel.org/~gergo
Index: auth.c
===================================================================
--- auth.c (revision 424)
+++ auth.c (working copy)
@@ -82,6 +82,7 @@
int createAuthHeaderAKAv1MD5(char * user, char * OP,
char * AMF,
char * K,
+ char * SQN,
char * method,
char * uri, char * msgbody, char * auth, char
*algo,
char * result);
@@ -142,6 +143,7 @@
char * aka_OP,
char * aka_AMF,
char * aka_K,
+ char * aka_SQN,
char * result) {
char algo[32]="MD5";
@@ -167,6 +169,7 @@
return createAuthHeaderAKAv1MD5(user, aka_OP,
aka_AMF,
aka_K,
+ aka_SQN,
method,uri,msgbody,auth,algo,result);
}else{
sprintf(result, "createAuthHeader: authentication must use MD5 or
AKAv1-MD5");
@@ -494,13 +497,14 @@
int createAuthHeaderAKAv1MD5(char * user, char * aka_OP,
char * aka_AMF,
char * aka_K,
+ char * aka_SQN,
char * method,
char * uri, char * msgbody, char * auth, char *algo,
char * result) {
char tmp[MAX_HEADER_LEN];
char *start, *end;
- int has_auts = 0, resuf = 1;
+ int has_auts = 0, resuf = 1, need2resync = 0;
char *nonce64, *nonce;
int noncelen;
RESHEX resp_hex;
@@ -565,13 +569,19 @@
/* the condition below is wrong.
* Should trigger synchronization when sqn_ms>>3!=sqn_he>>3 for example.
* Also, we need to store the SQN per user or put it as auth parameter. */
- if (1/*sqn[5] > sqn_he[5]*/) {
+ for (i=0; i < SQNLEN; i++)
+ if (sqn[i] < aka_SQN[i]) {
+ need2resync = 1;
+ break;
+ }
+
+ if (!need2resync) {
sqn_he[5] = sqn[5];
has_auts = 0;
/* RES has to be used as password to compute response */
resuf = createAuthHeaderMD5(user, (char *) res, RESLEN, method, uri,
msgbody, auth, algo, result);
} else {
- sqn_ms[5] = sqn_he[5] + 1;
+ memcpy(sqn_ms, aka_SQN, SQNLEN);
f5star(k, rnd, ak, op);
for(i=0; i<SQNLEN; i++)
auts_bin[i]=sqn_ms[i]^ak[i];
@@ -583,13 +593,13 @@
}
if (has_auts) {
/* Format data for output in the SIP message */
- for(i=0;i<AUTSLEN;i++){
- auts_hex[2*i]=hexa[(auts_bin[i]&0xF0)>>4];
- auts_hex[2*i+1]=hexa[auts_bin[i]&0x0F];
- }
- auts_hex[AUTS64LEN-1]=0;
- sprintf(result, "%s,auts=\"%s\"",result,auts_hex);
+ /* (rfc 3310 section 3.4 says AUTS should be BASE64 encoded) */
+ start = base64_encode_string(auts_bin, AUTSLEN, &noncelen);
+ start[noncelen]=0;
+
+ sprintf(result, "%s,auts=\"%s\"",result,start);
+ free(start);
}
free(nonce);
return 1;
Index: call.cpp
===================================================================
--- call.cpp (revision 424)
+++ call.cpp (working copy)
@@ -2252,15 +2252,17 @@
static char my_aka_OP[MAX_HEADER_LEN + 2];
static char my_aka_AMF[MAX_HEADER_LEN + 2];
static char my_aka_K[MAX_HEADER_LEN + 2];
+ static char my_aka_SQN[MAX_HEADER_LEN + 2];
createSendingMessage(auth_comp->comp_param.auth_param.auth_user, -2,
my_auth_user, sizeof(my_auth_user));
createSendingMessage(auth_comp->comp_param.auth_param.auth_pass, -2,
my_auth_pass, sizeof(my_auth_pass));
createSendingMessage(auth_comp->comp_param.auth_param.aka_K, -2, my_aka_K,
sizeof(my_aka_K));
createSendingMessage(auth_comp->comp_param.auth_param.aka_AMF, -2,
my_aka_AMF, sizeof(my_aka_AMF));
createSendingMessage(auth_comp->comp_param.auth_param.aka_OP, -2,
my_aka_OP, sizeof(my_aka_OP));
+ createSendingMessage(auth_comp->comp_param.auth_param.aka_SQN, -2,
my_aka_SQN, sizeof(my_aka_SQN));
if (createAuthHeader(my_auth_user, my_auth_pass, method, uri, body,
dialog_authentication,
- my_aka_OP, my_aka_AMF, my_aka_K, result + authlen) == 0) {
+ my_aka_OP, my_aka_AMF, my_aka_K, my_aka_SQN, result + authlen) == 0) {
ERROR("%s", result + authlen);
}
authlen = strlen(result);
Index: call.hpp
===================================================================
--- call.hpp (revision 424)
+++ call.hpp (working copy)
@@ -47,9 +47,9 @@
#define SIP_TRANSACTION_TIMEOUT 32000
#ifdef __HPUX
- extern int createAuthHeader(char * user, char * password, char * method,
char * uri, char * msgbody, char * auth, char * aka_OP, char * aka_AMF, char *
aka_K, char * result);
+ extern int createAuthHeader(char * user, char * password, char * method,
char * uri, char * msgbody, char * auth, char * aka_OP, char * aka_AMF, char *
aka_K, char * aka_SQN, char * result);
#else
- extern "C" { extern int createAuthHeader(char * user, char * password, char
* method, char * uri, char * msgbody, char * auth, char * aka_OP, char *
aka_AMF, char * aka_K, char * result); }
+ extern "C" { extern int createAuthHeader(char * user, char * password, char
* method, char * uri, char * msgbody, char * auth, char * aka_OP, char *
aka_AMF, char * aka_K, char * aka_SQN, char * result); }
#endif
class call : virtual public task, virtual public listener, public virtual
socketowner {
Index: message.cpp
===================================================================
--- message.cpp (revision 424)
+++ message.cpp (working copy)
@@ -481,7 +481,7 @@
dst->comp_param.auth_param.auth_user = new SendingMessage(msg_scenario,
my_auth_user, true /* skip sanity */);
dst->comp_param.auth_param.auth_pass = new SendingMessage(msg_scenario,
my_auth_pass, true);
- /* add aka_OP, aka_AMF, aka_K */
+ /* add aka_OP, aka_AMF, aka_K, aka_SQN */
getKeywordParam(keyword, "aka_K=", my_aka);
if (my_aka[0]==0){
memcpy(my_aka,my_auth_pass,16);
@@ -493,6 +493,8 @@
dst->comp_param.auth_param.aka_OP = new SendingMessage(msg_scenario, my_aka,
true);
getKeywordParam(keyword, "aka_AMF=", my_aka);
dst->comp_param.auth_param.aka_AMF = new SendingMessage(msg_scenario,
my_aka, true);
+ getKeywordParam(keyword, "aka_SQN=", my_aka);
+ dst->comp_param.auth_param.aka_SQN = new SendingMessage(msg_scenario,
my_aka, true);
}
void SendingMessage::freeMessageComponent(struct MessageComponent *comp) {
@@ -513,6 +515,9 @@
if (comp->comp_param.auth_param.aka_OP) {
delete comp->comp_param.auth_param.aka_OP;
}
+ if (comp->comp_param.auth_param.aka_SQN) {
+ delete comp->comp_param.auth_param.aka_SQN;
+ }
} else if (comp->type == E_Message_Injection) {
free(comp->comp_param.field_param.filename);
}
Index: message.hpp
===================================================================
--- message.hpp (revision 424)
+++ message.hpp (working copy)
@@ -133,6 +133,7 @@
SendingMessage *aka_OP;
SendingMessage *aka_AMF;
SendingMessage *aka_K;
+ SendingMessage *aka_SQN;
} auth_param;
/* Field Substitution. */
struct {
-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace
_______________________________________________
Sipp-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/sipp-users