]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/auth/SpnegoLoginModule.java
FS utils throws IOException
[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 if (!sharedState.containsKey(CmsAuthUtils.SHARED_STATE_NAME)) {
41 // workaround: set shared state name to empty
42 // in order to avoid Krb5LoginModule printing to System.out
43 // TODO ask upstream to only log in debug mode
44 sharedState.put(CmsAuthUtils.SHARED_STATE_NAME, "");
45 }
46 return false;
47 }
48 gssContext = checkToken(spnegoToken);
49 if (gssContext == null)
50 return false;
51 else {
52 if (!sharedState.containsKey(CmsAuthUtils.SHARED_STATE_NAME)) {
53 try {
54 if (gssContext.getCredDelegState()) {
55 // commit will succeeed only if we have credential delegation
56 GSSName name = gssContext.getSrcName();
57 String username = name.toString();
58 sharedState.put(CmsAuthUtils.SHARED_STATE_NAME, username);
59 }
60 } catch (GSSException e) {
61 throw new IllegalStateException("Cannot retrieve SPNEGO name", e);
62 }
63 }
64 return true;
65 }
66 }
67
68 @Override
69 public boolean commit() throws LoginException {
70 if (gssContext == null)
71 return false;
72
73 try {
74 Subject gssSubject;
75 if (gssContext.getCredDelegState())
76 gssSubject = (Subject) GSSUtil.createSubject(gssContext.getSrcName(), gssContext.getDelegCred());
77 else
78 gssSubject = (Subject) GSSUtil.createSubject(gssContext.getSrcName(), null);
79 // without credential delegation we won't have access to the Kerberos key
80 subject.getPrincipals().addAll(gssSubject.getPrincipals());
81 subject.getPrivateCredentials().addAll(gssSubject.getPrivateCredentials());
82 return true;
83 } catch (Exception e) {
84 throw new LoginException("Cannot commit SPNEGO " + e);
85 }
86
87 }
88
89 @Override
90 public boolean abort() throws LoginException {
91 if (gssContext != null) {
92 try {
93 gssContext.dispose();
94 } catch (GSSException e) {
95 if (log.isTraceEnabled())
96 log.warn("Could not abort", e);
97 }
98 gssContext = null;
99 }
100 return true;
101 }
102
103 @Override
104 public boolean logout() throws LoginException {
105 if (gssContext != null) {
106 try {
107 gssContext.dispose();
108 } catch (GSSException e) {
109 if (log.isTraceEnabled())
110 log.warn("Could not abort", e);
111 }
112 gssContext = null;
113 }
114 return true;
115 }
116
117 private GSSContext checkToken(byte[] authToken) {
118 GSSManager manager = GSSManager.getInstance();
119 try {
120 GSSContext gContext = manager.createContext(CmsContextImpl.getCmsContext().getAcceptorCredentials());
121 if (gContext == null) {
122 log.debug("SpnegoUserRealm: failed to establish GSSContext");
123 } else {
124 if (gContext.isEstablished())
125 return gContext;
126 byte[] outToken = gContext.acceptSecContext(authToken, 0, authToken.length);
127 if (outToken != null)
128 sharedState.put(CmsAuthUtils.SHARED_STATE_SPNEGO_OUT_TOKEN, outToken);
129 if (gContext.isEstablished())
130 return gContext;
131 }
132
133 } catch (GSSException gsse) {
134 log.warn(gsse, gsse);
135 }
136 return null;
137
138 }
139
140 }