1 /* 2 * Copyright (c) 2005, 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 sun.security.jgss.spnego; 27 28 import org.ietf.jgss.*; 29 import sun.security.jgss.*; 30 import sun.security.jgss.spi.*; 31 import sun.security.jgss.krb5.Krb5MechFactory; 32 import sun.security.jgss.krb5.Krb5InitCredential; 33 import sun.security.jgss.krb5.Krb5AcceptCredential; 34 import sun.security.jgss.krb5.Krb5NameElement; 35 import java.security.Provider; 36 import java.util.Vector; 37 38 /** 39 * SpNego Mechanism plug in for JGSS 40 * This is the properties object required by the JGSS framework. 41 * All mechanism specific information is defined here. 42 * 43 * @author Seema Malkani 44 * @since 1.6 45 */ 46 47 public final class SpNegoMechFactory implements MechanismFactory { 48 49 static final Provider PROVIDER = 50 new sun.security.jgss.SunProvider(); 51 52 static final Oid GSS_SPNEGO_MECH_OID = 53 GSSUtil.createOid("1.3.6.1.5.5.2"); 54 55 private static Oid[] nameTypes = 56 new Oid[] { GSSName.NT_USER_NAME, 57 GSSName.NT_HOSTBASED_SERVICE, 58 GSSName.NT_EXPORT_NAME}; 59 60 // The default underlying mech of SPNEGO, must not be SPNEGO itself. 61 private static final Oid DEFAULT_SPNEGO_MECH_OID = 62 ProviderList.DEFAULT_MECH_OID.equals(GSS_SPNEGO_MECH_OID)? 63 GSSUtil.GSS_KRB5_MECH_OID: 64 ProviderList.DEFAULT_MECH_OID; 65 66 // Use an instance of a GSSManager whose provider list 67 // does not include native provider 68 final GSSManagerImpl manager; 69 final Oid[] availableMechs; 70 getCredFromSubject(GSSNameSpi name, boolean initiate)71 private static SpNegoCredElement getCredFromSubject(GSSNameSpi name, 72 boolean initiate) 73 throws GSSException { 74 Vector<SpNegoCredElement> creds = 75 GSSUtil.searchSubject(name, GSS_SPNEGO_MECH_OID, 76 initiate, SpNegoCredElement.class); 77 78 SpNegoCredElement result = ((creds == null || creds.isEmpty()) ? 79 null : creds.firstElement()); 80 81 // Force permission check before returning the cred to caller 82 if (result != null) { 83 GSSCredentialSpi cred = result.getInternalCred(); 84 if (GSSUtil.isKerberosMech(cred.getMechanism())) { 85 if (initiate) { 86 Krb5InitCredential krbCred = (Krb5InitCredential) cred; 87 Krb5MechFactory.checkInitCredPermission 88 ((Krb5NameElement) krbCred.getName()); 89 } else { 90 Krb5AcceptCredential krbCred = (Krb5AcceptCredential) cred; 91 Krb5MechFactory.checkAcceptCredPermission 92 ((Krb5NameElement) krbCred.getName(), name); 93 } 94 } 95 } 96 return result; 97 } 98 SpNegoMechFactory(GSSCaller caller)99 public SpNegoMechFactory(GSSCaller caller) { 100 manager = new GSSManagerImpl(caller, false); 101 Oid[] mechs = manager.getMechs(); 102 availableMechs = new Oid[mechs.length-1]; 103 for (int i = 0, j = 0; i < mechs.length; i++) { 104 // Skip SpNego mechanism 105 if (!mechs[i].equals(GSS_SPNEGO_MECH_OID)) { 106 availableMechs[j++] = mechs[i]; 107 } 108 } 109 // Move the preferred mech to first place 110 for (int i=0; i<availableMechs.length; i++) { 111 if (availableMechs[i].equals(DEFAULT_SPNEGO_MECH_OID)) { 112 if (i != 0) { 113 availableMechs[i] = availableMechs[0]; 114 availableMechs[0] = DEFAULT_SPNEGO_MECH_OID; 115 } 116 break; 117 } 118 } 119 } 120 getNameElement(String nameStr, Oid nameType)121 public GSSNameSpi getNameElement(String nameStr, Oid nameType) 122 throws GSSException { 123 return manager.getNameElement( 124 nameStr, nameType, DEFAULT_SPNEGO_MECH_OID); 125 } 126 getNameElement(byte[] name, Oid nameType)127 public GSSNameSpi getNameElement(byte[] name, Oid nameType) 128 throws GSSException { 129 return manager.getNameElement(name, nameType, DEFAULT_SPNEGO_MECH_OID); 130 } 131 getCredentialElement(GSSNameSpi name, int initLifetime, int acceptLifetime, int usage)132 public GSSCredentialSpi getCredentialElement(GSSNameSpi name, 133 int initLifetime, int acceptLifetime, 134 int usage) throws GSSException { 135 136 SpNegoCredElement credElement = getCredFromSubject 137 (name, (usage != GSSCredential.ACCEPT_ONLY)); 138 139 if (credElement == null) { 140 // get CredElement for the default Mechanism 141 credElement = new SpNegoCredElement 142 (manager.getCredentialElement(name, initLifetime, 143 acceptLifetime, null, usage)); 144 } 145 return credElement; 146 } 147 getMechanismContext(GSSNameSpi peer, GSSCredentialSpi myInitiatorCred, int lifetime)148 public GSSContextSpi getMechanismContext(GSSNameSpi peer, 149 GSSCredentialSpi myInitiatorCred, int lifetime) 150 throws GSSException { 151 // get SpNego mechanism context 152 if (myInitiatorCred == null) { 153 myInitiatorCred = getCredFromSubject(null, true); 154 } else if (!(myInitiatorCred instanceof SpNegoCredElement)) { 155 // convert to SpNegoCredElement 156 SpNegoCredElement cred = new SpNegoCredElement(myInitiatorCred); 157 return new SpNegoContext(this, peer, cred, lifetime); 158 } 159 return new SpNegoContext(this, peer, myInitiatorCred, lifetime); 160 } 161 getMechanismContext(GSSCredentialSpi myAcceptorCred)162 public GSSContextSpi getMechanismContext(GSSCredentialSpi myAcceptorCred) 163 throws GSSException { 164 // get SpNego mechanism context 165 if (myAcceptorCred == null) { 166 myAcceptorCred = getCredFromSubject(null, false); 167 } else if (!(myAcceptorCred instanceof SpNegoCredElement)) { 168 // convert to SpNegoCredElement 169 SpNegoCredElement cred = new SpNegoCredElement(myAcceptorCred); 170 return new SpNegoContext(this, cred); 171 } 172 return new SpNegoContext(this, myAcceptorCred); 173 } 174 getMechanismContext(byte[] exportedContext)175 public GSSContextSpi getMechanismContext(byte[] exportedContext) 176 throws GSSException { 177 // get SpNego mechanism context 178 return new SpNegoContext(this, exportedContext); 179 } 180 getMechanismOid()181 public final Oid getMechanismOid() { 182 return GSS_SPNEGO_MECH_OID; 183 } 184 getProvider()185 public Provider getProvider() { 186 return PROVIDER; 187 } 188 getNameTypes()189 public Oid[] getNameTypes() { 190 // nameTypes is cloned in GSSManager.getNamesForMech 191 return nameTypes; 192 } 193 } 194