@@ -5,7 +5,7 @@ Gitblit is an open source, pure Java Git solution for managing, viewing, and ser | |||
More information about Gitblit can be found [here](http://gitblit.com). | |||
<a href='https://github.com/fzs/gitblit/releases/latest'><img src='https://img.shields.io/badge/dynamic/json?color=9cf&label=Download&query=%24.name&url=https%3A%2F%2Fapi.github.com%2Frepos%2Ffzs%2Fgitblit%2Freleases%2Flatest'></a> | |||
<a href='https://github.com/gitblit/gitblit/releases/latest'><img src='https://img.shields.io/badge/dynamic/json?color=9cf&label=Download&query=%24.name&url=https%3A%2F%2Fapi.github.com%2Frepos%2Fgitblit%2Fgitblit%2Freleases%2Flatest'></a> | |||
License | |||
------- |
@@ -10,12 +10,12 @@ name: Gitblit | |||
description: pure Java Git solution | |||
groupId: com.gitblit | |||
artifactId: gitblit | |||
version: 1.9.0-SNAPSHOT | |||
version: 1.9.1-SNAPSHOT | |||
inceptionYear: 2011 | |||
# Current stable release | |||
releaseVersion: 1.8.0 | |||
releaseDate: 2016-06-22 | |||
releaseVersion: 1.9.0 | |||
releaseDate: 2020-02-01 | |||
# Project urls | |||
url: 'http://gitblit.com' | |||
@@ -96,8 +96,8 @@ dependencyDirectory: ext | |||
registeredRepositories: | |||
- { id: central, url: 'https://repo1.maven.org/maven2' } | |||
- { id: mavencentral, url: 'https://repo1.maven.org/maven2' } | |||
- { id: eclipse, url: 'http://repo.eclipse.org/content/groups/releases' } | |||
- { id: eclipse-snapshots, url: 'http://repo.eclipse.org/content/groups/snapshots' } | |||
- { id: eclipse, url: 'https://repo.eclipse.org/content/groups/releases' } | |||
- { id: eclipse-snapshots, url: 'https://repo.eclipse.org/content/groups/snapshots' } | |||
- { id: gitblit, url: 'http://gitblit.github.io/gitblit-maven' } | |||
# Source all dependencies from the following repositories in the specified order |
@@ -1,10 +1,50 @@ | |||
# | |||
# ${project.version} release | |||
# | |||
r30: { | |||
r31: { | |||
title: ${project.name} ${project.version} released | |||
id: ${project.version} | |||
date: ${project.buildDate} | |||
note: '' | |||
When you have Gitblit installed as a service under Linux or Windows, you may need to edit your service script/definition. The command line to start Gitblit needs to be different, the classpath and class are speficied now. | |||
See notes for release 1.9.0. | |||
'' | |||
html: ~ | |||
text: '' | |||
!! IMPORTANT BUG FIX FOR PASSWORD HASH UPGRADE !! | |||
There is a severe bug in version 1.9.0, which can lock users out from their accounts. | |||
When updating from a previous version to 1.9.0, existing stored passwords are rehashed | |||
with a more secure password hash mechanism when a user first logs in after the update. | |||
This happens when the password hashing mechanism was left at default and not specifically | |||
set in the configuration. An error in the implementation will destroy the stored password | |||
instead and the user can no longer log in. | |||
Only certain circumstances will lead to this wrong behaviour. It will most likely | |||
affect users of the Gitblit Docker container. If you did not encounter any problems, | |||
update to 1.9.1 to be on the safe side. If you were hit by this bug, we are deeply sorry. | |||
There is no way to fix the affected accounts other than to set a new password. | |||
This is fixed in 1.9.1. Updates of existing installations should be made to 1.9.1, not 1.9.0. | |||
'' | |||
security: ~ | |||
fixes: | |||
- Fixed broken password hash upgrade destroying existing stored passwords on update. | |||
- Fixed Linux service scripts to use `-cp` parameter instead of `-jar`. | |||
changes: ~ | |||
additions: ~ | |||
dependencyChanges: ~ | |||
contributors: ~ | |||
} | |||
# | |||
# 1.9.0 release | |||
# | |||
r30: { | |||
title: Gitblit 1.9.0 released | |||
id: 1.9.0 | |||
date: 2020-02-01 | |||
note: '' | |||
Gitblit uses Servlet 3.0 and thus drops support for Tomcat 6. Run on Tomcat 6 at your own risk. | |||
@@ -18,7 +58,8 @@ r30: { | |||
When the `realm.ldap.bindpattern` property is set, GitBlit will only bind as the user to LDAP, not to a manager account or anonymously. | |||
Older password storage mechanisms are deprecated, PBKDF2 is the new default. When you switch from plaintext to a hashed scheme, or from the older hashed to the new PBKDF2 scheme, the stored password of a user will be rehashed with the more secure mechanism when the user logs in. | |||
Older password storage mechanisms are deprecated, PBKDF2 is the new default. When you switch from plaintext to a hashed scheme, or from the older hashed to the new PBKDF2 scheme, the stored password of a user will be rehashed with the more secure mechanism when the user logs in. | |||
!! THIS IS BROKEN IN 1.9.0. DO NOT UPDATE TO 1.9.0. USE 1.9.1 INSTEAD !! | |||
'' | |||
html: ~ | |||
text: '' | |||
@@ -1949,6 +1990,6 @@ r1: { | |||
- James Moger | |||
} | |||
snapshot: &r30 | |||
release: &r29 | |||
releases: &r[1..29] | |||
snapshot: &r31 | |||
release: &r30 | |||
releases: &r[1..30] |
@@ -1,2 +1,2 @@ | |||
#!/bin/bash | |||
java -cp gitblit.jar:ext/* com.gitblit.authority.GitblitAuthority --baseFolder data | |||
java -cp "gitblit.jar:ext/*" com.gitblit.authority.GitblitAuthority --baseFolder data |
@@ -18,16 +18,16 @@ After=network.target | |||
[Service] | |||
User=gitblit | |||
Group=gitblit | |||
Environment="ARGS=-server -Xmx1024M -Djava.awt.headless=true -jar" | |||
Environment="ARGS=-server -Xmx1024M -Djava.awt.headless=true -cp" | |||
EnvironmentFile=-/etc/sysconfig/gitblit | |||
WorkingDirectory=/opt/gitblit | |||
ExecStart=/usr/bin/java \$ARGS gitblit.jar --httpsPort \$GITBLIT_HTTPS_PORT --httpPort \$GITBLIT_HTTP_PORT --baseFolder \$GITBLIT_BASE_FOLDER --dailyLogFile | |||
ExecStop=/usr/bin/java \$ARGS gitblit.jar --baseFolder \$GITBLIT_BASE_FOLDER --stop | |||
ExecStart=/usr/bin/java \$ARGS gitblit.jar:ext/* com.gitblit.GitBlitServer --httpsPort \$GITBLIT_HTTPS_PORT --httpPort \$GITBLIT_HTTP_PORT --baseFolder \$GITBLIT_BASE_FOLDER --dailyLogFile | |||
ExecStop=/usr/bin/java \$ARGS gitblit.jar:ext/* com.gitblit.GitBlitServer --baseFolder \$GITBLIT_BASE_FOLDER --stop | |||
[Install] | |||
WantedBy=multi-user.target | |||
EOF | |||
# Finally copy the files to the destination and register the systemd unit. | |||
sudo su -c "cp /tmp/gitblit.defaults /etc/sysconfig/gitblit && cp /tmp/gitblit.service /etc/systemd/system/" | |||
sudo su -c "systemctl daemon-reload && systemctl enable gitblit.service && systemctl start gitblit.service" | |||
sudo sh -c "cp /tmp/gitblit.defaults /etc/sysconfig/gitblit && cp /tmp/gitblit.service /etc/systemd/system/" | |||
sudo sh -c "systemctl daemon-reload && systemctl enable gitblit.service && systemctl start gitblit.service" |
@@ -8,7 +8,7 @@ | |||
# | |||
# -------------------------------------------------------------------------- | |||
if [[ -z $1 || -z $2 ]]; then | |||
if [ -z $1 ] || [ -z $2 ]; then | |||
echo "Please specify the output ticket service and your baseFolder!"; | |||
echo ""; | |||
echo "usage:"; | |||
@@ -17,5 +17,5 @@ if [[ -z $1 || -z $2 ]]; then | |||
exit 1; | |||
fi | |||
java -cp gitblit.jar:./ext/* com.gitblit.MigrateTickets $1 --baseFolder $2 | |||
java -cp "gitblit.jar:ext/*" com.gitblit.MigrateTickets $1 --baseFolder $2 | |||
@@ -11,7 +11,7 @@ | |||
# | |||
# -------------------------------------------------------------------------- | |||
if [[ -z $1 ]]; then | |||
if [ -z $1 ] ; then | |||
echo "Please specify your baseFolder!"; | |||
echo ""; | |||
echo "usage:"; | |||
@@ -20,5 +20,5 @@ if [[ -z $1 ]]; then | |||
exit 1; | |||
fi | |||
java -cp gitblit.jar:./ext/* com.gitblit.ReindexTickets --baseFolder $1 | |||
java -cp "gitblit.jar:ext/*" com.gitblit.ReindexTickets --baseFolder $1 | |||
@@ -11,7 +11,7 @@ GITBLIT_HTTP_PORT=0 | |||
GITBLIT_HTTPS_PORT=8443 | |||
GITBLIT_LOG=/var/log/gitblit.log | |||
source ${GITBLIT_PATH}/java-proxy-config.sh | |||
JAVA="java -server -Xmx1024M ${JAVA_PROXY_CONFIG} -Djava.awt.headless=true -jar" | |||
JAVA="java -server -Xmx1024M ${JAVA_PROXY_CONFIG} -Djava.awt.headless=true -cp" | |||
RETVAL=0 | |||
@@ -21,7 +21,7 @@ case "$1" in | |||
then | |||
echo $"Starting gitblit server" | |||
cd $GITBLIT_PATH | |||
$JAVA $GITBLIT_PATH/gitblit.jar --httpsPort $GITBLIT_HTTPS_PORT --httpPort $GITBLIT_HTTP_PORT --baseFolder $GITBLIT_BASE_FOLDER --dailyLogFile & | |||
$JAVA "$GITBLIT_PATH/gitblit.jar:$GITBLIT_PATH/ext/*" com.gitblit.GitBlitServer --httpsPort $GITBLIT_HTTPS_PORT --httpPort $GITBLIT_HTTP_PORT --baseFolder $GITBLIT_BASE_FOLDER --dailyLogFile & | |||
echo "." | |||
exit $RETVAL | |||
fi | |||
@@ -32,7 +32,7 @@ case "$1" in | |||
then | |||
echo $"Stopping gitblit server" | |||
cd $GITBLIT_PATH | |||
$JAVA $GITBLIT_PATH/gitblit.jar --baseFolder $GITBLIT_BASE_FOLDER --stop > /dev/null & | |||
$JAVA "$GITBLIT_PATH/gitblit.jar:$GITBLIT_PATH/ext/*" com.gitblit.GitBlitServer --baseFolder $GITBLIT_BASE_FOLDER --stop > /dev/null & | |||
echo "." | |||
exit $RETVAL | |||
fi |
@@ -19,7 +19,7 @@ GITBLIT_PATH=/opt/gitblit | |||
GITBLIT_BASE_FOLDER=/opt/gitblit/data | |||
GITBLIT_USER="gitblit" | |||
source ${GITBLIT_PATH}/java-proxy-config.sh | |||
ARGS="-server -Xmx1024M ${JAVA_PROXY_CONFIG} -Djava.awt.headless=true -jar gitblit.jar --baseFolder $GITBLIT_BASE_FOLDER --dailyLogFile" | |||
ARGS="-server -Xmx1024M ${JAVA_PROXY_CONFIG} -Djava.awt.headless=true -cp gitblit.jar:ext/* com.gitblit.GitBlitServer --baseFolder $GITBLIT_BASE_FOLDER --dailyLogFile" | |||
RETVAL=0 | |||
@@ -18,10 +18,7 @@ package com.gitblit.manager; | |||
import java.nio.charset.Charset; | |||
import java.security.Principal; | |||
import java.text.MessageFormat; | |||
import java.util.ArrayList; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.*; | |||
import java.util.concurrent.TimeUnit; | |||
import javax.servlet.http.Cookie; | |||
@@ -455,7 +452,6 @@ public class AuthenticationManager implements IAuthenticationManager { | |||
/** | |||
* Authenticate a user based on a username and password. | |||
* | |||
* @see IUserService.authenticate(String, char[]) | |||
* @param username | |||
* @param password | |||
* @return a user object or null | |||
@@ -474,34 +470,39 @@ public class AuthenticationManager implements IAuthenticationManager { | |||
} | |||
String usernameDecoded = StringUtils.decodeUsername(username); | |||
String pw = new String(password); | |||
if (StringUtils.isEmpty(pw)) { | |||
if (StringUtils.isEmpty(password)) { | |||
// can not authenticate empty password | |||
return null; | |||
} | |||
UserModel user = userManager.getUserModel(usernameDecoded); | |||
// try local authentication | |||
if (user != null && user.isLocalAccount()) { | |||
UserModel returnedUser = authenticateLocal(user, password); | |||
if (returnedUser != null) { | |||
// user authenticated | |||
return returnedUser; | |||
} | |||
} else { | |||
// try registered external authentication providers | |||
for (AuthenticationProvider provider : authenticationProviders) { | |||
if (provider instanceof UsernamePasswordAuthenticationProvider) { | |||
UserModel returnedUser = provider.authenticate(usernameDecoded, password); | |||
if (returnedUser != null) { | |||
// user authenticated | |||
returnedUser.accountType = provider.getAccountType(); | |||
return validateAuthentication(returnedUser, AuthenticationType.CREDENTIALS); | |||
try { | |||
// try local authentication | |||
if (user != null && user.isLocalAccount()) { | |||
UserModel returnedUser = authenticateLocal(user, password); | |||
if (returnedUser != null) { | |||
// user authenticated | |||
return returnedUser; | |||
} | |||
} else { | |||
// try registered external authentication providers | |||
for (AuthenticationProvider provider : authenticationProviders) { | |||
if (provider instanceof UsernamePasswordAuthenticationProvider) { | |||
UserModel returnedUser = provider.authenticate(usernameDecoded, password); | |||
if (returnedUser != null) { | |||
// user authenticated | |||
returnedUser.accountType = provider.getAccountType(); | |||
return validateAuthentication(returnedUser, AuthenticationType.CREDENTIALS); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
finally { | |||
// Zero out password array to delete password from memory | |||
Arrays.fill(password, Character.MIN_VALUE); | |||
} | |||
// could not authenticate locally or with a provider | |||
logger.warn(MessageFormat.format("Failed login attempt for {0}, invalid credentials from {1}", username, | |||
@@ -520,21 +521,33 @@ public class AuthenticationManager implements IAuthenticationManager { | |||
protected UserModel authenticateLocal(UserModel user, char [] password) { | |||
UserModel returnedUser = null; | |||
PasswordHash pwdHash = PasswordHash.instanceFor(user.password); | |||
if (pwdHash != null) { | |||
if (pwdHash.matches(user.password, password, user.username)) { | |||
// Create a copy of the password that we can use to rehash to upgrade to a more secure hashing method. | |||
// This is done to be independent from the implementation of the PasswordHash, which might already clear out | |||
// the password it gets passed in. This looks a bit stupid, as we could simply clean up the mess, but this | |||
// falls under "better safe than sorry". | |||
char[] pwdToUpgrade = Arrays.copyOf(password, password.length); | |||
try { | |||
PasswordHash pwdHash = PasswordHash.instanceFor(user.password); | |||
if (pwdHash != null) { | |||
if (pwdHash.matches(user.password, password, user.username)) { | |||
returnedUser = user; | |||
} | |||
} else if (user.password.equals(new String(password))) { | |||
// plain-text password | |||
returnedUser = user; | |||
} | |||
} else if (user.password.equals(new String(password))) { | |||
// plain-text password | |||
returnedUser = user; | |||
} | |||
// validate user | |||
returnedUser = validateAuthentication(returnedUser, AuthenticationType.CREDENTIALS); | |||
// try to upgrade the stored password hash to a stronger hash, if necessary | |||
upgradeStoredPassword(returnedUser, password, pwdHash); | |||
// validate user | |||
returnedUser = validateAuthentication(returnedUser, AuthenticationType.CREDENTIALS); | |||
// try to upgrade the stored password hash to a stronger hash, if necessary | |||
upgradeStoredPassword(returnedUser, pwdToUpgrade, pwdHash); | |||
} | |||
finally { | |||
// Now we make sure that the password is zeroed out in any case. | |||
Arrays.fill(password, Character.MIN_VALUE); | |||
Arrays.fill(pwdToUpgrade, Character.MIN_VALUE); | |||
} | |||
return returnedUser; | |||
} |
@@ -56,6 +56,21 @@ public class StringUtils { | |||
return value == null || value.trim().length() == 0; | |||
} | |||
/** | |||
* Returns true if the character array represents an empty String. | |||
* An empty character sequence is defined as a sequence that | |||
* either has no characters at all, or no characters above | |||
* '\u0020' (space). | |||
* | |||
* @param value | |||
* @return true if value is null or represents an empty String | |||
*/ | |||
public static boolean isEmpty(char[] value) { | |||
if (value == null || value.length == 0) return true; | |||
for ( char c : value) if (c > '\u0020') return false; | |||
return true; | |||
} | |||
/** | |||
* Replaces carriage returns and line feeds with html line breaks. | |||
* |
@@ -335,6 +335,6 @@ Instead of using `federation.properties` you may directly specify a Gitblit inst | |||
java -cp fedclient.jar;"%CD%/ext/*" com.gitblit.FederationClient --url https://go.gitblit.com --mirror --bare --token 123456789 | |||
--repositoriesFolder c:/mymirror | |||
java -cp fedclient.jar:ext/* com.gitblit.FederationClient --url https://go.gitblit.com --mirror --bare --token 123456789 | |||
java -cp "fedclient.jar:ext/*" com.gitblit.FederationClient --url https://go.gitblit.com --mirror --bare --token 123456789 | |||
--repositoriesFolder /srv/mymirror --daemon --frequency "24 hours" | |||
@@ -8,7 +8,7 @@ Gitblit optionally allows a remote client to administer the Gitblit server. Thi | |||
web.enableRpcManagement=false | |||
web.enableRpcAdministration=false | |||
**https** is strongly recommended because passwords are insecurely transmitted form your browser/rpc client using Basic authentication! | |||
**https** is strongly recommended because passwords are insecurely transmitted from your browser/rpc client using Basic authentication! | |||
The Gitblit JSON RPC mechanism, like the Gitblit JGit servlet, syndication/feed servlet, etc, supports request-based authentication. Making an *admin* request will trigger Gitblit's basic authentication mechanism. Listing of repositories, generally, will not trigger this authentication mechanism unless *web.authenticateViewPages=true*. That means its possible to allow anonymous enumeration of repositories that are not *view restricted* or *clone restricted*. Of course, if credentials are provided then all private repositories that are available to the user account will be enumerated in the JSON response. | |||
@@ -17,7 +17,7 @@ Open `data/gitblit.properties` in your favorite text editor and make sure to rev | |||
**NOTE:** You can only have **one** SSL certificate specified for a port. | |||
4. exit the authority app | |||
4. Windows: Execute `gitblit.cmd` or `java -cp gitblit.jar;"%CD%\ext\*" com.gitblit.GitBlitServer --baseFolder data` from a command-line | |||
Linux/OSX: Execute `gitblit.sh` or `java -cp gitblit.jar;ext/* com.gitblit.GitBlitServer --baseFolder data` from a command-line | |||
Linux/OSX: Execute `gitblit.sh` or `java -cp "gitblit.jar:ext/*"" com.gitblit.GitBlitServer --baseFolder data` from a command-line | |||
5. Open your browser to <http://localhost:8080> or <https://localhost:8443> depending on your chosen configuration. | |||
6. Enter the default administrator credentials: **admin / admin** and click the *Login* button | |||
**NOTE:** Make sure to change the administrator username and/or password!! |
@@ -1,3 +1,25 @@ | |||
## Upgrading Gitblit GO (1.9.1+) | |||
The command line to start Gitblit has changed from | |||
``` | |||
java -jar gitblit.jar --baseFolder data | |||
``` | |||
to | |||
``` | |||
java -cp "gitblit.jar:ext/*" com.gitblit.GitBlitServer --baseFolder data | |||
``` | |||
or on Windows to | |||
``` | |||
java -cp gitblit.jar;"%CD%\ext\*" com.gitblit.GitBlitServer --baseFolder data | |||
``` | |||
The class path and main class need to be specified now. If you have installed Gitblit as a service you will need to adjust the service scripts or definitions accordingly. | |||
## Upgrading Gitblit GO (1.7.0+) | |||
The default `gitblit.properties` file has been split into two files: `gitblit.properties`, which is the recommended file for setting your configuration, and `defaults.properties` which are Gitblit's default settings. |
@@ -19,13 +19,7 @@ import java.io.BufferedReader; | |||
import java.io.IOException; | |||
import java.io.UnsupportedEncodingException; | |||
import java.security.Principal; | |||
import java.util.Collection; | |||
import java.util.Collections; | |||
import java.util.Enumeration; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
import java.util.Locale; | |||
import java.util.Map; | |||
import java.util.*; | |||
import javax.servlet.AsyncContext; | |||
import javax.servlet.DispatcherType; | |||
@@ -654,16 +648,84 @@ public class AuthenticationManagerTest extends GitblitUnitTest { | |||
public void testAuthenticate() throws Exception { | |||
IAuthenticationManager auth = newAuthenticationManager(); | |||
String password = "pass word"; | |||
UserModel user = new UserModel("sunnyjim"); | |||
user.password = "password"; | |||
user.password = password; | |||
users.updateUserModel(user); | |||
assertNotNull(auth.authenticate(user.username, user.password.toCharArray(), null)); | |||
char[] pwd = password.toCharArray(); | |||
assertNotNull(auth.authenticate(user.username, pwd, null)); | |||
// validate that the passed in password has been zeroed out in memory | |||
char[] zeroes = new char[pwd.length]; | |||
Arrays.fill(zeroes, Character.MIN_VALUE); | |||
assertArrayEquals(zeroes, pwd); | |||
} | |||
@Test | |||
public void testAuthenticateDisabledUser() throws Exception { | |||
IAuthenticationManager auth = newAuthenticationManager(); | |||
String password = "password"; | |||
UserModel user = new UserModel("sunnyjim"); | |||
user.password = password; | |||
user.disabled = true; | |||
users.updateUserModel(user); | |||
assertNull(auth.authenticate(user.username, password.toCharArray(), null)); | |||
user.disabled = false; | |||
users.updateUserModel(user); | |||
assertNotNull(auth.authenticate(user.username, password.toCharArray(), null)); | |||
} | |||
@Test | |||
public void testAuthenticateEmptyPassword() throws Exception { | |||
IAuthenticationManager auth = newAuthenticationManager(); | |||
String password = "password"; | |||
UserModel user = new UserModel("sunnyjim"); | |||
user.password = password; | |||
users.updateUserModel(user); | |||
assertNull(auth.authenticate(user.username, "".toCharArray(), null)); | |||
assertNull(auth.authenticate(user.username, " ".toCharArray(), null)); | |||
assertNull(auth.authenticate(user.username, new char[]{' ', '\u0010', '\u0015'}, null)); | |||
} | |||
@Test | |||
public void testAuthenticateWrongPassword() throws Exception { | |||
IAuthenticationManager auth = newAuthenticationManager(); | |||
String password = "password"; | |||
UserModel user = new UserModel("sunnyjim"); | |||
user.password = password; | |||
users.updateUserModel(user); | |||
assertNull(auth.authenticate(user.username, user.password.toCharArray(), null)); | |||
users.deleteUserModel(user); | |||
assertNull(auth.authenticate(user.username, "helloworld".toCharArray(), null)); | |||
} | |||
@Test | |||
public void testAuthenticateNoSuchUser() throws Exception { | |||
IAuthenticationManager auth = newAuthenticationManager(); | |||
String password = "password"; | |||
UserModel user = new UserModel("sunnyjim"); | |||
user.password = password; | |||
users.updateUserModel(user); | |||
assertNull(auth.authenticate("rainyjoe", password.toCharArray(), null)); | |||
} | |||
@@ -671,14 +733,18 @@ public class AuthenticationManagerTest extends GitblitUnitTest { | |||
public void testAuthenticateUpgradePlaintext() throws Exception { | |||
IAuthenticationManager auth = newAuthenticationManager(); | |||
String password = "topsecret"; | |||
UserModel user = new UserModel("sunnyjim"); | |||
user.password = "password"; | |||
user.password = password; | |||
users.updateUserModel(user); | |||
assertNotNull(auth.authenticate(user.username, user.password.toCharArray(), null)); | |||
assertNotNull(auth.authenticate(user.username, password.toCharArray(), null)); | |||
// validate that plaintext password was automatically updated to hashed one | |||
assertTrue(user.password.startsWith(PasswordHash.getDefaultType().name() + ":")); | |||
// validate that the password is still valid and the user can log in | |||
assertNotNull(auth.authenticate(user.username, password.toCharArray(), null)); | |||
} | |||
@@ -686,14 +752,18 @@ public class AuthenticationManagerTest extends GitblitUnitTest { | |||
public void testAuthenticateUpgradeMD5() throws Exception { | |||
IAuthenticationManager auth = newAuthenticationManager(); | |||
String password = "secretAndHashed"; | |||
UserModel user = new UserModel("sunnyjim"); | |||
user.password = "MD5:5F4DCC3B5AA765D61D8327DEB882CF99"; | |||
user.password = "MD5:BD95A1CFD00868B59B3564112D1E5847"; | |||
users.updateUserModel(user); | |||
assertNotNull(auth.authenticate(user.username, "password".toCharArray(), null)); | |||
assertNotNull(auth.authenticate(user.username, password.toCharArray(), null)); | |||
// validate that MD5 password was automatically updated to hashed one | |||
assertTrue(user.password.startsWith(PasswordHash.getDefaultType().name() + ":")); | |||
// validate that the password is still valid and the user can log in | |||
assertNotNull(auth.authenticate(user.username, password.toCharArray(), null)); | |||
} | |||
@@ -26,12 +26,25 @@ public class StringUtilsTest extends GitblitUnitTest { | |||
@Test | |||
public void testIsEmpty() throws Exception { | |||
assertTrue(StringUtils.isEmpty(null)); | |||
assertTrue(StringUtils.isEmpty((String)null)); | |||
assertTrue(StringUtils.isEmpty("")); | |||
assertTrue(StringUtils.isEmpty(" ")); | |||
assertFalse(StringUtils.isEmpty("A")); | |||
} | |||
@Test | |||
public void testIsEmptyCharArray() throws Exception { | |||
assertTrue(StringUtils.isEmpty((char[])null)); | |||
assertTrue(StringUtils.isEmpty(new char[0])); | |||
assertTrue(StringUtils.isEmpty(new char[]{ ' ' })); | |||
assertTrue(StringUtils.isEmpty(new char[]{ ' '})); | |||
assertTrue(StringUtils.isEmpty(new char[]{ ' ', ' ' })); | |||
assertTrue(StringUtils.isEmpty(new char[]{ ' ', ' ', ' ' })); | |||
assertFalse(StringUtils.isEmpty(new char[]{ '\u0020', 'f' })); | |||
assertFalse(StringUtils.isEmpty(new char[]{ '\u0148', '\u0020' })); | |||
assertFalse(StringUtils.isEmpty(new char[]{ 'A' })); | |||
} | |||
@Test | |||
public void testBreakLinesForHtml() throws Exception { | |||
String input = "this\nis\r\na\rtest\r\n\r\nof\n\nline\r\rbreaking"; |