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

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

ただいまの
回答率

90.47%

  • C++

    4522questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

SSL_readが初回1バイトしか読み込まない

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 952

whirota

score 1

httpsサーバーを実装しています。
以下のコードをMacbook pro(OS:sierra)でコンパイル、動作させたところ、
googlechromeではSSL_readが1バイトだけしか読み込みません。
対策のご教授をお願いいたします。

///
cpp file
///

include <stdio.h>

include <stdlib.h>

include <string.h>

include <unistd.h>

include <sys/socket.h>

include <arpa/inet.h>

include <sys/ioctl.h>

include <netinet/in.h>

include <openssl/ssl.h>

include <openssl/err.h>

include <openssl/crypto.h>

int main(void)
{
SSL_CTX *ctx;
SSL *ssl;

int server, client, sd;
int port = 8778
;
char crt_file[] = "server.crt";
char key_file[] = "server.key";

struct sockaddr_in addr;
socklen_t size = sizeof(struct sockaddr_in);

char buf[1024]={0};

char body[] = "hello world";
char header[] = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: 11\r\nConnection: Close\r\n";
char msg[1024];

SSL_load_error_strings();
SSL_library_init();
OpenSSL_add_all_algorithms();

ctx = SSL_CTX_new(SSLv23_server_method());
SSL_CTX_use_certificate_file(ctx, crt_file, SSL_FILETYPE_PEM);
SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM);

server = socket(PF_INET, SOCK_STREAM, 0);
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(port);

bind(server, (struct sockaddr*)&addr, sizeof(addr));
listen(server, 1);

while(1) {
memset(buf, 0, sizeof(buf));

client = accept(server, (struct sockaddr*)&addr, &size);

printf(
"Connection: %s:%d\n",
inet_ntoa(addr.sin_addr),
ntohs(addr.sin_port)
);

ssl = SSL_new(ctx);
SSL_set_fd(ssl, client);

if (SSL_accept(ssl) > 0) {

SSL_read(ssl, buf, sizeof(buf));
printf("request:%s\r\n", buf);
snprintf(msg, sizeof(msg), "%s\r\n%s", header, body);
SSL_write(ssl, msg, strlen(msg));
}

sd = SSL_get_fd(ssl);
SSL_free(ssl);
close(sd);
}

close(server);
SSL_CTX_free(ctx);

return EXIT_SUCCESS;
}
/// makefile
CC=g++
OS=linux
CPPFLAGS=-Wall -O2 -fPIC -Wno-write-strings -std=c++0x -lpthread $(USR_FLG) -lcurl -lm /usr/lib/libssl.dylib -lm /usr/lib/libcrypto.dylib
PROGRAM=openssl.out
STRIP=strip
OBJS=openssl.o
INCPATH=-I/usr/local/opt/openssl/include

all:$(OBJS)
$(CC) $(OBJS) $(CPPFLAGS) -o $(PROGRAM)

.cpp.o:
$(CC) $(INCPATH) $(CPPFLAGS) -c $<

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

恐らく実験用に、 Chrome できちんと検証できないサーバ証明書 (所謂「オレオレ証明書」等) を使用しているのではないでしょうか? この場合 Chrome は、仮に例外として接続の続行を指示したとしても、最初のコネクションを証明書の検証直後に切断する実装になっているようです。
つまり、 Chrome 側の実装の問題で、ご呈示の HTTPS サーバの実装に問題があるわけでは無いと思います。対策としては、 Chrome を --ignore-certificate-errors コマンドラインオプション付きで起動するか、あるいは検証可能な正規のサーバ証明書を使用すると良いのではないでしょうか。

ちなみにこの動作については、 Chromium のソースコード中でも以下の通り、 HttpNetworkTransaction::OnCertificateError のコメントに言及されています。

HttpNetworkTransaction::OnCertificateError

// TODO(mbelshe):  For now, we're going to pass the error through, and that
// will close the stream_request in all cases.  This means that we're always
// going to restart an entire STATE_CREATE_STREAM, even if the connection is
// good and the user chooses to ignore the error.  This is not ideal, but not
// the end of the world either.

「理想的な動作ではないが、破滅的でもない」と仰ってますね。ここでそのまま、ユーザがそれを無視したいかに関わらず、受け取った SSL エラー値を HttpNetworkTransaction::OnIOComplete に渡してしまうため、最終的に HttpNetworkTransaction::ResetConnectionAndRequestForResend で一度コネクションが閉じてしまいます。

一度閉じてはしまいますが、検証に失敗した証明書は、初回のエラー処理時に以下の HttpStreamFactoryImpl::Job::HandleCertificateError の箇所で SSLConfig::allowed_bad_certs へと保存されています。そのため、ユーザの操作によって再度接続が続行された時には、エラーを無視して最後までリクエストが完了するようになっているようです。

HttpStreamFactoryImpl::Job::HandleCertificateError

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/05/08 11:28

    回答ありがとうございます。勉強になりました。

    キャンセル

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

  • ただいまの回答率 90.47%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • C++

    4522questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。