package com.gitblit.tests; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.util.Date; import java.util.concurrent.atomic.AtomicBoolean; import org.apache.commons.codec.digest.DigestUtils; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import com.gitblit.Constants.AccessPermission; import com.gitblit.Constants.AccessRestrictionType; import com.gitblit.Constants.AuthorizationControl; import com.gitblit.Keys; import com.gitblit.models.FilestoreModel.Status; import com.gitblit.models.RepositoryModel; import com.gitblit.models.UserModel; import com.gitblit.utils.FileUtils; /** * Test of the filestore manager and confirming filesystem updated * * @author Paul Martin * */ public class FilestoreManagerTest extends GitblitUnitTest { private static final AtomicBoolean started = new AtomicBoolean(false); private static final BlobInfo blob_zero = new BlobInfo(0); private static final BlobInfo blob_512KB = new BlobInfo(512*FileUtils.KB); private static final BlobInfo blob_6MB = new BlobInfo(6*FileUtils.MB); private static int download_limit_default = -1; private static int download_limit_test = 5*FileUtils.MB; private static final String invalid_hash_empty = ""; private static final String invalid_hash_major = "INVALID_HASH"; private static final String invalid_hash_regex_attack = blob_512KB.hash.replace('a', '*'); private static final String invalid_hash_one_long = blob_512KB.hash.concat("a"); private static final String invalid_hash_one_short = blob_512KB.hash.substring(1); @BeforeClass public static void startGitblit() throws Exception { started.set(GitBlitSuite.startGitblit()); } @AfterClass public static void stopGitblit() throws Exception { if (started.get()) { GitBlitSuite.stopGitblit(); } } @Test public void testAdminAccess() throws Exception { FileUtils.delete(filestore().getStorageFolder()); filestore().clearFilestoreCache(); RepositoryModel r = new RepositoryModel("myrepo.git", null, null, new Date()); ByteArrayOutputStream streamOut = new ByteArrayOutputStream(); UserModel u = new UserModel("admin"); u.canAdmin = true; //No upload limit settings().overrideSetting(Keys.filestore.maxUploadSize, download_limit_default); //Invalid hash tests assertEquals(Status.Error_Invalid_Oid, filestore().downloadBlob(invalid_hash_major, u, r, streamOut)); assertEquals(Status.Error_Invalid_Oid, filestore().downloadBlob(invalid_hash_regex_attack, u, r, streamOut)); assertEquals(Status.Error_Invalid_Oid, filestore().downloadBlob(invalid_hash_one_long, u, r, streamOut)); assertEquals(Status.Error_Invalid_Oid, filestore().downloadBlob(invalid_hash_one_short, u, r, streamOut)); // Download prior to upload streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_512KB.hash, u, r, streamOut)); streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_512KB.hash, u, r, streamOut)); //Bad input is rejected with no upload taking place assertEquals(Status.Error_Invalid_Oid, filestore().uploadBlob(invalid_hash_empty, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.Error_Invalid_Oid, filestore().uploadBlob(invalid_hash_major, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.Error_Invalid_Oid, filestore().uploadBlob(invalid_hash_regex_attack, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.Error_Invalid_Oid, filestore().uploadBlob(invalid_hash_one_long, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.Error_Invalid_Oid, filestore().uploadBlob(invalid_hash_one_short, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.Error_Invalid_Size, filestore().uploadBlob(blob_512KB.hash, -1, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.Error_Size_Mismatch, filestore().uploadBlob(blob_512KB.hash, 0, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.Error_Size_Mismatch, filestore().uploadBlob(blob_512KB.hash, blob_512KB.length-1, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.Error_Size_Mismatch, filestore().uploadBlob(blob_512KB.hash, blob_512KB.length+1, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.Error_Hash_Mismatch, filestore().uploadBlob(blob_zero.hash, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); //Confirm no upload with bad input streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_512KB.hash, u, r, streamOut)); //Good input will accept the upload assertEquals(Status.Available, filestore().uploadBlob(blob_512KB.hash, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); streamOut.reset(); assertEquals(Status.Available, filestore().downloadBlob(blob_512KB.hash, u, r, streamOut)); assertArrayEquals(blob_512KB.blob, streamOut.toByteArray()); //Subsequent failed uploads do not affect file assertEquals(Status.Error_Size_Mismatch, filestore().uploadBlob(blob_512KB.hash, blob_512KB.length-1, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.Error_Size_Mismatch, filestore().uploadBlob(blob_512KB.hash, blob_512KB.length+1, u, r, new ByteArrayInputStream(blob_512KB.blob))); streamOut.reset(); assertEquals(Status.Available, filestore().downloadBlob(blob_512KB.hash, u, r, streamOut)); assertArrayEquals(blob_512KB.blob, streamOut.toByteArray()); //Zero length upload is valid assertEquals(Status.Available, filestore().uploadBlob(blob_zero.hash, blob_zero.length, u, r, new ByteArrayInputStream(blob_zero.blob))); streamOut.reset(); assertEquals(Status.Available, filestore().downloadBlob(blob_zero.hash, u, r, streamOut)); assertArrayEquals(blob_zero.blob, streamOut.toByteArray()); //Pre-informed upload identifies identical errors as immediate upload assertEquals(Status.Upload_Pending, filestore().addObject(blob_6MB.hash, blob_6MB.length, u, r)); streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_6MB.hash, u, r, streamOut)); assertEquals(Status.Error_Invalid_Oid, filestore().uploadBlob(invalid_hash_empty, blob_6MB.length, u, r, new ByteArrayInputStream(blob_6MB.blob))); assertEquals(Status.Error_Invalid_Oid, filestore().uploadBlob(invalid_hash_major, blob_6MB.length, u, r, new ByteArrayInputStream(blob_6MB.blob))); assertEquals(Status.Error_Invalid_Oid, filestore().uploadBlob(invalid_hash_regex_attack, blob_6MB.length, u, r, new ByteArrayInputStream(blob_6MB.blob))); assertEquals(Status.Error_Invalid_Oid, filestore().uploadBlob(invalid_hash_one_long, blob_6MB.length, u, r, new ByteArrayInputStream(blob_6MB.blob))); assertEquals(Status.Error_Invalid_Oid, filestore().uploadBlob(invalid_hash_one_short, blob_6MB.length, u, r, new ByteArrayInputStream(blob_6MB.blob))); assertEquals(Status.Error_Size_Mismatch, filestore().uploadBlob(blob_6MB.hash, 0, u, r, new ByteArrayInputStream(blob_6MB.blob))); assertEquals(Status.Error_Size_Mismatch, filestore().uploadBlob(blob_6MB.hash, blob_6MB.length-1, u, r, new ByteArrayInputStream(blob_6MB.blob))); assertEquals(Status.Error_Size_Mismatch, filestore().uploadBlob(blob_6MB.hash, blob_6MB.length+1, u, r, new ByteArrayInputStream(blob_6MB.blob))); streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_6MB.hash, u, r, streamOut)); //Good input will accept the upload assertEquals(Status.Available, filestore().uploadBlob(blob_6MB.hash, blob_6MB.length, u, r, new ByteArrayInputStream(blob_6MB.blob))); streamOut.reset(); assertEquals(Status.Available, filestore().downloadBlob(blob_6MB.hash, u, r, streamOut)); assertArrayEquals(blob_6MB.blob, streamOut.toByteArray()); //Confirm the relevant files exist assertTrue("Admin did not save zero length file!", filestore().getStoragePath(blob_zero.hash).exists()); assertTrue("Admin did not save 512KB file!", filestore().getStoragePath(blob_512KB.hash).exists()); assertTrue("Admin did not save 6MB file!", filestore().getStoragePath(blob_6MB.hash).exists()); //Clear the files and cache to test upload limit property FileUtils.delete(filestore().getStorageFolder()); filestore().clearFilestoreCache(); settings().overrideSetting(Keys.filestore.maxUploadSize, download_limit_test); assertEquals(Status.Available, filestore().uploadBlob(blob_512KB.hash, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); streamOut.reset(); assertEquals(Status.Available, filestore().downloadBlob(blob_512KB.hash, u, r, streamOut)); assertArrayEquals(blob_512KB.blob, streamOut.toByteArray()); assertEquals(Status.Error_Exceeds_Size_Limit, filestore().uploadBlob(blob_6MB.hash, blob_6MB.length, u, r, new ByteArrayInputStream(blob_6MB.blob))); streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_6MB.hash, u, r, streamOut)); assertTrue("Admin did not save 512KB file!", filestore().getStoragePath(blob_512KB.hash).exists()); assertFalse("Admin saved 6MB file despite (over filesize limit)!", filestore().getStoragePath(blob_6MB.hash).exists()); } @Test public void testAuthenticatedAccess() throws Exception { FileUtils.delete(filestore().getStorageFolder()); filestore().clearFilestoreCache(); RepositoryModel r = new RepositoryModel("myrepo.git", null, null, new Date()); r.authorizationControl = AuthorizationControl.AUTHENTICATED; r.accessRestriction = AccessRestrictionType.VIEW; ByteArrayOutputStream streamOut = new ByteArrayOutputStream(); UserModel u = new UserModel("test"); //No upload limit settings().overrideSetting(Keys.filestore.maxUploadSize, download_limit_default); //Invalid hash tests assertEquals(Status.Error_Invalid_Oid, filestore().downloadBlob(invalid_hash_major, u, r, streamOut)); assertEquals(Status.Error_Invalid_Oid, filestore().downloadBlob(invalid_hash_regex_attack, u, r, streamOut)); assertEquals(Status.Error_Invalid_Oid, filestore().downloadBlob(invalid_hash_one_long, u, r, streamOut)); assertEquals(Status.Error_Invalid_Oid, filestore().downloadBlob(invalid_hash_one_short, u, r, streamOut)); // Download prior to upload streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_512KB.hash, u, r, streamOut)); streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_512KB.hash, u, r, streamOut)); //Bad input is rejected with no upload taking place assertEquals(Status.Error_Invalid_Oid, filestore().uploadBlob(invalid_hash_empty, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.Error_Invalid_Oid, filestore().uploadBlob(invalid_hash_major, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.Error_Invalid_Oid, filestore().uploadBlob(invalid_hash_regex_attack, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.Error_Invalid_Oid, filestore().uploadBlob(invalid_hash_one_long, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.Error_Invalid_Oid, filestore().uploadBlob(invalid_hash_one_short, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.Error_Invalid_Size, filestore().uploadBlob(blob_512KB.hash, -1, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.Error_Size_Mismatch, filestore().uploadBlob(blob_512KB.hash, 0, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.Error_Size_Mismatch, filestore().uploadBlob(blob_512KB.hash, blob_512KB.length-1, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.Error_Size_Mismatch, filestore().uploadBlob(blob_512KB.hash, blob_512KB.length+1, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.Error_Hash_Mismatch, filestore().uploadBlob(blob_zero.hash, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); //Confirm no upload with bad input streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_512KB.hash, u, r, streamOut)); //Good input will accept the upload assertEquals(Status.Available, filestore().uploadBlob(blob_512KB.hash, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); streamOut.reset(); assertEquals(Status.Available, filestore().downloadBlob(blob_512KB.hash, u, r, streamOut)); assertArrayEquals(blob_512KB.blob, streamOut.toByteArray()); //Subsequent failed uploads do not affect file assertEquals(Status.Error_Size_Mismatch, filestore().uploadBlob(blob_512KB.hash, blob_512KB.length-1, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.Error_Size_Mismatch, filestore().uploadBlob(blob_512KB.hash, blob_512KB.length+1, u, r, new ByteArrayInputStream(blob_512KB.blob))); streamOut.reset(); assertEquals(Status.Available, filestore().downloadBlob(blob_512KB.hash, u, r, streamOut)); assertArrayEquals(blob_512KB.blob, streamOut.toByteArray()); //Zero length upload is valid assertEquals(Status.Available, filestore().uploadBlob(blob_zero.hash, blob_zero.length, u, r, new ByteArrayInputStream(blob_zero.blob))); streamOut.reset(); assertEquals(Status.Available, filestore().downloadBlob(blob_zero.hash, u, r, streamOut)); assertArrayEquals(blob_zero.blob, streamOut.toByteArray()); //Pre-informed upload identifies identical errors as immediate upload assertEquals(Status.Upload_Pending, filestore().addObject(blob_6MB.hash, blob_6MB.length, u, r)); streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_6MB.hash, u, r, streamOut)); assertEquals(Status.Error_Invalid_Oid, filestore().uploadBlob(invalid_hash_empty, blob_6MB.length, u, r, new ByteArrayInputStream(blob_6MB.blob))); assertEquals(Status.Error_Invalid_Oid, filestore().uploadBlob(invalid_hash_major, blob_6MB.length, u, r, new ByteArrayInputStream(blob_6MB.blob))); assertEquals(Status.Error_Invalid_Oid, filestore().uploadBlob(invalid_hash_regex_attack, blob_6MB.length, u, r, new ByteArrayInputStream(blob_6MB.blob))); assertEquals(Status.Error_Invalid_Oid, filestore().uploadBlob(invalid_hash_one_long, blob_6MB.length, u, r, new ByteArrayInputStream(blob_6MB.blob))); assertEquals(Status.Error_Invalid_Oid, filestore().uploadBlob(invalid_hash_one_short, blob_6MB.length, u, r, new ByteArrayInputStream(blob_6MB.blob))); assertEquals(Status.Error_Size_Mismatch, filestore().uploadBlob(blob_6MB.hash, 0, u, r, new ByteArrayInputStream(blob_6MB.blob))); assertEquals(Status.Error_Size_Mismatch, filestore().uploadBlob(blob_6MB.hash, blob_6MB.length-1, u, r, new ByteArrayInputStream(blob_6MB.blob))); assertEquals(Status.Error_Size_Mismatch, filestore().uploadBlob(blob_6MB.hash, blob_6MB.length+1, u, r, new ByteArrayInputStream(blob_6MB.blob))); streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_6MB.hash, u, r, streamOut)); //Good input will accept the upload assertEquals(Status.Available, filestore().uploadBlob(blob_6MB.hash, blob_6MB.length, u, r, new ByteArrayInputStream(blob_6MB.blob))); streamOut.reset(); assertEquals(Status.Available, filestore().downloadBlob(blob_6MB.hash, u, r, streamOut)); assertArrayEquals(blob_6MB.blob, streamOut.toByteArray()); //Confirm the relevant files exist assertTrue("Authenticated user did not save zero length file!", filestore().getStoragePath(blob_zero.hash).exists()); assertTrue("Authenticated user did not save 512KB file!", filestore().getStoragePath(blob_512KB.hash).exists()); assertTrue("Authenticated user did not save 6MB file!", filestore().getStoragePath(blob_6MB.hash).exists()); //Clear the files and cache to test upload limit property FileUtils.delete(filestore().getStorageFolder()); filestore().clearFilestoreCache(); settings().overrideSetting(Keys.filestore.maxUploadSize, download_limit_test); assertEquals(Status.Available, filestore().uploadBlob(blob_512KB.hash, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); streamOut.reset(); assertEquals(Status.Available, filestore().downloadBlob(blob_512KB.hash, u, r, streamOut)); assertArrayEquals(blob_512KB.blob, streamOut.toByteArray()); assertEquals(Status.Error_Exceeds_Size_Limit, filestore().uploadBlob(blob_6MB.hash, blob_6MB.length, u, r, new ByteArrayInputStream(blob_6MB.blob))); streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_6MB.hash, u, r, streamOut)); assertTrue("Authenticated user did not save 512KB file!", filestore().getStoragePath(blob_512KB.hash).exists()); assertFalse("Authenticated user saved 6MB file (over filesize limit)!", filestore().getStoragePath(blob_6MB.hash).exists()); } @Test public void testAnonymousAccess() throws Exception { FileUtils.delete(filestore().getStorageFolder()); filestore().clearFilestoreCache(); RepositoryModel r = new RepositoryModel("myrepo.git", null, null, new Date()); r.authorizationControl = AuthorizationControl.NAMED; r.accessRestriction = AccessRestrictionType.CLONE; ByteArrayOutputStream streamOut = new ByteArrayOutputStream(); UserModel u = UserModel.ANONYMOUS; //No upload limit settings().overrideSetting(Keys.filestore.maxUploadSize, download_limit_default); //Invalid hash tests assertEquals(Status.Error_Invalid_Oid, filestore().downloadBlob(invalid_hash_major, u, r, streamOut)); assertEquals(Status.Error_Invalid_Oid, filestore().downloadBlob(invalid_hash_regex_attack, u, r, streamOut)); assertEquals(Status.Error_Invalid_Oid, filestore().downloadBlob(invalid_hash_one_long, u, r, streamOut)); assertEquals(Status.Error_Invalid_Oid, filestore().downloadBlob(invalid_hash_one_short, u, r, streamOut)); // Download prior to upload streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_512KB.hash, u, r, streamOut)); streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_512KB.hash, u, r, streamOut)); //Bad input is rejected with no upload taking place assertEquals(Status.AuthenticationRequired, filestore().uploadBlob(invalid_hash_empty, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.AuthenticationRequired, filestore().uploadBlob(invalid_hash_major, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.AuthenticationRequired, filestore().uploadBlob(invalid_hash_regex_attack, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.AuthenticationRequired, filestore().uploadBlob(invalid_hash_one_long, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.AuthenticationRequired, filestore().uploadBlob(invalid_hash_one_short, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.AuthenticationRequired, filestore().uploadBlob(blob_512KB.hash, -1, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.AuthenticationRequired, filestore().uploadBlob(blob_512KB.hash, 0, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.AuthenticationRequired, filestore().uploadBlob(blob_512KB.hash, blob_512KB.length-1, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.AuthenticationRequired, filestore().uploadBlob(blob_512KB.hash, blob_512KB.length+1, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.AuthenticationRequired, filestore().uploadBlob(blob_zero.hash, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); //Confirm no upload with bad input streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_512KB.hash, u, r, streamOut)); //Good input will accept the upload assertEquals(Status.AuthenticationRequired, filestore().uploadBlob(blob_512KB.hash, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_512KB.hash, u, r, streamOut)); //Subsequent failed uploads do not affect file assertEquals(Status.AuthenticationRequired, filestore().uploadBlob(blob_512KB.hash, blob_512KB.length-1, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.AuthenticationRequired, filestore().uploadBlob(blob_512KB.hash, blob_512KB.length+1, u, r, new ByteArrayInputStream(blob_512KB.blob))); streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_512KB.hash, u, r, streamOut)); //Zero length upload is valid assertEquals(Status.AuthenticationRequired, filestore().uploadBlob(blob_zero.hash, blob_zero.length, u, r, new ByteArrayInputStream(blob_zero.blob))); streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_zero.hash, u, r, streamOut)); //Pre-informed upload identifies identical errors as immediate upload assertEquals(Status.AuthenticationRequired, filestore().addObject(blob_6MB.hash, blob_6MB.length, u, r)); streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_6MB.hash, u, r, streamOut)); assertEquals(Status.AuthenticationRequired, filestore().uploadBlob(invalid_hash_empty, blob_6MB.length, u, r, new ByteArrayInputStream(blob_6MB.blob))); assertEquals(Status.AuthenticationRequired, filestore().uploadBlob(invalid_hash_major, blob_6MB.length, u, r, new ByteArrayInputStream(blob_6MB.blob))); assertEquals(Status.AuthenticationRequired, filestore().uploadBlob(invalid_hash_regex_attack, blob_6MB.length, u, r, new ByteArrayInputStream(blob_6MB.blob))); assertEquals(Status.AuthenticationRequired, filestore().uploadBlob(invalid_hash_one_long, blob_6MB.length, u, r, new ByteArrayInputStream(blob_6MB.blob))); assertEquals(Status.AuthenticationRequired, filestore().uploadBlob(invalid_hash_one_short, blob_6MB.length, u, r, new ByteArrayInputStream(blob_6MB.blob))); assertEquals(Status.AuthenticationRequired, filestore().uploadBlob(blob_6MB.hash, -1, u, r, new ByteArrayInputStream(blob_6MB.blob))); assertEquals(Status.AuthenticationRequired, filestore().uploadBlob(blob_6MB.hash, 0, u, r, new ByteArrayInputStream(blob_6MB.blob))); assertEquals(Status.AuthenticationRequired, filestore().uploadBlob(blob_6MB.hash, blob_6MB.length-1, u, r, new ByteArrayInputStream(blob_6MB.blob))); assertEquals(Status.AuthenticationRequired, filestore().uploadBlob(blob_6MB.hash, blob_6MB.length+1, u, r, new ByteArrayInputStream(blob_6MB.blob))); streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_6MB.hash, u, r, streamOut)); //Good input will accept the upload assertEquals(Status.AuthenticationRequired, filestore().uploadBlob(blob_6MB.hash, blob_6MB.length, u, r, new ByteArrayInputStream(blob_6MB.blob))); streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_6MB.hash, u, r, streamOut)); //Confirm the relevant files do not exist assertFalse("Anonymous user saved zero length file!", filestore().getStoragePath(blob_zero.hash).exists()); assertFalse("Anonymous user 512KB file!", filestore().getStoragePath(blob_512KB.hash).exists()); assertFalse("Anonymous user 6MB file!", filestore().getStoragePath(blob_6MB.hash).exists()); //Clear the files and cache to test upload limit property FileUtils.delete(filestore().getStorageFolder()); filestore().clearFilestoreCache(); settings().overrideSetting(Keys.filestore.maxUploadSize, download_limit_test); assertEquals(Status.AuthenticationRequired, filestore().uploadBlob(blob_512KB.hash, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_512KB.hash, u, r, streamOut)); assertEquals(Status.AuthenticationRequired, filestore().uploadBlob(blob_6MB.hash, blob_6MB.length, u, r, new ByteArrayInputStream(blob_6MB.blob))); streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_6MB.hash, u, r, streamOut)); assertFalse("Anonymous user saved 512KB file!", filestore().getStoragePath(blob_512KB.hash).exists()); assertFalse("Anonymous user saved 6MB file (over filesize limit)!", filestore().getStoragePath(blob_6MB.hash).exists()); } @Test public void testUnauthorizedAccess() throws Exception { FileUtils.delete(filestore().getStorageFolder()); filestore().clearFilestoreCache(); RepositoryModel r = new RepositoryModel("myrepo.git", null, null, new Date()); r.authorizationControl = AuthorizationControl.NAMED; r.accessRestriction = AccessRestrictionType.VIEW; ByteArrayOutputStream streamOut = new ByteArrayOutputStream(); UserModel u = new UserModel("test"); u.setRepositoryPermission(r.name, AccessPermission.CLONE); //No upload limit settings().overrideSetting(Keys.filestore.maxUploadSize, download_limit_default); //Invalid hash tests assertEquals(Status.Error_Invalid_Oid, filestore().downloadBlob(invalid_hash_major, u, r, streamOut)); assertEquals(Status.Error_Invalid_Oid, filestore().downloadBlob(invalid_hash_regex_attack, u, r, streamOut)); assertEquals(Status.Error_Invalid_Oid, filestore().downloadBlob(invalid_hash_one_long, u, r, streamOut)); assertEquals(Status.Error_Invalid_Oid, filestore().downloadBlob(invalid_hash_one_short, u, r, streamOut)); // Download prior to upload streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_512KB.hash, u, r, streamOut)); streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_512KB.hash, u, r, streamOut)); //Bad input is rejected with no upload taking place assertEquals(Status.Error_Unauthorized, filestore().uploadBlob(invalid_hash_major, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.Error_Unauthorized, filestore().uploadBlob(invalid_hash_regex_attack, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.Error_Unauthorized, filestore().uploadBlob(invalid_hash_one_long, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.Error_Unauthorized, filestore().uploadBlob(invalid_hash_empty, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.Error_Unauthorized, filestore().uploadBlob(invalid_hash_one_short, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.Error_Unauthorized, filestore().uploadBlob(blob_512KB.hash, -1, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.Error_Unauthorized, filestore().uploadBlob(blob_512KB.hash, 0, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.Error_Unauthorized, filestore().uploadBlob(blob_512KB.hash, blob_512KB.length-1, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.Error_Unauthorized, filestore().uploadBlob(blob_512KB.hash, blob_512KB.length+1, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.Error_Unauthorized, filestore().uploadBlob(blob_zero.hash, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); //Confirm no upload with bad input streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_512KB.hash, u, r, streamOut)); //Good input will accept the upload assertEquals(Status.Error_Unauthorized, filestore().uploadBlob(blob_512KB.hash, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_512KB.hash, u, r, streamOut)); //Subsequent failed uploads do not affect file assertEquals(Status.Error_Unauthorized, filestore().uploadBlob(blob_512KB.hash, blob_512KB.length-1, u, r, new ByteArrayInputStream(blob_512KB.blob))); assertEquals(Status.Error_Unauthorized, filestore().uploadBlob(blob_512KB.hash, blob_512KB.length+1, u, r, new ByteArrayInputStream(blob_512KB.blob))); streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_512KB.hash, u, r, streamOut)); //Zero length upload is valid assertEquals(Status.Error_Unauthorized, filestore().uploadBlob(blob_zero.hash, blob_zero.length, u, r, new ByteArrayInputStream(blob_zero.blob))); streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_zero.hash, u, r, streamOut)); //Pre-informed upload identifies identical errors as immediate upload assertEquals(Status.Error_Unauthorized, filestore().addObject(blob_6MB.hash, blob_6MB.length, u, r)); streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_6MB.hash, u, r, streamOut)); assertEquals(Status.Error_Unauthorized, filestore().uploadBlob(invalid_hash_empty, blob_6MB.length, u, r, new ByteArrayInputStream(blob_6MB.blob))); assertEquals(Status.Error_Unauthorized, filestore().uploadBlob(invalid_hash_major, blob_6MB.length, u, r, new ByteArrayInputStream(blob_6MB.blob))); assertEquals(Status.Error_Unauthorized, filestore().uploadBlob(invalid_hash_regex_attack, blob_6MB.length, u, r, new ByteArrayInputStream(blob_6MB.blob))); assertEquals(Status.Error_Unauthorized, filestore().uploadBlob(invalid_hash_one_long, blob_6MB.length, u, r, new ByteArrayInputStream(blob_6MB.blob))); assertEquals(Status.Error_Unauthorized, filestore().uploadBlob(invalid_hash_one_short, blob_6MB.length, u, r, new ByteArrayInputStream(blob_6MB.blob))); assertEquals(Status.Error_Unauthorized, filestore().uploadBlob(blob_6MB.hash, -1, u, r, new ByteArrayInputStream(blob_6MB.blob))); assertEquals(Status.Error_Unauthorized, filestore().uploadBlob(blob_6MB.hash, 0, u, r, new ByteArrayInputStream(blob_6MB.blob))); assertEquals(Status.Error_Unauthorized, filestore().uploadBlob(blob_6MB.hash, blob_6MB.length-1, u, r, new ByteArrayInputStream(blob_6MB.blob))); assertEquals(Status.Error_Unauthorized, filestore().uploadBlob(blob_6MB.hash, blob_6MB.length+1, u, r, new ByteArrayInputStream(blob_6MB.blob))); streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_6MB.hash, u, r, streamOut)); //Good input will accept the upload assertEquals(Status.Error_Unauthorized, filestore().uploadBlob(blob_6MB.hash, blob_6MB.length, u, r, new ByteArrayInputStream(blob_6MB.blob))); streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_6MB.hash, u, r, streamOut)); //Confirm the relevant files exist assertFalse("Unauthorized user saved zero length file!", filestore().getStoragePath(blob_zero.hash).exists()); assertFalse("Unauthorized user saved 512KB file!", filestore().getStoragePath(blob_512KB.hash).exists()); assertFalse("Unauthorized user saved 6MB file!", filestore().getStoragePath(blob_6MB.hash).exists()); //Clear the files and cache to test upload limit property FileUtils.delete(filestore().getStorageFolder()); filestore().clearFilestoreCache(); settings().overrideSetting(Keys.filestore.maxUploadSize, download_limit_test); assertEquals(Status.Error_Unauthorized, filestore().uploadBlob(blob_512KB.hash, blob_512KB.length, u, r, new ByteArrayInputStream(blob_512KB.blob))); streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_512KB.hash, u, r, streamOut)); assertEquals(Status.Error_Unauthorized, filestore().uploadBlob(blob_6MB.hash, blob_6MB.length, u, r, new ByteArrayInputStream(blob_6MB.blob))); streamOut.reset(); assertEquals(Status.Unavailable, filestore().downloadBlob(blob_6MB.hash, u, r, streamOut)); assertFalse("Unauthorized user saved 512KB file!", filestore().getStoragePath(blob_512KB.hash).exists()); assertFalse("Unauthorized user saved 6MB file (over filesize limit)!", filestore().getStoragePath(blob_6MB.hash).exists()); } } /* * Test helper structure to create blobs of a given size */ final class BlobInfo { public byte[] blob; public String hash; public int length; public BlobInfo(int nBytes) { blob = new byte[nBytes]; new java.util.Random().nextBytes(blob); hash = DigestUtils.sha256Hex(blob); length = nBytes; } }