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 26package sun.security.jgss.spnego; 27 28import org.ietf.jgss.*; 29import sun.security.jgss.*; 30import sun.security.jgss.spi.*; 31import sun.security.jgss.krb5.Krb5MechFactory; 32import sun.security.jgss.krb5.Krb5InitCredential; 33import sun.security.jgss.krb5.Krb5AcceptCredential; 34import sun.security.jgss.krb5.Krb5NameElement; 35import java.security.Provider; 36import 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 47public 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 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 99 public SpNegoMechFactory() { 100 this(GSSCaller.CALLER_UNKNOWN); 101 } 102 103 public SpNegoMechFactory(GSSCaller caller) { 104 manager = new GSSManagerImpl(caller, false); 105 Oid[] mechs = manager.getMechs(); 106 availableMechs = new Oid[mechs.length-1]; 107 for (int i = 0, j = 0; i < mechs.length; i++) { 108 // Skip SpNego mechanism 109 if (!mechs[i].equals(GSS_SPNEGO_MECH_OID)) { 110 availableMechs[j++] = mechs[i]; 111 } 112 } 113 // Move the preferred mech to first place 114 for (int i=0; i<availableMechs.length; i++) { 115 if (availableMechs[i].equals(DEFAULT_SPNEGO_MECH_OID)) { 116 if (i != 0) { 117 availableMechs[i] = availableMechs[0]; 118 availableMechs[0] = DEFAULT_SPNEGO_MECH_OID; 119 } 120 break; 121 } 122 } 123 } 124 125 public GSSNameSpi getNameElement(String nameStr, Oid nameType) 126 throws GSSException { 127 return manager.getNameElement( 128 nameStr, nameType, DEFAULT_SPNEGO_MECH_OID); 129 } 130 131 public GSSNameSpi getNameElement(byte[] name, Oid nameType) 132 throws GSSException { 133 return manager.getNameElement(name, nameType, DEFAULT_SPNEGO_MECH_OID); 134 } 135 136 public GSSCredentialSpi getCredentialElement(GSSNameSpi name, 137 int initLifetime, int acceptLifetime, 138 int usage) throws GSSException { 139 140 SpNegoCredElement credElement = getCredFromSubject 141 (name, (usage != GSSCredential.ACCEPT_ONLY)); 142 143 if (credElement == null) { 144 // get CredElement for the default Mechanism 145 credElement = new SpNegoCredElement 146 (manager.getCredentialElement(name, initLifetime, 147 acceptLifetime, null, usage)); 148 } 149 return credElement; 150 } 151 152 public GSSContextSpi getMechanismContext(GSSNameSpi peer, 153 GSSCredentialSpi myInitiatorCred, int lifetime) 154 throws GSSException { 155 // get SpNego mechanism context 156 if (myInitiatorCred == null) { 157 myInitiatorCred = getCredFromSubject(null, true); 158 } else if (!(myInitiatorCred instanceof SpNegoCredElement)) { 159 // convert to SpNegoCredElement 160 SpNegoCredElement cred = new SpNegoCredElement(myInitiatorCred); 161 return new SpNegoContext(this, peer, cred, lifetime); 162 } 163 return new SpNegoContext(this, peer, myInitiatorCred, lifetime); 164 } 165 166 public GSSContextSpi getMechanismContext(GSSCredentialSpi myAcceptorCred) 167 throws GSSException { 168 // get SpNego mechanism context 169 if (myAcceptorCred == null) { 170 myAcceptorCred = getCredFromSubject(null, false); 171 } else if (!(myAcceptorCred instanceof SpNegoCredElement)) { 172 // convert to SpNegoCredElement 173 SpNegoCredElement cred = new SpNegoCredElement(myAcceptorCred); 174 return new SpNegoContext(this, cred); 175 } 176 return new SpNegoContext(this, myAcceptorCred); 177 } 178 179 public GSSContextSpi getMechanismContext(byte[] exportedContext) 180 throws GSSException { 181 // get SpNego mechanism context 182 return new SpNegoContext(this, exportedContext); 183 } 184 185 public final Oid getMechanismOid() { 186 return GSS_SPNEGO_MECH_OID; 187 } 188 189 public Provider getProvider() { 190 return PROVIDER; 191 } 192 193 public Oid[] getNameTypes() { 194 // nameTypes is cloned in GSSManager.getNamesForMech 195 return nameTypes; 196 } 197} 198