1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.wss4j.stax.impl.securityToken;
20
21 import java.io.IOException;
22 import java.security.Key;
23 import java.security.Principal;
24 import java.security.PrivilegedActionException;
25 import java.util.Set;
26
27 import javax.security.auth.Subject;
28 import javax.security.auth.callback.Callback;
29 import javax.security.auth.callback.CallbackHandler;
30 import javax.security.auth.callback.UnsupportedCallbackException;
31 import javax.security.auth.login.LoginContext;
32 import javax.security.auth.login.LoginException;
33
34 import org.apache.wss4j.common.ext.WSSecurityException;
35 import org.apache.wss4j.common.ext.WSSecurityException.ErrorCode;
36 import org.apache.wss4j.common.kerberos.KerberosContextAndServiceNameCallback;
37 import org.apache.wss4j.common.kerberos.KerberosServiceContext;
38 import org.apache.wss4j.common.kerberos.KerberosServiceExceptionAction;
39 import org.apache.wss4j.common.kerberos.KerberosTokenDecoder;
40 import org.apache.wss4j.common.kerberos.KerberosTokenDecoderException;
41 import org.apache.wss4j.common.util.KeyUtils;
42 import org.apache.wss4j.stax.ext.WSInboundSecurityContext;
43 import org.apache.wss4j.stax.securityToken.KerberosServiceSecurityToken;
44 import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants;
45 import org.apache.xml.security.exceptions.XMLSecurityException;
46 import org.apache.xml.security.stax.ext.XMLSecurityConstants;
47 import org.apache.xml.security.stax.impl.securityToken.AbstractInboundSecurityToken;
48
49 public class KerberosServiceSecurityTokenImpl extends AbstractInboundSecurityToken implements KerberosServiceSecurityToken {
50
51 private CallbackHandler callbackHandler;
52 private byte[] binaryContent;
53 private String kerberosTokenValueType;
54
55 private KerberosTokenDecoder kerberosTokenDecoder;
56 private Subject subject;
57 private Principal principal;
58 private byte[] sessionKey;
59
60 public KerberosServiceSecurityTokenImpl(WSInboundSecurityContext wsInboundSecurityContext, CallbackHandler callbackHandler,
61 byte[] binaryContent, String kerberosTokenValueType, String id,
62 WSSecurityTokenConstants.KeyIdentifier keyIdentifier) {
63 super(wsInboundSecurityContext, id, keyIdentifier, true);
64 this.callbackHandler = callbackHandler;
65 this.binaryContent = binaryContent;
66 this.kerberosTokenValueType = kerberosTokenValueType;
67 }
68
69 @Override
70 public boolean isAsymmetric() throws XMLSecurityException {
71 return false;
72 }
73
74 @Override
75 public WSSecurityTokenConstants.TokenType getTokenType() {
76 return WSSecurityTokenConstants.KERBEROS_TOKEN;
77 }
78
79 protected byte[] getTGTSessionKey() throws WSSecurityException {
80 if (sessionKey != null) {
81 return sessionKey;
82 }
83 try {
84 KerberosContextAndServiceNameCallback contextAndServiceNameCallback = new KerberosContextAndServiceNameCallback();
85 callbackHandler.handle(new Callback[]{contextAndServiceNameCallback});
86
87 if (contextAndServiceNameCallback.getContextName() == null) {
88 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "kerberosCallbackContextNameNotSupplied");
89 }
90 if (contextAndServiceNameCallback.getServiceName() == null) {
91 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "kerberosCallbackServiceNameNotSupplied");
92 }
93
94 LoginContext loginContext = new LoginContext(contextAndServiceNameCallback.getContextName(), callbackHandler);
95 loginContext.login();
96
97
98 this.subject = loginContext.getSubject();
99
100 String service = contextAndServiceNameCallback.getServiceName();
101 if (service == null) {
102 Set<Principal> principals = subject.getPrincipals();
103 if (principals.isEmpty()) {
104 throw new WSSecurityException(
105 WSSecurityException.ErrorCode.FAILURE,
106 "kerberosLoginError",
107 new Object[] {"No Client principals found after login"}
108 );
109 }
110 service = principals.iterator().next().getName();
111 }
112
113 KerberosServiceExceptionAction action =
114 new KerberosServiceExceptionAction(binaryContent,
115 service,
116 contextAndServiceNameCallback.isUsernameServiceNameForm(),
117 false);
118 KerberosServiceContext krbServiceCtx = null;
119 try {
120 krbServiceCtx = Subject.doAs(subject, action);
121 } catch (PrivilegedActionException e) {
122 Throwable cause = e.getCause();
123 if (cause instanceof WSSecurityException) {
124 throw (WSSecurityException) cause;
125 } else {
126 throw new WSSecurityException(
127 ErrorCode.FAILURE, new Exception(cause), "kerberosTicketValidationError"
128 );
129 }
130 }
131
132 this.principal = krbServiceCtx.getPrincipal();
133
134 Key key = krbServiceCtx.getSessionKey();
135 if (key != null) {
136 sessionKey = key.getEncoded();
137 } else if (kerberosTokenDecoder != null) {
138 kerberosTokenDecoder.clear();
139 kerberosTokenDecoder.setToken(binaryContent);
140 kerberosTokenDecoder.setSubject(subject);
141 sessionKey = kerberosTokenDecoder.getSessionKey();
142 }
143
144 return sessionKey;
145 } catch (LoginException | UnsupportedCallbackException | IOException e) {
146 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e);
147 } catch (KerberosTokenDecoderException e) {
148 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY_TOKEN, e);
149 }
150 }
151
152 @Override
153 protected Key getKey(String algorithmURI, XMLSecurityConstants.AlgorithmUsage algorithmUsage,
154 String correlationID) throws XMLSecurityException {
155
156 Key key = getSecretKey().get(algorithmURI);
157 if (key != null) {
158 return key;
159 }
160
161 byte[] sk = getTGTSessionKey();
162
163 key = KeyUtils.prepareSecretKey(algorithmURI, sk);
164 setSecretKey(algorithmURI, key);
165 return key;
166 }
167
168 public byte[] getBinaryContent() {
169 return binaryContent;
170 }
171
172 public String getKerberosTokenValueType() {
173 return kerberosTokenValueType;
174 }
175
176 @Override
177 public Subject getSubject() throws WSSecurityException {
178 return subject;
179 }
180
181 @Override
182 public Principal getPrincipal() throws WSSecurityException {
183 return principal;
184 }
185
186
187
188
189
190
191 public KerberosTokenDecoder getKerberosTokenDecoder() {
192 return kerberosTokenDecoder;
193 }
194
195
196
197
198
199
200 public void setKerberosTokenDecoder(KerberosTokenDecoder kerberosTokenDecoder) {
201 this.kerberosTokenDecoder = kerberosTokenDecoder;
202 }
203 }