commit - 5c3be72c5f44a87bd91169e87ddf128994522bde
commit + 38d6902abcd0b0df66b7f3fa21bc0dbaf3c9a184
blob - ba49b47a3801f32259b868d3c0ba6ea0c217e3a8
blob + c5667afd129b86653c2e164d411632fba01fe241
--- src/org/snipsnap/container/DefaultSessionService.java
+++ src/org/snipsnap/container/DefaultSessionService.java
package org.snipsnap.container;
import org.radeox.util.logging.Logger;
+import snipsnap.api.storage.UserStorage;
+import org.snipsnap.snip.HomePage;
+import org.snipsnap.user.AuthenticationService;
+import org.snipsnap.user.Digest;
+import org.snipsnap.user.UserManager;
+import org.snipsnap.util.Base64;
+import org.snipsnap.util.X509NameTokenizer;
import snipsnap.api.app.Application;
import snipsnap.api.config.Configuration;
-import snipsnap.api.snip.Snip;
import snipsnap.api.snip.SnipSpace;
-import org.snipsnap.snip.storage.UserStorage;
-import org.snipsnap.user.AuthenticationService;
-import org.snipsnap.user.Digest;
import snipsnap.api.user.User;
+import snipsnap.api.container.Components;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URL;
+import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
private final static String COOKIE_NAME = "SnipSnapUser";
private final static String ATT_USER = "user";
private final static int SECONDS_PER_YEAR = 60 * 60 * 24 * 365;
+ private final static int HTTP_UNAUTHORIZED = 401;
+
private Map authHash = new HashMap();
private Map robots = new HashMap();
private Map robotIds = new HashMap();
snipsnap.api.snip.Snip robots = space.load(snipsnap.api.config.Configuration.SNIPSNAP_CONFIG_ROBOTS);
if (robots != null) {
BufferedReader crawler = new BufferedReader(new StringReader(robots.getContent()));
- String line = null;
+ String line;
int ln = 0;
while ((line = crawler.readLine()) != null) {
ln++;
public User getUser(HttpServletRequest request, HttpServletResponse response) {
HttpSession session = request.getSession();
User user = (User) session.getAttribute(ATT_USER);
- String appOid = (String)Application.get().getObject(Application.OID);
+ String appOid = (String) Application.get().getObject(Application.OID);
if (null != user && !appOid.equals(user.getApplication())) {
- user = null;
+ user = null;
}
+ // TODO: refactor to several session service modules
+ // TODO: Idea: Basic, Digest or Certificate access and possible guest access (Cookie)
if (null == user) {
- Cookie cookie = getCookie(request, COOKIE_NAME);
- if (cookie != null) {
- String auth = cookie.getValue();
- if (!authHash.containsKey(auth)) {
- updateAuthHash();
+ if ("Cookie".equals(Application.get().getConfiguration().getAuth())) {
+ Cookie cookie = getCookie(request, COOKIE_NAME);
+ if (cookie != null) {
+ String auth = cookie.getValue();
+ if (!authHash.containsKey(auth)) {
+ updateAuthHash();
+ }
+
+ user = (User) authHash.get(auth);
+ if (user != null && appOid.equals(user.getApplication())) {
+ user = authService.authenticate(user.getLogin(), user.getPasswd(), AuthenticationService.ENCRYPTED);
+ if (null != user) {
+ setCookie(request, response, user);
+ }
+ } else {
+ Logger.warn("SessionService: invalid hash: " + auth);
+ user = null;
+ }
}
+ } else if ("Basic".equals(Application.get().getConfiguration().getAuth())) {
+ // make sure the user is authorized
+ String auth = request.getHeader("Authorization");
+ String login = "", password = "";
- user = (User) authHash.get(auth);
- if (user != null && appOid.equals(user.getApplication())) {
- user = authService.authenticate(user.getLogin(), user.getPasswd(), AuthenticationService.ENCRYPTED);
- if(null != user) {
- setCookie(request, response, user);
+ if (auth != null) {
+ auth = new String(Base64.decode(auth.substring(auth.indexOf(' ') + 1)));
+ login = auth.substring(0, auth.indexOf(':'));
+ password = auth.substring(auth.indexOf(':') + 1);
+ }
+
+ user = authService.authenticate(login, password);
+ if (user == null) {
+ response.setHeader("WWW-Authenticate", "Basic realm=\"SnipSnap\"");
+ response.setStatus(HTTP_UNAUTHORIZED);
+ return null;
+ }
+ } else if ("Certificate".equals(Application.get().getConfiguration().getAuth())) {
+ // Part for authenticating users with X509Certificates. If the user have a trusted client certificate
+ // he can get access to the server. Since the certificate is trusted already, by java/jsse, we don't
+ // have to verify it here.
+ // If the CA puts the users uid in the DN we can use that as login.
+
+ // Check if we have a user in the certificate authentication
+ X509Certificate[] certs = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate");
+ if (certs != null) {
+ X509Certificate clientCert = certs[0];
+ if (clientCert != null) {
+ // Get the Distinguised Name for the user.
+ java.security.Principal userDN = clientCert.getSubjectDN();
+ String dn = userDN.toString();
+ // Get uid, which is the username we will use
+ String uid = getPartFromDN(dn, "UID");
+ String email = getPartFromDN(dn, "emailAddress");
+ // Create users home page if it does not exist
+ UserManager um = (UserManager) Components.getComponent(UserManager.class);
+ user = authService.authenticate(uid);
+ // create a user and home page for new logins
+ if(null == user) {
+ // set password to "*", if we switch back to Cookie auth service
+ // this is no problem as the users password is expected to be encrypted
+ // switching to Basic auth poses a security risk as it compares unencrypted
+ // passwords.
+ user = um.create(uid, "*", email);
+ Application.get().setUser(user, session);
+ HomePage.create(uid);
+ user = authService.authenticate(uid);
+ }
}
- } else {
- Logger.warn("SessionService: invalid hash: " + auth);
- user = null;
}
}
/**
* Helper method for getUser to extract user from request/cookie/session
+ *
* @param request
* @param name
- * @return
+ * @return the cookie
*/
public Cookie getCookie(HttpServletRequest request, String name) {
Cookie cookies[] = request.getCookies();
}
return null;
}
+
+ /**
+ * Gets a specified part of a DN. Specifically the first occurrence it the DN contains several
+ * instances of a part (i.e. cn=x, cn=y returns x).
+ *
+ * @param dn String containing DN, The DN string has the format "C=SE, O=xx, OU=yy, CN=zz".
+ * @param dnpart String specifying which part of the DN to get, should be "CN" or "OU" etc.
+ * @return String containing dnpart or null if dnpart is not present
+ */
+ private String getPartFromDN(String dn, String dnpart) {
+ String part = null;
+ if ((dn != null) && (dnpart != null)) {
+ String o;
+ dnpart += "="; // we search for 'CN=' etc.
+ X509NameTokenizer xt = new X509NameTokenizer(dn);
+ while (xt.hasMoreTokens()) {
+ o = xt.nextToken();
+ if ((o.length() > dnpart.length()) &&
+ o.substring(0, dnpart.length()).equalsIgnoreCase(dnpart)) {
+ part = o.substring(dnpart.length());
+ break;
+ }
+ }
+ }
+ return part;
+ } //getPartFromDN
+
+
}
blob - /dev/null
blob + ac73430ca7c1c228ba4172b321b1ad831dce8e6a (mode 644)
--- /dev/null
+++ src/org/snipsnap/util/X509NameTokenizer.java
+package org.snipsnap.util;
+
+/**
+ * class for breaking up an X500 Name into it's component tokens, ala
+ * java.util.StringTokenizer. We need this class as some of the
+ * lightweight Java environment don't support classes like
+ * StringTokenizer.
+ * Class originally from the free JCE-provider bouncycastle.org, under BSD-like license.
+ */
+public class X509NameTokenizer
+{
+ private String value;
+ private int index;
+ private char seperator;
+ private StringBuffer buf = new StringBuffer();
+
+ public X509NameTokenizer(
+ String oid)
+ {
+ this(oid, ',');
+ }
+
+ public X509NameTokenizer(
+ String oid,
+ char seperator)
+ {
+ this.value = oid;
+ this.index = -1;
+ this.seperator = seperator;
+ }
+
+ public boolean hasMoreTokens()
+ {
+ return (index != value.length());
+ }
+
+ public String nextToken()
+ {
+ if (index == value.length())
+ {
+ return null;
+ }
+
+ int end = index + 1;
+ boolean quoted = false;
+ boolean escaped = false;
+
+ buf.setLength(0);
+
+ while (end != value.length())
+ {
+ char c = value.charAt(end);
+
+ if (c == '"')
+ {
+ if (!escaped)
+ {
+ quoted = !quoted;
+ }
+ else
+ {
+ buf.append(c);
+ }
+ escaped = false;
+ }
+ else
+ {
+ if (escaped || quoted)
+ {
+ buf.append(c);
+ escaped = false;
+ }
+ else if (c == '\\')
+ {
+ escaped = true;
+ }
+ else if (c == seperator)
+ {
+ break;
+ }
+ else
+ {
+ buf.append(c);
+ }
+ }
+ end++;
+ }
+
+ index = end;
+ return buf.toString().trim();
+ }
+}