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.shiro.negotiate;
15  
16  /**
17   * Derived from net.skorgenes.security.jsecurity.negotiate.NegotiateAuthenticationFilter.
18   * see: https://bitbucket.org/lothor/shiro-negotiate/src/7b25efde130b/src/main/java/net/skorgenes/security/jsecurity/negotiate/NegotiateAuthenticationRealm.java?at=default
19   *
20   * @author Dan Rollo
21   */
22  import javax.security.auth.Subject;
23  
24  import org.apache.shiro.authc.AuthenticationException;
25  import org.apache.shiro.authc.AuthenticationInfo;
26  import org.apache.shiro.authc.AuthenticationToken;
27  import org.apache.shiro.realm.AuthenticatingRealm;
28  
29  import org.slf4j.Logger;
30  import org.slf4j.LoggerFactory;
31  
32  import waffle.servlet.WindowsPrincipal;
33  import waffle.windows.auth.IWindowsAuthProvider;
34  import waffle.windows.auth.IWindowsIdentity;
35  import waffle.windows.auth.IWindowsSecurityContext;
36  import waffle.windows.auth.impl.WindowsAuthProviderImpl;
37  
38  import java.security.Principal;
39  
40  /**
41   * The Class NegotiateAuthenticationRealm.
42   */
43  public class NegotiateAuthenticationRealm extends AuthenticatingRealm {
44  
45      /**
46       * This class's private logger.
47       */
48      private static final Logger        LOGGER = LoggerFactory.getLogger(NegotiateAuthenticationRealm.class);
49  
50      /** The windows auth provider. */
51      private final IWindowsAuthProvider windowsAuthProvider;
52  
53      /**
54       * Instantiates a new negotiate authentication realm.
55       */
56      public NegotiateAuthenticationRealm() {
57          this.windowsAuthProvider = new WindowsAuthProviderImpl();
58      }
59  
60      /* (non-Javadoc)
61       * @see org.apache.shiro.realm.AuthenticatingRealm#supports(org.apache.shiro.authc.AuthenticationToken)
62       */
63      @Override
64      public boolean supports(final AuthenticationToken token) {
65          return token instanceof NegotiateToken;
66      }
67  
68      /* (non-Javadoc)
69       * @see org.apache.shiro.realm.AuthenticatingRealm#doGetAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken)
70       */
71      @Override
72      protected AuthenticationInfo doGetAuthenticationInfo(final AuthenticationToken t) {
73  
74          final NegotiateToken token = (NegotiateToken) t;
75          final byte[] inToken = token.getIn();
76  
77          if (token.isNtlmPost()) {
78              // type 2 NTLM authentication message received
79              this.windowsAuthProvider.resetSecurityToken(token.getConnectionId());
80          }
81  
82          final IWindowsSecurityContext securityContext;
83          try {
84              securityContext = this.windowsAuthProvider.acceptSecurityToken(token.getConnectionId(), inToken,
85                      token.getSecurityPackage());
86          } catch (final Exception e) {
87              NegotiateAuthenticationRealm.LOGGER.warn("error logging in user: {}", e.getMessage());
88              throw new AuthenticationException(e);
89          }
90  
91          final byte[] continueTokenBytes = securityContext.getToken();
92          token.setOut(continueTokenBytes);
93          if (continueTokenBytes != null) {
94              NegotiateAuthenticationRealm.LOGGER.debug("continue token bytes: {}", Integer.valueOf(continueTokenBytes.length));
95          } else {
96              NegotiateAuthenticationRealm.LOGGER.debug("no continue token bytes");
97          }
98  
99          if (securityContext.isContinue() || token.isNtlmPost()) {
100             throw new AuthenticationInProgressException();
101         }
102 
103         final IWindowsIdentity windowsIdentity = securityContext.getIdentity();
104         securityContext.dispose();
105 
106         NegotiateAuthenticationRealm.LOGGER.debug("logged in user: {} ({})", windowsIdentity.getFqn(), windowsIdentity.getSidString());
107 
108         final Principal principal = new WindowsPrincipal(windowsIdentity);
109         token.setPrincipal(principal);
110 
111         final Subject subject = new Subject();
112         subject.getPrincipals().add(principal);
113         token.setSubject(subject);
114 
115         return token.createInfo();
116     }
117 }