]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/internal/http/client/SpnegoAuthScheme.java
Fix automated Kerberos config
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / internal / http / client / SpnegoAuthScheme.java
1 package org.argeo.cms.internal.http.client;
2
3 import java.net.URI;
4 import java.net.URL;
5 import java.security.PrivilegedExceptionAction;
6 import java.util.ArrayList;
7 import java.util.Base64;
8
9 import javax.security.auth.Subject;
10 import javax.security.auth.login.LoginContext;
11
12 import org.apache.commons.httpclient.Credentials;
13 import org.apache.commons.httpclient.HttpClient;
14 import org.apache.commons.httpclient.HttpMethod;
15 import org.apache.commons.httpclient.URIException;
16 import org.apache.commons.httpclient.auth.AuthPolicy;
17 import org.apache.commons.httpclient.auth.AuthScheme;
18 import org.apache.commons.httpclient.auth.AuthenticationException;
19 import org.apache.commons.httpclient.auth.CredentialsProvider;
20 import org.apache.commons.httpclient.auth.MalformedChallengeException;
21 import org.apache.commons.httpclient.methods.GetMethod;
22 import org.apache.commons.httpclient.params.DefaultHttpParams;
23 import org.apache.commons.httpclient.params.HttpParams;
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.ietf.jgss.GSSContext;
27 import org.ietf.jgss.GSSException;
28 import org.ietf.jgss.GSSManager;
29 import org.ietf.jgss.GSSName;
30 import org.ietf.jgss.Oid;
31
32 /** Implementation of the SPNEGO auth scheme. */
33 public class SpnegoAuthScheme implements AuthScheme {
34 private final static Log log = LogFactory.getLog(SpnegoAuthScheme.class);
35
36 public static final String NAME = "Negotiate";
37 private final static Oid KERBEROS_OID;
38 static {
39 try {
40 KERBEROS_OID = new Oid("1.3.6.1.5.5.2");
41 } catch (GSSException e) {
42 throw new IllegalStateException("Cannot create Kerberos OID", e);
43 }
44 }
45
46 private boolean complete = false;
47 private String realm;
48 private String tokenStr;
49
50 @Override
51 public void processChallenge(String challenge) throws MalformedChallengeException {
52 // if(tokenStr!=null){
53 // log.error("Received challenge while there is a token. Failing.");
54 // complete = false;
55 // }
56
57 }
58
59 @Override
60 public String getSchemeName() {
61 return NAME;
62 }
63
64 @Override
65 public String getParameter(String name) {
66 return null;
67 }
68
69 @Override
70 public String getRealm() {
71 return realm;
72 }
73
74 @Override
75 public String getID() {
76 return NAME;
77 }
78
79 @Override
80 public boolean isConnectionBased() {
81 return true;
82 }
83
84 @Override
85 public boolean isComplete() {
86 return complete;
87 }
88
89 @Override
90 public String authenticate(Credentials credentials, String method, String uri) throws AuthenticationException {
91 // log.debug("authenticate " + method + " " + uri);
92 // return null;
93 throw new UnsupportedOperationException();
94 }
95
96 @Override
97 public String authenticate(Credentials credentials, HttpMethod method) throws AuthenticationException {
98 GSSContext context = null;
99 String tokenStr = null;
100 String hostname;
101 try {
102 hostname = method.getURI().getHost();
103 } catch (URIException e1) {
104 throw new IllegalStateException("Cannot authenticate", e1);
105 }
106 String serverPrinc = "HTTP@" + hostname;
107
108 try {
109 // Get service's principal name
110 GSSManager manager = GSSManager.getInstance();
111 GSSName serverName = manager.createName(serverPrinc, GSSName.NT_HOSTBASED_SERVICE, KERBEROS_OID);
112
113 // Get the context for authentication
114 context = manager.createContext(serverName, KERBEROS_OID, null, GSSContext.DEFAULT_LIFETIME);
115 // context.requestMutualAuth(true); // Request mutual authentication
116 // context.requestConf(true); // Request confidentiality
117 context.requestCredDeleg(true);
118
119 byte[] token = new byte[0];
120
121 // token is ignored on the first call
122 token = context.initSecContext(token, 0, token.length);
123
124 // Send a token to the server if one was generated by
125 // initSecContext
126 if (token != null) {
127 tokenStr = Base64.getEncoder().encodeToString(token);
128 // complete=true;
129 }
130 return "Negotiate " + tokenStr;
131 } catch (GSSException e) {
132 complete = true;
133 throw new AuthenticationException("Cannot authenticate to " + serverPrinc, e);
134 }
135 }
136
137 private void doAuthenticate(URI uri){
138
139 }
140
141 public static void main(String[] args) {
142 if (args.length == 0) {
143 System.err.println("usage: java " + SpnegoAuthScheme.class.getName() + " <url>");
144 System.exit(1);
145 return;
146 }
147 String url = args[0];
148
149 URL jaasUrl = SpnegoAuthScheme.class.getResource("jaas.cfg");
150 System.setProperty("java.security.auth.login.config", jaasUrl.toExternalForm());
151 try {
152 LoginContext lc = new LoginContext("SINGLE_USER");
153 lc.login();
154
155 AuthPolicy.registerAuthScheme(SpnegoAuthScheme.NAME, SpnegoAuthScheme.class);
156 HttpParams params = DefaultHttpParams.getDefaultParams();
157 ArrayList<String> schemes = new ArrayList<>();
158 schemes.add(SpnegoAuthScheme.NAME);
159 params.setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, schemes);
160 params.setParameter(CredentialsProvider.PROVIDER, new SpnegoCredentialProvider());
161
162 int responseCode = Subject.doAs(lc.getSubject(), new PrivilegedExceptionAction<Integer>() {
163 public Integer run() throws Exception {
164 HttpClient httpClient = new HttpClient();
165 return httpClient.executeMethod(new GetMethod(url));
166 }
167 });
168 System.out.println("Reponse code: " + responseCode);
169 } catch (Exception e) {
170 e.printStackTrace();
171 }
172 }
173
174 }