1 package org.mortbay.jetty.client.security;
2
3 import java.io.IOException;
4 import java.util.HashMap;
5 import java.util.Map;
6 import java.util.StringTokenizer;
7
8 import javax.servlet.http.HttpServletResponse;
9
10 import org.mortbay.io.Buffer;
11 import org.mortbay.jetty.HttpHeaders;
12 import org.mortbay.jetty.client.HttpDestination;
13 import org.mortbay.jetty.client.HttpEventListenerWrapper;
14 import org.mortbay.jetty.client.HttpExchange;
15 import org.mortbay.log.Log;
16 import org.mortbay.util.StringUtil;
17
18 public class SecurityListener extends HttpEventListenerWrapper
19 {
20 private HttpDestination _destination;
21 private HttpExchange _exchange;
22
23 private int _attempts = 0;
24
25 public SecurityListener(HttpDestination destination, HttpExchange ex)
26 {
27
28
29 super(ex.getEventListener(),true);
30 _destination=destination;
31 _exchange=ex;
32 }
33
34
35
36
37
38
39
40
41 protected String scrapeAuthenticationType( String authString )
42 {
43 String authType;
44
45 if ( authString.indexOf( " " ) == -1 )
46 {
47 authType = authString.toString().trim();
48 }
49 else
50 {
51 String authResponse = authString.toString();
52 authType = authResponse.substring( 0, authResponse.indexOf( " " ) ).trim();
53 }
54 return authType;
55 }
56
57
58
59
60
61
62
63 protected Map<String, String> scrapeAuthenticationDetails( String authString )
64 {
65 Map<String, String> authenticationDetails = new HashMap<String, String>();
66 authString = authString.substring( authString.indexOf( " " ) + 1, authString.length() );
67 StringTokenizer strtok = new StringTokenizer( authString, ",");
68
69 while ( strtok.hasMoreTokens() )
70 {
71 String[] pair = strtok.nextToken().split( "=" );
72 if ( pair.length == 2 )
73 {
74 String itemName = pair[0].trim();
75 String itemValue = pair[1].trim();
76
77 itemValue = StringUtil.unquote( itemValue );
78
79 authenticationDetails.put( itemName, itemValue );
80 }
81 else
82 {
83 throw new IllegalArgumentException( "unable to process authentication details" );
84 }
85 }
86 return authenticationDetails;
87 }
88
89 @Override
90 public void onResponseStatus( Buffer version, int status, Buffer reason )
91 throws IOException
92 {
93 System.err.println("SecurityListener:Response Status: " + status );
94 if ( status == HttpServletResponse.SC_UNAUTHORIZED && _attempts<_destination.getHttpClient().maxRetries())
95 {
96
97 setDelegating(false);
98 }
99 else
100 {
101 setDelegating(true);
102 }
103 super.onResponseStatus(version,status,reason);
104 }
105
106
107 @Override
108 public void onResponseHeader( Buffer name, Buffer value )
109 throws IOException
110 {
111 System.err.println( "SecurityListener:Header: " + name.toString() + " / " + value.toString() );
112 if (!isDelegating())
113 {
114 int header = HttpHeaders.CACHE.getOrdinal(name);
115 switch (header)
116 {
117 case HttpHeaders.WWW_AUTHENTICATE_ORDINAL:
118
119
120 String authString = value.toString();
121 String type = scrapeAuthenticationType( authString );
122
123
124 Map<String,String> details = scrapeAuthenticationDetails( authString );
125 String pathSpec="/";
126 SecurityRealmResolver realmResolver = _destination.getHttpClient().getSecurityRealmResolver();
127
128 if ( realmResolver == null )
129 {
130 break;
131 }
132
133 SecurityRealm realm = realmResolver.getRealm( details.get("realm"), _destination, pathSpec );
134
135 if ( realm == null )
136 {
137 Log.warn( "Unknown Security Realm: " + details.get("realm") );
138 }
139 else if ("digest".equalsIgnoreCase(type))
140 {
141 _destination.addAuthorization("/",new DigestAuthentication(realm,details));
142
143 }
144 else if ("basic".equalsIgnoreCase(type))
145 {
146 _destination.addAuthorization(pathSpec,new BasicAuthentication(realm));
147 }
148
149 break;
150 }
151 }
152 super.onResponseHeader(name,value);
153 }
154
155 @Override
156 public void onResponseComplete() throws IOException
157 {
158 if (!isDelegating())
159 _destination.resend(_exchange);
160 else
161 super.onResponseComplete();
162 }
163
164 @Override
165 public void onRetry()
166 {
167 _attempts++;
168 setDelegating(true);
169 super.onRetry();
170 }
171
172
173 }