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