From 8c9a2037b5c0fed881a3ad6dd9cff364eed603d9 Mon Sep 17 00:00:00 2001
From: James Moger <james.moger@gitblit.com>
Date: Tue, 14 Jun 2011 16:55:13 -0400
Subject: [PATCH] Added AccessRestrictionFilter and simplified authentication.

---
 src/com/gitblit/FileLoginService.java |  202 +++++++++++++-------------------------------------
 1 files changed, 52 insertions(+), 150 deletions(-)

diff --git a/src/com/gitblit/JettyLoginService.java b/src/com/gitblit/FileLoginService.java
similarity index 62%
rename from src/com/gitblit/JettyLoginService.java
rename to src/com/gitblit/FileLoginService.java
index 22f9ce3..b59a776 100644
--- a/src/com/gitblit/JettyLoginService.java
+++ b/src/com/gitblit/FileLoginService.java
@@ -16,98 +16,72 @@
 package com.gitblit;
 
 import java.io.File;
-import java.io.FileReader;
 import java.io.FileWriter;
 import java.io.IOException;
-import java.security.Principal;
 import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
 
-import javax.security.auth.Subject;
-
-import org.eclipse.jetty.http.security.Credential;
-import org.eclipse.jetty.security.IdentityService;
-import org.eclipse.jetty.security.MappedLoginService;
-import org.eclipse.jetty.server.UserIdentity;
-import org.eclipse.jetty.util.log.Log;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.gitblit.models.UserModel;
+import com.gitblit.utils.StringUtils;
 
-public class JettyLoginService extends MappedLoginService implements ILoginService {
+public class FileLoginService extends FileSettings implements ILoginService {
 
-	private final Logger logger = LoggerFactory.getLogger(JettyLoginService.class);
+	private final Logger logger = LoggerFactory.getLogger(FileLoginService.class);
 
-	private final File realmFile;
-
-	public JettyLoginService(File realmFile) {
-		super();
-		setName(Constants.NAME);
-		this.realmFile = realmFile;
+	public FileLoginService(File realmFile) {
+		super(realmFile.getAbsolutePath());
 	}
 
 	@Override
 	public UserModel authenticate(String username, char[] password) {
-		UserIdentity identity = login(username, new String(password));
-		if (identity == null || identity.equals(UserIdentity.UNAUTHENTICATED_IDENTITY)) {
+		Properties allUsers = read();
+		String userInfo = allUsers.getProperty(username);
+		if (StringUtils.isEmpty(userInfo)) {
 			return null;
 		}
-		UserModel user = new UserModel(username);
-		user.canAdmin = identity.isUserInRole(Constants.ADMIN_ROLE, null);
-
-		// Add repositories
-		for (Principal principal : identity.getSubject().getPrincipals()) {
-			if (principal instanceof RolePrincipal) {
-				RolePrincipal role = (RolePrincipal) principal;
-				String roleName = role.getName();
-				if (roleName.charAt(0) != '#') {
-					user.addRepository(roleName);
-				}
+		UserModel returnedUser = null;
+		UserModel user = getUserModel(username);
+		if (user.password.startsWith(StringUtils.MD5_TYPE)) {
+			String md5 = StringUtils.MD5_TYPE + StringUtils.getMD5(new String(password));
+			if (user.password.equalsIgnoreCase(md5)) {
+				returnedUser = user;
 			}
 		}
-		return user;
+		if (user.password.equals(new String(password))) {
+			returnedUser = user;
+		}
+		return returnedUser;
 	}
 
 	@Override
 	public UserModel getUserModel(String username) {
-		UserIdentity identity = _users.get(username);
-		if (identity == null) {
+		Properties allUsers = read();
+		String userInfo = allUsers.getProperty(username);
+		if (userInfo == null) {
 			return null;
 		}
 		UserModel model = new UserModel(username);
-		Subject subject = identity.getSubject();
-		for (Principal principal : subject.getPrincipals()) {
-			if (principal instanceof RolePrincipal) {
-				RolePrincipal role = (RolePrincipal) principal;
-				String name = role.getName();
-				switch (name.charAt(0)) {
-				case '#':
-					// Permissions
-					if (name.equalsIgnoreCase(Constants.ADMIN_ROLE)) {
-						model.canAdmin = true;
-					}
-					break;
-				default:
-					model.addRepository(name);
+		String[] userValues = userInfo.split(",");
+		model.password = userValues[0];
+		for (int i = 1; i < userValues.length; i++) {
+			String role = userValues[i];
+			switch (role.charAt(0)) {
+			case '#':
+				// Permissions
+				if (role.equalsIgnoreCase(Constants.ADMIN_ROLE)) {
+					model.canAdmin = true;
 				}
+				break;
+			default:
+				model.addRepository(role);
 			}
-		}
-		// Retrieve the password from the realm file.
-		// Stupid, I know, but the password is buried within protected inner
-		// classes in private variables. Too much work to reflectively retrieve.
-		try {
-			Properties allUsers = readRealmFile();
-			String value = allUsers.getProperty(username);
-			String password = value.split(",")[0];
-			model.password = password;
-		} catch (Throwable t) {
-			logger.error(MessageFormat.format("Failed to read password for user {0}!", username), t);
 		}
 		return model;
 	}
@@ -120,7 +94,7 @@
 	@Override
 	public boolean updateUserModel(String username, UserModel model) {
 		try {
-			Properties allUsers = readRealmFile();
+			Properties allUsers = read();
 			ArrayList<String> roles = new ArrayList<String>(model.repositories);
 
 			// Permissions
@@ -140,12 +114,7 @@
 			allUsers.remove(username);
 			allUsers.put(model.username, sb.toString());
 
-			writeRealmFile(allUsers);
-
-			// Update login service
-			removeUser(username);
-			putUser(model.username, Credential.getCredential(model.password),
-					roles.toArray(new String[0]));
+			write(allUsers);
 			return true;
 		} catch (Throwable t) {
 			logger.error(MessageFormat.format("Failed to update user model {0}!", model.username),
@@ -163,12 +132,9 @@
 	public boolean deleteUser(String username) {
 		try {
 			// Read realm file
-			Properties allUsers = readRealmFile();
+			Properties allUsers = read();
 			allUsers.remove(username);
-			writeRealmFile(allUsers);
-
-			// Drop user from map
-			removeUser(username);
+			write(allUsers);
 			return true;
 		} catch (Throwable t) {
 			logger.error(MessageFormat.format("Failed to delete user {0}!", username), t);
@@ -178,8 +144,8 @@
 
 	@Override
 	public List<String> getAllUsernames() {
-		List<String> list = new ArrayList<String>();
-		list.addAll(_users.keySet());
+		Properties allUsers = read();
+		List<String> list = new ArrayList<String>(allUsers.stringPropertyNames());
 		return list;
 	}
 
@@ -187,7 +153,7 @@
 	public List<String> getUsernamesForRole(String role) {
 		List<String> list = new ArrayList<String>();
 		try {
-			Properties allUsers = readRealmFile();
+			Properties allUsers = read();
 			for (String username : allUsers.stringPropertyNames()) {
 				String value = allUsers.getProperty(username);
 				String[] values = value.split(",");
@@ -214,7 +180,7 @@
 			Set<String> needsRemoveRole = new HashSet<String>();
 
 			// identify users which require add and remove role
-			Properties allUsers = readRealmFile();
+			Properties allUsers = read();
 			for (String username : allUsers.stringPropertyNames()) {
 				String value = allUsers.getProperty(username);
 				String[] values = value.split(",");
@@ -239,11 +205,6 @@
 				String userValues = allUsers.getProperty(user);
 				userValues += "," + role;
 				allUsers.put(user, userValues);
-				String[] values = userValues.split(",");
-				String password = values[0];
-				String[] roles = new String[values.length - 1];
-				System.arraycopy(values, 1, roles, 0, values.length - 1);
-				putUser(user, Credential.getCredential(password), roles);
 			}
 
 			// remove role from user
@@ -267,14 +228,10 @@
 
 				// update properties
 				allUsers.put(user, sb.toString());
-
-				// update memory
-				putUser(user, Credential.getCredential(password),
-						revisedRoles.toArray(new String[0]));
 			}
 
 			// persist changes
-			writeRealmFile(allUsers);
+			write(allUsers);
 			return true;
 		} catch (Throwable t) {
 			logger.error(MessageFormat.format("Failed to set usernames for role {0}!", role), t);
@@ -285,7 +242,7 @@
 	@Override
 	public boolean renameRole(String oldRole, String newRole) {
 		try {
-			Properties allUsers = readRealmFile();
+			Properties allUsers = read();
 			Set<String> needsRenameRole = new HashSet<String>();
 
 			// identify users which require role rename
@@ -325,14 +282,10 @@
 
 				// update properties
 				allUsers.put(user, sb.toString());
-
-				// update memory
-				putUser(user, Credential.getCredential(password),
-						revisedRoles.toArray(new String[0]));
 			}
 
 			// persist changes
-			writeRealmFile(allUsers);
+			write(allUsers);
 			return true;
 		} catch (Throwable t) {
 			logger.error(
@@ -344,7 +297,7 @@
 	@Override
 	public boolean deleteRole(String role) {
 		try {
-			Properties allUsers = readRealmFile();
+			Properties allUsers = read();
 			Set<String> needsDeleteRole = new HashSet<String>();
 
 			// identify users which require role rename
@@ -383,14 +336,10 @@
 
 				// update properties
 				allUsers.put(user, sb.toString());
-
-				// update memory
-				putUser(user, Credential.getCredential(password),
-						revisedRoles.toArray(new String[0]));
 			}
 
 			// persist changes
-			writeRealmFile(allUsers);
+			write(allUsers);
 			return true;
 		} catch (Throwable t) {
 			logger.error(MessageFormat.format("Failed to delete role {0}!", role), t);
@@ -398,74 +347,27 @@
 		return false;
 	}
 
-	private Properties readRealmFile() throws IOException {
-		Properties allUsers = new Properties();
-		FileReader reader = new FileReader(realmFile);
-		allUsers.load(reader);
-		reader.close();
-		return allUsers;
-	}
-
-	private void writeRealmFile(Properties properties) throws IOException {
+	private void write(Properties properties) throws IOException {
 		// Update realm file
-		File realmFileCopy = new File(realmFile.getAbsolutePath() + ".tmp");
+		File realmFileCopy = new File(propertiesFile.getAbsolutePath() + ".tmp");
 		FileWriter writer = new FileWriter(realmFileCopy);
 		properties
 				.store(writer,
 						"# Gitblit realm file format: username=password,\\#permission,repository1,repository2...");
 		writer.close();
 		if (realmFileCopy.exists() && realmFileCopy.length() > 0) {
-			if (realmFile.delete()) {
-				if (!realmFileCopy.renameTo(realmFile)) {
+			if (propertiesFile.delete()) {
+				if (!realmFileCopy.renameTo(propertiesFile)) {
 					throw new IOException(MessageFormat.format("Failed to rename {0} to {1}!",
-							realmFileCopy.getAbsolutePath(), realmFile.getAbsolutePath()));
+							realmFileCopy.getAbsolutePath(), propertiesFile.getAbsolutePath()));
 				}
 			} else {
 				throw new IOException(MessageFormat.format("Failed to delete (0)!",
-						realmFile.getAbsolutePath()));
+						propertiesFile.getAbsolutePath()));
 			}
 		} else {
 			throw new IOException(MessageFormat.format("Failed to save {0}!",
 					realmFileCopy.getAbsolutePath()));
 		}
-	}
-
-	/* ------------------------------------------------------------ */
-	@Override
-	public void loadUsers() throws IOException {
-		if (realmFile == null) {
-			return;
-		}
-
-		if (Log.isDebugEnabled()) {
-			Log.debug("Load " + this + " from " + realmFile);
-		}
-		Properties allUsers = readRealmFile();
-
-		// Map Users
-		for (Map.Entry<Object, Object> entry : allUsers.entrySet()) {
-			String username = ((String) entry.getKey()).trim();
-			String credentials = ((String) entry.getValue()).trim();
-			String roles = null;
-			int c = credentials.indexOf(',');
-			if (c > 0) {
-				roles = credentials.substring(c + 1).trim();
-				credentials = credentials.substring(0, c).trim();
-			}
-
-			if (username != null && username.length() > 0 && credentials != null
-					&& credentials.length() > 0) {
-				String[] roleArray = IdentityService.NO_ROLES;
-				if (roles != null && roles.length() > 0) {
-					roleArray = roles.split(",");
-				}
-				putUser(username, Credential.getCredential(credentials), roleArray);
-			}
-		}
-	}
-
-	@Override
-	protected UserIdentity loadUser(String username) {
-		return null;
 	}
 }

--
Gitblit v1.9.1