3

Windows でリモート サーバーの SSL 証明書を取得しようとしています。私が見つけた 1 つのオプションは、openssl を使用することです。インターネット上のいくつかの投稿で示されているように、それを行うコマンドは次のとおりです。

openssl.exe s_client -showcerts -connect {REMOTE_SERVER_IP}:{REMOTE_SERVER_PORT}

これは完全に機能しますが、私の問題は、上記のコマンドのタイムアウトが 300 秒であることです。証明書自体は非常に高速に印刷され、最初の数秒で必要な情報がすべて得られるのに 300 秒も待つ必要はありません。それでも、s_client のタイムアウト パラメータを変更する方法はないと思います。そこで、一定期間後に Windows でプロセスを強制終了する方法を見つけようとしましたが、やはりうまくいきませんでした。これをどのように行うことができるかについてのアイデアはありますか? リモートサーバーのSSL証明書を取得してファイルに保存する他のWindows方法がある場合、これも機能します。

編集: ブルーノの要求に従って、さらに情報を追加します。リモート サーバーの SSL 証明書を取得し、さらに処理するためにファイルに保存する C++ アプリケーションを作成しようとしています。私のアプリケーションはすでに openssl.exe を使用しているため、openssl.exe または標準の Windows コマンドを使用するソリューションが必要です (つまり、追加のライブラリは必要ありません)。

EDIT2:Linuxでの待機を回避する方法を見つけました-空のファイルを作成し、openssl s_clientの入力をそれにリダイレクトします(またはパイプを使用して空の入力を渡します)。これは Windows でも機能しますが、古いバージョンの openssl(0.9.8l) で機能します。0.9.8r と 1.0.1b で試してみましたが、入力を空のファイルにリダイレクトしても解決しません。

4

1 に答える 1

8

これは、サーバーに接続してそのssl証明書を標準出力に出力する、私が作成した最小限のプログラムです。他の誰かが同様の問題を解決するのに役立つことを願っています:

#ifdef WIN32
#include <windows.h>
#include <winsock2.h>
#else
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#endif

#include <openssl/ssl.h>    
#include <cstdlib>
#include <iostream>

static const char *host= "10.23.10.12";
static int port=443;

int tcp_connect(const char *host,int port)
{
#ifdef WIN32
   WSADATA wsaData;
   WORD version;
   int error;

   version = MAKEWORD( 2, 0 );

   error = WSAStartup( version, &wsaData );

   /* check for error */
   if ( error != 0 )
   {
       /* error occured */
       return -1;
   }

   /* check for correct version */
   if ( LOBYTE( wsaData.wVersion ) != 2 ||
        HIBYTE( wsaData.wVersion ) != 0 )
   {
       /* incorrect WinSock version */
       WSACleanup();
       return -1;
   }

   /* WinSock has been initialized */
#endif

   struct hostent *hp;
   struct sockaddr_in addr;
   int sock;

   if(!(hp=gethostbyname(host)))
      printf("Couldn't resolve host");
   memset(&addr,0,sizeof(addr));
   addr.sin_addr=*(struct in_addr*)
         hp->h_addr_list[0];
   addr.sin_family=AF_INET;
   addr.sin_port=htons(port);

   if((sock=(int)socket(AF_INET,SOCK_STREAM,
                   IPPROTO_TCP))<0)
      printf("Couldn't create socket");
   if(connect(sock,(struct sockaddr *)&addr,
              sizeof(addr))<0)
      printf("Couldn't connect socket");

   return sock;
}

int main(int argc,char **argv)
{
   SSL_CTX *ctx;
   SSL *ssl;
   BIO *sbio;
   int sock;

   SSL_METHOD *meth=NULL;
   meth=SSLv23_client_method();
   OpenSSL_add_ssl_algorithms();
   SSL_load_error_strings();
   ctx=SSL_CTX_new(meth);

   /* Connect the TCP socket*/
   sock=tcp_connect(host,port);

   /* Connect the SSL socket */
   ssl=SSL_new(ctx);
   sbio=BIO_new_socket(sock,BIO_NOCLOSE);
   SSL_set_bio(ssl,sbio,sbio);

   if(SSL_connect(ssl)<=0)
     printf("SSL connect error");

   X509 *peer;
   peer=SSL_get_peer_certificate(ssl);
   PEM_write_X509(stdout, peer);

   SSL_CTX_free(ctx);

   close(sock);
#ifdef WIN32
   closesocket(sock);
   WSACleanup();
#else
   close(sock);
#endif
   exit(0);
}

コードは、この投稿で提案されているように、ここにある例の修正版です。

編集: Windows で OPENSSL_UPLINK: no OPENSSL_APPLINK というエラーが発生し続けました。インターネットで多くの検索を行った後、この投稿を見つけて、これをコードに追加しました。

extern "C" {
   #include <openssl/applink.c>
}

これは、コンパイラと実行時オプションの互換性の要件を回避するための回避策のようです。

于 2012-05-16T08:30:51.643 に答える