View Javadoc
1   /*
2    * SPDX-License-Identifier: MIT
3    * See LICENSE file for details.
4    *
5    * Copyright 2010-2026 The Waffle Project Contributors: https://github.com/Waffle/waffle/graphs/contributors
6    */
7   package waffle.shiro.negotiate;
8   
9   import java.security.Principal;
10  
11  import javax.security.auth.Subject;
12  
13  import org.apache.shiro.authc.AuthenticationException;
14  import org.apache.shiro.authc.AuthenticationInfo;
15  import org.apache.shiro.authc.AuthenticationToken;
16  import org.apache.shiro.realm.AuthenticatingRealm;
17  import org.slf4j.Logger;
18  import org.slf4j.LoggerFactory;
19  
20  import waffle.servlet.WindowsPrincipal;
21  import waffle.windows.auth.IWindowsAuthProvider;
22  import waffle.windows.auth.IWindowsIdentity;
23  import waffle.windows.auth.IWindowsSecurityContext;
24  import waffle.windows.auth.impl.WindowsAuthProviderImpl;
25  
26  /**
27   * The Class NegotiateAuthenticationRealm. Derived from
28   * net.skorgenes.security.jsecurity.negotiate.NegotiateAuthenticationFilter.
29   */
30  public class NegotiateAuthenticationRealm extends AuthenticatingRealm {
31  
32      /**
33       * This class's private logger.
34       */
35      private static final Logger LOGGER = LoggerFactory.getLogger(NegotiateAuthenticationRealm.class);
36  
37      /** The windows auth provider. */
38      private final IWindowsAuthProvider windowsAuthProvider;
39  
40      /**
41       * Instantiates a new negotiate authentication realm.
42       */
43      public NegotiateAuthenticationRealm() {
44          this.windowsAuthProvider = new WindowsAuthProviderImpl();
45      }
46  
47      @Override
48      public boolean supports(final AuthenticationToken token) {
49          return token instanceof NegotiateToken;
50      }
51  
52      @Override
53      protected AuthenticationInfo doGetAuthenticationInfo(final AuthenticationToken t) {
54  
55          final NegotiateToken token = (NegotiateToken) t;
56          final byte[] inToken = token.getIn();
57  
58          if (token.isNtlmPost()) {
59              // type 2 NTLM authentication message received
60              this.windowsAuthProvider.resetSecurityToken(token.getConnectionId());
61          }
62  
63          final IWindowsSecurityContext securityContext;
64          try {
65              securityContext = this.windowsAuthProvider.acceptSecurityToken(token.getConnectionId(), inToken,
66                      token.getSecurityPackage());
67          } catch (final Exception e) {
68              NegotiateAuthenticationRealm.LOGGER.warn("error logging in user");
69              throw new AuthenticationException(e);
70          }
71  
72          final byte[] continueTokenBytes = securityContext.getToken();
73          token.setOut(continueTokenBytes);
74          if (continueTokenBytes != null) {
75              NegotiateAuthenticationRealm.LOGGER.debug("continue token bytes: {}",
76                      Integer.valueOf(continueTokenBytes.length));
77          } else {
78              NegotiateAuthenticationRealm.LOGGER.debug("no continue token bytes");
79          }
80  
81          if (securityContext.isContinue() || token.isNtlmPost()) {
82              throw new AuthenticationInProgressException();
83          }
84  
85          final IWindowsIdentity windowsIdentity = securityContext.getIdentity();
86          securityContext.dispose();
87  
88          NegotiateAuthenticationRealm.LOGGER.debug("logged in user: {} ({})", windowsIdentity.getFqn(),
89                  windowsIdentity.getSidString());
90  
91          final Principal principal = new WindowsPrincipal(windowsIdentity);
92          token.setPrincipal(principal);
93  
94          final Subject subject = new Subject();
95          subject.getPrincipals().add(principal);
96          token.setSubject(subject);
97  
98          return token.createInfo();
99      }
100 
101 }