View Javadoc

    1   //========================================================================
    2   //Copyright 2006-2008 Mort Bay Consulting Pty. Ltd.
    3   //------------------------------------------------------------------------
    4   //Licensed under the Apache License, Version 2.0 (the "License");
    5   //you may not use this file except in compliance with the License.
    6   //You may obtain a copy of the License at
    7   //http://www.apache.org/licenses/LICENSE-2.0
    8   //Unless required by applicable law or agreed to in writing, software
    9   //distributed under the License is distributed on an "AS IS" BASIS,
    10  //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  //See the License for the specific language governing permissions and
    12  //limitations under the License.
    13  //========================================================================
    14
    15  package org.mortbay.jetty.client.security;
    16
    17
    18  import java.io.IOException;
    19  import java.security.MessageDigest;
    20  import java.util.Map;
    21
    22  import org.mortbay.jetty.HttpHeaders;
    23  import org.mortbay.jetty.client.HttpExchange;
    24  import org.mortbay.util.StringUtil;
    25  import org.mortbay.util.TypeUtil;
    26
    27  public class DigestAuthorization implements Authorization
    28  {
    29      private static final String NC = "00000001";
    30      Realm securityRealm;
    31      Map details;
    32
    33      public DigestAuthorization(Realm realm, Map details)
    34      {
    35          this.securityRealm=realm;
    36          this.details=details;
    37      }
    38
    39
    40      public void setCredentials( HttpExchange exchange )
    41      throws IOException
    42      {
    43          StringBuilder buffer = new StringBuilder().append("Digest");
    44
    45          buffer.append(" ").append("username").append('=').append('"').append(securityRealm.getPrincipal()).append('"');
    46
    47          buffer.append(", ").append("realm").append('=').append('"').append(String.valueOf(details.get("realm"))).append('"');
    48
    49          buffer.append(", ").append("nonce").append('=').append('"').append(String.valueOf(details.get("nonce"))).append('"');
    50
    51          buffer.append(", ").append("uri").append('=').append('"').append(exchange.getURI()).append('"');
    52
    53          buffer.append(", ").append("algorithm").append('=').append(String.valueOf(details.get("algorithm")));
    54
    55          String cnonce = newCnonce(exchange, securityRealm, details);
    56
    57          buffer.append(", ").append("response").append('=').append('"').append(newResponse(cnonce,
    58                  exchange, securityRealm, details)).append('"');
    59
    60          buffer.append(", ").append("qop").append('=').append(String.valueOf(details.get("qop")));
    61
    62
    63          buffer.append(", ").append("nc").append('=').append(NC);
    64
    65          buffer.append(", ").append("cnonce").append('=').append('"').append(cnonce).append('"');
    66
    67          exchange.setRequestHeader( HttpHeaders.AUTHORIZATION,
    68                  new String(buffer.toString().getBytes(StringUtil.__ISO_8859_1)));
    69      }
    70
    71      protected String newResponse(String cnonce, HttpExchange exchange, Realm securityRealm, Map details)
    72      {
    73          try{
    74              MessageDigest md = MessageDigest.getInstance("MD5");
    75
    76              // calc A1 digest
    77              md.update(securityRealm.getPrincipal().getBytes(StringUtil.__ISO_8859_1));
    78              md.update((byte)':');
    79              md.update(String.valueOf(details.get("realm")).getBytes(StringUtil.__ISO_8859_1));
    80              md.update((byte)':');
    81              md.update(securityRealm.getCredentials().getBytes(StringUtil.__ISO_8859_1));
    82              byte[] ha1 = md.digest();
    83              // calc A2 digest
    84              md.reset();
    85              md.update(exchange.getMethod().getBytes(StringUtil.__ISO_8859_1));
    86              md.update((byte)':');
    87              md.update(exchange.getURI().getBytes(StringUtil.__ISO_8859_1));
    88              byte[] ha2=md.digest();
    89
    90              md.update(TypeUtil.toString(ha1,16).getBytes(StringUtil.__ISO_8859_1));
    91              md.update((byte)':');
    92              md.update(String.valueOf(details.get("nonce")).getBytes(StringUtil.__ISO_8859_1));
    93              md.update((byte)':');
    94              md.update(NC.getBytes(StringUtil.__ISO_8859_1));
    95              md.update((byte)':');
    96              md.update(cnonce.getBytes(StringUtil.__ISO_8859_1));
    97              md.update((byte)':');
    98              md.update(String.valueOf(details.get("qop")).getBytes(StringUtil.__ISO_8859_1));
    99              md.update((byte)':');
    100             md.update(TypeUtil.toString(ha2,16).getBytes(StringUtil.__ISO_8859_1));
    101             byte[] digest=md.digest();
    102
    103             // check digest
    104             return encode(digest);
    105         }
    106         catch(Exception e)
    107         {
    108             e.printStackTrace();
    109             return null;
    110         }
    111     }
    112
    113     protected String newCnonce(HttpExchange exchange, Realm securityRealm, Map details)
    114     {
    115         try
    116         {
    117             MessageDigest md = MessageDigest.getInstance("MD5");
    118             byte[] b= md.digest(String.valueOf(System.currentTimeMillis()).getBytes(StringUtil.__ISO_8859_1));
    119             return encode(b);
    120         }
    121         catch(Exception e)
    122         {
    123             e.printStackTrace();
    124             return null;
    125         }
    126     }
    127
    128     private static String encode(byte[] data)
    129     {
    130         StringBuilder buffer = new StringBuilder();
    131         for (int i=0; i<data.length; i++)
    132         {
    133             buffer.append(Integer.toHexString((data[i] & 0xf0) >>> 4));
    134             buffer.append(Integer.toHexString(data[i] & 0x0f));
    135         }
    136         return buffer.toString();
    137     }
    138
    139 }