メインコンテンツ

TLS/SSL 接続メソッドが設定されていません

プログラムで、クライアントとサーバーのどちらのルーチンを呼び出すかが判断できない

説明

この欠陥は、TLS/SSL コンテキストの接続メソッドを明示的に設定せずに、以下のいずれかの関数を呼び出した場合に発生します。

  • SSL_read

  • SSL_write

  • SSL_do_handshake

TLS/SSL 接続を使用するサーバー エンティティとクライアント エンティティ間の通信がハンドシェイクを開始します。ハンドシェイク中に、エンティティ同士が情報を交換し、セッション中に使用する暗号化アルゴリズムとセッション キーを設定します。サーバーとクライアントの接続メソッドは、ハンドシェイクに別々のルーチンを使用します。

チェッカーは以下の場合に欠陥を報告しません。

  • 関数の SSL_connect (クライアント) と SSL_accept (サーバー) を使用する。これらの関数は、正しいハンドシェイク ルーチンを自動的に設定します。

  • SSL_new を呼び出す関数に引数として SSL コンテキストを渡す。

  • 接続を処理する関数のスコープの外部で SSL コンテキストを宣言する。

リスク

SSL エンジンがどの接続メソッド ルーチンを呼び出すかを認識していなければ、ハンドシェイクを開始できません。

修正方法

  • クライアント ハンドシェイク ルーチンでは、ハンドシェイクを始める前に SSL_set_connect_state を呼び出します。

  • サーバー ハンドシェイク ルーチンでは、ハンドシェイクを始める前に SSL_set_accept_state を呼び出します。

すべて展開する

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <openssl/ssl.h>

#define fatal_error() exit(-1)

int len;
unsigned char buf;
volatile int rd;

const SSL_METHOD*  set_method()
{
    return SSLv23_server_method();
}

void func()
{
    int ret;
    SSL_CTX* ctx;
    SSL* ssl;
    const SSL_METHOD* method =  set_method();
    ctx = SSL_CTX_new(method);
    ssl = SSL_new(ctx);

    switch (rd) {
    case 1:
        ret = SSL_read(ssl, (void*)buf, len);
        if (ret <= 0) fatal_error();
        break;
    case 2:
        ret = SSL_do_handshake(ssl);
        if (ret <= 0) fatal_error();
        break;
    default:
        ret = SSL_write(ssl, (void*)buf, len);
        if (ret <= 0) fatal_error();
        break;
    }
}

この例では、SSL コンテキスト ctx がサーバー接続メソッド SSLv23_server_method を使用して生成されます。ただし、接続からの読み取り、ハンドシェイクの開始、または接続への書き込みを行う前に、SSL 構造体 ssl 用の接続メソッドが明示的に設定されていません。

修正 — サーバー接続メソッドを明示的に設定する

1 つの修正方法として、ハンドシェイクを開始する前に、SSL_set_accept_state を呼び出して SSL 構造体 ssl 用のサーバー役割を設定します。

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <openssl/ssl.h>

#define fatal_error() exit(-1)

int len;
unsigned char buf;
volatile int rd;

const SSL_METHOD*  set_method()
{
    return SSLv23_server_method();
}

void func()
{
    int ret;
    SSL_CTX* ctx;
    SSL* ssl;
    const SSL_METHOD* method =  set_method();
    ctx = SSL_CTX_new(method);
    ssl = SSL_new(ctx);
	SSL_set_accept_state(ssl);
	

    switch (rd) {
    case 1:
        ret = SSL_read(ssl, (void*)buf, len);
        if (ret <= 0) fatal_error();
        break;
    case 2:
        ret = SSL_do_handshake(ssl);
        if (ret <= 0) fatal_error();
        break;
    default:
        ret = SSL_write(ssl, (void*)buf, len);
        if (ret <= 0) fatal_error();
        break;
    }
} 

結果情報

グループ: 暗号化
言語: C | C++
既定値: オフ
コマンド ライン構文: CRYPTO_SSL_NO_ROLE
影響度: Medium

バージョン履歴

R2020a で導入