001: /**
002: * JOnAS: Java(TM) Open Application Server
003: * Copyright (C) 2004 Bull S.A.
004: * Contact: jonas-team@objectweb.org
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
019: * USA
020: *
021: * --------------------------------------------------------------------------
022: * $Id: Csiv2ServerInterceptor.java 6661 2005-04-28 08:43:27Z benoitf $
023: * --------------------------------------------------------------------------
024: */package org.objectweb.jonas.security.iiop;
025:
026: import org.omg.CORBA.Any;
027: import org.omg.CORBA.BAD_PARAM;
028: import org.omg.CORBA.NO_PERMISSION;
029: import org.omg.CSI.CompleteEstablishContext;
030: import org.omg.CSI.EstablishContext;
031: import org.omg.CSI.GSS_NT_ExportedNameHelper;
032: import org.omg.CSI.ITTPrincipalName;
033: import org.omg.CSI.IdentityToken;
034: import org.omg.CSI.MTEstablishContext;
035: import org.omg.CSI.MTMessageInContext;
036: import org.omg.CSI.SASContextBody;
037: import org.omg.CSI.SASContextBodyHelper;
038: import org.omg.GSSUP.InitialContextToken;
039: import org.omg.GSSUP.InitialContextTokenHelper;
040: import org.omg.IOP.Codec;
041: import org.omg.IOP.SecurityAttributeService;
042: import org.omg.IOP.ServiceContext;
043: import org.omg.IOP.CodecPackage.FormatMismatch;
044: import org.omg.IOP.CodecPackage.InvalidTypeForEncoding;
045: import org.omg.IOP.CodecPackage.TypeMismatch;
046: import org.omg.PortableInterceptor.ForwardRequest;
047: import org.omg.PortableInterceptor.ServerRequestInfo;
048: import org.omg.PortableInterceptor.ServerRequestInterceptor;
049:
050: import org.objectweb.carol.util.csiv2.gss.GSSHelper;
051:
052: import org.objectweb.util.monolog.api.BasicLevel;
053: import org.objectweb.util.monolog.api.Logger;
054:
055: /**
056: * SAS context interceptor on server side
057: * @see Csiv2 spec : A target security service (TSS) is the security service associated with the ORB that hosts the target object.
058: * @see Common Secure Interoperability V2 Specification (July 23,2001)
059: * @author Florent Benoit
060: */
061: public class Csiv2ServerInterceptor extends org.omg.CORBA.LocalObject
062: implements ServerRequestInterceptor {
063:
064: /**
065: * Name
066: */
067: private static final String NAME = "Csiv2ServerInterceptor";
068:
069: /**
070: * Codec to use
071: */
072: private Codec codec = null;
073:
074: /**
075: * Logger to use
076: */
077: private Logger logger = null;
078:
079: /**
080: * Logger details (On catching exception)
081: */
082: private Logger loggerDetails = null;
083:
084: /**
085: * Constructor
086: * @param codec used for encoding any objects
087: * @param logger used for logging useful information
088: * @param loggerDetails for all information (useless for most time :)
089: */
090: public Csiv2ServerInterceptor(Codec codec, Logger logger,
091: Logger loggerDetails) {
092: this .codec = codec;
093: this .logger = logger;
094: this .loggerDetails = loggerDetails;
095: }
096:
097: /**
098: * Allows an Interceptor to query request information after all the
099: * information, including operation parameters, are available. This
100: * interception point shall execute in the same thread as the target
101: * invocation.
102: * @param ri Information about the current request being intercepted.
103: * @exception ForwardRequest If thrown, indicates to the ORB that a
104: * retry of the request should occur with the new object given in
105: * the exception.
106: */
107: public void receive_request(ServerRequestInfo ri)
108: throws ForwardRequest {
109:
110: // Is there a security attribute service context (Csiv2 16.2 protocol message definition)
111: ServiceContext receiveServiceContext = null;
112: try {
113: // Csiv2 16.9.1 / Type defined for security attribute service
114: receiveServiceContext = ri
115: .get_request_service_context(SecurityAttributeService.value);
116: if (logger.isLoggable(BasicLevel.DEBUG)) {
117: logger.log(BasicLevel.DEBUG,
118: "Got security service context = "
119: + receiveServiceContext);
120: }
121: } catch (BAD_PARAM e) {
122: if (loggerDetails.isLoggable(BasicLevel.DEBUG)) {
123: loggerDetails.log(BasicLevel.DEBUG,
124: "No security service context found");
125: }
126: }
127:
128: // No serviceContext, just return
129: if (receiveServiceContext == null) {
130: return;
131: }
132:
133: // Analyze service context
134: SASContextBody receivedSASContextBody = null;
135: Any receiveAny = null;
136: try {
137: receiveAny = codec.decode_value(
138: receiveServiceContext.context_data,
139: SASContextBodyHelper.type());
140: } catch (FormatMismatch fm) {
141: logger.log(BasicLevel.ERROR,
142: "Format mismatch while decoding value :"
143: + fm.getMessage());
144: return;
145: } catch (TypeMismatch tm) {
146: logger.log(BasicLevel.ERROR,
147: "Type mismatch while decoding value :"
148: + tm.getMessage());
149: return;
150: }
151: receivedSASContextBody = SASContextBodyHelper
152: .extract(receiveAny);
153: if (receivedSASContextBody == null) {
154: logger.log(BasicLevel.ERROR,
155: "Received Sascontext body is null");
156: return;
157: }
158: short discriminator = receivedSASContextBody.discriminator();
159:
160: if (discriminator == MTEstablishContext.value) {
161: // Analyze the establish context message
162: EstablishContext receivedEstablishContext = receivedSASContextBody
163: .establish_msg();
164:
165: // client authentication token
166: byte[] clientAuthenticationToken = receivedEstablishContext.client_authentication_token;
167: // identity token
168: IdentityToken identityToken = receivedEstablishContext.identity_token;
169:
170: // client authentication token case
171: if (clientAuthenticationToken != null
172: && clientAuthenticationToken.length != 0) {
173: Any pAny = null;
174: try {
175: pAny = codec
176: .decode_value(
177: GSSHelper
178: .decodeToken(receivedEstablishContext.client_authentication_token),
179: InitialContextTokenHelper.type());
180: } catch (FormatMismatch fm) {
181: logger.log(BasicLevel.ERROR,
182: "Format mismatch while decoding value :"
183: + fm.getMessage());
184: return;
185: } catch (TypeMismatch tm) {
186: logger.log(BasicLevel.ERROR,
187: "Type mismatch while decoding value :"
188: + tm.getMessage());
189: return;
190: }
191: InitialContextToken initialContextToken = InitialContextTokenHelper
192: .extract(pAny);
193: String userName = new String(
194: initialContextToken.username);
195: String password = new String(
196: initialContextToken.password);
197: if (logger.isLoggable(BasicLevel.DEBUG)) {
198: logger.log(BasicLevel.DEBUG,
199: "Received InitialContextToken, login = '"
200: + userName + "' and password = '"
201: + password + "'.");
202: }
203: SecurityContextHelper.getInstance()
204: .loginAuthenticationToken(userName, password);
205:
206: } else if (identityToken != null) { // identity token case
207: try {
208: // Principal name case
209: if (identityToken.discriminator() == ITTPrincipalName.value) {
210: Any a = codec.decode_value(
211: receivedEstablishContext.identity_token
212: .principal_name(),
213: GSS_NT_ExportedNameHelper.type());
214: byte[] encodedName = GSS_NT_ExportedNameHelper
215: .extract(a);
216:
217: // Decode the principal name
218: String principalName = GSSHelper
219: .decodeExported(encodedName);
220: if (logger.isLoggable(BasicLevel.DEBUG)) {
221: logger.log(BasicLevel.DEBUG,
222: "Received identityToken, principalName = "
223: + principalName);
224: }
225: SecurityContextHelper.getInstance()
226: .loginIdentiyToken(principalName);
227: }
228: } catch (Exception e) {
229: logger.log(BasicLevel.ERROR, "Error = "
230: + e.getMessage());
231: return;
232: }
233: }
234:
235: } else if (discriminator == MTMessageInContext.value) { // not handle
236: throw new NO_PERMISSION();
237: }
238:
239: // Make CompleteEstablish context message
240: /**
241: * CompleteEstablishContext Message Format [23] <br>
242: * A CompleteEstablishContext message is sent by a TSS in response to an
243: * EstablishContext message to indicate that the context was
244: * established. The CompleteEstablishContext message contains the
245: * following fields:
246: * <ul>
247: * <li>client_context_id The CSS allocated identifier for the security
248: * attribute context. It is returned by the target so that a stateful
249: * CSS can link this message to the EstablishContext request. A TSS
250: * shall always return the value of the client_context_id it received in
251: * the EstablishContext message.</li>
252: * <li>context_stateful The value returned by the TSS to indicate
253: * whether or not the established context is stateful, and thus
254: * reusable. A stateless TSS shall always return false. A stateful TSS
255: * shall return true if the established context is reusable. Otherwise a
256: * stateful TSS shall return false.</li>
257: * <li>final_context_token The GSS mechanism-specific final context
258: * token that is returned by a TSS if the client requests mutual
259: * authentication. When a TSS accepts an EstablishContext message
260: * containing an initial context token that requires mutual
261: * authentication, the TSS shall return a mechanism-specific final
262: * context token. Not all GSS mechanisms support mutual authentication,
263: * and thus not all responses to initial context tokens may include
264: * final (or output) context tokens.5 When a CompleteEstablishContext
265: * message contains a final_context_token, the token shall be applied
266: * (with GSS_Init_sec_context) to the client-side GSS state machine
267: * </li>
268: * </ul>
269: */
270: CompleteEstablishContext completeEstablishContext = new CompleteEstablishContext(
271: Csiv2Const.STATELESS_CONTEXT_ID,
272: Csiv2Const.STATEFUL_MODE, Csiv2Const.EMPTY_BYTES);
273:
274: /**
275: * And then, this message should be added. see 16.2.1 The Security
276: * Attribute Service Context Element [10] This specification defines a
277: * new GIOP service context element type, the security attribute service
278: * (SAS) element. <br>
279: * [11] The SAS context element may be used to associate any or all of
280: * the following contexts with GIOP request and reply messages: "
281: * Identity context, to be accepted based on trust " Authorization
282: * context, including authorization-based delegation context " Client
283: * authentication context <br>
284: * [12] A new context_id has been defined for the SAS element. const
285: * ServiceId SecurityAttributeService = 15
286: */
287: Any pAny = null;
288: try {
289: pAny = ORBHelper.getOrb().create_any();
290: } catch (Csiv2InterceptorException csie) {
291: logger.log(BasicLevel.ERROR, "Cannot get orb for any = "
292: + csie.getMessage());
293: return;
294: }
295:
296: // Generate contextData of service context with EstablishContext
297: SASContextBody sasContextBody = new SASContextBody();
298: sasContextBody.complete_msg(completeEstablishContext);
299: SASContextBodyHelper.insert(pAny, sasContextBody);
300: byte[] contextData = null;
301:
302: try {
303: contextData = codec.encode_value(pAny);
304: } catch (InvalidTypeForEncoding itfe) {
305: logger.log(BasicLevel.ERROR,
306: "Cannot encode a given any corba object : "
307: + itfe.getMessage());
308: return;
309: }
310:
311: // build service context and add it
312: ServiceContext serviceContext = new ServiceContext(
313: SecurityAttributeService.value, contextData);
314: ri.add_reply_service_context(serviceContext,
315: Csiv2Const.REPLACE_SECURITY_ATTRIBUTE_SERVICE);
316:
317: }
318:
319: /**
320: * Allows the interceptor to process service context information.
321: * @param ri Information about the current request being intercepted.
322: * @exception ForwardRequest If thrown, indicates to the ORB that a
323: * retry of the request should occur with the new object given in
324: * the exception.
325: */
326: public void receive_request_service_contexts(ServerRequestInfo ri)
327: throws ForwardRequest {
328: // TODO Auto-generated method stub
329:
330: }
331:
332: /**
333: * Allows an Interceptor to query the exception information and modify
334: * the reply service context before the exception is thrown to the client.
335: * When an exception occurs, this interception point is called. This
336: * interception point shall execute in the same thread as the target
337: * invocation.
338: * @param ri Information about the current request being intercepted.
339: * @exception ForwardRequest If thrown, indicates to the ORB that a
340: * retry of the request should occur with the new object given in
341: * the exception.
342: */
343: public void send_exception(ServerRequestInfo ri)
344: throws ForwardRequest {
345: // TODO Auto-generated method stub
346:
347: }
348:
349: /**
350: * Allows an Interceptor to query the information available when a
351: * request results in something other than a normal reply or an
352: * exception.
353: * @param ri Information about the current request being intercepted.
354: * @exception ForwardRequest If thrown, indicates to the ORB that a
355: * retry of the request should occur with the new object given in
356: * the exception.
357: */
358: public void send_other(ServerRequestInfo ri) throws ForwardRequest {
359: // TODO Auto-generated method stub
360:
361: }
362:
363: /**
364: * Allows an Interceptor to query reply information and modify the
365: * reply service context after the target operation has been invoked
366: * and before the reply is returned to the client. This interception
367: * point shall execute in the same thread as the target invocation.
368: * @param ri Information about the current request being intercepted.
369: */
370: public void send_reply(ServerRequestInfo ri) {
371:
372: }
373:
374: /**
375: * Provides an opportunity to destroy this interceptor.
376: */
377: public void destroy() {
378:
379: }
380:
381: /**
382: * Returns the name of the interceptor.
383: * @return the name of the interceptor.
384: */
385: public String name() {
386: return NAME;
387: }
388: }
|