realm.userService = users.properties\r
\r
# How to store passwords.\r
-# Valid values are plain or md5. Default is md5.\r
+# Valid values are plain, md5, or combined-md5. md5 is the hash of password.\r
+# combined-md5 is the hash of username.toLowerCase()+password.\r
+# Default is md5.\r
#\r
# SINCE 0.5.0 \r
realm.passwordStorage = md5\r
- added: Gitblit Manager (Java/Swing Application) for remote administration of a Gitblit server.\r
- added: per-repository setting to skip size calculation (faster repositories page loading)\r
- added: per-repository setting to skip summary metrics calculation (faster summary page loading)\r
+- added: IUserService.setup(IStoredSettings) for custom user service implementations\r
+- added: setting to control Gitblit GO context path for proxy setups \r
+ **New:** *server.contextPath = /*\r
+- added: *combined-md5* password storage option which stores the hash of username+password as the password\r
- fixed: federation protocol timestamps. dates are now serialized to the [iso8601](http://en.wikipedia.org/wiki/ISO_8601) standard. \r
**This breaks 0.6.0 federation clients/servers.**\r
- fixed: collision on rename for repositories and users\r
- fixed: Set the RSS content type of syndication feeds for Firefox 4 (issue 22)\r
- fixed: Null pointer exception if did not set federation strategy (issue 20)\r
- fixed: Gitblit GO allows SSL renegotiation if running on Java 1.6.0_22 or later\r
-- added: IUserService.setup(IStoredSettings) for custom user service implementations\r
-- added: setting to control Gitblit GO context path for proxy setups \r
- **New:** *server.contextPath = /*\r
- updated: MarkdownPapers 1.2.4\r
\r
issues, binaries, and sources @ [Google Code][googlecode]<br/>\r
- added: Gitblit Manager (Java/Swing Application) for remote administration of a Gitblit server.\r
- added: per-repository setting to skip size calculation (faster repositories page loading)\r
- added: per-repository setting to skip summary metrics calculation (faster summary page loading)\r
+- added: IUserService.setup(IStoredSettings) for custom user service implementations\r
+- added: setting to control Gitblit GO context path for proxy setups \r
+ **New:** *server.contextPath = /*\r
+- added: *combined-md5* password storage option which stores the hash of username+password as the password\r
- fixed: federation protocol timestamps. dates are now serialized to the [iso8601](http://en.wikipedia.org/wiki/ISO_8601) standard. \r
**This breaks 0.6.0 federation clients/servers.**\r
- fixed: collision on rename for repositories and users\r
- fixed: Set the RSS content type of syndication feeds for Firefox 4 (issue 22)\r
- fixed: Null pointer exception if did not set federation strategy (issue 20)\r
- fixed: Gitblit GO allows SSL renegotiation if running on Java 1.6.0_22 or later\r
-- added: IUserService.setup(IStoredSettings) for custom user service implementations\r
-- added: setting to control Gitblit GO context path for proxy setups \r
- **New:** *server.contextPath = /*\r
- updated: MarkdownPapers 1.2.4\r
\r
### Older Releases\r
UserModel returnedUser = null;\r
UserModel user = getUserModel(username);\r
if (user.password.startsWith(StringUtils.MD5_TYPE)) {\r
+ // password digest\r
String md5 = StringUtils.MD5_TYPE + StringUtils.getMD5(new String(password));\r
if (user.password.equalsIgnoreCase(md5)) {\r
returnedUser = user;\r
}\r
+ } else if (user.password.startsWith(StringUtils.COMBINED_MD5_TYPE)) {\r
+ // username+password digest\r
+ String md5 = StringUtils.COMBINED_MD5_TYPE\r
+ + StringUtils.getMD5(username.toLowerCase() + new String(password));\r
+ if (user.password.equalsIgnoreCase(md5)) {\r
+ returnedUser = user;\r
+ }\r
} else if (user.password.equals(new String(password))) {\r
+ // plain-text password\r
returnedUser = user;\r
}\r
return returnedUser;\r
return false;\r
}\r
\r
+ boolean rename = false;\r
// verify username uniqueness on create\r
if (isCreate) {\r
if (usernames.contains(uname.toLowerCase())) {\r
}\r
} else {\r
// check rename collision\r
- if (!username.equalsIgnoreCase(uname)) {\r
+ rename = !StringUtils.isEmpty(username) && !username.equalsIgnoreCase(uname);\r
+ if (rename) {\r
if (usernames.contains(uname.toLowerCase())) {\r
error(MessageFormat.format(\r
"Failed to rename ''{0}'' because ''{1}'' already exists.", username,\r
}\r
}\r
}\r
+ user.username = uname;\r
\r
int minLength = settings.get(Keys.realm.minPasswordLength).getInteger(5);\r
if (minLength < 4) {\r
minLength = 4;\r
}\r
- char[] pw = passwordField.getPassword();\r
- if (pw == null || pw.length < minLength) {\r
+\r
+ String password = new String(passwordField.getPassword());\r
+ if (StringUtils.isEmpty(password) || password.length() < minLength) {\r
error(MessageFormat.format("Password is too short. Minimum length is {0} characters.",\r
minLength));\r
return false;\r
}\r
- char[] cpw = confirmPasswordField.getPassword();\r
- if (cpw == null || cpw.length != pw.length) {\r
- error("Please confirm the password!");\r
- return false;\r
- }\r
- if (!Arrays.equals(pw, cpw)) {\r
- error("Passwords do not match!");\r
+ if (!password.toUpperCase().startsWith(StringUtils.MD5_TYPE)\r
+ && !password.toUpperCase().startsWith(StringUtils.COMBINED_MD5_TYPE)) {\r
+ String cpw = new String(confirmPasswordField.getPassword());\r
+ if (cpw == null || cpw.length() != password.length()) {\r
+ error("Please confirm the password!");\r
+ return false;\r
+ }\r
+ if (!password.equals(cpw)) {\r
+ error("Passwords do not match!");\r
+ return false;\r
+ }\r
+\r
+ String type = settings.get(Keys.realm.passwordStorage).getString("md5");\r
+ if (type.equalsIgnoreCase("md5")) {\r
+ // store MD5 digest of password\r
+ user.password = StringUtils.MD5_TYPE + StringUtils.getMD5(password);\r
+ } else if (type.equalsIgnoreCase("combined-md5")) {\r
+ // store MD5 digest of username+password\r
+ user.password = StringUtils.COMBINED_MD5_TYPE\r
+ + StringUtils.getMD5(username.toLowerCase() + password);\r
+ } else {\r
+ // plain-text password\r
+ user.password = password;\r
+ }\r
+ } else if (rename && password.toUpperCase().startsWith(StringUtils.COMBINED_MD5_TYPE)) {\r
+ error("Gitblit is configured for combined-md5 password hashing. You must enter a new password on account rename.");\r
return false;\r
- }\r
- user.username = uname;\r
- String type = settings.get(Keys.realm.passwordStorage).getString("md5");\r
- if (type.equalsIgnoreCase("md5")) {\r
- // store MD5 digest of password\r
- user.password = StringUtils.MD5_TYPE + StringUtils.getMD5(new String(pw));\r
} else {\r
- user.password = new String(pw);\r
+ // no change in password\r
+ user.password = password;\r
}\r
+\r
user.canAdmin = canAdminCheckbox.isSelected();\r
user.excludeFromFederation = notFederatedCheckbox.isSelected();\r
\r
public class StringUtils {\r
\r
public static final String MD5_TYPE = "MD5:";\r
+ \r
+ public static final String COMBINED_MD5_TYPE = "CMD5:";\r
\r
/**\r
* Returns true if the string is null or empty.\r
return;\r
}\r
\r
+ UserModel user = GitBlitWebSession.get().getUser();\r
+\r
// convert to MD5 digest, if appropriate\r
String type = GitBlit.getString(Keys.realm.passwordStorage, "md5");\r
if (type.equalsIgnoreCase("md5")) {\r
// store MD5 digest of password\r
password = StringUtils.MD5_TYPE + StringUtils.getMD5(password);\r
+ } else if (type.equalsIgnoreCase("combined-md5")) {\r
+ // store MD5 digest of username+password\r
+ password = StringUtils.COMBINED_MD5_TYPE\r
+ + StringUtils.getMD5(user.username.toLowerCase() + password);\r
}\r
\r
- UserModel user = GitBlitWebSession.get().getUser();\r
user.password = password;\r
try {\r
GitBlit.self().updateUserModel(user.username, user, false);\r
} else {\r
super.setupPage(getString("gb.edit"), userModel.username);\r
}\r
- \r
+\r
final Model<String> confirmPassword = new Model<String>(\r
StringUtils.isEmpty(userModel.password) ? "" : userModel.password);\r
CompoundPropertyModel<UserModel> model = new CompoundPropertyModel<UserModel>(userModel);\r
return;\r
}\r
}\r
+ boolean rename = !StringUtils.isEmpty(oldName) && !oldName.equalsIgnoreCase(username);\r
if (!userModel.password.equals(confirmPassword.getObject())) {\r
error("Passwords do not match!");\r
return;\r
}\r
String password = userModel.password;\r
- if (!password.toUpperCase().startsWith(StringUtils.MD5_TYPE)) {\r
+ if (!password.toUpperCase().startsWith(StringUtils.MD5_TYPE)\r
+ && !password.toUpperCase().startsWith(StringUtils.COMBINED_MD5_TYPE)) {\r
// This is a plain text password.\r
// Check length.\r
int minLength = GitBlit.getInteger(Keys.realm.minPasswordLength, 5);\r
// store MD5 digest of password\r
userModel.password = StringUtils.MD5_TYPE\r
+ StringUtils.getMD5(userModel.password);\r
+ } else if (type.equalsIgnoreCase("combined-md5")) {\r
+ // store MD5 digest of username+password\r
+ userModel.password = StringUtils.COMBINED_MD5_TYPE\r
+ + StringUtils.getMD5(username.toLowerCase() + userModel.password);\r
}\r
+ } else if (rename\r
+ && password.toUpperCase().startsWith(StringUtils.COMBINED_MD5_TYPE)) {\r
+ error("Gitblit is configured for combined-md5 password hashing. You must enter a new password on account rename.");\r
+ return;\r
}\r
\r
Iterator<String> selectedRepositories = repositories.getSelectedChoices();\r