<html>
<head>
<base href="https://wiki.asterisk.org/wiki">
<link rel="stylesheet" href="/wiki/s/en/2160/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/~kpfleming">Kevin P. Fleming</a>
</h4>
<div id="versionComment">
<b>Comment:</b>
remove unsupported 'language=slice' tags<br />
</div>
<br/>
<h4>Changes (3)</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" >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 {{RequestInfo}} class: <br> <br></td></tr>
<tr><td class="diff-changed-lines" ><span class="diff-changed-words">{code<span class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">:language=slice</span>}</span> <br></td></tr>
<tr><td class="diff-unchanged" >dictionary<string, string> PropertyDict; <br> <br></td></tr>
<tr><td class="diff-snipped" >...<br></td></tr>
<tr><td class="diff-unchanged" >With all this in mind, we define the following datatypes: <br> <br></td></tr>
<tr><td class="diff-changed-lines" ><span class="diff-changed-words">{code<span class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">:language=slice</span>}</span> <br></td></tr>
<tr><td class="diff-unchanged" >enum Algorithm <br>{ <br></td></tr>
<tr><td class="diff-snipped" >...<br></td></tr>
<tr><td class="diff-unchanged" >The SIP component of Asterisk will expose an interface similar to the one defined in [Extension Points and Hooks]. <br> <br></td></tr>
<tr><td class="diff-changed-lines" ><span class="diff-changed-words">{code<span class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">:language=slice</span>}</span> <br></td></tr>
<tr><td class="diff-unchanged" > <br>sequence<DigestChallenge> DigestChallengeSeq; <br></td></tr>
<tr><td class="diff-snipped" >...<br></td></tr>
</table>
</div> <h4>Full Content</h4>
<div class="notificationGreySide">
<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">
<pre class="theme: Confluence; brush: java; gutter: false">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;
}</pre>
</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">
<pre class="theme: Confluence; brush: java; gutter: false">enum Algorithm
{
MD5,
MD5sess,
AKAv1MD5,
AKAv1MD5sess,
AKAv2MD5,
AKAv2MD5sess
};
class DigestChallenge
{
string username;
string password;
StringSeq domain;
string realm;
StringSeq nonce;
StringSeq opaque;
Algorithm algorithm;
};</pre>
</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">
<pre class="theme: Confluence; brush: java; gutter: false">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();
};</pre>
</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;" class="grey">
<a href="https://wiki.asterisk.org/wiki/users/removespacenotification.action?spaceKey=TOP">Stop watching space</a>
<span style="padding: 0px 5px;">|</span>
<a href="https://wiki.asterisk.org/wiki/users/editmyemailsettings.action">Change email 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=13&originalVersion=12">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>