1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.ws.security.message.token;
21
22 import java.security.Principal;
23 import java.util.Set;
24
25 import javax.crypto.SecretKey;
26 import javax.security.auth.Subject;
27 import javax.security.auth.callback.CallbackHandler;
28 import javax.security.auth.kerberos.KerberosTicket;
29 import javax.security.auth.login.LoginContext;
30 import javax.security.auth.login.LoginException;
31
32 import org.apache.ws.security.WSConstants;
33 import org.apache.ws.security.WSSecurityException;
34 import org.w3c.dom.Document;
35 import org.w3c.dom.Element;
36
37
38
39
40 public class KerberosSecurity extends BinarySecurity {
41
42 private static org.apache.commons.logging.Log log =
43 org.apache.commons.logging.LogFactory.getLog(KerberosSecurity.class);
44 private SecretKey secretKey;
45
46
47
48
49
50
51
52
53 public KerberosSecurity(Element elem) throws WSSecurityException {
54 this(elem, true);
55 }
56
57
58
59
60
61
62
63
64
65 public KerberosSecurity(Element elem, boolean bspCompliant) throws WSSecurityException {
66 super(elem, bspCompliant);
67 String valueType = getValueType();
68 if (bspCompliant && !WSConstants.WSS_GSS_KRB_V5_AP_REQ.equals(valueType)) {
69 throw new WSSecurityException(
70 WSSecurityException.INVALID_SECURITY_TOKEN,
71 "invalidValueType",
72 new Object[]{valueType}
73 );
74 }
75 }
76
77
78
79
80
81
82 public KerberosSecurity(Document doc) {
83 super(doc);
84 }
85
86
87
88
89 public boolean isV5ApReq() {
90 String type = getValueType();
91 if (WSConstants.WSS_KRB_V5_AP_REQ.equals(type)
92 || WSConstants.WSS_KRB_V5_AP_REQ1510.equals(type)
93 || WSConstants.WSS_KRB_V5_AP_REQ4120.equals(type)) {
94 return true;
95 }
96 return false;
97 }
98
99
100
101
102 public boolean isGssV5ApReq() {
103 String type = getValueType();
104 if (WSConstants.WSS_GSS_KRB_V5_AP_REQ.equals(type)
105 || WSConstants.WSS_GSS_KRB_V5_AP_REQ1510.equals(type)
106 || WSConstants.WSS_GSS_KRB_V5_AP_REQ4120.equals(type)) {
107 return true;
108 }
109 return false;
110 }
111
112
113
114
115
116
117
118
119
120 public void retrieveServiceTicket(
121 String jaasLoginModuleName,
122 CallbackHandler callbackHandler,
123 String serviceName
124 ) throws WSSecurityException {
125
126 LoginContext loginContext = null;
127 try {
128 if (callbackHandler == null) {
129 loginContext = new LoginContext(jaasLoginModuleName);
130 } else {
131 loginContext = new LoginContext(jaasLoginModuleName, callbackHandler);
132 }
133 loginContext.login();
134 } catch (LoginException ex) {
135 if (log.isDebugEnabled()) {
136 log.debug(ex.getMessage(), ex);
137 }
138 throw new WSSecurityException(
139 WSSecurityException.FAILURE,
140 "kerberosLoginError",
141 new Object[] {ex.getMessage()},
142 ex
143 );
144 }
145 if (log.isDebugEnabled()) {
146 log.debug("Successfully authenticated to the TGT");
147 }
148
149 Subject clientSubject = loginContext.getSubject();
150 Set<Principal> clientPrincipals = clientSubject.getPrincipals();
151 if (clientPrincipals.isEmpty()) {
152 throw new WSSecurityException(
153 WSSecurityException.FAILURE,
154 "kerberosLoginError",
155 new Object[] {"No Client principals found after login"}
156 );
157 }
158
159 KerberosTicket tgt = getKerberosTicket(clientSubject, null);
160
161
162 KerberosClientAction action =
163 new KerberosClientAction(clientPrincipals.iterator().next(), serviceName);
164 byte[] ticket = (byte[])Subject.doAs(clientSubject, action);
165 if (ticket == null) {
166 throw new WSSecurityException(
167 WSSecurityException.FAILURE, "kerberosServiceTicketError"
168 );
169 }
170 if (log.isDebugEnabled()) {
171 log.debug("Successfully retrieved a service ticket");
172 }
173
174
175 KerberosTicket serviceTicket = getKerberosTicket(clientSubject, tgt);
176 if (serviceTicket != null) {
177 secretKey = serviceTicket.getSessionKey();
178 }
179
180 setToken(ticket);
181
182 if ("".equals(getValueType())) {
183 setValueType(WSConstants.WSS_GSS_KRB_V5_AP_REQ);
184 }
185 }
186
187
188
189
190
191 private KerberosTicket getKerberosTicket(Subject clientSubject, KerberosTicket previousTicket) {
192 Set<KerberosTicket> privateCredentials = clientSubject.getPrivateCredentials(KerberosTicket.class);
193 if (privateCredentials == null || privateCredentials.isEmpty()) {
194 if (log.isDebugEnabled()) {
195 log.debug("Kerberos client subject private credentials are null");
196 }
197 return null;
198 }
199
200 for (KerberosTicket privateCredential : privateCredentials) {
201 if (!privateCredential.equals(previousTicket)) {
202 return privateCredential;
203 }
204 }
205 return null;
206 }
207
208
209
210
211
212 public SecretKey getSecretKey() {
213 return secretKey;
214 }
215
216
217
218
219
220
221 public static boolean isKerberosToken(String valueType) {
222 if (WSConstants.WSS_KRB_V5_AP_REQ.equals(valueType)
223 || WSConstants.WSS_GSS_KRB_V5_AP_REQ.equals(valueType)
224 || WSConstants.WSS_KRB_V5_AP_REQ1510.equals(valueType)
225 || WSConstants.WSS_GSS_KRB_V5_AP_REQ1510.equals(valueType)
226 || WSConstants.WSS_KRB_V5_AP_REQ4120.equals(valueType)
227 || WSConstants.WSS_GSS_KRB_V5_AP_REQ4120.equals(valueType)) {
228 return true;
229 }
230 return false;
231 }
232
233 }