parent
1ca3ff900d
commit
d1e591b448
@ -0,0 +1,39 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
package com.arialyy.aria.core.common; |
||||||
|
|
||||||
|
import android.support.annotation.StringDef; |
||||||
|
import java.lang.annotation.Retention; |
||||||
|
import java.lang.annotation.RetentionPolicy; |
||||||
|
|
||||||
|
@StringDef({ |
||||||
|
ProtocolType.Default, |
||||||
|
ProtocolType.SSL, |
||||||
|
ProtocolType.SSLv3, |
||||||
|
ProtocolType.TLS, |
||||||
|
ProtocolType.TLSv1, |
||||||
|
ProtocolType.TLSv1_1, |
||||||
|
ProtocolType.TLSv1_2 |
||||||
|
}) |
||||||
|
@Retention(RetentionPolicy.SOURCE) public @interface ProtocolType { |
||||||
|
String Default = "Default"; |
||||||
|
String SSL = "SSL"; |
||||||
|
String SSLv3 = "SSLv3"; |
||||||
|
String TLS = "TLS"; |
||||||
|
String TLSv1 = "TLSv1"; |
||||||
|
String TLSv1_1 = "TLSv1.1"; |
||||||
|
String TLSv1_2 = "TLSv1.2"; |
||||||
|
} |
@ -0,0 +1,104 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
package com.arialyy.aria.core.common.ftp; |
||||||
|
|
||||||
|
import android.text.TextUtils; |
||||||
|
import com.arialyy.aria.core.FtpUrlEntity; |
||||||
|
import com.arialyy.aria.core.common.ProtocolType; |
||||||
|
import com.arialyy.aria.core.inf.AbsTarget; |
||||||
|
import com.arialyy.aria.core.inf.ITarget; |
||||||
|
|
||||||
|
/** |
||||||
|
* FTP SSL/TSL配置 |
||||||
|
*/ |
||||||
|
public class FTPSSLConfig<TARGET extends AbsTarget> implements ITarget { |
||||||
|
private final String TAG = "FTPSSLConfig"; |
||||||
|
private TARGET mTarget; |
||||||
|
private FtpUrlEntity mUrlEntity; |
||||||
|
|
||||||
|
public FTPSSLConfig(TARGET target) { |
||||||
|
mTarget = target; |
||||||
|
mUrlEntity = mTarget.getTaskEntity().getUrlEntity(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 设置协议类型 |
||||||
|
* |
||||||
|
* @param protocol {@link ProtocolType} |
||||||
|
*/ |
||||||
|
public FTPSSLConfig setProtocol(@ProtocolType String protocol) { |
||||||
|
if (TextUtils.isEmpty(protocol)) { |
||||||
|
throw new NullPointerException("协议为空"); |
||||||
|
} |
||||||
|
mUrlEntity.SSLProtocol = protocol; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 设置证书别名 |
||||||
|
* |
||||||
|
* @param keyAlias 别名 |
||||||
|
*/ |
||||||
|
public FTPSSLConfig setAlias(String keyAlias) { |
||||||
|
if (TextUtils.isEmpty(keyAlias)) { |
||||||
|
throw new NullPointerException("别名为空"); |
||||||
|
} |
||||||
|
mUrlEntity.keyAlias = keyAlias; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 设置证书密码 |
||||||
|
* |
||||||
|
* @param storePass 私钥密码 |
||||||
|
*/ |
||||||
|
public FTPSSLConfig setStorePass(String storePass) { |
||||||
|
if (TextUtils.isEmpty(storePass)) { |
||||||
|
throw new NullPointerException("证书密码为空"); |
||||||
|
} |
||||||
|
mUrlEntity.storePass = storePass; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 设置证书路径 |
||||||
|
* |
||||||
|
* @param storePath 证书路径 |
||||||
|
*/ |
||||||
|
public FTPSSLConfig setStorePath(String storePath) { |
||||||
|
if (TextUtils.isEmpty(storePath)) { |
||||||
|
throw new NullPointerException("证书路径为空"); |
||||||
|
} |
||||||
|
mUrlEntity.storePath = storePath; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void start() { |
||||||
|
mTarget.start(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void stop() { |
||||||
|
mTarget.stop(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void resume() { |
||||||
|
mTarget.resume(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void cancel() { |
||||||
|
mTarget.cancel(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,54 @@ |
|||||||
|
package com.arialyy.aria.core.common.ftp; |
||||||
|
|
||||||
|
import com.arialyy.aria.util.ALog; |
||||||
|
import java.io.IOException; |
||||||
|
import java.lang.reflect.Field; |
||||||
|
import java.lang.reflect.Method; |
||||||
|
import java.net.Socket; |
||||||
|
import java.util.Locale; |
||||||
|
import javax.net.ssl.SSLContext; |
||||||
|
import javax.net.ssl.SSLSession; |
||||||
|
import javax.net.ssl.SSLSessionContext; |
||||||
|
import javax.net.ssl.SSLSocket; |
||||||
|
import org.apache.commons.net.ftp.FTPSClient; |
||||||
|
|
||||||
|
public class SSLSessionReuseFTPSClient extends FTPSClient { |
||||||
|
|
||||||
|
SSLSessionReuseFTPSClient(boolean b, SSLContext context) { |
||||||
|
super(b, context); |
||||||
|
} |
||||||
|
|
||||||
|
// adapted from:
|
||||||
|
// https://trac.cyberduck.io/browser/trunk/ftp/src/main/java/ch/cyberduck/core/ftp/FTPClient.java
|
||||||
|
@Override |
||||||
|
protected void _prepareDataSocket_(final Socket socket) throws IOException { |
||||||
|
if (socket instanceof SSLSocket) { |
||||||
|
// Control socket is SSL
|
||||||
|
final SSLSession session = ((SSLSocket) _socket_).getSession(); |
||||||
|
if (session.isValid()) { |
||||||
|
final SSLSessionContext context = session.getSessionContext(); |
||||||
|
try { |
||||||
|
//final Field sessionHostPortCache = context.getClass().getDeclaredField("sessionHostPortCache");
|
||||||
|
final Field sessionHostPortCache = |
||||||
|
context.getClass().getDeclaredField("sessionsByHostAndPort"); |
||||||
|
sessionHostPortCache.setAccessible(true); |
||||||
|
final Object cache = sessionHostPortCache.get(context); |
||||||
|
final Method method = |
||||||
|
cache.getClass().getDeclaredMethod("put", Object.class, Object.class); |
||||||
|
method.setAccessible(true); |
||||||
|
method.invoke(cache, String.format("%s:%s", socket.getInetAddress().getHostName(), |
||||||
|
String.valueOf(socket.getPort())).toLowerCase(Locale.ROOT), session); |
||||||
|
method.invoke(cache, String.format("%s:%s", socket.getInetAddress().getHostAddress(), |
||||||
|
String.valueOf(socket.getPort())).toLowerCase(Locale.ROOT), session); |
||||||
|
ALog.d("tag", "GGGG"); |
||||||
|
} catch (NoSuchFieldException e) { |
||||||
|
throw new IOException(e); |
||||||
|
} catch (Exception e) { |
||||||
|
throw new IOException(e); |
||||||
|
} |
||||||
|
} else { |
||||||
|
throw new IOException("Invalid SSL Session"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue