KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jonas > security > iiop > Csiv2ClientInterceptor


1 /**
2  * JOnAS: Java(TM) Open Application Server
3  * Copyright (C) 2004 Bull S.A.
4  * Contact: jonas-team@objectweb.org
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  * USA
20  *
21  * --------------------------------------------------------------------------
22  * $Id: Csiv2ClientInterceptor.java,v 1.4 2005/01/07 13:28:28 joaninh Exp $
23  * --------------------------------------------------------------------------
24  */

25 package org.objectweb.jonas.security.iiop;
26
27 import java.io.IOException JavaDoc;
28 import java.io.UnsupportedEncodingException JavaDoc;
29
30 import org.omg.CORBA.Any JavaDoc;
31 import org.omg.CORBA.BAD_PARAM JavaDoc;
32 import org.omg.CSI.AuthorizationElement;
33 import org.omg.CSI.EstablishContext;
34 import org.omg.CSI.GSS_NT_ExportedNameHelper;
35 import org.omg.CSI.IdentityToken;
36 import org.omg.CSI.SASContextBody;
37 import org.omg.CSI.SASContextBodyHelper;
38 import org.omg.CSIIOP.CompoundSecMech;
39 import org.omg.CSIIOP.CompoundSecMechList;
40 import org.omg.CSIIOP.CompoundSecMechListHelper;
41 import org.omg.CSIIOP.EstablishTrustInClient;
42 import org.omg.CSIIOP.IdentityAssertion;
43 import org.omg.CSIIOP.TAG_CSI_SEC_MECH_LIST;
44 import org.omg.GSSUP.InitialContextToken;
45 import org.omg.GSSUP.InitialContextTokenHelper;
46 import org.omg.IOP.Codec JavaDoc;
47 import org.omg.IOP.SecurityAttributeService;
48 import org.omg.IOP.ServiceContext JavaDoc;
49 import org.omg.IOP.TaggedComponent JavaDoc;
50 import org.omg.IOP.CodecPackage.FormatMismatch JavaDoc;
51 import org.omg.IOP.CodecPackage.InvalidTypeForEncoding JavaDoc;
52 import org.omg.IOP.CodecPackage.TypeMismatch JavaDoc;
53 import org.omg.PortableInterceptor.ClientRequestInfo JavaDoc;
54 import org.omg.PortableInterceptor.ClientRequestInterceptor JavaDoc;
55 import org.omg.PortableInterceptor.ForwardRequest JavaDoc;
56
57 import org.objectweb.carol.util.csiv2.gss.GSSHelper;
58
59 import org.objectweb.util.monolog.api.BasicLevel;
60 import org.objectweb.util.monolog.api.Logger;
61
62 /**
63  * SAS context interceptor on client side.
64  * @see Csiv2 spec : A client security service (CSS) is the security service
65  * associated with the ORB that is used by the client to invoke the target
66  * object.
67  * @see client state machine (fig 16-3)
68  * @see Common Secure Interoperability V2 Specification (July 23,2001)
69  * @author Florent Benoit
70  */

71 public class Csiv2ClientInterceptor extends org.omg.CORBA.LocalObject JavaDoc implements ClientRequestInterceptor JavaDoc {
72
73     /**
74      * Name
75      */

76     private static final String JavaDoc NAME = "Csiv2ClientInterceptor";
77
78     /**
79      * Codec to use
80      */

81     private Codec JavaDoc codec = null;
82
83     /**
84      * Logger to use
85      */

86     private Logger logger = null;
87
88     /**
89      * Logger details (On catching exception)
90      */

91     private Logger loggerDetails = null;
92
93     /**
94      * Constructor
95      * @param codec used for encoding any objects
96      * @param logger used for logging useful information
97      * @param loggerDetails for all information (useless for most time :)
98      */

99     public Csiv2ClientInterceptor(Codec JavaDoc codec, Logger logger, Logger loggerDetails) {
100         this.codec = codec;
101         this.logger = logger;
102         this.loggerDetails = loggerDetails;
103     }
104
105     /**
106      * Indicates to the interceptor that an exception occurred. Allows
107      * an Interceptor to query the exception's information before it is
108      * thrown to the client.
109      * @param ri Information about the current request being intercepted.
110      * @exception ForwardRequest If thrown, indicates to the ORB that a
111      * retry of the request should occur with the new object given in
112      * the exception.
113      */

114     public void receive_exception(ClientRequestInfo JavaDoc ri) throws ForwardRequest JavaDoc {
115
116     }
117
118     /**
119      * Allows an Interceptor to query the information available when a
120      * request results in something other than a normal reply or an
121      * exception.
122      * @param ri Information about the current request being intercepted.
123      * @exception ForwardRequest If thrown, indicates to the ORB that a
124      * retry of the request should occur with the new object given in
125      * the exception.
126      */

127     public void receive_other(ClientRequestInfo JavaDoc ri) throws ForwardRequest JavaDoc {
128
129     }
130
131     /**
132      * Allows an Interceptor to query the information on a reply after it
133      * is returned from the server and before control is returned to the
134      * client.
135      * <p>
136      * @param ri Information about the current request being intercepted.
137      */

138     public void receive_reply(ClientRequestInfo JavaDoc ri) {
139
140     }
141
142     /**
143      * Allows an Interceptor to query information during a Time-Independent
144      * Invocation (TII) polling get reply sequence.
145      * @param ri Information about the current request being intercepted.
146      */

147     public void send_poll(ClientRequestInfo JavaDoc ri) {
148
149     }
150
151     /**
152      * Need to send an establish context as described in the CSS state machine
153      * Compliance with level 0, so stateless context
154      * @see fig 16-3 of spec. [109] <br>
155      */

156     public void send_request(ClientRequestInfo JavaDoc ri) throws ForwardRequest JavaDoc {
157
158         // Is there a TAG_CSI_SEC_MECH tagged component in the request ?
159
TaggedComponent JavaDoc taggedComponent = null;
160         try {
161             taggedComponent = ri.get_effective_component(TAG_CSI_SEC_MECH_LIST.value);
162             if (logger.isLoggable(BasicLevel.DEBUG)) {
163                 logger.log(BasicLevel.DEBUG, "There is a TAG_CSI_SEC_MECH_LIST tagged component");
164             }
165
166         } catch (BAD_PARAM JavaDoc e) {
167             if (loggerDetails.isLoggable(BasicLevel.DEBUG)) {
168                 loggerDetails.log(BasicLevel.DEBUG, "No tagged component with id " + TAG_CSI_SEC_MECH_LIST.value);
169             }
170             return;
171
172         }
173
174         // Nothing to do if the component is not here
175
if (taggedComponent == null) {
176             return;
177         }
178
179
180         // Extract infos from the received TaggedComponent
181
Any JavaDoc pAny = null;
182         try {
183             pAny = codec.decode_value(taggedComponent.component_data, CompoundSecMechListHelper.type());
184         } catch (FormatMismatch JavaDoc fm) {
185             logger.log(BasicLevel.ERROR, "Format mismatch while decoding value :" + fm.getMessage());
186             return;
187         } catch (TypeMismatch JavaDoc tm) {
188             logger.log(BasicLevel.ERROR, "Type mismatch while decoding value :" + tm.getMessage());
189             return;
190         }
191
192         // TODO : there can have several compound sech mech
193
// For now, take first
194
CompoundSecMechList compoundSecMechList = CompoundSecMechListHelper.extract(pAny);
195         CompoundSecMech compoundSecMech = null;
196         if (compoundSecMechList.mechanism_list.length > 0) {
197             compoundSecMech = compoundSecMechList.mechanism_list[0];
198         } else {
199             // no compound sec mech received !
200
if (logger.isLoggable(BasicLevel.DEBUG)) {
201                 logger.log(BasicLevel.DEBUG, "No coumpound sec mech in the list.");
202             }
203             return;
204         }
205
206
207         /**
208          * Now, build the EstablishContext message with stateless mode [17]
209          * EstablishContextMessage format Interoperability EstablishContext <br>
210          * <br>
211          * An EstablishContext message is sent by a CSS to establish a SAS
212          * context with a TSS. The SAS context and the context identifier
213          * allocated by the CSS to refer to it are scoped to the transport layer
214          * connection or association over which the CSS and TSS are
215          * communicating. When an association is dismantled, all SAS contexts
216          * scoped to the connection shall be invalidated and may be discarded.
217          * The EstablishContext message contains the following fields: <br>
218          * <ul>
219          * <li>client_context_id The CSS allocated identifier for the security
220          * attribute service context. A stateless CSS shall set the
221          * client_context_id to 0, indicating to the TSS that it is stateless. A
222          * stateful CSS may allocate a nonzero client_context_id.</li>
223          * <li>authorization_token May be used by a CSS to push privilege
224          * information to a TSS. A CSS may use this token to send proxy
225          * privileges to a TSS as a means to enable the target to issue calls as
226          * the client.</li>
227          * <li>identity_token Carries a representation of the invocation
228          * identity for the call (that is, the identity under which the call is
229          * to be authorized). The identity_token carries a representation of the
230          * invocation identity in one of the following forms:
231          * <ol>
232          * <li>A typed mechanism-specific representation of a principal name
233          * </li>
234          * <li>A chain of identity certificates representing the subject and a
235          * chain of verifying authorities</li>
236          * <li>A distinguished name</li>
237          * <li>The anonymous principal identity (a type, not a name)</li>
238          * </ol>
239          * An identity_token is used to assert a caller identity when that
240          * identity differs from the identity proven by authentication in the
241          * authentication layer(s). If the caller identity is intended to be the
242          * same as that established in the authentication layer(s), then it does
243          * not need to be asserted in an identity_token.</li>
244          * <li>client_authentication_token Carries a mechanism-specific GSS
245          * initial context token that authenticates the client to the TSS. It
246          * contains a mechanism type identifier and the mechanism-specific
247          * evidence (that is, the authenticator) required by the TSS to
248          * authenticate the client. When an initial context token contains
249          * private credentials, such as a password, this message may be safely
250          * sent only after a confidential connection with a trusted TSS has been
251          * established. The determination of when it is safe to send a client
252          * authentication token in an EstablishContext message shall be
253          * considered in the context of the CORBA location-binding paradigm for
254          * persistent objects (where an invocation may be location forwarded by
255          * a location daemon to the target object).</li>
256          * </ul>
257          */

258
259         long clientContextId = Csiv2Const.STATELESS_CONTEXT_ID;
260         AuthorizationElement[] withoutAuthorizationToken = new AuthorizationElement[0];
261
262         IdentityToken identityToken = null;
263
264         // Anonymous
265
IdentityToken anonymousIdentityToken = new IdentityToken();
266         anonymousIdentityToken.anonymous(true);
267
268         // Absent
269
IdentityToken absentIdentityToken = new IdentityToken();
270         absentIdentityToken.absent(true);
271
272
273         byte[] clientAuthenticationToken = Csiv2Const.EMPTY_BYTES;
274
275
276         // Test what we need to send (depending of the support)
277
// see 16-5.2 section
278

279         // Client authentication token
280
if ((compoundSecMech.as_context_mech.target_requires & EstablishTrustInClient.value) == EstablishTrustInClient.value) {
281             pAny = null;
282             try {
283                 pAny = ORBHelper.getOrb().create_any();
284             } catch (Csiv2InterceptorException csie) {
285                 logger.log(BasicLevel.ERROR, "Cannot get orb for any = " + csie.getMessage());
286                 return;
287             }
288             InitialContextToken initialContextToken = null;
289             try {
290                 initialContextToken = SecurityContextHelper.getInstance().getInitialContextToken();
291             } catch (UnsupportedEncodingException JavaDoc uee) {
292                 logger.log(BasicLevel.ERROR, "Unsupported encoding for UTF8" + uee.getMessage());
293                 return;
294             }
295             InitialContextTokenHelper.insert(pAny, initialContextToken);
296             byte[] contextData = null;
297
298             try {
299                 contextData = codec.encode_value(pAny);
300             } catch (InvalidTypeForEncoding JavaDoc itfe) {
301                 logger.log(BasicLevel.ERROR, "Cannot encode a given any corba object : " + itfe.getMessage());
302                 return;
303             }
304
305             try {
306                 clientAuthenticationToken = GSSHelper.encodeToken(contextData);
307             } catch (IOException JavaDoc ioe) {
308                 logger.log(BasicLevel.ERROR, "Cannot encode client authentication token : " + ioe.getMessage());
309                 return;
310             }
311         }
312
313
314         // Identity token case
315
if ((compoundSecMech.sas_context_mech.target_supports & IdentityAssertion.value) == IdentityAssertion.value) {
316             pAny = null;
317             try {
318                 pAny = ORBHelper.getOrb().create_any();
319             } catch (Csiv2InterceptorException csie) {
320                 logger.log(BasicLevel.ERROR, "Cannot get orb for any = " + csie.getMessage());
321                 return;
322             }
323
324
325             // Insert username
326
String JavaDoc identity = SecurityContextHelper.getInstance().getIdentityToken();
327             byte[] name = GSSHelper.encodeExported(identity);
328             byte[] principalName = null;
329             GSS_NT_ExportedNameHelper.insert(pAny, name);
330             try {
331                 principalName = codec.encode_value(pAny);
332             } catch (InvalidTypeForEncoding JavaDoc itfe) {
333                 logger.log(BasicLevel.ERROR, "Cannot encode a given any corba object : " + itfe.getMessage());
334                 return;
335             }
336
337
338             // Put name in the token
339
identityToken = new IdentityToken();
340             identityToken.principal_name(principalName);
341
342         }
343
344         // No identity was set (principal name), so use absent identity
345
if (identityToken == null) {
346             identityToken = absentIdentityToken;
347         }
348
349         // if absent and no client auth token, don't do anything
350
if (identityToken == absentIdentityToken && clientAuthenticationToken == Csiv2Const.EMPTY_BYTES) {
351             return;
352         }
353
354
355         EstablishContext establishContext = new EstablishContext(clientContextId, withoutAuthorizationToken,
356                 identityToken, clientAuthenticationToken);
357
358
359
360
361
362         /**
363          * And then, this message should be added. see 16.2.1 The Security
364          * Attribute Service Context Element [10] This specification defines a
365          * new GIOP service context element type, the security attribute service
366          * (SAS) element. <br>
367          * [11] The SAS context element may be used to associate any or all of
368          * the following contexts with GIOP request and reply messages: "
369          * Identity context, to be accepted based on trust " Authorization
370          * context, including authorization-based delegation context " Client
371          * authentication context <br>
372          * [12] A new context_id has been defined for the SAS element. const
373          * ServiceId SecurityAttributeService = 15
374          */

375         try {
376             pAny = ORBHelper.getOrb().create_any();
377         } catch (Csiv2InterceptorException csie) {
378             logger.log(BasicLevel.ERROR, "Cannot get orb for any = " + csie.getMessage());
379             return;
380         }
381
382         // Generate contextData of service context with EstablishContext
383
SASContextBody sasContextBody = new SASContextBody();
384         sasContextBody.establish_msg(establishContext);
385         SASContextBodyHelper.insert(pAny, sasContextBody);
386         byte[] contextData = null;
387
388         try {
389             contextData = codec.encode_value(pAny);
390         } catch (InvalidTypeForEncoding JavaDoc itfe) {
391             logger.log(BasicLevel.ERROR, "Cannot encode a given any corba object : " + itfe.getMessage());
392             return;
393         }
394
395         // build service context and add it
396
ServiceContext JavaDoc serviceContext = new ServiceContext JavaDoc(SecurityAttributeService.value, contextData);
397         ri.add_request_service_context(serviceContext, Csiv2Const.REPLACE_SECURITY_ATTRIBUTE_SERVICE);
398
399     }
400
401     /**
402      * Provides an opportunity to destroy this interceptor.
403      */

404     public void destroy() {
405         // TODO Auto-generated method stub
406

407     }
408
409     /**
410      * Returns the name of the interceptor.
411      * @return the name of the interceptor.
412      */

413     public String JavaDoc name() {
414         return NAME;
415     }
416
417 }
Popular Tags