
// X509 証明書関係、HTTPSの接続テストコマンド

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<netdb.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in_systm.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include<arpa/inet.h>
#include<fcntl.h>

#include<sys/stat.h>
#include<errno.h>

/* SSL/TSL 関係のヘッダーファイル */
#include <openssl/crypto.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/rand.h>

#include"sitar_scan.h"
#include"sitar_com.h"
#include"sitar_ssl.h"
#include <almemsys/almemsys.h>
#include"jpreturn.h"
#include "version.h"


// 259200 = 3day 証明書の期限が切れる3日前の時間
#define AF_TIME 259200 

// char *  verify_ssl(char * data, SSL *ssl, int * err);

// DE BUG 用
// #define SSL_BUG

int main(int argc, char * argv[])
{
int sk, re, stat, ret, retval, dcount, arglen, sslerr, i;
unsigned long resoip;
char ipa[IP_LEN];
char dom[BUF_URL];
char pass[BUF_URL];
char rec[256];
char swa[2048];

char * ip_addr = ipa;
char * url_dom = dom;
char * url_pass = pass;
struct sockaddr_in my_addr;
fd_set rfds;
struct timeval tv;
char * senddata;
char * ssl_senddata;
char * backdata;
char * swapdata = swa;
char * recvdata = rec;
char bu[IP_LEN];
char * buff = bu;

extern char *optarg;

int port;
int timeout;
long int cert_lim;
char * url_data; 
char * dns_data; 
int resolv_ret;

time_t B_time, A_time, N_time, Na_time;
B_time =0; A_time =0; N_time =0;
ASN1_TIME * notBefore;
ASN1_TIME * notAfter;
SSL * ssl;
SSL_CTX * ctx;
#ifdef SSL_BUG
SSL_CIPHER * cipher;
#endif
X509 * cert;
int cert_length;
cert_length = 0;

dcount = 0;
arglen = sizeof(int);
ret = -1;
errno = 0;
sslerr = 0;
port = 0;
timeout = 0;
cert_lim = 0;
resolv_ret = 0;

if((senddata = (char *)calloc(BUF_LEN, sizeof(char)))==NULL){ exit(1);}
if((url_data = (char *)calloc(BUF_LEN, sizeof(char)))==NULL){ exit(1);}
if((dns_data = (char *)calloc(BUF_LEN, sizeof(char)))==NULL){ exit(1);}
if((backdata = (char *)calloc(BUF_LEN, sizeof(char)))==NULL){ exit(1);}

memset(recvdata, 0x00, 256);
memset(swapdata, 0x00, 2048);
memset(ip_addr, 0x00, IP_LEN);
memset(url_dom, 0x00, BUF_URL);
memset(url_pass, 0x00, BUF_URL);

// defaultのDNSを設定
dns_data = safe_memcpy(dns_data, "127.0.0.1", 1024);

// optionの処理
while((i=getopt(argc,argv,"a:p:t:c:u:v:d:z"))!= EOF){
   switch(i){
      case 'p': if(0 == ch_int2(optarg)){
                   port = strtol(optarg, (char **)NULL, 10);
                   }
              break;
      case 't': if(0 == ch_int2(optarg)){
                   timeout = strtol(optarg, (char **)NULL, 10);
                   }
              break;
      case 'c': if(0 == ch_int2(optarg)){
                   cert_lim = (long int)strtol(optarg, (char **)NULL, 10);
                   }
              break;
      case 'u': if(optarg != NULL){
                   url_data = safe_memcpy(url_data, optarg, 1024);
                   }
                else{
                   url_data = safe_memcpy(url_data, "http:///", 1024);
                   }
              break;
      case 'd': if(optarg != NULL){
                   dns_data = safe_memcpy(dns_data, optarg, 1024);
                   }
                else{
                   dns_data = safe_memcpy(dns_data, "127.0.0.1", 1024);
                   }
              break;

      default : printf("scanssl-%s $scanssl -d <DNS IP> -p <port> -t <timout> -c <cert time limmit> -u <https://URL>\n",VERSION);
              free(senddata);
              free(url_data);
              free(dns_data);
              free(backdata);
              exit(1);
              break;
      }
   }

stat = urldompass_port(url_data, url_dom, url_pass, strlen(url_data)); 
if(stat > 0){
   port = stat;
   }


#ifdef SSL_BUG
printf("SSL_BUG: scanssl():\n url_data=<%s>\n url_dom=<%s>\n url_pass=<%s>\n url_port=<%d>\n", url_data, url_dom, url_pass, port);
#endif

// ソケット生成
if((sk = socket(AF_INET, SOCK_STREAM, 0))==-1){
   // ソケットつくれないので離脱
   printf("URL %s: Port %d: %s\n", url_data, port, SOCK_1);
   #ifdef SSL_BUG
   printf("SSL_BUG: scanssl(1): NOT CLEATE SOCKETS %s\n", backdata);
   #endif
   free(senddata);
   free(url_data);
   free(dns_data);
   free(backdata);
   exit(1);
   }

my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(port);

// backdata = out_resolvename(backdata, url_dom, timeout, &resoip);
// my_addr.sin_addr.s_addr = resoip;

backdata = resolvename_sk(backdata, url_dom, timeout, &resoip, dns_data, &resolv_ret, '4');
if(resolv_ret < 0){
   // 名前解決出来ないので離脱
   printf("DNS %s: URL %s: %s\n", dns_data, url_dom, SOCK_2);
   #ifdef SSL_BUG
   fprintf(stderr,"RESOLV ERR: DNS name resolution failure <%s> <%s> <%s>\n", url_dom, backdata, dns_data);
   #endif
   free(senddata);
   free(url_data);
   free(dns_data);
   free(backdata);
   exit(1);
   }

my_addr.sin_addr.s_addr = resoip;


if(0 == (int)my_addr.sin_addr.s_addr || resoip == (int)NULL){
   // 名前解決したIPがNULLだから離脱
// printf("%s %s %d\n", SOCK_2, url_dom, (int)my_addr.sin_addr.s_addr);
   printf("URL %s: %s\n", url_dom, SOCK_2);
   #ifdef SSL_BUG
   printf("SSL_BUG: scanssl(2):  NOT RESOLV NAME %s\n", backdata);
   #endif
   close(sk);
   free(senddata);
   free(url_data);
   free(dns_data);
   free(backdata);
   // アドレスがへんだから離脱
   exit(1);
   }

// ip_addr = inet_ntoa(my_addr.sin_addr);
ip_addr = (char *)inet_ntop(AF_INET, &my_addr.sin_addr, buff, IP_LEN);

#ifdef SSL_BUG
printf("SSL_BUG: scanssl(3): %s\n", ip_addr);
#endif

// 非同期通信の開始 TCP ポートにコネ串ょん
fcntl(sk, F_SETFL, O_NONBLOCK);
re = connect(sk, (struct sockaddr *)(long)&my_addr, sizeof(my_addr));

// 速攻でつながった場合の処理
if(re >= 0){
   // 非同期通信から同期通信に
   fcntl(sk, F_SETFL, 0);
   #ifdef SSL_BUG
   printf("SSL_BUG: scan_url_connect(4): CONNECT SUCCESS %s\n", backdata);
   #endif
   goto notselect;
   }

// errno が EINPROGRESS なばやい
if(errno == EINPROGRESS){
   tv.tv_sec = timeout;
   tv.tv_usec = 0;
   while(1){
      FD_ZERO(&rfds);
      FD_SET(sk, &rfds);
      retval = select(sk + 1, NULL, &rfds, NULL, &tv);
      // select の異常終了
      if(retval < 0){
         printf("URL %s: Port %d: %s\n", url_data, port, SOCK_15);
         #ifdef SSL_BUG
         printf("SSL_BUG: scanssl(4): select error BREAK- %d - %s\n", retval, backdata);
         #endif
         // 非同期通信から同期通信に
         fcntl(sk, F_SETFL, 0);
         close(sk);
         free(senddata);
         free(url_data);
         free(dns_data);
         free(backdata);
         // select へんなんで離脱
         exit(1);
         }

      // select のタイムアウト
      else if(retval == 0){
         printf("URL %s: Port %d: %s\n", url_data, port, SOCK_16);
         #ifdef SSL_BUG
         printf("SSL_BUG: scanssl(5): select time out BREAK- %d - %s\n", retval, backdata);
         #endif
         // 非同期通信から同期通信に
         fcntl(sk, F_SETFL, 0);
         close(sk);
         free(senddata);
         free(url_data);
         free(dns_data);
         free(backdata);
         // select timeout なので離脱
         exit(1);
         }
      // 時間内に接続出来たのでLoopOUTします
      else{
         #ifdef SSL_BUG
         printf("SSL_BUG: scanssl(6): select time succes BREAK-%d- %s\n", retval, backdata);
         #endif
         break;
         }
      }

   // 非同期通信から同期通信に
   fcntl(sk, F_SETFL, 0);

   // select を省いた GOTO
   notselect :;

   // ソケットに関するペンディングエラーを返す
   if(getsockopt(sk, SOL_SOCKET, SO_ERROR, (void *)&retval, (void *)&arglen) < 0){
      printf("URL %s: Port %d: %s\n", url_data, port, SOCK_13);
      #ifdef SSL_BUG
      printf("SSL_BUG: scanssl(): getsockopt(7) Errors!\n");
      #endif
      close(sk);
      free(senddata);
      free(url_data);
      free(dns_data);
      free(backdata);
      // getsockopt異常、離脱
      exit(1);
      }
   else{
      // エラーがある場合
      if(retval){
         printf("URL %s: Port %d: %s: %s\n", url_data, port, (retval != 0) ? strerror(retval): "0", SOCK_5);
         #ifdef SSL_BUG
         printf("SSL_BUG: scanssl(8): 1 SO_ERROR %d %s\n", retval, backdata);
         #endif
         close(sk);
         free(senddata);
         free(url_data);
         free(dns_data);
         free(backdata);
         // エラーがあるの
         exit(1);
         }

      // エラーが無い場合
      else{
         // SSL の初期化を実行
         /* SSL 用ディスクプリターの初期化 */
         SSL_load_error_strings();        // err を文字にする
         SSL_library_init();              // SSL/TLSの初期化
         ctx = SSL_CTX_new(SSLv23_client_method());
         if( ctx == NULL ){
            // ERR_print_errors_fp(stderr);
            printf("URL %s: Port %d: %s\n", url_data, port, "ssl_ctx object cannot be generated.");
            #ifdef SSL_BUG
            printf("SSL_BUG: scanssl(): SSL_CTX_new() failed:\n");
            #endif
            SSL_CTX_free(ctx);
            ERR_free_strings();
            close(sk);
            free(senddata);
            free(url_data);
            free(dns_data);
            free(backdata);
            // SSLライブラリが初期化できぬ
            exit(1);
            }

         // SSL幸三体の初期化
         ssl = SSL_new(ctx);

         if( ssl == NULL ){
            sslerr = SSL_get_error(ssl, ret);
            ERR_error_string(sslerr, swapdata);
            printf("URL %s: Port %d: %s: %s\n", url_data, port, swapdata, "structure cannot be initialized.");
            #ifdef SSL_BUG
            printf("SSL_BUG: scanssl(): SSL_new() failed: %s\n", swapdata);
            #endif
            SSL_free(ssl);
            SSL_CTX_free(ctx);
            ERR_free_strings();
            close(sk);
            free(senddata);
            free(url_data);
            free(dns_data);
            free(backdata);
            // SSL構造体が初期化できぬ
            exit(1);
            }

         /* SSL ディスクプリターとHTTPSのソケットディスクプリターの置き換え */
         ret = SSL_set_fd(ssl, sk);

         if( ret == 0 ){
            sslerr = SSL_get_error(ssl, ret);
            ERR_error_string(sslerr, swapdata);
            printf("URL %s: Port %d: %s: %s\n", url_data, port, swapdata, "descriptor cannot be made.");
            #ifdef SSL_BUG
            printf("SSL_BUG: scanssl(): SSL_set_fd() failed: %s\n", swapdata);
            #endif
            SSL_free(ssl);
            SSL_CTX_free(ctx);
            ERR_free_strings();
            close(sk);
            free(senddata);
            free(url_data);
            free(dns_data);
            free(backdata);
            // SSLディスクリプタのすり替えがしっぱい
            exit(1);
            }

         /* 擬似乱数 PRNG 初期化 */
         RAND_poll();
         while( RAND_status() == 0 ){
            unsigned short rand_ret = rand() % 65536;
            RAND_seed(&rand_ret, sizeof(rand_ret));
            }


         /* SSL でコネクト、TCPではすでに確立しているが、ここではSSLでの話 */
         ret = SSL_connect(ssl);

         if( ret != 1 ){
            sslerr = SSL_get_error(ssl, ret);
            ERR_error_string(sslerr, swapdata);
            printf("URL %s: Port %d: %s: %s\n", url_data, port, swapdata, "SSL cannot be used.\n");
            #ifdef SSL_BUG
            printf("SSL_BUG: scanssl(): SSL_connect() failed: %d %s\n",ret, swapdata);
            #endif
            SSL_shutdown(ssl); 
            SSL_free(ssl);
            SSL_CTX_free(ctx);
            ERR_free_strings();
            close(sk);
            free(senddata);
            free(url_data);
            free(dns_data);
            free(backdata);
            // SSLでのコネクションが確立できぬ
            exit(1);
            }
         // SSL 初期化はここまで

/*
         // SSL 確認
         #ifdef SSL_BUG
         cipher  = SSL_get_current_cipher(ssl);

         backdata=safe_sprintf(backdata, BUF_MAX,
           "Cipher info:\n\tproversion=%s\n\tversion=%s\n\tname=%s\n\tbits=%d",
            SSL_get_version(ssl),
            SSL_CIPHER_get_version(cipher),
            SSL_CIPHER_get_name(cipher),
            SSL_CIPHER_get_bits(cipher, NULL));

         printf("SSL: scanssl(cipher): %s\n", backdata);
         #endif
*/

         // X509 の初期化 証明書関係の確認
         cert = SSL_get_peer_certificate (ssl);


/*
         backdata=safe_sprintf(backdata, BUF_MAX,
           "X509 info :\n\tsubject=%s\n\tissuer=%s\n\tcert length=%d\n\tPresent time=%d Before time=%d After time=%d\n\t%s",
            X509_NAME_oneline(X509_get_subject_name(cert), 0, 0),
            X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0),
            cert_length, N_time, B_time, A_time,
            "It is outside the expiration date."); 

         #ifdef SSL_BUG
         printf("SSL_BUG: scanssl(cert): %s\n", backdata);
         #endif
*/


         if (cert != NULL) {
            cert_length = i2d_X509(cert, NULL);

            N_time = time(NULL);
            notBefore = X509_get_notBefore(cert);
            B_time = (int)cert_time_get((char *)notBefore->data);      // 期限開始
            notAfter  = X509_get_notAfter(cert);
            A_time = (int)cert_time_get((char *)notAfter->data);       // 期限終了
            Na_time = A_time - (time_t)cert_lim;                       // 期限しきい値


            // 証明書の有効期限を確認

            if(cert_lim != 0){                                            // 閾値が0で無い場合は詳細に
               if(B_time >= N_time){                                      // 有効期限に現在時間が達していない
                  /*                                                      // あまり意味を感じないのでとりあえずコメント 
                  printf("cert: %s=%d:%d:%d %s=%d:%d:%d %s=%d:%d:%d %s=%d:%d:%d info: %s\n",
                     X509_11,
                     utime_getr(N_time, 'y'),
                     utime_getr(N_time, 'm'),
                     utime_getr(N_time, 'd'),
                     X509_12,
                     utime_getr(B_time, 'y'),
                     utime_getr(B_time, 'm'),
                     utime_getr(B_time, 'd'),
                     X509_13,
                     utime_getr(A_time, 'y'),
                     utime_getr(A_time, 'm'),
                     utime_getr(A_time, 'd'),
                     X509_14,
                     utime_getr(Na_time, 'y'),
                     utime_getr(Na_time, 'm'),
                     utime_getr(Na_time, 'd'),
                     X509_1); 
                  #ifdef SSL_BUG
                  printf("SSL_BUG: scanssl(x509): %s\n", backdata);
                  #endif

                  X509_free(cert);
                  SSL_shutdown(ssl); 
                  close(sk);
                  SSL_free(ssl);
                  SSL_CTX_free(ctx);
                  ERR_free_strings();
                  free(senddata);
                  free(url_data);
                  free(dns_data);
                  free(backdata);
                  // 有効期限に達してないのでエラーはやすぎんだよ。
                  exit(1);
                  */
                  }
               else if(Na_time < N_time && (A_time - AF_TIME) > N_time){   // 現在時間が期限のしきい値内に入った
                  printf("cert: %s=%d:%d:%d %s=%d:%d:%d %s=%d:%d:%d %s=%d:%d:%d info: %s\n",
                     X509_11,
                     utime_getr(N_time, 'y'),
                     utime_getr(N_time, 'm'),
                     utime_getr(N_time, 'd'),
                     X509_12,
                     utime_getr(B_time, 'y'),
                     utime_getr(B_time, 'm'),
                     utime_getr(B_time, 'd'),
                     X509_13,
                     utime_getr(A_time, 'y'),
                     utime_getr(A_time, 'm'),
                     utime_getr(A_time, 'd'),
                     X509_14,
                     utime_getr(Na_time, 'y'),
                     utime_getr(Na_time, 'm'),
                     utime_getr(Na_time, 'd'),
                     X509_2); 
                  #ifdef SSL_BUG
                  printf("SSL_BUG: scanssl(x509): %s\n", backdata);
                  #endif
                  X509_free(cert);
                  SSL_shutdown(ssl); 
                  close(sk);
                  SSL_free(ssl);
                  SSL_CTX_free(ctx);
                  ERR_free_strings();
                  free(senddata);
                  free(url_data);
                  free(dns_data);
                  free(backdata);
                  // そろそろ注意だといってみる
                  exit(1);
                  }
               else if((A_time - AF_TIME) < N_time && A_time > N_time){   // 期限の残り3日いないに入った
                  printf("cert: %s=%d:%d:%d %s=%d:%d:%d %s=%d:%d:%d %s=%d:%d:%d info: %s\n",
                     X509_11,
                     utime_getr(N_time, 'y'),
                     utime_getr(N_time, 'm'),
                     utime_getr(N_time, 'd'),
                     X509_12,
                     utime_getr(B_time, 'y'),
                     utime_getr(B_time, 'm'),
                     utime_getr(B_time, 'd'),
                     X509_13,
                     utime_getr(A_time, 'y'),
                     utime_getr(A_time, 'm'),
                     utime_getr(A_time, 'd'),
                     X509_14,
                     utime_getr(Na_time, 'y'),
                     utime_getr(Na_time, 'm'),
                     utime_getr(Na_time, 'd'),
                     X509_3); 
                  #ifdef SSL_BUG
                  printf("SSL_BUG: scanssl(x509): %s\n", backdata);
                  #endif

                  X509_free(cert);
                  SSL_shutdown(ssl); 
                  close(sk);
                  SSL_free(ssl);
                  SSL_CTX_free(ctx);
                  ERR_free_strings();
                  free(senddata);
                  free(url_data);
                  free(dns_data);
                  free(backdata);
                  // のこり3日で離脱
                  exit(1);
                  }
               else if(A_time < N_time){                                // 期限を過ぎてしまいました
                  printf("cert: %s=%d:%d:%d %s=%d:%d:%d %s=%d:%d:%d %s=%d:%d:%d info: %s\n",
                     X509_11,
                     utime_getr(N_time, 'y'),
                     utime_getr(N_time, 'm'),
                     utime_getr(N_time, 'd'),
                     X509_12,
                     utime_getr(B_time, 'y'),
                     utime_getr(B_time, 'm'),
                     utime_getr(B_time, 'd'),
                     X509_13,
                     utime_getr(A_time, 'y'),
                     utime_getr(A_time, 'm'),
                     utime_getr(A_time, 'd'),
                     X509_14,
                     utime_getr(Na_time, 'y'),
                     utime_getr(Na_time, 'm'),
                     utime_getr(Na_time, 'd'),
                     X509_4); 
                  #ifdef SSL_BUG
                  printf("SSL_BUG: scanssl(x509): %s\n", backdata);
                  #endif

                  X509_free(cert);
                  SSL_shutdown(ssl); 
                  close(sk);
                  SSL_free(ssl);
                  SSL_CTX_free(ctx);
                  ERR_free_strings();
                  free(senddata);
                  free(url_data);
                  free(dns_data);
                  free(backdata);
                  // すぎちゃったの
                  exit(1);
                  }
               else {
                  #ifdef SSL_BUG
                  printf("SSL_BUG: scanssl(x509): %s\n", backdata);
                  #endif
                  }
               }
            else{                                                  // 閾値が0の場合はCERTの期限監視は行わない
//             fprintf(stderr,"SSL_BUG: scanssl(): 鍵の有効期限を過ぎていますが、閾値が0なので無視しています \n");
               }


            // X509 Verify 
            backdata = verify_ssl(backdata, ssl, &sslerr);

            if(sslerr != 0 && sslerr != 20){
               printf("509_verify NG: id %d: data %s\n", sslerr, backdata);
               #ifdef SSL_BUG
               printf("SSL_BUG: scanssl(x509_verify) NG: id=%d, data=%s\n", sslerr, backdata);
               #endif

               X509_free(cert);
               SSL_shutdown(ssl); 
               close(sk);
               SSL_free(ssl);
               SSL_CTX_free(ctx);
               ERR_free_strings();
               free(senddata);
               free(url_data);
               free(dns_data);
               free(backdata);
               // 証明書になにやら問題があるね。
               exit(1);
               }
            else{
               #ifdef SSL_BUG
               printf("SSL_BUG: scanssl(x509_verify) OK: id=%d, data=%s\n", sslerr, backdata);
               #endif
               }
            }
         else {
            printf("Server does not have certificate.\n");
            #ifdef SSL_BUG
            printf("SSL_BUG: scanssl(x509): %s\n", backdata);
            #endif
            X509_free(cert);
            SSL_shutdown(ssl); 
            close(sk);
            SSL_free(ssl);
            SSL_CTX_free(ctx);
            ERR_free_strings();
            free(senddata);
            free(url_data);
            free(dns_data);
            free(backdata);
            exit(1);
            }


         // cert の開放
         X509_free(cert);


         // SSL 確認はここまで

         backdata=safe_sprintf(backdata,BUF_MAX, "URL %s: Port %d: %s", url_data, port, SOCK_3);

         senddata = set_request(senddata, url_dom, url_pass);
         #ifdef SSL_BUG
         printf("SSL_BUG: scanssl(9): set_request*send-%s- %s\n", senddata, backdata);
         #endif

         // 再度非同期通信の開始  SSL にした場合にFDはこれ使っていいのかな？？？
         fcntl(sk, F_SETFL, O_NONBLOCK);

         // HEAD メソッドの送信 SSL専用の関数を使用。
         ret = SSL_write(ssl, senddata, strlen(senddata));

         tv.tv_sec = timeout;
         tv.tv_usec = 0;
         while(1){
            FD_ZERO(&rfds);
            FD_SET(sk, &rfds);
            retval = select(sk + 1, &rfds, NULL, NULL, &tv);
            // select 異常終了
            if(retval < 0){
               printf("URL %s: Port %d: %s: %s\n", url_data, port, SOCK_15, URL_2);
               #ifdef SSL_BUG
               printf("SSL_BUG: scanssl(10): select error %s\n", backdata);
               #endif 
               // 非同期通信から同期通信
               fcntl(sk, F_SETFL, 0);
               // SSL回りの開放
               SSL_shutdown(ssl); 
               close(sk);
               SSL_free(ssl);
               SSL_CTX_free(ctx);
               ERR_free_strings();
               free(senddata);
               free(url_data);
               free(dns_data);
               free(backdata);
               exit(1);
               }
            // select のタイムアウト
            else if(retval == 0){
               printf("URL %s: Port %d: %s %s\n", url_data, port, SOCK_16, URL_3);
               #ifdef SSL_BUG
               printf("SSL_BUG: scanssl(11): select timed out %s\n", backdata); 
               #endif 
               // 非同期通信から同期通信に
               fcntl(sk, F_SETFL, 0);
               // SSL回りの開放
               SSL_shutdown(ssl); 
               close(sk);
               SSL_free(ssl);
               SSL_CTX_free(ctx);
               ERR_free_strings();
               free(senddata);
               free(url_data);
               free(dns_data);
               free(backdata);
               exit(1);
               }
            else{
               // 受信 SSL専用の関数を使用。
               dcount = SSL_read(ssl, recvdata, (256-1));
               recvdata[dcount] = 0x00;


               // 受信量が異常
               if(dcount < 1){
                  printf("URL %s: Port %d: %s\n", url_data, port, URL_2);
                  // 非同期通信から同期通信に
                  fcntl(sk, F_SETFL, 0);
                  // SSL回りの開放
                  SSL_shutdown(ssl); 
                  close(sk);
                  SSL_free(ssl);
                  SSL_CTX_free(ctx);
                  ERR_free_strings();
                  free(senddata);
                  free(url_data);
                  free(dns_data);
                  free(backdata);
                  exit(1);
                  }
               // 受信量が正常である
               else{
                  ssl_senddata = (char *)calloc((dcount + 10), sizeof(char));
                  // 200 番だいであることの確認
                  ssl_senddata = check_recvdata(recvdata, ssl_senddata, &ret);
                  swap_mem(ssl_senddata, ',', ' ');

                  if(ret < 0){
                     printf("%s: %s\n", ssl_senddata, URL_1);
                     #ifdef SSL_BUG
                     printf("SSL_BUG: scanssl(13): url check. not 200. ret<%d> %s\n", ret,backdata);
                     #endif 
                     // 非同期通信から同期通信に
                     fcntl(sk, F_SETFL, 0);
                     // SSL回りの開放
                     SSL_shutdown(ssl); 
                     close(sk);
                     SSL_free(ssl);
                     SSL_CTX_free(ctx);
                     ERR_free_strings();
                     free(senddata);
                     free(url_data);
                     free(dns_data);
                     free(backdata);
                     exit(1);
                     }
                  else{
                     backdata = safe_sprintf(backdata, BUF_MAX,"%s: %s\n", ssl_senddata, URL_4);
                     #ifdef SSL_BUG
                     printf("SSL_BUG: scanssl(14): url check. all succesd. ret<%d> %s\n", ret, backdata);
                     #endif 
                     }

                  free(ssl_senddata);
                  }

               // 非同期通信から同期通信に
               fcntl(sk, F_SETFL, 0);
               // SSL回りの開放
               SSL_shutdown(ssl); 
               close(sk);
               SSL_free(ssl);
               SSL_CTX_free(ctx);
               ERR_free_strings();
               free(senddata);
               free(url_data);
               free(dns_data);
               free(backdata);
               exit(1);
               }
            }

         // 非同期通信から同期通信に
         fcntl(sk, F_SETFL, 0);
         // SSL回りの開放
         SSL_shutdown(ssl); 
         close(sk);
         SSL_free(ssl);
         SSL_CTX_free(ctx);
         ERR_free_strings();
         free(senddata);
         free(url_data);
         free(dns_data);
         free(backdata);
         exit(1);
         }
      }
   }

//  HOST IP が存在すらしない
// 非同期通信
fcntl(sk, F_SETFL, 0);

backdata=safe_sprintf(backdata,BUF_MAX, "URL %s: Port %d: %s", url_data, port, SOCK_14);
#ifdef SSL_BUG
printf("SSL_BUG: scanssl(14): not connection err. %s\n", backdata); 
#endif 

close(sk);

free(senddata);
free(url_data);
free(dns_data);
free(backdata);
return 0;

}




