View Javadoc
1   /*
2    * Copyright 2013–2019 Michael Osipov
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package net.sf.michaelo.tomcat.authenticator;
17  
18  import java.io.IOException;
19  import java.security.Principal;
20  import java.security.PrivilegedActionException;
21  import java.security.PrivilegedExceptionAction;
22  
23  import javax.security.auth.Subject;
24  import javax.security.auth.login.LoginContext;
25  import javax.security.auth.login.LoginException;
26  import javax.servlet.http.HttpServletResponse;
27  
28  import org.apache.catalina.GSSRealm;
29  import org.apache.catalina.connector.Request;
30  import org.ietf.jgss.GSSCredential;
31  import org.ietf.jgss.GSSException;
32  import org.ietf.jgss.GSSManager;
33  import org.ietf.jgss.GSSName;
34  
35  /**
36   * A Windows Identity Authenticator which uses GSS-API to retrieve to currently logged in user.
37   *
38   * This authenticator requires a realm which implements the {@link GSSRealm} interface.
39   *
40   * @version $Id: CurrentWindowsIdentityAuthenticator.java 347 2019-12-20 11:10:04Z michael-o $
41   */
42  public class CurrentWindowsIdentityAuthenticator extends GSSAuthenticatorBase {
43  
44      protected static final String CURRENT_WINDOWS_IDENTITY_METHOD = "CURRENT_WINDOWS_IDENTITY";
45      protected static final String CURRENT_WINDOWS_IDENTITY_AUTH_SCHEME = "CWI";
46  
47      @Override
48      protected boolean doAuthenticate(Request request, HttpServletResponse response)
49              throws IOException {
50  
51          if (checkForCachedAuthentication(request, response, true)) {
52              return true;
53          }
54  
55          LoginContext lc = null;
56  
57          try {
58              try {
59                  lc = new LoginContext(getLoginEntryName());
60                  lc.login();
61              } catch (LoginException e) {
62                  logger.error(sm.getString("cwiAuthenticator.obtainFailed"), e);
63  
64                  sendUnauthorized(request, response, CURRENT_WINDOWS_IDENTITY_AUTH_SCHEME,
65                          "cwiAuthenticator.obtainFailed");
66                  return false;
67              }
68  
69              final GSSManager manager = GSSManager.getInstance();
70              final PrivilegedExceptionAction<GSSCredential> action = new PrivilegedExceptionAction<GSSCredential>() {
71                  @Override
72                  public GSSCredential run() throws GSSException {
73                      return manager.createCredential(null, GSSCredential.INDEFINITE_LIFETIME,
74                              KRB5_MECHANISM, GSSCredential.INITIATE_ONLY);
75                  }
76              };
77  
78              GSSCredential gssCredential = null;
79  
80              try {
81                  gssCredential = Subject.doAs(lc.getSubject(), action);
82              } catch (PrivilegedActionException e) {
83                  logger.error(sm.getString("cwiAuthenticator.obtainFailed"), e.getException());
84  
85                  sendUnauthorized(request, response, CURRENT_WINDOWS_IDENTITY_AUTH_SCHEME,
86                          "cwiAuthenticator.obtainFailed");
87                  return false;
88              }
89  
90              try {
91                  GSSRealm realm = (GSSRealm) context.getRealm();
92                  GSSName gssName = gssCredential.getName();
93  
94                  Principal principal = realm.authenticate(gssName,
95                          isStoreDelegatedCredential() ? gssCredential : null);
96  
97                  if (principal != null) {
98                      register(request, response, principal, getAuthMethod(), principal.getName(),
99                              null);
100                     return true;
101                 } else {
102                     sendUnauthorized(request, response, CURRENT_WINDOWS_IDENTITY_AUTH_SCHEME,
103                             "gssAuthenticatorBase.userNotFound", gssName);
104                     return false;
105                 }
106             } catch (GSSException e) {
107                 logger.error(sm.getString("gssAuthenticatorBase.inquireNameFailed"), e);
108 
109                 sendInternalServerError(request, response, "gssAuthenticatorBase.inquireNameFailed");
110                 return false;
111             }
112         } finally {
113             if (lc != null) {
114                 try {
115                     lc.logout();
116                 } catch (LoginException e) {
117                     ; // Ignore
118                 }
119             }
120         }
121     }
122 
123     @Override
124     protected String getAuthMethod() {
125         return CURRENT_WINDOWS_IDENTITY_METHOD;
126     }
127 
128 }