Beispiel #1
0
/******************************************************************************
 * FunctionName : upgrade_task
 * Description  : task to connect with target server and get firmware data 
 * Parameters   : pvParameters--save the server address\port\request frame for
 *              : the upgrade server\call back functions to tell the userapp
 *              : the result of this upgrade task
 * Returns      : none
*******************************************************************************/
void upgrade_ssl_task(void *pvParameters)
{
    int recbytes;
    int sta_socket;
    int retry_count = 0;
    struct ip_info ipconfig;
    
    struct upgrade_server_info *server = pvParameters;

    flash_erased=FALSE;
    precv_buf = (char*)malloc(UPGRADE_DATA_SEG_LEN);//the max data length
    
    while (retry_count++ < UPGRADE_RETRY_TIMES) {
        if (giveup) break;
		
        wifi_get_ip_info(STATION_IF, &ipconfig);

        /* check the ip address or net connection state*/
        while (ipconfig.ip.addr == 0) {
            vTaskDelay(1000 / portTICK_RATE_MS);
            wifi_get_ip_info(STATION_IF, &ipconfig);
        }
        
        sta_socket = socket(PF_INET,SOCK_STREAM,0);
        if (-1 == sta_socket) {
            close(sta_socket);
            vTaskDelay(1000 / portTICK_RATE_MS);
            os_printf("socket fail !\r\n");
            continue;
        }

        /*for upgrade connection debug*/
        //server->sockaddrin.sin_addr.s_addr= inet_addr("192.168.1.170");
        if(0 != connect(sta_socket,(struct sockaddr *)(&server->sockaddrin),sizeof(struct sockaddr))) {
            close(sta_socket);
            vTaskDelay(1000 / portTICK_RATE_MS);
            os_printf("connect fail!\r\n");
            continue;
        }

        uint32_t options = SSL_DISPLAY_CERTS | SSL_NO_DEFAULT_KEY;
        int i=0;
        int quiet = 0;
        int cert_index = 0, ca_cert_index = 0;
        int cert_size, ca_cert_size;
        char **ca_cert, **cert;
        SSL *ssl;
        SSL_CTX *ssl_ctx;
        uint8_t *read_buf = NULL;

        cert_size = ssl_get_config(SSL_MAX_CERT_CFG_OFFSET);
        ca_cert_size = ssl_get_config(SSL_MAX_CA_CERT_CFG_OFFSET);
        ca_cert = (char **)calloc(1, sizeof(char *)*ca_cert_size);
        cert = (char **)calloc(1, sizeof(char *)*cert_size);

        if ((ssl_ctx= ssl_ctx_new(options, SSL_DEFAULT_CLNT_SESS)) == NULL) {
            printf("Error: Client context is invalid\n");
            close(sta_socket);
            continue;
        }

		ssl_obj_memory_load(ssl_ctx, SSL_OBJ_X509_CACERT, default_certificate, default_certificate_len, NULL);

        for (i = 0; i < cert_index; i++) {
            if (ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CERT, cert[i], NULL)){
                printf("Certificate '%s' is undefined.\n", cert[i]);
            }
        }
        
        for (i = 0; i < ca_cert_index; i++) {
            if (ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, ca_cert[i], NULL)){
                printf("Certificate '%s' is undefined.\n", ca_cert[i]);
            }
        }

        free(cert);
        free(ca_cert);

        ssl= ssl_client_new(ssl_ctx, sta_socket, NULL, 0);
        if (ssl == NULL){
            ssl_ctx_free(ssl_ctx);
            close(sta_socket);
            continue;
        }
        
        if(ssl_handshake_status(ssl) != SSL_OK){
            printf("client handshake fail.\n");
            ssl_free(ssl);
            ssl_ctx_free(ssl_ctx);
            close(sta_socket);
            continue;
        }
        
        //handshake sucesses,show cert and free x509_ctx here
        if (!quiet) {
            const char *common_name = ssl_get_cert_dn(ssl,SSL_X509_CERT_COMMON_NAME);
            if (common_name) {
                printf("Common Name:\t\t\t%s\n", common_name);
            }
            display_session_id(ssl);
            display_cipher(ssl);
            quiet = true;

            x509_free(ssl->x509_ctx);
            ssl->x509_ctx=NULL;
        }

        system_upgrade_init();
        system_upgrade_flag_set(UPGRADE_FLAG_START);

        if(ssl_write(ssl, server->url, strlen(server->url)+1) < 0) {
            ssl_free(ssl);
            ssl_ctx_free(ssl_ctx);
            close(sta_socket);
            vTaskDelay(1000 / portTICK_RATE_MS);
            os_printf("send fail\n");
            continue;
        }
        os_printf("Request send success\n");

        while((recbytes = ssl_read(ssl, &read_buf)) >= 0) {

            if(recbytes == 0){
                vTaskDelay(500 / portTICK_RATE_MS);
                continue;
            }
            
            if(recbytes > UPGRADE_DATA_SEG_LEN) {
                ssl_free(ssl);
                ssl_ctx_free(ssl_ctx);
                close(sta_socket);
                vTaskDelay(2000 / portTICK_RATE_MS);
                printf("bigger than UPGRADE_DATA_SEG_LEN\n");
            }

            if((recbytes)<=1460)
                memcpy(precv_buf,read_buf,recbytes);
            else
                os_printf("ERR2:arr_overflow,%u,%d\n",__LINE__,recbytes);

            if(FALSE==flash_erased){
                ssl_free(ssl);
                ssl_ctx_free(ssl_ctx);
                close(sta_socket);
                os_printf("pre erase flash!\n");
                upgrade_data_load(precv_buf,recbytes);
                break;
            }
            
            if(false == upgrade_data_load(read_buf,recbytes)) {
                os_printf("upgrade data error!\n");
                ssl_free(ssl);
                ssl_ctx_free(ssl_ctx);
                close(sta_socket);
                flash_erased=FALSE;
                vTaskDelay(1000 / portTICK_RATE_MS);
                break;
            }
            /*this two length data should be equal, if totallength is bigger, 
             *maybe data wrong or server send extra info, drop it anyway*/
            if(totallength >= sumlength) {
                os_printf("upgrade data load finish.\n");
                ssl_free(ssl);
                ssl_ctx_free(ssl_ctx);
                close(sta_socket);
                goto finish;
            }
            os_printf("upgrade_task %d word left\n",uxTaskGetStackHighWaterMark(NULL));
            
        }
        
        if(recbytes < 0) {
            os_printf("ERROR:read data fail! recbytes %d\r\n",recbytes);
            ssl_free(ssl);
            ssl_ctx_free(ssl_ctx);
            close(sta_socket);
            flash_erased=FALSE;
            vTaskDelay(1000 / portTICK_RATE_MS);
        }
        
        os_printf("upgrade_task %d word left\n",uxTaskGetStackHighWaterMark(NULL));
        
        totallength =0;
        sumlength = 0;
    }
    
finish:

	if(upgrade_crc_check(system_get_fw_start_sec(),sumlength) != 0)
	{
		printf("upgrade crc check failed !\n");
		server->upgrade_flag = false;
        system_upgrade_flag_set(UPGRADE_FLAG_IDLE);	
	}

    os_timer_disarm(&upgrade_timer);

    totallength = 0;
    sumlength = 0;
    flash_erased=FALSE;
    free(precv_buf);
    
    if(retry_count == UPGRADE_RETRY_TIMES){
        /*retry too many times, fail*/
        server->upgrade_flag = false;
        system_upgrade_flag_set(UPGRADE_FLAG_IDLE);

    }else{
        if (server->upgrade_flag == true)
			system_upgrade_flag_set(UPGRADE_FLAG_FINISH);
    }
    
    upgrade_deinit();
    
    os_printf("\n Exit upgrade task.\n");
    if (server->check_cb != NULL) {
        server->check_cb(server);
    }
    vTaskDelay(100 / portTICK_RATE_MS);
    vTaskDelete(NULL);
}
Beispiel #2
0
 SSLContext() {
     if (_ssl_ctx_refcnt == 0) {
         _ssl_ctx = ssl_ctx_new(SSL_SERVER_VERIFY_LATER | SSL_DEBUG_OPTS, 0);
     }
     ++_ssl_ctx_refcnt;
 }
 SSLContext() {
     if (_ssl_ctx_refcnt == 0) {
         _ssl_ctx = ssl_ctx_new(SSL_SERVER_VERIFY_LATER | SSL_DEBUG_OPTS | SSL_CONNECT_IN_PARTS | SSL_READ_BLOCKING, 0);
     }
     ++_ssl_ctx_refcnt;
 }
Beispiel #4
0
/*
 * This function is called after the TCP connect has completed. Setup the TLS
 * layer and do all necessary magic.
 */
CURLcode
Curl_axtls_connect(struct connectdata *conn,
                  int sockindex)

{
  struct SessionHandle *data = conn->data;
  SSL_CTX *ssl_ctx;
  SSL *ssl;
  int cert_types[] = {SSL_OBJ_X509_CERT, SSL_OBJ_PKCS12, 0};
  int key_types[] = {SSL_OBJ_RSA_KEY, SSL_OBJ_PKCS8, SSL_OBJ_PKCS12, 0};
  int i, ssl_fcn_return;
  const uint8_t *ssl_sessionid;
  size_t ssl_idsize;
  const char *peer_CN;
  uint32_t dns_altname_index;
  const char *dns_altname;
  int8_t found_subject_alt_names = 0;
  int8_t found_subject_alt_name_matching_conn = 0;

  /* Assuming users will not compile in custom key/cert to axTLS */
  uint32_t client_option = SSL_NO_DEFAULT_KEY|SSL_SERVER_VERIFY_LATER;

  if(conn->ssl[sockindex].state == ssl_connection_complete)
    /* to make us tolerant against being called more than once for the
       same connection */
    return CURLE_OK;

  /* axTLS only supports TLSv1 */
  /* check to see if we've been told to use an explicit SSL/TLS version */
  switch(data->set.ssl.version) {
  case CURL_SSLVERSION_DEFAULT:
  case CURL_SSLVERSION_TLSv1:
    break;
  default:
    failf(data, "axTLS only supports TLSv1");
    return CURLE_SSL_CONNECT_ERROR;
  }

#ifdef  AXTLSDEBUG
  client_option |= SSL_DISPLAY_STATES | SSL_DISPLAY_RSA | SSL_DISPLAY_CERTS;
#endif /* AXTLSDEBUG */

  /* Allocate an SSL_CTX struct */
  ssl_ctx = ssl_ctx_new(client_option, SSL_DEFAULT_CLNT_SESS);
  if(ssl_ctx == NULL) {
    failf(data, "unable to create client SSL context");
    return CURLE_SSL_CONNECT_ERROR;
  }

  /* Load the trusted CA cert bundle file */
  if(data->set.ssl.CAfile) {
    if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, data->set.ssl.CAfile, NULL)
       != SSL_OK) {
      infof(data, "error reading ca cert file %s \n",
            data->set.ssl.CAfile);
      if(data->set.ssl.verifypeer) {
        Curl_axtls_close(conn, sockindex);
        return CURLE_SSL_CACERT_BADFILE;
      }
    }
    else
      infof(data, "found certificates in %s\n", data->set.ssl.CAfile);
  }

  /* gtls.c tasks we're skipping for now:
   * 1) certificate revocation list checking
   * 2) dns name assignment to host
   * 3) set protocol priority.  axTLS is TLSv1 only, so can probably ignore
   * 4) set certificate priority.  axTLS ignores type and sends certs in
   *  order added.  can probably ignore this.
   */

  /* Load client certificate */
  if(data->set.str[STRING_CERT]) {
    i=0;
    /* Instead of trying to analyze cert type here, let axTLS try them all. */
    while(cert_types[i] != 0) {
      ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i],
                                    data->set.str[STRING_CERT], NULL);
      if(ssl_fcn_return == SSL_OK) {
        infof(data, "successfully read cert file %s \n",
              data->set.str[STRING_CERT]);
        break;
      }
      i++;
    }
    /* Tried all cert types, none worked. */
    if(cert_types[i] == 0) {
      failf(data, "%s is not x509 or pkcs12 format",
            data->set.str[STRING_CERT]);
      Curl_axtls_close(conn, sockindex);
      return CURLE_SSL_CERTPROBLEM;
    }
  }

  /* Load client key.
     If a pkcs12 file successfully loaded a cert, then there's nothing to do
     because the key has already been loaded. */
  if(data->set.str[STRING_KEY] && cert_types[i] != SSL_OBJ_PKCS12) {
    i=0;
    /* Instead of trying to analyze key type here, let axTLS try them all. */
    while(key_types[i] != 0) {
      ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i],
                                    data->set.str[STRING_KEY], NULL);
      if(ssl_fcn_return == SSL_OK) {
        infof(data, "successfully read key file %s \n",
              data->set.str[STRING_KEY]);
        break;
      }
      i++;
    }
    /* Tried all key types, none worked. */
    if(key_types[i] == 0) {
      failf(data, "Failure: %s is not a supported key file",
            data->set.str[STRING_KEY]);
      Curl_axtls_close(conn, sockindex);
      return CURLE_SSL_CONNECT_ERROR;
    }
  }

  /* gtls.c does more here that is being left out for now
   * 1) set session credentials.  can probably ignore since axtls puts this
   *    info in the ssl_ctx struct
   * 2) setting up callbacks.  these seem gnutls specific
   */

  /* In axTLS, handshaking happens inside ssl_client_new. */
  if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize)) {
    /* we got a session id, use it! */
    infof (data, "SSL re-using session ID\n");
    ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex],
                         ssl_sessionid, (uint8_t)ssl_idsize);
  }
  else
    ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0);

  /* Check to make sure handshake was ok. */
  ssl_fcn_return = ssl_handshake_status(ssl);
  if(ssl_fcn_return != SSL_OK) {
    Curl_axtls_close(conn, sockindex);
    ssl_display_error(ssl_fcn_return); /* goes to stdout. */
    return map_error_to_curl(ssl_fcn_return);
  }
  infof (data, "handshake completed successfully\n");

  /* Here, gtls.c gets the peer certificates and fails out depending on
   * settings in "data."  axTLS api doesn't have get cert chain fcn, so omit?
   */

  /* Verify server's certificate */
  if(data->set.ssl.verifypeer) {
    if(ssl_verify_cert(ssl) != SSL_OK) {
      Curl_axtls_close(conn, sockindex);
      failf(data, "server cert verify failed");
      return CURLE_SSL_CONNECT_ERROR;
    }
  }
  else
    infof(data, "\t server certificate verification SKIPPED\n");

  /* Here, gtls.c does issuer verification. axTLS has no straightforward
   * equivalent, so omitting for now.*/

  /* Here, gtls.c does the following
   * 1) x509 hostname checking per RFC2818.  axTLS doesn't support this, but
   *    it seems useful. This is now implemented, by Oscar Koeroo
   * 2) checks cert validity based on time.  axTLS does this in ssl_verify_cert
   * 3) displays a bunch of cert information.  axTLS doesn't support most of
   *    this, but a couple fields are available.
   */


  /* There is no (DNS) Altnames count in the version 1.4.8 API. There is a
     risk of an inifite loop */
  for(dns_altname_index = 0; ; dns_altname_index++) {
    dns_altname = ssl_get_cert_subject_alt_dnsname(ssl, dns_altname_index);
    if(dns_altname == NULL) {
      break;
    }
    found_subject_alt_names = 1;

    infof(data, "\tComparing subject alt name DNS with hostname: %s <-> %s\n",
          dns_altname, conn->host.name);
    if(Curl_cert_hostcheck(dns_altname, conn->host.name)) {
      found_subject_alt_name_matching_conn = 1;
      break;
    }
  }

  /* RFC2818 checks */
  if(found_subject_alt_names && !found_subject_alt_name_matching_conn) {
    /* Break connection ! */
    Curl_axtls_close(conn, sockindex);
    failf(data, "\tsubjectAltName(s) do not match %s\n", conn->host.dispname);
    return CURLE_PEER_FAILED_VERIFICATION;
  }
  else if(found_subject_alt_names == 0) {
    /* Per RFC2818, when no Subject Alt Names were available, examine the peer
       CN as a legacy fallback */
    peer_CN = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME);
    if(peer_CN == NULL) {
      /* Similar behaviour to the OpenSSL interface */
      Curl_axtls_close(conn, sockindex);
      failf(data, "unable to obtain common name from peer certificate");
      return CURLE_PEER_FAILED_VERIFICATION;
    }
    else {
      if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) {
        if(data->set.ssl.verifyhost) {
          /* Break connection ! */
          Curl_axtls_close(conn, sockindex);
          failf(data, "\tcommon name \"%s\" does not match \"%s\"\n",
                peer_CN, conn->host.dispname);
          return CURLE_PEER_FAILED_VERIFICATION;
        }
        else
          infof(data, "\tcommon name \"%s\" does not match \"%s\"\n",
                peer_CN, conn->host.dispname);
      }
    }
  }

  /* General housekeeping */
  conn->ssl[sockindex].state = ssl_connection_complete;
  conn->ssl[sockindex].ssl = ssl;
  conn->ssl[sockindex].ssl_ctx = ssl_ctx;
  conn->recv[sockindex] = axtls_recv;
  conn->send[sockindex] = axtls_send;

  /* Put our freshly minted SSL session in cache */
  ssl_idsize = ssl_get_session_id_size(ssl);
  ssl_sessionid = ssl_get_session_id(ssl);
  if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize)
     != CURLE_OK)
    infof (data, "failed to add session to cache\n");

  return CURLE_OK;
}
Beispiel #5
0
/*
 * For both blocking and non-blocking connects, this function sets up the
 * ssl context and state.  This function is called after the TCP connect
 * has completed.
 */
static CURLcode connect_prep(struct connectdata *conn, int sockindex)
{
  struct SessionHandle *data = conn->data;
  SSL_CTX *ssl_ctx;
  SSL *ssl = NULL;
  int cert_types[] = {SSL_OBJ_X509_CERT, SSL_OBJ_PKCS12, 0};
  int key_types[] = {SSL_OBJ_RSA_KEY, SSL_OBJ_PKCS8, SSL_OBJ_PKCS12, 0};
  int i, ssl_fcn_return;
  const uint8_t *ssl_sessionid;
  size_t ssl_idsize;

  /* Assuming users will not compile in custom key/cert to axTLS.
  *  Also, even for blocking connects, use axTLS non-blocking feature.
  */
  uint32_t client_option = SSL_NO_DEFAULT_KEY |
    SSL_SERVER_VERIFY_LATER |
    SSL_CONNECT_IN_PARTS;

  if(conn->ssl[sockindex].state == ssl_connection_complete)
    /* to make us tolerant against being called more than once for the
       same connection */
    return CURLE_OK;

  /* axTLS only supports TLSv1 */
  /* check to see if we've been told to use an explicit SSL/TLS version */
  switch(data->set.ssl.version) {
  case CURL_SSLVERSION_DEFAULT:
  case CURL_SSLVERSION_TLSv1:
    break;
  default:
    failf(data, "axTLS only supports TLS 1.0 and 1.1, "
          "and it cannot be specified which one to use");
    return CURLE_SSL_CONNECT_ERROR;
  }

#ifdef  AXTLSDEBUG
  client_option |= SSL_DISPLAY_STATES | SSL_DISPLAY_RSA | SSL_DISPLAY_CERTS;
#endif /* AXTLSDEBUG */

  /* Allocate an SSL_CTX struct */
  ssl_ctx = ssl_ctx_new(client_option, SSL_DEFAULT_CLNT_SESS);
  if(ssl_ctx == NULL) {
    failf(data, "unable to create client SSL context");
    return CURLE_SSL_CONNECT_ERROR;
  }

  conn->ssl[sockindex].ssl_ctx = ssl_ctx;
  conn->ssl[sockindex].ssl = NULL;

  /* Load the trusted CA cert bundle file */
  if(data->set.ssl.CAfile) {
    if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, data->set.ssl.CAfile, NULL)
       != SSL_OK) {
      infof(data, "error reading ca cert file %s \n",
            data->set.ssl.CAfile);
      if(data->set.ssl.verifypeer) {
        return CURLE_SSL_CACERT_BADFILE;
      }
    }
    else
      infof(data, "found certificates in %s\n", data->set.ssl.CAfile);
  }

  /* gtls.c tasks we're skipping for now:
   * 1) certificate revocation list checking
   * 2) dns name assignment to host
   * 3) set protocol priority.  axTLS is TLSv1 only, so can probably ignore
   * 4) set certificate priority.  axTLS ignores type and sends certs in
   *  order added.  can probably ignore this.
   */

  /* Load client certificate */
  if(data->set.str[STRING_CERT]) {
    i=0;
    /* Instead of trying to analyze cert type here, let axTLS try them all. */
    while(cert_types[i] != 0) {
      ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i],
                                    data->set.str[STRING_CERT], NULL);
      if(ssl_fcn_return == SSL_OK) {
        infof(data, "successfully read cert file %s \n",
              data->set.str[STRING_CERT]);
        break;
      }
      i++;
    }
    /* Tried all cert types, none worked. */
    if(cert_types[i] == 0) {
      failf(data, "%s is not x509 or pkcs12 format",
            data->set.str[STRING_CERT]);
      return CURLE_SSL_CERTPROBLEM;
    }
  }

  /* Load client key.
     If a pkcs12 file successfully loaded a cert, then there's nothing to do
     because the key has already been loaded. */
  if(data->set.str[STRING_KEY] && cert_types[i] != SSL_OBJ_PKCS12) {
    i=0;
    /* Instead of trying to analyze key type here, let axTLS try them all. */
    while(key_types[i] != 0) {
      ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i],
                                    data->set.str[STRING_KEY], NULL);
      if(ssl_fcn_return == SSL_OK) {
        infof(data, "successfully read key file %s \n",
              data->set.str[STRING_KEY]);
        break;
      }
      i++;
    }
    /* Tried all key types, none worked. */
    if(key_types[i] == 0) {
      failf(data, "Failure: %s is not a supported key file",
            data->set.str[STRING_KEY]);
      return CURLE_SSL_CONNECT_ERROR;
    }
  }

  /* gtls.c does more here that is being left out for now
   * 1) set session credentials.  can probably ignore since axtls puts this
   *    info in the ssl_ctx struct
   * 2) setting up callbacks.  these seem gnutls specific
   */

  /* In axTLS, handshaking happens inside ssl_client_new. */
  Curl_ssl_sessionid_lock(conn);
  if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize)) {
    /* we got a session id, use it! */
    infof (data, "SSL re-using session ID\n");
    ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex],
                         ssl_sessionid, (uint8_t)ssl_idsize);
    Curl_ssl_sessionid_unlock();
  }
  else {
    Curl_ssl_sessionid_unlock();
    ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0);
  }

  conn->ssl[sockindex].ssl = ssl;
  return CURLE_OK;
}
Beispiel #6
0
int main(int argc, char *argv[]) 
{
    fd_set rfds, wfds;
    struct connstruct *tp, *to;
    struct serverstruct *sp;
    int rnum, wnum, active;
    int i = 1;
    time_t currtime;
    char *httpAddress = NULL;
    int httpPort = CONFIG_HTTP_PORT;
    char *httpsAddress = NULL;
    int httpsPort = CONFIG_HTTP_HTTPS_PORT;
    uint32_t options = CONFIG_HTTP_DEFAULT_SSL_OPTIONS;
    char *portStr;
    char *private_key = NULL;
    char *cert = NULL;

#ifdef WIN32
    WORD wVersionRequested = MAKEWORD(2, 2);
    WSADATA wsaData;
    WSAStartup(wVersionRequested,&wsaData);
#else
    signal(SIGPIPE, SIG_IGN);
#if defined(CONFIG_HTTP_HAS_CGI)
    signal(SIGCHLD, reaper);
#endif
#ifdef CONFIG_HTTP_VERBOSE
    signal(SIGQUIT, die);
#endif
#endif

#ifdef CONFIG_HTTP_VERBOSE
    signal(SIGTERM, die);
    signal(SIGINT, sigint_cleanup);
#endif
    tdate_init();

    /* get some command-line parameters */
    while (argv[i] != NULL)
    {
        if (strcmp(argv[i], "-p") == 0 && argv[i+1] != NULL)
        {
            if ((portStr = strchr(argv[i+1], ':')) != NULL)
            {
                httpAddress = argv[i+1];
                *portStr = 0;
                httpPort = atoi(portStr + 1);
            }
            else
                httpPort = atoi(argv[i+1]);

            i += 2;
            continue;
        }

        if (strcmp(argv[i], "-s") == 0 && argv[i+1] != NULL)
        {
            if ((portStr = strchr(argv[i+1], ':')) != NULL)
            {
                httpsAddress = argv[i+1];
                *portStr = 0;
                httpsPort = atoi(portStr + 1);
            }
            else
                httpsPort = atoi(argv[i+1]);

            i += 2;
            continue;
        }

        if (strcmp(argv[i], "-w") == 0 && argv[i+1] != NULL)
        {
            webroot = argv[i+1];
            i += 2;
            continue;
        }

        if (strcmp(argv[i], "-cert") == 0 && argv[i+1] != NULL)
        {
            cert = argv[i+1];
            i += 2;
            continue;
        }

        if (strcmp(argv[i], "-key") == 0 && argv[i+1] != NULL)
        {
            private_key = argv[i+1];
            i += 2;
            continue;
        }
        printf("%s:\n"
               "    [-p [address:]httpport]\n"
               "    [-s [address:]httpsport]\n"
               "    [-key private_key]\n"
               "    [-cert cert]\n"
               "    [-w webroot]\n", argv[0]);
        exit(1);
    }

    for (i = 0; i < INITIAL_CONNECTION_SLOTS; i++) 
    {
        tp = freeconns;
        freeconns = (struct connstruct *)calloc(1, sizeof(struct connstruct));
        freeconns->next = tp;
    }

    if ((active = openlistener(httpAddress, httpPort)) == -1) 
    {
#ifdef CONFIG_HTTP_VERBOSE
        fprintf(stderr, "ERR: Couldn't bind to port %d\n", httpPort);
#endif
        exit(1);
    }

    addtoservers(active);

    if ((active = openlistener(httpsAddress, httpsPort)) == -1) 
    {
#ifdef CONFIG_HTTP_VERBOSE
        fprintf(stderr, "ERR: Couldn't bind to port %d\n", httpsPort);
#endif
        exit(1);
    }

    addtoservers(active);

    if (cert != NULL && private_key != NULL)
        options |=  SSL_NO_DEFAULT_KEY;

    servers->ssl_ctx = ssl_ctx_new(options, CONFIG_HTTP_SESSION_CACHE_SIZE);
    servers->is_ssl = 1;

    if (cert != NULL && private_key != NULL)
    {
        printf("YEAH\n");
        if (ssl_obj_load(servers->ssl_ctx, SSL_OBJ_RSA_KEY, private_key,
                    NULL))
        {
#ifdef CONFIG_HTTP_VERBOSE
            fprintf(stderr, "ERR: Couldn't load private key %s\n", private_key);
#endif
            exit(1);
        }

        if (ssl_obj_load(servers->ssl_ctx, SSL_OBJ_X509_CERT, cert,
                    NULL))
        {
#ifdef CONFIG_HTTP_VERBOSE
            fprintf(stderr, "ERR: Couldn't load cert %s\n", cert);
#endif
            exit(1);
        }
    }

#if defined(CONFIG_HTTP_HAS_CGI)
    addcgiext(CONFIG_HTTP_CGI_EXTENSIONS);
#endif

#if defined(CONFIG_HTTP_VERBOSE)
#if defined(CONFIG_HTTP_HAS_CGI)
    printf("addcgiext %s\n", CONFIG_HTTP_CGI_EXTENSIONS); 
#endif
    printf("%s: listening on ports %d (http) and %d (https)\n", 
            server_version, httpPort, httpsPort);
    TTY_FLUSH();
#endif

    ax_chdir();

#ifdef CONFIG_HTTP_ENABLE_DIFFERENT_USER
    {
        struct passwd *pd = getpwnam(CONFIG_HTTP_USER);

        if (pd != NULL)
        {
            int res = setuid(pd->pw_uid);
            res |= setgid(pd->pw_gid);

#if defined(CONFIG_HTTP_VERBOSE)
            if (res == 0)
            {
                printf("change to '%s' successful\n", CONFIG_HTTP_USER); 
                TTY_FLUSH();
            }
#endif
        }

    }
#endif

#ifndef WIN32 
#ifdef CONFIG_HTTP_IS_DAEMON
    if (fork() > 0)  /* parent will die */
        exit(0);

    setsid();
#endif
#endif

    /* main loop */
    while (1)
    {
        struct timeval tv = { 10, 0 };
        FD_ZERO(&rfds);
        FD_ZERO(&wfds);
        rnum = wnum = -1;
        sp = servers;

        while (sp != NULL)  /* read each server port */
        {
            FD_SET(sp->sd, &rfds);

            if (sp->sd > rnum) 
                rnum = sp->sd;
            sp = sp->next;
        }

        /* Add the established sockets */
        tp = usedconns;
        currtime = time(NULL);

        while (tp != NULL) 
        {
            if (currtime > tp->timeout)     /* timed out? Kill it. */
            {
                to = tp;
                tp = tp->next;
                removeconnection(to);
                continue;
            }

            if (tp->state == STATE_WANT_TO_READ_HEAD) 
            {
                FD_SET(tp->networkdesc, &rfds);
                if (tp->networkdesc > rnum) 
                    rnum = tp->networkdesc;
            }

            if (tp->state == STATE_WANT_TO_SEND_HEAD) 
            {
                FD_SET(tp->networkdesc, &wfds);
                if (tp->networkdesc > wnum) 
                    wnum = tp->networkdesc;
            }

            if (tp->state == STATE_WANT_TO_READ_FILE) 
            {
                FD_SET(tp->filedesc, &rfds);
                if (tp->filedesc > rnum) 
                    rnum = tp->filedesc;
            }

            if (tp->state == STATE_WANT_TO_SEND_FILE) 
            {
                FD_SET(tp->networkdesc, &wfds);
                if (tp->networkdesc > wnum) 
                    wnum = tp->networkdesc;
            }

#if defined(CONFIG_HTTP_DIRECTORIES)
            if (tp->state == STATE_DOING_DIR) 
            {
                FD_SET(tp->networkdesc, &wfds);
                if (tp->networkdesc > wnum) 
                    wnum = tp->networkdesc;
            }
#endif
            tp = tp->next;
        }

        active = select(wnum > rnum ? wnum+1 : rnum+1,
                rnum != -1 ? &rfds : NULL, 
                wnum != -1 ? &wfds : NULL,
                NULL, usedconns ? &tv : NULL);

        /* timeout? */
        if (active == 0)
            continue;

        /* New connection? */
        sp = servers;
        while (active > 0 && sp != NULL) 
        {
            if (FD_ISSET(sp->sd, &rfds)) 
            {
                handlenewconnection(sp->sd, sp->is_ssl);
                active--;
            }

            sp = sp->next;
        }

        /* Handle the established sockets */
        tp = usedconns;

        while (active > 0 && tp != NULL) 
        {
            to = tp;
            tp = tp->next;

            if (to->state == STATE_WANT_TO_READ_HEAD &&
                        FD_ISSET(to->networkdesc, &rfds)) 
            {
                active--;
#if defined(CONFIG_HTTP_HAS_CGI)
                if (to->post_state)
                    read_post_data(to);
                else
#endif
                    procreadhead(to);
            } 

            if (to->state == STATE_WANT_TO_SEND_HEAD &&
                        FD_ISSET(to->networkdesc, &wfds)) 
            {
                active--;
                procsendhead(to);
            } 

            if (to->state == STATE_WANT_TO_READ_FILE && 
                        FD_ISSET(to->filedesc, &rfds)) 
            {
                active--;
                procreadfile(to);
            } 

            if (to->state == STATE_WANT_TO_SEND_FILE && 
                        FD_ISSET(to->networkdesc, &wfds)) 
            {
                active--;
                procsendfile(to);
            }

#if defined(CONFIG_HTTP_DIRECTORIES)
            if (to->state == STATE_DOING_DIR &&
                        FD_ISSET(to->networkdesc, &wfds)) 
            {
                active--;
                procdodir(to);
            }
#endif
        }
    }

    return 0;
}
 NPT_TlsContextImpl() :
     m_SSL_CTX(ssl_ctx_new(SSL_SERVER_VERIFY_LATER, NPT_TLS_CONTEXT_DEFAULT_SESSION_CACHE)) {};
Beispiel #8
0
SSL_CTX * SSL_CTX_new(void *meth)
{
    SSL_CTX *ssl_ctx = ssl_ctx_new(SSL_SERVER_VERIFY_LATER, 5);
    return ssl_ctx;
}
Beispiel #9
0
/**
 * Implement the SSL server logic.
 */
static void do_server(int argc, char *argv[])
{
    int i = 2;
    uint16_t port = 4433;
    uint32_t options = SSL_DISPLAY_CERTS;
    int client_fd;
    SSL_CTX *ssl_ctx;
    int server_fd, res = 0;
    socklen_t client_len;
#ifndef CONFIG_SSL_SKELETON_MODE
    char *private_key_file = NULL;
    const char *password = NULL;
    char **cert;
    int cert_index = 0;
    int cert_size = ssl_get_config(SSL_MAX_CERT_CFG_OFFSET);
#endif
#ifdef WIN32
    char yes = 1;
#else
    int yes = 1;
#endif
    struct sockaddr_in serv_addr;
    struct sockaddr_in client_addr;
    int quiet = 0;
#ifdef CONFIG_SSL_CERT_VERIFICATION
    int ca_cert_index = 0;
    int ca_cert_size = ssl_get_config(SSL_MAX_CA_CERT_CFG_OFFSET);
    char **ca_cert = (char **)calloc(1, sizeof(char *)*ca_cert_size);
#endif
    fd_set read_set;

#ifndef CONFIG_SSL_SKELETON_MODE
    cert = (char **)calloc(1, sizeof(char *)*cert_size);
#endif

    while (i < argc) {
        if (strcmp(argv[i], "-accept") == 0)  {
            if (i >= argc - 1)  {
                print_server_options(argv[i]);
            }

            port = atoi(argv[++i]);
        }
#ifndef CONFIG_SSL_SKELETON_MODE
        else if (strcmp(argv[i], "-cert") == 0) {
            if (i >= argc - 1 || cert_index >= cert_size) {
                print_server_options(argv[i]);
            }

            cert[cert_index++] = argv[++i];
        } else if (strcmp(argv[i], "-key") == 0) {
            if (i >= argc - 1) {
                print_server_options(argv[i]);
            }

            private_key_file = argv[++i];
            options |= SSL_NO_DEFAULT_KEY;
        } else if (strcmp(argv[i], "-pass") == 0) {
            if (i >= argc - 1) {
                print_server_options(argv[i]);
            }

            password = argv[++i];
        }
#endif
        else if (strcmp(argv[i], "-quiet") == 0) {
            quiet = 1;
            options &= ~SSL_DISPLAY_CERTS;
        }
#ifdef CONFIG_SSL_CERT_VERIFICATION
        else if (strcmp(argv[i], "-verify") == 0) {
            options |= SSL_CLIENT_AUTHENTICATION;
        } else if (strcmp(argv[i], "-CAfile") == 0)  {
            if (i >= argc - 1 || ca_cert_index >= ca_cert_size) {
                print_server_options(argv[i]);
            }

            ca_cert[ca_cert_index++] = argv[++i];
        }
#endif
#ifdef CONFIG_SSL_FULL_MODE
        else if (strcmp(argv[i], "-debug") == 0)  {
            options |= SSL_DISPLAY_BYTES;
        } else if (strcmp(argv[i], "-state") == 0) {
            options |= SSL_DISPLAY_STATES;
        } else if (strcmp(argv[i], "-show-rsa") == 0) {
            options |= SSL_DISPLAY_RSA;
        }
#endif
        else  {
            /* don't know what this is */
            print_server_options(argv[i]);
        }

        i++;
    }

    if ((ssl_ctx = ssl_ctx_new(options, SSL_DEFAULT_SVR_SESS)) == NULL)  {
        fprintf(stderr, "Error: Server context is invalid\n");
        exit(1);
    }

#ifndef CONFIG_SSL_SKELETON_MODE
    if (private_key_file)   {
        int obj_type = SSL_OBJ_RSA_KEY;

        /* auto-detect the key type from the file extension */
        if (strstr(private_key_file, ".p8")) {
            obj_type = SSL_OBJ_PKCS8;
        } else if (strstr(private_key_file, ".p12")) {
            obj_type = SSL_OBJ_PKCS12;
        }

        if (ssl_obj_load(ssl_ctx, obj_type, private_key_file, password)) {
            fprintf(stderr, "Error: Private key '%s' is undefined.\n",
                    private_key_file);
            exit(1);
        }
    }

    for (i = 0; i < cert_index; i++)  {
        if (ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CERT, cert[i], NULL)) {
            printf("Certificate '%s' is undefined.\n", cert[i]);
            exit(1);
        }
    }
#endif

#ifdef CONFIG_SSL_CERT_VERIFICATION
    for (i = 0; i < ca_cert_index; i++) {
        if (ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, ca_cert[i], NULL)) {
            printf("Certificate '%s' is undefined.\n", ca_cert[i]);
            exit(1);
        }
    }

    free(ca_cert);
#endif
#ifndef CONFIG_SSL_SKELETON_MODE
    free(cert);
#endif

    /* Create socket for incoming connections */
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("socket");
        return;
    }

    setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));

    /* Construct local address structure */
    memset(&serv_addr, 0, sizeof(serv_addr));      /* Zero out structure */
    serv_addr.sin_family = AF_INET;                /* Internet address family */
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
    serv_addr.sin_port = htons(port);              /* Local port */

    /* Bind to the local address */
    if (bind(server_fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)    {
        perror("bind");
        exit(1);
    }

    if (listen(server_fd, 5) < 0)    {
        perror("listen");
        exit(1);
    }

    client_len = sizeof(client_addr);

    /*************************************************************************
     * This is where the interesting stuff happens. Up until now we've
     * just been setting up sockets etc. Now we do the SSL handshake.
     *************************************************************************/
    for (;;)    {
        SSL *ssl;
        int reconnected = 0;

        if (!quiet)        {
            printf("ACCEPT\n");
            TTY_FLUSH();
        }

        if ((client_fd = accept(server_fd,
                                (struct sockaddr *)&client_addr, &client_len)) < 0)        {
            break;
        }

        ssl = ssl_server_new(ssl_ctx, client_fd);

        /* now read (and display) whatever the client sends us */
        for (;;)        {
            /* allow parallel reading of client and standard input */
            FD_ZERO(&read_set);
            FD_SET(client_fd, &read_set);

#ifndef WIN32
            /* win32 doesn't like mixing up stdin and sockets */
            if (isatty(STDIN_FILENO)) { /* but only if we are in an active shell */
                FD_SET(STDIN_FILENO, &read_set);
            }

            if ((res = select(client_fd + 1, &read_set, NULL, NULL, NULL)) > 0)  {
                uint8_t buf[1024];

                /* read standard input? */
                if (FD_ISSET(STDIN_FILENO, &read_set))  {
                    if (fgets((char *)buf, sizeof(buf), stdin) == NULL) {
                        res = SSL_ERROR_CONN_LOST;
                    } else {
                        /* small hack to check renegotiation */
                        if (buf[0] == 'r' && (buf[1] == '\n' || buf[1] == '\r')) {
                            res = ssl_renegotiate(ssl);
                        }  else  {
                            /* write our ramblings to the client */
                            res = ssl_write(ssl, buf, strlen((char *)buf) + 1);
                        }
                    }
                } else  /* a socket read */
#endif
                {
                    /* keep reading until we get something interesting */
                    uint8_t *read_buf;

                    if ((res = ssl_read(ssl, &read_buf)) == SSL_OK) {
                        /* are we in the middle of doing a handshake? */
                        if (ssl_handshake_status(ssl) != SSL_OK) {
                            reconnected = 0;
                        } else if (!reconnected) {
                            /* we are connected/reconnected */
                            if (!quiet) {
                                display_session_id(ssl);
                                display_cipher(ssl);
                            }

                            reconnected = 1;
                        }
                    }

                    if (res > SSL_OK) {  /* display our interesting output */
                        int written = 0;
                        while (written < res) {
                            written += write(STDOUT_FILENO, read_buf + written,
                                             res - written);
                        }
                        TTY_FLUSH();
                    } else if (res == SSL_CLOSE_NOTIFY) {
                        printf("shutting down SSL\n");
                        TTY_FLUSH();
                    } else if (res < SSL_OK && !quiet) {
                        ssl_display_error(res);
                    }
                }
#ifndef WIN32
            }
#endif

            if (res < SSL_OK)  {
                if (!quiet)  {
                    printf("CONNECTION CLOSED\n");
                    TTY_FLUSH();
                }

                break;
            }
        }

        /* client was disconnected or the handshake failed. */
        ssl_free(ssl);
        SOCKET_CLOSE(client_fd);
    }

    ssl_ctx_free(ssl_ctx);
}
Beispiel #10
0
/**
 * Implement the SSL client logic.
 */
static void do_client(int argc, char *argv[])
{
#ifdef CONFIG_SSL_ENABLE_CLIENT
    int res, i = 2;
    uint16_t port = 4433;
    uint32_t options = SSL_SERVER_VERIFY_LATER | SSL_DISPLAY_CERTS;
    int client_fd;
    char *private_key_file = NULL;
    struct sockaddr_in client_addr;
    struct hostent *hostent;
    int reconnect = 0;
    uint32_t sin_addr;
    SSL_CTX *ssl_ctx;
    SSL *ssl = NULL;
    int quiet = 0;
    int cert_index = 0, ca_cert_index = 0;
    int cert_size, ca_cert_size;
    char **ca_cert, **cert;
    uint8_t session_id[SSL_SESSION_ID_SIZE];
    fd_set read_set;
    const char *password = NULL;

    FD_ZERO(&read_set);
    sin_addr = inet_addr("127.0.0.1");
    cert_size = ssl_get_config(SSL_MAX_CERT_CFG_OFFSET);
    ca_cert_size = ssl_get_config(SSL_MAX_CA_CERT_CFG_OFFSET);
    ca_cert = (char **)calloc(1, sizeof(char *)*ca_cert_size);
    cert = (char **)calloc(1, sizeof(char *)*cert_size);

    while (i < argc) {
        if (strcmp(argv[i], "-connect") == 0)        {
            char *host, *ptr;

            if (i >= argc - 1) {
                print_client_options(argv[i]);
            }

            host = argv[++i];
            if ((ptr = strchr(host, ':')) == NULL) {
                print_client_options(argv[i]);
            }

            *ptr++ = 0;
            port = atoi(ptr);
            hostent = gethostbyname(host);

            if (hostent == NULL) {
                print_client_options(argv[i]);
            }

            sin_addr = *((uint32_t **)hostent->h_addr_list)[0];
        } else if (strcmp(argv[i], "-cert") == 0) {
            if (i >= argc - 1 || cert_index >= cert_size) {
                print_client_options(argv[i]);
            }

            cert[cert_index++] = argv[++i];
        } else if (strcmp(argv[i], "-key") == 0) {
            if (i >= argc - 1) {
                print_client_options(argv[i]);
            }

            private_key_file = argv[++i];
            options |= SSL_NO_DEFAULT_KEY;
        } else if (strcmp(argv[i], "-CAfile") == 0) {
            if (i >= argc - 1 || ca_cert_index >= ca_cert_size) {
                print_client_options(argv[i]);
            }

            ca_cert[ca_cert_index++] = argv[++i];
        } else if (strcmp(argv[i], "-verify") == 0) {
            options &= ~SSL_SERVER_VERIFY_LATER;
        } else if (strcmp(argv[i], "-reconnect") == 0) {
            reconnect = 4;
        } else if (strcmp(argv[i], "-quiet") == 0) {
            quiet = 1;
            options &= ~SSL_DISPLAY_CERTS;
        } else if (strcmp(argv[i], "-pass") == 0) {
            if (i >= argc - 1) {
                print_client_options(argv[i]);
            }

            password = argv[++i];
        }
#ifdef CONFIG_SSL_FULL_MODE
        else if (strcmp(argv[i], "-debug") == 0)  {
            options |= SSL_DISPLAY_BYTES;
        } else if (strcmp(argv[i], "-state") == 0)  {
            options |= SSL_DISPLAY_STATES;
        } else if (strcmp(argv[i], "-show-rsa") == 0) {
            options |= SSL_DISPLAY_RSA;
        }
#endif
        else  {
            /* don't know what this is */
            print_client_options(argv[i]);
        }

        i++;
    }

    if ((ssl_ctx = ssl_ctx_new(options, SSL_DEFAULT_CLNT_SESS)) == NULL) {
        fprintf(stderr, "Error: Client context is invalid\n");
        exit(1);
    }

    if (private_key_file)  {
        int obj_type = SSL_OBJ_RSA_KEY;

        /* auto-detect the key type from the file extension */
        if (strstr(private_key_file, ".p8")) {
            obj_type = SSL_OBJ_PKCS8;
        } else if (strstr(private_key_file, ".p12")) {
            obj_type = SSL_OBJ_PKCS12;
        }

        if (ssl_obj_load(ssl_ctx, obj_type, private_key_file, password))  {
            fprintf(stderr, "Error: Private key '%s' is undefined.\n",
                    private_key_file);
            exit(1);
        }
    }

    for (i = 0; i < cert_index; i++) {
        if (ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CERT, cert[i], NULL)) {
            printf("Certificate '%s' is undefined.\n", cert[i]);
            exit(1);
        }
    }
    for (i = 0; i < ca_cert_index; i++) {
        if (ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, ca_cert[i], NULL)) {
            printf("Certificate '%s' is undefined.\n", ca_cert[i]);
            exit(1);
        }
    }


    free(cert);
    free(ca_cert);

    /*************************************************************************
     * This is where the interesting stuff happens. Up until now we've
     * just been setting up sockets etc. Now we do the SSL handshake.
     *************************************************************************/
    client_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    memset(&client_addr, 0, sizeof(client_addr));
    client_addr.sin_family = AF_INET;
    client_addr.sin_port = htons(port);
    client_addr.sin_addr.s_addr = sin_addr;

    if (connect(client_fd, (struct sockaddr *)&client_addr,
                sizeof(client_addr)) < 0) {
        perror("connect");
        exit(1);
    }

    if (!quiet) {
        printf("CONNECTED\n");
        TTY_FLUSH();
    }

    /* Try session resumption? */
    if (reconnect) {
        while (reconnect--) {
            ssl = ssl_client_new(ssl_ctx, client_fd, session_id,
                                 sizeof(session_id));
            if ((res = ssl_handshake_status(ssl)) != SSL_OK) {
                if (!quiet) {
                    ssl_display_error(res);
                }

                ssl_free(ssl);
                exit(1);
            }

            display_session_id(ssl);
            memcpy(session_id, ssl_get_session_id(ssl), SSL_SESSION_ID_SIZE);

            if (reconnect) {
                ssl_free(ssl);
                SOCKET_CLOSE(client_fd);

                client_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
                connect(client_fd, (struct sockaddr *)&client_addr,
                        sizeof(client_addr));
            }
        }
    } else {
        ssl = ssl_client_new(ssl_ctx, client_fd, NULL, 0);
    }

    /* check the return status */
    if ((res = ssl_handshake_status(ssl)) != SSL_OK) {
        if (!quiet) {
            ssl_display_error(res);
        }

        exit(1);
    }

    if (!quiet) {
        const char *common_name = ssl_get_cert_dn(ssl,
                                  SSL_X509_CERT_COMMON_NAME);
        if (common_name) {
            printf("Common Name:\t\t\t%s\n", common_name);
        }

        display_session_id(ssl);
        display_cipher(ssl);
    }

    for (;;) {
        uint8_t buf[1024];

        /* allow parallel reading of server and standard input */
        FD_SET(client_fd, &read_set);
#ifndef WIN32
        /* win32 doesn't like mixing up stdin and sockets */
        FD_SET(STDIN_FILENO, &read_set);

        if ((res = select(client_fd + 1, &read_set, NULL, NULL, NULL)) > 0) {
            /* read standard input? */
            if (FD_ISSET(STDIN_FILENO, &read_set))
#endif
            {
                if (fgets((char *)buf, sizeof(buf), stdin) == NULL) {
                    /* bomb out of here */
                    ssl_free(ssl);
                    break;
                } else {
                    /* small hack to check renegotiation */
                    if (buf[0] == 'R' && (buf[1] == '\n' || buf[1] == '\r')) {
                        res = ssl_renegotiate(ssl);
                    } else {
                        res = ssl_write(ssl, buf, strlen((char *)buf));
                    }
                }
            }
#ifndef WIN32
            else {  /* a socket read */
                uint8_t *read_buf;

                res = ssl_read(ssl, &read_buf);

                if (res > 0) {  /* display our interesting output */
                    int written = 0;
                    while (written < res) {
                        written += write(STDOUT_FILENO, read_buf + written,
                                         res - written);
                    }
                    TTY_FLUSH();
                }
            }
        }
#endif

        if (res < 0) {
            if (!quiet) {
                ssl_display_error(res);
            }

            break;      /* get outta here */
        }
    }

    ssl_ctx_free(ssl_ctx);
    SOCKET_CLOSE(client_fd);
#else
    print_client_options(argv[1]);
#endif
}