赞
踩
21 应答代码
应答码是包含了,并且扩展了HTTP/1.1应答码。并不是所有的HTTP/1.1应答码都适当应用,只有在这里指出的是适当的。其他HTTP/1.1应答码不应当使用。并且,SIP也定义了新的应答码系列,6xx。
21.1 临时应答1xx
临时应答,也就是消息性质的应答,标志了对方服务器正在处理请求,并且还没有决定最后的应答。如果服务器处理请求需要花200ms以上才能产生终结应答的时候,它应当发送一个1xx应答。
注意1xx应答并不是可靠传输的。他们不会导致客户端传送一个ACK应答。临时性质的(1xx)应答可以包含消息体,包含会话描述。
21.1.1 100 Trying
这个应答表示下一个节点的服务器已经接收到了这个请求并且还没有执行这个请求的特定动作(比如,正在打开数据库的时候)。这个应答,就像其他临时应答一样,种植了UAC重新传送INVITE请求。100(Trying)应答和其他临时应答不同的是,在这里,它永远不会被有状态proxy转发到上行流中。
21.1.2 180 Ringing
UA收到INVITE请求并且试图提示给用户。这个应答应当出世化一个本地回铃。
21.1.3 818 Call is Being Forwarded(呼叫被转发)
服务器可以用这个应答代码来表示呼叫正在转发到另一个目的地集合。
21.1.4 182 Queued
当呼叫的对方暂时不能接收呼叫的时候,并且服务器决定将呼叫排队等候,而不是拒绝呼叫的时候,那么就应当发出这个应答。当被叫方一旦恢复接收呼叫,他会返回合适的终结应答。对于这个呼叫状态,可以有一个表示原因的短语,比如:”5 calls queued;expected waiting time is 15minutes”。服务器可以给出好几个182(Queued)应答告诉呼叫方排队的情况(比如排队靠前了等等)。
21.1.5 183 会话进度
183(Session Progress)应答用于提示建立对话的进度信息。Reason-Phrase(表达原因的句子)、头域或者消息体可以用于提示呼叫进度的更消息的信息。
21.2 成功信息2xx
这个应答表示请求是成功的。
21.2.1 200 OK
请求已经处理成功。这个信息取决于不同方法的请求的应答。
21.3 转发请求3XX
3xx系列的应答是用于提示用户的新位置信息的,或者为了满足呼叫而转发的额外服务地点。
21.3.1 300 Multiple Choices
请求的地址有多个选择,每个选择都有自己的地址,用户或者(UA)可以选择合适的通讯终端,并且转发这个请求到这个地址。
应答可以包含一个具有每一个地点的在Accept请求头域中允许的资源特性,这样用户或者UA可以选择一个最合适的地址来转发请求。没有未这个应答的消息体定义MIME类型。
这些地址选择也应当在Contact头域中列出(20.10节)。不同于HTTP,SIP应答可以包含多个Contact头域或者一个Contact头域中具有一个地址列表。UA可以使用Contact头域来自动转发或者要求用户确认转发。不过,本规范没有定义自动转发的标准。
如果被叫方可以在多个地址被找到,并且服务器不能或者不愿意转发请求的时候,可以使用这个应答来给呼叫方。
21.3.2 301 Moved Permently
当不能在Request-URI指定的地址找到用户的时候,请求的客户端应当使用Contact头域(20.10)所指出的新的地址重新尝试。请求者应当用这个新的值来更新本地的目录,地址本,和用户地址cache,并且在后续请求中,发送到这个/这些列出的地址。
21.3.3 302 Moved Temporarily
请求方应当把请求重新发到这个Contact头域所指出的新地址(20.10)。新请求的Request-URI应当用这个应答的Contact头域所指出的值。
在应答中的Expires(20.19节)或者Contact头域的expires参数定义了这个Contact URI的生存周期。UA或者proxy在这个生存周期内cache这个URI。如果没有严格的有效时见,那么这个地址仅仅本次有效,并且不能在以后的事务中保存。
如果cache的Contact头域的值失败了,那么被转发请求的Request-URI应当再次尝试一次。临时URI可以比超时时间更快的失效,并且可以有一个新的临时URI。
21.3.4 305 Use Proxy
请求的资源必须通过Contact头域中指出的proxy来访问。Contact头域指定了一个proxy的URI。接收到这个应答的对象应当通过这个proxy重新发送这个单个请求。305(UseProxy)必须是UAS产生的。
21.3.5 380 Alternative Service
呼叫不成工,但是可以尝试另外的服务。另外的服务在应答的消息体中定义。消息体的格式在这里没有定义,可能在以后的规范中定义。
21.4 请求失败4xx
4xx应答定义了特定服务器响应的请求失败的情况。客户端不应当在不更改请求的情况下重新尝试同一个请求。(例如,增加合适的认证信息)。不过,同一个请求交给不同服务器也许就会成功。
21.4.1 400 Bad Request
请求中的语法错误。Reason-Phrase应当标志这个详细的语法错误,比如”Missing Call-ID header field”。
21.4.2 401 Unauthorized
请求需要用户认证。这个应答是由UAS和注册服务器产生的,当407(Proxy Authentication Required)是proxy服务器产生的。
21.4.3 402 Payment Required
保留/以后使用
小虎 2006-05-25 00:11
21.4.4 403 Forbidden
服务端支持这个请求,但是拒绝执行请求。增加验证信息是没有必要的,并且请求应当不被重试。
21.4.5 404 Not Found
服务器返回最终信息:用户在Request-URI指定的域上不存在。当Request-URI的domain和接收这个请求的domain不匹配的情况下, 也会产生这个应答。
21.4.6 405 Method Not Allowed
服务器支持Request-Line中的方法,但是对于这个Request-URI中的地址来说,是不允许应用这个方法的。
应答必须包括一个Allow头域,这个头域包含了指定地址允许的方法列表。
21.4.7 Not Acceptable
请求中的资源只会导致产生一个在请求中的Accept头域外的,内容无法接收的错误。
21.4.8 407 Proxy Authentication Required
这个返回码和401(Unauthorized)很类四,但是标志了客户端应当首先在proxy上通过认证。SIP对认证的访问请参见26节和22.3节。
这个返回码用于应用程序访问通讯网关(比如,电话网关),而很少用于被叫方要求认证。
21.4.9 408 Request Timeout
在一段时间内,服务器不能产生一个终结应答,例如,如果它无法及时决定用户的位置。客户端可以在稍后不更改请求的内容然后重新尝试请求。
21.4.10 410 Gone
请求的资源在本服务器上已经不存在了,并且不知道应当把请求转发到哪里。这个问题将会使永久性的。如果服务器不知道,或者不容易检测,这个资源消失是临时性质的还是永久性质的,那么应当返回一个404(Not Found)。
21.4.11 413请求实体过大。
服务器拒绝处理请求,因为这个请求的实体超过了服务器希望或者能够处理的大小。这个服务器应当关闭连接避免客户端重发这个请求。
如果这个情况是暂时的,那么服务端应当包含一个Retry-After头域来表明这是一个暂时的故障,并且客户端可以过一段时间再次尝试。
21.4.12 414 Request-URI Too Long
服务器拒绝这个请求,因为Request-URI超过了服务器能够处理的长度。
21.4.13 415 Unsupported Media Type
服务器由于请求的消息体的格式本服务器不支持,所以拒绝处理这个请求。这个服务器必须根据内容的故障类型,返回一个Accept,Accpet-Encoding,或者Accept-Language头域列表。UAC根据8.1.3.5节定义的方法处理这个应答。
21.4.14 416 Unsupported URI Scheme
服务器由于不支持Request-URI中的URI方案而终止处理这个请求。客户端处理这个应答参照8.1.3.5。
21.4.15 Bad Extension
服务器不知道在请求中的Proxy-Require(20.29)或者Require(20.32)头域所指出的协议扩展。服务器必须在Unsupported头域中列出不支持的扩展。UAC处理这个应答请参见8.1.3.5
21.4.16 421Extension Required
UAS需要特定的扩展来处理这个请求,但是这个扩展并没有在请求的Supported头域中列出。具有这个应答码的应答必须包含一个Require头域列出所需要的扩展。
UAS不应当使用这个应答除非它真的不能给客户端提供有效的服务。相反,如果在Support头域中没有列出需要的扩展,服务器应当根据基准的SIP兼容的方法和客户端支持的扩展来进行处理。
21.4.17 423 Interval Too Brief
服务器因为在请求中设置的资源刷新时间(或者有效时间)过短而拒绝请求。这个应答可以用于注册服务器来拒绝那些Contact头域有效期过短的注册请求。这个应答的用法和相关的Min-Expires头域在10.2.8,10.3,20.23节中介绍和说明。
21.4.18 480 Temporarily Unavailable
请求成功到达被叫方的终端系统,但是被叫方当前不可用(例如,没有登陆,或者登陆了但是状态是不能通讯,或者有”请勿打扰”的标记)。应答应当在Retry-After中标志一个合适的重发时间。这个用户也有可能在其他地方是有效的(在本服务器中不知道)。Reason-Phrase(原因短句)应当提示更详细的原因,为什么被叫方暂时不可用。这个值应当是可以被UA设置的。状态码486(Busy Here)可以用来更精确的表示本请求失败的特定原因。
这个状态码也可以是转发服务或者proxy服务器返回的,因为他们发现Request-URI指定的用户存在,但是没有一个给这个用户的合适的当前转发的地址。
21.4.19 481 Call/Transaction Does Not Exist
这个状态表示了UAS接收到请求,但是没有和现存的对话或者事务匹配。
21.4.20 482 Loop Detected
服务器检测到了一个循环(16.3/4)
21.4.21 483 Too Many Hops
服务器接收到了一个请求包含的Max-Forwards(20.22)头域是0
21.4.22 484 Address InComplete
服务器接收到了一个请求,它的Request-URI是不完整的。在原因短语中应当有附加的信息说明。这个状态码可以和拨号交叠。在和拨号交叠中,客户端不知道拨号串的长度。它发送增加长度的字串,并且提示用户输入更多的字串,直到不在出现484(Address Incomplete)应答为止。
21.4.23 485 Ambiguous
Request-URI是不明确的。应答可以在Contact头域中包含一个可能的明确的地址列表。这个提示列表肯囊个在安全性和隐私性对用户或者组织造成破坏。必须能够由配置决定是否以404(NotFound)代替这个应答,又或者禁止对不明确的地址使用可能的选择列表。
给带有Request-URI的请求的一个应答例子:
sip: lee@example.com:
SIP/2.0 485 Ambiguous
Contact: Carol Lee <sip:carol.lee@example.com>
Contact: Ping Lee <sip:p.lee@example.com>
Contact: Lee M.Foote <sips:lee.foote@example.com>
部分email和语音邮箱系统提供了这个功能。这个状态码和3xx状态码不同:对于300来说,它是假定同一个人或者服务有不同的地址选择。所以对3xx来说,自动选择系统或者连续查找就有效,但是对485(Ambiguous)应答来说,一定要用户的干预。
21.4.24 486 Busy Here
当成功联系到被叫方的终端系统,但是被叫方当前在这个终端系统上不能接听这个电话,那么应答应当回给呼叫方一个更合适的时间在Retry-After头域重试。这个用户也许在其他地方有效,比如电话邮箱系统等等。如果我们知道没有其他终端系统能够接听这个呼叫,那么应当返回一个状态码600(Busy Everywhere)。
21.4.25 487 Request Terminated
请求被BYE或者CANCEL所终止。这个应答永远不会给CANCEL请求本身回复。
21.4.26 488 Not Acceptable Here
这个应答和606(Not Acceptable)有相同的含义,但是只是应用于Request-URI所指出的特定资源不能接受,在其他地方请求可能可以接受。
包含了媒体兼容性描述的消息体可以出现在应答中,并且根据INVITE请求中的Accept头域进行规格化(如果没有Accept头域,那么就是application/sdp)。这个应答就像给OPTIONS请求的200(OK)应答的消息体一样。
21.4.27 491 Request Pending
在同一个对话中,UAS接收到的请求有一个依赖的请求正在处理。14.2描述了这种情况应当怎样解决。
21.4.28 493 Undecipherable
UAS接收到了一个请求,包含了一个加密的MIME,并且不知道或者没有提供合适的解密密钥。这个应答可以包含单个包体,这个包体包含了合适的公钥,这个公钥用于给这个UAS通讯中加密包体使用的。细节描述在23.2节。
21.5 Server Failure 5xx
5xx应答是当服务器本身故障的时候给出的失败应答。
21.5.1 500 Server Internal Error
服务器遇到了未知的情况,并且不能继续处理请求。客户端可以显示特定的错误情况,并且可以在几秒种以后重新尝试这个请求。
如果这个情况是临时的,服务器应当在Retry-After头域标志客户端过多少秒钟之后重新尝试这个请求。
21.5.2 501 Not Implemented
服务器没有实现相关的请求功能。当UAS不认识请求的方法的时候,并且对每一个用户都无法支持这个方法的时候,应当返回这个应答。(proxy不考虑请求的方法而转发请求)。
注意405(Method Not Allowed)是因为服务器实现了这个请求方法,但是这个请求方法在特定请求中不被支持。
21.5.3 502 Bad Gateway
如果服务器,作为gateway或者proxy存在,从下行服务器上接收到了一个非法的应答(这个应答对应的请求是本服务器为了完成请求而转发给下行服务器的)。
21.5.4 503 Service Unavailable
由于临时的过载或者服务器管理导致的服务器暂时不可用。这个服务器可以在应答中增加一个Retry-After来让客户端重试这个请求。如果没有Retry-After指出,客户端必须就像收到了一个500(Server Internal Error)应答一样处理。
客户端(proxy或者UAC)收到503(Service Unavailable)应当尝试转发这个请求到另外一个服务器处理。并且在Retry-After头域中指定的时间内,不应当转发其他请求到这个服务器。
作为503(Service Unavaliable)的替代,服务器可以拒绝连接或者把请求扔掉。
21.5.5 504 Server Time-out
服务器在一个外部服务器上没有收到一个及时的应答。这个外部服务器是本服务器用来访问处理这个请求所需要的。如果从上行服务器上收到的请求中的Expires头域超时,那么应当返回一个408(Request TimeOut)错误。
21.5.6 505 Version Not Supported
服务器不支持对应的SIP版本。服务器是无法处理具有客户端提供的相同主版本号的请求,就会导致这样的错误信息。
21.5.7 Message To Large
服务器无法处理请求,因为消息长度超过了处理的长度。
21.6 Global Failures 6xx
6xx应答意味这服务器给特定用户有一个最终的信息,并不只是在Request-URI的特定实例有最终信息。
21.6.1 600 Busy Everywhere
成功联系到被叫方的终端系统,但是被叫方处于忙的状态,并不打算接听电话。这个应答可以通过增加一个Retry-After头域更明确的告诉呼叫方多久以后可以继续呼叫。如果被叫方不希望提示拒绝的原因,被叫方应当使用603(Decline)。只有当终端系统知道没有其他终端节点(比如语音邮箱系统)能够访问到这个用户的时候才能使用这个应答。否则应当返回一个486(Busy Here)的应答。
21.6.2 603 Decline
当成功访问到被叫方的设备,但是用户明确的不想应答。这个应答可以通过增加一个Retry-After头域更明确的告诉呼叫方多久以后可以继续呼叫。只有当终端知道没有其他任何终端设备能够响应这个呼叫的势能才能给出这个应答。
21.6.3 604 Does Not Exists Anywhere
服务器验证了在请求中Request-URI的用户信息,哪里都不存在
21.6.4 606 Not Acceptable
当成功联系到一个UA,但是会话描述的一些部分比如请求的媒体,带宽,或者地址类型不被接收。
606(NotAcceptable)应答意味着用户希望通讯,但是不能充分支持会话描述。606(Not Acceptable)应答可以在Warning头域中包含一个原因列表,用于解释为何会话描述不能被支持。警告原因代码在20.43节中列出。
在应答中,可以出现一个包含媒体兼容性描述的消息体,这个消息体的格式根据INVITE请求中的Accept头域指出的格式进行规格化(如果没有Accept头域,那么就是application/sdp),就像给OPTIONS亲求的200(OK)应答中的消息一样。
我们希望这些媒体协商不要经常需要,并且当一个新用户被邀请加入已经存在的会话的时候,这个媒体协商可能不需要。这取决于邀请的初始化者是否需要对606(Not Acceptable)进行处理。
这个应答只有当客户端知道没有其他终端能够处理这个请求的时候才能发出。
22 使用HTTP认证
SIP为认证系统提供了一个无状态的,试错机制,这个认证机制式基于HTTP的认证机制的。任何时候proxy服务器或者UA接收到一个请求(22.1节例外),它尝试检查请求发起者提供的身份确认。当发起方身份确认了,请求的接受方应当确认这个用户是否式通过认证的。在本文档中,没有建议或者讨论认证系统。
本节描述的“Digest”认证机制,只提供了消息认证和复查保护,没有提供消息完整性或者机密性的保证。上述的保护级别和基于这些Digest提供的保护,可以防止SIP攻击者改变SIP请求和应答。
注意由于这个脆弱的安全性,我们不赞成”Basic”(基本的)认证方法。服务器必须不能接收验证方法式”Basic”类型的信任书,并且服务器必须拒绝”Basic”。这是和RFC2543的改变。
22.1 框架
SIP认证的框架和HTTP非常接近(RFC2617[17])。特别式,auth-scheme的BNF范式,auth-param,challenge,realm,realm-value,以及信任书都是一样的(虽然对”Basic”认证方案是不允许的)。在SIP,UAS使用401(Unauthorized)应答来拒绝UAC的身份(或者讲是考验UAC的身份,如果不通过,就是401)。另外,注册服务器,转发服务器可以使用401(Unauthorized)来应答身份认证,但是proxy必须不能用401,只能用407(Proxy Authentication Required)应答。对于Proxy-Authenticate的包含要求,Proxy-Authroization,WWW-Authenticate,Authorization在不同的消息中是相同的,如同在RFC2617[17]中讲述的一样。
由于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字串。
o Realm字串必须是全局唯一的。我们强调这个realm字串必须包含一个主机名或者域名,遵循3.2.1节或者RFC2617[17]的推荐
o 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的请求来自同一个节点(假设某种通讯协议,或者网络层有安全关系26.2.1节描述),服务器应当接收CANCEL请求。
当UAC接收到验证拒绝,并且UAC设备并不知道realm验证失败的具体原因,它必须展示给用户,验证失败的”realm”参数内容(既可以在WWW-Authenticate头域或者Proxy-Authenticate头域)。对于给自己的realm预先配置信任状的UA服务提供商来说,应当注意到这样一点:当被一个预先配置信任状的设备拒绝的时候,用户不会有机会在这个realm中展示他们自己的信任状。
最后,注意即使一个UAC能够定位与相关realm匹配的信任书,也有可能存在这个信任书可能不在有效,或者某个服务器会用什么原因不接受这个信任书(特别是当提供的是没有口令的”anonymous”用户时)。在这种情况下,服务器可能会继续拒绝,或者返回一个403 Forbidden。UAC必须不能再次使用刚才被拒绝的信任书进行尝试(如果当前环境没有改变,那么请求可以再次尝试)。
22.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头域的值,就像发送一个正常的新请求一样。
22.3 Proxy到用户的认证
类似的,当UAC发送一个请求到proxy服务器,proxy服务器可以在处理请求之前,验证原始请求的认证。如果请求中没有信任书(在Proxy-Authorization头域),proxy可以用407(Proxy Authentication Required)拒绝这个原始请求,并且要求客户端提供适当的信任书。proxy必须在407(ProxyAuthenticationRequired)应答中增加一个Proxy-Authenticate头域,并且在这个头域中给出适用于本proxy的认证资源。
对于Proxy-Authenticate和Proxy-Authorization一起在[17]中描述,两者有一个不同。Proxy不能在Proxy-Authorization头域中增加值。所有的407(ProxyAuthenticationRequired)应答必须转发到上行队列,遵循发送应答的步骤发送到UAC。UAC负责在Proxy-Authorization头域值增加适用于这个proxy要求认证的这个proxy的realm的信任书。
如果proxy要求UAC在请求中增加Proxy-Authorization头域并且重新提交请求,那么UAC应当增加Cseq头域的值,就像一个新请求一样。不过,这样就导致提交原始请求的UAC需要忽略UAS的应答,因为Cseq的值可能是不一样的。
当原始请求的UAC接收到一个407(Proxy Authentication Required)的时候,如果可能,
小虎 2006-05-25 00:11
它应当使用正确的信任书重新组织请求。它应当和对前边讲述的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 Authentication Required)应答之后――可以在请求中增加一个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的认证方案。
如果一个请求被分支(参见16.7节),可能对同一个UAC有不同的proxy服务器和/或者UA希望要求认证。在这种情况下,分支的proxy服务器有责任把这些被拒绝的认证合并成为一个应答。每一个分支请求的应答中接收到WWW-Authenticate和Proxy-Authenticate头域值必须由这个分支proxy放置在同一个应答中发送给UA;这些头域值的顺序并没有影响。
当proxy服务器给一个请求发出拒绝认证的应答,在UAC用正确的信任书重新发请求过来之前,不会转发这个请求。分支proxy可以同时向多个要求认证的proxy服务器转发请求。每一个proxy在没有接收到UAC在他们各自的realm的认证之前,都不会转发这个请求。如果UAC没有给这些失败的验证提供信任书,那些发出拒绝通过认证的proxy是不会把请求转发给UA的目标用户的,因此,分支的优点就少了很多。
当针对包含多个拒绝认证的401(Unauthorized)或者407(Proxy Authentication Required)应答重新提交请求时,UAC应当对每一个WWW-Authenticate和Proxy-Authorization头域值提供一个信任书。根据上边的说明,一个请求的多个认证书应当用”realm”参数分开。
不过,在同一个401(Unauthorized)或者407(Proxy Authentication Required)应答中,可能包含对同一个realm的多个验证拒绝。例如,当在相同域的多个proxy,使用共同的realm,接收到了一个分支请求,并且认证拒绝了的时候,就会有这样的情况。当UAC重新尝试这个请求的时候,UAC因此会提供多个Authorization或者Proxy-Authorization头域,包含相同的”realm”参数。并且对于同一个realm,应当有相同的信任书。
22.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; 在25节定义。
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中定义的新机制,
23 S/MIME
SIP消息可以加载一个MIME 消息体,并且MIME标准包括了MIME内容的保密机制,确保完整性和机密性(包括”multipart/signed”和”application/pkcs7-mime”的MIME类别,参见RFC 1847[22],RFC 2630[23],RFC2633[24])。实现中应当注意,不管怎样,也会有很少的网络节点(不是典型的proxy服务器),会依赖于查看修改SIP消息(特别是SDP),采用加密的MIME可以防止这类网络节点操作。
这个实现特别对某些类型防火墙有效。
在RFC2543描述的对于SIP头域和包体的PGP加密机制,已经不建议使用了。
23.1 S/MIME 认证
用于区别服务器使用的S/MIME而进行的最终用户的鉴定,有一种重要的特点-这些信任状的持有者是被最终用户地址鉴定的,而不是由一个特定的hostname所鉴定的。这个地址是由SIP或者SIPS URI的”userinfo””@”和”domainname”组成的(换句话说,就是用的email格式,类似bob@biloxi.com),最常见的就是和用户的address-of-record对应的地址。
这些认证也同样和用于标记或者加密SIP消息包体的密钥相关联。包体由发送方的私钥所标记(这个发送方在适当情况下,可以包含他们的公钥),并且包体是由被接受方的公钥所加密。显然,发送方必须事先知道接受方的公钥,这样才能加密包体。公钥可以在UA的一个虚拟的钥匙环上保存。
每一个支持S/MIME的UA都必须包含用于终端用户验证的一个特定密钥组。这个密钥组应当由address-of-record和相应的认证信息的映射组成。在时间上,当用户产生具有相同address-of-record的原始的信号URI(From头域)时,用户应当使用相同的认证信息。
任何依赖于现存的终端用户认证的机制都是严格受限于:事实上,目前没有一个统一的权威认证机构为终端用户应用提供认证。不过,用户应当从已知的公共认证机构获得认证。作为替代,用户可以创建自标记(self-signed)的信任书。self-signed信任书在26.4.2节中有介绍。在实现中,也可以采用在配置中存放预先配置的信任书,这个配置中存放的时上次SIP实体之间的信任关系。
在获得终端用户的认证问题上,很少有广为人知的集中发布终端用户认证的目录机构。信任书的拥有者应当在一些公共的目录机构中,适当的发布自己的信任书。类似的,UAC应当支持从与SIP请求的目标URI有关的公共目录机构导入信任书(手工或者自动的)。
23.2 S/MIME 密钥交换
SIP自身可以根据下列的方法发布公钥。
无论何时SIP的S/MIME使用了CMS SignedData消息,他必须包含由公钥所加密的信任书,用于检查签名。
当UAC发送一个创建对话的请求,包含了一个S/MIME包体,或者在对话外发送一个非INVITE请求,UAC应当创建一个S/MIME ‘multipart/signed’ CMS SignedData包体结构的包体。
如果特定的CMS服务时EnvelopedData(并且知道目标用户的公钥),UAC应当在一个SignedData消息中发送EnvelopedData消息。
当UAS接收到一个包含S/MIME CMS包体的请求,并且这个包体包含一个信任书,UAS应当首先检查这个信任书,如果可能,使用以后的root信任书来进行信任书检查。UAS也应当检查信任书的主题(subject)(对于S/MIME,SubjectAltName应当包含了适当的标记)并且,把这个值和请求From头域进行比较。如果信任书不被通过,因为它是self-signed(自签发),或者被位置的信任机构所颁发的,或者它是可信任的,但是他的主题和请求的From头域不匹配,UAS必须把这个通知用户(包括信任书的主题,签发者,和密钥指纹信息),并且在继续处理之前,要求用户确认。如果信任书成功通过认证,并且信任书的主题(subject)和SIP请求的From头域相同,或者如果用户(在知会之后)批准了这个信任书的使用,那么UAS应当增加这个信任书到本地密钥组中(keyring),并且用信任书拥有者的address-of-record作为索引。
当UAS要发送一个包含S/MIME消息体的应答,这个应答回应了在对话中的前一个请求,或者是给对话外的一个非INVITE请求的应答,UAS应当构造一个S/MIME ‘multipart/signed’ CMS SignedData包体。如果给定的CMS服务要求EnvelopedData,UAS应当发送一个EnvelopedData的SignedData消息
当UAC收到一个包含S/MIME CMS包体的应答,这个应答中包含了一个信任书,UAC应当首先检查这个信任书,如果可能,使用任何适当的root信任书来进行检查。UAC应当同样检查信任书的主题(subject),并且和应答的To头域进行比较;虽然两个可能完全不同,这个也没有必要当作是不安全的。如果因为self-signed,或者由未知认证机关颁发而导致信任书不能通过认证,那么UAC应当通知它的使用者这个状态(包含信任书的主题,它的签发者,以及密钥的指纹信息),并且在继续操作之前,要求使用者确认。如果信任书通过了认证,并且信任书的主题和应答的To头域相同,或者用户(在提示确认后)明确的确认这个信任书以后,UAC应当把这个信任书放在本地密钥组中,用这个信任书的拥有者的address-of-record作为索引。如果UAC没有把自己的信任书事先传送给UAS,它在下一个请求或者应答时应当使用一个CMS SignedData包体。
在以后,当UA接收到包伙那一个From头域的请求或者应答,并且这个From头域和本地的一个密钥组的索引匹配,那么UA应当比较消息中的信任书和这个密钥组对应索引的信任书。如果他们不匹配,那么UA必须通知用户信任书改变了(更合适的是提示这个可能是一个潜在的安全冲突),并且在继续处理前要求用户的确认。如果用户确认了这个信任书,它应当在本地密钥组的这个address-of-record项的前一个值旁边附加这个信任书。
注意,这个值的改变机制,在self-signed信任书的情况或者未知机关颁发的信任书情况下,并不保证密钥变更的安全性,并且这个缺陷被广为人知的攻击。在本文的作者看来,它提供的安全性当然比什么也没有要强;实际上可以和广泛应用的SSH应用相比。这些限制在26.4.2节中有详细描述。
如果UA接收到了一个S/MIME包体,并且是由本接受方所不知道的公钥加密的,它必须用493(Undecipherable)拒绝这个请求。这个应答应当回答一个合法的信任书(相应的,如果可能,给被拒绝请求的To头域指出的全部地址),这个信任书包含一个’certs-only’ “smime-type”参数的MIME包体。。
一个没有任何信任书信息的493(Undecipherable)应答表示回答者不能或者不会利用S/MIME加密信息,虽然他们可以依旧支持S/MIME标记。
注意UA接收到一个包含一个S/MIME包体的请求(这个请求包含了Content-Disposition头域和”required”的”handling”参数),如果这个MIME类型是不被支持的,那么就必须用415 Unsupported MediaType来拒绝这个请求。当UA接收到这个应答,并且这个应答表示的是对方不支持刚才发送的S/MIME类型的请求,那么UA应当通知它的使用者对方不支持这个S/MIME类型,并且如果可以,他可以在随后的请求中不包含S/MIME部分;另外,这个415应答可以制造一个下级的攻击。
如果一个UA在请求中发送了一个S/MIME包体,但是接收到的应答包含了一个未加密的MIME包体,UAC应当提示用户,这个会话可能是不安全的。可是,如果一个支持S/MIME的UA接收到一个包含未加密的包体的请求,它不应当给出一个包含加密包体的应答,但是如果它希望从发送方获得一个S/MIME(比如,因为发送方的From头域值在它的密钥组中存在关联),UAS应当通知它的使用者这个会话可能是不安全的。
当信任书管理不正常的情况下,许多条件都可以导致前边讲的要给用户提示以及确认的情况。使用者可能会问在这个情况下应当怎样做。首先,一个信任书的异常改变,或者在需要安全保护的时候不安全,是导致这个警告出现的原因,但是并非表示正在遭受攻击。使用者可以中断现有的连接或者拒绝连接请求;在电话谈话中,他们可以挂机并且回叫。使用者可能会使用另外的方式来联系对方并且确认他们的密钥是否合法的更改了。注意用户有时候需要强制更改他们的信任书,例如当他们怀疑他们的私钥不够安全的情况。当他们的私钥不再私钥,用户必须合法的产生一个新的密钥并且重新和其他持有旧密钥的用户建立信任关系。
最后,如果在对话中UA收到了在一个CMS SignedData Message中的信任书,并且和早先对话中交换的信任书不一致,那么UA必须提示它的使用者这个变化,更好的方法是展示成为一个安全隐患。
23.3 加密MIME 包体
SIP中,总共由两种类型的加密MIME包体:对他们的使用应当遵循S/MIME规范[24],并且有几点不同:
l multipart/signed”只在CMS 分离签名的时候有用。这是为了和非S/MIME规范接受者兼容。
l S/MIME包体应当包含一个Content-Disposition头域,并且他的”handling”参数的值应当是”required”
l 如果UAC在它的密钥组中没有对应要发送请求的接受者的address-of-record的信任书,它不能发送加密的”application/pkcs7-mime” MIME消息。UAC可以发送一个初始化的请求(比如OPTIONS消息),包含一个为了方便对方处理的CMS分离的签名(签名应当基于一个”message/sip”包体,类型描述在23.4节)。
注意以后的S/MIME标准工作可以定义基于非信任书的密钥。
l S/MIME的发送方应当使用”SMIMECapabilities”(参见2.5.2 [24])属性来为以后的通讯介绍他们自己的能力和参数。注意,特别是那些可能用”preferSignedData”的发送方希望接受方应答一个CMS SignedData消息(例如,当发送一个OPTIONS请求的时候)。
l S/MIME实现必须至少支持SHA1作为数字签名算法,并且3DES作为加密算法。其他的签名和加密算法也可以支持,实现上应当可以用”SMIMECapabilities”属性进行这些算法的协商。
l 在SIP中的每一个S/MIME包体应当只有一个信任书的签名。如果UA接收到的消息有多个信任书,最外边的信任书应当当作这个包体的信任书。并行的签名应当不能使用。
下边是一个SIP中的加密的S/MIME SDP包体的例子:
INVITE sip:bob@biloxi.com SIP/2.0
Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8
To: Bob <sip:bob@biloxi.com>
From: Alice <sip:alice@atlanta.com>;tag=1928301774
Call-ID: a84b4c76e66710
CSeq: 314159 INVITE
Max-Forwards: 70
Contact: <sip:alice@pc33.atlanta.com>
Content-Type: application/pkcs7-mime; smime-type=enveloped-data;
name=smime.p7m
Content-Disposition: attachment; filename=smime.p7m
handling=required
********************************************************************
* Content-Type: application/sdp *
* *
* v=0 *
* o=alice 53655765 2353687637 IN IP4 pc33.atlanta.com *
* s=- *
* t=0 0 *
* c=IN IP4 pc33.atlanta.com *
* m=audio 3456 RTP/AVP 0 1 3 99 *
* a=rtpmap:0 PCMU/8000 *
********************************************************************
23.4 SIP头隐私和用S/MIME的完整性:SIP地道
作为提供端到端的某种程度认证来说,SIP头域的完整性或者机密性,SI/MIME可以把SIP消息通过”message/sip”的包体类型,整个装入一个MIME包体,并且接着就像处理普通SIP包体一样,对这个大的包体用MIME安全性来保护。这些被封装的SIP请求和应答并不产生另外的对话或者事务,他们只是一个用来检验完整性的或者提供附加信息的”outer”外部包装消息。
如果UAS接收到一个请求,包含一个”message/sip”隧道的S/MIME包体,它应当把应答用同样的SMIME-TYPE封装成一个”message/sip”隧道包体。
任何传统的MIME包体(比如SDP),应当附加为”inner”内部消息,这样他们可以使用到S/MIME安全性。注意,如果在请求中需要传送未加密的MIME类型的内容,那么”message/sip”包体可以作为MIME “multipart/mixed”包体的一部分存在,
23.4.1 SIP头的完整性和机密属性
当应用了S/MIME完整性或者机密性机制,那么在”inner”消息和”outer”消息中的值可能会有差异。对于所有头域来说,处理这些差异的规则在本节指出。
注意,由于松散的时间戳,所有的在”message/sip”隧道中的SIP消息应当在”inner”和”outer”消息中都包含一个Date头域。
23.4.1.1 完整性
无论何时,当完整性被检查,头域的完整性应当通过检查被封装包体中的头域值和”outer”消息的头域值,使用20节描述的SIP比较规则。
头域可以被proxy服务器合法修改的是:Request-URI, Via, Record-Route, Route, Max-Forwards, 和Proxy-Authorization。如果这些头域不完全相等,实现中不应当认为是一个安全错误。对于其他头域的修改就是破坏了完整性,必须通知使用者关于这个差异。
23.4.1.2 机密性
当消息加密以后,头域可以在加密的包体中存在,而不用在”outer”消息中存在。
有一些头域必须有一个明码格式的版本,因为他们是请求和应答中必须要求的头域-他们是:To, From, Call-ID, Cseq, Contact。 虽然提供一个额外的Call-ID,Cseq,或者Contact的加密版本没有什么用处,我们允许把To/From 放一份在”outer”消息的To或者From头域中。注意这些加密包体中的值并不用作鉴别事务或者对话――加密包体中的这些值仅仅作为提示信息使用。如果在加密包体中的From头域和在”outer”消息中的值不一样,那么这个加密包体中的值应当显示给用户,但是不能用于后续”outer”消息的头域中。
首先,UA应当希望加密有着端到端语义的头域,包括: Subject,Replay-To,Organization, Accept,Accept-Encoding,Accept-Language,Alter-Info,Error-Info, Authentication-Info , Expires, In-Replay-To, Require, Supported, Unsupported, Retry-After, User-Agent, Server, 和Warning。 如果这些头域在加密包体中出现,那么就应当替换在”outer”消息中的头域,而不管这个头域是显示给用户的还是设置UA内部状态的。他们应当在后续消息中不在在”outer”消息的头域中使用。
如果存在Date头域,那么Date头域必须在”inner”和”outer”头域中的值一样。
由于MIME包体是在”inner”消息中的,实现中通常会加密MIME指定的头域,包括:MIME-Version,Content-Type,Content-Length, Content-Language, Content-Encoding, 和Content-Disposition。”outer”消息会为S/MIME包体使用适当的MIME头域。这些头域(和他们开始的任何MIME包体)在SIP消息中,应当作为普通的MIME头域和包体
小虎 2006-05-25 00:11
接收。
对下边这些头域的加密并不是特别有用: Min-Expires, Timestamp, Authorization, Priority, 和 WWWAuthenticate。这类头域包含了那些能够被proxy服务器所更改的头域(在前边章节有讲述)。如果这些头域不出现在”outer”消息中,那么UA应当不在”inner”消息中包含这些头域。如果UA在加密的包体中接收到这些头域,应当忽略到这些加密的值。
注意,SIP的扩展可能会定义附加的头域;那么这些扩展的作者应当描述这些头域的完整性和机密性特性。如果一个SIP UA遇到了一个不认识的头域,并且产生了一个完整性冲突,它必须忽略掉这个头域。
23.4.2 隧道的完整性和身份认证
通过S/MIME包体的SIP消息隧道可以提供SIP头域的完整性保证,只要发送方把这个包整个打包放在用CMS分离签名的”message/sip” MIME包体中。
假设那个”message/sip”包体包含了最基本的对话要素(最小集合)(To, From, Call-ID, CSEq),并且一个签名的MIME包体可以提供优先的身份认证。在这个特别的最小集合上,如果接受方不认识用于签名MIME包体的信任状,并且不能被检验,那么在同一个信任状拥有者所初始化的会话中,这个信任状拥有者可以稍后发送一个在会话中的请求,包含这个签名来进行确认。如果签名MIME包体的接受方选择信任这个信任书(他们可以检验信任书,他们已经从信任列表中检查了,或者他们经常使用这个信任书),那么这个签名就和这个信任书的主题有着相同的身份一致性。
为了排出可能的对实体包头域增加减少的相关困惑,发送方应当把请求的所有头域放在签名的包体中。任何需要完整性保护的包体都必须添加到”inner”消息中。
如果有一个签名包体的消息中包含一个Date头域,接受方应当比较它自己的内部时钟和这个头域值。如果检测到了时差(比如超过1个小时或者更多),UA应当警告使用者,并且提示这个可能是安全隐患。
如果接受方检测到消息的完整性破坏了,如果是这个消息是请求,那么应当使用403(Forbidden)来拒绝这个请求,或者终止现存的对话。UA应当提示用户这个情况,并且要求明确的操作指示。
下边是一个使用隧道”message/sip”的例子:
INVITE sip:bob@biloxi.com SIP/2.0
Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8
To: Bob <sip:bob@biloxi.com>
From: Alice <sip:alice@atlanta.com>;tag=1928301774
Call-ID: a84b4c76e66710
CSeq: 314159 INVITE
Max-Forwards: 70
Date: Thu, 21 Feb 2002 13:02:03 GMT
Contact: <sip:alice@pc33.atlanta.com>
Content-Type: multipart/signed;
protocol="application/pkcs7-signature";
micalg=sha1; boundary=boundary42
Content-Length: 568
--boundary42
Content-Type: message/sip
INVITE sip:bob@biloxi.com SIP/2.0
Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8
To: Bob <bob@biloxi.com>
From: Alice <alice@atlanta.com>;tag=1928301774
Call-ID: a84b4c76e66710
CSeq: 314159 INVITE
Max-Forwards: 70
Date: Thu, 21 Feb 2002 13:02:03 GMT
Contact: <sip:alice@pc33.atlanta.com>
Content-Type: application/sdp
Content-Length: 147
v=0
o=UserA 2890844526 2890844526 IN IP4 here.com
s=Session SDP
c=IN IP4 pc33.atlanta.com
t=0 0
m=audio 49172 RTP/AVP 0
a=rtpmap:0 PCMU/8000
--boundary42
Content-Type: application/pkcs7-signature; name=smime.p7s
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=smime.p7s;
handling=required
ghyHhHUujhJhjH77n8HHGTrfvbnj756tbB9HG4VQpfyF467GhIGfHfYT6
4VQpfyF467GhIGfHfYT6jH77n8HHGghyHhHUujhJh756tbB9HGTrfvbnj
n8HHGTrfvhJhjH776tbB9HG4VQbnj7567GhIGfHfYT6ghyHhHUujpfyF4
7GhIGfHfYT64VQbnj756
--boundary42-
23.4.3 隧道加密
把”message/sip”MIME包体用CMS EnvelopedData消息S/MIME包体进行加密是值得的,但是在实践中,大部分头域都是用于网络的;而通常使用S/MIME进行的加密都是加密类似SDP的消息体的,而不是消息头的。有一部分头域的信息,比如Subject或者Organization或许需要端到端的安全保证。以后的SIP应用可能会定义其他的头域,这些头域也或许需要端到端的安全保证。
另一个加密头域的可能的应用是选择性匿名。可以构造一个没有个人信息的From头域(比如sip:anonymous@anonymizer.invalid)。不过,第二个From头域包含了真实的请求者的address-of-record信息,并且加密存放在”message/sip”MIME包体中,并且只会在对话的对方节点被看到。
注意如果这个机制用于匿名,那么将接受方将不再用From头域来作为密钥组的索引,并且也不用于从密钥组查询合适的发送方的S/MIME密钥。这个消息必须首先被解密,并且”inner”From头域必须当作一个索引。
为了提供端到端的完整性,加密的”message/sip”MIME包体应当由发送方签名。这个创建了一个包含一个加密包体和一个签名的”multipart/signed” MIME包体,包体类型都是”application/pkcs7-mime”.。
在下边这个例子中,是一个加密和签名的消息,在*括起来的文字是加密的:
INVITE sip:bob@biloxi.com SIP/2.0
Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8
To: Bob <sip:bob@biloxi.com>
From: Anonymous <sip:anonymous@atlanta.com>;tag=1928301774
Call-ID: a84b4c76e66710
CSeq: 314159 INVITE
Max-Forwards: 70
Date: Thu, 21 Feb 2002 13:02:03 GMT
Contact: <sip:pc33.atlanta.com>
Content-Type: multipart/signed;
protocol="application/pkcs7-signature";
micalg=sha1; boundary=boundary42
Content-Length: 568
--boundary42
Content-Type: application/pkcs7-mime; smime-type=enveloped-data;
name=smime.p7m
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=smime.p7m
handling=required
Content-Length: 231
******************************************************************************
* Content-Type: message/sip *
* *
* INVITE sip:bob@biloxi.com SIP/2.0 *
* Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8 *
* To: Bob <bob@biloxi.com> *
* From: Alice <alice@atlanta.com>;tag=1928301774 *
* Call-ID: a84b4c76e66710 *
* CSeq: 314159 INVITE *
* Max-Forwards: 70 *
* Date: Thu, 21 Feb 2002 13:02:03 GMT *
* Contact: <sip:alice@pc33.atlanta.com> *
* *
* Content-Type: application/sdp *
* *
* v=0 *
* o=alice 53655765 2353687637 IN IP4 pc33.atlanta.com *
* s=Session SDP *
* t=0 0 *
* c=IN IP4 pc33.atlanta.com *
* m=audio 3456 RTP/AVP 0 1 3 99 *
* a=rtpmap:0 PCMU/8000 *
******************************************************************************
--boundary42
Content-Type: application/pkcs7-signature; name=smime.p7s
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=smime.p7s;
handling=required
ghyHhHUujhJhjH77n8HHGTrfvbnj756tbB9HG4VQpfyF467GhIGfHfYT6
4VQpfyF467GhIGfHfYT6jH77n8HHGghyHhHUujhJh756tbB9HGTrfvbnj
n8HHGTrfvhJhjH776tbB9HG4VQbnj7567GhIGfHfYT6ghyHhHUujpfyF4
7GhIGfHfYT64VQbnj756
--boundary42-
24 例子
在下边这个例子中,由于简略介绍的关系我们经常省略消息体和对应的Content-Length和Content-Type头域。
24.1 注册
Bob在启动的时候进行注册。这个消息流在图9中展示。注意对于注册服务来说,通常需要认证,而且不像下边描述的这样简单。
图9: SIP 注册例子
F1 REGISTER Bob -> Registrar
REGISTER sip:registrar.biloxi.com SIP/2.0
Via: SIP/2.0/UDP bobspc.biloxi.com:5060;branch=z9hG4bKnashds7
Max-Forwards: 70
To: Bob <sip:bob@biloxi.com>
From: Bob <sip:bob@biloxi.com>;tag=456248
Call-ID: 843817637684230@998sdasdh09
CSeq: 1826 REGISTER
Contact: <sip:bob@192.0.2.4>
Expires: 7200
Content-Length: 0
注册会在2小时后超时。注册服务器回应一个200OK:
F2 200 OK Registar -> Bob
SIP/2.0 200 OK
Via: SIP/2.0/UDP bobspc.biloxi.com:5060;branch=z9hG4bKnashds7
;received=192.0.2.4
To: Bob <sip:bob@biloxi.com>;tag=2493k59kd
From: Bob <sip:bob@biloxi.com>;tag=456248
Call-ID: 843817637684230@998sdasdh09
CSeq: 1826 REGISTER
Contact: <sip:bob@192.0.2.4>
Expires: 7200
Content-Length: 0
24.2 建立会话
这个例子包括了4节描述的建立会话的细节。消息流在图1中展示了。注意这些消息流展示了头域的最小集合--一般来说还需要包含一些其他头域,比如Allow和Supported头域。
F1 INVITE Alice -> atlanta.com proxy
INVITE sip:bob@biloxi.com SIP/2.0
Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8
Max-Forwards: 70
To: Bob <sip:bob@biloxi.com>
From: Alice <sip:alice@atlanta.com>;tag=1928301774
Call-ID: a84b4c76e66710
CSeq: 314159 INVITE
Contact: <sip:alice@pc33.atlanta.com>
Content-Type: application/sdp
Content-Length: 142
(Alice’s SDP not shown)
F2 100 Trying atlanta.com proxy -> Alice
SIP/2.0 100 Trying
Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8
;received=192.0.2.1
To: Bob <sip:bob@biloxi.com>
From: Alice <sip:alice@atlanta.com>;tag=1928301774
Call-ID: a84b4c76e66710
CSeq: 314159 INVITE
Content-Length: 0
F3 INVITE atlanta.com proxy -> biloxi.com proxy
INVITE sip:bob@biloxi.com SIP/2.0
Via: SIP/2.0/UDP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c2312983.1
Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8
;received=192.0.2.1
Max-Forwards: 69
To: Bob <sip:bob@biloxi.com>
From: Alice <sip:alice@atlanta.com>;tag=1928301774
Call-ID: a84b4c76e66710
CSeq: 314159 INVITE
Contact: <sip:alice@pc33.atlanta.com>
Content-Type: application/sdp
Content-Length: 142
(Alice’s SDP not shown)
F4 100 Trying biloxi.com proxy -> atlanta.com proxy
SIP/2.0 100 Trying
Via: SIP/2.0/UDP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c2312983.1
;received=192.0.2.2
Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8
;received=192.0.2.1
To: Bob <sip:bob@biloxi.com>
From: Alice <sip:alice@atlanta.com>;tag=1928301774
Call-ID: a84b4c76e66710
CSeq: 314159 INVITE
Content-Length: 0
F5 INVITE biloxi.com proxy -> Bob
INVITE sip:bob@192.0.2.4 SIP/2.0
Via: SIP/2.0/UDP server10.biloxi.com;branch=z9hG4bK4b43c2ff8.1
Via: SIP/2.0/UDP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c2312983.1
;received=192.0.2.2
Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8
;received=192.0.2.1
Max-Forwards: 68
To: Bob <sip:bob@biloxi.com>
From: Alice <sip:alice@atlanta.com>;tag=1928301774
Call-ID: a84b4c76e66710
CSeq: 314159 INVITE
Contact: <sip:alice@pc33.atlanta.com>
Content-Type: application/sdp
Content-Length: 142
(Alice’s SDP not shown)
F6 180 Ringing Bob -> biloxi.com proxy
SIP/2.0 180 Ringing
Via: SIP/2.0/UDP server10.biloxi.com;branch=z9hG4bK4b43c2ff8.1
;received=192.0.2.3
Via: SIP/2.0/UDP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c2312983.1
;received=192.0.2.2
Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8
;received=192.0.2.1
To: Bob <sip:bob@biloxi.com>;tag=a6c85cf
From: Alice <sip:alice@atlanta.com>;tag=1928301774
Call-ID: a84b4c76e66710
Contact: <sip:bob@192.0.2.4>
CSeq: 314159 INVITE
Content-Length: 0
F7 180 Ringing biloxi.com proxy -> atlanta.com proxy
SIP/2.0 180 Ringing
Via: SIP/2.0/UDP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c2312983.1
;received=192.0.2.2
Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8
;received=192.0.2.1
To: Bob <sip:bob@biloxi.com>;tag=a6c85cf
From: Alice <sip:alice@atlanta.com>;tag=1928301774
Call-ID: a84b4c76e66710
Contact: <sip:bob@192.0.2.4>
CSeq: 314159 INVITE
Content-Length: 0
F8 180 Ringing atlanta.com proxy -> Alice
SIP/2.0 180 Ringing
Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8
;received=192.0.2.1
To: Bob <sip:bob@biloxi.com>;tag=a6c85cf
From: Alice <sip:alice@atlanta.com>;tag=1928301774
Call-ID: a84b4c76e66710
Contact: <sip:bob@192.0.2.4>
CSeq: 314159 INVITE
Content-Length: 0
F9 200 OK Bob -> biloxi.com proxy
SIP/2.0 200 OK
Via: SIP/2.0/UDP server10.biloxi.com;branch=z9hG4bK4b43c2ff8.1
;received=192.0.2.3
Via: SIP/2.0/UDP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c2312983.1
;received=192.0.2.2
Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8
;received=192.0.2.1
To: Bob <sip:bob@biloxi.com>;tag=a6c85cf
From: Alice <sip:alice@atlanta.com>;tag=1928301774
Call-ID: a84b4c76e66710
CSeq: 314159 INVITE
Contact: <sip:bob@192.0.2.4>
Content-Type: application/sdp
Content-Length: 131
(Bob’s SDP not shown)
F10 200 OK biloxi.com proxy -> atlanta.com proxy
SIP/2.0 200 OK
Via: SIP/2.0/UDP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c2312983.1
;received=192.0.2.2
Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8
;received=192.0.2.1
To: Bob <sip:bob@biloxi.com>;tag=a6c85cf
From: Alice <sip:alice@atlanta.com>;tag=1928301774
Call-ID: a84b4c76e66710
CSeq: 314159 INVITE
Contact: <sip:bob@192.0.2.4>
Content-Type: application/sdp
Content-Length: 131
(Bob’s SDP not shown)
F11 200 OK atlanta.com proxy -> Alice
SIP/2.0 200 OK
Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8
;received=192.0.2.1
To: Bob <sip:bob@biloxi.com>;tag=a6c85cf
From: Alice <sip:alice@atlanta.com>;tag=1928301774
Call-ID: a84b4c76e66710
CSeq: 314159 INVITE
Contact: <sip:bob@192.0.2.4>
Content-Type: application/sdp
Content-Length: 131
(Bob’s SDP not shown)
F12 ACK Alice -> Bob
ACK sip:bob@192.0.2.4 SIP/2.0
Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds9
Max-Forwards: 70
To: Bob <sip:bob@biloxi.com>;tag=a6c85cf
From: Alice <sip:alice@atlanta.com>;tag=1928301774
Call-ID: a84b4c76e66710
CSeq: 314159 ACK
Content-Length: 0
在Alice和Bob之间的媒体会话现在建立了。Bob首先挂机。注意Bob的SIP电话维持它自己的Cseq号码空间,在这里,是231开始的。由于Bob发起请求,那么To和From URI和tags交换了。
F13 BYE Bob -> Alice
BYE sip:alice@pc33.atlanta.com SIP/2.0
Via: SIP/2.0/UDP 192.0.2.4;branch=z9hG4bKnashds10
Max-Forwards: 70
From: Bob <sip:bob@biloxi.com>;tag=a6c85cf
To: Alice <sip:alice@atlanta.com>;tag=1928301774
Call-ID: a84b4c76e66710
CSeq: 231 BYE
Content-Length: 0
F14 200 OK Alice -> Bob
SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.0.2.4;branch=z9hG4bKnashds10
From: Bob <sip:bob@biloxi.com>;tag=a6c85cf
To: Alice <sip:alice@atlanta.com>;tag=1928301774
Call-ID: a84b4c76e66710
CSeq: 231 BYE
Content-Length: 0
这个SIP呼叫流程文档[40]包含了SIP消息的更多例子。
25 SIP协议的BNF范式
本协议中定义的机制都用文本和Backus-Naur Form(BNF)范式定义(RFC2234[10])。6.1节和RFC2234定义了一个本文档使用的基本核心规则,这里就不赘述了。实现者需要熟悉RFC2234协议,这样才能理解整理定义的规范。某些基本规则是用大写字母表示的,比如SP,LWS,HTAB,CRLF,DIGIT,ALPHA,等等。尖括号定义了规则的名字。
方括号的使用是在语法上可选的。在这里用于特定参数是可选的语义提示。
25.1 基本规则
下列贯穿本规范的规则是用于描述基本的语法结构。US-ASCII码字符集是在ANSI X3.4-1986中定义的。
alphanum = ALPHA/DIGIT
部分规则是和RFC2396[5]中合并使用的,但是依据RFC2234[10]做了更新,这些包括:
reserved = ";" / "/" / "?" / ":" / "@" / "&" / "=" / "+" / "$" / ","
unreserved = alphanum / mark
mark = "-" / "_" / "." / "!" / "?" / "*" / "’" / "(" / ")"
escaped = "%" HEXDIG HEXDIG
SIP头域值可以折叠成为多行,如果每行的开始是一个空格或者一个水平制表符(就是Tab键啦)。所有的线形空白,包含折叠的空白,和SP有着同样的语义(SP就是空格啦)。一个接受方在处理头域值之前或者转发消息到下行队列之前,可以把任何线形空白当作一个单个SP处理。这个和RFC2616[8]中描述的HTTP/1.1处理方法完全一样。当线形空白是可选的时候,SWS构造就需要了,通常在两个符号和分隔符之间存在:
LWS = [*WSP CRLF] 1*WSP ; linear whitespace
SWS = [LWS] ; sep whitespace
为了把头域名和头域值分开,就需要使用冒号,根据上边的规则,允许在冒号之前有空白,但是不允许有行分隔符,并且允许在冒号之后有空白,或者行分隔符。HCOLON有如下定义:
HCOLON = *( SP / HTAB ) ":" SWS
TEXT-UTF8规则只用于描述不被消息分析所分析的域内容和域值。*TEXT-UTF8包含了UTF-8字符集的字符(RFC2279[7])。TEXT-UTF8-TRIM规则是用于描述一个n t引号引起来的字符串,其前后的空白是无意义的。在这里,SIP和HTTP不同,HTTP使用的是ISO 8859-1字符集。
TEXT-UTF8-TRIM = 1*TEXT-UTF8char *(*LWS TEXT-UTF8char)
TEXT-UTF8char = %x21-7E / UTF8-NONASCII
UTF8-NONASCII = %xC0-DF 1UTF8-CONT
/ %xE0-EF 2UTF8-CONT
/ %xF0-F7 3UTF8-CONT
/ %xF8-Fb 4UTF8-CONT
/ %xFC-FD 5UTF8-CONT
UTF8-CONT = %x80-BF
在TEXT-UTF8-TRIM的定义中,CRLF只允许作为头域的延长部分存在。当LWS(空格)折叠的时候,在分析TEXTUTF8-TRIM之前,会使用单个SP代替。
部分协议要素使用了十六进制数字字符。有一些要素(authentication)强制十六进制数字使用小写字母。
LHEX = DIGIT / %x61-66 ;lowercase a-f
许多SIP头域值都包含用LWS或者特殊符号分开的词。除非有额外的说明,这些符号是大小写不铭感的。当特殊字符作为参数值存在的时候,这些特殊字符必须通过引号引起来。Call-ID中建立的词组允许使用绝大部分分隔符。
token = 1 * ( alphanum / "-" / "." / "!" / "%" / "*"
/ "_" / "+" / "‘" / "’" / "?" )
separators = "(" / ")" / "<" / ">" / "@" /
"," / ";" / ":" / "\" / DQUOTE /
"/" / "[" / "]" / "?" / "=" /
"{" / "}" / SP / HTAB
word = 1*(alphanum / "-" / "." / "!" / "%" / "*" /
"_" / "+" / "‘" / "’" / "?" /
"(" / ")" / "<" / ">" /
":" / "\" / DQUOTE /
"/" / "[" / "]" / "?" /
"{" / "}" )
当标志符号或者分隔符用在要素之间是,空白通常允许在这些字符之前或者之后。
STAR = SWS "*" SWS ; asterisk
SLASH = SWS "/" SWS ; slash
EQUAL = SWS "=" SWS ; equal
LPAREN = SWS "(" SWS ; left parenthesis
RPAREN = SWS ")" SWS ; right parenthesis
RAQUOT = ">" SWS ; right angle quote
LAQUOT = SWS "<"; left angle quote
COMMA = SWS "," SWS ; comma
SEMI = SWS ";" SWS ; semicolon
COLON = SWS ":" SWS ; colon
LDQUOT = SWS DQUOTE; open double quotation mark
RDQUOT = DQUOTE SWS ; close double quotation mark
在SIP头域中可以使用注释,通过把注释放在圆括号中就可以了。只有在头域的定义中允许”comment”作为他们的头域值的一部分才可以使用注释。在其他头域中,圆括号被视同为头域值的一部分。
comment = LPAREN *(ctext / quoted-pair / comment) RPAREN
ctext = %x21-27 / %x2A-5B / %x5D-7E / UTF8-NONASCII
/ LWS
ctext包含了除了左右括号和反斜线之外的所有的字符。在双引号引起来的字符串中的字串,被视为单个词。在引起来的字串中,引号(“)和反斜线需要转码。
quoted-string = SWS DQUOTE *(qdtext / quoted-pair ) DQUOTE
qdtext = LWS / %x21 / %x23-5B / %x5D-7E
/ UTF8-NONASCII
反斜线(“\”)可以当作单个字符使用,转义机制只有在引号引起来的字符串中或者注释结构中有效。和HTTP/1.1不同的是,CR和LF不能通过这个机制来转义,这样可以避免同头的折叠的冲突。
quoted-pair = "\" (%x00-09 / %x0B-0C
/ %x0E-7F)
SIP-URI = "sip:" [ userinfo ] hostport
uri-parameters [ headers ]
SIPS-URI = "sips:" [ userinfo ] hostport
uri-parameters [ headers ]
userinfo = ( user / telephone-subscriber ) [ ":" password ] "@"
user = 1*( unreserved / escaped / user-unreserved )
user-unreserved = "&" / "=" / "+" / "$" / "," / ";" / "?" / "/"
password = *( unreserved / escaped /
"&" / "=" / "+" / "$" / "," )
hostport = host [ ":" port ]
host = hostname / IPv4address / IPv6reference
hostname = *( domainlabel "." ) toplabel [ "." ]
domainlabel = alphanum
/ alphanum *( alphanum / "-" ) alphanum
toplabel = ALPHA / ALPHA *( alphanum / "-" ) alphanum
IPv4address = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT
IPv6reference = "[" IPv6address "]"
IPv6address = hexpart [ ":" IPv4address ]
hexpart = hexseq / hexseq "::" [ hexseq ] / "::" [ hexseq ]
hexseq = hex4 *( ":" hex4)
小虎 2006-05-25 00:12
hex4 = 1*4HEXDIG
port = 1*DIGIT
对于电话描述(telephone-subscriber)的BNF说明在RFC2806[9]中。注意,无论如何,如果在这里允许的字符,如果在SIP URI中的user部分不许可,那么就一定要用转义。
uri-parameters = *( ";" uri-parameter)
uri-parameter = transport-param / user-param / method-param
/ ttl-param / maddr-param / lr-param / other-param
transport-param = "transport="
( "udp" / "tcp" / "sctp" / "tls"
/ other-transport)
other-transport = token
user-param = "user=" ( "phone" / "ip" / other-user)
other-user = token
method-param = "method=" Method
ttl-param = "ttl=" ttl
maddr-param = "maddr=" host
lr-param = "lr"
other-param = pname [ "=" pvalue ]
pname = 1*paramchar
pvalue = 1*paramchar
paramchar = param-unreserved / unreserved / escaped
param-unreserved = "[" / "]" / "/" / ":" / "&" / "+" / "$"
headers = "?" header *( "&" header )
header = hname "=" hvalue
hname = 1*( hnv-unreserved / unreserved / escaped )
hvalue = *( hnv-unreserved / unreserved / escaped )
hnv-unreserved = "[" / "]" / "/" / "?" / ":" / "+" / "$"
SIP-message = Request / Response
Request = Request-Line
*( message-header )
CRLF
[ message-body ]
Request-Line = Method SP Request-URI SP SIP-Version CRLF
Request-URI = SIP-URI / SIPS-URI / absoluteURI
absoluteURI = scheme ":" ( hier-part / opaque-part )
hier-part = ( net-path / abs-path ) [ "?" query ]
net-path = "//" authority [ abs-path ]
abs-path = "/" path-segments
opaque-part = uric-no-slash *uric
uric = reserved / unreserved / escaped
uric-no-slash = unreserved / escaped / ";" / "?" / ":" / "@"
/ "&" / "=" / "+" / "$" / ","
path-segments = segment *( "/" segment )
segment = *pchar *( ";" param )
param = *pchar
pchar = unreserved / escaped /
":" / "@" / "&" / "=" / "+" / "$" / ","
scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
authority = srvr / reg-name
srvr = [ [ userinfo "@" ] hostport ]
reg-name = 1*( unreserved / escaped / "$" / ","
/ ";" / ":" / "@" / "&" / "=" / "+" )
query = *uric
SIP-Version = "SIP" "/" 1*DIGIT "." 1*DIGIT
message-header = (Accept
/ Accept-Encoding
/ Accept-Language
/ Alert-Info
/ Allow
/ Authentication-Info
/ Authorization
/ Call-ID
/ Call-Info
/ Contact
/ Content-Disposition
/ Content-Encoding
/ Content-Language
/ Content-Length
/ Content-Type
/ CSeq
/ Date
/ Error-Info
/ Expires
/ From
/ In-Reply-To
/ Max-Forwards
/ MIME-Version
/ Min-Expires
/ Organization
/ Priority
/ Proxy-Authenticate
/ Proxy-Authorization
/ Proxy-Require
/ Record-Route
/ Reply-To
/ Require
/ Retry-After
/ Route
/ Server
/ Subject
/ Supported
/ Timestamp
/ To
/ Unsupported
/ User-Agent
/ Via
/ Warning
/ WWW-Authenticate
/ extension-header) CRLF
INVITEm = %x49.4E.56.49.54.45 ; INVITE in caps
ACKm = %x41.43.4B ; ACK in caps
OPTIONSm = %x4F.50.54.49.4F.4E.53 ; OPTIONS in caps
BYEm = %x42.59.45 ; BYE in caps
CANCELm = %x43.41.4E.43.45.4C ; CANCEL in caps
REGISTERm = %x52.45.47.49.53.54.45.52 ; REGISTER in caps
Method = INVITEm / ACKm / OPTIONSm / BYEm
/ CANCELm / REGISTERm
/ extension-method
extension-method = token
Response = Status-Line
*( message-header )
CRLF
[ message-body ]
Status-Line = SIP-Version SP Status-Code SP Reason-Phrase CRLF
Status-Code = Informational
/ Redirection
/ Success
/ Client-Error
/ Server-Error
/ Global-Failure
/ extension-code
extension-code = 3DIGIT
Reason-Phrase = *(reserved / unreserved / escaped
/ UTF8-NONASCII / UTF8-CONT / SP / HTAB)
Informational = "100" ; Trying
/ "180" ; Ringing
/ "181" ; Call Is Being Forwarded
/ "182" ; Queued
/ "183" ; Session Progress
Success = "200" ; OK
Redirection = "300" ; Multiple Choices
/ "301" ; Moved Permanently
/ "302" ; Moved Temporarily
/ "305" ; Use Proxy
/ "380" ; Alternative Service
Client-Error = "400" ; Bad Request
/ "401" ; Unauthorized
/ "402" ; Payment Required
/ "403" ; Forbidden
/ "404" ; Not Found
/ "405" ; Method Not Allowed
/ "406" ; Not Acceptable
/ "407" ; Proxy Authentication Required
/ "408" ; Request Timeout
/ "410" ; Gone
/ "413" ; Request Entity Too Large
/ "414" ; Request-URI Too Large
/ "415" ; Unsupported Media Type
/ "416" ; Unsupported URI Scheme
/ "420" ; Bad Extension
/ "421" ; Extension Required
/ "423" ; Interval Too Brief
/ "480" ; Temporarily not available
/ "481" ; Call Leg/Transaction Does Not Exist
/ "482" ; Loop Detected
/ "483" ; Too Many Hops
/ "484" ; Address Incomplete
/ "485" ; Ambiguous
/ "486" ; Busy Here
/ "487" ; Request Terminated
/ "488" ; Not Acceptable Here
/ "491" ; Request Pending
/ "493" ; Undecipherable
Server-Error = "500" ; Internal Server Error
/ "501" ; Not Implemented
/ "502" ; Bad Gateway
/ "503" ; Service Unavailable
/ "504" ; Server Time-out
/ "505" ; SIP Version not supported
/ "513" ; Message Too Large
Global-Failure = "600" ; Busy Everywhere
/ "603" ; Decline
/ "604" ; Does not exist anywhere
/ "606" ; Not Acceptable
Accept = "Accept" HCOLON
[ accept-range *(COMMA accept-range) ]
accept-range = media-range *(SEMI accept-param)
media-range = ( "*/*"
/ ( m-type SLASH "*" )
/ ( m-type SLASH m-subtype )
) *( SEMI m-parameter )
accept-param = ("q" EQUAL qvalue) / generic-param
qvalue = ( "0" [ "." 0*3DIGIT ] )
/ ( "1" [ "." 0*3("0") ] )
generic-param = token [ EQUAL gen-value ]
gen-value = token / host / quoted-string
Accept-Encoding = "Accept-Encoding" HCOLON
[ encoding *(COMMA encoding) ]
encoding = codings *(SEMI accept-param)
codings = content-coding / "*"
content-coding = token
Accept-Language = "Accept-Language" HCOLON
[ language *(COMMA language) ]
language = language-range *(SEMI accept-param)
language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) / "*" )
Alert-Info = "Alert-Info" HCOLON alert-param *(COMMA alert-param)
alert-param = LAQUOT absoluteURI RAQUOT *( SEMI generic-param )
Allow = "Allow" HCOLON [Method *(COMMA Method)]
Authorization = "Authorization" HCOLON credentials
credentials = ("Digest" LWS digest-response)
/ other-response
digest-response = dig-resp *(COMMA dig-resp)
dig-resp = username / realm / nonce / digest-uri
/ dresponse / algorithm / cnonce
/ opaque / message-qop
/ nonce-count / auth-param
username = "username" EQUAL username-value
username-value = quoted-string
digest-uri = "uri" EQUAL LDQUOT digest-uri-value RDQUOT
digest-uri-value = rquest-uri ; Equal to request-uri as specified
by HTTP/1.1
message-qop = "qop" EQUAL qop-value
cnonce = "cnonce" EQUAL cnonce-value
cnonce-value = nonce-value
nonce-count = "nc" EQUAL nc-value
nc-value = 8LHEX
dresponse = "response" EQUAL request-digest
request-digest = LDQUOT 32LHEX RDQUOT
auth-param = auth-param-name EQUAL
( token / quoted-string )
auth-param-name = token
other-response = auth-scheme LWS auth-param
*(COMMA auth-param)
auth-scheme = token
Authentication-Info = "Authentication-Info" HCOLON ainfo
*(COMMA ainfo)
ainfo = nextnonce / message-qop
/ response-auth / cnonce
/ nonce-count
nextnonce = "nextnonce" EQUAL nonce-value
response-auth = "rspauth" EQUAL response-digest
response-digest = LDQUOT *LHEX RDQUOT
Call-ID = ( "Call-ID" / "i" ) HCOLON callid
callid = word [ "@" word ]
Call-Info = "Call-Info" HCOLON info *(COMMA info)
info = LAQUOT absoluteURI RAQUOT *( SEMI info-param)
info-param = ( "purpose" EQUAL ( "icon" / "info"
/ "card" / token ) ) / generic-param
Contact = ("Contact" / "m" ) HCOLON
( STAR / (contact-param *(COMMA contact-param)))
contact-param = (name-addr / addr-spec) *(SEMI contact-params)
name-addr = [ display-name ] LAQUOT addr-spec RAQUOT
addr-spec = SIP-URI / SIPS-URI / absoluteURI
display-name = *(token LWS)/ quoted-string
contact-params = c-p-q / c-p-expires
/ contact-extension
c-p-q = "q" EQUAL qvalue
c-p-expires = "expires" EQUAL delta-seconds
contact-extension = generic-param
delta-seconds = 1*DIGIT
Content-Disposition = "Content-Disposition" HCOLON
disp-type *( SEMI disp-param )
disp-type = "render" / "session" / "icon" / "alert"
/ disp-extension-token
disp-param = handling-param / generic-param
handling-param = "handling" EQUAL
( "optional" / "required"
/ other-handling )
other-handling = token
disp-extension-token = token
Content-Encoding = ( "Content-Encoding" / "e" ) HCOLON
content-coding *(COMMA content-coding)
Content-Language = "Content-Language" HCOLON
language-tag *(COMMA language-tag)
language-tag = primary-tag *( "-" subtag )
primary-tag = 1*8ALPHA
subtag = 1*8ALPHA
Content-Length = ( "Content-Length" / "l" ) HCOLON 1*DIGIT
Content-Type = ( "Content-Type" / "c" ) HCOLON media-type
media-type = m-type SLASH m-subtype *(SEMI m-parameter)
m-type = discrete-type / composite-type
discrete-type = "text" / "image" / "audio" / "video"
/ "application" / extension-token
composite-type = "message" / "multipart" / extension-token
extension-token = ietf-token / x-token
ietf-token = token
x-token = "x-" token
m-subtype = extension-token / iana-token
iana-token = token
m-parameter = m-attribute EQUAL m-value
m-attribute = token
m-value = token / quoted-string
CSeq = "CSeq" HCOLON 1*DIGIT LWS Method
Date = "Date" HCOLON SIP-date
SIP-date = rfc1123-date
rfc1123-date = wkday "," SP date1 SP time SP "GMT"
date1 = 2DIGIT SP month SP 4DIGIT
; day month year (e.g., 02 Jun 1982)
time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
; 00:00:00 - 23:59:59
wkday = "Mon" / "Tue" / "Wed"
/ "Thu" / "Fri" / "Sat" / "Sun"
month = "Jan" / "Feb" / "Mar" / "Apr"
/ "May" / "Jun" / "Jul" / "Aug"
/ "Sep" / "Oct" / "Nov" / "Dec"
Error-Info = "Error-Info" HCOLON error-uri *(COMMA error-uri)
error-uri = LAQUOT absoluteURI RAQUOT *( SEMI generic-param )
Expires = "Expires" HCOLON delta-seconds
From = ( "From" / "f" ) HCOLON from-spec
from-spec = ( name-addr / addr-spec )
*( SEMI from-param )
from-param = tag-param / generic-param
tag-param = "tag" EQUAL token
In-Reply-To = "In-Reply-To" HCOLON callid *(COMMA callid)
Max-Forwards = "Max-Forwards" HCOLON 1*DIGIT
MIME-Version = "MIME-Version" HCOLON 1*DIGIT "." 1*DIGIT
Min-Expires = "Min-Expires" HCOLON delta-seconds
Organization = "Organization" HCOLON [TEXT-UTF8-TRIM]
Priority = "Priority" HCOLON priority-value
priority-value = "emergency" / "urgent" / "normal"
/ "non-urgent" / other-priority
other-priority = token
Proxy-Authenticate = "Proxy-Authenticate" HCOLON challenge
challenge = ("Digest" LWS digest-cln *(COMMA digest-cln))
/ other-challenge
other-challenge = auth-scheme LWS auth-param
*(COMMA auth-param)
digest-cln = realm / domain / nonce
/ opaque / stale / algorithm
/ qop-options / auth-param
realm = "realm" EQUAL realm-value
realm-value = quoted-string
domain = "domain" EQUAL LDQUOT URI
*( 1*SP URI ) RDQUOT
URI = absoluteURI / abs-path
nonce = "nonce" EQUAL nonce-value
nonce-value = quoted-string
opaque = "opaque" EQUAL quoted-string
stale = "stale" EQUAL ( "true" / "false" )
algorithm = "algorithm" EQUAL ( "MD5" / "MD5-sess"
/ token )
qop-options = "qop" EQUAL LDQUOT qop-value
*("," qop-value) RDQUOT
qop-value = "auth" / "auth-int" / token
Proxy-Authorization = "Proxy-Authorization" HCOLON credentials
Proxy-Require = "Proxy-Require" HCOLON option-tag
*(COMMA option-tag)
option-tag = token
Record-Route = "Record-Route" HCOLON rec-route *(COMMA rec-route)
rec-route = name-addr *( SEMI rr-param )
rr-param = generic-param
Reply-To = "Reply-To" HCOLON rplyto-spec
rplyto-spec = ( name-addr / addr-spec )
*( SEMI rplyto-param )
rplyto-param = generic-param
Require = "Require" HCOLON option-tag *(COMMA option-tag)
Retry-After = "Retry-After" HCOLON delta-seconds
[ comment ] *( SEMI retry-param )
retry-param = ("duration" EQUAL delta-seconds)
/ generic-param
Route = "Route" HCOLON route-param *(COMMA route-param)
route-param = name-addr *( SEMI rr-param )
Server = "Server" HCOLON server-val *(LWS server-val)
server-val = product / comment
product = token [SLASH product-version]
product-version = token
Subject = ( "Subject" / "s" ) HCOLON [TEXT-UTF8-TRIM]
Supported = ( "Supported" / "k" ) HCOLON
[option-tag *(COMMA option-tag)]
Timestamp = "Timestamp" HCOLON 1*(DIGIT)
[ "." *(DIGIT) ] [ LWS delay ]
delay = *(DIGIT) [ "." *(DIGIT) ]
To = ( "To" / "t" ) HCOLON ( name-addr
/ addr-spec ) *( SEMI to-param )
to-param = tag-param / generic-param
Unsupported = "Unsupported" HCOLON option-tag *(COMMA option-tag)
User-Agent = "User-Agent" HCOLON server-val *(LWS server-val)
Via = ( "Via" / "v" ) HCOLON via-parm *(COMMA via-parm)
via-parm = sent-protocol LWS sent-by *( SEMI via-params )
via-params = via-ttl / via-maddr
/ via-received / via-branch
/ via-extension
via-ttl = "ttl" EQUAL ttl
via-maddr = "maddr" EQUAL host
via-received = "received" EQUAL (IPv4address / IPv6address)
via-branch = "branch" EQUAL token
via-extension = generic-param
sent-protocol = protocol-name SLASH protocol-version
SLASH transport
protocol-name = "SIP" / token
protocol-version = token
transport = "UDP" / "TCP" / "TLS" / "SCTP"
/ other-transport
sent-by = host [ COLON port ]
ttl = 1*3DIGIT ; 0 to 255
Warning = "Warning" HCOLON warning-value *(COMMA warning-value)
warning-value = warn-code SP warn-agent SP warn-text
warn-code = 3DIGIT
warn-agent = hostport / pseudonym
; the name or pseudonym of the server adding
; the Warning header, for use in debugging
warn-text = quoted-string
pseudonym = token
WWW-Authenticate = "WWW-Authenticate" HCOLON challenge
extension-header = header-name HCOLON header-value
header-name = token
header-value = *(TEXT-UTF8char / UTF8-CONT / LWS)
message-body = *OCTET
26 安全考虑:威胁模式和安全应用建议。
SIP不是一个容易进行安全保护的协议。它使用的中间媒体,以及它的多面信任关系,它希望的节点之间交互基于互不信任的关系,它的用户到用户的操作使得安全保证非常重要。今天,我们需要找到基于广泛环境和使用方法的很好的安全解决方案。为了达到这一目标,我们需要建立对SIP的不同使用的几种安全机制。
注意SIP的安全性本身同SIP使用的传输协议比如RTP的安全性或者和SIP包体的实现的安全性本身没有继承关系(虽然MIME安全体系是SIP安全体系的一个基石)。任何和一个会话相关的媒介都可以被端到端的加密,并且这个和相关的SIP信令无关。媒体加密是在本文档讨论范畴之外的。
首先对一系列的经典的威胁模式的分析可以在很大程度上描绘了SIP所需要的安全需要。这些威胁模式所针对的地址需要一些安全保护,我们接下来通过对集中安全集中的详细分析,来讲述如何这些安全机制能够提供对这个地址的安全保护。接着我们就可以定义SIP实现者的需求,并且通过提供一个安全配置样例来描述应用于提高SIP安全性的这些安全机制。本节也标注了一些隐私相关的注解。
26.1 攻击和威胁模式
本节讲述了对SIP部属来说常见的威胁模式。这些威胁模式是经过特别筛选的,用来体现各个SIP所需要的安全保卫服务。接下来的例子并不是完整的针对SIP的威胁模式列表;不过他们是”经典”的例子,用来代表各类对SIP的攻击。
这些攻击假设攻击者可以从网络上读取任何报文-这是因为SIP会通常基于公共网络Internet。在网络上的攻击者通常可以更改报文内容(可能基于中间某个节点来更改)。攻击者可以希望盗取服务,窃听通讯,或者干扰会话。
26.1.1 注册服务 Hijacking。
SIP注册机制是提供一个用户UA把自己的信息到一个注册服务器上,在这个信息中,可以用address-of-record找到这个用户的地址。注册服务器会检查在REGISTER消息中的From头域所提供的身份说明,来决定是否这个请求可以修改由To头域所包含的address-of-record的相关联系地址。这两个头域通常是相同的,也会有很多第三方代替用户注册联系地址的情况。
SIP请求的From头域,可以被一个UA的拥有者任意修改,这就给恶意注册信息打开了方便之门。一个成功模拟一个UA,通过检查来修改一个address-of-record的相关联系地址,可以,例如先注销某个URI的所有联系地址,然后把自己的设备地址注册上去,这样所有对原来URI的地址的请求将发往攻击者的设备。
这种攻击属于很常见的对没有请求发前方数字签名的攻击。任何有意义的SIP UAS(比如对传统电话呼叫的SIP 网关等等),也许希望通过对收到的请求做认证来控制对自己资源的访问。就算是最终终端UA,例如SIP电话,也会有对原始请求身份的验证要求。这个威胁表明了SIP实体需要对原是请求做安全认证的安全服务需要。
26.1.2 模仿一个服务器
对于请求发送到的区域,一般是用Request-URI来标志的。UA通常直接联系这个区域中的服务器来发送请求。不过总会存在一个可能,就是攻击者把自己模仿成为远端的服务器,这样UA的请求可能会被其他人中间截获。
例如,我们考虑这样一个情况:一个转发服务器在一个区域:chicago.com,它模拟的转发服务器在另外一个区域: biloxi.com。用户UA要发送一个请求到biloxi.com,但是chicago.com的转发服务器回答了一个伪造的应答,并且有伪造的头域就好像应答是从biloxi.com回来的一样。在转发应答中的伪造的联系地址可以引导原始UA到一个不合适的或者不安全的资源,或者简单的阻止发送请求到biloxi.com。
这个常见的威胁有着许多的成员,并且相当严重。作为和注册服务hijacking相反的威胁,我们考虑这个情况: 当注册服务信息发送给biloxi.com的被chicago.com截获,并且回应给注册者一个伪造的301(Moved Permanently)应答。这个应答可能看起来是从biloxi.com来得,并且指明了chicago.com作为新的注册服务。那么这个原始UA的所有REGISTER请求就会转发到chicago.com了。
要想防止这个威胁,那么就需要UA能够对接收他们请求的服务器进行身份鉴定。
26.1.3 修改消息包体
当然,SIP UA路由请求通过信任的proxy服务器是一件必然的事情。不管这个信任关系是如何建立的(在本节的其他地方有讲proxy的认证),UA可以信任proxy来转发请求,而不是检查怀疑请求中的包体被修改了。
考虑UA使用SIP消息体来进行媒体会话的会话密钥通讯的情况。虽然它信任本域的proxy服务器,但是它也不希望域的管理者能够解密后续的媒体通讯(就是不希望proxy得到这个会话密钥)。更糟糕的是,如果这个proxy服务器是有恶意的,他可以修改这个会话密钥,就像中间人一样,或者改变原始请求UA的安全特性。
这个类型的威胁不仅仅是对会话密钥,对所有SIP端到端的内容都有威胁。这可能包含对需要展示给用户的MIME包体,SDP或者电话信令等内容的威胁。攻击者可能试图修改SDP包体,例如,给RTP媒体流增加一个窃听设备来偷听语音通话信息。
同样需要注意的是,有一些SIP头域是对端到端有一定含义的,比如Subject。UA可以决定保护这些头域和包体(比如中间恶意的攻击者可以把Subject头域更改成为看起来好像是一个恶意邮件)。不过,因为很多头域都是proxy服务器在处理请求转发的时候需要合法检查或者更改的,所以不是所有的头域都需要端到端的保护。
基于这些原因,UA可以加密SIP包体,并且对端到端的头域做一定的限制。对包体的安全服务要求包含了机密性,完整性和身份认证。这些端到端的安全服务应当与用于和中间节点交互的安全机制无关或者不依赖。
26.1.4 破坏会话
当对话被初始消息所建立,后续的请求可以用于修改对话并且/或者会话的状态。对于会话的负责者来说,非常重要的事情是确定请求不是由攻击者伪造的。
我们考虑这样一个情况,一个第三者攻击者截获了一些初始信息,这些初始信息是对话的双方在建立会话是交换的参数等等(To tag,From tag,等等),并且这个攻击者在会话中插入了一个BYE请求。攻击者可以选择假造一个从会话的任意方的请求。当一个BYE被对方接收到,会话就会被提前终止。
类似会话中的威胁,有伪造re-INVITE修改会话(可能减少会话的安全性,或者作为窃听攻击转发媒体流)。
对于这种威胁,最有效的对策就是对BYE的发送方做身份认证。在这个例子中,接受方只需要确认BYE是从建立对话的对方发起的就可以了。同样的,如果攻击者不能够知道会话的参数,他也没有办法伪造BYE。但是,有些中间节点(比如proxy服务器)需要这些参数来判定是否会话已经建立连接。
26.1.5 拒绝服务和扩展。
DOS(拒绝服务)攻击主要是使得一个特定网络节点无法工作,通常是通过转发超大量的网络通讯阻塞它的网络接口。分布式的拒绝服务攻击允许一个网络用户导致大量的网络服务器来对一个目标做洪水攻击。
在很多架构下,SIP proxy服务器是基于公网的,因为它需要处理全球的IP终端的请求。这样SIP就给这些分布式拒绝服务攻击者提供了很多机会,这样就必须要求SIP系统的设计者和管理者能够识别这样的攻击并且定位这样的攻击者。
攻击者可以发出包含假IP地址及其相关的Via头域的请求,这个Via头域标志了被攻击的主机地址,就像这个请求是从这个主机地址来的一样。然后把这个请求发给大量的SIP节点,这样不幸的SIP UA或者proxy就会给被攻击的主机产生大量的垃圾应答,从而形成拒绝服务攻击。
类似的,攻击者可以用在请求中伪造的Route头域值来标志被攻击的目的主机,并且把这个消息发送到分支proxy,这些分支proxy会放大请求数量发送给目标主机。
Record-Route头域也可以产生类似的效果。当一个攻击者确定一个被请求初始化的SIP对话会向回产生很多事务的时候,那么Record-Route头域也可以被用于攻击。
如果REGISTER请求没有经过注册服务器进行适当的认证,那么就会有很多拒绝服务的攻击的机会。攻击者可以在一个域中,首先把一些或者全部的用户都注销,从而防止这些用户被加入新的会话。接着一个攻击者可以在注册服务器上注册大量的联系地址,这些联系地址都指向同一个被攻击的服务器,这样可以使得这个注册服务器和其他相关的proxy服务器对分布式DOS攻击进行放大。攻击者也会尝试通过注册大量的垃圾来耗尽注册服务器可能的内存或者硬盘。
多点传送的SIP请求可以非常明显的增大拒绝服务攻击的可能性。
小虎 2006-05-25 00:13
这些展示的问题需要定义一个架构来把拒绝服务攻击造成的影响最小化,并且需要在安全机制中对这类攻击特别留意。
26.2 安全机制
从上边讲述的威胁来看,我们得到了SIP协议所需要的基本安全服务,他们是:保护消息的隐私性和完整性,保护重现(replay)攻击或者消息欺骗,提供会话参与者的身份认证和隐私保护,保护拒绝服务攻击。SIP消息中的包体分别要求机密性,完整性和身份认证。
比为SIP重新定义新的安全机制更好的是,SIP可以重用已经存在的HTTP或者SMTP的安全机制。
全加密的消息提供了最好的机密保护-它也可以保证消息不被恶心的中间节点更改。不过SIP请求和应答不能简单的进行端到端的加密,因为在大多数网络架构下,消息的头域比如Request-URI,Route,Via在中间经过的proxy中需要可见,这样SIP请求才能被正确路由。注意,proxy服务器需要修改一些消息的特定属性(比如增加Via头域),这样才能保证SIP正常工作。那么proxy服务器就必须被UA信任,至少在某种程度上信任。为了这个目标,我们建议为SIP提供低层次的安全机制,他们是基于节点到节点的整个SIP请求和应答的在线加密,并且语序终端节点校验他们发出请求的proxy服务器的身份。
SIP实体也可以为安全保证,需要验证对方的身份。当SIP终端向对方UA或者proxy服务器,声明它的用户的身份时,这个身份应当是可以通过某种方法验证的。SIP中的数字签名机制就是为了这个需要的。
SIP消息体的一个独立的安全(加密)机制提供了另一个端到端的相互认证方式,也降低了UA必须信任中间节点的程度。
26.2.1 通讯和网络层的安全
通讯或者网络层的安全机制是加密信号通讯,保证消息机密的和完整的传送。
很多情况下,低层次的安全是通过证书实现的,这些证书可以在很多架构下用于提供身份认证使用。
两个通常使用的方法,提供了通讯层和网络层的安全,他们是TLS[25]和IPSec[26]。
IPSec是一组网络层的协议工具,他们可以一起使用来作为传统IP通讯的安全替代。IPSec最常用于一组主机或者管理的域有一个现存的互相信任关系的架构下。Ipsec通常由主机的操作系统级别实现,或者在一个提供机密通讯和完整性保证的通讯安全网关上实现(比如VPN结构),IPSec也可以用于点到点的结构。
在很多结构下,IPSec并不要求和SIP应用一起使用;IPSec可能是最适合于部属在那种难于直接在SIP服务器上增加安全性的情况。具有预先共享密钥关系的UA和他们的第一个节点的proxy服务器很适合使用IPSec。为SIP部属的IPSec要求一个IPSec 描述了协议工具的profile。这个profile在本文档中没有提供。
TLS提供了通讯层的安全性,基于连接相关的协议(TCP)。可以通过在Via头域或者在一个SIP URI中列明”tls” (表示基于TCP的TLS)指定通讯协议为TLS。TLS最适合没有事先定义的信任关系的点到点的结构。例如Alice 信任她的本地proxy服务器,这个服务器在进行证书交换后信任Bob的本地proxy服务器,这个Bob的本地proxy服务器是Bob信任的,因此Bob可以和Alice安全的通讯。
TLS必须和SIP应用紧紧联系在一起。注意在SIP中的通讯机制是点到点的,因此一个基于TLS发送请求到proxy服务器的UA并不能保证这个TLS会在端到端的应用。
当实现者在SIP应用中使用TLS的时候,实现者必须支持最小集合的TLS_RSA_WITH_AES_128_CBC_SHA密码套件[6]。并且为了向后兼容,proxy服务器,重定向服务器和注册服务器应当支持TLS_RSA_WITH3DES_EDE_CBC_SHA。实现者也可以支持其他密码套件。
26.2.2 SIPS URI方案
SIPS URI方案是SIP URI(19节)语法的一个附加,虽然这个方案串是”sips”不同于”sip”。SIPS的语义和SIP URI的语义十分不同。SIPS 允许指定希望通过安全访问的资源。SIPS URI可以当作一个特定用户的address-of-record使用-这个用户是已知的(根据他们的名片,在他盟请求的From头域,在REGISTER请求的To头域)。当在请求中使用Request-URI,SIPS 方案指出请求经过的每一个节点,知道请求到达目的这个Request-URI指明的SIP元素,必须通过TLS进行加密;当请求抵达目标的域,他会根据目标域的本地安全策略和转发策略,很有可能最后一部也是用TLS到达UAS。当用在请求的发起方(就像这种情况,当他们使用SIPS URI当作目标的address-of-record一样),SIPS只是这个实体请求,到目的主机的所有路径都应当加密。
SIPS方案适用于很多在SIP中应用的SIP URI,比如附加域Request-Uri,包含在address-of-record,联系地址(Contact的内容,包含REGISTER方法的头域等等),还有Route头域等等。在每个用法中,SIPS URI方案允许这些存在的URI来指明需要安全访问的资源。这些由SIPS URI所替换的东西,有他们自己的安全属性([4]中详细介绍)。
对SIPS的使用在细节上要求必须具备TLS互相的认证,并且要求支持密码套件TLS_RSA_WITH_AES_128_CBC_SHA。在认证过程中接收到的信任书应当从客户端持有的信任书跟节点开始验证;对信任书验证失败应当导致请求的失败。
注意在SIPS URI方案中,通讯层是和TLS没有依赖关系的,并且因此”sips:alice@atlanta.com;transport=tcp”和”sips:alice@atlanta.com;transport=sctp”都是合法的(虽然注意到UDP不能用于SIPS的传送)。我们不建议使用类似”transport=tls”的方式,部分原因是因为这是用于请求的单个节点之间的通讯。这是从RFC2543的一个变化。
将address-of-record用SIPS URI发出的用户,如果在非可靠通讯协议上收到的请求,可以操作设备来拒绝这个请求。
26.2.3 HTTP Authentication
SIP提供了认证机制,基于HTTP认证的身份认证机制,他们依赖于401倒407应答码和相关头域来提供拒绝不信任的信任书。对于SIP使用的HTTP Digest认证机制,并没有做重大的修改,它提供了replay攻击的保护和单向认证关系。
对SIP的Digest 认证使用在22节有描述。
26.2.4 S/MIME
就像上边讲述的,在端到端的过程中加密整个SIP消息体,可以提供机密性的保护,但是并非所有的字段都能使用这个机制进行保护,因为中间的网络节点(比如proxy服务器),需要根据读取适当的头域然后决定这个消息应当转发倒哪里,并且如果这些中间节点由于安全原因被排出在外,那么SIP消息从本质上就是不能路由的。
不过,S/MIME允许SIP 的UA在SIP中加密MIME包体,在不影响消息头的情况下,在端到端的通讯中加密这些MIME包体。S/MIME可以提供消息体的端到端的完整性和机密性,同样也提供了双向的认证机制。使用S/MIME也可以通过SIP消息隧道,为SIP头域提供一个完整性和机密性的方案。
对SIP的S/MIME使用在23节讲述。
26.3 安全机制的实现
26.3.1 对SIP实现者的要求
proxy服务器,重定向服务器,和注册服务器必须实现TLS,并且必须支持双向的和单向的认证关系。强烈建议UA可以初始化TLS;UA同样可以作为一个TLS服务器。proxy服务器,重定向服务器和注册服务器应当有一个站点信任书,这个信任书的主题和他们的规范主机名相关。对于TLS的双向认证,UA可以有他们自己的信任书,但是本文档中,没有规定他们的具体用法。所有的支持TLS的SIP元素必须具备在TLS协商中,验证信任书的机制;这个使得证书机关(可能是有名的类似web浏览器证书发行机构的发行机构)发布的一个或者多个根信任书成为必须。所有支持TLS的SIP元素必须同样支持SIPS URI方案。
Proxy服务器,重定向服务器,注册服务器,和UA可以实现IPSec或者其他底层的安全协议。
当UA试图联系一个proxy服务器,重定向服务器或者主阿服务器,UAC应当初始化一个TLS连接,在这个连接上发起SIP消息。在某些结构吓,UAS可以同样在这些TLS接收请求
Proxy服务器,重定向服务器,注册服务器,和UA必须实现Digest身份认证,包括所有的22节要求的要点。Proxy服务器,重定向服务器,注册服务器应当配置成为至少有一个Digest realm,并且对于给定服务器来说,必须支持至少有一个”realm”字符串和这个服务器的主机名或者hostname相关联。
UA可以支持MIME包体的加密,并且通过23节描述的那样使用S/MIME传送信任书。如果UA具有一个或者多个根身份认证的信任书,用来鉴定TLS或者IPSec的信任书,它应当适当的可以用这些来鉴定S/MIME的信任书。UA可以为S/MIME身份认证而具有特定的根信任书。
注意,随着S/MIME实现,将来会有安全扩展,来提高S/MIME的强度。
26.3.2 安全解决方案
这些安全机制的操作,可以在某种程度上和现存的WEB和EMAIL安全模式一致。在高一点的级别来看,UA通过Digest 用户名和口令把他们自己的身份向服务器(proxy服务器,重定向服务器,注册服务器)认证;服务器把他们自己向UA单节点认证,或者向另外一个服务器进行单节点(one hop)认证(反之亦然),并且是通过TLS来传送服务器节点信任书。
在点对点的级别,UA一般信任网络来进行对方身份的鉴别;不过,如果网络不能够鉴定对方身份,或者网络本身不被信任的情况下,也可以使用S/MIME来提供直接的身份认证。
接下来是一个例子,在这个例子中,不同的UA和服务器使用这些安全机制防止26.1节描述的攻击威胁。实现者和网络管理员可以遵循本节末尾给出的指示来防止攻击威胁,这些指示是作为实现例子提供的。
26.3.2.1 注册
当UA上线,并且注册到它自己的域上,它应当和它的注册服务器建立一个TLS连接(10节描述了UA怎样找到它的注册服务器)。注册服务器应当提供一个信任书给UA,并且这个信任书的节点必须是这个UA想要注册的域相关的信任书节点;例如,如果UA向注册alice@atlanta.com这个address-of-record,这个信任书节点必须是一个atlanta.com域的主机(比如sip.atlanta.com)。如果它收到了TLS信任书消息,UA应当校验这个信任书,并且检查这个信任书的节点。如果信任书是非法的,作废的,或者它和持有者不符,UA必须不能发送REGISTER消息和进行注册处理。
当UA收到注册服务器提供的一个有效的信任书,UA知道注册服务器并非一个攻击者(可能重定向、窃取口令、或者试图做类似攻击的攻击者)。
于是UA创建了一个REGISTER请求,并且Request-URI应当指向从注册服务器所接收到的信任书站点。当UA通过刚才建立的TLS连接发送REGISTER请求,注册服务器应当给出一个401(Proxy Authentication Required)应答。在这个应答中,Proxy-Authenticate头域的”realm”参数,应当和前边给出的信任书节点的域相同。当UAC收到这个拒绝,它应当提示给用户要求信任书,或者根据应答中的”realm”参数,从现有的密钥组中查找对应的信任书。这个信任书的用户名应当和REGISTER请求的To头域的URI的”userinfo”部分相关。当在一个合适的Proxy-Authorization头域中插入和这个信任书,REGISTER应当重新发送到注册服务器。
由于注册服务器要求UA认证它自己,对于攻击者来说,伪造一个用户的address-of-record的REGISTER请求是很困难的。同样注意到由于REGISTER是通过机密的TLS连接发送的,攻击者不能通过截取REGISTER来记录信任书来进行重放攻击。
当注册请求被注册服务器接收,UA应当继续保持TLS连接,这样使得注册服务器可以既当作proxy服务器,这个proxy服务器可以作为管理这个域的proxy服务器。刚完成注册的TLS连接会继续保留用于接收UA后续发起的请求。
由于UA已经通过在TLS连接的对方的服务器的认证,所有在这个连接上的请求都是经过proxy 服务器的(由于保留了TLS连接,也就是说,刚才的注册服务器更换了角色,变成一个proxy服务器)--攻击者不能伪造好像是刚才从这个proxy服务器发送的请求。
26.3.2.2 在域之间的请求
现在我们说,Alice的UA希望和远端管理的域的一个用户,这个用户叫做”bob@biloxi.com”,初始化一个会话。我们讲会说本地管理的域(atlanta.com)有一个本地外发proxy。
对于一个管理域的Proxy服务器处理那发请求,可以同样作为本地的外发proxy;基于简单的原则,我们假定这就是atlanta.com(否则这时候UA将要初始化一个新的TLS连接到一个独立的服务器)。假定这时候,这个客户端已经完成了注册(参见前边的步骤),当它发出INVITE请求邀请另外一个用户的时候,它将重用这个TLS连接到本地proxy服务器(刚才的注册服务器)。这个UA在INVITE请求中,将会重用刚才cache的信任书,这样可以避免不必要的要求用户输入信任书。
当本地的发外服务器验证了这个UA在INVITE请求中的信任书,它应当检查Request-URI来决定这个消息应当如何路由(参见[4])。如果这个Request-URI的”domainname”部分和一个本地域相关联(atlanta.com)而不是和biloxi.com相关,那么proxy服务器会向本地服务查询来决定怎样最好的访问到被呼叫的用户。
“alice@atlanta.com”正在尝试联系呼叫”alex@atlanta.com”,本地proxy将会转发这个请求到Alex和它的注册服务器所建立的TLS连接上。由于Alex将会通过它的已经通过认证的连接上收到这个请求,它就确定这个Alice的请求是通过了本地管理域的proxy的身份验证的。
不过,在这个例子中,Request-URI指向的是一个远程域。在atlanta.com的本地外发服务器应当因此而建立一个和在biloxi.com的远程proxy服务器的TLS连接。由于这个TLS连接的两端都是服务器,并且都有服务器的信任书,那么应当使用双向的TLS身份认证。连接的双方应当验证和检查对方的信任书,把在信任书中的域名同SIP消息中的头域做比较。例如,atlanta.com 这个proxy服务器,在这步,应当检查从对方接收到的关于biloxi.com域的信任书。当检查完毕,并且TLS协商完成,就建立了基于两个proxy的安全通道,atlanta.com proxy于是可以把INVITE请求转发给biloxi.com了。
在biloxi.com的proxy服务器应当检查atlanta.com的信任书,并且比较信任书提供的域名和INVITE请求的From头域的”domainname”部分。这个biloxi proxy可以执行严格的安全机制,拒绝那些他们被转发的域和本proxy所管理的域不匹配的请求(这个不太明白)。
这些安全机制可以用来防止SIP和SMTP ‘open relays’一样经常被用于产生垃圾邮件一样的信息。
这个政策,只是保证了请求声明的来源确实是它自己;他并不允许biloxi.com确知如何atlanta.com认证的Alice。只有当biloxi.com由其他方法知道atlanta.com的身份认证机制,他才可能确知Alice如何证明她的身份的。biloxi.com可以接着使用更严格的方法,禁止来自未确定和biloxi.com相同的认证策略的域的请求(就是说所有biloxi.com接受的请求,都必须来自biloxi.com所知道身份认证方式的域)。
当INVITE请求被biloxi.com核准,proxy服务器应当鉴别现存的TLS通道,如果存在现存的TLS通道,并且是和这个请求中的被叫用户(在这个例子中是bob@biloxi.com)相关联的。那么这个INVITE请求应当通过这个TLS通道发送给Bob。由于通过这个TLS连接收到的请求,这个TLS连接是刚才已经在biloxi proxy上通过了身份认证,Bob于是知道From头域没有被篡改,并且atlanta.com已经认证了Alice,所以就没有必要犹豫是否信任Alice的身份。
在他们转发请求钱,两个proxy服务器应当在请求中增加Record-Route头域,这样所有在这个对话中的后续的请求讲过通过这两个proxy服务器。proxy服务器因此可以在对话生存周期中,继续提供安全服务。如果proxy服务器并不在Record-Route头域增加他们自己,以后的消息将会直接端到端的在Alice和Bob中发送,而没有任何安全措施(除非两个端点使用了某种独立的端到端的安全措施,比如S/MIME)。在这个考虑上,SIP梯形模式可以提供一个精美的结构来在proxy服务器节点之间进行磋商,以提供一个Alice和Bob之间的有道理的安全通道。
例如,一个攻击这个结构的攻击者将会不能伪造BYE请求并且把他插入Bob和Alice的信令流,因为攻击者无从探听会话的参数,这也是由于通讯的完整性机制保证了Alice和Bob之间的通讯是机密的完整的。
26.3.2.3 点对点请求
另外,考虑这样一个情况,UA声称carol@chicago.com没有一个本地外发proxy。当Carol希望发送INVITE到bob@biloxi.com,她的UA应当直接初始化一个TLS连接到biloxi proxy(使用附件[4]中描述的机制来检查怎样到达指定的Request-URI)。当她的UA收到一个biloxi proxy发送的信任书,她应当在通过TLS连接发送她的INVITE请求前,正常校验这个信任书。不过,Carol并没有义务相biloxi proxy提供她自己的身份,但是她在INVITE请求的”message/sip”包体中,有一个CMS-detached(分离的)签名。如果Carol在biloxi.com realm有其他信任书的话,就不一定提供这个签名,但是她在biloxi.com上没有正式关系,所以她没有信任书,也就必须提供这个签名。biloxi proxy可以有严格的机制直接把这个请求踢掉,甚至不用麻烦被叫方来验证这个请求,因为在From头域的”domainname”部分,并没有biloxi.com-它可以被当作这个用户是未认证的。
biloxi proxy对于Bob用户有一个政策,就是所有未认证的请求都应当转发到一个适当的地址,对于bob@biloxic.om,就是<sipo:bob@192.0.2.4>。Carol在和biloxi proxy建立的TLS连接上,收到这个转发请求的应答,于是它信任这个转发地址的真实性。
Carol应当和目标地址建立一个TCP连接,并且发送一个新的INVITE请求,在这个请求中,Request-URI包含刚才接收到的联系地址(需要重新计算包体中的签名,因为请求重新构造了)。Bob从不安全的界面上接收到这个INVITE请求,但是这个UA是特意预留一个不安全的界面,在这个情况下,认可请求中的From头域并且随后把INVITE包体中的签名和一个本地cache的信任书进行匹配。Bob用类似的方法应答,把他自己相Carol进行认证,这样一个安全的对话就开始了。
某些情况下,在一个域的NAT或者防火墙会阻止UA之间直接建立TCP连接。在这个情况下,如果本地策略许可,proxy服务器可以隐含的做UA之间的请求转发,并且这个转发是基于没有信任关系的(比如不用现存的TLS连接,而是通过TCP明码的请求转发)
26.3.2.4 DoS 防护
基于这些安全解决方案,为了使得拒绝服务(DoS)攻击造成的影响最小,实现者应当注意如下的指引:
当SIP proxy服务器所在的主机是基于公共internte做路由的,他应当部署在一个具有防护操作策略的管理域中(比如block源路由,过滤ping包等等)。TLS和IPSec都可以在管理域的边界的防护主机,一起参与安全系统的构家,来提高安全性。这些防护主机可以防护拒绝服务攻击,确保在管理域中的SIP主机不会被大量的消息阻塞。
不管使用什么样的安全措施,对proxy服务器的洪水消息攻击可以耗尽proxy服务器的资源,并且阻止发送到目的地的正确的请求。对于proxy服务器来说,每一个SIP事务都会好用一定的资源,对于有状态的服务器来说这个消耗会更大。因此,有状态的proxy比无状态的proxy更容易受到洪水攻击的影响。
UA和proxy服务器应当用一个401(Unauthorized)或者407(Proxy Authentication Required)拒绝有问题的请求,并且对这些有问题的请求不使用正常的应答重发机制,并且对这些未认证的请求把自己当作无状态的服务器使用。如果攻击者使用假的头域值(例如Via)指向一个第三方的被攻击的服务器,那么对于401(Unauthorized)或者407(Proxy Authentication Required)应答的重发可能正中攻击者的下怀。
总得来说,基于TLS签名的proxy服务器之间的双向认证机制,降低了中间节点潜在的风险,并且减少了可以用作拒绝服务攻击的伪造的请求或者应答。这也同样提高了攻击者利用无知的SIP节点进行放大攻击的难度。
26.4 限制
虽然有这些安全机制,在正确应用的时候,可以阻止很多攻击,但是对于网络管理者和开发者来说,也必须明白他们也会有很多限制的地方。
26.4.1 HTTP Digest
在SIP中对于HTTP Digest一个限制是Digest的完整性机制在SIP下运作的不是很完美。尤其是,他们提供了对消息中的Request-URI和方法的保护,但是并没有对UA希望提供加密的所有头域进行了保护。
RFC2617所提供的回放攻击保护对于SIP来说也有一些限制。例如,next-nonce机制,并不支持通过管道传送的请求。防止回放攻击应当使用nonce-count机制。
另一个HTTP Digest限制是realm的范围。当用户希望把他们自己的身份向一个资源(这个资源和他们有着预先存在的关系)进行认证的时候,Digest是有用的,它就像一个服务提供者,用户是一个客户端(这是十分常见的场景,因此Digest提供了一个十分有用的功能)。与之对应的,TLS的范围是基于域之间的,或者multirealm的,因为信任书通常是全局可验证的,所以UA可以在不需要预先存在关系的服务器上进行身份验证。
26.4.2 S/MIME
对于S/MIME的一个最大的限制是对终端用户来说,缺少广泛的公共密钥机构。如果使用的是自签名(selfsigned)信任书(或者信任书不能被对话的对方所验证),23.2节描述的基于SIP的密钥交换机制就容易遭受中间人攻击(man-in-the-middle),在这个中间人攻击中,攻击者可以悄悄检查和修改S/MIME包体。攻击者需要截取对话中,双方的第一个密钥交换,在请求和应答中移去现有的CMS-detached签名,并且插入另外的包含攻击者提供的信任书(但是看起来像是正确地address-of-record的信任书)的CMS-detached 签名。通讯的双方都回以为他们和对方交换了密钥,实际上他们互相有的只是攻击者的公钥。
必须明确注意到攻击者只能攻击双方的第一次的密钥交换-在后续的情况,密钥的变更对于UA来说就是不可见的了。同样使得攻击者难以窃听对话双方的以后的对话中(比如一天内的对话,周内的,或者一年的对话)。
SSH在第一次密钥交换的时候,也同样容易受到这个中间人攻击;但是,虽然众所周知SSH不完美,但是它确实提高了连接的安全性。对于SIP来说,使用密钥的指纹可以有些帮助,就像在SSH中一样。例如,如果SIP的双方建立了一个语音通讯会话,每一个都可以读取对方传送的密钥指纹,并且可以根据这个指纹和原始指纹做比较。这使得中间人更加难以在语音中模拟通话双方的密钥指纹(实际上这个在Clipper 基于芯片的保密电话中使用)。
在S/MIME机制下,如果UA在他们的密钥组中持有对方address-of-record的信任书,允许UA不用导言来发送加密的请求。不过,存在这个样的情况,如果某个设备注册了这个address-of-record,并且没有持有持有设备当前用户先前使用的信任书。并且它将因此不能正常处理加密的请求,于是可能会导致某些原本可以避免的错误信号。这很像加密的请求被分支的情况。
S/MIME相关的密钥通常用于和特定用户(一个address-of-record)关联起来使用,而不是和一个设备(UA)一起使用。当用户在设备之间移动,很难把私钥安全的在UA之间传递;一个设备如何获得这些密钥不在本文讨论。
另外,使用S/MIME更常见的困难是,它可以导致很大的消息,特别是当采用23.4节的SIP隧道戒指的时候。基于这个原因,当使用S/MIME隧道机制的时候,一定要使用TCP通讯协议。
26.4.3 TLS
TLS最大的问题是,它不能基于UDP;TLS要求面向连接的底层通讯协议,对于本文来说,就是TCP。
对于TLS来说,在本地外发proxy服务器和/或者主车服务器上和大量UA,维持很多并发TLS长连接,是一件费力的事情。这导致某些容量问题,特别是在使用加强密钥套件的时候更容易出现容量问题。维持冗余的TLS长连接,特别是当UA独立负责他们的连接,会很耗资源。
TLS只允许SIP实体到他们临近的认证服务器的连接;TLS提供了严格的节点到节点的安全性(hop-by-hop)。无论TLS,还是其他本文档规定的安全机制,当不能直接建立TCP连接的情况下,都允许客户通过验证自己到proxy服务器来到达目的地。
26.4.4 SIPS URI
实际上在请求经过的每一段都使用TLS,要求了最终的UAS必须能够通过TLS到达(也许是通过SIPS URI作为一个联系地址注册的)。通常这个目的地是用SIPS描述的。在很多结构下,使用TLS保护一部分请求路径,最后一部确实依赖于其他的安全机制到UAS。因此SIPS不能保证TLS是真正的端到端的使用。注意,这是由于许多UA不接受进来的TLS连接,甚至那些支持TLS的UA也可能要求要维持一个永久的TLS连接(就像前边的TLS限制节讲述的一样),目的是为了作为UAS从TLS上接收请求。
位置服务,对于SIPS Request-URI来说,是不要求提供SIPS绑定的。虽然位置服务通常由用户注册(10.2.1节描述)组成,但是对于一个address-of-record来说,可以由不同的协议和界面都可以提供联系地址,并且这些工具都可以用来映射SIPS URI到适当的SIP URI。当对绑定信息查询的时候,位置服务返回它的联系地址,而不关心这个是否是从一个SIPS的Request-URI上收到的请求。如果是转发服务器访问位置服务,那就是说取决于处理转发的Contact头域的SIP实体来决定联系地址的属性。
如果要求请求经过的全部路径都使用TLS通讯,那么对目的域来说稍稍有点麻烦。如果实现困难,也允许在请求传送节点中的基于密码认证的proxy服务器,不兼容或者选择一个折中方案来略过SIPS的转发机制(在16.6节定义的通常转发规则)。但是,恶意的中间节点就有可能把一个基于SIPS URI的请求,重新降级成为SIP URI。
另外,中间节点也可以正常的把一个基于SIP的请求更改成基于SIPS URI的请求。请求的接受方发现请求的Request-URI是基于SIPS URI方案的并不能假设原始请求的Request-URI也是基于SIPS通过中间节点传送的(从客户端往后)。
为了解决这个问题,我们建议请求的收件人,在请求的Request-URI包含一个SIP或者SIPS URI的情况下,检查To头域值,看看是否包含一个SIPS URI(虽然注意到Request-URI可以和To头域URI有相同的URI方案,但是他们不相等并不意味者是一个安全隐患)。虽然客户端可以在一个请求中把Request-URI和To头域做成不一样的,但是当两个字段的SIPS不一样的话,那就是可能的安全隐患,并且请求因此应当被接受方拒绝。接受方也可以检查Via头域链来双重检查是否TLS在整个请求路径中被使用,一直到最近的本地管理域。源UAC也可以用S/MIME来帮助确保原始格式的To头域被端到端的发送。
如果UAS有原因来相信Request-URI的URI方案在通讯中被非法修改,UA应当提示用户这个潜在的安全隐患。
作为更深远的考量,为了防止底层的攻击,如果SIP实体只接受SIPS请求,那么可以拒绝在非安全端口的连接。
终端用户应当完全清楚SIPS和SIP URI的区别,他们可以在应答中手工更改这个URI方案。这可以增加或者降低安全性。例如,如果一个攻击者攻陷了一个DNS的cache,插入了一个假的记录集,这个记录集有效删去了一个proxy服务器的所有SIPS记录,接着经过这个proxy服务器的SIPS请求就会失效。这时候,一个用户,看见这个SIPS address-of-record总是失败,他可以手工改掉URI从SIPS改成SIP,并且重试。当然,这也有一些安全机制防止这类事情发生(如果目标UA真是有神经病拒绝所有非SIPS请求的话)。但是这个限制毫无价值。往好了想,用户也可以把SIP URI变成SIPS URI。
26.5 Privacy(隐私)
SIP消息经常包含发送者的敏感信息-不只是他们将说些什么,也包括了他们和谁在通讯,以及他们通讯了多久,以及从那里到哪里的通讯等等。很多应用和他们的用户都要求这类隐私信息对于没有必要知道的方面来说都必须保持隐秘。
注意,也有隐私信息也有少数直接泄漏的方式。如果用户或者服务,位于一个容易猜到的地址,比如通过用户的名字或者机构的联系(这是构成Address-of-record的最经常的情形),传统保证隐私性的方式是通过一个未列出的”电话号码表”来实现的。在呼叫方发起的会话邀请中,用户位置服务可以提供精确的被叫方的位置从而破坏了隐私;在实现上因此应当更严格,基于每用户的原则,根据不同的呼叫方给出不同的位置信息和可用性的信息。这是一个SIP需要解决的完整的问题。
在某些情况下,用户可能希望在通过身份验证时,在头域中隐藏个人信息。这可以应用于不仅是From和相关表现请求发起方信息的头域,也应用于To头域-他可能不能由快速拨号的nick-name转换成为最终的目的地信息,或者一个为扩展的一组目标的标志,当请求被路由的时候,每一个都可以从Request-URI上被移去,但是如果和To头域初始值相等的时候,不能更改To头域。因此,他可能由于隐私的原因创建和Request-URI不同的To头域。
27 IANA 认证
SIP应用中的所有的方法名字,头域名字,状态码,和option tags,都是通过RFC中关于IANA认证节的说明在IANA注册的。
本规范指示IANA创建了4个新的子注册项目在:http://www.iana.org/assignments/sip-parameters: Option Tags,Warning Codes(warn-codes),Methods和Response Codes,头域的子项也在那里。
27.1 Option Tags
这个规范在http://www.iana.org/assignments/sip-parameters建立了Option Tags注册项.
Option tags用于类似Require,Supported,Proxy-Require,Unsupoprted这类的头域,用来支持SIP的扩展兼容性机制(19.2节)。Option tag自身时一个字符串,和特定的SIP选项相关(也就是和特定的SIP扩展相关)。它为SIP终端确定这个选项。Option tags当被标准的RFC轨迹扩展,它就在IANA注册了。RFC的IANA认证节必须包含如下内容,这些内容与RFC出版号码一起在IANA注册表登记。
o option tag的名字。名字可以是任意长度的,但是应当不要超过20个字母。丙子必须是alphanum(25节)字符。
o 描述扩展的描述信息
27.2 Warn-Codes
本规范在http://www.iana.org/assignments/sip-parameters建立了Warn-Codes注册项。并且初始发布的warn-codes值在20.43节列出。附加的warn-codes通过RFC出版物注册发表。
对于warn-codes表的描述信息如下:
当一个会话描述协议(SDP)(RFC 2327[1])出现问题导致事务失败的时候,Warning codes在SIP应答信息中提供了对状态码的补充信息。
“warn-code”包含了3位数字。第一个数字”3”表示warning是SIP的警告信息。除非以后另有描述,只有3xx警告信息可以被注册。
300到329的警告信息为会话描述保留字错误保留,330到339为会话要求基本网络服务错误保留,370到379是为会话描述要求的QoS参数数量错误保留,390到399是无法归类的杂项警告信息。
27.3 头域名
本规范在http://www.iana.org/assignments/sip-parameters建立了头域的注册项。
为了注册一个新的头域名,下列信息需要在RFC出版物中提供,
o 头域注册的RFC号码
o 注册的头域名
o 如果有缩写,头域的缩写版本。
部分常用的头域可以缩写成1个字母的简写形式(7.3.3节)。简写形式只能在SIP工作组复查的时候被登记在RFC出版物上。
27.4 方法和应答码
本规范在http://www.iana.org/assignments/sip-parameters建立了Method和Response-code的注册项。并且下边列出了他们的初始值。初始的方法表如下:
INVITE [RFC3261]
ACK [RFC3261]
BYE [RFC3261]
CANCEL [RFC3261]
REGISTER [RFC3261]
OPTIONS [RFC3261]
INFO [RFC2976]
应答码的初始值在21节列出,分为信息部分(Informational),成功(Success),转发(Redirection),客户端错误(Client-Error),服务端错误(Server-Error),全局错误(Global-Failure)几个部分。这个表格有如下格式:
类型(Type,就是Informational), Number, Default Reason Phrase [RFC3261]
如下信息需要提供给RFC出版机构来注册新的应答码或者方法:
o 应答码和方法需要注册的RFC号码
o 应答码号码或者方法名
o 缺省应答码的原因说明
27.5 “message/sip” MIME类型
本文档注册了”message/sip”MIME媒体类型,目的是允许SIP可以通过SIP包体隧道,首要用于端到端的安全保障。这个媒体类型由如下部分组成:
媒体类型名字: message
媒体子类型: sip
要求的参数: none
可选的参数: version/Encoding scheme/Security considerations
version: 这个打包的消息的SIP-version号码(比如”2.0”)。如果没有提供,version的缺省值就是”2.0”。
Encoding scheme: SIP消息包含一个8位的头,在二进制的MIME数据对象后边可选。同样的,SIP消息必须把这个当作一个二进制值。在通常情况下,SIP消息通过二进制兼容的通讯协议传送,不需要特别的编码方式。
Security considerations: 本参数用于同23.4给出的S/MIME安全机制一致,请参见下边的例子和说明。
27.6 新Content-Disposition 参数注册
本文档也注册了4个新的Content-Disposition头”disposition-types”: altert,icon,session和render。作者要求这些值在IANA中为Content-Disposition登记。
对于”disposition-types”的描述,包括例子和说明,在20.11中说明。
在IANA注册中的简单描述是:
alter 包体是一个客户定义的铃声用于提醒用户。
icon 包体是一个显示给用户的icon
render 包体应当显示给用户
session 包体描述了一个通讯会话,例如RFC2327 SDP包体
28 同RFC 2543的改变
这个RFC修订了RFC 2543。它主要和RFC2543向后兼容。这里描述的变更主要修订了RFC2543中发现的错误,并且提供了在RFC2543中没有提及的相关情节信息。在本文中,协议以更清晰的层次结构描述。
我们把和RFC2543的永久改变,分成按功能行为划分这些区别。比如在互操作上不兼容,或者修正了某些情况下的错误操作,以及和RFC2543功能行为不同但是不是一个潜在的兼容性问题。以及有数不清楚的澄清,在本文中没有提及。
28.1 主要的功能改变
o 在UAC还没有给出应答之前,UAC希望终止一个会话,它发送CANCEL来终止。如果原始INVITE依旧给出2xx应答,那么UAC接着发送BYE。BYE只能发给现存的呼叫对话(leg)中(在这个RFC中成为对话(dialog)),但是在RFC2543中可以在任何时间发送BYE。
o SIP的BNF改成RFC2234兼容的了。
o SIP URL的BNF更改的更加通用,在user部分,允许一个很大的字符集。此外,比较规则也简化为首先大小写不敏感,接着详细比较各个参数。最主要的变化是带参数的URI和不带这个参数(但是缺省值相等)的URI 判定是不相等的。
o 删除了隐藏的Via。这要求发出绝对的信任,由于它依赖于下一个节点来执行这个不明确的操作。作为替代,Via隐藏可以通过在proxy服务器上的本地实现选择完成,于是在这里不在说明。
o 在RFC2543,CANCEL和INVITE请求是混和的。他们现在分开了。当用户发出一个INVITE请求接着CANCEL掉,INVITE事务将正常终结。UAS应当对原始INVITE请求给出一个487应答。
o类似的,CANCEL和BYE事务也是混和的;RFC2543允许UAS在收到BYE的时候,不给INVTE请求发送应答。本文档不允许这种情况出现。原始的INVITE请求需要一个应答。
o 在RFC2543中,UA需要支持只有UDP的情况。在这个RFC中,UA应当支持UDP和TCP。
o 在RFC2543中,forking 分支proxy在收到多个拒绝应答的时候,只向下行元素发出一个拒绝身份认证应答,在这个RFC中,proxy应当搜集所有的拒绝并且把他们放在应答中发送。
o 在Digest信任书中,URI需要被引号引起来;这个在RFC2617和RFC2069是不一致的。
o SDP处理被分为独立的规范[13],并且更全面的描述了正式的通过SIP包体隧道进行的offer/answer交换过程。作为SIP实现基线,SIP允许在INVITE/200或者200/ACK中存在;RFC2543间接指出了在INVITE,200和ACK中的单个事务使用这个方法,但是这个在RFC2543中没有很好的定义。在SIP扩展中允许使用更复杂的SDP。
o 增加了对URI中和在Via头域中的IPV6的全面支持。Via头域允许方括号和冒号的参数,要求对Via头域的IPV6的支持。这些字符在先前是不允许的。在理论上,这颗一导致和旧规范实现上的相互操作的问题。不过,我们观察到大部分实现在这个参数上,接受非控制ASCII字符。
o DNS SRV处理步骤现在使用了单独的规范[4]。这个步骤使用了SRV和NAPTR资源
小虎 2006-05-25 00:13
记录,并且不在合并从SRV记录的数据(RFC2543)。
o 循环检测变成可选的了,替代为强制使用Max-Forwards参数。这个循环检测在RFC2543由严重bug,可能会在正常情况下把”螺旋”报告成为一个错误。在这里,可选的循环检测步骤是更加全面的和正确的。
o 由于他们现在在对话中是作为识别对话的基本要素存在,所以,对tag的使用是强制的(他们在RFC2543中是可选的)。
o 增加了Supported头域,允许客户端向服务器表示它支持什么样的扩展,服务器可以根据这个字段决定给出包含什么样扩展的应答,并且把他们需要的扩展支持放在Require字段里边。
o 几个头域的扩展参数的BNF描述在RFC2543中忽略了,这里增加了。
o 处理Route和Record-Route的构在在RFC2543中是很不规范的,并且也不正确。它在本规范中更改成为规范正确的(并且大大简化了)。这是很大的改变。对于没有使用”预先加载路由的”部属情况下(在预先加载路由的时候,初始的请求有一个Route路由集合,这个集合不是由Record-Route构造的),依旧提供了向后兼容性。在预先加载路由的情况下,新旧机制是不能互相操作的。
o 在RFC2543中,消息中的行是可以由CR/LF/或者CRLF终端的。本规范只允许CRLF。
o 在CANCLE和ACK请求中的Route的使用,在RFC2543中没有精确定义,在本文档中定义了;如果请求有一个Route头域,他的为一个给请求的非2xx应答的CANCEL或者ACK应当包含相同的Route头域。为2xx应答的ACK请求使用2xx应答的Record-Route构造Route头域值。
o RFC 2543允许一个UDP包中多个请求。这个使用方法在本文档中删去了。
o 对于Expires头域和参数中的绝对时间的使用方式被删去了。当各个节点之间时间不同步的时候,他会带来户操作的问题。本文档使用相对时间。
o Via头域中的branch参数现在是强制每一个元素都使用。它现在作为事务的唯一标志。这避免了RFC2543容易出错的事务鉴别规则的复杂性。我们在这个参数值使用一个乱数cookie来检查上一个节点产生的这个参数是否全局唯一的,如果不是,那么旧采用旧的比较规则。因此,保证了互操作性。
o 在RFC2543,对TCP连接的关闭和CANCEL是相同的。当TCP连接在两个proxy之间的时候,这在实现上是几乎不可能的(也是错误的)。这个要求在这里被删去了,所以,TCP连接状态和SIP处理之间没有直接关系。
o RFC2543中,当UA到一个节点可以初始化一个新的事务,当对方正在进行事务处理的时候。在这里被精确定义了。只允许初始化非INVITE请求,不允许INVITE请求。
o PGP被删去了。它没有很充分的定义,并且和更复杂的PGP MIME不兼容。替换成为S/MIME。
o 增加了”sips” URI方案用于端到端的TLS通讯。这个方案是和RFC2543不能年个兼容的。现有的节点如果接收到请求的Request-URI中包含SIPS URI方案,将拒绝这个请求。这实际上是一个特性;它保证了对SIPS URI只会在所有节点都是安全的情况下被传送。
o 在TLS上附加了安全特性,并且这里也更广泛更完整的描述了安全考虑。
o 在RFC 2543中,并不要求proxy转发101到199的临时应答到上行队列。这里被更改成为必须转发。这是非常重要的,因为很多后续的特性都依赖于传送所有的101到199的临时应答。
o RFC 2543提及了很少的503应答。它用于标志proxy失败或者过载的情况。这要求某些特别的处理。尤其是,接收到503的接受方应当触发一个对于下一个节点在DNS SRV的重新查找。同样的,503应答只由proxy服务器在特定情况下转发到上行队列。
o RFC2543定义了,但是没有充分指出,对于UA认证一个服务器的机制。这个已经删去了。作为替代,允许使用RFC2617的双向认证步骤。
o 对于UA来说,除非它收到了初始请求的ACK,不能发送BYE到一个呼叫。这个在RFC2543是允许的,但是可能导致潜在的空转可能。
o UA或者proxy不能发送CANCEL到一个事务,直到它得到了一个临时应答。这个在RFC2543中是允许的,但是可能导致空转的可能。
o 在注册中的action参数被禁止使用了。它不足以提供任何有用的服务,并且会导致在proxy上的应用程序处理上的冲突。
o RFC2543对于multicast有一堆特别的情况。例如某个应答被禁止了,定时器调整了,等等。multicast现在受到更多限制,并且同unicast相反,协议操作不影响对multicast的使用。
o 基本的认证整个被删除了,不允许用基本的认证。
o proxy不再立刻收到就转发6xx应答。他们立刻CANCEL相关等待的分支。这也避免了潜在的空转,使得UAC再2xx之后收到一个6xx。在除了这个空转的情况,结果都必须是相同的-6xx转发到上行队列。
o RFC2543并不对请求的合并认为是一个错误。这就导致在proxy上分支的请求稍后会在一个节点合并。只有在UA上能进行合并操作,并且处理步骤定义的是除了第一个请求都统统拒绝。
28.2 小功能性的变更
o 为给用户展示可选的内容,增加了Alert-Info,Error-Info,Call-Info头域。
o 增加了Content-Language,Content-Disposition和MIME-Verison头域。
o 增加了一个”glare hanling”机制来处理双方同时都向对方提出一个re-INVITE。它使用信的491(Request Pending)错误码。
o 增加了 In-Reply_To和Reply-To头域来支持稍后对未接呼叫/消息的返回。
o 在SIP通讯协议中增加了TLS和SCTP。
o 描写了很多机制来处理呼叫中的发生的错误;现在做了统一的处理。BYE用来发送会话终结。
o RFC2543要求INVITE应答通过TCP重新传送,但是注意到实际上只对2xx应答是需要的。这就导致了人为的协议不足。通过定义了一个一致的事务层,这就不在需要了。只有给INVITE的2xx应答需要基于TCP重传。
o 客户端和服务端事务机器现在基于超时机制,而不是基于重传次数。这允许状态机能够更好的适应TCP和UDP。
o Date头域在REGISTER应答中使用,提供一个简单的自动配置UA的日期的机制。
o 允许注册服务器拒绝过小的超时时间的注册。并且为此定义了423应答码和Min-Expires头域。
29 标准索引
[1] Handley, M. and V. Jacobson, "SDP: Session Description Protocol", RFC 2327, April 1998.
[2] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.
[3] Resnick, P., "Internet Message Format", RFC 2822, April 2001.
[4] Rosenberg, J. and H. Schulzrinne, "SIP: Locating SIP Servers",RFC 3263, June 2002.
[5] Berners-Lee, T., Fielding, R. and L. Masinter, "Uniform Resource Identifiers (URI): Generic Syntax", RFC 2396, August 1998.
[6] Chown, P., "Advanced Encryption Standard (AES) Ciphersuites for Transport Layer Security (TLS)", RFC 3268, June 2002.
[7] Yergeau, F., "UTF-8, a transformation format of ISO 10646", RFC 2279, January 1998.
[8] Fielding, R., Gettys, J., Mogul, J., Frystyk, H., Masinter, L.,Leach, P. and T. Berners-Lee, "Hypertext Transfer Protocol -- HTTP/1.1", RFC 2616, June 1999.
[9] Vaha-Sipila, A., "URLs for Telephone Calls", RFC 2806, April 2000.
[10] Crocker, D. and P. Overell, "Augmented BNF for Syntax Specifications: ABNF", RFC 2234, November 1997.
[11] Freed, F. and N. Borenstein, "Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types", RFC 2046, November 1996.
[12] Eastlake, D., Crocker, S. and J. Schiller, "Randomness Recommendations for Security", RFC 1750, December 1994.
[13] Rosenberg, J. and H. Schulzrinne, "An Offer/Answer Model with SDP", RFC 3264, June 2002.
[14] Postel, J., "User Datagram Protocol", STD 6, RFC 768, August 1980.
[15] Postel, J., "DoD Standard Transmission Control Protocol", RFC 761, January 1980.
[16] Stewart, R., Xie, Q., Morneault, K., Sharp, C., Schwarzbauer,H., Taylor, T., Rytina, I., Kalla, M., Zhang, L. and V. Paxson,"Stream Control Transmission Protocol", RFC 2960, October 2000.
[17] Franks, J., Hallam-Baker, P., Hostetler, J., Lawrence, S.,Leach, P., Luotonen, A. and L. Stewart, "HTTP authentication:Basic and Digest Access Authentication", RFC 2617, June 1999.
[18] Troost, R., Dorner, S. and K. Moore, "Communicating Presentation Information in Internet Messages: The Content-Disposition Header Field", RFC 2183, August 1997.
[19] Zimmerer, E., Peterson, J., Vemuri, A., Ong, L., Audet, F.,Watson, M. and M. Zonoun, "MIME media types for ISUP and QSIG Objects", RFC 3204, December 2001.
[20] Braden, R., "Requirements for Internet Hosts - Application and Support", STD 3, RFC 1123, October 1989.
[21] Alvestrand, H., "IETF Policy on Character Sets and Languages",BCP 18, RFC 2277, January 1998.
[22] Galvin, J., Murphy, S., Crocker, S. and N. Freed, "Security Multiparts for MIME: Multipart/Signed and Multipart/Encrypted", RFC 1847, October 1995.
[23] Housley, R., "Cryptographic Message Syntax", RFC 2630, June 1999.
[24] Ramsdell B., "S/MIME Version 3 Message Specification", RFC 2633, June 1999.
[25] Dierks, T. and C. Allen, "The TLS Protocol Version 1.0", RFC 2246, January 1999.
[26] Kent, S. and R. Atkinson, "Security Architecture for the Internet Protocol", RFC 2401, November 1998.30
30 信息索引:
[27] R. Pandya, "Emerging mobile and personal communication systems," IEEE Communications Magazine, Vol. 33, pp. 44--52, June 1995.
[28] Schulzrinne, H., Casner, S., Frederick, R. and V. Jacobson, "RTP: A Transport Protocol for Real-Time Applications", RFC 1889, January 1996.
[29] Schulzrinne, H., Rao, R. and R. Lanphier, "Real Time Streaming Protocol (RTSP)", RFC 2326, April 1998.
[30] Cuervo, F., Greene, N., Rayhan, A., Huitema, C., Rosen, B. and J. Segers, "Megaco Protocol Version 1.0", RFC 3015, November 2000.
[31] Handley, M., Schulzrinne, H., Schooler, E. and J. Rosenberg, "SIP: Session Initiation Protocol", RFC 2543, March 1999.
[32] Hoffman, P., Masinter, L. and J. Zawinski, "The mailto URL scheme", RFC 2368, July 1998.
[33] E. M. Schooler, "A multicast user directory service for synchronous rendezvous," Master’s Thesis CS-TR-96-18, Department of Computer Science, California Institute of Technology, Pasadena, California, Aug. 1996.
[34] Donovan, S., "The SIP INFO Method", RFC 2976, October 2000.
[35] Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321, April 1992.
[36] Dawson, F. and T. Howes, "vCard MIME Directory Profile", RFC 2426, September 1998.
[37] Good, G., "The LDAP Data Interchange Format (LDIF) – Technical Specification", RFC 2849, June 2000.
[38] Palme, J., "Common Internet Message Headers", RFC 2076, February 1997.
[39] Franks, J., Hallam-Baker, P., Hostetler, J., Leach, P., Luotonen, A., Sink, E. and L. Stewart, "An Extension to HTTP: Digest Access Authentication", RFC 2069, January 1997.
[40] Johnston, A., Donovan, S., Sparks, R., Cunningham, C., Willis, D., Rosenberg, J., Summers, K. and H. Schulzrinne, "SIP Call Flow Examples", Work in Progress.
[41] E. M. Schooler, "Case study: multimedia conference control in a packet-switched teleconferencing system," Journal of Internetworking: Research and Experience, Vol. 4, pp. 99--120, June 1993. ISI reprint series ISI/RS-93-359.
[42] H. Schulzrinne, "Personal mobility for multimedia services inthe Internet," in European Workshop on Interactive Distributed Multimedia Systems and Services (IDMS), (Berlin, Germany), Mar. 1996.
[43] Floyd, S., "Congestion Control Principles", RFC 2914, September 2000.
定时器值的表格:
表4:本规范使用的定时器意义机器缺省值:
定时器 值 章节 意义
T1 500 ms 缺省 17.1.1.1 预估的RTT时间
T2 4s 17.1.2.2 给非INVITE请求和INVITE应答的最大重传时间间隔
T4 5s 17.1.2.2 最大网络传送消息时间
定时器A 初始值T1 17.1.1.2 INVITE请求重传间隔,UDP only
定时器B 64×T1 17.1.1.2 INVITE请求超时时间
定时器C >3分钟 16.6/11 proxyINVITE请求超时时间
定时器D >32秒 UDP0 TCP/SCTP 17.1.1.2 应答重发的等待时间
定时器E 初始值T1 17.1.2.2 非INVITE请求重传间隔,UDP only
定时器F 64×T1 17.1.2.2 非INVITE请求事务超时时间
定时器G 初始值T1 17.2.1 INVITE应答重传间隔
定时器H 64×T1 17.2.1 等待ACK的时间
定时器I T4 UDP0 TCP/SCTP 17.2.1 ACK重传的等待时间
定时器J 64×T1 UDP0 TCP/SCTP 17.2.2 非INVITE请求重传的等待时间
定时器K T4 UDP0 TCP/SCP 17.1.2.2 应答重传的等待时间
感谢书
我们感谢IETF MMUSIC和SIP WGs的意见和建议。Ofir Arkin,Brian Bidulock,Jim Buller,Neil Deason,Dave Devanathan,Keith Drage,Bill Fenner, Cedric Fluckiger, Yaron Goland, John Hearty, Bernie Hoeneisen, Jo Hornsby, Phil Hoffer, Christian Huitema, Hisham Khartabil, Jean Jervis, Gadi Karmi, Peter Kjellerstedt, Anders Kristensen, Joanthan Lennox, Gethin Liddell, Allison Mankin, William Marshall, Rohan Mahy, Keith Moore, Vern Paxson, Bob Penfield, Moshe J. Sambol, Chip Sharp, igor Slepchin, Eric Tremblay, Rick Workman 提供了详细的注释
Brian Rosen 提供了完整的BNF
Jean Mahoney 提供了技术写作协助
这个工作是基于 inter alia [41,42]
作者地址
这里作者的地址是按照字母顺序的,首先是作者,接着是RFC2543原著。所有列出的作者都对本文有着巨大贡献:
Jonathan Rosenberg
dynamicsoft
72 Eagle Rock Ave
East Hanover, NJ 07936
USA
EMail: jdrosen@dynamicsoft.com
Henning Schulzrinne
Dept. of Computer Science
Columbia University
1214 Amsterdam Avenue
New York, NY 10027
USA
EMail: schulzrinne@cs.columbia.edu
Gonzalo Camarillo
Ericsson
Advanced Signalling Research Lab.
FIN-02420 Jorvas
Finland
EMail: Gonzalo.Camarillo@ericsson.com
Alan Johnston
WorldCom
100 South 4th Street
St. Louis, MO 63102
USA
EMail: alan.johnston@wcom.com
Jon Peterson
NeuStar, Inc
1800 Sutter Street, Suite 570
Concord, CA 94520
USA
EMail: jon.peterson@neustar.com
Robert Sparks
dynamicsoft, Inc.
5100 Tennyson Parkway
Suite 1200
Plano, Texas 75024
USA
EMail: rsparks@dynamicsoft.com
Mark Handley
International Computer Science Institute
1947 Center St, Suite 600
Berkeley, CA 94704
USA
EMail: mjh@icir.org
Eve Schooler
AT&T Labs-Research
75 Willow Road
Menlo Park, CA 94025
USA
EMail: schooler@research.att.com
版权声明
Copyright (C) The Internet Society (2002). All Rights Reserved.
This document and translations of it may be copied and furnished to
others, and derivative works that comment on or otherwise explain it
or assist in its implementation may be prepared, copied, published
and distributed, in whole or in part, without restriction of any
kind, provided that the above copyright notice and this paragraph are
included on all such copies and derivative works. However, this
document itself may not be modified in any way, such as by removing
the copyright notice or references to the Internet Society or other
Internet organizations, except as needed for the purpose of
developing Internet standards in which case the procedures for
copyrights defined in the Internet Standards process must be
followed, or as required to translate it into languages other than
English.
The limited permissions granted above are perpetual and will not be
revoked by the Internet Society or its successors or assigns.
This document and the information contained herein is provided on an
"AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Acknowledgement
Funding for the RFC Editor function is currently provided by the
Internet Society.
译者:崮山路上走9遍 2004-9-23于深圳完稿。
BLOG: sharp838.mblogger.cn
EMAIL: sharp838@21cn.com;guangweishi@gmail.com
所有的版权归于原作者。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。