Exemple #1
0
PUBLIC int sslUpgrade(Webs *wp)
{
    EstSocket   *est;
    WebsSocket  *sp;

    assert(wp);
    if ((est = malloc(sizeof(EstSocket))) == 0) {
        return -1;
    }
    wp->ssl = est;

    ssl_free(&est->ctx);
    havege_init(&est->hs);
    ssl_init(&est->ctx);
	ssl_set_endpoint(&est->ctx, 1);

	ssl_set_authmode(&est->ctx, BIT_GOAHEAD_VERIFY_PEER ? SSL_VERIFY_OPTIONAL : SSL_VERIFY_NO_CHECK);
    ssl_set_rng(&est->ctx, havege_rand, &est->hs);
	ssl_set_dbg(&est->ctx, estTrace, NULL);
    sp = socketPtr(wp->sid);
	ssl_set_bio(&est->ctx, net_recv, &sp->sock, net_send, &sp->sock);
    ssl_set_ciphers(&est->ctx, estConfig.ciphers);
	ssl_set_session(&est->ctx, 1, 0, &est->session);
	memset(&est->session, 0, sizeof(ssl_session));

	ssl_set_ca_chain(&est->ctx, *BIT_GOAHEAD_CA ? &estConfig.ca : NULL, NULL);
    if (*BIT_GOAHEAD_CERTIFICATE && *BIT_GOAHEAD_KEY) {
        ssl_set_own_cert(&est->ctx, &estConfig.cert, &estConfig.rsa);
    }
	ssl_set_dh_param(&est->ctx, dhKey, dhg);

    if (estHandshake(wp) < 0) {
        return -1;
    }
    return 0;
}
Exemple #2
0
static CURLcode
polarssl_connect_step1(struct connectdata *conn,
                     int sockindex)
{
  struct SessionHandle *data = conn->data;
  struct ssl_connect_data* connssl = &conn->ssl[sockindex];

  bool sni = TRUE; /* default is SNI enabled */
  int ret = -1;
#ifdef ENABLE_IPV6
  struct in6_addr addr;
#else
  struct in_addr addr;
#endif
  void *old_session = NULL;
  size_t old_session_size = 0;

  char errorbuf[128];
  memset(errorbuf, 0, sizeof(errorbuf));


  /* PolarSSL only supports SSLv3 and TLSv1 */
  if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
    failf(data, "PolarSSL does not support SSLv2");
    return CURLE_SSL_CONNECT_ERROR;
  }
  else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3)
    sni = FALSE; /* SSLv3 has no SNI */

#if POLARSSL_VERSION_NUMBER<0x01010000
  havege_init(&connssl->hs);
#else
#ifdef THREADING_SUPPORT
  entropy_init_mutex(&entropy);

  if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func_mutex, &entropy,
                               connssl->ssn.id, connssl->ssn.length)) != 0) {
#ifdef POLARSSL_ERROR_C
     error_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* POLARSSL_ERROR_C */
     failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n",
                                                            -ret, errorbuf);
  }
#else
  entropy_init(&connssl->entropy);

  if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func, &connssl->entropy,
                                connssl->ssn.id, connssl->ssn.length)) != 0) {
#ifdef POLARSSL_ERROR_C
     error_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* POLARSSL_ERROR_C */
     failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n",
                                                            -ret, errorbuf);
  }
#endif /* THREADING_SUPPORT */
#endif /* POLARSSL_VERSION_NUMBER<0x01010000 */

  /* Load the trusted CA */
  memset(&connssl->cacert, 0, sizeof(x509_cert));

  if(data->set.str[STRING_SSL_CAFILE]) {
    ret = x509parse_crtfile(&connssl->cacert,
                            data->set.str[STRING_SSL_CAFILE]);

    if(ret<0) {
#ifdef POLARSSL_ERROR_C
      error_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* POLARSSL_ERROR_C */
      failf(data, "Error reading ca cert file %s - PolarSSL: (-0x%04X) %s",
            data->set.str[STRING_SSL_CAFILE], -ret, errorbuf);

      if(data->set.ssl.verifypeer)
        return CURLE_SSL_CACERT_BADFILE;
    }
  }

  /* Load the client certificate */
  memset(&connssl->clicert, 0, sizeof(x509_cert));

  if(data->set.str[STRING_CERT]) {
    ret = x509parse_crtfile(&connssl->clicert,
                            data->set.str[STRING_CERT]);

    if(ret) {
#ifdef POLARSSL_ERROR_C
      error_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* POLARSSL_ERROR_C */
      failf(data, "Error reading client cert file %s - PolarSSL: (-0x%04X) %s",
            data->set.str[STRING_CERT], -ret, errorbuf);

      return CURLE_SSL_CERTPROBLEM;
    }
  }

  /* Load the client private key */
  if(data->set.str[STRING_KEY]) {
    ret = x509parse_keyfile(&connssl->rsa,
                            data->set.str[STRING_KEY],
                            data->set.str[STRING_KEY_PASSWD]);

    if(ret) {
#ifdef POLARSSL_ERROR_C
      error_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* POLARSSL_ERROR_C */
      failf(data, "Error reading private key %s - PolarSSL: (-0x%04X) %s",
            data->set.str[STRING_KEY], -ret, errorbuf);

      return CURLE_SSL_CERTPROBLEM;
    }
  }

  /* Load the CRL */
  memset(&connssl->crl, 0, sizeof(x509_crl));

  if(data->set.str[STRING_SSL_CRLFILE]) {
    ret = x509parse_crlfile(&connssl->crl,
                            data->set.str[STRING_SSL_CRLFILE]);

    if(ret) {
#ifdef POLARSSL_ERROR_C
      error_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* POLARSSL_ERROR_C */
      failf(data, "Error reading CRL file %s - PolarSSL: (-0x%04X) %s",
            data->set.str[STRING_SSL_CRLFILE], -ret, errorbuf);

      return CURLE_SSL_CRL_BADFILE;
    }
  }

  infof(data, "PolarSSL: Connecting to %s:%d\n",
        conn->host.name, conn->remote_port);

  if(ssl_init(&connssl->ssl)) {
    failf(data, "PolarSSL: ssl_init failed");
    return CURLE_SSL_CONNECT_ERROR;
  }

  ssl_set_endpoint(&connssl->ssl, SSL_IS_CLIENT);
  ssl_set_authmode(&connssl->ssl, SSL_VERIFY_OPTIONAL);

#if POLARSSL_VERSION_NUMBER<0x01010000
  ssl_set_rng(&connssl->ssl, havege_rand,
              &connssl->hs);
#else
  ssl_set_rng(&connssl->ssl, ctr_drbg_random,
              &connssl->ctr_drbg);
#endif /* POLARSSL_VERSION_NUMBER<0x01010000 */
  ssl_set_bio(&connssl->ssl,
              net_recv, &conn->sock[sockindex],
              net_send, &conn->sock[sockindex]);


#if POLARSSL_VERSION_NUMBER<0x01000000
  ssl_set_ciphers(&connssl->ssl, ssl_default_ciphers);
#else
  ssl_set_ciphersuites(&connssl->ssl, ssl_default_ciphersuites);
#endif
  if(!Curl_ssl_getsessionid(conn, &old_session, &old_session_size)) {
    memcpy(&connssl->ssn, old_session, old_session_size);
    infof(data, "PolarSSL re-using session\n");
  }

/* PolarSSL SVN revision r1316 to r1317, matching <1.2.0 is to cover Ubuntu's
   1.1.4 version and the like */
#if POLARSSL_VERSION_NUMBER<0x01020000
  ssl_set_session(&connssl->ssl, 1, 600,
                  &connssl->ssn);
#else
  ssl_set_session(&connssl->ssl,
                  &connssl->ssn);
#endif

  ssl_set_ca_chain(&connssl->ssl,
                   &connssl->cacert,
                   &connssl->crl,
                   conn->host.name);

  ssl_set_own_cert(&connssl->ssl,
                   &connssl->clicert, &connssl->rsa);

  if(!Curl_inet_pton(AF_INET, conn->host.name, &addr) &&
#ifdef ENABLE_IPV6
     !Curl_inet_pton(AF_INET6, conn->host.name, &addr) &&
#endif
     sni && ssl_set_hostname(&connssl->ssl, conn->host.name)) {
     infof(data, "WARNING: failed to configure "
                 "server name indication (SNI) TLS extension\n");
  }

#ifdef POLARSSL_DEBUG
  ssl_set_dbg(&connssl->ssl, polarssl_debug, data);
#endif

  connssl->connecting_state = ssl_connect_2;

  return CURLE_OK;
}
Exemple #3
0
tcpcon_t *
tcp_connect(const char *hostname, int port, char *errbuf, size_t errbufsize,
	    int timeout, int ssl)
{
  struct net_hostent *hp;
  char *tmphstbuf;
  int fd, r, err, herr, optval;
  const char *errtxt;
  struct sockaddr_in in;
  socklen_t errlen = sizeof(int);


  if(!strcmp(hostname, "localhost")) {
    if((fd = getstreamsocket(AF_INET, errbuf, errbufsize)) == -1)
      return NULL;

    memset(&in, 0, sizeof(in));
    in.sin_family = AF_INET;
    in.sin_port = htons(port);
    in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    r = netConnect(fd, (struct sockaddr *)&in, sizeof(struct sockaddr_in));
  } else {

    herr = 0;
    tmphstbuf = NULL; /* free NULL is a nop */
    hp = netGetHostByName(hostname);
    if(hp == NULL)
      herr = h_errno;

    if(herr != 0) {
      switch(herr) {
      case HOST_NOT_FOUND:
	errtxt = "Unknown host";
	break;

      case NO_ADDRESS:
	errtxt = "The requested name is valid but does not have an IP address";
	break;
      
      case NO_RECOVERY:
	errtxt = "A non-recoverable name server error occurred";
	break;
      
      case TRY_AGAIN:
	errtxt = "A temporary error occurred on an authoritative name server";
	break;
      
      default:
	errtxt = "Unknown error";
	break;
      }

      snprintf(errbuf, errbufsize, "%s", errtxt);
      free(tmphstbuf);
      return NULL;
    } else if(hp == NULL) {
      snprintf(errbuf, errbufsize, "Resolver internal error");
      free(tmphstbuf);
      return NULL;
    }

    if((fd = getstreamsocket(hp->h_addrtype, errbuf, errbufsize)) == -1) {
      free(tmphstbuf);
      return NULL;
    }

    switch(hp->h_addrtype) {
    case AF_INET:
      memset(&in, 0, sizeof(in));
      in.sin_family = AF_INET;
      in.sin_port = htons(port);
      lv2_void* netaddrlist = (lv2_void*)(u64)hp->h_addr_list;
      memcpy(&in.sin_addr, (char*)(u64)netaddrlist[0], sizeof(struct in_addr));
      r = netConnect(fd, (struct sockaddr *)&in, sizeof(struct sockaddr_in));
      break;

    default:
      snprintf(errbuf, errbufsize, "Invalid protocol family");
      free(tmphstbuf);
      return NULL;
    }

    free(tmphstbuf);
  }

  if(r < 0) {
    if(net_errno == NET_EINPROGRESS) {

      struct pollfd pfd;
      pfd.fd = fd;
      pfd.events = POLLOUT;
      pfd.revents = 0;

      r = netPoll(&pfd, 1, timeout);
      if(r == 0) {
	/* Timeout */
	snprintf(errbuf, errbufsize, "Connection attempt timed out");
	netClose(fd);
	return NULL;
      }
      
      if(r == -1) {
	snprintf(errbuf, errbufsize, "poll() error: %s", 
		 strerror(net_errno));
	netClose(fd);
	return NULL;
      }

      netGetSockOpt(fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen);
    } else {
      err = net_errno;
    }
  } else {
    err = 0;
  }

  if(err != 0) {
    snprintf(errbuf, errbufsize, "%s", strerror(err));
    netClose(fd);
    return NULL;
  }
  
  optval = 0;
  r = netSetSockOpt(fd, SOL_SOCKET, SO_NBIO, &optval, sizeof(optval));
  if(r < 0) {
    snprintf(errbuf, errbufsize, "Unable to go blocking: %s",
	     strerror(net_errno));
    netClose(fd);
    return NULL;
  }

  tcpcon_t *tc = calloc(1, sizeof(tcpcon_t));
  tc->fd = fd;
  htsbuf_queue_init(&tc->spill, 0);


  if(ssl) {
#if ENABLE_POLARSSL
    if(1) {
      tc->ssl = malloc(sizeof(ssl_context));
      if(ssl_init(tc->ssl)) {
	snprintf(errbuf, errlen, "SSL failed to initialize");
	close(fd);
	free(tc->ssl);
	free(tc);
	return NULL;
      }

      tc->ssn = malloc(sizeof(ssl_session));
      tc->hs = malloc(sizeof(havege_state));

      havege_init(tc->hs);
      memset(tc->ssn, 0, sizeof(ssl_session));


      ssl_set_endpoint(tc->ssl, SSL_IS_CLIENT );
      ssl_set_authmode(tc->ssl, SSL_VERIFY_NONE );

      ssl_set_rng(tc->ssl, havege_rand, tc->hs );
      ssl_set_bio(tc->ssl, net_recv, &tc->fd, net_send, &tc->fd);
      ssl_set_ciphers(tc->ssl, ssl_default_ciphers );
      ssl_set_session(tc->ssl, 1, 600, tc->ssn );
      
      tc->read = polarssl_read;
      tc->write = polarssl_write;
      
    } else
#endif
    {

      snprintf(errbuf, errlen, "SSL not supported");
      tcp_close(tc);
      return NULL;
    }
  } else {
    tc->read = tcp_read;
    tc->write = tcp_write;
  }

  return tc;
}
int main(void)
{
    int ret, len, server_fd = -1;
    unsigned char buf[1024];
    havege_state hs;
    ssl_context ssl;
    ssl_session ssn;

    /*
     * 0. Initialize the RNG and the session data
     */
    havege_init(&hs);
    memset(&ssl, 0, sizeof(ssl));
    memset(&ssn, 0, sizeof(ssl_session));

    /*
     * 1. Start the connection
     */
    printf("\n  . Connecting to tcp/%s/%4d...", SERVER_NAME, SERVER_PORT);
    fflush(stdout);

    if ((ret = net_connect(&server_fd, SERVER_NAME, SERVER_PORT)) != 0) {
        printf(" failed\n  ! net_connect returned %d\n\n", ret);
        goto exit;
    }

    printf(" ok\n");

    /*
     * 2. Setup stuff
     */
    printf("  . Setting up the SSL/TLS structure...");
    fflush(stdout);

    if ((ret = ssl_init(&ssl)) != 0) {
        printf(" failed\n  ! ssl_init returned %d\n\n", ret);
        goto exit;
    }

    printf(" ok\n");

    ssl_set_endpoint(&ssl, SSL_IS_CLIENT);
    ssl_set_authmode(&ssl, SSL_VERIFY_NONE);

    ssl_set_rng(&ssl, havege_rand, &hs);
    ssl_set_dbg(&ssl, my_debug, stdout);
    ssl_set_bio(&ssl, net_recv, &server_fd, net_send, &server_fd);

    ssl_set_ciphers(&ssl, ssl_default_ciphers);
    ssl_set_session(&ssl, 1, 600, &ssn);

    /*
     * 3. Write the GET request
     */
    printf("  > Write to server:");
    fflush(stdout);

    len = sprintf((char *)buf, GET_REQUEST);

    while ((ret = ssl_write(&ssl, buf, len)) <= 0) {
        if (ret != TROPICSSL_ERR_NET_TRY_AGAIN) {
            printf(" failed\n  ! ssl_write returned %d\n\n", ret);
            goto exit;
        }
    }

    len = ret;
    printf(" %d bytes written\n\n%s", len, (char *)buf);

    /*
     * 7. Read the HTTP response
     */
    printf("  < Read from server:");
    fflush(stdout);

    do {
        len = sizeof(buf) - 1;
        memset(buf, 0, sizeof(buf));
        ret = ssl_read(&ssl, buf, len);

        if (ret == TROPICSSL_ERR_NET_TRY_AGAIN)
            continue;

        if (ret == TROPICSSL_ERR_SSL_PEER_CLOSE_NOTIFY)
            break;

        if (ret <= 0) {
            printf("failed\n  ! ssl_read returned %d\n\n", ret);
            break;
        }

        len = ret;
        printf(" %d bytes read\n\n%s", len, (char *)buf);
    }
    while (0);

    ssl_close_notify(&ssl);

exit:
    net_close(server_fd);
    ssl_free(&ssl);

    memset(&ssl, 0, sizeof(ssl));

#ifdef WIN32
    printf("  + Press Enter to exit this program.\n");
    fflush(stdout);
    getchar();
#endif

    return (ret);
}
Exemple #5
0
int main( void )
{
    int ret, len;
    int listen_fd;
    int client_fd;
    unsigned char buf[1024];

    havege_state hs;
    ssl_context ssl;
    ssl_session ssn;
    x509_cert srvcert;
    rsa_context rsa;

    /*
     * 1. Load the certificates and private RSA key
     */
    printf( "\n  . Loading the server cert. and key..." );
    fflush( stdout );

    memset( &srvcert, 0, sizeof( x509_cert ) );

    /*
     * This demonstration program uses embedded test certificates.
     * Instead, you may want to use x509parse_crtfile() to read the
     * server and CA certificates, as well as x509parse_keyfile().
     */
    ret = x509parse_crt( &srvcert, (unsigned char *) test_srv_crt,
                         strlen( test_srv_crt ) );
    if( ret != 0 )
    {
        printf( " failed\n  !  x509parse_crt returned %d\n\n", ret );
        goto exit;
    }

    ret = x509parse_crt( &srvcert, (unsigned char *) test_ca_crt,
                         strlen( test_ca_crt ) );
    if( ret != 0 )
    {
        printf( " failed\n  !  x509parse_crt returned %d\n\n", ret );
        goto exit;
    }

    ret =  x509parse_key( &rsa, (unsigned char *) test_srv_key,
                          strlen( test_srv_key ), NULL, 0 );
    if( ret != 0 )
    {
        printf( " failed\n  !  x509parse_key returned %d\n\n", ret );
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 2. Setup the listening TCP socket
     */
    printf( "  . Bind on https://localhost:4433/ ..." );
    fflush( stdout );

    if( ( ret = net_bind( &listen_fd, NULL, 4433 ) ) != 0 )
    {
        printf( " failed\n  ! net_bind returned %d\n\n", ret );
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 3. Wait until a client connects
     */
#ifdef WIN32
    ShellExecute( NULL, "open", "https://localhost:4433/",
                  NULL, NULL, SW_SHOWNORMAL );
#endif

    client_fd = -1;
    memset( &ssl, 0, sizeof( ssl ) );

accept:

    net_close( client_fd );
    ssl_free( &ssl );

    printf( "  . Waiting for a remote connection ..." );
    fflush( stdout );

    if( ( ret = net_accept( listen_fd, &client_fd, NULL ) ) != 0 )
    {
        printf( " failed\n  ! net_accept returned %d\n\n", ret );
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 4. Setup stuff
     */
    printf( "  . Setting up the RNG and SSL data...." );
    fflush( stdout );

    havege_init( &hs );

    if( ( ret = ssl_init( &ssl ) ) != 0 )
    {
        printf( " failed\n  ! ssl_init returned %d\n\n", ret );
        goto accept;
    }

    printf( " ok\n" );

    ssl_set_endpoint( &ssl, SSL_IS_SERVER );
    ssl_set_authmode( &ssl, SSL_VERIFY_NONE );

    ssl_set_rng( &ssl, havege_rand, &hs );
    ssl_set_dbg( &ssl, my_debug, stdout );
    ssl_set_bio( &ssl, net_recv, &client_fd,
                       net_send, &client_fd );
    ssl_set_scb( &ssl, my_get_session,
                       my_set_session );

    ssl_set_ciphers( &ssl, my_ciphers );
    ssl_set_session( &ssl, 1, 0, &ssn );

    memset( &ssn, 0, sizeof( ssl_session ) );

    ssl_set_ca_chain( &ssl, srvcert.next, NULL, NULL );
    ssl_set_own_cert( &ssl, &srvcert, &rsa );
    ssl_set_dh_param( &ssl, my_dhm_P, my_dhm_G );

    /*
     * 5. Handshake
     */
    printf( "  . Performing the SSL/TLS handshake..." );
    fflush( stdout );

    while( ( ret = ssl_handshake( &ssl ) ) != 0 )
    {
        if( ret != POLARSSL_ERR_NET_TRY_AGAIN )
        {
            printf( " failed\n  ! ssl_handshake returned %d\n\n", ret );
            goto accept;
        }
    }

    printf( " ok\n" );

    /*
     * 6. Read the HTTP Request
     */
    printf( "  < Read from client:" );
    fflush( stdout );

    do
    {
        len = sizeof( buf ) - 1;
        memset( buf, 0, sizeof( buf ) );
        ret = ssl_read( &ssl, buf, len );

        if( ret == POLARSSL_ERR_NET_TRY_AGAIN )
            continue;

        if( ret <= 0 )
        {
            switch( ret )
            {
                case POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY:
                    printf( " connection was closed gracefully\n" );
                    break;

                case POLARSSL_ERR_NET_CONN_RESET:
                    printf( " connection was reset by peer\n" );
                    break;

                default:
                    printf( " ssl_read returned %d\n", ret );
                    break;
            }

            break;
        }

        len = ret;
        printf( " %d bytes read\n\n%s", len, (char *) buf );
    }
    while( 0 );

    /*
     * 7. Write the 200 Response
     */
    printf( "  > Write to client:" );
    fflush( stdout );

    len = sprintf( (char *) buf, HTTP_RESPONSE,
                   ssl_get_cipher( &ssl ) );

    while( ( ret = ssl_write( &ssl, buf, len ) ) <= 0 )
    {
        if( ret == POLARSSL_ERR_NET_CONN_RESET )
        {
            printf( " failed\n  ! peer closed the connection\n\n" );
            goto accept;
        }

        if( ret != POLARSSL_ERR_NET_TRY_AGAIN )
        {
            printf( " failed\n  ! ssl_write returned %d\n\n", ret );
            goto exit;
        }
    }

    len = ret;
    printf( " %d bytes written\n\n%s\n", len, (char *) buf );

    ssl_close_notify( &ssl );
    goto accept;

exit:

    net_close( client_fd );
    x509_free( &srvcert );
    rsa_free( &rsa );
    ssl_free( &ssl );

    cur = s_list_1st;
    while( cur != NULL )
    {
        prv = cur;
        cur = cur->next;
        memset( prv, 0, sizeof( ssl_session ) );
        free( prv );
    }

    memset( &ssl, 0, sizeof( ssl_context ) );

#ifdef WIN32
    printf( "  Press Enter to exit this program.\n" );
    fflush( stdout ); getchar();
#endif

    return( ret );
}
Exemple #6
0
int main( int argc, char *argv[] )
{
    int ret = 0, server_fd;
    unsigned char buf[1024];
    havege_state hs;
    ssl_context ssl;
    ssl_session ssn;
    x509_cert clicert;
    rsa_context rsa;
    int i, j, n;
    char *p, *q;

    if( argc == 0 )
    {
    usage:
        printf( USAGE );
        goto exit;
    }

    opt.mode                = DFL_MODE;
    opt.filename            = DFL_FILENAME;
    opt.server_name         = DFL_SERVER_NAME;
    opt.server_port         = DFL_SERVER_PORT;
    opt.debug_level         = DFL_DEBUG_LEVEL;

    for( i = 1; i < argc; i++ )
    {
        n = strlen( argv[i] );

        for( j = 0; j < n; j++ )
        {
            if( argv[i][j] >= 'A' && argv[i][j] <= 'Z' )
                argv[i][j] |= 0x20;
        }

        p = argv[i];
        if( ( q = strchr( p, '=' ) ) == NULL )
            goto usage;
        *q++ = '\0';

        if( strcmp( p, "mode" ) == 0 )
        {
            if( strcmp( q, "file" ) == 0 )
                opt.mode = MODE_FILE;
            else if( strcmp( q, "ssl" ) == 0 )
                opt.mode = MODE_SSL;
            else
                goto usage;
        }
        else if( strcmp( p, "filename" ) == 0 )
            opt.filename = q;
        else if( strcmp( p, "server_name" ) == 0 )
            opt.server_name = q;
        else if( strcmp( p, "server_port" ) == 0 )
        {
            opt.server_port = atoi( q );
            if( opt.server_port < 1 || opt.server_port > 65535 )
                goto usage;
        }
        else if( strcmp( p, "debug_level" ) == 0 )
        {
            opt.debug_level = atoi( q );
            if( opt.debug_level < 0 || opt.debug_level > 65535 )
                goto usage;
        }
        else
            goto usage;
    }

    if( opt.mode == MODE_FILE )
    {
        x509_cert crt;

        memset( &crt, 0, sizeof( x509_cert ) );

        /*
         * 1.1. Load the certificate
         */
        printf( "\n  . Loading the certificate ..." );
        fflush( stdout );

        ret = x509parse_crtfile( &crt, opt.filename );

        if( ret != 0 )
        {
            printf( " failed\n  !  x509parse_crt returned %d\n\n", ret );
            x509_free( &crt );
            goto exit;
        }

        printf( " ok\n" );

        /*
         * 1.2 Print the certificate
         */
        printf( "  . Peer certificate information    ...\n" );
        ret = x509parse_cert_info( (char *) buf, sizeof( buf ) - 1, "      ", &crt );
        if( ret == -1 )
        {
            printf( " failed\n  !  x509parse_cert_info returned %d\n\n", ret );
            x509_free( &crt );
            goto exit;
        }

        printf( "%s\n", buf );

        x509_free( &crt );
    }
    else if( opt.mode == MODE_SSL )
    {
        /*
         * 1. Initialize the RNG and the session data
         */
        havege_init( &hs );
        memset( &ssn, 0, sizeof( ssl_session ) );

        /*
         * 2. Start the connection
         */
        printf( "  . SSL connection to tcp/%s/%-4d...", opt.server_name,
                                                        opt.server_port );
        fflush( stdout );

        if( ( ret = net_connect( &server_fd, opt.server_name,
                                             opt.server_port ) ) != 0 )
        {
            printf( " failed\n  ! net_connect returned %d\n\n", ret );
            goto exit;
        }

        /*
         * 3. Setup stuff
         */
        if( ( ret = ssl_init( &ssl ) ) != 0 )
        {
            printf( " failed\n  ! ssl_init returned %d\n\n", ret );
            goto exit;
        }

        ssl_set_endpoint( &ssl, SSL_IS_CLIENT );
        ssl_set_authmode( &ssl, SSL_VERIFY_NONE );

        ssl_set_rng( &ssl, havege_rand, &hs );
        ssl_set_dbg( &ssl, my_debug, stdout );
        ssl_set_bio( &ssl, net_recv, &server_fd,
                net_send, &server_fd );

        ssl_set_ciphers( &ssl, ssl_default_ciphers );
        ssl_set_session( &ssl, 1, 600, &ssn );

        ssl_set_own_cert( &ssl, &clicert, &rsa );

        ssl_set_hostname( &ssl, opt.server_name );

        /*
         * 4. Handshake
         */
        while( ( ret = ssl_handshake( &ssl ) ) != 0 )
        {
            if( ret != POLARSSL_ERR_NET_TRY_AGAIN )
            {
                printf( " failed\n  ! ssl_handshake returned %d\n\n", ret );
                goto exit;
            }
        }

        printf( " ok\n" );

        /*
         * 5. Print the certificate
         */
        printf( "  . Peer certificate information    ...\n" );
        ret = x509parse_cert_info( (char *) buf, sizeof( buf ) - 1, "      ", ssl.peer_cert );
        if( ret == -1 )
        {
            printf( " failed\n  !  x509parse_cert_info returned %d\n\n", ret );
            goto exit;
        }

        printf( "%s\n", buf );

        ssl_close_notify( &ssl );
    }
    else
        goto usage;

exit:

    net_close( server_fd );
    x509_free( &clicert );
    rsa_free( &rsa );
    ssl_free( &ssl );

    memset( &ssl, 0, sizeof( ssl ) );

#ifdef WIN32
    printf( "  + Press Enter to exit this program.\n" );
    fflush( stdout ); getchar();
#endif

    return( ret );
}
Exemple #7
0
tcpcon_t *
tcp_connect(const char *hostname, int port, char *errbuf, size_t errbufsize,
	    int timeout, int ssl)
{
  struct hostent *hp;
  char *tmphstbuf;
  int fd, val, r, err, herr;
  const char *errtxt;
#if !defined(__APPLE__)
  struct hostent hostbuf;
  size_t hstbuflen;
  int res;
#endif
  struct sockaddr_in6 in6;
  struct sockaddr_in in;
  socklen_t errlen = sizeof(int);


  if(!strcmp(hostname, "localhost")) {
    if((fd = getstreamsocket(AF_INET, errbuf, errbufsize)) == -1)
      return NULL;

    memset(&in, 0, sizeof(in));
    in.sin_family = AF_INET;
    in.sin_port = htons(port);
    in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    r = connect(fd, (struct sockaddr *)&in, sizeof(struct sockaddr_in));
  } else {

#if defined(__APPLE__)
    herr = 0;
    tmphstbuf = NULL; /* free NULL is a nop */
    /* TODO: AF_INET6 */
    hp = gethostbyname(hostname);
    if(hp == NULL)
      herr = h_errno;
#else
    hstbuflen = 1024;
    tmphstbuf = malloc(hstbuflen);

    while((res = gethostbyname_r(hostname, &hostbuf, tmphstbuf, hstbuflen,
				 &hp, &herr)) == ERANGE) {
      hstbuflen *= 2;
      tmphstbuf = realloc(tmphstbuf, hstbuflen);
    }
#endif
    if(herr != 0) {
      switch(herr) {
      case HOST_NOT_FOUND:
	errtxt = "Unknown host";
	break;

      case NO_ADDRESS:
	errtxt = "The requested name is valid but does not have an IP address";
	break;
      
      case NO_RECOVERY:
	errtxt = "A non-recoverable name server error occurred";
	break;
      
      case TRY_AGAIN:
	errtxt = "A temporary error occurred on an authoritative name server";
	break;
      
      default:
	errtxt = "Unknown error";
	break;
      }

      snprintf(errbuf, errbufsize, "%s", errtxt);
      free(tmphstbuf);
      return NULL;
    } else if(hp == NULL) {
      snprintf(errbuf, errbufsize, "Resolver internal error");
      free(tmphstbuf);
      return NULL;
    }

    if((fd = getstreamsocket(hp->h_addrtype, errbuf, errbufsize)) == -1) {
      free(tmphstbuf);
      return NULL;
    }

    switch(hp->h_addrtype) {
    case AF_INET:
      memset(&in, 0, sizeof(in));
      in.sin_family = AF_INET;
      in.sin_port = htons(port);
      memcpy(&in.sin_addr, hp->h_addr_list[0], sizeof(struct in_addr));
      r = connect(fd, (struct sockaddr *)&in, sizeof(struct sockaddr_in));
      break;

    case AF_INET6:
      memset(&in6, 0, sizeof(in6));
      in6.sin6_family = AF_INET6;
      in6.sin6_port = htons(port);
      memcpy(&in6.sin6_addr, hp->h_addr_list[0], sizeof(struct in6_addr));
      r = connect(fd, (struct sockaddr *)&in, sizeof(struct sockaddr_in6));
      break;

    default:
      snprintf(errbuf, errbufsize, "Invalid protocol family");
      free(tmphstbuf);
      return NULL;
    }

    free(tmphstbuf);
  }
  if(r == -1) {
    if(errno == EINPROGRESS) {
      struct pollfd pfd;

      pfd.fd = fd;
      pfd.events = POLLOUT;
      pfd.revents = 0;

      r = poll(&pfd, 1, timeout);
      if(r == 0) {
	/* Timeout */
	snprintf(errbuf, errbufsize, "Connection attempt timed out");
	close(fd);
	return NULL;
      }
      
      if(r == -1) {
	snprintf(errbuf, errbufsize, "poll() error: %s", strerror(errno));
	close(fd);
	return NULL;
      }

      getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen);
    } else {
      err = errno;
    }
  } else {
    err = 0;
  }

  if(err != 0) {
    snprintf(errbuf, errbufsize, "%s", strerror(err));
    close(fd);
    return NULL;
  }
  
  fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK);

  val = 1;
  setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));

  tcpcon_t *tc = calloc(1, sizeof(tcpcon_t));
  tc->fd = fd;
  htsbuf_queue_init(&tc->spill, 0);
  

  if(ssl) {
#if ENABLE_OPENSSL
    if(showtime_ssl_ctx != NULL) {
      char errmsg[120];

      if((tc->ssl = SSL_new(showtime_ssl_ctx)) == NULL) {
	ERR_error_string(ERR_get_error(), errmsg);
	snprintf(errbuf, errlen, "SSL: %s", errmsg);
	tcp_close(tc);
	return NULL;
      }
      if(SSL_set_fd(tc->ssl, tc->fd) == 0) {
	ERR_error_string(ERR_get_error(), errmsg);
	snprintf(errbuf, errlen, "SSL fd: %s", errmsg);
	tcp_close(tc);
	return NULL;
      }

      if(SSL_connect(tc->ssl) <= 0) {
	ERR_error_string(ERR_get_error(), errmsg);
	snprintf(errbuf, errlen, "SSL connect: %s", errmsg);
	tcp_close(tc);
	return NULL;
      }

      SSL_set_mode(tc->ssl, SSL_MODE_AUTO_RETRY);
      tc->read = ssl_read;
      tc->write = ssl_write;
    } else
#elif ENABLE_POLARSSL
    if(1) {
      tc->ssl = malloc(sizeof(ssl_context));
      if(ssl_init(tc->ssl)) {
	snprintf(errbuf, errlen, "SSL failed to initialize");
	close(fd);
	free(tc->ssl);
	free(tc);
	return NULL;
      }

      tc->ssn = malloc(sizeof(ssl_session));
      tc->hs = malloc(sizeof(havege_state));

      havege_init(tc->hs);
      memset(tc->ssn, 0, sizeof(ssl_session));


      ssl_set_endpoint(tc->ssl, SSL_IS_CLIENT );
      ssl_set_authmode(tc->ssl, SSL_VERIFY_NONE );

      ssl_set_rng(tc->ssl, havege_rand, tc->hs );
      ssl_set_bio(tc->ssl, net_recv, &tc->fd, net_send, &tc->fd);
      ssl_set_ciphers(tc->ssl, ssl_default_ciphers );
      ssl_set_session(tc->ssl, 1, 600, tc->ssn );
      
      tc->read = polarssl_read;
      tc->write = polarssl_write;
      
    } else
#endif
    {

      snprintf(errbuf, errlen, "SSL not supported");
      tcp_close(tc);
      return NULL;
    }
  } else {
    tc->read = tcp_read;
    tc->write = tcp_write;
  }

  return tc;
}
Exemple #8
0
/*
 * This function loads all the client/CA certificates and CRLs. Setup the TLS
 * layer and do all necessary magic.
 */
CURLcode
Curl_polarssl_connect(struct connectdata *conn,
                      int sockindex)
{
  struct SessionHandle *data = conn->data;
  bool sni = TRUE; /* default is SNI enabled */
  int ret = -1;
#ifdef ENABLE_IPV6
  struct in6_addr addr;
#else
  struct in_addr addr;
#endif
  void *old_session = NULL;
  size_t old_session_size = 0;
  char buffer[1024];

  if(conn->ssl[sockindex].state == ssl_connection_complete)
    return CURLE_OK;

  /* PolarSSL only supports SSLv3 and TLSv1 */
  if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
    failf(data, "PolarSSL does not support SSLv2");
    return CURLE_SSL_CONNECT_ERROR;
  }
  else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3)
    sni = FALSE; /* SSLv3 has no SNI */

  havege_init(&conn->ssl[sockindex].hs);

  /* Load the trusted CA */
  memset(&conn->ssl[sockindex].cacert, 0, sizeof(x509_cert));

  if(data->set.str[STRING_SSL_CAFILE]) {
    ret = x509parse_crtfile(&conn->ssl[sockindex].cacert,
                            data->set.str[STRING_SSL_CAFILE]);

    if(ret) {
      failf(data, "Error reading ca cert file %s: -0x%04X",
            data->set.str[STRING_SSL_CAFILE], -ret);

      if(data->set.ssl.verifypeer)
        return CURLE_SSL_CACERT_BADFILE;
    }
  }

  /* Load the client certificate */
  memset(&conn->ssl[sockindex].clicert, 0, sizeof(x509_cert));

  if(data->set.str[STRING_CERT]) {
    ret = x509parse_crtfile(&conn->ssl[sockindex].clicert,
                            data->set.str[STRING_CERT]);

    if(ret) {
      failf(data, "Error reading client cert file %s: -0x%04X",
            data->set.str[STRING_CERT], -ret);
      return CURLE_SSL_CERTPROBLEM;
    }
  }

  /* Load the client private key */
  if(data->set.str[STRING_KEY]) {
    ret = x509parse_keyfile(&conn->ssl[sockindex].rsa,
                            data->set.str[STRING_KEY],
                            data->set.str[STRING_KEY_PASSWD]);

    if(ret) {
      failf(data, "Error reading private key %s: -0x%04X",
            data->set.str[STRING_KEY], -ret);
      return CURLE_SSL_CERTPROBLEM;
    }
  }

  /* Load the CRL */
  memset(&conn->ssl[sockindex].crl, 0, sizeof(x509_crl));

  if(data->set.str[STRING_SSL_CRLFILE]) {
    ret = x509parse_crlfile(&conn->ssl[sockindex].crl,
                            data->set.str[STRING_SSL_CRLFILE]);

    if(ret) {
      failf(data, "Error reading CRL file %s: -0x%04X",
            data->set.str[STRING_SSL_CRLFILE], -ret);
      return CURLE_SSL_CRL_BADFILE;
    }
  }

  infof(data, "PolarSSL: Connected to %s:%d\n",
        conn->host.name, conn->remote_port);

  havege_init(&conn->ssl[sockindex].hs);

  if(ssl_init(&conn->ssl[sockindex].ssl)) {
    failf(data, "PolarSSL: ssl_init failed");
    return CURLE_SSL_CONNECT_ERROR;
  }

  ssl_set_endpoint(&conn->ssl[sockindex].ssl, SSL_IS_CLIENT);
  ssl_set_authmode(&conn->ssl[sockindex].ssl, SSL_VERIFY_OPTIONAL);

  ssl_set_rng(&conn->ssl[sockindex].ssl, havege_rand,
              &conn->ssl[sockindex].hs);
  ssl_set_bio(&conn->ssl[sockindex].ssl,
              net_recv, &conn->sock[sockindex],
              net_send, &conn->sock[sockindex]);

  ssl_set_ciphers(&conn->ssl[sockindex].ssl, ssl_default_ciphers);

  if(!Curl_ssl_getsessionid(conn, &old_session, &old_session_size)) {
    memcpy(&conn->ssl[sockindex].ssn, old_session, old_session_size);
    infof(data, "PolarSSL re-using session\n");
  }

  ssl_set_session(&conn->ssl[sockindex].ssl, 1, 600,
                  &conn->ssl[sockindex].ssn);

  ssl_set_ca_chain(&conn->ssl[sockindex].ssl,
                   &conn->ssl[sockindex].cacert,
                   &conn->ssl[sockindex].crl,
                   conn->host.name);

  ssl_set_own_cert(&conn->ssl[sockindex].ssl,
                   &conn->ssl[sockindex].clicert, &conn->ssl[sockindex].rsa);

  if(!Curl_inet_pton(AF_INET, conn->host.name, &addr) &&
#ifdef ENABLE_IPV6
     !Curl_inet_pton(AF_INET6, conn->host.name, &addr) &&
#endif
     sni && ssl_set_hostname(&conn->ssl[sockindex].ssl, conn->host.name)) {
     infof(data, "WARNING: failed to configure "
                 "server name indication (SNI) TLS extension\n");
  }

  infof(data, "PolarSSL: performing SSL/TLS handshake...\n");

#ifdef POLARSSL_DEBUG
  ssl_set_dbg(&conn->ssl[sockindex].ssl, polarssl_debug, data);
#endif

  for(;;) {
    if(!(ret = ssl_handshake(&conn->ssl[sockindex].ssl)))
      break;
    else if(ret != POLARSSL_ERR_NET_TRY_AGAIN) {
      failf(data, "ssl_handshake returned -0x%04X", -ret);
      return CURLE_SSL_CONNECT_ERROR;
    }
    else {
      /* wait for data from server... */
      long timeout_ms = Curl_timeleft(data, NULL, TRUE);

      if(timeout_ms < 0) {
        failf(data, "SSL connection timeout");
        return CURLE_OPERATION_TIMEDOUT;
      }

      switch(Curl_socket_ready(conn->sock[sockindex],
                        CURL_SOCKET_BAD, timeout_ms)) {
      case 0:
        failf(data, "SSL handshake timeout");
        return CURLE_OPERATION_TIMEDOUT;
        break;
      case CURL_CSELECT_IN:
        continue;
        break;
      default:
        return CURLE_SSL_CONNECT_ERROR;
        break;
      }
    }
  }

  infof(data, "PolarSSL: Handshake complete, cipher is %s\n",
        ssl_get_cipher(&conn->ssl[sockindex].ssl));

  ret = ssl_get_verify_result(&conn->ssl[sockindex].ssl);

  if(ret && data->set.ssl.verifypeer) {
    if(ret & BADCERT_EXPIRED)
      failf(data, "Cert verify failed: BADCERT_EXPIRED\n");

    if(ret & BADCERT_REVOKED)
      failf(data, "Cert verify failed: BADCERT_REVOKED");

    if(ret & BADCERT_CN_MISMATCH)
      failf(data, "Cert verify failed: BADCERT_CN_MISMATCH");

    if(ret & BADCERT_NOT_TRUSTED)
      failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED");

    return CURLE_SSL_CACERT;
  }

  if(conn->ssl[sockindex].ssl.peer_cert) {
    /* If the session was resumed, there will be no peer certs */
    memset(buffer, 0, sizeof(buffer));

    if(x509parse_cert_info(buffer, sizeof(buffer), (char *)"* ",
                           conn->ssl[sockindex].ssl.peer_cert) != -1)
      infof(data, "Dumping cert info:\n%s\n", buffer);
  }

  conn->ssl[sockindex].state = ssl_connection_complete;
  conn->recv[sockindex] = polarssl_recv;
  conn->send[sockindex] = polarssl_send;

  /* Save the current session data for possible re-use */
  {
    void *new_session = malloc(sizeof(conn->ssl[sockindex].ssn));

    if(new_session) {
      memcpy(new_session, &conn->ssl[sockindex].ssn,
             sizeof(conn->ssl[sockindex].ssn));

      if(old_session)
        Curl_ssl_delsessionid(conn, old_session);

      return Curl_ssl_addsessionid(conn, new_session,
                                   sizeof(conn->ssl[sockindex].ssn));
    }
  }

  return CURLE_OK;
}
Exemple #9
0
static CURLcode
polarssl_connect_step1(struct connectdata *conn,
                     int sockindex)
{
  struct SessionHandle *data = conn->data;
  struct ssl_connect_data* connssl = &conn->ssl[sockindex];

  bool sni = TRUE; /* default is SNI enabled */
  int ret = -1;
#ifdef ENABLE_IPV6
  struct in6_addr addr;
#else
  struct in_addr addr;
#endif
  void *old_session = NULL;
  size_t old_session_size = 0;

  /* PolarSSL only supports SSLv3 and TLSv1 */
  if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
    failf(data, "PolarSSL does not support SSLv2");
    return CURLE_SSL_CONNECT_ERROR;
  }
  else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3)
    sni = FALSE; /* SSLv3 has no SNI */

  havege_init(&connssl->hs);

  /* Load the trusted CA */
  memset(&connssl->cacert, 0, sizeof(x509_cert));

  if(data->set.str[STRING_SSL_CAFILE]) {
    ret = x509parse_crtfile(&connssl->cacert,
                            data->set.str[STRING_SSL_CAFILE]);

    if(ret<0) {
      failf(data, "Error reading ca cert file %s: -0x%04X",
            data->set.str[STRING_SSL_CAFILE], ret);

      if(data->set.ssl.verifypeer)
        return CURLE_SSL_CACERT_BADFILE;
    }
  }

  /* Load the client certificate */
  memset(&connssl->clicert, 0, sizeof(x509_cert));

  if(data->set.str[STRING_CERT]) {
    ret = x509parse_crtfile(&connssl->clicert,
                            data->set.str[STRING_CERT]);

    if(ret) {
      failf(data, "Error reading client cert file %s: -0x%04X",
            data->set.str[STRING_CERT], -ret);
      return CURLE_SSL_CERTPROBLEM;
    }
  }

  /* Load the client private key */
  if(data->set.str[STRING_KEY]) {
    ret = x509parse_keyfile(&connssl->rsa,
                            data->set.str[STRING_KEY],
                            data->set.str[STRING_KEY_PASSWD]);

    if(ret) {
      failf(data, "Error reading private key %s: -0x%04X",
            data->set.str[STRING_KEY], -ret);
      return CURLE_SSL_CERTPROBLEM;
    }
  }

  /* Load the CRL */
  memset(&connssl->crl, 0, sizeof(x509_crl));

  if(data->set.str[STRING_SSL_CRLFILE]) {
    ret = x509parse_crlfile(&connssl->crl,
                            data->set.str[STRING_SSL_CRLFILE]);

    if(ret) {
      failf(data, "Error reading CRL file %s: -0x%04X",
            data->set.str[STRING_SSL_CRLFILE], -ret);
      return CURLE_SSL_CRL_BADFILE;
    }
  }

  infof(data, "PolarSSL: Connecting to %s:%d\n",
        conn->host.name, conn->remote_port);

  if(ssl_init(&connssl->ssl)) {
    failf(data, "PolarSSL: ssl_init failed");
    return CURLE_SSL_CONNECT_ERROR;
  }

  ssl_set_endpoint(&connssl->ssl, SSL_IS_CLIENT);
  ssl_set_authmode(&connssl->ssl, SSL_VERIFY_OPTIONAL);

  ssl_set_rng(&connssl->ssl, HAVEGE_RANDOM,
              &connssl->hs);
  ssl_set_bio(&connssl->ssl,
              net_recv, &conn->sock[sockindex],
              net_send, &conn->sock[sockindex]);


#if POLARSSL_VERSION_NUMBER<0x01000000
  ssl_set_ciphers(&connssl->ssl, ssl_default_ciphers);
#else
  ssl_set_ciphersuites(&connssl->ssl, ssl_default_ciphersuites);
#endif
  if(!Curl_ssl_getsessionid(conn, &old_session, &old_session_size)) {
    memcpy(&connssl->ssn, old_session, old_session_size);
    infof(data, "PolarSSL re-using session\n");
  }

  ssl_set_session(&connssl->ssl, 1, 600,
                  &connssl->ssn);

  ssl_set_ca_chain(&connssl->ssl,
                   &connssl->cacert,
                   &connssl->crl,
                   conn->host.name);

  ssl_set_own_cert(&connssl->ssl,
                   &connssl->clicert, &connssl->rsa);

  if(!Curl_inet_pton(AF_INET, conn->host.name, &addr) &&
#ifdef ENABLE_IPV6
     !Curl_inet_pton(AF_INET6, conn->host.name, &addr) &&
#endif
     sni && ssl_set_hostname(&connssl->ssl, conn->host.name)) {
     infof(data, "WARNING: failed to configure "
                 "server name indication (SNI) TLS extension\n");
  }

#ifdef POLARSSL_DEBUG
  ssl_set_dbg(&connssl->ssl, polarssl_debug, data);
#endif

  connssl->connecting_state = ssl_connect_2;

  return CURLE_OK;
}
int main( void )
{
    int ret, len, server_fd;
    unsigned char buf[1024];
    havege_state hs;
    ssl_context ssl;
    ssl_session ssn;
    x509_cert cacert;
    x509_cert clicert;
    rsa_context rsa;

    /*
     * 0. Initialize the RNG and the session data
     */
    havege_init( &hs );
    memset( &ssn, 0, sizeof( ssl_session ) );

    /*
     * 1.1. Load the trusted CA
     */
    printf( "\n  . Loading the CA root certificate ..." );
    fflush( stdout );

    memset( &cacert, 0, sizeof( x509_cert ) );

    /*
     * Alternatively, you may load the CA certificates from a .pem or
     * .crt file by calling x509parse_crtfile( &cacert, "myca.crt" ).
     */
    ret = x509parse_crt( &cacert, (unsigned char *) xyssl_ca_crt,
                         strlen( xyssl_ca_crt ) );
    if( ret != 0 )
    {
        printf( " failed\n  !  x509parse_crt returned %d\n\n", ret );
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 1.2. Load own certificate and private key
     *
     * (can be skipped if client authentication is not required)
     */
    printf( "  . Loading the client cert. and key..." );
    fflush( stdout );

    memset( &clicert, 0, sizeof( x509_cert ) );

    ret = x509parse_crt( &clicert, (unsigned char *) test_cli_crt,
                         strlen( test_cli_crt ) );
    if( ret != 0 )
    {
        printf( " failed\n  !  x509parse_crt returned %d\n\n", ret );
        goto exit;
    }

    ret = x509parse_key( &rsa, (unsigned char *) test_cli_key,
                         strlen( test_cli_key ), NULL, 0 );
    if( ret != 0 )
    {
        printf( " failed\n  !  x509parse_key returned %d\n\n", ret );
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 2. Start the connection
     */
    printf( "  . Connecting to tcp/%s/%-4d...", SERVER_NAME,
                                                SERVER_PORT );
    fflush( stdout );

    if( ( ret = net_connect( &server_fd, SERVER_NAME,
                                         SERVER_PORT ) ) != 0 )
    {
        printf( " failed\n  ! net_connect returned %d\n\n", ret );
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 3. Setup stuff
     */
    printf( "  . Setting up the SSL/TLS structure..." );
    fflush( stdout );

    havege_init( &hs );

    if( ( ret = ssl_init( &ssl ) ) != 0 )
    {
        printf( " failed\n  ! ssl_init returned %d\n\n", ret );
        goto exit;
    }

    printf( " ok\n" );

    ssl_set_endpoint( &ssl, SSL_IS_CLIENT );
    ssl_set_authmode( &ssl, SSL_VERIFY_OPTIONAL );

    ssl_set_rng( &ssl, havege_rand, &hs );
    ssl_set_bio( &ssl, net_recv, &server_fd,
                       net_send, &server_fd );

    ssl_set_ciphers( &ssl, ssl_default_ciphers );
    ssl_set_session( &ssl, 1, 600, &ssn );

    ssl_set_ca_chain( &ssl, &cacert, SERVER_NAME );
    ssl_set_own_cert( &ssl, &clicert, &rsa );

    ssl_set_hostname( &ssl, SERVER_NAME );

    /*
     * 4. Handshake
     */
    printf( "  . Performing the SSL/TLS handshake..." );
    fflush( stdout );

    while( ( ret = ssl_handshake( &ssl ) ) != 0 )
    {
        if( ret != POLARSSL_ERR_NET_TRY_AGAIN )
        {
            printf( " failed\n  ! ssl_handshake returned %d\n\n", ret );
            goto exit;
        }
    }

    printf( " ok\n    [ Cipher is %s ]\n",
            ssl_get_cipher( &ssl ) );

    /*
     * 5. Verify the server certificate
     */
    printf( "  . Verifying peer X.509 certificate..." );

    if( ( ret = ssl_get_verify_result( &ssl ) ) != 0 )
    {
        printf( " failed\n" );

        if( ( ret & BADCERT_EXPIRED ) != 0 )
            printf( "  ! server certificate has expired\n" );

        if( ( ret & BADCERT_REVOKED ) != 0 )
            printf( "  ! server certificate has been revoked\n" );

        if( ( ret & BADCERT_CN_MISMATCH ) != 0 )
            printf( "  ! CN mismatch (expected CN=%s)\n", SERVER_NAME );

        if( ( ret & BADCERT_NOT_TRUSTED ) != 0 )
            printf( "  ! self-signed or not signed by a trusted CA\n" );

        printf( "\n" );
    }
    else
        printf( " ok\n" );

    printf( "  . Peer certificate information    ...\n" );
    printf( "%s", x509parse_cert_info( "      ", ssl.peer_cert ) );

    /*
     * 6. Write the GET request
     */
    printf( "  > Write to server:" );
    fflush( stdout );

    len = sprintf( (char *) buf, GET_REQUEST );

    while( ( ret = ssl_write( &ssl, buf, len ) ) <= 0 )
    {
        if( ret != POLARSSL_ERR_NET_TRY_AGAIN )
        {
            printf( " failed\n  ! ssl_write returned %d\n\n", ret );
            goto exit;
        }
    }

    len = ret;
    printf( " %d bytes written\n\n%s", len, (char *) buf );

    /*
     * 7. Read the HTTP response
     */
    printf( "  < Read from server:" );
    fflush( stdout );

    do
    {
        len = sizeof( buf ) - 1;
        memset( buf, 0, sizeof( buf ) );
        ret = ssl_read( &ssl, buf, len );

        if( ret == POLARSSL_ERR_NET_TRY_AGAIN )
            continue;

        if( ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY )
            break;

        if( ret <= 0 )
        {
            printf( "failed\n  ! ssl_read returned %d\n\n", ret );
            break;
        }

        len = ret;
        printf( " %d bytes read\n\n%s", len, (char *) buf );
    }
    while( 0 );

    ssl_close_notify( &ssl );

exit:

    net_close( server_fd );
    x509_free( &clicert );
    x509_free( &cacert );
    rsa_free( &rsa );
    ssl_free( &ssl );

    memset( &ssl, 0, sizeof( ssl ) );

#ifdef WIN32
    printf( "  + Press Enter to exit this program.\n" );
    fflush( stdout ); getchar();
#endif

    return( ret );
}
Exemple #11
0
int main( int argc, char *argv[] )
{
    int ret, len, server_fd;
    unsigned char buf[2];
    havege_state hs;
    ssl_context ssl;
    ssl_session ssn;
    x509_cert cacert;
    x509_cert clicert;
    rsa_context rsa;

    char *SERVER_NAME = argv[1];
    char GET_REQUEST[128];

    sprintf( GET_REQUEST, "GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", argv[2],
	     argv[1] );

    /*
     * 0. Initialize the RNG and the session data
     */
    havege_init( &hs );
    memset( &ssn, 0, sizeof( ssl_session ) );

    memset( &cacert, 0, sizeof( x509_cert ) );

    /*
     * Alternatively, you may load the CA certificates from a .pem or
     * .crt file by calling x509parse_crtfile( &cacert, "myca.crt" ).
     */
    ret = x509parse_crt( &cacert, ( unsigned char * )xyssl_ca_crt,
			 strlen( xyssl_ca_crt ) );
    if( ret != 0 )
    {
	printf( " failed\n  !  x509parse_crt returned %d\n\n", ret );
	goto exit;
    }

    /*
     * 1.2. Load own certificate and private key
     *
     * (can be skipped if client authentication is not required)
     */

    memset( &clicert, 0, sizeof( x509_cert ) );

    ret = x509parse_crt( &clicert, ( unsigned char * )test_cli_crt,
			 strlen( test_cli_crt ) );
    if( ret != 0 )
    {
	printf( " failed\n  !  x509parse_crt returned %d\n\n", ret );
	goto exit;
    }

    ret = x509parse_key( &rsa, ( unsigned char * )test_cli_key,
			 strlen( test_cli_key ), NULL, 0 );
    if( ret != 0 )
    {
	printf( " failed\n  !  x509parse_key returned %d\n\n", ret );
	goto exit;
    }

    if( ( ret = net_connect( &server_fd, SERVER_NAME, SERVER_PORT ) ) != 0 )
    {
	printf( " failed\n  ! net_connect returned %d\n\n", ret );
	goto exit;
    }

    havege_init( &hs );

    if( ( ret = ssl_init( &ssl ) ) != 0 )
    {
	printf( " failed\n  ! ssl_init returned %d\n\n", ret );
	goto exit;
    }

    ssl_set_endpoint( &ssl, SSL_IS_CLIENT );
    ssl_set_authmode( &ssl, SSL_VERIFY_OPTIONAL );

    ssl_set_rng( &ssl, havege_rand, &hs );
    ssl_set_bio( &ssl, net_recv, &server_fd, net_send, &server_fd );

    ssl_set_ciphers( &ssl, ssl_default_ciphers );
    ssl_set_session( &ssl, 1, 600, &ssn );

    ssl_set_ca_chain( &ssl, &cacert, SERVER_NAME );
    ssl_set_own_cert( &ssl, &clicert, &rsa );

    ssl_set_hostname( &ssl, SERVER_NAME );

    while( ( ret = ssl_handshake( &ssl ) ) != 0 )
    {
	if( ret != XYSSL_ERR_NET_TRY_AGAIN )
	{
	    printf( " failed\n  ! ssl_handshake returned %d\n\n", ret );
	    goto exit;
	}
    }

    if( ( ret = ssl_get_verify_result( &ssl ) ) != 0 )
    {
	printf( "certificate check failed\n" );

	if( ( ret & BADCERT_EXPIRED ) != 0 )
	    printf( "  ! server certificate has expired\n" );

	if( ( ret & BADCERT_REVOKED ) != 0 )
	    printf( "  ! server certificate has been revoked\n" );

	if( ( ret & BADCERT_CN_MISMATCH ) != 0 )
	    printf( "  ! CN mismatch (expected CN=%s)\n", SERVER_NAME );

	if( ( ret & BADCERT_NOT_TRUSTED ) != 0 )
	    printf( "  ! self-signed or not signed by a trusted CA\n" );

	printf( "\n" );
    }

    len = sprintf( ( char * )buf, GET_REQUEST );

    while( ( ret = ssl_write( &ssl, buf, len ) ) <= 0 )
    {
	if( ret != XYSSL_ERR_NET_TRY_AGAIN )
	{
	    printf( " failed\n  ! ssl_write returned %d\n\n", ret );
	    goto exit;
	}
    }

    len = ret;

    /*
     * 7. Read the HTTP response
     */
    fflush( stdout );
    FILE *out = fopen( argv[3], "wb" );
    int found = 0;
    int offset = 0;

    do
    {
	offset = 0;
	len = sizeof( buf ) - 1;
	memset( buf, 0, sizeof( buf ) );
	ret = ssl_read( &ssl, buf, len );

	if( ret == XYSSL_ERR_NET_TRY_AGAIN )
	    continue;

	if( ret == XYSSL_ERR_SSL_PEER_CLOSE_NOTIFY )
	    break;

	if( ret <= 0 )
	{
	    printf( "failed\n  ! ssl_read returned %d\n\n", ret );
	    break;
	}
	if( found < 4 )
	{
	    if( found == 0 || found == 2 )
		if( buf[0] == '\r' )
		{
		    found++;
		    continue;
		}
		else
		    found = 0;
	    if( found == 1 || found == 3 )
		if( buf[0] == '\n' )
		{
		    found++;
		    continue;
		}
		else
		    found = 0;
	}
	else
	    putc( buf[0], out );
	len = ret;
    }
    while( 1 );

    ssl_close_notify( &ssl );

  exit:
    fclose( out );

    net_close( server_fd );
    x509_free( &clicert );
    x509_free( &cacert );
    rsa_free( &rsa );
    ssl_free( &ssl );

    memset( &ssl, 0, sizeof( ssl ) );

    return ( ret );
}