View Javadoc
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  
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  
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  
77      public void setMech(Oid mech) throws GSSException {
78          cStub = GSSLibStub.getInstance(mech);
79      }
80  
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  
93      public GSSNameSpi getNameElement(byte[] name, Oid nameType)
94          throws GSSException {
95          return new GSSNameElement(name, nameType, cStub);
96      }
97  
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 
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 
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 
167     public GSSContextSpi getMechanismContext(byte[] exportedContext)
168         throws GSSException {
169         return cStub.importContext(exportedContext);
170     }
171 
172     public final Oid getMechanismOid() {
173         return cStub.getMech();
174     }
175 
176     public Provider getProvider() {
177         return SunNativeProvider.INSTANCE;
178     }
179 
180     public Oid[] getNameTypes() throws GSSException {
181         return cStub.inquireNamesForMech();
182     }
183 }