1 package ch
.cyberduck
.core
.s3
;
3 import ch
.cyberduck
.core
.*;
4 import ch
.cyberduck
.core
.analytics
.AnalyticsProvider
;
5 import ch
.cyberduck
.core
.cdn
.DistributionConfiguration
;
6 import ch
.cyberduck
.core
.exception
.AccessDeniedException
;
7 import ch
.cyberduck
.core
.exception
.BackgroundException
;
8 import ch
.cyberduck
.core
.exception
.ConnectionCanceledException
;
9 import ch
.cyberduck
.core
.exception
.ConnectionTimeoutException
;
10 import ch
.cyberduck
.core
.exception
.LoginCanceledException
;
11 import ch
.cyberduck
.core
.exception
.LoginFailureException
;
12 import ch
.cyberduck
.core
.features
.AclPermission
;
13 import ch
.cyberduck
.core
.features
.Copy
;
14 import ch
.cyberduck
.core
.features
.Delete
;
15 import ch
.cyberduck
.core
.features
.Encryption
;
16 import ch
.cyberduck
.core
.features
.Lifecycle
;
17 import ch
.cyberduck
.core
.features
.Location
;
18 import ch
.cyberduck
.core
.features
.Logging
;
19 import ch
.cyberduck
.core
.features
.Redundancy
;
20 import ch
.cyberduck
.core
.features
.Versioning
;
21 import ch
.cyberduck
.core
.identity
.IdentityConfiguration
;
22 import ch
.cyberduck
.core
.ssl
.DefaultX509KeyManager
;
23 import ch
.cyberduck
.core
.ssl
.DefaultX509TrustManager
;
24 import ch
.cyberduck
.core
.ssl
.KeychainX509KeyManager
;
25 import ch
.cyberduck
.core
.ssl
.X509TrustManager
;
27 import org
.junit
.Ignore
;
28 import org
.junit
.Test
;
30 import java
.net
.UnknownHostException
;
31 import java
.security
.PublicKey
;
32 import java
.security
.cert
.CertificateException
;
33 import java
.security
.cert
.X509Certificate
;
34 import java
.util
.EnumSet
;
35 import java
.util
.concurrent
.atomic
.AtomicBoolean
;
37 import static org
.junit
.Assert
.*;
42 public class S3SessionTest
extends AbstractTestCase
{
45 public void testHttpProfile() throws Exception
{
46 final Profile profile
= ProfileReaderFactory
.get().read(
47 new Local("profiles/S3 (HTTP).cyberduckprofile"));
48 final Host host
= new Host(profile
, profile
.getDefaultHostname(), new Credentials(
49 properties
.getProperty("s3.key"), properties
.getProperty("s3.secret")
51 assertFalse(host
.getProtocol().isSecure());
52 final S3Session session
= new S3Session(host
, new X509TrustManager() {
54 public X509TrustManager
init() {
59 public void verify(final String hostname
, final X509Certificate
[] certs
, final String cipher
) throws CertificateException
{
60 throw new CertificateException();
64 public void checkClientTrusted(X509Certificate
[] x509Certificates
, final String cipher
) throws CertificateException
{
69 public void checkServerTrusted(X509Certificate
[] x509Certificates
, final String cipher
) throws CertificateException
{
74 public X509Certificate
[] getAcceptedIssuers() {
78 }, new DefaultX509KeyManager());
79 assertNotNull(session
.open(new DisabledHostKeyCallback(), new DisabledTranscriptListener()));
80 assertTrue(session
.isConnected());
82 assertFalse(session
.isConnected());
86 public void testConnectUnsecured() throws Exception
{
87 final Host host
= new Host(new S3Protocol(), new S3Protocol().getDefaultHostname(), new Credentials(
88 properties
.getProperty("s3.key"), properties
.getProperty("s3.secret")
90 final S3Session session
= new S3Session(host
);
91 assertNotNull(session
.open(new DisabledHostKeyCallback(), new DisabledTranscriptListener()));
92 assertTrue(session
.isConnected());
93 assertNotNull(session
.getClient());
94 final PathCache cache
= new PathCache(1);
95 session
.login(new DisabledPasswordStore(), new DisabledLoginCallback(), new DisabledCancelCallback(), cache
);
96 assertNotNull(session
.workdir());
97 assertTrue(cache
.containsKey(new Path("/", EnumSet
.of(Path
.Type
.directory
, Path
.Type
.volume
))));
98 assertTrue(cache
.get(new Path("/", EnumSet
.of(Path
.Type
.directory
, Path
.Type
.volume
))).contains(new Path("/test.cyberduck.ch", EnumSet
.of(Path
.Type
.directory
, Path
.Type
.volume
))));
99 assertTrue(session
.isConnected());
101 assertFalse(session
.isConnected());
102 assertEquals(Session
.State
.closed
, session
.getState());
103 session
.open(new DisabledHostKeyCallback(), new DisabledTranscriptListener());
104 assertTrue(session
.isConnected());
105 assertNotNull(session
.workdir());
107 assertFalse(session
.isConnected());
111 public void testConnectDefaultPath() throws Exception
{
112 final Host host
= new Host(new S3Protocol(), new S3Protocol().getDefaultHostname(), new Credentials(
113 properties
.getProperty("s3.key"), properties
.getProperty("s3.secret")
115 host
.setDefaultPath("/test.cyberduck.ch");
116 final S3Session session
= new S3Session(host
);
117 session
.open(new DisabledHostKeyCallback(), new DisabledTranscriptListener());
118 final PathCache cache
= new PathCache(1);
119 session
.login(new DisabledPasswordStore(), new DisabledLoginCallback(), new DisabledCancelCallback(), cache
);
120 assertFalse(cache
.containsKey(new Path("/", EnumSet
.of(Path
.Type
.directory
, Path
.Type
.volume
))));
121 assertTrue(cache
.containsKey(new Path("/test.cyberduck.ch", EnumSet
.of(Path
.Type
.directory
, Path
.Type
.volume
))));
125 @Test(expected
= LoginFailureException
.class)
126 public void testLoginFailure() throws Exception
{
127 final Host host
= new Host(new S3Protocol(), new S3Protocol().getDefaultHostname(), new Credentials(
128 properties
.getProperty("s3.key"), "s"
130 final S3Session session
= new S3Session(host
);
131 session
.open(new DisabledHostKeyCallback(), new DisabledTranscriptListener());
132 session
.login(new DisabledPasswordStore(), new DisabledLoginCallback(), new DisabledCancelCallback());
136 public void testLoginFailureFix() throws Exception
{
137 final Host host
= new Host(new S3Protocol(), new S3Protocol().getDefaultHostname(), new Credentials(
138 properties
.getProperty("s3.key"), "s"
140 final AtomicBoolean p
= new AtomicBoolean();
141 final S3Session session
= new S3Session(host
);
142 new LoginConnectionService(new DisabledLoginCallback() {
144 public void prompt(final Host bookmark
, final Credentials credentials
, final String title
, final String reason
, final LoginOptions options
) throws LoginCanceledException
{
146 throw new LoginCanceledException();
149 credentials
.setPassword(properties
.getProperty("s3.secret"));
151 }, new DisabledHostKeyCallback(), new DisabledPasswordStore(), new DisabledProgressListener(), new DisabledTranscriptListener()).connect(session
, PathCache
.empty());
156 @Test(expected
= BackgroundException
.class)
157 public void testCustomHostnameUnknown() throws Exception
{
158 final Host host
= new Host(new S3Protocol(), "testu.cyberduck.ch", new Credentials(
159 properties
.getProperty("s3.key"), "s"
161 final S3Session session
= new S3Session(host
);
163 session
.open(new DisabledHostKeyCallback(), new DisabledTranscriptListener());
164 session
.login(new DisabledPasswordStore(), new DisabledLoginCallback(), new DisabledCancelCallback());
166 catch(BackgroundException e
) {
167 assertTrue(e
.getCause() instanceof UnknownHostException
);
172 @Test(expected
= AccessDeniedException
.class)
173 public void testCustomHostname() throws Exception
{
174 final Host host
= new Host(new S3Protocol(), "test.cyberduck.ch", new Credentials(
175 properties
.getProperty("s3.key"), "s"
177 final AtomicBoolean set
= new AtomicBoolean();
178 final S3Session session
= new S3Session(host
);
179 session
.open(new HostKeyCallback() {
181 public boolean verify(final String hostname
, final int port
, final PublicKey key
)
182 throws ConnectionCanceledException
{
183 assertEquals("test.cyberduck.ch", hostname
);
186 }, new TranscriptListener() {
188 public void log(final boolean request
, final String message
) {
190 if(message
.contains("Host:")) {
191 assertEquals("Host: test.cyberduck.ch:443", message
);
198 session
.login(new DisabledPasswordStore(), new DisabledLoginCallback(), new DisabledCancelCallback());
200 catch(BackgroundException e
) {
201 assertTrue(set
.get());
208 public void testConnectInteroperabilityEvault() throws Exception
{
209 final Host host
= new Host(new S3Protocol(), "s3.lts2.evault.com", new Credentials(
210 properties
.getProperty("evault.s3.key"), properties
.getProperty("evault.s3.secret")
212 final S3Session session
= new S3Session(host
);
213 session
.open(new DisabledHostKeyCallback(), new DisabledTranscriptListener());
214 assertTrue(session
.isConnected());
215 final PathCache cache
= new PathCache(1);
216 session
.login(new DisabledPasswordStore(), new DisabledLoginCallback(), new DisabledCancelCallback(), cache
);
217 assertTrue(cache
.containsKey(new Path("/", EnumSet
.of(Path
.Type
.directory
, Path
.Type
.volume
))));
222 public void testFeatures() throws Exception
{
223 final S3Session aws
= new S3Session(new Host(new S3Protocol(), new S3Protocol().getDefaultHostname()));
224 assertNotNull(aws
.getFeature(Copy
.class));
225 assertNotNull(aws
.getFeature(AclPermission
.class));
226 assertNotNull(aws
.getFeature(Versioning
.class));
227 assertNotNull(aws
.getFeature(AnalyticsProvider
.class));
228 assertNotNull(aws
.getFeature(Lifecycle
.class));
229 assertNotNull(aws
.getFeature(Location
.class));
230 assertNotNull(aws
.getFeature(Encryption
.class));
231 assertNotNull(aws
.getFeature(Redundancy
.class));
232 assertNotNull(aws
.getFeature(Logging
.class));
233 assertNotNull(aws
.getFeature(DistributionConfiguration
.class));
234 assertNotNull(aws
.getFeature(IdentityConfiguration
.class));
235 assertNotNull(aws
.getFeature(IdentityConfiguration
.class));
236 assertEquals(S3MultipleDeleteFeature
.class, aws
.getFeature(Delete
.class).getClass());
237 final S3Session o
= new S3Session(new Host(new S3Protocol(), "o"));
238 assertNotNull(o
.getFeature(Copy
.class));
239 assertNotNull(o
.getFeature(AclPermission
.class));
240 assertNull(o
.getFeature(Versioning
.class));
241 assertNull(o
.getFeature(AnalyticsProvider
.class));
242 assertNull(o
.getFeature(Lifecycle
.class));
243 assertNotNull(o
.getFeature(Location
.class));
244 assertNull(o
.getFeature(Encryption
.class));
245 assertNull(o
.getFeature(Redundancy
.class));
246 assertNull(o
.getFeature(Logging
.class));
247 assertNotNull(o
.getFeature(DistributionConfiguration
.class));
248 assertNull(o
.getFeature(IdentityConfiguration
.class));
249 assertEquals(S3DefaultDeleteFeature
.class, o
.getFeature(Delete
.class).getClass());
253 public void testBucketVirtualHostStyleCustomHost() throws Exception
{
254 final Host host
= new Host(new S3Protocol(), "test.cyberduck.ch");
255 assertTrue(new S3Session(host
).configure().getBoolProperty("s3service.disable-dns-buckets", true));
259 public void testBucketVirtualHostStyleAmazon() throws Exception
{
260 final Host host
= new Host(new S3Protocol(), new S3Protocol().getDefaultHostname());
261 assertFalse(new S3Session(host
).configure().getBoolProperty("s3service.disable-dns-buckets", true));
265 public void testBucketVirtualHostStyleEucalyptusDefaultHost() throws Exception
{
266 final Profile profile
= ProfileReaderFactory
.get().read(
267 new Local("profiles/Eucalyptus Walrus S3.cyberduckprofile"));
268 final Host host
= new Host(profile
, profile
.getDefaultHostname());
269 assertTrue(new S3Session(host
).configure().getBoolProperty("s3service.disable-dns-buckets", false));
273 public void testBucketVirtualHostStyleEucalyptusCustomDeployment() throws Exception
{
274 final Profile profile
= ProfileReaderFactory
.get().read(
275 new Local("profiles/Eucalyptus Walrus S3.cyberduckprofile"));
276 final Host host
= new Host(profile
, "ec.cyberduck.io");
277 assertTrue(new S3Session(host
).configure().getBoolProperty("s3service.disable-dns-buckets", false));
280 @Test(expected
= LoginFailureException
.class)
282 public void testTemporaryAccessToken() throws Exception
{
283 final Profile profile
= ProfileReaderFactory
.get().read(
284 new Local("profiles/S3 (Temporary Credentials).cyberduckprofile"));
285 assertTrue(profile
.validate(new Credentials(), new LoginOptions(profile
)));
286 final Host host
= new Host(profile
);
287 final S3Session s
= new S3Session(host
);
288 s
.open(new DisabledHostKeyCallback(), new DisabledTranscriptListener());
290 s
.login(new DisabledPasswordStore(), new DisabledLoginCallback(), new DisabledCancelCallback());
292 catch(LoginFailureException e
) {
293 assertEquals(ConnectionTimeoutException
.class, e
.getCause().getClass());
299 public void testTrustChain() throws Exception
{
300 final Host host
= new Host(new S3Protocol(), new S3Protocol().getDefaultHostname(), new Credentials(
301 properties
.getProperty("s3.key"), properties
.getProperty("s3.secret")
303 final AtomicBoolean verified
= new AtomicBoolean();
304 final S3Session session
= new S3Session(host
, new DefaultX509TrustManager() {
306 public void verify(final String hostname
, final X509Certificate
[] certs
, final String cipher
) throws CertificateException
{
307 assertEquals(3, certs
.length
);
308 assertEquals("CN=VeriSign Class 3 Public Primary Certification Authority - G5,OU=(c) 2006 VeriSign\\, Inc. - For authorized use only,OU=VeriSign Trust Network,O=VeriSign\\, Inc.,C=US",
309 certs
[certs
.length
- 1].getSubjectX500Principal().getName());
310 assertEquals("C=US,ST=Washington,L=Seattle,O=Amazon.com\\, Inc.,CN=s3.amazonaws.com",
311 certs
[0].getSubjectDN().getName());
313 super.verify(hostname
, certs
, cipher
);
316 new KeychainX509KeyManager(new DisabledCertificateStore()));
317 final LoginConnectionService c
= new LoginConnectionService(
318 new DisabledLoginCallback(),
319 new DisabledHostKeyCallback(),
320 new DisabledPasswordStore(),
321 new DisabledProgressListener(),
322 new DisabledTranscriptListener());
323 c
.connect(session
, PathCache
.empty());
324 assertTrue(verified
.get());