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