1 /*
   2  * Copyright (c) 2000, 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;
  27 
  28 import org.ietf.jgss.*;
  29 import sun.security.jgss.spi.*;
  30 import java.security.Provider;
  31 import java.security.AccessController;
  32 import java.security.PrivilegedAction;
  33 
  34 /**
  35  * This class provides the default implementation of the GSSManager
  36  * interface.
  37  */
  38 public class GSSManagerImpl extends GSSManager {
  39 
  40     // Undocumented property
  41     private static final String USE_NATIVE_PROP =
  42         "sun.security.jgss.native";
  43     private static final Boolean USE_NATIVE;
  44 
  45     static {
  46         USE_NATIVE =
  47             AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
  48                     public Boolean run() {
  49                             String osname = System.getProperty("os.name");
  50                             if (osname.startsWith("SunOS") ||
  51                                 osname.startsWith("Linux")) {
  52                                 return new Boolean(System.getProperty
  53                                     (USE_NATIVE_PROP));
  54                             }
  55                             return Boolean.FALSE;
  56                     }
  57             });
  58 
  59     }
  60 
  61     private ProviderList list;
  62 
  63     // Used by java SPNEGO impl to make sure native is disabled
  64     public GSSManagerImpl(GSSCaller caller, boolean useNative) {
  65         list = new ProviderList(caller, useNative);
  66     }
  67 
  68     // Used by HTTP/SPNEGO NegotiatorImpl
  69     public GSSManagerImpl(GSSCaller caller) {
  70         list = new ProviderList(caller, USE_NATIVE);
  71     }
  72 
  73     public GSSManagerImpl() {
  74         list = new ProviderList(GSSCaller.CALLER_UNKNOWN, USE_NATIVE);
  75     }
  76 
  77     public Oid[] getMechs(){
  78         return list.getMechs();
  79     }
  80 
  81     public Oid[] getNamesForMech(Oid mech)
  82         throws GSSException {
  83         MechanismFactory factory = list.getMechFactory(mech);
  84         return factory.getNameTypes().clone();
  85     }
  86 
  87     public Oid[] getMechsForName(Oid nameType){
  88         Oid[] mechs = list.getMechs();
  89         Oid[] retVal = new Oid[mechs.length];
  90         int pos = 0;
  91 
  92         // Compatibility with RFC 2853 old NT_HOSTBASED_SERVICE value.
  93         if (nameType.equals(GSSNameImpl.oldHostbasedServiceName)) {
  94             nameType = GSSName.NT_HOSTBASED_SERVICE;
  95         }
  96 
  97         // Iterate thru all mechs in GSS
  98         for (int i = 0; i < mechs.length; i++) {
  99             // what nametypes does this mech support?
 100             Oid mech = mechs[i];
 101             try {
 102                 Oid[] namesForMech = getNamesForMech(mech);
 103                 // Is the desired Oid present in that list?
 104                 if (nameType.containedIn(namesForMech)) {
 105                     retVal[pos++] = mech;
 106                 }
 107             } catch (GSSException e) {
 108                 // Squelch it and just skip over this mechanism
 109                 GSSUtil.debug("Skip " + mech +
 110                               ": error retrieving supported name types");
 111             }
 112         }
 113 
 114         // Trim the list if needed
 115         if (pos < retVal.length) {
 116             Oid[] temp = new Oid[pos];
 117             for (int i = 0; i < pos; i++)
 118                 temp[i] = retVal[i];
 119             retVal = temp;
 120         }
 121 
 122         return retVal;
 123     }
 124 
 125     public GSSName createName(String nameStr, Oid nameType)
 126         throws GSSException {
 127         return new GSSNameImpl(this, nameStr, nameType);
 128     }
 129 
 130     public GSSName createName(byte name[], Oid nameType)
 131         throws GSSException {
 132         return new GSSNameImpl(this, name, nameType);
 133     }
 134 
 135     public GSSName createName(String nameStr, Oid nameType,
 136                               Oid mech) throws GSSException {
 137         return new GSSNameImpl(this, nameStr, nameType, mech);
 138     }
 139 
 140     public GSSName createName(byte name[], Oid nameType, Oid mech)
 141         throws GSSException {
 142         return new GSSNameImpl(this, name, nameType, mech);
 143     }
 144 
 145     public GSSCredential createCredential(int usage)
 146         throws GSSException {
 147         return new GSSCredentialImpl(this, usage);
 148     }
 149 
 150     public GSSCredential createCredential(GSSName aName,
 151                                           int lifetime, Oid mech, int usage)
 152         throws GSSException {
 153         return new GSSCredentialImpl(this, aName, lifetime, mech, usage);
 154     }
 155 
 156     public GSSCredential createCredential(GSSName aName,
 157                                           int lifetime, Oid mechs[], int usage)
 158         throws GSSException {
 159         return new GSSCredentialImpl(this, aName, lifetime, mechs, usage);
 160     }
 161 
 162     public GSSContext createContext(GSSName peer, Oid mech,
 163                                     GSSCredential myCred, int lifetime)
 164         throws GSSException {
 165         return new GSSContextImpl(this, peer, mech, myCred, lifetime);
 166     }
 167 
 168     public GSSContext createContext(GSSCredential myCred)
 169         throws GSSException {
 170         return new GSSContextImpl(this, myCred);
 171     }
 172 
 173     public GSSContext createContext(byte[] interProcessToken)
 174         throws GSSException {
 175         return new GSSContextImpl(this, interProcessToken);
 176     }
 177 
 178     public void addProviderAtFront(Provider p, Oid mech)
 179         throws GSSException {
 180         list.addProviderAtFront(p, mech);
 181     }
 182 
 183     public void addProviderAtEnd(Provider p, Oid mech)
 184         throws GSSException {
 185         list.addProviderAtEnd(p, mech);
 186     }
 187 
 188     public GSSCredentialSpi getCredentialElement(GSSNameSpi name, int initLifetime,
 189                                           int acceptLifetime, Oid mech, int usage)
 190         throws GSSException {
 191         MechanismFactory factory = list.getMechFactory(mech);
 192         return factory.getCredentialElement(name, initLifetime,
 193                                             acceptLifetime, usage);
 194     }
 195 
 196     // Used by java SPNEGO impl
 197     public GSSNameSpi getNameElement(String name, Oid nameType, Oid mech)
 198         throws GSSException {
 199         // Just use the most preferred MF impl assuming GSSNameSpi
 200         // objects are interoperable among providers
 201         MechanismFactory factory = list.getMechFactory(mech);
 202         return factory.getNameElement(name, nameType);
 203     }
 204 
 205     // Used by java SPNEGO impl
 206     public GSSNameSpi getNameElement(byte[] name, Oid nameType, Oid mech)
 207         throws GSSException {
 208         // Just use the most preferred MF impl assuming GSSNameSpi
 209         // objects are interoperable among providers
 210         MechanismFactory factory = list.getMechFactory(mech);
 211         return factory.getNameElement(name, nameType);
 212     }
 213 
 214     GSSContextSpi getMechanismContext(GSSNameSpi peer,
 215                                       GSSCredentialSpi myInitiatorCred,
 216                                       int lifetime, Oid mech)
 217         throws GSSException {
 218         Provider p = null;
 219         if (myInitiatorCred != null) {
 220             p = myInitiatorCred.getProvider();
 221         }
 222         MechanismFactory factory = list.getMechFactory(mech, p);
 223         return factory.getMechanismContext(peer, myInitiatorCred, lifetime);
 224     }
 225 
 226     GSSContextSpi getMechanismContext(GSSCredentialSpi myAcceptorCred,
 227                                       Oid mech)
 228         throws GSSException {
 229         Provider p = null;
 230         if (myAcceptorCred != null) {
 231             p = myAcceptorCred.getProvider();
 232         }
 233         MechanismFactory factory = list.getMechFactory(mech, p);
 234         return factory.getMechanismContext(myAcceptorCred);
 235     }
 236 
 237     GSSContextSpi getMechanismContext(byte[] exportedContext)
 238         throws GSSException {
 239         if ((exportedContext == null) || (exportedContext.length == 0)) {
 240             throw new GSSException(GSSException.NO_CONTEXT);
 241         }
 242         GSSContextSpi result = null;
 243 
 244         // Only allow context import with native provider since JGSS
 245         // still has not defined its own interprocess token format
 246         Oid[] mechs = list.getMechs();
 247         for (int i = 0; i < mechs.length; i++) {
 248             MechanismFactory factory = list.getMechFactory(mechs[i]);
 249             if (factory.getProvider().getName().equals("SunNativeGSS")) {
 250                 result = factory.getMechanismContext(exportedContext);
 251                 if (result != null) break;
 252             }
 253         }
 254         if (result == null) {
 255             throw new GSSException(GSSException.UNAVAILABLE);
 256         }
 257         return result;
 258     }
 259 }