import static org.argeo.cms.CmsMsg.username;
import java.io.IOException;
-import java.net.Authenticator;
-import java.net.PasswordAuthentication;
-import java.net.URI;
-import java.net.http.HttpClient;
-import java.net.http.HttpRequest;
-import java.net.http.HttpResponse;
-import java.net.http.HttpResponse.BodyHandler;
-import java.net.http.HttpResponse.BodyHandlers;
-import java.security.KeyManagementException;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivilegedAction;
-import java.security.cert.X509Certificate;
import java.util.List;
import java.util.Locale;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509TrustManager;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import org.argeo.cms.CmsMsg;
import org.argeo.cms.LocaleUtils;
import org.argeo.cms.auth.RemoteAuthCallback;
-import org.argeo.cms.auth.RemoteAuthUtils;
import org.argeo.cms.servlet.ServletHttpRequest;
import org.argeo.cms.servlet.ServletHttpResponse;
import org.argeo.cms.swt.CmsStyles;
else
loginContext = new LoginContext(CmsAuth.LOGIN_CONTEXT_USER, subject, this);
loginContext.login();
-// try {
-// openHttpClient(loginContext.getSubject(), "id-internal.work.argeo.net");
-// } catch (Exception e) {
-// e.printStackTrace();
-// }
cmsView.authChange(loginContext);
return true;
} catch (LoginException e) {
// }
}
- private static HttpClient openHttpClient(Subject subject, String server) {
- try {
- String domain = "WORK.ARGEO.ORG";
- // disable https check
- // jdk.internal.httpclient.disableHostnameVerification=true
- HttpClient client = HttpClient.newBuilder().sslContext(insecureContext())
- .authenticator(new Authenticator() {
- public PasswordAuthentication getPasswordAuthentication() {
- // I haven't checked getRequestingScheme() here, since for NTLM
- // and Negotiate, the usrname and password are all the same.
- System.err.println("Feeding username and password for " + getRequestingScheme());
- return (new PasswordAuthentication("mbaudier@" + domain, null));
- }
-
- }).build();
-
- String token = RemoteAuthUtils.getGssToken(subject, "HTTP/" + server + "@" + domain);
-
- HttpRequest request = HttpRequest.newBuilder(URI.create("https://" + server + "/ipa/session/json")).GET()
- .header("Authorization", "Negotiate " + token).build();
- BodyHandler<String> bodyHandler = BodyHandlers.ofString();
- HttpResponse<String> response = client.send(request, bodyHandler);
- System.out.println(response.body());
- return client;
-
- // return client;
-// AuthPolicy.registerAuthScheme(SpnegoAuthScheme.NAME, SpnegoAuthScheme.class);
-// HttpParams params = DefaultHttpParams.getDefaultParams();
-// ArrayList<String> schemes = new ArrayList<>();
-// schemes.add(SpnegoAuthScheme.NAME);
-// params.setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, schemes);
-// params.setParameter(CredentialsProvider.PROVIDER, new HttpCredentialProvider());
-// HttpClient httpClient = new HttpClient();
-// httpClient.executeMethod(new GetMethod(("https://" + server + "/ipa/session/json")));
-// return httpClient;
- } catch (
-
- Exception e) {
- throw new IllegalStateException("Cannot open client to IPA server " + server, e);
- }
-
- }
-
- private static SSLContext insecureContext() {
- TrustManager[] noopTrustManager = new TrustManager[] { new X509TrustManager() {
- public void checkClientTrusted(X509Certificate[] xcs, String string) {
- }
-
- public void checkServerTrusted(X509Certificate[] xcs, String string) {
- }
-
- public X509Certificate[] getAcceptedIssuers() {
- return null;
- }
- } };
- try {
- SSLContext sc = SSLContext.getInstance("ssl");
- sc.init(null, noopTrustManager, null);
- return sc;
- } catch (KeyManagementException | NoSuchAlgorithmException e) {
- throw new IllegalStateException("Cannot create insecure SSL context ", e);
- }
- }
protected void logout() {
cmsView.logout();
/** Remote authentication utilities. */
public class RemoteAuthUtils {
static final String REMOTE_USER = "org.osgi.service.http.authentication.remote.user";
-// private static BundleContext bundleContext = FrameworkUtil.getBundle(RemoteAuthUtils.class).getBundleContext();
+ private final static Oid KERBEROS_OID;
+// private final static Oid KERB_V5_OID, KRB5_PRINCIPAL_NAME_OID;
+ static {
+ try {
+ KERBEROS_OID = new Oid("1.3.6.1.5.5.2");
+// KERB_V5_OID = new Oid("1.2.840.113554.1.2.2");
+// KRB5_PRINCIPAL_NAME_OID = new Oid("1.2.840.113554.1.2.2.1");
+ } catch (GSSException e) {
+ throw new IllegalStateException("Cannot create Kerberos OID", e);
+ }
+ }
/**
* Execute this supplier, using the CMS class loader as context classloader.
return cmsSession;
}
- private final static Oid KERBEROS_OID;
- static {
- try {
- KERBEROS_OID = new Oid("1.3.6.1.5.5.2");
- } catch (GSSException e) {
- throw new IllegalStateException("Cannot create Kerberos OID", e);
- }
- }
-
- public static String getGssToken(Subject subject, String serverPrinc) {
+ public static String getGssToken(Subject subject, String service, String server) {
if (subject.getPrivateCredentials(KerberosTicket.class).isEmpty())
throw new IllegalArgumentException("Subject " + subject + " is not GSS authenticated.");
return Subject.doAs(subject, (PrivilegedAction<String>) () -> {
+ // !! different format than Kerberos
+ String serverPrinc = service + "@" + server;
GSSContext context = null;
String tokenStr = null;
package org.argeo.cms.auth;
-import java.lang.reflect.Method;
import java.util.Map;
import javax.security.auth.Subject;
import org.argeo.api.cms.CmsLog;
import org.argeo.cms.internal.runtime.CmsContextImpl;
import org.ietf.jgss.GSSContext;
-import org.ietf.jgss.GSSCredential;
import org.ietf.jgss.GSSException;
import org.ietf.jgss.GSSManager;
-import org.ietf.jgss.GSSName;
+
+import com.sun.security.jgss.GSSUtil;
/** SPNEGO login */
public class SpnegoLoginModule implements LoginModule {
gssContext = checkToken(spnegoToken);
if (gssContext == null)
return false;
- else
+ else {
+// if (!sharedState.containsKey(CmsAuthUtils.SHARED_STATE_NAME)) {
+// try {
+// GSSName name = gssContext.getSrcName();
+// String username = name.toString();
+// // TODO deal with connecting service
+// // TODO generate IPA DN?
+// username = username.substring(0, username.lastIndexOf('@'));
+// sharedState.put(CmsAuthUtils.SHARED_STATE_NAME, username);
+// } catch (GSSException e) {
+// throw new IllegalStateException("Cannot retrieve SPNEGO name", e);
+// }
+// }
return true;
+ }
// try {
// String clientName = gssContext.getSrcName().toString();
// String role = clientName.substring(clientName.indexOf('@') + 1);
return false;
try {
- Class<?> gssUtilsClass = Class.forName("com.sun.security.jgss.GSSUtil");
- Method createSubjectMethod = gssUtilsClass.getMethod("createSubject", GSSName.class, GSSCredential.class);
+// Class<?> gssUtilsClass = Class.forName("com.sun.security.jgss.GSSUtil");
+// Method createSubjectMethod = gssUtilsClass.getMethod("createSubject", GSSName.class, GSSCredential.class);
Subject gssSubject;
if (gssContext.getCredDelegState())
- gssSubject = (Subject) createSubjectMethod.invoke(null, gssContext.getSrcName(),
- gssContext.getDelegCred());
+ gssSubject = (Subject) GSSUtil.createSubject(gssContext.getSrcName(), gssContext.getDelegCred());
else
- gssSubject = (Subject) createSubjectMethod.invoke(null, gssContext.getSrcName(), null);
+ gssSubject = (Subject) GSSUtil.createSubject(gssContext.getSrcName(), null);
subject.getPrincipals().addAll(gssSubject.getPrincipals());
subject.getPrivateCredentials().addAll(gssSubject.getPrivateCredentials());
return true;
import java.net.URL;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
-import java.util.Base64;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
-import org.apache.commons.httpclient.URIException;
import org.apache.commons.httpclient.auth.AuthPolicy;
import org.apache.commons.httpclient.auth.AuthScheme;
import org.apache.commons.httpclient.auth.AuthenticationException;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.DefaultHttpParams;
import org.apache.commons.httpclient.params.HttpParams;
-import org.ietf.jgss.GSSContext;
-import org.ietf.jgss.GSSException;
-import org.ietf.jgss.GSSManager;
-import org.ietf.jgss.GSSName;
-import org.ietf.jgss.Oid;
+import org.argeo.cms.auth.RemoteAuthUtils;
/** Implementation of the SPNEGO auth scheme. */
public class SpnegoAuthScheme implements AuthScheme {
// private final static Log log = LogFactory.getLog(SpnegoAuthScheme.class);
public static final String NAME = "Negotiate";
- private final static Oid KERBEROS_OID;
- static {
- try {
- KERBEROS_OID = new Oid("1.3.6.1.5.5.2");
- } catch (GSSException e) {
- throw new IllegalStateException("Cannot create Kerberos OID", e);
- }
- }
+// private final static Oid KERBEROS_OID;
+// static {
+// try {
+// KERBEROS_OID = new Oid("1.3.6.1.5.5.2");
+// } catch (GSSException e) {
+// throw new IllegalStateException("Cannot create Kerberos OID", e);
+// }
+// }
private final static String DEFAULT_KERBEROS_SERVICE = "HTTP";
@Override
public String authenticate(Credentials credentials, HttpMethod method) throws AuthenticationException {
- GSSContext context = null;
- String tokenStr = null;
+// GSSContext context = null;
String hostname;
try {
hostname = method.getURI().getHost();
- } catch (URIException e1) {
- throw new IllegalStateException("Cannot authenticate", e1);
- }
- String serverPrinc = DEFAULT_KERBEROS_SERVICE + "@" + hostname;
-
- try {
- // Get service's principal name
- GSSManager manager = GSSManager.getInstance();
- GSSName serverName = manager.createName(serverPrinc, GSSName.NT_HOSTBASED_SERVICE, KERBEROS_OID);
-
- // Get the context for authentication
- context = manager.createContext(serverName, KERBEROS_OID, null, GSSContext.DEFAULT_LIFETIME);
- // context.requestMutualAuth(true); // Request mutual authentication
- // context.requestConf(true); // Request confidentiality
- context.requestCredDeleg(true);
-
- byte[] token = new byte[0];
-
- // token is ignored on the first call
- token = context.initSecContext(token, 0, token.length);
-
- // Send a token to the server if one was generated by
- // initSecContext
- if (token != null) {
- tokenStr = Base64.getEncoder().encodeToString(token);
- // complete=true;
- }
+ String tokenStr = RemoteAuthUtils.getGssToken(null, DEFAULT_KERBEROS_SERVICE, hostname);
return "Negotiate " + tokenStr;
- } catch (GSSException e) {
+ } catch (Exception e1) {
complete = true;
- throw new AuthenticationException("Cannot authenticate to " + serverPrinc, e);
+ throw new AuthenticationException("Cannot authenticate " + method, e1);
}
+// String serverPrinc = DEFAULT_KERBEROS_SERVICE + "@" + hostname;
+//
+// try {
+// // Get service's principal name
+// GSSManager manager = GSSManager.getInstance();
+// GSSName serverName = manager.createName(serverPrinc, GSSName.NT_HOSTBASED_SERVICE, KERBEROS_OID);
+//
+// // Get the context for authentication
+// context = manager.createContext(serverName, KERBEROS_OID, null, GSSContext.DEFAULT_LIFETIME);
+// // context.requestMutualAuth(true); // Request mutual authentication
+// // context.requestConf(true); // Request confidentiality
+// context.requestCredDeleg(true);
+//
+// byte[] token = new byte[0];
+//
+// // token is ignored on the first call
+// token = context.initSecContext(token, 0, token.length);
+//
+// // Send a token to the server if one was generated by
+// // initSecContext
+// if (token != null) {
+// tokenStr = Base64.getEncoder().encodeToString(token);
+// // complete=true;
+// }
+// } catch (GSSException e) {
+// complete = true;
+// throw new AuthenticationException("Cannot authenticate to " + serverPrinc, e);
+// }
}
public static void main(String[] args) {
--- /dev/null
+package org.argeo.cms.internal.http.client;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.net.http.HttpResponse.BodyHandler;
+import java.net.http.HttpResponse.BodyHandlers;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginContext;
+
+import org.argeo.cms.auth.RemoteAuthUtils;
+
+public class SpnegoHttpClient {
+ public static void main(String[] args) throws MalformedURLException {
+ String principal = System.getProperty("javax.security.auth.login.name");
+ if (args.length == 0 || principal == null) {
+ System.err.println("usage: java -Djavax.security.auth.login.name=<principal@REALM> "
+ + SpnegoHttpClient.class.getName() + " <url>");
+ System.exit(1);
+ return;
+ }
+ String url = args[0];
+ URL u = new URL(url);
+ String server = u.getHost();
+
+ URL jaasUrl = SpnegoAuthScheme.class.getResource("jaas.cfg");
+ System.setProperty("java.security.auth.login.config", jaasUrl.toExternalForm());
+ try {
+ LoginContext lc = new LoginContext("SINGLE_USER");
+ lc.login();
+
+// int responseCode = Subject.doAs(lc.getSubject(), new PrivilegedExceptionAction<Integer>() {
+//
+// public Integer run() throws Exception {
+
+// InputStream ins = u.openConnection().getInputStream();
+// BufferedReader reader = new BufferedReader(new InputStreamReader(ins));
+// String str;
+// while ((str = reader.readLine()) != null)
+// System.out.println(str);
+// return 666;
+
+ HttpClient httpClient = openHttpClient(lc.getSubject());
+ String token = RemoteAuthUtils.getGssToken(lc.getSubject(), "HTTP", server);
+
+ HttpRequest request = HttpRequest.newBuilder().uri(u.toURI()) //
+ .header("Authorization", "Negotiate " + token) //
+ .build();
+ BodyHandler<String> bodyHandler = BodyHandlers.ofString();
+ HttpResponse<String> response = httpClient.send(request, bodyHandler);
+ System.out.println(response.body());
+ int responseCode = response.statusCode();
+// return response.statusCode();
+// }
+// });
+ System.out.println("Reponse code: " + responseCode);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static HttpClient openHttpClient(Subject subject) {
+ // disable https check
+ // jdk.internal.httpclient.disableHostnameVerification=true
+ HttpClient client = HttpClient.newBuilder().sslContext(insecureContext())
+// .authenticator(new Authenticator() {
+// public PasswordAuthentication getPasswordAuthentication() {
+// return null;
+// }
+//
+// })
+ .version(HttpClient.Version.HTTP_1_1).build();
+
+ return client;
+
+ // return client;
+// AuthPolicy.registerAuthScheme(SpnegoAuthScheme.NAME, SpnegoAuthScheme.class);
+// HttpParams params = DefaultHttpParams.getDefaultParams();
+// ArrayList<String> schemes = new ArrayList<>();
+// schemes.add(SpnegoAuthScheme.NAME);
+// params.setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, schemes);
+// params.setParameter(CredentialsProvider.PROVIDER, new HttpCredentialProvider());
+// HttpClient httpClient = new HttpClient();
+// httpClient.executeMethod(new GetMethod(("https://" + server + "/ipa/session/json")));
+// return httpClient;
+
+ }
+
+ private static SSLContext insecureContext() {
+ TrustManager[] noopTrustManager = new TrustManager[] { new X509TrustManager() {
+ public void checkClientTrusted(X509Certificate[] xcs, String string) {
+ }
+
+ public void checkServerTrusted(X509Certificate[] xcs, String string) {
+ }
+
+ public X509Certificate[] getAcceptedIssuers() {
+ return null;
+ }
+ } };
+ try {
+ SSLContext sc = SSLContext.getInstance("ssl");
+ sc.init(null, noopTrustManager, null);
+ return sc;
+ } catch (KeyManagementException | NoSuchAlgorithmException e) {
+ throw new IllegalStateException("Cannot create insecure SSL context ", e);
+ }
+ }
+
+}
SINGLE_USER {
- com.sun.security.auth.module.Krb5LoginModule optional
- useTicketCache=true;
+ com.sun.security.auth.module.Krb5LoginModule required
+ useTicketCache=true
+ debug=true;
};
+
+com.sun.security.jgss.krb5.initiate {
+ com.sun.security.auth.module.Krb5LoginModule
+ required useTicketCache=true;
+};
\ No newline at end of file