View Javadoc
1   /*
2    * Copyright 2013–2023 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.Realm;
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  public class CurrentWindowsIdentityAuthenticator extends GSSAuthenticatorBase {
39  
40  	protected static final String CURRENT_WINDOWS_IDENTITY_METHOD = "CURRENT_WINDOWS_IDENTITY";
41  	protected static final String CURRENT_WINDOWS_IDENTITY_AUTH_SCHEME = "CWI";
42  
43  	@Override
44  	protected boolean doAuthenticate(Request request, HttpServletResponse response)
45  			throws IOException {
46  
47  		if (checkForCachedAuthentication(request, response, true)) {
48  			return true;
49  		}
50  
51  		LoginContext lc = null;
52  
53  		try {
54  			try {
55  				lc = new LoginContext(getLoginEntryName());
56  				lc.login();
57  			} catch (LoginException e) {
58  				logger.error(sm.getString("cwiAuthenticator.obtainFailed"), e);
59  
60  				sendUnauthorized(request, response, CURRENT_WINDOWS_IDENTITY_AUTH_SCHEME,
61  						"cwiAuthenticator.obtainFailed");
62  				return false;
63  			}
64  
65  			final GSSManager manager = GSSManager.getInstance();
66  			final PrivilegedExceptionAction<GSSCredential> action = () -> manager.createCredential(null,
67  					GSSCredential.INDEFINITE_LIFETIME, KRB5_MECHANISM, GSSCredential.INITIATE_ONLY);
68  
69  			GSSCredential gssCredential = null;
70  
71  			try {
72  				gssCredential = Subject.doAs(lc.getSubject(), action);
73  			} catch (PrivilegedActionException e) {
74  				logger.error(sm.getString("cwiAuthenticator.obtainFailed"), e.getException());
75  
76  				sendUnauthorized(request, response, CURRENT_WINDOWS_IDENTITY_AUTH_SCHEME,
77  						"cwiAuthenticator.obtainFailed");
78  				return false;
79  			}
80  
81  			try {
82  				Realm realm = context.getRealm();
83  				GSSName gssName = gssCredential.getName();
84  
85  				Principal principal = realm.authenticate(gssName,
86  						isStoreDelegatedCredential() ? gssCredential : null);
87  
88  				if (principal != null) {
89  					register(request, response, principal, getAuthMethod(), principal.getName(),
90  							null);
91  					return true;
92  				} else {
93  					sendUnauthorized(request, response, CURRENT_WINDOWS_IDENTITY_AUTH_SCHEME,
94  							"gssAuthenticatorBase.userNotFound", gssName);
95  					return false;
96  				}
97  			} catch (GSSException e) {
98  				logger.error(sm.getString("gssAuthenticatorBase.inquireNameFailed"), e);
99  
100 				sendInternalServerError(request, response, "gssAuthenticatorBase.inquireNameFailed");
101 				return false;
102 			}
103 		} finally {
104 			if (lc != null) {
105 				try {
106 					lc.logout();
107 				} catch (LoginException e) {
108 					; // Ignore
109 				}
110 			}
111 		}
112 	}
113 
114 	@Override
115 	protected String getAuthMethod() {
116 		return CURRENT_WINDOWS_IDENTITY_METHOD;
117 	}
118 
119 }