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