KickJava   Java API By Example, From Geeks To Geeks.

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


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 java.io.IOException JavaDoc;
27 import java.io.InputStream JavaDoc;
28 import sun.security.util.ObjectIdentifier;
29 import sun.security.util.DerInputStream;
30 import sun.security.util.DerOutputStream;
31
32 import com.sun.corba.ee.org.omg.GSSUP.GSSUPMechOID;
33 import com.sun.corba.ee.org.omg.CSI.GSS_NT_Export_Name_OID;
34 import com.sun.corba.ee.org.omg.CSI.GSS_NT_Scoped_Username_OID;
35 import java.util.logging.*;
36 import com.sun.logging.*;
37
38 /*
39  * @author Sekhar Vajjhala
40  * (Almost complete rewrite of an old version)
41  *
42  */

43
44 public class GSSUtils
45 {
46     private static java.util.logging.Logger JavaDoc _logger=null;
47     static{
48        _logger=LogDomains.getLogger(LogDomains.CORBA_LOGGER);
49         }
50     public static ObjectIdentifier GSSUP_MECH_OID = null;
51
52     public static ObjectIdentifier GSS_NT_EXPORT_NAME_OID = null;
53
54     /* GSS_NT_SCOPED_USERNAME_OID is currently not used by this class. It is
55      * defined here for the sake of completeness.
56      */

57     public static ObjectIdentifier GSS_NT_SCOPED_USERNAME_OID = null;
58
59     static {
60
61         int i ; // index
62
ObjectIdentifier x = null;
63
64         /* Construct an ObjectIdentifer by extracting each OID */
65
66         try {
67             i = GSSUPMechOID.value.indexOf(':');
68             x = new ObjectIdentifier( GSSUPMechOID.value.substring(i+1));
69     } catch(IOException JavaDoc e) {
70             x = null;
71             _logger.log(Level.SEVERE,"iiop.IOexception",e);
72     }
73         GSSUP_MECH_OID = x;
74
75         try {
76             i = GSS_NT_Export_Name_OID.value.indexOf(':');
77             x = new ObjectIdentifier( GSS_NT_Export_Name_OID.value.substring(i+1));
78     } catch(IOException JavaDoc e) {
79             x = null;
80                 _logger.log(Level.SEVERE,"iiop.IOexception",e);
81     }
82         GSS_NT_EXPORT_NAME_OID = x;
83
84         try {
85             i = GSS_NT_Scoped_Username_OID.value.indexOf(':');
86             x = new ObjectIdentifier( GSS_NT_Scoped_Username_OID.value.substring(i+1));
87     } catch(IOException JavaDoc e) {
88             x = null;
89                 _logger.log(Level.SEVERE,"iiop.IOexception",e);
90     }
91         GSS_NT_SCOPED_USERNAME_OID = x;
92
93         try {
94         if(_logger.isLoggable(Level.FINE)) {
95         _logger.log(Level.FINE,"GSSUP_MECH_OID: " + dumpHex(getDER(GSSUP_MECH_OID)));
96         _logger.log(Level.FINE,"GSS_NT_EXPORT_NAME_OID: " + dumpHex(getDER(GSS_NT_EXPORT_NAME_OID)));
97         _logger.log(Level.FINE,"GSS_NT_SCOPED_USERNAME_OID: " + dumpHex(getDER(GSS_NT_SCOPED_USERNAME_OID)));
98         }
99     } catch(IOException JavaDoc e) {
100                 _logger.log(Level.SEVERE,"iiop.IOexception",e);
101     }
102     }
103
104     // Dumps the hex values in the given byte array
105
public static String JavaDoc dumpHex( byte[] octets ) {
106     StringBuffer JavaDoc result = new StringBuffer JavaDoc( "" );
107     for( int i = 0; i < octets.length; i++ ) {
108         if( (i != 0) && ((i % 16) == 0) ) result.append( "\n " );
109         int b = octets[i];
110         if( b < 0 ) b = 256 + b;
111         String JavaDoc hex = Integer.toHexString( b );
112         if( hex.length() == 1 ) {
113         hex = "0" + hex;
114         }
115         result.append( hex + " " );
116     }
117
118     return result.toString();
119     }
120
121     /* Import the exported name from the mechanism independent
122      * exported name.
123      */

124      
125     public static byte[] importName(ObjectIdentifier oid, byte[] externalName)
126     throws IOException JavaDoc
127     {
128         if(_logger.isLoggable(Level.FINE)) {
129         _logger.log(Level.FINE,"Attempting to import mechanism independent name");
130         _logger.log(Level.FINE,dumpHex(externalName));
131     }
132
133     IOException JavaDoc e = new IOException JavaDoc("Invalid Name");
134
135     if (externalName[0] != 0x04)
136         throw e;
137
138         if (externalName[1] != 0x01)
139         throw e;
140
141     int mechoidlen = (((int)externalName[2]) << 8)+ externalName[3];
142
143         if(_logger.isLoggable(Level.FINE))
144         _logger.log(Level.FINE,"Mech OID length = " + mechoidlen);
145     if (externalName.length < (4 + mechoidlen + 4))
146         throw e;
147
148         /* get the mechanism OID and verify it is the same as oid
149          * passed as an argument.
150          */

151
152         byte[] deroid = new byte[mechoidlen];
153     System.arraycopy(externalName, 4, deroid, 0, mechoidlen);
154         ObjectIdentifier oid1 = getOID(deroid);
155         if ( ! oid1.equals(oid) )
156             throw e;
157
158         int pos = 4 + mechoidlen;
159
160     int namelen = (((int) externalName[pos]) << 24)
161                       + (((int) externalName[pos+1]) << 16)
162                       + (((int) externalName[pos+2]) << 8)
163                       + (((int) externalName[pos+3]));
164
165         pos += 4; // start of the mechanism specific exported name
166

167         if (externalName.length != (4 + mechoidlen + 4 + namelen))
168         throw e;
169
170         byte[] name = new byte[externalName.length - pos];
171         System.arraycopy(externalName, pos, name, 0, externalName.length - pos);
172         if(_logger.isLoggable(Level.FINE)) {
173         _logger.log(Level.FINE,"Mechanism specific name:");
174         _logger.log(Level.FINE,dumpHex(name));
175         _logger.log(Level.FINE,"Successfully imported mechanism independent name");
176     }
177     return name;
178     }
179
180     /* verify if exportedName is of object ObjectIdentifier.*/
181      
182     public static boolean verifyMechOID(ObjectIdentifier oid, byte[] externalName)
183     throws IOException JavaDoc
184     {
185         if(_logger.isLoggable(Level.FINE)) {
186         _logger.log(Level.FINE,"Attempting to verify mechanism independent name");
187         _logger.log(Level.FINE,dumpHex(externalName));
188     }
189
190     IOException JavaDoc e = new IOException JavaDoc("Invalid Name");
191
192     if (externalName[0] != 0x04)
193         throw e;
194
195         if (externalName[1] != 0x01)
196         throw e;
197
198     int mechoidlen = (((int)externalName[2]) << 8)+ externalName[3];
199
200         if(_logger.isLoggable(Level.FINE)) {
201         _logger.log(Level.FINE,"Mech OID length = " + mechoidlen);
202             }
203     if (externalName.length < (4 + mechoidlen + 4))
204         throw e;
205
206         /* get the mechanism OID and verify it is the same as oid
207          * passed as an argument.
208          */

209
210         byte[] deroid = new byte[mechoidlen];
211     System.arraycopy(externalName, 4, deroid, 0, mechoidlen);
212         ObjectIdentifier oid1 = getOID(deroid);
213         if ( ! oid1.equals(oid) )
214             return false;
215         else
216             return true;
217     }
218
219
220     /*
221      * Generate an exported name as specified in [RFC 2743]
222      * section 3.2, "Mechanism-Independent Exported Name Object Format".
223      * For convenience, the format of the exported name is reproduced here
224      * from [RFC2743] :
225      *
226      * Format:
227      * Bytes
228      * 2 0x04 0x01
229      * 2 mech OID length (len)
230      * len mech OID's DER value
231      * 4 exported name len
232      * name len exported name
233      *
234      */

235
236     public static byte[] createExportedName(ObjectIdentifier oid, byte[] extName)
237     throws IOException JavaDoc
238     {
239     byte[] oidDER = getDER(oid);
240     int tokensize = 2 + 2 + oidDER.length + 4 + extName.length;
241
242     byte[] token = new byte[tokensize];
243
244         // construct the Exported Name
245
int pos = 0;
246
247         token[0] = 0x04;
248         token[1] = 0x01;
249         token[2] = (byte)(oidDER.length & 0xFF00);
250         token[3] = (byte)(oidDER.length & 0x00FF);
251
252         pos = 4;
253         System.arraycopy(oidDER, 0, token, pos, oidDER.length);
254         pos += oidDER.length;
255
256         int namelen = extName.length;
257
258         token[pos++] = (byte)(namelen & 0xFF000000);
259         token[pos++] = (byte)(namelen & 0x00FF0000);
260         token[pos++] = (byte)(namelen & 0x0000FF00);
261         token[pos++] = (byte)(namelen & 0x000000FF);
262
263         System.arraycopy(extName, 0, token, pos, namelen);
264
265         return token;
266     }
267
268     /*
269      * Return the DER representation of an ObjectIdentifier.
270      * The DER representation is as follows:
271      *
272      * 0x06 -- Tag for OBJECT IDENTIFIER
273      * derOID.length -- length in octets of OID
274      * DER value of OID -- written as specified byte the DER representation
275      * for an ObjectIdentifier.
276      */

277
278     public static byte[] getDER(ObjectIdentifier id)
279     throws IOException JavaDoc
280     {
281         if(_logger.isLoggable(Level.FINE)) {
282             _logger.log(Level.FINE,"Returning OID in DER format");
283             _logger.log(Level.FINE," OID = " + id.toString());
284         }
285     DerOutputStream dos = new DerOutputStream();
286     dos.putOID(id);
287     byte[] oid = dos.toByteArray();
288         if(_logger.isLoggable(Level.FINE)) {
289         _logger.log(Level.FINE," DER OID: " + dumpHex(oid));
290         }
291     return oid;
292     }
293
294     /*
295      * Return the OID corresponding to an OID represented in DER format
296      * as follows:
297      *
298      * 0x06 -- Tag for OBJECT IDENTIFIER
299      * derOID.length -- length in octets of OID
300      * DER value of OID -- written as specified byte the DER representation
301      * for an ObjectIdentifier.
302      */

303
304      public static ObjectIdentifier getOID(byte[] derOID)
305          throws IOException JavaDoc
306      {
307          DerInputStream dis = new DerInputStream(derOID);
308          ObjectIdentifier oid = dis.getOID();
309
310          /* Note: getOID() method call generates an IOException
311           * if derOID contains any malformed data
312           */

313          return oid;
314      }
315
316
317     /*
318      * Construct a mechanism level independent token as specified in section
319      * 3.1, [RFC 2743]. This consists of a token tag followed byte a mechanism
320      * specific token. The format - here for convenience - is as follows:
321      *
322      * Token Tag Description
323      *
324      * 0x60 | Tag for [APPLICATION 0] SEQUENCE
325      * <token-length-octets> |
326      * 0x06 | Along with the next two entries
327      * <object-identifier-length> | is a DER encoding of an object
328      * <object-identifier-octets> | identifier
329      *
330      * Mechanism specific token | format defined by the mechanism itself
331      * outside of RFC 2743.
332      */

333
334     public static byte[] createMechIndToken(ObjectIdentifier mechoid, byte mechtok[])
335     throws IOException JavaDoc
336     {
337     byte [] deroid = getDER(mechoid);
338
339         byte [] token = new byte[ 1 // for 0x60
340
+ getDERLengthSize(deroid.length+mechtok.length)
341                  + deroid.length
342                                  + mechtok.length];
343         if(_logger.isLoggable(Level.FINE)){
344             _logger.log(Level.FINE,"Going to create a mechanism independent token");
345         }
346     int index=0;
347
348     token[index++] = 0x60;
349
350     index = writeDERLength(token, index, deroid.length + mechtok.length);
351
352         System.arraycopy(deroid, 0, token, index, deroid.length);
353
354     index += deroid.length;
355     System.arraycopy(mechtok, 0, token, index, mechtok.length);
356
357         if(_logger.isLoggable(Level.FINE)){
358             _logger.log(Level.FINE,"Mechanism independent token created: ");
359             _logger.log(Level.FINE,dumpHex(token));
360         }
361     return token;
362     }
363
364     /*
365      * Retrieve a mechanism specific token from a mechanism independent token.
366      * The format of a mechanism independent token is specified in section
367      * 3.1, [RFC 2743].
368      */

369
370     public static byte[] getMechToken(ObjectIdentifier oid, byte[] token) {
371
372     byte[] mechtoken = null;
373         if(_logger.isLoggable(Level.FINE)) {
374         _logger.log(Level.FINE,"Received mechanism independent token: ");
375         _logger.log(Level.FINE,dumpHex(token));
376     }
377
378     try {
379         int index = verifyTokenHeader(oid, token);
380         int mechtoklen = token.length - index;
381         mechtoken = new byte[mechtoklen];
382             System.arraycopy(token, index, mechtoken, 0, mechtoklen);
383         if(_logger.isLoggable(Level.FINE)) {
384         _logger.log(Level.FINE,"Mechanism specific token : ");
385         _logger.log(Level.FINE,dumpHex(mechtoken));
386         }
387     } catch(IOException JavaDoc e) {
388             _logger.log(Level.SEVERE,"iiop.IOexception",e);
389     }
390     return mechtoken;
391     }
392
393
394    /* Verfies the header of a mechanism independent token. The header must
395     * be as specified in RFC 2743, section 3.1. The header must contain
396     * an object identifier specified by the first parameter.
397     *
398     * If the header is well formed, then the starting position of the
399     * mechanism specific token within the token is returned.
400     *
401     * If the header is mal formed, then an exception is thrown.
402     */

403
404     private static int verifyTokenHeader(ObjectIdentifier oid, byte [] token)
405     throws IOException JavaDoc
406     {
407     int index=0;
408         if(_logger.isLoggable(Level.FINE)){
409             _logger.log(Level.FINE,"Attempting to verify tokenheader in the mechanism independent token.");
410         }
411         // verify header
412
if (token[index++] != 0x60)
413         throw new IOException JavaDoc("Defective Token");
414
415         int toklen = readDERLength(token, index); // derOID length + token length
416

417         if(_logger.isLoggable(Level.FINE)) {
418         _logger.log(Level.FINE,"Mech OID length + Mech specific length = " + toklen);
419         }
420         index += getDERLengthSize(toklen);
421         if(_logger.isLoggable(Level.FINE)){
422         _logger.log(Level.FINE,"Mechanism OID index : " + index);
423         }
424
425         if (token[index] != 0x06)
426         throw new IOException JavaDoc("Defective Token");
427
428         byte[] buf = new byte[ token.length - index ];
429
430     System.arraycopy(token, index, buf, 0, token.length - index);
431
432         ObjectIdentifier mechoid = getOID(buf);
433
434         if(_logger.isLoggable(Level.FINE)) {
435             _logger.log(Level.FINE,"Comparing mech OID in token with the expected mech OID");
436             _logger.log(Level.FINE,"mech OID: " + dumpHex(getDER(mechoid)));
437             _logger.log(Level.FINE,"expected mech OID: " + dumpHex(getDER(oid)));
438     }
439
440         if ( ! mechoid.equals(oid)) {
441             if(_logger.isLoggable(Level.FINE)) {
442                 _logger.log(Level.FINE,"mech OID in token does not match expected mech OID");
443             }
444             throw new IOException JavaDoc("Defective token");
445         }
446         int mechoidlen = getDER(oid).length;
447
448         if(_logger.isLoggable(Level.FINE)) {
449         _logger.log(Level.FINE,"Mechanism specific token index : " + index + mechoidlen);
450         _logger.log(Level.FINE,"Successfully verified header in the mechanism independent token.");
451     }
452         return (index + mechoidlen); // starting position of mech specific token
453
}
454
455     static int getDERLengthSize(int length)
456     {
457     if (length < (1<<7))
458         return (1);
459     else if (length < (1<<8))
460         return (2);
461     else if (length < (1<<16))
462         return (3);
463     else if (length < (1<<24))
464         return (4);
465     else
466         return (5);
467     }
468
469     static int writeDERLength(byte [] token, int index, int length)
470     {
471     if (length < (1<<7)) {
472         token[index++] = (byte)length;
473     } else {
474         token[index++] = (byte)(getDERLengthSize(length)+127);
475         if (length >= (1<<24))
476         token[index++] = (byte)(length>>24);
477         if (length >= (1<<16))
478         token[index++] = (byte)((length>>16)&0xff);
479         if (length >= (1<<8))
480         token[index++] = (byte)((length>>8)&0xff);
481         token[index++] = (byte)(length&0xff);
482     }
483     return (index);
484     }
485
486     static int readDERLength(byte[] token, int index)
487     {
488     byte sf;
489         int ret = 0;
490         int nooctets;
491
492     sf = token[index++];
493
494     if ((sf & 0x80) == 0x80) { // value > 128
495
// bit 8 is 1 ; bits 0-7 of first bye is the number of octets
496
nooctets = (sf & 0x7f) ; // remove the 8th bit
497
for (; nooctets != 0; nooctets--)
498                 ret = (ret<<8) + (token[index++] & 0x00FF);
499     } else
500             ret = sf;
501   
502     return(ret);
503     }
504
505     public static void main(String JavaDoc[] args) {
506     try {
507             byte[] len = new byte[3];
508             len[0] = (byte) 0x82;
509             len[1] = (byte) 0x01;
510             len[2] = (byte) 0xd3;
511         if(_logger.isLoggable(Level.FINE)) {
512         _logger.log(Level.FINE,"Length byte array : " + dumpHex(len));
513         _logger.log(Level.FINE," Der length = " + readDERLength(len,0));
514         }
515         String JavaDoc name = "default";
516         byte[] externalName = createExportedName(GSSUtils.GSSUP_MECH_OID, name.getBytes());
517         byte[] m = importName(GSSUtils.GSSUP_MECH_OID, externalName);
518         if(_logger.isLoggable(Level.FINE))
519                 _logger.log(Level.FINE,"BAR:" + new String JavaDoc(m));
520         String JavaDoc msg = "dummy_gss_export_sec_context" ;
521         byte[] foo = createMechIndToken(GSSUtils.GSSUP_MECH_OID, msg.getBytes());
522         if(_logger.isLoggable(Level.FINE))
523                 _logger.log(Level.FINE,"FOO:" + dumpHex(foo));
524         byte[] msg1 = getMechToken(GSSUtils.GSSUP_MECH_OID, foo);
525         if(_logger.isLoggable(Level.FINE)) {
526                 _logger.log(Level.FINE,"BAR:" + dumpHex(msg1));
527             _logger.log(Level.FINE,"BAR string: " + new String JavaDoc(msg1));
528         }
529     } catch(Exception JavaDoc e) {
530                 _logger.log(Level.SEVERE,"iiop.name_exception",e);
531     }
532     }
533
534 }
535
536
Popular Tags