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 }