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