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 | |