KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > iiop > security > SecClientRequestInterceptor


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24 package com.sun.enterprise.iiop.security;
25
26 import org.omg.CORBA.*;
27 import org.omg.PortableInterceptor.*;
28 import org.omg.IOP.*;
29 import java.util.*;
30 import java.security.AccessController JavaDoc;
31 import java.security.PrivilegedAction JavaDoc;
32 import java.security.cert.X509Certificate JavaDoc;
33
34 /* Import classes generated from CSIV2 idl files */
35 import com.sun.corba.ee.org.omg.CSI.*;
36 import com.sun.corba.ee.org.omg.GSSUP.*;
37
38 /* Import classes required for DER encoding and decoding */
39 import sun.security.util.DerInputStream;
40 import sun.security.util.DerOutputStream;
41 import sun.security.util.DerValue;
42
43 import sun.security.x509.*; // for X500 DN names
44
import javax.security.auth.*; // for JAAS subject
45

46 import com.sun.enterprise.security.auth.login.PasswordCredential;
47 import com.sun.enterprise.security.auth.login.X509CertificateCredential;
48 import com.sun.enterprise.util.ORBManager;
49 import com.sun.enterprise.util.LocalStringManagerImpl;
50 import com.sun.enterprise.iiop.CSIV2TaggedComponentInfo;
51 import java.util.logging.*;
52 import com.sun.logging.*;
53
54 /**
55  * This class implements a client side security request interceptor for CSIV2.
56  * It is used to send and receive the service context in a service context
57  * element in the service context list in an IIOP header.
58  *
59  * @author Sekhar Vajjhala
60  */

61
62 public class SecClientRequestInterceptor
63     extends org.omg.CORBA.LocalObject JavaDoc
64     implements ClientRequestInterceptor {
65     private static java.util.logging.Logger JavaDoc _logger=null;
66     static{
67        _logger=LogDomains.getLogger(LogDomains.CORBA_LOGGER);
68         }
69
70     private static LocalStringManagerImpl localStrings =
71     new LocalStringManagerImpl(SecClientRequestInterceptor.class);
72
73     private String JavaDoc name; // name of interceptor
74

75     /**
76      * prname (name + "::") is name of interceptor used for logging
77      * purposes. It is only used in the call to Logger.methodentry()
78      * in this file. Its purpose is to identify the interceptor name
79      */

80     private String JavaDoc prname;
81     private Codec codec; // used for marshalling
82
private ORB orb;
83     private SecurityService secsvc;
84
85     /**
86      * Hard code the value of 15 for SecurityAttributeService until
87      * it is defined in IOP.idl.
88      * sc.context_id = SecurityAttributeService.value;
89      */

90     protected static final int SECURITY_ATTRIBUTE_SERVICE_ID = 15;
91
92     public SecClientRequestInterceptor(String JavaDoc name, Codec codec) {
93     this.name = name;
94         this.codec = codec;
95         this.prname = name + "::";
96     }
97
98     public String JavaDoc name() {
99     return name;
100     }
101
102     /**
103      * Retrieves a single credential from a credset for the specified class.
104      * It also performs some semantic checking and logging.
105      *
106      * A null is returned if semantic checking fails.
107      */

108     private java.lang.Object JavaDoc getCred(Set credset, Class JavaDoc c) {
109
110         java.lang.Object JavaDoc cred = null ; // return value
111
String JavaDoc clsname = c.getName() ;
112         
113         /* check that there is only instance of a credential in the subject */
114         if(_logger.isLoggable(Level.FINE)) {
115         _logger.log(Level.FINE,"Checking for a single instance of class in subject");
116                 _logger.log(Level.FINE," Classname = " + clsname);
117     }
118         if (credset.size() != 1) {
119         if(_logger.isLoggable(Level.SEVERE))
120         _logger.log(Level.SEVERE,"iiop.multiple_credset",new java.lang.Object JavaDoc[]{new Integer JavaDoc(credset.size()),clsname});
121             throw new SecurityException JavaDoc(
122         localStrings.getLocalString("secclientreqinterceptor.inv_credlist_size",
123                                     "Credential list size is not 1."));
124     }
125
126         Iterator iter = credset.iterator();
127         while (iter.hasNext())
128             cred = iter.next();
129         if(_logger.isLoggable(Level.FINE))
130                 _logger.log(Level.FINE,"Verified single instance of class ( " +clsname + " )");
131         return cred;
132     }
133
134     /**
135      * Returns a client authentication token for the
136      * PasswordCredential in the subject.
137      * The client authentication token is cdr encoded.
138      */

139
140     private byte[] createAuthToken(java.lang.Object JavaDoc cred, Class JavaDoc cls)
141         throws Exception JavaDoc
142     {
143         byte[] gsstoken = {}; // GSS token
144

145         if (PasswordCredential.class.isAssignableFrom(cls)) {
146
147                 _logger.log(Level.FINE,"Constructing a PasswordCredential client auth token");
148
149             /* Generate mechanism specific GSS token for the GSSUP mechanism */
150             PasswordCredential pwdcred = (PasswordCredential) cred;
151         GSSUPToken tok = GSSUPToken.getClientSideInstance(orb, codec, pwdcred);
152             gsstoken = tok.getGSSToken();
153     }
154         return gsstoken;
155     }
156  
157     /**
158      * create and return an identity token from the credential.
159      * The identity token is cdr encoded.
160      */

161     private IdentityToken createIdToken(java.lang.Object JavaDoc cred, Class JavaDoc cls)
162         throws Exception JavaDoc {
163
164         IdentityToken idtok = null;
165
166         DerOutputStream dos = new DerOutputStream();
167         DerValue[] derval = {} ; // DER encoding buffer
168
byte[] cdrval ; // CDR encoding buffer
169
Any any = orb.create_any();
170         idtok = new IdentityToken();
171   
172         if (X500Name.class.isAssignableFrom(cls)) {
173                 _logger.log(Level.FINE,"Constructing an X500 DN Identity Token");
174             X500Name name = (X500Name) cred;
175             name.encode(dos); // ASN.1 encoding
176
X501DistinguishedNameHelper.insert(any, dos.toByteArray());
177
178             /* IdentityToken with CDR encoded X501 name */
179             idtok.dn(codec.encode_value(any));
180         } else if (X509CertificateCredential.class.isAssignableFrom(cls)) {
181                 _logger.log(Level.FINE,"Constructing an X509 Certificate Chain Identity Token");
182         /* create a DER encoding */
183             X509CertificateCredential certcred = (X509CertificateCredential) cred;
184             X509Certificate JavaDoc[] certchain = certcred.getX509CertificateChain();
185                 _logger.log(Level.FINE,"Certchain length = " + certchain.length);
186             derval = new DerValue[certchain.length];
187             for (int i = 0; i < certchain.length ; i++)
188                 derval[i] = new DerValue(certchain[i].getEncoded());
189             dos.putSequence(derval);
190             X509CertificateChainHelper.insert(any, dos.toByteArray());
191
192             /* IdentityToken with CDR encoded certificate chain */
193             idtok.certificate_chain(codec.encode_value(any));
194         } else if (AnonCredential.class.isAssignableFrom(cls)) {
195                 _logger.log(Level.FINE,"Constructing an Anonymous Identity Token");
196             idtok.anonymous(true);
197
198         } else if (GSSUPName.class.isAssignableFrom(cls)) {
199             /* GSSAPI Exported name */
200             _logger.log(Level.FINE,"Constructing a GSS Exported name Identity Token");
201         /* create a DER encoding */
202             GSSUPName gssname = (GSSUPName) cred;
203
204             byte[] expname = gssname.getExportedName();
205
206             GSS_NT_ExportedNameHelper.insert(any, expname);
207
208             /* IdentityToken with CDR encoded GSSUPName */
209             idtok.principal_name(codec.encode_value(any));
210     }
211         return (idtok);
212     }
213
214     /**
215      * send_request() interception point adds the security context to the
216      * service context field.
217      */

218     public void send_request(ClientRequestInfo ri) throws ForwardRequest
219     {
220         /**
221          * CSIV2 level 0 implementation only requires stateless clients.
222          * Client context id is therefore always set to 0.
223          */

224         long cContextId = 0; // CSIV2 requires type to be long
225

226         /**
227          * CSIV2 level 0 implementation does not require any authorization
228          * tokens to be sent over the wire. So set cAuthzElem to empty.
229          */

230     AuthorizationElement[] cAuthzElem = {} ;
231
232         /* Client identity token to be added to the service context field */
233         IdentityToken cIdentityToken = null;
234
235         /* Client authentication token to be added to the service context field */
236         byte[] cAuthenticationToken = {} ;
237
238         /* CDR encoded Security Attribute Service element */
239         byte[] cdr_encoded_saselm = {} ;
240
241         java.lang.Object JavaDoc cred = null ; // A single JAAS credential
242

243     if(_logger.isLoggable(Level.FINE))
244                 _logger.log(Level.FINE,"++++ Entered " + prname + "send_request" + "()");
245         SecurityContext secctxt = null; // SecurityContext to be sent
246

247         secsvc = Csiv2Manager.getSecurityService();
248     orb = ORBManager.getORB();
249         if (secsvc == null) {
250             _logger.log(Level.WARNING,"iiop.no_security_service");
251             return;
252     }
253     org.omg.CORBA.Object JavaDoc effective_target = ri.effective_target();
254     try{
255         secctxt = secsvc.getSecurityContext(effective_target);
256     }catch(InvalidMechanismException ime){
257                _logger.log(Level.SEVERE,"iiop.sec_context_exception",ime);
258         throw new RuntimeException JavaDoc(ime.getMessage());
259     }catch(InvalidIdentityTokenException iite){
260                 _logger.log(Level.SEVERE,"iiop.runtime_exception",iite);
261         throw new RuntimeException JavaDoc(iite.getMessage());
262     }
263
264         /**
265          * In an unprotected invocation, there is nothing to be sent to
266          * the service context field. Check for this case.
267          */

268         if (secctxt == null) {
269             if(_logger.isLoggable(Level.FINE)){
270                 _logger.log(Level.FINE,"Security context is null (nothing to add to service context)");
271             }
272             return;
273     }
274
275     final SecurityContext sCtx = secctxt;
276         /* Construct an authentication token */
277         if (secctxt.authcls != null) {
278             cred = AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
279                 public java.lang.Object JavaDoc run() {
280                     return getCred(sCtx.subject.getPrivateCredentials(sCtx.authcls), sCtx.authcls);
281                 }
282             });
283
284             try {
285                 cAuthenticationToken = createAuthToken(cred, secctxt.authcls);
286             } catch (Exception JavaDoc e) {
287                 _logger.log(Level.SEVERE,"iiop.createauthtoken_exception",e);
288             throw new SecurityException JavaDoc(
289             localStrings.getLocalString("secclientreqinterceptor.err_authtok_create",
290                             "Error while constructing an authentication token."));
291             }
292     }
293         
294
295         /* Construct an identity token */
296         if (secctxt.identcls != null) {
297             cred = getCred(secctxt.subject.getPublicCredentials(secctxt.identcls),
298                            secctxt.identcls);
299             try {
300                 cIdentityToken = createIdToken(cred, secctxt.identcls);
301             } catch (Exception JavaDoc e) {
302                 _logger.log(Level.SEVERE,"iiop.createidtoken_exception",e);
303             throw new SecurityException JavaDoc(
304             localStrings.getLocalString("secclientreqinterceptor.err_idtok_create",
305                             "Error while constructing an identity token."));
306             }
307     } else {
308             if(_logger.isLoggable(Level.FINE)){
309                 _logger.log(Level.FINE,"Constructing an Absent Identity Token");
310             }
311              cIdentityToken = new IdentityToken();
312              cIdentityToken.absent(true);
313     }
314
315         if(_logger.isLoggable(Level.FINE)){
316             _logger.log(Level.FINE,"Creating an EstablishContext message");
317         }
318     EstablishContext ec = new EstablishContext(cContextId,
319                                                    cAuthzElem,
320                                                    cIdentityToken,
321                                                    cAuthenticationToken);
322
323     SASContextBody sasctxbody = new SASContextBody();
324     sasctxbody.establish_msg(ec);
325
326         /* CDR encode the SASContextBody */
327         Any SasAny = orb.create_any();
328         SASContextBodyHelper.insert(SasAny, sasctxbody);
329
330         try {
331         cdr_encoded_saselm = codec.encode_value(SasAny);
332         } catch (Exception JavaDoc e) {
333                 _logger.log(Level.SEVERE,"iiop.encode_exception",e);
334         throw new SecurityException JavaDoc(
335         localStrings.getLocalString("secclientreqinterceptor.err_cdr_encode",
336                                     "CDR Encoding error for a SAS context element."));
337         }
338
339         /* add SAS element to service context list*/
340         ServiceContext sc = new ServiceContext();
341         sc.context_id = SECURITY_ATTRIBUTE_SERVICE_ID;
342         sc.context_data = cdr_encoded_saselm;
343         if(_logger.isLoggable(Level.FINE)){
344             _logger.log(Level.FINE,"Adding EstablishContext message to service context list");
345         }
346         boolean no_replace = false;
347         ri.add_request_service_context(sc, no_replace);
348         if(_logger.isLoggable(Level.FINE)){
349             _logger.log(Level.FINE,"Added EstablishContext message to service context list");
350         }
351     }
352
353     public void send_poll(ClientRequestInfo ri) {
354     }
355
356
357     /**
358      * set the reply status
359      */

360     private void setreplyStatus(int status, org.omg.CORBA.Object JavaDoc target) {
361         if(_logger.isLoggable(Level.FINE)){
362             _logger.log(Level.FINE,"Status to be set : " + status);
363         }
364         secsvc = Csiv2Manager.getSecurityService();
365         if (secsvc == null) {
366                 _logger.log(Level.WARNING,"iiop.no_security_service");
367             return;
368     }
369         secsvc.receivedReply(status, target);
370         if(_logger.isLoggable(Level.FINE)){
371                 _logger.log(Level.FINE,"Invoked receivedReply()");
372         }
373     }
374
375     /**
376      * Map the reply status code to a format suitable for J2EE RI.
377      *
378      * @param repst reply status from the service context field.
379      * @return mapped status code
380      *
381      */

382     private int mapreplyStatus(int repst)
383     {
384         int status;
385
386         if(_logger.isLoggable(Level.FINE)){
387                 _logger.log(Level.FINE,"Reply status to be mapped = " + repst);
388         }
389
390         switch (repst) {
391
392     case SUCCESSFUL.value:
393         case USER_EXCEPTION.value:
394             status = SecurityService.STATUS_PASSED;
395             break;
396
397         case LOCATION_FORWARD.value:
398         case TRANSPORT_RETRY.value:
399             status = SecurityService.STATUS_RETRY;
400             break;
401
402         case SYSTEM_EXCEPTION.value:
403         status = SecurityService.STATUS_FAILED;
404             break;
405
406     default:
407             status = repst;
408             /**
409              * There is currently no mapping defined for any other status
410              * codes. So map this is to a STATUS_FAILED.
411              */

412             break;
413         }
414         if(_logger.isLoggable(Level.FINE)){
415             _logger.log(Level.FINE,"Mapped reply status = " + status);
416         }
417         return status;
418     }
419
420     public void receive_reply(ClientRequestInfo ri)
421     {
422         ServiceContext sc = null;
423         int status = -1;
424  
425     if(_logger.isLoggable(Level.FINE)){
426                 _logger.log(Level.FINE,"++++ Entered " + prname + "receive_reply");
427         }
428     orb = ORBManager.getORB();
429
430         /**
431          * get the service context element from the reply and decode the
432          * mesage.
433          */

434     try {
435             sc = ri.get_reply_service_context(SECURITY_ATTRIBUTE_SERVICE_ID);
436     } catch(org.omg.CORBA.BAD_PARAM JavaDoc e) {
437         if(_logger.isLoggable(Level.FINE)){
438             _logger.log(Level.FINE,"No SAS context element found in service context list");
439         }
440             setreplyStatus(SecurityService.STATUS_PASSED, ri.effective_target());
441         return;
442     } catch(Exception JavaDoc ex) {
443             _logger.log(Level.SEVERE,"iiop.service_context_exception",ex);
444         return;
445     }
446
447         Any a = orb.create_any();
448         try {
449             a = codec.decode_value(sc.context_data, SASContextBodyHelper.type()); //decode the CDR encoding
450
} catch (Exception JavaDoc e) {
451                 _logger.log(Level.SEVERE,"iiop.decode_exception",e);
452         throw new SecurityException JavaDoc(
453         localStrings.getLocalString("secclientreqinterceptor.err_cdr_decode",
454                                     "CDR Decoding error for SAS context element."));
455     }
456
457         SASContextBody sasctxbody = SASContextBodyHelper.extract(a);
458         short sasdiscr = sasctxbody.discriminator();
459         if(_logger.isLoggable(Level.FINE)){
460             _logger.log(Level.FINE,"Received " + SvcContextUtils.getMsgname(sasdiscr) + " message");
461         }
462
463         /**
464          * Verify that either a CompleteEstablishContext msg or an
465          * ContextError message was received.
466          */

467          if(_logger.isLoggable(Level.FINE)){
468             _logger.log(Level.FINE,"Verifying the SAS protocol reply message");
469          }
470
471         /* Check the discriminator value */
472                  
473         if ((sasdiscr != MTCompleteEstablishContext.value)
474                && (sasdiscr != MTContextError.value)) {
475                     _logger.log(Level.SEVERE,"iiop.invalid_reply_message");
476         throw new SecurityException JavaDoc(
477         localStrings.getLocalString("secclientreqinterceptor.err_not_cecec_msg",
478                                     "Reply message not one of CompleteEstablishContext or ContextError."));
479     }
480
481         /* Map the error code */
482         int st = mapreplyStatus(ri.reply_status());
483  
484         setreplyStatus(st, ri.effective_target());
485     }
486   
487     public void receive_exception(ClientRequestInfo ri) throws ForwardRequest
488     {
489     if(_logger.isLoggable(Level.FINE)){
490                 _logger.log(Level.FINE,"++++ Entered " + prname + "receive_exception");
491         }
492     }
493    
494     public void receive_other(ClientRequestInfo ri) throws ForwardRequest
495     {
496     }
497
498     public void destroy()
499     {
500     }
501 }
502
Popular Tags