Permalink
Browse files

Initial check in of spnego servlet demos. Included are:

1) HelloKDC (spnego.sourceforge.net)
2) HelloSpnegoServlet (using our forked spnego-pac filter, see spnego.sourceforge.net for docs)
3) ManualSpnegoNegotiateServlet (exposes the underlying mechanisms involved in performing a succesfull WIA Kerberos SPNEGO over HTTP with PAC information retrieval)
  • Loading branch information...
1 parent 01543a7 commit a5bc9d4220d18ec8ddb3842178a712d7ef3118ae @EleotleCram committed Apr 10, 2012
View
115 pom.xml
@@ -0,0 +1,115 @@
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>com.example</groupId>
+ <artifactId>jetty-spnego-demo</artifactId>
+ <version>0.9.1</version>
+ <packaging>war</packaging>
+ <name>Jetty SPNEGO Demo</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <jettyVersion>8.0.4.v20111024</jettyVersion>
+ <slf4jVersion>1.6.1</slf4jVersion>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ <version>${jettyVersion}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-websocket</artifactId>
+ <version>${jettyVersion}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-servlet</artifactId>
+ <version>${jettyVersion}</version>
+ <type>jar</type>
+ </dependency>
+
+ <dependency>
+ <groupId>net.sourceforge.spnego</groupId>
+ <artifactId>spnego-pac</artifactId>
+ <version>7.0-with-chromium-fix</version>
+ <type>jar</type>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>${slf4jVersion}</version>
+ </dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>1.2.14</version>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>1.4</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>commons-configuration</groupId>
+ <artifactId>commons-configuration</artifactId>
+ <version>1.7</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jaaslounge</groupId>
+ <artifactId>jaaslounge-decoding</artifactId>
+ <version>1.1.0</version>
+ <type>jar</type>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ <version>${jettyVersion}</version>
+ <configuration>
+<!-- <scanIntervalSeconds>2</scanIntervalSeconds>-->
+ <systemProperties>
+ <systemProperty>
+ <name>java.security.egd</name>
+ <value>file:/dev/./urandom</value>
+ </systemProperty>
+ </systemProperties>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-war-plugin</artifactId>
+ <version>2.1.1</version>
+ <configuration>
+ <packagingExcludes>WEB-INF/web.xml</packagingExcludes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.0.2</version>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <repositories>
+ <repository>
+ <id>github-eleotlecram-releases</id>
+ <url>https://github.com/EleotleCram/maven-repo/raw/master/releases</url>
+ </repository>
+ </repositories>
+</project>
@@ -0,0 +1,9 @@
+spnego-client {
+ com.sun.security.auth.module.Krb5LoginModule required;
+};
+
+spnego-server {
+ com.sun.security.auth.module.Krb5LoginModule required
+ storeKey=true
+ isInitiator=false;
+};
View
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2009 "Darwin V. Felix" <dfelix@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.security.NoSuchAlgorithmException;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.login.Configuration;
+import javax.security.auth.login.LoginContext;
+
+public final class HelloKDC {
+
+ private HelloKDC() {
+ // default private
+ }
+
+ public static void main(final String[] args) throws Exception {
+
+ // Domain (pre-authentication) account
+// final String username = "HTTP/example.com"; // For Non-WIA authentication against libre Kerberos/LDAP servers
+ final String username = "Zeus";
+
+ // Password for the pre-auth acct.
+ final String password = "Z3usP@55";
+
+ // Name of our krb5 config file
+ final String krbfile = "/etc/krb5.conf";
+
+ // Name of our login config file
+ final String loginfile = "src/main/conf/spnego.conf";
+
+ // Name of our login module
+ final String module = "spnego-client";
+
+ // set some system properties
+ System.setProperty("java.security.krb5.conf", krbfile);
+ System.setProperty("java.security.auth.login.config", loginfile);
+ System.setProperty("sun.security.krb5.debug", "true");
+
+ // assert
+ HelloKDC.validate(username, password, krbfile, loginfile, module);
+
+ final CallbackHandler handler =
+ HelloKDC.getUsernamePasswordHandler(username, password);
+
+ final LoginContext loginContext = new LoginContext(module, handler);
+
+ // attempt to login
+ loginContext.login();
+
+ // output some info
+ System.out.println("Subject=" + loginContext.getSubject());
+
+ // logout
+ loginContext.logout();
+
+ System.out.println("Connection test successful.");
+ }
+
+ private static void validate(final String username, final String password
+ , final String krbfile, final String loginfile, final String moduleName)
+ throws FileNotFoundException, NoSuchAlgorithmException {
+
+ // confirm username was provided
+ if (null == username || username.isEmpty()) {
+ throw new IllegalArgumentException("Must provide a username");
+ }
+
+ // confirm password was provided
+ if (null == password || password.isEmpty()) {
+ throw new IllegalArgumentException("Must provide a password");
+ }
+
+ // confirm krb5.conf file exists
+ if (null == krbfile || krbfile.isEmpty()) {
+ throw new IllegalArgumentException("Must provide a krb5 file");
+ } else {
+ final File file = new File(krbfile);
+ if (!file.exists()) {
+ throw new FileNotFoundException(krbfile);
+ }
+ }
+
+ // confirm loginfile
+ if (null == loginfile || loginfile.isEmpty()) {
+ throw new IllegalArgumentException("Must provide a login file");
+ } else {
+ final File file = new File(loginfile);
+ if (!file.exists()) {
+ throw new FileNotFoundException(loginfile);
+ }
+ }
+
+ // confirm that runtime loaded the login file
+ final Configuration config = Configuration.getConfiguration();
+
+ // confirm that the module name exists in the file
+ if (null == config.getAppConfigurationEntry(moduleName)) {
+ throw new IllegalArgumentException("The module name "
+ + moduleName + " was not found in the login file");
+ }
+ }
+
+ private static CallbackHandler getUsernamePasswordHandler(
+ final String username, final String password) {
+
+ final CallbackHandler handler = new CallbackHandler() {
+ public void handle(final Callback[] callback) {
+ for (int i=0; i<callback.length; i++) {
+ if (callback[i] instanceof NameCallback) {
+ final NameCallback nameCallback = (NameCallback) callback[i];
+ nameCallback.setName(username);
+ } else if (callback[i] instanceof PasswordCallback) {
+ final PasswordCallback passCallback = (PasswordCallback) callback[i];
+ passCallback.setPassword(password.toCharArray());
+ } else {
+ System.err.println("Unsupported Callback: "
+ + callback[i].getClass().getName());
+ }
+ }
+ }
+ };
+
+ return handler;
+ }
+}
@@ -0,0 +1,53 @@
+package com.example;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.Arrays;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import net.sourceforge.spnego.SpnegoLogonInfo;
+import net.sourceforge.spnego.SpnegoPrincipal;
+
+/**
+ * Hello Servlet that is intended to be used in combination with the SpnegoHttpFilter.
+ * It shows how single sign on (SSO) can be achieved using SPNEGO, and, if available,
+ * how to read the group SIDs (Active Directory/Samba4 issued Kerberos tickets).
+ *
+ * All complexities are encapsulated by the filter, so this file shows simply how
+ * to get to the data. If you want to learn about the details involved to achieve
+ * all this beauty, please check out: ManualSpnegoNegotiateServlet, which basically
+ * does the same thing, but with all implementation details exposed.
+ *
+ * @author mtoele
+ */
+public class HelloSpnegoServlet extends HttpServlet
+{
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ response.setContentType("text/html");
+ response.setStatus(HttpServletResponse.SC_OK);
+ response.getWriter().println("<h1>SPNEGO via ServletFilter Hello Servlet</h1>");
+ response.getWriter().println("<pre>");
+
+ Principal principal = request.getUserPrincipal();
+ response.getWriter().println("Hello, " + principal);
+
+ if(principal instanceof SpnegoPrincipal) {
+ SpnegoPrincipal spnegoPrincipal = (SpnegoPrincipal)principal;
+ SpnegoLogonInfo logonInfo = spnegoPrincipal.getLogonInfo();
+ if(logonInfo != null) {
+ String[] groupSIDs = logonInfo.getGroupSids();
+ response.getWriter().println("Found group SIDs: " + Arrays.toString(groupSIDs));
+ } else {
+ response.getWriter().println("No logon info available for principal.");
+ }
+ }
+
+ response.getWriter().println("Authenticated.");
+
+ response.getWriter().println("</pre>");
+ }
+}
+
Oops, something went wrong.

0 comments on commit a5bc9d4

Please sign in to comment.