diff options
author | Florian Zschocke <f.zschocke+git@gmail.com> | 2020-04-05 13:07:25 +0200 |
---|---|---|
committer | Florian Zschocke <f.zschocke+git@gmail.com> | 2020-04-05 13:07:25 +0200 |
commit | a93cd37bc60b4f311692e0e9c6b0ddf320eb5c29 (patch) | |
tree | f48a9a963233f1f23d4e77e9ba9e908ea5bb6472 | |
parent | 08666d065be34a227a9b5bb16810280d8ee39178 (diff) | |
parent | 34e77ddf09e58ea0a817d31ed74a6bce574bff97 (diff) | |
download | gitblit-a93cd37bc60b4f311692e0e9c6b0ddf320eb5c29.tar.gz gitblit-a93cd37bc60b4f311692e0e9c6b0ddf320eb5c29.zip |
Merge branch 'master' into releaser1.9.1
-rw-r--r-- | README.markdown | 2 | ||||
-rw-r--r-- | build.moxie | 10 | ||||
-rw-r--r-- | releases.moxie | 51 | ||||
-rw-r--r-- | src/main/distrib/linux/authority.sh | 2 | ||||
-rwxr-xr-x | src/main/distrib/linux/install-service-fedora.sh | 10 | ||||
-rw-r--r-- | src/main/distrib/linux/migrate-tickets.sh | 4 | ||||
-rw-r--r-- | src/main/distrib/linux/reindex-tickets.sh | 4 | ||||
-rw-r--r-- | src/main/distrib/linux/service-centos.sh | 6 | ||||
-rw-r--r-- | src/main/distrib/linux/service-ubuntu.sh | 2 | ||||
-rw-r--r-- | src/main/java/com/gitblit/manager/AuthenticationManager.java | 85 | ||||
-rw-r--r-- | src/main/java/com/gitblit/utils/StringUtils.java | 15 | ||||
-rw-r--r-- | src/site/federation.mkd | 2 | ||||
-rw-r--r-- | src/site/rpc.mkd | 2 | ||||
-rw-r--r-- | src/site/setup_go.mkd | 2 | ||||
-rw-r--r-- | src/site/upgrade_go.mkd | 22 | ||||
-rw-r--r-- | src/test/java/com/gitblit/tests/AuthenticationManagerTest.java | 100 | ||||
-rw-r--r-- | src/test/java/com/gitblit/tests/StringUtilsTest.java | 15 |
17 files changed, 254 insertions, 80 deletions
diff --git a/README.markdown b/README.markdown index a40ccdf6..af76c2df 100644 --- a/README.markdown +++ b/README.markdown @@ -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
-------
diff --git a/build.moxie b/build.moxie index d95db89a..fd7b1309 100644 --- a/build.moxie +++ b/build.moxie @@ -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 diff --git a/releases.moxie b/releases.moxie index 9776f0a9..b73038de 100644 --- a/releases.moxie +++ b/releases.moxie @@ -1,11 +1,51 @@ # # ${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. With the update to Lucene 5.5.2 reindexing of the tickets is necessary. This is done automatically during the first server start after an upgrade. Depending on the amount of tickets you have, this could take a little while. The old index is kept, so that a downgrade is still possible without losing information. The old index can be deleted, when a downgrade is no longer required. @@ -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] diff --git a/src/main/distrib/linux/authority.sh b/src/main/distrib/linux/authority.sh index 740f51a8..c5c6c687 100644 --- a/src/main/distrib/linux/authority.sh +++ b/src/main/distrib/linux/authority.sh @@ -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 diff --git a/src/main/distrib/linux/install-service-fedora.sh b/src/main/distrib/linux/install-service-fedora.sh index 4fb43c61..df17590f 100755 --- a/src/main/distrib/linux/install-service-fedora.sh +++ b/src/main/distrib/linux/install-service-fedora.sh @@ -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" diff --git a/src/main/distrib/linux/migrate-tickets.sh b/src/main/distrib/linux/migrate-tickets.sh index f521528e..4f360918 100644 --- a/src/main/distrib/linux/migrate-tickets.sh +++ b/src/main/distrib/linux/migrate-tickets.sh @@ -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 diff --git a/src/main/distrib/linux/reindex-tickets.sh b/src/main/distrib/linux/reindex-tickets.sh index 8261b819..42239ea1 100644 --- a/src/main/distrib/linux/reindex-tickets.sh +++ b/src/main/distrib/linux/reindex-tickets.sh @@ -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 diff --git a/src/main/distrib/linux/service-centos.sh b/src/main/distrib/linux/service-centos.sh index 843f015a..a2645e7e 100644 --- a/src/main/distrib/linux/service-centos.sh +++ b/src/main/distrib/linux/service-centos.sh @@ -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 diff --git a/src/main/distrib/linux/service-ubuntu.sh b/src/main/distrib/linux/service-ubuntu.sh index 769e3072..461a678c 100644 --- a/src/main/distrib/linux/service-ubuntu.sh +++ b/src/main/distrib/linux/service-ubuntu.sh @@ -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 diff --git a/src/main/java/com/gitblit/manager/AuthenticationManager.java b/src/main/java/com/gitblit/manager/AuthenticationManager.java index 83ca4b70..68c83dae 100644 --- a/src/main/java/com/gitblit/manager/AuthenticationManager.java +++ b/src/main/java/com/gitblit/manager/AuthenticationManager.java @@ -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; } diff --git a/src/main/java/com/gitblit/utils/StringUtils.java b/src/main/java/com/gitblit/utils/StringUtils.java index b192c80b..442acbbf 100644 --- a/src/main/java/com/gitblit/utils/StringUtils.java +++ b/src/main/java/com/gitblit/utils/StringUtils.java @@ -57,6 +57,21 @@ public class StringUtils { }
/**
+ * 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.
*
* @param string
diff --git a/src/site/federation.mkd b/src/site/federation.mkd index 231a9f35..b802a087 100644 --- a/src/site/federation.mkd +++ b/src/site/federation.mkd @@ -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"
diff --git a/src/site/rpc.mkd b/src/site/rpc.mkd index e51fbaae..ac963a87 100644 --- a/src/site/rpc.mkd +++ b/src/site/rpc.mkd @@ -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.
diff --git a/src/site/setup_go.mkd b/src/site/setup_go.mkd index 20b4ba48..e0470f31 100644 --- a/src/site/setup_go.mkd +++ b/src/site/setup_go.mkd @@ -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!!
diff --git a/src/site/upgrade_go.mkd b/src/site/upgrade_go.mkd index a0092588..4bc2272f 100644 --- a/src/site/upgrade_go.mkd +++ b/src/site/upgrade_go.mkd @@ -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.
diff --git a/src/test/java/com/gitblit/tests/AuthenticationManagerTest.java b/src/test/java/com/gitblit/tests/AuthenticationManagerTest.java index 45009856..81d68895 100644 --- a/src/test/java/com/gitblit/tests/AuthenticationManagerTest.java +++ b/src/test/java/com/gitblit/tests/AuthenticationManagerTest.java @@ -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)); } diff --git a/src/test/java/com/gitblit/tests/StringUtilsTest.java b/src/test/java/com/gitblit/tests/StringUtilsTest.java index 7176b88c..3dae66f4 100644 --- a/src/test/java/com/gitblit/tests/StringUtilsTest.java +++ b/src/test/java/com/gitblit/tests/StringUtilsTest.java @@ -26,13 +26,26 @@ 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";
String output = "this<br/>is<br/>a<br/>test<br/><br/>of<br/><br/>line<br/><br/>breaking";
|