1 /*
2  * Copyright (c) 2005, 2011, 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 java.io.UnsupportedEncodingException;
29 import java.security.Provider;
30 import java.util.Vector;
31 import org.ietf.jgss.*;
32 import sun.security.jgss.GSSUtil;
33 import sun.security.jgss.GSSCaller;
34 import sun.security.jgss.GSSExceptionImpl;
35 import sun.security.jgss.spi.*;
36 
37 /**
38  * JGSS plugin for generic mechanisms provided through native GSS framework.
39  *
40  * @author Valerie Peng
41  */
42 
43 public final class NativeGSSFactory implements MechanismFactory {
44 
45     GSSLibStub cStub = null;
46     private final GSSCaller caller;
47 
getCredFromSubject(GSSNameElement name, boolean initiate)48     private GSSCredElement getCredFromSubject(GSSNameElement name,
49                                               boolean initiate)
50         throws GSSException {
51         Oid mech = cStub.getMech();
52         Vector<GSSCredElement> creds = GSSUtil.searchSubject
53             (name, mech, initiate, GSSCredElement.class);
54 
55         // If Subject is present but no native creds available
56         if (creds != null && creds.isEmpty()) {
57             if (GSSUtil.useSubjectCredsOnly(caller)) {
58                 throw new GSSException(GSSException.NO_CRED);
59             }
60         }
61 
62         GSSCredElement result = ((creds == null || creds.isEmpty()) ?
63                                  null : creds.firstElement());
64         // Force permission check before returning the cred to caller
65         if (result != null) {
66             result.doServicePermCheck();
67         }
68         return result;
69     }
70 
NativeGSSFactory(GSSCaller caller)71     public NativeGSSFactory(GSSCaller caller) {
72         this.caller = caller;
73         // Have to call setMech(Oid) explicitly before calling other
74         // methods. Otherwise, NPE may be thrown unexpectantly
75     }
76 
setMech(Oid mech)77     public void setMech(Oid mech) throws GSSException {
78         cStub = GSSLibStub.getInstance(mech);
79     }
80 
getNameElement(String nameStr, Oid nameType)81     public GSSNameSpi getNameElement(String nameStr, Oid nameType)
82         throws GSSException {
83         try {
84             byte[] nameBytes =
85                 (nameStr == null ? null : nameStr.getBytes("UTF-8"));
86             return new GSSNameElement(nameBytes, nameType, cStub);
87         } catch (UnsupportedEncodingException uee) {
88             // Shouldn't happen
89             throw new GSSExceptionImpl(GSSException.FAILURE, uee);
90         }
91     }
92 
getNameElement(byte[] name, Oid nameType)93     public GSSNameSpi getNameElement(byte[] name, Oid nameType)
94         throws GSSException {
95         return new GSSNameElement(name, nameType, cStub);
96     }
97 
getCredentialElement(GSSNameSpi name, int initLifetime, int acceptLifetime, int usage)98     public GSSCredentialSpi getCredentialElement(GSSNameSpi name,
99                                                  int initLifetime,
100                                                  int acceptLifetime,
101                                                  int usage)
102         throws GSSException {
103         GSSNameElement nname = null;
104         if (name != null && !(name instanceof GSSNameElement)) {
105             nname = (GSSNameElement)
106                 getNameElement(name.toString(), name.getStringNameType());
107         } else nname = (GSSNameElement) name;
108 
109         if (usage == GSSCredential.INITIATE_AND_ACCEPT) {
110             // Force separate acqusition of cred element since
111             // MIT's impl does not correctly report NO_CRED error.
112             usage = GSSCredential.INITIATE_ONLY;
113         }
114 
115         GSSCredElement credElement =
116             getCredFromSubject(nname, (usage == GSSCredential.INITIATE_ONLY));
117 
118         if (credElement == null) {
119             // No cred in the Subject
120             if (usage == GSSCredential.INITIATE_ONLY) {
121                 credElement = new GSSCredElement(nname, initLifetime,
122                                                  usage, cStub);
123             } else if (usage == GSSCredential.ACCEPT_ONLY) {
124                 if (nname == null) {
125                     nname = GSSNameElement.DEF_ACCEPTOR;
126                 }
127                 credElement = new GSSCredElement(nname, acceptLifetime,
128                                                  usage, cStub);
129             } else {
130                 throw new GSSException(GSSException.FAILURE, -1,
131                                        "Unknown usage mode requested");
132             }
133         }
134         return credElement;
135     }
136 
getMechanismContext(GSSNameSpi peer, GSSCredentialSpi myCred, int lifetime)137     public GSSContextSpi getMechanismContext(GSSNameSpi peer,
138                                              GSSCredentialSpi myCred,
139                                              int lifetime)
140         throws GSSException {
141         if (peer == null) {
142             throw new GSSException(GSSException.BAD_NAME);
143         } else if (!(peer instanceof GSSNameElement)) {
144             peer = (GSSNameElement)
145                 getNameElement(peer.toString(), peer.getStringNameType());
146         }
147         if (myCred == null) {
148             myCred = getCredFromSubject(null, true);
149         } else if (!(myCred instanceof GSSCredElement)) {
150             throw new GSSException(GSSException.NO_CRED);
151         }
152         return new NativeGSSContext((GSSNameElement) peer,
153                                      (GSSCredElement) myCred,
154                                      lifetime, cStub);
155     }
156 
getMechanismContext(GSSCredentialSpi myCred)157     public GSSContextSpi getMechanismContext(GSSCredentialSpi myCred)
158         throws GSSException {
159         if (myCred == null) {
160             myCred = getCredFromSubject(null, false);
161         } else if (!(myCred instanceof GSSCredElement)) {
162             throw new GSSException(GSSException.NO_CRED);
163         }
164         return new NativeGSSContext((GSSCredElement) myCred, cStub);
165     }
166 
getMechanismContext(byte[] exportedContext)167     public GSSContextSpi getMechanismContext(byte[] exportedContext)
168         throws GSSException {
169         return cStub.importContext(exportedContext);
170     }
171 
getMechanismOid()172     public final Oid getMechanismOid() {
173         return cStub.getMech();
174     }
175 
getProvider()176     public Provider getProvider() {
177         return SunNativeProvider.INSTANCE;
178     }
179 
getNameTypes()180     public Oid[] getNameTypes() throws GSSException {
181         return cStub.inquireNamesForMech();
182     }
183 }
184