001: /*
002: * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.security.jgss.wrapper;
027:
028: import org.ietf.jgss.*;
029: import java.security.Provider;
030: import java.security.Security;
031: import java.io.IOException;
032: import java.io.UnsupportedEncodingException;
033: import sun.security.jgss.GSSUtil;
034: import sun.security.util.ObjectIdentifier;
035: import sun.security.util.DerInputStream;
036: import sun.security.util.DerOutputStream;
037: import sun.security.jgss.GSSUtil;
038: import sun.security.jgss.GSSExceptionImpl;
039: import sun.security.jgss.spi.GSSNameSpi;
040:
041: /**
042: * This class is essentially a wrapper class for the gss_name_t
043: * structure of the native GSS library.
044: * @author Valerie Peng
045: * @version 1.16, 05/05/07
046: * @since 1.6
047: */
048:
049: public class GSSNameElement implements GSSNameSpi {
050:
051: long pName = 0; // Pointer to the gss_name_t structure
052: private String printableName;
053: private Oid printableType;
054: private GSSLibStub cStub;
055:
056: static final GSSNameElement DEF_ACCEPTOR = new GSSNameElement();
057:
058: private static Oid getNativeNameType(Oid nameType, GSSLibStub stub) {
059: if (GSSUtil.NT_GSS_KRB5_PRINCIPAL.equals(nameType)
060: || GSSName.NT_HOSTBASED_SERVICE.equals(nameType)) {
061: Oid[] supportedNTs = null;
062: try {
063: supportedNTs = stub.inquireNamesForMech();
064: } catch (GSSException ge) {
065: if (ge.getMajor() == GSSException.BAD_MECH
066: && GSSUtil.isSpNegoMech(stub.getMech())) {
067: // Workaround known Heimdal issue and retry with KRB5
068: try {
069: stub = GSSLibStub
070: .getInstance(GSSUtil.GSS_KRB5_MECH_OID);
071: supportedNTs = stub.inquireNamesForMech();
072: } catch (GSSException ge2) {
073: // Should never happen
074: SunNativeProvider
075: .debug("Name type list unavailable: "
076: + ge2.getMajorString());
077: }
078: } else {
079: SunNativeProvider
080: .debug("Name type list unavailable: "
081: + ge.getMajorString());
082: }
083: }
084: if (supportedNTs != null) {
085: for (int i = 0; i < supportedNTs.length; i++) {
086: if (supportedNTs[i].equals(nameType))
087: return nameType;
088: }
089: // Special handling the specified name type
090: if (GSSUtil.NT_GSS_KRB5_PRINCIPAL.equals(nameType)) {
091: SunNativeProvider.debug("Override " + nameType
092: + " with mechanism default(null)");
093: return null; // Use mechanism specific default
094: } else {
095: SunNativeProvider.debug("Override " + nameType
096: + " with " + GSSUtil.NT_HOSTBASED_SERVICE2);
097: return GSSUtil.NT_HOSTBASED_SERVICE2;
098: }
099: }
100: }
101: return nameType;
102: }
103:
104: private GSSNameElement() {
105: printableName = "<DEFAULT ACCEPTOR>";
106: }
107:
108: GSSNameElement(long pNativeName, GSSLibStub stub)
109: throws GSSException {
110: assert (stub != null);
111: if (pNativeName == 0) {
112: throw new GSSException(GSSException.BAD_NAME);
113: }
114: // Note: pNativeName is assumed to be a MN.
115: pName = pNativeName;
116: cStub = stub;
117: setPrintables();
118: }
119:
120: GSSNameElement(byte[] nameBytes, Oid nameType, GSSLibStub stub)
121: throws GSSException {
122: assert (stub != null);
123: if (nameBytes == null) {
124: throw new GSSException(GSSException.BAD_NAME);
125: }
126: cStub = stub;
127: byte[] name = nameBytes;
128:
129: if (nameType != null) {
130: // Special handling the specified name type if
131: // necessary
132: nameType = getNativeNameType(nameType, stub);
133:
134: if (GSSName.NT_EXPORT_NAME.equals(nameType)) {
135: // Need to add back the mech Oid portion (stripped
136: // off by GSSNameImpl class prior to calling this
137: // method) for "NT_EXPORT_NAME"
138: byte[] mechBytes = null;
139: DerOutputStream dout = new DerOutputStream();
140: Oid mech = cStub.getMech();
141: try {
142: dout.putOID(new ObjectIdentifier(mech.toString()));
143: } catch (IOException e) {
144: throw new GSSExceptionImpl(GSSException.FAILURE, e);
145: }
146: mechBytes = dout.toByteArray();
147: name = new byte[2 + 2 + mechBytes.length + 4
148: + nameBytes.length];
149: int pos = 0;
150: name[pos++] = 0x04;
151: name[pos++] = 0x01;
152: name[pos++] = (byte) (mechBytes.length >>> 8);
153: name[pos++] = (byte) mechBytes.length;
154: System.arraycopy(mechBytes, 0, name, pos,
155: mechBytes.length);
156: pos += mechBytes.length;
157: name[pos++] = (byte) (nameBytes.length >>> 24);
158: name[pos++] = (byte) (nameBytes.length >>> 16);
159: name[pos++] = (byte) (nameBytes.length >>> 8);
160: name[pos++] = (byte) nameBytes.length;
161: System.arraycopy(nameBytes, 0, name, pos,
162: nameBytes.length);
163: }
164: }
165: pName = cStub.importName(name, nameType);
166: setPrintables();
167:
168: SunNativeProvider.debug("Imported " + printableName
169: + " w/ type " + printableType);
170: }
171:
172: private void setPrintables() throws GSSException {
173: Object[] printables = null;
174: printables = cStub.displayName(pName);
175: assert ((printables != null) && (printables.length == 2));
176: printableName = (String) printables[0];
177: assert (printableName != null);
178: printableType = (Oid) printables[1];
179: if (printableType == null) {
180: printableType = GSSName.NT_USER_NAME;
181: }
182: }
183:
184: // Need to be public for GSSUtil.getSubject()
185: public String getKrbName() throws GSSException {
186: long mName = 0;
187: GSSLibStub stub = cStub;
188: if (!GSSUtil.isKerberosMech(cStub.getMech())) {
189: stub = GSSLibStub.getInstance(GSSUtil.GSS_KRB5_MECH_OID);
190: }
191: mName = stub.canonicalizeName(pName);
192: Object[] printables2 = stub.displayName(mName);
193: stub.releaseName(mName);
194: SunNativeProvider.debug("Got kerberized name: "
195: + printables2[0]);
196: return (String) printables2[0];
197: }
198:
199: public Provider getProvider() {
200: return SunNativeProvider.INSTANCE;
201: }
202:
203: public boolean equals(GSSNameSpi other) throws GSSException {
204: if (!(other instanceof GSSNameElement)) {
205: return false;
206: }
207: return cStub.compareName(pName, ((GSSNameElement) other).pName);
208: }
209:
210: public boolean equals(Object other) {
211: if (!(other instanceof GSSNameElement)) {
212: return false;
213: }
214: try {
215: return equals((GSSNameElement) other);
216: } catch (GSSException ex) {
217: return false;
218: }
219: }
220:
221: public int hashCode() {
222: return new Long(pName).hashCode();
223: }
224:
225: public byte[] export() throws GSSException {
226: byte[] nameVal = cStub.exportName(pName);
227:
228: // Need to strip off the mech Oid portion of the exported
229: // bytes since GSSNameImpl class will subsequently add it.
230: int pos = 0;
231: if ((nameVal[pos++] != 0x04) || (nameVal[pos++] != 0x01))
232: throw new GSSException(GSSException.BAD_NAME);
233:
234: int mechOidLen = (((0xFF & nameVal[pos++]) << 8) | (0xFF & nameVal[pos++]));
235: ObjectIdentifier temp = null;
236: try {
237: DerInputStream din = new DerInputStream(nameVal, pos,
238: mechOidLen);
239: temp = new ObjectIdentifier(din);
240: } catch (IOException e) {
241: throw new GSSExceptionImpl(GSSException.BAD_NAME, e);
242: }
243: Oid mech2 = new Oid(temp.toString());
244: assert (mech2.equals(getMechanism()));
245: pos += mechOidLen;
246: int mechPortionLen = (((0xFF & nameVal[pos++]) << 24)
247: | ((0xFF & nameVal[pos++]) << 16)
248: | ((0xFF & nameVal[pos++]) << 8) | (0xFF & nameVal[pos++]));
249: byte[] mechPortion = new byte[mechPortionLen];
250: System.arraycopy(nameVal, pos, mechPortion, 0, mechPortionLen);
251: return mechPortion;
252: }
253:
254: public Oid getMechanism() {
255: return cStub.getMech();
256: }
257:
258: public String toString() {
259: return printableName;
260: }
261:
262: public Oid getStringNameType() {
263: return printableType;
264: }
265:
266: public boolean isAnonymousName() {
267: return (GSSName.NT_ANONYMOUS.equals(printableType));
268: }
269:
270: public void dispose() {
271: if (pName != 0) {
272: cStub.releaseName(pName);
273: pName = 0;
274: }
275: }
276:
277: protected void finalize() throws Throwable {
278: dispose();
279: }
280: }
|