質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
FTP

FTP(File Transfer Protocol)は、ネットワークでのファイル転送を行うための通信プロトコルの1つである。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Socket.IO

Socket.IOはNode.js上で動くライブラリであり、すべてのブラウザとモバイルデバイスでリアルタイムのアプリを作動させる事を目的としています。

SSL

SSL(Secure Sockets Layer)とは、暗号化されたプロトコルで、インターネット上での通信セキュリティを提供しています。

Q&A

2回答

15345閲覧

JavaでSSLSocketを使いFTPS(explicit)でファイルをSTORしたい

teratail_user

総合スコア14

FTP

FTP(File Transfer Protocol)は、ネットワークでのファイル転送を行うための通信プロトコルの1つである。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Socket.IO

Socket.IOはNode.js上で動くライブラリであり、すべてのブラウザとモバイルデバイスでリアルタイムのアプリを作動させる事を目的としています。

SSL

SSL(Secure Sockets Layer)とは、暗号化されたプロトコルで、インターネット上での通信セキュリティを提供しています。

1グッド

1クリップ

投稿2015/11/01 23:57

javaの業務で、ファイルを他サーバーに転送しなくちゃなのですが、できなくて困っています。
転送先のサーバがFTPはFTPSのみ受け付けている、という状態です。
大変困っています。ご回答お待ちしています。よろしくお願い致します。

以下のようなコードを書きましたが、
ハンドシェイクに失敗します。

code

1 Socket ctrlSocket; 2 PrintWriter ctrlOutput; 3 BufferedReader ctrlInput; 4 byte[] localHostAddress; 5 char[] inbuffer; 6 int i; 7 String sendCommand; 8 try { 9 // FTPサーバーへ接続します 10 ctrlSocket = new Socket(host, port); 11 localHostAddress = ctrlSocket.getLocalAddress().getAddress(); 12 ctrlOutput = new PrintWriter(ctrlSocket.getOutputStream()); 13 ctrlInput = new BufferedReader(new InputStreamReader(ctrlSocket.getInputStream())); 14 inbuffer = new char[1000]; 15 i = ctrlInput.read(inbuffer); 16 17 // 暗号化する場合(FTPS) 18 if (isEncrypt) { 19 sendCommand = "AUTH TLS"; 20 ctrlOutput.println(sendCommand); 21 ctrlOutput.flush(); 22 inbuffer = new char[1000]; 23 i = ctrlInput.read(inbuffer); 24 25★ SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault(); 26 ctrlSocket = (SSLSocket) factory.createSocket(ctrlSocket, host, port, true); 27 28☆ ((SSLSocket)ctrlSocket).startHandshake(); 29 30 sendCommand = "PBSZ 0"; 31 ctrlOutput.println(sendCommand); 32 ctrlOutput.flush(); 33 inbuffer = new char[1000]; 34 i = ctrlInput.read(inbuffer); 35 36 sendCommand = "PROT P"; 37 ctrlOutput.println(sendCommand); 38 ctrlOutput.flush(); 39 inbuffer = new char[1000]; 40 i = ctrlInput.read(inbuffer); 41 } 42 43 if (isPasv) { 44 sendCommand = "PASV"; 45 ctrlOutput.println(sendCommand); 46 ctrlOutput.flush(); 47 } 48 49 // ユーザー認証します 50 sendCommand = "USER " + userName; 51 ctrlOutput.println(sendCommand); 52 ctrlOutput.flush(); 53 inbuffer = new char[1000]; 54 i = ctrlInput.read(inbuffer); 55 sendCommand = "PASS " + password; 56 ctrlOutput.println(sendCommand); 57 ctrlOutput.flush(); 58 inbuffer = new char[1000]; 59 i = ctrlInput.read(inbuffer); 60 61 // 指定したディレクトリに移動します 62 sendCommand = "CWD /"; 63 ctrlOutput.println(sendCommand); 64 ctrlOutput.flush(); 65 inbuffer = new char[1000]; 66 i = ctrlInput.read(inbuffer); 67 68 // バイナリモードに変更します 69 sendCommand = "TYPE I"; 70 ctrlOutput.println(sendCommand); 71 ctrlOutput.flush(); 72 inbuffer = new char[1000]; 73 i = ctrlInput.read(inbuffer); 74 75 // アップロードします 76 Socket dataSocket = dataConnection("STOR " + uploadPath); 77 OutputStream outstr = dataSocket.getOutputStream(); 78 79 byte[] buf = readFileToByte(inputPath); 80 outstr.write(buf); 81 outstr.flush(); 82 dataSocket.close(); 83 inbuffer = new char[1000]; 84 i = ctrlInput.read(inbuffer); 85 86 // 終了 87 sendCommand = "QUIT"; 88 ctrlOutput.println(sendCommand); 89 ctrlOutput.flush(); 90 inbuffer = new char[1000]; 91 i = ctrlInput.read(inbuffer); 92 93 以下略

【状況】
★factoryの中身
c53d99[SSL_NULL_WITH_NULL_NULL: Socket[addr=ホスト/IPアドレス,port=21,localport=58782]]

☆を実行したあとExceptionが発生します
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

※FTPSではない、暗号化してないFTP通信ではファイル転送に成功しています。

通信相手はショッピングモールの「ポンパレモール」の店舗向けFTPサーバになります。
また、FTPソフトの「winSCP」や「FFFTP」で接続したところ問題なくファイル転送ができました。

WireSharkで上記プログラム実行中FTPのパケットモニタリングしてみたところ、
RES 220 FTP
REQ AUTH TLS
RES 234 AUTH TLS successful
REQ \200e\001\003 …
RES \026\003\001 …
RES \275\036C\207K …
REQ \025\003\001 …
RES 550 TLS handshake failed

という結果になりました。

【質問】
☆の位置でハンドシェイクに失敗していまいます。
FTPSでファイル転送をする場合
・コマンド送信の順番
・SSLSocketの作成手順
に間違いがあるのかもしれませんが、わからなくて困っています。

また、ハンドシェイクに成功したあとは「PBSZ 0」「PROT P」というコマンドを送信し、
FTPSではない、FTPでのファイル転送と同じ手順で、ファイル転送ができるのでしょうか?

具体的なコードを交えて教えていただけると大変助かります。
よろしくお願い致します。m(_ _)m

A-pZ👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

SSLSocketの使用を諦め、org.apache.commons.net.ftp.FTPSClient を使用することにしました。

また、ログインやPASVモードの指定、ハンドシェイクのコマンドを送信する順番があって、順番を守らないと正しく通信できないことがわかりました。

下記にコメントやログ出力部分などを除外したソースコードを記述します。
(順番を参考に・・・)
また、サーバ証明書を無視するコードにしていますのでこの方法はよくないとは思いますが通信する相手が決まっているので今回は採用しました。

JAVA

1 public boolean upload(int flg, String inputPath, 2 String uploadPath) throws Exception { 3 4 boolean isEncrypt = false; // 非暗号化 (true=暗号化) 5 boolean isPasv = true; // パッシブモード (false=アクティブモード) 6 boolean isOverWrite = false; // 既にファイルがある場合は上書き(false=しない,true=する) 7 if ((flg & FLG_ACTIVE_MODE) != 0) 8 isPasv = false; 9 if ((flg & FLG_ENCRYPT) != 0) 10 isEncrypt = true; 11 if ((flg & FLG_OVERWRITE) != 0) 12 isOverWrite = true; 13 14 // アクティブモードは別処理 15 // アクティブモードはSocketを使う。FTPClientではPOSTコマンドでIPを指定 16 // できないので 17 if (isPasv == false) { 18 return uploadForActiveModeServer(isOverWrite, inputPath, uploadPath); 19 } 20 21 boolean res = true; // アップロード成功可否 22 boolean st = false; // コマンド実行成功可否 23 FTPClient client = null; 24 if (isEncrypt) { 25 client = new FTPSClient(false); 26 27 } else { 28 client = new FTPClient(); 29 } 30 FileInputStream fis = null; 31 try { 32 // サーバ接続 33 client.setDefaultTimeout(TIMEOUT_SEC); 34 client.connect(host, port); 35 client.setBufferSize(4000); 36 37 // タイムアウト時間設定 38 client.setSoTimeout(SET_SO_TIMEOUT); 39 40 // TLSハンドシェイク 41 if (isEncrypt) { 42 ((FTPSClient) client).setTrustManager(IGNORE_ALL); 43 ((FTPSClient) client).execAUTH("TLS"); 44 ((FTPSClient) client).execPBSZ(0); 45 ((FTPSClient) client).execPROT("P"); 46 } 47 48 // ログイン 49 client.login(userName, password); 50 51 if (isPasv) { 52 // パッシブモード 53 client.enterLocalPassiveMode(); 54 st = client.doCommand("PASV", ""); 55 } 56 57 // フォルダ移動 58 st = client.doCommand("CWD", "/"); 59 60 // バイナリ転送モード 61 st = client.doCommand("TYPE", "I"); 62 63 // アップロード先のファイルがすでにあるかチェック 64 if (isOverWrite == false) { // 上書きしない場合 65 if (checkFileExists(client, uploadPath)) { // ファイルチェックメソッド 66 return false; 67 } 68 } 69 70 // アップロードするファイルのStream取得 71 fis = new FileInputStream(inputPath); 72 73 // ファイルアップロード 74 res = client.storeFile(uploadPath, fis); 75 fis.close(); 76 } catch (Exception e) { 77 res = false; 78 } finally { 79 try { 80 // ログアウト・切断 81 if (client.isConnected()) { 82 client.logout(); 83 client.disconnect(); 84 } 85 if (fis != null) { 86 fis.close(); 87 fis = null; 88 } 89 } catch (Exception e) { 90 } 91 } 92 return res; 93 }
/** * サーバー証明書を無視する */ static final TrustManager IGNORE_ALL = new X509TrustManager() { @Override public X509Certificate[] getAcceptedIssuers() { return null; } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } };

投稿2015/12/10 04:18

teratail_user

総合スコア14

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

teratail_user

2015/12/10 04:26

↑FTPClientではアクティブモードのサーバにPORTコマンドをなげてもデータコネクション時にPASV用のコマンドを勝手になげちゃうので、自分でひとつひとつコマンドを送信するSocketを使う。なんのコマンドをなげていたのかパケット監視していたけど、ちょっと前のことなので失念・・・
guest

0

投稿2015/11/02 05:03

trick

総合スコア366

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

teratail_user

2015/11/03 23:45

ありがとうございます。 サイトを見てソースをほぼコピってみましたが factory = SSLSocketFactory.getDefault() sock = factory.createSocket(host, port) sock.startHandshake() のハンドシェイクのところでやはり同様exceptionが発生します。
trick

2015/11/04 00:04

ちなみに port は何番ですか?
teratail_user

2015/12/10 04:19

>trick 遅くなりました。ポートは21です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問