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.windows.auth.impl;
15  
16  import waffle.windows.auth.IWindowsCredentialsHandle;
17  import waffle.windows.auth.IWindowsIdentity;
18  import waffle.windows.auth.IWindowsImpersonationContext;
19  import waffle.windows.auth.IWindowsSecurityContext;
20  
21  import com.sun.jna.platform.win32.Secur32;
22  import com.sun.jna.platform.win32.Sspi;
23  import com.sun.jna.platform.win32.Sspi.CredHandle;
24  import com.sun.jna.platform.win32.Sspi.CtxtHandle;
25  import com.sun.jna.platform.win32.Sspi.SecBufferDesc;
26  import com.sun.jna.platform.win32.Win32Exception;
27  import com.sun.jna.platform.win32.WinError;
28  import com.sun.jna.platform.win32.WinNT.HANDLEByReference;
29  import com.sun.jna.ptr.IntByReference;
30  
31  /**
32   * Windows Security Context.
33   * 
34   * @author dblock[at]dblock[dot]org
35   */
36  public class WindowsSecurityContextImpl implements IWindowsSecurityContext {
37  
38      /** The principal name. */
39      private String         principalName;
40      
41      /** The security package. */
42      private String         securityPackage;
43      
44      /** The token. */
45      private SecBufferDesc  token;
46      
47      /** The ctx. */
48      private CtxtHandle     ctx;
49      
50      /** The attr. */
51      private IntByReference attr;
52      
53      /** The credentials. */
54      private CredHandle     credentials;
55      
56      /** The continue flag. */
57      private boolean        continueFlag;
58  
59      /* (non-Javadoc)
60       * @see waffle.windows.auth.IWindowsSecurityContext#impersonate()
61       */
62      @Override
63      public IWindowsImpersonationContext impersonate() {
64          return new WindowsSecurityContextImpersonationContextImpl(this.ctx);
65      }
66  
67      /* (non-Javadoc)
68       * @see waffle.windows.auth.IWindowsSecurityContext#getIdentity()
69       */
70      @Override
71      public IWindowsIdentity getIdentity() {
72          final HANDLEByReference phContextToken = new HANDLEByReference();
73          final int rc = Secur32.INSTANCE.QuerySecurityContextToken(this.ctx, phContextToken);
74          if (WinError.SEC_E_OK != rc) {
75              throw new Win32Exception(rc);
76          }
77          return new WindowsIdentityImpl(phContextToken.getValue());
78      }
79  
80      /* (non-Javadoc)
81       * @see waffle.windows.auth.IWindowsSecurityContext#getSecurityPackage()
82       */
83      @Override
84      public String getSecurityPackage() {
85          return this.securityPackage;
86      }
87  
88      /* (non-Javadoc)
89       * @see waffle.windows.auth.IWindowsSecurityContext#getToken()
90       */
91      @Override
92      public byte[] getToken() {
93          return this.token == null || this.token.getBytes() == null ? null : this.token.getBytes().clone();
94      }
95  
96      /**
97       * Get the current Windows security context for a given SSPI package.
98       * 
99       * @param securityPackage
100      *            SSPI package.
101      * @param targetName
102      *            The target of the context. The string contents are security-package specific.
103      * @return Windows security context.
104      */
105     public static IWindowsSecurityContext getCurrent(final String securityPackage, final String targetName) {
106         final IWindowsCredentialsHandle credentialsHandle = WindowsCredentialsHandleImpl.getCurrent(securityPackage);
107         credentialsHandle.initialize();
108         try {
109             final WindowsSecurityContextImpl ctx = new WindowsSecurityContextImpl();
110             ctx.setPrincipalName(WindowsAccountImpl.getCurrentUsername());
111             ctx.setCredentialsHandle(credentialsHandle.getHandle());
112             ctx.setSecurityPackage(securityPackage);
113             ctx.initialize(null, null, targetName);
114             return ctx;
115         } finally {
116             credentialsHandle.dispose();
117         }
118     }
119 
120     /* (non-Javadoc)
121      * @see waffle.windows.auth.IWindowsSecurityContext#initialize(com.sun.jna.platform.win32.Sspi.CtxtHandle, com.sun.jna.platform.win32.Sspi.SecBufferDesc, java.lang.String)
122      */
123     @Override
124     public void initialize(final CtxtHandle continueCtx, final SecBufferDesc continueToken, final String targetName) {
125         this.attr = new IntByReference();
126         this.ctx = new CtxtHandle();
127         int tokenSize = Sspi.MAX_TOKEN_SIZE;
128         int rc = 0;
129         do {
130             this.token = new SecBufferDesc(Sspi.SECBUFFER_TOKEN, tokenSize);
131             rc = Secur32.INSTANCE.InitializeSecurityContext(this.credentials, continueCtx, targetName,
132                     Sspi.ISC_REQ_CONNECTION, 0, Sspi.SECURITY_NATIVE_DREP, continueToken, 0, this.ctx, this.token,
133                     this.attr, null);
134             switch (rc) {
135                 case WinError.SEC_E_INSUFFICIENT_MEMORY:
136                     tokenSize += Sspi.MAX_TOKEN_SIZE;
137                     break;
138                 case WinError.SEC_I_CONTINUE_NEEDED:
139                     this.continueFlag = true;
140                     break;
141                 case WinError.SEC_E_OK:
142                     this.continueFlag = false;
143                     break;
144                 default:
145                     throw new Win32Exception(rc);
146             }
147         } while (rc == WinError.SEC_E_INSUFFICIENT_MEMORY);
148     }
149 
150     /* (non-Javadoc)
151      * @see waffle.windows.auth.IWindowsSecurityContext#dispose()
152      */
153     @Override
154     public void dispose() {
155         WindowsSecurityContextImpl.dispose(this.ctx);
156     }
157 
158     /**
159      * Dispose a security context.
160      * 
161      * @param ctx
162      *            Security context.
163      * @return True if a context was disposed.
164      */
165     public static boolean dispose(final CtxtHandle ctx) {
166         if (ctx != null && !ctx.isNull()) {
167             final int rc = Secur32.INSTANCE.DeleteSecurityContext(ctx);
168             if (WinError.SEC_E_OK != rc) {
169                 throw new Win32Exception(rc);
170             }
171             return true;
172         }
173         return false;
174     }
175 
176     /* (non-Javadoc)
177      * @see waffle.windows.auth.IWindowsSecurityContext#getPrincipalName()
178      */
179     @Override
180     public String getPrincipalName() {
181         return this.principalName;
182     }
183 
184     /**
185      * Sets the principal name.
186      *
187      * @param value
188      *            the new principal name
189      */
190     public void setPrincipalName(final String value) {
191         this.principalName = value;
192     }
193 
194     /* (non-Javadoc)
195      * @see waffle.windows.auth.IWindowsSecurityContext#getHandle()
196      */
197     @Override
198     public CtxtHandle getHandle() {
199         return this.ctx;
200     }
201 
202     /**
203      * Sets the credentials handle.
204      *
205      * @param handle
206      *            the new credentials handle
207      */
208     public void setCredentialsHandle(final CredHandle handle) {
209         this.credentials = handle;
210     }
211 
212     /**
213      * Sets the token.
214      *
215      * @param bytes
216      *            the new token
217      */
218     public void setToken(final byte[] bytes) {
219         this.token = new SecBufferDesc(Sspi.SECBUFFER_TOKEN, bytes);
220     }
221 
222     /**
223      * Sets the security package.
224      *
225      * @param value
226      *            the new security package
227      */
228     public void setSecurityPackage(final String value) {
229         this.securityPackage = value;
230     }
231 
232     /**
233      * Sets the security context.
234      *
235      * @param phNewServerContext
236      *            the new security context
237      */
238     public void setSecurityContext(final CtxtHandle phNewServerContext) {
239         this.ctx = phNewServerContext;
240     }
241 
242     /* (non-Javadoc)
243      * @see waffle.windows.auth.IWindowsSecurityContext#isContinue()
244      */
245     @Override
246     public boolean isContinue() {
247         return this.continueFlag;
248     }
249 
250     /**
251      * Sets the continue.
252      *
253      * @param b
254      *            the new continue
255      */
256     public void setContinue(final boolean b) {
257         this.continueFlag = b;
258     }
259 
260 }