1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 package org.ogf.graap.wsag.security.core.server;
36
37 import java.math.BigInteger;
38 import java.security.Principal;
39 import java.security.cert.X509Certificate;
40 import java.util.Arrays;
41 import java.util.List;
42 import java.util.Vector;
43
44 import javax.security.auth.Subject;
45 import javax.security.auth.x500.X500Principal;
46
47 import org.apache.axis2.context.MessageContext;
48 import org.apache.log4j.Logger;
49 import org.apache.ws.security.WSConstants;
50 import org.apache.ws.security.WSSecurityEngineResult;
51 import org.apache.ws.security.WSSecurityException;
52 import org.apache.ws.security.components.crypto.Crypto;
53 import org.apache.ws.security.handler.WSHandlerConstants;
54 import org.apache.ws.security.handler.WSHandlerResult;
55 import org.ogf.graap.wsag.security.core.SecurityConstants;
56 import org.ogf.graap.wsag.security.core.SecurityUtils;
57 import org.ogf.graap.wsag.server.api.WsagMessageContext;
58 import org.ogf.graap.wsag.server.engine.WsagEngine;
59 import org.w3c.dom.Element;
60
61
62
63
64
65
66
67
68
69
70 public class WSSecurityHandler implements ServerSecurityHandler
71 {
72
73 private static final Logger LOG = Logger.getLogger( WSSecurityHandler.class );
74
75
76
77
78
79
80 public void handleRequest( Element request ) throws Exception
81 {
82 MessageContext messageContext = MessageContext.getCurrentMessageContext();
83
84 Crypto crypto = SecurityUtils.getCryptoFromLoginContext( WsagEngine.getLoginContext() );
85
86 if ( crypto != null )
87 {
88 processSecurityHeader( crypto, messageContext );
89 }
90 else
91 {
92 LOG.error( "Could not process security headers. Reason: server crypto not found." );
93 }
94 }
95
96
97
98
99 public void handleResponse( Element response ) throws Exception
100 {
101
102 }
103
104 @SuppressWarnings( { "unchecked" } )
105 private void processSecurityHeader( Crypto crypto, MessageContext messageContext )
106 throws WSSecurityException
107 {
108 WsagMessageContext context = WsagEngine.getWsagMessageContext();
109 Vector<WSHandlerResult> handlerResults =
110 (Vector<WSHandlerResult>) messageContext.getProperty( WSHandlerConstants.RECV_RESULTS );
111
112 X509Certificate userCertificate = null;
113
114
115 for ( int i = 0; i < handlerResults.size(); i++ )
116 {
117 WSHandlerResult currentResult = handlerResults.get( i );
118
119 Vector<WSSecurityEngineResult> wsSecEngineResults = currentResult.getResults();
120 for ( int j = 0; j < wsSecEngineResults.size(); j++ )
121 {
122 WSSecurityEngineResult wser = wsSecEngineResults.get( j );
123 if ( ( (Integer) wser.get( WSSecurityEngineResult.TAG_ACTION ) ).intValue() == WSConstants.SIGN
124 && wser.get( WSSecurityEngineResult.TAG_X509_CERTIFICATE ) != null )
125 {
126
127 userCertificate =
128 (X509Certificate) wser.get( WSSecurityEngineResult.TAG_X509_CERTIFICATE );
129
130 if ( LOG.isTraceEnabled() )
131 {
132 String issuerName =
133 ( (Principal) wser.get( WSSecurityEngineResult.TAG_PRINCIPAL ) ).getName();
134 LOG.trace( "Found WS-Security engine result. Message signed by " + issuerName );
135 }
136
137 context.put( SecurityConstants.X509_CLIENT_CERTIFICATE, userCertificate );
138
139
140 context.put( SecurityConstants.X509_CLIENT_CERTIFICATE_CHAIN,
141 createClientCertificateChain( crypto, userCertificate ) );
142 }
143 }
144 }
145
146
147
148
149
150
151
152
153 if ( userCertificate != null )
154 {
155 Subject subject = new Subject();
156 subject.getPrincipals().add( userCertificate.getSubjectX500Principal() );
157 subject.getPrincipals().add( userCertificate.getIssuerX500Principal() );
158 subject.getPublicCredentials().add( userCertificate );
159
160 WsagEngine.getWsagMessageContext().put( SecurityConstants.AUTHENTICATED_USER, subject );
161 }
162 else if ( WsagEngine.isAllowAnonymousAccess() )
163 {
164 Subject subject = new Subject();
165 subject.getPrincipals().add( new X500Principal( "anonymous" ) );
166 subject.getPublicCredentials().add( userCertificate );
167 WsagEngine.getWsagMessageContext().put( SecurityConstants.AUTHENTICATED_USER, subject );
168 }
169 else
170 {
171 throw new WSSecurityException( "The user was not authenticated." );
172 }
173 }
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188 private X509Certificate[] createClientCertificateChain( Crypto crypto, X509Certificate certificate )
189 throws WSSecurityException
190 {
191 X509Certificate[] result;
192
193
194 String subjectString = certificate.getSubjectDN().getName();
195 String issuerString = certificate.getIssuerDN().getName();
196 BigInteger issuerSerial = certificate.getSerialNumber();
197
198 String alias = crypto.getAliasForX509Cert( issuerString, issuerSerial );
199
200 if ( alias != null )
201 {
202
203 try
204 {
205 result = crypto.getCertificates( alias );
206
207
208
209 if ( result != null && result.length > 0 && certificate.equals( result[0] ) )
210 {
211 return result;
212 }
213 result = null;
214 }
215 catch ( WSSecurityException ex )
216 {
217 throw new WSSecurityException( getClass().getName()
218 + ": Could not get certificates for alias " + alias, ex );
219 }
220 }
221
222
223 String[] aliases = null;
224 try
225 {
226 aliases = crypto.getAliasesForDN( issuerString );
227 }
228 catch ( WSSecurityException ex )
229 {
230 throw new WSSecurityException( getClass().getName()
231 + ": Could not get alias for certificate with " + issuerString );
232 }
233
234
235
236 if ( aliases == null || aliases.length < 1 )
237 {
238 if ( LOG.isDebugEnabled() )
239 {
240 LOG.debug( "No aliases found in keystore for issuer " + issuerString + " of certificate for "
241 + subjectString + "." );
242 }
243
244 return null;
245 }
246
247
248
249 for ( int i = 0; i < aliases.length; i++ )
250 {
251 alias = aliases[i];
252
253 if ( LOG.isTraceEnabled() )
254 {
255 LOG.trace( "Preparing to validate certificate path with alias " + alias + " for issuer "
256 + issuerString + "." );
257 }
258
259
260 X509Certificate[] certs;
261 try
262 {
263 certs = crypto.getCertificates( alias );
264 }
265 catch ( WSSecurityException ex )
266 {
267 throw new WSSecurityException( getClass().getName()
268 + ": Could not get certificates for alias " + alias, ex );
269 }
270
271
272
273 if ( certs == null | certs.length < 1 )
274 {
275 throw new WSSecurityException( getClass().getName()
276 + ": Could not get certificates for alias " + alias );
277 }
278
279
280
281
282 try
283 {
284 if ( crypto.validateCertPath( certs ) )
285 {
286 if ( LOG.isTraceEnabled() )
287 {
288 LOG.trace( getClass().getName()
289 + ": Certificate path has been verified for certificate with subject "
290 + subjectString );
291 }
292
293
294 List<X509Certificate> resultCerts = new Vector<X509Certificate>();
295 resultCerts.add( certificate );
296 resultCerts.addAll( Arrays.asList( certs ) );
297 return resultCerts.toArray( new X509Certificate[resultCerts.size()] );
298 }
299 }
300 catch ( WSSecurityException ex )
301 {
302 throw new WSSecurityException( getClass().getName()
303 + ": Certificate path verification failed for certificate with subject " + subjectString,
304 ex );
305 }
306 }
307
308 if ( LOG.isInfoEnabled() )
309 {
310 LOG.info( getClass().getName() + ": Could not retrieve client certificate chain for subject "
311 + subjectString );
312 }
313
314 return null;
315 }
316
317 }