直接看最后认证的源代码(sofia_reg.c:sofia_reg_parse_auth):
for_the_sake_of_interop:
if ((input = switch_mprintf("%s:%q", regstr, uri))) {
switch_md5_string(uridigest, (void *) input, strlen(input));
}
if (nc && cnonce && qop) {
input2 = switch_mprintf("%s:%s:%s:%s:%s:%s", a1_hash, nonce, nc, cnonce, qop, uridigest);
} else {
input2 = switch_mprintf("%s:%s:%s", a1_hash, nonce, uridigest);
}
if (input2) {
switch_md5_string(bigdigest, (void *) input2, strlen(input2));
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "input=%s, input2=%s, bigdigest=%s, response=%s\n",
input, input2, bigdigest, response);
if (input2 && !strcasecmp(bigdigest, response)) {
ret = AUTH_OK;
} else {
if ((profile->ndlb & PFLAG_NDLB_BROKEN_AUTH_HASH) && strcasecmp(regstr, "REGISTER") && strcasecmp(regstr, "INVITE")) {
/* some clients send an ACK with the method 'INVITE' in the hash which will break auth so we will
try again with INVITE so we don't get people complaining to us when someone else's client has a bug......
*/
switch_safe_free(input);
switch_safe_free(input2);
regstr = "INVITE";
goto for_the_sake_of_interop;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "ndlb=%u, regstr=%s\n", profile->ndlb, regstr);
ret = AUTH_FORBIDDEN;
}
单看这段代码逻辑很简单,就是比较算出来的bigdigest和sip的response是否一致,如果不一致,认证不通过,回复403。
结和日志和sip消息来看:
REGISTER sip:6500100052@39.108.105.163:5070 SIP/2.0
Max-Forwards: 10
Record-Route: <sip:39.108.105.163:5070;r2=on;lr>
Record-Route: <sip:39.108.105.163:5070;transport=tcp;r2=on;lr>
Via: SIP/2.0/UDP 39.108.105.163:5070;branch=z9hG4bK2545.677ff012.0;i=a44e4143
Via: SIP/2.0/TCP 172.18.41.220:6068;received=39.108.105.163;rport=6068
From: "6500100052"<sip:6500100052@39.108.105.163:5070>;tag=1
To: "6500100052"<sip:6500100052@39.108.105.163:5070>
Call-ID: 1-8508@172.18.41.220
CSeq: 2 REGISTER
Contact: <sip:6500100052@39.108.105.163:6068;transport=TCP>
Allow: INVITE, ACK, BYE, CANCEL, REGISTER
Authorization: Digest username="6500100052",realm="39.108.105.163",cnonce="6b8b4567",nc=00000001,qop=auth,uri="sip:39.108.105.163:5070",nonce="2d6838cb-f905-4ca7-9dc7-074a9e425edd",response="fc2d7c00ba2ee8d62fe528759e4da9fd",algorithm=MD5
Content-Length: 0
Expires: 1800
2020-11-19 18:12:16.532021 [DEBUG:140322046412544] sofia_reg.c:2371 enter sofia_reg_handle_sip_i_register
2020-11-19 18:12:16.532021 [DEBUG:140322046412544] sofia_reg.c:2466 register token, type=0,key=,is_nat=(null),acl_token=(null),private=0x7f9f45baf5f8
2020-11-19 18:12:16.532021 [DEBUG:140322046412544] sofia_reg.c:2873 enter sofia_reg_parse_auth,regstr=REGISTER,np=,response=fc2d7c00ba2ee8d62fe528759e4da9fd, uri=sip:39.108.105.163:5070
2020-11-19 18:12:16.532021 [DEBUG:140322046412544] sofia_reg.c:2905 sofia_reg_parse_auth sql=select nonce,last_nc from sip_authentication where nonce='2d6838cb-f905-4ca7-9dc7-074a9e425edd' and last_nc < 1,ret=1
2020-11-19 18:12:16.532021 [DEBUG:140322046412544] sofia_reg.c:3073 auth_acl=(null),ip=172.18.41.220,ret=1
2020-11-19 18:12:16.532021 [DEBUG:140322046412544] sofia_reg.c:3149 input=(null),a1_hash=ff8fbff2781de9743a03f16d766abe40,ret=1
2020-11-19 18:12:16.532021 [WARNING:140322046412544] sofia_reg.c:3209 input=REGISTER:sip:39.108.105.163:5070, input2=ff8fbff2781de9743a03f16d766abe40:2d6838cb-f905-4ca7-9dc7-074a9e425edd:00000001:6b8b4567:auth:6e2ce047c7d70094ec58f0a4d4b697a3, bigdigest=50f5ad8dd34aa0b1fc7b7a4392776522, response=fc2d7c00ba2ee8d62fe528759e4da9fd
2020-11-19 18:12:16.532021 [WARNING:140322046412544] sofia_reg.c:3225 ndlb=0, regstr=REGISTER
2020-11-19 18:12:16.552025 [WARNING:140322046412544] sofia_reg.c:1763 auth_res=1,stale=0,network_ip=172.18.41.220,uparams=transport=TCP,authorization=0x4084c60,regtype=0,req_method_name=REGISTER,contact_str="6500100052" <sip:6500100052@39.108.105.163:6068;transport=TCP>,key=2d6838cb-f905-4ca7-9dc7-074a9e425edd
md5值计算过程:
bigdigest
=> md5(input2)
=> input2 = switch_mprintf("%s:%s:%s:%s:%s:%s", a1_hash, nonce, nc, cnonce, qop, uridigest);
=> uridigest = md5(input)
=> input = switch_mprintf("%s:%q", regstr, uri)
=> a1_hash = md5(input)
=> input = switch_mprintf("%s:%s:%s", username, realm, passwd);
=> nonce取自sip消息,服务器密码随机数
=> nc取自sip消息,请求计数
=> cnonce取自sip消息,客户端密码随机数
=> qop 取自sip消息,保护质量
实际值代入:
bigdigest
=> md5(input2) = md5('ff8fbff2781de9743a03f16d766abe40:2d6838cb-f905-4ca7-9dc7-074a9e425edd:00000001:6b8b4567:auth:6e2ce047c7d70094ec58f0a4d4b697a3') = 50f5ad8dd34aa0b1fc7b7a4392776522
=> input2 = ff8fbff2781de9743a03f16d766abe40:2d6838cb-f905-4ca7-9dc7-074a9e425edd:00000001:6b8b4567:auth:6e2ce047c7d70094ec58f0a4d4b697a3;
=> uridigest = md5('REGISTER:sip:39.108.105.163:5070') = 6e2ce047c7d70094ec58f0a4d4b697a3
=> input = REGISTER:sip:39.108.105.163:5070
=> a1_hash = ff8fbff2781de9743a03f16d766abe40
=> input = md5('6500100052:39.108.105.163:Q4mu0id20nu4')
=> nonce=2d6838cb-f905-4ca7-9dc7-074a9e425edd
=> nc=00000001
=> cnonce=6b8b4567
=> qop=auth
密码来自于user.xml
<?xml version="1.0"?>
<user id="6500100052" domain-name="akuvox-freeswitch.com">
<profile-variables></profile-variables>
<params>
<param name="dial-string" value="{presence_id=${dialed_user}@${dialed_domain}}${sofia_contact(${dialed_user}@${dialed_domain})}"></param>
<param name="password" value="Q4mu0id20nu4"></param>
<param name="vm-password" value="Q4mu0id20nu4"></param>
</params>
<variables>
<variable name="toll_allow" value="domestic,international,local"></variable>
<variable name="accountcode" value="6500100052"></variable>
<variable name="user_context" value="default"></variable>
<variable name="directory-visible" value="true"></variable>
<variable name="directory-exten-visible" value="true"></variable>
<variable name="limit_max" value="15"></variable>
<variable name="effective_caller_id_name" value="6500100052"></variable>
<variable name="effective_caller_id_number" value="6500100052"></variable>
<variable name="outbound_caller_id_name" value="${outbound_caller_name}"></variable>
<variable name="outbound_caller_id_number" value="${outbound_caller_id}"></variable>
<variable name="callgroup" value="techsupport"></variable>
<variable name="sip-force-contact" value="NDLB-connectile-dysfunction-2.0"></variable>
</variables>
</user>
这个xml文件是通过Lua生成的。
同理proxy认证过程类似。
同理proxy认证过程类似。