1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.wss4j.common.spnego;
21
22 import java.security.Principal;
23 import java.security.PrivilegedActionException;
24 import java.util.Set;
25
26 import javax.security.auth.Subject;
27 import javax.security.auth.callback.CallbackHandler;
28 import javax.security.auth.login.LoginContext;
29 import javax.security.auth.login.LoginException;
30
31 import org.apache.wss4j.common.ext.WSSecurityException;
32 import org.apache.wss4j.common.ext.WSSecurityException.ErrorCode;
33 import org.apache.wss4j.common.kerberos.KerberosClientExceptionAction;
34 import org.apache.wss4j.common.kerberos.KerberosContext;
35 import org.apache.wss4j.common.kerberos.KerberosServiceContext;
36 import org.apache.wss4j.common.kerberos.KerberosServiceExceptionAction;
37 import org.ietf.jgss.GSSContext;
38 import org.ietf.jgss.GSSCredential;
39 import org.ietf.jgss.GSSException;
40 import org.ietf.jgss.MessageProp;
41
42
43
44
45 public class SpnegoTokenContext {
46
47 private static final org.slf4j.Logger LOG =
48 org.slf4j.LoggerFactory.getLogger(SpnegoTokenContext.class);
49
50 private GSSContext secContext;
51 private byte[] token;
52 private boolean mutualAuth;
53 private SpnegoClientAction clientAction;
54 private SpnegoServiceAction serviceAction;
55 private GSSCredential delegationCredential;
56 private Principal spnegoPrincipal;
57
58
59
60
61
62
63
64
65
66 public void retrieveServiceTicket(
67 String jaasLoginModuleName,
68 CallbackHandler callbackHandler,
69 String serviceName
70 ) throws WSSecurityException {
71 retrieveServiceTicket(jaasLoginModuleName, callbackHandler, serviceName, false);
72 }
73
74
75
76
77
78
79
80
81
82
83
84 public void retrieveServiceTicket(
85 String jaasLoginModuleName,
86 CallbackHandler callbackHandler,
87 String serviceName,
88 boolean isUsernameServiceNameForm
89 ) throws WSSecurityException {
90 retrieveServiceTicket(jaasLoginModuleName, callbackHandler, serviceName,
91 isUsernameServiceNameForm, false, null);
92 }
93
94
95
96
97
98
99
100
101
102
103
104
105 public void retrieveServiceTicket(
106 String jaasLoginModuleName,
107 CallbackHandler callbackHandler,
108 String serviceName,
109 boolean isUsernameServiceNameForm,
110 boolean requestCredDeleg,
111 GSSCredential delegationCredential
112 ) throws WSSecurityException {
113
114
115 LoginContext loginContext = null;
116 try {
117 if (callbackHandler == null) {
118 loginContext = new LoginContext(jaasLoginModuleName);
119 } else {
120 loginContext = new LoginContext(jaasLoginModuleName, callbackHandler);
121 }
122 loginContext.login();
123 } catch (LoginException ex) {
124 LOG.debug(ex.getMessage(), ex);
125 throw new WSSecurityException(
126 WSSecurityException.ErrorCode.FAILURE, ex, "kerberosLoginError",
127 new Object[] {ex.getMessage()});
128 }
129 LOG.debug("Successfully authenticated to the TGT");
130
131 Subject clientSubject = loginContext.getSubject();
132 Set<Principal> clientPrincipals = clientSubject.getPrincipals();
133 if (clientPrincipals.isEmpty()) {
134 throw new WSSecurityException(
135 WSSecurityException.ErrorCode.FAILURE,
136 "kerberosLoginError",
137 new Object[] {"No Client principals found after login"});
138 }
139
140
141 if (clientAction != null) {
142 clientAction.setServiceName(serviceName);
143 clientAction.setMutualAuth(mutualAuth);
144 clientAction.setUserNameServiceForm(isUsernameServiceNameForm);
145 token = Subject.doAs(clientSubject, clientAction);
146 if (token == null) {
147 throw new WSSecurityException(
148 WSSecurityException.ErrorCode.FAILURE, "kerberosServiceTicketError"
149 );
150 }
151
152 secContext = clientAction.getContext();
153 } else {
154 KerberosClientExceptionAction action =
155 new KerberosClientExceptionAction(null, serviceName,
156 isUsernameServiceNameForm,
157 requestCredDeleg,
158 delegationCredential,
159 true,
160 mutualAuth);
161 KerberosContext krbCtx = null;
162 try {
163 krbCtx = (KerberosContext) Subject.doAs(clientSubject, action);
164
165 token = krbCtx.getKerberosToken();
166 if (token == null) {
167 throw new WSSecurityException(
168 WSSecurityException.ErrorCode.FAILURE, "kerberosServiceTicketError"
169 );
170 }
171
172 secContext = krbCtx.getGssContext();
173 } catch (PrivilegedActionException e) {
174 Throwable cause = e.getCause();
175 if (cause instanceof WSSecurityException) {
176 throw (WSSecurityException) cause;
177 } else {
178 throw new WSSecurityException(
179 ErrorCode.FAILURE, new Exception(cause), "kerberosServiceTicketError"
180 );
181 }
182 }
183 }
184
185 LOG.debug("Successfully retrieved a service ticket");
186 }
187
188
189
190
191
192
193
194
195
196 public void validateServiceTicket(
197 String jaasLoginModuleName,
198 CallbackHandler callbackHandler,
199 String serviceName,
200 byte[] ticket
201 ) throws WSSecurityException {
202 validateServiceTicket(jaasLoginModuleName, callbackHandler, serviceName, false, ticket);
203 }
204
205
206
207
208
209
210
211
212
213 public void validateServiceTicket(
214 String jaasLoginModuleName,
215 CallbackHandler callbackHandler,
216 String serviceName,
217 boolean isUsernameServiceNameForm,
218 byte[] ticket
219 ) throws WSSecurityException {
220
221 LoginContext loginContext = null;
222 try {
223 if (callbackHandler == null) {
224 loginContext = new LoginContext(jaasLoginModuleName);
225 } else {
226 loginContext = new LoginContext(jaasLoginModuleName, callbackHandler);
227 }
228 loginContext.login();
229 } catch (LoginException ex) {
230 LOG.debug(ex.getMessage(), ex);
231 throw new WSSecurityException(
232 WSSecurityException.ErrorCode.FAILURE, ex, "kerberosLoginError",
233 new Object[] {ex.getMessage()});
234 }
235 LOG.debug("Successfully authenticated to the TGT");
236
237
238 Subject subject = loginContext.getSubject();
239 String service = serviceName;
240 if (service == null) {
241 Set<Principal> principals = subject.getPrincipals();
242 if (principals.isEmpty()) {
243 throw new WSSecurityException(
244 WSSecurityException.ErrorCode.FAILURE,
245 "kerberosLoginError",
246 new Object[] {"No Client principals found after login"});
247 }
248 service = principals.iterator().next().getName();
249 }
250
251
252 if (serviceAction != null) {
253 serviceAction.setTicket(ticket);
254 serviceAction.setServiceName(service);
255 serviceAction.setUsernameServiceNameForm(isUsernameServiceNameForm);
256 token = Subject.doAs(subject, serviceAction);
257 secContext = serviceAction.getContext();
258 } else {
259 KerberosServiceExceptionAction action =
260 new KerberosServiceExceptionAction(ticket, service,
261 isUsernameServiceNameForm, true);
262 KerberosServiceContext krbCtx = null;
263 try {
264 krbCtx = (KerberosServiceContext) Subject.doAs(subject, action);
265
266 token = krbCtx.getKerberosToken();
267 if (token == null) {
268 throw new WSSecurityException(
269 WSSecurityException.ErrorCode.FAILURE, "kerberosServiceTicketError"
270 );
271 }
272
273 secContext = krbCtx.getGssContext();
274 delegationCredential = krbCtx.getDelegationCredential();
275 spnegoPrincipal = krbCtx.getPrincipal();
276 } catch (PrivilegedActionException e) {
277 Throwable cause = e.getCause();
278 if (cause instanceof WSSecurityException) {
279 throw (WSSecurityException) cause;
280 } else {
281 throw new WSSecurityException(
282 ErrorCode.FAILURE, new Exception(cause), "kerberosServiceTicketError"
283 );
284 }
285 }
286 }
287
288 LOG.debug("Successfully validated a service ticket");
289 }
290
291
292
293
294 public void setMutualAuth(boolean mutualAuthentication) {
295 mutualAuth = mutualAuthentication;
296 }
297
298
299
300
301 public byte[] getToken() {
302 return token;
303 }
304
305
306
307
308 public boolean isEstablished() {
309 if (secContext == null) {
310 return false;
311 }
312 return secContext.isEstablished();
313 }
314
315
316
317
318 public byte[] unwrapKey(byte[] secret) throws WSSecurityException {
319 MessageProp mProp = new MessageProp(0, true);
320 try {
321 return secContext.unwrap(secret, 0, secret.length, mProp);
322 } catch (GSSException e) {
323 LOG.debug("Error in cleaning up a GSS context", e);
324 throw new WSSecurityException(
325 WSSecurityException.ErrorCode.FAILURE, e, "spnegoKeyError"
326 );
327 }
328 }
329
330
331
332
333 public byte[] wrapKey(byte[] secret) throws WSSecurityException {
334 MessageProp mProp = new MessageProp(0, true);
335 try {
336 return secContext.wrap(secret, 0, secret.length, mProp);
337 } catch (GSSException e) {
338 LOG.debug("Error in cleaning up a GSS context", e);
339 throw new WSSecurityException(
340 WSSecurityException.ErrorCode.FAILURE, e, "spnegoKeyError"
341 );
342 }
343 }
344
345
346
347
348 public void setSpnegoClientAction(SpnegoClientAction spnegoClientAction) {
349 this.clientAction = spnegoClientAction;
350 }
351
352
353
354
355 public void setSpnegoServiceAction(SpnegoServiceAction spnegoServiceAction) {
356 this.serviceAction = spnegoServiceAction;
357 }
358
359 public void clear() {
360 token = null;
361 mutualAuth = false;
362 delegationCredential = null;
363 spnegoPrincipal = null;
364 try {
365 secContext.dispose();
366 } catch (GSSException e) {
367 LOG.debug("Error in cleaning up a GSS context", e);
368 }
369 }
370
371 public GSSCredential getDelegationCredential() {
372 return delegationCredential;
373 }
374
375 public Principal getSpnegoPrincipal() {
376 return spnegoPrincipal;
377 }
378
379 }