Showing the changes to java/pkg/org (133 of 18352 files). Show all
Unified · Split
Binary file not shown.
| @@ -0,0 +1,212 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. | ||
| 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | ||
| 4 | * | ||
| 5 | * This code is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms of the GNU General Public License version 2 only, as | ||
| 7 | * published by the Free Software Foundation. Oracle designates this | ||
| 8 | * particular file as subject to the "Classpath" exception as provided | ||
| 9 | * by Oracle in the LICENSE file that accompanied this code. | ||
| 10 | * | ||
| 11 | * This code is distributed in the hope that it will be useful, but WITHOUT | ||
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
| 14 | * version 2 for more details (a copy is included in the LICENSE file that | ||
| 15 | * accompanied this code). | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License version | ||
| 18 | * 2 along with this work; if not, write to the Free Software Foundation, | ||
| 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 20 | * | ||
| 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | ||
| 22 | * or visit www.oracle.com if you need additional information or have any | ||
| 23 | * questions. | ||
| 24 | */ | ||
| 25 | |||
| 26 | package org.ietf.jgss; | ||
| 27 | |||
| 28 | import java.net.InetAddress; | ||
| 29 | import java.util.Arrays; | ||
| 30 | |||
| 31 | /** | ||
| 32 | * This class encapsulates the concept of caller-provided channel | ||
| 33 | * binding information. Channel bindings are used to strengthen the | ||
| 34 | * quality with which peer entity authentication is provided during | ||
| 35 | * context establishment. They enable the GSS-API callers to bind the | ||
| 36 | * establishment of the security context to relevant characteristics | ||
| 37 | * like addresses or to application specific data.<p> | ||
| 38 | * | ||
| 39 | * The caller initiating the security context must determine the | ||
| 40 | * appropriate channel binding values to set in the GSSContext object. | ||
| 41 | * The acceptor must provide an identical binding in order to validate | ||
| 42 | * that received tokens possess correct channel-related characteristics.<p> | ||
| 43 | * | ||
| 44 | * Use of channel bindings is optional in GSS-API. ChannelBinding can be | ||
| 45 | * set for the {@link GSSContext GSSContext} using the {@link | ||
| 46 | * GSSContext#setChannelBinding(ChannelBinding) setChannelBinding} method | ||
| 47 | * before the first call to {@link GSSContext#initSecContext(byte[], int, int) | ||
| 48 | * initSecContext} or {@link GSSContext#acceptSecContext(byte[], int, int) | ||
| 49 | * acceptSecContext} has been performed. Unless the <code>setChannelBinding</code> | ||
| 50 | * method has been used to set the ChannelBinding for a GSSContext object, | ||
| 51 | * <code>null</code> ChannelBinding will be assumed. <p> | ||
| 52 | * | ||
| 53 | * Conceptually, the GSS-API concatenates the initiator and acceptor | ||
| 54 | * address information, and the application supplied byte array to form an | ||
| 55 | * octet string. The mechanism calculates a MIC over this octet string and | ||
| 56 | * binds the MIC to the context establishment token emitted by | ||
| 57 | * <code>initSecContext</code> method of the <code>GSSContext</code> | ||
| 58 | * interface. The same bindings are set by the context acceptor for its | ||
| 59 | * <code>GSSContext</code> object and during processing of the | ||
| 60 | * <code>acceptSecContext</code> method a MIC is calculated in the same | ||
| 61 | * way. The calculated MIC is compared with that found in the token, and if | ||
| 62 | * the MICs differ, accept will throw a <code>GSSException</code> with the | ||
| 63 | * major code set to {@link GSSException#BAD_BINDINGS BAD_BINDINGS}, and | ||
| 64 | * the context will not be established. Some mechanisms may include the | ||
| 65 | * actual channel binding data in the token (rather than just a MIC); | ||
| 66 | * applications should therefore not use confidential data as | ||
| 67 | * channel-binding components.<p> | ||
| 68 | * | ||
| 69 | * Individual mechanisms may impose additional constraints on addresses | ||
| 70 | * that may appear in channel bindings. For example, a mechanism may | ||
| 71 | * verify that the initiator address field of the channel binding | ||
| 72 | * contains the correct network address of the host system. Portable | ||
| 73 | * applications should therefore ensure that they either provide correct | ||
| 74 | * information for the address fields, or omit setting of the addressing | ||
| 75 | * information. | ||
| 76 | * | ||
| 77 | * @author Mayank Upadhyay | ||
| 78 | * @since 1.4 | ||
| 79 | */ | ||
| 80 | public class ChannelBinding { | ||
| 81 | |||
| 82 | private InetAddress initiator; | ||
| 83 | private InetAddress acceptor; | ||
| 84 | private byte[] appData; | ||
| 85 | |||
| 86 | /** | ||
| 87 | * Create a ChannelBinding object with user supplied address information | ||
| 88 | * and data. <code>null</code> values can be used for any fields which the | ||
| 89 | * application does not want to specify. | ||
| 90 | * | ||
| 91 | * @param initAddr the address of the context initiator. | ||
| 92 | * <code>null</code> value can be supplied to indicate that the | ||
| 93 | * application does not want to set this value. | ||
| 94 | * @param acceptAddr the address of the context | ||
| 95 | * acceptor. <code>null</code> value can be supplied to indicate that | ||
| 96 | * the application does not want to set this value. | ||
| 97 | * @param appData application supplied data to be used as part of the | ||
| 98 | * channel bindings. <code>null</code> value can be supplied to | ||
| 99 | * indicate that the application does not want to set this value. | ||
| 100 | */ | ||
| 101 | public ChannelBinding(InetAddress initAddr, InetAddress acceptAddr, | ||
| 102 | byte[] appData) { | ||
| 103 | |||
| 104 | initiator = initAddr; | ||
| 105 | acceptor = acceptAddr; | ||
| 106 | |||
| 107 | if (appData != null) { | ||
| 108 | this.appData = new byte[appData.length]; | ||
| 109 | java.lang.System.arraycopy(appData, 0, this.appData, 0, | ||
| 110 | appData.length); | ||
| 111 | } | ||
| 112 | } | ||
| 113 | |||
| 114 | /** | ||
| 115 | * Creates a ChannelBinding object without any addressing information. | ||
| 116 | * | ||
| 117 | * @param appData application supplied data to be used as part of the | ||
| 118 | * channel bindings. | ||
| 119 | */ | ||
| 120 | public ChannelBinding(byte[] appData) { | ||
| 121 | this(null, null, appData); | ||
| 122 | } | ||
| 123 | |||
| 124 | /** | ||
| 125 | * Get the initiator's address for this channel binding. | ||
| 126 | * | ||
| 127 | * @return the initiator's address. <code>null</code> is returned if | ||
| 128 | * the address has not been set. | ||
| 129 | */ | ||
| 130 | public InetAddress getInitiatorAddress() { | ||
| 131 | return initiator; | ||
| 132 | } | ||
| 133 | |||
| 134 | /** | ||
| 135 | * Get the acceptor's address for this channel binding. | ||
| 136 | * | ||
| 137 | * @return the acceptor's address. null is returned if the address has | ||
| 138 | * not been set. | ||
| 139 | */ | ||
| 140 | public InetAddress getAcceptorAddress() { | ||
| 141 | return acceptor; | ||
| 142 | } | ||
| 143 | |||
| 144 | /** | ||
| 145 | * Get the application specified data for this channel binding. | ||
| 146 | * | ||
| 147 | * @return the application data being used as part of the | ||
| 148 | * ChannelBinding. <code>null</code> is returned if no application data | ||
| 149 | * has been specified for the channel binding. | ||
| 150 | */ | ||
| 151 | public byte[] getApplicationData() { | ||
| 152 | |||
| 153 | if (appData == null) { | ||
| 154 | return null; | ||
| 155 | } | ||
| 156 | |||
| 157 | byte[] retVal = new byte[appData.length]; | ||
| 158 | System.arraycopy(appData, 0, retVal, 0, appData.length); | ||
| 159 | return retVal; | ||
| 160 | } | ||
| 161 | |||
| 162 | /** | ||
| 163 | * Compares two instances of ChannelBinding. | ||
| 164 | * | ||
| 165 | * @param obj another ChannelBinding to compare this one with | ||
| 166 | * @return true if the two ChannelBinding's contain | ||
| 167 | * the same values for the initiator and acceptor addresses and the | ||
| 168 | * application data. | ||
| 169 | */ | ||
| 170 | public boolean equals(Object obj) { | ||
| 171 | |||
| 172 | if (this == obj) | ||
| 173 | return true; | ||
| 174 | |||
| 175 | if (! (obj instanceof ChannelBinding)) | ||
| 176 | return false; | ||
| 177 | |||
| 178 | ChannelBinding cb = (ChannelBinding) obj; | ||
| 179 | |||
| 180 | if ((initiator != null && cb.initiator == null) || | ||
| 181 | (initiator == null && cb.initiator != null)) | ||
| 182 | return false; | ||
| 183 | |||
| 184 | if (initiator != null && !initiator.equals(cb.initiator)) | ||
| 185 | return false; | ||
| 186 | |||
| 187 | if ((acceptor != null && cb.acceptor == null) || | ||
| 188 | (acceptor == null && cb.acceptor != null)) | ||
| 189 | return false; | ||
| 190 | |||
| 191 | if (acceptor != null && !acceptor.equals(cb.acceptor)) | ||
| 192 | return false; | ||
| 193 | |||
| 194 | return Arrays.equals(appData, cb.appData); | ||
| 195 | } | ||
| 196 | |||
| 197 | /** | ||
| 198 | * Returns a hashcode value for this ChannelBinding object. | ||
| 199 | * | ||
| 200 | * @return a hashCode value | ||
| 201 | */ | ||
| 202 | public int hashCode() { | ||
| 203 | if (initiator != null) | ||
| 204 | return initiator.hashCode(); | ||
| 205 | else if (acceptor != null) | ||
| 206 | return acceptor.hashCode(); | ||
| 207 | else if (appData != null) | ||
| 208 | return new String(appData).hashCode(); | ||
| 209 | else | ||
| 210 | return 1; | ||
| 211 | } | ||
| 212 | } | ||
Binary file not shown.
| @@ -0,0 +1,1347 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved. | ||
| 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | ||
| 4 | * | ||
| 5 | * This code is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms of the GNU General Public License version 2 only, as | ||
| 7 | * published by the Free Software Foundation. Oracle designates this | ||
| 8 | * particular file as subject to the "Classpath" exception as provided | ||
| 9 | * by Oracle in the LICENSE file that accompanied this code. | ||
| 10 | * | ||
| 11 | * This code is distributed in the hope that it will be useful, but WITHOUT | ||
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
| 14 | * version 2 for more details (a copy is included in the LICENSE file that | ||
| 15 | * accompanied this code). | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License version | ||
| 18 | * 2 along with this work; if not, write to the Free Software Foundation, | ||
| 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 20 | * | ||
| 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | ||
| 22 | * or visit www.oracle.com if you need additional information or have any | ||
| 23 | * questions. | ||
| 24 | */ | ||
| 25 | |||
| 26 | package org.ietf.jgss; | ||
| 27 | |||
| 28 | import sun.security.jgss.spi.*; | ||
| 29 | import java.io.InputStream; | ||
| 30 | import java.io.OutputStream; | ||
| 31 | |||
| 32 | /** | ||
| 33 | * This interface encapsulates the GSS-API security context and provides | ||
| 34 | * the security services that are available over the context. Security | ||
| 35 | * contexts are established between peers using locally acquired | ||
| 36 | * credentials. Multiple contexts may exist simultaneously between a pair | ||
| 37 | * of peers, using the same or different set of credentials. GSS-API | ||
| 38 | * functions in a manner independent of the underlying transport protocol | ||
| 39 | * and depends on its calling application to transport the tokens that are | ||
| 40 | * generated by the security context between the peers.<p> | ||
| 41 | * | ||
| 42 | * If the caller instantiates the context using the default | ||
| 43 | * <code>GSSManager</code> instance, then the Kerberos v5 GSS-API mechanism | ||
| 44 | * is guaranteed to be available for context establishment. This mechanism | ||
| 45 | * is identified by the Oid "1.2.840.113554.1.2.2" and is defined in RFC | ||
| 46 | * 1964.<p> | ||
| 47 | * | ||
| 48 | * Before the context establishment phase is initiated, the context | ||
| 49 | * initiator may request specific characteristics desired of the | ||
| 50 | * established context. Not all underlying mechanisms support all | ||
| 51 | * characteristics that a caller might desire. After the context is | ||
| 52 | * established, the caller can check the actual characteristics and services | ||
| 53 | * offered by that context by means of various query methods. When using | ||
| 54 | * the Kerberos v5 GSS-API mechanism offered by the default | ||
| 55 | * <code>GSSManager</code> instance, all optional services will be | ||
| 56 | * available locally. They are mutual authentication, credential | ||
| 57 | * delegation, confidentiality and integrity protection, and per-message | ||
| 58 | * replay detection and sequencing. Note that in the GSS-API, message integrity | ||
| 59 | * is a prerequisite for message confidentiality.<p> | ||
| 60 | * | ||
| 61 | * The context establishment occurs in a loop where the | ||
| 62 | * initiator calls {@link #initSecContext(byte[], int, int) initSecContext} | ||
| 63 | * and the acceptor calls {@link #acceptSecContext(byte[], int, int) | ||
| 64 | * acceptSecContext} until the context is established. While in this loop | ||
| 65 | * the <code>initSecContext</code> and <code>acceptSecContext</code> | ||
| 66 | * methods produce tokens that the application sends over to the peer. The | ||
| 67 | * peer passes any such token as input to its <code>acceptSecContext</code> | ||
| 68 | * or <code>initSecContext</code> as the case may be.<p> | ||
| 69 | * | ||
| 70 | * During the context establishment phase, the {@link | ||
| 71 | * #isProtReady() isProtReady} method may be called to determine if the | ||
| 72 | * context can be used for the per-message operations of {@link | ||
| 73 | * #wrap(byte[], int, int, MessageProp) wrap} and {@link #getMIC(byte[], | ||
| 74 | * int, int, MessageProp) getMIC}. This allows applications to use | ||
| 75 | * per-message operations on contexts which aren't yet fully | ||
| 76 | * established.<p> | ||
| 77 | * | ||
| 78 | * After the context has been established or the <code>isProtReady</code> | ||
| 79 | * method returns <code>true</code>, the query routines can be invoked to | ||
| 80 | * determine the actual characteristics and services of the established | ||
| 81 | * context. The application can also start using the per-message methods | ||
| 82 | * of {@link #wrap(byte[], int, int, MessageProp) wrap} and | ||
| 83 | * {@link #getMIC(byte[], int, int, MessageProp) getMIC} to obtain | ||
| 84 | * cryptographic operations on application supplied data.<p> | ||
| 85 | * | ||
| 86 | * When the context is no longer needed, the application should call | ||
| 87 | * {@link #dispose() dispose} to release any system resources the context | ||
| 88 | * may be using.<p> | ||
| 89 | * | ||
| 90 | * A security context typically maintains sequencing and replay detection | ||
| 91 | * information about the tokens it processes. Therefore, the sequence in | ||
| 92 | * which any tokens are presented to this context for processing can be | ||
| 93 | * important. Also note that none of the methods in this interface are | ||
| 94 | * synchronized. Therefore, it is not advisable to share a | ||
| 95 | * <code>GSSContext</code> among several threads unless some application | ||
| 96 | * level synchronization is in place.<p> | ||
| 97 | * | ||
| 98 | * Finally, different mechanism providers might place different security | ||
| 99 | * restrictions on using GSS-API contexts. These will be documented by the | ||
| 100 | * mechanism provider. The application will need to ensure that it has the | ||
| 101 | * appropriate permissions if such checks are made in the mechanism layer.<p> | ||
| 102 | * | ||
| 103 | * The example code presented below demonstrates the usage of the | ||
| 104 | * <code>GSSContext</code> interface for the initiating peer. Different | ||
| 105 | * operations on the <code>GSSContext</code> object are presented, | ||
| 106 | * including: object instantiation, setting of desired flags, context | ||
| 107 | * establishment, query of actual context flags, per-message operations on | ||
| 108 | * application data, and finally context deletion.<p> | ||
| 109 | * | ||
| 110 | * <pre> | ||
| 111 | * // Create a context using default credentials | ||
| 112 | * // and the implementation specific default mechanism | ||
| 113 | * GSSManager manager ... | ||
| 114 | * GSSName targetName ... | ||
| 115 | * GSSContext context = manager.createContext(targetName, null, null, | ||
| 116 | * GSSContext.INDEFINITE_LIFETIME); | ||
| 117 | * | ||
| 118 | * // set desired context options prior to context establishment | ||
| 119 | * context.requestConf(true); | ||
| 120 | * context.requestMutualAuth(true); | ||
| 121 | * context.requestReplayDet(true); | ||
| 122 | * context.requestSequenceDet(true); | ||
| 123 | * | ||
| 124 | * // establish a context between peers | ||
| 125 | * | ||
| 126 | * byte []inToken = new byte[0]; | ||
| 127 | * | ||
| 128 | * // Loop while there still is a token to be processed | ||
| 129 | * | ||
| 130 | * while (!context.isEstablished()) { | ||
| 131 | * | ||
| 132 | * byte[] outToken | ||
| 133 | * = context.initSecContext(inToken, 0, inToken.length); | ||
| 134 | * | ||
| 135 | * // send the output token if generated | ||
| 136 | * if (outToken != null) | ||
| 137 | * sendToken(outToken); | ||
| 138 | * | ||
| 139 | * if (!context.isEstablished()) { | ||
| 140 | * inToken = readToken(); | ||
| 141 | * } | ||
| 142 | * | ||
| 143 | * // display context information | ||
| 144 | * System.out.println("Remaining lifetime in seconds = " | ||
| 145 | * + context.getLifetime()); | ||
| 146 | * System.out.println("Context mechanism = " + context.getMech()); | ||
| 147 | * System.out.println("Initiator = " + context.getSrcName()); | ||
| 148 | * System.out.println("Acceptor = " + context.getTargName()); | ||
| 149 | * | ||
| 150 | * if (context.getConfState()) | ||
| 151 | * System.out.println("Confidentiality (i.e., privacy) is available"); | ||
| 152 | * | ||
| 153 | * if (context.getIntegState()) | ||
| 154 | * System.out.println("Integrity is available"); | ||
| 155 | * | ||
| 156 | * // perform wrap on an application supplied message, appMsg, | ||
| 157 | * // using QOP = 0, and requesting privacy service | ||
| 158 | * byte [] appMsg ... | ||
| 159 | * | ||
| 160 | * MessageProp mProp = new MessageProp(0, true); | ||
| 161 | * | ||
| 162 | * byte []tok = context.wrap(appMsg, 0, appMsg.length, mProp); | ||
| 163 | * | ||
| 164 | * sendToken(tok); | ||
| 165 | * | ||
| 166 | * // release the local-end of the context | ||
| 167 | * context.dispose(); | ||
| 168 | * | ||
| 169 | * </pre> | ||
| 170 | * | ||
| 171 | * @author Mayank Upadhyay | ||
| 172 | * @since 1.4 | ||
| 173 | */ | ||
| 174 | public interface GSSContext { | ||
| 175 | |||
| 176 | /** | ||
| 177 | * A lifetime constant representing the default context lifetime. This | ||
| 178 | * value is set to 0. | ||
| 179 | */ | ||
| 180 | public static final int DEFAULT_LIFETIME = 0; | ||
| 181 | |||
| 182 | /** | ||
| 183 | * A lifetime constant representing indefinite context lifetime. | ||
| 184 | * This value must is set to the maximum integer value in Java - | ||
| 185 | * {@link java.lang.Integer#MAX_VALUE Integer.MAX_VALUE}. | ||
| 186 | */ | ||
| 187 | public static final int INDEFINITE_LIFETIME = Integer.MAX_VALUE; | ||
| 188 | |||
| 189 | /** | ||
| 190 | * Called by the context initiator to start the context creation | ||
| 191 | * phase and process any tokens generated | ||
| 192 | * by the peer's <code>acceptSecContext</code> method. | ||
| 193 | * This method may return an output token which the application will need | ||
| 194 | * to send to the peer for processing by its <code>acceptSecContext</code> | ||
| 195 | * method. The application can call {@link #isEstablished() | ||
| 196 | * isEstablished} to determine if the context establishment phase is | ||
| 197 | * complete on this side of the context. A return value of | ||
| 198 | * <code>false</code> from <code>isEstablished</code> indicates that | ||
| 199 | * more tokens are expected to be supplied to | ||
| 200 | * <code>initSecContext</code>. Upon completion of the context | ||
| 201 | * establishment, the available context options may be queried through | ||
| 202 | * the get methods.<p> | ||
| 203 | * | ||
| 204 | * Note that it is possible that the <code>initSecContext</code> method | ||
| 205 | * return a token for the peer, and <code>isEstablished</code> return | ||
| 206 | * <code>true</code> also. This indicates that the token needs to be sent | ||
| 207 | * to the peer, but the local end of the context is now fully | ||
| 208 | * established.<p> | ||
| 209 | * | ||
| 210 | * Some mechanism providers might require that the caller be granted | ||
| 211 | * permission to initiate a security context. A failed permission check | ||
| 212 | * might cause a {@link java.lang.SecurityException SecurityException} | ||
| 213 | * to be thrown from this method.<p> | ||
| 214 | * | ||
| 215 | * @return a byte[] containing the token to be sent to the | ||
| 216 | * peer. <code>null</code> indicates that no token is generated. | ||
| 217 | * @param inputBuf token generated by the peer. This parameter is ignored | ||
| 218 | * on the first call since no token has been received from the peer. | ||
| 219 | * @param offset the offset within the inputBuf where the token begins. | ||
| 220 | * @param len the length of the token. | ||
| 221 | * | ||
| 222 | * @throws GSSException containing the following | ||
| 223 | * major error codes: | ||
| 224 | * {@link GSSException#DEFECTIVE_TOKEN GSSException.DEFECTIVE_TOKEN}, | ||
| 225 | * {@link GSSException#BAD_MIC GSSException.BAD_MIC}, | ||
| 226 | * {@link GSSException#NO_CRED GSSException.NO_CRED}, | ||
| 227 | * {@link GSSException#CREDENTIALS_EXPIRED | ||
| 228 | * GSSException.CREDENTIALS_EXPIRED}, | ||
| 229 | * {@link GSSException#BAD_BINDINGS GSSException.BAD_BINDINGS}, | ||
| 230 | * {@link GSSException#OLD_TOKEN GSSException.OLD_TOKEN}, | ||
| 231 | * {@link GSSException#DUPLICATE_TOKEN GSSException.DUPLICATE_TOKEN}, | ||
| 232 | * {@link GSSException#BAD_NAMETYPE GSSException.BAD_NAMETYPE}, | ||
| 233 | * {@link GSSException#BAD_MECH GSSException.BAD_MECH}, | ||
| 234 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 235 | */ | ||
| 236 | public byte[] initSecContext(byte inputBuf[], int offset, int len) | ||
| 237 | throws GSSException; | ||
| 238 | |||
| 239 | /** | ||
| 240 | * Called by the context initiator to start the context creation | ||
| 241 | * phase and process any tokens generated | ||
| 242 | * by the peer's <code>acceptSecContext</code> method using | ||
| 243 | * streams. This method may write an output token to the | ||
| 244 | * <code>OutpuStream</code>, which the application will | ||
| 245 | * need to send to the peer for processing by its | ||
| 246 | * <code>acceptSecContext</code> call. Typically, the application would | ||
| 247 | * ensure this by calling the {@link java.io.OutputStream#flush() flush} | ||
| 248 | * method on an <code>OutputStream</code> that encapsulates the | ||
| 249 | * connection between the two peers. The application can | ||
| 250 | * determine if a token is written to the OutputStream from the return | ||
| 251 | * value of this method. A return value of <code>0</code> indicates that | ||
| 252 | * no token was written. The application can call | ||
| 253 | * {@link #isEstablished() isEstablished} to determine if the context | ||
| 254 | * establishment phase is complete on this side of the context. A | ||
| 255 | * return value of <code>false</code> from <code>isEstablished</code> | ||
| 256 | * indicates that more tokens are expected to be supplied to | ||
| 257 | * <code>initSecContext</code>. | ||
| 258 | * Upon completion of the context establishment, the available context | ||
| 259 | * options may be queried through the get methods.<p> | ||
| 260 | * | ||
| 261 | * Note that it is possible that the <code>initSecContext</code> method | ||
| 262 | * return a token for the peer, and <code>isEstablished</code> return | ||
| 263 | * <code>true</code> also. This indicates that the token needs to be sent | ||
| 264 | * to the peer, but the local end of the context is now fully | ||
| 265 | * established.<p> | ||
| 266 | * | ||
| 267 | * The GSS-API authentication tokens contain a definitive start and | ||
| 268 | * end. This method will attempt to read one of these tokens per | ||
| 269 | * invocation, and may block on the stream if only part of the token is | ||
| 270 | * available. In all other respects this method is equivalent to the | ||
| 271 | * byte array based {@link #initSecContext(byte[], int, int) | ||
| 272 | * initSecContext}.<p> | ||
| 273 | * | ||
| 274 | * Some mechanism providers might require that the caller be granted | ||
| 275 | * permission to initiate a security context. A failed permission check | ||
| 276 | * might cause a {@link java.lang.SecurityException SecurityException} | ||
| 277 | * to be thrown from this method.<p> | ||
| 278 | * | ||
| 279 | * The following example code demonstrates how this method might be | ||
| 280 | * used:<p> | ||
| 281 | * <pre> | ||
| 282 | * InputStream is ... | ||
| 283 | * OutputStream os ... | ||
| 284 | * GSSContext context ... | ||
| 285 | * | ||
| 286 | * // Loop while there is still a token to be processed | ||
| 287 | * | ||
| 288 | * while (!context.isEstablished()) { | ||
| 289 | * | ||
| 290 | * context.initSecContext(is, os); | ||
| 291 | * | ||
| 292 | * // send output token if generated | ||
| 293 | * os.flush(); | ||
| 294 | * } | ||
| 295 | * </pre> | ||
| 296 | * | ||
| 297 | * | ||
| 298 | * @return the number of bytes written to the OutputStream as part of the | ||
| 299 | * token to be sent to the peer. A value of 0 indicates that no token | ||
| 300 | * needs to be sent. | ||
| 301 | * @param inStream an InputStream that contains the token generated by | ||
| 302 | * the peer. This parameter is ignored on the first call since no token | ||
| 303 | * has been or will be received from the peer at that point. | ||
| 304 | * @param outStream an OutputStream where the output token will be | ||
| 305 | * written. During the final stage of context establishment, there may be | ||
| 306 | * no bytes written. | ||
| 307 | * | ||
| 308 | * @throws GSSException containing the following | ||
| 309 | * major error codes: | ||
| 310 | * {@link GSSException#DEFECTIVE_TOKEN GSSException.DEFECTIVE_TOKEN}, | ||
| 311 | * {@link GSSException#BAD_MIC GSSException.BAD_MIC}, | ||
| 312 | * {@link GSSException#NO_CRED GSSException.NO_CRED}, | ||
| 313 | * {@link GSSException#CREDENTIALS_EXPIRED GSSException.CREDENTIALS_EXPIRED}, | ||
| 314 | * {@link GSSException#BAD_BINDINGS GSSException.BAD_BINDINGS}, | ||
| 315 | * {@link GSSException#OLD_TOKEN GSSException.OLD_TOKEN}, | ||
| 316 | * {@link GSSException#DUPLICATE_TOKEN GSSException.DUPLICATE_TOKEN}, | ||
| 317 | * {@link GSSException#BAD_NAMETYPE GSSException.BAD_NAMETYPE}, | ||
| 318 | * {@link GSSException#BAD_MECH GSSException.BAD_MECH}, | ||
| 319 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 320 | */ | ||
| 321 | public int initSecContext(InputStream inStream, | ||
| 322 | OutputStream outStream) throws GSSException; | ||
| 323 | |||
| 324 | /** | ||
| 325 | * Called by the context acceptor upon receiving a token from the | ||
| 326 | * peer. This method may return an output token which the application | ||
| 327 | * will need to send to the peer for further processing by its | ||
| 328 | * <code>initSecContext</code> call.<p> | ||
| 329 | * | ||
| 330 | * The application can call {@link #isEstablished() isEstablished} to | ||
| 331 | * determine if the context establishment phase is complete for this | ||
| 332 | * peer. A return value of <code>false</code> from | ||
| 333 | * <code>isEstablished</code> indicates that more tokens are expected to | ||
| 334 | * be supplied to this method. Upon completion of the context | ||
| 335 | * establishment, the available context options may be queried through | ||
| 336 | * the get methods.<p> | ||
| 337 | * | ||
| 338 | * Note that it is possible that <code>acceptSecContext</code> return a | ||
| 339 | * token for the peer, and <code>isEstablished</code> return | ||
| 340 | * <code>true</code> also. This indicates that the token needs to be | ||
| 341 | * sent to the peer, but the local end of the context is now fully | ||
| 342 | * established.<p> | ||
| 343 | * | ||
| 344 | * Some mechanism providers might require that the caller be granted | ||
| 345 | * permission to accept a security context. A failed permission check | ||
| 346 | * might cause a {@link java.lang.SecurityException SecurityException} | ||
| 347 | * to be thrown from this method.<p> | ||
| 348 | * | ||
| 349 | * The following example code demonstrates how this method might be | ||
| 350 | * used:<p> | ||
| 351 | * <pre> | ||
| 352 | * byte[] inToken; | ||
| 353 | * byte[] outToken; | ||
| 354 | * GSSContext context ... | ||
| 355 | * | ||
| 356 | * // Loop while there is still a token to be processed | ||
| 357 | * | ||
| 358 | * while (!context.isEstablished()) { | ||
| 359 | * inToken = readToken(); | ||
| 360 | * outToken = context.acceptSecContext(inToken, 0, | ||
| 361 | * inToken.length); | ||
| 362 | * // send output token if generated | ||
| 363 | * if (outToken != null) | ||
| 364 | * sendToken(outToken); | ||
| 365 | * } | ||
| 366 | * </pre> | ||
| 367 | * | ||
| 368 | * | ||
| 369 | * @return a byte[] containing the token to be sent to the | ||
| 370 | * peer. <code>null</code> indicates that no token is generated. | ||
| 371 | * @param inToken token generated by the peer. | ||
| 372 | * @param offset the offset within the inToken where the token begins. | ||
| 373 | * @param len the length of the token. | ||
| 374 | * | ||
| 375 | * @throws GSSException containing the following | ||
| 376 | * major error codes: | ||
| 377 | * {@link GSSException#DEFECTIVE_TOKEN GSSException.DEFECTIVE_TOKEN}, | ||
| 378 | * {@link GSSException#BAD_MIC GSSException.BAD_MIC}, | ||
| 379 | * {@link GSSException#NO_CRED GSSException.NO_CRED}, | ||
| 380 | * {@link GSSException#CREDENTIALS_EXPIRED | ||
| 381 | * GSSException.CREDENTIALS_EXPIRED}, | ||
| 382 | * {@link GSSException#BAD_BINDINGS GSSException.BAD_BINDINGS}, | ||
| 383 | * {@link GSSException#OLD_TOKEN GSSException.OLD_TOKEN}, | ||
| 384 | * {@link GSSException#DUPLICATE_TOKEN GSSException.DUPLICATE_TOKEN}, | ||
| 385 | * {@link GSSException#BAD_MECH GSSException.BAD_MECH}, | ||
| 386 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 387 | */ | ||
| 388 | public byte[] acceptSecContext(byte inToken[], int offset, int len) | ||
| 389 | throws GSSException; | ||
| 390 | |||
| 391 | /** | ||
| 392 | * Called by the context acceptor to process a token from the peer using | ||
| 393 | * streams. It may write an output token to the | ||
| 394 | * <code>OutputStream</code>, which the application | ||
| 395 | * will need to send to the peer for processing by its | ||
| 396 | * <code>initSecContext</code> method. Typically, the application would | ||
| 397 | * ensure this by calling the {@link java.io.OutputStream#flush() flush} | ||
| 398 | * method on an <code>OutputStream</code> that encapsulates the | ||
| 399 | * connection between the two peers. The application can call | ||
| 400 | * {@link #isEstablished() isEstablished} to determine if the context | ||
| 401 | * establishment phase is complete on this side of the context. A | ||
| 402 | * return value of <code>false</code> from <code>isEstablished</code> | ||
| 403 | * indicates that more tokens are expected to be supplied to | ||
| 404 | * <code>acceptSecContext</code>. | ||
| 405 | * Upon completion of the context establishment, the available context | ||
| 406 | * options may be queried through the get methods.<p> | ||
| 407 | * | ||
| 408 | * Note that it is possible that <code>acceptSecContext</code> return a | ||
| 409 | * token for the peer, and <code>isEstablished</code> return | ||
| 410 | * <code>true</code> also. This indicates that the token needs to be | ||
| 411 | * sent to the peer, but the local end of the context is now fully | ||
| 412 | * established.<p> | ||
| 413 | * | ||
| 414 | * The GSS-API authentication tokens contain a definitive start and | ||
| 415 | * end. This method will attempt to read one of these tokens per | ||
| 416 | * invocation, and may block on the stream if only part of the token is | ||
| 417 | * available. In all other respects this method is equivalent to the byte | ||
| 418 | * array based {@link #acceptSecContext(byte[], int, int) | ||
| 419 | * acceptSecContext}.<p> | ||
| 420 | * | ||
| 421 | * Some mechanism providers might require that the caller be granted | ||
| 422 | * permission to accept a security context. A failed permission check | ||
| 423 | * might cause a {@link java.lang.SecurityException SecurityException} | ||
| 424 | * to be thrown from this method.<p> | ||
| 425 | * | ||
| 426 | * The following example code demonstrates how this method might be | ||
| 427 | * used:<p> | ||
| 428 | * <pre> | ||
| 429 | * InputStream is ... | ||
| 430 | * OutputStream os ... | ||
| 431 | * GSSContext context ... | ||
| 432 | * | ||
| 433 | * // Loop while there is still a token to be processed | ||
| 434 | * | ||
| 435 | * while (!context.isEstablished()) { | ||
| 436 | * | ||
| 437 | * context.acceptSecContext(is, os); | ||
| 438 | * | ||
| 439 | * // send output token if generated | ||
| 440 | * os.flush(); | ||
| 441 | * } | ||
| 442 | * </pre> | ||
| 443 | * | ||
| 444 | * | ||
| 445 | * @param inStream an InputStream that contains the token generated by | ||
| 446 | * the peer. | ||
| 447 | * @param outStream an OutputStream where the output token will be | ||
| 448 | * written. During the final stage of context establishment, there may be | ||
| 449 | * no bytes written. | ||
| 450 | * | ||
| 451 | * @throws GSSException containing the following | ||
| 452 | * major error codes: | ||
| 453 | * {@link GSSException#DEFECTIVE_TOKEN GSSException.DEFECTIVE_TOKEN}, | ||
| 454 | * {@link GSSException#BAD_MIC GSSException.BAD_MIC}, | ||
| 455 | * {@link GSSException#NO_CRED GSSException.NO_CRED}, | ||
| 456 | * {@link GSSException#CREDENTIALS_EXPIRED | ||
| 457 | * GSSException.CREDENTIALS_EXPIRED}, | ||
| 458 | * {@link GSSException#BAD_BINDINGS GSSException.BAD_BINDINGS}, | ||
| 459 | * {@link GSSException#OLD_TOKEN GSSException.OLD_TOKEN}, | ||
| 460 | * {@link GSSException#DUPLICATE_TOKEN GSSException.DUPLICATE_TOKEN}, | ||
| 461 | * {@link GSSException#BAD_MECH GSSException.BAD_MECH}, | ||
| 462 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 463 | */ | ||
| 464 | /* Missing return value in RFC. int should have been returned. | ||
| 465 | * ----------------------------------------------------------- | ||
| 466 | * | ||
| 467 | * The application can determine if a token is written to the | ||
| 468 | * OutputStream from the return value of this method. A return value of | ||
| 469 | * <code>0</code> indicates that no token was written. | ||
| 470 | * | ||
| 471 | * @return <strong>the number of bytes written to the | ||
| 472 | * OutputStream as part of the token to be sent to the peer. A value of | ||
| 473 | * 0 indicates that no token needs to be | ||
| 474 | * sent.</strong> | ||
| 475 | */ | ||
| 476 | public void acceptSecContext(InputStream inStream, | ||
| 477 | OutputStream outStream) throws GSSException; | ||
| 478 | |||
| 479 | /** | ||
| 480 | * Used during context establishment to determine the state of the | ||
| 481 | * context. | ||
| 482 | * | ||
| 483 | * @return <code>true</code> if this is a fully established context on | ||
| 484 | * the caller's side and no more tokens are needed from the peer. | ||
| 485 | */ | ||
| 486 | public boolean isEstablished(); | ||
| 487 | |||
| 488 | /** | ||
| 489 | * Releases any system resources and cryptographic information stored in | ||
| 490 | * the context object and invalidates the context. | ||
| 491 | * | ||
| 492 | * | ||
| 493 | * @throws GSSException containing the following | ||
| 494 | * major error codes: | ||
| 495 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 496 | */ | ||
| 497 | public void dispose() throws GSSException; | ||
| 498 | |||
| 499 | /** | ||
| 500 | * Used to determine limits on the size of the message | ||
| 501 | * that can be passed to <code>wrap</code>. Returns the maximum | ||
| 502 | * message size that, if presented to the <code>wrap</code> method with | ||
| 503 | * the same <code>confReq</code> and <code>qop</code> parameters, will | ||
| 504 | * result in an output token containing no more | ||
| 505 | * than <code>maxTokenSize</code> bytes.<p> | ||
| 506 | * | ||
| 507 | * This call is intended for use by applications that communicate over | ||
| 508 | * protocols that impose a maximum message size. It enables the | ||
| 509 | * application to fragment messages prior to applying protection.<p> | ||
| 510 | * | ||
| 511 | * GSS-API implementations are recommended but not required to detect | ||
| 512 | * invalid QOP values when <code>getWrapSizeLimit</code> is called. | ||
| 513 | * This routine guarantees only a maximum message size, not the | ||
| 514 | * availability of specific QOP values for message protection.<p> | ||
| 515 | * | ||
| 516 | * @param qop the level of protection wrap will be asked to provide. | ||
| 517 | * @param confReq <code>true</code> if wrap will be asked to provide | ||
| 518 | * privacy, <code>false</code> otherwise. | ||
| 519 | * @param maxTokenSize the desired maximum size of the token emitted by | ||
| 520 | * wrap. | ||
| 521 | * @return the maximum size of the input token for the given output | ||
| 522 | * token size | ||
| 523 | * | ||
| 524 | * @throws GSSException containing the following | ||
| 525 | * major error codes: | ||
| 526 | * {@link GSSException#CONTEXT_EXPIRED GSSException.CONTEXT_EXPIRED}, | ||
| 527 | * {@link GSSException#BAD_QOP GSSException.BAD_QOP}, | ||
| 528 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 529 | */ | ||
| 530 | public int getWrapSizeLimit(int qop, boolean confReq, | ||
| 531 | int maxTokenSize) throws GSSException; | ||
| 532 | |||
| 533 | /** | ||
| 534 | * Applies per-message security services over the established security | ||
| 535 | * context. The method will return a token with the | ||
| 536 | * application supplied data and a cryptographic MIC over it. | ||
| 537 | * The data may be encrypted if confidentiality (privacy) was | ||
| 538 | * requested.<p> | ||
| 539 | * | ||
| 540 | * The MessageProp object is instantiated by the application and used | ||
| 541 | * to specify a QOP value which selects cryptographic algorithms, and a | ||
| 542 | * privacy service to optionally encrypt the message. The underlying | ||
| 543 | * mechanism that is used in the call may not be able to provide the | ||
| 544 | * privacy service. It sets the actual privacy service that it does | ||
| 545 | * provide in this MessageProp object which the caller should then | ||
| 546 | * query upon return. If the mechanism is not able to provide the | ||
| 547 | * requested QOP, it throws a GSSException with the BAD_QOP code.<p> | ||
| 548 | * | ||
| 549 | * Since some application-level protocols may wish to use tokens | ||
| 550 | * emitted by wrap to provide "secure framing", implementations should | ||
| 551 | * support the wrapping of zero-length messages.<p> | ||
| 552 | * | ||
| 553 | * The application will be responsible for sending the token to the | ||
| 554 | * peer. | ||
| 555 | * | ||
| 556 | * @param inBuf application data to be protected. | ||
| 557 | * @param offset the offset within the inBuf where the data begins. | ||
| 558 | * @param len the length of the data | ||
| 559 | * @param msgProp instance of MessageProp that is used by the | ||
| 560 | * application to set the desired QOP and privacy state. Set the | ||
| 561 | * desired QOP to 0 to request the default QOP. Upon return from this | ||
| 562 | * method, this object will contain the the actual privacy state that | ||
| 563 | * was applied to the message by the underlying mechanism. | ||
| 564 | * @return a byte[] containing the token to be sent to the peer. | ||
| 565 | * | ||
| 566 | * @throws GSSException containing the following major error codes: | ||
| 567 | * {@link GSSException#CONTEXT_EXPIRED GSSException.CONTEXT_EXPIRED}, | ||
| 568 | * {@link GSSException#BAD_QOP GSSException.BAD_QOP}, | ||
| 569 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 570 | */ | ||
| 571 | public byte[] wrap(byte inBuf[], int offset, int len, | ||
| 572 | MessageProp msgProp) throws GSSException; | ||
| 573 | |||
| 574 | /** | ||
| 575 | * Applies per-message security services over the established security | ||
| 576 | * context using streams. The method will return a | ||
| 577 | * token with the application supplied data and a cryptographic MIC over it. | ||
| 578 | * The data may be encrypted if confidentiality | ||
| 579 | * (privacy) was requested. This method is equivalent to the byte array | ||
| 580 | * based {@link #wrap(byte[], int, int, MessageProp) wrap} method.<p> | ||
| 581 | * | ||
| 582 | * The application will be responsible for sending the token to the | ||
| 583 | * peer. Typically, the application would | ||
| 584 | * ensure this by calling the {@link java.io.OutputStream#flush() flush} | ||
| 585 | * method on an <code>OutputStream</code> that encapsulates the | ||
| 586 | * connection between the two peers.<p> | ||
| 587 | * | ||
| 588 | * The MessageProp object is instantiated by the application and used | ||
| 589 | * to specify a QOP value which selects cryptographic algorithms, and a | ||
| 590 | * privacy service to optionally encrypt the message. The underlying | ||
| 591 | * mechanism that is used in the call may not be able to provide the | ||
| 592 | * privacy service. It sets the actual privacy service that it does | ||
| 593 | * provide in this MessageProp object which the caller should then | ||
| 594 | * query upon return. If the mechanism is not able to provide the | ||
| 595 | * requested QOP, it throws a GSSException with the BAD_QOP code.<p> | ||
| 596 | * | ||
| 597 | * Since some application-level protocols may wish to use tokens | ||
| 598 | * emitted by wrap to provide "secure framing", implementations should | ||
| 599 | * support the wrapping of zero-length messages.<p> | ||
| 600 | * | ||
| 601 | * @param inStream an InputStream containing the application data to be | ||
| 602 | * protected. All of the data that is available in | ||
| 603 | * inStream is used. | ||
| 604 | * @param outStream an OutputStream to write the protected message | ||
| 605 | * to. | ||
| 606 | * @param msgProp instance of MessageProp that is used by the | ||
| 607 | * application to set the desired QOP and privacy state. Set the | ||
| 608 | * desired QOP to 0 to request the default QOP. Upon return from this | ||
| 609 | * method, this object will contain the the actual privacy state that | ||
| 610 | * was applied to the message by the underlying mechanism. | ||
| 611 | * | ||
| 612 | * @throws GSSException containing the following | ||
| 613 | * major error codes: | ||
| 614 | * {@link GSSException#CONTEXT_EXPIRED GSSException.CONTEXT_EXPIRED}, | ||
| 615 | * {@link GSSException#BAD_QOP GSSException.BAD_QOP}, | ||
| 616 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 617 | */ | ||
| 618 | public void wrap(InputStream inStream, OutputStream outStream, | ||
| 619 | MessageProp msgProp) throws GSSException; | ||
| 620 | |||
| 621 | /** | ||
| 622 | * Used to process tokens generated by the <code>wrap</code> method on | ||
| 623 | * the other side of the context. The method will return the message | ||
| 624 | * supplied by the peer application to its wrap call, while at the same | ||
| 625 | * time verifying the embedded MIC for that message.<p> | ||
| 626 | * | ||
| 627 | * The MessageProp object is instantiated by the application and is | ||
| 628 | * used by the underlying mechanism to return information to the caller | ||
| 629 | * such as the QOP, whether confidentiality was applied to the message, | ||
| 630 | * and other supplementary message state information.<p> | ||
| 631 | * | ||
| 632 | * Since some application-level protocols may wish to use tokens | ||
| 633 | * emitted by wrap to provide "secure framing", implementations should | ||
| 634 | * support the wrapping and unwrapping of zero-length messages.<p> | ||
| 635 | * | ||
| 636 | * @param inBuf a byte array containing the wrap token received from | ||
| 637 | * peer. | ||
| 638 | * @param offset the offset where the token begins. | ||
| 639 | * @param len the length of the token | ||
| 640 | * @param msgProp upon return from the method, this object will contain | ||
| 641 | * the applied QOP, the privacy state of the message, and supplementary | ||
| 642 | * information stating if the token was a duplicate, old, out of | ||
| 643 | * sequence or arriving after a gap. | ||
| 644 | * @return a byte[] containing the message unwrapped from the input | ||
| 645 | * token. | ||
| 646 | * | ||
| 647 | * @throws GSSException containing the following | ||
| 648 | * major error codes: | ||
| 649 | * {@link GSSException#DEFECTIVE_TOKEN GSSException.DEFECTIVE_TOKEN}, | ||
| 650 | * {@link GSSException#BAD_MIC GSSException.BAD_MIC}, | ||
| 651 | * {@link GSSException#CONTEXT_EXPIRED GSSException.CONTEXT_EXPIRED}, | ||
| 652 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 653 | */ | ||
| 654 | public byte [] unwrap(byte[] inBuf, int offset, int len, | ||
| 655 | MessageProp msgProp) throws GSSException; | ||
| 656 | |||
| 657 | /** | ||
| 658 | * Uses streams to process tokens generated by the <code>wrap</code> | ||
| 659 | * method on the other side of the context. The method will return the | ||
| 660 | * message supplied by the peer application to its wrap call, while at | ||
| 661 | * the same time verifying the embedded MIC for that message.<p> | ||
| 662 | * | ||
| 663 | * The MessageProp object is instantiated by the application and is | ||
| 664 | * used by the underlying mechanism to return information to the caller | ||
| 665 | * such as the QOP, whether confidentiality was applied to the message, | ||
| 666 | * and other supplementary message state information.<p> | ||
| 667 | * | ||
| 668 | * Since some application-level protocols may wish to use tokens | ||
| 669 | * emitted by wrap to provide "secure framing", implementations should | ||
| 670 | * support the wrapping and unwrapping of zero-length messages.<p> | ||
| 671 | * | ||
| 672 | * The format of the input token that this method | ||
| 673 | * reads is defined in the specification for the underlying mechanism that | ||
| 674 | * will be used. This method will attempt to read one of these tokens per | ||
| 675 | * invocation. If the mechanism token contains a definitive start and | ||
| 676 | * end this method may block on the <code>InputStream</code> if only | ||
| 677 | * part of the token is available. If the start and end of the token | ||
| 678 | * are not definitive then the method will attempt to treat all | ||
| 679 | * available bytes as part of the token.<p> | ||
| 680 | * | ||
| 681 | * Other than the possible blocking behavior described above, this | ||
| 682 | * method is equivalent to the byte array based {@link #unwrap(byte[], | ||
| 683 | * int, int, MessageProp) unwrap} method.<p> | ||
| 684 | * | ||
| 685 | * @param inStream an InputStream that contains the wrap token generated | ||
| 686 | * by the peer. | ||
| 687 | * @param outStream an OutputStream to write the application message | ||
| 688 | * to. | ||
| 689 | * @param msgProp upon return from the method, this object will contain | ||
| 690 | * the applied QOP, the privacy state of the message, and supplementary | ||
| 691 | * information stating if the token was a duplicate, old, out of | ||
| 692 | * sequence or arriving after a gap. | ||
| 693 | * | ||
| 694 | * @throws GSSException containing the following | ||
| 695 | * major error codes: | ||
| 696 | * {@link GSSException#DEFECTIVE_TOKEN GSSException.DEFECTIVE_TOKEN}, | ||
| 697 | * {@link GSSException#BAD_MIC GSSException.BAD_MIC}, | ||
| 698 | * {@link GSSException#CONTEXT_EXPIRED GSSException.CONTEXT_EXPIRED}, | ||
| 699 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 700 | */ | ||
| 701 | public void unwrap(InputStream inStream, OutputStream outStream, | ||
| 702 | MessageProp msgProp) throws GSSException; | ||
| 703 | |||
| 704 | /** | ||
| 705 | * Returns a token containing a cryptographic Message Integrity Code | ||
| 706 | * (MIC) for the supplied message, for transfer to the peer | ||
| 707 | * application. Unlike wrap, which encapsulates the user message in the | ||
| 708 | * returned token, only the message MIC is returned in the output | ||
| 709 | * token.<p> | ||
| 710 | * | ||
| 711 | * Note that privacy can only be applied through the wrap call.<p> | ||
| 712 | * | ||
| 713 | * Since some application-level protocols may wish to use tokens emitted | ||
| 714 | * by getMIC to provide "secure framing", implementations should support | ||
| 715 | * derivation of MICs from zero-length messages. | ||
| 716 | * | ||
| 717 | * @param inMsg the message to generate the MIC over. | ||
| 718 | * @param offset offset within the inMsg where the message begins. | ||
| 719 | * @param len the length of the message | ||
| 720 | * @param msgProp an instance of <code>MessageProp</code> that is used | ||
| 721 | * by the application to set the desired QOP. Set the desired QOP to | ||
| 722 | * <code>0</code> in <code>msgProp</code> to request the default | ||
| 723 | * QOP. Alternatively pass in <code>null</code> for <code>msgProp</code> | ||
| 724 | * to request the default QOP. | ||
| 725 | * @return a byte[] containing the token to be sent to the peer. | ||
| 726 | * | ||
| 727 | * @throws GSSException containing the following | ||
| 728 | * major error codes: | ||
| 729 | * {@link GSSException#CONTEXT_EXPIRED GSSException.CONTEXT_EXPIRED}, | ||
| 730 | * {@link GSSException#BAD_QOP GSSException.BAD_QOP}, | ||
| 731 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 732 | */ | ||
| 733 | public byte[] getMIC(byte []inMsg, int offset, int len, | ||
| 734 | MessageProp msgProp) throws GSSException; | ||
| 735 | |||
| 736 | /** | ||
| 737 | * Uses streams to produce a token containing a cryptographic MIC for | ||
| 738 | * the supplied message, for transfer to the peer application. | ||
| 739 | * Unlike wrap, which encapsulates the user message in the returned | ||
| 740 | * token, only the message MIC is produced in the output token. This | ||
| 741 | * method is equivalent to the byte array based {@link #getMIC(byte[], | ||
| 742 | * int, int, MessageProp) getMIC} method. | ||
| 743 | * | ||
| 744 | * Note that privacy can only be applied through the wrap call.<p> | ||
| 745 | * | ||
| 746 | * Since some application-level protocols may wish to use tokens emitted | ||
| 747 | * by getMIC to provide "secure framing", implementations should support | ||
| 748 | * derivation of MICs from zero-length messages. | ||
| 749 | * | ||
| 750 | * @param inStream an InputStream containing the message to generate the | ||
| 751 | * MIC over. All of the data that is available in | ||
| 752 | * inStream is used. | ||
| 753 | * @param outStream an OutputStream to write the output token to. | ||
| 754 | * @param msgProp an instance of <code>MessageProp</code> that is used | ||
| 755 | * by the application to set the desired QOP. Set the desired QOP to | ||
| 756 | * <code>0</code> in <code>msgProp</code> to request the default | ||
| 757 | * QOP. Alternatively pass in <code>null</code> for <code>msgProp</code> | ||
| 758 | * to request the default QOP. | ||
| 759 | * | ||
| 760 | * @throws GSSException containing the following | ||
| 761 | * major error codes: | ||
| 762 | * {@link GSSException#CONTEXT_EXPIRED GSSException.CONTEXT_EXPIRED}, | ||
| 763 | * {@link GSSException#BAD_QOP GSSException.BAD_QOP}, | ||
| 764 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 765 | */ | ||
| 766 | public void getMIC(InputStream inStream, OutputStream outStream, | ||
| 767 | MessageProp msgProp) throws GSSException; | ||
| 768 | |||
| 769 | /** | ||
| 770 | * Verifies the cryptographic MIC, contained in the token parameter, | ||
| 771 | * over the supplied message.<p> | ||
| 772 | * | ||
| 773 | * The MessageProp object is instantiated by the application and is used | ||
| 774 | * by the underlying mechanism to return information to the caller such | ||
| 775 | * as the QOP indicating the strength of protection that was applied to | ||
| 776 | * the message and other supplementary message state information.<p> | ||
| 777 | * | ||
| 778 | * Since some application-level protocols may wish to use tokens emitted | ||
| 779 | * by getMIC to provide "secure framing", implementations should support | ||
| 780 | * the calculation and verification of MICs over zero-length messages. | ||
| 781 | * | ||
| 782 | * @param inToken the token generated by peer's getMIC method. | ||
| 783 | * @param tokOffset the offset within the inToken where the token | ||
| 784 | * begins. | ||
| 785 | * @param tokLen the length of the token. | ||
| 786 | * @param inMsg the application message to verify the cryptographic MIC | ||
| 787 | * over. | ||
| 788 | * @param msgOffset the offset in inMsg where the message begins. | ||
| 789 | * @param msgLen the length of the message. | ||
| 790 | * @param msgProp upon return from the method, this object will contain | ||
| 791 | * the applied QOP and supplementary information stating if the token | ||
| 792 | * was a duplicate, old, out of sequence or arriving after a gap. | ||
| 793 | * | ||
| 794 | * @throws GSSException containing the following | ||
| 795 | * major error codes: | ||
| 796 | * {@link GSSException#DEFECTIVE_TOKEN GSSException.DEFECTIVE_TOKEN} | ||
| 797 | * {@link GSSException#BAD_MIC GSSException.BAD_MIC} | ||
| 798 | * {@link GSSException#CONTEXT_EXPIRED GSSException.CONTEXT_EXPIRED} | ||
| 799 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 800 | */ | ||
| 801 | public void verifyMIC(byte[] inToken, int tokOffset, int tokLen, | ||
| 802 | byte[] inMsg, int msgOffset, int msgLen, | ||
| 803 | MessageProp msgProp) throws GSSException; | ||
| 804 | |||
| 805 | /** | ||
| 806 | * Uses streams to verify the cryptographic MIC, contained in the token | ||
| 807 | * parameter, over the supplied message. This method is equivalent to | ||
| 808 | * the byte array based {@link #verifyMIC(byte[], int, int, byte[], int, | ||
| 809 | * int, MessageProp) verifyMIC} method. | ||
| 810 | * | ||
| 811 | * The MessageProp object is instantiated by the application and is used | ||
| 812 | * by the underlying mechanism to return information to the caller such | ||
| 813 | * as the QOP indicating the strength of protection that was applied to | ||
| 814 | * the message and other supplementary message state information.<p> | ||
| 815 | * | ||
| 816 | * Since some application-level protocols may wish to use tokens emitted | ||
| 817 | * by getMIC to provide "secure framing", implementations should support | ||
| 818 | * the calculation and verification of MICs over zero-length messages.<p> | ||
| 819 | * | ||
| 820 | * The format of the input token that this method | ||
| 821 | * reads is defined in the specification for the underlying mechanism that | ||
| 822 | * will be used. This method will attempt to read one of these tokens per | ||
| 823 | * invocation. If the mechanism token contains a definitive start and | ||
| 824 | * end this method may block on the <code>InputStream</code> if only | ||
| 825 | * part of the token is available. If the start and end of the token | ||
| 826 | * are not definitive then the method will attempt to treat all | ||
| 827 | * available bytes as part of the token.<p> | ||
| 828 | * | ||
| 829 | * Other than the possible blocking behavior described above, this | ||
| 830 | * method is equivalent to the byte array based {@link #verifyMIC(byte[], | ||
| 831 | * int, int, byte[], int, int, MessageProp) verifyMIC} method.<p> | ||
| 832 | * | ||
| 833 | * @param tokStream an InputStream containing the token generated by the | ||
| 834 | * peer's getMIC method. | ||
| 835 | * @param msgStream an InputStream containing the application message to | ||
| 836 | * verify the cryptographic MIC over. All of the data | ||
| 837 | * that is available in msgStream is used. | ||
| 838 | * @param msgProp upon return from the method, this object will contain | ||
| 839 | * the applied QOP and supplementary information stating if the token | ||
| 840 | * was a duplicate, old, out of sequence or arriving after a gap. | ||
| 841 | * | ||
| 842 | * @throws GSSException containing the following | ||
| 843 | * major error codes: | ||
| 844 | * {@link GSSException#DEFECTIVE_TOKEN GSSException.DEFECTIVE_TOKEN} | ||
| 845 | * {@link GSSException#BAD_MIC GSSException.BAD_MIC} | ||
| 846 | * {@link GSSException#CONTEXT_EXPIRED GSSException.CONTEXT_EXPIRED} | ||
| 847 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 848 | */ | ||
| 849 | public void verifyMIC(InputStream tokStream, InputStream msgStream, | ||
| 850 | MessageProp msgProp) throws GSSException; | ||
| 851 | |||
| 852 | /** | ||
| 853 | * Exports this context so that another process may | ||
| 854 | * import it.. Provided to support the sharing of work between | ||
| 855 | * multiple processes. This routine will typically be used by the | ||
| 856 | * context-acceptor, in an application where a single process receives | ||
| 857 | * incoming connection requests and accepts security contexts over | ||
| 858 | * them, then passes the established context to one or more other | ||
| 859 | * processes for message exchange.<p> | ||
| 860 | * | ||
| 861 | * This method deactivates the security context and creates an | ||
| 862 | * interprocess token which, when passed to {@link | ||
| 863 | * GSSManager#createContext(byte[]) GSSManager.createContext} in | ||
| 864 | * another process, will re-activate the context in the second process. | ||
| 865 | * Only a single instantiation of a given context may be active at any | ||
| 866 | * one time; a subsequent attempt by a context exporter to access the | ||
| 867 | * exported security context will fail.<p> | ||
| 868 | * | ||
| 869 | * The implementation may constrain the set of processes by which the | ||
| 870 | * interprocess token may be imported, either as a function of local | ||
| 871 | * security policy, or as a result of implementation decisions. For | ||
| 872 | * example, some implementations may constrain contexts to be passed | ||
| 873 | * only between processes that run under the same account, or which are | ||
| 874 | * part of the same process group.<p> | ||
| 875 | * | ||
| 876 | * The interprocess token may contain security-sensitive information | ||
| 877 | * (for example cryptographic keys). While mechanisms are encouraged | ||
| 878 | * to either avoid placing such sensitive information within | ||
| 879 | * interprocess tokens, or to encrypt the token before returning it to | ||
| 880 | * the application, in a typical GSS-API implementation this may not be | ||
| 881 | * possible. Thus the application must take care to protect the | ||
| 882 | * interprocess token, and ensure that any process to which the token | ||
| 883 | * is transferred is trustworthy. <p> | ||
| 884 | * | ||
| 885 | * Implementations are not required to support the inter-process | ||
| 886 | * transfer of security contexts. Calling the {@link #isTransferable() | ||
| 887 | * isTransferable} method will indicate if the context object is | ||
| 888 | * transferable.<p> | ||
| 889 | * | ||
| 890 | * Calling this method on a context that | ||
| 891 | * is not exportable will result in this exception being thrown with | ||
| 892 | * the error code {@link GSSException#UNAVAILABLE | ||
| 893 | * GSSException.UNAVAILABLE}. | ||
| 894 | * | ||
| 895 | * @return a byte[] containing the exported context | ||
| 896 | * @see GSSManager#createContext(byte[]) | ||
| 897 | * | ||
| 898 | * @throws GSSException containing the following | ||
| 899 | * major error codes: | ||
| 900 | * {@link GSSException#UNAVAILABLE GSSException.UNAVAILABLE}, | ||
| 901 | * {@link GSSException#CONTEXT_EXPIRED GSSException.CONTEXT_EXPIRED}, | ||
| 902 | * {@link GSSException#NO_CONTEXT GSSException.NO_CONTEXT}, | ||
| 903 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 904 | */ | ||
| 905 | public byte [] export() throws GSSException; | ||
| 906 | |||
| 907 | /** | ||
| 908 | * Requests that mutual authentication be done during | ||
| 909 | * context establishment. This request can only be made on the context | ||
| 910 | * initiator's side and it has to be done prior to the first call to | ||
| 911 | * <code>initSecContext</code>.<p> | ||
| 912 | * | ||
| 913 | * Not all mechanisms support mutual authentication and some mechanisms | ||
| 914 | * might require mutual authentication even if the application | ||
| 915 | * doesn't. Therefore, the application should check to see if the | ||
| 916 | * request was honored with the {@link #getMutualAuthState() | ||
| 917 | * getMutualAuthState} method.<p> | ||
| 918 | * | ||
| 919 | * @param state a boolean value indicating whether mutual | ||
| 920 | * authentication should be used or not. | ||
| 921 | * @see #getMutualAuthState() | ||
| 922 | * | ||
| 923 | * @throws GSSException containing the following | ||
| 924 | * major error codes: | ||
| 925 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 926 | */ | ||
| 927 | public void requestMutualAuth(boolean state) throws GSSException; | ||
| 928 | |||
| 929 | /** | ||
| 930 | * Requests that replay detection be enabled for the | ||
| 931 | * per-message security services after context establishment. This | ||
| 932 | * request can only be made on the context initiator's side and it has | ||
| 933 | * to be done prior to the first call to | ||
| 934 | * <code>initSecContext</code>. During context establishment replay | ||
| 935 | * detection is not an option and is a function of the underlying | ||
| 936 | * mechanism's capabilities.<p> | ||
| 937 | * | ||
| 938 | * Not all mechanisms support replay detection and some mechanisms | ||
| 939 | * might require replay detection even if the application | ||
| 940 | * doesn't. Therefore, the application should check to see if the | ||
| 941 | * request was honored with the {@link #getReplayDetState() | ||
| 942 | * getReplayDetState} method. If replay detection is enabled then the | ||
| 943 | * {@link MessageProp#isDuplicateToken() MessageProp.isDuplicateToken} and {@link | ||
| 944 | * MessageProp#isOldToken() MessageProp.isOldToken} methods will return | ||
| 945 | * valid results for the <code>MessageProp</code> object that is passed | ||
| 946 | * in to the <code>unwrap</code> method or the <code>verifyMIC</code> | ||
| 947 | * method.<p> | ||
| 948 | * | ||
| 949 | * @param state a boolean value indicating whether replay detection | ||
| 950 | * should be enabled over the established context or not. | ||
| 951 | * @see #getReplayDetState() | ||
| 952 | * | ||
| 953 | * @throws GSSException containing the following | ||
| 954 | * major error codes: | ||
| 955 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 956 | */ | ||
| 957 | public void requestReplayDet(boolean state) throws GSSException; | ||
| 958 | |||
| 959 | /** | ||
| 960 | * Requests that sequence checking be enabled for the | ||
| 961 | * per-message security services after context establishment. This | ||
| 962 | * request can only be made on the context initiator's side and it has | ||
| 963 | * to be done prior to the first call to | ||
| 964 | * <code>initSecContext</code>. During context establishment sequence | ||
| 965 | * checking is not an option and is a function of the underlying | ||
| 966 | * mechanism's capabilities.<p> | ||
| 967 | * | ||
| 968 | * Not all mechanisms support sequence checking and some mechanisms | ||
| 969 | * might require sequence checking even if the application | ||
| 970 | * doesn't. Therefore, the application should check to see if the | ||
| 971 | * request was honored with the {@link #getSequenceDetState() | ||
| 972 | * getSequenceDetState} method. If sequence checking is enabled then the | ||
| 973 | * {@link MessageProp#isDuplicateToken() MessageProp.isDuplicateToken}, | ||
| 974 | * {@link MessageProp#isOldToken() MessageProp.isOldToken}, | ||
| 975 | * {@link MessageProp#isUnseqToken() MessageProp.isUnseqToken}, and | ||
| 976 | * {@link MessageProp#isGapToken() MessageProp.isGapToken} methods will return | ||
| 977 | * valid results for the <code>MessageProp</code> object that is passed | ||
| 978 | * in to the <code>unwrap</code> method or the <code>verifyMIC</code> | ||
| 979 | * method.<p> | ||
| 980 | * | ||
| 981 | * @param state a boolean value indicating whether sequence checking | ||
| 982 | * should be enabled over the established context or not. | ||
| 983 | * @see #getSequenceDetState() | ||
| 984 | * | ||
| 985 | * @throws GSSException containing the following | ||
| 986 | * major error codes: | ||
| 987 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 988 | */ | ||
| 989 | public void requestSequenceDet(boolean state) throws GSSException; | ||
| 990 | |||
| 991 | /** | ||
| 992 | * Requests that the initiator's credentials be | ||
| 993 | * delegated to the acceptor during context establishment. This | ||
| 994 | * request can only be made on the context initiator's side and it has | ||
| 995 | * to be done prior to the first call to | ||
| 996 | * <code>initSecContext</code>. | ||
| 997 | * | ||
| 998 | * Not all mechanisms support credential delegation. Therefore, an | ||
| 999 | * application that desires delegation should check to see if the | ||
| 1000 | * request was honored with the {@link #getCredDelegState() | ||
| 1001 | * getCredDelegState} method. If the application indicates that | ||
| 1002 | * delegation must not be used, then the mechanism will honor the | ||
| 1003 | * request and delegation will not occur. This is an exception | ||
| 1004 | * to the general rule that a mechanism may enable a service even if it | ||
| 1005 | * is not requested.<p> | ||
| 1006 | * | ||
| 1007 | * @param state a boolean value indicating whether the credentials | ||
| 1008 | * should be delegated or not. | ||
| 1009 | * @see #getCredDelegState() | ||
| 1010 | * | ||
| 1011 | * @throws GSSException containing the following | ||
| 1012 | * major error codes: | ||
| 1013 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 1014 | */ | ||
| 1015 | public void requestCredDeleg(boolean state) throws GSSException; | ||
| 1016 | |||
| 1017 | /** | ||
| 1018 | * Requests that the initiator's identity not be | ||
| 1019 | * disclosed to the acceptor. This request can only be made on the | ||
| 1020 | * context initiator's side and it has to be done prior to the first | ||
| 1021 | * call to <code>initSecContext</code>. | ||
| 1022 | * | ||
| 1023 | * Not all mechanisms support anonymity for the initiator. Therefore, the | ||
| 1024 | * application should check to see if the request was honored with the | ||
| 1025 | * {@link #getAnonymityState() getAnonymityState} method.<p> | ||
| 1026 | * | ||
| 1027 | * @param state a boolean value indicating if the initiator should | ||
| 1028 | * be authenticated to the acceptor as an anonymous principal. | ||
| 1029 | * @see #getAnonymityState | ||
| 1030 | * | ||
| 1031 | * @throws GSSException containing the following | ||
| 1032 | * major error codes: | ||
| 1033 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 1034 | */ | ||
| 1035 | public void requestAnonymity(boolean state) throws GSSException; | ||
| 1036 | |||
| 1037 | /** | ||
| 1038 | * Requests that data confidentiality be enabled | ||
| 1039 | * for the <code>wrap</code> method. This request can only be made on | ||
| 1040 | * the context initiator's side and it has to be done prior to the | ||
| 1041 | * first call to <code>initSecContext</code>. | ||
| 1042 | * | ||
| 1043 | * Not all mechanisms support confidentiality and other mechanisms | ||
| 1044 | * might enable it even if the application doesn't request | ||
| 1045 | * it. The application may check to see if the request was honored with | ||
| 1046 | * the {@link #getConfState() getConfState} method. If confidentiality | ||
| 1047 | * is enabled, only then will the mechanism honor a request for privacy | ||
| 1048 | * in the {@link MessageProp#MessageProp(int, boolean) MessageProp} | ||
| 1049 | * object that is passed in to the <code>wrap</code> method.<p> | ||
| 1050 | * | ||
| 1051 | * Enabling confidentiality will also automatically enable | ||
| 1052 | * integrity.<p> | ||
| 1053 | * | ||
| 1054 | * @param state a boolean value indicating whether confidentiality | ||
| 1055 | * should be enabled or not. | ||
| 1056 | * @see #getConfState() | ||
| 1057 | * @see #getIntegState() | ||
| 1058 | * @see #requestInteg(boolean) | ||
| 1059 | * @see MessageProp | ||
| 1060 | * | ||
| 1061 | * @throws GSSException containing the following | ||
| 1062 | * major error codes: | ||
| 1063 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 1064 | */ | ||
| 1065 | public void requestConf(boolean state) throws GSSException; | ||
| 1066 | |||
| 1067 | /** | ||
| 1068 | * Requests that data integrity be enabled | ||
| 1069 | * for the <code>wrap</code> and <code>getMIC</code>methods. This | ||
| 1070 | * request can only be made on the context initiator's side and it has | ||
| 1071 | * to be done prior to the first call to <code>initSecContext</code>. | ||
| 1072 | * | ||
| 1073 | * Not all mechanisms support integrity and other mechanisms | ||
| 1074 | * might enable it even if the application doesn't request | ||
| 1075 | * it. The application may check to see if the request was honored with | ||
| 1076 | * the {@link #getIntegState() getIntegState} method.<p> | ||
| 1077 | * | ||
| 1078 | * Disabling integrity will also automatically disable | ||
| 1079 | * confidentiality.<p> | ||
| 1080 | * | ||
| 1081 | * @param state a boolean value indicating whether integrity | ||
| 1082 | * should be enabled or not. | ||
| 1083 | * @see #getIntegState() | ||
| 1084 | * | ||
| 1085 | * @throws GSSException containing the following | ||
| 1086 | * major error codes: | ||
| 1087 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 1088 | */ | ||
| 1089 | public void requestInteg(boolean state) throws GSSException; | ||
| 1090 | |||
| 1091 | /** | ||
| 1092 | * Requests a lifetime in seconds for the | ||
| 1093 | * context. This method can only be called on the context initiator's | ||
| 1094 | * side and it has to be done prior to the first call to | ||
| 1095 | * <code>initSecContext</code>.<p> | ||
| 1096 | * | ||
| 1097 | * The actual lifetime of the context will depend on the capabilites of | ||
| 1098 | * the underlying mechanism and the application should call the {@link | ||
| 1099 | * #getLifetime() getLifetime} method to determine this.<p> | ||
| 1100 | * | ||
| 1101 | * @param lifetime the desired context lifetime in seconds. Use | ||
| 1102 | * <code>INDEFINITE_LIFETIME</code> to request an indefinite lifetime | ||
| 1103 | * and <code>DEFAULT_LIFETIME</code> to request a default lifetime. | ||
| 1104 | * @see #getLifetime() | ||
| 1105 | * | ||
| 1106 | * @throws GSSException containing the following | ||
| 1107 | * major error codes: | ||
| 1108 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 1109 | */ | ||
| 1110 | public void requestLifetime(int lifetime) throws GSSException; | ||
| 1111 | |||
| 1112 | /** | ||
| 1113 | * Sets the channel bindings to be used during context | ||
| 1114 | * establishment. This method can be called on both | ||
| 1115 | * the context initiator's and the context acceptor's side, but it must | ||
| 1116 | * be called before context establishment begins. This means that an | ||
| 1117 | * initiator must call it before the first call to | ||
| 1118 | * <code>initSecContext</code> and the acceptor must call it before the | ||
| 1119 | * first call to <code>acceptSecContext</code>. | ||
| 1120 | * | ||
| 1121 | * @param cb the channel bindings to use. | ||
| 1122 | * | ||
| 1123 | * @throws GSSException containing the following | ||
| 1124 | * major error codes: | ||
| 1125 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 1126 | */ | ||
| 1127 | public void setChannelBinding(ChannelBinding cb) throws GSSException; | ||
| 1128 | |||
| 1129 | /** | ||
| 1130 | * Determines if credential delegation is enabled on | ||
| 1131 | * this context. It can be called by both the context initiator and the | ||
| 1132 | * context acceptor. For a definitive answer this method must be | ||
| 1133 | * called only after context establishment is complete. Note that if an | ||
| 1134 | * initiator requests that delegation not be allowed the {@link | ||
| 1135 | * #requestCredDeleg(boolean) requestCredDeleg} method will honor that | ||
| 1136 | * request and this method will return <code>false</code> on the | ||
| 1137 | * initiator's side from that point onwards. <p> | ||
| 1138 | * | ||
| 1139 | * @return true if delegation is enabled, false otherwise. | ||
| 1140 | * @see #requestCredDeleg(boolean) | ||
| 1141 | */ | ||
| 1142 | public boolean getCredDelegState(); | ||
| 1143 | |||
| 1144 | /** | ||
| 1145 | * Determines if mutual authentication is enabled on | ||
| 1146 | * this context. It can be called by both the context initiator and the | ||
| 1147 | * context acceptor. For a definitive answer this method must be | ||
| 1148 | * called only after context establishment is complete. An initiator | ||
| 1149 | * that requests mutual authentication can call this method after | ||
| 1150 | * context completion and dispose the context if its request was not | ||
| 1151 | * honored.<p> | ||
| 1152 | * | ||
| 1153 | * @return true if mutual authentication is enabled, false otherwise. | ||
| 1154 | * @see #requestMutualAuth(boolean) | ||
| 1155 | */ | ||
| 1156 | public boolean getMutualAuthState(); | ||
| 1157 | |||
| 1158 | /** | ||
| 1159 | * Determines if replay detection is enabled for the | ||
| 1160 | * per-message security services from this context. It can be called by | ||
| 1161 | * both the context initiator and the context acceptor. For a | ||
| 1162 | * definitive answer this method must be called only after context | ||
| 1163 | * establishment is complete. An initiator that requests replay | ||
| 1164 | * detection can call this method after context completion and | ||
| 1165 | * dispose the context if its request was not honored.<p> | ||
| 1166 | * | ||
| 1167 | * @return true if replay detection is enabled, false otherwise. | ||
| 1168 | * @see #requestReplayDet(boolean) | ||
| 1169 | */ | ||
| 1170 | public boolean getReplayDetState(); | ||
| 1171 | |||
| 1172 | /** | ||
| 1173 | * Determines if sequence checking is enabled for the | ||
| 1174 | * per-message security services from this context. It can be called by | ||
| 1175 | * both the context initiator and the context acceptor. For a | ||
| 1176 | * definitive answer this method must be called only after context | ||
| 1177 | * establishment is complete. An initiator that requests sequence | ||
| 1178 | * checking can call this method after context completion and | ||
| 1179 | * dispose the context if its request was not honored.<p> | ||
| 1180 | * | ||
| 1181 | * @return true if sequence checking is enabled, false otherwise. | ||
| 1182 | * @see #requestSequenceDet(boolean) | ||
| 1183 | */ | ||
| 1184 | public boolean getSequenceDetState(); | ||
| 1185 | |||
| 1186 | /** | ||
| 1187 | * Determines if the context initiator is | ||
| 1188 | * anonymously authenticated to the context acceptor. It can be called by | ||
| 1189 | * both the context initiator and the context acceptor, and at any | ||
| 1190 | * time. <strong>On the initiator side, a call to this method determines | ||
| 1191 | * if the identity of the initiator has been disclosed in any of the | ||
| 1192 | * context establishment tokens that might have been generated thus far | ||
| 1193 | * by <code>initSecContext</code>. An initiator that absolutely must be | ||
| 1194 | * authenticated anonymously should call this method after each call to | ||
| 1195 | * <code>initSecContext</code> to determine if the generated token | ||
| 1196 | * should be sent to the peer or the context aborted.</strong> On the | ||
| 1197 | * acceptor side, a call to this method determines if any of the tokens | ||
| 1198 | * processed by <code>acceptSecContext</code> thus far have divulged | ||
| 1199 | * the identity of the initiator.<p> | ||
| 1200 | * | ||
| 1201 | * @return true if the context initiator is still anonymous, false | ||
| 1202 | * otherwise. | ||
| 1203 | * @see #requestAnonymity(boolean) | ||
| 1204 | */ | ||
| 1205 | public boolean getAnonymityState(); | ||
| 1206 | |||
| 1207 | /** | ||
| 1208 | * Determines if the context is transferable to other processes | ||
| 1209 | * through the use of the {@link #export() export} method. This call | ||
| 1210 | * is only valid on fully established contexts. | ||
| 1211 | * | ||
| 1212 | * @return true if this context can be exported, false otherwise. | ||
| 1213 | * | ||
| 1214 | * @throws GSSException containing the following | ||
| 1215 | * major error codes: | ||
| 1216 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 1217 | */ | ||
| 1218 | public boolean isTransferable() throws GSSException; | ||
| 1219 | |||
| 1220 | /** | ||
| 1221 | * Determines if the context is ready for per message operations to be | ||
| 1222 | * used over it. Some mechanisms may allow the usage of the | ||
| 1223 | * per-message operations before the context is fully established. | ||
| 1224 | * | ||
| 1225 | * @return true if methods like <code>wrap</code>, <code>unwrap</code>, | ||
| 1226 | * <code>getMIC</code>, and <code>verifyMIC</code> can be used with | ||
| 1227 | * this context at the current stage of context establishment, false | ||
| 1228 | * otherwise. | ||
| 1229 | */ | ||
| 1230 | public boolean isProtReady(); | ||
| 1231 | |||
| 1232 | /** | ||
| 1233 | * Determines if data confidentiality is available | ||
| 1234 | * over the context. This method can be called by both the context | ||
| 1235 | * initiator and the context acceptor, but only after one of {@link | ||
| 1236 | * #isProtReady() isProtReady} or {@link #isEstablished() | ||
| 1237 | * isEstablished} return <code>true</code>. If this method returns | ||
| 1238 | * <code>true</code>, so will {@link #getIntegState() | ||
| 1239 | * getIntegState}<p> | ||
| 1240 | * | ||
| 1241 | * @return true if confidentiality services are available, false | ||
| 1242 | * otherwise. | ||
| 1243 | * @see #requestConf(boolean) | ||
| 1244 | */ | ||
| 1245 | public boolean getConfState(); | ||
| 1246 | |||
| 1247 | /** | ||
| 1248 | * Determines if data integrity is available | ||
| 1249 | * over the context. This method can be called by both the context | ||
| 1250 | * initiator and the context acceptor, but only after one of {@link | ||
| 1251 | * #isProtReady() isProtReady} or {@link #isEstablished() | ||
| 1252 | * isEstablished} return <code>true</code>. This method will always | ||
| 1253 | * return <code>true</code> if {@link #getConfState() getConfState} | ||
| 1254 | * returns true.<p> | ||
| 1255 | * | ||
| 1256 | * @return true if integrity services are available, false otherwise. | ||
| 1257 | * @see #requestInteg(boolean) | ||
| 1258 | */ | ||
| 1259 | public boolean getIntegState(); | ||
| 1260 | |||
| 1261 | /** | ||
| 1262 | * Determines what the remaining lifetime for this | ||
| 1263 | * context is. It can be called by both the context initiator and the | ||
| 1264 | * context acceptor, but for a definitive answer it should be called | ||
| 1265 | * only after {@link #isEstablished() isEstablished} returns | ||
| 1266 | * true.<p> | ||
| 1267 | * | ||
| 1268 | * @return the remaining lifetime in seconds | ||
| 1269 | * @see #requestLifetime(int) | ||
| 1270 | */ | ||
| 1271 | public int getLifetime(); | ||
| 1272 | |||
| 1273 | /** | ||
| 1274 | * Returns the name of the context initiator. This call is valid only | ||
| 1275 | * after one of {@link #isProtReady() isProtReady} or {@link | ||
| 1276 | * #isEstablished() isEstablished} return <code>true</code>. | ||
| 1277 | * | ||
| 1278 | * @return a GSSName that is an MN containing the name of the context | ||
| 1279 | * initiator. | ||
| 1280 | * @see GSSName | ||
| 1281 | * | ||
| 1282 | * @throws GSSException containing the following | ||
| 1283 | * major error codes: | ||
| 1284 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 1285 | */ | ||
| 1286 | public GSSName getSrcName() throws GSSException; | ||
| 1287 | |||
| 1288 | /** | ||
| 1289 | * Returns the name of the context acceptor. This call is valid only | ||
| 1290 | * after one of {@link #isProtReady() isProtReady} or {@link | ||
| 1291 | * #isEstablished() isEstablished} return <code>true</code>. | ||
| 1292 | * | ||
| 1293 | * @return a GSSName that is an MN containing the name of the context | ||
| 1294 | * acceptor. | ||
| 1295 | * | ||
| 1296 | * @throws GSSException containing the following | ||
| 1297 | * major error codes: | ||
| 1298 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 1299 | */ | ||
| 1300 | public GSSName getTargName() throws GSSException; | ||
| 1301 | |||
| 1302 | /** | ||
| 1303 | * Determines what mechanism is being used for this | ||
| 1304 | * context. This method may be called before the context is fully | ||
| 1305 | * established, but the mechanism returned may change on successive | ||
| 1306 | * calls in the negotiated mechanism case. | ||
| 1307 | * | ||
| 1308 | * @return the Oid of the mechanism being used | ||
| 1309 | * | ||
| 1310 | * @throws GSSException containing the following | ||
| 1311 | * major error codes: | ||
| 1312 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 1313 | */ | ||
| 1314 | public Oid getMech() throws GSSException; | ||
| 1315 | |||
| 1316 | /** | ||
| 1317 | * Obtains the credentials delegated by the context | ||
| 1318 | * initiator to the context acceptor. It should be called only on the | ||
| 1319 | * context acceptor's side, and once the context is fully | ||
| 1320 | * established. The caller can use the method {@link | ||
| 1321 | * #getCredDelegState() getCredDelegState} to determine if there are | ||
| 1322 | * any delegated credentials. | ||
| 1323 | * | ||
| 1324 | * @return a GSSCredential containing the initiator's delegated | ||
| 1325 | * credentials, or <code>null</code> is no credentials | ||
| 1326 | * were delegated. | ||
| 1327 | * | ||
| 1328 | * @throws GSSException containing the following | ||
| 1329 | * major error codes: | ||
| 1330 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 1331 | */ | ||
| 1332 | public GSSCredential getDelegCred() throws GSSException; | ||
| 1333 | |||
| 1334 | /** | ||
| 1335 | * Determines if this is the context initiator. This | ||
| 1336 | * can be called on both the context initiator's and context acceptor's | ||
| 1337 | * side. | ||
| 1338 | * | ||
| 1339 | * @return true if this is the context initiator, false if it is the | ||
| 1340 | * context acceptor. | ||
| 1341 | * | ||
| 1342 | * @throws GSSException containing the following | ||
| 1343 | * major error codes: | ||
| 1344 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 1345 | */ | ||
| 1346 | public boolean isInitiator() throws GSSException; | ||
| 1347 | } | ||
Binary file not shown.
| @@ -0,0 +1,370 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. | ||
| 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | ||
| 4 | * | ||
| 5 | * This code is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms of the GNU General Public License version 2 only, as | ||
| 7 | * published by the Free Software Foundation. Oracle designates this | ||
| 8 | * particular file as subject to the "Classpath" exception as provided | ||
| 9 | * by Oracle in the LICENSE file that accompanied this code. | ||
| 10 | * | ||
| 11 | * This code is distributed in the hope that it will be useful, but WITHOUT | ||
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
| 14 | * version 2 for more details (a copy is included in the LICENSE file that | ||
| 15 | * accompanied this code). | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License version | ||
| 18 | * 2 along with this work; if not, write to the Free Software Foundation, | ||
| 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 20 | * | ||
| 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | ||
| 22 | * or visit www.oracle.com if you need additional information or have any | ||
| 23 | * questions. | ||
| 24 | */ | ||
| 25 | |||
| 26 | package org.ietf.jgss; | ||
| 27 | |||
| 28 | /** | ||
| 29 | * This interface encapsulates the GSS-API credentials for an entity. A | ||
| 30 | * credential contains all the necessary cryptographic information to | ||
| 31 | * enable the creation of a context on behalf of the entity that it | ||
| 32 | * represents. It may contain multiple, distinct, mechanism specific | ||
| 33 | * credential elements, each containing information for a specific | ||
| 34 | * security mechanism, but all referring to the same entity. A credential | ||
| 35 | * may be used to perform context initiation, acceptance, or both.<p> | ||
| 36 | * | ||
| 37 | * Credentials are instantiated using one of the | ||
| 38 | * <code>createCredential</code> methods in the {@link GSSManager | ||
| 39 | * GSSManager} class. GSS-API credential creation is not | ||
| 40 | * intended to provide a "login to the network" function, as such a | ||
| 41 | * function would involve the creation of new credentials rather than | ||
| 42 | * merely acquiring a handle to existing credentials. The | ||
| 43 | * <a href=package-summary.html#useSubjectCredsOnly>section on credential | ||
| 44 | * acquisition</a> in the package level description describes | ||
| 45 | * how existing credentials are acquired in the Java platform. GSS-API | ||
| 46 | * implementations must impose a local access-control policy on callers to | ||
| 47 | * prevent unauthorized callers from acquiring credentials to which they | ||
| 48 | * are not entitled. <p> | ||
| 49 | * | ||
| 50 | * Applications will create a credential object passing the desired | ||
| 51 | * parameters. The application can then use the query methods to obtain | ||
| 52 | * specific information about the instantiated credential object. | ||
| 53 | * When the credential is no longer needed, the application should call | ||
| 54 | * the {@link #dispose() dispose} method to release any resources held by | ||
| 55 | * the credential object and to destroy any cryptographically sensitive | ||
| 56 | * information.<p> | ||
| 57 | * | ||
| 58 | * This example code demonstrates the creation of a GSSCredential | ||
| 59 | * implementation for a specific entity, querying of its fields, and its | ||
| 60 | * release when it is no longer needed:<p> | ||
| 61 | * <pre> | ||
| 62 | * GSSManager manager = GSSManager.getInstance(); | ||
| 63 | * | ||
| 64 | * // start by creating a name object for the entity | ||
| 65 | * GSSName name = manager.createName("myusername", GSSName.NT_USER_NAME); | ||
| 66 | * | ||
| 67 | * // now acquire credentials for the entity | ||
| 68 | * GSSCredential cred = manager.createCredential(name, | ||
| 69 | * GSSCredential.ACCEPT_ONLY); | ||
| 70 | * | ||
| 71 | * // display credential information - name, remaining lifetime, | ||
| 72 | * // and the mechanisms it has been acquired over | ||
| 73 | * System.out.println(cred.getName().toString()); | ||
| 74 | * System.out.println(cred.getRemainingLifetime()); | ||
| 75 | * | ||
| 76 | * Oid [] mechs = cred.getMechs(); | ||
| 77 | * if (mechs != null) { | ||
| 78 | * for (int i = 0; i < mechs.length; i++) | ||
| 79 | * System.out.println(mechs[i].toString()); | ||
| 80 | * } | ||
| 81 | * | ||
| 82 | * // release system resources held by the credential | ||
| 83 | * cred.dispose(); | ||
| 84 | * </pre> | ||
| 85 | * | ||
| 86 | * @see GSSManager#createCredential(int) | ||
| 87 | * @see GSSManager#createCredential(GSSName, int, Oid, int) | ||
| 88 | * @see GSSManager#createCredential(GSSName, int, Oid[], int) | ||
| 89 | * @see #dispose() | ||
| 90 | * | ||
| 91 | * @author Mayank Upadhyay | ||
| 92 | * @since 1.4 | ||
| 93 | */ | ||
| 94 | public interface GSSCredential extends Cloneable{ | ||
| 95 | |||
| 96 | /** | ||
| 97 | * Credential usage flag requesting that it be usable | ||
| 98 | * for both context initiation and acceptance. | ||
| 99 | * | ||
| 100 | */ | ||
| 101 | public static final int INITIATE_AND_ACCEPT = 0; | ||
| 102 | |||
| 103 | |||
| 104 | /** | ||
| 105 | * Credential usage flag requesting that it be usable | ||
| 106 | * for context initiation only. | ||
| 107 | * | ||
| 108 | */ | ||
| 109 | public static final int INITIATE_ONLY = 1; | ||
| 110 | |||
| 111 | |||
| 112 | /** | ||
| 113 | * Credential usage flag requesting that it be usable | ||
| 114 | * for context acceptance only. | ||
| 115 | * | ||
| 116 | */ | ||
| 117 | public static final int ACCEPT_ONLY = 2; | ||
| 118 | |||
| 119 | |||
| 120 | /** | ||
| 121 | * A lifetime constant representing the default credential lifetime. This | ||
| 122 | * value it set to 0. | ||
| 123 | */ | ||
| 124 | public static final int DEFAULT_LIFETIME = 0; | ||
| 125 | |||
| 126 | /** | ||
| 127 | * A lifetime constant representing indefinite credential lifetime. | ||
| 128 | * This value must is set to the maximum integer value in Java - | ||
| 129 | * {@link java.lang.Integer#MAX_VALUE Integer.MAX_VALUE}. | ||
| 130 | */ | ||
| 131 | public static final int INDEFINITE_LIFETIME = Integer.MAX_VALUE; | ||
| 132 | |||
| 133 | /** | ||
| 134 | * Releases any sensitive information that the GSSCredential object may | ||
| 135 | * be containing. Applications should call this method as soon as the | ||
| 136 | * credential is no longer needed to minimize the time any sensitive | ||
| 137 | * information is maintained. | ||
| 138 | * | ||
| 139 | * @throws GSSException containing the following | ||
| 140 | * major error codes: | ||
| 141 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 142 | */ | ||
| 143 | public void dispose() throws GSSException; | ||
| 144 | |||
| 145 | /** | ||
| 146 | * Retrieves the name of the entity that the credential asserts. | ||
| 147 | * | ||
| 148 | * @return a GSSName representing the entity | ||
| 149 | * | ||
| 150 | * @throws GSSException containing the following | ||
| 151 | * major error codes: | ||
| 152 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 153 | */ | ||
| 154 | public GSSName getName() throws GSSException; | ||
| 155 | |||
| 156 | /** | ||
| 157 | * Retrieves a Mechanism Name of the entity that the credential | ||
| 158 | * asserts. This is equivalent to calling {@link | ||
| 159 | * GSSName#canonicalize(Oid) canonicalize} on the value returned by | ||
| 160 | * the other form of {@link #getName() getName}. | ||
| 161 | * | ||
| 162 | * @param mech the Oid of the mechanism for which the Mechanism Name | ||
| 163 | * should be returned. | ||
| 164 | * @return a GSSName representing the entity canonicalized for the | ||
| 165 | * desired mechanism | ||
| 166 | * | ||
| 167 | * @throws GSSException containing the following | ||
| 168 | * major error codes: | ||
| 169 | * {@link GSSException#BAD_MECH GSSException.BAD_MECH}, | ||
| 170 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 171 | */ | ||
| 172 | public GSSName getName(Oid mech) throws GSSException; | ||
| 173 | |||
| 174 | /** | ||
| 175 | * Returns the remaining lifetime in seconds for a credential. The | ||
| 176 | * remaining lifetime is the minimum lifetime amongst all of the underlying | ||
| 177 | * mechanism specific credential elements. | ||
| 178 | * | ||
| 179 | * @return the minimum remaining lifetime in seconds for this | ||
| 180 | * credential. A return value of {@link #INDEFINITE_LIFETIME | ||
| 181 | * INDEFINITE_LIFETIME} indicates that the credential does | ||
| 182 | * not expire. A return value of 0 indicates that the credential is | ||
| 183 | * already expired. | ||
| 184 | * | ||
| 185 | * @see #getRemainingInitLifetime(Oid) | ||
| 186 | * @see #getRemainingAcceptLifetime(Oid) | ||
| 187 | * | ||
| 188 | * @throws GSSException containing the following | ||
| 189 | * major error codes: | ||
| 190 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 191 | */ | ||
| 192 | public int getRemainingLifetime() throws GSSException; | ||
| 193 | |||
| 194 | /** | ||
| 195 | * Returns the lifetime in seconds for the credential to remain capable | ||
| 196 | * of initiating security contexts using the specified mechanism. This | ||
| 197 | * method queries the initiator credential element that belongs to the | ||
| 198 | * specified mechanism. | ||
| 199 | * | ||
| 200 | * @return the number of seconds remaining in the life of this credential | ||
| 201 | * element. A return value of {@link #INDEFINITE_LIFETIME | ||
| 202 | * INDEFINITE_LIFETIME} indicates that the credential element does not | ||
| 203 | * expire. A return value of 0 indicates that the credential element is | ||
| 204 | * already expired. | ||
| 205 | * | ||
| 206 | * @param mech the Oid of the mechanism whose intiator credential element | ||
| 207 | * should be queried. | ||
| 208 | * | ||
| 209 | * @throws GSSException containing the following | ||
| 210 | * major error codes: | ||
| 211 | * {@link GSSException#BAD_MECH GSSException.BAD_MECH}, | ||
| 212 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 213 | */ | ||
| 214 | public int getRemainingInitLifetime(Oid mech) throws GSSException; | ||
| 215 | |||
| 216 | /** | ||
| 217 | * Returns the lifetime in seconds for the credential to remain capable | ||
| 218 | * of accepting security contexts using the specified mechanism. This | ||
| 219 | * method queries the acceptor credential element that belongs to the | ||
| 220 | * specified mechanism. | ||
| 221 | * | ||
| 222 | * @return the number of seconds remaining in the life of this credential | ||
| 223 | * element. A return value of {@link #INDEFINITE_LIFETIME | ||
| 224 | * INDEFINITE_LIFETIME} indicates that the credential element does not | ||
| 225 | * expire. A return value of 0 indicates that the credential element is | ||
| 226 | * already expired. | ||
| 227 | * | ||
| 228 | * @param mech the Oid of the mechanism whose acceptor credential element | ||
| 229 | * should be queried. | ||
| 230 | * | ||
| 231 | * @throws GSSException containing the following | ||
| 232 | * major error codes: | ||
| 233 | * {@link GSSException#BAD_MECH GSSException.BAD_MECH}, | ||
| 234 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 235 | */ | ||
| 236 | public int getRemainingAcceptLifetime(Oid mech) throws GSSException; | ||
| 237 | |||
| 238 | /** | ||
| 239 | * Returns the credential usage mode. In other words, it | ||
| 240 | * tells us if this credential can be used for initiating or accepting | ||
| 241 | * security contexts. It does not tell us which mechanism(s) has to be | ||
| 242 | * used in order to do so. It is expected that an application will allow | ||
| 243 | * the GSS-API to pick a default mechanism after calling this method. | ||
| 244 | * | ||
| 245 | * @return The return value will be one of {@link #INITIATE_ONLY | ||
| 246 | * INITIATE_ONLY}, {@link #ACCEPT_ONLY ACCEPT_ONLY}, and {@link | ||
| 247 | * #INITIATE_AND_ACCEPT INITIATE_AND_ACCEPT}. | ||
| 248 | * | ||
| 249 | * @throws GSSException containing the following | ||
| 250 | * major error codes: | ||
| 251 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 252 | */ | ||
| 253 | public int getUsage() throws GSSException; | ||
| 254 | |||
| 255 | /** | ||
| 256 | * Returns the credential usage mode for a specific mechanism. In other | ||
| 257 | * words, it tells us if this credential can be used | ||
| 258 | * for initiating or accepting security contexts with a given underlying | ||
| 259 | * mechanism. | ||
| 260 | * | ||
| 261 | * @return The return value will be one of {@link #INITIATE_ONLY | ||
| 262 | * INITIATE_ONLY}, {@link #ACCEPT_ONLY ACCEPT_ONLY}, and {@link | ||
| 263 | * #INITIATE_AND_ACCEPT INITIATE_AND_ACCEPT}. | ||
| 264 | * @param mech the Oid of the mechanism whose credentials usage mode is | ||
| 265 | * to be determined. | ||
| 266 | * | ||
| 267 | * @throws GSSException containing the following | ||
| 268 | * major error codes: | ||
| 269 | * {@link GSSException#BAD_MECH GSSException.BAD_MECH}, | ||
| 270 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 271 | */ | ||
| 272 | public int getUsage(Oid mech) throws GSSException; | ||
| 273 | |||
| 274 | /** | ||
| 275 | * Returns a list of mechanisms supported by this credential. It does | ||
| 276 | * not tell us which ones can be used to initiate | ||
| 277 | * contexts and which ones can be used to accept contexts. The | ||
| 278 | * application must call the {@link #getUsage(Oid) getUsage} method with | ||
| 279 | * each of the returned Oid's to determine the possible modes of | ||
| 280 | * usage. | ||
| 281 | * | ||
| 282 | * @return an array of Oid's corresponding to the supported mechanisms. | ||
| 283 | * | ||
| 284 | * @throws GSSException containing the following | ||
| 285 | * major error codes: | ||
| 286 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 287 | */ | ||
| 288 | public Oid[] getMechs() throws GSSException; | ||
| 289 | |||
| 290 | /** | ||
| 291 | * Adds a mechanism specific credential-element to an existing | ||
| 292 | * credential. This method allows the construction of credentials, one | ||
| 293 | * mechanism at a time.<p> | ||
| 294 | * | ||
| 295 | * This routine is envisioned to be used mainly by context acceptors | ||
| 296 | * during the creation of acceptor credentials which are to be used | ||
| 297 | * with a variety of clients using different security mechanisms.<p> | ||
| 298 | * | ||
| 299 | * This routine adds the new credential element "in-place". To add the | ||
| 300 | * element in a new credential, first call <code>clone</code> to obtain a | ||
| 301 | * copy of this credential, then call its <code>add</code> method.<p> | ||
| 302 | * | ||
| 303 | * As always, GSS-API implementations must impose a local access-control | ||
| 304 | * policy on callers to prevent unauthorized callers from acquiring | ||
| 305 | * credentials to which they are not entitled. | ||
| 306 | * | ||
| 307 | * Non-default values for initLifetime and acceptLifetime cannot always | ||
| 308 | * be honored by the underlying mechanisms, thus callers should be | ||
| 309 | * prepared to call {@link #getRemainingInitLifetime(Oid) | ||
| 310 | * getRemainingInitLifetime} and {@link #getRemainingAcceptLifetime(Oid) | ||
| 311 | * getRemainingAcceptLifetime} on the credential. | ||
| 312 | * | ||
| 313 | * @param name the name of the principal for whom this credential is to | ||
| 314 | * be acquired. Use <code>null</code> to specify the default | ||
| 315 | * principal. | ||
| 316 | * @param initLifetime the number of seconds that the credential element | ||
| 317 | * should remain valid for initiating of security contexts. Use {@link | ||
| 318 | * GSSCredential#INDEFINITE_LIFETIME GSSCredential.INDEFINITE_LIFETIME} | ||
| 319 | * to request that the credentials have the maximum permitted lifetime | ||
| 320 | * for this. Use {@link GSSCredential#DEFAULT_LIFETIME | ||
| 321 | * GSSCredential.DEFAULT_LIFETIME} to request default credential lifetime | ||
| 322 | * for this. | ||
| 323 | * @param acceptLifetime the number of seconds that the credential | ||
| 324 | * element should remain valid for accepting security contexts. Use {@link | ||
| 325 | * GSSCredential#INDEFINITE_LIFETIME GSSCredential.INDEFINITE_LIFETIME} | ||
| 326 | * to request that the credentials have the maximum permitted lifetime | ||
| 327 | * for this. Use {@link GSSCredential#DEFAULT_LIFETIME | ||
| 328 | * GSSCredential.DEFAULT_LIFETIME} to request default credential lifetime | ||
| 329 | * for this. | ||
| 330 | * @param mech the mechanism over which the credential is to be acquired. | ||
| 331 | * @param usage the usage mode that this credential | ||
| 332 | * element should add to the credential. The value | ||
| 333 | * of this parameter must be one of: | ||
| 334 | * {@link #INITIATE_AND_ACCEPT INITIATE_AND_ACCEPT}, | ||
| 335 | * {@link #ACCEPT_ONLY ACCEPT_ONLY}, and | ||
| 336 | * {@link #INITIATE_ONLY INITIATE_ONLY}. | ||
| 337 | * | ||
| 338 | * @throws GSSException containing the following | ||
| 339 | * major error codes: | ||
| 340 | * {@link GSSException#DUPLICATE_ELEMENT | ||
| 341 | * GSSException.DUPLICATE_ELEMENT}, | ||
| 342 | * {@link GSSException#BAD_MECH GSSException.BAD_MECH}, | ||
| 343 | * {@link GSSException#BAD_NAMETYPE GSSException.BAD_NAMETYPE}, | ||
| 344 | * {@link GSSException#NO_CRED GSSException.NO_CRED}, | ||
| 345 | * {@link GSSException#CREDENTIALS_EXPIRED | ||
| 346 | * GSSException.CREDENTIALS_EXPIRED}, | ||
| 347 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 348 | */ | ||
| 349 | public void add(GSSName name, int initLifetime, int acceptLifetime, | ||
| 350 | Oid mech, int usage) throws GSSException; | ||
| 351 | |||
| 352 | /** | ||
| 353 | * Tests if this GSSCredential asserts the same entity as the supplied | ||
| 354 | * object. The two credentials must be acquired over the same | ||
| 355 | * mechanisms and must refer to the same principal. | ||
| 356 | * | ||
| 357 | * @return <code>true</code> if the two GSSCredentials assert the same | ||
| 358 | * entity; <code>false</code> otherwise. | ||
| 359 | * @param another another GSSCredential for comparison to this one | ||
| 360 | */ | ||
| 361 | public boolean equals(Object another); | ||
| 362 | |||
| 363 | /** | ||
| 364 | * Returns a hashcode value for this GSSCredential. | ||
| 365 | * | ||
| 366 | * @return a hashCode value | ||
| 367 | */ | ||
| 368 | public int hashCode(); | ||
| 369 | |||
| 370 | } | ||
Binary file not shown.
| @@ -0,0 +1,403 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved. | ||
| 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | ||
| 4 | * | ||
| 5 | * This code is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms of the GNU General Public License version 2 only, as | ||
| 7 | * published by the Free Software Foundation. Oracle designates this | ||
| 8 | * particular file as subject to the "Classpath" exception as provided | ||
| 9 | * by Oracle in the LICENSE file that accompanied this code. | ||
| 10 | * | ||
| 11 | * This code is distributed in the hope that it will be useful, but WITHOUT | ||
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
| 14 | * version 2 for more details (a copy is included in the LICENSE file that | ||
| 15 | * accompanied this code). | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License version | ||
| 18 | * 2 along with this work; if not, write to the Free Software Foundation, | ||
| 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 20 | * | ||
| 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | ||
| 22 | * or visit www.oracle.com if you need additional information or have any | ||
| 23 | * questions. | ||
| 24 | */ | ||
| 25 | |||
| 26 | package org.ietf.jgss; | ||
| 27 | |||
| 28 | /** | ||
| 29 | * This exception is thrown whenever a GSS-API error occurs, including | ||
| 30 | * any mechanism specific error. It may contain both the major and the | ||
| 31 | * minor GSS-API status codes. Major error codes are those defined at the | ||
| 32 | * GSS-API level in this class. Minor error codes are mechanism specific | ||
| 33 | * error codes that can provide additional information. The underlying | ||
| 34 | * mechanism implementation is responsible for setting appropriate minor | ||
| 35 | * status codes when throwing this exception. Aside from delivering the | ||
| 36 | * numeric error codes to the caller, this class performs the mapping from | ||
| 37 | * their numeric values to textual representations. <p> | ||
| 38 | * | ||
| 39 | * @author Mayank Upadhyay | ||
| 40 | * @since 1.4 | ||
| 41 | */ | ||
| 42 | public class GSSException extends Exception { | ||
| 43 | |||
| 44 | private static final long serialVersionUID = -2706218945227726672L; | ||
| 45 | |||
| 46 | /** | ||
| 47 | * Channel bindings mismatch. | ||
| 48 | */ | ||
| 49 | public static final int BAD_BINDINGS = 1; //start with 1 | ||
| 50 | |||
| 51 | /** | ||
| 52 | * Unsupported mechanism requested. | ||
| 53 | */ | ||
| 54 | public static final int BAD_MECH = 2; | ||
| 55 | |||
| 56 | /** | ||
| 57 | * Invalid name provided. | ||
| 58 | */ | ||
| 59 | public static final int BAD_NAME = 3; | ||
| 60 | |||
| 61 | /** | ||
| 62 | * Name of unsupported type provided. | ||
| 63 | */ | ||
| 64 | public static final int BAD_NAMETYPE = 4; | ||
| 65 | |||
| 66 | /** | ||
| 67 | * Invalid status code. | ||
| 68 | */ | ||
| 69 | /* | ||
| 70 | * This is meant to be thrown by display_status which displays | ||
| 71 | * major/minor status when an incorrect status type is passed in to it! | ||
| 72 | */ | ||
| 73 | public static final int BAD_STATUS = 5; | ||
| 74 | |||
| 75 | /** | ||
| 76 | * Token had invalid integrity check. | ||
| 77 | */ | ||
| 78 | public static final int BAD_MIC = 6; | ||
| 79 | |||
| 80 | /** | ||
| 81 | * Security context expired. | ||
| 82 | */ | ||
| 83 | public static final int CONTEXT_EXPIRED = 7; | ||
| 84 | |||
| 85 | /** | ||
| 86 | * Expired credentials. | ||
| 87 | */ | ||
| 88 | public static final int CREDENTIALS_EXPIRED = 8; | ||
| 89 | |||
| 90 | /** | ||
| 91 | * Defective credentials. | ||
| 92 | * | ||
| 93 | */ | ||
| 94 | public static final int DEFECTIVE_CREDENTIAL = 9; | ||
| 95 | |||
| 96 | /** | ||
| 97 | * Defective token. | ||
| 98 | * | ||
| 99 | */ | ||
| 100 | public static final int DEFECTIVE_TOKEN = 10; | ||
| 101 | |||
| 102 | /** | ||
| 103 | * General failure, unspecified at GSS-API level. | ||
| 104 | */ | ||
| 105 | public static final int FAILURE = 11; | ||
| 106 | |||
| 107 | /** | ||
| 108 | * Invalid security context. | ||
| 109 | */ | ||
| 110 | public static final int NO_CONTEXT = 12; | ||
| 111 | |||
| 112 | /** | ||
| 113 | * Invalid credentials. | ||
| 114 | */ | ||
| 115 | public static final int NO_CRED = 13; | ||
| 116 | |||
| 117 | /** | ||
| 118 | * Unsupported QOP value. | ||
| 119 | */ | ||
| 120 | public static final int BAD_QOP = 14; | ||
| 121 | |||
| 122 | /** | ||
| 123 | * Operation unauthorized. | ||
| 124 | */ | ||
| 125 | public static final int UNAUTHORIZED = 15; | ||
| 126 | |||
| 127 | /** | ||
| 128 | * Operation unavailable. | ||
| 129 | */ | ||
| 130 | public static final int UNAVAILABLE = 16; | ||
| 131 | |||
| 132 | /** | ||
| 133 | * Duplicate credential element requested. | ||
| 134 | */ | ||
| 135 | public static final int DUPLICATE_ELEMENT = 17; | ||
| 136 | |||
| 137 | /** | ||
| 138 | * Name contains multi-mechanism elements. | ||
| 139 | */ | ||
| 140 | public static final int NAME_NOT_MN = 18; | ||
| 141 | |||
| 142 | /** | ||
| 143 | * The token was a duplicate of an earlier token. | ||
| 144 | * This is a fatal error code that may occur during | ||
| 145 | * context establishment. It is not used to indicate | ||
| 146 | * supplementary status values. The MessageProp object is | ||
| 147 | * used for that purpose. | ||
| 148 | */ | ||
| 149 | public static final int DUPLICATE_TOKEN = 19; | ||
| 150 | |||
| 151 | /** | ||
| 152 | * The token's validity period has expired. This is a | ||
| 153 | * fatal error code that may occur during context establishment. | ||
| 154 | * It is not used to indicate supplementary status values. | ||
| 155 | * The MessageProp object is used for that purpose. | ||
| 156 | */ | ||
| 157 | public static final int OLD_TOKEN = 20; | ||
| 158 | |||
| 159 | |||
| 160 | /** | ||
| 161 | * A later token has already been processed. This is a | ||
| 162 | * fatal error code that may occur during context establishment. | ||
| 163 | * It is not used to indicate supplementary status values. | ||
| 164 | * The MessageProp object is used for that purpose. | ||
| 165 | */ | ||
| 166 | public static final int UNSEQ_TOKEN = 21; | ||
| 167 | |||
| 168 | |||
| 169 | /** | ||
| 170 | * An expected per-message token was not received. This is a | ||
| 171 | * fatal error code that may occur during context establishment. | ||
| 172 | * It is not used to indicate supplementary status values. | ||
| 173 | * The MessageProp object is used for that purpose. | ||
| 174 | */ | ||
| 175 | public static final int GAP_TOKEN = 22; | ||
| 176 | |||
| 177 | |||
| 178 | private static String[] messages = { | ||
| 179 | "Channel binding mismatch", // BAD_BINDINGS | ||
| 180 | "Unsupported mechanism requested", // BAD_MECH | ||
| 181 | "Invalid name provided", // BAD_NAME | ||
| 182 | "Name of unsupported type provided", //BAD_NAMETYPE | ||
| 183 | "Invalid input status selector", // BAD_STATUS | ||
| 184 | "Token had invalid integrity check", // BAD_SIG | ||
| 185 | "Specified security context expired", // CONTEXT_EXPIRED | ||
| 186 | "Expired credentials detected", // CREDENTIALS_EXPIRED | ||
| 187 | "Defective credential detected", // DEFECTIVE_CREDENTIAL | ||
| 188 | "Defective token detected", // DEFECTIVE_TOKEN | ||
| 189 | "Failure unspecified at GSS-API level", // FAILURE | ||
| 190 | "Security context init/accept not yet called or context deleted", | ||
| 191 | // NO_CONTEXT | ||
| 192 | "No valid credentials provided", // NO_CRED | ||
| 193 | "Unsupported QOP value", // BAD_QOP | ||
| 194 | "Operation unauthorized", // UNAUTHORIZED | ||
| 195 | "Operation unavailable", // UNAVAILABLE | ||
| 196 | "Duplicate credential element requested", //DUPLICATE_ELEMENT | ||
| 197 | "Name contains multi-mechanism elements", // NAME_NOT_MN | ||
| 198 | "The token was a duplicate of an earlier token", //DUPLICATE_TOKEN | ||
| 199 | "The token's validity period has expired", //OLD_TOKEN | ||
| 200 | "A later token has already been processed", //UNSEQ_TOKEN | ||
| 201 | "An expected per-message token was not received", //GAP_TOKEN | ||
| 202 | }; | ||
| 203 | |||
| 204 | /** | ||
| 205 | * The major code for this exception | ||
| 206 | * | ||
| 207 | * @serial | ||
| 208 | */ | ||
| 209 | private int major; | ||
| 210 | |||
| 211 | /** | ||
| 212 | * The minor code for this exception | ||
| 213 | * | ||
| 214 | * @serial | ||
| 215 | */ | ||
| 216 | private int minor = 0; | ||
| 217 | |||
| 218 | /** | ||
| 219 | * The text string for minor code | ||
| 220 | * | ||
| 221 | * @serial | ||
| 222 | */ | ||
| 223 | private String minorMessage = null; | ||
| 224 | |||
| 225 | /** | ||
| 226 | * Alternate text string for major code | ||
| 227 | * | ||
| 228 | * @serial | ||
| 229 | */ | ||
| 230 | |||
| 231 | private String majorString = null; | ||
| 232 | |||
| 233 | /** | ||
| 234 | * Creates a GSSException object with a specified major code. | ||
| 235 | * | ||
| 236 | * @param majorCode the The GSS error code for the problem causing this | ||
| 237 | * exception to be thrown. | ||
| 238 | */ | ||
| 239 | public GSSException (int majorCode) { | ||
| 240 | |||
| 241 | if (validateMajor(majorCode)) | ||
| 242 | major = majorCode; | ||
| 243 | else | ||
| 244 | major = FAILURE; | ||
| 245 | } | ||
| 246 | |||
| 247 | /** | ||
| 248 | * Construct a GSSException object with a specified major code and a | ||
| 249 | * specific major string for it. | ||
| 250 | * | ||
| 251 | * @param majorCode the fatal error code causing this exception. | ||
| 252 | * @param majorString an expicit message to be included in this exception | ||
| 253 | */ | ||
| 254 | GSSException (int majorCode, String majorString) { | ||
| 255 | |||
| 256 | if (validateMajor(majorCode)) | ||
| 257 | major = majorCode; | ||
| 258 | else | ||
| 259 | major = FAILURE; | ||
| 260 | this.majorString = majorString; | ||
| 261 | } | ||
| 262 | |||
| 263 | |||
| 264 | /** | ||
| 265 | * Creates a GSSException object with the specified major code, minor | ||
| 266 | * code, and minor code textual explanation. This constructor is to be | ||
| 267 | * used when the exception is originating from the underlying mechanism | ||
| 268 | * level. It allows the setting of both the GSS code and the mechanism | ||
| 269 | * code. | ||
| 270 | * | ||
| 271 | * @param majorCode the GSS error code for the problem causing this | ||
| 272 | * exception to be thrown. | ||
| 273 | * @param minorCode the mechanism level error code for the problem | ||
| 274 | * causing this exception to be thrown. | ||
| 275 | * @param minorString the textual explanation of the mechanism error | ||
| 276 | * code. | ||
| 277 | */ | ||
| 278 | public GSSException (int majorCode, int minorCode, String minorString) { | ||
| 279 | |||
| 280 | if (validateMajor(majorCode)) | ||
| 281 | major = majorCode; | ||
| 282 | else | ||
| 283 | major = FAILURE; | ||
| 284 | |||
| 285 | minor = minorCode; | ||
| 286 | minorMessage = minorString; | ||
| 287 | } | ||
| 288 | |||
| 289 | /** | ||
| 290 | * Returns the GSS-API level major error code for the problem causing | ||
| 291 | * this exception to be thrown. Major error codes are | ||
| 292 | * defined at the mechanism independent GSS-API level in this | ||
| 293 | * class. Mechanism specific error codes that might provide more | ||
| 294 | * information aer set as the minor error code. | ||
| 295 | * | ||
| 296 | * @return int the GSS-API level major error code causing this exception | ||
| 297 | * @see #getMajorString | ||
| 298 | * @see #getMinor | ||
| 299 | * @see #getMinorString | ||
| 300 | */ | ||
| 301 | public int getMajor() { | ||
| 302 | return major; | ||
| 303 | } | ||
| 304 | |||
| 305 | /** | ||
| 306 | * Returns the mechanism level error code for the problem causing this | ||
| 307 | * exception to be thrown. The minor code is set by the underlying | ||
| 308 | * mechanism. | ||
| 309 | * | ||
| 310 | * @return int the mechanism error code; 0 indicates that it has not | ||
| 311 | * been set. | ||
| 312 | * @see #getMinorString | ||
| 313 | * @see #setMinor | ||
| 314 | */ | ||
| 315 | public int getMinor(){ | ||
| 316 | return minor; | ||
| 317 | } | ||
| 318 | |||
| 319 | /** | ||
| 320 | * Returns a string explaining the GSS-API level major error code in | ||
| 321 | * this exception. | ||
| 322 | * | ||
| 323 | * @return String explanation string for the major error code | ||
| 324 | * @see #getMajor | ||
| 325 | * @see #toString | ||
| 326 | */ | ||
| 327 | public String getMajorString() { | ||
| 328 | |||
| 329 | if (majorString != null) | ||
| 330 | return majorString; | ||
| 331 | else | ||
| 332 | return messages[major - 1]; | ||
| 333 | } | ||
| 334 | |||
| 335 | |||
| 336 | /** | ||
| 337 | * Returns a string explaining the mechanism specific error code. | ||
| 338 | * If the minor status code is 0, then no mechanism level error details | ||
| 339 | * will be available. | ||
| 340 | * | ||
| 341 | * @return String a textual explanation of mechanism error code | ||
| 342 | * @see #getMinor | ||
| 343 | * @see #getMajorString | ||
| 344 | * @see #toString | ||
| 345 | */ | ||
| 346 | public String getMinorString() { | ||
| 347 | |||
| 348 | return minorMessage; | ||
| 349 | } | ||
| 350 | |||
| 351 | |||
| 352 | /** | ||
| 353 | * Used by the exception thrower to set the mechanism | ||
| 354 | * level minor error code and its string explanation. This is used by | ||
| 355 | * mechanism providers to indicate error details. | ||
| 356 | * | ||
| 357 | * @param minorCode the mechanism specific error code | ||
| 358 | * @param message textual explanation of the mechanism error code | ||
| 359 | * @see #getMinor | ||
| 360 | */ | ||
| 361 | public void setMinor(int minorCode, String message) { | ||
| 362 | |||
| 363 | minor = minorCode; | ||
| 364 | minorMessage = message; | ||
| 365 | } | ||
| 366 | |||
| 367 | |||
| 368 | /** | ||
| 369 | * Returns a textual representation of both the major and the minor | ||
| 370 | * status codes. | ||
| 371 | * | ||
| 372 | * @return a String with the error descriptions | ||
| 373 | */ | ||
| 374 | public String toString() { | ||
| 375 | return ("GSSException: " + getMessage()); | ||
| 376 | } | ||
| 377 | |||
| 378 | /** | ||
| 379 | * Returns a textual representation of both the major and the minor | ||
| 380 | * status codes. | ||
| 381 | * | ||
| 382 | * @return a String with the error descriptions | ||
| 383 | */ | ||
| 384 | public String getMessage() { | ||
| 385 | if (minor == 0) | ||
| 386 | return (getMajorString()); | ||
| 387 | |||
| 388 | return (getMajorString() | ||
| 389 | + " (Mechanism level: " + getMinorString() + ")"); | ||
| 390 | } | ||
| 391 | |||
| 392 | |||
| 393 | /* | ||
| 394 | * Validates the major code in the proper range. | ||
| 395 | */ | ||
| 396 | private boolean validateMajor(int major) { | ||
| 397 | |||
| 398 | if (major > 0 && major <= messages.length) | ||
| 399 | return (true); | ||
| 400 | |||
| 401 | return (false); | ||
| 402 | } | ||
| 403 | } | ||
Binary file not shown.
| @@ -0,0 +1,729 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. | ||
| 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | ||
| 4 | * | ||
| 5 | * This code is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms of the GNU General Public License version 2 only, as | ||
| 7 | * published by the Free Software Foundation. Oracle designates this | ||
| 8 | * particular file as subject to the "Classpath" exception as provided | ||
| 9 | * by Oracle in the LICENSE file that accompanied this code. | ||
| 10 | * | ||
| 11 | * This code is distributed in the hope that it will be useful, but WITHOUT | ||
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
| 14 | * version 2 for more details (a copy is included in the LICENSE file that | ||
| 15 | * accompanied this code). | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License version | ||
| 18 | * 2 along with this work; if not, write to the Free Software Foundation, | ||
| 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 20 | * | ||
| 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | ||
| 22 | * or visit www.oracle.com if you need additional information or have any | ||
| 23 | * questions. | ||
| 24 | */ | ||
| 25 | |||
| 26 | package org.ietf.jgss; | ||
| 27 | |||
| 28 | import java.security.Provider; | ||
| 29 | |||
| 30 | /** | ||
| 31 | * This class serves as a factory for other important | ||
| 32 | * GSS-API classes and also provides information about the mechanisms that | ||
| 33 | * are supported. It can create instances of classes | ||
| 34 | * implementing the following three GSS-API interfaces: {@link | ||
| 35 | * GSSName GSSName}, {@link GSSCredential GSSCredential}, and {@link | ||
| 36 | * GSSContext GSSContext}. It also has methods to query for the list | ||
| 37 | * of available mechanisms and the nametypes that each mechanism | ||
| 38 | * supports.<p> | ||
| 39 | * | ||
| 40 | * An instance of the default <code>GSSManager</code> subclass | ||
| 41 | * may be obtained through the static method {@link #getInstance() | ||
| 42 | * getInstance}, but applications are free to instantiate other subclasses | ||
| 43 | * of <code>GSSManager</code>. The default <code>GSSManager</code> instance | ||
| 44 | * will support the Kerberos v5 GSS-API mechanism in addition to any | ||
| 45 | * others. This mechanism is identified by the Oid "1.2.840.113554.1.2.2" | ||
| 46 | * and is defined in RFC 1964.<p> | ||
| 47 | * | ||
| 48 | * A subclass extending the <code>GSSManager</code> abstract class may be | ||
| 49 | * implemented as a modular provider based layer that utilizes some well | ||
| 50 | * known service provider specification. The <code>GSSManager</code> API | ||
| 51 | * allows the application to set provider preferences on | ||
| 52 | * such an implementation. These methods also allow the implementation to | ||
| 53 | * throw a well-defined exception in case provider based configuration is | ||
| 54 | * not supported. Applications that expect to be portable should be aware | ||
| 55 | * of this and recover cleanly by catching the exception.<p> | ||
| 56 | * | ||
| 57 | * It is envisioned that there will be three most common ways in which | ||
| 58 | * providers will be used:<p> | ||
| 59 | * <ol> | ||
| 60 | * <li> The application does not care about what provider is used (the | ||
| 61 | * default case). | ||
| 62 | * <li> The application wants a particular provider to be used | ||
| 63 | * preferentially, either for a particular mechanism or all the | ||
| 64 | * time, irrespective of mechanism. | ||
| 65 | * <li> The application wants to use the locally configured providers | ||
| 66 | * as far as possible but if support is missing for one or more | ||
| 67 | * mechanisms then it wants to fall back on its own provider. | ||
| 68 | *</ol><p> | ||
| 69 | * | ||
| 70 | * The <code>GSSManager</code> class has two methods that enable these modes of | ||
| 71 | * usage: {@link #addProviderAtFront(Provider, Oid) addProviderAtFront} and | ||
| 72 | * {@link #addProviderAtEnd(Provider, Oid) addProviderAtEnd}. These methods | ||
| 73 | * have the effect of creating an ordered list of <i><provider, | ||
| 74 | * oid></i> pairs where each pair indicates a preference of provider | ||
| 75 | * for a given oid.<p> | ||
| 76 | * | ||
| 77 | * It is important to note that there are certain interactions | ||
| 78 | * between the different GSS-API objects that are created by a | ||
| 79 | * GSSManager, where the provider that is used for a particular mechanism | ||
| 80 | * might need to be consistent across all objects. For instance, if a | ||
| 81 | * GSSCredential contains elements from a provider <i>p</i> for a mechanism | ||
| 82 | * <i>m</i>, it should generally be passed in to a GSSContext that will use | ||
| 83 | * provider <i>p</i> for the mechanism <i>m</i>. A simple rule of thumb | ||
| 84 | * that will maximize portability is that objects created from different | ||
| 85 | * GSSManager's should not be mixed, and if possible, a different | ||
| 86 | * GSSManager instance should be created if the application wants to invoke | ||
| 87 | * the <code>addProviderAtFront</code> method on a GSSManager that has | ||
| 88 | * already created an object.<p> | ||
| 89 | * | ||
| 90 | * Here is some sample code showing how the GSSManager might be used: <p> | ||
| 91 | * <pre> | ||
| 92 | * GSSManager manager = GSSManager.getInstance(); | ||
| 93 | * | ||
| 94 | * Oid krb5Mechanism = new Oid("1.2.840.113554.1.2.2"); | ||
| 95 | * Oid krb5PrincipalNameType = new Oid("1.2.840.113554.1.2.2.1"); | ||
| 96 | * | ||
| 97 | * // Identify who the client wishes to be | ||
| 98 | * GSSName userName = manager.createName("duke", GSSName.NT_USER_NAME); | ||
| 99 | * | ||
| 100 | * // Identify the name of the server. This uses a Kerberos specific | ||
| 101 | * // name format. | ||
| 102 | * GSSName serverName = manager.createName("nfs/foo.sun.com", | ||
| 103 | * krb5PrincipalNameType); | ||
| 104 | * | ||
| 105 | * // Acquire credentials for the user | ||
| 106 | * GSSCredential userCreds = manager.createCredential(userName, | ||
| 107 | * GSSCredential.DEFAULT_LIFETIME, | ||
| 108 | * krb5Mechanism, | ||
| 109 | * GSSCredential.INITIATE_ONLY); | ||
| 110 | * | ||
| 111 | * // Instantiate and initialize a security context that will be | ||
| 112 | * // established with the server | ||
| 113 | * GSSContext context = manager.createContext(serverName, | ||
| 114 | * krb5Mechanism, | ||
| 115 | * userCreds, | ||
| 116 | * GSSContext.DEFAULT_LIFETIME); | ||
| 117 | * </pre><p> | ||
| 118 | * | ||
| 119 | * The server side might use the following variation of this source:<p> | ||
| 120 | * | ||
| 121 | * <pre> | ||
| 122 | * // Acquire credentials for the server | ||
| 123 | * GSSCredential serverCreds = manager.createCredential(serverName, | ||
| 124 | * GSSCredential.DEFAULT_LIFETIME, | ||
| 125 | * krb5Mechanism, | ||
| 126 | * GSSCredential.ACCEPT_ONLY); | ||
| 127 | * | ||
| 128 | * // Instantiate and initialize a security context that will | ||
| 129 | * // wait for an establishment request token from the client | ||
| 130 | * GSSContext context = manager.createContext(serverCreds); | ||
| 131 | * </pre> | ||
| 132 | * | ||
| 133 | * @author Mayank Upadhyay | ||
| 134 | * @see GSSName | ||
| 135 | * @see GSSCredential | ||
| 136 | * @see GSSContext | ||
| 137 | * @since 1.4 | ||
| 138 | */ | ||
| 139 | public abstract class GSSManager { | ||
| 140 | |||
| 141 | /** | ||
| 142 | * Returns the default GSSManager implementation. | ||
| 143 | * | ||
| 144 | * @return a GSSManager implementation | ||
| 145 | */ | ||
| 146 | public static GSSManager getInstance() { | ||
| 147 | return new sun.security.jgss.GSSManagerImpl(); | ||
| 148 | } | ||
| 149 | |||
| 150 | /** | ||
| 151 | * Returns a list of mechanisms that are available to GSS-API callers | ||
| 152 | * through this GSSManager. The default GSSManager obtained from the | ||
| 153 | * {@link #getInstance() getInstance()} method includes the Oid | ||
| 154 | * "1.2.840.113554.1.2.2" in its list. This Oid identifies the Kerberos | ||
| 155 | * v5 GSS-API mechanism that is defined in RFC 1964. | ||
| 156 | * | ||
| 157 | * @return an array of Oid objects corresponding to the mechanisms that | ||
| 158 | * are available. A <code>null</code> value is returned when no | ||
| 159 | * mechanism are available (an example of this would be when mechanism | ||
| 160 | * are dynamically configured, and currently no mechanisms are | ||
| 161 | * installed). | ||
| 162 | */ | ||
| 163 | public abstract Oid[] getMechs(); | ||
| 164 | |||
| 165 | /** | ||
| 166 | * Returns then name types supported by the indicated mechanism.<p> | ||
| 167 | * | ||
| 168 | * The default GSSManager instance includes support for the Kerberos v5 | ||
| 169 | * mechanism. When this mechanism ("1.2.840.113554.1.2.2") is indicated, | ||
| 170 | * the returned list will contain at least the following nametypes: | ||
| 171 | * {@link GSSName#NT_HOSTBASED_SERVICE GSSName.NT_HOSTBASED_SERVICE}, | ||
| 172 | * {@link GSSName#NT_EXPORT_NAME GSSName.NT_EXPORT_NAME}, and the | ||
| 173 | * Kerberos v5 specific Oid "1.2.840.113554.1.2.2.1". The namespace for | ||
| 174 | * the Oid "1.2.840.113554.1.2.2.1" is defined in RFC 1964. | ||
| 175 | * | ||
| 176 | * @return an array of Oid objects corresponding to the name types that | ||
| 177 | * the mechanism supports. | ||
| 178 | * @param mech the Oid of the mechanism to query | ||
| 179 | * | ||
| 180 | * @see #getMechsForName(Oid) | ||
| 181 | * | ||
| 182 | * @throws GSSException containing the following | ||
| 183 | * major error codes: | ||
| 184 | * {@link GSSException#BAD_MECH GSSException.BAD_MECH} | ||
| 185 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 186 | */ | ||
| 187 | public abstract Oid[] getNamesForMech(Oid mech) | ||
| 188 | throws GSSException; | ||
| 189 | |||
| 190 | /** | ||
| 191 | * Returns a list of mechanisms that support the indicated name type.<p> | ||
| 192 | * | ||
| 193 | * The Kerberos v5 mechanism ("1.2.840.113554.1.2.2") will always be | ||
| 194 | * returned in this list when the indicated nametype is one of | ||
| 195 | * {@link GSSName#NT_HOSTBASED_SERVICE GSSName.NT_HOSTBASED_SERVICE}, | ||
| 196 | * {@link GSSName#NT_EXPORT_NAME GSSName.NT_EXPORT_NAME}, or | ||
| 197 | * "1.2.840.113554.1.2.2.1". | ||
| 198 | * | ||
| 199 | * @return an array of Oid objects corresponding to the mechanisms that | ||
| 200 | * support the specified name type. <code>null</code> is returned when no | ||
| 201 | * mechanisms are found to support the specified name type. | ||
| 202 | * @param nameType the Oid of the name type to look for | ||
| 203 | * | ||
| 204 | * @see #getNamesForMech(Oid) | ||
| 205 | */ | ||
| 206 | public abstract Oid[] getMechsForName(Oid nameType); | ||
| 207 | |||
| 208 | /** | ||
| 209 | * Factory method to convert a string name from the | ||
| 210 | * specified namespace to a GSSName object. In general, the | ||
| 211 | * <code>GSSName</code> object created will contain multiple | ||
| 212 | * representations of the name, one for each mechanism that is | ||
| 213 | * supported; two examples that are exceptions to this are when | ||
| 214 | * the namespace type parameter indicates NT_EXPORT_NAME or when the | ||
| 215 | * GSS-API implementation is not multi-mechanism. It is | ||
| 216 | * not recommended to use this method with a NT_EXPORT_NAME type because | ||
| 217 | * representing a previously exported name consisting of abitrary bytes | ||
| 218 | * as a String might cause problems with character encoding schemes. In | ||
| 219 | * such cases it is recommended that the bytes be passed in directly to | ||
| 220 | * the overloaded form of this method {@link #createName(byte[], | ||
| 221 | * Oid) createName}. | ||
| 222 | * | ||
| 223 | * @param nameStr the string representing a printable form of the name to | ||
| 224 | * create. | ||
| 225 | * @param nameType the Oid specifying the namespace of the printable name | ||
| 226 | * supplied. <code>null</code> can be used to specify | ||
| 227 | * that a mechanism specific default printable syntax should | ||
| 228 | * be assumed by each mechanism that examines nameStr. | ||
| 229 | * It is not advisable to use the nametype NT_EXPORT_NAME with this | ||
| 230 | * method. | ||
| 231 | * @return a GSSName representing the indicated principal | ||
| 232 | * | ||
| 233 | * @see GSSName | ||
| 234 | * @see GSSName#NT_EXPORT_NAME | ||
| 235 | * | ||
| 236 | * @throws GSSException containing the following | ||
| 237 | * major error codes: | ||
| 238 | * {@link GSSException#BAD_NAMETYPE GSSException.BAD_NAMETYPE}, | ||
| 239 | * {@link GSSException#BAD_NAME GSSException.BAD_NAME}, | ||
| 240 | * {@link GSSException#BAD_MECH GSSException.BAD_MECH}, | ||
| 241 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 242 | */ | ||
| 243 | public abstract GSSName createName(String nameStr, Oid nameType) | ||
| 244 | throws GSSException; | ||
| 245 | |||
| 246 | /** | ||
| 247 | * Factory method to convert a byte array containing a | ||
| 248 | * name from the specified namespace to a GSSName object. In general, | ||
| 249 | * the <code>GSSName</code> object created will contain multiple | ||
| 250 | * representations of the name, one for each mechanism that is | ||
| 251 | * supported; two examples that are exceptions to this are when the | ||
| 252 | * namespace type parameter indicates NT_EXPORT_NAME or when the | ||
| 253 | * GSS-API implementation is not multi-mechanism. The bytes that are | ||
| 254 | * passed in are interpreted by each underlying mechanism according to | ||
| 255 | * some encoding scheme of its choice for the given nametype. | ||
| 256 | * | ||
| 257 | * @param name the byte array containing the name to create | ||
| 258 | * @param nameType the Oid specifying the namespace of the name supplied | ||
| 259 | * in the byte array. <code>null</code> can be used to specify that a | ||
| 260 | * mechanism specific default syntax should be assumed by each mechanism | ||
| 261 | * that examines the byte array. | ||
| 262 | * @return a GSSName representing the indicated principal | ||
| 263 | * | ||
| 264 | * @see GSSName | ||
| 265 | * @see GSSName#NT_EXPORT_NAME | ||
| 266 | * | ||
| 267 | * @throws GSSException containing the following | ||
| 268 | * major error codes: | ||
| 269 | * {@link GSSException#BAD_NAMETYPE GSSException.BAD_NAMETYPE}, | ||
| 270 | * {@link GSSException#BAD_NAME GSSException.BAD_NAME}, | ||
| 271 | * {@link GSSException#BAD_MECH GSSException.BAD_MECH}, | ||
| 272 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 273 | */ | ||
| 274 | public abstract GSSName createName(byte name[], Oid nameType) | ||
| 275 | throws GSSException; | ||
| 276 | |||
| 277 | /** | ||
| 278 | * Factory method to convert a string name from the | ||
| 279 | * specified namespace to a GSSName object and canonicalize it at the | ||
| 280 | * same time for a mechanism. In other words, this method is | ||
| 281 | * a utility that does the equivalent of two steps: the {@link | ||
| 282 | * #createName(String, Oid) createName} and then also the {@link | ||
| 283 | * GSSName#canonicalize(Oid) GSSName.canonicalize}. | ||
| 284 | * | ||
| 285 | * @param nameStr the string representing a printable form of the name to | ||
| 286 | * create. | ||
| 287 | * @param nameType the Oid specifying the namespace of the printable name | ||
| 288 | * supplied. <code>null</code> can be used to specify | ||
| 289 | * that a mechanism specific default printable syntax should | ||
| 290 | * be assumed by each mechanism that examines nameStr. | ||
| 291 | * It is not advisable to use the nametype NT_EXPORT_NAME with this | ||
| 292 | * method. | ||
| 293 | * @param mech Oid specifying the mechanism for which the name should be | ||
| 294 | * canonicalized | ||
| 295 | * @return a GSSName representing the indicated principal | ||
| 296 | * | ||
| 297 | * @see GSSName#canonicalize(Oid) | ||
| 298 | * @see GSSName#NT_EXPORT_NAME | ||
| 299 | * | ||
| 300 | * @throws GSSException containing the following | ||
| 301 | * major error codes: | ||
| 302 | * {@link GSSException#BAD_NAMETYPE GSSException.BAD_NAMETYPE}, | ||
| 303 | * {@link GSSException#BAD_NAME GSSException.BAD_NAME}, | ||
| 304 | * {@link GSSException#BAD_MECH GSSException.BAD_MECH}, | ||
| 305 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 306 | */ | ||
| 307 | public abstract GSSName createName(String nameStr, Oid nameType, | ||
| 308 | Oid mech) throws GSSException; | ||
| 309 | |||
| 310 | /** | ||
| 311 | * Factory method to convert a byte array containing a | ||
| 312 | * name from the specified namespace to a GSSName object and canonicalize | ||
| 313 | * it at the same time for a mechanism. In other words, this method is a | ||
| 314 | * utility that does the equivalent of two steps: the {@link | ||
| 315 | * #createName(byte[], Oid) createName} and then also {@link | ||
| 316 | * GSSName#canonicalize(Oid) GSSName.canonicalize}. | ||
| 317 | * | ||
| 318 | * @param name the byte array containing the name to create | ||
| 319 | * @param nameType the Oid specifying the namespace of the name supplied | ||
| 320 | * in the byte array. <code>null</code> can be used to specify that a | ||
| 321 | * mechanism specific default syntax should be assumed by each mechanism | ||
| 322 | * that examines the byte array. | ||
| 323 | * @param mech Oid specifying the mechanism for which the name should be | ||
| 324 | * canonicalized | ||
| 325 | * @return a GSSName representing the indicated principal | ||
| 326 | * | ||
| 327 | * @see GSSName#canonicalize(Oid) | ||
| 328 | * @see GSSName#NT_EXPORT_NAME | ||
| 329 | * | ||
| 330 | * @throws GSSException containing the following | ||
| 331 | * major error codes: | ||
| 332 | * {@link GSSException#BAD_NAMETYPE GSSException.BAD_NAMETYPE}, | ||
| 333 | * {@link GSSException#BAD_NAME GSSException.BAD_NAME}, | ||
| 334 | * {@link GSSException#BAD_MECH GSSException.BAD_MECH}, | ||
| 335 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 336 | */ | ||
| 337 | public abstract GSSName createName(byte name[], Oid nameType, Oid mech) | ||
| 338 | throws GSSException; | ||
| 339 | |||
| 340 | /** | ||
| 341 | * Factory method for acquiring default credentials. This will cause | ||
| 342 | * the GSS-API to use system specific defaults for the set of mechanisms, | ||
| 343 | * name, and lifetime.<p> | ||
| 344 | * | ||
| 345 | * GSS-API mechanism providers must impose a local access-control | ||
| 346 | * policy on callers to prevent unauthorized callers from acquiring | ||
| 347 | * credentials to which they are not entitled. The kinds of permissions | ||
| 348 | * needed by different mechanism providers will be documented on a | ||
| 349 | * per-mechanism basis. A failed permission check might cause a {@link | ||
| 350 | * java.lang.SecurityException SecurityException} to be thrown from | ||
| 351 | * this method. | ||
| 352 | * | ||
| 353 | * @param usage The intended usage for this credential object. The value | ||
| 354 | * of this parameter must be one of: | ||
| 355 | * {@link GSSCredential#INITIATE_AND_ACCEPT | ||
| 356 | * GSSCredential.INITIATE_AND_ACCEPT}, | ||
| 357 | * {@link GSSCredential#ACCEPT_ONLY GSSCredential.ACCEPT_ONLY}, and | ||
| 358 | * {@link GSSCredential#INITIATE_ONLY GSSCredential.INITIATE_ONLY}. | ||
| 359 | * @return a GSSCredential of the requested type. | ||
| 360 | * | ||
| 361 | * @see GSSCredential | ||
| 362 | * | ||
| 363 | * @throws GSSException containing the following | ||
| 364 | * major error codes: | ||
| 365 | * {@link GSSException#BAD_MECH GSSException.BAD_MECH}, | ||
| 366 | * {@link GSSException#BAD_NAMETYPE GSSException.BAD_NAMETYPE}, | ||
| 367 | * {@link GSSException#BAD_NAME GSSException.BAD_NAME}, | ||
| 368 | * {@link GSSException#CREDENTIALS_EXPIRED | ||
| 369 | * GSSException.CREDENTIALS_EXPIRED}, | ||
| 370 | * {@link GSSException#NO_CRED GSSException.NO_CRED}, | ||
| 371 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 372 | */ | ||
| 373 | public abstract GSSCredential createCredential (int usage) | ||
| 374 | throws GSSException; | ||
| 375 | |||
| 376 | /** | ||
| 377 | * Factory method for acquiring a single mechanism credential.<p> | ||
| 378 | * | ||
| 379 | * GSS-API mechanism providers must impose a local access-control | ||
| 380 | * policy on callers to prevent unauthorized callers from acquiring | ||
| 381 | * credentials to which they are not entitled. The kinds of permissions | ||
| 382 | * needed by different mechanism providers will be documented on a | ||
| 383 | * per-mechanism basis. A failed permission check might cause a {@link | ||
| 384 | * java.lang.SecurityException SecurityException} to be thrown from | ||
| 385 | * this method. <p> | ||
| 386 | * | ||
| 387 | * Non-default values for lifetime cannot always be honored by the | ||
| 388 | * underlying mechanisms, thus applications should be prepared to call | ||
| 389 | * {@link GSSCredential#getRemainingLifetime() getRemainingLifetime} | ||
| 390 | * on the returned credential.<p> | ||
| 391 | * | ||
| 392 | * @param name the name of the principal for whom this credential is to be | ||
| 393 | * acquired. Use <code>null</code> to specify the default principal. | ||
| 394 | * @param lifetime The number of seconds that credentials should remain | ||
| 395 | * valid. Use {@link GSSCredential#INDEFINITE_LIFETIME | ||
| 396 | * GSSCredential.INDEFINITE_LIFETIME} to request that the credentials | ||
| 397 | * have the maximum permitted lifetime. Use {@link | ||
| 398 | * GSSCredential#DEFAULT_LIFETIME GSSCredential.DEFAULT_LIFETIME} to | ||
| 399 | * request default credential lifetime. | ||
| 400 | * @param mech the Oid of the desired mechanism. Use <code>(Oid) null | ||
| 401 | * </code> to request the default mechanism. | ||
| 402 | * @param usage The intended usage for this credential object. The value | ||
| 403 | * of this parameter must be one of: | ||
| 404 | * {@link GSSCredential#INITIATE_AND_ACCEPT | ||
| 405 | * GSSCredential.INITIATE_AND_ACCEPT}, | ||
| 406 | * {@link GSSCredential#ACCEPT_ONLY GSSCredential.ACCEPT_ONLY}, and | ||
| 407 | * {@link GSSCredential#INITIATE_ONLY GSSCredential.INITIATE_ONLY}. | ||
| 408 | * @return a GSSCredential of the requested type. | ||
| 409 | * | ||
| 410 | * @see GSSCredential | ||
| 411 | * | ||
| 412 | * @throws GSSException containing the following | ||
| 413 | * major error codes: | ||
| 414 | * {@link GSSException#BAD_MECH GSSException.BAD_MECH}, | ||
| 415 | * {@link GSSException#BAD_NAMETYPE GSSException.BAD_NAMETYPE}, | ||
| 416 | * {@link GSSException#BAD_NAME GSSException.BAD_NAME}, | ||
| 417 | * {@link GSSException#CREDENTIALS_EXPIRED | ||
| 418 | * GSSException.CREDENTIALS_EXPIRED}, | ||
| 419 | * {@link GSSException#NO_CRED GSSException.NO_CRED}, | ||
| 420 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 421 | */ | ||
| 422 | public abstract GSSCredential createCredential (GSSName name, | ||
| 423 | int lifetime, Oid mech, int usage) | ||
| 424 | throws GSSException; | ||
| 425 | |||
| 426 | /** | ||
| 427 | * Factory method for acquiring credentials over a set of | ||
| 428 | * mechanisms. This method attempts to acquire credentials for | ||
| 429 | * each of the mechanisms specified in the array called mechs. To | ||
| 430 | * determine the list of mechanisms for which the acquisition of | ||
| 431 | * credentials succeeded, the caller should use the {@link | ||
| 432 | * GSSCredential#getMechs() GSSCredential.getMechs} method.<p> | ||
| 433 | * | ||
| 434 | * GSS-API mechanism providers must impose a local access-control | ||
| 435 | * policy on callers to prevent unauthorized callers from acquiring | ||
| 436 | * credentials to which they are not entitled. The kinds of permissions | ||
| 437 | * needed by different mechanism providers will be documented on a | ||
| 438 | * per-mechanism basis. A failed permission check might cause a {@link | ||
| 439 | * java.lang.SecurityException SecurityException} to be thrown from | ||
| 440 | * this method.<p> | ||
| 441 | * | ||
| 442 | * Non-default values for lifetime cannot always be honored by the | ||
| 443 | * underlying mechanisms, thus applications should be prepared to call | ||
| 444 | * {@link GSSCredential#getRemainingLifetime() getRemainingLifetime} | ||
| 445 | * on the returned credential.<p> | ||
| 446 | * | ||
| 447 | * @param name the name of the principal for whom this credential is to | ||
| 448 | * be acquired. Use <code>null</code> to specify the default | ||
| 449 | * principal. | ||
| 450 | * @param lifetime The number of seconds that credentials should remain | ||
| 451 | * valid. Use {@link GSSCredential#INDEFINITE_LIFETIME | ||
| 452 | * GSSCredential.INDEFINITE_LIFETIME} to request that the credentials | ||
| 453 | * have the maximum permitted lifetime. Use {@link | ||
| 454 | * GSSCredential#DEFAULT_LIFETIME GSSCredential.DEFAULT_LIFETIME} to | ||
| 455 | * request default credential lifetime. | ||
| 456 | * @param mechs an array of Oid's indicating the mechanisms over which | ||
| 457 | * the credential is to be acquired. Use <code>(Oid[]) null</code> for | ||
| 458 | * requesting a system specific default set of mechanisms. | ||
| 459 | * @param usage The intended usage for this credential object. The value | ||
| 460 | * of this parameter must be one of: | ||
| 461 | * {@link GSSCredential#INITIATE_AND_ACCEPT | ||
| 462 | * GSSCredential.INITIATE_AND_ACCEPT}, | ||
| 463 | * {@link GSSCredential#ACCEPT_ONLY GSSCredential.ACCEPT_ONLY}, and | ||
| 464 | * {@link GSSCredential#INITIATE_ONLY GSSCredential.INITIATE_ONLY}. | ||
| 465 | * @return a GSSCredential of the requested type. | ||
| 466 | * | ||
| 467 | * @see GSSCredential | ||
| 468 | * | ||
| 469 | * @throws GSSException containing the following | ||
| 470 | * major error codes: | ||
| 471 | * {@link GSSException#BAD_MECH GSSException.BAD_MECH}, | ||
| 472 | * {@link GSSException#BAD_NAMETYPE GSSException.BAD_NAMETYPE}, | ||
| 473 | * {@link GSSException#BAD_NAME GSSException.BAD_NAME}, | ||
| 474 | * {@link GSSException#CREDENTIALS_EXPIRED | ||
| 475 | * GSSException.CREDENTIALS_EXPIRED}, | ||
| 476 | * {@link GSSException#NO_CRED GSSException.NO_CRED}, | ||
| 477 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 478 | */ | ||
| 479 | public abstract GSSCredential createCredential(GSSName name, | ||
| 480 | int lifetime, Oid mechs[], int usage) | ||
| 481 | throws GSSException; | ||
| 482 | |||
| 483 | /** | ||
| 484 | * Factory method for creating a context on the initiator's | ||
| 485 | * side. | ||
| 486 | * | ||
| 487 | * Some mechanism providers might require that the caller be granted | ||
| 488 | * permission to initiate a security context. A failed permission check | ||
| 489 | * might cause a {@link java.lang.SecurityException SecurityException} | ||
| 490 | * to be thrown from this method.<p> | ||
| 491 | * | ||
| 492 | * Non-default values for lifetime cannot always be honored by the | ||
| 493 | * underlying mechanism, thus applications should be prepared to call | ||
| 494 | * {@link GSSContext#getLifetime() getLifetime} on the returned | ||
| 495 | * context.<p> | ||
| 496 | * | ||
| 497 | * @param peer the name of the target peer. | ||
| 498 | * @param mech the Oid of the desired mechanism. Use <code>null</code> | ||
| 499 | * to request the default mechanism. | ||
| 500 | * @param myCred the credentials of the initiator. Use | ||
| 501 | * <code>null</code> to act as the default initiator principal. | ||
| 502 | * @param lifetime the lifetime, in seconds, requested for the | ||
| 503 | * context. Use {@link GSSContext#INDEFINITE_LIFETIME | ||
| 504 | * GSSContext.INDEFINITE_LIFETIME} to request that the context have the | ||
| 505 | * maximum permitted lifetime. Use {@link GSSContext#DEFAULT_LIFETIME | ||
| 506 | * GSSContext.DEFAULT_LIFETIME} to request a default lifetime for the | ||
| 507 | * context. | ||
| 508 | * @return an unestablished GSSContext | ||
| 509 | * | ||
| 510 | * @see GSSContext | ||
| 511 | * | ||
| 512 | * @throws GSSException containing the following | ||
| 513 | * major error codes: | ||
| 514 | * {@link GSSException#NO_CRED GSSException.NO_CRED} | ||
| 515 | * {@link GSSException#CREDENTIALS_EXPIRED | ||
| 516 | * GSSException.CREDENTIALS_EXPIRED} | ||
| 517 | * {@link GSSException#BAD_NAMETYPE GSSException.BAD_NAMETYPE} | ||
| 518 | * {@link GSSException#BAD_MECH GSSException.BAD_MECH} | ||
| 519 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 520 | */ | ||
| 521 | public abstract GSSContext createContext(GSSName peer, Oid mech, | ||
| 522 | GSSCredential myCred, int lifetime) | ||
| 523 | throws GSSException; | ||
| 524 | |||
| 525 | /** | ||
| 526 | * Factory method for creating a context on the acceptor' side. The | ||
| 527 | * context's properties will be determined from the input token supplied | ||
| 528 | * to the accept method. | ||
| 529 | * | ||
| 530 | * Some mechanism providers might require that the caller be granted | ||
| 531 | * permission to accept a security context. A failed permission check | ||
| 532 | * might cause a {@link java.lang.SecurityException SecurityException} | ||
| 533 | * to be thrown from this method. | ||
| 534 | * | ||
| 535 | * @param myCred the credentials for the acceptor. Use | ||
| 536 | * <code>null</code> to act as a default acceptor principal. | ||
| 537 | * @return an unestablished GSSContext | ||
| 538 | * | ||
| 539 | * @see GSSContext | ||
| 540 | * | ||
| 541 | * @throws GSSException containing the following | ||
| 542 | * major error codes: | ||
| 543 | * {@link GSSException#NO_CRED GSSException.NO_CRED} | ||
| 544 | * {@link GSSException#CREDENTIALS_EXPIRED | ||
| 545 | * GSSException.CREDENTIALS_EXPIRED} | ||
| 546 | * {@link GSSException#BAD_MECH GSSException.BAD_MECH} | ||
| 547 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 548 | */ | ||
| 549 | public abstract GSSContext createContext(GSSCredential myCred) | ||
| 550 | throws GSSException; | ||
| 551 | |||
| 552 | /** | ||
| 553 | * Factory method for creating a previously exported context. The | ||
| 554 | * context properties will be determined from the input token and | ||
| 555 | * cannot be modified through the set methods.<p> | ||
| 556 | * | ||
| 557 | * Implementations are not required to support the inter-process | ||
| 558 | * transfer of security contexts. Before exporting a context, calling | ||
| 559 | * the {@link GSSContext#isTransferable() GSSContext.isTransferable} | ||
| 560 | * will indicate if the context is transferable. Calling this method in | ||
| 561 | * an implementation that does not support it will result in a | ||
| 562 | * <code>GSSException</code> with the error | ||
| 563 | * code {@link GSSException#UNAVAILABLE GSSException.UNAVAILABLE}. | ||
| 564 | * | ||
| 565 | * Some mechanism providers might require that the caller be granted | ||
| 566 | * permission to initiate or accept a security context. A failed | ||
| 567 | * permission check might cause a {@link java.lang.SecurityException | ||
| 568 | * SecurityException} to be thrown from this method. | ||
| 569 | * | ||
| 570 | * @param interProcessToken the token previously emitted from the | ||
| 571 | * export method. | ||
| 572 | * @return the previously established GSSContext | ||
| 573 | * | ||
| 574 | * @see GSSContext | ||
| 575 | * | ||
| 576 | * @throws GSSException containing the following | ||
| 577 | * major error codes: | ||
| 578 | * {@link GSSException#NO_CONTEXT GSSException.NO_CONTEXT}, | ||
| 579 | * {@link GSSException#DEFECTIVE_TOKEN GSSException.DEFECTIVE_TOKEN}, | ||
| 580 | * {@link GSSException#UNAVAILABLE GSSException.UNAVAILABLE}, | ||
| 581 | * {@link GSSException#UNAUTHORIZED GSSException.UNAUTHORIZED}, | ||
| 582 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 583 | */ | ||
| 584 | public abstract GSSContext createContext(byte [] interProcessToken) | ||
| 585 | throws GSSException; | ||
| 586 | |||
| 587 | /** | ||
| 588 | * This method is used to indicate to the GSSManager that the | ||
| 589 | * application would like a particular provider to be used ahead of all | ||
| 590 | * others when support is desired for the given mechanism. When a value | ||
| 591 | * of null is used instead of an <code>Oid</code> for the mechanism, | ||
| 592 | * the GSSManager must use the indicated provider ahead of all others | ||
| 593 | * no matter what the mechanism is. Only when the indicated provider | ||
| 594 | * does not support the needed mechanism should the GSSManager move on | ||
| 595 | * to a different provider.<p> | ||
| 596 | * | ||
| 597 | * Calling this method repeatedly preserves the older settings but | ||
| 598 | * lowers them in preference thus forming an ordered list of provider | ||
| 599 | * and <code>Oid</code> pairs that grows at the top.<p> | ||
| 600 | * | ||
| 601 | * Calling addProviderAtFront with a null <code>Oid</code> will remove | ||
| 602 | * all previous preferences that were set for this provider in the | ||
| 603 | * GSSManager instance. Calling addProviderAtFront with a non-null | ||
| 604 | * <code>Oid</code> will remove any previous preference that was set | ||
| 605 | * using this mechanism and this provider together.<p> | ||
| 606 | * | ||
| 607 | * If the GSSManager implementation does not support an SPI with a | ||
| 608 | * pluggable provider architecture it should throw a GSSException with | ||
| 609 | * the status code GSSException.UNAVAILABLE to indicate that the | ||
| 610 | * operation is unavailable.<p> | ||
| 611 | * | ||
| 612 | * Suppose an application desired that the provider A always be checked | ||
| 613 | * first when any mechanism is needed, it would call:<p> | ||
| 614 | * <pre> | ||
| 615 | * GSSManager mgr = GSSManager.getInstance(); | ||
| 616 | * // mgr may at this point have its own pre-configured list | ||
| 617 | * // of provider preferences. The following will prepend to | ||
| 618 | * // any such list: | ||
| 619 | * | ||
| 620 | * mgr.addProviderAtFront(A, null); | ||
| 621 | * </pre> | ||
| 622 | * Now if it also desired that the mechanism of Oid m1 always be | ||
| 623 | * obtained from the provider B before the previously set A was checked, | ||
| 624 | * it would call:<p> | ||
| 625 | * <pre> | ||
| 626 | * mgr.addProviderAtFront(B, m1); | ||
| 627 | * </pre> | ||
| 628 | * The GSSManager would then first check with B if m1 was needed. In | ||
| 629 | * case B did not provide support for m1, the GSSManager would continue | ||
| 630 | * on to check with A. If any mechanism m2 is needed where m2 is | ||
| 631 | * different from m1 then the GSSManager would skip B and check with A | ||
| 632 | * directly.<p> | ||
| 633 | * | ||
| 634 | * Suppose at a later time the following call is made to the same | ||
| 635 | * GSSManager instance:<p> | ||
| 636 | * <pre> | ||
| 637 | * mgr.addProviderAtFront(B, null) | ||
| 638 | * </pre> | ||
| 639 | * then the previous setting with the pair (B, m1) is subsumed by this | ||
| 640 | * and should be removed. Effectively the list of preferences now | ||
| 641 | * becomes {(B, null), (A, null), | ||
| 642 | * ... //followed by the pre-configured list.<p> | ||
| 643 | * | ||
| 644 | * Please note, however, that the following call: | ||
| 645 | * <pre> | ||
| 646 | * mgr.addProviderAtFront(A, m3) | ||
| 647 | * </pre> | ||
| 648 | * does not subsume the previous setting of (A, null) and the list will | ||
| 649 | * effectively become {(A, m3), (B, null), (A, null), ...} | ||
| 650 | * | ||
| 651 | * @param p the provider instance that should be used whenever support | ||
| 652 | * is needed for mech. | ||
| 653 | * @param mech the mechanism for which the provider is being set | ||
| 654 | * | ||
| 655 | * @throws GSSException containing the following | ||
| 656 | * major error codes: | ||
| 657 | * {@link GSSException#UNAVAILABLE GSSException.UNAVAILABLE}, | ||
| 658 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 659 | */ | ||
| 660 | public abstract void addProviderAtFront(Provider p, Oid mech) | ||
| 661 | throws GSSException; | ||
| 662 | |||
| 663 | /** | ||
| 664 | * This method is used to indicate to the GSSManager that the | ||
| 665 | * application would like a particular provider to be used if no other | ||
| 666 | * provider can be found that supports the given mechanism. When a value | ||
| 667 | * of null is used instead of an Oid for the mechanism, the GSSManager | ||
| 668 | * must use the indicated provider for any mechanism.<p> | ||
| 669 | * | ||
| 670 | * Calling this method repeatedly preserves the older settings but | ||
| 671 | * raises them above newer ones in preference thus forming an ordered | ||
| 672 | * list of providers and Oid pairs that grows at the bottom. Thus the | ||
| 673 | * older provider settings will be utilized first before this one is.<p> | ||
| 674 | * | ||
| 675 | * If there are any previously existing preferences that conflict with | ||
| 676 | * the preference being set here, then the GSSManager should ignore this | ||
| 677 | * request.<p> | ||
| 678 | * | ||
| 679 | * If the GSSManager implementation does not support an SPI with a | ||
| 680 | * pluggable provider architecture it should throw a GSSException with | ||
| 681 | * the status code GSSException.UNAVAILABLE to indicate that the | ||
| 682 | * operation is unavailable.<p> | ||
| 683 | * | ||
| 684 | * Suppose an application desired that when a mechanism of Oid m1 is | ||
| 685 | * needed the system default providers always be checked first, and only | ||
| 686 | * when they do not support m1 should a provider A be checked. It would | ||
| 687 | * then make the call:<p> | ||
| 688 | * <pre> | ||
| 689 | * GSSManager mgr = GSSManager.getInstance(); | ||
| 690 | * mgr.addProviderAtEnd(A, m1); | ||
| 691 | * </pre> | ||
| 692 | * Now, if it also desired that for all mechanisms the provider B be | ||
| 693 | * checked after all configured providers have been checked, it would | ||
| 694 | * then call:<p> | ||
| 695 | * <pre> | ||
| 696 | * mgr.addProviderAtEnd(B, null); | ||
| 697 | * </pre> | ||
| 698 | * Effectively the list of preferences now becomes {..., (A, m1), (B, | ||
| 699 | * null)}.<p> | ||
| 700 | * | ||
| 701 | * Suppose at a later time the following call is made to the same | ||
| 702 | * GSSManager instance:<p> | ||
| 703 | * <pre> | ||
| 704 | * mgr.addProviderAtEnd(B, m2) | ||
| 705 | * </pre> | ||
| 706 | * then the previous setting with the pair (B, null) subsumes this and | ||
| 707 | * therefore this request should be ignored. The same would happen if a | ||
| 708 | * request is made for the already existing pairs of (A, m1) or (B, | ||
| 709 | * null).<p> | ||
| 710 | * | ||
| 711 | * Please note, however, that the following call:<p> | ||
| 712 | * <pre> | ||
| 713 | * mgr.addProviderAtEnd(A, null) | ||
| 714 | * </pre> | ||
| 715 | * is not subsumed by the previous setting of (A, m1) and the list will | ||
| 716 | * effectively become {..., (A, m1), (B, null), (A, null)} | ||
| 717 | * | ||
| 718 | * @param p the provider instance that should be used whenever support | ||
| 719 | * is needed for mech. | ||
| 720 | * @param mech the mechanism for which the provider is being set | ||
| 721 | * | ||
| 722 | * @throws GSSException containing the following | ||
| 723 | * major error codes: | ||
| 724 | * {@link GSSException#UNAVAILABLE GSSException.UNAVAILABLE}, | ||
| 725 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 726 | */ | ||
| 727 | public abstract void addProviderAtEnd(Provider p, Oid mech) | ||
| 728 | throws GSSException; | ||
| 729 | } | ||
Binary file not shown.
| @@ -0,0 +1,295 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. | ||
| 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | ||
| 4 | * | ||
| 5 | * This code is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms of the GNU General Public License version 2 only, as | ||
| 7 | * published by the Free Software Foundation. Oracle designates this | ||
| 8 | * particular file as subject to the "Classpath" exception as provided | ||
| 9 | * by Oracle in the LICENSE file that accompanied this code. | ||
| 10 | * | ||
| 11 | * This code is distributed in the hope that it will be useful, but WITHOUT | ||
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
| 14 | * version 2 for more details (a copy is included in the LICENSE file that | ||
| 15 | * accompanied this code). | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License version | ||
| 18 | * 2 along with this work; if not, write to the Free Software Foundation, | ||
| 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 20 | * | ||
| 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | ||
| 22 | * or visit www.oracle.com if you need additional information or have any | ||
| 23 | * questions. | ||
| 24 | */ | ||
| 25 | |||
| 26 | package org.ietf.jgss; | ||
| 27 | |||
| 28 | import sun.security.jgss.spi.*; | ||
| 29 | import java.util.Vector; | ||
| 30 | import java.util.Enumeration; | ||
| 31 | |||
| 32 | /** | ||
| 33 | * This interface encapsulates a single GSS-API principal entity. The | ||
| 34 | * application obtains an implementation of this interface | ||
| 35 | * through one of the <code>createName</code> methods that exist in the {@link | ||
| 36 | * GSSManager GSSManager} class. Conceptually a GSSName contains many | ||
| 37 | * representations of the entity or many primitive name elements, one for | ||
| 38 | * each supported underlying mechanism. In GSS terminology, a GSSName that | ||
| 39 | * contains an element from just one mechanism is called a Mechanism Name | ||
| 40 | * (MN)<p> | ||
| 41 | * | ||
| 42 | * Since different authentication mechanisms may employ different | ||
| 43 | * namespaces for identifying their principals, GSS-API's naming support is | ||
| 44 | * necessarily complex in multi-mechanism environments (or even in some | ||
| 45 | * single-mechanism environments where the underlying mechanism supports | ||
| 46 | * multiple namespaces). Different name formats and their definitions are | ||
| 47 | * identified with {@link Oid Oid's} and some standard types | ||
| 48 | * are defind in this interface. The format of the names can be derived | ||
| 49 | * based on the unique <code>Oid</code> of its name type.<p> | ||
| 50 | * | ||
| 51 | * Included below are code examples utilizing the <code>GSSName</code> interface. | ||
| 52 | * The code below creates a <code>GSSName</code>, converts it to an MN, performs a | ||
| 53 | * comparison, obtains a printable representation of the name, exports it | ||
| 54 | * to a byte array and then re-imports to obtain a | ||
| 55 | * new <code>GSSName</code>.<p> | ||
| 56 | * <pre> | ||
| 57 | * GSSManager manager = GSSManager.getInstance(); | ||
| 58 | * | ||
| 59 | * // create a host based service name | ||
| 60 | * GSSName name = manager.createName("service@host", | ||
| 61 | * GSSName.NT_HOSTBASED_SERVICE); | ||
| 62 | * | ||
| 63 | * Oid krb5 = new Oid("1.2.840.113554.1.2.2"); | ||
| 64 | * | ||
| 65 | * GSSName mechName = name.canonicalize(krb5); | ||
| 66 | * | ||
| 67 | * // the above two steps are equivalent to the following | ||
| 68 | * GSSName mechName = manager.createName("service@host", | ||
| 69 | * GSSName.NT_HOSTBASED_SERVICE, krb5); | ||
| 70 | * | ||
| 71 | * // perform name comparison | ||
| 72 | * if (name.equals(mechName)) | ||
| 73 | * print("Names are equals."); | ||
| 74 | * | ||
| 75 | * // obtain textual representation of name and its printable | ||
| 76 | * // name type | ||
| 77 | * print(mechName.toString() + | ||
| 78 | * mechName.getStringNameType().toString()); | ||
| 79 | * | ||
| 80 | * // export and re-import the name | ||
| 81 | * byte [] exportName = mechName.export(); | ||
| 82 | * | ||
| 83 | * // create a new name object from the exported buffer | ||
| 84 | * GSSName newName = manager.createName(exportName, | ||
| 85 | * GSSName.NT_EXPORT_NAME); | ||
| 86 | * | ||
| 87 | * </pre> | ||
| 88 | * @see #export() | ||
| 89 | * @see #equals(GSSName) | ||
| 90 | * @see GSSManager#createName(String, Oid) | ||
| 91 | * @see GSSManager#createName(String, Oid, Oid) | ||
| 92 | * @see GSSManager#createName(byte[], Oid) | ||
| 93 | * | ||
| 94 | * @author Mayank Upadhyay | ||
| 95 | * @since 1.4 | ||
| 96 | */ | ||
| 97 | public interface GSSName { | ||
| 98 | |||
| 99 | /** | ||
| 100 | * Oid indicating a host-based service name form. It is used to | ||
| 101 | * represent services associated with host computers. This name form | ||
| 102 | * is constructed using two elements, "service" and "hostname", as | ||
| 103 | * follows: service@hostname.<p> | ||
| 104 | * | ||
| 105 | * It represents the following Oid value:<br> | ||
| 106 | * <code>{ iso(1) member-body(2) United | ||
| 107 | * States(840) mit(113554) infosys(1) gssapi(2) generic(1) service_name(4) | ||
| 108 | * }</code> | ||
| 109 | */ | ||
| 110 | public static final Oid NT_HOSTBASED_SERVICE | ||
| 111 | = Oid.getInstance("1.2.840.113554.1.2.1.4"); | ||
| 112 | |||
| 113 | /** | ||
| 114 | * Name type to indicate a named user on a local system.<p> | ||
| 115 | * It represents the following Oid value:<br> | ||
| 116 | * <code>{ iso(1) member-body(2) United | ||
| 117 | * States(840) mit(113554) infosys(1) gssapi(2) generic(1) user_name(1) | ||
| 118 | * }</code> | ||
| 119 | */ | ||
| 120 | public static final Oid NT_USER_NAME | ||
| 121 | = Oid.getInstance("1.2.840.113554.1.2.1.1"); | ||
| 122 | |||
| 123 | /** | ||
| 124 | * Name type to indicate a numeric user identifier corresponding to a | ||
| 125 | * user on a local system. (e.g. Uid).<p> | ||
| 126 | * | ||
| 127 | * It represents the following Oid value:<br> | ||
| 128 | * <code>{ iso(1) member-body(2) United States(840) mit(113554) | ||
| 129 | * infosys(1) gssapi(2) generic(1) machine_uid_name(2) }</code> | ||
| 130 | */ | ||
| 131 | public static final Oid NT_MACHINE_UID_NAME | ||
| 132 | = Oid.getInstance("1.2.840.113554.1.2.1.2"); | ||
| 133 | |||
| 134 | /** | ||
| 135 | * Name type to indicate a string of digits representing the numeric | ||
| 136 | * user identifier of a user on a local system.<p> | ||
| 137 | * | ||
| 138 | * It represents the following Oid value:<br> | ||
| 139 | * <code>{ iso(1) member-body(2) United | ||
| 140 | * States(840) mit(113554) infosys(1) gssapi(2) generic(1) | ||
| 141 | * string_uid_name(3) }</code> | ||
| 142 | */ | ||
| 143 | public static final Oid NT_STRING_UID_NAME | ||
| 144 | = Oid.getInstance("1.2.840.113554.1.2.1.3"); | ||
| 145 | |||
| 146 | /** | ||
| 147 | * Name type for representing an anonymous entity.<p> | ||
| 148 | * It represents the following Oid value:<br> | ||
| 149 | * <code>{ 1(iso), 3(org), 6(dod), 1(internet), | ||
| 150 | * 5(security), 6(nametypes), 3(gss-anonymous-name) }</code> | ||
| 151 | */ | ||
| 152 | public static final Oid NT_ANONYMOUS | ||
| 153 | = Oid.getInstance("1.3.6.1.5.6.3"); | ||
| 154 | |||
| 155 | /** | ||
| 156 | * Name type used to indicate an exported name produced by the export | ||
| 157 | * method.<p> | ||
| 158 | * | ||
| 159 | * It represents the following Oid value:<br> <code>{ 1(iso), | ||
| 160 | * 3(org), 6(dod), 1(internet), 5(security), 6(nametypes), | ||
| 161 | * 4(gss-api-exported-name) }</code> | ||
| 162 | */ | ||
| 163 | public static final Oid NT_EXPORT_NAME | ||
| 164 | = Oid.getInstance("1.3.6.1.5.6.4"); | ||
| 165 | |||
| 166 | /** | ||
| 167 | * Compares two <code>GSSName</code> objects to determine if they refer to the | ||
| 168 | * same entity. | ||
| 169 | * | ||
| 170 | * @param another the <code>GSSName</code> to compare this name with | ||
| 171 | * @return true if the two names contain at least one primitive element | ||
| 172 | * in common. If either of the names represents an anonymous entity, the | ||
| 173 | * method will return false. | ||
| 174 | * | ||
| 175 | * @throws GSSException when the names cannot be compared, containing the following | ||
| 176 | * major error codes: | ||
| 177 | * {@link GSSException#BAD_NAMETYPE GSSException.BAD_NAMETYPE}, | ||
| 178 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 179 | */ | ||
| 180 | public boolean equals(GSSName another) throws GSSException; | ||
| 181 | |||
| 182 | /** | ||
| 183 | * Compares this <code>GSSName</code> object to another Object that might be a | ||
| 184 | * <code>GSSName</code>. The behaviour is exactly the same as in {@link | ||
| 185 | * #equals(GSSName) equals} except that no GSSException is thrown; | ||
| 186 | * instead, false will be returned in the situation where an error | ||
| 187 | * occurs. | ||
| 188 | * @return true if the object to compare to is also a <code>GSSName</code> and the two | ||
| 189 | * names refer to the same entity. | ||
| 190 | * @param another the object to compare this name to | ||
| 191 | * @see #equals(GSSName) | ||
| 192 | */ | ||
| 193 | public boolean equals(Object another); | ||
| 194 | |||
| 195 | /** | ||
| 196 | * Returns a hashcode value for this GSSName. | ||
| 197 | * | ||
| 198 | * @return a hashCode value | ||
| 199 | */ | ||
| 200 | public int hashCode(); | ||
| 201 | |||
| 202 | /** | ||
| 203 | * Creates a name that is canonicalized for some | ||
| 204 | * mechanism. | ||
| 205 | * | ||
| 206 | * @return a <code>GSSName</code> that contains just one primitive | ||
| 207 | * element representing this name in a canonicalized form for the desired | ||
| 208 | * mechanism. | ||
| 209 | * @param mech the oid for the mechanism for which the canonical form of | ||
| 210 | * the name is requested. | ||
| 211 | * | ||
| 212 | * @throws GSSException containing the following | ||
| 213 | * major error codes: | ||
| 214 | * {@link GSSException#BAD_MECH GSSException.BAD_MECH}, | ||
| 215 | * {@link GSSException#BAD_NAMETYPE GSSException.BAD_NAMETYPE}, | ||
| 216 | * {@link GSSException#BAD_NAME GSSException.BAD_NAME}, | ||
| 217 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 218 | */ | ||
| 219 | public GSSName canonicalize(Oid mech) throws GSSException; | ||
| 220 | |||
| 221 | /** | ||
| 222 | * Returns a canonical contiguous byte representation of a mechanism name | ||
| 223 | * (MN), suitable for direct, byte by byte comparison by authorization | ||
| 224 | * functions. If the name is not an MN, implementations may throw a | ||
| 225 | * GSSException with the NAME_NOT_MN status code. If an implementation | ||
| 226 | * chooses not to throw an exception, it should use some system specific | ||
| 227 | * default mechanism to canonicalize the name and then export | ||
| 228 | * it. Structurally, an exported name object consists of a header | ||
| 229 | * containing an OID identifying the mechanism that authenticated the | ||
| 230 | * name, and a trailer containing the name itself, where the syntax of | ||
| 231 | * the trailer is defined by the individual mechanism specification. The | ||
| 232 | * format of the header of the output buffer is specified in RFC 2743.<p> | ||
| 233 | * | ||
| 234 | * The exported name is useful when used in large access control lists | ||
| 235 | * where the overhead of creating a <code>GSSName</code> object on each | ||
| 236 | * name and invoking the equals method on each name from the ACL may be | ||
| 237 | * prohibitive.<p> | ||
| 238 | * | ||
| 239 | * Exported names may be re-imported by using the byte array factory | ||
| 240 | * method {@link GSSManager#createName(byte[], Oid) | ||
| 241 | * GSSManager.createName} and specifying the NT_EXPORT_NAME as the name | ||
| 242 | * type object identifier. The resulting <code>GSSName</code> name will | ||
| 243 | * also be a MN.<p> | ||
| 244 | * @return a byte[] containing the exported name. RFC 2743 defines the | ||
| 245 | * "Mechanism-Independent Exported Name Object Format" for these bytes. | ||
| 246 | * | ||
| 247 | * @throws GSSException containing the following | ||
| 248 | * major error codes: | ||
| 249 | * {@link GSSException#BAD_NAME GSSException.BAD_NAME}, | ||
| 250 | * {@link GSSException#BAD_NAMETYPE GSSException.BAD_NAMETYPE}, | ||
| 251 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 252 | */ | ||
| 253 | public byte[] export() throws GSSException; | ||
| 254 | |||
| 255 | /** | ||
| 256 | * Returns a textual representation of the <code>GSSName</code> object. To retrieve | ||
| 257 | * the printed name format, which determines the syntax of the returned | ||
| 258 | * string, use the {@link #getStringNameType() getStringNameType} | ||
| 259 | * method. | ||
| 260 | * | ||
| 261 | * @return a String representing this name in printable form. | ||
| 262 | */ | ||
| 263 | public String toString(); | ||
| 264 | |||
| 265 | /** | ||
| 266 | * Returns the name type of the printable | ||
| 267 | * representation of this name that can be obtained from the <code> | ||
| 268 | * toString</code> method. | ||
| 269 | * | ||
| 270 | * @return an Oid representing the namespace of the name returned | ||
| 271 | * from the toString method. | ||
| 272 | * | ||
| 273 | * @throws GSSException containing the following | ||
| 274 | * major error codes: | ||
| 275 | * {@link GSSException#FAILURE GSSException.FAILURE} | ||
| 276 | */ | ||
| 277 | public Oid getStringNameType() throws GSSException; | ||
| 278 | |||
| 279 | /** | ||
| 280 | * Tests if this name object represents an anonymous entity. | ||
| 281 | * | ||
| 282 | * @return true if this is an anonymous name, false otherwise. | ||
| 283 | */ | ||
| 284 | public boolean isAnonymous(); | ||
| 285 | |||
| 286 | /** | ||
| 287 | * Tests if this name object represents a Mechanism Name (MN). An MN is | ||
| 288 | * a GSSName the contains exactly one mechanism's primitive name | ||
| 289 | * element. | ||
| 290 | * | ||
| 291 | * @return true if this is an MN, false otherwise. | ||
| 292 | */ | ||
| 293 | public boolean isMN(); | ||
| 294 | |||
| 295 | } | ||
Binary file not shown.
| @@ -0,0 +1,235 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. | ||
| 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | ||
| 4 | * | ||
| 5 | * This code is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms of the GNU General Public License version 2 only, as | ||
| 7 | * published by the Free Software Foundation. Oracle designates this | ||
| 8 | * particular file as subject to the "Classpath" exception as provided | ||
| 9 | * by Oracle in the LICENSE file that accompanied this code. | ||
| 10 | * | ||
| 11 | * This code is distributed in the hope that it will be useful, but WITHOUT | ||
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
| 14 | * version 2 for more details (a copy is included in the LICENSE file that | ||
| 15 | * accompanied this code). | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License version | ||
| 18 | * 2 along with this work; if not, write to the Free Software Foundation, | ||
| 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 20 | * | ||
| 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | ||
| 22 | * or visit www.oracle.com if you need additional information or have any | ||
| 23 | * questions. | ||
| 24 | */ | ||
| 25 | |||
| 26 | package org.ietf.jgss; | ||
| 27 | |||
| 28 | /** | ||
| 29 | * This is a utility class used within the per-message GSSContext | ||
| 30 | * methods to convey per-message properties.<p> | ||
| 31 | * | ||
| 32 | * When used with the GSSContext interface's wrap and getMIC methods, an | ||
| 33 | * instance of this class is used to indicate the desired | ||
| 34 | * Quality-of-Protection (QOP) and to request if confidentiality services | ||
| 35 | * are to be applied to caller supplied data (wrap only). To request | ||
| 36 | * default QOP, the value of 0 should be used for QOP.<p> | ||
| 37 | * | ||
| 38 | * When used with the unwrap and verifyMIC methods of the GSSContext | ||
| 39 | * interface, an instance of this class will be used to indicate the | ||
| 40 | * applied QOP and confidentiality services over the supplied message. | ||
| 41 | * In the case of verifyMIC, the confidentiality state will always be | ||
| 42 | * <code>false</code>. Upon return from these methods, this object will also | ||
| 43 | * contain any supplementary status values applicable to the processed | ||
| 44 | * token. The supplementary status values can indicate old tokens, out | ||
| 45 | * of sequence tokens, gap tokens or duplicate tokens.<p> | ||
| 46 | * | ||
| 47 | * @see GSSContext#wrap | ||
| 48 | * @see GSSContext#unwrap | ||
| 49 | * @see GSSContext#getMIC | ||
| 50 | * @see GSSContext#verifyMIC | ||
| 51 | * | ||
| 52 | * @author Mayank Upadhyay | ||
| 53 | * @since 1.4 | ||
| 54 | */ | ||
| 55 | public class MessageProp { | ||
| 56 | |||
| 57 | private boolean privacyState; | ||
| 58 | private int qop; | ||
| 59 | private boolean dupToken; | ||
| 60 | private boolean oldToken; | ||
| 61 | private boolean unseqToken; | ||
| 62 | private boolean gapToken; | ||
| 63 | private int minorStatus; | ||
| 64 | private String minorString; | ||
| 65 | |||
| 66 | /** | ||
| 67 | * Constructor which sets the desired privacy state. The QOP value used | ||
| 68 | * is 0. | ||
| 69 | * | ||
| 70 | * @param privState the privacy (i.e. confidentiality) state | ||
| 71 | */ | ||
| 72 | public MessageProp(boolean privState) { | ||
| 73 | this(0, privState); | ||
| 74 | } | ||
| 75 | |||
| 76 | /** | ||
| 77 | * Constructor which sets the values for the qop and privacy state. | ||
| 78 | * | ||
| 79 | * @param qop the QOP value | ||
| 80 | * @param privState the privacy (i.e. confidentiality) state | ||
| 81 | */ | ||
| 82 | public MessageProp(int qop, boolean privState) { | ||
| 83 | this.qop = qop; | ||
| 84 | this.privacyState = privState; | ||
| 85 | resetStatusValues(); | ||
| 86 | } | ||
| 87 | |||
| 88 | /** | ||
| 89 | * Retrieves the QOP value. | ||
| 90 | * | ||
| 91 | * @return an int representing the QOP value | ||
| 92 | * @see #setQOP | ||
| 93 | */ | ||
| 94 | public int getQOP() { | ||
| 95 | return qop; | ||
| 96 | } | ||
| 97 | |||
| 98 | /** | ||
| 99 | * Retrieves the privacy state. | ||
| 100 | * | ||
| 101 | * @return true if the privacy (i.e., confidentiality) state is true, | ||
| 102 | * false otherwise. | ||
| 103 | * @see #setPrivacy | ||
| 104 | */ | ||
| 105 | public boolean getPrivacy() { | ||
| 106 | |||
| 107 | return (privacyState); | ||
| 108 | } | ||
| 109 | |||
| 110 | /** | ||
| 111 | * Sets the QOP value. | ||
| 112 | * | ||
| 113 | * @param qop the int value to set the QOP to | ||
| 114 | * @see #getQOP | ||
| 115 | */ | ||
| 116 | public void setQOP(int qop) { | ||
| 117 | this.qop = qop; | ||
| 118 | } | ||
| 119 | |||
| 120 | |||
| 121 | /** | ||
| 122 | * Sets the privacy state. | ||
| 123 | * | ||
| 124 | * @param privState true is the privacy (i.e., confidentiality) state | ||
| 125 | * is true, false otherwise. | ||
| 126 | * @see #getPrivacy | ||
| 127 | */ | ||
| 128 | public void setPrivacy(boolean privState) { | ||
| 129 | |||
| 130 | this.privacyState = privState; | ||
| 131 | } | ||
| 132 | |||
| 133 | |||
| 134 | /** | ||
| 135 | * Tests if this is a duplicate of an earlier token. | ||
| 136 | * | ||
| 137 | * @return true if this is a duplicate, false otherwise. | ||
| 138 | */ | ||
| 139 | public boolean isDuplicateToken() { | ||
| 140 | return dupToken; | ||
| 141 | } | ||
| 142 | |||
| 143 | /** | ||
| 144 | * Tests if this token's validity period has expired, i.e., the token | ||
| 145 | * is too old to be checked for duplication. | ||
| 146 | * | ||
| 147 | * @return true if the token's validity period has expired, false | ||
| 148 | * otherwise. | ||
| 149 | */ | ||
| 150 | public boolean isOldToken() { | ||
| 151 | return oldToken; | ||
| 152 | } | ||
| 153 | |||
| 154 | /** | ||
| 155 | * Tests if a later token had already been processed. | ||
| 156 | * | ||
| 157 | * @return true if a later token had already been processed, false otherwise. | ||
| 158 | */ | ||
| 159 | public boolean isUnseqToken() { | ||
| 160 | return unseqToken; | ||
| 161 | } | ||
| 162 | |||
| 163 | /** | ||
| 164 | * Tests if an expected token was not received, i.e., one or more | ||
| 165 | * predecessor tokens have not yet been successfully processed. | ||
| 166 | * | ||
| 167 | * @return true if an expected per-message token was not received, | ||
| 168 | * false otherwise. | ||
| 169 | */ | ||
| 170 | public boolean isGapToken() { | ||
| 171 | return gapToken; | ||
| 172 | } | ||
| 173 | |||
| 174 | /** | ||
| 175 | * Retrieves the minor status code that the underlying mechanism might | ||
| 176 | * have set for this per-message operation. | ||
| 177 | * | ||
| 178 | * @return the int minor status | ||
| 179 | */ | ||
| 180 | public int getMinorStatus(){ | ||
| 181 | return minorStatus; | ||
| 182 | } | ||
| 183 | |||
| 184 | /** | ||
| 185 | * Retrieves a string explaining the minor status code. | ||
| 186 | * | ||
| 187 | * @return a String corresponding to the minor status | ||
| 188 | * code. <code>null</code> will be returned when no minor status code | ||
| 189 | * has been set. | ||
| 190 | */ | ||
| 191 | public String getMinorString(){ | ||
| 192 | return minorString; | ||
| 193 | } | ||
| 194 | |||
| 195 | /** | ||
| 196 | * This method sets the state for the supplementary information flags | ||
| 197 | * and the minor status in MessageProp. It is not used by the | ||
| 198 | * application but by the GSS implementation to return this information | ||
| 199 | * to the caller of a per-message context method. | ||
| 200 | * | ||
| 201 | * @param duplicate true if the token was a duplicate of an earlier | ||
| 202 | * token, false otherwise | ||
| 203 | * @param old true if the token's validity period has expired, false | ||
| 204 | * otherwise | ||
| 205 | * @param unseq true if a later token has already been processed, false | ||
| 206 | * otherwise | ||
| 207 | * @param gap true if one or more predecessor tokens have not yet been | ||
| 208 | * successfully processed, false otherwise | ||
| 209 | * @param minorStatus the int minor status code for the per-message | ||
| 210 | * operation | ||
| 211 | * @param minorString the textual representation of the minorStatus value | ||
| 212 | */ | ||
| 213 | public void setSupplementaryStates(boolean duplicate, | ||
| 214 | boolean old, boolean unseq, boolean gap, | ||
| 215 | int minorStatus, String minorString) { | ||
| 216 | this.dupToken = duplicate; | ||
| 217 | this.oldToken = old; | ||
| 218 | this.unseqToken = unseq; | ||
| 219 | this.gapToken = gap; | ||
| 220 | this.minorStatus = minorStatus; | ||
| 221 | this.minorString = minorString; | ||
| 222 | } | ||
| 223 | |||
| 224 | /** | ||
| 225 | * Resets the supplementary status values to false. | ||
| 226 | */ | ||
| 227 | private void resetStatusValues() { | ||
| 228 | dupToken = false; | ||
| 229 | oldToken = false; | ||
| 230 | unseqToken = false; | ||
| 231 | gapToken = false; | ||
| 232 | minorStatus = 0; | ||
| 233 | minorString = null; | ||
| 234 | } | ||
| 235 | } | ||
Binary file not shown.
| @@ -0,0 +1,216 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. | ||
| 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | ||
| 4 | * | ||
| 5 | * This code is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms of the GNU General Public License version 2 only, as | ||
| 7 | * published by the Free Software Foundation. Oracle designates this | ||
| 8 | * particular file as subject to the "Classpath" exception as provided | ||
| 9 | * by Oracle in the LICENSE file that accompanied this code. | ||
| 10 | * | ||
| 11 | * This code is distributed in the hope that it will be useful, but WITHOUT | ||
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
| 14 | * version 2 for more details (a copy is included in the LICENSE file that | ||
| 15 | * accompanied this code). | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License version | ||
| 18 | * 2 along with this work; if not, write to the Free Software Foundation, | ||
| 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 20 | * | ||
| 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | ||
| 22 | * or visit www.oracle.com if you need additional information or have any | ||
| 23 | * questions. | ||
| 24 | */ | ||
| 25 | |||
| 26 | package org.ietf.jgss; | ||
| 27 | |||
| 28 | import java.io.InputStream; | ||
| 29 | import java.io.IOException; | ||
| 30 | import sun.security.util.DerValue; | ||
| 31 | import sun.security.util.DerOutputStream; | ||
| 32 | import sun.security.util.ObjectIdentifier; | ||
| 33 | |||
| 34 | /** | ||
| 35 | * This class represents Universal Object Identifiers (Oids) and their | ||
| 36 | * associated operations.<p> | ||
| 37 | * | ||
| 38 | * Oids are hierarchically globally-interpretable identifiers used | ||
| 39 | * within the GSS-API framework to identify mechanisms and name formats.<p> | ||
| 40 | * | ||
| 41 | * The structure and encoding of Oids is defined in ISOIEC-8824 and | ||
| 42 | * ISOIEC-8825. For example the Oid representation of Kerberos V5 | ||
| 43 | * mechanism is "1.2.840.113554.1.2.2"<p> | ||
| 44 | * | ||
| 45 | * The GSSName name class contains public static Oid objects | ||
| 46 | * representing the standard name types defined in GSS-API. | ||
| 47 | * | ||
| 48 | * @author Mayank Upadhyay | ||
| 49 | * @since 1.4 | ||
| 50 | */ | ||
| 51 | public class Oid { | ||
| 52 | |||
| 53 | private ObjectIdentifier oid; | ||
| 54 | private byte[] derEncoding; | ||
| 55 | |||
| 56 | /** | ||
| 57 | * Constructs an Oid object from a string representation of its | ||
| 58 | * integer components. | ||
| 59 | * | ||
| 60 | * @param strOid the dot separated string representation of the oid. | ||
| 61 | * For instance, "1.2.840.113554.1.2.2". | ||
| 62 | * @exception GSSException may be thrown when the string is incorrectly | ||
| 63 | * formatted | ||
| 64 | */ | ||
| 65 | public Oid(String strOid) throws GSSException { | ||
| 66 | |||
| 67 | try { | ||
| 68 | oid = new ObjectIdentifier(strOid); | ||
| 69 | derEncoding = null; | ||
| 70 | } catch (Exception e) { | ||
| 71 | throw new GSSException(GSSException.FAILURE, | ||
| 72 | "Improperly formatted Object Identifier String - " | ||
| 73 | + strOid); | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 77 | /** | ||
| 78 | * Creates an Oid object from its ASN.1 DER encoding. This refers to | ||
| 79 | * the full encoding including tag and length. The structure and | ||
| 80 | * encoding of Oids is defined in ISOIEC-8824 and ISOIEC-8825. This | ||
| 81 | * method is identical in functionality to its byte array counterpart. | ||
| 82 | * | ||
| 83 | * @param derOid stream containing the DER encoded oid | ||
| 84 | * @exception GSSException may be thrown when the DER encoding does not | ||
| 85 | * follow the prescribed format. | ||
| 86 | */ | ||
| 87 | public Oid(InputStream derOid) throws GSSException { | ||
| 88 | try { | ||
| 89 | DerValue derVal = new DerValue(derOid); | ||
| 90 | derEncoding = derVal.toByteArray(); | ||
| 91 | oid = derVal.getOID(); | ||
| 92 | } catch (IOException e) { | ||
| 93 | throw new GSSException(GSSException.FAILURE, | ||
| 94 | "Improperly formatted ASN.1 DER encoding for Oid"); | ||
| 95 | } | ||
| 96 | } | ||
| 97 | |||
| 98 | |||
| 99 | /** | ||
| 100 | * Creates an Oid object from its ASN.1 DER encoding. This refers to | ||
| 101 | * the full encoding including tag and length. The structure and | ||
| 102 | * encoding of Oids is defined in ISOIEC-8824 and ISOIEC-8825. This | ||
| 103 | * method is identical in functionality to its InputStream conterpart. | ||
| 104 | * | ||
| 105 | * @param data byte array containing the DER encoded oid | ||
| 106 | * @exception GSSException may be thrown when the DER encoding does not | ||
| 107 | * follow the prescribed format. | ||
| 108 | */ | ||
| 109 | public Oid(byte [] data) throws GSSException { | ||
| 110 | try { | ||
| 111 | DerValue derVal = new DerValue(data); | ||
| 112 | derEncoding = derVal.toByteArray(); | ||
| 113 | oid = derVal.getOID(); | ||
| 114 | } catch (IOException e) { | ||
| 115 | throw new GSSException(GSSException.FAILURE, | ||
| 116 | "Improperly formatted ASN.1 DER encoding for Oid"); | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | /** | ||
| 121 | * Only for calling by initializators used with declarations. | ||
| 122 | * | ||
| 123 | * @param strOid | ||
| 124 | */ | ||
| 125 | static Oid getInstance(String strOid) { | ||
| 126 | Oid retVal = null; | ||
| 127 | try { | ||
| 128 | retVal = new Oid(strOid); | ||
| 129 | } catch (GSSException e) { | ||
| 130 | // squelch it! | ||
| 131 | } | ||
| 132 | return retVal; | ||
| 133 | } | ||
| 134 | |||
| 135 | /** | ||
| 136 | * Returns a string representation of the oid's integer components | ||
| 137 | * in dot separated notation. | ||
| 138 | * | ||
| 139 | * @return string representation in the following format: "1.2.3.4.5" | ||
| 140 | */ | ||
| 141 | public String toString() { | ||
| 142 | return oid.toString(); | ||
| 143 | } | ||
| 144 | |||
| 145 | /** | ||
| 146 | * Tests if two Oid objects represent the same Object identifier | ||
| 147 | * value. | ||
| 148 | * | ||
| 149 | * @return <code>true</code> if the two Oid objects represent the same | ||
| 150 | * value, <code>false</code> otherwise. | ||
| 151 | * @param other the Oid object that has to be compared to this one | ||
| 152 | */ | ||
| 153 | public boolean equals(Object other) { | ||
| 154 | |||
| 155 | //check if both reference the same object | ||
| 156 | if (this == other) | ||
| 157 | return (true); | ||
| 158 | |||
| 159 | if (other instanceof Oid) | ||
| 160 | return this.oid.equals(((Oid) other).oid); | ||
| 161 | else if (other instanceof ObjectIdentifier) | ||
| 162 | return this.oid.equals(other); | ||
| 163 | else | ||
| 164 | return false; | ||
| 165 | } | ||
| 166 | |||
| 167 | |||
| 168 | /** | ||
| 169 | * Returns the full ASN.1 DER encoding for this oid object, which | ||
| 170 | * includes the tag and length. | ||
| 171 | * | ||
| 172 | * @return byte array containing the DER encoding of this oid object. | ||
| 173 | * @exception GSSException may be thrown when the oid can't be encoded | ||
| 174 | */ | ||
| 175 | public byte[] getDER() throws GSSException { | ||
| 176 | |||
| 177 | if (derEncoding == null) { | ||
| 178 | DerOutputStream dout = new DerOutputStream(); | ||
| 179 | try { | ||
| 180 | dout.putOID(oid); | ||
| 181 | } catch (IOException e) { | ||
| 182 | throw new GSSException(GSSException.FAILURE, e.getMessage()); | ||
| 183 | } | ||
| 184 | derEncoding = dout.toByteArray(); | ||
| 185 | } | ||
| 186 | |||
| 187 | return derEncoding.clone(); | ||
| 188 | } | ||
| 189 | |||
| 190 | /** | ||
| 191 | * A utility method to test if this Oid value is contained within the | ||
| 192 | * supplied Oid array. | ||
| 193 | * | ||
| 194 | * @param oids the array of Oid's to search | ||
| 195 | * @return true if the array contains this Oid value, false otherwise | ||
| 196 | */ | ||
| 197 | public boolean containedIn(Oid[] oids) { | ||
| 198 | |||
| 199 | for (int i = 0; i < oids.length; i++) { | ||
| 200 | if (oids[i].equals(this)) | ||
| 201 | return (true); | ||
| 202 | } | ||
| 203 | |||
| 204 | return (false); | ||
| 205 | } | ||
| 206 | |||
| 207 | |||
| 208 | /** | ||
| 209 | * Returns a hashcode value for this Oid. | ||
| 210 | * | ||
| 211 | * @return a hashCode value | ||
| 212 | */ | ||
| 213 | public int hashCode() { | ||
| 214 | return oid.hashCode(); | ||
| 215 | } | ||
| 216 | } | ||
| @@ -0,0 +1,15 @@ | |||
| 1 | <../../../../../mkconfig | ||
| 2 | |||
| 3 | TARG=\ | ||
| 4 | ChannelBinding.dis\ | ||
| 5 | GSSContext.dis\ | ||
| 6 | GSSCredential.dis\ | ||
| 7 | GSSException.dis\ | ||
| 8 | GSSManager.dis\ | ||
| 9 | GSSName.dis\ | ||
| 10 | MessageProp.dis\ | ||
| 11 | Oid.dis\ | ||
| 12 | |||
| 13 | DISBIN=$ROOT/java/dis/java/java/org/ietf/jgss | ||
| 14 | |||
| 15 | <$ROOT/mkfiles/mkjava | ||
| @@ -0,0 +1,127 @@ | |||
| 1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> | ||
| 2 | <html> | ||
| 3 | <head> | ||
| 4 | <!-- | ||
| 5 | Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. | ||
| 6 | DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | ||
| 7 | |||
| 8 | This code is free software; you can redistribute it and/or modify it | ||
| 9 | under the terms of the GNU General Public License version 2 only, as | ||
| 10 | published by the Free Software Foundation. Oracle designates this | ||
| 11 | particular file as subject to the "Classpath" exception as provided | ||
| 12 | by Oracle in the LICENSE file that accompanied this code. | ||
| 13 | |||
| 14 | This code is distributed in the hope that it will be useful, but WITHOUT | ||
| 15 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 16 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
| 17 | version 2 for more details (a copy is included in the LICENSE file that | ||
| 18 | accompanied this code). | ||
| 19 | |||
| 20 | You should have received a copy of the GNU General Public License version | ||
| 21 | 2 along with this work; if not, write to the Free Software Foundation, | ||
| 22 | Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 23 | |||
| 24 | Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | ||
| 25 | or visit www.oracle.com if you need additional information or have any | ||
| 26 | questions. | ||
| 27 | --> | ||
| 28 | |||
| 29 | </head> | ||
| 30 | <body bgcolor="white"> | ||
| 31 | |||
| 32 | This package presents a framework that allows application developers to | ||
| 33 | make use of security services like authentication, data integrity and | ||
| 34 | data confidentiality from a variety of underlying security mechanisms | ||
| 35 | like Kerberos, using a unified API. The security mechanisms that an | ||
| 36 | application can | ||
| 37 | chose to use are identified with unique object identifiers. One example | ||
| 38 | of such a mechanism is the Kerberos v5 GSS-API mechanism (object | ||
| 39 | identifier 1.2.840.113554.1.2.2). This mechanism is available through | ||
| 40 | the default instance of the GSSManager class.<p> | ||
| 41 | |||
| 42 | The GSS-API is defined in a language independent way in | ||
| 43 | <a href=http://www.ietf.org/rfc/rfc2743.txt>RFC 2743</a>. The Java | ||
| 44 | language bindings are defined in | ||
| 45 | <a href=http://www.ietf.org/rfc/rfc2853.txt>RFC 2853</a><p> | ||
| 46 | |||
| 47 | An application starts out by instantiating a <code>GSSManager</code> | ||
| 48 | which then serves as a factory for a security context. An application | ||
| 49 | can use specific principal names and credentials that are also created | ||
| 50 | using the GSSManager; or it can instantiate a | ||
| 51 | context with system defaults. It then goes through a context | ||
| 52 | establishment loop. Once a context is established with the | ||
| 53 | peer, authentication is complete. Data protection such as integrity | ||
| 54 | and confidentiality can then be obtained from this context.<p> | ||
| 55 | |||
| 56 | The GSS-API does not perform any communication with the peer. It merely | ||
| 57 | produces tokens that the application must somehow transport to the | ||
| 58 | other end.<p> | ||
| 59 | |||
| 60 | <h3>Credential Acquisition</h3> | ||
| 61 | <a name=useSubjectCredsOnly> | ||
| 62 | The GSS-API itself does not dictate how an underlying mechanism | ||
| 63 | obtains the credentials that are needed for authentication. It is | ||
| 64 | assumed that prior to calling the GSS-API, these credentials are | ||
| 65 | obtained and stored in a location that the mechanism provider is | ||
| 66 | aware of. However, the default model in the Java platform will be | ||
| 67 | that mechanism providers must obtain credentials only from the private | ||
| 68 | or public credential sets associated with the | ||
| 69 | {@link javax.security.auth.Subject Subject} in the | ||
| 70 | current access control context. The Kerberos v5 | ||
| 71 | mechanism will search for the required INITIATE and ACCEPT credentials | ||
| 72 | ({@link javax.security.auth.kerberos.KerberosTicket KerberosTicket} and | ||
| 73 | {@link javax.security.auth.kerberos.KerberosKey KerberosKey}) in | ||
| 74 | the private credential set where as some other mechanism might look | ||
| 75 | in the public set or in both. If the desired credential is not | ||
| 76 | present in the appropriate sets of the current Subject, the GSS-API | ||
| 77 | call must fail.<p> | ||
| 78 | |||
| 79 | This model has the advantage that credential management | ||
| 80 | is simple and predictable from the applications point of view. An | ||
| 81 | application, given the right permissions, can purge the credentials in | ||
| 82 | the Subject or renew them using standard Java API's. If it purged | ||
| 83 | the credentials, it would be sure that the JGSS mechanism would fail, | ||
| 84 | or if it renewed a time based credential it would be sure that a JGSS | ||
| 85 | mechanism would succeed.<p> | ||
| 86 | |||
| 87 | This model does require that a {@link | ||
| 88 | javax.security.auth.login JAAS login} be performed in order to | ||
| 89 | authenticate and populate a Subject that the JGSS mechnanism can later | ||
| 90 | utilize. However, applications have the ability to relax this | ||
| 91 | restiction by means of a system property: | ||
| 92 | <code>javax.security.auth.useSubjectCredsOnly</code>. By default | ||
| 93 | this system property will be assumed to be <code>true</code> (even when | ||
| 94 | it is unset) indicating that providers must only use the credentials | ||
| 95 | that are present in the current Subject. However, if this property is | ||
| 96 | explicitly set to false by the application, then it indicates that | ||
| 97 | the provider is free to use any credentials cache of its choice. Such | ||
| 98 | a credential cache might be a disk cache, an in-memory cache, or even | ||
| 99 | just the current Subject itself. | ||
| 100 | </a> | ||
| 101 | |||
| 102 | <h2>Related Documentation</h2> | ||
| 103 | <p> | ||
| 104 | For an online tutorial on using Java GSS-API, please see | ||
| 105 | <a href="../../../../technotes/guides/security/jgss/tutorials/index.html">Introduction to JAAS and Java GSS-API</a>. | ||
| 106 | </p> | ||
| 107 | |||
| 108 | <!-- | ||
| 109 | <h2>Package Specification</h2> | ||
| 110 | |||
| 111 | ##### FILL IN ANY SPECS NEEDED BY JAVA COMPATIBILITY KIT ##### | ||
| 112 | <ul> | ||
| 113 | <li><a href="">##### REFER TO ANY FRAMEMAKER SPECIFICATION HERE #####</a> | ||
| 114 | </ul> | ||
| 115 | |||
| 116 | <h2>Related Documentation</h2> | ||
| 117 | |||
| 118 | For overviews, tutorials, examples, guides, and tool documentation, please see: | ||
| 119 | <ul> | ||
| 120 | <li><a href="">##### REFER TO NON-SPEC DOCUMENTATION HERE #####</a> | ||
| 121 | </ul> | ||
| 122 | |||
| 123 | --> | ||
| 124 | |||
| 125 | @since 1.4 | ||
| 126 | </body> | ||
| 127 | </html> | ||
| @@ -0,0 +1,6 @@ | |||
| 1 | <../../../../mkconfig | ||
| 2 | |||
| 3 | DIRS=\ | ||
| 4 | jgss\ | ||
| 5 | |||
| 6 | <$ROOT/mkfiles/mksubdirs | ||
| @@ -0,0 +1,6 @@ | |||
| 1 | <../../../../mkconfig | ||
| 2 | |||
| 3 | DIRS=\ | ||
| 4 | xml\ | ||
| 5 | |||
| 6 | <$ROOT/mkfiles/mksubdirs | ||
Binary file not shown.
| @@ -0,0 +1,123 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 1999-2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DigesterOutputStream.java,v 1.2 2008/07/24 15:20:31 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal; | ||
| 28 | |||
| 29 | import java.io.ByteArrayInputStream; | ||
| 30 | import java.io.InputStream; | ||
| 31 | import java.io.OutputStream; | ||
| 32 | import java.security.MessageDigest; | ||
| 33 | import java.util.logging.Logger; | ||
| 34 | import java.util.logging.Level; | ||
| 35 | |||
| 36 | import com.sun.org.apache.xml.internal.security.utils.UnsyncByteArrayOutputStream; | ||
| 37 | |||
| 38 | /** | ||
| 39 | * This class has been modified slightly to use java.security.MessageDigest | ||
| 40 | * objects as input, rather than | ||
| 41 | * com.sun.org.apache.xml.internal.security.algorithms.MessageDigestAlgorithm objects. | ||
| 42 | * It also optionally caches the input bytes. | ||
| 43 | * | ||
| 44 | * @author raul | ||
| 45 | * @author Sean Mullan | ||
| 46 | */ | ||
| 47 | public class DigesterOutputStream extends OutputStream { | ||
| 48 | private boolean buffer = false; | ||
| 49 | private UnsyncByteArrayOutputStream bos; | ||
| 50 | private final MessageDigest md; | ||
| 51 | private static Logger log = Logger.getLogger("org.jcp.xml.dsig.internal"); | ||
| 52 | |||
| 53 | /** | ||
| 54 | * Creates a DigesterOutputStream. | ||
| 55 | * | ||
| 56 | * @param md the MessageDigest | ||
| 57 | */ | ||
| 58 | public DigesterOutputStream(MessageDigest md) { | ||
| 59 | this(md, false); | ||
| 60 | } | ||
| 61 | |||
| 62 | /** | ||
| 63 | * Creates a DigesterOutputStream. | ||
| 64 | * | ||
| 65 | * @param md the MessageDigest | ||
| 66 | * @param buffer if true, caches the input bytes | ||
| 67 | */ | ||
| 68 | public DigesterOutputStream(MessageDigest md, boolean buffer) { | ||
| 69 | this.md = md; | ||
| 70 | this.buffer = buffer; | ||
| 71 | if (buffer) { | ||
| 72 | bos = new UnsyncByteArrayOutputStream(); | ||
| 73 | } | ||
| 74 | } | ||
| 75 | |||
| 76 | /** @inheritDoc */ | ||
| 77 | public void write(byte[] input) { | ||
| 78 | write(input, 0, input.length); | ||
| 79 | } | ||
| 80 | |||
| 81 | /** @inheritDoc */ | ||
| 82 | public void write(int input) { | ||
| 83 | if (buffer) { | ||
| 84 | bos.write(input); | ||
| 85 | } | ||
| 86 | md.update((byte)input); | ||
| 87 | } | ||
| 88 | |||
| 89 | /** @inheritDoc */ | ||
| 90 | public void write(byte[] input, int offset, int len) { | ||
| 91 | if (buffer) { | ||
| 92 | bos.write(input, offset, len); | ||
| 93 | } | ||
| 94 | if (log.isLoggable(Level.FINER)) { | ||
| 95 | log.log(Level.FINER, "Pre-digested input:"); | ||
| 96 | StringBuffer sb = new StringBuffer(len); | ||
| 97 | for (int i=offset; i<(offset+len); i++) { | ||
| 98 | sb.append((char) input[i]); | ||
| 99 | } | ||
| 100 | log.log(Level.FINER, sb.toString()); | ||
| 101 | } | ||
| 102 | md.update(input, offset, len); | ||
| 103 | } | ||
| 104 | |||
| 105 | /** | ||
| 106 | * @return the digest value | ||
| 107 | */ | ||
| 108 | public byte[] getDigestValue() { | ||
| 109 | return md.digest(); | ||
| 110 | } | ||
| 111 | |||
| 112 | /** | ||
| 113 | * @return an input stream containing the cached bytes, or | ||
| 114 | * null if not cached | ||
| 115 | */ | ||
| 116 | public InputStream getInputStream() { | ||
| 117 | if (buffer) { | ||
| 118 | return new ByteArrayInputStream(bos.toByteArray()); | ||
| 119 | } else { | ||
| 120 | return null; | ||
| 121 | } | ||
| 122 | } | ||
| 123 | } | ||
Binary file not shown.
| @@ -0,0 +1,58 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 1999-2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | package org.jcp.xml.dsig.internal; | ||
| 22 | |||
| 23 | import java.io.ByteArrayOutputStream; | ||
| 24 | import javax.crypto.Mac; | ||
| 25 | |||
| 26 | /** | ||
| 27 | * Derived from Apache sources and changed to use Mac objects instead of | ||
| 28 | * com.sun.org.apache.xml.internal.security.algorithms.SignatureAlgorithm objects. | ||
| 29 | * | ||
| 30 | * @author raul | ||
| 31 | * @author Sean Mullan | ||
| 32 | * | ||
| 33 | */ | ||
| 34 | public class MacOutputStream extends ByteArrayOutputStream { | ||
| 35 | private final Mac mac; | ||
| 36 | |||
| 37 | public MacOutputStream(Mac mac) { | ||
| 38 | this.mac = mac; | ||
| 39 | } | ||
| 40 | |||
| 41 | /** @inheritDoc */ | ||
| 42 | public void write(byte[] arg0) { | ||
| 43 | super.write(arg0, 0, arg0.length); | ||
| 44 | mac.update(arg0); | ||
| 45 | } | ||
| 46 | |||
| 47 | /** @inheritDoc */ | ||
| 48 | public void write(int arg0) { | ||
| 49 | super.write(arg0); | ||
| 50 | mac.update((byte) arg0); | ||
| 51 | } | ||
| 52 | |||
| 53 | /** @inheritDoc */ | ||
| 54 | public void write(byte[] arg0, int arg1, int arg2) { | ||
| 55 | super.write(arg0, arg1, arg2); | ||
| 56 | mac.update(arg0, arg1, arg2); | ||
| 57 | } | ||
| 58 | } | ||
Binary file not shown.
| @@ -0,0 +1,77 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 1999-2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: SignerOutputStream.java,v 1.2 2008/07/24 15:20:31 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal; | ||
| 28 | |||
| 29 | import java.io.ByteArrayOutputStream; | ||
| 30 | import java.security.Signature; | ||
| 31 | import java.security.SignatureException; | ||
| 32 | |||
| 33 | /** | ||
| 34 | * Derived from Apache sources and changed to use java.security.Signature | ||
| 35 | * objects as input instead of com.sun.org.apache.xml.internal.security.algorithms.SignatureAlgorithm | ||
| 36 | * objects. | ||
| 37 | * | ||
| 38 | * @author raul | ||
| 39 | * @author Sean Mullan | ||
| 40 | */ | ||
| 41 | public class SignerOutputStream extends ByteArrayOutputStream { | ||
| 42 | private final Signature sig; | ||
| 43 | |||
| 44 | public SignerOutputStream(Signature sig) { | ||
| 45 | this.sig=sig; | ||
| 46 | } | ||
| 47 | |||
| 48 | /** @inheritDoc */ | ||
| 49 | public void write(byte[] arg0) { | ||
| 50 | super.write(arg0, 0, arg0.length); | ||
| 51 | try { | ||
| 52 | sig.update(arg0); | ||
| 53 | } catch (SignatureException e) { | ||
| 54 | throw new RuntimeException(""+e); | ||
| 55 | } | ||
| 56 | } | ||
| 57 | |||
| 58 | /** @inheritDoc */ | ||
| 59 | public void write(int arg0) { | ||
| 60 | super.write(arg0); | ||
| 61 | try { | ||
| 62 | sig.update((byte)arg0); | ||
| 63 | } catch (SignatureException e) { | ||
| 64 | throw new RuntimeException(""+e); | ||
| 65 | } | ||
| 66 | } | ||
| 67 | |||
| 68 | /** @inheritDoc */ | ||
| 69 | public void write(byte[] arg0, int arg1, int arg2) { | ||
| 70 | super.write(arg0, arg1, arg2); | ||
| 71 | try { | ||
| 72 | sig.update(arg0,arg1,arg2); | ||
| 73 | } catch (SignatureException e) { | ||
| 74 | throw new RuntimeException(""+e); | ||
| 75 | } | ||
| 76 | } | ||
| 77 | } | ||
Binary file not shown.
| @@ -0,0 +1,262 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: ApacheCanonicalizer.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import java.io.ByteArrayInputStream; | ||
| 30 | import java.io.ByteArrayOutputStream; | ||
| 31 | import java.io.IOException; | ||
| 32 | import java.io.OutputStream; | ||
| 33 | import java.security.spec.AlgorithmParameterSpec; | ||
| 34 | import java.security.InvalidAlgorithmParameterException; | ||
| 35 | import java.util.Set; | ||
| 36 | import java.util.logging.Logger; | ||
| 37 | import java.util.logging.Level; | ||
| 38 | import javax.xml.crypto.*; | ||
| 39 | import javax.xml.crypto.dom.DOMCryptoContext; | ||
| 40 | import javax.xml.crypto.dsig.TransformException; | ||
| 41 | import javax.xml.crypto.dsig.TransformService; | ||
| 42 | import javax.xml.crypto.dsig.XMLSignatureException; | ||
| 43 | import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec; | ||
| 44 | |||
| 45 | import com.sun.org.apache.xml.internal.security.c14n.Canonicalizer; | ||
| 46 | import com.sun.org.apache.xml.internal.security.c14n.InvalidCanonicalizerException; | ||
| 47 | import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput; | ||
| 48 | import com.sun.org.apache.xml.internal.security.transforms.Transform; | ||
| 49 | import org.w3c.dom.Document; | ||
| 50 | import org.w3c.dom.Element; | ||
| 51 | import org.w3c.dom.NodeList; | ||
| 52 | |||
| 53 | public abstract class ApacheCanonicalizer extends TransformService { | ||
| 54 | |||
| 55 | static { | ||
| 56 | com.sun.org.apache.xml.internal.security.Init.init(); | ||
| 57 | } | ||
| 58 | |||
| 59 | private static Logger log = Logger.getLogger("org.jcp.xml.dsig.internal.dom"); | ||
| 60 | protected Canonicalizer apacheCanonicalizer; | ||
| 61 | private Transform apacheTransform; | ||
| 62 | protected String inclusiveNamespaces; | ||
| 63 | protected C14NMethodParameterSpec params; | ||
| 64 | protected Document ownerDoc; | ||
| 65 | protected Element transformElem; | ||
| 66 | |||
| 67 | public final AlgorithmParameterSpec getParameterSpec() { | ||
| 68 | return params; | ||
| 69 | } | ||
| 70 | |||
| 71 | public void init(XMLStructure parent, XMLCryptoContext context) | ||
| 72 | throws InvalidAlgorithmParameterException { | ||
| 73 | if (context != null && !(context instanceof DOMCryptoContext)) { | ||
| 74 | throw new ClassCastException | ||
| 75 | ("context must be of type DOMCryptoContext"); | ||
| 76 | } | ||
| 77 | transformElem = (Element) | ||
| 78 | ((javax.xml.crypto.dom.DOMStructure) parent).getNode(); | ||
| 79 | ownerDoc = DOMUtils.getOwnerDocument(transformElem); | ||
| 80 | } | ||
| 81 | |||
| 82 | public void marshalParams(XMLStructure parent, XMLCryptoContext context) | ||
| 83 | throws MarshalException { | ||
| 84 | if (context != null && !(context instanceof DOMCryptoContext)) { | ||
| 85 | throw new ClassCastException | ||
| 86 | ("context must be of type DOMCryptoContext"); | ||
| 87 | } | ||
| 88 | transformElem = (Element) | ||
| 89 | ((javax.xml.crypto.dom.DOMStructure) parent).getNode(); | ||
| 90 | ownerDoc = DOMUtils.getOwnerDocument(transformElem); | ||
| 91 | } | ||
| 92 | |||
| 93 | public Data canonicalize(Data data, XMLCryptoContext xc) | ||
| 94 | throws TransformException { | ||
| 95 | return canonicalize(data, xc, null); | ||
| 96 | } | ||
| 97 | |||
| 98 | public Data canonicalize(Data data, XMLCryptoContext xc, OutputStream os) | ||
| 99 | throws TransformException { | ||
| 100 | |||
| 101 | if (apacheCanonicalizer == null) { | ||
| 102 | try { | ||
| 103 | apacheCanonicalizer = Canonicalizer.getInstance(getAlgorithm()); | ||
| 104 | if (log.isLoggable(Level.FINE)) { | ||
| 105 | log.log(Level.FINE, "Created canonicalizer for algorithm: " | ||
| 106 | + getAlgorithm()); | ||
| 107 | } | ||
| 108 | } catch (InvalidCanonicalizerException ice) { | ||
| 109 | throw new TransformException | ||
| 110 | ("Couldn't find Canonicalizer for: " + getAlgorithm() + | ||
| 111 | ": " + ice.getMessage(), ice); | ||
| 112 | } | ||
| 113 | } | ||
| 114 | |||
| 115 | if (os != null) { | ||
| 116 | apacheCanonicalizer.setWriter(os); | ||
| 117 | } else { | ||
| 118 | apacheCanonicalizer.setWriter(new ByteArrayOutputStream()); | ||
| 119 | } | ||
| 120 | |||
| 121 | try { | ||
| 122 | Set nodeSet = null; | ||
| 123 | if (data instanceof ApacheData) { | ||
| 124 | XMLSignatureInput in = | ||
| 125 | ((ApacheData) data).getXMLSignatureInput(); | ||
| 126 | if (in.isElement()) { | ||
| 127 | if (inclusiveNamespaces != null) { | ||
| 128 | return new OctetStreamData(new ByteArrayInputStream | ||
| 129 | (apacheCanonicalizer.canonicalizeSubtree | ||
| 130 | (in.getSubNode(), inclusiveNamespaces))); | ||
| 131 | } else { | ||
| 132 | return new OctetStreamData(new ByteArrayInputStream | ||
| 133 | (apacheCanonicalizer.canonicalizeSubtree | ||
| 134 | (in.getSubNode()))); | ||
| 135 | } | ||
| 136 | } else if (in.isNodeSet()) { | ||
| 137 | nodeSet = in.getNodeSet(); | ||
| 138 | } else { | ||
| 139 | return new OctetStreamData(new ByteArrayInputStream( | ||
| 140 | apacheCanonicalizer.canonicalize( | ||
| 141 | Utils.readBytesFromStream(in.getOctetStream())))); | ||
| 142 | } | ||
| 143 | } else if (data instanceof DOMSubTreeData) { | ||
| 144 | DOMSubTreeData subTree = (DOMSubTreeData) data; | ||
| 145 | if (inclusiveNamespaces != null) { | ||
| 146 | return new OctetStreamData(new ByteArrayInputStream | ||
| 147 | (apacheCanonicalizer.canonicalizeSubtree | ||
| 148 | (subTree.getRoot(), inclusiveNamespaces))); | ||
| 149 | } else { | ||
| 150 | return new OctetStreamData(new ByteArrayInputStream | ||
| 151 | (apacheCanonicalizer.canonicalizeSubtree | ||
| 152 | (subTree.getRoot()))); | ||
| 153 | } | ||
| 154 | } else if (data instanceof NodeSetData) { | ||
| 155 | NodeSetData nsd = (NodeSetData) data; | ||
| 156 | // convert Iterator to Set | ||
| 157 | nodeSet = Utils.toNodeSet(nsd.iterator()); | ||
| 158 | if (log.isLoggable(Level.FINE)) { | ||
| 159 | log.log(Level.FINE, "Canonicalizing " + nodeSet.size() | ||
| 160 | + " nodes"); | ||
| 161 | } | ||
| 162 | } else { | ||
| 163 | return new OctetStreamData(new ByteArrayInputStream( | ||
| 164 | apacheCanonicalizer.canonicalize( | ||
| 165 | Utils.readBytesFromStream( | ||
| 166 | ((OctetStreamData)data).getOctetStream())))); | ||
| 167 | } | ||
| 168 | if (inclusiveNamespaces != null) { | ||
| 169 | return new OctetStreamData(new ByteArrayInputStream( | ||
| 170 | apacheCanonicalizer.canonicalizeXPathNodeSet | ||
| 171 | (nodeSet, inclusiveNamespaces))); | ||
| 172 | } else { | ||
| 173 | return new OctetStreamData(new ByteArrayInputStream( | ||
| 174 | apacheCanonicalizer.canonicalizeXPathNodeSet(nodeSet))); | ||
| 175 | } | ||
| 176 | } catch (Exception e) { | ||
| 177 | throw new TransformException(e); | ||
| 178 | } | ||
| 179 | } | ||
| 180 | |||
| 181 | public Data transform(Data data, XMLCryptoContext xc, OutputStream os) | ||
| 182 | throws TransformException { | ||
| 183 | if (data == null) { | ||
| 184 | throw new NullPointerException("data must not be null"); | ||
| 185 | } | ||
| 186 | if (os == null) { | ||
| 187 | throw new NullPointerException("output stream must not be null"); | ||
| 188 | } | ||
| 189 | |||
| 190 | if (ownerDoc == null) { | ||
| 191 | throw new TransformException("transform must be marshalled"); | ||
| 192 | } | ||
| 193 | |||
| 194 | if (apacheTransform == null) { | ||
| 195 | try { | ||
| 196 | apacheTransform = Transform.getInstance | ||
| 197 | (ownerDoc, getAlgorithm(), transformElem.getChildNodes()); | ||
| 198 | apacheTransform.setElement(transformElem, xc.getBaseURI()); | ||
| 199 | if (log.isLoggable(Level.FINE)) { | ||
| 200 | log.log(Level.FINE, "Created transform for algorithm: " | ||
| 201 | + getAlgorithm()); | ||
| 202 | } | ||
| 203 | } catch (Exception ex) { | ||
| 204 | throw new TransformException | ||
| 205 | ("Couldn't find Transform for: " + getAlgorithm(), ex); | ||
| 206 | } | ||
| 207 | } | ||
| 208 | |||
| 209 | XMLSignatureInput in; | ||
| 210 | if (data instanceof ApacheData) { | ||
| 211 | if (log.isLoggable(Level.FINE)) { | ||
| 212 | log.log(Level.FINE, "ApacheData = true"); | ||
| 213 | } | ||
| 214 | in = ((ApacheData) data).getXMLSignatureInput(); | ||
| 215 | } else if (data instanceof NodeSetData) { | ||
| 216 | if (log.isLoggable(Level.FINE)) { | ||
| 217 | log.log(Level.FINE, "isNodeSet() = true"); | ||
| 218 | } | ||
| 219 | if (data instanceof DOMSubTreeData) { | ||
| 220 | DOMSubTreeData subTree = (DOMSubTreeData) data; | ||
| 221 | in = new XMLSignatureInput(subTree.getRoot()); | ||
| 222 | in.setExcludeComments(subTree.excludeComments()); | ||
| 223 | } else { | ||
| 224 | Set nodeSet = | ||
| 225 | Utils.toNodeSet(((NodeSetData) data).iterator()); | ||
| 226 | in = new XMLSignatureInput(nodeSet); | ||
| 227 | } | ||
| 228 | } else { | ||
| 229 | if (log.isLoggable(Level.FINE)) { | ||
| 230 | log.log(Level.FINE, "isNodeSet() = false"); | ||
| 231 | } | ||
| 232 | try { | ||
| 233 | in = new XMLSignatureInput | ||
| 234 | (((OctetStreamData)data).getOctetStream()); | ||
| 235 | } catch (Exception ex) { | ||
| 236 | throw new TransformException(ex); | ||
| 237 | } | ||
| 238 | } | ||
| 239 | |||
| 240 | try { | ||
| 241 | in = apacheTransform.performTransform(in, os); | ||
| 242 | if (!in.isNodeSet() && !in.isElement()) { | ||
| 243 | return null; | ||
| 244 | } | ||
| 245 | if (in.isOctetStream()) { | ||
| 246 | return new ApacheOctetStreamData(in); | ||
| 247 | } else { | ||
| 248 | return new ApacheNodeSetData(in); | ||
| 249 | } | ||
| 250 | } catch (Exception ex) { | ||
| 251 | throw new TransformException(ex); | ||
| 252 | } | ||
| 253 | } | ||
| 254 | |||
| 255 | public final boolean isFeatureSupported(String feature) { | ||
| 256 | if (feature == null) { | ||
| 257 | throw new NullPointerException(); | ||
| 258 | } else { | ||
| 259 | return false; | ||
| 260 | } | ||
| 261 | } | ||
| 262 | } | ||
Binary file not shown.
| @@ -0,0 +1,43 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: ApacheData.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import javax.xml.crypto.Data; | ||
| 30 | import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput; | ||
| 31 | |||
| 32 | /** | ||
| 33 | * XMLSignatureInput Data wrapper. | ||
| 34 | * | ||
| 35 | * @author Sean Mullan | ||
| 36 | */ | ||
| 37 | public interface ApacheData extends Data { | ||
| 38 | |||
| 39 | /** | ||
| 40 | * Returns the XMLSignatureInput. | ||
| 41 | */ | ||
| 42 | public XMLSignatureInput getXMLSignatureInput(); | ||
| 43 | } | ||
Binary file not shown.
| @@ -0,0 +1,95 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: ApacheNodeSetData.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import java.util.Collections; | ||
| 30 | import java.util.HashSet; | ||
| 31 | import java.util.Iterator; | ||
| 32 | import java.util.LinkedHashSet; | ||
| 33 | import java.util.List; | ||
| 34 | import java.util.Set; | ||
| 35 | import javax.xml.crypto.NodeSetData; | ||
| 36 | import org.w3c.dom.Node; | ||
| 37 | import com.sun.org.apache.xml.internal.security.signature.NodeFilter; | ||
| 38 | import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput; | ||
| 39 | import com.sun.org.apache.xml.internal.security.utils.XMLUtils; | ||
| 40 | |||
| 41 | public class ApacheNodeSetData implements ApacheData, NodeSetData { | ||
| 42 | |||
| 43 | private XMLSignatureInput xi; | ||
| 44 | |||
| 45 | public ApacheNodeSetData(XMLSignatureInput xi) { | ||
| 46 | this.xi = xi; | ||
| 47 | } | ||
| 48 | |||
| 49 | public Iterator iterator() { | ||
| 50 | // If nodefilters are set, must execute them first to create node-set | ||
| 51 | if (xi.getNodeFilters() != null) { | ||
| 52 | return Collections.unmodifiableSet | ||
| 53 | (getNodeSet(xi.getNodeFilters())).iterator(); | ||
| 54 | } | ||
| 55 | try { | ||
| 56 | return Collections.unmodifiableSet(xi.getNodeSet()).iterator(); | ||
| 57 | } catch (Exception e) { | ||
| 58 | // should not occur | ||
| 59 | throw new RuntimeException | ||
| 60 | ("unrecoverable error retrieving nodeset", e); | ||
| 61 | } | ||
| 62 | } | ||
| 63 | |||
| 64 | public XMLSignatureInput getXMLSignatureInput() { | ||
| 65 | return xi; | ||
| 66 | } | ||
| 67 | |||
| 68 | private Set getNodeSet(List nodeFilters) { | ||
| 69 | if (xi.isNeedsToBeExpanded()) { | ||
| 70 | XMLUtils.circumventBug2650 | ||
| 71 | (XMLUtils.getOwnerDocument(xi.getSubNode())); | ||
| 72 | } | ||
| 73 | |||
| 74 | Set inputSet = new LinkedHashSet(); | ||
| 75 | XMLUtils.getSet | ||
| 76 | (xi.getSubNode(), inputSet, null, !xi.isExcludeComments()); | ||
| 77 | Set nodeSet = new LinkedHashSet(); | ||
| 78 | Iterator i = inputSet.iterator(); | ||
| 79 | while (i.hasNext()) { | ||
| 80 | Node currentNode = (Node) i.next(); | ||
| 81 | Iterator it = nodeFilters.iterator(); | ||
| 82 | boolean skipNode = false; | ||
| 83 | while (it.hasNext() && !skipNode) { | ||
| 84 | NodeFilter nf = (NodeFilter) it.next(); | ||
| 85 | if (nf.isNodeInclude(currentNode)!=1) { | ||
| 86 | skipNode = true; | ||
| 87 | } | ||
| 88 | } | ||
| 89 | if (!skipNode) { | ||
| 90 | nodeSet.add(currentNode); | ||
| 91 | } | ||
| 92 | } | ||
| 93 | return nodeSet; | ||
| 94 | } | ||
| 95 | } | ||
Binary file not shown.
| @@ -0,0 +1,48 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: ApacheOctetStreamData.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import java.io.IOException; | ||
| 30 | import javax.xml.crypto.OctetStreamData; | ||
| 31 | import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException; | ||
| 32 | import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput; | ||
| 33 | |||
| 34 | public class ApacheOctetStreamData extends OctetStreamData | ||
| 35 | implements ApacheData { | ||
| 36 | |||
| 37 | private XMLSignatureInput xi; | ||
| 38 | |||
| 39 | public ApacheOctetStreamData(XMLSignatureInput xi) | ||
| 40 | throws CanonicalizationException, IOException { | ||
| 41 | super(xi.getOctetStream(), xi.getSourceURI(), xi.getMIMEType()); | ||
| 42 | this.xi = xi; | ||
| 43 | } | ||
| 44 | |||
| 45 | public XMLSignatureInput getXMLSignatureInput() { | ||
| 46 | return xi; | ||
| 47 | } | ||
| 48 | } | ||
Binary file not shown.
| @@ -0,0 +1,193 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: ApacheTransform.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import java.io.OutputStream; | ||
| 30 | import java.security.InvalidAlgorithmParameterException; | ||
| 31 | import java.security.spec.AlgorithmParameterSpec; | ||
| 32 | import java.util.Set; | ||
| 33 | import java.util.logging.Level; | ||
| 34 | import java.util.logging.Logger; | ||
| 35 | import org.w3c.dom.Document; | ||
| 36 | import org.w3c.dom.Element; | ||
| 37 | import org.w3c.dom.NodeList; | ||
| 38 | |||
| 39 | import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput; | ||
| 40 | import com.sun.org.apache.xml.internal.security.transforms.Transform; | ||
| 41 | |||
| 42 | import javax.xml.crypto.*; | ||
| 43 | import javax.xml.crypto.dom.DOMCryptoContext; | ||
| 44 | import javax.xml.crypto.dsig.*; | ||
| 45 | import javax.xml.crypto.dsig.spec.TransformParameterSpec; | ||
| 46 | |||
| 47 | /** | ||
| 48 | * This is a wrapper/glue class which invokes the Apache XML-Security | ||
| 49 | * Transform. | ||
| 50 | * | ||
| 51 | * @author Sean Mullan | ||
| 52 | * @author Erwin van der Koogh | ||
| 53 | */ | ||
| 54 | public abstract class ApacheTransform extends TransformService { | ||
| 55 | |||
| 56 | static { | ||
| 57 | com.sun.org.apache.xml.internal.security.Init.init(); | ||
| 58 | } | ||
| 59 | |||
| 60 | private static Logger log = Logger.getLogger("org.jcp.xml.dsig.internal.dom"); | ||
| 61 | private Transform apacheTransform; | ||
| 62 | protected Document ownerDoc; | ||
| 63 | protected Element transformElem; | ||
| 64 | protected TransformParameterSpec params; | ||
| 65 | |||
| 66 | public final AlgorithmParameterSpec getParameterSpec() { | ||
| 67 | return params; | ||
| 68 | } | ||
| 69 | |||
| 70 | public void init(XMLStructure parent, XMLCryptoContext context) | ||
| 71 | throws InvalidAlgorithmParameterException { | ||
| 72 | if (context != null && !(context instanceof DOMCryptoContext)) { | ||
| 73 | throw new ClassCastException | ||
| 74 | ("context must be of type DOMCryptoContext"); | ||
| 75 | } | ||
| 76 | transformElem = (Element) | ||
| 77 | ((javax.xml.crypto.dom.DOMStructure) parent).getNode(); | ||
| 78 | ownerDoc = DOMUtils.getOwnerDocument(transformElem); | ||
| 79 | } | ||
| 80 | |||
| 81 | public void marshalParams(XMLStructure parent, XMLCryptoContext context) | ||
| 82 | throws MarshalException { | ||
| 83 | if (context != null && !(context instanceof DOMCryptoContext)) { | ||
| 84 | throw new ClassCastException | ||
| 85 | ("context must be of type DOMCryptoContext"); | ||
| 86 | } | ||
| 87 | transformElem = (Element) | ||
| 88 | ((javax.xml.crypto.dom.DOMStructure) parent).getNode(); | ||
| 89 | ownerDoc = DOMUtils.getOwnerDocument(transformElem); | ||
| 90 | } | ||
| 91 | |||
| 92 | public Data transform(Data data, XMLCryptoContext xc) | ||
| 93 | throws TransformException { | ||
| 94 | if (data == null) { | ||
| 95 | throw new NullPointerException("data must not be null"); | ||
| 96 | } | ||
| 97 | return transformIt(data, xc, (OutputStream) null); | ||
| 98 | } | ||
| 99 | |||
| 100 | public Data transform(Data data, XMLCryptoContext xc, OutputStream os) | ||
| 101 | throws TransformException { | ||
| 102 | if (data == null) { | ||
| 103 | throw new NullPointerException("data must not be null"); | ||
| 104 | } | ||
| 105 | if (os == null) { | ||
| 106 | throw new NullPointerException("output stream must not be null"); | ||
| 107 | } | ||
| 108 | return transformIt(data, xc, os); | ||
| 109 | } | ||
| 110 | |||
| 111 | private Data transformIt(Data data, XMLCryptoContext xc, OutputStream os) | ||
| 112 | throws TransformException { | ||
| 113 | |||
| 114 | if (ownerDoc == null) { | ||
| 115 | throw new TransformException("transform must be marshalled"); | ||
| 116 | } | ||
| 117 | |||
| 118 | if (apacheTransform == null) { | ||
| 119 | try { | ||
| 120 | apacheTransform = Transform.getInstance | ||
| 121 | (ownerDoc, getAlgorithm(), transformElem.getChildNodes()); | ||
| 122 | apacheTransform.setElement(transformElem, xc.getBaseURI()); | ||
| 123 | if (log.isLoggable(Level.FINE)) { | ||
| 124 | log.log(Level.FINE, "Created transform for algorithm: " | ||
| 125 | + getAlgorithm()); | ||
| 126 | } | ||
| 127 | } catch (Exception ex) { | ||
| 128 | throw new TransformException | ||
| 129 | ("Couldn't find Transform for: " + getAlgorithm(), ex); | ||
| 130 | } | ||
| 131 | } | ||
| 132 | |||
| 133 | XMLSignatureInput in; | ||
| 134 | if (data instanceof ApacheData) { | ||
| 135 | if (log.isLoggable(Level.FINE)) { | ||
| 136 | log.log(Level.FINE, "ApacheData = true"); | ||
| 137 | } | ||
| 138 | in = ((ApacheData) data).getXMLSignatureInput(); | ||
| 139 | } else if (data instanceof NodeSetData) { | ||
| 140 | if (log.isLoggable(Level.FINE)) { | ||
| 141 | log.log(Level.FINE, "isNodeSet() = true"); | ||
| 142 | } | ||
| 143 | if (data instanceof DOMSubTreeData) { | ||
| 144 | if (log.isLoggable(Level.FINE)) { | ||
| 145 | log.log(Level.FINE, "DOMSubTreeData = true"); | ||
| 146 | } | ||
| 147 | DOMSubTreeData subTree = (DOMSubTreeData) data; | ||
| 148 | in = new XMLSignatureInput(subTree.getRoot()); | ||
| 149 | in.setExcludeComments(subTree.excludeComments()); | ||
| 150 | } else { | ||
| 151 | Set nodeSet = | ||
| 152 | Utils.toNodeSet(((NodeSetData) data).iterator()); | ||
| 153 | in = new XMLSignatureInput(nodeSet); | ||
| 154 | } | ||
| 155 | } else { | ||
| 156 | if (log.isLoggable(Level.FINE)) { | ||
| 157 | log.log(Level.FINE, "isNodeSet() = false"); | ||
| 158 | } | ||
| 159 | try { | ||
| 160 | in = new XMLSignatureInput | ||
| 161 | (((OctetStreamData)data).getOctetStream()); | ||
| 162 | } catch (Exception ex) { | ||
| 163 | throw new TransformException(ex); | ||
| 164 | } | ||
| 165 | } | ||
| 166 | |||
| 167 | try { | ||
| 168 | if (os != null) { | ||
| 169 | in = apacheTransform.performTransform(in, os); | ||
| 170 | if (!in.isNodeSet() && !in.isElement()) { | ||
| 171 | return null; | ||
| 172 | } | ||
| 173 | } else { | ||
| 174 | in = apacheTransform.performTransform(in); | ||
| 175 | } | ||
| 176 | if (in.isOctetStream()) { | ||
| 177 | return new ApacheOctetStreamData(in); | ||
| 178 | } else { | ||
| 179 | return new ApacheNodeSetData(in); | ||
| 180 | } | ||
| 181 | } catch (Exception ex) { | ||
| 182 | throw new TransformException(ex); | ||
| 183 | } | ||
| 184 | } | ||
| 185 | |||
| 186 | public final boolean isFeatureSupported(String feature) { | ||
| 187 | if (feature == null) { | ||
| 188 | throw new NullPointerException(); | ||
| 189 | } else { | ||
| 190 | return false; | ||
| 191 | } | ||
| 192 | } | ||
| 193 | } | ||
Binary file not shown.
| @@ -0,0 +1,48 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DOMBase64Transform.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import java.security.InvalidAlgorithmParameterException; | ||
| 30 | |||
| 31 | import javax.xml.crypto.XMLStructure; | ||
| 32 | import javax.xml.crypto.dsig.spec.TransformParameterSpec; | ||
| 33 | |||
| 34 | /** | ||
| 35 | * DOM-based implementation of Base64 Encoding Transform. | ||
| 36 | * (Uses Apache XML-Sec Transform implementation) | ||
| 37 | * | ||
| 38 | * @author Sean Mullan | ||
| 39 | */ | ||
| 40 | public final class DOMBase64Transform extends ApacheTransform { | ||
| 41 | |||
| 42 | public void init(TransformParameterSpec params) | ||
| 43 | throws InvalidAlgorithmParameterException { | ||
| 44 | if (params != null) { | ||
| 45 | throw new InvalidAlgorithmParameterException("params must be null"); | ||
| 46 | } | ||
| 47 | } | ||
| 48 | } | ||
Binary file not shown.
| @@ -0,0 +1,79 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2008 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DOMCanonicalXMLC14N11Method.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import javax.xml.crypto.*; | ||
| 30 | import javax.xml.crypto.dsig.*; | ||
| 31 | import javax.xml.crypto.dsig.spec.TransformParameterSpec; | ||
| 32 | |||
| 33 | import java.security.InvalidAlgorithmParameterException; | ||
| 34 | |||
| 35 | import com.sun.org.apache.xml.internal.security.c14n.Canonicalizer; | ||
| 36 | import com.sun.org.apache.xml.internal.security.c14n.InvalidCanonicalizerException; | ||
| 37 | |||
| 38 | /** | ||
| 39 | * DOM-based implementation of CanonicalizationMethod for Canonical XML 1.1 | ||
| 40 | * (with or without comments). Uses Apache XML-Sec Canonicalizer. | ||
| 41 | * | ||
| 42 | * @author Sean Mullan | ||
| 43 | */ | ||
| 44 | public final class DOMCanonicalXMLC14N11Method extends ApacheCanonicalizer { | ||
| 45 | |||
| 46 | public static final String C14N_11 = "http://www.w3.org/2006/12/xml-c14n11"; | ||
| 47 | public static final String C14N_11_WITH_COMMENTS | ||
| 48 | = "http://www.w3.org/2006/12/xml-c14n11#WithComments"; | ||
| 49 | |||
| 50 | public void init(TransformParameterSpec params) | ||
| 51 | throws InvalidAlgorithmParameterException { | ||
| 52 | if (params != null) { | ||
| 53 | throw new InvalidAlgorithmParameterException("no parameters " + | ||
| 54 | "should be specified for Canonical XML 1.1 algorithm"); | ||
| 55 | } | ||
| 56 | } | ||
| 57 | |||
| 58 | public Data transform(Data data, XMLCryptoContext xc) | ||
| 59 | throws TransformException { | ||
| 60 | |||
| 61 | // ignore comments if dereferencing same-document URI that requires | ||
| 62 | // you to omit comments, even if the Transform says otherwise - | ||
| 63 | // this is to be compliant with section 4.3.3.3 of W3C Rec. | ||
| 64 | if (data instanceof DOMSubTreeData) { | ||
| 65 | DOMSubTreeData subTree = (DOMSubTreeData) data; | ||
| 66 | if (subTree.excludeComments()) { | ||
| 67 | try { | ||
| 68 | apacheCanonicalizer = Canonicalizer.getInstance(C14N_11); | ||
| 69 | } catch (InvalidCanonicalizerException ice) { | ||
| 70 | throw new TransformException | ||
| 71 | ("Couldn't find Canonicalizer for: " + | ||
| 72 | C14N_11 + ": " + ice.getMessage(), ice); | ||
| 73 | } | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 77 | return canonicalize(data, xc); | ||
| 78 | } | ||
| 79 | } | ||
Binary file not shown.
| @@ -0,0 +1,77 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DOMCanonicalXMLC14NMethod.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import javax.xml.crypto.*; | ||
| 30 | import javax.xml.crypto.dsig.*; | ||
| 31 | import javax.xml.crypto.dsig.spec.TransformParameterSpec; | ||
| 32 | |||
| 33 | import java.security.InvalidAlgorithmParameterException; | ||
| 34 | |||
| 35 | import com.sun.org.apache.xml.internal.security.c14n.Canonicalizer; | ||
| 36 | import com.sun.org.apache.xml.internal.security.c14n.InvalidCanonicalizerException; | ||
| 37 | |||
| 38 | /** | ||
| 39 | * DOM-based implementation of CanonicalizationMethod for Canonical XML | ||
| 40 | * (with or without comments). Uses Apache XML-Sec Canonicalizer. | ||
| 41 | * | ||
| 42 | * @author Sean Mullan | ||
| 43 | */ | ||
| 44 | public final class DOMCanonicalXMLC14NMethod extends ApacheCanonicalizer { | ||
| 45 | |||
| 46 | public void init(TransformParameterSpec params) | ||
| 47 | throws InvalidAlgorithmParameterException { | ||
| 48 | if (params != null) { | ||
| 49 | throw new InvalidAlgorithmParameterException("no parameters " + | ||
| 50 | "should be specified for Canonical XML C14N algorithm"); | ||
| 51 | } | ||
| 52 | } | ||
| 53 | |||
| 54 | public Data transform(Data data, XMLCryptoContext xc) | ||
| 55 | throws TransformException { | ||
| 56 | |||
| 57 | // ignore comments if dereferencing same-document URI that requires | ||
| 58 | // you to omit comments, even if the Transform says otherwise - | ||
| 59 | // this is to be compliant with section 4.3.3.3 of W3C Rec. | ||
| 60 | if (data instanceof DOMSubTreeData) { | ||
| 61 | DOMSubTreeData subTree = (DOMSubTreeData) data; | ||
| 62 | if (subTree.excludeComments()) { | ||
| 63 | try { | ||
| 64 | apacheCanonicalizer = Canonicalizer.getInstance | ||
| 65 | (CanonicalizationMethod.INCLUSIVE); | ||
| 66 | } catch (InvalidCanonicalizerException ice) { | ||
| 67 | throw new TransformException | ||
| 68 | ("Couldn't find Canonicalizer for: " + | ||
| 69 | CanonicalizationMethod.INCLUSIVE + ": " + | ||
| 70 | ice.getMessage(), ice); | ||
| 71 | } | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 75 | return canonicalize(data, xc); | ||
| 76 | } | ||
| 77 | } | ||
Binary file not shown.
| @@ -0,0 +1,104 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DOMCanonicalizationMethod.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import java.io.OutputStream; | ||
| 30 | import java.security.InvalidAlgorithmParameterException; | ||
| 31 | import java.security.Provider; | ||
| 32 | |||
| 33 | import org.w3c.dom.Element; | ||
| 34 | |||
| 35 | import javax.xml.crypto.*; | ||
| 36 | import javax.xml.crypto.dsig.*; | ||
| 37 | |||
| 38 | /** | ||
| 39 | * DOM-based abstract implementation of CanonicalizationMethod. | ||
| 40 | * | ||
| 41 | * @author Sean Mullan | ||
| 42 | */ | ||
| 43 | public class DOMCanonicalizationMethod extends DOMTransform | ||
| 44 | implements CanonicalizationMethod { | ||
| 45 | |||
| 46 | /** | ||
| 47 | * Creates a <code>DOMCanonicalizationMethod</code>. | ||
| 48 | * | ||
| 49 | * @param spi TransformService | ||
| 50 | */ | ||
| 51 | public DOMCanonicalizationMethod(TransformService spi) | ||
| 52 | throws InvalidAlgorithmParameterException { | ||
| 53 | super(spi); | ||
| 54 | } | ||
| 55 | |||
| 56 | /** | ||
| 57 | * Creates a <code>DOMCanonicalizationMethod</code> from an element. This | ||
| 58 | * ctor invokes the abstract {@link #unmarshalParams unmarshalParams} | ||
| 59 | * method to unmarshal any algorithm-specific input parameters. | ||
| 60 | * | ||
| 61 | * @param cmElem a CanonicalizationMethod element | ||
| 62 | */ | ||
| 63 | public DOMCanonicalizationMethod(Element cmElem, XMLCryptoContext context, | ||
| 64 | Provider provider) throws MarshalException { | ||
| 65 | super(cmElem, context, provider); | ||
| 66 | } | ||
| 67 | |||
| 68 | /** | ||
| 69 | * Canonicalizes the specified data using the underlying canonicalization | ||
| 70 | * algorithm. This is a convenience method that is equivalent to invoking | ||
| 71 | * the {@link #transform transform} method. | ||
| 72 | * | ||
| 73 | * @param data the data to be canonicalized | ||
| 74 | * @param xc the <code>XMLCryptoContext</code> containing | ||
| 75 | * additional context (may be <code>null</code> if not applicable) | ||
| 76 | * @return the canonicalized data | ||
| 77 | * @throws NullPointerException if <code>data</code> is <code>null</code> | ||
| 78 | * @throws TransformException if an unexpected error occurs while | ||
| 79 | * canonicalizing the data | ||
| 80 | */ | ||
| 81 | public Data canonicalize(Data data, XMLCryptoContext xc) | ||
| 82 | throws TransformException { | ||
| 83 | return transform(data, xc); | ||
| 84 | } | ||
| 85 | |||
| 86 | public Data canonicalize(Data data, XMLCryptoContext xc, OutputStream os) | ||
| 87 | throws TransformException { | ||
| 88 | return transform(data, xc, os); | ||
| 89 | } | ||
| 90 | |||
| 91 | public boolean equals(Object o) { | ||
| 92 | if (this == o) { | ||
| 93 | return true; | ||
| 94 | } | ||
| 95 | |||
| 96 | if (!(o instanceof CanonicalizationMethod)) { | ||
| 97 | return false; | ||
| 98 | } | ||
| 99 | CanonicalizationMethod ocm = (CanonicalizationMethod) o; | ||
| 100 | |||
| 101 | return (getAlgorithm().equals(ocm.getAlgorithm()) && | ||
| 102 | DOMUtils.paramsEqual(getParameterSpec(), ocm.getParameterSpec())); | ||
| 103 | } | ||
| 104 | } | ||
Binary file not shown.
| @@ -0,0 +1,102 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DOMCryptoBinary.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import java.math.BigInteger; | ||
| 30 | import javax.xml.crypto.*; | ||
| 31 | import javax.xml.crypto.dom.DOMCryptoContext; | ||
| 32 | import javax.xml.crypto.dsig.*; | ||
| 33 | import org.w3c.dom.Node; | ||
| 34 | import org.w3c.dom.Text; | ||
| 35 | |||
| 36 | import com.sun.org.apache.xml.internal.security.utils.Base64; | ||
| 37 | |||
| 38 | /** | ||
| 39 | * A DOM-based representation of the XML <code>CryptoBinary</code> simple type | ||
| 40 | * as defined in the W3C specification for XML-Signature Syntax and Processing. | ||
| 41 | * The XML Schema Definition is defined as: | ||
| 42 | * | ||
| 43 | * <xmp> | ||
| 44 | * <simpleType name="CryptoBinary"> | ||
| 45 | * <restriction base = "base64Binary"> | ||
| 46 | * </restriction> | ||
| 47 | * </simpleType> | ||
| 48 | * </xmp> | ||
| 49 | * | ||
| 50 | * @author Sean Mullan | ||
| 51 | */ | ||
| 52 | public final class DOMCryptoBinary extends DOMStructure { | ||
| 53 | |||
| 54 | private final BigInteger bigNum; | ||
| 55 | private final String value; | ||
| 56 | |||
| 57 | /** | ||
| 58 | * Create a <code>DOMCryptoBinary</code> instance from the specified | ||
| 59 | * <code>BigInteger</code> | ||
| 60 | * | ||
| 61 | * @param bigNum the arbitrary-length integer | ||
| 62 | * @throws NullPointerException if <code>bigNum</code> is <code>null</code> | ||
| 63 | */ | ||
| 64 | public DOMCryptoBinary(BigInteger bigNum) { | ||
| 65 | if (bigNum == null) { | ||
| 66 | throw new NullPointerException("bigNum is null"); | ||
| 67 | } | ||
| 68 | this.bigNum = bigNum; | ||
| 69 | // convert to bitstring | ||
| 70 | value = Base64.encode(bigNum); | ||
| 71 | } | ||
| 72 | |||
| 73 | /** | ||
| 74 | * Creates a <code>DOMCryptoBinary</code> from a node. | ||
| 75 | * | ||
| 76 | * @param cbNode a CryptoBinary text node | ||
| 77 | * @throws MarshalException if value cannot be decoded (invalid format) | ||
| 78 | */ | ||
| 79 | public DOMCryptoBinary(Node cbNode) throws MarshalException { | ||
| 80 | value = cbNode.getNodeValue(); | ||
| 81 | try { | ||
| 82 | bigNum = Base64.decodeBigIntegerFromText((Text) cbNode); | ||
| 83 | } catch (Exception ex) { | ||
| 84 | throw new MarshalException(ex); | ||
| 85 | } | ||
| 86 | } | ||
| 87 | |||
| 88 | /** | ||
| 89 | * Returns the <code>BigInteger</code> that this object contains. | ||
| 90 | * | ||
| 91 | * @return the <code>BigInteger</code> that this object contains | ||
| 92 | */ | ||
| 93 | public BigInteger getBigNum() { | ||
| 94 | return bigNum; | ||
| 95 | } | ||
| 96 | |||
| 97 | public void marshal(Node parent, String prefix, DOMCryptoContext context) | ||
| 98 | throws MarshalException { | ||
| 99 | parent.appendChild | ||
| 100 | (DOMUtils.getOwnerDocument(parent).createTextNode(value)); | ||
| 101 | } | ||
| 102 | } | ||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,264 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DOMDigestMethod.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import javax.xml.crypto.*; | ||
| 30 | import javax.xml.crypto.dom.DOMCryptoContext; | ||
| 31 | import javax.xml.crypto.dsig.*; | ||
| 32 | import javax.xml.crypto.dsig.spec.DigestMethodParameterSpec; | ||
| 33 | |||
| 34 | import java.security.InvalidAlgorithmParameterException; | ||
| 35 | import java.security.spec.AlgorithmParameterSpec; | ||
| 36 | import org.w3c.dom.Document; | ||
| 37 | import org.w3c.dom.Element; | ||
| 38 | import org.w3c.dom.Node; | ||
| 39 | |||
| 40 | /** | ||
| 41 | * DOM-based abstract implementation of DigestMethod. | ||
| 42 | * | ||
| 43 | * @author Sean Mullan | ||
| 44 | */ | ||
| 45 | public abstract class DOMDigestMethod extends DOMStructure | ||
| 46 | implements DigestMethod { | ||
| 47 | |||
| 48 | final static String SHA384 = | ||
| 49 | "http://www.w3.org/2001/04/xmldsig-more#sha384"; // see RFC 4051 | ||
| 50 | private DigestMethodParameterSpec params; | ||
| 51 | |||
| 52 | /** | ||
| 53 | * Creates a <code>DOMDigestMethod</code>. | ||
| 54 | * | ||
| 55 | * @param params the algorithm-specific params (may be <code>null</code>) | ||
| 56 | * @throws InvalidAlgorithmParameterException if the parameters are not | ||
| 57 | * appropriate for this digest method | ||
| 58 | */ | ||
| 59 | DOMDigestMethod(AlgorithmParameterSpec params) | ||
| 60 | throws InvalidAlgorithmParameterException { | ||
| 61 | if (params != null && !(params instanceof DigestMethodParameterSpec)) { | ||
| 62 | throw new InvalidAlgorithmParameterException | ||
| 63 | ("params must be of type DigestMethodParameterSpec"); | ||
| 64 | } | ||
| 65 | checkParams((DigestMethodParameterSpec) params); | ||
| 66 | this.params = (DigestMethodParameterSpec) params; | ||
| 67 | } | ||
| 68 | |||
| 69 | /** | ||
| 70 | * Creates a <code>DOMDigestMethod</code> from an element. This constructor | ||
| 71 | * invokes the abstract {@link #unmarshalParams unmarshalParams} method to | ||
| 72 | * unmarshal any algorithm-specific input parameters. | ||
| 73 | * | ||
| 74 | * @param dmElem a DigestMethod element | ||
| 75 | */ | ||
| 76 | DOMDigestMethod(Element dmElem) throws MarshalException { | ||
| 77 | Element paramsElem = DOMUtils.getFirstChildElement(dmElem); | ||
| 78 | if (paramsElem != null) { | ||
| 79 | params = unmarshalParams(paramsElem); | ||
| 80 | } | ||
| 81 | try { | ||
| 82 | checkParams(params); | ||
| 83 | } catch (InvalidAlgorithmParameterException iape) { | ||
| 84 | throw new MarshalException(iape); | ||
| 85 | } | ||
| 86 | } | ||
| 87 | |||
| 88 | static DigestMethod unmarshal(Element dmElem) throws MarshalException { | ||
| 89 | String alg = DOMUtils.getAttributeValue(dmElem, "Algorithm"); | ||
| 90 | if (alg.equals(DigestMethod.SHA1)) { | ||
| 91 | return new SHA1(dmElem); | ||
| 92 | } else if (alg.equals(DigestMethod.SHA256)) { | ||
| 93 | return new SHA256(dmElem); | ||
| 94 | } else if (alg.equals(SHA384)) { | ||
| 95 | return new SHA384(dmElem); | ||
| 96 | } else if (alg.equals(DigestMethod.SHA512)) { | ||
| 97 | return new SHA512(dmElem); | ||
| 98 | } else { | ||
| 99 | throw new MarshalException | ||
| 100 | ("unsupported DigestMethod algorithm: " + alg); | ||
| 101 | } | ||
| 102 | } | ||
| 103 | |||
| 104 | /** | ||
| 105 | * Checks if the specified parameters are valid for this algorithm. By | ||
| 106 | * default, this method throws an exception if parameters are specified | ||
| 107 | * since most DigestMethod algorithms do not have parameters. Subclasses | ||
| 108 | * should override it if they have parameters. | ||
| 109 | * | ||
| 110 | * @param params the algorithm-specific params (may be <code>null</code>) | ||
| 111 | * @throws InvalidAlgorithmParameterException if the parameters are not | ||
| 112 | * appropriate for this digest method | ||
| 113 | */ | ||
| 114 | void checkParams(DigestMethodParameterSpec params) | ||
| 115 | throws InvalidAlgorithmParameterException { | ||
| 116 | if (params != null) { | ||
| 117 | throw new InvalidAlgorithmParameterException("no parameters " + | ||
| 118 | "should be specified for the " + getMessageDigestAlgorithm() | ||
| 119 | + " DigestMethod algorithm"); | ||
| 120 | } | ||
| 121 | } | ||
| 122 | |||
| 123 | public final AlgorithmParameterSpec getParameterSpec() { | ||
| 124 | return params; | ||
| 125 | } | ||
| 126 | |||
| 127 | /** | ||
| 128 | * Unmarshals <code>DigestMethodParameterSpec</code> from the specified | ||
| 129 | * <code>Element</code>. By default, this method throws an exception since | ||
| 130 | * most DigestMethod algorithms do not have parameters. Subclasses should | ||
| 131 | * override it if they have parameters. | ||
| 132 | * | ||
| 133 | * @param paramsElem the <code>Element</code> holding the input params | ||
| 134 | * @return the algorithm-specific <code>DigestMethodParameterSpec</code> | ||
| 135 | * @throws MarshalException if the parameters cannot be unmarshalled | ||
| 136 | */ | ||
| 137 | DigestMethodParameterSpec | ||
| 138 | unmarshalParams(Element paramsElem) throws MarshalException { | ||
| 139 | throw new MarshalException("no parameters should " + | ||
| 140 | "be specified for the " + getMessageDigestAlgorithm() + | ||
| 141 | " DigestMethod algorithm"); | ||
| 142 | } | ||
| 143 | |||
| 144 | /** | ||
| 145 | * This method invokes the abstract {@link #marshalParams marshalParams} | ||
| 146 | * method to marshal any algorithm-specific parameters. | ||
| 147 | */ | ||
| 148 | public void marshal(Node parent, String prefix, DOMCryptoContext context) | ||
| 149 | throws MarshalException { | ||
| 150 | Document ownerDoc = DOMUtils.getOwnerDocument(parent); | ||
| 151 | |||
| 152 | Element dmElem = DOMUtils.createElement | ||
| 153 | (ownerDoc, "DigestMethod", XMLSignature.XMLNS, prefix); | ||
| 154 | DOMUtils.setAttribute(dmElem, "Algorithm", getAlgorithm()); | ||
| 155 | |||
| 156 | if (params != null) { | ||
| 157 | marshalParams(dmElem, prefix); | ||
| 158 | } | ||
| 159 | |||
| 160 | parent.appendChild(dmElem); | ||
| 161 | } | ||
| 162 | |||
| 163 | public boolean equals(Object o) { | ||
| 164 | if (this == o) { | ||
| 165 | return true; | ||
| 166 | } | ||
| 167 | |||
| 168 | if (!(o instanceof DigestMethod)) { | ||
| 169 | return false; | ||
| 170 | } | ||
| 171 | DigestMethod odm = (DigestMethod) o; | ||
| 172 | |||
| 173 | boolean paramsEqual = (params == null ? odm.getParameterSpec() == null : | ||
| 174 | params.equals(odm.getParameterSpec())); | ||
| 175 | |||
| 176 | return (getAlgorithm().equals(odm.getAlgorithm()) && paramsEqual); | ||
| 177 | } | ||
| 178 | |||
| 179 | /** | ||
| 180 | * Marshals the algorithm-specific parameters to an Element and | ||
| 181 | * appends it to the specified parent element. By default, this method | ||
| 182 | * throws an exception since most DigestMethod algorithms do not have | ||
| 183 | * parameters. Subclasses should override it if they have parameters. | ||
| 184 | * | ||
| 185 | * @param parent the parent element to append the parameters to | ||
| 186 | * @param the namespace prefix to use | ||
| 187 | * @throws MarshalException if the parameters cannot be marshalled | ||
| 188 | */ | ||
| 189 | void marshalParams(Element parent, String prefix) | ||
| 190 | throws MarshalException { | ||
| 191 | throw new MarshalException("no parameters should " + | ||
| 192 | "be specified for the " + getMessageDigestAlgorithm() + | ||
| 193 | " DigestMethod algorithm"); | ||
| 194 | } | ||
| 195 | |||
| 196 | /** | ||
| 197 | * Returns the MessageDigest standard algorithm name. | ||
| 198 | */ | ||
| 199 | abstract String getMessageDigestAlgorithm(); | ||
| 200 | |||
| 201 | static final class SHA1 extends DOMDigestMethod { | ||
| 202 | SHA1(AlgorithmParameterSpec params) | ||
| 203 | throws InvalidAlgorithmParameterException { | ||
| 204 | super(params); | ||
| 205 | } | ||
| 206 | SHA1(Element dmElem) throws MarshalException { | ||
| 207 | super(dmElem); | ||
| 208 | } | ||
| 209 | public String getAlgorithm() { | ||
| 210 | return DigestMethod.SHA1; | ||
| 211 | } | ||
| 212 | String getMessageDigestAlgorithm() { | ||
| 213 | return "SHA-1"; | ||
| 214 | } | ||
| 215 | } | ||
| 216 | |||
| 217 | static final class SHA256 extends DOMDigestMethod { | ||
| 218 | SHA256(AlgorithmParameterSpec params) | ||
| 219 | throws InvalidAlgorithmParameterException { | ||
| 220 | super(params); | ||
| 221 | } | ||
| 222 | SHA256(Element dmElem) throws MarshalException { | ||
| 223 | super(dmElem); | ||
| 224 | } | ||
| 225 | public String getAlgorithm() { | ||
| 226 | return DigestMethod.SHA256; | ||
| 227 | } | ||
| 228 | String getMessageDigestAlgorithm() { | ||
| 229 | return "SHA-256"; | ||
| 230 | } | ||
| 231 | } | ||
| 232 | |||
| 233 | static final class SHA384 extends DOMDigestMethod { | ||
| 234 | SHA384(AlgorithmParameterSpec params) | ||
| 235 | throws InvalidAlgorithmParameterException { | ||
| 236 | super(params); | ||
| 237 | } | ||
| 238 | SHA384(Element dmElem) throws MarshalException { | ||
| 239 | super(dmElem); | ||
| 240 | } | ||
| 241 | public String getAlgorithm() { | ||
| 242 | return SHA384; | ||
| 243 | } | ||
| 244 | String getMessageDigestAlgorithm() { | ||
| 245 | return "SHA-384"; | ||
| 246 | } | ||
| 247 | } | ||
| 248 | |||
| 249 | static final class SHA512 extends DOMDigestMethod { | ||
| 250 | SHA512(AlgorithmParameterSpec params) | ||
| 251 | throws InvalidAlgorithmParameterException { | ||
| 252 | super(params); | ||
| 253 | } | ||
| 254 | SHA512(Element dmElem) throws MarshalException { | ||
| 255 | super(dmElem); | ||
| 256 | } | ||
| 257 | public String getAlgorithm() { | ||
| 258 | return DigestMethod.SHA512; | ||
| 259 | } | ||
| 260 | String getMessageDigestAlgorithm() { | ||
| 261 | return "SHA-512"; | ||
| 262 | } | ||
| 263 | } | ||
| 264 | } | ||
Binary file not shown.
| @@ -0,0 +1,46 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DOMEnvelopedTransform.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import java.security.InvalidAlgorithmParameterException; | ||
| 30 | import javax.xml.crypto.dsig.spec.TransformParameterSpec; | ||
| 31 | |||
| 32 | /** | ||
| 33 | * DOM-based implementation of Enveloped Signature Transform. | ||
| 34 | * (Uses Apache XML-Sec Transform implementation) | ||
| 35 | * | ||
| 36 | * @author Sean Mullan | ||
| 37 | */ | ||
| 38 | public final class DOMEnvelopedTransform extends ApacheTransform { | ||
| 39 | |||
| 40 | public void init(TransformParameterSpec params) | ||
| 41 | throws InvalidAlgorithmParameterException { | ||
| 42 | if (params != null) { | ||
| 43 | throw new InvalidAlgorithmParameterException("params must be null"); | ||
| 44 | } | ||
| 45 | } | ||
| 46 | } | ||
Binary file not shown.
| @@ -0,0 +1,155 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DOMExcC14NMethod.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import javax.xml.crypto.*; | ||
| 30 | import javax.xml.crypto.dsig.*; | ||
| 31 | import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec; | ||
| 32 | import javax.xml.crypto.dsig.spec.ExcC14NParameterSpec; | ||
| 33 | import javax.xml.crypto.dsig.spec.TransformParameterSpec; | ||
| 34 | |||
| 35 | import java.security.InvalidAlgorithmParameterException; | ||
| 36 | import java.security.spec.AlgorithmParameterSpec; | ||
| 37 | import java.util.*; | ||
| 38 | import org.w3c.dom.Element; | ||
| 39 | |||
| 40 | import com.sun.org.apache.xml.internal.security.c14n.Canonicalizer; | ||
| 41 | import com.sun.org.apache.xml.internal.security.c14n.InvalidCanonicalizerException; | ||
| 42 | |||
| 43 | /** | ||
| 44 | * DOM-based implementation of CanonicalizationMethod for Exclusive | ||
| 45 | * Canonical XML algorithm (with or without comments). | ||
| 46 | * Uses Apache XML-Sec Canonicalizer. | ||
| 47 | * | ||
| 48 | * @author Sean Mullan | ||
| 49 | */ | ||
| 50 | public final class DOMExcC14NMethod extends ApacheCanonicalizer { | ||
| 51 | |||
| 52 | public void init(TransformParameterSpec params) | ||
| 53 | throws InvalidAlgorithmParameterException { | ||
| 54 | if (params != null) { | ||
| 55 | if (!(params instanceof ExcC14NParameterSpec)) { | ||
| 56 | throw new InvalidAlgorithmParameterException | ||
| 57 | ("params must be of type ExcC14NParameterSpec"); | ||
| 58 | } | ||
| 59 | this.params = (C14NMethodParameterSpec) params; | ||
| 60 | } | ||
| 61 | } | ||
| 62 | |||
| 63 | public void init(XMLStructure parent, XMLCryptoContext context) | ||
| 64 | throws InvalidAlgorithmParameterException { | ||
| 65 | super.init(parent, context); | ||
| 66 | Element paramsElem = DOMUtils.getFirstChildElement(transformElem); | ||
| 67 | if (paramsElem == null) { | ||
| 68 | this.params = null; | ||
| 69 | this.inclusiveNamespaces = null; | ||
| 70 | return; | ||
| 71 | } | ||
| 72 | unmarshalParams(paramsElem); | ||
| 73 | } | ||
| 74 | |||
| 75 | private void unmarshalParams(Element paramsElem) { | ||
| 76 | String prefixListAttr = paramsElem.getAttributeNS(null, "PrefixList"); | ||
| 77 | this.inclusiveNamespaces = prefixListAttr; | ||
| 78 | int begin = 0; | ||
| 79 | int end = prefixListAttr.indexOf(' '); | ||
| 80 | List prefixList = new ArrayList(); | ||
| 81 | while (end != -1) { | ||
| 82 | prefixList.add(prefixListAttr.substring(begin, end)); | ||
| 83 | begin = end + 1; | ||
| 84 | end = prefixListAttr.indexOf(' ', begin); | ||
| 85 | } | ||
| 86 | if (begin <= prefixListAttr.length()) { | ||
| 87 | prefixList.add(prefixListAttr.substring(begin)); | ||
| 88 | } | ||
| 89 | this.params = new ExcC14NParameterSpec(prefixList); | ||
| 90 | } | ||
| 91 | |||
| 92 | public void marshalParams(XMLStructure parent, XMLCryptoContext context) | ||
| 93 | throws MarshalException { | ||
| 94 | |||
| 95 | super.marshalParams(parent, context); | ||
| 96 | AlgorithmParameterSpec spec = getParameterSpec(); | ||
| 97 | if (spec == null) { | ||
| 98 | return; | ||
| 99 | } | ||
| 100 | |||
| 101 | String prefix = | ||
| 102 | DOMUtils.getNSPrefix(context, CanonicalizationMethod.EXCLUSIVE); | ||
| 103 | Element excElem = DOMUtils.createElement | ||
| 104 | (ownerDoc, "InclusiveNamespaces", | ||
| 105 | CanonicalizationMethod.EXCLUSIVE, prefix); | ||
| 106 | if (prefix == null || prefix.length() == 0) { | ||
| 107 | excElem.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", | ||
| 108 | CanonicalizationMethod.EXCLUSIVE); | ||
| 109 | } else { | ||
| 110 | excElem.setAttributeNS("http://www.w3.org/2000/xmlns/", | ||
| 111 | "xmlns:" + prefix, CanonicalizationMethod.EXCLUSIVE); | ||
| 112 | } | ||
| 113 | |||
| 114 | ExcC14NParameterSpec params = (ExcC14NParameterSpec) spec; | ||
| 115 | StringBuffer prefixListAttr = new StringBuffer(""); | ||
| 116 | List prefixList = params.getPrefixList(); | ||
| 117 | for (int i = 0, size = prefixList.size(); i < size; i++) { | ||
| 118 | prefixListAttr.append((String) prefixList.get(i)); | ||
| 119 | if (i < size - 1) { | ||
| 120 | prefixListAttr.append(" "); | ||
| 121 | } | ||
| 122 | } | ||
| 123 | DOMUtils.setAttribute(excElem, "PrefixList", prefixListAttr.toString()); | ||
| 124 | this.inclusiveNamespaces = prefixListAttr.toString(); | ||
| 125 | transformElem.appendChild(excElem); | ||
| 126 | } | ||
| 127 | |||
| 128 | public String getParamsNSURI() { | ||
| 129 | return CanonicalizationMethod.EXCLUSIVE; | ||
| 130 | } | ||
| 131 | |||
| 132 | public Data transform(Data data, XMLCryptoContext xc) | ||
| 133 | throws TransformException { | ||
| 134 | |||
| 135 | // ignore comments if dereferencing same-document URI that require | ||
| 136 | // you to omit comments, even if the Transform says otherwise - | ||
| 137 | // this is to be compliant with section 4.3.3.3 of W3C Rec. | ||
| 138 | if (data instanceof DOMSubTreeData) { | ||
| 139 | DOMSubTreeData subTree = (DOMSubTreeData) data; | ||
| 140 | if (subTree.excludeComments()) { | ||
| 141 | try { | ||
| 142 | apacheCanonicalizer = Canonicalizer.getInstance | ||
| 143 | (CanonicalizationMethod.EXCLUSIVE); | ||
| 144 | } catch (InvalidCanonicalizerException ice) { | ||
| 145 | throw new TransformException | ||
| 146 | ("Couldn't find Canonicalizer for: " + | ||
| 147 | CanonicalizationMethod.EXCLUSIVE + ": " + | ||
| 148 | ice.getMessage(), ice); | ||
| 149 | } | ||
| 150 | } | ||
| 151 | } | ||
| 152 | |||
| 153 | return canonicalize(data, xc); | ||
| 154 | } | ||
| 155 | } | ||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,268 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DOMHMACSignatureMethod.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import javax.xml.crypto.*; | ||
| 30 | import javax.xml.crypto.dsig.*; | ||
| 31 | import javax.xml.crypto.dsig.spec.HMACParameterSpec; | ||
| 32 | import javax.xml.crypto.dsig.spec.SignatureMethodParameterSpec; | ||
| 33 | |||
| 34 | import java.security.InvalidAlgorithmParameterException; | ||
| 35 | import java.security.InvalidKeyException; | ||
| 36 | import java.security.Key; | ||
| 37 | import java.security.MessageDigest; | ||
| 38 | import java.security.NoSuchAlgorithmException; | ||
| 39 | import java.security.SignatureException; | ||
| 40 | import java.security.spec.AlgorithmParameterSpec; | ||
| 41 | import java.util.logging.Level; | ||
| 42 | import java.util.logging.Logger; | ||
| 43 | import javax.crypto.Mac; | ||
| 44 | import javax.crypto.SecretKey; | ||
| 45 | import org.w3c.dom.Document; | ||
| 46 | import org.w3c.dom.Element; | ||
| 47 | |||
| 48 | import org.jcp.xml.dsig.internal.MacOutputStream; | ||
| 49 | |||
| 50 | /** | ||
| 51 | * DOM-based implementation of HMAC SignatureMethod. | ||
| 52 | * | ||
| 53 | * @author Sean Mullan | ||
| 54 | */ | ||
| 55 | public abstract class DOMHMACSignatureMethod extends DOMSignatureMethod { | ||
| 56 | |||
| 57 | private static Logger log = | ||
| 58 | Logger.getLogger("org.jcp.xml.dsig.internal.dom"); | ||
| 59 | private Mac hmac; | ||
| 60 | private int outputLength; | ||
| 61 | private boolean outputLengthSet; | ||
| 62 | |||
| 63 | /** | ||
| 64 | * Creates a <code>DOMHMACSignatureMethod</code> with the specified params | ||
| 65 | * | ||
| 66 | * @param params algorithm-specific parameters (may be <code>null</code>) | ||
| 67 | * @throws InvalidAlgorithmParameterException if params are inappropriate | ||
| 68 | */ | ||
| 69 | DOMHMACSignatureMethod(AlgorithmParameterSpec params) | ||
| 70 | throws InvalidAlgorithmParameterException { | ||
| 71 | super(params); | ||
| 72 | } | ||
| 73 | |||
| 74 | /** | ||
| 75 | * Creates a <code>DOMHMACSignatureMethod</code> from an element. | ||
| 76 | * | ||
| 77 | * @param smElem a SignatureMethod element | ||
| 78 | */ | ||
| 79 | DOMHMACSignatureMethod(Element smElem) throws MarshalException { | ||
| 80 | super(smElem); | ||
| 81 | } | ||
| 82 | |||
| 83 | void checkParams(SignatureMethodParameterSpec params) | ||
| 84 | throws InvalidAlgorithmParameterException { | ||
| 85 | if (params != null) { | ||
| 86 | if (!(params instanceof HMACParameterSpec)) { | ||
| 87 | throw new InvalidAlgorithmParameterException | ||
| 88 | ("params must be of type HMACParameterSpec"); | ||
| 89 | } | ||
| 90 | outputLength = ((HMACParameterSpec) params).getOutputLength(); | ||
| 91 | outputLengthSet = true; | ||
| 92 | if (log.isLoggable(Level.FINE)) { | ||
| 93 | log.log(Level.FINE, | ||
| 94 | "Setting outputLength from HMACParameterSpec to: " | ||
| 95 | + outputLength); | ||
| 96 | } | ||
| 97 | } else { | ||
| 98 | outputLength = -1; | ||
| 99 | } | ||
| 100 | } | ||
| 101 | |||
| 102 | SignatureMethodParameterSpec unmarshalParams(Element paramsElem) | ||
| 103 | throws MarshalException { | ||
| 104 | outputLength = new Integer | ||
| 105 | (paramsElem.getFirstChild().getNodeValue()).intValue(); | ||
| 106 | outputLengthSet = true; | ||
| 107 | if (log.isLoggable(Level.FINE)) { | ||
| 108 | log.log(Level.FINE, "unmarshalled outputLength: " + outputLength); | ||
| 109 | } | ||
| 110 | return new HMACParameterSpec(outputLength); | ||
| 111 | } | ||
| 112 | |||
| 113 | void marshalParams(Element parent, String prefix) | ||
| 114 | throws MarshalException { | ||
| 115 | |||
| 116 | Document ownerDoc = DOMUtils.getOwnerDocument(parent); | ||
| 117 | Element hmacElem = DOMUtils.createElement(ownerDoc, "HMACOutputLength", | ||
| 118 | XMLSignature.XMLNS, prefix); | ||
| 119 | hmacElem.appendChild(ownerDoc.createTextNode | ||
| 120 | (String.valueOf(outputLength))); | ||
| 121 | |||
| 122 | parent.appendChild(hmacElem); | ||
| 123 | } | ||
| 124 | |||
| 125 | boolean verify(Key key, DOMSignedInfo si, byte[] sig, | ||
| 126 | XMLValidateContext context) | ||
| 127 | throws InvalidKeyException, SignatureException, XMLSignatureException { | ||
| 128 | if (key == null || si == null || sig == null) { | ||
| 129 | throw new NullPointerException(); | ||
| 130 | } | ||
| 131 | if (!(key instanceof SecretKey)) { | ||
| 132 | throw new InvalidKeyException("key must be SecretKey"); | ||
| 133 | } | ||
| 134 | if (hmac == null) { | ||
| 135 | try { | ||
| 136 | hmac = Mac.getInstance(getSignatureAlgorithm()); | ||
| 137 | } catch (NoSuchAlgorithmException nsae) { | ||
| 138 | throw new XMLSignatureException(nsae); | ||
| 139 | } | ||
| 140 | } | ||
| 141 | if (outputLengthSet && outputLength < getDigestLength()) { | ||
| 142 | throw new XMLSignatureException | ||
| 143 | ("HMACOutputLength must not be less than " + getDigestLength()); | ||
| 144 | } | ||
| 145 | hmac.init((SecretKey) key); | ||
| 146 | si.canonicalize(context, new MacOutputStream(hmac)); | ||
| 147 | byte[] result = hmac.doFinal(); | ||
| 148 | |||
| 149 | return MessageDigest.isEqual(sig, result); | ||
| 150 | } | ||
| 151 | |||
| 152 | byte[] sign(Key key, DOMSignedInfo si, XMLSignContext context) | ||
| 153 | throws InvalidKeyException, XMLSignatureException { | ||
| 154 | if (key == null || si == null) { | ||
| 155 | throw new NullPointerException(); | ||
| 156 | } | ||
| 157 | if (!(key instanceof SecretKey)) { | ||
| 158 | throw new InvalidKeyException("key must be SecretKey"); | ||
| 159 | } | ||
| 160 | if (hmac == null) { | ||
| 161 | try { | ||
| 162 | hmac = Mac.getInstance(getSignatureAlgorithm()); | ||
| 163 | } catch (NoSuchAlgorithmException nsae) { | ||
| 164 | throw new XMLSignatureException(nsae); | ||
| 165 | } | ||
| 166 | } | ||
| 167 | if (outputLengthSet && outputLength < getDigestLength()) { | ||
| 168 | throw new XMLSignatureException | ||
| 169 | ("HMACOutputLength must not be less than " + getDigestLength()); | ||
| 170 | } | ||
| 171 | hmac.init((SecretKey) key); | ||
| 172 | si.canonicalize(context, new MacOutputStream(hmac)); | ||
| 173 | return hmac.doFinal(); | ||
| 174 | } | ||
| 175 | |||
| 176 | boolean paramsEqual(AlgorithmParameterSpec spec) { | ||
| 177 | if (getParameterSpec() == spec) { | ||
| 178 | return true; | ||
| 179 | } | ||
| 180 | if (!(spec instanceof HMACParameterSpec)) { | ||
| 181 | return false; | ||
| 182 | } | ||
| 183 | HMACParameterSpec ospec = (HMACParameterSpec) spec; | ||
| 184 | |||
| 185 | return (outputLength == ospec.getOutputLength()); | ||
| 186 | } | ||
| 187 | |||
| 188 | /** | ||
| 189 | * Returns the output length of the hash/digest. | ||
| 190 | */ | ||
| 191 | abstract int getDigestLength(); | ||
| 192 | |||
| 193 | static final class SHA1 extends DOMHMACSignatureMethod { | ||
| 194 | SHA1(AlgorithmParameterSpec params) | ||
| 195 | throws InvalidAlgorithmParameterException { | ||
| 196 | super(params); | ||
| 197 | } | ||
| 198 | SHA1(Element dmElem) throws MarshalException { | ||
| 199 | super(dmElem); | ||
| 200 | } | ||
| 201 | public String getAlgorithm() { | ||
| 202 | return SignatureMethod.HMAC_SHA1; | ||
| 203 | } | ||
| 204 | String getSignatureAlgorithm() { | ||
| 205 | return "HmacSHA1"; | ||
| 206 | } | ||
| 207 | int getDigestLength() { | ||
| 208 | return 160; | ||
| 209 | } | ||
| 210 | } | ||
| 211 | |||
| 212 | static final class SHA256 extends DOMHMACSignatureMethod { | ||
| 213 | SHA256(AlgorithmParameterSpec params) | ||
| 214 | throws InvalidAlgorithmParameterException { | ||
| 215 | super(params); | ||
| 216 | } | ||
| 217 | SHA256(Element dmElem) throws MarshalException { | ||
| 218 | super(dmElem); | ||
| 219 | } | ||
| 220 | public String getAlgorithm() { | ||
| 221 | return HMAC_SHA256; | ||
| 222 | } | ||
| 223 | String getSignatureAlgorithm() { | ||
| 224 | return "HmacSHA256"; | ||
| 225 | } | ||
| 226 | int getDigestLength() { | ||
| 227 | return 256; | ||
| 228 | } | ||
| 229 | } | ||
| 230 | |||
| 231 | static final class SHA384 extends DOMHMACSignatureMethod { | ||
| 232 | SHA384(AlgorithmParameterSpec params) | ||
| 233 | throws InvalidAlgorithmParameterException { | ||
| 234 | super(params); | ||
| 235 | } | ||
| 236 | SHA384(Element dmElem) throws MarshalException { | ||
| 237 | super(dmElem); | ||
| 238 | } | ||
| 239 | public String getAlgorithm() { | ||
| 240 | return HMAC_SHA384; | ||
| 241 | } | ||
| 242 | String getSignatureAlgorithm() { | ||
| 243 | return "HmacSHA384"; | ||
| 244 | } | ||
| 245 | int getDigestLength() { | ||
| 246 | return 384; | ||
| 247 | } | ||
| 248 | } | ||
| 249 | |||
| 250 | static final class SHA512 extends DOMHMACSignatureMethod { | ||
| 251 | SHA512(AlgorithmParameterSpec params) | ||
| 252 | throws InvalidAlgorithmParameterException { | ||
| 253 | super(params); | ||
| 254 | } | ||
| 255 | SHA512(Element dmElem) throws MarshalException { | ||
| 256 | super(dmElem); | ||
| 257 | } | ||
| 258 | public String getAlgorithm() { | ||
| 259 | return HMAC_SHA512; | ||
| 260 | } | ||
| 261 | String getSignatureAlgorithm() { | ||
| 262 | return "HmacSHA512"; | ||
| 263 | } | ||
| 264 | int getDigestLength() { | ||
| 265 | return 512; | ||
| 266 | } | ||
| 267 | } | ||
| 268 | } | ||
Binary file not shown.
| @@ -0,0 +1,204 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DOMKeyInfo.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import javax.xml.crypto.*; | ||
| 30 | import javax.xml.crypto.dsig.*; | ||
| 31 | import javax.xml.crypto.dsig.dom.DOMSignContext; | ||
| 32 | import javax.xml.crypto.dsig.keyinfo.KeyInfo; | ||
| 33 | import javax.xml.crypto.dom.*; | ||
| 34 | |||
| 35 | import java.security.Provider; | ||
| 36 | import java.util.*; | ||
| 37 | import org.w3c.dom.Document; | ||
| 38 | import org.w3c.dom.Element; | ||
| 39 | import org.w3c.dom.Node; | ||
| 40 | import org.w3c.dom.NodeList; | ||
| 41 | |||
| 42 | /** | ||
| 43 | * DOM-based implementation of KeyInfo. | ||
| 44 | * | ||
| 45 | * @author Sean Mullan | ||
| 46 | */ | ||
| 47 | public final class DOMKeyInfo extends DOMStructure implements KeyInfo { | ||
| 48 | |||
| 49 | private final String id; | ||
| 50 | private final List keyInfoTypes; | ||
| 51 | |||
| 52 | /** | ||
| 53 | * Creates a <code>DOMKeyInfo</code>. | ||
| 54 | * | ||
| 55 | * @param content a list of one or more {@link XMLStructure}s representing | ||
| 56 | * key information types. The list is defensively copied to protect | ||
| 57 | * against subsequent modification. | ||
| 58 | * @param id an ID attribute | ||
| 59 | * @throws NullPointerException if <code>content</code> is <code>null</code> | ||
| 60 | * @throws IllegalArgumentException if <code>content</code> is empty | ||
| 61 | * @throws ClassCastException if <code>content</code> contains any entries | ||
| 62 | * that are not of type {@link XMLStructure} | ||
| 63 | */ | ||
| 64 | public DOMKeyInfo(List content, String id) { | ||
| 65 | if (content == null) { | ||
| 66 | throw new NullPointerException("content cannot be null"); | ||
| 67 | } | ||
| 68 | List typesCopy = new ArrayList(content); | ||
| 69 | if (typesCopy.isEmpty()) { | ||
| 70 | throw new IllegalArgumentException("content cannot be empty"); | ||
| 71 | } | ||
| 72 | for (int i = 0, size = typesCopy.size(); i < size; i++) { | ||
| 73 | if (!(typesCopy.get(i) instanceof XMLStructure)) { | ||
| 74 | throw new ClassCastException | ||
| 75 | ("content["+i+"] is not a valid KeyInfo type"); | ||
| 76 | } | ||
| 77 | } | ||
| 78 | this.keyInfoTypes = Collections.unmodifiableList(typesCopy); | ||
| 79 | this.id = id; | ||
| 80 | } | ||
| 81 | |||
| 82 | /** | ||
| 83 | * Creates a <code>DOMKeyInfo</code> from XML. | ||
| 84 | * | ||
| 85 | * @param kiElem KeyInfo element | ||
| 86 | */ | ||
| 87 | public DOMKeyInfo(Element kiElem, XMLCryptoContext context, | ||
| 88 | Provider provider) throws MarshalException { | ||
| 89 | // get Id attribute, if specified | ||
| 90 | id = DOMUtils.getAttributeValue(kiElem, "Id"); | ||
| 91 | |||
| 92 | // get all children nodes | ||
| 93 | NodeList nl = kiElem.getChildNodes(); | ||
| 94 | int length = nl.getLength(); | ||
| 95 | if (length < 1) { | ||
| 96 | throw new MarshalException | ||
| 97 | ("KeyInfo must contain at least one type"); | ||
| 98 | } | ||
| 99 | List content = new ArrayList(length); | ||
| 100 | for (int i = 0; i < length; i++) { | ||
| 101 | Node child = nl.item(i); | ||
| 102 | // ignore all non-Element nodes | ||
| 103 | if (child.getNodeType() != Node.ELEMENT_NODE) { | ||
| 104 | continue; | ||
| 105 | } | ||
| 106 | Element childElem = (Element) child; | ||
| 107 | String localName = childElem.getLocalName(); | ||
| 108 | if (localName.equals("X509Data")) { | ||
| 109 | content.add(new DOMX509Data(childElem)); | ||
| 110 | } else if (localName.equals("KeyName")) { | ||
| 111 | content.add(new DOMKeyName(childElem)); | ||
| 112 | } else if (localName.equals("KeyValue")) { | ||
| 113 | content.add(new DOMKeyValue(childElem)); | ||
| 114 | } else if (localName.equals("RetrievalMethod")) { | ||
| 115 | content.add | ||
| 116 | (new DOMRetrievalMethod(childElem, context, provider)); | ||
| 117 | } else if (localName.equals("PGPData")) { | ||
| 118 | content.add(new DOMPGPData(childElem)); | ||
| 119 | } else { //may be MgmtData, SPKIData or element from other namespace | ||
| 120 | content.add(new javax.xml.crypto.dom.DOMStructure((childElem))); | ||
| 121 | } | ||
| 122 | } | ||
| 123 | keyInfoTypes = Collections.unmodifiableList(content); | ||
| 124 | } | ||
| 125 | |||
| 126 | public String getId() { | ||
| 127 | return id; | ||
| 128 | } | ||
| 129 | |||
| 130 | public List getContent() { | ||
| 131 | return keyInfoTypes; | ||
| 132 | } | ||
| 133 | |||
| 134 | public void marshal(XMLStructure parent, XMLCryptoContext context) | ||
| 135 | throws MarshalException { | ||
| 136 | if (parent == null) { | ||
| 137 | throw new NullPointerException("parent is null"); | ||
| 138 | } | ||
| 139 | |||
| 140 | Node pNode = ((javax.xml.crypto.dom.DOMStructure) parent).getNode(); | ||
| 141 | String dsPrefix = DOMUtils.getSignaturePrefix(context); | ||
| 142 | Element kiElem = DOMUtils.createElement | ||
| 143 | (DOMUtils.getOwnerDocument(pNode), "KeyInfo", | ||
| 144 | XMLSignature.XMLNS, dsPrefix); | ||
| 145 | if (dsPrefix == null || dsPrefix.length() == 0) { | ||
| 146 | kiElem.setAttributeNS | ||
| 147 | ("http://www.w3.org/2000/xmlns/", "xmlns", XMLSignature.XMLNS); | ||
| 148 | } else { | ||
| 149 | kiElem.setAttributeNS | ||
| 150 | ("http://www.w3.org/2000/xmlns/", "xmlns:" + dsPrefix, | ||
| 151 | XMLSignature.XMLNS); | ||
| 152 | } | ||
| 153 | marshal(pNode, kiElem, null, dsPrefix, (DOMCryptoContext) context); | ||
| 154 | } | ||
| 155 | |||
| 156 | public void marshal(Node parent, String dsPrefix, | ||
| 157 | DOMCryptoContext context) throws MarshalException { | ||
| 158 | marshal(parent, null, dsPrefix, context); | ||
| 159 | } | ||
| 160 | |||
| 161 | public void marshal(Node parent, Node nextSibling, String dsPrefix, | ||
| 162 | DOMCryptoContext context) throws MarshalException { | ||
| 163 | Document ownerDoc = DOMUtils.getOwnerDocument(parent); | ||
| 164 | |||
| 165 | Element kiElem = DOMUtils.createElement | ||
| 166 | (ownerDoc, "KeyInfo", XMLSignature.XMLNS, dsPrefix); | ||
| 167 | marshal(parent, kiElem, nextSibling, dsPrefix, context); | ||
| 168 | } | ||
| 169 | |||
| 170 | private void marshal(Node parent, Element kiElem, Node nextSibling, | ||
| 171 | String dsPrefix, DOMCryptoContext context) throws MarshalException { | ||
| 172 | // create and append KeyInfoType elements | ||
| 173 | for (int i = 0, size = keyInfoTypes.size(); i < size; i++) { | ||
| 174 | XMLStructure kiType = (XMLStructure) keyInfoTypes.get(i); | ||
| 175 | if (kiType instanceof DOMStructure) { | ||
| 176 | ((DOMStructure) kiType).marshal(kiElem, dsPrefix, context); | ||
| 177 | } else { | ||
| 178 | DOMUtils.appendChild(kiElem, | ||
| 179 | ((javax.xml.crypto.dom.DOMStructure) kiType).getNode()); | ||
| 180 | } | ||
| 181 | } | ||
| 182 | |||
| 183 | // append id attribute | ||
| 184 | DOMUtils.setAttributeID(kiElem, "Id", id); | ||
| 185 | |||
| 186 | parent.insertBefore(kiElem, nextSibling); | ||
| 187 | } | ||
| 188 | |||
| 189 | public boolean equals(Object o) { | ||
| 190 | if (this == o) { | ||
| 191 | return true; | ||
| 192 | } | ||
| 193 | |||
| 194 | if (!(o instanceof KeyInfo)) { | ||
| 195 | return false; | ||
| 196 | } | ||
| 197 | KeyInfo oki = (KeyInfo) o; | ||
| 198 | |||
| 199 | boolean idsEqual = (id == null ? oki.getId() == null : | ||
| 200 | id.equals(oki.getId())); | ||
| 201 | |||
| 202 | return (keyInfoTypes.equals(oki.getContent()) && idsEqual); | ||
| 203 | } | ||
| 204 | } | ||
Binary file not shown.
| @@ -0,0 +1,142 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DOMKeyInfoFactory.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import java.math.BigInteger; | ||
| 30 | import java.security.KeyException; | ||
| 31 | import java.security.PublicKey; | ||
| 32 | import java.util.List; | ||
| 33 | import javax.xml.crypto.*; | ||
| 34 | import javax.xml.crypto.dsig.*; | ||
| 35 | import javax.xml.crypto.dom.*; | ||
| 36 | import javax.xml.crypto.dsig.keyinfo.*; | ||
| 37 | import org.w3c.dom.Document; | ||
| 38 | import org.w3c.dom.Element; | ||
| 39 | import org.w3c.dom.Node; | ||
| 40 | |||
| 41 | /** | ||
| 42 | * DOM-based implementation of KeyInfoFactory. | ||
| 43 | * | ||
| 44 | * @author Sean Mullan | ||
| 45 | */ | ||
| 46 | public final class DOMKeyInfoFactory extends KeyInfoFactory { | ||
| 47 | |||
| 48 | public DOMKeyInfoFactory() { } | ||
| 49 | |||
| 50 | public KeyInfo newKeyInfo(List content) { | ||
| 51 | return newKeyInfo(content, null); | ||
| 52 | } | ||
| 53 | |||
| 54 | public KeyInfo newKeyInfo(List content, String id) { | ||
| 55 | return new DOMKeyInfo(content, id); | ||
| 56 | } | ||
| 57 | |||
| 58 | public KeyName newKeyName(String name) { | ||
| 59 | return new DOMKeyName(name); | ||
| 60 | } | ||
| 61 | |||
| 62 | public KeyValue newKeyValue(PublicKey key) throws KeyException { | ||
| 63 | return new DOMKeyValue(key); | ||
| 64 | } | ||
| 65 | |||
| 66 | public PGPData newPGPData(byte[] keyId) { | ||
| 67 | return newPGPData(keyId, null, null); | ||
| 68 | } | ||
| 69 | |||
| 70 | public PGPData newPGPData(byte[] keyId, byte[] keyPacket, List other) { | ||
| 71 | return new DOMPGPData(keyId, keyPacket, other); | ||
| 72 | } | ||
| 73 | |||
| 74 | public PGPData newPGPData(byte[] keyPacket, List other) { | ||
| 75 | return new DOMPGPData(keyPacket, other); | ||
| 76 | } | ||
| 77 | |||
| 78 | public RetrievalMethod newRetrievalMethod(String uri) { | ||
| 79 | return newRetrievalMethod(uri, null, null); | ||
| 80 | } | ||
| 81 | |||
| 82 | public RetrievalMethod newRetrievalMethod(String uri, String type, | ||
| 83 | List transforms) { | ||
| 84 | if (uri == null) { | ||
| 85 | throw new NullPointerException("uri must not be null"); | ||
| 86 | } | ||
| 87 | return new DOMRetrievalMethod(uri, type, transforms); | ||
| 88 | } | ||
| 89 | |||
| 90 | public X509Data newX509Data(List content) { | ||
| 91 | return new DOMX509Data(content); | ||
| 92 | } | ||
| 93 | |||
| 94 | public X509IssuerSerial newX509IssuerSerial(String issuerName, | ||
| 95 | BigInteger serialNumber) { | ||
| 96 | return new DOMX509IssuerSerial(issuerName, serialNumber); | ||
| 97 | } | ||
| 98 | |||
| 99 | public boolean isFeatureSupported(String feature) { | ||
| 100 | if (feature == null) { | ||
| 101 | throw new NullPointerException(); | ||
| 102 | } else { | ||
| 103 | return false; | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | public URIDereferencer getURIDereferencer() { | ||
| 108 | return DOMURIDereferencer.INSTANCE; | ||
| 109 | } | ||
| 110 | |||
| 111 | public KeyInfo unmarshalKeyInfo(XMLStructure xmlStructure) | ||
| 112 | throws MarshalException { | ||
| 113 | if (xmlStructure == null) { | ||
| 114 | throw new NullPointerException("xmlStructure cannot be null"); | ||
| 115 | } | ||
| 116 | Node node = | ||
| 117 | ((javax.xml.crypto.dom.DOMStructure) xmlStructure).getNode(); | ||
| 118 | node.normalize(); | ||
| 119 | |||
| 120 | Element element = null; | ||
| 121 | if (node.getNodeType() == Node.DOCUMENT_NODE) { | ||
| 122 | element = ((Document) node).getDocumentElement(); | ||
| 123 | } else if (node.getNodeType() == Node.ELEMENT_NODE) { | ||
| 124 | element = (Element) node; | ||
| 125 | } else { | ||
| 126 | throw new MarshalException | ||
| 127 | ("xmlStructure does not contain a proper Node"); | ||
| 128 | } | ||
| 129 | |||
| 130 | // check tag | ||
| 131 | String tag = element.getLocalName(); | ||
| 132 | if (tag == null) { | ||
| 133 | throw new MarshalException("Document implementation must " + | ||
| 134 | "support DOM Level 2 and be namespace aware"); | ||
| 135 | } | ||
| 136 | if (tag.equals("KeyInfo")) { | ||
| 137 | return new DOMKeyInfo(element, null, getProvider()); | ||
| 138 | } else { | ||
| 139 | throw new MarshalException("invalid KeyInfo tag: " + tag); | ||
| 140 | } | ||
| 141 | } | ||
| 142 | } | ||
Binary file not shown.
| @@ -0,0 +1,93 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DOMKeyName.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import javax.xml.crypto.*; | ||
| 30 | import javax.xml.crypto.dom.DOMCryptoContext; | ||
| 31 | import javax.xml.crypto.dsig.*; | ||
| 32 | import javax.xml.crypto.dsig.keyinfo.KeyName; | ||
| 33 | |||
| 34 | import org.w3c.dom.Document; | ||
| 35 | import org.w3c.dom.Element; | ||
| 36 | import org.w3c.dom.Node; | ||
| 37 | |||
| 38 | /** | ||
| 39 | * DOM-based implementation of KeyName. | ||
| 40 | * | ||
| 41 | * @author Sean Mullan | ||
| 42 | */ | ||
| 43 | public final class DOMKeyName extends DOMStructure implements KeyName { | ||
| 44 | |||
| 45 | private final String name; | ||
| 46 | |||
| 47 | /** | ||
| 48 | * Creates a <code>DOMKeyName</code>. | ||
| 49 | * | ||
| 50 | * @param name the name of the key identifier | ||
| 51 | * @throws NullPointerException if <code>name</code> is null | ||
| 52 | */ | ||
| 53 | public DOMKeyName(String name) { | ||
| 54 | if (name == null) { | ||
| 55 | throw new NullPointerException("name cannot be null"); | ||
| 56 | } | ||
| 57 | this.name = name; | ||
| 58 | } | ||
| 59 | |||
| 60 | /** | ||
| 61 | * Creates a <code>DOMKeyName</code> from a KeyName element. | ||
| 62 | * | ||
| 63 | * @param knElem a KeyName element | ||
| 64 | */ | ||
| 65 | public DOMKeyName(Element knElem) { | ||
| 66 | name = knElem.getFirstChild().getNodeValue(); | ||
| 67 | } | ||
| 68 | |||
| 69 | public String getName() { | ||
| 70 | return name; | ||
| 71 | } | ||
| 72 | |||
| 73 | public void marshal(Node parent, String dsPrefix, DOMCryptoContext context) | ||
| 74 | throws MarshalException { | ||
| 75 | Document ownerDoc = DOMUtils.getOwnerDocument(parent); | ||
| 76 | // prepend namespace prefix, if necessary | ||
| 77 | Element knElem = DOMUtils.createElement | ||
| 78 | (ownerDoc, "KeyName", XMLSignature.XMLNS, dsPrefix); | ||
| 79 | knElem.appendChild(ownerDoc.createTextNode(name)); | ||
| 80 | parent.appendChild(knElem); | ||
| 81 | } | ||
| 82 | |||
| 83 | public boolean equals(Object obj) { | ||
| 84 | if (this == obj) { | ||
| 85 | return true; | ||
| 86 | } | ||
| 87 | if (!(obj instanceof KeyName)) { | ||
| 88 | return false; | ||
| 89 | } | ||
| 90 | KeyName okn = (KeyName) obj; | ||
| 91 | return name.equals(okn.getName()); | ||
| 92 | } | ||
| 93 | } | ||
Binary file not shown.
| @@ -0,0 +1,272 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DOMKeyValue.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import javax.xml.crypto.*; | ||
| 30 | import javax.xml.crypto.dom.DOMCryptoContext; | ||
| 31 | import javax.xml.crypto.dsig.*; | ||
| 32 | import javax.xml.crypto.dsig.keyinfo.KeyValue; | ||
| 33 | |||
| 34 | import java.security.KeyException; | ||
| 35 | import java.security.KeyFactory; | ||
| 36 | import java.security.NoSuchAlgorithmException; | ||
| 37 | import java.security.PublicKey; | ||
| 38 | import java.security.interfaces.DSAParams; | ||
| 39 | import java.security.interfaces.DSAPublicKey; | ||
| 40 | import java.security.interfaces.RSAPublicKey; | ||
| 41 | import java.security.spec.DSAPublicKeySpec; | ||
| 42 | import java.security.spec.InvalidKeySpecException; | ||
| 43 | import java.security.spec.KeySpec; | ||
| 44 | import java.security.spec.RSAPublicKeySpec; | ||
| 45 | import org.w3c.dom.Document; | ||
| 46 | import org.w3c.dom.Element; | ||
| 47 | import org.w3c.dom.Node; | ||
| 48 | |||
| 49 | /** | ||
| 50 | * DOM-based implementation of KeyValue. | ||
| 51 | * | ||
| 52 | * @author Sean Mullan | ||
| 53 | */ | ||
| 54 | public final class DOMKeyValue extends DOMStructure implements KeyValue { | ||
| 55 | |||
| 56 | private KeyFactory rsakf, dsakf; | ||
| 57 | private PublicKey publicKey; | ||
| 58 | private javax.xml.crypto.dom.DOMStructure externalPublicKey; | ||
| 59 | |||
| 60 | // DSAKeyValue CryptoBinaries | ||
| 61 | private DOMCryptoBinary p, q, g, y, j, seed, pgen; | ||
| 62 | |||
| 63 | // RSAKeyValue CryptoBinaries | ||
| 64 | private DOMCryptoBinary modulus, exponent; | ||
| 65 | |||
| 66 | public DOMKeyValue(PublicKey key) throws KeyException { | ||
| 67 | if (key == null) { | ||
| 68 | throw new NullPointerException("key cannot be null"); | ||
| 69 | } | ||
| 70 | this.publicKey = key; | ||
| 71 | if (key instanceof DSAPublicKey) { | ||
| 72 | DSAPublicKey dkey = (DSAPublicKey) key; | ||
| 73 | DSAParams params = dkey.getParams(); | ||
| 74 | p = new DOMCryptoBinary(params.getP()); | ||
| 75 | q = new DOMCryptoBinary(params.getQ()); | ||
| 76 | g = new DOMCryptoBinary(params.getG()); | ||
| 77 | y = new DOMCryptoBinary(dkey.getY()); | ||
| 78 | } else if (key instanceof RSAPublicKey) { | ||
| 79 | RSAPublicKey rkey = (RSAPublicKey) key; | ||
| 80 | exponent = new DOMCryptoBinary(rkey.getPublicExponent()); | ||
| 81 | modulus = new DOMCryptoBinary(rkey.getModulus()); | ||
| 82 | } else { | ||
| 83 | throw new KeyException("unsupported key algorithm: " + | ||
| 84 | key.getAlgorithm()); | ||
| 85 | } | ||
| 86 | } | ||
| 87 | |||
| 88 | /** | ||
| 89 | * Creates a <code>DOMKeyValue</code> from an element. | ||
| 90 | * | ||
| 91 | * @param kvElem a KeyValue element | ||
| 92 | */ | ||
| 93 | public DOMKeyValue(Element kvElem) throws MarshalException { | ||
| 94 | Element kvtElem = DOMUtils.getFirstChildElement(kvElem); | ||
| 95 | if (kvtElem.getLocalName().equals("DSAKeyValue")) { | ||
| 96 | publicKey = unmarshalDSAKeyValue(kvtElem); | ||
| 97 | } else if (kvtElem.getLocalName().equals("RSAKeyValue")) { | ||
| 98 | publicKey = unmarshalRSAKeyValue(kvtElem); | ||
| 99 | } else { | ||
| 100 | publicKey = null; | ||
| 101 | externalPublicKey = new javax.xml.crypto.dom.DOMStructure(kvtElem); | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 | public PublicKey getPublicKey() throws KeyException { | ||
| 106 | if (publicKey == null) { | ||
| 107 | throw new KeyException("can't convert KeyValue to PublicKey"); | ||
| 108 | } else { | ||
| 109 | return publicKey; | ||
| 110 | } | ||
| 111 | } | ||
| 112 | |||
| 113 | public void marshal(Node parent, String dsPrefix, DOMCryptoContext context) | ||
| 114 | throws MarshalException { | ||
| 115 | Document ownerDoc = DOMUtils.getOwnerDocument(parent); | ||
| 116 | |||
| 117 | // create KeyValue element | ||
| 118 | Element kvElem = DOMUtils.createElement | ||
| 119 | (ownerDoc, "KeyValue", XMLSignature.XMLNS, dsPrefix); | ||
| 120 | marshalPublicKey(kvElem, ownerDoc, dsPrefix, context); | ||
| 121 | |||
| 122 | parent.appendChild(kvElem); | ||
| 123 | } | ||
| 124 | |||
| 125 | private void marshalPublicKey(Node parent, Document doc, String dsPrefix, | ||
| 126 | DOMCryptoContext context) throws MarshalException { | ||
| 127 | if (publicKey != null) { | ||
| 128 | if (publicKey instanceof DSAPublicKey) { | ||
| 129 | // create and append DSAKeyValue element | ||
| 130 | marshalDSAPublicKey(parent, doc, dsPrefix, context); | ||
| 131 | } else if (publicKey instanceof RSAPublicKey) { | ||
| 132 | // create and append RSAKeyValue element | ||
| 133 | marshalRSAPublicKey(parent, doc, dsPrefix, context); | ||
| 134 | } else { | ||
| 135 | throw new MarshalException(publicKey.getAlgorithm() + | ||
| 136 | " public key algorithm not supported"); | ||
| 137 | } | ||
| 138 | } else { | ||
| 139 | parent.appendChild(externalPublicKey.getNode()); | ||
| 140 | } | ||
| 141 | } | ||
| 142 | |||
| 143 | private void marshalDSAPublicKey(Node parent, Document doc, | ||
| 144 | String dsPrefix, DOMCryptoContext context) throws MarshalException { | ||
| 145 | Element dsaElem = DOMUtils.createElement | ||
| 146 | (doc, "DSAKeyValue", XMLSignature.XMLNS, dsPrefix); | ||
| 147 | // parameters J, Seed & PgenCounter are not included | ||
| 148 | Element pElem = DOMUtils.createElement | ||
| 149 | (doc, "P", XMLSignature.XMLNS, dsPrefix); | ||
| 150 | Element qElem = DOMUtils.createElement | ||
| 151 | (doc, "Q", XMLSignature.XMLNS, dsPrefix); | ||
| 152 | Element gElem = DOMUtils.createElement | ||
| 153 | (doc, "G", XMLSignature.XMLNS, dsPrefix); | ||
| 154 | Element yElem = DOMUtils.createElement | ||
| 155 | (doc, "Y", XMLSignature.XMLNS, dsPrefix); | ||
| 156 | p.marshal(pElem, dsPrefix, context); | ||
| 157 | q.marshal(qElem, dsPrefix, context); | ||
| 158 | g.marshal(gElem, dsPrefix, context); | ||
| 159 | y.marshal(yElem, dsPrefix, context); | ||
| 160 | dsaElem.appendChild(pElem); | ||
| 161 | dsaElem.appendChild(qElem); | ||
| 162 | dsaElem.appendChild(gElem); | ||
| 163 | dsaElem.appendChild(yElem); | ||
| 164 | parent.appendChild(dsaElem); | ||
| 165 | } | ||
| 166 | |||
| 167 | private void marshalRSAPublicKey(Node parent, Document doc, | ||
| 168 | String dsPrefix, DOMCryptoContext context) throws MarshalException { | ||
| 169 | Element rsaElem = DOMUtils.createElement | ||
| 170 | (doc, "RSAKeyValue", XMLSignature.XMLNS, dsPrefix); | ||
| 171 | Element modulusElem = DOMUtils.createElement | ||
| 172 | (doc, "Modulus", XMLSignature.XMLNS, dsPrefix); | ||
| 173 | Element exponentElem = DOMUtils.createElement | ||
| 174 | (doc, "Exponent", XMLSignature.XMLNS, dsPrefix); | ||
| 175 | modulus.marshal(modulusElem, dsPrefix, context); | ||
| 176 | exponent.marshal(exponentElem, dsPrefix, context); | ||
| 177 | rsaElem.appendChild(modulusElem); | ||
| 178 | rsaElem.appendChild(exponentElem); | ||
| 179 | parent.appendChild(rsaElem); | ||
| 180 | } | ||
| 181 | |||
| 182 | private DSAPublicKey unmarshalDSAKeyValue(Element kvtElem) | ||
| 183 | throws MarshalException { | ||
| 184 | if (dsakf == null) { | ||
| 185 | try { | ||
| 186 | dsakf = KeyFactory.getInstance("DSA"); | ||
| 187 | } catch (NoSuchAlgorithmException e) { | ||
| 188 | throw new RuntimeException("unable to create DSA KeyFactory: " + | ||
| 189 | e.getMessage()); | ||
| 190 | } | ||
| 191 | } | ||
| 192 | Element curElem = DOMUtils.getFirstChildElement(kvtElem); | ||
| 193 | // check for P and Q | ||
| 194 | if (curElem.getLocalName().equals("P")) { | ||
| 195 | p = new DOMCryptoBinary(curElem.getFirstChild()); | ||
| 196 | curElem = DOMUtils.getNextSiblingElement(curElem); | ||
| 197 | q = new DOMCryptoBinary(curElem.getFirstChild()); | ||
| 198 | curElem = DOMUtils.getNextSiblingElement(curElem); | ||
| 199 | } | ||
| 200 | if (curElem.getLocalName().equals("G")) { | ||
| 201 | g = new DOMCryptoBinary(curElem.getFirstChild()); | ||
| 202 | curElem = DOMUtils.getNextSiblingElement(curElem); | ||
| 203 | } | ||
| 204 | y = new DOMCryptoBinary(curElem.getFirstChild()); | ||
| 205 | curElem = DOMUtils.getNextSiblingElement(curElem); | ||
| 206 | if (curElem != null && curElem.getLocalName().equals("J")) { | ||
| 207 | j = new DOMCryptoBinary(curElem.getFirstChild()); | ||
| 208 | curElem = DOMUtils.getNextSiblingElement(curElem); | ||
| 209 | } | ||
| 210 | if (curElem != null) { | ||
| 211 | seed = new DOMCryptoBinary(curElem.getFirstChild()); | ||
| 212 | curElem = DOMUtils.getNextSiblingElement(curElem); | ||
| 213 | pgen = new DOMCryptoBinary(curElem.getFirstChild()); | ||
| 214 | } | ||
| 215 | //@@@ do we care about j, pgenCounter or seed? | ||
| 216 | DSAPublicKeySpec spec = new DSAPublicKeySpec | ||
| 217 | (y.getBigNum(), p.getBigNum(), q.getBigNum(), g.getBigNum()); | ||
| 218 | return (DSAPublicKey) generatePublicKey(dsakf, spec); | ||
| 219 | } | ||
| 220 | |||
| 221 | private RSAPublicKey unmarshalRSAKeyValue(Element kvtElem) | ||
| 222 | throws MarshalException { | ||
| 223 | if (rsakf == null) { | ||
| 224 | try { | ||
| 225 | rsakf = KeyFactory.getInstance("RSA"); | ||
| 226 | } catch (NoSuchAlgorithmException e) { | ||
| 227 | throw new RuntimeException("unable to create RSA KeyFactory: " + | ||
| 228 | e.getMessage()); | ||
| 229 | } | ||
| 230 | } | ||
| 231 | Element modulusElem = DOMUtils.getFirstChildElement(kvtElem); | ||
| 232 | modulus = new DOMCryptoBinary(modulusElem.getFirstChild()); | ||
| 233 | Element exponentElem = DOMUtils.getNextSiblingElement(modulusElem); | ||
| 234 | exponent = new DOMCryptoBinary(exponentElem.getFirstChild()); | ||
| 235 | RSAPublicKeySpec spec = new RSAPublicKeySpec | ||
| 236 | (modulus.getBigNum(), exponent.getBigNum()); | ||
| 237 | return (RSAPublicKey) generatePublicKey(rsakf, spec); | ||
| 238 | } | ||
| 239 | |||
| 240 | private PublicKey generatePublicKey(KeyFactory kf, KeySpec keyspec) { | ||
| 241 | try { | ||
| 242 | return kf.generatePublic(keyspec); | ||
| 243 | } catch (InvalidKeySpecException e) { | ||
| 244 | //@@@ should dump exception to log | ||
| 245 | return null; | ||
| 246 | } | ||
| 247 | } | ||
| 248 | |||
| 249 | public boolean equals(Object obj) { | ||
| 250 | if (this == obj) { | ||
| 251 | return true; | ||
| 252 | } | ||
| 253 | if (!(obj instanceof KeyValue)) { | ||
| 254 | return false; | ||
| 255 | } | ||
| 256 | try { | ||
| 257 | KeyValue kv = (KeyValue) obj; | ||
| 258 | if (publicKey == null ) { | ||
| 259 | if (kv.getPublicKey() != null) { | ||
| 260 | return false; | ||
| 261 | } | ||
| 262 | } else if (!publicKey.equals(kv.getPublicKey())) { | ||
| 263 | return false; | ||
| 264 | } | ||
| 265 | } catch (KeyException ke) { | ||
| 266 | // no practical way to determine if the keys are equal | ||
| 267 | return false; | ||
| 268 | } | ||
| 269 | |||
| 270 | return true; | ||
| 271 | } | ||
| 272 | } | ||
Binary file not shown.
| @@ -0,0 +1,138 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DOMManifest.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import javax.xml.crypto.*; | ||
| 30 | import javax.xml.crypto.dom.DOMCryptoContext; | ||
| 31 | import javax.xml.crypto.dsig.*; | ||
| 32 | |||
| 33 | import java.security.Provider; | ||
| 34 | import java.util.*; | ||
| 35 | import org.w3c.dom.Document; | ||
| 36 | import org.w3c.dom.Element; | ||
| 37 | import org.w3c.dom.Node; | ||
| 38 | |||
| 39 | /** | ||
| 40 | * DOM-based implementation of Manifest. | ||
| 41 | * | ||
| 42 | * @author Sean Mullan | ||
| 43 | */ | ||
| 44 | public final class DOMManifest extends DOMStructure implements Manifest { | ||
| 45 | |||
| 46 | private final List references; | ||
| 47 | private final String id; | ||
| 48 | |||
| 49 | /** | ||
| 50 | * Creates a <code>DOMManifest</code> containing the specified | ||
| 51 | * list of {@link Reference}s and optional id. | ||
| 52 | * | ||
| 53 | * @param references a list of one or more <code>Reference</code>s. The list | ||
| 54 | * is defensively copied to protect against subsequent modification. | ||
| 55 | * @param id the id (may be <code>null</code> | ||
| 56 | * @throws NullPointerException if <code>references</code> is | ||
| 57 | * <code>null</code> | ||
| 58 | * @throws IllegalArgumentException if <code>references</code> is empty | ||
| 59 | * @throws ClassCastException if <code>references</code> contains any | ||
| 60 | * entries that are not of type {@link Reference} | ||
| 61 | */ | ||
| 62 | public DOMManifest(List references, String id) { | ||
| 63 | if (references == null) { | ||
| 64 | throw new NullPointerException("references cannot be null"); | ||
| 65 | } | ||
| 66 | List refCopy = new ArrayList(references); | ||
| 67 | if (refCopy.isEmpty()) { | ||
| 68 | throw new IllegalArgumentException("list of references must " + | ||
| 69 | "contain at least one entry"); | ||
| 70 | } | ||
| 71 | for (int i = 0, size = refCopy.size(); i < size; i++) { | ||
| 72 | if (!(refCopy.get(i) instanceof Reference)) { | ||
| 73 | throw new ClassCastException | ||
| 74 | ("references["+i+"] is not a valid type"); | ||
| 75 | } | ||
| 76 | } | ||
| 77 | this.references = Collections.unmodifiableList(refCopy); | ||
| 78 | this.id = id; | ||
| 79 | } | ||
| 80 | |||
| 81 | /** | ||
| 82 | * Creates a <code>DOMManifest</code> from an element. | ||
| 83 | * | ||
| 84 | * @param manElem a Manifest element | ||
| 85 | */ | ||
| 86 | public DOMManifest(Element manElem, XMLCryptoContext context, | ||
| 87 | Provider provider) throws MarshalException { | ||
| 88 | this.id = DOMUtils.getAttributeValue(manElem, "Id"); | ||
| 89 | Element refElem = DOMUtils.getFirstChildElement(manElem); | ||
| 90 | List refs = new ArrayList(); | ||
| 91 | while (refElem != null) { | ||
| 92 | refs.add(new DOMReference(refElem, context, provider)); | ||
| 93 | refElem = DOMUtils.getNextSiblingElement(refElem); | ||
| 94 | } | ||
| 95 | this.references = Collections.unmodifiableList(refs); | ||
| 96 | } | ||
| 97 | |||
| 98 | public String getId() { | ||
| 99 | return id; | ||
| 100 | } | ||
| 101 | |||
| 102 | public List getReferences() { | ||
| 103 | return references; | ||
| 104 | } | ||
| 105 | |||
| 106 | public void marshal(Node parent, String dsPrefix, DOMCryptoContext context) | ||
| 107 | throws MarshalException { | ||
| 108 | Document ownerDoc = DOMUtils.getOwnerDocument(parent); | ||
| 109 | |||
| 110 | Element manElem = DOMUtils.createElement | ||
| 111 | (ownerDoc, "Manifest", XMLSignature.XMLNS, dsPrefix); | ||
| 112 | |||
| 113 | DOMUtils.setAttributeID(manElem, "Id", id); | ||
| 114 | |||
| 115 | // add references | ||
| 116 | for (int i = 0, size = references.size(); i < size; i++) { | ||
| 117 | DOMReference ref = (DOMReference) references.get(i); | ||
| 118 | ref.marshal(manElem, dsPrefix, context); | ||
| 119 | } | ||
| 120 | parent.appendChild(manElem); | ||
| 121 | } | ||
| 122 | |||
| 123 | public boolean equals(Object o) { | ||
| 124 | if (this == o) { | ||
| 125 | return true; | ||
| 126 | } | ||
| 127 | |||
| 128 | if (!(o instanceof Manifest)) { | ||
| 129 | return false; | ||
| 130 | } | ||
| 131 | Manifest oman = (Manifest) o; | ||
| 132 | |||
| 133 | boolean idsEqual = (id == null ? oman.getId() == null : | ||
| 134 | id.equals(oman.getId())); | ||
| 135 | |||
| 136 | return (idsEqual && references.equals(oman.getReferences())); | ||
| 137 | } | ||
| 138 | } | ||
Binary file not shown.
| @@ -0,0 +1,254 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DOMPGPData.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import java.util.*; | ||
| 30 | import javax.xml.crypto.*; | ||
| 31 | import javax.xml.crypto.dom.DOMCryptoContext; | ||
| 32 | import javax.xml.crypto.dsig.*; | ||
| 33 | import javax.xml.crypto.dsig.keyinfo.PGPData; | ||
| 34 | import org.w3c.dom.Document; | ||
| 35 | import org.w3c.dom.Element; | ||
| 36 | import org.w3c.dom.Node; | ||
| 37 | import org.w3c.dom.NodeList; | ||
| 38 | |||
| 39 | import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException; | ||
| 40 | import com.sun.org.apache.xml.internal.security.utils.Base64; | ||
| 41 | |||
| 42 | /** | ||
| 43 | * DOM-based implementation of PGPData. | ||
| 44 | * | ||
| 45 | * @author Sean Mullan | ||
| 46 | */ | ||
| 47 | public final class DOMPGPData extends DOMStructure implements PGPData { | ||
| 48 | |||
| 49 | private final byte[] keyId; | ||
| 50 | private final byte[] keyPacket; | ||
| 51 | private final List externalElements; | ||
| 52 | |||
| 53 | /** | ||
| 54 | * Creates a <code>DOMPGPData</code> containing the specified key packet. | ||
| 55 | * and optional list of external elements. | ||
| 56 | * | ||
| 57 | * @param keyPacket a PGP Key Material Packet as defined in section 5.5 of | ||
| 58 | * <a href="http://www.ietf.org/rfc/rfc2440.txt"/>RFC 2440</a>. The | ||
| 59 | * array is cloned to prevent subsequent modification. | ||
| 60 | * @param other a list of {@link XMLStructure}s representing elements from | ||
| 61 | * an external namespace. The list is defensively copied to prevent | ||
| 62 | * subsequent modification. May be <code>null</code> or empty. | ||
| 63 | * @throws NullPointerException if <code>keyPacket</code> is | ||
| 64 | * <code>null</code> | ||
| 65 | * @throws IllegalArgumentException if the key packet is not in the | ||
| 66 | * correct format | ||
| 67 | * @throws ClassCastException if <code>other</code> contains any | ||
| 68 | * entries that are not of type {@link XMLStructure} | ||
| 69 | */ | ||
| 70 | public DOMPGPData(byte[] keyPacket, List other) { | ||
| 71 | if (keyPacket == null) { | ||
| 72 | throw new NullPointerException("keyPacket cannot be null"); | ||
| 73 | } | ||
| 74 | if (other == null || other.isEmpty()) { | ||
| 75 | this.externalElements = Collections.EMPTY_LIST; | ||
| 76 | } else { | ||
| 77 | List otherCopy = new ArrayList(other); | ||
| 78 | for (int i = 0, size = otherCopy.size(); i < size; i++) { | ||
| 79 | if (!(otherCopy.get(i) instanceof XMLStructure)) { | ||
| 80 | throw new ClassCastException | ||
| 81 | ("other["+i+"] is not a valid PGPData type"); | ||
| 82 | } | ||
| 83 | } | ||
| 84 | this.externalElements = Collections.unmodifiableList(otherCopy); | ||
| 85 | } | ||
| 86 | this.keyPacket = (byte []) keyPacket.clone(); | ||
| 87 | checkKeyPacket(keyPacket); | ||
| 88 | this.keyId = null; | ||
| 89 | } | ||
| 90 | |||
| 91 | /** | ||
| 92 | * Creates a <code>DOMPGPData</code> containing the specified key id and | ||
| 93 | * optional key packet and list of external elements. | ||
| 94 | * | ||
| 95 | * @param keyId a PGP public key id as defined in section 11.2 of | ||
| 96 | * <a href="http://www.ietf.org/rfc/rfc2440.txt"/>RFC 2440</a>. The | ||
| 97 | * array is cloned to prevent subsequent modification. | ||
| 98 | * @param keyPacket a PGP Key Material Packet as defined in section 5.5 of | ||
| 99 | * <a href="http://www.ietf.org/rfc/rfc2440.txt"/>RFC 2440</a> (may | ||
| 100 | * be <code>null</code>). The array is cloned to prevent subsequent | ||
| 101 | * modification. | ||
| 102 | * @param other a list of {@link XMLStructure}s representing elements from | ||
| 103 | * an external namespace. The list is defensively copied to prevent | ||
| 104 | * subsequent modification. May be <code>null</code> or empty. | ||
| 105 | * @throws NullPointerException if <code>keyId</code> is <code>null</code> | ||
| 106 | * @throws IllegalArgumentException if the key id or packet is not in the | ||
| 107 | * correct format | ||
| 108 | * @throws ClassCastException if <code>other</code> contains any | ||
| 109 | * entries that are not of type {@link XMLStructure} | ||
| 110 | */ | ||
| 111 | public DOMPGPData(byte[] keyId, byte[] keyPacket, List other) { | ||
| 112 | if (keyId == null) { | ||
| 113 | throw new NullPointerException("keyId cannot be null"); | ||
| 114 | } | ||
| 115 | // key ids must be 8 bytes | ||
| 116 | if (keyId.length != 8) { | ||
| 117 | throw new IllegalArgumentException("keyId must be 8 bytes long"); | ||
| 118 | } | ||
| 119 | if (other == null || other.isEmpty()) { | ||
| 120 | this.externalElements = Collections.EMPTY_LIST; | ||
| 121 | } else { | ||
| 122 | List otherCopy = new ArrayList(other); | ||
| 123 | for (int i = 0, size = otherCopy.size(); i < size; i++) { | ||
| 124 | if (!(otherCopy.get(i) instanceof XMLStructure)) { | ||
| 125 | throw new ClassCastException | ||
| 126 | ("other["+i+"] is not a valid PGPData type"); | ||
| 127 | } | ||
| 128 | } | ||
| 129 | this.externalElements = Collections.unmodifiableList(otherCopy); | ||
| 130 | } | ||
| 131 | this.keyId = (byte []) keyId.clone(); | ||
| 132 | this.keyPacket = keyPacket == null ? null : (byte []) keyPacket.clone(); | ||
| 133 | if (keyPacket != null) { | ||
| 134 | checkKeyPacket(keyPacket); | ||
| 135 | } | ||
| 136 | } | ||
| 137 | |||
| 138 | /** | ||
| 139 | * Creates a <code>DOMPGPData</code> from an element. | ||
| 140 | * | ||
| 141 | * @param pdElem a PGPData element | ||
| 142 | */ | ||
| 143 | public DOMPGPData(Element pdElem) throws MarshalException { | ||
| 144 | // get all children nodes | ||
| 145 | byte[] keyId = null; | ||
| 146 | byte[] keyPacket = null; | ||
| 147 | NodeList nl = pdElem.getChildNodes(); | ||
| 148 | int length = nl.getLength(); | ||
| 149 | List other = new ArrayList(length); | ||
| 150 | for (int x = 0; x < length; x++) { | ||
| 151 | Node n = nl.item(x); | ||
| 152 | if (n.getNodeType() == Node.ELEMENT_NODE) { | ||
| 153 | Element childElem = (Element) n; | ||
| 154 | String localName = childElem.getLocalName(); | ||
| 155 | try { | ||
| 156 | if (localName.equals("PGPKeyID")) { | ||
| 157 | keyId = Base64.decode(childElem); | ||
| 158 | } else if (localName.equals("PGPKeyPacket")){ | ||
| 159 | keyPacket = Base64.decode(childElem); | ||
| 160 | } else { | ||
| 161 | other.add | ||
| 162 | (new javax.xml.crypto.dom.DOMStructure(childElem)); | ||
| 163 | } | ||
| 164 | } catch (Base64DecodingException bde) { | ||
| 165 | throw new MarshalException(bde); | ||
| 166 | } | ||
| 167 | } | ||
| 168 | } | ||
| 169 | this.keyId = keyId; | ||
| 170 | this.keyPacket = keyPacket; | ||
| 171 | this.externalElements = Collections.unmodifiableList(other); | ||
| 172 | } | ||
| 173 | |||
| 174 | public byte[] getKeyId() { | ||
| 175 | return (keyId == null ? null : (byte []) keyId.clone()); | ||
| 176 | } | ||
| 177 | |||
| 178 | public byte[] getKeyPacket() { | ||
| 179 | return (keyPacket == null ? null : (byte []) keyPacket.clone()); | ||
| 180 | } | ||
| 181 | |||
| 182 | public List getExternalElements() { | ||
| 183 | return externalElements; | ||
| 184 | } | ||
| 185 | |||
| 186 | public void marshal(Node parent, String dsPrefix, DOMCryptoContext context) | ||
| 187 | throws MarshalException { | ||
| 188 | Document ownerDoc = DOMUtils.getOwnerDocument(parent); | ||
| 189 | |||
| 190 | Element pdElem = DOMUtils.createElement | ||
| 191 | (ownerDoc, "PGPData", XMLSignature.XMLNS, dsPrefix); | ||
| 192 | |||
| 193 | // create and append PGPKeyID element | ||
| 194 | if (keyId != null) { | ||
| 195 | Element keyIdElem = DOMUtils.createElement | ||
| 196 | (ownerDoc, "PGPKeyID", XMLSignature.XMLNS, dsPrefix); | ||
| 197 | keyIdElem.appendChild | ||
| 198 | (ownerDoc.createTextNode(Base64.encode(keyId))); | ||
| 199 | pdElem.appendChild(keyIdElem); | ||
| 200 | } | ||
| 201 | |||
| 202 | // create and append PGPKeyPacket element | ||
| 203 | if (keyPacket != null) { | ||
| 204 | Element keyPktElem = DOMUtils.createElement | ||
| 205 | (ownerDoc, "PGPKeyPacket", XMLSignature.XMLNS, dsPrefix); | ||
| 206 | keyPktElem.appendChild | ||
| 207 | (ownerDoc.createTextNode(Base64.encode(keyPacket))); | ||
| 208 | pdElem.appendChild(keyPktElem); | ||
| 209 | } | ||
| 210 | |||
| 211 | // create and append any elements | ||
| 212 | for (int i = 0, size = externalElements.size(); i < size; i++) { | ||
| 213 | DOMUtils.appendChild(pdElem, ((javax.xml.crypto.dom.DOMStructure) | ||
| 214 | externalElements.get(i)).getNode()); | ||
| 215 | } | ||
| 216 | |||
| 217 | parent.appendChild(pdElem); | ||
| 218 | } | ||
| 219 | |||
| 220 | /** | ||
| 221 | * We assume packets use the new format packet syntax, as specified in | ||
| 222 | * section 4 of RFC 2440. | ||
| 223 | * | ||
| 224 | * This method only checks if the packet contains a valid tag. The | ||
| 225 | * contents of the packet should be checked by the application. | ||
| 226 | */ | ||
| 227 | private void checkKeyPacket(byte[] keyPacket) { | ||
| 228 | // length must be at least 3 (one byte for tag, one byte for length, | ||
| 229 | // and minimally one byte of content | ||
| 230 | if (keyPacket.length < 3) { | ||
| 231 | throw new IllegalArgumentException("keypacket must be at least " + | ||
| 232 | "3 bytes long"); | ||
| 233 | } | ||
| 234 | |||
| 235 | int tag = keyPacket[0]; | ||
| 236 | // first bit must be set | ||
| 237 | if ((tag & 128) != 128) { | ||
| 238 | throw new IllegalArgumentException("keypacket tag is invalid: " + | ||
| 239 | "bit 7 is not set"); | ||
| 240 | } | ||
| 241 | // make sure using new format | ||
| 242 | if ((tag & 64) != 64) { | ||
| 243 | throw new IllegalArgumentException("old keypacket tag format is " + | ||
| 244 | "unsupported"); | ||
| 245 | } | ||
| 246 | |||
| 247 | // tag value must be 6, 14, 5 or 7 | ||
| 248 | if (((tag & 6) != 6) && ((tag & 14) != 14) && | ||
| 249 | ((tag & 5) != 5) && ((tag & 7) != 7)) { | ||
| 250 | throw new IllegalArgumentException("keypacket tag is invalid: " + | ||
| 251 | "must be 6, 14, 5, or 7"); | ||
| 252 | } | ||
| 253 | } | ||
| 254 | } | ||
Binary file not shown.
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,555 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * =========================================================================== | ||
| 26 | * | ||
| 27 | * (C) Copyright IBM Corp. 2003 All Rights Reserved. | ||
| 28 | * | ||
| 29 | * =========================================================================== | ||
| 30 | */ | ||
| 31 | /* | ||
| 32 | * $Id: DOMReference.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 33 | */ | ||
| 34 | package org.jcp.xml.dsig.internal.dom; | ||
| 35 | |||
| 36 | import javax.xml.crypto.*; | ||
| 37 | import javax.xml.crypto.dsig.*; | ||
| 38 | import javax.xml.crypto.dom.DOMCryptoContext; | ||
| 39 | import javax.xml.crypto.dom.DOMURIReference; | ||
| 40 | |||
| 41 | import java.io.*; | ||
| 42 | import java.net.URI; | ||
| 43 | import java.net.URISyntaxException; | ||
| 44 | import java.security.*; | ||
| 45 | import java.util.*; | ||
| 46 | import java.util.logging.Level; | ||
| 47 | import java.util.logging.Logger; | ||
| 48 | import org.w3c.dom.Attr; | ||
| 49 | import org.w3c.dom.Document; | ||
| 50 | import org.w3c.dom.Element; | ||
| 51 | import org.w3c.dom.Node; | ||
| 52 | |||
| 53 | import org.jcp.xml.dsig.internal.DigesterOutputStream; | ||
| 54 | import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException; | ||
| 55 | import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput; | ||
| 56 | import com.sun.org.apache.xml.internal.security.utils.Base64; | ||
| 57 | import com.sun.org.apache.xml.internal.security.utils.UnsyncBufferedOutputStream; | ||
| 58 | |||
| 59 | /** | ||
| 60 | * DOM-based implementation of Reference. | ||
| 61 | * | ||
| 62 | * @author Sean Mullan | ||
| 63 | * @author Joyce Leung | ||
| 64 | */ | ||
| 65 | public final class DOMReference extends DOMStructure | ||
| 66 | implements Reference, DOMURIReference { | ||
| 67 | |||
| 68 | /** | ||
| 69 | * Look up useC14N11 system property. If true, an explicit C14N11 transform | ||
| 70 | * will be added if necessary when generating the signature. See section | ||
| 71 | * 3.1.1 of http://www.w3.org/2007/xmlsec/Drafts/xmldsig-core/ for more info. | ||
| 72 | * | ||
| 73 | * If true, overrides the same property if set in the XMLSignContext. | ||
| 74 | */ | ||
| 75 | private static boolean useC14N11 = | ||
| 76 | AccessController.doPrivileged(new PrivilegedAction<Boolean>() { | ||
| 77 | public Boolean run() { | ||
| 78 | return Boolean.getBoolean | ||
| 79 | ("com.sun.org.apache.xml.internal.security.useC14N11"); | ||
| 80 | } | ||
| 81 | }); | ||
| 82 | |||
| 83 | private static Logger log = Logger.getLogger("org.jcp.xml.dsig.internal.dom"); | ||
| 84 | |||
| 85 | private final DigestMethod digestMethod; | ||
| 86 | private final String id; | ||
| 87 | private final List transforms; | ||
| 88 | private List allTransforms; | ||
| 89 | private final Data appliedTransformData; | ||
| 90 | private Attr here; | ||
| 91 | private final String uri; | ||
| 92 | private final String type; | ||
| 93 | private byte[] digestValue; | ||
| 94 | private byte[] calcDigestValue; | ||
| 95 | private Element refElem; | ||
| 96 | private boolean digested = false; | ||
| 97 | private boolean validated = false; | ||
| 98 | private boolean validationStatus; | ||
| 99 | private Data derefData; | ||
| 100 | private InputStream dis; | ||
| 101 | private MessageDigest md; | ||
| 102 | private Provider provider; | ||
| 103 | |||
| 104 | /** | ||
| 105 | * Creates a <code>Reference</code> from the specified parameters. | ||
| 106 | * | ||
| 107 | * @param uri the URI (may be null) | ||
| 108 | * @param type the type (may be null) | ||
| 109 | * @param dm the digest method | ||
| 110 | * @param transforms a list of {@link Transform}s. The list | ||
| 111 | * is defensively copied to protect against subsequent modification. | ||
| 112 | * May be <code>null</code> or empty. | ||
| 113 | * @param id the reference ID (may be <code>null</code>) | ||
| 114 | * @return a <code>Reference</code> | ||
| 115 | * @throws NullPointerException if <code>dm</code> is <code>null</code> | ||
| 116 | * @throws ClassCastException if any of the <code>transforms</code> are | ||
| 117 | * not of type <code>Transform</code> | ||
| 118 | */ | ||
| 119 | public DOMReference(String uri, String type, DigestMethod dm, | ||
| 120 | List transforms, String id, Provider provider) { | ||
| 121 | this(uri, type, dm, null, null, transforms, id, null, provider); | ||
| 122 | } | ||
| 123 | |||
| 124 | public DOMReference(String uri, String type, DigestMethod dm, | ||
| 125 | List appliedTransforms, Data result, List transforms, String id, | ||
| 126 | Provider provider) { | ||
| 127 | this(uri, type, dm, appliedTransforms, | ||
| 128 | result, transforms, id, null, provider); | ||
| 129 | } | ||
| 130 | |||
| 131 | public DOMReference(String uri, String type, DigestMethod dm, | ||
| 132 | List appliedTransforms, Data result, List transforms, String id, | ||
| 133 | byte[] digestValue, Provider provider) { | ||
| 134 | if (dm == null) { | ||
| 135 | throw new NullPointerException("DigestMethod must be non-null"); | ||
| 136 | } | ||
| 137 | this.allTransforms = new ArrayList(); | ||
| 138 | if (appliedTransforms != null) { | ||
| 139 | List transformsCopy = new ArrayList(appliedTransforms); | ||
| 140 | for (int i = 0, size = transformsCopy.size(); i < size; i++) { | ||
| 141 | if (!(transformsCopy.get(i) instanceof Transform)) { | ||
| 142 | throw new ClassCastException | ||
| 143 | ("appliedTransforms["+i+"] is not a valid type"); | ||
| 144 | } | ||
| 145 | } | ||
| 146 | this.allTransforms = transformsCopy; | ||
| 147 | } | ||
| 148 | if (transforms == null) { | ||
| 149 | this.transforms = Collections.EMPTY_LIST; | ||
| 150 | } else { | ||
| 151 | List transformsCopy = new ArrayList(transforms); | ||
| 152 | for (int i = 0, size = transformsCopy.size(); i < size; i++) { | ||
| 153 | if (!(transformsCopy.get(i) instanceof Transform)) { | ||
| 154 | throw new ClassCastException | ||
| 155 | ("transforms["+i+"] is not a valid type"); | ||
| 156 | } | ||
| 157 | } | ||
| 158 | this.transforms = transformsCopy; | ||
| 159 | this.allTransforms.addAll(transformsCopy); | ||
| 160 | } | ||
| 161 | this.digestMethod = dm; | ||
| 162 | this.uri = uri; | ||
| 163 | if ((uri != null) && (!uri.equals(""))) { | ||
| 164 | try { | ||
| 165 | new URI(uri); | ||
| 166 | } catch (URISyntaxException e) { | ||
| 167 | throw new IllegalArgumentException(e.getMessage()); | ||
| 168 | } | ||
| 169 | } | ||
| 170 | this.type = type; | ||
| 171 | this.id = id; | ||
| 172 | if (digestValue != null) { | ||
| 173 | this.digestValue = (byte[]) digestValue.clone(); | ||
| 174 | this.digested = true; | ||
| 175 | } | ||
| 176 | this.appliedTransformData = result; | ||
| 177 | this.provider = provider; | ||
| 178 | } | ||
| 179 | |||
| 180 | /** | ||
| 181 | * Creates a <code>DOMReference</code> from an element. | ||
| 182 | * | ||
| 183 | * @param refElem a Reference element | ||
| 184 | */ | ||
| 185 | public DOMReference(Element refElem, XMLCryptoContext context, | ||
| 186 | Provider provider) throws MarshalException { | ||
| 187 | // unmarshal Transforms, if specified | ||
| 188 | Element nextSibling = DOMUtils.getFirstChildElement(refElem); | ||
| 189 | List transforms = new ArrayList(5); | ||
| 190 | if (nextSibling.getLocalName().equals("Transforms")) { | ||
| 191 | Element transformElem = DOMUtils.getFirstChildElement(nextSibling); | ||
| 192 | while (transformElem != null) { | ||
| 193 | transforms.add | ||
| 194 | (new DOMTransform(transformElem, context, provider)); | ||
| 195 | transformElem = DOMUtils.getNextSiblingElement(transformElem); | ||
| 196 | } | ||
| 197 | nextSibling = DOMUtils.getNextSiblingElement(nextSibling); | ||
| 198 | } | ||
| 199 | |||
| 200 | // unmarshal DigestMethod | ||
| 201 | Element dmElem = nextSibling; | ||
| 202 | this.digestMethod = DOMDigestMethod.unmarshal(dmElem); | ||
| 203 | |||
| 204 | // unmarshal DigestValue | ||
| 205 | try { | ||
| 206 | Element dvElem = DOMUtils.getNextSiblingElement(dmElem); | ||
| 207 | this.digestValue = Base64.decode(dvElem); | ||
| 208 | } catch (Base64DecodingException bde) { | ||
| 209 | throw new MarshalException(bde); | ||
| 210 | } | ||
| 211 | |||
| 212 | // unmarshal attributes | ||
| 213 | this.uri = DOMUtils.getAttributeValue(refElem, "URI"); | ||
| 214 | this.id = DOMUtils.getAttributeValue(refElem, "Id"); | ||
| 215 | |||
| 216 | this.type = DOMUtils.getAttributeValue(refElem, "Type"); | ||
| 217 | this.here = refElem.getAttributeNodeNS(null, "URI"); | ||
| 218 | this.refElem = refElem; | ||
| 219 | this.transforms = transforms; | ||
| 220 | this.allTransforms = transforms; | ||
| 221 | this.appliedTransformData = null; | ||
| 222 | this.provider = provider; | ||
| 223 | } | ||
| 224 | |||
| 225 | public DigestMethod getDigestMethod() { | ||
| 226 | return digestMethod; | ||
| 227 | } | ||
| 228 | |||
| 229 | public String getId() { | ||
| 230 | return id; | ||
| 231 | } | ||
| 232 | |||
| 233 | public String getURI() { | ||
| 234 | return uri; | ||
| 235 | } | ||
| 236 | |||
| 237 | public String getType() { | ||
| 238 | return type; | ||
| 239 | } | ||
| 240 | |||
| 241 | public List getTransforms() { | ||
| 242 | return Collections.unmodifiableList(allTransforms); | ||
| 243 | } | ||
| 244 | |||
| 245 | public byte[] getDigestValue() { | ||
| 246 | return (digestValue == null ? null : (byte[]) digestValue.clone()); | ||
| 247 | } | ||
| 248 | |||
| 249 | public byte[] getCalculatedDigestValue() { | ||
| 250 | return (calcDigestValue == null ? null | ||
| 251 | : (byte[]) calcDigestValue.clone()); | ||
| 252 | } | ||
| 253 | |||
| 254 | public void marshal(Node parent, String dsPrefix, DOMCryptoContext context) | ||
| 255 | throws MarshalException { | ||
| 256 | if (log.isLoggable(Level.FINE)) { | ||
| 257 | log.log(Level.FINE, "Marshalling Reference"); | ||
| 258 | } | ||
| 259 | Document ownerDoc = DOMUtils.getOwnerDocument(parent); | ||
| 260 | |||
| 261 | refElem = DOMUtils.createElement | ||
| 262 | (ownerDoc, "Reference", XMLSignature.XMLNS, dsPrefix); | ||
| 263 | |||
| 264 | // set attributes | ||
| 265 | DOMUtils.setAttributeID(refElem, "Id", id); | ||
| 266 | DOMUtils.setAttribute(refElem, "URI", uri); | ||
| 267 | DOMUtils.setAttribute(refElem, "Type", type); | ||
| 268 | |||
| 269 | // create and append Transforms element | ||
| 270 | if (!allTransforms.isEmpty()) { | ||
| 271 | Element transformsElem = DOMUtils.createElement | ||
| 272 | (ownerDoc, "Transforms", XMLSignature.XMLNS, dsPrefix); | ||
| 273 | refElem.appendChild(transformsElem); | ||
| 274 | for (int i = 0, size = allTransforms.size(); i < size; i++) { | ||
| 275 | DOMStructure transform = | ||
| 276 | (DOMStructure) allTransforms.get(i); | ||
| 277 | transform.marshal(transformsElem, dsPrefix, context); | ||
| 278 | } | ||
| 279 | } | ||
| 280 | |||
| 281 | // create and append DigestMethod element | ||
| 282 | ((DOMDigestMethod) digestMethod).marshal(refElem, dsPrefix, context); | ||
| 283 | |||
| 284 | // create and append DigestValue element | ||
| 285 | if (log.isLoggable(Level.FINE)) { | ||
| 286 | log.log(Level.FINE, "Adding digestValueElem"); | ||
| 287 | } | ||
| 288 | Element digestValueElem = DOMUtils.createElement | ||
| 289 | (ownerDoc, "DigestValue", XMLSignature.XMLNS, dsPrefix); | ||
| 290 | if (digestValue != null) { | ||
| 291 | digestValueElem.appendChild | ||
| 292 | (ownerDoc.createTextNode(Base64.encode(digestValue))); | ||
| 293 | } | ||
| 294 | refElem.appendChild(digestValueElem); | ||
| 295 | |||
| 296 | parent.appendChild(refElem); | ||
| 297 | here = refElem.getAttributeNodeNS(null, "URI"); | ||
| 298 | } | ||
| 299 | |||
| 300 | public void digest(XMLSignContext signContext) | ||
| 301 | throws XMLSignatureException { | ||
| 302 | Data data = null; | ||
| 303 | if (appliedTransformData == null) { | ||
| 304 | data = dereference(signContext); | ||
| 305 | } else { | ||
| 306 | data = appliedTransformData; | ||
| 307 | } | ||
| 308 | digestValue = transform(data, signContext); | ||
| 309 | |||
| 310 | // insert digestValue into DigestValue element | ||
| 311 | String encodedDV = Base64.encode(digestValue); | ||
| 312 | if (log.isLoggable(Level.FINE)) { | ||
| 313 | log.log(Level.FINE, "Reference object uri = " + uri); | ||
| 314 | } | ||
| 315 | Element digestElem = DOMUtils.getLastChildElement(refElem); | ||
| 316 | if (digestElem == null) { | ||
| 317 | throw new XMLSignatureException("DigestValue element expected"); | ||
| 318 | } | ||
| 319 | DOMUtils.removeAllChildren(digestElem); | ||
| 320 | digestElem.appendChild | ||
| 321 | (refElem.getOwnerDocument().createTextNode(encodedDV)); | ||
| 322 | |||
| 323 | digested = true; | ||
| 324 | if (log.isLoggable(Level.FINE)) { | ||
| 325 | log.log(Level.FINE, "Reference digesting completed"); | ||
| 326 | } | ||
| 327 | } | ||
| 328 | |||
| 329 | public boolean validate(XMLValidateContext validateContext) | ||
| 330 | throws XMLSignatureException { | ||
| 331 | if (validateContext == null) { | ||
| 332 | throw new NullPointerException("validateContext cannot be null"); | ||
| 333 | } | ||
| 334 | if (validated) { | ||
| 335 | return validationStatus; | ||
| 336 | } | ||
| 337 | Data data = dereference(validateContext); | ||
| 338 | calcDigestValue = transform(data, validateContext); | ||
| 339 | |||
| 340 | if (log.isLoggable(Level.FINE)) { | ||
| 341 | log.log(Level.FINE, "Expected digest: " | ||
| 342 | + Base64.encode(digestValue)); | ||
| 343 | log.log(Level.FINE, "Actual digest: " | ||
| 344 | + Base64.encode(calcDigestValue)); | ||
| 345 | } | ||
| 346 | |||
| 347 | validationStatus = Arrays.equals(digestValue, calcDigestValue); | ||
| 348 | validated = true; | ||
| 349 | return validationStatus; | ||
| 350 | } | ||
| 351 | |||
| 352 | public Data getDereferencedData() { | ||
| 353 | return derefData; | ||
| 354 | } | ||
| 355 | |||
| 356 | public InputStream getDigestInputStream() { | ||
| 357 | return dis; | ||
| 358 | } | ||
| 359 | |||
| 360 | private Data dereference(XMLCryptoContext context) | ||
| 361 | throws XMLSignatureException { | ||
| 362 | Data data = null; | ||
| 363 | |||
| 364 | // use user-specified URIDereferencer if specified; otherwise use deflt | ||
| 365 | URIDereferencer deref = context.getURIDereferencer(); | ||
| 366 | if (deref == null) { | ||
| 367 | deref = DOMURIDereferencer.INSTANCE; | ||
| 368 | } | ||
| 369 | try { | ||
| 370 | data = deref.dereference(this, context); | ||
| 371 | if (log.isLoggable(Level.FINE)) { | ||
| 372 | log.log(Level.FINE, "URIDereferencer class name: " | ||
| 373 | + deref.getClass().getName()); | ||
| 374 | log.log(Level.FINE, "Data class name: " | ||
| 375 | + data.getClass().getName()); | ||
| 376 | } | ||
| 377 | } catch (URIReferenceException ure) { | ||
| 378 | throw new XMLSignatureException(ure); | ||
| 379 | } | ||
| 380 | |||
| 381 | return data; | ||
| 382 | } | ||
| 383 | |||
| 384 | private byte[] transform(Data dereferencedData, | ||
| 385 | XMLCryptoContext context) throws XMLSignatureException { | ||
| 386 | |||
| 387 | if (md == null) { | ||
| 388 | try { | ||
| 389 | md = MessageDigest.getInstance | ||
| 390 | (((DOMDigestMethod) digestMethod).getMessageDigestAlgorithm()); | ||
| 391 | } catch (NoSuchAlgorithmException nsae) { | ||
| 392 | throw new XMLSignatureException(nsae); | ||
| 393 | } | ||
| 394 | } | ||
| 395 | md.reset(); | ||
| 396 | DigesterOutputStream dos; | ||
| 397 | Boolean cache = (Boolean) | ||
| 398 | context.getProperty("javax.xml.crypto.dsig.cacheReference"); | ||
| 399 | if (cache != null && cache.booleanValue() == true) { | ||
| 400 | this.derefData = copyDerefData(dereferencedData); | ||
| 401 | dos = new DigesterOutputStream(md, true); | ||
| 402 | } else { | ||
| 403 | dos = new DigesterOutputStream(md); | ||
| 404 | } | ||
| 405 | OutputStream os = new UnsyncBufferedOutputStream(dos); | ||
| 406 | Data data = dereferencedData; | ||
| 407 | for (int i = 0, size = transforms.size(); i < size; i++) { | ||
| 408 | DOMTransform transform = (DOMTransform) transforms.get(i); | ||
| 409 | try { | ||
| 410 | if (i < size - 1) { | ||
| 411 | data = transform.transform(data, context); | ||
| 412 | } else { | ||
| 413 | data = transform.transform(data, context, os); | ||
| 414 | } | ||
| 415 | } catch (TransformException te) { | ||
| 416 | throw new XMLSignatureException(te); | ||
| 417 | } | ||
| 418 | } | ||
| 419 | |||
| 420 | try { | ||
| 421 | if (data != null) { | ||
| 422 | XMLSignatureInput xi; | ||
| 423 | // explicitly use C14N 1.1 when generating signature | ||
| 424 | // first check system property, then context property | ||
| 425 | boolean c14n11 = useC14N11; | ||
| 426 | String c14nalg = CanonicalizationMethod.INCLUSIVE; | ||
| 427 | if (context instanceof XMLSignContext) { | ||
| 428 | if (!c14n11) { | ||
| 429 | Boolean prop = (Boolean) context.getProperty | ||
| 430 | ("com.sun.org.apache.xml.internal.security.useC14N11"); | ||
| 431 | c14n11 = (prop != null && prop.booleanValue() == true); | ||
| 432 | if (c14n11) { | ||
| 433 | c14nalg = "http://www.w3.org/2006/12/xml-c14n11"; | ||
| 434 | } | ||
| 435 | } else { | ||
| 436 | c14nalg = "http://www.w3.org/2006/12/xml-c14n11"; | ||
| 437 | } | ||
| 438 | } | ||
| 439 | if (data instanceof ApacheData) { | ||
| 440 | xi = ((ApacheData) data).getXMLSignatureInput(); | ||
| 441 | } else if (data instanceof OctetStreamData) { | ||
| 442 | xi = new XMLSignatureInput | ||
| 443 | (((OctetStreamData)data).getOctetStream()); | ||
| 444 | } else if (data instanceof NodeSetData) { | ||
| 445 | TransformService spi = null; | ||
| 446 | try { | ||
| 447 | spi = TransformService.getInstance(c14nalg, "DOM"); | ||
| 448 | } catch (NoSuchAlgorithmException nsae) { | ||
| 449 | spi = TransformService.getInstance | ||
| 450 | (c14nalg, "DOM", provider); | ||
| 451 | } | ||
| 452 | data = spi.transform(data, context); | ||
| 453 | xi = new XMLSignatureInput | ||
| 454 | (((OctetStreamData)data).getOctetStream()); | ||
| 455 | } else { | ||
| 456 | throw new XMLSignatureException("unrecognized Data type"); | ||
| 457 | } | ||
| 458 | if (context instanceof XMLSignContext && c14n11 | ||
| 459 | && !xi.isOctetStream() && !xi.isOutputStreamSet()) { | ||
| 460 | DOMTransform t = new DOMTransform | ||
| 461 | (TransformService.getInstance(c14nalg, "DOM")); | ||
| 462 | Element transformsElem = null; | ||
| 463 | String dsPrefix = DOMUtils.getSignaturePrefix(context); | ||
| 464 | if (allTransforms.isEmpty()) { | ||
| 465 | transformsElem = DOMUtils.createElement( | ||
| 466 | refElem.getOwnerDocument(), | ||
| 467 | "Transforms", XMLSignature.XMLNS, dsPrefix); | ||
| 468 | refElem.insertBefore(transformsElem, | ||
| 469 | DOMUtils.getFirstChildElement(refElem)); | ||
| 470 | } else { | ||
| 471 | transformsElem = DOMUtils.getFirstChildElement(refElem); | ||
| 472 | } | ||
| 473 | t.marshal(transformsElem, dsPrefix, (DOMCryptoContext) context); | ||
| 474 | allTransforms.add(t); | ||
| 475 | xi.updateOutputStream(os, true); | ||
| 476 | } else { | ||
| 477 | xi.updateOutputStream(os); | ||
| 478 | } | ||
| 479 | } | ||
| 480 | os.flush(); | ||
| 481 | if (cache != null && cache.booleanValue() == true) { | ||
| 482 | this.dis = dos.getInputStream(); | ||
| 483 | } | ||
| 484 | return dos.getDigestValue(); | ||
| 485 | } catch (Exception e) { | ||
| 486 | throw new XMLSignatureException(e); | ||
| 487 | } | ||
| 488 | } | ||
| 489 | |||
| 490 | public Node getHere() { | ||
| 491 | return here; | ||
| 492 | } | ||
| 493 | |||
| 494 | public boolean equals(Object o) { | ||
| 495 | if (this == o) { | ||
| 496 | return true; | ||
| 497 | } | ||
| 498 | |||
| 499 | if (!(o instanceof Reference)) { | ||
| 500 | return false; | ||
| 501 | } | ||
| 502 | Reference oref = (Reference) o; | ||
| 503 | |||
| 504 | boolean idsEqual = (id == null ? oref.getId() == null : | ||
| 505 | id.equals(oref.getId())); | ||
| 506 | boolean urisEqual = (uri == null ? oref.getURI() == null : | ||
| 507 | uri.equals(oref.getURI())); | ||
| 508 | boolean typesEqual = (type == null ? oref.getType() == null : | ||
| 509 | type.equals(oref.getType())); | ||
| 510 | boolean digestValuesEqual = | ||
| 511 | Arrays.equals(digestValue, oref.getDigestValue()); | ||
| 512 | |||
| 513 | return (digestMethod.equals(oref.getDigestMethod()) && idsEqual && | ||
| 514 | urisEqual && typesEqual && allTransforms.equals(oref.getTransforms())); | ||
| 515 | } | ||
| 516 | |||
| 517 | boolean isDigested() { | ||
| 518 | return digested; | ||
| 519 | } | ||
| 520 | |||
| 521 | private static Data copyDerefData(Data dereferencedData) { | ||
| 522 | if (dereferencedData instanceof ApacheData) { | ||
| 523 | // need to make a copy of the Data | ||
| 524 | ApacheData ad = (ApacheData) dereferencedData; | ||
| 525 | XMLSignatureInput xsi = ad.getXMLSignatureInput(); | ||
| 526 | if (xsi.isNodeSet()) { | ||
| 527 | try { | ||
| 528 | final Set s = xsi.getNodeSet(); | ||
| 529 | return new NodeSetData() { | ||
| 530 | public Iterator iterator() { return s.iterator(); } | ||
| 531 | }; | ||
| 532 | } catch (Exception e) { | ||
| 533 | // log a warning | ||
| 534 | log.log(Level.WARNING, | ||
| 535 | "cannot cache dereferenced data: " + e); | ||
| 536 | return null; | ||
| 537 | } | ||
| 538 | } else if (xsi.isElement()) { | ||
| 539 | return new DOMSubTreeData | ||
| 540 | (xsi.getSubNode(), xsi.isExcludeComments()); | ||
| 541 | } else if (xsi.isOctetStream() || xsi.isByteArray()) { | ||
| 542 | try { | ||
| 543 | return new OctetStreamData | ||
| 544 | (xsi.getOctetStream(), xsi.getSourceURI(), xsi.getMIMEType()); | ||
| 545 | } catch (IOException ioe) { | ||
| 546 | // log a warning | ||
| 547 | log.log(Level.WARNING, | ||
| 548 | "cannot cache dereferenced data: " + ioe); | ||
| 549 | return null; | ||
| 550 | } | ||
| 551 | } | ||
| 552 | } | ||
| 553 | return dereferencedData; | ||
| 554 | } | ||
| 555 | } | ||
Binary file not shown.
| @@ -0,0 +1,256 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * =========================================================================== | ||
| 26 | * | ||
| 27 | * (C) Copyright IBM Corp. 2003 All Rights Reserved. | ||
| 28 | * | ||
| 29 | * =========================================================================== | ||
| 30 | */ | ||
| 31 | /* | ||
| 32 | * $Id: DOMRetrievalMethod.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 33 | */ | ||
| 34 | package org.jcp.xml.dsig.internal.dom; | ||
| 35 | |||
| 36 | import java.io.ByteArrayInputStream; | ||
| 37 | import java.net.URI; | ||
| 38 | import java.net.URISyntaxException; | ||
| 39 | import java.security.Provider; | ||
| 40 | import java.util.*; | ||
| 41 | import javax.xml.crypto.*; | ||
| 42 | import javax.xml.crypto.dsig.*; | ||
| 43 | import javax.xml.crypto.dom.DOMCryptoContext; | ||
| 44 | import javax.xml.crypto.dom.DOMURIReference; | ||
| 45 | import javax.xml.crypto.dsig.keyinfo.RetrievalMethod; | ||
| 46 | import javax.xml.parsers.*; | ||
| 47 | import org.w3c.dom.Attr; | ||
| 48 | import org.w3c.dom.Document; | ||
| 49 | import org.w3c.dom.Element; | ||
| 50 | import org.w3c.dom.Node; | ||
| 51 | |||
| 52 | import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput; | ||
| 53 | |||
| 54 | /** | ||
| 55 | * DOM-based implementation of RetrievalMethod. | ||
| 56 | * | ||
| 57 | * @author Sean Mullan | ||
| 58 | * @author Joyce Leung | ||
| 59 | */ | ||
| 60 | public final class DOMRetrievalMethod extends DOMStructure | ||
| 61 | implements RetrievalMethod, DOMURIReference { | ||
| 62 | |||
| 63 | private final List transforms; | ||
| 64 | private String uri; | ||
| 65 | private String type; | ||
| 66 | private Attr here; | ||
| 67 | |||
| 68 | /** | ||
| 69 | * Creates a <code>DOMRetrievalMethod</code> containing the specified | ||
| 70 | * URIReference and List of Transforms. | ||
| 71 | * | ||
| 72 | * @param uri the URI | ||
| 73 | * @param type the type | ||
| 74 | * @param transforms a list of {@link Transform}s. The list is defensively | ||
| 75 | * copied to prevent subsequent modification. May be <code>null</code> | ||
| 76 | * or empty. | ||
| 77 | * @throws IllegalArgumentException if the format of <code>uri</code> is | ||
| 78 | * invalid, as specified by Reference's URI attribute in the W3C | ||
| 79 | * specification for XML-Signature Syntax and Processing | ||
| 80 | * @throws NullPointerException if <code>uriReference</code> | ||
| 81 | * is <code>null</code> | ||
| 82 | * @throws ClassCastException if <code>transforms</code> contains any | ||
| 83 | * entries that are not of type {@link Transform} | ||
| 84 | */ | ||
| 85 | public DOMRetrievalMethod(String uri, String type, List transforms) { | ||
| 86 | if (uri == null) { | ||
| 87 | throw new NullPointerException("uri cannot be null"); | ||
| 88 | } | ||
| 89 | if (transforms == null || transforms.isEmpty()) { | ||
| 90 | this.transforms = Collections.EMPTY_LIST; | ||
| 91 | } else { | ||
| 92 | List transformsCopy = new ArrayList(transforms); | ||
| 93 | for (int i = 0, size = transformsCopy.size(); i < size; i++) { | ||
| 94 | if (!(transformsCopy.get(i) instanceof Transform)) { | ||
| 95 | throw new ClassCastException | ||
| 96 | ("transforms["+i+"] is not a valid type"); | ||
| 97 | } | ||
| 98 | } | ||
| 99 | this.transforms = Collections.unmodifiableList(transformsCopy); | ||
| 100 | } | ||
| 101 | this.uri = uri; | ||
| 102 | if ((uri != null) && (!uri.equals(""))) { | ||
| 103 | try { | ||
| 104 | new URI(uri); | ||
| 105 | } catch (URISyntaxException e) { | ||
| 106 | throw new IllegalArgumentException(e.getMessage()); | ||
| 107 | } | ||
| 108 | } | ||
| 109 | |||
| 110 | this.type = type; | ||
| 111 | } | ||
| 112 | |||
| 113 | /** | ||
| 114 | * Creates a <code>DOMRetrievalMethod</code> from an element. | ||
| 115 | * | ||
| 116 | * @param rmElem a RetrievalMethod element | ||
| 117 | */ | ||
| 118 | public DOMRetrievalMethod(Element rmElem, XMLCryptoContext context, | ||
| 119 | Provider provider) throws MarshalException { | ||
| 120 | // get URI and Type attributes | ||
| 121 | uri = DOMUtils.getAttributeValue(rmElem, "URI"); | ||
| 122 | type = DOMUtils.getAttributeValue(rmElem, "Type"); | ||
| 123 | |||
| 124 | // get here node | ||
| 125 | here = rmElem.getAttributeNodeNS(null, "URI"); | ||
| 126 | |||
| 127 | // get Transforms, if specified | ||
| 128 | List transforms = new ArrayList(); | ||
| 129 | Element transformsElem = DOMUtils.getFirstChildElement(rmElem); | ||
| 130 | if (transformsElem != null) { | ||
| 131 | Element transformElem = | ||
| 132 | DOMUtils.getFirstChildElement(transformsElem); | ||
| 133 | while (transformElem != null) { | ||
| 134 | transforms.add | ||
| 135 | (new DOMTransform(transformElem, context, provider)); | ||
| 136 | transformElem = DOMUtils.getNextSiblingElement(transformElem); | ||
| 137 | } | ||
| 138 | } | ||
| 139 | if (transforms.isEmpty()) { | ||
| 140 | this.transforms = Collections.EMPTY_LIST; | ||
| 141 | } else { | ||
| 142 | this.transforms = Collections.unmodifiableList(transforms); | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 146 | public String getURI() { | ||
| 147 | return uri; | ||
| 148 | } | ||
| 149 | |||
| 150 | public String getType() { | ||
| 151 | return type; | ||
| 152 | } | ||
| 153 | |||
| 154 | public List getTransforms() { | ||
| 155 | return transforms; | ||
| 156 | } | ||
| 157 | |||
| 158 | public void marshal(Node parent, String dsPrefix, DOMCryptoContext context) | ||
| 159 | throws MarshalException { | ||
| 160 | Document ownerDoc = DOMUtils.getOwnerDocument(parent); | ||
| 161 | |||
| 162 | Element rmElem = DOMUtils.createElement | ||
| 163 | (ownerDoc, "RetrievalMethod", XMLSignature.XMLNS, dsPrefix); | ||
| 164 | |||
| 165 | // add URI and Type attributes | ||
| 166 | DOMUtils.setAttribute(rmElem, "URI", uri); | ||
| 167 | DOMUtils.setAttribute(rmElem, "Type", type); | ||
| 168 | |||
| 169 | // add Transforms elements | ||
| 170 | if (!transforms.isEmpty()) { | ||
| 171 | Element transformsElem = DOMUtils.createElement | ||
| 172 | (ownerDoc, "Transforms", XMLSignature.XMLNS, dsPrefix); | ||
| 173 | rmElem.appendChild(transformsElem); | ||
| 174 | for (int i = 0, size = transforms.size(); i < size; i++) { | ||
| 175 | ((DOMTransform) transforms.get(i)).marshal | ||
| 176 | (transformsElem, dsPrefix, context); | ||
| 177 | } | ||
| 178 | } | ||
| 179 | |||
| 180 | parent.appendChild(rmElem); | ||
| 181 | |||
| 182 | // save here node | ||
| 183 | here = rmElem.getAttributeNodeNS(null, "URI"); | ||
| 184 | } | ||
| 185 | |||
| 186 | public Node getHere() { | ||
| 187 | return here; | ||
| 188 | } | ||
| 189 | |||
| 190 | public Data dereference(XMLCryptoContext context) | ||
| 191 | throws URIReferenceException { | ||
| 192 | |||
| 193 | if (context == null) { | ||
| 194 | throw new NullPointerException("context cannot be null"); | ||
| 195 | } | ||
| 196 | |||
| 197 | /* | ||
| 198 | * If URIDereferencer is specified in context; use it, otherwise use | ||
| 199 | * built-in. | ||
| 200 | */ | ||
| 201 | URIDereferencer deref = context.getURIDereferencer(); | ||
| 202 | if (deref == null) { | ||
| 203 | deref = DOMURIDereferencer.INSTANCE; | ||
| 204 | } | ||
| 205 | |||
| 206 | Data data = deref.dereference(this, context); | ||
| 207 | |||
| 208 | // pass dereferenced data through Transforms | ||
| 209 | try { | ||
| 210 | for (int i = 0, size = transforms.size(); i < size; i++) { | ||
| 211 | Transform transform = (Transform) transforms.get(i); | ||
| 212 | data = ((DOMTransform) transform).transform(data, context); | ||
| 213 | } | ||
| 214 | } catch (Exception e) { | ||
| 215 | throw new URIReferenceException(e); | ||
| 216 | } | ||
| 217 | return data; | ||
| 218 | } | ||
| 219 | |||
| 220 | public XMLStructure dereferenceAsXMLStructure(XMLCryptoContext context) | ||
| 221 | throws URIReferenceException { | ||
| 222 | |||
| 223 | try { | ||
| 224 | ApacheData data = (ApacheData) dereference(context); | ||
| 225 | DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); | ||
| 226 | dbf.setNamespaceAware(true); | ||
| 227 | DocumentBuilder db = dbf.newDocumentBuilder(); | ||
| 228 | Document doc = db.parse(new ByteArrayInputStream | ||
| 229 | (data.getXMLSignatureInput().getBytes())); | ||
| 230 | Element kiElem = doc.getDocumentElement(); | ||
| 231 | if (kiElem.getLocalName().equals("X509Data")) { | ||
| 232 | return new DOMX509Data(kiElem); | ||
| 233 | } else { | ||
| 234 | return null; // unsupported | ||
| 235 | } | ||
| 236 | } catch (Exception e) { | ||
| 237 | throw new URIReferenceException(e); | ||
| 238 | } | ||
| 239 | } | ||
| 240 | |||
| 241 | public boolean equals(Object obj) { | ||
| 242 | if (this == obj) { | ||
| 243 | return true; | ||
| 244 | } | ||
| 245 | if (!(obj instanceof RetrievalMethod)) { | ||
| 246 | return false; | ||
| 247 | } | ||
| 248 | RetrievalMethod orm = (RetrievalMethod) obj; | ||
| 249 | |||
| 250 | boolean typesEqual = (type == null ? orm.getType() == null : | ||
| 251 | type.equals(orm.getType())); | ||
| 252 | |||
| 253 | return (uri.equals(orm.getURI()) && | ||
| 254 | transforms.equals(orm.getTransforms()) && typesEqual); | ||
| 255 | } | ||
| 256 | } | ||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,527 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DOMSignatureMethod.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import javax.xml.crypto.*; | ||
| 30 | import javax.xml.crypto.dom.DOMCryptoContext; | ||
| 31 | import javax.xml.crypto.dsig.*; | ||
| 32 | import javax.xml.crypto.dsig.spec.SignatureMethodParameterSpec; | ||
| 33 | |||
| 34 | import java.io.IOException; | ||
| 35 | import java.security.*; | ||
| 36 | import java.security.spec.AlgorithmParameterSpec; | ||
| 37 | import java.util.logging.Level; | ||
| 38 | import java.util.logging.Logger; | ||
| 39 | import org.w3c.dom.Document; | ||
| 40 | import org.w3c.dom.Element; | ||
| 41 | import org.w3c.dom.Node; | ||
| 42 | |||
| 43 | import org.jcp.xml.dsig.internal.SignerOutputStream; | ||
| 44 | |||
| 45 | /** | ||
| 46 | * DOM-based abstract implementation of SignatureMethod. | ||
| 47 | * | ||
| 48 | * @author Sean Mullan | ||
| 49 | */ | ||
| 50 | public abstract class DOMSignatureMethod extends DOMStructure | ||
| 51 | implements SignatureMethod { | ||
| 52 | |||
| 53 | private static Logger log = | ||
| 54 | Logger.getLogger("org.jcp.xml.dsig.internal.dom"); | ||
| 55 | |||
| 56 | // see RFC 4051 for these algorithm definitions | ||
| 57 | final static String RSA_SHA256 = | ||
| 58 | "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"; | ||
| 59 | final static String RSA_SHA384 = | ||
| 60 | "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384"; | ||
| 61 | final static String RSA_SHA512 = | ||
| 62 | "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"; | ||
| 63 | final static String HMAC_SHA256 = | ||
| 64 | "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256"; | ||
| 65 | final static String HMAC_SHA384 = | ||
| 66 | "http://www.w3.org/2001/04/xmldsig-more#hmac-sha384"; | ||
| 67 | final static String HMAC_SHA512 = | ||
| 68 | "http://www.w3.org/2001/04/xmldsig-more#hmac-sha512"; | ||
| 69 | |||
| 70 | private SignatureMethodParameterSpec params; | ||
| 71 | private Signature signature; | ||
| 72 | |||
| 73 | /** | ||
| 74 | * Creates a <code>DOMSignatureMethod</code>. | ||
| 75 | * | ||
| 76 | * @param params the algorithm-specific params (may be <code>null</code>) | ||
| 77 | * @throws InvalidAlgorithmParameterException if the parameters are not | ||
| 78 | * appropriate for this signature method | ||
| 79 | */ | ||
| 80 | DOMSignatureMethod(AlgorithmParameterSpec params) | ||
| 81 | throws InvalidAlgorithmParameterException { | ||
| 82 | if (params != null && | ||
| 83 | !(params instanceof SignatureMethodParameterSpec)) { | ||
| 84 | throw new InvalidAlgorithmParameterException | ||
| 85 | ("params must be of type SignatureMethodParameterSpec"); | ||
| 86 | } | ||
| 87 | checkParams((SignatureMethodParameterSpec) params); | ||
| 88 | this.params = (SignatureMethodParameterSpec) params; | ||
| 89 | } | ||
| 90 | |||
| 91 | /** | ||
| 92 | * Creates a <code>DOMSignatureMethod</code> from an element. This ctor | ||
| 93 | * invokes the abstract {@link #unmarshalParams unmarshalParams} method to | ||
| 94 | * unmarshal any algorithm-specific input parameters. | ||
| 95 | * | ||
| 96 | * @param smElem a SignatureMethod element | ||
| 97 | */ | ||
| 98 | DOMSignatureMethod(Element smElem) throws MarshalException { | ||
| 99 | Element paramsElem = DOMUtils.getFirstChildElement(smElem); | ||
| 100 | if (paramsElem != null) { | ||
| 101 | params = unmarshalParams(paramsElem); | ||
| 102 | } | ||
| 103 | try { | ||
| 104 | checkParams(params); | ||
| 105 | } catch (InvalidAlgorithmParameterException iape) { | ||
| 106 | throw new MarshalException(iape); | ||
| 107 | } | ||
| 108 | } | ||
| 109 | |||
| 110 | static SignatureMethod unmarshal(Element smElem) throws MarshalException { | ||
| 111 | String alg = DOMUtils.getAttributeValue(smElem, "Algorithm"); | ||
| 112 | if (alg.equals(SignatureMethod.RSA_SHA1)) { | ||
| 113 | return new SHA1withRSA(smElem); | ||
| 114 | } else if (alg.equals(RSA_SHA256)) { | ||
| 115 | return new SHA256withRSA(smElem); | ||
| 116 | } else if (alg.equals(RSA_SHA384)) { | ||
| 117 | return new SHA384withRSA(smElem); | ||
| 118 | } else if (alg.equals(RSA_SHA512)) { | ||
| 119 | return new SHA512withRSA(smElem); | ||
| 120 | } else if (alg.equals(SignatureMethod.DSA_SHA1)) { | ||
| 121 | return new SHA1withDSA(smElem); | ||
| 122 | } else if (alg.equals(SignatureMethod.HMAC_SHA1)) { | ||
| 123 | return new DOMHMACSignatureMethod.SHA1(smElem); | ||
| 124 | } else if (alg.equals(HMAC_SHA256)) { | ||
| 125 | return new DOMHMACSignatureMethod.SHA256(smElem); | ||
| 126 | } else if (alg.equals(HMAC_SHA384)) { | ||
| 127 | return new DOMHMACSignatureMethod.SHA384(smElem); | ||
| 128 | } else if (alg.equals(HMAC_SHA512)) { | ||
| 129 | return new DOMHMACSignatureMethod.SHA512(smElem); | ||
| 130 | } else { | ||
| 131 | throw new MarshalException | ||
| 132 | ("unsupported SignatureMethod algorithm: " + alg); | ||
| 133 | } | ||
| 134 | } | ||
| 135 | |||
| 136 | /** | ||
| 137 | * Checks if the specified parameters are valid for this algorithm. By | ||
| 138 | * default, this method throws an exception if parameters are specified | ||
| 139 | * since most SignatureMethod algorithms do not have parameters. Subclasses | ||
| 140 | * should override it if they have parameters. | ||
| 141 | * | ||
| 142 | * @param params the algorithm-specific params (may be <code>null</code>) | ||
| 143 | * @throws InvalidAlgorithmParameterException if the parameters are not | ||
| 144 | * appropriate for this signature method | ||
| 145 | */ | ||
| 146 | void checkParams(SignatureMethodParameterSpec params) | ||
| 147 | throws InvalidAlgorithmParameterException { | ||
| 148 | if (params != null) { | ||
| 149 | throw new InvalidAlgorithmParameterException("no parameters " + | ||
| 150 | "should be specified for the " + getSignatureAlgorithm() | ||
| 151 | + " SignatureMethod algorithm"); | ||
| 152 | } | ||
| 153 | } | ||
| 154 | |||
| 155 | public final AlgorithmParameterSpec getParameterSpec() { | ||
| 156 | return params; | ||
| 157 | } | ||
| 158 | |||
| 159 | /** | ||
| 160 | * Unmarshals <code>SignatureMethodParameterSpec</code> from the specified | ||
| 161 | * <code>Element</code>. By default, this method throws an exception since | ||
| 162 | * most SignatureMethod algorithms do not have parameters. Subclasses should | ||
| 163 | * override it if they have parameters. | ||
| 164 | * | ||
| 165 | * @param paramsElem the <code>Element</code> holding the input params | ||
| 166 | * @return the algorithm-specific <code>SignatureMethodParameterSpec</code> | ||
| 167 | * @throws MarshalException if the parameters cannot be unmarshalled | ||
| 168 | */ | ||
| 169 | SignatureMethodParameterSpec | ||
| 170 | unmarshalParams(Element paramsElem) throws MarshalException { | ||
| 171 | throw new MarshalException("no parameters should " + | ||
| 172 | "be specified for the " + getSignatureAlgorithm() + | ||
| 173 | " SignatureMethod algorithm"); | ||
| 174 | } | ||
| 175 | |||
| 176 | /** | ||
| 177 | * This method invokes the abstract {@link #marshalParams marshalParams} | ||
| 178 | * method to marshal any algorithm-specific parameters. | ||
| 179 | */ | ||
| 180 | public void marshal(Node parent, String dsPrefix, DOMCryptoContext context) | ||
| 181 | throws MarshalException { | ||
| 182 | Document ownerDoc = DOMUtils.getOwnerDocument(parent); | ||
| 183 | |||
| 184 | Element smElem = DOMUtils.createElement | ||
| 185 | (ownerDoc, "SignatureMethod", XMLSignature.XMLNS, dsPrefix); | ||
| 186 | DOMUtils.setAttribute(smElem, "Algorithm", getAlgorithm()); | ||
| 187 | |||
| 188 | if (params != null) { | ||
| 189 | marshalParams(smElem, dsPrefix); | ||
| 190 | } | ||
| 191 | |||
| 192 | parent.appendChild(smElem); | ||
| 193 | } | ||
| 194 | |||
| 195 | /** | ||
| 196 | * Verifies the passed-in signature with the specified key, using the | ||
| 197 | * underlying signature or MAC algorithm. | ||
| 198 | * | ||
| 199 | * @param key the verification key | ||
| 200 | * @param si the DOMSignedInfo | ||
| 201 | * @param signature the signature bytes to be verified | ||
| 202 | * @param context the XMLValidateContext | ||
| 203 | * @return <code>true</code> if the signature verified successfully, | ||
| 204 | * <code>false</code> if not | ||
| 205 | * @throws NullPointerException if <code>key</code>, <code>si</code> or | ||
| 206 | * <code>signature</code> are <code>null</code> | ||
| 207 | * @throws InvalidKeyException if the key is improperly encoded, of | ||
| 208 | * the wrong type, or parameters are missing, etc | ||
| 209 | * @throws SignatureException if an unexpected error occurs, such | ||
| 210 | * as the passed in signature is improperly encoded | ||
| 211 | * @throws XMLSignatureException if an unexpected error occurs | ||
| 212 | */ | ||
| 213 | boolean verify(Key key, DOMSignedInfo si, byte[] sig, | ||
| 214 | XMLValidateContext context) throws InvalidKeyException, | ||
| 215 | SignatureException, XMLSignatureException { | ||
| 216 | if (key == null || si == null || sig == null) { | ||
| 217 | throw new NullPointerException(); | ||
| 218 | } | ||
| 219 | |||
| 220 | if (!(key instanceof PublicKey)) { | ||
| 221 | throw new InvalidKeyException("key must be PublicKey"); | ||
| 222 | } | ||
| 223 | if (signature == null) { | ||
| 224 | try { | ||
| 225 | Provider p = (Provider) context.getProperty | ||
| 226 | ("org.jcp.xml.dsig.internal.dom.SignatureProvider"); | ||
| 227 | signature = (p == null) | ||
| 228 | ? Signature.getInstance(getSignatureAlgorithm()) | ||
| 229 | : Signature.getInstance(getSignatureAlgorithm(), p); | ||
| 230 | } catch (NoSuchAlgorithmException nsae) { | ||
| 231 | throw new XMLSignatureException(nsae); | ||
| 232 | } | ||
| 233 | } | ||
| 234 | signature.initVerify((PublicKey) key); | ||
| 235 | if (log.isLoggable(Level.FINE)) { | ||
| 236 | log.log(Level.FINE, "Signature provider:"+ signature.getProvider()); | ||
| 237 | log.log(Level.FINE, "verifying with key: " + key); | ||
| 238 | } | ||
| 239 | si.canonicalize(context, new SignerOutputStream(signature)); | ||
| 240 | |||
| 241 | if (getAlgorithm().equals(SignatureMethod.DSA_SHA1)) { | ||
| 242 | try { | ||
| 243 | return signature.verify(convertXMLDSIGtoASN1(sig)); | ||
| 244 | } catch (IOException ioe) { | ||
| 245 | throw new XMLSignatureException(ioe); | ||
| 246 | } | ||
| 247 | } else { | ||
| 248 | return signature.verify(sig); | ||
| 249 | } | ||
| 250 | } | ||
| 251 | |||
| 252 | /** | ||
| 253 | * Signs the bytes with the specified key, using the underlying | ||
| 254 | * signature or MAC algorithm. | ||
| 255 | * | ||
| 256 | * @param key the signing key | ||
| 257 | * @param si the DOMSignedInfo | ||
| 258 | * @param context the XMLSignContext | ||
| 259 | * @return the signature | ||
| 260 | * @throws NullPointerException if <code>key</code> or | ||
| 261 | * <code>si</code> are <code>null</code> | ||
| 262 | * @throws InvalidKeyException if the key is improperly encoded, of | ||
| 263 | * the wrong type, or parameters are missing, etc | ||
| 264 | * @throws XMLSignatureException if an unexpected error occurs | ||
| 265 | */ | ||
| 266 | byte[] sign(Key key, DOMSignedInfo si, XMLSignContext context) | ||
| 267 | throws InvalidKeyException, XMLSignatureException { | ||
| 268 | if (key == null || si == null) { | ||
| 269 | throw new NullPointerException(); | ||
| 270 | } | ||
| 271 | |||
| 272 | if (!(key instanceof PrivateKey)) { | ||
| 273 | throw new InvalidKeyException("key must be PrivateKey"); | ||
| 274 | } | ||
| 275 | if (signature == null) { | ||
| 276 | try { | ||
| 277 | Provider p = (Provider) context.getProperty | ||
| 278 | ("org.jcp.xml.dsig.internal.dom.SignatureProvider"); | ||
| 279 | signature = (p == null) | ||
| 280 | ? Signature.getInstance(getSignatureAlgorithm()) | ||
| 281 | : Signature.getInstance(getSignatureAlgorithm(), p); | ||
| 282 | } catch (NoSuchAlgorithmException nsae) { | ||
| 283 | throw new XMLSignatureException(nsae); | ||
| 284 | } | ||
| 285 | } | ||
| 286 | signature.initSign((PrivateKey) key); | ||
| 287 | if (log.isLoggable(Level.FINE)) { | ||
| 288 | log.log(Level.FINE, "Signature provider:" +signature.getProvider()); | ||
| 289 | log.log(Level.FINE, "Signing with key: " + key); | ||
| 290 | } | ||
| 291 | |||
| 292 | si.canonicalize(context, new SignerOutputStream(signature)); | ||
| 293 | |||
| 294 | try { | ||
| 295 | if (getAlgorithm().equals(SignatureMethod.DSA_SHA1)) { | ||
| 296 | return convertASN1toXMLDSIG(signature.sign()); | ||
| 297 | } else { | ||
| 298 | return signature.sign(); | ||
| 299 | } | ||
| 300 | } catch (SignatureException se) { | ||
| 301 | throw new XMLSignatureException(se); | ||
| 302 | } catch (IOException ioe) { | ||
| 303 | throw new XMLSignatureException(ioe); | ||
| 304 | } | ||
| 305 | } | ||
| 306 | |||
| 307 | /** | ||
| 308 | * Marshals the algorithm-specific parameters to an Element and | ||
| 309 | * appends it to the specified parent element. By default, this method | ||
| 310 | * throws an exception since most SignatureMethod algorithms do not have | ||
| 311 | * parameters. Subclasses should override it if they have parameters. | ||
| 312 | * | ||
| 313 | * @param parent the parent element to append the parameters to | ||
| 314 | * @param paramsPrefix the algorithm parameters prefix to use | ||
| 315 | * @throws MarshalException if the parameters cannot be marshalled | ||
| 316 | */ | ||
| 317 | void marshalParams(Element parent, String paramsPrefix) | ||
| 318 | throws MarshalException { | ||
| 319 | throw new MarshalException("no parameters should " + | ||
| 320 | "be specified for the " + getSignatureAlgorithm() + | ||
| 321 | " SignatureMethod algorithm"); | ||
| 322 | } | ||
| 323 | |||
| 324 | /** | ||
| 325 | * Returns the java.security.Signature standard algorithm name. | ||
| 326 | */ | ||
| 327 | abstract String getSignatureAlgorithm(); | ||
| 328 | |||
| 329 | /** | ||
| 330 | * Returns true if parameters are equal; false otherwise. | ||
| 331 | * | ||
| 332 | * Subclasses should override this method to compare algorithm-specific | ||
| 333 | * parameters. | ||
| 334 | */ | ||
| 335 | boolean paramsEqual(AlgorithmParameterSpec spec) { | ||
| 336 | return (getParameterSpec() == spec); | ||
| 337 | } | ||
| 338 | |||
| 339 | public boolean equals(Object o) { | ||
| 340 | if (this == o) { | ||
| 341 | return true; | ||
| 342 | } | ||
| 343 | |||
| 344 | if (!(o instanceof SignatureMethod)) { | ||
| 345 | return false; | ||
| 346 | } | ||
| 347 | SignatureMethod osm = (SignatureMethod) o; | ||
| 348 | |||
| 349 | return (getAlgorithm().equals(osm.getAlgorithm()) && | ||
| 350 | paramsEqual(osm.getParameterSpec())); | ||
| 351 | } | ||
| 352 | |||
| 353 | /** | ||
| 354 | * Converts an ASN.1 DSA value to a XML Signature DSA Value. | ||
| 355 | * | ||
| 356 | * The JAVA JCE DSA Signature algorithm creates ASN.1 encoded (r,s) value | ||
| 357 | * pairs; the XML Signature requires the core BigInteger values. | ||
| 358 | * | ||
| 359 | * @param asn1Bytes | ||
| 360 | * | ||
| 361 | * @throws IOException | ||
| 362 | * @see <A HREF="http://www.w3.org/TR/xmldsig-core/#dsa-sha1">6.4.1 DSA</A> | ||
| 363 | */ | ||
| 364 | private static byte[] convertASN1toXMLDSIG(byte asn1Bytes[]) | ||
| 365 | throws IOException { | ||
| 366 | |||
| 367 | byte rLength = asn1Bytes[3]; | ||
| 368 | int i; | ||
| 369 | |||
| 370 | for (i = rLength; (i > 0) && (asn1Bytes[(4 + rLength) - i] == 0); i--); | ||
| 371 | |||
| 372 | byte sLength = asn1Bytes[5 + rLength]; | ||
| 373 | int j; | ||
| 374 | |||
| 375 | for (j = sLength; | ||
| 376 | (j > 0) && (asn1Bytes[(6 + rLength + sLength) - j] == 0); j--); | ||
| 377 | |||
| 378 | if ((asn1Bytes[0] != 48) || (asn1Bytes[1] != asn1Bytes.length - 2) | ||
| 379 | || (asn1Bytes[2] != 2) || (i > 20) | ||
| 380 | || (asn1Bytes[4 + rLength] != 2) || (j > 20)) { | ||
| 381 | throw new IOException("Invalid ASN.1 format of DSA signature"); | ||
| 382 | } else { | ||
| 383 | byte xmldsigBytes[] = new byte[40]; | ||
| 384 | |||
| 385 | System.arraycopy(asn1Bytes, (4+rLength)-i, xmldsigBytes, 20-i, i); | ||
| 386 | System.arraycopy(asn1Bytes, (6+rLength+sLength)-j, xmldsigBytes, | ||
| 387 | 40 - j, j); | ||
| 388 | |||
| 389 | return xmldsigBytes; | ||
| 390 | } | ||
| 391 | } | ||
| 392 | |||
| 393 | /** | ||
| 394 | * Converts a XML Signature DSA Value to an ASN.1 DSA value. | ||
| 395 | * | ||
| 396 | * The JAVA JCE DSA Signature algorithm creates ASN.1 encoded (r,s) value | ||
| 397 | * pairs; the XML Signature requires the core BigInteger values. | ||
| 398 | * | ||
| 399 | * @param xmldsigBytes | ||
| 400 | * | ||
| 401 | * @throws IOException | ||
| 402 | * @see <A HREF="http://www.w3.org/TR/xmldsig-core/#dsa-sha1">6.4.1 DSA</A> | ||
| 403 | */ | ||
| 404 | private static byte[] convertXMLDSIGtoASN1(byte xmldsigBytes[]) | ||
| 405 | throws IOException { | ||
| 406 | |||
| 407 | if (xmldsigBytes.length != 40) { | ||
| 408 | throw new IOException("Invalid XMLDSIG format of DSA signature"); | ||
| 409 | } | ||
| 410 | |||
| 411 | int i; | ||
| 412 | |||
| 413 | for (i = 20; (i > 0) && (xmldsigBytes[20 - i] == 0); i--); | ||
| 414 | |||
| 415 | int j = i; | ||
| 416 | |||
| 417 | if (xmldsigBytes[20 - i] < 0) { | ||
| 418 | j += 1; | ||
| 419 | } | ||
| 420 | |||
| 421 | int k; | ||
| 422 | |||
| 423 | for (k = 20; (k > 0) && (xmldsigBytes[40 - k] == 0); k--); | ||
| 424 | |||
| 425 | int l = k; | ||
| 426 | |||
| 427 | if (xmldsigBytes[40 - k] < 0) { | ||
| 428 | l += 1; | ||
| 429 | } | ||
| 430 | |||
| 431 | byte asn1Bytes[] = new byte[6 + j + l]; | ||
| 432 | |||
| 433 | asn1Bytes[0] = 48; | ||
| 434 | asn1Bytes[1] = (byte) (4 + j + l); | ||
| 435 | asn1Bytes[2] = 2; | ||
| 436 | asn1Bytes[3] = (byte) j; | ||
| 437 | |||
| 438 | System.arraycopy(xmldsigBytes, 20 - i, asn1Bytes, (4 + j) - i, i); | ||
| 439 | |||
| 440 | asn1Bytes[4 + j] = 2; | ||
| 441 | asn1Bytes[5 + j] = (byte) l; | ||
| 442 | |||
| 443 | System.arraycopy(xmldsigBytes, 40 - k, asn1Bytes, (6 + j + l) - k, k); | ||
| 444 | |||
| 445 | return asn1Bytes; | ||
| 446 | } | ||
| 447 | |||
| 448 | static final class SHA1withRSA extends DOMSignatureMethod { | ||
| 449 | SHA1withRSA(AlgorithmParameterSpec params) | ||
| 450 | throws InvalidAlgorithmParameterException { | ||
| 451 | super(params); | ||
| 452 | } | ||
| 453 | SHA1withRSA(Element dmElem) throws MarshalException { | ||
| 454 | super(dmElem); | ||
| 455 | } | ||
| 456 | public String getAlgorithm() { | ||
| 457 | return SignatureMethod.RSA_SHA1; | ||
| 458 | } | ||
| 459 | String getSignatureAlgorithm() { | ||
| 460 | return "SHA1withRSA"; | ||
| 461 | } | ||
| 462 | } | ||
| 463 | |||
| 464 | static final class SHA256withRSA extends DOMSignatureMethod { | ||
| 465 | SHA256withRSA(AlgorithmParameterSpec params) | ||
| 466 | throws InvalidAlgorithmParameterException { | ||
| 467 | super(params); | ||
| 468 | } | ||
| 469 | SHA256withRSA(Element dmElem) throws MarshalException { | ||
| 470 | super(dmElem); | ||
| 471 | } | ||
| 472 | public String getAlgorithm() { | ||
| 473 | return RSA_SHA256; | ||
| 474 | } | ||
| 475 | String getSignatureAlgorithm() { | ||
| 476 | return "SHA256withRSA"; | ||
| 477 | } | ||
| 478 | } | ||
| 479 | |||
| 480 | static final class SHA384withRSA extends DOMSignatureMethod { | ||
| 481 | SHA384withRSA(AlgorithmParameterSpec params) | ||
| 482 | throws InvalidAlgorithmParameterException { | ||
| 483 | super(params); | ||
| 484 | } | ||
| 485 | SHA384withRSA(Element dmElem) throws MarshalException { | ||
| 486 | super(dmElem); | ||
| 487 | } | ||
| 488 | public String getAlgorithm() { | ||
| 489 | return RSA_SHA384; | ||
| 490 | } | ||
| 491 | String getSignatureAlgorithm() { | ||
| 492 | return "SHA384withRSA"; | ||
| 493 | } | ||
| 494 | } | ||
| 495 | |||
| 496 | static final class SHA512withRSA extends DOMSignatureMethod { | ||
| 497 | SHA512withRSA(AlgorithmParameterSpec params) | ||
| 498 | throws InvalidAlgorithmParameterException { | ||
| 499 | super(params); | ||
| 500 | } | ||
| 501 | SHA512withRSA(Element dmElem) throws MarshalException { | ||
| 502 | super(dmElem); | ||
| 503 | } | ||
| 504 | public String getAlgorithm() { | ||
| 505 | return RSA_SHA512; | ||
| 506 | } | ||
| 507 | String getSignatureAlgorithm() { | ||
| 508 | return "SHA512withRSA"; | ||
| 509 | } | ||
| 510 | } | ||
| 511 | |||
| 512 | static final class SHA1withDSA extends DOMSignatureMethod { | ||
| 513 | SHA1withDSA(AlgorithmParameterSpec params) | ||
| 514 | throws InvalidAlgorithmParameterException { | ||
| 515 | super(params); | ||
| 516 | } | ||
| 517 | SHA1withDSA(Element dmElem) throws MarshalException { | ||
| 518 | super(dmElem); | ||
| 519 | } | ||
| 520 | public String getAlgorithm() { | ||
| 521 | return SignatureMethod.DSA_SHA1; | ||
| 522 | } | ||
| 523 | String getSignatureAlgorithm() { | ||
| 524 | return "SHA1withDSA"; | ||
| 525 | } | ||
| 526 | } | ||
| 527 | } | ||
Binary file not shown.
| @@ -0,0 +1,150 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DOMSignatureProperties.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import javax.xml.crypto.*; | ||
| 30 | import javax.xml.crypto.dom.DOMCryptoContext; | ||
| 31 | import javax.xml.crypto.dsig.*; | ||
| 32 | |||
| 33 | import java.util.*; | ||
| 34 | import org.w3c.dom.Document; | ||
| 35 | import org.w3c.dom.Element; | ||
| 36 | import org.w3c.dom.Node; | ||
| 37 | import org.w3c.dom.NodeList; | ||
| 38 | |||
| 39 | /** | ||
| 40 | * DOM-based implementation of SignatureProperties. | ||
| 41 | * | ||
| 42 | * @author Sean Mullan | ||
| 43 | */ | ||
| 44 | public final class DOMSignatureProperties extends DOMStructure | ||
| 45 | implements SignatureProperties { | ||
| 46 | |||
| 47 | private final String id; | ||
| 48 | private final List properties; | ||
| 49 | |||
| 50 | /** | ||
| 51 | * Creates a <code>DOMSignatureProperties</code> from the specified | ||
| 52 | * parameters. | ||
| 53 | * | ||
| 54 | * @param properties a list of one or more {@link SignatureProperty}s. The | ||
| 55 | * list is defensively copied to protect against subsequent modification. | ||
| 56 | * @param id the Id (may be <code>null</code>) | ||
| 57 | * @return a <code>DOMSignatureProperties</code> | ||
| 58 | * @throws ClassCastException if <code>properties</code> contains any | ||
| 59 | * entries that are not of type {@link SignatureProperty} | ||
| 60 | * @throws IllegalArgumentException if <code>properties</code> is empty | ||
| 61 | * @throws NullPointerException if <code>properties</code> | ||
| 62 | */ | ||
| 63 | public DOMSignatureProperties(List properties, String id) { | ||
| 64 | if (properties == null) { | ||
| 65 | throw new NullPointerException("properties cannot be null"); | ||
| 66 | } else if (properties.isEmpty()) { | ||
| 67 | throw new IllegalArgumentException("properties cannot be empty"); | ||
| 68 | } else { | ||
| 69 | List propsCopy = new ArrayList(properties); | ||
| 70 | for (int i = 0, size = propsCopy.size(); i < size; i++) { | ||
| 71 | if (!(propsCopy.get(i) instanceof SignatureProperty)) { | ||
| 72 | throw new ClassCastException | ||
| 73 | ("properties["+i+"] is not a valid type"); | ||
| 74 | } | ||
| 75 | } | ||
| 76 | this.properties = Collections.unmodifiableList(propsCopy); | ||
| 77 | } | ||
| 78 | this.id = id; | ||
| 79 | } | ||
| 80 | |||
| 81 | /** | ||
| 82 | * Creates a <code>DOMSignatureProperties</code> from an element. | ||
| 83 | * | ||
| 84 | * @param propsElem a SignatureProperties element | ||
| 85 | * @throws MarshalException if a marshalling error occurs | ||
| 86 | */ | ||
| 87 | public DOMSignatureProperties(Element propsElem) throws MarshalException{ | ||
| 88 | // unmarshal attributes | ||
| 89 | id = DOMUtils.getAttributeValue(propsElem, "Id"); | ||
| 90 | |||
| 91 | NodeList nodes = propsElem.getChildNodes(); | ||
| 92 | int length = nodes.getLength(); | ||
| 93 | List properties = new ArrayList(length); | ||
| 94 | for (int i = 0; i < length; i++) { | ||
| 95 | Node child = nodes.item(i); | ||
| 96 | if (child.getNodeType() == Node.ELEMENT_NODE) { | ||
| 97 | properties.add(new DOMSignatureProperty((Element) child)); | ||
| 98 | } | ||
| 99 | } | ||
| 100 | if (properties.isEmpty()) { | ||
| 101 | throw new MarshalException("properties cannot be empty"); | ||
| 102 | } else { | ||
| 103 | this.properties = Collections.unmodifiableList(properties); | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | public List getProperties() { | ||
| 108 | return properties; | ||
| 109 | } | ||
| 110 | |||
| 111 | public String getId() { | ||
| 112 | return id; | ||
| 113 | } | ||
| 114 | |||
| 115 | public void marshal(Node parent, String dsPrefix, DOMCryptoContext context) | ||
| 116 | throws MarshalException { | ||
| 117 | Document ownerDoc = DOMUtils.getOwnerDocument(parent); | ||
| 118 | |||
| 119 | Element propsElem = DOMUtils.createElement | ||
| 120 | (ownerDoc, "SignatureProperties", XMLSignature.XMLNS, dsPrefix); | ||
| 121 | |||
| 122 | // set attributes | ||
| 123 | DOMUtils.setAttributeID(propsElem, "Id", id); | ||
| 124 | |||
| 125 | // create and append any properties | ||
| 126 | for (int i = 0, size = properties.size(); i < size; i++) { | ||
| 127 | DOMSignatureProperty property = | ||
| 128 | (DOMSignatureProperty) properties.get(i); | ||
| 129 | property.marshal(propsElem, dsPrefix, context); | ||
| 130 | } | ||
| 131 | |||
| 132 | parent.appendChild(propsElem); | ||
| 133 | } | ||
| 134 | |||
| 135 | public boolean equals(Object o) { | ||
| 136 | if (this == o) { | ||
| 137 | return true; | ||
| 138 | } | ||
| 139 | |||
| 140 | if (!(o instanceof SignatureProperties)) { | ||
| 141 | return false; | ||
| 142 | } | ||
| 143 | SignatureProperties osp = (SignatureProperties) o; | ||
| 144 | |||
| 145 | boolean idsEqual = (id == null ? osp.getId() == null : | ||
| 146 | id.equals(osp.getId())); | ||
| 147 | |||
| 148 | return (properties.equals(osp.getProperties()) && idsEqual); | ||
| 149 | } | ||
| 150 | } | ||
Binary file not shown.
| @@ -0,0 +1,190 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DOMSignatureProperty.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import javax.xml.crypto.*; | ||
| 30 | import javax.xml.crypto.dom.DOMCryptoContext; | ||
| 31 | import javax.xml.crypto.dsig.*; | ||
| 32 | |||
| 33 | import java.util.*; | ||
| 34 | import org.w3c.dom.Document; | ||
| 35 | import org.w3c.dom.Element; | ||
| 36 | import org.w3c.dom.Node; | ||
| 37 | import org.w3c.dom.NodeList; | ||
| 38 | |||
| 39 | /** | ||
| 40 | * DOM-based implementation of SignatureProperty. | ||
| 41 | * | ||
| 42 | * @author Sean Mullan | ||
| 43 | */ | ||
| 44 | public final class DOMSignatureProperty extends DOMStructure | ||
| 45 | implements SignatureProperty { | ||
| 46 | |||
| 47 | private final String id; | ||
| 48 | private final String target; | ||
| 49 | private final List content; | ||
| 50 | |||
| 51 | /** | ||
| 52 | * Creates a <code>SignatureProperty</code> from the specified parameters. | ||
| 53 | * | ||
| 54 | * @param content a list of one or more {@link XMLStructure}s. The list | ||
| 55 | * is defensively copied to protect against subsequent modification. | ||
| 56 | * @param target the target URI | ||
| 57 | * @param id the Id (may be <code>null</code>) | ||
| 58 | * @return a <code>SignatureProperty</code> | ||
| 59 | * @throws ClassCastException if <code>content</code> contains any | ||
| 60 | * entries that are not of type {@link XMLStructure} | ||
| 61 | * @throws IllegalArgumentException if <code>content</code> is empty | ||
| 62 | * @throws NullPointerException if <code>content</code> or | ||
| 63 | * <code>target</code> is <code>null</code> | ||
| 64 | */ | ||
| 65 | public DOMSignatureProperty(List content, String target, String id) { | ||
| 66 | if (target == null) { | ||
| 67 | throw new NullPointerException("target cannot be null"); | ||
| 68 | } else if (content == null) { | ||
| 69 | throw new NullPointerException("content cannot be null"); | ||
| 70 | } else if (content.isEmpty()) { | ||
| 71 | throw new IllegalArgumentException("content cannot be empty"); | ||
| 72 | } else { | ||
| 73 | List contentCopy = new ArrayList(content); | ||
| 74 | for (int i = 0, size = contentCopy.size(); i < size; i++) { | ||
| 75 | if (!(contentCopy.get(i) instanceof XMLStructure)) { | ||
| 76 | throw new ClassCastException | ||
| 77 | ("content["+i+"] is not a valid type"); | ||
| 78 | } | ||
| 79 | } | ||
| 80 | this.content = Collections.unmodifiableList(contentCopy); | ||
| 81 | } | ||
| 82 | this.target = target; | ||
| 83 | this.id = id; | ||
| 84 | } | ||
| 85 | |||
| 86 | /** | ||
| 87 | * Creates a <code>DOMSignatureProperty</code> from an element. | ||
| 88 | * | ||
| 89 | * @param propElem a SignatureProperty element | ||
| 90 | */ | ||
| 91 | public DOMSignatureProperty(Element propElem) throws MarshalException { | ||
| 92 | // unmarshal attributes | ||
| 93 | target = DOMUtils.getAttributeValue(propElem, "Target"); | ||
| 94 | if (target == null) { | ||
| 95 | throw new MarshalException("target cannot be null"); | ||
| 96 | } | ||
| 97 | id = DOMUtils.getAttributeValue(propElem, "Id"); | ||
| 98 | |||
| 99 | NodeList nodes = propElem.getChildNodes(); | ||
| 100 | int length = nodes.getLength(); | ||
| 101 | List content = new ArrayList(length); | ||
| 102 | for (int i = 0; i < length; i++) { | ||
| 103 | content.add(new javax.xml.crypto.dom.DOMStructure(nodes.item(i))); | ||
| 104 | } | ||
| 105 | if (content.isEmpty()) { | ||
| 106 | throw new MarshalException("content cannot be empty"); | ||
| 107 | } else { | ||
| 108 | this.content = Collections.unmodifiableList(content); | ||
| 109 | } | ||
| 110 | } | ||
| 111 | |||
| 112 | public List getContent() { | ||
| 113 | return content; | ||
| 114 | } | ||
| 115 | |||
| 116 | public String getId() { | ||
| 117 | return id; | ||
| 118 | } | ||
| 119 | |||
| 120 | public String getTarget() { | ||
| 121 | return target; | ||
| 122 | } | ||
| 123 | |||
| 124 | public void marshal(Node parent, String dsPrefix, DOMCryptoContext context) | ||
| 125 | throws MarshalException { | ||
| 126 | Document ownerDoc = DOMUtils.getOwnerDocument(parent); | ||
| 127 | |||
| 128 | Element propElem = DOMUtils.createElement | ||
| 129 | (ownerDoc, "SignatureProperty", XMLSignature.XMLNS, dsPrefix); | ||
| 130 | |||
| 131 | // set attributes | ||
| 132 | DOMUtils.setAttributeID(propElem, "Id", id); | ||
| 133 | DOMUtils.setAttribute(propElem, "Target", target); | ||
| 134 | |||
| 135 | // create and append any elements and mixed content | ||
| 136 | for (int i = 0, size = content.size(); i < size; i++) { | ||
| 137 | javax.xml.crypto.dom.DOMStructure property = | ||
| 138 | (javax.xml.crypto.dom.DOMStructure) content.get(i); | ||
| 139 | DOMUtils.appendChild(propElem, property.getNode()); | ||
| 140 | } | ||
| 141 | |||
| 142 | parent.appendChild(propElem); | ||
| 143 | } | ||
| 144 | |||
| 145 | public boolean equals(Object o) { | ||
| 146 | if (this == o) { | ||
| 147 | return true; | ||
| 148 | } | ||
| 149 | |||
| 150 | if (!(o instanceof SignatureProperty)) { | ||
| 151 | return false; | ||
| 152 | } | ||
| 153 | SignatureProperty osp = (SignatureProperty) o; | ||
| 154 | |||
| 155 | boolean idsEqual = (id == null ? osp.getId() == null : | ||
| 156 | id.equals(osp.getId())); | ||
| 157 | |||
| 158 | return (equalsContent(osp.getContent()) && | ||
| 159 | target.equals(osp.getTarget()) && idsEqual); | ||
| 160 | } | ||
| 161 | |||
| 162 | private boolean equalsContent(List otherContent) { | ||
| 163 | int osize = otherContent.size(); | ||
| 164 | if (content.size() != osize) { | ||
| 165 | return false; | ||
| 166 | } | ||
| 167 | for (int i = 0; i < osize; i++) { | ||
| 168 | XMLStructure oxs = (XMLStructure) otherContent.get(i); | ||
| 169 | XMLStructure xs = (XMLStructure) content.get(i); | ||
| 170 | if (oxs instanceof javax.xml.crypto.dom.DOMStructure) { | ||
| 171 | if (!(xs instanceof javax.xml.crypto.dom.DOMStructure)) { | ||
| 172 | return false; | ||
| 173 | } | ||
| 174 | Node onode = | ||
| 175 | ((javax.xml.crypto.dom.DOMStructure) oxs).getNode(); | ||
| 176 | Node node = | ||
| 177 | ((javax.xml.crypto.dom.DOMStructure) xs).getNode(); | ||
| 178 | if (!DOMUtils.nodesEqual(node, onode)) { | ||
| 179 | return false; | ||
| 180 | } | ||
| 181 | } else { | ||
| 182 | if (!(xs.equals(oxs))) { | ||
| 183 | return false; | ||
| 184 | } | ||
| 185 | } | ||
| 186 | } | ||
| 187 | |||
| 188 | return true; | ||
| 189 | } | ||
| 190 | } | ||
Binary file not shown.
| @@ -0,0 +1,266 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DOMSignedInfo.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import javax.xml.crypto.*; | ||
| 30 | import javax.xml.crypto.dom.DOMCryptoContext; | ||
| 31 | import javax.xml.crypto.dsig.*; | ||
| 32 | |||
| 33 | import java.io.ByteArrayInputStream; | ||
| 34 | import java.io.ByteArrayOutputStream; | ||
| 35 | import java.io.InputStream; | ||
| 36 | import java.io.IOException; | ||
| 37 | import java.io.InputStreamReader; | ||
| 38 | import java.io.OutputStream; | ||
| 39 | import java.security.Provider; | ||
| 40 | import java.util.*; | ||
| 41 | import java.util.logging.Level; | ||
| 42 | import java.util.logging.Logger; | ||
| 43 | import org.w3c.dom.Document; | ||
| 44 | import org.w3c.dom.Element; | ||
| 45 | import org.w3c.dom.Node; | ||
| 46 | |||
| 47 | import com.sun.org.apache.xml.internal.security.utils.Base64; | ||
| 48 | import com.sun.org.apache.xml.internal.security.utils.UnsyncBufferedOutputStream; | ||
| 49 | import com.sun.org.apache.xml.internal.security.utils.XMLUtils; | ||
| 50 | |||
| 51 | /** | ||
| 52 | * DOM-based implementation of SignedInfo. | ||
| 53 | * | ||
| 54 | * @author Sean Mullan | ||
| 55 | */ | ||
| 56 | public final class DOMSignedInfo extends DOMStructure implements SignedInfo { | ||
| 57 | |||
| 58 | private static Logger log = Logger.getLogger("org.jcp.xml.dsig.internal.dom"); | ||
| 59 | private List references; | ||
| 60 | private CanonicalizationMethod canonicalizationMethod; | ||
| 61 | private SignatureMethod signatureMethod; | ||
| 62 | private String id; | ||
| 63 | private Document ownerDoc; | ||
| 64 | private Element localSiElem; | ||
| 65 | private InputStream canonData; | ||
| 66 | |||
| 67 | /** | ||
| 68 | * Creates a <code>DOMSignedInfo</code> from the specified parameters. Use | ||
| 69 | * this constructor when the <code>Id</code> is not specified. | ||
| 70 | * | ||
| 71 | * @param cm the canonicalization method | ||
| 72 | * @param sm the signature method | ||
| 73 | * @param references the list of references. The list is copied. | ||
| 74 | * @throws NullPointerException if | ||
| 75 | * <code>cm</code>, <code>sm</code>, or <code>references</code> is | ||
| 76 | * <code>null</code> | ||
| 77 | * @throws IllegalArgumentException if <code>references</code> is empty | ||
| 78 | * @throws ClassCastException if any of the references are not of | ||
| 79 | * type <code>Reference</code> | ||
| 80 | */ | ||
| 81 | public DOMSignedInfo(CanonicalizationMethod cm, SignatureMethod sm, | ||
| 82 | List references) { | ||
| 83 | if (cm == null || sm == null || references == null) { | ||
| 84 | throw new NullPointerException(); | ||
| 85 | } | ||
| 86 | this.canonicalizationMethod = cm; | ||
| 87 | this.signatureMethod = sm; | ||
| 88 | this.references = Collections.unmodifiableList | ||
| 89 | (new ArrayList(references)); | ||
| 90 | if (this.references.isEmpty()) { | ||
| 91 | throw new IllegalArgumentException("list of references must " + | ||
| 92 | "contain at least one entry"); | ||
| 93 | } | ||
| 94 | for (int i = 0, size = this.references.size(); i < size; i++) { | ||
| 95 | Object obj = this.references.get(i); | ||
| 96 | if (!(obj instanceof Reference)) { | ||
| 97 | throw new ClassCastException("list of references contains " + | ||
| 98 | "an illegal type"); | ||
| 99 | } | ||
| 100 | } | ||
| 101 | } | ||
| 102 | |||
| 103 | /** | ||
| 104 | * Creates a <code>DOMSignedInfo</code> from the specified parameters. | ||
| 105 | * | ||
| 106 | * @param cm the canonicalization method | ||
| 107 | * @param sm the signature method | ||
| 108 | * @param references the list of references. The list is copied. | ||
| 109 | * @param id an optional identifer that will allow this | ||
| 110 | * <code>SignedInfo</code> to be referenced by other signatures and | ||
| 111 | * objects | ||
| 112 | * @throws NullPointerException if <code>cm</code>, <code>sm</code>, | ||
| 113 | * or <code>references</code> is <code>null</code> | ||
| 114 | * @throws IllegalArgumentException if <code>references</code> is empty | ||
| 115 | * @throws ClassCastException if any of the references are not of | ||
| 116 | * type <code>Reference</code> | ||
| 117 | */ | ||
| 118 | public DOMSignedInfo(CanonicalizationMethod cm, SignatureMethod sm, | ||
| 119 | List references, String id) { | ||
| 120 | this(cm, sm, references); | ||
| 121 | this.id = id; | ||
| 122 | } | ||
| 123 | |||
| 124 | /** | ||
| 125 | * Creates a <code>DOMSignedInfo</code> from an element. | ||
| 126 | * | ||
| 127 | * @param siElem a SignedInfo element | ||
| 128 | */ | ||
| 129 | public DOMSignedInfo(Element siElem, XMLCryptoContext context, | ||
| 130 | Provider provider) throws MarshalException { | ||
| 131 | localSiElem = siElem; | ||
| 132 | ownerDoc = siElem.getOwnerDocument(); | ||
| 133 | |||
| 134 | // get Id attribute, if specified | ||
| 135 | id = DOMUtils.getAttributeValue(siElem, "Id"); | ||
| 136 | |||
| 137 | // unmarshal CanonicalizationMethod | ||
| 138 | Element cmElem = DOMUtils.getFirstChildElement(siElem); | ||
| 139 | canonicalizationMethod = new DOMCanonicalizationMethod | ||
| 140 | (cmElem, context, provider); | ||
| 141 | |||
| 142 | // unmarshal SignatureMethod | ||
| 143 | Element smElem = DOMUtils.getNextSiblingElement(cmElem); | ||
| 144 | signatureMethod = DOMSignatureMethod.unmarshal(smElem); | ||
| 145 | |||
| 146 | // unmarshal References | ||
| 147 | ArrayList refList = new ArrayList(5); | ||
| 148 | Element refElem = DOMUtils.getNextSiblingElement(smElem); | ||
| 149 | while (refElem != null) { | ||
| 150 | refList.add(new DOMReference(refElem, context, provider)); | ||
| 151 | refElem = DOMUtils.getNextSiblingElement(refElem); | ||
| 152 | } | ||
| 153 | references = Collections.unmodifiableList(refList); | ||
| 154 | } | ||
| 155 | |||
| 156 | public CanonicalizationMethod getCanonicalizationMethod() { | ||
| 157 | return canonicalizationMethod; | ||
| 158 | } | ||
| 159 | |||
| 160 | public SignatureMethod getSignatureMethod() { | ||
| 161 | return signatureMethod; | ||
| 162 | } | ||
| 163 | |||
| 164 | public String getId() { | ||
| 165 | return id; | ||
| 166 | } | ||
| 167 | |||
| 168 | public List getReferences() { | ||
| 169 | return references; | ||
| 170 | } | ||
| 171 | |||
| 172 | public InputStream getCanonicalizedData() { | ||
| 173 | return canonData; | ||
| 174 | } | ||
| 175 | |||
| 176 | public void canonicalize(XMLCryptoContext context,ByteArrayOutputStream bos) | ||
| 177 | throws XMLSignatureException { | ||
| 178 | |||
| 179 | if (context == null) { | ||
| 180 | throw new NullPointerException("context cannot be null"); | ||
| 181 | } | ||
| 182 | |||
| 183 | OutputStream os = new UnsyncBufferedOutputStream(bos); | ||
| 184 | try { | ||
| 185 | os.close(); | ||
| 186 | } catch (IOException e) { | ||
| 187 | // Impossible | ||
| 188 | } | ||
| 189 | |||
| 190 | DOMSubTreeData subTree = new DOMSubTreeData(localSiElem, true); | ||
| 191 | |||
| 192 | try { | ||
| 193 | Data data = ((DOMCanonicalizationMethod) | ||
| 194 | canonicalizationMethod).canonicalize(subTree, context, os); | ||
| 195 | } catch (TransformException te) { | ||
| 196 | throw new XMLSignatureException(te); | ||
| 197 | } | ||
| 198 | |||
| 199 | byte[] signedInfoBytes = bos.toByteArray(); | ||
| 200 | |||
| 201 | // this whole block should only be done if logging is enabled | ||
| 202 | if (log.isLoggable(Level.FINE)) { | ||
| 203 | InputStreamReader isr = new InputStreamReader | ||
| 204 | (new ByteArrayInputStream(signedInfoBytes)); | ||
| 205 | char[] siBytes = new char[signedInfoBytes.length]; | ||
| 206 | try { | ||
| 207 | isr.read(siBytes); | ||
| 208 | log.log(Level.FINE, "Canonicalized SignedInfo:\n" | ||
| 209 | + new String(siBytes)); | ||
| 210 | } catch (IOException ioex) { | ||
| 211 | log.log(Level.FINE, "IOException reading SignedInfo bytes"); | ||
| 212 | } | ||
| 213 | log.log(Level.FINE, "Data to be signed/verified:" | ||
| 214 | + Base64.encode(signedInfoBytes)); | ||
| 215 | } | ||
| 216 | |||
| 217 | this.canonData = new ByteArrayInputStream(signedInfoBytes); | ||
| 218 | } | ||
| 219 | |||
| 220 | public void marshal(Node parent, String dsPrefix, DOMCryptoContext context) | ||
| 221 | throws MarshalException { | ||
| 222 | ownerDoc = DOMUtils.getOwnerDocument(parent); | ||
| 223 | |||
| 224 | Element siElem = DOMUtils.createElement | ||
| 225 | (ownerDoc, "SignedInfo", XMLSignature.XMLNS, dsPrefix); | ||
| 226 | |||
| 227 | // create and append CanonicalizationMethod element | ||
| 228 | DOMCanonicalizationMethod dcm = | ||
| 229 | (DOMCanonicalizationMethod) canonicalizationMethod; | ||
| 230 | dcm.marshal(siElem, dsPrefix, context); | ||
| 231 | |||
| 232 | // create and append SignatureMethod element | ||
| 233 | ((DOMSignatureMethod) signatureMethod).marshal | ||
| 234 | (siElem, dsPrefix, context); | ||
| 235 | |||
| 236 | // create and append Reference elements | ||
| 237 | for (int i = 0, size = references.size(); i < size; i++) { | ||
| 238 | DOMReference reference = (DOMReference) references.get(i); | ||
| 239 | reference.marshal(siElem, dsPrefix, context); | ||
| 240 | } | ||
| 241 | |||
| 242 | // append Id attribute | ||
| 243 | DOMUtils.setAttributeID(siElem, "Id", id); | ||
| 244 | |||
| 245 | parent.appendChild(siElem); | ||
| 246 | localSiElem = siElem; | ||
| 247 | } | ||
| 248 | |||
| 249 | public boolean equals(Object o) { | ||
| 250 | if (this == o) { | ||
| 251 | return true; | ||
| 252 | } | ||
| 253 | |||
| 254 | if (!(o instanceof SignedInfo)) { | ||
| 255 | return false; | ||
| 256 | } | ||
| 257 | SignedInfo osi = (SignedInfo) o; | ||
| 258 | |||
| 259 | boolean idEqual = (id == null ? osi.getId() == null : | ||
| 260 | id.equals(osi.getId())); | ||
| 261 | |||
| 262 | return (canonicalizationMethod.equals(osi.getCanonicalizationMethod()) | ||
| 263 | && signatureMethod.equals(osi.getSignatureMethod()) && | ||
| 264 | references.equals(osi.getReferences()) && idEqual); | ||
| 265 | } | ||
| 266 | } | ||
Binary file not shown.
| @@ -0,0 +1,51 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DOMStructure.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import javax.xml.crypto.MarshalException; | ||
| 30 | import javax.xml.crypto.XMLStructure; | ||
| 31 | import javax.xml.crypto.dom.DOMCryptoContext; | ||
| 32 | import org.w3c.dom.Node; | ||
| 33 | |||
| 34 | /** | ||
| 35 | * DOM-based abstract implementation of XMLStructure. | ||
| 36 | * | ||
| 37 | * @author Sean Mullan | ||
| 38 | */ | ||
| 39 | public abstract class DOMStructure implements XMLStructure { | ||
| 40 | |||
| 41 | public final boolean isFeatureSupported(String feature) { | ||
| 42 | if (feature == null) { | ||
| 43 | throw new NullPointerException(); | ||
| 44 | } else { | ||
| 45 | return false; | ||
| 46 | } | ||
| 47 | } | ||
| 48 | |||
| 49 | public abstract void marshal(Node parent, String dsPrefix, | ||
| 50 | DOMCryptoContext context) throws MarshalException; | ||
| 51 | } | ||
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,169 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2006 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DOMSubTreeData.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import javax.xml.crypto.NodeSetData; | ||
| 30 | import java.util.ArrayList; | ||
| 31 | import java.util.Iterator; | ||
| 32 | import java.util.List; | ||
| 33 | import java.util.ListIterator; | ||
| 34 | import java.util.NoSuchElementException; | ||
| 35 | import org.w3c.dom.NamedNodeMap; | ||
| 36 | import org.w3c.dom.Node; | ||
| 37 | |||
| 38 | /** | ||
| 39 | * This is a subtype of NodeSetData that represents a dereferenced | ||
| 40 | * same-document URI as the root of a subdocument. The main reason is | ||
| 41 | * for efficiency and performance, as some transforms can operate | ||
| 42 | * directly on the subdocument and there is no need to convert it | ||
| 43 | * first to an XPath node-set. | ||
| 44 | */ | ||
| 45 | public class DOMSubTreeData implements NodeSetData { | ||
| 46 | |||
| 47 | private boolean excludeComments; | ||
| 48 | private Iterator ni; | ||
| 49 | private Node root; | ||
| 50 | |||
| 51 | public DOMSubTreeData(Node root, boolean excludeComments) { | ||
| 52 | this.root = root; | ||
| 53 | this.ni = new DelayedNodeIterator(root, excludeComments); | ||
| 54 | this.excludeComments = excludeComments; | ||
| 55 | } | ||
| 56 | |||
| 57 | public Iterator iterator() { | ||
| 58 | return ni; | ||
| 59 | } | ||
| 60 | |||
| 61 | public Node getRoot() { | ||
| 62 | return root; | ||
| 63 | } | ||
| 64 | |||
| 65 | public boolean excludeComments() { | ||
| 66 | return excludeComments; | ||
| 67 | } | ||
| 68 | |||
| 69 | /** | ||
| 70 | * This is an Iterator that contains a backing node-set that is | ||
| 71 | * not populated until the caller first attempts to advance the iterator. | ||
| 72 | */ | ||
| 73 | static class DelayedNodeIterator implements Iterator { | ||
| 74 | private Node root; | ||
| 75 | private List nodeSet; | ||
| 76 | private ListIterator li; | ||
| 77 | private boolean withComments; | ||
| 78 | |||
| 79 | DelayedNodeIterator(Node root, boolean excludeComments) { | ||
| 80 | this.root = root; | ||
| 81 | this.withComments = !excludeComments; | ||
| 82 | } | ||
| 83 | |||
| 84 | public boolean hasNext() { | ||
| 85 | if (nodeSet == null) { | ||
| 86 | nodeSet = dereferenceSameDocumentURI(root); | ||
| 87 | li = nodeSet.listIterator(); | ||
| 88 | } | ||
| 89 | return li.hasNext(); | ||
| 90 | } | ||
| 91 | |||
| 92 | public Object next() { | ||
| 93 | if (nodeSet == null) { | ||
| 94 | nodeSet = dereferenceSameDocumentURI(root); | ||
| 95 | li = nodeSet.listIterator(); | ||
| 96 | } | ||
| 97 | if (li.hasNext()) { | ||
| 98 | return (Node) li.next(); | ||
| 99 | } else { | ||
| 100 | throw new NoSuchElementException(); | ||
| 101 | } | ||
| 102 | } | ||
| 103 | |||
| 104 | public void remove() { | ||
| 105 | throw new UnsupportedOperationException(); | ||
| 106 | } | ||
| 107 | |||
| 108 | /** | ||
| 109 | * Dereferences a same-document URI fragment. | ||
| 110 | * | ||
| 111 | * @param node the node (document or element) referenced by the | ||
| 112 | * URI fragment. If null, returns an empty set. | ||
| 113 | * @return a set of nodes (minus any comment nodes) | ||
| 114 | */ | ||
| 115 | private List dereferenceSameDocumentURI(Node node) { | ||
| 116 | List nodeSet = new ArrayList(); | ||
| 117 | if (node != null) { | ||
| 118 | nodeSetMinusCommentNodes(node, nodeSet, null); | ||
| 119 | } | ||
| 120 | return nodeSet; | ||
| 121 | } | ||
| 122 | |||
| 123 | /** | ||
| 124 | * Recursively traverses the subtree, and returns an XPath-equivalent | ||
| 125 | * node-set of all nodes traversed, excluding any comment nodes, | ||
| 126 | * if specified. | ||
| 127 | * | ||
| 128 | * @param node the node to traverse | ||
| 129 | * @param nodeSet the set of nodes traversed so far | ||
| 130 | * @param the previous sibling node | ||
| 131 | */ | ||
| 132 | private void nodeSetMinusCommentNodes(Node node, List nodeSet, | ||
| 133 | Node prevSibling) { | ||
| 134 | switch (node.getNodeType()) { | ||
| 135 | case Node.ELEMENT_NODE : | ||
| 136 | NamedNodeMap attrs = node.getAttributes(); | ||
| 137 | if (attrs != null) { | ||
| 138 | for (int i = 0, len = attrs.getLength(); i < len; i++) { | ||
| 139 | nodeSet.add(attrs.item(i)); | ||
| 140 | } | ||
| 141 | } | ||
| 142 | nodeSet.add(node); | ||
| 143 | case Node.DOCUMENT_NODE : | ||
| 144 | Node pSibling = null; | ||
| 145 | for (Node child = node.getFirstChild(); child != null; | ||
| 146 | child = child.getNextSibling()) { | ||
| 147 | nodeSetMinusCommentNodes(child, nodeSet, pSibling); | ||
| 148 | pSibling = child; | ||
| 149 | } | ||
| 150 | break; | ||
| 151 | case Node.TEXT_NODE : | ||
| 152 | case Node.CDATA_SECTION_NODE: | ||
| 153 | // emulate XPath which only returns the first node in | ||
| 154 | // contiguous text/cdata nodes | ||
| 155 | if (prevSibling != null && | ||
| 156 | (prevSibling.getNodeType() == Node.TEXT_NODE || | ||
| 157 | prevSibling.getNodeType() == Node.CDATA_SECTION_NODE)){ return; | ||
| 158 | } | ||
| 159 | case Node.PROCESSING_INSTRUCTION_NODE : | ||
| 160 | nodeSet.add(node); | ||
| 161 | break; | ||
| 162 | case Node.COMMENT_NODE: | ||
| 163 | if (withComments) { | ||
| 164 | nodeSet.add(node); | ||
| 165 | } | ||
| 166 | } | ||
| 167 | } | ||
| 168 | } | ||
| 169 | } | ||
Binary file not shown.
| @@ -0,0 +1,193 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DOMTransform.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import java.io.OutputStream; | ||
| 30 | import java.security.InvalidAlgorithmParameterException; | ||
| 31 | import java.security.NoSuchAlgorithmException; | ||
| 32 | import java.security.Provider; | ||
| 33 | import java.security.spec.AlgorithmParameterSpec; | ||
| 34 | |||
| 35 | import org.w3c.dom.Document; | ||
| 36 | import org.w3c.dom.Element; | ||
| 37 | import org.w3c.dom.Node; | ||
| 38 | import org.w3c.dom.NodeList; | ||
| 39 | |||
| 40 | import javax.xml.crypto.*; | ||
| 41 | import javax.xml.crypto.dsig.*; | ||
| 42 | import javax.xml.crypto.dom.DOMCryptoContext; | ||
| 43 | import javax.xml.crypto.dsig.dom.DOMSignContext; | ||
| 44 | import javax.xml.crypto.dsig.spec.TransformParameterSpec; | ||
| 45 | |||
| 46 | /** | ||
| 47 | * DOM-based abstract implementation of Transform. | ||
| 48 | * | ||
| 49 | * @author Sean Mullan | ||
| 50 | */ | ||
| 51 | public class DOMTransform extends DOMStructure implements Transform { | ||
| 52 | |||
| 53 | protected TransformService spi; | ||
| 54 | |||
| 55 | /** | ||
| 56 | * Creates a <code>DOMTransform</code>. | ||
| 57 | * | ||
| 58 | * @param spi the TransformService | ||
| 59 | */ | ||
| 60 | public DOMTransform(TransformService spi) { | ||
| 61 | this.spi = spi; | ||
| 62 | } | ||
| 63 | |||
| 64 | /** | ||
| 65 | * Creates a <code>DOMTransform</code> from an element. This constructor | ||
| 66 | * invokes the abstract {@link #unmarshalParams unmarshalParams} method to | ||
| 67 | * unmarshal any algorithm-specific input parameters. | ||
| 68 | * | ||
| 69 | * @param transElem a Transform element | ||
| 70 | */ | ||
| 71 | public DOMTransform(Element transElem, XMLCryptoContext context, | ||
| 72 | Provider provider) throws MarshalException { | ||
| 73 | String algorithm = DOMUtils.getAttributeValue(transElem, "Algorithm"); | ||
| 74 | try { | ||
| 75 | spi = TransformService.getInstance(algorithm, "DOM"); | ||
| 76 | } catch (NoSuchAlgorithmException e1) { | ||
| 77 | try { | ||
| 78 | spi = TransformService.getInstance(algorithm, "DOM", provider); | ||
| 79 | } catch (NoSuchAlgorithmException e2) { | ||
| 80 | throw new MarshalException(e2); | ||
| 81 | } | ||
| 82 | } | ||
| 83 | try { | ||
| 84 | spi.init(new javax.xml.crypto.dom.DOMStructure(transElem), context); | ||
| 85 | } catch (InvalidAlgorithmParameterException iape) { | ||
| 86 | throw new MarshalException(iape); | ||
| 87 | } | ||
| 88 | } | ||
| 89 | |||
| 90 | public final AlgorithmParameterSpec getParameterSpec() { | ||
| 91 | return spi.getParameterSpec(); | ||
| 92 | } | ||
| 93 | |||
| 94 | public final String getAlgorithm() { | ||
| 95 | return spi.getAlgorithm(); | ||
| 96 | } | ||
| 97 | |||
| 98 | /** | ||
| 99 | * This method invokes the abstract {@link #marshalParams marshalParams} | ||
| 100 | * method to marshal any algorithm-specific parameters. | ||
| 101 | */ | ||
| 102 | public void marshal(Node parent, String dsPrefix, DOMCryptoContext context) | ||
| 103 | throws MarshalException { | ||
| 104 | Document ownerDoc = DOMUtils.getOwnerDocument(parent); | ||
| 105 | |||
| 106 | Element transformElem = null; | ||
| 107 | if (parent.getLocalName().equals("Transforms")) { | ||
| 108 | transformElem = DOMUtils.createElement | ||
| 109 | (ownerDoc, "Transform", XMLSignature.XMLNS, dsPrefix); | ||
| 110 | } else { | ||
| 111 | transformElem = DOMUtils.createElement | ||
| 112 | (ownerDoc, "CanonicalizationMethod", XMLSignature.XMLNS, dsPrefix); | ||
| 113 | } | ||
| 114 | DOMUtils.setAttribute(transformElem, "Algorithm", getAlgorithm()); | ||
| 115 | |||
| 116 | spi.marshalParams | ||
| 117 | (new javax.xml.crypto.dom.DOMStructure(transformElem), context); | ||
| 118 | |||
| 119 | parent.appendChild(transformElem); | ||
| 120 | } | ||
| 121 | |||
| 122 | /** | ||
| 123 | * Transforms the specified data using the underlying transform algorithm. | ||
| 124 | * | ||
| 125 | * @param data the data to be transformed | ||
| 126 | * @param sc the <code>XMLCryptoContext</code> containing | ||
| 127 | * additional context (may be <code>null</code> if not applicable) | ||
| 128 | * @return the transformed data | ||
| 129 | * @throws NullPointerException if <code>data</code> is <code>null</code> | ||
| 130 | * @throws XMLSignatureException if an unexpected error occurs while | ||
| 131 | * executing the transform | ||
| 132 | */ | ||
| 133 | public Data transform(Data data, XMLCryptoContext xc) | ||
| 134 | throws TransformException { | ||
| 135 | return spi.transform(data, xc); | ||
| 136 | } | ||
| 137 | |||
| 138 | /** | ||
| 139 | * Transforms the specified data using the underlying transform algorithm. | ||
| 140 | * | ||
| 141 | * @param data the data to be transformed | ||
| 142 | * @param sc the <code>XMLCryptoContext</code> containing | ||
| 143 | * additional context (may be <code>null</code> if not applicable) | ||
| 144 | * @param os the <code>OutputStream</code> that should be used to write | ||
| 145 | * the transformed data to | ||
| 146 | * @return the transformed data | ||
| 147 | * @throws NullPointerException if <code>data</code> is <code>null</code> | ||
| 148 | * @throws XMLSignatureException if an unexpected error occurs while | ||
| 149 | * executing the transform | ||
| 150 | */ | ||
| 151 | public Data transform(Data data, XMLCryptoContext xc, OutputStream os) | ||
| 152 | throws TransformException { | ||
| 153 | return spi.transform(data, xc, os); | ||
| 154 | } | ||
| 155 | |||
| 156 | public boolean equals(Object o) { | ||
| 157 | if (this == o) { | ||
| 158 | return true; | ||
| 159 | } | ||
| 160 | |||
| 161 | if (!(o instanceof Transform)) { | ||
| 162 | return false; | ||
| 163 | } | ||
| 164 | Transform otransform = (Transform) o; | ||
| 165 | |||
| 166 | return (getAlgorithm().equals(otransform.getAlgorithm()) && | ||
| 167 | DOMUtils.paramsEqual | ||
| 168 | (getParameterSpec(), otransform.getParameterSpec())); | ||
| 169 | } | ||
| 170 | |||
| 171 | /** | ||
| 172 | * Transforms the specified data using the underlying transform algorithm. | ||
| 173 | * This method invokes the {@link #marshal marshal} method and passes it | ||
| 174 | * the specified <code>DOMSignContext</code> before transforming the data. | ||
| 175 | * | ||
| 176 | * @param data the data to be transformed | ||
| 177 | * @param sc the <code>XMLCryptoContext</code> containing | ||
| 178 | * additional context (may be <code>null</code> if not applicable) | ||
| 179 | * @param context the marshalling context | ||
| 180 | * @return the transformed data | ||
| 181 | * @throws MarshalException if an exception occurs while marshalling | ||
| 182 | * @throws NullPointerException if <code>data</code> or <code>context</code> | ||
| 183 | * is <code>null</code> | ||
| 184 | * @throws XMLSignatureException if an unexpected error occurs while | ||
| 185 | * executing the transform | ||
| 186 | */ | ||
| 187 | Data transform(Data data, XMLCryptoContext xc, DOMSignContext context) | ||
| 188 | throws MarshalException, TransformException { | ||
| 189 | marshal(context.getParent(), | ||
| 190 | DOMUtils.getSignaturePrefix(context), context); | ||
| 191 | return transform(data, xc); | ||
| 192 | } | ||
| 193 | } | ||
Binary file not shown.
| @@ -0,0 +1,105 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DOMURIDereferencer.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import org.w3c.dom.Attr; | ||
| 30 | import org.w3c.dom.Element; | ||
| 31 | import org.w3c.dom.Node; | ||
| 32 | |||
| 33 | import com.sun.org.apache.xml.internal.security.Init; | ||
| 34 | import com.sun.org.apache.xml.internal.security.utils.IdResolver; | ||
| 35 | import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver; | ||
| 36 | import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput; | ||
| 37 | |||
| 38 | import javax.xml.crypto.*; | ||
| 39 | import javax.xml.crypto.dom.*; | ||
| 40 | import javax.xml.crypto.dsig.*; | ||
| 41 | |||
| 42 | /** | ||
| 43 | * DOM-based implementation of URIDereferencer. | ||
| 44 | * | ||
| 45 | * @author Sean Mullan | ||
| 46 | */ | ||
| 47 | public class DOMURIDereferencer implements URIDereferencer { | ||
| 48 | |||
| 49 | static final URIDereferencer INSTANCE = new DOMURIDereferencer(); | ||
| 50 | |||
| 51 | private DOMURIDereferencer() { | ||
| 52 | // need to call com.sun.org.apache.xml.internal.security.Init.init() | ||
| 53 | // before calling any apache security code | ||
| 54 | Init.init(); | ||
| 55 | } | ||
| 56 | |||
| 57 | public Data dereference(URIReference uriRef, XMLCryptoContext context) | ||
| 58 | throws URIReferenceException { | ||
| 59 | |||
| 60 | if (uriRef == null) { | ||
| 61 | throw new NullPointerException("uriRef cannot be null"); | ||
| 62 | } | ||
| 63 | if (context == null) { | ||
| 64 | throw new NullPointerException("context cannot be null"); | ||
| 65 | } | ||
| 66 | |||
| 67 | DOMURIReference domRef = (DOMURIReference) uriRef; | ||
| 68 | Attr uriAttr = (Attr) domRef.getHere(); | ||
| 69 | String uri = uriRef.getURI(); | ||
| 70 | DOMCryptoContext dcc = (DOMCryptoContext) context; | ||
| 71 | |||
| 72 | // Check if same-document URI and register ID | ||
| 73 | if (uri != null && uri.length() != 0 && uri.charAt(0) == '#') { | ||
| 74 | String id = uri.substring(1); | ||
| 75 | |||
| 76 | if (id.startsWith("xpointer(id(")) { | ||
| 77 | int i1 = id.indexOf('\''); | ||
| 78 | int i2 = id.indexOf('\'', i1+1); | ||
| 79 | id = id.substring(i1+1, i2); | ||
| 80 | } | ||
| 81 | |||
| 82 | // this is a bit of a hack to check for registered | ||
| 83 | // IDRefs and manually register them with Apache's IdResolver | ||
| 84 | // map which includes builtin schema knowledge of DSig/Enc IDs | ||
| 85 | Node referencedElem = dcc.getElementById(id); | ||
| 86 | if (referencedElem != null) { | ||
| 87 | IdResolver.registerElementById((Element) referencedElem, id); | ||
| 88 | } | ||
| 89 | } | ||
| 90 | |||
| 91 | try { | ||
| 92 | String baseURI = context.getBaseURI(); | ||
| 93 | ResourceResolver apacheResolver = | ||
| 94 | ResourceResolver.getInstance(uriAttr, baseURI); | ||
| 95 | XMLSignatureInput in = apacheResolver.resolve(uriAttr, baseURI); | ||
| 96 | if (in.isOctetStream()) { | ||
| 97 | return new ApacheOctetStreamData(in); | ||
| 98 | } else { | ||
| 99 | return new ApacheNodeSetData(in); | ||
| 100 | } | ||
| 101 | } catch (Exception e) { | ||
| 102 | throw new URIReferenceException(e); | ||
| 103 | } | ||
| 104 | } | ||
| 105 | } | ||
Binary file not shown.
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,363 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DOMUtils.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import java.util.*; | ||
| 30 | import java.security.spec.AlgorithmParameterSpec; | ||
| 31 | import org.w3c.dom.Attr; | ||
| 32 | import org.w3c.dom.Document; | ||
| 33 | import org.w3c.dom.Element; | ||
| 34 | import org.w3c.dom.Node; | ||
| 35 | import org.w3c.dom.NodeList; | ||
| 36 | import javax.xml.crypto.*; | ||
| 37 | import javax.xml.crypto.dsig.dom.DOMSignContext; | ||
| 38 | import javax.xml.crypto.dsig.*; | ||
| 39 | import javax.xml.crypto.dsig.spec.*; | ||
| 40 | |||
| 41 | import com.sun.org.apache.xml.internal.security.utils.IdResolver; | ||
| 42 | |||
| 43 | /** | ||
| 44 | * Useful static DOM utility methods. | ||
| 45 | * | ||
| 46 | * @author Sean Mullan | ||
| 47 | */ | ||
| 48 | public class DOMUtils { | ||
| 49 | |||
| 50 | // class cannot be instantiated | ||
| 51 | private DOMUtils() {} | ||
| 52 | |||
| 53 | /** | ||
| 54 | * Returns the owner document of the specified node. | ||
| 55 | * | ||
| 56 | * @param node the node | ||
| 57 | * @return the owner document | ||
| 58 | */ | ||
| 59 | public static Document getOwnerDocument(Node node) { | ||
| 60 | if (node.getNodeType() == Node.DOCUMENT_NODE) { | ||
| 61 | return (Document) node; | ||
| 62 | } else { | ||
| 63 | return node.getOwnerDocument(); | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | /** | ||
| 68 | * Creates an element in the specified namespace, with the specified tag | ||
| 69 | * and namespace prefix. | ||
| 70 | * | ||
| 71 | * @param doc the owner document | ||
| 72 | * @param tag the tag | ||
| 73 | * @param nsURI the namespace URI | ||
| 74 | * @param prefix the namespace prefix | ||
| 75 | * @return the newly created element | ||
| 76 | */ | ||
| 77 | public static Element createElement(Document doc, String tag, String nsURI, | ||
| 78 | String prefix) { | ||
| 79 | String qName = (prefix == null || prefix.length() == 0) | ||
| 80 | ? tag : prefix + ":" + tag; | ||
| 81 | return doc.createElementNS(nsURI, qName); | ||
| 82 | } | ||
| 83 | |||
| 84 | /** | ||
| 85 | * Sets an element's attribute (using DOM level 2) with the | ||
| 86 | * specified value and namespace prefix. | ||
| 87 | * | ||
| 88 | * @param elem the element to set the attribute on | ||
| 89 | * @param name the name of the attribute | ||
| 90 | * @param value the attribute value. If null, no attribute is set. | ||
| 91 | */ | ||
| 92 | public static void setAttribute(Element elem, String name, String value) { | ||
| 93 | if (value == null) return; | ||
| 94 | elem.setAttributeNS(null, name, value); | ||
| 95 | } | ||
| 96 | |||
| 97 | /** | ||
| 98 | * Sets an element's attribute (using DOM level 2) with the | ||
| 99 | * specified value and namespace prefix AND registers the ID value with | ||
| 100 | * the specified element. This is for resolving same-document | ||
| 101 | * ID references. | ||
| 102 | * | ||
| 103 | * @param elem the element to set the attribute on | ||
| 104 | * @param name the name of the attribute | ||
| 105 | * @param value the attribute value. If null, no attribute is set. | ||
| 106 | */ | ||
| 107 | public static void setAttributeID(Element elem, String name, String value) { | ||
| 108 | if (value == null) return; | ||
| 109 | elem.setAttributeNS(null, name, value); | ||
| 110 | IdResolver.registerElementById(elem, value); | ||
| 111 | } | ||
| 112 | |||
| 113 | /** | ||
| 114 | * Returns the first child element of the specified node, or null if there | ||
| 115 | * is no such element. | ||
| 116 | * | ||
| 117 | * @param node the node | ||
| 118 | * @return the first child element of the specified node, or null if there | ||
| 119 | * is no such element | ||
| 120 | * @throws NullPointerException if <code>node == null</code> | ||
| 121 | */ | ||
| 122 | public static Element getFirstChildElement(Node node) { | ||
| 123 | Node child = node.getFirstChild(); | ||
| 124 | while (child != null && child.getNodeType() != Node.ELEMENT_NODE) { | ||
| 125 | child = child.getNextSibling(); | ||
| 126 | } | ||
| 127 | return (Element) child; | ||
| 128 | } | ||
| 129 | |||
| 130 | /** | ||
| 131 | * Returns the last child element of the specified node, or null if there | ||
| 132 | * is no such element. | ||
| 133 | * | ||
| 134 | * @param node the node | ||
| 135 | * @return the last child element of the specified node, or null if there | ||
| 136 | * is no such element | ||
| 137 | * @throws NullPointerException if <code>node == null</code> | ||
| 138 | */ | ||
| 139 | public static Element getLastChildElement(Node node) { | ||
| 140 | Node child = node.getLastChild(); | ||
| 141 | while (child != null && child.getNodeType() != Node.ELEMENT_NODE) { | ||
| 142 | child = child.getPreviousSibling(); | ||
| 143 | } | ||
| 144 | return (Element) child; | ||
| 145 | } | ||
| 146 | |||
| 147 | /** | ||
| 148 | * Returns the next sibling element of the specified node, or null if there | ||
| 149 | * is no such element. | ||
| 150 | * | ||
| 151 | * @param node the node | ||
| 152 | * @return the next sibling element of the specified node, or null if there | ||
| 153 | * is no such element | ||
| 154 | * @throws NullPointerException if <code>node == null</code> | ||
| 155 | */ | ||
| 156 | public static Element getNextSiblingElement(Node node) { | ||
| 157 | Node sibling = node.getNextSibling(); | ||
| 158 | while (sibling != null && sibling.getNodeType() != Node.ELEMENT_NODE) { | ||
| 159 | sibling = sibling.getNextSibling(); | ||
| 160 | } | ||
| 161 | return (Element) sibling; | ||
| 162 | } | ||
| 163 | |||
| 164 | /** | ||
| 165 | * Returns the attribute value for the attribute with the specified name. | ||
| 166 | * Returns null if there is no such attribute, or | ||
| 167 | * the empty string if the attribute value is empty. | ||
| 168 | * | ||
| 169 | * <p>This works around a limitation of the DOM | ||
| 170 | * <code>Element.getAttributeNode</code> method, which does not distinguish | ||
| 171 | * between an unspecified attribute and an attribute with a value of | ||
| 172 | * "" (it returns "" for both cases). | ||
| 173 | * | ||
| 174 | * @param elem the element containing the attribute | ||
| 175 | * @param name the name of the attribute | ||
| 176 | * @return the attribute value (may be null if unspecified) | ||
| 177 | */ | ||
| 178 | public static String getAttributeValue(Element elem, String name) { | ||
| 179 | Attr attr = elem.getAttributeNodeNS(null, name); | ||
| 180 | return (attr == null) ? null : attr.getValue(); | ||
| 181 | } | ||
| 182 | |||
| 183 | /** | ||
| 184 | * Returns a Set of <code>Node</code>s, backed by the specified | ||
| 185 | * <code>NodeList</code>. | ||
| 186 | * | ||
| 187 | * @param nl the NodeList | ||
| 188 | * @return a Set of Nodes | ||
| 189 | */ | ||
| 190 | public static Set nodeSet(NodeList nl) { | ||
| 191 | return new NodeSet(nl); | ||
| 192 | } | ||
| 193 | |||
| 194 | static class NodeSet extends AbstractSet { | ||
| 195 | private NodeList nl; | ||
| 196 | public NodeSet(NodeList nl) { | ||
| 197 | this.nl = nl; | ||
| 198 | } | ||
| 199 | |||
| 200 | public int size() { return nl.getLength(); } | ||
| 201 | public Iterator iterator() { | ||
| 202 | return new Iterator() { | ||
| 203 | int index = 0; | ||
| 204 | |||
| 205 | public void remove() { | ||
| 206 | throw new UnsupportedOperationException(); | ||
| 207 | } | ||
| 208 | public Object next() { | ||
| 209 | if (!hasNext()) { | ||
| 210 | throw new NoSuchElementException(); | ||
| 211 | } | ||
| 212 | return nl.item(index++); | ||
| 213 | } | ||
| 214 | public boolean hasNext() { | ||
| 215 | return index < nl.getLength() ? true : false; | ||
| 216 | } | ||
| 217 | }; | ||
| 218 | } | ||
| 219 | } | ||
| 220 | |||
| 221 | /** | ||
| 222 | * Returns the prefix associated with the specified namespace URI | ||
| 223 | * | ||
| 224 | * @param context contains the namespace map | ||
| 225 | * @param nsURI the namespace URI | ||
| 226 | * @return the prefix associated with the specified namespace URI, or | ||
| 227 | * null if not set | ||
| 228 | */ | ||
| 229 | public static String getNSPrefix(XMLCryptoContext context, String nsURI) { | ||
| 230 | if (context != null) { | ||
| 231 | return context.getNamespacePrefix | ||
| 232 | (nsURI, context.getDefaultNamespacePrefix()); | ||
| 233 | } else { | ||
| 234 | return null; | ||
| 235 | } | ||
| 236 | } | ||
| 237 | |||
| 238 | /** | ||
| 239 | * Returns the prefix associated with the XML Signature namespace URI | ||
| 240 | * | ||
| 241 | * @param context contains the namespace map | ||
| 242 | * @return the prefix associated with the specified namespace URI, or | ||
| 243 | * null if not set | ||
| 244 | */ | ||
| 245 | public static String getSignaturePrefix(XMLCryptoContext context) { | ||
| 246 | return getNSPrefix(context, XMLSignature.XMLNS); | ||
| 247 | } | ||
| 248 | |||
| 249 | /** | ||
| 250 | * Removes all children nodes from the specified node. | ||
| 251 | * | ||
| 252 | * @param node the parent node whose children are to be removed | ||
| 253 | */ | ||
| 254 | public static void removeAllChildren(Node node) { | ||
| 255 | NodeList children = node.getChildNodes(); | ||
| 256 | for (int i = 0, length = children.getLength(); i < length; i++) { | ||
| 257 | node.removeChild(children.item(i)); | ||
| 258 | } | ||
| 259 | } | ||
| 260 | |||
| 261 | /** | ||
| 262 | * Compares 2 nodes for equality. Implementation is not complete. | ||
| 263 | */ | ||
| 264 | public static boolean nodesEqual(Node thisNode, Node otherNode) { | ||
| 265 | if (thisNode == otherNode) { | ||
| 266 | return true; | ||
| 267 | } | ||
| 268 | if (thisNode.getNodeType() != otherNode.getNodeType()) { | ||
| 269 | return false; | ||
| 270 | } | ||
| 271 | // FIXME - test content, etc | ||
| 272 | return true; | ||
| 273 | } | ||
| 274 | |||
| 275 | /** | ||
| 276 | * Checks if child element has same owner document before | ||
| 277 | * appending to the parent, and imports it to the parent's document | ||
| 278 | * if necessary. | ||
| 279 | */ | ||
| 280 | public static void appendChild(Node parent, Node child) { | ||
| 281 | Document ownerDoc = getOwnerDocument(parent); | ||
| 282 | if (child.getOwnerDocument() != ownerDoc) { | ||
| 283 | parent.appendChild(ownerDoc.importNode(child, true)); | ||
| 284 | } else { | ||
| 285 | parent.appendChild(child); | ||
| 286 | } | ||
| 287 | } | ||
| 288 | |||
| 289 | public static boolean paramsEqual(AlgorithmParameterSpec spec1, | ||
| 290 | AlgorithmParameterSpec spec2) { | ||
| 291 | if (spec1 == spec2) { | ||
| 292 | return true; | ||
| 293 | } | ||
| 294 | if (spec1 instanceof XPathFilter2ParameterSpec && | ||
| 295 | spec2 instanceof XPathFilter2ParameterSpec) { | ||
| 296 | return paramsEqual((XPathFilter2ParameterSpec) spec1, | ||
| 297 | (XPathFilter2ParameterSpec) spec2); | ||
| 298 | } | ||
| 299 | if (spec1 instanceof ExcC14NParameterSpec && | ||
| 300 | spec2 instanceof ExcC14NParameterSpec) { | ||
| 301 | return paramsEqual((ExcC14NParameterSpec) spec1, | ||
| 302 | (ExcC14NParameterSpec) spec2); | ||
| 303 | } | ||
| 304 | if (spec1 instanceof XPathFilterParameterSpec && | ||
| 305 | spec2 instanceof XPathFilterParameterSpec) { | ||
| 306 | return paramsEqual((XPathFilterParameterSpec) spec1, | ||
| 307 | (XPathFilterParameterSpec) spec2); | ||
| 308 | } | ||
| 309 | if (spec1 instanceof XSLTTransformParameterSpec && | ||
| 310 | spec2 instanceof XSLTTransformParameterSpec) { | ||
| 311 | return paramsEqual((XSLTTransformParameterSpec) spec1, | ||
| 312 | (XSLTTransformParameterSpec) spec2); | ||
| 313 | } | ||
| 314 | return false; | ||
| 315 | } | ||
| 316 | |||
| 317 | private static boolean paramsEqual(XPathFilter2ParameterSpec spec1, | ||
| 318 | XPathFilter2ParameterSpec spec2) { | ||
| 319 | |||
| 320 | List types = spec1.getXPathList(); | ||
| 321 | List otypes = spec2.getXPathList(); | ||
| 322 | int size = types.size(); | ||
| 323 | if (size != otypes.size()) { | ||
| 324 | return false; | ||
| 325 | } | ||
| 326 | for (int i = 0; i < size; i++) { | ||
| 327 | XPathType type = (XPathType) types.get(i); | ||
| 328 | XPathType otype = (XPathType) otypes.get(i); | ||
| 329 | if (!type.getExpression().equals(otype.getExpression()) || | ||
| 330 | !type.getNamespaceMap().equals(otype.getNamespaceMap()) || | ||
| 331 | type.getFilter() != otype.getFilter()) { | ||
| 332 | return false; | ||
| 333 | } | ||
| 334 | } | ||
| 335 | return true; | ||
| 336 | } | ||
| 337 | |||
| 338 | private static boolean paramsEqual(ExcC14NParameterSpec spec1, | ||
| 339 | ExcC14NParameterSpec spec2) { | ||
| 340 | return spec1.getPrefixList().equals(spec2.getPrefixList()); | ||
| 341 | } | ||
| 342 | |||
| 343 | private static boolean paramsEqual(XPathFilterParameterSpec spec1, | ||
| 344 | XPathFilterParameterSpec spec2) { | ||
| 345 | return (spec1.getXPath().equals(spec2.getXPath()) && | ||
| 346 | spec1.getNamespaceMap().equals(spec2.getNamespaceMap())); | ||
| 347 | } | ||
| 348 | |||
| 349 | private static boolean paramsEqual(XSLTTransformParameterSpec spec1, | ||
| 350 | XSLTTransformParameterSpec spec2) { | ||
| 351 | |||
| 352 | XMLStructure ostylesheet = spec2.getStylesheet(); | ||
| 353 | if (!(ostylesheet instanceof javax.xml.crypto.dom.DOMStructure)) { | ||
| 354 | return false; | ||
| 355 | } | ||
| 356 | Node ostylesheetElem = | ||
| 357 | ((javax.xml.crypto.dom.DOMStructure) ostylesheet).getNode(); | ||
| 358 | XMLStructure stylesheet = spec1.getStylesheet(); | ||
| 359 | Node stylesheetElem = | ||
| 360 | ((javax.xml.crypto.dom.DOMStructure) stylesheet).getNode(); | ||
| 361 | return nodesEqual(stylesheetElem, ostylesheetElem); | ||
| 362 | } | ||
| 363 | } | ||
Binary file not shown.
| @@ -0,0 +1,285 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DOMX509Data.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import java.io.ByteArrayInputStream; | ||
| 30 | import java.security.cert.*; | ||
| 31 | import java.util.*; | ||
| 32 | import javax.xml.crypto.*; | ||
| 33 | import javax.xml.crypto.dom.DOMCryptoContext; | ||
| 34 | import javax.xml.crypto.dsig.*; | ||
| 35 | import javax.xml.crypto.dsig.keyinfo.X509IssuerSerial; | ||
| 36 | import javax.xml.crypto.dsig.keyinfo.X509Data; | ||
| 37 | import javax.security.auth.x500.X500Principal; | ||
| 38 | import org.w3c.dom.Document; | ||
| 39 | import org.w3c.dom.Element; | ||
| 40 | import org.w3c.dom.Node; | ||
| 41 | import org.w3c.dom.NodeList; | ||
| 42 | |||
| 43 | import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException; | ||
| 44 | import com.sun.org.apache.xml.internal.security.utils.Base64; | ||
| 45 | |||
| 46 | /** | ||
| 47 | * DOM-based implementation of X509Data. | ||
| 48 | * | ||
| 49 | * @author Sean Mullan | ||
| 50 | */ | ||
| 51 | //@@@ check for illegal combinations of data violating MUSTs in W3c spec | ||
| 52 | public final class DOMX509Data extends DOMStructure implements X509Data { | ||
| 53 | |||
| 54 | private final List content; | ||
| 55 | private CertificateFactory cf; | ||
| 56 | |||
| 57 | /** | ||
| 58 | * Creates a DOMX509Data. | ||
| 59 | * | ||
| 60 | * @param content a list of one or more X.509 data types. Valid types are | ||
| 61 | * {@link String} (subject names), <code>byte[]</code> (subject key ids), | ||
| 62 | * {@link java.security.cert.X509Certificate}, {@link X509CRL}, | ||
| 63 | * or {@link javax.xml.dsig.XMLStructure} ({@link X509IssuerSerial} | ||
| 64 | * objects or elements from an external namespace). The list is | ||
| 65 | * defensively copied to protect against subsequent modification. | ||
| 66 | * @return a <code>X509Data</code> | ||
| 67 | * @throws NullPointerException if <code>content</code> is <code>null</code> | ||
| 68 | * @throws IllegalArgumentException if <code>content</code> is empty | ||
| 69 | * @throws ClassCastException if <code>content</code> contains any entries | ||
| 70 | * that are not of one of the valid types mentioned above | ||
| 71 | */ | ||
| 72 | public DOMX509Data(List content) { | ||
| 73 | if (content == null) { | ||
| 74 | throw new NullPointerException("content cannot be null"); | ||
| 75 | } | ||
| 76 | List contentCopy = new ArrayList(content); | ||
| 77 | if (contentCopy.isEmpty()) { | ||
| 78 | throw new IllegalArgumentException("content cannot be empty"); | ||
| 79 | } | ||
| 80 | for (int i = 0, size = contentCopy.size(); i < size; i++) { | ||
| 81 | Object x509Type = contentCopy.get(i); | ||
| 82 | if (x509Type instanceof String) { | ||
| 83 | new X500Principal((String) x509Type); | ||
| 84 | } else if (!(x509Type instanceof byte[]) && | ||
| 85 | !(x509Type instanceof X509Certificate) && | ||
| 86 | !(x509Type instanceof X509CRL) && | ||
| 87 | !(x509Type instanceof XMLStructure)) { | ||
| 88 | throw new ClassCastException | ||
| 89 | ("content["+i+"] is not a valid X509Data type"); | ||
| 90 | } | ||
| 91 | } | ||
| 92 | this.content = Collections.unmodifiableList(contentCopy); | ||
| 93 | } | ||
| 94 | |||
| 95 | /** | ||
| 96 | * Creates a <code>DOMX509Data</code> from an element. | ||
| 97 | * | ||
| 98 | * @param xdElem an X509Data element | ||
| 99 | * @throws MarshalException if there is an error while unmarshalling | ||
| 100 | */ | ||
| 101 | public DOMX509Data(Element xdElem) throws MarshalException { | ||
| 102 | // get all children nodes | ||
| 103 | NodeList nl = xdElem.getChildNodes(); | ||
| 104 | int length = nl.getLength(); | ||
| 105 | List content = new ArrayList(length); | ||
| 106 | for (int i = 0; i < length; i++) { | ||
| 107 | Node child = nl.item(i); | ||
| 108 | // ignore all non-Element nodes | ||
| 109 | if (child.getNodeType() != Node.ELEMENT_NODE) { | ||
| 110 | continue; | ||
| 111 | } | ||
| 112 | |||
| 113 | Element childElem = (Element) child; | ||
| 114 | String localName = childElem.getLocalName(); | ||
| 115 | if (localName.equals("X509Certificate")) { | ||
| 116 | content.add(unmarshalX509Certificate(childElem)); | ||
| 117 | } else if (localName.equals("X509IssuerSerial")) { | ||
| 118 | content.add(new DOMX509IssuerSerial(childElem)); | ||
| 119 | } else if (localName.equals("X509SubjectName")) { | ||
| 120 | content.add(childElem.getFirstChild().getNodeValue()); | ||
| 121 | } else if (localName.equals("X509SKI")) { | ||
| 122 | try { | ||
| 123 | content.add(Base64.decode(childElem)); | ||
| 124 | } catch (Base64DecodingException bde) { | ||
| 125 | throw new MarshalException("cannot decode X509SKI", bde); | ||
| 126 | } | ||
| 127 | } else if (localName.equals("X509CRL")) { | ||
| 128 | content.add(unmarshalX509CRL(childElem)); | ||
| 129 | } else { | ||
| 130 | content.add(new javax.xml.crypto.dom.DOMStructure(childElem)); | ||
| 131 | } | ||
| 132 | } | ||
| 133 | this.content = Collections.unmodifiableList(content); | ||
| 134 | } | ||
| 135 | |||
| 136 | public List getContent() { | ||
| 137 | return content; | ||
| 138 | } | ||
| 139 | |||
| 140 | public void marshal(Node parent, String dsPrefix, DOMCryptoContext context) | ||
| 141 | throws MarshalException { | ||
| 142 | Document ownerDoc = DOMUtils.getOwnerDocument(parent); | ||
| 143 | |||
| 144 | Element xdElem = DOMUtils.createElement | ||
| 145 | (ownerDoc, "X509Data", XMLSignature.XMLNS, dsPrefix); | ||
| 146 | |||
| 147 | // append children and preserve order | ||
| 148 | for (int i = 0, size = content.size(); i < size; i++) { | ||
| 149 | Object object = content.get(i); | ||
| 150 | if (object instanceof X509Certificate) { | ||
| 151 | marshalCert((X509Certificate) object,xdElem,ownerDoc,dsPrefix); | ||
| 152 | } else if (object instanceof XMLStructure) { | ||
| 153 | if (object instanceof X509IssuerSerial) { | ||
| 154 | ((DOMX509IssuerSerial) object).marshal | ||
| 155 | (xdElem, dsPrefix, context); | ||
| 156 | } else { | ||
| 157 | javax.xml.crypto.dom.DOMStructure domContent = | ||
| 158 | (javax.xml.crypto.dom.DOMStructure) object; | ||
| 159 | DOMUtils.appendChild(xdElem, domContent.getNode()); | ||
| 160 | } | ||
| 161 | } else if (object instanceof byte[]) { | ||
| 162 | marshalSKI((byte[]) object, xdElem, ownerDoc, dsPrefix); | ||
| 163 | } else if (object instanceof String) { | ||
| 164 | marshalSubjectName((String) object, xdElem, ownerDoc,dsPrefix); | ||
| 165 | } else if (object instanceof X509CRL) { | ||
| 166 | marshalCRL((X509CRL) object, xdElem, ownerDoc, dsPrefix); | ||
| 167 | } | ||
| 168 | } | ||
| 169 | |||
| 170 | parent.appendChild(xdElem); | ||
| 171 | } | ||
| 172 | |||
| 173 | private void marshalSKI(byte[] skid, Node parent, Document doc, | ||
| 174 | String dsPrefix) { | ||
| 175 | |||
| 176 | Element skidElem = DOMUtils.createElement | ||
| 177 | (doc, "X509SKI", XMLSignature.XMLNS, dsPrefix); | ||
| 178 | skidElem.appendChild(doc.createTextNode(Base64.encode(skid))); | ||
| 179 | parent.appendChild(skidElem); | ||
| 180 | } | ||
| 181 | |||
| 182 | private void marshalSubjectName(String name, Node parent, Document doc, | ||
| 183 | String dsPrefix) { | ||
| 184 | |||
| 185 | Element snElem = DOMUtils.createElement | ||
| 186 | (doc, "X509SubjectName", XMLSignature.XMLNS, dsPrefix); | ||
| 187 | snElem.appendChild(doc.createTextNode(name)); | ||
| 188 | parent.appendChild(snElem); | ||
| 189 | } | ||
| 190 | |||
| 191 | private void marshalCert(X509Certificate cert, Node parent, Document doc, | ||
| 192 | String dsPrefix) throws MarshalException { | ||
| 193 | |||
| 194 | Element certElem = DOMUtils.createElement | ||
| 195 | (doc, "X509Certificate", XMLSignature.XMLNS, dsPrefix); | ||
| 196 | try { | ||
| 197 | certElem.appendChild(doc.createTextNode | ||
| 198 | (Base64.encode(cert.getEncoded()))); | ||
| 199 | } catch (CertificateEncodingException e) { | ||
| 200 | throw new MarshalException("Error encoding X509Certificate", e); | ||
| 201 | } | ||
| 202 | parent.appendChild(certElem); | ||
| 203 | } | ||
| 204 | |||
| 205 | private void marshalCRL(X509CRL crl, Node parent, Document doc, | ||
| 206 | String dsPrefix) throws MarshalException { | ||
| 207 | |||
| 208 | Element crlElem = DOMUtils.createElement | ||
| 209 | (doc, "X509CRL", XMLSignature.XMLNS, dsPrefix); | ||
| 210 | try { | ||
| 211 | crlElem.appendChild(doc.createTextNode | ||
| 212 | (Base64.encode(crl.getEncoded()))); | ||
| 213 | } catch (CRLException e) { | ||
| 214 | throw new MarshalException("Error encoding X509CRL", e); | ||
| 215 | } | ||
| 216 | parent.appendChild(crlElem); | ||
| 217 | } | ||
| 218 | |||
| 219 | private X509Certificate unmarshalX509Certificate(Element elem) | ||
| 220 | throws MarshalException { | ||
| 221 | try { | ||
| 222 | ByteArrayInputStream bs = unmarshalBase64Binary(elem); | ||
| 223 | return (X509Certificate) cf.generateCertificate(bs); | ||
| 224 | } catch (CertificateException e) { | ||
| 225 | throw new MarshalException("Cannot create X509Certificate", e); | ||
| 226 | } | ||
| 227 | } | ||
| 228 | |||
| 229 | private X509CRL unmarshalX509CRL(Element elem) throws MarshalException { | ||
| 230 | try { | ||
| 231 | ByteArrayInputStream bs = unmarshalBase64Binary(elem); | ||
| 232 | return (X509CRL) cf.generateCRL(bs); | ||
| 233 | } catch (CRLException e) { | ||
| 234 | throw new MarshalException("Cannot create X509CRL", e); | ||
| 235 | } | ||
| 236 | } | ||
| 237 | |||
| 238 | private ByteArrayInputStream unmarshalBase64Binary(Element elem) | ||
| 239 | throws MarshalException { | ||
| 240 | try { | ||
| 241 | if (cf == null) { | ||
| 242 | cf = CertificateFactory.getInstance("X.509"); | ||
| 243 | } | ||
| 244 | return new ByteArrayInputStream(Base64.decode(elem)); | ||
| 245 | } catch (CertificateException e) { | ||
| 246 | throw new MarshalException("Cannot create CertificateFactory", e); | ||
| 247 | } catch (Base64DecodingException bde) { | ||
| 248 | throw new MarshalException("Cannot decode Base64-encoded val", bde); | ||
| 249 | } | ||
| 250 | } | ||
| 251 | |||
| 252 | public boolean equals(Object o) { | ||
| 253 | if (this == o) { | ||
| 254 | return true; | ||
| 255 | } | ||
| 256 | |||
| 257 | if (!(o instanceof X509Data)) { | ||
| 258 | return false; | ||
| 259 | } | ||
| 260 | X509Data oxd = (X509Data) o; | ||
| 261 | |||
| 262 | List ocontent = oxd.getContent(); | ||
| 263 | int size = content.size(); | ||
| 264 | if (size != ocontent.size()) { | ||
| 265 | return false; | ||
| 266 | } | ||
| 267 | |||
| 268 | for (int i = 0; i < size; i++) { | ||
| 269 | Object x = content.get(i); | ||
| 270 | Object ox = ocontent.get(i); | ||
| 271 | if (x instanceof byte[]) { | ||
| 272 | if (!(ox instanceof byte[]) || | ||
| 273 | !Arrays.equals((byte[]) x, (byte[]) ox)) { | ||
| 274 | return false; | ||
| 275 | } | ||
| 276 | } else { | ||
| 277 | if (!(x.equals(ox))) { | ||
| 278 | return false; | ||
| 279 | } | ||
| 280 | } | ||
| 281 | } | ||
| 282 | |||
| 283 | return true; | ||
| 284 | } | ||
| 285 | } | ||
Binary file not shown.
| @@ -0,0 +1,124 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DOMX509IssuerSerial.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import javax.xml.crypto.*; | ||
| 30 | import javax.xml.crypto.dom.DOMCryptoContext; | ||
| 31 | import javax.xml.crypto.dsig.*; | ||
| 32 | import javax.xml.crypto.dsig.keyinfo.X509IssuerSerial; | ||
| 33 | |||
| 34 | import java.math.BigInteger; | ||
| 35 | import javax.security.auth.x500.X500Principal; | ||
| 36 | import org.w3c.dom.Document; | ||
| 37 | import org.w3c.dom.Element; | ||
| 38 | import org.w3c.dom.Node; | ||
| 39 | |||
| 40 | /** | ||
| 41 | * DOM-based implementation of X509IssuerSerial. | ||
| 42 | * | ||
| 43 | * @author Sean Mullan | ||
| 44 | */ | ||
| 45 | public final class DOMX509IssuerSerial extends DOMStructure | ||
| 46 | implements X509IssuerSerial { | ||
| 47 | |||
| 48 | private final String issuerName; | ||
| 49 | private final BigInteger serialNumber; | ||
| 50 | |||
| 51 | /** | ||
| 52 | * Creates a <code>DOMX509IssuerSerial</code> containing the specified | ||
| 53 | * issuer distinguished name/serial number pair. | ||
| 54 | * | ||
| 55 | * @param issuerName the X.509 issuer distinguished name in RFC 2253 | ||
| 56 | * String format | ||
| 57 | * @param serialNumber the serial number | ||
| 58 | * @throws IllegalArgumentException if the format of <code>issuerName</code> | ||
| 59 | * is not RFC 2253 compliant | ||
| 60 | * @throws NullPointerException if <code>issuerName</code> or | ||
| 61 | * <code>serialNumber</code> is <code>null</code> | ||
| 62 | */ | ||
| 63 | public DOMX509IssuerSerial(String issuerName, BigInteger serialNumber) { | ||
| 64 | if (issuerName == null) { | ||
| 65 | throw new NullPointerException("issuerName cannot be null"); | ||
| 66 | } | ||
| 67 | if (serialNumber == null) { | ||
| 68 | throw new NullPointerException("serialNumber cannot be null"); | ||
| 69 | } | ||
| 70 | // check that issuer distinguished name conforms to RFC 2253 | ||
| 71 | new X500Principal(issuerName); | ||
| 72 | this.issuerName = issuerName; | ||
| 73 | this.serialNumber = serialNumber; | ||
| 74 | } | ||
| 75 | |||
| 76 | /** | ||
| 77 | * Creates a <code>DOMX509IssuerSerial</code> from an element. | ||
| 78 | * | ||
| 79 | * @param isElem an X509IssuerSerial element | ||
| 80 | */ | ||
| 81 | public DOMX509IssuerSerial(Element isElem) { | ||
| 82 | Element iNElem = DOMUtils.getFirstChildElement(isElem); | ||
| 83 | Element sNElem = DOMUtils.getNextSiblingElement(iNElem); | ||
| 84 | issuerName = iNElem.getFirstChild().getNodeValue(); | ||
| 85 | serialNumber = new BigInteger(sNElem.getFirstChild().getNodeValue()); | ||
| 86 | } | ||
| 87 | |||
| 88 | public String getIssuerName() { | ||
| 89 | return issuerName; | ||
| 90 | } | ||
| 91 | |||
| 92 | public BigInteger getSerialNumber() { | ||
| 93 | return serialNumber; | ||
| 94 | } | ||
| 95 | |||
| 96 | public void marshal(Node parent, String dsPrefix, DOMCryptoContext context) | ||
| 97 | throws MarshalException { | ||
| 98 | Document ownerDoc = DOMUtils.getOwnerDocument(parent); | ||
| 99 | |||
| 100 | Element isElem = DOMUtils.createElement | ||
| 101 | (ownerDoc, "X509IssuerSerial", XMLSignature.XMLNS, dsPrefix); | ||
| 102 | Element inElem = DOMUtils.createElement | ||
| 103 | (ownerDoc, "X509IssuerName", XMLSignature.XMLNS, dsPrefix); | ||
| 104 | Element snElem = DOMUtils.createElement | ||
| 105 | (ownerDoc, "X509SerialNumber", XMLSignature.XMLNS, dsPrefix); | ||
| 106 | inElem.appendChild(ownerDoc.createTextNode(issuerName)); | ||
| 107 | snElem.appendChild(ownerDoc.createTextNode(serialNumber.toString())); | ||
| 108 | isElem.appendChild(inElem); | ||
| 109 | isElem.appendChild(snElem); | ||
| 110 | parent.appendChild(isElem); | ||
| 111 | } | ||
| 112 | |||
| 113 | public boolean equals(Object obj) { | ||
| 114 | if (this == obj) { | ||
| 115 | return true; | ||
| 116 | } | ||
| 117 | if (!(obj instanceof X509IssuerSerial)) { | ||
| 118 | return false; | ||
| 119 | } | ||
| 120 | X509IssuerSerial ois = (X509IssuerSerial) obj; | ||
| 121 | return (issuerName.equals(ois.getIssuerName()) && | ||
| 122 | serialNumber.equals(ois.getSerialNumber())); | ||
| 123 | } | ||
| 124 | } | ||
Binary file not shown.
| @@ -0,0 +1,217 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DOMXMLObject.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import javax.xml.crypto.*; | ||
| 30 | import javax.xml.crypto.dom.DOMCryptoContext; | ||
| 31 | import javax.xml.crypto.dsig.*; | ||
| 32 | |||
| 33 | import java.security.Provider; | ||
| 34 | import java.util.*; | ||
| 35 | import org.w3c.dom.Document; | ||
| 36 | import org.w3c.dom.Element; | ||
| 37 | import org.w3c.dom.Node; | ||
| 38 | import org.w3c.dom.NodeList; | ||
| 39 | |||
| 40 | /** | ||
| 41 | * DOM-based implementation of XMLObject. | ||
| 42 | * | ||
| 43 | * @author Sean Mullan | ||
| 44 | */ | ||
| 45 | public final class DOMXMLObject extends DOMStructure implements XMLObject { | ||
| 46 | |||
| 47 | private final String id; | ||
| 48 | private final String mimeType; | ||
| 49 | private final String encoding; | ||
| 50 | private final List content; | ||
| 51 | |||
| 52 | /** | ||
| 53 | * Creates an <code>XMLObject</code> from the specified parameters. | ||
| 54 | * | ||
| 55 | * @param content a list of {@link XMLStructure}s. The list | ||
| 56 | * is defensively copied to protect against subsequent modification. | ||
| 57 | * May be <code>null</code> or empty. | ||
| 58 | * @param id the Id (may be <code>null</code>) | ||
| 59 | * @param mimeType the mime type (may be <code>null</code>) | ||
| 60 | * @param encoding the encoding (may be <code>null</code>) | ||
| 61 | * @return an <code>XMLObject</code> | ||
| 62 | * @throws ClassCastException if <code>content</code> contains any | ||
| 63 | * entries that are not of type {@link XMLStructure} | ||
| 64 | */ | ||
| 65 | public DOMXMLObject(List content, String id, String mimeType, | ||
| 66 | String encoding) { | ||
| 67 | if (content == null || content.isEmpty()) { | ||
| 68 | this.content = Collections.EMPTY_LIST; | ||
| 69 | } else { | ||
| 70 | List contentCopy = new ArrayList(content); | ||
| 71 | for (int i = 0, size = contentCopy.size(); i < size; i++) { | ||
| 72 | if (!(contentCopy.get(i) instanceof XMLStructure)) { | ||
| 73 | throw new ClassCastException | ||
| 74 | ("content["+i+"] is not a valid type"); | ||
| 75 | } | ||
| 76 | } | ||
| 77 | this.content = Collections.unmodifiableList(contentCopy); | ||
| 78 | } | ||
| 79 | this.id = id; | ||
| 80 | this.mimeType = mimeType; | ||
| 81 | this.encoding = encoding; | ||
| 82 | } | ||
| 83 | |||
| 84 | /** | ||
| 85 | * Creates an <code>XMLObject</code> from an element. | ||
| 86 | * | ||
| 87 | * @param objElem an Object element | ||
| 88 | * @throws MarshalException if there is an error when unmarshalling | ||
| 89 | */ | ||
| 90 | public DOMXMLObject(Element objElem, XMLCryptoContext context, | ||
| 91 | Provider provider) throws MarshalException { | ||
| 92 | // unmarshal attributes | ||
| 93 | this.encoding = DOMUtils.getAttributeValue(objElem, "Encoding"); | ||
| 94 | this.id = DOMUtils.getAttributeValue(objElem, "Id"); | ||
| 95 | this.mimeType = DOMUtils.getAttributeValue(objElem, "MimeType"); | ||
| 96 | |||
| 97 | NodeList nodes = objElem.getChildNodes(); | ||
| 98 | int length = nodes.getLength(); | ||
| 99 | List content = new ArrayList(length); | ||
| 100 | for (int i = 0; i < length; i++) { | ||
| 101 | Node child = nodes.item(i); | ||
| 102 | if (child.getNodeType() == Node.ELEMENT_NODE) { | ||
| 103 | Element childElem = (Element) child; | ||
| 104 | String tag = childElem.getLocalName(); | ||
| 105 | if (tag.equals("Manifest")) { | ||
| 106 | content.add(new DOMManifest(childElem, context, provider)); | ||
| 107 | continue; | ||
| 108 | } else if (tag.equals("SignatureProperties")) { | ||
| 109 | content.add(new DOMSignatureProperties(childElem)); | ||
| 110 | continue; | ||
| 111 | } else if (tag.equals("X509Data")) { | ||
| 112 | content.add(new DOMX509Data(childElem)); | ||
| 113 | continue; | ||
| 114 | } | ||
| 115 | //@@@FIXME: check for other dsig structures | ||
| 116 | } | ||
| 117 | content.add(new javax.xml.crypto.dom.DOMStructure(child)); | ||
| 118 | } | ||
| 119 | if (content.isEmpty()) { | ||
| 120 | this.content = Collections.EMPTY_LIST; | ||
| 121 | } else { | ||
| 122 | this.content = Collections.unmodifiableList(content); | ||
| 123 | } | ||
| 124 | } | ||
| 125 | |||
| 126 | public List getContent() { | ||
| 127 | return content; | ||
| 128 | } | ||
| 129 | |||
| 130 | public String getId() { | ||
| 131 | return id; | ||
| 132 | } | ||
| 133 | |||
| 134 | public String getMimeType() { | ||
| 135 | return mimeType; | ||
| 136 | } | ||
| 137 | |||
| 138 | public String getEncoding() { | ||
| 139 | return encoding; | ||
| 140 | } | ||
| 141 | |||
| 142 | public void marshal(Node parent, String dsPrefix, DOMCryptoContext context) | ||
| 143 | throws MarshalException { | ||
| 144 | Document ownerDoc = DOMUtils.getOwnerDocument(parent); | ||
| 145 | |||
| 146 | Element objElem = DOMUtils.createElement | ||
| 147 | (ownerDoc, "Object", XMLSignature.XMLNS, dsPrefix); | ||
| 148 | |||
| 149 | // set attributes | ||
| 150 | DOMUtils.setAttributeID(objElem, "Id", id); | ||
| 151 | DOMUtils.setAttribute(objElem, "MimeType", mimeType); | ||
| 152 | DOMUtils.setAttribute(objElem, "Encoding", encoding); | ||
| 153 | |||
| 154 | // create and append any elements and mixed content, if necessary | ||
| 155 | for (int i = 0, size = content.size(); i < size; i++) { | ||
| 156 | XMLStructure object = (XMLStructure) content.get(i); | ||
| 157 | if (object instanceof DOMStructure) { | ||
| 158 | ((DOMStructure) object).marshal(objElem, dsPrefix, context); | ||
| 159 | } else { | ||
| 160 | javax.xml.crypto.dom.DOMStructure domObject = | ||
| 161 | (javax.xml.crypto.dom.DOMStructure) object; | ||
| 162 | DOMUtils.appendChild(objElem, domObject.getNode()); | ||
| 163 | } | ||
| 164 | } | ||
| 165 | |||
| 166 | parent.appendChild(objElem); | ||
| 167 | } | ||
| 168 | |||
| 169 | public boolean equals(Object o) { | ||
| 170 | if (this == o) { | ||
| 171 | return true; | ||
| 172 | } | ||
| 173 | |||
| 174 | if (!(o instanceof XMLObject)) { | ||
| 175 | return false; | ||
| 176 | } | ||
| 177 | XMLObject oxo = (XMLObject) o; | ||
| 178 | |||
| 179 | boolean idsEqual = (id == null ? oxo.getId() == null : | ||
| 180 | id.equals(oxo.getId())); | ||
| 181 | boolean encodingsEqual = (encoding == null ? oxo.getEncoding() == null : | ||
| 182 | encoding.equals(oxo.getEncoding())); | ||
| 183 | boolean mimeTypesEqual = (mimeType == null ? oxo.getMimeType() == null : | ||
| 184 | mimeType.equals(oxo.getMimeType())); | ||
| 185 | |||
| 186 | return (idsEqual && encodingsEqual && mimeTypesEqual && | ||
| 187 | equalsContent(oxo.getContent())); | ||
| 188 | } | ||
| 189 | |||
| 190 | private boolean equalsContent(List otherContent) { | ||
| 191 | if (content.size() != otherContent.size()) { | ||
| 192 | return false; | ||
| 193 | } | ||
| 194 | for (int i = 0, osize = otherContent.size(); i < osize; i++) { | ||
| 195 | XMLStructure oxs = (XMLStructure) otherContent.get(i); | ||
| 196 | XMLStructure xs = (XMLStructure) content.get(i); | ||
| 197 | if (oxs instanceof javax.xml.crypto.dom.DOMStructure) { | ||
| 198 | if (!(xs instanceof javax.xml.crypto.dom.DOMStructure)) { | ||
| 199 | return false; | ||
| 200 | } | ||
| 201 | Node onode = | ||
| 202 | ((javax.xml.crypto.dom.DOMStructure) oxs).getNode(); | ||
| 203 | Node node = | ||
| 204 | ((javax.xml.crypto.dom.DOMStructure) xs).getNode(); | ||
| 205 | if (!DOMUtils.nodesEqual(node, onode)) { | ||
| 206 | return false; | ||
| 207 | } | ||
| 208 | } else { | ||
| 209 | if (!(xs.equals(oxs))) { | ||
| 210 | return false; | ||
| 211 | } | ||
| 212 | } | ||
| 213 | } | ||
| 214 | |||
| 215 | return true; | ||
| 216 | } | ||
| 217 | } | ||
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,586 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * =========================================================================== | ||
| 26 | * | ||
| 27 | * (C) Copyright IBM Corp. 2003 All Rights Reserved. | ||
| 28 | * | ||
| 29 | * =========================================================================== | ||
| 30 | */ | ||
| 31 | /* | ||
| 32 | * $Id: DOMXMLSignature.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 33 | */ | ||
| 34 | package org.jcp.xml.dsig.internal.dom; | ||
| 35 | |||
| 36 | import javax.xml.crypto.*; | ||
| 37 | import javax.xml.crypto.dom.*; | ||
| 38 | import javax.xml.crypto.dsig.*; | ||
| 39 | import javax.xml.crypto.dsig.dom.DOMSignContext; | ||
| 40 | import javax.xml.crypto.dsig.dom.DOMValidateContext; | ||
| 41 | import javax.xml.crypto.dsig.keyinfo.KeyInfo; | ||
| 42 | |||
| 43 | import java.io.*; | ||
| 44 | import java.security.InvalidKeyException; | ||
| 45 | import java.security.Key; | ||
| 46 | import java.security.Provider; | ||
| 47 | import java.util.Collections; | ||
| 48 | import java.util.ArrayList; | ||
| 49 | import java.util.HashMap; | ||
| 50 | import java.util.List; | ||
| 51 | import java.util.logging.Level; | ||
| 52 | import java.util.logging.Logger; | ||
| 53 | import org.w3c.dom.Document; | ||
| 54 | import org.w3c.dom.Element; | ||
| 55 | import org.w3c.dom.Node; | ||
| 56 | |||
| 57 | import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException; | ||
| 58 | import com.sun.org.apache.xml.internal.security.utils.Base64; | ||
| 59 | |||
| 60 | /** | ||
| 61 | * DOM-based implementation of XMLSignature. | ||
| 62 | * | ||
| 63 | * @author Sean Mullan | ||
| 64 | * @author Joyce Leung | ||
| 65 | */ | ||
| 66 | public final class DOMXMLSignature extends DOMStructure | ||
| 67 | implements XMLSignature { | ||
| 68 | |||
| 69 | private static Logger log = Logger.getLogger("org.jcp.xml.dsig.internal.dom"); | ||
| 70 | private String id; | ||
| 71 | private SignatureValue sv; | ||
| 72 | private KeyInfo ki; | ||
| 73 | private List objects; | ||
| 74 | private SignedInfo si; | ||
| 75 | private Document ownerDoc = null; | ||
| 76 | private Element localSigElem = null; | ||
| 77 | private Element sigElem = null; | ||
| 78 | private boolean validationStatus; | ||
| 79 | private boolean validated = false; | ||
| 80 | private KeySelectorResult ksr; | ||
| 81 | private HashMap signatureIdMap; | ||
| 82 | |||
| 83 | static { | ||
| 84 | com.sun.org.apache.xml.internal.security.Init.init(); | ||
| 85 | } | ||
| 86 | |||
| 87 | /** | ||
| 88 | * Creates a <code>DOMXMLSignature</code> from the specified components. | ||
| 89 | * | ||
| 90 | * @param si the <code>SignedInfo</code> | ||
| 91 | * @param ki the <code>KeyInfo</code>, or <code>null</code> if not specified | ||
| 92 | * @param objs a list of <code>XMLObject</code>s or <code>null</code> | ||
| 93 | * if not specified. The list is copied to protect against subsequent | ||
| 94 | * modification. | ||
| 95 | * @param id an optional id (specify <code>null</code> to omit) | ||
| 96 | * @param signatureValueId an optional id (specify <code>null</code> to | ||
| 97 | * omit) | ||
| 98 | * @throws NullPointerException if <code>si</code> is <code>null</code> | ||
| 99 | */ | ||
| 100 | public DOMXMLSignature(SignedInfo si, KeyInfo ki, List objs, String id, | ||
| 101 | String signatureValueId) | ||
| 102 | { | ||
| 103 | if (si == null) { | ||
| 104 | throw new NullPointerException("signedInfo cannot be null"); | ||
| 105 | } | ||
| 106 | this.si = si; | ||
| 107 | this.id = id; | ||
| 108 | this.sv = new DOMSignatureValue(signatureValueId); | ||
| 109 | if (objs == null) { | ||
| 110 | this.objects = Collections.EMPTY_LIST; | ||
| 111 | } else { | ||
| 112 | List objsCopy = new ArrayList(objs); | ||
| 113 | for (int i = 0, size = objsCopy.size(); i < size; i++) { | ||
| 114 | if (!(objsCopy.get(i) instanceof XMLObject)) { | ||
| 115 | throw new ClassCastException | ||
| 116 | ("objs["+i+"] is not an XMLObject"); | ||
| 117 | } | ||
| 118 | } | ||
| 119 | this.objects = Collections.unmodifiableList(objsCopy); | ||
| 120 | } | ||
| 121 | this.ki = ki; | ||
| 122 | } | ||
| 123 | |||
| 124 | /** | ||
| 125 | * Creates a <code>DOMXMLSignature</code> from XML. | ||
| 126 | * | ||
| 127 | * @param sigElem Signature element | ||
| 128 | * @throws MarshalException if XMLSignature cannot be unmarshalled | ||
| 129 | */ | ||
| 130 | public DOMXMLSignature(Element sigElem, XMLCryptoContext context, | ||
| 131 | Provider provider) throws MarshalException { | ||
| 132 | localSigElem = sigElem; | ||
| 133 | ownerDoc = localSigElem.getOwnerDocument(); | ||
| 134 | |||
| 135 | // get Id attribute, if specified | ||
| 136 | id = DOMUtils.getAttributeValue(localSigElem, "Id"); | ||
| 137 | |||
| 138 | // unmarshal SignedInfo | ||
| 139 | Element siElem = DOMUtils.getFirstChildElement(localSigElem); | ||
| 140 | si = new DOMSignedInfo(siElem, context, provider); | ||
| 141 | |||
| 142 | // unmarshal SignatureValue | ||
| 143 | Element sigValElem = DOMUtils.getNextSiblingElement(siElem); | ||
| 144 | sv = new DOMSignatureValue(sigValElem); | ||
| 145 | |||
| 146 | // unmarshal KeyInfo, if specified | ||
| 147 | Element nextSibling = DOMUtils.getNextSiblingElement(sigValElem); | ||
| 148 | if (nextSibling != null && nextSibling.getLocalName().equals("KeyInfo")) { | ||
| 149 | ki = new DOMKeyInfo(nextSibling, context, provider); | ||
| 150 | nextSibling = DOMUtils.getNextSiblingElement(nextSibling); | ||
| 151 | } | ||
| 152 | |||
| 153 | // unmarshal Objects, if specified | ||
| 154 | if (nextSibling == null) { | ||
| 155 | objects = Collections.EMPTY_LIST; | ||
| 156 | } else { | ||
| 157 | List tempObjects = new ArrayList(); | ||
| 158 | while (nextSibling != null) { | ||
| 159 | tempObjects.add | ||
| 160 | (new DOMXMLObject(nextSibling, context, provider)); | ||
| 161 | nextSibling = DOMUtils.getNextSiblingElement(nextSibling); | ||
| 162 | } | ||
| 163 | objects = Collections.unmodifiableList(tempObjects); | ||
| 164 | } | ||
| 165 | } | ||
| 166 | |||
| 167 | public String getId() { | ||
| 168 | return id; | ||
| 169 | } | ||
| 170 | |||
| 171 | public KeyInfo getKeyInfo() { | ||
| 172 | return ki; | ||
| 173 | } | ||
| 174 | |||
| 175 | public SignedInfo getSignedInfo() { | ||
| 176 | return si; | ||
| 177 | } | ||
| 178 | |||
| 179 | public List getObjects() { | ||
| 180 | return objects; | ||
| 181 | } | ||
| 182 | |||
| 183 | public SignatureValue getSignatureValue() { | ||
| 184 | return sv; | ||
| 185 | } | ||
| 186 | |||
| 187 | public KeySelectorResult getKeySelectorResult() { | ||
| 188 | return ksr; | ||
| 189 | } | ||
| 190 | |||
| 191 | public void marshal(Node parent, String dsPrefix, DOMCryptoContext context) | ||
| 192 | throws MarshalException { | ||
| 193 | marshal(parent, null, dsPrefix, context); | ||
| 194 | } | ||
| 195 | |||
| 196 | public void marshal(Node parent, Node nextSibling, String dsPrefix, | ||
| 197 | DOMCryptoContext context) throws MarshalException { | ||
| 198 | ownerDoc = DOMUtils.getOwnerDocument(parent); | ||
| 199 | |||
| 200 | sigElem = DOMUtils.createElement | ||
| 201 | (ownerDoc, "Signature", XMLSignature.XMLNS, dsPrefix); | ||
| 202 | |||
| 203 | // append xmlns attribute | ||
| 204 | if (dsPrefix == null || dsPrefix.length() == 0) { | ||
| 205 | sigElem.setAttributeNS | ||
| 206 | ("http://www.w3.org/2000/xmlns/", "xmlns", XMLSignature.XMLNS); | ||
| 207 | } else { | ||
| 208 | sigElem.setAttributeNS | ||
| 209 | ("http://www.w3.org/2000/xmlns/", "xmlns:" + dsPrefix, | ||
| 210 | XMLSignature.XMLNS); | ||
| 211 | } | ||
| 212 | |||
| 213 | // create and append SignedInfo element | ||
| 214 | ((DOMSignedInfo) si).marshal(sigElem, dsPrefix, context); | ||
| 215 | |||
| 216 | // create and append SignatureValue element | ||
| 217 | ((DOMSignatureValue) sv).marshal(sigElem, dsPrefix, context); | ||
| 218 | |||
| 219 | // create and append KeyInfo element if necessary | ||
| 220 | if (ki != null) { | ||
| 221 | ((DOMKeyInfo) ki).marshal(sigElem, null, dsPrefix, context); | ||
| 222 | } | ||
| 223 | |||
| 224 | // create and append Object elements if necessary | ||
| 225 | for (int i = 0, size = objects.size(); i < size; i++) { | ||
| 226 | ((DOMXMLObject) objects.get(i)).marshal(sigElem, dsPrefix, context); | ||
| 227 | } | ||
| 228 | |||
| 229 | // append Id attribute | ||
| 230 | DOMUtils.setAttributeID(sigElem, "Id", id); | ||
| 231 | |||
| 232 | parent.insertBefore(sigElem, nextSibling); | ||
| 233 | } | ||
| 234 | |||
| 235 | public boolean validate(XMLValidateContext vc) | ||
| 236 | throws XMLSignatureException { | ||
| 237 | |||
| 238 | if (vc == null) { | ||
| 239 | throw new NullPointerException("validateContext is null"); | ||
| 240 | } | ||
| 241 | |||
| 242 | if (!(vc instanceof DOMValidateContext)) { | ||
| 243 | throw new ClassCastException | ||
| 244 | ("validateContext must be of type DOMValidateContext"); | ||
| 245 | } | ||
| 246 | |||
| 247 | if (validated) { | ||
| 248 | return validationStatus; | ||
| 249 | } | ||
| 250 | |||
| 251 | // validate the signature | ||
| 252 | boolean sigValidity = sv.validate(vc); | ||
| 253 | if (!sigValidity) { | ||
| 254 | validationStatus = false; | ||
| 255 | validated = true; | ||
| 256 | return validationStatus; | ||
| 257 | } | ||
| 258 | |||
| 259 | // validate all References | ||
| 260 | List refs = this.si.getReferences(); | ||
| 261 | boolean validateRefs = true; | ||
| 262 | for (int i = 0, size = refs.size(); validateRefs && i < size; i++) { | ||
| 263 | Reference ref = (Reference) refs.get(i); | ||
| 264 | boolean refValid = ref.validate(vc); | ||
| 265 | if (log.isLoggable(Level.FINE)) { | ||
| 266 | log.log(Level.FINE, "Reference[" + ref.getURI() + "] is valid: " | ||
| 267 | + refValid); | ||
| 268 | } | ||
| 269 | validateRefs &= refValid; | ||
| 270 | } | ||
| 271 | if (!validateRefs) { | ||
| 272 | if (log.isLoggable(Level.FINE)) { | ||
| 273 | log.log(Level.FINE, "Couldn't validate the References"); | ||
| 274 | } | ||
| 275 | validationStatus = false; | ||
| 276 | validated = true; | ||
| 277 | return validationStatus; | ||
| 278 | } | ||
| 279 | |||
| 280 | // validate Manifests, if property set | ||
| 281 | boolean validateMans = true; | ||
| 282 | if (Boolean.TRUE.equals(vc.getProperty | ||
| 283 | ("org.jcp.xml.dsig.validateManifests"))) { | ||
| 284 | |||
| 285 | for (int i=0, size=objects.size(); validateMans && i < size; i++) { | ||
| 286 | XMLObject xo = (XMLObject) objects.get(i); | ||
| 287 | List content = xo.getContent(); | ||
| 288 | int csize = content.size(); | ||
| 289 | for (int j = 0; validateMans && j < csize; j++) { | ||
| 290 | XMLStructure xs = (XMLStructure) content.get(j); | ||
| 291 | if (xs instanceof Manifest) { | ||
| 292 | if (log.isLoggable(Level.FINE)) { | ||
| 293 | log.log(Level.FINE, "validating manifest"); | ||
| 294 | } | ||
| 295 | Manifest man = (Manifest) xs; | ||
| 296 | List manRefs = man.getReferences(); | ||
| 297 | int rsize = manRefs.size(); | ||
| 298 | for (int k = 0; validateMans && k < rsize; k++) { | ||
| 299 | Reference ref = (Reference) manRefs.get(k); | ||
| 300 | boolean refValid = ref.validate(vc); | ||
| 301 | if (log.isLoggable(Level.FINE)) { | ||
| 302 | log.log(Level.FINE, "Manifest ref[" | ||
| 303 | + ref.getURI() + "] is valid: " + refValid); | ||
| 304 | } | ||
| 305 | validateMans &= refValid; | ||
| 306 | } | ||
| 307 | } | ||
| 308 | } | ||
| 309 | } | ||
| 310 | } | ||
| 311 | |||
| 312 | validationStatus = validateMans; | ||
| 313 | validated = true; | ||
| 314 | return validationStatus; | ||
| 315 | } | ||
| 316 | |||
| 317 | public void sign(XMLSignContext signContext) | ||
| 318 | throws MarshalException, XMLSignatureException { | ||
| 319 | if (signContext == null) { | ||
| 320 | throw new NullPointerException("signContext cannot be null"); | ||
| 321 | } | ||
| 322 | DOMSignContext context = (DOMSignContext) signContext; | ||
| 323 | if (context != null) { | ||
| 324 | marshal(context.getParent(), context.getNextSibling(), | ||
| 325 | DOMUtils.getSignaturePrefix(context), context); | ||
| 326 | } | ||
| 327 | |||
| 328 | // generate references and signature value | ||
| 329 | List allReferences = new ArrayList(); | ||
| 330 | |||
| 331 | // traverse the Signature and register all objects with IDs that | ||
| 332 | // may contain References | ||
| 333 | signatureIdMap = new HashMap(); | ||
| 334 | signatureIdMap.put(id, this); | ||
| 335 | signatureIdMap.put(si.getId(), si); | ||
| 336 | List refs = si.getReferences(); | ||
| 337 | for (int i = 0, size = refs.size(); i < size; i++) { | ||
| 338 | Reference ref = (Reference) refs.get(i); | ||
| 339 | signatureIdMap.put(ref.getId(), ref); | ||
| 340 | } | ||
| 341 | for (int i = 0, size = objects.size(); i < size; i++) { | ||
| 342 | XMLObject obj = (XMLObject) objects.get(i); | ||
| 343 | signatureIdMap.put(obj.getId(), obj); | ||
| 344 | List content = obj.getContent(); | ||
| 345 | for (int j = 0, csize = content.size(); j < csize; j++) { | ||
| 346 | XMLStructure xs = (XMLStructure) content.get(j); | ||
| 347 | if (xs instanceof Manifest) { | ||
| 348 | Manifest man = (Manifest) xs; | ||
| 349 | signatureIdMap.put(man.getId(), man); | ||
| 350 | List manRefs = man.getReferences(); | ||
| 351 | for (int k = 0, msize = manRefs.size(); k < msize; k++) { | ||
| 352 | Reference ref = (Reference) manRefs.get(k); | ||
| 353 | allReferences.add(ref); | ||
| 354 | signatureIdMap.put(ref.getId(), ref); | ||
| 355 | } | ||
| 356 | } | ||
| 357 | } | ||
| 358 | } | ||
| 359 | // always add SignedInfo references after Manifest references so | ||
| 360 | // that Manifest reference are digested first | ||
| 361 | allReferences.addAll(si.getReferences()); | ||
| 362 | |||
| 363 | // generate/digest each reference | ||
| 364 | for (int i = 0, size = allReferences.size(); i < size; i++) { | ||
| 365 | DOMReference ref = (DOMReference) allReferences.get(i); | ||
| 366 | digestReference(ref, signContext); | ||
| 367 | } | ||
| 368 | |||
| 369 | // do final sweep to digest any references that were skipped or missed | ||
| 370 | for (int i = 0, size = allReferences.size(); i < size; i++) { | ||
| 371 | DOMReference ref = (DOMReference) allReferences.get(i); | ||
| 372 | if (ref.isDigested()) { | ||
| 373 | continue; | ||
| 374 | } | ||
| 375 | ref.digest(signContext); | ||
| 376 | } | ||
| 377 | |||
| 378 | Key signingKey = null; | ||
| 379 | KeySelectorResult ksr = null; | ||
| 380 | try { | ||
| 381 | ksr = signContext.getKeySelector().select | ||
| 382 | (ki, KeySelector.Purpose.SIGN, | ||
| 383 | si.getSignatureMethod(), signContext); | ||
| 384 | signingKey = ksr.getKey(); | ||
| 385 | if (signingKey == null) { | ||
| 386 | throw new XMLSignatureException("the keySelector did not " + | ||
| 387 | "find a signing key"); | ||
| 388 | } | ||
| 389 | } catch (KeySelectorException kse) { | ||
| 390 | throw new XMLSignatureException("cannot find signing key", kse); | ||
| 391 | } | ||
| 392 | |||
| 393 | // calculate signature value | ||
| 394 | byte[] val = null; | ||
| 395 | try { | ||
| 396 | val = ((DOMSignatureMethod) si.getSignatureMethod()).sign | ||
| 397 | (signingKey, (DOMSignedInfo) si, signContext); | ||
| 398 | } catch (InvalidKeyException ike) { | ||
| 399 | throw new XMLSignatureException(ike); | ||
| 400 | } | ||
| 401 | |||
| 402 | if (log.isLoggable(Level.FINE)) { | ||
| 403 | log.log(Level.FINE, "SignatureValue = " + val); | ||
| 404 | } | ||
| 405 | ((DOMSignatureValue) sv).setValue(val); | ||
| 406 | |||
| 407 | this.localSigElem = sigElem; | ||
| 408 | this.ksr = ksr; | ||
| 409 | } | ||
| 410 | |||
| 411 | public boolean equals(Object o) { | ||
| 412 | if (this == o) { | ||
| 413 | return true; | ||
| 414 | } | ||
| 415 | |||
| 416 | if (!(o instanceof XMLSignature)) { | ||
| 417 | return false; | ||
| 418 | } | ||
| 419 | XMLSignature osig = (XMLSignature) o; | ||
| 420 | |||
| 421 | boolean idEqual = | ||
| 422 | (id == null ? osig.getId() == null : id.equals(osig.getId())); | ||
| 423 | boolean keyInfoEqual = | ||
| 424 | (ki == null ? osig.getKeyInfo() == null : | ||
| 425 | ki.equals(osig.getKeyInfo())); | ||
| 426 | |||
| 427 | return (idEqual && keyInfoEqual && | ||
| 428 | sv.equals(osig.getSignatureValue()) && | ||
| 429 | si.equals(osig.getSignedInfo()) && | ||
| 430 | objects.equals(osig.getObjects())); | ||
| 431 | } | ||
| 432 | |||
| 433 | private void digestReference(DOMReference ref, XMLSignContext signContext) | ||
| 434 | throws XMLSignatureException { | ||
| 435 | if (ref.isDigested()) { | ||
| 436 | return; | ||
| 437 | } | ||
| 438 | // check dependencies | ||
| 439 | String uri = ref.getURI(); | ||
| 440 | if (Utils.sameDocumentURI(uri)) { | ||
| 441 | String id = Utils.parseIdFromSameDocumentURI(uri); | ||
| 442 | if (id != null && signatureIdMap.containsKey(id)) { | ||
| 443 | Object obj = signatureIdMap.get(id); | ||
| 444 | if (obj instanceof DOMReference) { | ||
| 445 | digestReference((DOMReference) obj, signContext); | ||
| 446 | } else if (obj instanceof Manifest) { | ||
| 447 | Manifest man = (Manifest) obj; | ||
| 448 | List manRefs = man.getReferences(); | ||
| 449 | for (int i = 0, size = manRefs.size(); i < size; i++) { | ||
| 450 | digestReference | ||
| 451 | ((DOMReference) manRefs.get(i), signContext); | ||
| 452 | } | ||
| 453 | } | ||
| 454 | } | ||
| 455 | // if uri="" and there are XPath Transforms, there may be | ||
| 456 | // reference dependencies in the XPath Transform - so be on | ||
| 457 | // the safe side, and skip and do at end in the final sweep | ||
| 458 | if (uri.length() == 0) { | ||
| 459 | List transforms = ref.getTransforms(); | ||
| 460 | for (int i = 0, size = transforms.size(); i < size; i++) { | ||
| 461 | Transform transform = (Transform) transforms.get(i); | ||
| 462 | String transformAlg = transform.getAlgorithm(); | ||
| 463 | if (transformAlg.equals(Transform.XPATH) || | ||
| 464 | transformAlg.equals(Transform.XPATH2)) { | ||
| 465 | return; | ||
| 466 | } | ||
| 467 | } | ||
| 468 | } | ||
| 469 | } | ||
| 470 | ref.digest(signContext); | ||
| 471 | } | ||
| 472 | |||
| 473 | public class DOMSignatureValue extends DOMStructure | ||
| 474 | implements SignatureValue { | ||
| 475 | |||
| 476 | private String id; | ||
| 477 | private byte[] value; | ||
| 478 | private String valueBase64; | ||
| 479 | private Element sigValueElem; | ||
| 480 | private boolean validated = false; | ||
| 481 | private boolean validationStatus; | ||
| 482 | |||
| 483 | DOMSignatureValue(String id) { | ||
| 484 | this.id = id; | ||
| 485 | } | ||
| 486 | |||
| 487 | DOMSignatureValue(Element sigValueElem) throws MarshalException { | ||
| 488 | try { | ||
| 489 | // base64 decode signatureValue | ||
| 490 | value = Base64.decode(sigValueElem); | ||
| 491 | } catch (Base64DecodingException bde) { | ||
| 492 | throw new MarshalException(bde); | ||
| 493 | } | ||
| 494 | |||
| 495 | id = DOMUtils.getAttributeValue(sigValueElem, "Id"); | ||
| 496 | this.sigValueElem = sigValueElem; | ||
| 497 | } | ||
| 498 | |||
| 499 | public String getId() { | ||
| 500 | return id; | ||
| 501 | } | ||
| 502 | |||
| 503 | public byte[] getValue() { | ||
| 504 | return (value == null) ? null : (byte[]) value.clone(); | ||
| 505 | } | ||
| 506 | |||
| 507 | public boolean validate(XMLValidateContext validateContext) | ||
| 508 | throws XMLSignatureException { | ||
| 509 | |||
| 510 | if (validateContext == null) { | ||
| 511 | throw new NullPointerException("context cannot be null"); | ||
| 512 | } | ||
| 513 | |||
| 514 | if (validated) { | ||
| 515 | return validationStatus; | ||
| 516 | } | ||
| 517 | |||
| 518 | // get validating key | ||
| 519 | SignatureMethod sm = si.getSignatureMethod(); | ||
| 520 | Key validationKey = null; | ||
| 521 | KeySelectorResult ksResult; | ||
| 522 | try { | ||
| 523 | ksResult = validateContext.getKeySelector().select | ||
| 524 | (ki, KeySelector.Purpose.VERIFY, sm, validateContext); | ||
| 525 | validationKey = ksResult.getKey(); | ||
| 526 | if (validationKey == null) { | ||
| 527 | throw new XMLSignatureException("the keyselector did " + | ||
| 528 | "not find a validation key"); | ||
| 529 | } | ||
| 530 | } catch (KeySelectorException kse) { | ||
| 531 | throw new XMLSignatureException("cannot find validation " + | ||
| 532 | "key", kse); | ||
| 533 | } | ||
| 534 | |||
| 535 | // canonicalize SignedInfo and verify signature | ||
| 536 | try { | ||
| 537 | validationStatus = ((DOMSignatureMethod) sm).verify | ||
| 538 | (validationKey, (DOMSignedInfo) si, value, validateContext); | ||
| 539 | } catch (Exception e) { | ||
| 540 | throw new XMLSignatureException(e); | ||
| 541 | } | ||
| 542 | |||
| 543 | validated = true; | ||
| 544 | ksr = ksResult; | ||
| 545 | return validationStatus; | ||
| 546 | } | ||
| 547 | |||
| 548 | public boolean equals(Object o) { | ||
| 549 | if (this == o) { | ||
| 550 | return true; | ||
| 551 | } | ||
| 552 | |||
| 553 | if (!(o instanceof SignatureValue)) { | ||
| 554 | return false; | ||
| 555 | } | ||
| 556 | SignatureValue osv = (SignatureValue) o; | ||
| 557 | |||
| 558 | boolean idEqual = | ||
| 559 | (id == null ? osv.getId() == null : id.equals(osv.getId())); | ||
| 560 | |||
| 561 | //XXX compare signature values? | ||
| 562 | return idEqual; | ||
| 563 | } | ||
| 564 | |||
| 565 | public void marshal(Node parent, String dsPrefix, | ||
| 566 | DOMCryptoContext context) throws MarshalException { | ||
| 567 | |||
| 568 | // create SignatureValue element | ||
| 569 | sigValueElem = DOMUtils.createElement | ||
| 570 | (ownerDoc, "SignatureValue", XMLSignature.XMLNS, dsPrefix); | ||
| 571 | if (valueBase64 != null) { | ||
| 572 | sigValueElem.appendChild(ownerDoc.createTextNode(valueBase64)); | ||
| 573 | } | ||
| 574 | |||
| 575 | // append Id attribute, if specified | ||
| 576 | DOMUtils.setAttributeID(sigValueElem, "Id", id); | ||
| 577 | parent.appendChild(sigValueElem); | ||
| 578 | } | ||
| 579 | |||
| 580 | void setValue(byte[] value) { | ||
| 581 | this.value = value; | ||
| 582 | valueBase64 = Base64.encode(value); | ||
| 583 | sigValueElem.appendChild(ownerDoc.createTextNode(valueBase64)); | ||
| 584 | } | ||
| 585 | } | ||
| 586 | } | ||
Binary file not shown.
| @@ -0,0 +1,298 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DOMXMLSignatureFactory.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import javax.xml.crypto.*; | ||
| 30 | import javax.xml.crypto.dsig.*; | ||
| 31 | import javax.xml.crypto.dsig.dom.DOMValidateContext; | ||
| 32 | import javax.xml.crypto.dsig.keyinfo.*; | ||
| 33 | import javax.xml.crypto.dsig.spec.*; | ||
| 34 | |||
| 35 | import java.security.InvalidAlgorithmParameterException; | ||
| 36 | import java.security.NoSuchAlgorithmException; | ||
| 37 | import java.security.spec.AlgorithmParameterSpec; | ||
| 38 | import java.util.List; | ||
| 39 | import org.w3c.dom.Document; | ||
| 40 | import org.w3c.dom.Element; | ||
| 41 | import org.w3c.dom.Node; | ||
| 42 | |||
| 43 | /** | ||
| 44 | * DOM-based implementation of XMLSignatureFactory. | ||
| 45 | * | ||
| 46 | * @author Sean Mullan | ||
| 47 | */ | ||
| 48 | public final class DOMXMLSignatureFactory extends XMLSignatureFactory { | ||
| 49 | |||
| 50 | /** | ||
| 51 | * Initializes a new instance of this class. | ||
| 52 | */ | ||
| 53 | public DOMXMLSignatureFactory() {} | ||
| 54 | |||
| 55 | public XMLSignature newXMLSignature(SignedInfo si, KeyInfo ki) { | ||
| 56 | return new DOMXMLSignature(si, ki, null, null, null); | ||
| 57 | } | ||
| 58 | |||
| 59 | public XMLSignature newXMLSignature(SignedInfo si, KeyInfo ki, | ||
| 60 | List objects, String id, String signatureValueId) { | ||
| 61 | return new DOMXMLSignature(si, ki, objects, id, signatureValueId); | ||
| 62 | } | ||
| 63 | |||
| 64 | public Reference newReference(String uri, DigestMethod dm) { | ||
| 65 | return newReference(uri, dm, null, null, null); | ||
| 66 | } | ||
| 67 | |||
| 68 | public Reference newReference(String uri, DigestMethod dm, List transforms, | ||
| 69 | String type, String id) { | ||
| 70 | return new DOMReference(uri, type, dm, transforms, id, getProvider()); | ||
| 71 | } | ||
| 72 | |||
| 73 | public Reference newReference(String uri, DigestMethod dm, | ||
| 74 | List appliedTransforms, Data result, List transforms, String type, | ||
| 75 | String id) { | ||
| 76 | if (appliedTransforms == null) { | ||
| 77 | throw new NullPointerException("appliedTransforms cannot be null"); | ||
| 78 | } | ||
| 79 | if (appliedTransforms.isEmpty()) { | ||
| 80 | throw new NullPointerException("appliedTransforms cannot be empty"); | ||
| 81 | } | ||
| 82 | if (result == null) { | ||
| 83 | throw new NullPointerException("result cannot be null"); | ||
| 84 | } | ||
| 85 | return new DOMReference | ||
| 86 | (uri, type, dm, appliedTransforms, result, transforms, id, getProvider()); | ||
| 87 | } | ||
| 88 | |||
| 89 | public Reference newReference(String uri, DigestMethod dm, List transforms, | ||
| 90 | String type, String id, byte[] digestValue) { | ||
| 91 | if (digestValue == null) { | ||
| 92 | throw new NullPointerException("digestValue cannot be null"); | ||
| 93 | } | ||
| 94 | return new DOMReference | ||
| 95 | (uri, type, dm, null, null, transforms, id, digestValue, getProvider()); | ||
| 96 | } | ||
| 97 | |||
| 98 | public SignedInfo newSignedInfo(CanonicalizationMethod cm, | ||
| 99 | SignatureMethod sm, List references) { | ||
| 100 | return newSignedInfo(cm, sm, references, null); | ||
| 101 | } | ||
| 102 | |||
| 103 | public SignedInfo newSignedInfo(CanonicalizationMethod cm, | ||
| 104 | SignatureMethod sm, List references, String id) { | ||
| 105 | return new DOMSignedInfo(cm, sm, references, id); | ||
| 106 | } | ||
| 107 | |||
| 108 | // Object factory methods | ||
| 109 | public XMLObject newXMLObject(List content, String id, String mimeType, | ||
| 110 | String encoding) { | ||
| 111 | return new DOMXMLObject(content, id, mimeType, encoding); | ||
| 112 | } | ||
| 113 | |||
| 114 | public Manifest newManifest(List references) { | ||
| 115 | return newManifest(references, null); | ||
| 116 | } | ||
| 117 | |||
| 118 | public Manifest newManifest(List references, String id) { | ||
| 119 | return new DOMManifest(references, id); | ||
| 120 | } | ||
| 121 | |||
| 122 | public SignatureProperties newSignatureProperties(List props, String id) { | ||
| 123 | return new DOMSignatureProperties(props, id); | ||
| 124 | } | ||
| 125 | |||
| 126 | public SignatureProperty newSignatureProperty | ||
| 127 | (List info, String target, String id) { | ||
| 128 | return new DOMSignatureProperty(info, target, id); | ||
| 129 | } | ||
| 130 | |||
| 131 | public XMLSignature unmarshalXMLSignature(XMLValidateContext context) | ||
| 132 | throws MarshalException { | ||
| 133 | |||
| 134 | if (context == null) { | ||
| 135 | throw new NullPointerException("context cannot be null"); | ||
| 136 | } | ||
| 137 | return unmarshal(((DOMValidateContext) context).getNode(), context); | ||
| 138 | } | ||
| 139 | |||
| 140 | public XMLSignature unmarshalXMLSignature(XMLStructure xmlStructure) | ||
| 141 | throws MarshalException { | ||
| 142 | |||
| 143 | if (xmlStructure == null) { | ||
| 144 | throw new NullPointerException("xmlStructure cannot be null"); | ||
| 145 | } | ||
| 146 | return unmarshal | ||
| 147 | (((javax.xml.crypto.dom.DOMStructure) xmlStructure).getNode(), | ||
| 148 | null); | ||
| 149 | } | ||
| 150 | |||
| 151 | private XMLSignature unmarshal(Node node, XMLValidateContext context) | ||
| 152 | throws MarshalException { | ||
| 153 | |||
| 154 | node.normalize(); | ||
| 155 | |||
| 156 | Element element = null; | ||
| 157 | if (node.getNodeType() == Node.DOCUMENT_NODE) { | ||
| 158 | element = ((Document) node).getDocumentElement(); | ||
| 159 | } else if (node.getNodeType() == Node.ELEMENT_NODE) { | ||
| 160 | element = (Element) node; | ||
| 161 | } else { | ||
| 162 | throw new MarshalException | ||
| 163 | ("Signature element is not a proper Node"); | ||
| 164 | } | ||
| 165 | |||
| 166 | // check tag | ||
| 167 | String tag = element.getLocalName(); | ||
| 168 | if (tag == null) { | ||
| 169 | throw new MarshalException("Document implementation must " + | ||
| 170 | "support DOM Level 2 and be namespace aware"); | ||
| 171 | } | ||
| 172 | if (tag.equals("Signature")) { | ||
| 173 | return new DOMXMLSignature(element, context, getProvider()); | ||
| 174 | } else { | ||
| 175 | throw new MarshalException("invalid Signature tag: " + tag); | ||
| 176 | } | ||
| 177 | } | ||
| 178 | |||
| 179 | public boolean isFeatureSupported(String feature) { | ||
| 180 | if (feature == null) { | ||
| 181 | throw new NullPointerException(); | ||
| 182 | } else { | ||
| 183 | return false; | ||
| 184 | } | ||
| 185 | } | ||
| 186 | |||
| 187 | public DigestMethod newDigestMethod(String algorithm, | ||
| 188 | DigestMethodParameterSpec params) throws NoSuchAlgorithmException, | ||
| 189 | InvalidAlgorithmParameterException { | ||
| 190 | if (algorithm == null) { | ||
| 191 | throw new NullPointerException(); | ||
| 192 | } | ||
| 193 | if (algorithm.equals(DigestMethod.SHA1)) { | ||
| 194 | return new DOMDigestMethod.SHA1(params); | ||
| 195 | } else if (algorithm.equals(DigestMethod.SHA256)) { | ||
| 196 | return new DOMDigestMethod.SHA256(params); | ||
| 197 | } else if (algorithm.equals(DOMDigestMethod.SHA384)) { | ||
| 198 | return new DOMDigestMethod.SHA384(params); | ||
| 199 | } else if (algorithm.equals(DigestMethod.SHA512)) { | ||
| 200 | return new DOMDigestMethod.SHA512(params); | ||
| 201 | } else { | ||
| 202 | throw new NoSuchAlgorithmException("unsupported algorithm"); | ||
| 203 | } | ||
| 204 | } | ||
| 205 | |||
| 206 | public SignatureMethod newSignatureMethod(String algorithm, | ||
| 207 | SignatureMethodParameterSpec params) throws NoSuchAlgorithmException, | ||
| 208 | InvalidAlgorithmParameterException { | ||
| 209 | if (algorithm == null) { | ||
| 210 | throw new NullPointerException(); | ||
| 211 | } | ||
| 212 | if (algorithm.equals(SignatureMethod.RSA_SHA1)) { | ||
| 213 | return new DOMSignatureMethod.SHA1withRSA(params); | ||
| 214 | } else if (algorithm.equals(DOMSignatureMethod.RSA_SHA256)) { | ||
| 215 | return new DOMSignatureMethod.SHA256withRSA(params); | ||
| 216 | } else if (algorithm.equals(DOMSignatureMethod.RSA_SHA384)) { | ||
| 217 | return new DOMSignatureMethod.SHA384withRSA(params); | ||
| 218 | } else if (algorithm.equals(DOMSignatureMethod.RSA_SHA512)) { | ||
| 219 | return new DOMSignatureMethod.SHA512withRSA(params); | ||
| 220 | } else if (algorithm.equals(SignatureMethod.DSA_SHA1)) { | ||
| 221 | return new DOMSignatureMethod.SHA1withDSA(params); | ||
| 222 | } else if (algorithm.equals(SignatureMethod.HMAC_SHA1)) { | ||
| 223 | return new DOMHMACSignatureMethod.SHA1(params); | ||
| 224 | } else if (algorithm.equals(DOMSignatureMethod.HMAC_SHA256)) { | ||
| 225 | return new DOMHMACSignatureMethod.SHA256(params); | ||
| 226 | } else if (algorithm.equals(DOMSignatureMethod.HMAC_SHA384)) { | ||
| 227 | return new DOMHMACSignatureMethod.SHA384(params); | ||
| 228 | } else if (algorithm.equals(DOMSignatureMethod.HMAC_SHA512)) { | ||
| 229 | return new DOMHMACSignatureMethod.SHA512(params); | ||
| 230 | } else { | ||
| 231 | throw new NoSuchAlgorithmException("unsupported algorithm"); | ||
| 232 | } | ||
| 233 | } | ||
| 234 | |||
| 235 | public Transform newTransform(String algorithm, | ||
| 236 | TransformParameterSpec params) throws NoSuchAlgorithmException, | ||
| 237 | InvalidAlgorithmParameterException { | ||
| 238 | TransformService spi; | ||
| 239 | try { | ||
| 240 | spi = TransformService.getInstance(algorithm, "DOM"); | ||
| 241 | } catch (NoSuchAlgorithmException nsae) { | ||
| 242 | spi = TransformService.getInstance(algorithm, "DOM", getProvider()); | ||
| 243 | } | ||
| 244 | spi.init(params); | ||
| 245 | return new DOMTransform(spi); | ||
| 246 | } | ||
| 247 | |||
| 248 | public Transform newTransform(String algorithm, | ||
| 249 | XMLStructure params) throws NoSuchAlgorithmException, | ||
| 250 | InvalidAlgorithmParameterException { | ||
| 251 | TransformService spi; | ||
| 252 | try { | ||
| 253 | spi = TransformService.getInstance(algorithm, "DOM"); | ||
| 254 | } catch (NoSuchAlgorithmException nsae) { | ||
| 255 | spi = TransformService.getInstance(algorithm, "DOM", getProvider()); | ||
| 256 | } | ||
| 257 | if (params == null) { | ||
| 258 | spi.init(null); | ||
| 259 | } else { | ||
| 260 | spi.init(params, null); | ||
| 261 | } | ||
| 262 | return new DOMTransform(spi); | ||
| 263 | } | ||
| 264 | |||
| 265 | public CanonicalizationMethod newCanonicalizationMethod(String algorithm, | ||
| 266 | C14NMethodParameterSpec params) throws NoSuchAlgorithmException, | ||
| 267 | InvalidAlgorithmParameterException { | ||
| 268 | TransformService spi; | ||
| 269 | try { | ||
| 270 | spi = TransformService.getInstance(algorithm, "DOM"); | ||
| 271 | } catch (NoSuchAlgorithmException nsae) { | ||
| 272 | spi = TransformService.getInstance(algorithm, "DOM", getProvider()); | ||
| 273 | } | ||
| 274 | spi.init(params); | ||
| 275 | return new DOMCanonicalizationMethod(spi); | ||
| 276 | } | ||
| 277 | |||
| 278 | public CanonicalizationMethod newCanonicalizationMethod(String algorithm, | ||
| 279 | XMLStructure params) throws NoSuchAlgorithmException, | ||
| 280 | InvalidAlgorithmParameterException { | ||
| 281 | TransformService spi; | ||
| 282 | try { | ||
| 283 | spi = TransformService.getInstance(algorithm, "DOM"); | ||
| 284 | } catch (NoSuchAlgorithmException nsae) { | ||
| 285 | spi = TransformService.getInstance(algorithm, "DOM", getProvider()); | ||
| 286 | } | ||
| 287 | if (params == null) { | ||
| 288 | spi.init(null); | ||
| 289 | } else { | ||
| 290 | spi.init(params, null); | ||
| 291 | } | ||
| 292 | return new DOMCanonicalizationMethod(spi); | ||
| 293 | } | ||
| 294 | |||
| 295 | public URIDereferencer getURIDereferencer() { | ||
| 296 | return DOMURIDereferencer.INSTANCE; | ||
| 297 | } | ||
| 298 | } | ||
Binary file not shown.
| @@ -0,0 +1,155 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * =========================================================================== | ||
| 23 | * | ||
| 24 | * (C) Copyright IBM Corp. 2003 All Rights Reserved. | ||
| 25 | * | ||
| 26 | * =========================================================================== | ||
| 27 | */ | ||
| 28 | /* | ||
| 29 | * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. | ||
| 30 | */ | ||
| 31 | /* | ||
| 32 | * $Id: DOMXPathFilter2Transform.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 33 | */ | ||
| 34 | package org.jcp.xml.dsig.internal.dom; | ||
| 35 | |||
| 36 | import javax.xml.crypto.*; | ||
| 37 | import javax.xml.crypto.dsig.*; | ||
| 38 | import javax.xml.crypto.dsig.spec.TransformParameterSpec; | ||
| 39 | import javax.xml.crypto.dsig.spec.XPathType; | ||
| 40 | import javax.xml.crypto.dsig.spec.XPathFilter2ParameterSpec; | ||
| 41 | import java.security.InvalidAlgorithmParameterException; | ||
| 42 | import java.util.ArrayList; | ||
| 43 | import java.util.Iterator; | ||
| 44 | import java.util.List; | ||
| 45 | import java.util.Map; | ||
| 46 | import java.util.HashMap; | ||
| 47 | import org.w3c.dom.Attr; | ||
| 48 | import org.w3c.dom.Element; | ||
| 49 | import org.w3c.dom.NamedNodeMap; | ||
| 50 | |||
| 51 | /** | ||
| 52 | * DOM-based implementation of XPath Filter 2.0 Transform. | ||
| 53 | * (Uses Apache XML-Sec Transform implementation) | ||
| 54 | * | ||
| 55 | * @author Joyce Leung | ||
| 56 | */ | ||
| 57 | public final class DOMXPathFilter2Transform extends ApacheTransform { | ||
| 58 | |||
| 59 | public void init(TransformParameterSpec params) | ||
| 60 | throws InvalidAlgorithmParameterException { | ||
| 61 | if (params == null) { | ||
| 62 | throw new InvalidAlgorithmParameterException("params are required"); | ||
| 63 | } else if (!(params instanceof XPathFilter2ParameterSpec)) { | ||
| 64 | throw new InvalidAlgorithmParameterException | ||
| 65 | ("params must be of type XPathFilter2ParameterSpec"); | ||
| 66 | } | ||
| 67 | this.params = params; | ||
| 68 | } | ||
| 69 | |||
| 70 | public void init(XMLStructure parent, XMLCryptoContext context) | ||
| 71 | throws InvalidAlgorithmParameterException { | ||
| 72 | |||
| 73 | super.init(parent, context); | ||
| 74 | try { | ||
| 75 | unmarshalParams(DOMUtils.getFirstChildElement(transformElem)); | ||
| 76 | } catch (MarshalException me) { | ||
| 77 | throw (InvalidAlgorithmParameterException) | ||
| 78 | new InvalidAlgorithmParameterException().initCause(me); | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | private void unmarshalParams(Element curXPathElem) throws MarshalException { | ||
| 83 | List list = new ArrayList(); | ||
| 84 | while (curXPathElem != null) { | ||
| 85 | String xPath = curXPathElem.getFirstChild().getNodeValue(); | ||
| 86 | String filterVal = | ||
| 87 | DOMUtils.getAttributeValue(curXPathElem, "Filter"); | ||
| 88 | if (filterVal == null) { | ||
| 89 | throw new MarshalException("filter cannot be null"); | ||
| 90 | } | ||
| 91 | XPathType.Filter filter = null; | ||
| 92 | if (filterVal.equals("intersect")) { | ||
| 93 | filter = XPathType.Filter.INTERSECT; | ||
| 94 | } else if (filterVal.equals("subtract")) { | ||
| 95 | filter = XPathType.Filter.SUBTRACT; | ||
| 96 | } else if (filterVal.equals("union")) { | ||
| 97 | filter = XPathType.Filter.UNION; | ||
| 98 | } else { | ||
| 99 | throw new MarshalException("Unknown XPathType filter type" | ||
| 100 | + filterVal); | ||
| 101 | } | ||
| 102 | NamedNodeMap attributes = curXPathElem.getAttributes(); | ||
| 103 | if (attributes != null) { | ||
| 104 | int length = attributes.getLength(); | ||
| 105 | Map namespaceMap = new HashMap(length); | ||
| 106 | for (int i = 0; i < length; i++) { | ||
| 107 | Attr attr = (Attr) attributes.item(i); | ||
| 108 | String prefix = attr.getPrefix(); | ||
| 109 | if (prefix != null && prefix.equals("xmlns")) { | ||
| 110 | namespaceMap.put(attr.getLocalName(), attr.getValue()); | ||
| 111 | } | ||
| 112 | } | ||
| 113 | list.add(new XPathType(xPath, filter, namespaceMap)); | ||
| 114 | } else { | ||
| 115 | list.add(new XPathType(xPath, filter)); | ||
| 116 | } | ||
| 117 | |||
| 118 | curXPathElem = DOMUtils.getNextSiblingElement(curXPathElem); | ||
| 119 | } | ||
| 120 | this.params = new XPathFilter2ParameterSpec(list); | ||
| 121 | } | ||
| 122 | |||
| 123 | public void marshalParams(XMLStructure parent, XMLCryptoContext context) | ||
| 124 | throws MarshalException { | ||
| 125 | |||
| 126 | super.marshalParams(parent, context); | ||
| 127 | XPathFilter2ParameterSpec xp = | ||
| 128 | (XPathFilter2ParameterSpec) getParameterSpec(); | ||
| 129 | String prefix = DOMUtils.getNSPrefix(context, Transform.XPATH2); | ||
| 130 | String qname = (prefix == null || prefix.length() == 0) | ||
| 131 | ? "xmlns" : "xmlns:" + prefix; | ||
| 132 | List list = xp.getXPathList(); | ||
| 133 | for (int i = 0, size = list.size(); i < size; i++) { | ||
| 134 | XPathType xpathType = (XPathType) list.get(i); | ||
| 135 | Element elem = DOMUtils.createElement | ||
| 136 | (ownerDoc, "XPath", Transform.XPATH2, prefix); | ||
| 137 | elem.appendChild | ||
| 138 | (ownerDoc.createTextNode(xpathType.getExpression())); | ||
| 139 | DOMUtils.setAttribute | ||
| 140 | (elem, "Filter", xpathType.getFilter().toString()); | ||
| 141 | elem.setAttributeNS("http://www.w3.org/2000/xmlns/", qname, | ||
| 142 | Transform.XPATH2); | ||
| 143 | |||
| 144 | // add namespace attributes, if necessary | ||
| 145 | Iterator it = xpathType.getNamespaceMap().entrySet().iterator(); | ||
| 146 | while (it.hasNext()) { | ||
| 147 | Map.Entry entry = (Map.Entry) it.next(); | ||
| 148 | elem.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:" | ||
| 149 | + (String) entry.getKey(), (String) entry.getValue()); | ||
| 150 | } | ||
| 151 | |||
| 152 | transformElem.appendChild(elem); | ||
| 153 | } | ||
| 154 | } | ||
| 155 | } | ||
Binary file not shown.
| @@ -0,0 +1,108 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DOMXPathTransform.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import javax.xml.crypto.*; | ||
| 30 | import javax.xml.crypto.dsig.*; | ||
| 31 | import javax.xml.crypto.dsig.spec.TransformParameterSpec; | ||
| 32 | import javax.xml.crypto.dsig.spec.XPathFilterParameterSpec; | ||
| 33 | import java.security.InvalidAlgorithmParameterException; | ||
| 34 | import java.util.Iterator; | ||
| 35 | import java.util.Map; | ||
| 36 | import java.util.HashMap; | ||
| 37 | import org.w3c.dom.Attr; | ||
| 38 | import org.w3c.dom.Element; | ||
| 39 | import org.w3c.dom.NamedNodeMap; | ||
| 40 | |||
| 41 | /** | ||
| 42 | * DOM-based implementation of XPath Filtering Transform. | ||
| 43 | * (Uses Apache XML-Sec Transform implementation) | ||
| 44 | * | ||
| 45 | * @author Sean Mullan | ||
| 46 | */ | ||
| 47 | public final class DOMXPathTransform extends ApacheTransform { | ||
| 48 | |||
| 49 | public void init(TransformParameterSpec params) | ||
| 50 | throws InvalidAlgorithmParameterException { | ||
| 51 | if (params == null) { | ||
| 52 | throw new InvalidAlgorithmParameterException("params are required"); | ||
| 53 | } else if (!(params instanceof XPathFilterParameterSpec)) { | ||
| 54 | throw new InvalidAlgorithmParameterException | ||
| 55 | ("params must be of type XPathFilterParameterSpec"); | ||
| 56 | } | ||
| 57 | this.params = params; | ||
| 58 | } | ||
| 59 | |||
| 60 | public void init(XMLStructure parent, XMLCryptoContext context) | ||
| 61 | throws InvalidAlgorithmParameterException { | ||
| 62 | |||
| 63 | super.init(parent, context); | ||
| 64 | unmarshalParams(DOMUtils.getFirstChildElement(transformElem)); | ||
| 65 | } | ||
| 66 | |||
| 67 | private void unmarshalParams(Element paramsElem) { | ||
| 68 | String xPath = paramsElem.getFirstChild().getNodeValue(); | ||
| 69 | // create a Map of namespace prefixes | ||
| 70 | NamedNodeMap attributes = paramsElem.getAttributes(); | ||
| 71 | if (attributes != null) { | ||
| 72 | int length = attributes.getLength(); | ||
| 73 | Map namespaceMap = new HashMap(length); | ||
| 74 | for (int i = 0; i < length; i++) { | ||
| 75 | Attr attr = (Attr) attributes.item(i); | ||
| 76 | String prefix = attr.getPrefix(); | ||
| 77 | if (prefix != null && prefix.equals("xmlns")) { | ||
| 78 | namespaceMap.put(attr.getLocalName(), attr.getValue()); | ||
| 79 | } | ||
| 80 | } | ||
| 81 | this.params = new XPathFilterParameterSpec(xPath, namespaceMap); | ||
| 82 | } else { | ||
| 83 | this.params = new XPathFilterParameterSpec(xPath); | ||
| 84 | } | ||
| 85 | } | ||
| 86 | |||
| 87 | public void marshalParams(XMLStructure parent, XMLCryptoContext context) | ||
| 88 | throws MarshalException { | ||
| 89 | |||
| 90 | super.marshalParams(parent, context); | ||
| 91 | XPathFilterParameterSpec xp = | ||
| 92 | (XPathFilterParameterSpec) getParameterSpec(); | ||
| 93 | Element xpathElem = DOMUtils.createElement | ||
| 94 | (ownerDoc, "XPath", XMLSignature.XMLNS, | ||
| 95 | DOMUtils.getSignaturePrefix(context)); | ||
| 96 | xpathElem.appendChild(ownerDoc.createTextNode(xp.getXPath())); | ||
| 97 | |||
| 98 | // add namespace attributes, if necessary | ||
| 99 | Iterator i = xp.getNamespaceMap().entrySet().iterator(); | ||
| 100 | while (i.hasNext()) { | ||
| 101 | Map.Entry entry = (Map.Entry) i.next(); | ||
| 102 | xpathElem.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:" | ||
| 103 | + (String) entry.getKey(), (String) entry.getValue()); | ||
| 104 | } | ||
| 105 | |||
| 106 | transformElem.appendChild(xpathElem); | ||
| 107 | } | ||
| 108 | } | ||
Binary file not shown.
| @@ -0,0 +1,78 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: DOMXSLTTransform.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import java.security.InvalidAlgorithmParameterException; | ||
| 30 | import org.w3c.dom.Element; | ||
| 31 | import org.w3c.dom.Node; | ||
| 32 | |||
| 33 | import javax.xml.crypto.*; | ||
| 34 | import javax.xml.crypto.dsig.*; | ||
| 35 | import javax.xml.crypto.dsig.spec.TransformParameterSpec; | ||
| 36 | import javax.xml.crypto.dsig.spec.XSLTTransformParameterSpec; | ||
| 37 | |||
| 38 | /** | ||
| 39 | * DOM-based implementation of XSLT Transform. | ||
| 40 | * (Uses Apache XML-Sec Transform implementation) | ||
| 41 | * | ||
| 42 | * @author Sean Mullan | ||
| 43 | */ | ||
| 44 | public final class DOMXSLTTransform extends ApacheTransform { | ||
| 45 | |||
| 46 | public void init(TransformParameterSpec params) | ||
| 47 | throws InvalidAlgorithmParameterException { | ||
| 48 | if (params == null) { | ||
| 49 | throw new InvalidAlgorithmParameterException("params are required"); | ||
| 50 | } | ||
| 51 | if (!(params instanceof XSLTTransformParameterSpec)) { | ||
| 52 | throw new InvalidAlgorithmParameterException("unrecognized params"); | ||
| 53 | } | ||
| 54 | this.params = params; | ||
| 55 | } | ||
| 56 | |||
| 57 | public void init(XMLStructure parent, XMLCryptoContext context) | ||
| 58 | throws InvalidAlgorithmParameterException { | ||
| 59 | |||
| 60 | super.init(parent, context); | ||
| 61 | unmarshalParams(DOMUtils.getFirstChildElement(transformElem)); | ||
| 62 | } | ||
| 63 | |||
| 64 | private void unmarshalParams(Element sheet) { | ||
| 65 | this.params = new XSLTTransformParameterSpec | ||
| 66 | (new javax.xml.crypto.dom.DOMStructure(sheet)); | ||
| 67 | } | ||
| 68 | |||
| 69 | public void marshalParams(XMLStructure parent, XMLCryptoContext context) | ||
| 70 | throws MarshalException { | ||
| 71 | super.marshalParams(parent, context); | ||
| 72 | XSLTTransformParameterSpec xp = | ||
| 73 | (XSLTTransformParameterSpec) getParameterSpec(); | ||
| 74 | Node xsltElem = | ||
| 75 | ((javax.xml.crypto.dom.DOMStructure) xp.getStylesheet()).getNode(); | ||
| 76 | DOMUtils.appendChild(transformElem, xsltElem); | ||
| 77 | } | ||
| 78 | } | ||
Binary file not shown.
| @@ -0,0 +1,107 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. | ||
| 23 | */ | ||
| 24 | /* | ||
| 25 | * $Id: Utils.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 26 | */ | ||
| 27 | package org.jcp.xml.dsig.internal.dom; | ||
| 28 | |||
| 29 | import java.io.ByteArrayOutputStream; | ||
| 30 | import java.io.InputStream; | ||
| 31 | import java.io.IOException; | ||
| 32 | import java.util.*; | ||
| 33 | import org.w3c.dom.NamedNodeMap; | ||
| 34 | import org.w3c.dom.Node; | ||
| 35 | |||
| 36 | /** | ||
| 37 | * Miscellaneous static utility methods for use in JSR 105 RI. | ||
| 38 | * | ||
| 39 | * @author Sean Mullan | ||
| 40 | */ | ||
| 41 | public final class Utils { | ||
| 42 | |||
| 43 | private Utils() {} | ||
| 44 | |||
| 45 | public static byte[] readBytesFromStream(InputStream is) | ||
| 46 | throws IOException { | ||
| 47 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); | ||
| 48 | byte[] buf = new byte[1024]; | ||
| 49 | while (true) { | ||
| 50 | int read = is.read(buf); | ||
| 51 | if (read == -1) { // EOF | ||
| 52 | break; | ||
| 53 | } | ||
| 54 | baos.write(buf, 0, read); | ||
| 55 | if (read < 1024) { | ||
| 56 | break; | ||
| 57 | } | ||
| 58 | } | ||
| 59 | return baos.toByteArray(); | ||
| 60 | } | ||
| 61 | |||
| 62 | /** | ||
| 63 | * Converts an Iterator to a Set of Nodes, according to the XPath | ||
| 64 | * Data Model. | ||
| 65 | * | ||
| 66 | * @param i the Iterator | ||
| 67 | * @return the Set of Nodes | ||
| 68 | */ | ||
| 69 | static Set toNodeSet(Iterator i) { | ||
| 70 | Set nodeSet = new HashSet(); | ||
| 71 | while (i.hasNext()) { | ||
| 72 | Node n = (Node) i.next(); | ||
| 73 | nodeSet.add(n); | ||
| 74 | // insert attributes nodes to comply with XPath | ||
| 75 | if (n.getNodeType() == Node.ELEMENT_NODE) { | ||
| 76 | NamedNodeMap nnm = n.getAttributes(); | ||
| 77 | for (int j = 0, length = nnm.getLength(); j < length; j++) { | ||
| 78 | nodeSet.add(nnm.item(j)); | ||
| 79 | } | ||
| 80 | } | ||
| 81 | } | ||
| 82 | return nodeSet; | ||
| 83 | } | ||
| 84 | |||
| 85 | /** | ||
| 86 | * Returns the ID from a same-document URI (ex: "#id") | ||
| 87 | */ | ||
| 88 | public static String parseIdFromSameDocumentURI(String uri) { | ||
| 89 | if (uri.length() == 0) { | ||
| 90 | return null; | ||
| 91 | } | ||
| 92 | String id = uri.substring(1); | ||
| 93 | if (id != null && id.startsWith("xpointer(id(")) { | ||
| 94 | int i1 = id.indexOf('\''); | ||
| 95 | int i2 = id.indexOf('\'', i1+1); | ||
| 96 | id = id.substring(i1+1, i2); | ||
| 97 | } | ||
| 98 | return id; | ||
| 99 | } | ||
| 100 | |||
| 101 | /** | ||
| 102 | * Returns true if uri is a same-document URI, false otherwise. | ||
| 103 | */ | ||
| 104 | public static boolean sameDocumentURI(String uri) { | ||
| 105 | return (uri != null && (uri.length() == 0 || uri.charAt(0) == '#')); | ||
| 106 | } | ||
| 107 | } | ||
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,163 @@ | |||
| 1 | /* | ||
| 2 | * reserved comment block | ||
| 3 | * DO NOT REMOVE OR ALTER! | ||
| 4 | */ | ||
| 5 | /* | ||
| 6 | * Copyright 2005 The Apache Software Foundation. | ||
| 7 | * | ||
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | * you may not use this file except in compliance with the License. | ||
| 10 | * You may obtain a copy of the License at | ||
| 11 | * | ||
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | * | ||
| 14 | * Unless required by applicable law or agreed to in writing, software | ||
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | * See the License for the specific language governing permissions and | ||
| 18 | * limitations under the License. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * =========================================================================== | ||
| 23 | * | ||
| 24 | * (C) Copyright IBM Corp. 2003 All Rights Reserved. | ||
| 25 | * | ||
| 26 | * =========================================================================== | ||
| 27 | */ | ||
| 28 | /* | ||
| 29 | * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. | ||
| 30 | */ | ||
| 31 | /* | ||
| 32 | * $Id: XMLDSigRI.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ | ||
| 33 | */ | ||
| 34 | package org.jcp.xml.dsig.internal.dom; | ||
| 35 | |||
| 36 | import java.util.*; | ||
| 37 | import java.security.*; | ||
| 38 | |||
| 39 | import javax.xml.crypto.dsig.*; | ||
| 40 | |||
| 41 | /** | ||
| 42 | * The XMLDSig RI Provider. | ||
| 43 | * | ||
| 44 | * @author Joyce Leung | ||
| 45 | */ | ||
| 46 | |||
| 47 | /** | ||
| 48 | * Defines the XMLDSigRI provider. | ||
| 49 | */ | ||
| 50 | |||
| 51 | public final class XMLDSigRI extends Provider { | ||
| 52 | |||
| 53 | static final long serialVersionUID = -5049765099299494554L; | ||
| 54 | |||
| 55 | private static final String INFO = "XMLDSig " + | ||
| 56 | "(DOM XMLSignatureFactory; DOM KeyInfoFactory)"; | ||
| 57 | |||
| 58 | public XMLDSigRI() { | ||
| 59 | /* We are the XMLDSig provider */ | ||
| 60 | super("XMLDSig", 1.0, INFO); | ||
| 61 | |||
| 62 | final Map map = new HashMap(); | ||
| 63 | map.put("XMLSignatureFactory.DOM", | ||
| 64 | "org.jcp.xml.dsig.internal.dom.DOMXMLSignatureFactory"); | ||
| 65 | map.put("KeyInfoFactory.DOM", | ||
| 66 | "org.jcp.xml.dsig.internal.dom.DOMKeyInfoFactory"); | ||
| 67 | |||
| 68 | |||
| 69 | // Inclusive C14N | ||
| 70 | map.put((String)"TransformService." + CanonicalizationMethod.INCLUSIVE, | ||
| 71 | "org.jcp.xml.dsig.internal.dom.DOMCanonicalXMLC14NMethod"); | ||
| 72 | map.put("Alg.Alias.TransformService.INCLUSIVE", | ||
| 73 | CanonicalizationMethod.INCLUSIVE); | ||
| 74 | map.put((String)"TransformService." + CanonicalizationMethod.INCLUSIVE + | ||
| 75 | " MechanismType", "DOM"); | ||
| 76 | |||
| 77 | // InclusiveWithComments C14N | ||
| 78 | map.put((String) "TransformService." + | ||
| 79 | CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS, | ||
| 80 | "org.jcp.xml.dsig.internal.dom.DOMCanonicalXMLC14NMethod"); | ||
| 81 | map.put("Alg.Alias.TransformService.INCLUSIVE_WITH_COMMENTS", | ||
| 82 | CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS); | ||
| 83 | map.put((String) "TransformService." + | ||
| 84 | CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS + | ||
| 85 | " MechanismType", "DOM"); | ||
| 86 | |||
| 87 | // Inclusive C14N 1.1 | ||
| 88 | map.put((String)"TransformService." + | ||
| 89 | "http://www.w3.org/2006/12/xml-c14n11", | ||
| 90 | "org.jcp.xml.dsig.internal.dom.DOMCanonicalXMLC14N11Method"); | ||
| 91 | map.put((String)"TransformService." + | ||
| 92 | "http://www.w3.org/2006/12/xml-c14n11" + | ||
| 93 | " MechanismType", "DOM"); | ||
| 94 | |||
| 95 | // InclusiveWithComments C14N 1.1 | ||
| 96 | map.put((String)"TransformService." + | ||
| 97 | "http://www.w3.org/2006/12/xml-c14n11#WithComments", | ||
| 98 | "org.jcp.xml.dsig.internal.dom.DOMCanonicalXMLC14N11Method"); | ||
| 99 | map.put((String)"TransformService." + | ||
| 100 | "http://www.w3.org/2006/12/xml-c14n11#WithComments" + | ||
| 101 | " MechanismType", "DOM"); | ||
| 102 | |||
| 103 | // Exclusive C14N | ||
| 104 | map.put((String) "TransformService." + CanonicalizationMethod.EXCLUSIVE, | ||
| 105 | "org.jcp.xml.dsig.internal.dom.DOMExcC14NMethod"); | ||
| 106 | map.put("Alg.Alias.TransformService.EXCLUSIVE", | ||
| 107 | CanonicalizationMethod.EXCLUSIVE); | ||
| 108 | map.put((String)"TransformService." + CanonicalizationMethod.EXCLUSIVE + | ||
| 109 | " MechanismType", "DOM"); | ||
| 110 | |||
| 111 | // ExclusiveWithComments C14N | ||
| 112 | map.put((String) "TransformService." + | ||
| 113 | CanonicalizationMethod.EXCLUSIVE_WITH_COMMENTS, | ||
| 114 | "org.jcp.xml.dsig.internal.dom.DOMExcC14NMethod"); | ||
| 115 | map.put("Alg.Alias.TransformService.EXCLUSIVE_WITH_COMMENTS", | ||
| 116 | CanonicalizationMethod.EXCLUSIVE_WITH_COMMENTS); | ||
| 117 | map.put((String) "TransformService." + | ||
| 118 | CanonicalizationMethod.EXCLUSIVE_WITH_COMMENTS + | ||
| 119 | " MechanismType", "DOM"); | ||
| 120 | |||
| 121 | // Base64 Transform | ||
| 122 | map.put((String) "TransformService." + Transform.BASE64, | ||
| 123 | "org.jcp.xml.dsig.internal.dom.DOMBase64Transform"); | ||
| 124 | map.put("Alg.Alias.TransformService.BASE64", Transform.BASE64); | ||
| 125 | map.put((String) "TransformService." + Transform.BASE64 + | ||
| 126 | " MechanismType", "DOM"); | ||
| 127 | |||
| 128 | // Enveloped Transform | ||
| 129 | map.put((String) "TransformService." + Transform.ENVELOPED, | ||
| 130 | "org.jcp.xml.dsig.internal.dom.DOMEnvelopedTransform"); | ||
| 131 | map.put("Alg.Alias.TransformService.ENVELOPED", Transform.ENVELOPED); | ||
| 132 | map.put((String) "TransformService." + Transform.ENVELOPED + | ||
| 133 | " MechanismType", "DOM"); | ||
| 134 | |||
| 135 | // XPath2 Transform | ||
| 136 | map.put((String) "TransformService." + Transform.XPATH2, | ||
| 137 | "org.jcp.xml.dsig.internal.dom.DOMXPathFilter2Transform"); | ||
| 138 | map.put("Alg.Alias.TransformService.XPATH2", Transform.XPATH2); | ||
| 139 | map.put((String) "TransformService." + Transform.XPATH2 + | ||
| 140 | " MechanismType", "DOM"); | ||
| 141 | |||
| 142 | // XPath Transform | ||
| 143 | map.put((String) "TransformService." + Transform.XPATH, | ||
| 144 | "org.jcp.xml.dsig.internal.dom.DOMXPathTransform"); | ||
| 145 | map.put("Alg.Alias.TransformService.XPATH", Transform.XPATH); | ||
| 146 | map.put((String) "TransformService." + Transform.XPATH + | ||
| 147 | " MechanismType", "DOM"); | ||
| 148 | |||
| 149 | // XSLT Transform | ||
| 150 | map.put((String) "TransformService." + Transform.XSLT, | ||
| 151 | "org.jcp.xml.dsig.internal.dom.DOMXSLTTransform"); | ||
| 152 | map.put("Alg.Alias.TransformService.XSLT", Transform.XSLT); | ||
| 153 | map.put((String) "TransformService." + Transform.XSLT + | ||
| 154 | " MechanismType", "DOM"); | ||
| 155 | |||
| 156 | AccessController.doPrivileged(new java.security.PrivilegedAction() { | ||
| 157 | public Object run() { | ||
| 158 | putAll(map); | ||
| 159 | return null; | ||
| 160 | } | ||
| 161 | }); | ||
| 162 | } | ||
| 163 | } | ||
| @@ -0,0 +1,48 @@ | |||
| 1 | <../../../../../../../../mkconfig | ||
| 2 | |||
| 3 | TARG=\ | ||
| 4 | ApacheCanonicalizer.dis\ | ||
| 5 | ApacheData.dis\ | ||
| 6 | ApacheNodeSetData.dis\ | ||
| 7 | ApacheOctetStreamData.dis\ | ||
| 8 | ApacheTransform.dis\ | ||
| 9 | DOMBase64Transform.dis\ | ||
| 10 | DOMCanonicalizationMethod.dis\ | ||
| 11 | DOMCanonicalXMLC14N11Method.dis\ | ||
| 12 | DOMCanonicalXMLC14NMethod.dis\ | ||
| 13 | DOMCryptoBinary.dis\ | ||
| 14 | DOMDigestMethod.dis\ | ||
| 15 | DOMEnvelopedTransform.dis\ | ||
| 16 | DOMExcC14NMethod.dis\ | ||
| 17 | DOMHMACSignatureMethod.dis\ | ||
| 18 | DOMKeyInfo.dis\ | ||
| 19 | DOMKeyInfoFactory.dis\ | ||
| 20 | DOMKeyName.dis\ | ||
| 21 | DOMKeyValue.dis\ | ||
| 22 | DOMManifest.dis\ | ||
| 23 | DOMPGPData.dis\ | ||
| 24 | DOMReference.dis\ | ||
| 25 | DOMRetrievalMethod.dis\ | ||
| 26 | DOMSignatureMethod.dis\ | ||
| 27 | DOMSignatureProperties.dis\ | ||
| 28 | DOMSignatureProperty.dis\ | ||
| 29 | DOMSignedInfo.dis\ | ||
| 30 | DOMStructure.dis\ | ||
| 31 | DOMSubTreeData.dis\ | ||
| 32 | DOMTransform.dis\ | ||
| 33 | DOMURIDereferencer.dis\ | ||
| 34 | DOMUtils.dis\ | ||
| 35 | DOMX509Data.dis\ | ||
| 36 | DOMX509IssuerSerial.dis\ | ||
| 37 | DOMXMLObject.dis\ | ||
| 38 | DOMXMLSignature.dis\ | ||
| 39 | DOMXMLSignatureFactory.dis\ | ||
| 40 | DOMXPathFilter2Transform.dis\ | ||
| 41 | DOMXPathTransform.dis\ | ||
| 42 | DOMXSLTTransform.dis\ | ||
| 43 | Utils.dis\ | ||
| 44 | XMLDSigRI.dis\ | ||
| 45 | |||
| 46 | DISBIN=$ROOT/java/dis/java/java/org/jcp/xml/dsig/internal/dom | ||
| 47 | |||
| 48 | <$ROOT/mkfiles/mkjava | ||
| @@ -0,0 +1,14 @@ | |||
| 1 | <../../../../../../../mkconfig | ||
| 2 | |||
| 3 | DIRS=\ | ||
| 4 | dom\ | ||
| 5 | |||
| 6 | TARG=\ | ||
| 7 | DigesterOutputStream.dis\ | ||
| 8 | MacOutputStream.dis\ | ||
| 9 | SignerOutputStream.dis\ | ||
| 10 | |||
| 11 | DISBIN=$ROOT/java/dis/java/java/org/jcp/xml/dsig/internal | ||
| 12 | |||
| 13 | <$ROOT/mkfiles/mkjava | ||
| 14 | <$ROOT/mkfiles/mksubdirs | ||
| @@ -0,0 +1,6 @@ | |||
| 1 | <../../../../../../mkconfig | ||
| 2 | |||
| 3 | DIRS=\ | ||
| 4 | internal\ | ||
| 5 | |||
| 6 | <$ROOT/mkfiles/mksubdirs | ||
| @@ -0,0 +1,6 @@ | |||
| 1 | <../../../../../mkconfig | ||
| 2 | |||
| 3 | DIRS=\ | ||
| 4 | dsig\ | ||
| 5 | |||
| 6 | <$ROOT/mkfiles/mksubdirs | ||
| @@ -0,0 +1,7 @@ | |||
| 1 | <../../../mkconfig | ||
| 2 | |||
| 3 | DIRS=\ | ||
| 4 | ietf\ | ||
| 5 | jcp\ | ||
| 6 | |||
| 7 | <$ROOT/mkfiles/mksubdirs | ||