PageRenderTime 52ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/jboss-5.1.0/iiop/src/main/org/jboss/iiop/csiv2/CSIv2Util.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 955 lines | 585 code | 118 blank | 252 comment | 74 complexity | 72c8b85eb94bb54838b3d6b3a216a115 MD5 | raw file
  1. /*
  2. * JBoss, Home of Professional Open Source.
  3. * Copyright 2006, Red Hat Middleware LLC, and individual contributors
  4. * as indicated by the @author tags. See the copyright.txt file in the
  5. * distribution for a full listing of individual contributors.
  6. *
  7. * This is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU Lesser General Public License as
  9. * published by the Free Software Foundation; either version 2.1 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This software is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this software; if not, write to the Free
  19. * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  20. * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  21. */
  22. package org.jboss.iiop.csiv2;
  23. import java.io.UnsupportedEncodingException;
  24. import java.net.InetAddress;
  25. import org.ietf.jgss.GSSException;
  26. import org.ietf.jgss.Oid;
  27. import org.jboss.logging.Logger;
  28. import org.jboss.metadata.IorSecurityConfigMetaData;
  29. import org.jboss.metadata.IorSecurityConfigMetaData.AsContext;
  30. import org.jboss.metadata.IorSecurityConfigMetaData.SasContext;
  31. import org.jboss.metadata.IorSecurityConfigMetaData.TransportConfig;
  32. import org.omg.CORBA.Any;
  33. import org.omg.CORBA.BAD_PARAM;
  34. import org.omg.CORBA.MARSHAL;
  35. import org.omg.CORBA.ORB;
  36. import org.omg.CSI.ITTAnonymous;
  37. import org.omg.CSI.ITTDistinguishedName;
  38. import org.omg.CSI.ITTPrincipalName;
  39. import org.omg.CSI.ITTX509CertChain;
  40. import org.omg.CSIIOP.AS_ContextSec;
  41. import org.omg.CSIIOP.CompoundSecMech;
  42. import org.omg.CSIIOP.CompoundSecMechList;
  43. import org.omg.CSIIOP.CompoundSecMechListHelper;
  44. import org.omg.CSIIOP.Confidentiality;
  45. import org.omg.CSIIOP.DetectMisordering;
  46. import org.omg.CSIIOP.DetectReplay;
  47. import org.omg.CSIIOP.EstablishTrustInClient;
  48. import org.omg.CSIIOP.EstablishTrustInTarget;
  49. import org.omg.CSIIOP.IdentityAssertion;
  50. import org.omg.CSIIOP.Integrity;
  51. import org.omg.CSIIOP.SAS_ContextSec;
  52. import org.omg.CSIIOP.ServiceConfiguration;
  53. import org.omg.CSIIOP.TAG_CSI_SEC_MECH_LIST;
  54. import org.omg.CSIIOP.TAG_NULL_TAG;
  55. import org.omg.CSIIOP.TAG_TLS_SEC_TRANS;
  56. import org.omg.CSIIOP.TLS_SEC_TRANS;
  57. import org.omg.CSIIOP.TLS_SEC_TRANSHelper;
  58. import org.omg.CSIIOP.TransportAddress;
  59. import org.omg.GSSUP.GSSUPMechOID;
  60. import org.omg.GSSUP.InitialContextToken;
  61. import org.omg.GSSUP.InitialContextTokenHelper;
  62. import org.omg.IOP.Codec;
  63. import org.omg.IOP.TaggedComponent;
  64. import org.omg.IOP.CodecPackage.InvalidTypeForEncoding;
  65. import org.omg.PortableInterceptor.ClientRequestInfo;
  66. import org.omg.SSLIOP.SSL;
  67. import org.omg.SSLIOP.SSLHelper;
  68. import org.omg.SSLIOP.TAG_SSL_SEC_TRANS;
  69. /**
  70. * Helper class
  71. *
  72. * @author Dimitris.Andreadis@jboss.org
  73. * @author Francisco Reverbel
  74. * @author Stefan Neusatz Guilhen
  75. * @version $Revision: 64028 $
  76. */
  77. public final class CSIv2Util
  78. {
  79. private static final Logger log = Logger.getLogger(CSIv2Util.class);
  80. /** DER-encoded ASN.1 representation of the GSSUP mechanism OID. */
  81. private static final byte[] gssUpMechOidArray = createGSSUPMechOID();
  82. private CSIv2Util()
  83. {
  84. // static calls only
  85. }
  86. /**
  87. * Make a deep copy of an IOP:TaggedComponent
  88. **/
  89. public static TaggedComponent createCopy(TaggedComponent tc)
  90. {
  91. TaggedComponent copy = null;
  92. if( tc != null )
  93. {
  94. byte[] buf = new byte[tc.component_data.length];
  95. System.arraycopy(tc.component_data, 0, buf, 0, tc.component_data.length);
  96. copy = new TaggedComponent(tc.tag, buf);
  97. }
  98. return copy;
  99. }
  100. /**
  101. * Return a top-level IOP::TaggedComponent to be stuffed into an IOR,
  102. * containing an structure SSLIOP::SSL, tagged as TAG_SSL_SEC_TRANS.
  103. *
  104. * Should be called with non-null metadata, in which case we probably
  105. * don't want to include security info in the IOR.
  106. **/
  107. public static TaggedComponent createSSLTaggedComponent(
  108. IorSecurityConfigMetaData metadata,
  109. Codec codec,
  110. int sslPort,
  111. ORB orb)
  112. {
  113. if( metadata == null )
  114. {
  115. log.debug("createSSLTaggedComponent() called with null metadata");
  116. return null;
  117. }
  118. TaggedComponent tc = null;
  119. try
  120. {
  121. int supports = createTargetSupports(metadata.getTransportConfig());
  122. int requires = createTargetRequires(metadata.getTransportConfig());
  123. SSL ssl = new SSL((short) supports, (short) requires, (short) sslPort);
  124. Any any = orb.create_any();
  125. SSLHelper.insert(any, ssl);
  126. byte[] componentData = codec.encode_value(any);
  127. tc = new TaggedComponent(TAG_SSL_SEC_TRANS.value, componentData);
  128. }
  129. catch(InvalidTypeForEncoding e)
  130. {
  131. log.warn("Caught unexcepted exception while encoding SSL component", e);
  132. throw new RuntimeException(e);
  133. }
  134. return tc;
  135. }
  136. /**
  137. * Return a top-level IOP:TaggedComponent to be stuffed into an IOR,
  138. * containing a CSIIOP.CompoundSecMechList, tagged as TAG_CSI_SEC_MECH_LIST.
  139. * Only one such component can exist inside an IOR.
  140. *
  141. * Should be called with non-null metadata, in which case we probably
  142. * don't want to include security info in the IOR.
  143. **/
  144. public static TaggedComponent createSecurityTaggedComponent(
  145. IorSecurityConfigMetaData metadata,
  146. Codec codec,
  147. int sslPort,
  148. ORB orb
  149. )
  150. {
  151. if( metadata == null )
  152. {
  153. log.debug("createSecurityTaggedComponent() called with null metadata");
  154. return null;
  155. }
  156. TaggedComponent tc = null;
  157. // Get the the supported security mechanisms (just one :)
  158. CompoundSecMech[] mechList =
  159. createCompoundSecMechanisms(metadata, codec, sslPort, orb);
  160. // the above is wrapped into a CSIIOP.CompoundSecMechList
  161. // structure, which is NOT a CompoundSecMech[] !!!
  162. //
  163. // We DONT support stateful/reusable security contexts (false)
  164. CompoundSecMechList csmList = new CompoundSecMechList(false,
  165. mechList);
  166. // finally, the CompoundSecMechList must be encoded as a TaggedComponent
  167. try
  168. {
  169. Any any = orb.create_any();
  170. CompoundSecMechListHelper.insert(any, csmList);
  171. byte[] b = codec.encode_value(any);
  172. tc = new TaggedComponent(TAG_CSI_SEC_MECH_LIST.value, b);
  173. }
  174. catch(InvalidTypeForEncoding e)
  175. {
  176. log.warn("Caught unexcepted exception while encoding CompoundSecMechList", e);
  177. throw new RuntimeException(e);
  178. }
  179. return tc;
  180. }
  181. /**
  182. * Create a CSIIOP.CompoundSecMechanisms which is a sequence of
  183. * CompoundSecMech. Here we only support one security mechanism.
  184. **/
  185. public static CompoundSecMech[] createCompoundSecMechanisms(
  186. IorSecurityConfigMetaData metadata,
  187. Codec codec,
  188. int sslPort,
  189. ORB orb
  190. )
  191. {
  192. // Support just 1 security mechanism for now (and ever :)
  193. CompoundSecMech[] csmList = new CompoundSecMech[1];
  194. // A CompoundSecMech contains:
  195. // target_requires, transport_mech, as_context_mech, sas_context_mech
  196. // The transport mechanism is an IOP.TaggedComponent itself
  197. // to allow for arbitrary transport mechanisms be specified.
  198. // This will configure SSL or none.
  199. TaggedComponent transport_mech = createTransportMech(
  200. metadata.getTransportConfig(), codec, sslPort, orb
  201. );
  202. // Create AS Context
  203. AS_ContextSec asContext = createAuthenticationServiceContext(metadata);
  204. // Create SAS Context
  205. SAS_ContextSec sasContext = createSecureAttributeServiceContext(metadata);
  206. // Create target_requires bit field (AssociationOption)
  207. // can't read directly the transport_mech TaggedComponent
  208. int target_requires =
  209. createTargetRequires(metadata.getTransportConfig()) |
  210. asContext.target_requires |
  211. sasContext.target_requires;
  212. // wrap it up
  213. CompoundSecMech csm = new CompoundSecMech((short) target_requires,
  214. transport_mech,
  215. asContext,
  216. sasContext);
  217. // store it in csmList as the only security mechanism
  218. csmList[0] = csm;
  219. return csmList;
  220. }
  221. /**
  222. * Create the Secure Attribute Service (SAS) context
  223. * included in a CompoundSecMech definition
  224. **/
  225. public static SAS_ContextSec createSecureAttributeServiceContext(
  226. IorSecurityConfigMetaData metadata
  227. )
  228. {
  229. SAS_ContextSec context = null;
  230. // context contains
  231. // target_supports, target_requires, privilige_authorities,
  232. // supported_naming_mechanisms, supported_identity_types
  233. int support = 0;
  234. int require = 0;
  235. ServiceConfiguration[] privilAuth = new ServiceConfiguration[0];
  236. byte[][] supNamMechs = {};
  237. int supIdenTypes = 0; // 0 means ITTAbsent
  238. // the the SasContext metadata
  239. SasContext sasMeta = metadata.getSasContext();
  240. // if no SAS context metadata, or caller propagation is not
  241. // supported, we return with a more or less empty sas context
  242. if( sasMeta == null || !sasMeta.isCallerPropagationSupported() )
  243. {
  244. context = new SAS_ContextSec((short) support,
  245. (short) require,
  246. privilAuth,
  247. supNamMechs,
  248. supIdenTypes);
  249. }
  250. else
  251. {
  252. support = IdentityAssertion.value;
  253. // supporting GSSUP (username/password) naming mechanism
  254. byte[] upMech = createGSSUPMechOID();
  255. supNamMechs = new byte[1][upMech.length];
  256. System.arraycopy(upMech, 0, supNamMechs[0], 0, upMech.length);
  257. // since we support IdentityAssertion we need to specify
  258. // supported identity types. CTS says we need them all
  259. supIdenTypes = ITTAnonymous.value |
  260. ITTPrincipalName.value |
  261. ITTX509CertChain.value |
  262. ITTDistinguishedName.value;
  263. // wrap it up
  264. context = new SAS_ContextSec((short) support,
  265. (short) require,
  266. privilAuth,
  267. supNamMechs,
  268. supIdenTypes);
  269. }
  270. return context;
  271. }
  272. /**
  273. * Create the client Authentication Service (AS) context
  274. * included in a CompoundSecMech definition.
  275. **/
  276. public static AS_ContextSec createAuthenticationServiceContext(
  277. IorSecurityConfigMetaData metadata
  278. )
  279. {
  280. AS_ContextSec context = null;
  281. // the content of the context
  282. int support = 0;
  283. int require = 0;
  284. byte[] clientAuthMech = {};
  285. byte[] targetName = {};
  286. // get the AsContext metadata
  287. AsContext asMeta = metadata.getAsContext();
  288. // if no AS context metatada exists, or authentication method
  289. // "none" is specified, we can produce an empty AS context
  290. if( asMeta == null || asMeta.getAuthMethod().equals(AsContext.AUTH_METHOD_NONE)
  291. /*|| asMeta.isRequired() == false*/ )
  292. {
  293. context = new AS_ContextSec((short) support,
  294. (short) require,
  295. clientAuthMech,
  296. targetName);
  297. }
  298. else
  299. {
  300. // we do support
  301. support = EstablishTrustInClient.value;
  302. // required depends on the metadata
  303. if( asMeta.isRequired() )
  304. require = EstablishTrustInClient.value;
  305. // we only support GSSUP authentication method
  306. clientAuthMech = createGSSUPMechOID();
  307. // finally, encode the "realm" name as a CSI.GSS_NT_ExportedName.
  308. // clientAuthMech should contain the DER encoded GSSUPMechOID
  309. // at this point.
  310. String realm = asMeta.getRealm();
  311. targetName = createGSSExportedName(clientAuthMech, realm.getBytes());
  312. // wrap it up
  313. context = new AS_ContextSec((short) support,
  314. (short) require,
  315. clientAuthMech,
  316. targetName);
  317. }
  318. return context;
  319. }
  320. /**
  321. * Create a transport mechanism TaggedComponent to be stuffed into a
  322. * CompoundSecMech.
  323. *
  324. * If no TransportConfig metadata is specified, or ssl port is negative,
  325. * or the specified metadata indicates that transport config is not supported,
  326. * then a TAG_NULL_TAG (empty) TaggedComponent will be returned.
  327. *
  328. * Otherwise a CSIIOP.TLS_SEC_TRANS, tagged as TAG_TLS_SEC_TRANS will
  329. * be returned, indicating support for TLS/SSL as a CSIv2 transport
  330. * mechanism.
  331. *
  332. * Multiple TransportAddress may be included in the SSL info
  333. * (host/port pairs), but we only include one.
  334. **/
  335. public static TaggedComponent createTransportMech(
  336. TransportConfig tconfig,
  337. Codec codec,
  338. int sslPort,
  339. ORB orb
  340. )
  341. {
  342. TaggedComponent tc = null;
  343. // what we support and require as a target
  344. int support = 0;
  345. int require = 0;
  346. if( tconfig != null )
  347. {
  348. require = createTargetRequires(tconfig);
  349. support = createTargetSupports(tconfig);
  350. }
  351. if( tconfig == null || support == 0 || sslPort < 0 )
  352. {
  353. // no support for transport security
  354. tc = new TaggedComponent(TAG_NULL_TAG.value, new byte[0]);
  355. }
  356. else
  357. {
  358. // my ip address
  359. String host;
  360. try
  361. {
  362. host = InetAddress.getLocalHost().getHostAddress();
  363. }
  364. catch(java.net.UnknownHostException e)
  365. {
  366. host = "127.0.0.1";
  367. }
  368. // this will create only one transport address
  369. TransportAddress[] taList = createTransportAddress(host, sslPort);
  370. TLS_SEC_TRANS tst = new TLS_SEC_TRANS((short) support,
  371. (short) require,
  372. taList);
  373. // The tricky part, we must encode TLS_SEC_TRANS into an octet sequence
  374. try
  375. {
  376. Any any = orb.create_any();
  377. TLS_SEC_TRANSHelper.insert(any, tst);
  378. byte[] b = codec.encode_value(any);
  379. tc = new TaggedComponent(TAG_TLS_SEC_TRANS.value, b);
  380. }
  381. catch(InvalidTypeForEncoding e)
  382. {
  383. log.warn("Caught unexcepted exception while encoding TLS_SEC_TRANS", e);
  384. throw new RuntimeException(e);
  385. }
  386. }
  387. return tc;
  388. }
  389. /**
  390. * Create a TransportAddress[] with a single TransportAddress
  391. **/
  392. public static TransportAddress[] createTransportAddress(
  393. String host, int port
  394. )
  395. {
  396. // idl type is unsighned sort, so we need this trick
  397. short short_port = (port > 32767) ? (short) (port - 65536) : (short) port;
  398. TransportAddress ta = new TransportAddress(host, short_port);
  399. TransportAddress[] taList = new TransportAddress[1];
  400. taList[0] = ta;
  401. return taList;
  402. }
  403. /**
  404. * Create the AssociationOption for CompoundSecMech - target_requires
  405. **/
  406. public static int createTargetRequires(TransportConfig tc)
  407. {
  408. int requires = 0;
  409. if( tc != null )
  410. {
  411. if( tc.getIntegrity().equals(TransportConfig.INTEGRITY_REQUIRED) )
  412. requires = requires | Integrity.value;
  413. if( tc.getConfidentiality().equals(TransportConfig.CONFIDENTIALITY_REQUIRED) )
  414. requires = requires | Confidentiality.value;
  415. if( tc.getDetectMisordering().equalsIgnoreCase(TransportConfig.DETECT_MISORDERING_REQUIRED) )
  416. requires = requires | DetectMisordering.value;
  417. if( tc.getDetectReplay().equalsIgnoreCase(TransportConfig.DETECT_REPLAY_REQUIRED) )
  418. requires = requires | DetectReplay.value;
  419. // no EstablishTrustInTarget required - client decides
  420. if( tc.getEstablishTrustInClient().equals(TransportConfig.ESTABLISH_TRUST_IN_CLIENT_REQUIRED) )
  421. requires = requires | EstablishTrustInClient.value;
  422. }
  423. return requires;
  424. }
  425. /**
  426. * Create bitmask of what the target supports
  427. **/
  428. public static int createTargetSupports(TransportConfig tc)
  429. {
  430. int supports = 0;
  431. if( tc != null )
  432. {
  433. if( !tc.getIntegrity().equals(TransportConfig.INTEGRITY_NONE) )
  434. supports = supports | Integrity.value;
  435. if( !tc.getConfidentiality().equals(TransportConfig.CONFIDENTIALITY_NONE) )
  436. supports = supports | Confidentiality.value;
  437. if( !tc.getDetectMisordering().equalsIgnoreCase(TransportConfig.DETECT_MISORDERING_NONE) )
  438. supports = supports | DetectMisordering.value;
  439. if( !tc.getDetectReplay().equalsIgnoreCase(TransportConfig.DETECT_REPLAY_NONE) )
  440. supports = supports | DetectReplay.value;
  441. if( !tc.getEstablishTrustInTarget().equals(TransportConfig.ESTABLISH_TRUST_IN_TARGET_NONE) )
  442. supports = supports | EstablishTrustInTarget.value;
  443. if( !tc.getEstablishTrustInClient().equals(TransportConfig.ESTABLISH_TRUST_IN_CLIENT_NONE) )
  444. supports = supports | EstablishTrustInClient.value;
  445. }
  446. return supports;
  447. }
  448. /**
  449. * Create an ASN.1, DER encoded representation for
  450. * the GSSUP OID mechanism
  451. **/
  452. public static byte[] createGSSUPMechOID()
  453. {
  454. // kudos to org.ietf.jgss.Oid for the Oid utility
  455. // need to strip the "oid:" part of the GSSUPMechOID first
  456. byte[] retval = {};
  457. try
  458. {
  459. Oid oid = new Oid(GSSUPMechOID.value.substring(4));
  460. retval = oid.getDER();
  461. }
  462. catch(GSSException e)
  463. {
  464. log.warn("Caught exception while encoding GSSUPMechOID", e);
  465. }
  466. return retval;
  467. }
  468. /**
  469. * Return an ASN.1, DER encoded representation for the GSSUP OID mechanism.
  470. **/
  471. public static byte[] gssUpMechOid()
  472. {
  473. return (byte[])gssUpMechOidArray.clone();
  474. }
  475. /**
  476. * Generate an exported name as specified in [RFC 2743], section 3.2
  477. * copied below:
  478. *
  479. * 3.2: Mechanism-Independent Exported Name Object Format
  480. *
  481. * This section specifies a mechanism-independent level of encapsulating
  482. * representation for names exported via the GSS_Export_name() call,
  483. * including an object identifier representing the exporting mechanism.
  484. * The format of names encapsulated via this representation shall be
  485. * defined within individual mechanism drafts. The Object Identifier
  486. * value to indicate names of this type is defined in Section 4.7 of
  487. * this document.
  488. *
  489. * No name type OID is included in this mechanism-independent level of
  490. * format definition, since (depending on individual mechanism
  491. * specifications) the enclosed name may be implicitly typed or may be
  492. * explicitly typed using a means other than OID encoding.
  493. *
  494. * The bytes within MECH_OID_LEN and NAME_LEN elements are represented
  495. * most significant byte first (equivalently, in IP network byte order).
  496. *
  497. * Length Name Description
  498. *
  499. * 2 TOK_ID Token Identifier
  500. * For exported name objects, this
  501. * must be hex 04 01.
  502. * 2 MECH_OID_LEN Length of the Mechanism OID
  503. * MECH_OID_LEN MECH_OID Mechanism OID, in DER
  504. * 4 NAME_LEN Length of name
  505. * NAME_LEN NAME Exported name; format defined in
  506. * applicable mechanism draft.
  507. *
  508. * A concrete example of the contents of an exported name object,
  509. * derived from the Kerberos Version 5 mechanism, is as follows:
  510. *
  511. * 04 01 00 0B 06 09 2A 86 48 86 F7 12 01 02 02 hx xx xx xl pp qq ... zz
  512. *
  513. * ...
  514. *
  515. * @param oid the DER encoded OID
  516. * @param name the name to be converted to GSSExportedName
  517. **/
  518. public static byte[] createGSSExportedName(byte[] oid, byte[] name)
  519. {
  520. int olen = oid.length;
  521. int nlen = name.length;
  522. // size according to spec
  523. int size = 2 + 2 + olen + 4 + nlen;
  524. // allocate space for the exported name
  525. byte[] buf = new byte[size];
  526. // index
  527. int i = 0;
  528. // standard header
  529. buf[i++] = 0x04;
  530. buf[i++] = 0x01;
  531. // encode oid length
  532. buf[i++] = (byte) (olen & 0xFF00);
  533. buf[i++] = (byte) (olen & 0x00FF);
  534. // copy the oid in the exported name buffer
  535. System.arraycopy(oid, 0, buf, i, olen);
  536. i += olen;
  537. // encode the name length in the exported buffer
  538. buf[i++] = (byte) (nlen & 0xFF000000);
  539. buf[i++] = (byte) (nlen & 0x00FF0000);
  540. buf[i++] = (byte) (nlen & 0x0000FF00);
  541. buf[i++] = (byte) (nlen & 0x000000FF);
  542. // finally, copy the name bytes
  543. System.arraycopy(name, 0, buf, i, nlen);
  544. // done
  545. return buf;
  546. }
  547. /**
  548. * ASN.1-encode an InitialContextToken as defined in RFC 2743, Section 3.1,
  549. * "Mechanism-Independent Token Format", pp. 81-82. The encoded token
  550. * contains the ASN.1 tag 0x60, followed by a token length (which is itself
  551. * stored in a variable-lenght format and takes 1 to 5 bytes), the GSSUP
  552. * mechanism identifier, and a mechanism-specific token, which in this
  553. * case is a CDR encapsulation of the GSSUP InitialContextToken in the
  554. * authToken parameter.
  555. */
  556. public static byte[] encodeInitialContextToken(InitialContextToken authToken,
  557. Codec codec)
  558. {
  559. byte[] out = null;
  560. Any any = ORB.init().create_any();
  561. InitialContextTokenHelper.insert(any, authToken);
  562. try
  563. {
  564. out = codec.encode_value(any);
  565. }
  566. catch (Exception e)
  567. {
  568. // logger.error("Error encoding for GSSNameSpi: " + e);
  569. return new byte[0];
  570. }
  571. int length = out.length + gssUpMechOidArray.length;
  572. int n;
  573. if (length < (1 << 7))
  574. n = 0;
  575. else if (length < (1 << 8))
  576. n = 1;
  577. else if (length < (1 << 16))
  578. n = 2;
  579. else if (length < (1 << 24))
  580. n = 3;
  581. else // if (length < (1 << 32))
  582. n = 4;
  583. byte[] encodedToken = new byte[2 + n + length];
  584. encodedToken[0] = 0x60;
  585. if (n == 0)
  586. encodedToken[1] = (byte)length;
  587. else
  588. {
  589. encodedToken[1] = (byte)(n | 0x80);
  590. switch (n)
  591. {
  592. case 1:
  593. encodedToken[2] = (byte)length;
  594. break;
  595. case 2:
  596. encodedToken[2] = (byte)(length >> 8);
  597. encodedToken[3] = (byte)length;
  598. break;
  599. case 3:
  600. encodedToken[2] = (byte)(length >> 16);
  601. encodedToken[3] = (byte)(length >> 8);
  602. encodedToken[4] = (byte)length;
  603. break;
  604. default: // case 4:
  605. encodedToken[2] = (byte)(length >> 24);
  606. encodedToken[3] = (byte)(length >> 16);
  607. encodedToken[4] = (byte)(length >> 8);
  608. encodedToken[5] = (byte)length;
  609. }
  610. }
  611. System.arraycopy(gssUpMechOidArray, 0,
  612. encodedToken, 2 + n,
  613. gssUpMechOidArray.length);
  614. System.arraycopy(out, 0,
  615. encodedToken, 2 + n + gssUpMechOidArray.length,
  616. out.length);
  617. return encodedToken;
  618. }
  619. /**
  620. * Decodes an ASN.1-encoded InitialContextToken.
  621. * See encodeInitialContextToken for a description of the encoded token
  622. * format.
  623. */
  624. public static InitialContextToken decodeInitialContextToken(
  625. byte[] encodedToken,
  626. Codec codec)
  627. {
  628. if(encodedToken[0] != 0x60)
  629. return null;
  630. int encodedLength = 0;
  631. int n = 0;
  632. if(encodedToken[1] >= 0)
  633. encodedLength = encodedToken[1];
  634. else
  635. {
  636. n = encodedToken[1] & 0x7F;
  637. for(int i = 1; i <= n; i++)
  638. encodedLength += (encodedToken[1 + i] & 0xFF) << (n-i)*8;
  639. }
  640. int length = encodedLength - gssUpMechOidArray.length;
  641. byte[] encodedInitialContextToken = new byte[length];
  642. System.arraycopy(encodedToken, 2 + n + gssUpMechOidArray.length,
  643. encodedInitialContextToken, 0,
  644. length);
  645. Any any = null;
  646. try
  647. {
  648. any = codec.decode_value(encodedInitialContextToken,
  649. InitialContextTokenHelper.type());
  650. }
  651. catch(Exception e)
  652. {
  653. return null;
  654. }
  655. InitialContextToken contextToken =
  656. InitialContextTokenHelper.extract(any);
  657. return contextToken;
  658. }
  659. /**
  660. * ASN.1-encodes a GSS exported name with the GSSUP mechanism OID.
  661. * See createGSSExportedName for a description of the encoding format.
  662. */
  663. public static byte[] encodeGssExportedName(byte[] name)
  664. {
  665. return createGSSExportedName(gssUpMechOidArray, name);
  666. }
  667. /**
  668. * Decodes a GSS exported name that has been encoded with the GSSUP
  669. * mechanism OID. See createGSSExportedName for a description of the
  670. * encoding format.
  671. */
  672. public static byte[] decodeGssExportedName(byte[] encodedName)
  673. {
  674. if(encodedName[0] != 0x04 || encodedName[1] != 0x01)
  675. return null;
  676. int mechOidLength = (encodedName[2] & 0xFF) << 8; //MECH_OID_LEN
  677. mechOidLength += (encodedName[3] & 0xFF); // MECH_OID_LEN
  678. byte[] oidArray = new byte[mechOidLength];
  679. System.arraycopy(encodedName, 4,
  680. oidArray, 0,
  681. mechOidLength);
  682. for(int i = 0; i < mechOidLength; i++)
  683. {
  684. if(gssUpMechOidArray[i] != oidArray[i])
  685. return null;
  686. }
  687. int offset = 4 + mechOidLength;
  688. int nameLength = (encodedName[ offset] & 0xFF) << 24;
  689. nameLength += (encodedName[++offset] & 0xFF) << 16;
  690. nameLength += (encodedName[++offset] & 0xFF) << 8;
  691. nameLength += (encodedName[++offset] & 0xFF);
  692. byte[] name = new byte[nameLength];
  693. System.arraycopy(encodedName, ++offset,
  694. name, 0,
  695. nameLength);
  696. return name;
  697. }
  698. /**
  699. * Helper method to be called from a client request interceptor.
  700. * The <code>ri</code> parameter refers to the current request.
  701. * This method returns the first <code>CompoundSecMech</code>
  702. * found in the target IOR such that
  703. * <ul>
  704. * <li>all <code>CompoundSecMech</code> requirements are satisfied
  705. * by the options in the <code>clientSupports</code> parameter,
  706. * and</li>
  707. * <li>every requirement in the <code>clientRequires</code> parameter
  708. * is satisfied by the <code>CompoundSecMech</code>.</li>
  709. * </ul>
  710. * The method returns null if the target IOR contains no
  711. * <code>CompoundSecMech</code>s or if no
  712. * matching <code>CompoundSecMech</code> is found.
  713. *
  714. * Since this method is intended to be called from a client request
  715. * interceptor, it converts unexpected exceptions into <code>MARSHAL</code>
  716. * exceptions.
  717. */
  718. public static CompoundSecMech getMatchingSecurityMech(ClientRequestInfo ri,
  719. Codec codec,
  720. short clientSupports,
  721. short clientRequires)
  722. {
  723. CompoundSecMechList csmList = null;
  724. try
  725. {
  726. TaggedComponent tc =
  727. ri.get_effective_component(TAG_CSI_SEC_MECH_LIST.value);
  728. Any any = codec.decode_value(tc.component_data,
  729. CompoundSecMechListHelper.type());
  730. csmList = CompoundSecMechListHelper.extract(any);
  731. // look for the first matching security mech
  732. for(int i = 0; i < csmList.mechanism_list.length; i++)
  733. {
  734. CompoundSecMech securityMech = csmList.mechanism_list[i];
  735. AS_ContextSec authConfig = securityMech.as_context_mech;
  736. if( (EstablishTrustInTarget.value
  737. & (clientRequires ^ authConfig.target_supports)
  738. & ~authConfig.target_supports) != 0 )
  739. {
  740. // client requires EstablishTrustInTarget,
  741. // but target does not support it:
  742. continue; // skip this securityMech
  743. }
  744. if( (EstablishTrustInClient.value
  745. & (authConfig.target_requires ^ clientSupports)
  746. & ~clientSupports) != 0 )
  747. {
  748. // target requires EstablishTrustInClient,
  749. // but client does not support it:
  750. continue; // skip this securityMech
  751. }
  752. SAS_ContextSec identityConfig = securityMech.sas_context_mech;
  753. if( (IdentityAssertion.value
  754. & (identityConfig.target_requires ^ clientSupports)
  755. & ~clientSupports) != 0 )
  756. {
  757. // target requires IdentityAssertion,
  758. // but client does not support it:
  759. continue; // skip this securityMech
  760. }
  761. // found matching securityMech
  762. return securityMech;
  763. }
  764. // no matching securityMech was found
  765. return null;
  766. }
  767. catch(BAD_PARAM e)
  768. {
  769. // no component with TAG_CSI_SEC_MECH_LIST was found
  770. return null;
  771. }
  772. catch(org.omg.IOP.CodecPackage.TypeMismatch e)
  773. {
  774. // unexpected exception in codec.decode_value
  775. throw new MARSHAL("Unexpected exception: " + e);
  776. }
  777. catch(org.omg.IOP.CodecPackage.FormatMismatch e)
  778. {
  779. // unexpected exception in codec.decode_value
  780. throw new MARSHAL("Unexpected exception: " + e);
  781. }
  782. }
  783. /** Generate a string representation of the CompoundSecMech
  784. * @param securityMech - the CompoundSecMech to create the string for
  785. * @param buffer - the buffer to write to
  786. */
  787. public static void toString(CompoundSecMech securityMech, StringBuffer buffer)
  788. {
  789. AS_ContextSec asMech = securityMech != null ? securityMech.as_context_mech : null;
  790. SAS_ContextSec sasMech = securityMech != null ? securityMech.sas_context_mech : null;
  791. if( securityMech != null )
  792. {
  793. buffer.append("CompoundSecMech[");
  794. buffer.append("target_requires: ");
  795. buffer.append(securityMech.target_requires);
  796. if( asMech != null )
  797. {
  798. buffer.append("AS_ContextSec[");
  799. buffer.append("client_authentication_mech: ");
  800. try
  801. {
  802. buffer.append(new String(asMech.client_authentication_mech, "UTF-8"));
  803. }
  804. catch(UnsupportedEncodingException e)
  805. {
  806. buffer.append(e.getMessage());
  807. }
  808. buffer.append(", target_name: ");
  809. try
  810. {
  811. buffer.append(new String(asMech.target_name, "UTF-8"));
  812. }
  813. catch(UnsupportedEncodingException e)
  814. {
  815. buffer.append(e.getMessage());
  816. }
  817. buffer.append(", target_requires: ");
  818. buffer.append(asMech.target_requires);
  819. buffer.append(", target_supports: ");
  820. buffer.append(asMech.target_supports);
  821. buffer.append("]");
  822. }
  823. if( sasMech != null )
  824. {
  825. buffer.append("SAS_ContextSec[");
  826. buffer.append("supported_identity_types: ");
  827. buffer.append(sasMech.supported_identity_types);
  828. buffer.append(", target_requires: ");
  829. buffer.append(sasMech.target_requires);
  830. buffer.append(", target_supports: ");
  831. buffer.append(sasMech.target_supports);
  832. buffer.append("]");
  833. }
  834. buffer.append("]");
  835. }
  836. }
  837. }