blob: d96a47b522d492eceed6774dcb77ead9f9bea1d3 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.security.jgss.wrapper;
27
28import org.ietf.jgss.*;
29import java.security.Provider;
30import java.security.Security;
31import java.io.IOException;
32import java.io.UnsupportedEncodingException;
33import sun.security.jgss.GSSUtil;
34import sun.security.util.ObjectIdentifier;
35import sun.security.util.DerInputStream;
36import sun.security.util.DerOutputStream;
37import sun.security.jgss.GSSUtil;
38import sun.security.jgss.GSSExceptionImpl;
39import sun.security.jgss.spi.GSSNameSpi;
40
41/**
42 * This class is essentially a wrapper class for the gss_name_t
43 * structure of the native GSS library.
44 * @author Valerie Peng
45 * @since 1.6
46 */
47
48public class GSSNameElement implements GSSNameSpi {
49
50 long pName = 0; // Pointer to the gss_name_t structure
51 private String printableName;
52 private Oid printableType;
53 private GSSLibStub cStub;
54
55 static final GSSNameElement DEF_ACCEPTOR = new GSSNameElement();
56
57 private static Oid getNativeNameType(Oid nameType, GSSLibStub stub) {
58 if (GSSUtil.NT_GSS_KRB5_PRINCIPAL.equals(nameType) ||
59 GSSName.NT_HOSTBASED_SERVICE.equals(nameType)) {
60 Oid[] supportedNTs = null;
61 try {
62 supportedNTs = stub.inquireNamesForMech();
63 } catch (GSSException ge) {
64 if (ge.getMajor() == GSSException.BAD_MECH &&
65 GSSUtil.isSpNegoMech(stub.getMech())) {
66 // Workaround known Heimdal issue and retry with KRB5
67 try {
68 stub = GSSLibStub.getInstance
69 (GSSUtil.GSS_KRB5_MECH_OID);
70 supportedNTs = stub.inquireNamesForMech();
71 } catch (GSSException ge2) {
72 // Should never happen
73 SunNativeProvider.debug("Name type list unavailable: " +
74 ge2.getMajorString());
75 }
76 } else {
77 SunNativeProvider.debug("Name type list unavailable: " +
78 ge.getMajorString());
79 }
80 }
81 if (supportedNTs != null) {
82 for (int i = 0; i < supportedNTs.length; i++) {
83 if (supportedNTs[i].equals(nameType)) return nameType;
84 }
85 // Special handling the specified name type
86 if (GSSUtil.NT_GSS_KRB5_PRINCIPAL.equals(nameType)) {
87 SunNativeProvider.debug("Override " + nameType +
88 " with mechanism default(null)");
89 return null; // Use mechanism specific default
90 } else {
91 SunNativeProvider.debug("Override " + nameType +
92 " with " + GSSUtil.NT_HOSTBASED_SERVICE2);
93 return GSSUtil.NT_HOSTBASED_SERVICE2;
94 }
95 }
96 }
97 return nameType;
98 }
99
100 private GSSNameElement() {
101 printableName = "<DEFAULT ACCEPTOR>";
102 }
103
104 GSSNameElement(long pNativeName, GSSLibStub stub) throws GSSException {
105 assert(stub != null);
106 if (pNativeName == 0) {
107 throw new GSSException(GSSException.BAD_NAME);
108 }
109 // Note: pNativeName is assumed to be a MN.
110 pName = pNativeName;
111 cStub = stub;
112 setPrintables();
113 }
114
115 GSSNameElement(byte[] nameBytes, Oid nameType, GSSLibStub stub)
116 throws GSSException {
117 assert(stub != null);
118 if (nameBytes == null) {
119 throw new GSSException(GSSException.BAD_NAME);
120 }
121 cStub = stub;
122 byte[] name = nameBytes;
123
124 if (nameType != null) {
125 // Special handling the specified name type if
126 // necessary
127 nameType = getNativeNameType(nameType, stub);
128
129 if (GSSName.NT_EXPORT_NAME.equals(nameType)) {
130 // Need to add back the mech Oid portion (stripped
131 // off by GSSNameImpl class prior to calling this
132 // method) for "NT_EXPORT_NAME"
133 byte[] mechBytes = null;
134 DerOutputStream dout = new DerOutputStream();
135 Oid mech = cStub.getMech();
136 try {
137 dout.putOID(new ObjectIdentifier(mech.toString()));
138 } catch (IOException e) {
139 throw new GSSExceptionImpl(GSSException.FAILURE, e);
140 }
141 mechBytes = dout.toByteArray();
142 name = new byte[2 + 2 + mechBytes.length + 4 + nameBytes.length];
143 int pos = 0;
144 name[pos++] = 0x04;
145 name[pos++] = 0x01;
146 name[pos++] = (byte) (mechBytes.length>>>8);
147 name[pos++] = (byte) mechBytes.length;
148 System.arraycopy(mechBytes, 0, name, pos, mechBytes.length);
149 pos += mechBytes.length;
150 name[pos++] = (byte) (nameBytes.length>>>24);
151 name[pos++] = (byte) (nameBytes.length>>>16);
152 name[pos++] = (byte) (nameBytes.length>>>8);
153 name[pos++] = (byte) nameBytes.length;
154 System.arraycopy(nameBytes, 0, name, pos, nameBytes.length);
155 }
156 }
157 pName = cStub.importName(name, nameType);
158 setPrintables();
159
160 SunNativeProvider.debug("Imported " + printableName + " w/ type " +
161 printableType);
162 }
163
164 private void setPrintables() throws GSSException {
165 Object[] printables = null;
166 printables = cStub.displayName(pName);
167 assert((printables != null) && (printables.length == 2));
168 printableName = (String) printables[0];
169 assert(printableName != null);
170 printableType = (Oid) printables[1];
171 if (printableType == null) {
172 printableType = GSSName.NT_USER_NAME;
173 }
174 }
175
176 // Need to be public for GSSUtil.getSubject()
177 public String getKrbName() throws GSSException {
178 long mName = 0;
179 GSSLibStub stub = cStub;
180 if (!GSSUtil.isKerberosMech(cStub.getMech())) {
181 stub = GSSLibStub.getInstance(GSSUtil.GSS_KRB5_MECH_OID);
182 }
183 mName = stub.canonicalizeName(pName);
184 Object[] printables2 = stub.displayName(mName);
185 stub.releaseName(mName);
186 SunNativeProvider.debug("Got kerberized name: " + printables2[0]);
187 return (String) printables2[0];
188 }
189
190 public Provider getProvider() {
191 return SunNativeProvider.INSTANCE;
192 }
193
194 public boolean equals(GSSNameSpi other) throws GSSException {
195 if (!(other instanceof GSSNameElement)) {
196 return false;
197 }
198 return cStub.compareName(pName, ((GSSNameElement)other).pName);
199 }
200
201 public boolean equals(Object other) {
202 if (!(other instanceof GSSNameElement)) {
203 return false;
204 }
205 try {
206 return equals((GSSNameElement) other);
207 } catch (GSSException ex) {
208 return false;
209 }
210 }
211
212 public int hashCode() {
213 return new Long(pName).hashCode();
214 }
215
216 public byte[] export() throws GSSException {
217 byte[] nameVal = cStub.exportName(pName);
218
219 // Need to strip off the mech Oid portion of the exported
220 // bytes since GSSNameImpl class will subsequently add it.
221 int pos = 0;
222 if ((nameVal[pos++] != 0x04) ||
223 (nameVal[pos++] != 0x01))
224 throw new GSSException(GSSException.BAD_NAME);
225
226 int mechOidLen = (((0xFF & nameVal[pos++]) << 8) |
227 (0xFF & nameVal[pos++]));
228 ObjectIdentifier temp = null;
229 try {
230 DerInputStream din = new DerInputStream(nameVal, pos,
231 mechOidLen);
232 temp = new ObjectIdentifier(din);
233 } catch (IOException e) {
234 throw new GSSExceptionImpl(GSSException.BAD_NAME, e);
235 }
236 Oid mech2 = new Oid(temp.toString());
237 assert(mech2.equals(getMechanism()));
238 pos += mechOidLen;
239 int mechPortionLen = (((0xFF & nameVal[pos++]) << 24) |
240 ((0xFF & nameVal[pos++]) << 16) |
241 ((0xFF & nameVal[pos++]) << 8) |
242 (0xFF & nameVal[pos++]));
243 byte[] mechPortion = new byte[mechPortionLen];
244 System.arraycopy(nameVal, pos, mechPortion, 0, mechPortionLen);
245 return mechPortion;
246 }
247
248 public Oid getMechanism() {
249 return cStub.getMech();
250 }
251
252 public String toString() {
253 return printableName;
254 }
255
256 public Oid getStringNameType() {
257 return printableType;
258 }
259
260 public boolean isAnonymousName() {
261 return (GSSName.NT_ANONYMOUS.equals(printableType));
262 }
263
264 public void dispose() {
265 if (pName != 0) {
266 cStub.releaseName(pName);
267 pName = 0;
268 }
269 }
270
271 protected void finalize() throws Throwable {
272 dispose();
273 }
274}