使用HTTP认证

来源:互联网 发布:课件下载软件 编辑:程序博客网 时间:2024/06/07 22:36

SIP为认证系统提供了一个无状态的,试错机制,这个认证机制是基于HTTP认证机制的。任何时候proxy服务器或者UA接收到一个请求(1节例外),它尝试检查请求发起者提供的身份确认。当发起方,身份确认了,请求的接受方应当确认这个用户,是否式通过认证的。在本文档中,没有建议或者讨论认证系统。

 

本节描述的Digest认证机制,只提供了消息认证和复查保护,没有提供消息完整性或者机密性的保证。上述的保护级别和基于这些Digest提供的保护,可以防止SIP攻击者改变SIP请求和应答。

 

注意由于这个脆弱的安全性,我们不赞成Basic(基本的)认证方法。服务器必须不能接收验证方法式Basic类型的信任书,并且服务器必须拒绝Basic。这是和RFC2543的改变。

 

1.   框架

SIP认证的框架和HTTP非常接近(RFC2617)。特别是auth-scheme的BNF范式,auth-param、challenge、realm、realm-value以及信任书都是一样的(虽然对Basic认证方案是不允许的)。在SIP的UAS使用401(Unauthorized)应答来拒绝UAC的身份(或者讲是考验UAC的身份,如果不通过,就是401)。另外,注册服务器,转发服务器可以使用401(Unauthorized)来应答身份认证,但是proxy必须不能用401,只能用407(Proxy AuthenticationRequired)应答。对于Proxy-Authenticate的包含要求,Proxy-Authroization、WWW-Authenticate和Authorization在不同的消息中是相同的,如同在RFC2617中讲述的一样。

 

由于SIP并没有一个规范的root URL的概念,所以,需要保护的空间的概念在SIP中的解释也不一样。realm字串单独定义被保护的区域。这个是和RFC2543的改变,在2543中Request-URI和realm一起定义了被保护的区域。

 

这个先前定义的被保护的区域会导致一定程度的混乱,因为Request-URI是UAC发送的,并且接收到Request-URI的认证服务器可能是不同的,并且真正的最终的Request-URI的格式可能对UAC并不知道。同样,早先的定义依赖于一个Request-URI中的SIP URI,并且看起来不允许其他的URI 方案(比如tel URL)需要鉴别接收到的请求的UA使用者或者proxy服务器,必须根据下边的指导来为他们的服务器创建一个realm字串。

 

Ø  Realm字串必须是全局唯一的。我们强调这个realm字串必须包含一个主机名或者域名。 

Ø  Realm字串应当是一个可读的能够展示给用户的字串。

例如:

INVITE sip:bob@biloxi.com SIP/2.0

Authorization: Digest realm=”biloxi.com”,<…>

通常,SIP认证对于特定realm(一个保护区域)是有意义的。因此,对于Digest认证来说,每一个类似的保护区域都有自己的用户名和密码集合。如果服务器对特定请求没有要求认证,那么它可以接收缺省的用户名anonymous,并且这个用户名没有密码(密码是””)。类似的,代表多个用户的UAC,比如PSTN网关,可以有他们自己的设备相关的用户名和密码,而不是每一个用户名和一个密码(这就是说,比如网关,有一个网关的用户和密码,而不是说通过网关的每一个实际用户和密码)。

 

当服务器可以正确处理绝大部分SIP请求,有本文档约定了两类请求要求特别的认证处理:ACK和CANCEL。在某一个认证方案下,并且这个认证方案是使用应答来放置计算nonces(比如Digest),那么对于某些没有应答的情况,就会出现问题,比如ACK。所以,基于这个原因,一个服务器接受在INVITE请求中的信任书,也必须同样接收对应ACK的信任书。UAC通过赋值所有的INVITE请求中的Authorization和Proxy-Authorization头域值来创建一个相关的ACK消息。服务器必须接收这个ACK请求。

 

虽然CANCEL方法具有应答(2xx),服务器必须不能拒绝CANCEL请求,因为这些请求不能被重新提交。通常,如果CANCEL请求和被CANCEL的请求来自同一个节点,服务器应当接收CANCEL请求。

 

当UAC接收到验证拒绝,并且UAC设备并不知道realm验证失败的具体原因,它必须展示给用户,验证失败的realm参数内容(既可以在WWW-Authenticate头域或者Proxy-Authenticate头域)。对于给自己的realm预先配置信任状的UA服务提供商来说,应当注意到这样一点:当被一个预先配置信任状的设备拒绝的时候,用户不会有机会在这个realm中展示他们自己的信任状。

 

最后,注意即使一个UAC能够定位与相关realm匹配的信任书,也有可能存在这个信任书可能不在有效,或者某个服务器会用什么原因不接受这个信任书(特别是当提供的是没有口令的anonymous用户时)。在这种情况下,服务器可能会继续拒绝,或者返回一个403 Forbidden。UAC必须不能再次使用刚才被拒绝的信任书进行尝试(如果当前环境没有改变,那么请求可以再次尝试)。

 

2.   用户到用户的认证

当UAS收到一个UAC发起的请求,UAS在请求被处理之前进行身份认证。如果请求中没有信任书(在Authorization头域),UAS可以使用401(Unauthorized)拒绝认证,并且让客户端提供一个认证书。

 

WWW-Authenticate应答头域必须在401(Unauthorized)应答消息中出现。这个头域值包含了至少一个表明认证方式和适用realm的参数的拒绝原因。

 

在401中的WWW-Authenticate头域例子:

WWW-Authenticate:Digest,

realm=”biloxi.com”,

qop=”auth,auth-int”,

nonce=”dcd98b7102dd2f0e8b11d0f600bfb0c093",

opaque="5ccc069c403ebaf9f0171e9517f40e41"

 

当原始请求的UAC接收到这个401(Unauthorized)应答的时候,如果可能的话,他应当重新组织这个请求,并且填写正确的信任书。在继续处理之前,UAC可以要求原始用户输入信任书。一旦信任书(不管是用户输入的,还是内部密钥)提供了,UA应当把这个给特定To头域和realm字段的信任书cache起来,以备给这个地址下一个请求时候使用。UA可以用任何方式来cache这个信任书。

 

如果没有找到对应realm的信任书,UAC应当尝试用用户anonymous和空口令来重新尝试这个请求。

 

一旦找到了一个信任书,那么UA应当要求在UAS或者注册服务器上认证自己,这是通常的情况,但是并非一定要求的,在接收到一个401(Unauthorized)应答后-可以在请求中增加一个Authorization头域然后再认证。Authorization头域包含了具有这个UA到请求的资源所在的realm(区域)的信任书和所需要的认证支持的参数和重现保护的参数。

 

Authorization头域例子:

Authorization: Digest username=”bob”,

      realm=”biloxi.com”,

      nonce=”dcd98b7102dd2f0e8b11d0f600bfb0c093",

      uri=”sip:bob@biloxi.com”,

qop=auth,

nc=00000001,

       cnonce=”0a4f113b”,

      response=”6629fae49393a05397450978507c4ef1",

      opaque=”5ccc069c403ebaf9f0171e9517f40e41"

 

当UAC在接收到401(Unauthorized)或者407(ProxyAuthenticationRequired)应答之后,重新用它的信任书来提交请求,它必须增加Cseq头域的值,就像发送一个正常的新请求一样。

 

3.   Proxy到用户的认证

类似的,当UAC发送一个请求到proxy服务器,proxy服务器可以在处理请求之前,验证原始请求的认证。如果请求中没有信任书(在Proxy-Authorization头域),proxy可以用407(Proxy AuthenticationRequired)拒绝这个原始请求,并且要求客户端提供适当的信任书。proxy必须在407(ProxyAuthenticationRequired)应答中增加一个Proxy-Authenticate头域,并且在这个头域中给出适用于本proxy的认证资源。

 

对于Proxy-Authenticate和Proxy-Authorization描述,两者有一个不同。Proxy不能在Proxy-Authorization头域中增加值。所有的407(ProxyAuthenticationRequired)应答必须转发到上行队列,遵循发送应答的步骤发送到UAC。UAC负责在Proxy-Authorization头域的值中增加适用于这个proxy要求认证,这个proxy的realm的信任书。

 

如果proxy要求UAC在请求中增加Proxy-Authorization头域并且重新提交请求,那么UAC应当增加Cseq头域的值,就像一个新请求一样。不过,这样就导致提交原始请求的UAC需要忽略UAS的应答,因为Cseq的值可能是不一样的。

 

当原始请求的UAC接收到一个407(Proxy AuthenticationRequired)的时候,如果可能,它应当使用正确的信任书重新组织请求。它应当和对前边讲述的401应答的处理步骤一样显示和处理realm参数。

 

如果没有找到对应realm的信任书,那么UAC应当尝试用用户anonymous和空口令重新尝试请求。

 

UAC也应当cache这个在重新发送请求中的信任书。

 

我们建议使用下列步骤来cache一个proxy的信任书:

 

如果UA在给特定Call-ID的请求的401/407应答中,接收到一个Proxy-Authenticate头域,它应当合并对这个realm的信任书,并且为以后具有相同Call-ID的请求发送这个信任书。这些信任书必须在对话中被cache住;不过如果UA配置的是它自己的本地外发proxy,那么如果出现要求认证的情况,那么UA应当cache住跨对话的信任书。注意,这个意味着在一个对话中的请求可以包含在Route头域中所经过proxy都不需要的信任书。

 

任何希望在proxy服务器上认证的UA――通常,但是并非必须,在接收到407(Proxy AuthenticationRequired)应答之后――可以在请求中增加一个Proxy-Authorization头域然后再次尝试。Proxy-Authorization请求头域允许客户端像proxy来证明自己(或者使用者)的身份。Proxy-Authorization头域包含了UA提供给proxy和/或者请求资源所在的realm的身份认证信息的信任书。

 

一个Proxy-Authorization头域值只提供给指定proxy验证的,这个proxy的realm是在realm参数中指明的(这个proxy可以事先通过Proxy-Authenticat头域提出认证要求)。当多个proxy组成一个链路的时候,如果proxy的realm和请求中的Proxy-Authorization头域的realm参数不匹配,那么这个proxy就不能使用本Proxy-Authorization头域值来验证。

 

注意,如果一个认证机制不支持Proxy-Authorization头域的realm,porxy服务器必须尝试分析所有的Proxy-Authorization头域值来决定是否其中之一有这个proxy认为合适的信任书。因为这个方法在大型网络上很耗时间,proxy服务器应当使用一个一个支持Proxy-Authorization头域的realm的认证方案。

 

如果一个请求被分支,可能对同一个UAC有不同的proxy服务器和/或者UA希望要求认证。在这种情况下,分支的proxy服务器有责任把这些被拒绝的认证合并成为一个应答。每一个分支请求的应答中接收到WWW-Authenticate和Proxy-Authenticate头域值必须由这个分支proxy放置在同一个应答中发送给UA;这些头域值的顺序并没有影响。

 

当proxy服务器给一个请求发出拒绝认证的应答,在UAC用正确的信任书重新发请求过来之前,不会转发这个请求。分支proxy可以同时向多个要求认证的proxy服务器转发请求。每一个proxy在没有接收到UAC在他们各自的realm的认证之前,都不会转发这个请求。如果UAC没有给这些失败的验证提供信任书,那些发出拒绝通过认证的proxy是不会把请求转发给UA的目标用户的,因此,分支的优点就少了很多。

 

当针对包含多个拒绝认证的401(Unauthorized)或者407(ProxyAuthentication Required)应答重新提交请求时,UAC应当对每一个WWW-Authenticate和Proxy-Authorization头域值提供一个信任书。根据上边的说明,一个请求的多个认证书应当用realm参数分开。

 

不过,在同一个401(Unauthorized)或者407(Proxy AuthenticationRequired)应答中,可能包含对同一个realm的多个验证拒绝。例如,当在相同域的多个proxy,使用共同的realm,接收到了一个分支请求,并且认证拒绝了的时候,就会有这样的情况。当UAC重新尝试这个请求的时候,UAC因此会提供多个Authorization或者Proxy-Authorization头域,包含相同的”realm”参数。并且对于同一个realm,应当有相同的信任书。

 

4.   Digest认证方案

描述了对HTTP Digest 认证方案的SIP修改和简化。SIP使用了和HTTP[17]几乎完全一样的方案。

 

由于RFC 2543是基于RFC2069[39]定义的HTTP Digest的,支持RFC2617的SIP服务器也必须确保他们和RFC2069兼容。RFC2617定义了保证兼容性的步骤。注意,SIP服务器必须不能接收或者发出Basic认证请求。

 

Digest认证的规则在[17]中定义,只是使用“SIP/2.0”替换“HTTP/1.1”,并且有如下的不同:

 

1、URI有着如下的BNF:

URI=SIP-URI/SIPS-URI

2、在RFC 2617定义中,有一个HTTP Digest认证的Authorization头域uri参数的错误,是没有括号配对的错误。(在RFC2617的3.5节的例子是正确的)。对于SIP来说,uri参数必须在引号中引起来。

3、digest-uri-value的BNF是:

digest-uri-value=Request-URI;

4、对SIP来说,产生基于Etag的nonce的步骤例子不适用。

5、对SIP来说,RFC2617[17]关于chache操作不适用。

6、RFC2617[17]要求服务器检查请求行的URI,并且在Authorization头域的URI要指向相同的资源。在SIP中,这两个URI可以指向不同的用户,因为是同一个proxy转发的。因此,在SIP,一个服务器应当检查在Authorization头域值的Request-URI和服务器希望接收请求的用户是否一致,但是如果两者不一致,并无必要展示成为错误。

7、在Digest认证方案中,关于计算消息完整性保证的A2值的一个澄清,实现着应当假定,当包体是空的(也就是说,当SIP消息没有包体)应当对包体的hash值产生一个M5hash空串,或者:

H(entity-body)=MD5(“”)=

"d41d8cd98f00b204e9800998ecf8427e"

8、RFC2617指出了在Authorization(以及扩展的Proxy-Authorization)头域中,如果没有qop指示参数,就不能出现cnonce值。因此,任何基于cnonce(包括”MD5-Sess”)的运算都要求qop指数先发送。在RFC2617中的qop参数是可选的,这是为了向后兼容RFC2069;由于RFC2543是基于RFC2069的,qop参数必须被客户和服务器依旧是当作可选参数存在。不过,服务器必须始终在WWW-Authentication和Proxy-Authenticate头域值中传送qop参数。如果一个客户端在一个拒绝认证的应答中收到一个qop参数,他必须把这个qop参数放在后续的认证头域中。

 

RFC 2543不允许使用Authentication-Info头域(在RFC2069中使用)。不过我们现在允许使用这个头域,因为他提供了对包体的完整性检测以及提供了相互认证。RFC2617[17]定义了在请求中使用qop属性的向后兼容机制。这些机制必须在服务器使用,用来检测是否客户支持RFC2617的,没有在RFC2069中定义的新机制。

0 0
原创粉丝点击