View Javadoc
1   /**
2    * Waffle (https://github.com/dblock/waffle)
3    *
4    * Copyright (c) 2010 - 2015 Application Security, Inc.
5    *
6    * All rights reserved. This program and the accompanying materials
7    * are made available under the terms of the Eclipse Public License v1.0
8    * which accompanies this distribution, and is available at
9    * http://www.eclipse.org/legal/epl-v10.html
10   *
11   * Contributors:
12   *     Application Security, Inc.
13   */
14  package waffle.apache;
15  
16  import java.io.IOException;
17  import java.util.Arrays;
18  import java.util.LinkedHashSet;
19  import java.util.Locale;
20  import java.util.Set;
21  
22  import javax.servlet.http.HttpServletResponse;
23  
24  import org.apache.catalina.authenticator.AuthenticatorBase;
25  import org.apache.catalina.connector.Response;
26  import org.slf4j.Logger;
27  
28  import waffle.windows.auth.IWindowsAuthProvider;
29  import waffle.windows.auth.PrincipalFormat;
30  import waffle.windows.auth.impl.WindowsAuthProviderImpl;
31  
32  /**
33   * The Class WaffleAuthenticatorBase.
34   *
35   * @author dblock[at]dblock[dot]org
36   */
37  abstract class WaffleAuthenticatorBase extends AuthenticatorBase {
38  
39      /** The Constant SUPPORTED_PROTOCOLS. */
40      private static final Set<String> SUPPORTED_PROTOCOLS = new LinkedHashSet<String>(Arrays.asList("Negotiate", "NTLM"));
41  
42      /** The info. */
43      protected String                 info;
44      
45      /** The log. */
46      protected Logger                 log;
47      
48      /** The principal format. */
49      protected PrincipalFormat        principalFormat     = PrincipalFormat.FQN;
50      
51      /** The role format. */
52      protected PrincipalFormat        roleFormat          = PrincipalFormat.FQN;
53      
54      /** The allow guest login. */
55      protected boolean                allowGuestLogin     = true;
56      
57      /** The protocols. */
58      protected Set<String>            protocols           = WaffleAuthenticatorBase.SUPPORTED_PROTOCOLS;
59  
60      /** The auth. */
61      protected IWindowsAuthProvider   auth                = new WindowsAuthProviderImpl();
62  
63      /**
64       * Windows authentication provider.
65       * 
66       * @return IWindowsAuthProvider.
67       */
68      public IWindowsAuthProvider getAuth() {
69          return this.auth;
70      }
71  
72      /**
73       * Set Windows auth provider.
74       * 
75       * @param provider
76       *            Class implements IWindowsAuthProvider.
77       */
78      public void setAuth(final IWindowsAuthProvider provider) {
79          this.auth = provider;
80      }
81  
82      /* (non-Javadoc)
83       * @see org.apache.catalina.authenticator.AuthenticatorBase#getInfo()
84       */
85      @Override
86      public String getInfo() {
87          return this.info;
88      }
89  
90      /**
91       * Set the principal format.
92       * 
93       * @param format
94       *            Principal format.
95       */
96      public void setPrincipalFormat(final String format) {
97          this.principalFormat = PrincipalFormat.valueOf(format.toUpperCase(Locale.ENGLISH));
98          this.log.debug("principal format: {}", this.principalFormat);
99      }
100 
101     /**
102      * Principal format.
103      * 
104      * @return Principal format.
105      */
106     public PrincipalFormat getPrincipalFormat() {
107         return this.principalFormat;
108     }
109 
110     /**
111      * Set the principal format.
112      * 
113      * @param format
114      *            Role format.
115      */
116     public void setRoleFormat(final String format) {
117         this.roleFormat = PrincipalFormat.valueOf(format.toUpperCase(Locale.ENGLISH));
118         this.log.debug("role format: {}", this.roleFormat);
119     }
120 
121     /**
122      * Principal format.
123      * 
124      * @return Role format.
125      */
126     public PrincipalFormat getRoleFormat() {
127         return this.roleFormat;
128     }
129 
130     /**
131      * True if Guest login permitted.
132      * 
133      * @return True if Guest login permitted, false otherwise.
134      */
135     public boolean isAllowGuestLogin() {
136         return this.allowGuestLogin;
137     }
138 
139     /**
140      * Set whether Guest login is permitted. Default is true, if the Guest account is enabled, an invalid
141      * username/password results in a Guest login.
142      * 
143      * @param value
144      *            True or false.
145      */
146     public void setAllowGuestLogin(final boolean value) {
147         this.allowGuestLogin = value;
148     }
149 
150     /**
151      * Set the authentication protocols. Default is "Negotiate, NTLM".
152      * 
153      * @param value
154      *            Authentication protocols
155      */
156     public void setProtocols(final String value) {
157         this.protocols = new LinkedHashSet<String>();
158         final String[] protocolNames = value.split(",");
159         for (String protocolName : protocolNames) {
160             protocolName = protocolName.trim();
161             if (!protocolName.isEmpty()) {
162                 this.log.debug("init protocol: {}", protocolName);
163                 if (WaffleAuthenticatorBase.SUPPORTED_PROTOCOLS.contains(protocolName)) {
164                     this.protocols.add(protocolName);
165                 } else {
166                     this.log.error("unsupported protocol: {}", protocolName);
167                     throw new RuntimeException("Unsupported protocol: " + protocolName);
168                 }
169             }
170         }
171     }
172 
173     /**
174      * Send a 401 Unauthorized along with protocol authentication headers.
175      * 
176      * @param response
177      *            HTTP Response
178      */
179     protected void sendUnauthorized(final Response response) {
180         try {
181             for (final String protocol : this.protocols) {
182                 response.addHeader("WWW-Authenticate", protocol);
183             }
184             response.setHeader("Connection", "close");
185             response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
186             response.flushBuffer();
187         } catch (final IOException e) {
188             throw new RuntimeException(e);
189         }
190     }
191 
192     /**
193      * Send an error code.
194      * 
195      * @param response
196      *            HTTP Response
197      * @param code
198      *            Error Code
199      */
200     protected void sendError(final Response response, final int code) {
201         try {
202             response.sendError(code);
203         } catch (final IOException e) {
204             this.log.error(e.getMessage());
205             this.log.trace("{}", e);
206             throw new RuntimeException(e);
207         }
208     }
209 }