]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/auth/SpnegoLoginModule.java
Make tree view more robust
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / auth / SpnegoLoginModule.java
1 package org.argeo.cms.auth;
2
3 import java.util.Map;
4
5 import javax.security.auth.Subject;
6 import javax.security.auth.callback.CallbackHandler;
7 import javax.security.auth.login.LoginException;
8 import javax.security.auth.spi.LoginModule;
9
10 import org.argeo.api.cms.CmsLog;
11 import org.argeo.cms.internal.runtime.CmsContextImpl;
12 import org.ietf.jgss.GSSContext;
13 import org.ietf.jgss.GSSException;
14 import org.ietf.jgss.GSSManager;
15 import org.ietf.jgss.GSSName;
16
17 import com.sun.security.jgss.GSSUtil;
18
19 /** SPNEGO login */
20 public class SpnegoLoginModule implements LoginModule {
21 private final static CmsLog log = CmsLog.getLog(SpnegoLoginModule.class);
22
23 private Subject subject;
24 private Map<String, Object> sharedState = null;
25
26 private GSSContext gssContext = null;
27
28 @SuppressWarnings("unchecked")
29 @Override
30 public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
31 Map<String, ?> options) {
32 this.subject = subject;
33 this.sharedState = (Map<String, Object>) sharedState;
34 }
35
36 @Override
37 public boolean login() throws LoginException {
38 byte[] spnegoToken = (byte[]) sharedState.get(CmsAuthUtils.SHARED_STATE_SPNEGO_TOKEN);
39 if (spnegoToken == null)
40 return false;
41 gssContext = checkToken(spnegoToken);
42 if (gssContext == null)
43 return false;
44 else {
45 if (!sharedState.containsKey(CmsAuthUtils.SHARED_STATE_NAME)) {
46 try {
47 if (gssContext.getCredDelegState()) {
48 // commit will succeeed only if we have credential delegation
49 GSSName name = gssContext.getSrcName();
50 String username = name.toString();
51 sharedState.put(CmsAuthUtils.SHARED_STATE_NAME, username);
52 }
53 } catch (GSSException e) {
54 throw new IllegalStateException("Cannot retrieve SPNEGO name", e);
55 }
56 }
57 return true;
58 }
59 }
60
61 @Override
62 public boolean commit() throws LoginException {
63 if (gssContext == null)
64 return false;
65
66 try {
67 Subject gssSubject;
68 if (gssContext.getCredDelegState())
69 gssSubject = (Subject) GSSUtil.createSubject(gssContext.getSrcName(), gssContext.getDelegCred());
70 else
71 gssSubject = (Subject) GSSUtil.createSubject(gssContext.getSrcName(), null);
72 // without credential delegation we won't have access to the Kerberos key
73 subject.getPrincipals().addAll(gssSubject.getPrincipals());
74 subject.getPrivateCredentials().addAll(gssSubject.getPrivateCredentials());
75 return true;
76 } catch (Exception e) {
77 throw new LoginException("Cannot commit SPNEGO " + e);
78 }
79
80 }
81
82 @Override
83 public boolean abort() throws LoginException {
84 if (gssContext != null) {
85 try {
86 gssContext.dispose();
87 } catch (GSSException e) {
88 if (log.isTraceEnabled())
89 log.warn("Could not abort", e);
90 }
91 gssContext = null;
92 }
93 return true;
94 }
95
96 @Override
97 public boolean logout() throws LoginException {
98 if (gssContext != null) {
99 try {
100 gssContext.dispose();
101 } catch (GSSException e) {
102 if (log.isTraceEnabled())
103 log.warn("Could not abort", e);
104 }
105 gssContext = null;
106 }
107 return true;
108 }
109
110 private GSSContext checkToken(byte[] authToken) {
111 GSSManager manager = GSSManager.getInstance();
112 try {
113 GSSContext gContext = manager.createContext(CmsContextImpl.getCmsContext().getAcceptorCredentials());
114 if (gContext == null) {
115 log.debug("SpnegoUserRealm: failed to establish GSSContext");
116 } else {
117 if (gContext.isEstablished())
118 return gContext;
119 byte[] outToken = gContext.acceptSecContext(authToken, 0, authToken.length);
120 if (outToken != null)
121 sharedState.put(CmsAuthUtils.SHARED_STATE_SPNEGO_OUT_TOKEN, outToken);
122 if (gContext.isEstablished())
123 return gContext;
124 }
125
126 } catch (GSSException gsse) {
127 log.warn(gsse, gsse);
128 }
129 return null;
130
131 }
132
133 }