<html>
<head>
<base href="https://wiki.asterisk.org/wiki">
<link rel="stylesheet" href="/wiki/s/2036/1/7/_/styles/combined.css?spaceKey=TOP&forWysiwyg=true" type="text/css">
</head>
<body style="background: white;" bgcolor="white" class="email-body">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
<h2><a href="https://wiki.asterisk.org/wiki/display/TOP/Sip+Authentication+Hook">Sip Authentication Hook</a></h2>
<h4>Page <b>edited</b> by <a href="https://wiki.asterisk.org/wiki/display/~mmichelson">Mark Michelson</a>
</h4>
<div id="versionComment">
<b>Comment:</b>
Addressing Kevin's comments on CR-ASTSCF-43<br />
</div>
<br/>
<h4>Changes (16)</h4>
<div id="page-diffs">
<table class="diff" cellpadding="0" cellspacing="0">
<tr><td class="diff-snipped" >...<br></td></tr>
<tr><td class="diff-unchanged" >h1. Intro <br> <br></td></tr>
<tr><td class="diff-changed-lines" >When it comes to authenticating SIP <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">users,</span> <span class="diff-added-words"style="background-color: #dfd;">requesters,</span> it's tough to define operations in such a way that suits <span class="diff-changed-words">all<span class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;"> users</span>.</span> Authentication is heavily policy-based, and as such should be handled by code not included with Asterisk SCF. Since authentication is a decision point during the overall processing of a SIP message, a user-defined hook could be used, with an extension point built into any SIP modules that might make use of the hook. The hook will be called upon whenever it may be useful to require authentication for a <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">user.</span> <span class="diff-added-words"style="background-color: #dfd;">SIP requester.</span> The SIP component will provide information from the SIP request to the hook. It is the hook's job to decide whether authentication should be requested, and if so, supply information for the SIP component to use when creating the challenge to send to the <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">client.</span> <span class="diff-added-words"style="background-color: #dfd;">requester.</span> <br></td></tr>
<tr><td class="diff-unchanged" > <br>h1. Authentication in SIP <br></td></tr>
<tr><td class="diff-snipped" >...<br></td></tr>
<tr><td class="diff-unchanged" >class RequestInfo <br>{ <br></td></tr>
<tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;"> // The SIP method the client is using <br> string method; <br></td></tr>
<tr><td class="diff-unchanged" > // The display name in the From header <br> string fromName; <br></td></tr>
<tr><td class="diff-snipped" >...<br></td></tr>
<tr><td class="diff-unchanged" > <br>A challenge sent by a server contains the following information for the client: <br></td></tr>
<tr><td class="diff-changed-lines" >* realm - A string used so that the <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">client</span> <span class="diff-added-words"style="background-color: #dfd;">requester</span> can know which credentials to use when authenticating <br></td></tr>
<tr><td class="diff-unchanged" >* domain - A list of URIs that define the protection space. This is a bit confusing when reading RFC 3261, because they specifically say that with SIP, the protection space is defined solely by the realm. <br></td></tr>
<tr><td class="diff-changed-lines" >* nonce - A string <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">re-generated</span> <span class="diff-added-words"style="background-color: #dfd;">randomly generated</span> for each challenge sent. <br></td></tr>
<tr><td class="diff-changed-lines" >* opaque - A string generated by the <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">server</span> <span class="diff-added-words"style="background-color: #dfd;">challenger</span> and used by the <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">client</span> <span class="diff-added-words"style="background-color: #dfd;">requester</span> when authenticating to any URI in the protection space. <br></td></tr>
<tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">* qop - Quality of protection: List of supported values, each of which causes slight variations to hashing algorithms used. <br></td></tr>
<tr><td class="diff-added-lines" style="background-color: #dfd;">* qop - Quality of protection: List of supported values, each of which causes slight variations regarding information used in the hashing algorithm. <br></td></tr>
<tr><td class="diff-unchanged" >* algorithm - Hashing algorithm for the client to use when generating the digest response. <br> <br></td></tr>
<tr><td class="diff-snipped" >...<br></td></tr>
<tr><td class="diff-unchanged" > string username; <br> string password; <br></td></tr>
<tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;"> bool doAuth; <br></td></tr>
<tr><td class="diff-unchanged" > StringSeq domain; <br> string realm; <br></td></tr>
<tr><td class="diff-snipped" >...<br></td></tr>
<tr><td class="diff-unchanged" >}; <br>{code} <br></td></tr>
<tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">The most important member is {{doAuth}}. If false, then the hook has indicated it does not want for Asterisk to send an authentication challenge to the client. If set true, then an authentication challenge should be sent. Why are {{StringSeqs}} used for items which can only contain a single value? The reason is that they're all optional for the user to set. An empty sequence will be treated as like a null string. Any of the StringSeqs may be empty, although it is recommended that the user provides values for {{domain}}. If the {{nonce}} or {{opaque}} sequences are empty, then Asterisk SCF will create one on behalf of the user. If multiple values are provided for {{nonce}} or {{opaque}} then only the first one will actually be used. <br></td></tr>
<tr><td class="diff-added-lines" style="background-color: #dfd;">Why are {{StringSeqs}} used for items which can only contain a single value? The reason is that they're all optional for the user to set. An empty sequence will be treated like a null string. Any of the StringSeqs may be empty, although it is recommended that the user provides values for {{domain}}. If the {{nonce}} or {{opaque}} sequences are empty, then Asterisk SCF will generate one on behalf of the user. If multiple values are provided for {{nonce}} or {{opaque}} then only the first of the sequence will actually be used. <br></td></tr>
<tr><td class="diff-unchanged" > <br>The {{username}} and {{password}} are provided so that Asterisk SCF will be able to properly authenticate the user once the authentication response is received from the client. Since this information is passed using Ice, it is recommended that this information is transferred over an encrypted transport so that the information is not in the clear on the wire. <br></td></tr>
<tr><td class="diff-snipped" >...<br></td></tr>
<tr><td class="diff-unchanged" > <br>{code:language=slice} <br></td></tr>
<tr><td class="diff-added-lines" style="background-color: #dfd;"> <br>sequence<DigestChallenge> DigestChallengeSeq; <br> <br></td></tr>
<tr><td class="diff-unchanged" >interface AuthHook <br>{ <br></td></tr>
<tr><td class="diff-changed-lines" >HookResult getAuthChallenge(RequestInfo info, out <span class="diff-changed-words">DigestChallenge<span class="diff-added-chars"style="background-color: #dfd;">Seq</span></span> challenge); <br></td></tr>
<tr><td class="diff-unchanged" >}; <br> <br></td></tr>
<tr><td class="diff-snipped" >...<br></td></tr>
<tr><td class="diff-unchanged" >} <br> <br></td></tr>
<tr><td class="diff-changed-lines" >sequence<RequestType> <span class="diff-changed-words">RequestTypeSeq<span class="diff-added-chars"style="background-color: #dfd;">;</span></span> <br></td></tr>
<tr><td class="diff-unchanged" > <br>interface SipExtensionPoints <br></td></tr>
<tr><td class="diff-snipped" >...<br></td></tr>
<tr><td class="diff-unchanged" >{code} <br> <br></td></tr>
<tr><td class="diff-changed-lines" >{{HookId}} and {{HookResult}} are defined in the page linked to above. <span class="diff-added-words"style="background-color: #dfd;">A {{DigestChallengeSeq}} out parameter is used in {{getAuthChallenge}} because it is possible to have multiple WWW-Authenticate headers in the 401 response. If the sequence is empty, then that indicates the user has no desire to authenticate the SIP requester.</span> The {{RequestTypeSeq}} in {{addAuthHook}} <span class="diff-changed-words">let<span class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">'</span>s</span> a SIP component know whether to call into a hook for out of dialog requests, in dialog requests, or both. <br></td></tr>
<tr><td class="diff-unchanged" > <br>h1. Example <br></td></tr>
<tr><td class="diff-snipped" >...<br></td></tr>
<tr><td class="diff-unchanged" >!AuthenticationHook.png! <br> <br></td></tr>
<tr><td class="diff-changed-lines" >In the above example, {{UserComponent}} registers an {{AuthHook}} with the {{SipSessionManager}}. Alice sends an INVITE into the {{SipSessionManager}}, who is told by the {{AuthHook}} <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">via the {{doAuth}} member</span> to send an authentication challenge to Alice. <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">We send</span> <span class="diff-added-words"style="background-color: #dfd;">The {{SipSessionManager}} sends</span> a 401 response, to which Alice sends a new INVITE with proper <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">authorization.</span> <span class="diff-added-words"style="background-color: #dfd;">credentials.</span> Later, Bob sends an INVITE into the {{SipSessionManager}}. This time, the {{AuthHook}} instructs the {{SipSessionManager}} not to send a challenge. In this case, the {{SipSessionManager}} responds to Bob's INVITE with a 200 OK. <br></td></tr>
<tr><td class="diff-unchanged" > <br>h1. The future <br> <br></td></tr>
<tr><td class="diff-changed-lines" >The authentication hook is a prime example of something that could make use of cookies. For instance, if a user registers a hook for both out of dialog and in dialog requests, it would make sense to allow for the user to provide some opaque data to the SIP component that called <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">into</span> <span class="diff-added-words"style="background-color: #dfd;">out to</span> the hook. Then for all future calls on this dialog into the authentication hook, the SIP component could then provide the cookie back to the hook. <br></td></tr>
</table>
</div> <h4>Full Content</h4>
<div class="notificationGreySide">
<div class='panelMacro'><table class='warningMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="/wiki/images/icons/emoticons/forbidden.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td><b>BRAAAAAAAAAAAAAAAAINS</b><br /><h1><a name="SipAuthenticationHook-Thisisaworkinprogress.Pleaserefrainfrommakingcommentsatthistime"></a>This is a work in progress. Please refrain from making comments at this time</h1></td></tr></table></div>
<h1><a name="SipAuthenticationHook-Intro"></a>Intro</h1>
<p>When it comes to authenticating SIP requesters, it's tough to define operations in such a way that suits all. Authentication is heavily policy-based, and as such should be handled by code not included with Asterisk SCF. Since authentication is a decision point during the overall processing of a SIP message, a user-defined hook could be used, with an extension point built into any SIP modules that might make use of the hook. The hook will be called upon whenever it may be useful to require authentication for a SIP requester. The SIP component will provide information from the SIP request to the hook. It is the hook's job to decide whether authentication should be requested, and if so, supply information for the SIP component to use when creating the challenge to send to the requester.</p>
<h1><a name="SipAuthenticationHook-AuthenticationinSIP"></a>Authentication in SIP</h1>
<p>Authentication in SIP is based off of HTTP authentication as defined in <a href="http://www.ietf.org/rfc/rfc2617.txt" class="external-link" rel="nofollow">RFC 2617</a>. In that document, the Basic and Digest schemes are defined. In <a href="http://www.ietf.org/rfc/rfc3261.txt" class="external-link" rel="nofollow">RFC 3261</a> it is expressly forbidden for servers to challenge using the Basic scheme, so this leaves just the Digest as an option. RFCs <a href="http://tools.ietf.org/rfc/rfc3310.txt" class="external-link" rel="nofollow">3310</a> and <a href="http://tools.ietf.org/rfc/rfc4169.txt" class="external-link" rel="nofollow">4169</a> define AKAv1 and AKAv2 extensions to Digest authentication, which are both supported by PJSIP.</p>
<h1><a name="SipAuthenticationHook-PresentinginformationtotheUserHook"></a>Presenting information to the User Hook</h1>
<p>What information will a user need in order to choose whether to challenge the client? Challenge decisions can be made for nearly any reason, but it seems wise to present the user with some information from the SIP message to aid in the decision. For this, we define the <tt>RequestInfo</tt> class:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="toolbar: false; theme: Confluence; brush: java; gutter: false"><![CDATA[
dictionary<string, string> PropertyDict;
enum Transport
{
UDP,
TCP,
TLS
};
class RequestInfo
{
// The display name in the From header
string fromName;
// The URI in the From header
string fromURI;
// URI parameters in the From header
PropertyDict fromParams;
// The display name in the To header
string toName;
// The URI in the To header
string toURI;
// URI parameters in the To header
PropertyDict toParams;
// The request URI
string requestURI;
// request URI parameters
PropertyDict requestURIParams;
// Source IP address
string IPAddr;
// Source Port
int port;
// Transport over which request was received
Transport transport;
}
]]></script>
</div></div>
<p>Different request methods may have additional information to expose to the hook. For instance, when calling into the hook when a SUBSCRIBE is received, the event package may be included. This can be done by subclassing <tt>RequestInfo</tt>.</p>
<h1><a name="SipAuthenticationHook-ReceivingachallengerequestfromtheUserHook"></a>Receiving a challenge request from the User Hook</h1>
<p>A challenge sent by a server contains the following information for the client:</p>
<ul>
        <li>realm - A string used so that the requester can know which credentials to use when authenticating</li>
        <li>domain - A list of URIs that define the protection space. This is a bit confusing when reading RFC 3261, because they specifically say that with SIP, the protection space is defined solely by the realm.</li>
        <li>nonce - A string randomly generated for each challenge sent.</li>
        <li>opaque - A string generated by the challenger and used by the requester when authenticating to any URI in the protection space.</li>
        <li>qop - Quality of protection: List of supported values, each of which causes slight variations regarding information used in the hashing algorithm.</li>
        <li>algorithm - Hashing algorithm for the client to use when generating the digest response.</li>
</ul>
<p>So of this information, what is useful for a user hook to be able to generate? The <tt>realm</tt> and <tt>domain</tt> are important elements that the hook should provide. The <tt>nonce</tt> and <tt>opaque</tt> are completely unnecessary for the hook to provide; however, it could be argued that a user may want to be able to control this information, so it makes sense to be allowed to provide it if desired. The <tt>qop</tt> during the challenge is completely unnecessary for the user to provide. The <tt>algorithm</tt> may be useful for the user to set.</p>
<p>With all this in mind, we define the following datatypes:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="toolbar: false; theme: Confluence; brush: java; gutter: false"><![CDATA[
enum Algorithm
{
MD5,
MD5sess,
AKAv1MD5,
AKAv1MD5sess,
AKAv2MD5,
AKAv2MD5sess
};
class DigestChallenge
{
string username;
string password;
StringSeq domain;
string realm;
StringSeq nonce;
StringSeq opaque;
Algorithm algorithm;
};
]]></script>
</div></div>
<p>Why are <tt>StringSeqs</tt> used for items which can only contain a single value? The reason is that they're all optional for the user to set. An empty sequence will be treated like a null string. Any of the StringSeqs may be empty, although it is recommended that the user provides values for <tt>domain</tt>. If the <tt>nonce</tt> or <tt>opaque</tt> sequences are empty, then Asterisk SCF will generate one on behalf of the user. If multiple values are provided for <tt>nonce</tt> or <tt>opaque</tt> then only the first of the sequence will actually be used.</p>
<p>The <tt>username</tt> and <tt>password</tt> are provided so that Asterisk SCF will be able to properly authenticate the user once the authentication response is received from the client. Since this information is passed using Ice, it is recommended that this information is transferred over an encrypted transport so that the information is not in the clear on the wire.</p>
<h1><a name="SipAuthenticationHook-RegisteringahookwithAsteriskSCF"></a>Registering a hook with Asterisk SCF</h1>
<p>The SIP component of Asterisk will expose an interface similar to the one defined in <a href="/wiki/display/TOP/Extension+Points+and+Hooks" title="Extension Points and Hooks">Extension Points and Hooks</a>.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="toolbar: false; theme: Confluence; brush: java; gutter: false"><![CDATA[
sequence<DigestChallenge> DigestChallengeSeq;
interface AuthHook
{
HookResult getAuthChallenge(RequestInfo info, out DigestChallengeSeq challenge);
};
enum RequestType
{
OutOfDialog,
InDialog
}
sequence<RequestType> RequestTypeSeq;
interface SipExtensionPoints
{
void addAuthHook(HookId id, AuthHook *hook, RequestTypeSeq types);
void removeAuthHook(HookId id);
void clearAuthHooks();
};
]]></script>
</div></div>
<p><tt>HookId</tt> and <tt>HookResult</tt> are defined in the page linked to above. A <tt>DigestChallengeSeq</tt> out parameter is used in <tt>getAuthChallenge</tt> because it is possible to have multiple WWW-Authenticate headers in the 401 response. If the sequence is empty, then that indicates the user has no desire to authenticate the SIP requester. The <tt>RequestTypeSeq</tt> in <tt>addAuthHook</tt> lets a SIP component know whether to call into a hook for out of dialog requests, in dialog requests, or both.</p>
<h1><a name="SipAuthenticationHook-Example"></a>Example</h1>
<p><span class="image-wrap" style=""><img src="/wiki/download/attachments/10650199/AuthenticationHook.png?version=1&modificationDate=1295278578919" style="border: 0px solid black" /></span></p>
<p>In the above example, <tt>UserComponent</tt> registers an <tt>AuthHook</tt> with the <tt>SipSessionManager</tt>. Alice sends an INVITE into the <tt>SipSessionManager</tt>, who is told by the <tt>AuthHook</tt> to send an authentication challenge to Alice. The <tt>SipSessionManager</tt> sends a 401 response, to which Alice sends a new INVITE with proper credentials. Later, Bob sends an INVITE into the <tt>SipSessionManager</tt>. This time, the <tt>AuthHook</tt> instructs the <tt>SipSessionManager</tt> not to send a challenge. In this case, the <tt>SipSessionManager</tt> responds to Bob's INVITE with a 200 OK.</p>
<h1><a name="SipAuthenticationHook-Thefuture"></a>The future</h1>
<p>The authentication hook is a prime example of something that could make use of cookies. For instance, if a user registers a hook for both out of dialog and in dialog requests, it would make sense to allow for the user to provide some opaque data to the SIP component that called out to the hook. Then for all future calls on this dialog into the authentication hook, the SIP component could then provide the cookie back to the hook.</p>
</div>
<div id="commentsSection" class="wiki-content pageSection">
<div style="float: right;">
<a href="https://wiki.asterisk.org/wiki/users/viewnotifications.action" class="grey">Change Notification Preferences</a>
</div>
<a href="https://wiki.asterisk.org/wiki/display/TOP/Sip+Authentication+Hook">View Online</a>
|
<a href="https://wiki.asterisk.org/wiki/pages/diffpagesbyversion.action?pageId=10650199&revisedVersion=11&originalVersion=10">View Changes</a>
|
<a href="https://wiki.asterisk.org/wiki/display/TOP/Sip+Authentication+Hook?showComments=true&showCommentArea=true#addcomment">Add Comment</a>
</div>
</div>
</div>
</div>
</div>
</body>
</html>