1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.wss4j.common.kerberos;
20
21 import java.lang.reflect.InvocationTargetException;
22 import java.lang.reflect.Method;
23 import java.security.Key;
24 import java.security.PrivilegedExceptionAction;
25
26 import javax.security.auth.kerberos.KerberosPrincipal;
27
28 import org.apache.wss4j.common.ext.WSSecurityException;
29 import org.apache.wss4j.common.ext.WSSecurityException.ErrorCode;
30 import org.ietf.jgss.GSSContext;
31 import org.ietf.jgss.GSSCredential;
32 import org.ietf.jgss.GSSException;
33 import org.ietf.jgss.GSSManager;
34 import org.ietf.jgss.GSSName;
35 import org.ietf.jgss.Oid;
36
37
38 public class KerberosServiceExceptionAction implements PrivilegedExceptionAction<KerberosServiceContext> {
39
40 private static final boolean IS_IBM_VENDOR = System.getProperty("java.vendor").startsWith("IBM");
41
42 private static final String SUN_JGSS_INQUIRE_TYPE_CLASS = "com.sun.security.jgss.InquireType";
43 private static final String SUN_JGSS_EXT_GSSCTX_CLASS = "com.sun.security.jgss.ExtendedGSSContext";
44
45 private static final String IBM_JGSS_INQUIRE_TYPE_CLASS = "com.ibm.security.jgss.InquireType";
46 private static final String IBM_JGSS_EXT_GSSCTX_CLASS = "com.ibm.security.jgss.ExtendedGSSContext";
47
48 private static final String EXTENDED_JGSS_CONTEXT_INQUIRE_SEC_CONTEXT_METHOD_NAME = "inquireSecContext";
49 private static final String EXTENDED_JGSS_CONTEXT_INQUIRE_TYPE_KRB5_GET_SESSION_KEY = "KRB5_GET_SESSION_KEY";
50
51 private static final String JGSS_KERBEROS_TICKET_OID = "1.2.840.113554.1.2.2";
52 private static final String JGSS_SPNEGO_TICKET_OID = "1.3.6.1.5.5.2";
53
54 private static final String KERBEROS_TICKET_VALIDATION_ERROR_MSG_ID = "kerberosTicketValidationError";
55
56 private byte[] ticket;
57 private String serviceName;
58 private boolean isUsernameServiceNameForm;
59 private boolean spnego;
60
61 public KerberosServiceExceptionAction(byte[] ticket, String serviceName, boolean isUsernameServiceNameForm,
62 boolean spnego) {
63 this.ticket = ticket;
64 this.serviceName = serviceName;
65 this.isUsernameServiceNameForm = isUsernameServiceNameForm;
66 this.spnego = spnego;
67 }
68
69
70
71
72
73 public KerberosServiceContext run() throws GSSException, WSSecurityException {
74
75 GSSManager gssManager = GSSManager.getInstance();
76
77 GSSContext secContext = null;
78 GSSName gssService = gssManager.createName(serviceName, isUsernameServiceNameForm
79 ? GSSName.NT_USER_NAME : GSSName.NT_HOSTBASED_SERVICE);
80 if (spnego) {
81 Oid oid = new Oid(JGSS_SPNEGO_TICKET_OID);
82 secContext = gssManager.createContext(gssService, oid, null, GSSContext.DEFAULT_LIFETIME);
83 } else {
84 Oid oid = new Oid(JGSS_KERBEROS_TICKET_OID);
85 GSSCredential credentials =
86 gssManager.createCredential(
87 gssService, GSSCredential.DEFAULT_LIFETIME, oid, GSSCredential.ACCEPT_ONLY
88 );
89 secContext = gssManager.createContext(credentials);
90 }
91
92 KerberosServiceContext krbServiceCtx = null;
93
94 try {
95 byte[] returnedToken = secContext.acceptSecContext(ticket, 0, ticket.length);
96
97 krbServiceCtx = new KerberosServiceContext();
98
99 if (secContext.getCredDelegState()) {
100 krbServiceCtx.setDelegationCredential(secContext.getDelegCred());
101 }
102
103 GSSName clientName = secContext.getSrcName();
104 krbServiceCtx.setPrincipal(new KerberosPrincipal(clientName.toString()));
105 krbServiceCtx.setGssContext(secContext);
106 krbServiceCtx.setKerberosToken(returnedToken);
107
108 try {
109 @SuppressWarnings("rawtypes")
110 Class inquireType = Class.forName(IS_IBM_VENDOR ? IBM_JGSS_INQUIRE_TYPE_CLASS
111 : SUN_JGSS_INQUIRE_TYPE_CLASS);
112
113 @SuppressWarnings("rawtypes")
114 Class extendedGSSContext = Class.forName(IS_IBM_VENDOR ? IBM_JGSS_EXT_GSSCTX_CLASS
115 : SUN_JGSS_EXT_GSSCTX_CLASS);
116
117 @SuppressWarnings("unchecked")
118 Method inquireSecContext =
119 extendedGSSContext.getMethod(EXTENDED_JGSS_CONTEXT_INQUIRE_SEC_CONTEXT_METHOD_NAME, inquireType);
120
121 @SuppressWarnings("unchecked")
122 Object obj = Enum.valueOf(inquireType, EXTENDED_JGSS_CONTEXT_INQUIRE_TYPE_KRB5_GET_SESSION_KEY);
123 Key key = (Key) inquireSecContext.invoke(secContext, obj);
124
125 krbServiceCtx.setSessionKey(key);
126 } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException
127 | InvocationTargetException e) {
128 throw new WSSecurityException(
129 ErrorCode.FAILURE, e, KERBEROS_TICKET_VALIDATION_ERROR_MSG_ID
130 );
131 }
132 } finally {
133 if (null != secContext && !spnego) {
134 secContext.dispose();
135 }
136 }
137
138 return krbServiceCtx;
139 }
140
141 }