<html>
<head>
    <base href="https://wiki.asterisk.org/wiki">
            <link rel="stylesheet" href="/wiki/s/2036/1/7/_/styles/combined.css?spaceKey=TOP&amp;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>
        <br/>
                         <h4>Changes (1)</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" >} <br> <br></td></tr>
            <tr><td class="diff-changed-lines" ><span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">sequence&lt;DialogStatus&gt;</span> <span class="diff-added-words"style="background-color: #dfd;">sequence&lt;RequestType&gt;</span> RequestTypeSeq <br></td></tr>
            <tr><td class="diff-unchanged" > <br>interface SipExtensionPoints <br></td></tr>
            <tr><td class="diff-snipped" >...<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 users, it's tough to define operations in such a way that suits all users. 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, it doesn't make sense that an entire separate component be designed for authentication. Instead, 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 user. 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 client.</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&lt;string, string&gt; PropertyDict;

enum Transport
{
    UDP,
    TCP,
    TLS
};

class RequestInfo
{
    // The SIP method the client is using
    string method;
    // 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 client 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 re-generated for each challenge sent.</li>
        <li>opaque - A string generated by the server and used by the client 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 to hashing algorithms used.</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;
    bool doAuth;
    StringSeq domain;
    string realm;
    StringSeq nonce;
    StringSeq opaque;
    Algorithm algorithm;
};
]]></script>
</div></div>
<p>The most important member is <tt>doAuth</tt>. 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 <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 as 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 create one on behalf of the user. If multiple values are provided for <tt>nonce</tt> or <tt>opaque</tt> then only the first one 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[
interface AuthHook
{
    HookResult getAuthChallenge(RequestInfo info, out DigestChallenge challenge);
};

enum RequestType
{
    OutOfDialog,
    InDialog
}

sequence&lt;RequestType&gt; 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. The <tt>RequestTypeSeq</tt> in <tt>addAuthHook</tt> let's 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&amp;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> via the <tt>doAuth</tt> member to send an authentication challenge to Alice. We send a 401 response, to which Alice sends a new INVITE with proper authorization. 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 into 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=9&originalVersion=8">View Changes</a>
                |
        <a href="https://wiki.asterisk.org/wiki/display/TOP/Sip+Authentication+Hook?showComments=true&amp;showCommentArea=true#addcomment">Add Comment</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>