Esempio n. 1
0
static void ustream_ssl_verify_cert(struct ustream_ssl *us)
{
    void *ssl = us->ssl;
    const char *msg = NULL;
    bool cn_mismatch;
    int r;

    r = ssl_get_verify_result(ssl);
    cn_mismatch = r & BADCERT_CN_MISMATCH;
    r &= ~BADCERT_CN_MISMATCH;

    if (r & BADCERT_EXPIRED)
        msg = "certificate has expired";
    else if (r & BADCERT_REVOKED)
        msg = "certificate has been revoked";
    else if (r & BADCERT_NOT_TRUSTED)
        msg = "certificate is self-signed or not signed by a trusted CA";
    else
        msg = "unknown error";

    if (r) {
        if (us->notify_verify_error)
            us->notify_verify_error(us, r, msg);
        return;
    }

    if (!cn_mismatch)
        us->valid_cn = true;
}
Esempio n. 2
0
        virtual int finally()
        {
            if (m_retVal)
                *m_retVal = ssl_get_verify_result(&m_pThis->m_ssl);

            return 0;
        }
Esempio n. 3
0
static int do_handshake( ssl_context *ssl, struct options *opt )
{
    int ret;
    unsigned char buf[1024];
    memset(buf, 0, 1024);

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

    while( ( ret = ssl_handshake( ssl ) ) != 0 )
    {
        if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
        {
#if defined(POLARSSL_ERROR_C)
            polarssl_strerror( ret, (char *) buf, 1024 );
#endif
            printf( " failed\n  ! ssl_handshake returned %d: %s\n\n", ret, buf );
            return( -1 );
        }
    }

    printf( " ok\n    [ Ciphersuite is %s ]\n",
            ssl_get_ciphersuite( 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", opt->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" );
    x509_crt_info( (char *) buf, sizeof( buf ) - 1, "      ",
                   ssl_get_peer_cert( ssl ) );
    printf( "%s\n", buf );

    return( 0 );
}
Esempio n. 4
0
uint32_t
verify_signature (ssl_context *ssl, const char *hostname)
{
  int ssl_verify_result;

  ssl_verify_result = ssl_get_verify_result (ssl);
  if (ssl_verify_result & BADCERT_EXPIRED)
  {
    die ("certificate has expired");
  }
  if (ssl_verify_result & BADCERT_REVOKED)
  {
    die ("certificate has been revoked");
  }
  if (ssl_verify_result & BADCERT_CN_MISMATCH)
  {
    die ("CN and subject AltName mismatch for certificate");
  }
  if (ssl_verify_result & BADCERT_NOT_TRUSTED)
  {
    die ("certificate is self-signed or not signed by a trusted CA");
  }

  if (0 == ssl_verify_result)
  {
    verb ("V: verify success");
  }
  else
  {
    die ("certificate verification error: -0x%04x", -ssl_verify_result);
  }
  return 0;
}
Esempio n. 5
0
int CTTLS::checkCert() {
    int ret;

    ssl_context *ssl=&((T_SSL*)pSSL)->ssl;
    while( ( ret = ssl_handshake( ssl ) ) != 0 )
    {
        if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
        {
            tivi_slog( " failed\n  ! ssl_handshake returned %d\n", ret );
            //lev[1]/Users/janisnarbuts/libs/polarssl-1.1.1/iphone/polar_ssl/polar_ssl/../../../library/ssl_tls.c(1035): ssl_fetch_input() returned -29312 (0xffff8d80)

            return -1;
        }
#ifndef _WIN32
        usleep(20);
#else
        Sleep(15);
#endif
    }

    tivi_slog( " ok\n    [ Ciphersuite is %s ]", ssl_get_ciphersuite( ssl ) );

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

    if( ( ret = ssl_get_verify_result( ssl ) ) != 0 )
    {
        tivi_slog( " failed" );
        printf("ssl_get_verify_result()=%d\n",ret);

        // ssl_context *ssl2=&((T_SSL*)pSSL)->ssl;
        //  puts((char*)ssl2->ca_chain->subject.val.p);

        if( ( ret & BADCERT_EXPIRED ) != 0 )
            failedCert( "  ! server certificate has expired",NULL,1 );

        if( ( ret & BADCERT_REVOKED ) != 0 )
            failedCert( "  ! server certificate has been revoked",NULL,1 );

        if( ( ret & BADCERT_CN_MISMATCH ) != 0 ) {
            failedCert( "  ! CN mismatch (expected CN=%s)",this->bufCertHost,1);
        }

        if( ( ret & BADCERT_NOT_TRUSTED ) != 0 )
            failedCert( "  ! self-signed or not signed by a trusted CA",NULL,1 );

    }
    else
        tivi_slog( " ok" );
    /*
        tivi_slog( "  . Peer certificate information    ..." );
        x509parse_cert_info( (char *) buf, sizeof( buf ) - 1, "      ", ssl->peer_cert );
        tivi_slog( "%s", buf );*/
    return 0;
}
Esempio n. 6
0
int ssl_init_info(int *server_fd,ssl_info *sslinfo)
{
    int ret;
    const char *pers = "ssl";
    x509_crt_init(&sslinfo->cacert );
    entropy_init(&sslinfo->entropy );
    if( ( ret = ctr_drbg_init( &sslinfo->ctr_drbg, entropy_func, &sslinfo->entropy,
                               (const unsigned char *) pers,
                               strlen( pers ) ) ) != 0 )
    {

        return -1;
    }
    if( ( ret = ssl_init( &sslinfo->ssl ) ) != 0 )
    {
        echo( " failed\n  ! ssl_init returned %d\n\n", ret );
        return -1;
    }

    ssl_set_endpoint( &sslinfo->ssl, SSL_IS_CLIENT );
    ssl_set_authmode( &sslinfo->ssl, SSL_VERIFY_OPTIONAL );
    ssl_set_ca_chain( &sslinfo->ssl, &sslinfo->cacert, NULL, "" );
    ssl_set_rng( &sslinfo->ssl, ctr_drbg_random, &sslinfo->ctr_drbg );
    ssl_set_bio( &sslinfo->ssl, net_recv, server_fd,net_send, server_fd );
    ssl_set_session(&sslinfo->ssl, &ssn);



    while((ret = ssl_handshake(&sslinfo->ssl))!=0)
    {
        if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
        {
            echo( " failed\n  ! ssl_handshake returned -0x%x\n\n", -ret );
            return -1;
        }
        //CPU sleep
        sleeps(1);
    }

    if((ret = ssl_get_verify_result( &sslinfo->ssl ) ) != 0 )
    {
       // echo( "Verifying peer X.509 certificate...failed \r\n" );
    }
    else
    {
        echo( " ok\n" );
    }
    //保存session加快握手速度
    if( ( ret = ssl_get_session( &sslinfo->ssl, &ssn ) ) != 0 )
    {
        //失败初始化
        memset(&ssn, 0, sizeof(ssl_session));
    }
    return 0;
}
Esempio n. 7
0
ngx_int_t
ngx_ssl_verify_result(ngx_connection_t *c, long *rc, const char **errstr)
{
    int  sslerr;

    sslerr = ssl_get_verify_result(c->ssl->connection);

    if (sslerr != 0) {
        *rc = sslerr;
        *errstr = ngx_mbedtls_verify_error_str(sslerr);

        return NGX_ERROR;
    }

    return NGX_OK;
}
Esempio n. 8
0
ngx_int_t
ngx_ssl_get_client_verify(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
{
    const x509_cert  *cert;

    if (ssl_get_verify_result(c->ssl->connection) != 0) {
        ngx_str_set(s, "FAILED");
        return NGX_OK;
    }

    cert = ssl_get_peer_cert(c->ssl->connection);

    if (cert) {
        ngx_str_set(s, "SUCCESS");
    } else {
        ngx_str_set(s, "NONE");
    }

    return NGX_OK;
}
int main( int argc, char *argv[] )
{
    int ret, len, server_fd = -1;
    unsigned char buf[1024];
    const char *pers = "dtls_client";
    int retry_left = MAX_RETRY;

    entropy_context entropy;
    ctr_drbg_context ctr_drbg;
    ssl_context ssl;
    x509_crt cacert;

    ((void) argc);
    ((void) argv);

#if defined(POLARSSL_DEBUG_C)
    debug_set_threshold( DEBUG_LEVEL );
#endif

    /*
     * 0. Initialize the RNG and the session data
     */
    memset( &ssl, 0, sizeof( ssl_context ) );
    x509_crt_init( &cacert );

    printf( "\n  . Seeding the random number generator..." );
    fflush( stdout );

    entropy_init( &entropy );
    if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy,
                               (const unsigned char *) pers,
                               strlen( pers ) ) ) != 0 )
    {
        printf( " failed\n  ! ctr_drbg_init returned %d\n", ret );
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 0. Initialize certificates
     */
    printf( "  . Loading the CA root certificate ..." );
    fflush( stdout );

#if defined(POLARSSL_CERTS_C)
    ret = x509_crt_parse( &cacert, (const unsigned char *) test_ca_list,
                          strlen( test_ca_list ) );
#else
    ret = 1;
    printf("POLARSSL_CERTS_C not defined.");
#endif

    if( ret < 0 )
    {
        printf( " failed\n  !  x509_crt_parse returned -0x%x\n\n", -ret );
        goto exit;
    }

    printf( " ok (%d skipped)\n", ret );

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

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

    printf( " ok\n" );

    /*
     * 2. Setup stuff
     */
    printf( "  . Setting up the DTLS 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_transport( &ssl, SSL_TRANSPORT_DATAGRAM );

    /* OPTIONAL is usually a bad choice for security, but makes interop easier
     * in this simplified example, in which the ca chain is hardcoded.
     * Production code should set a proper ca chain and use REQUIRED. */
    ssl_set_authmode( &ssl, SSL_VERIFY_OPTIONAL );
    ssl_set_ca_chain( &ssl, &cacert, NULL, SERVER_NAME );

    ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg );
    ssl_set_dbg( &ssl, my_debug, stdout );

    ssl_set_bio_timeout( &ssl, &server_fd,
                         net_send, net_recv, net_recv_timeout,
                         READ_TIMEOUT_MS );

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

    do ret = ssl_handshake( &ssl );
    while( ret == POLARSSL_ERR_NET_WANT_READ ||
           ret == POLARSSL_ERR_NET_WANT_WRITE );

    if( ret != 0 )
    {
        printf( " failed\n  ! ssl_handshake returned -0x%x\n\n", -ret );
        goto exit;
    }

    printf( " ok\n" );

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

    /* In real life, we would have used SSL_VERIFY_REQUIRED so that the
     * handshake would not succeed if the peer's cert is bad.  Even if we used
     * SSL_VERIFY_OPTIONAL, we would bail out here if ret != 0 */
    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" );

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

    len = sizeof( MESSAGE ) - 1;

    do ret = ssl_write( &ssl, (unsigned char *) MESSAGE, len );
    while( ret == POLARSSL_ERR_NET_WANT_READ ||
           ret == POLARSSL_ERR_NET_WANT_WRITE );

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

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

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

    len = sizeof( buf ) - 1;
    memset( buf, 0, sizeof( buf ) );

    do ret = ssl_read( &ssl, buf, len );
    while( ret == POLARSSL_ERR_NET_WANT_READ ||
           ret == POLARSSL_ERR_NET_WANT_WRITE );

    if( ret <= 0 )
    {
        switch( ret )
        {
            case POLARSSL_ERR_NET_TIMEOUT:
                printf( " timeout\n\n" );
                if( retry_left-- > 0 )
                    goto send_request;
                goto exit;

            case POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY:
                printf( " connection was closed gracefully\n" );
                ret = 0;
                goto close_notify;

            default:
                printf( " ssl_read returned -0x%x\n\n", -ret );
                goto exit;
        }
    }

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

    /*
     * 8. Done, cleanly close the connection
     */
close_notify:
    printf( "  . Closing the connection..." );

    /* No error checking, the connection might be closed already */
    do ret = ssl_close_notify( &ssl );
    while( ret == POLARSSL_ERR_NET_WANT_WRITE );
    ret = 0;

    printf( " done\n" );

    /*
     * 9. Final clean-ups and exit
     */
exit:

#ifdef POLARSSL_ERROR_C
    if( ret != 0 )
    {
        char error_buf[100];
        polarssl_strerror( ret, error_buf, 100 );
        printf( "Last error was: %d - %s\n\n", ret, error_buf );
    }
#endif

    if( server_fd != -1 )
        net_close( server_fd );

    x509_crt_free( &cacert );
    ssl_free( &ssl );
    ctr_drbg_free( &ctr_drbg );
    entropy_free( &entropy );

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

    /* Shell can not handle large exit numbers -> 1 for errors */
    if( ret < 0 )
        ret = 1;

    return( ret );
}
Esempio n. 10
0
static CURLcode
polarssl_connect_step2(struct connectdata *conn,
                     int sockindex)
{
  int ret;
  struct SessionHandle *data = conn->data;
  struct ssl_connect_data* connssl = &conn->ssl[sockindex];
  char buffer[1024];

#ifdef HAS_ALPN
  const char* next_protocol;
#endif

  char errorbuf[128];
  errorbuf[0] = 0;

  conn->recv[sockindex] = polarssl_recv;
  conn->send[sockindex] = polarssl_send;

  for(;;) {
    if(!(ret = ssl_handshake(&connssl->ssl)))
      break;
    else if(ret != POLARSSL_ERR_NET_WANT_READ &&
            ret != POLARSSL_ERR_NET_WANT_WRITE) {
#ifdef POLARSSL_ERROR_C
     error_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* POLARSSL_ERROR_C */
     failf(data, "ssl_handshake returned - PolarSSL: (-0x%04X) %s",
                                                    -ret, errorbuf);

     return CURLE_SSL_CONNECT_ERROR;
    }
    else {
      if(ret == POLARSSL_ERR_NET_WANT_READ) {
        connssl->connecting_state = ssl_connect_2_reading;
        return CURLE_OK;
      }
      if(ret == POLARSSL_ERR_NET_WANT_WRITE) {
        connssl->connecting_state = ssl_connect_2_writing;
        return CURLE_OK;
      }
      failf(data, "SSL_connect failed with error %d.", ret);
      return CURLE_SSL_CONNECT_ERROR;

    }
  }

  infof(data, "PolarSSL: Handshake complete, cipher is %s\n",
        ssl_get_ciphersuite(&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");

    if(ret & BADCERT_REVOKED) {
      failf(data, "Cert verify failed: BADCERT_REVOKED");
      return CURLE_SSL_CACERT;
    }

    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_PEER_FAILED_VERIFICATION;
  }

  if(ssl_get_peer_cert(&(connssl->ssl))) {
    /* If the session was resumed, there will be no peer certs */
    memset(buffer, 0, sizeof(buffer));

    if(x509_crt_info(buffer, sizeof(buffer), (char *)"* ",
                     ssl_get_peer_cert(&(connssl->ssl))) != -1)
      infof(data, "Dumping cert info:\n%s\n", buffer);
  }

#ifdef HAS_ALPN
  if(data->set.ssl_enable_alpn) {
    next_protocol = ssl_get_alpn_protocol(&connssl->ssl);

    if(next_protocol != NULL) {
      infof(data, "ALPN, server accepted to use %s\n", next_protocol);

      if(strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID,
                  NGHTTP2_PROTO_VERSION_ID_LEN)) {
        conn->negnpn = NPN_HTTP2;
      }
      else if(strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH)) {
        conn->negnpn = NPN_HTTP1_1;
      }
    }
    else {
      infof(data, "ALPN, server did not agree to a protocol\n");
    }
  }
#endif

  connssl->connecting_state = ssl_connect_3;
  infof(data, "SSL connected\n");

  return CURLE_OK;
}
Esempio n. 11
0
/*
    Initiate or continue SSL handshaking with the peer. This routine does not block.
    Return -1 on errors, 0 incomplete and awaiting I/O, 1 if successful
 */
static int estHandshake(Webs *wp)
{
    WebsSocket  *sp;
    EstSocket   *est;
    int         rc, vrc, trusted;

    est = (EstSocket*) wp->ssl;
    trusted = 1;
    rc = 0;

    sp = socketPtr(wp->sid);
    sp->flags |= SOCKET_HANDSHAKING;

    while (est->ctx.state != SSL_HANDSHAKE_OVER) {
        if ((rc = ssl_handshake(&est->ctx)) != 0) {
            if (rc == EST_ERR_NET_TRY_AGAIN) {
                return 0;
            }
            break;
        }
    }
    sp->flags &= ~SOCKET_HANDSHAKING;

    /*
        Analyze the handshake result
     */
    if (rc < 0) {
        if (rc == EST_ERR_SSL_PRIVATE_KEY_REQUIRED && !(*BIT_GOAHEAD_KEY || *BIT_GOAHEAD_CERTIFICATE)) {
            error("Missing required certificate and key");
        } else {
            error("Cannot handshake: error -0x%x", -rc);
        }
        sp->flags |= SOCKET_EOF;
        errno = EPROTO;
        return -1;
       
    } else if ((vrc = ssl_get_verify_result(&est->ctx)) != 0) {
        if (vrc & BADCERT_EXPIRED) {
            logmsg(2, "Certificate expired");

        } else if (vrc & BADCERT_REVOKED) {
            logmsg(2, "Certificate revoked");

        } else if (vrc & BADCERT_CN_MISMATCH) {
            logmsg(2, "Certificate common name mismatch");

        } else if (vrc & BADCERT_NOT_TRUSTED) {
            if (vrc & BADCERT_SELF_SIGNED) {                                                               
                logmsg(2, "Self-signed certificate");
            } else {
                logmsg(2, "Certificate not trusted");
            }
            trusted = 0;

        } else {
            if (est->ctx.client_auth && !*BIT_GOAHEAD_CERTIFICATE) {
                logmsg(2, "Server requires a client certificate");
            } else if (rc == EST_ERR_NET_CONN_RESET) {
                logmsg(2, "Peer disconnected");
            } else {
                logmsg(2, "Cannot handshake: error -0x%x", -rc);
            }
        }
        if (BIT_GOAHEAD_VERIFY_PEER) {
            /* 
               If not verifying the issuer, permit certs that are only untrusted (no other error).
               This allows self-signed certs.
             */
            if (!BIT_GOAHEAD_VERIFY_ISSUER && !trusted) {
                return 1;
            } else {
                sp->flags |= SOCKET_EOF;
                errno = EPROTO;
                return -1;
            }
        }
    }
    return 1;
}
Esempio n. 12
0
static CURLcode
polarssl_connect_step2(struct connectdata *conn,
                     int sockindex)
{
  int ret;
  struct SessionHandle *data = conn->data;
  struct ssl_connect_data* connssl = &conn->ssl[sockindex];
  char buffer[1024];

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

  conn->recv[sockindex] = polarssl_recv;
  conn->send[sockindex] = polarssl_send;

  for(;;) {
    if(!(ret = ssl_handshake(&connssl->ssl)))
      break;
    else if(ret != POLARSSL_ERR_NET_WANT_READ &&
            ret != POLARSSL_ERR_NET_WANT_WRITE) {
#ifdef POLARSSL_ERROR_C
     error_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* POLARSSL_ERROR_C */
     failf(data, "ssl_handshake returned - PolarSSL: (-0x%04X) %s",
                                                    -ret, errorbuf);

     return CURLE_SSL_CONNECT_ERROR;
    }
    else {
      if(ret == POLARSSL_ERR_NET_WANT_READ) {
        connssl->connecting_state = ssl_connect_2_reading;
        return CURLE_OK;
      }
      if(ret == POLARSSL_ERR_NET_WANT_WRITE) {
        connssl->connecting_state = ssl_connect_2_writing;
        return CURLE_OK;
      }
      failf(data, "SSL_connect failed with error %d.", ret);
      return CURLE_SSL_CONNECT_ERROR;

    }
  }

  infof(data, "PolarSSL: Handshake complete, cipher is %s\n",
#if POLARSSL_VERSION_NUMBER<0x01000000
        ssl_get_cipher(&conn->ssl[sockindex].ssl)
#elif POLARSSL_VERSION_NUMBER >= 0x01010000
        ssl_get_ciphersuite(&conn->ssl[sockindex].ssl)
#else
        ssl_get_ciphersuite_name(&conn->ssl[sockindex].ssl)
#endif
    );

  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");

    if(ret & BADCERT_REVOKED) {
      failf(data, "Cert verify failed: BADCERT_REVOKED");
      return CURLE_SSL_CACERT;
    }

    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_PEER_FAILED_VERIFICATION;
  }

/* 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
  if(conn->ssl[sockindex].ssl.peer_cert) {
#else
  if(ssl_get_peer_cert(&(connssl->ssl))) {
#endif
    /* If the session was resumed, there will be no peer certs */
    memset(buffer, 0, sizeof(buffer));

/* 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
    if(x509parse_cert_info(buffer, sizeof(buffer), (char *)"* ",
                           conn->ssl[sockindex].ssl.peer_cert) != -1)
#else
    if(x509parse_cert_info(buffer, sizeof(buffer), (char *)"* ",
                           ssl_get_peer_cert(&(connssl->ssl))) != -1)
#endif
      infof(data, "Dumping cert info:\n%s\n", buffer);
  }

  connssl->connecting_state = ssl_connect_3;
  infof(data, "SSL connected\n");

  return CURLE_OK;
}

static CURLcode
polarssl_connect_step3(struct connectdata *conn,
                     int sockindex)
{
  CURLcode retcode = CURLE_OK;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct SessionHandle *data = conn->data;
  void *old_ssl_sessionid = NULL;
  ssl_session *our_ssl_sessionid = &conn->ssl[sockindex].ssn ;
  int incache;

  DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);

  /* Save the current session data for possible re-use */
  incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL));
  if(incache) {
    if(old_ssl_sessionid != our_ssl_sessionid) {
      infof(data, "old SSL session ID is stale, removing\n");
      Curl_ssl_delsessionid(conn, old_ssl_sessionid);
      incache = FALSE;
    }
  }
  if(!incache) {
    void *new_session = malloc(sizeof(ssl_session));

    if(new_session) {
      memcpy(new_session, our_ssl_sessionid,
             sizeof(ssl_session));

      retcode = Curl_ssl_addsessionid(conn, new_session,
                                   sizeof(ssl_session));
    }
    else {
      retcode = CURLE_OUT_OF_MEMORY;
    }

    if(retcode) {
      failf(data, "failed to store ssl session");
      return retcode;
    }
  }

  connssl->connecting_state = ssl_connect_done;

  return CURLE_OK;
}
Esempio n. 13
0
int main( int argc, const char *argv[] )
{
    /* Client and server declarations. */
    int ret;
    int len;
#if SOCKET_COMMUNICATION
    int listen_fd = -1;
    int client_fd = -1;
    int server_fd = -1;
#endif
    unsigned char buf[1024];
    /* Handshake step counter */
    size_t step = 1;
    int flags;

    ssl_context s_ssl, c_ssl;
    x509_crt srvcert;
    pk_context pkey;
#if defined(POLARSSL_SSL_CACHE_C)
    ssl_cache_context cache;
#endif

    if( argc == 3)
    {
        packet_in_num = atoi(argv[1]);
        packet_in_file = argv[2];
    }
    else if( argc != 1)
    {
        usage(argv[0]);
        exit(1);
    }

    /* Server init */
    memset( &s_ssl, 0, sizeof( ssl_context ) );
#if defined(POLARSSL_SSL_CACHE_C)
    ssl_cache_init( &cache );
#endif
    x509_crt_init( &srvcert );
    pk_init( &pkey );

    /* Client init */
    memset( &c_ssl, 0, sizeof( ssl_context ) );
    /*x509_crt_init( &cacert );*/

#if defined(POLARSSL_DEBUG_C)
    debug_set_threshold( DEBUG_LEVEL );
#endif

    /*
     * Server:
     * Load the certificates and private RSA key
     */
    if( packet_in_num == 0 )
    {
        printf( "  . Loading the server cert. and key..." );
        fflush( stdout );
    }

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

    ret = x509_crt_parse( &srvcert, (const unsigned char *) test_ca_list,
                          strlen( test_ca_list ) );
    if( ret != 0 )
    {
        polarssl_printf( " failed\n  !  x509_crt_parse returned %d\n\n", ret );
        goto exit;
    }

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

    if( packet_in_num == 0 )
    {
        printf( " ok\n" );
    }

    /*
     * Server:
     * Setup stuff
     */
    if( packet_in_num == 0 )
    {
        printf( "  . Server: Setting up the SSL data...." );
        fflush( stdout );
    }

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

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

    /* SSLv3 is deprecated, set minimum to TLS 1.0 */
    ssl_set_min_version( &s_ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1 );
    /* RC4 is deprecated, disable it */
    ssl_set_arc4_support( &s_ssl, SSL_ARC4_DISABLED );

    ssl_set_rng( &s_ssl, ctr_drbg_deterministic, NULL );
    ssl_set_dbg( &s_ssl, my_debug, stdout );

#if defined(POLARSSL_SSL_CACHE_C)
    ssl_set_session_cache( &s_ssl, ssl_cache_get, &cache,
                           ssl_cache_set, &cache );
#endif

    ssl_set_ca_chain( &s_ssl, srvcert.next, NULL, NULL );
    if( ( ret = ssl_set_own_cert( &s_ssl, &srvcert, &pkey ) ) != 0 )
    {
        printf( " failed\n  ! ssl_set_own_cert returned %d\n\n", ret );
        goto exit;
    }

    if( packet_in_num == 0 )
    {
        printf( " ok\n" );
    }

    ssl_session_reset( &s_ssl );

#if SOCKET_COMMUNICATION
    /*
     * Server:
     * Setup the listening TCP socket
     */
    if( packet_in_num == 0 )
    {
        printf( "  . Bind on https://localhost:%d/ ...", SERVER_PORT );
        fflush( stdout );
    }

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

    if( packet_in_num == 0 )
    {
        printf( " ok\n" );
    }

    /*
     * Client:
     * Start the connection
     */
    if( packet_in_num == 0 )
    {
        printf( "  . Connecting to tcp/%s/%d...", 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;
    }

    if( packet_in_num == 0 )
    {
        printf( " ok\n" );
    }

    /*
     * Server:
     * Start listening for client connections
     */
    if( packet_in_num == 0 )
    {
        printf( "  . Waiting for a remote connection ..." );
        fflush( stdout );
    }

    /*
     * Server:
     * Accept client connection (socket is set non-blocking in
     * library/net.c)
     */
    if( ( ret = net_accept( listen_fd, &client_fd,
                            NULL ) ) != 0 )
    {
        printf( " failed\n  ! net_accept returned %d\n\n", ret );
        goto exit;
    }

    if( packet_in_num == 0 )
    {
        printf( " ok\n" );
    }

    ssl_set_bio( &s_ssl, recv_custom, &client_fd, send_custom, &client_fd );
#else
    ssl_set_bio( &s_ssl, func_server_recv_buf, NULL, func_server_send_buf, NULL );
#endif

    /*
     * Client:
     * Setup stuff
     */
    if( packet_in_num == 0 )
    {
        printf( "  . Client: Setting up the SSL/TLS structure..." );
        fflush( stdout );
    }

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

    if( packet_in_num == 0 )
    {
        polarssl_printf( " ok\n" );
    }

    ssl_set_endpoint( &c_ssl, SSL_IS_CLIENT );
    /* OPTIONAL is not optimal for security,
     * but makes interop easier in this simplified example */
    ssl_set_authmode( &c_ssl, SSL_VERIFY_OPTIONAL );
    /* NONE permits man-in-the-middle attacks. */
    /*ssl_set_authmode( &c_ssl, VERIFY_NONE );*/
    /*ssl_set_authmode( &c_ssl, SSL_VERIFY_REQUIRED );*/
    ssl_set_ca_chain( &c_ssl, &srvcert, NULL, "PolarSSL Server 1" );

    /* SSLv3 is deprecated, set minimum to TLS 1.0 */
    ssl_set_min_version( &c_ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1 );
    /* RC4 is deprecated, disable it */
    ssl_set_arc4_support( &c_ssl, SSL_ARC4_DISABLED );

    ssl_set_rng( &c_ssl, ctr_drbg_deterministic, NULL );
    ssl_set_dbg( &c_ssl, my_debug, stdout );

    if( ( ret = ssl_set_hostname( &c_ssl, "mbed TLS Server 1" ) ) != 0 )
    {
        printf( " failed\n  ! ssl_set_hostname returned %d\n\n", ret );
        goto exit;
    }

#if SOCKET_COMMUNICATION
    ssl_set_bio( &c_ssl, recv_custom, &server_fd, send_custom, &server_fd );
#else
    ssl_set_bio( &c_ssl, func_client_recv_buf, NULL, func_client_send_buf,  NULL );
#endif

    if( packet_in_num == 0 )
    {
        printf( "  . Performing the SSL/TLS handshake...\n" );
        fflush( stdout );
    }

    /*
     * The following number of steps are hardcoded to ensure
     * that the client and server complete the handshake without
     * waiting infinitely for the other side to send data.
     *
     *                     1  2  3  4  5  6  7  8  9
     */
    int client_steps[] = { 2, 1, 1, 1, 4, 2, 1, 1, 3 };
    int server_steps[] = { 3, 1, 1, 3, 2, 1, 2, 1, 2 };

    do {
        /*
         * Client:
         * Handshake step
         */
        int i;
        int no_steps;

        if( c_ssl.state == SSL_HANDSHAKE_OVER ) {
            no_steps = 0;
        } else {
            no_steps = client_steps[step - 1];
        }

        for (i = 0; i < no_steps; i++) {
            if(  ( ret = ssl_handshake_step( &c_ssl ) ) != 0 )
            {
                if(  ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
                {
                    printf( " failed\n  ! ssl_handshake returned -0x%x\n\n", -ret );
                    goto exit;
                }
            }
        }

        if( packet_in_num == 0 )
        {
            printf( "--- client handshake step %zd ok\n", step );
        }

        /*
         * Server:
         * Handshake step
         */
        if( s_ssl.state == SSL_HANDSHAKE_OVER ) {
            printf("over\n");
            no_steps = 0;
        } else {
            no_steps = server_steps[step - 1];
        }

        for (i = 0; i < no_steps; i++) {
            if(  ( ret = ssl_handshake_step( &s_ssl ) ) != 0 )
            {
                if(  ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
                {
                    printf( " failed\n  ! ssl_handshake returned %d\n\n", ret );
                    goto exit;
                }
            }
        }

        if( packet_in_num == 0 )
        {
            printf( "--- server handshake step %zd ok\n", step );
        }

        step++;
    } while( ((c_ssl.state != SSL_HANDSHAKE_OVER)
              || (s_ssl.state != SSL_HANDSHAKE_OVER))
             && (step <= MAX_HANDSHAKE_STEPS) );

    if( packet_in_num == 0 )
    {
        printf( "c_ssl.state: %d\n", c_ssl.state != SSL_HANDSHAKE_OVER );
        printf( "s_ssl.state: %d\n", s_ssl.state != SSL_HANDSHAKE_OVER );
    }

    /*
     * Client:
     * Verify the server certificate
     */
    if( packet_in_num == 0 )
    {
        printf( "  . Verifying peer X.509 certificate..." );
    }

    /* In real life, we probably want to bail out when ret != 0 */
    if( ( flags = ssl_get_verify_result( &c_ssl ) ) != 0 )
    {
        char vrfy_buf[512];

        printf( " failed\n" );

        x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), "  ! ", flags );

        printf( "%s\n", vrfy_buf );
    }
    else if( packet_in_num == 0 )
    {
        printf( " ok\n" );
    }

    /*
     * Client:
     * Write the GET request
     */
    if( packet_in_num == 0 )
    {
        printf( "  > Write to server:" );
        fflush( stdout );
    }

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

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

    len = ret;
    if( packet_in_num == 0 )
    {
        printf( " %d bytes written\n\n%s", len, (char *) buf );
    }

    /*
     * Server:
     * Read the HTTP Request
     */
    if( packet_in_num == 0 )
    {
        printf( "  < Read from client:" );
        fflush( stdout );
    }

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

        if( ret ==POLARSSL_ERR_NET_WANT_READ || ret ==POLARSSL_ERR_NET_WANT_WRITE )
            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 -0x%x\n", -ret );
                break;
            }

            break;
        }

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

        if( ret > 0 )
            break;
    }
    while( 1 );

    /*
     * Server:
     * Write the 200 Response
     */
    if( packet_in_num == 0 )
    {
        printf( "  > Write to client:" );
        fflush( stdout );
    }

    len = sprintf( (char *) buf, HTTP_RESPONSE,
                   ssl_get_ciphersuite( &s_ssl ) );

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

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

    len = ret;
    if( packet_in_num == 0 )
    {
        printf( " %d bytes written\n\n%s\n", len, (char *) buf );
    }

    /*
     * Client:
     * Read the HTTP response
     */
    if( packet_in_num == 0 )
    {
        printf( "  < Read from server:" );
        fflush( stdout );
    }

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

        if( ret == POLARSSL_ERR_NET_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE )
            continue;

        if( ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY )
        {
            ret = 0;
            break;
        }

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

        if( ret == 0 )
        {
            printf( "\n\nEOF\n\n" );
            break;
        }

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

        /*
         * Server:
         * Client read response. Close connection.
         */
        if ( packet_in_num == 0 )
        {
            printf( "  . Closing the connection..." );
            fflush( stdout );
        }

        while( ( ret = ssl_close_notify( &s_ssl ) ) < 0 )
        {
            if( ret != POLARSSL_ERR_NET_WANT_READ &&
                    ret != POLARSSL_ERR_NET_WANT_WRITE )
            {
                printf( " failed\n  ! ssl_close_notify returned %d\n\n", ret );
                goto exit;
            }
        }

        if( packet_in_num == 0 )
        {
            printf( " ok\n" );
        }
    }
    while( 1 );

    /*
     * Client:
     * Close connection.
     */
    if( packet_in_num == 0 )
    {
        printf( "  . Closing the connection..." );
        fflush( stdout );
    }

    ssl_close_notify( &c_ssl );

    if( packet_in_num == 0 )
    {
        printf( " ok\n" );
    }

    /*
     * Server:
     * We do not have multiple clients and therefore do not goto reset.
     */
    /*ret = 0;*/
    /*goto reset;*/

exit:

#ifdef POLARSSL_ERROR_C
    if( ret != 0 )
    {
        char error_buf[100];
        polarssl_strerror( ret, error_buf, 100 );
        printf("Last error was: %d - %s\n\n", ret, error_buf );
    }
#endif

#if SOCKET_COMMUNICATION
    if ( client_fd != 1 )
        net_close( client_fd );
    if( server_fd != -1 )
        net_close( server_fd );
    if ( listen_fd != 1 )
        net_close( listen_fd );
#endif

    x509_crt_free( &srvcert );
    pk_free( &pkey );
    ssl_free( &s_ssl );
    ssl_free( &c_ssl );
#if defined(POLARSSL_SSL_CACHE_C)
    ssl_cache_free( &cache );
#endif

#if defined(_WIN32)
    printf( "  Press Enter to exit this program.\n" );
    fflush( stdout );
    getchar();
#endif

    return( ret );
}
Esempio n. 14
0
int main( int argc, char *argv[] )
{
    int ret, len, server_fd;
    unsigned char buf[1024];
    char *pers = "ssl_client1";

    entropy_context entropy;
    ctr_drbg_context ctr_drbg;
    ssl_context ssl;
    x509_cert cacert;

    ((void) argc);
    ((void) argv);

    /*
     * 0. Initialize the RNG and the session data
     */
    memset( &ssl, 0, sizeof( ssl_context ) );
    memset( &cacert, 0, sizeof( x509_cert ) );

    printf( "\n  . Seeding the random number generator..." );
    fflush( stdout );

    entropy_init( &entropy );
    if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy,
                               (unsigned char *) pers, strlen( pers ) ) ) != 0 )
    {
        printf( " failed\n  ! ctr_drbg_init returned %d\n", ret );
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 0. Initialize certificates
     */
    printf( "  . Loading the CA root certificate ..." );
    fflush( stdout );

#if defined(POLARSSL_CERTS_C)
    ret = x509parse_crt( &cacert, (unsigned char *) test_ca_crt,
                         strlen( test_ca_crt ) );
#else
    ret = 1;
    printf("POLARSSL_CERTS_C not defined.");
#endif

    if( ret < 0 )
    {
        printf( " failed\n  !  x509parse_crt returned -0x%x\n\n", -ret );
        goto exit;
    }

    printf( " ok (%d skipped)\n", ret );

    /*
     * 1. 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" );

    /*
     * 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_OPTIONAL );
    ssl_set_ca_chain( &ssl, &cacert, NULL, "PolarSSL Server 1" );

    ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg );
    ssl_set_dbg( &ssl, my_debug, stdout );
    ssl_set_bio( &ssl, net_recv, &server_fd,
                       net_send, &server_fd );

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

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

    printf( " ok\n" );

    /*
     * 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", "PolarSSL Server 1" );

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

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

    /*
     * 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 != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
        {
            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_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE )
            continue;

        if( ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY )
            break;

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

        if( ret == 0 )
        {
            printf( "\n\nEOF\n\n" );
            break;
        }

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

    ssl_close_notify( &ssl );

exit:

#ifdef POLARSSL_ERROR_C
    if( ret != 0 )
    {
        char error_buf[100];
        error_strerror( ret, error_buf, 100 );
        printf("Last error was: %d - %s\n\n", ret, error_buf );
    }
#endif

    x509_free( &cacert );
    net_close( server_fd );
    ssl_free( &ssl );

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

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

    return( ret );
}
Esempio n. 15
0
int main( int argc, char *argv[] )
{
    int ret = 0, len, server_fd;
    unsigned char buf[1024];
    char *pers = "ssl_client2";

    entropy_context entropy;
    ctr_drbg_context ctr_drbg;
    ssl_context ssl;
    x509_cert cacert;
    x509_cert clicert;
    rsa_context rsa;
    int i;
    char *p, *q;
    const int *list;

    /*
     * Make sure memory references are valid.
     */
    server_fd = 0;
    memset( &ssl, 0, sizeof( ssl_context ) );
    memset( &cacert, 0, sizeof( x509_cert ) );
    memset( &clicert, 0, sizeof( x509_cert ) );
    memset( &rsa, 0, sizeof( rsa_context ) );

    if( argc == 0 )
    {
    usage:
        if( ret == 0 )
            ret = 1;

        printf( USAGE );

        list = ssl_list_ciphersuites();
        while( *list )
        {
            printf("    %s\n", ssl_get_ciphersuite_name( *list ) );
            list++;
        }
        printf("\n");
        goto exit;
    }

    opt.server_name         = DFL_SERVER_NAME;
    opt.server_port         = DFL_SERVER_PORT;
    opt.debug_level         = DFL_DEBUG_LEVEL;
    opt.request_page        = DFL_REQUEST_PAGE;
    opt.ca_file             = DFL_CA_FILE;
    opt.ca_path             = DFL_CA_PATH;
    opt.crt_file            = DFL_CRT_FILE;
    opt.key_file            = DFL_KEY_FILE;
    opt.force_ciphersuite[0]= DFL_FORCE_CIPHER;
    opt.renegotiation       = DFL_RENEGOTIATION;
    opt.allow_legacy        = DFL_ALLOW_LEGACY;
    opt.min_version         = DFL_MIN_VERSION;
    opt.max_version         = DFL_MAX_VERSION;
    opt.auth_mode           = DFL_AUTH_MODE;

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

        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 if( strcmp( p, "request_page" ) == 0 )
            opt.request_page = q;
        else if( strcmp( p, "ca_file" ) == 0 )
            opt.ca_file = q;
        else if( strcmp( p, "ca_path" ) == 0 )
            opt.ca_path = q;
        else if( strcmp( p, "crt_file" ) == 0 )
            opt.crt_file = q;
        else if( strcmp( p, "key_file" ) == 0 )
            opt.key_file = q;
        else if( strcmp( p, "force_ciphersuite" ) == 0 )
        {
            opt.force_ciphersuite[0] = -1;

            opt.force_ciphersuite[0] = ssl_get_ciphersuite_id( q );

            if( opt.force_ciphersuite[0] <= 0 )
            {
                ret = 2;
                goto usage;
            }
            opt.force_ciphersuite[1] = 0;
        }
        else if( strcmp( p, "renegotiation" ) == 0 )
        {
            opt.renegotiation = (atoi( q )) ? SSL_RENEGOTIATION_ENABLED :
                                              SSL_RENEGOTIATION_DISABLED;
        }
        else if( strcmp( p, "allow_legacy" ) == 0 )
        {
            opt.allow_legacy = atoi( q );
            if( opt.allow_legacy < 0 || opt.allow_legacy > 1 )
                goto usage;
        }
        else if( strcmp( p, "min_version" ) == 0 )
        {
            if( strcmp( q, "ssl3" ) == 0 )
                opt.min_version = SSL_MINOR_VERSION_0;
            else if( strcmp( q, "tls1" ) == 0 )
                opt.min_version = SSL_MINOR_VERSION_1;
            else if( strcmp( q, "tls1_1" ) == 0 )
                opt.min_version = SSL_MINOR_VERSION_2;
            else if( strcmp( q, "tls1_2" ) == 0 )
                opt.min_version = SSL_MINOR_VERSION_3;
            else
                goto usage;
        }
        else if( strcmp( p, "max_version" ) == 0 )
        {
            if( strcmp( q, "ssl3" ) == 0 )
                opt.max_version = SSL_MINOR_VERSION_0;
            else if( strcmp( q, "tls1" ) == 0 )
                opt.max_version = SSL_MINOR_VERSION_1;
            else if( strcmp( q, "tls1_1" ) == 0 )
                opt.max_version = SSL_MINOR_VERSION_2;
            else if( strcmp( q, "tls1_2" ) == 0 )
                opt.max_version = SSL_MINOR_VERSION_3;
            else
                goto usage;
        }
        else if( strcmp( p, "force_version" ) == 0 )
        {
            if( strcmp( q, "ssl3" ) == 0 )
            {
                opt.min_version = SSL_MINOR_VERSION_0;
                opt.max_version = SSL_MINOR_VERSION_0;
            }
            else if( strcmp( q, "tls1" ) == 0 )
            {
                opt.min_version = SSL_MINOR_VERSION_1;
                opt.max_version = SSL_MINOR_VERSION_1;
            }
            else if( strcmp( q, "tls1_1" ) == 0 )
            {
                opt.min_version = SSL_MINOR_VERSION_2;
                opt.max_version = SSL_MINOR_VERSION_2;
            }
            else if( strcmp( q, "tls1_2" ) == 0 )
            {
                opt.min_version = SSL_MINOR_VERSION_3;
                opt.max_version = SSL_MINOR_VERSION_3;
            }
            else
                goto usage;
        }
        else if( strcmp( p, "auth_mode" ) == 0 )
        {
            if( strcmp( q, "none" ) == 0 )
                opt.auth_mode = SSL_VERIFY_NONE;
            else if( strcmp( q, "optional" ) == 0 )
                opt.auth_mode = SSL_VERIFY_OPTIONAL;
            else if( strcmp( q, "required" ) == 0 )
                opt.auth_mode = SSL_VERIFY_REQUIRED;
            else
                goto usage;
        }
        else
            goto usage;
    }

    /*
     * 0. Initialize the RNG and the session data
     */
    printf( "\n  . Seeding the random number generator..." );
    fflush( stdout );

    entropy_init( &entropy );
    if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy,
                               (unsigned char *) pers, strlen( pers ) ) ) != 0 )
    {
        printf( " failed\n  ! ctr_drbg_init returned -0x%x\n", -ret );
        goto exit;
    }

    printf( " ok\n" );

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

#if defined(POLARSSL_FS_IO)
    if( strlen( opt.ca_path ) )
        ret = x509parse_crtpath( &cacert, opt.ca_path );
    else if( strlen( opt.ca_file ) )
        ret = x509parse_crtfile( &cacert, opt.ca_file );
    else 
#endif
#if defined(POLARSSL_CERTS_C)
        ret = x509parse_crt( &cacert, (unsigned char *) test_ca_crt,
                strlen( test_ca_crt ) );
#else
    {
        ret = 1;
        printf("POLARSSL_CERTS_C not defined.");
    }
#endif
    if( ret < 0 )
    {
        printf( " failed\n  !  x509parse_crt returned -0x%x\n\n", -ret );
        goto exit;
    }

    printf( " ok (%d skipped)\n", ret );

    /*
     * 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 );

#if defined(POLARSSL_FS_IO)
    if( strlen( opt.crt_file ) )
        ret = x509parse_crtfile( &clicert, opt.crt_file );
    else 
#endif
#if defined(POLARSSL_CERTS_C)
        ret = x509parse_crt( &clicert, (unsigned char *) test_cli_crt,
                strlen( test_cli_crt ) );
#else
    {
        ret = 1;
        printf("POLARSSL_CERTS_C not defined.");
    }
#endif
    if( ret != 0 )
    {
        printf( " failed\n  !  x509parse_crt returned -0x%x\n\n", -ret );
        goto exit;
    }

#if defined(POLARSSL_FS_IO)
    if( strlen( opt.key_file ) )
        ret = x509parse_keyfile( &rsa, opt.key_file, "" );
    else
#endif
#if defined(POLARSSL_CERTS_C)
        ret = x509parse_key( &rsa, (unsigned char *) test_cli_key,
                strlen( test_cli_key ), NULL, 0 );
#else
    {
        ret = 1;
        printf("POLARSSL_CERTS_C not defined.");
    }
#endif
    if( ret != 0 )
    {
        printf( " failed\n  !  x509parse_key returned -0x%x\n\n", -ret );
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 2. Start the connection
     */
    printf( "  . Connecting 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 -0x%x\n\n", -ret );
        goto exit;
    }

    printf( " ok\n" );

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

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

    printf( " ok\n" );

    if( opt.debug_level > 0 )
        ssl_set_verify( &ssl, my_verify, NULL );

    ssl_set_endpoint( &ssl, SSL_IS_CLIENT );
    ssl_set_authmode( &ssl, opt.auth_mode );

    ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg );
    ssl_set_dbg( &ssl, my_debug, stdout );
    ssl_set_bio( &ssl, net_recv, &server_fd,
                       net_send, &server_fd );

    if( opt.force_ciphersuite[0] != DFL_FORCE_CIPHER )
        ssl_set_ciphersuites( &ssl, opt.force_ciphersuite );

    ssl_set_renegotiation( &ssl, opt.renegotiation );
    ssl_legacy_renegotiation( &ssl, opt.allow_legacy );

    ssl_set_ca_chain( &ssl, &cacert, NULL, opt.server_name );
    ssl_set_own_cert( &ssl, &clicert, &rsa );

    ssl_set_hostname( &ssl, opt.server_name );

    if( opt.min_version != -1 )
        ssl_set_min_version( &ssl, SSL_MAJOR_VERSION_3, opt.min_version );
    if( opt.max_version != -1 )
        ssl_set_max_version( &ssl, SSL_MAJOR_VERSION_3, opt.max_version );

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

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

    printf( " ok\n    [ Ciphersuite is %s ]\n",
            ssl_get_ciphersuite( &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", opt.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" );
    x509parse_cert_info( (char *) buf, sizeof( buf ) - 1, "      ",
                         ssl_get_peer_cert( &ssl ) );
    printf( "%s\n", buf );

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

    len = sprintf( (char *) buf, GET_REQUEST, opt.request_page );

    while( ( ret = ssl_write( &ssl, buf, len ) ) <= 0 )
    {
        if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
        {
            printf( " failed\n  ! ssl_write returned -0x%x\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_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE )
            continue;

        if( ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY )
            break;

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

        if( ret == 0 )
        {
            printf("\n\nEOF\n\n");
            break;
        }

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

    ssl_close_notify( &ssl );

exit:

#ifdef POLARSSL_ERROR_C
    if( ret != 0 )
    {
        char error_buf[100];
        error_strerror( ret, error_buf, 100 );
        printf("Last error was: -0x%X - %s\n\n", -ret, error_buf );
    }
#endif

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

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

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

    return( ret );
}
Esempio n. 16
0
bool polarssl_io::open(stream* s)
{
	if (s == NULL)
	{
		logger_error("stream null");
		return false;
	}

	stream_ = s;

#ifdef HAS_POLARSSL
	// 防止重复调用 open 过程
	acl_assert(ssl_ == NULL);

	ssl_ = acl_mycalloc(1, sizeof(ssl_context));

	int   ret;

	// 初始化 SSL 对象
	if ((ret = ::ssl_init((ssl_context*) ssl_)) != 0)
	{
		logger_error("failed, ssl_init error: -0x%04x\n", ret);
		acl_myfree(ssl_);
		ssl_ = NULL;
		return false;
	}

	// 需要区分 SSL 连接是客户端模式还是服务器模式
	if (server_side_)
		::ssl_set_endpoint((ssl_context*) ssl_, SSL_IS_SERVER);
	else
		::ssl_set_endpoint((ssl_context*) ssl_, SSL_IS_CLIENT);

	// 初始化随机数生成过程

# ifdef HAS_HAVEGE
	rnd_  = acl_mymalloc(sizeof(havege_state));
	::havege_init((havege_state*) rnd_);

	// 设置随机数生成器
	::ssl_set_rng((ssl_context*) ssl_, havege_random, rnd_);
# else
	rnd_ = acl_mymalloc(sizeof(ctr_drbg_context));

	char pers[50];
	snprintf(pers, sizeof(pers), "SSL Pthread Thread %lu",
		(unsigned long) acl_pthread_self());

	ret = ::ctr_drbg_init((ctr_drbg_context*) rnd_, entropy_func,
			(entropy_context*) conf_.get_entropy(),
			(const unsigned char *) pers, strlen(pers));
	if (ret != 0)
	{
		logger_error("ctr_drbg_init error: -0x%04x\n", ret);
		return false;
	}

	// 设置随机数生成器
	::ssl_set_rng((ssl_context*) ssl_, ctr_drbg_random, rnd_);
# endif

# ifdef	DEBUG_SSL
	ssl_set_dbg((ssl_context*) ssl_, my_debug, stdout);
# endif
	
	if (!server_side_)
	{
		// 只有客户端模式下才会调用此过程

		ssn_ = acl_mycalloc(1, sizeof(ssl_session));
# ifdef POLARSSL_1_3_X
		ret = ::ssl_set_session((ssl_context*) ssl_,
			(ssl_session*) ssn_);
		if (ret != 0)
		{
			logger_error("ssl_set_session error: -0x%04x\n", ret);
			acl_myfree(ssn_);
			ssn_ = NULL;
		}
# else
		::ssl_set_session((ssl_context*) ssl_, (ssl_session*) ssn_);
# endif
	}

	// 配置全局参数(包含证书、私钥)
	conf_.setup_certs(ssl_, server_side_);

	// Setup SSL IO callback
	::ssl_set_bio((ssl_context*) ssl_, sock_read, this, sock_send, this);

	// SSL 握手过程
	while((ret = ::ssl_handshake((ssl_context*) ssl_)) != 0)
	{
		if (ret != POLARSSL_ERR_NET_WANT_READ
			&& ret != POLARSSL_ERR_NET_WANT_WRITE)
		{
			logger_error("ssl_handshake failed: -0x%04x", ret);
			return false;
		}
	}

#if 0
	if ((ret = ssl_get_verify_result((ssl_context*) ssl_)) != 0)
	{
		printf("failed\n");

		if (!ssl_get_peer_cert((ssl_context*) ssl_))
			printf("! no client certificate sent\n");

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

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

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

		printf("\n");
	}
#endif

	return true;
#else
	logger_error("define HAS_POLARSSL first!");
	return false;
#endif
}
Esempio n. 17
0
int main( int argc, char *argv[] )
{
    int ret = 0, len;
    int listen_fd;
    int client_fd = -1;
    unsigned char buf[1024];
    const char *pers = "ssl_server2";

    entropy_context entropy;
    ctr_drbg_context ctr_drbg;
    ssl_context ssl;
    x509_cert cacert;
    x509_cert srvcert;
    rsa_context rsa;
#if defined(POLARSSL_SSL_CACHE_C)
    ssl_cache_context cache;
#endif

    int i;
    char *p, *q;
    const int *list;

    /*
     * Make sure memory references are valid.
     */
    listen_fd = 0;
    memset( &cacert, 0, sizeof( x509_cert ) );
    memset( &srvcert, 0, sizeof( x509_cert ) );
    memset( &rsa, 0, sizeof( rsa_context ) );
#if defined(POLARSSL_SSL_CACHE_C)
    ssl_cache_init( &cache );
#endif

    if( argc == 0 )
    {
    usage:
        if( ret == 0 )
            ret = 1;

        printf( USAGE );

        list = ssl_list_ciphersuites();
        while( *list )
        {
            printf("    %s\n", ssl_get_ciphersuite_name( *list ) );
            list++;
        }
        printf("\n");
        goto exit;
    }

    opt.server_port         = DFL_SERVER_PORT;
    opt.debug_level         = DFL_DEBUG_LEVEL;
    opt.ca_file             = DFL_CA_FILE;
    opt.ca_path             = DFL_CA_PATH;
    opt.crt_file            = DFL_CRT_FILE;
    opt.key_file            = DFL_KEY_FILE;
    opt.force_ciphersuite[0]= DFL_FORCE_CIPHER;
    opt.renegotiation       = DFL_RENEGOTIATION;
    opt.allow_legacy        = DFL_ALLOW_LEGACY;
    opt.min_version         = DFL_MIN_VERSION;
    opt.auth_mode           = DFL_AUTH_MODE;

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

        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 if( strcmp( p, "ca_file" ) == 0 )
            opt.ca_file = q;
        else if( strcmp( p, "ca_path" ) == 0 )
            opt.ca_path = q;
        else if( strcmp( p, "crt_file" ) == 0 )
            opt.crt_file = q;
        else if( strcmp( p, "key_file" ) == 0 )
            opt.key_file = q;
        else if( strcmp( p, "force_ciphersuite" ) == 0 )
        {
            opt.force_ciphersuite[0] = -1;

            opt.force_ciphersuite[0] = ssl_get_ciphersuite_id( q );

            if( opt.force_ciphersuite[0] <= 0 )
            {
                ret = 2;
                goto usage;
            }
            opt.force_ciphersuite[1] = 0;
        }
        else if( strcmp( p, "renegotiation" ) == 0 )
        {
            opt.renegotiation = (atoi( q )) ? SSL_RENEGOTIATION_ENABLED :
                                              SSL_RENEGOTIATION_DISABLED;
        }
        else if( strcmp( p, "allow_legacy" ) == 0 )
        {
            opt.allow_legacy = atoi( q );
            if( opt.allow_legacy < 0 || opt.allow_legacy > 1 )
                goto usage;
        }
        else if( strcmp( p, "min_version" ) == 0 )
        {
            if( strcmp( q, "ssl3" ) == 0 )
                opt.min_version = SSL_MINOR_VERSION_0;
            else if( strcmp( q, "tls1" ) == 0 )
                opt.min_version = SSL_MINOR_VERSION_1;
            else if( strcmp( q, "tls1_1" ) == 0 )
                opt.min_version = SSL_MINOR_VERSION_2;
            else if( strcmp( q, "tls1_2" ) == 0 )
                opt.min_version = SSL_MINOR_VERSION_3;
            else
                goto usage;
        }
        else if( strcmp( p, "auth_mode" ) == 0 )
        {
            if( strcmp( q, "none" ) == 0 )
                opt.auth_mode = SSL_VERIFY_NONE;
            else if( strcmp( q, "optional" ) == 0 )
                opt.auth_mode = SSL_VERIFY_OPTIONAL;
            else if( strcmp( q, "required" ) == 0 )
                opt.auth_mode = SSL_VERIFY_REQUIRED;
            else
                goto usage;
        }
        else
            goto usage;
    }

    /*
     * 0. Initialize the RNG and the session data
     */
    printf( "\n  . Seeding the random number generator..." );
    fflush( stdout );

    entropy_init( &entropy );
    if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy,
                               (const unsigned char *) pers,
                               strlen( pers ) ) ) != 0 )
    {
        printf( " failed\n  ! ctr_drbg_init returned -0x%x\n", -ret );
        goto exit;
    }

    printf( " ok\n" );

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

#if defined(POLARSSL_FS_IO)
    if( strlen( opt.ca_path ) )
        ret = x509parse_crtpath( &cacert, opt.ca_path );
    else if( strlen( opt.ca_file ) )
        ret = x509parse_crtfile( &cacert, opt.ca_file );
    else 
#endif
#if defined(POLARSSL_CERTS_C)
        ret = x509parse_crt( &cacert, (const unsigned char *) test_ca_crt,
                strlen( test_ca_crt ) );
#else
    {
        ret = 1;
        printf("POLARSSL_CERTS_C not defined.");
    }
#endif
    if( ret < 0 )
    {
        printf( " failed\n  !  x509parse_crt returned -0x%x\n\n", -ret );
        goto exit;
    }

    printf( " ok (%d skipped)\n", ret );

    /*
     * 1.2. Load own certificate and private key
     */
    printf( "  . Loading the server cert. and key..." );
    fflush( stdout );

#if defined(POLARSSL_FS_IO)
    if( strlen( opt.crt_file ) )
        ret = x509parse_crtfile( &srvcert, opt.crt_file );
    else 
#endif
#if defined(POLARSSL_CERTS_C)
        ret = x509parse_crt( &srvcert, (const unsigned char *) test_srv_crt,
                strlen( test_srv_crt ) );
#else
    {
        ret = 1;
        printf("POLARSSL_CERTS_C not defined.");
    }
#endif
    if( ret != 0 )
    {
        printf( " failed\n  !  x509parse_crt returned -0x%x\n\n", -ret );
        goto exit;
    }

#if defined(POLARSSL_FS_IO)
    if( strlen( opt.key_file ) )
        ret = x509parse_keyfile( &rsa, opt.key_file, "" );
    else
#endif
#if defined(POLARSSL_CERTS_C)
        ret = x509parse_key( &rsa, (const unsigned char *) test_srv_key,
                strlen( test_srv_key ), NULL, 0 );
#else
    {
        ret = 1;
        printf("POLARSSL_CERTS_C not defined.");
    }
#endif
    if( ret != 0 )
    {
        printf( " failed\n  !  x509parse_key returned -0x%x\n\n", -ret );
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 2. Setup the listening TCP socket
     */
    printf( "  . Bind on tcp://localhost:%-4d/ ...", opt.server_port );
    fflush( stdout );

    if( ( ret = net_bind( &listen_fd, NULL, opt.server_port ) ) != 0 )
    {
        printf( " failed\n  ! net_bind returned -0x%x\n\n", -ret );
        goto exit;
    }

    printf( " ok\n" );

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

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

    ssl_set_endpoint( &ssl, SSL_IS_SERVER );
    ssl_set_authmode( &ssl, opt.auth_mode );

    ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg );
    ssl_set_dbg( &ssl, my_debug, stdout );

#if defined(POLARSSL_SSL_CACHE_C)
    ssl_set_session_cache( &ssl, ssl_cache_get, &cache,
                                 ssl_cache_set, &cache );
#endif

    if( opt.force_ciphersuite[0] == DFL_FORCE_CIPHER )
        ssl_set_ciphersuites( &ssl, my_ciphersuites );
    else
        ssl_set_ciphersuites( &ssl, opt.force_ciphersuite );

    ssl_set_renegotiation( &ssl, opt.renegotiation );
    ssl_legacy_renegotiation( &ssl, opt.allow_legacy );

    ssl_set_ca_chain( &ssl, &cacert, NULL, NULL );
    ssl_set_own_cert( &ssl, &srvcert, &rsa );

#if defined(POLARSSL_DHM_C)
    /*
     * Use different group than default DHM group
     */
    ssl_set_dh_param( &ssl, POLARSSL_DHM_RFC5114_MODP_2048_P,
                            POLARSSL_DHM_RFC5114_MODP_2048_G );
#endif

    if( opt.min_version != -1 )
        ssl_set_min_version( &ssl, SSL_MAJOR_VERSION_3, opt.min_version );

    printf( " ok\n" );

reset:
#ifdef POLARSSL_ERROR_C
    if( ret != 0 )
    {
        char error_buf[100];
        error_strerror( ret, error_buf, 100 );
        printf("Last error was: %d - %s\n\n", ret, error_buf );
    }
#endif

    if( client_fd != -1 )
        net_close( client_fd );

    ssl_session_reset( &ssl );

    /*
     * 3. Wait until a client connects
     */
#if defined(_WIN32_WCE)
    {
        SHELLEXECUTEINFO sei;

        ZeroMemory( &sei, sizeof( SHELLEXECUTEINFO ) );

        sei.cbSize = sizeof( SHELLEXECUTEINFO );
        sei.fMask = 0;
        sei.hwnd = 0;
        sei.lpVerb = _T( "open" );
        sei.lpFile = _T( "https://localhost:4433/" );
        sei.lpParameters = NULL;
        sei.lpDirectory = NULL;
        sei.nShow = SW_SHOWNORMAL;

        ShellExecuteEx( &sei );
    }
#elif defined(_WIN32)
    ShellExecute( NULL, "open", "https://localhost:4433/",
                  NULL, NULL, SW_SHOWNORMAL );
#endif

    client_fd = -1;

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

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

    ssl_set_bio( &ssl, net_recv, &client_fd,
                       net_send, &client_fd );

    printf( " ok\n" );

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

    while( ( ret = ssl_handshake( &ssl ) ) != 0 )
    {
        if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
        {
            printf( " failed\n  ! ssl_handshake returned -0x%x\n\n", -ret );
            goto reset;
        }
    }

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

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

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

        if( !ssl_get_peer_cert( &ssl ) )
            printf( "  ! no client certificate sent\n" );

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

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

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

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

    if( ssl_get_peer_cert( &ssl ) )
    {
        printf( "  . Peer certificate information    ...\n" );
        x509parse_cert_info( (char *) buf, sizeof( buf ) - 1, "      ",
                             ssl_get_peer_cert( &ssl ) );
        printf( "%s\n", buf );
    }

    /*
     * 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_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE )
            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 -0x%x\n", -ret );
                    break;
            }

            break;
        }

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

        if( ret > 0 )
            break;
    }
    while( 1 );

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

    len = sprintf( (char *) buf, HTTP_RESPONSE,
                   ssl_get_ciphersuite( &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 reset;
        }

        if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
        {
            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 );

    ret = 0;
    goto reset;

exit:

#ifdef POLARSSL_ERROR_C
    if( ret != 0 )
    {
        char error_buf[100];
        error_strerror( ret, error_buf, 100 );
        printf("Last error was: -0x%X - %s\n\n", -ret, error_buf );
    }
#endif

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

#if defined(POLARSSL_SSL_CACHE_C)
    ssl_cache_free( &cache );
#endif

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

    return( ret );
}
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 );
}
Esempio n. 19
0
int main( int argc, char *argv[] )
{
    int ret = 0, len, server_fd, i, written, frags;
    unsigned char buf[SSL_MAX_CONTENT_LEN + 1];
#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
    unsigned char psk[POLARSSL_PSK_MAX_LEN];
    size_t psk_len = 0;
#endif
#if defined(POLARSSL_SSL_ALPN)
    const char *alpn_list[10];
#endif
    const char *pers = "ssl_client2";

    entropy_context entropy;
    ctr_drbg_context ctr_drbg;
    ssl_context ssl;
    ssl_session saved_session;
#if defined(POLARSSL_X509_CRT_PARSE_C)
    x509_crt cacert;
    x509_crt clicert;
    pk_context pkey;
#endif
    char *p, *q;
    const int *list;

    /*
     * Make sure memory references are valid.
     */
    server_fd = 0;
    memset( &ssl, 0, sizeof( ssl_context ) );
    memset( &saved_session, 0, sizeof( ssl_session ) );
#if defined(POLARSSL_X509_CRT_PARSE_C)
    x509_crt_init( &cacert );
    x509_crt_init( &clicert );
    pk_init( &pkey );
#endif
#if defined(POLARSSL_SSL_ALPN)
    memset( (void * ) alpn_list, 0, sizeof( alpn_list ) );
#endif

    if( argc == 0 )
    {
    usage:
        if( ret == 0 )
            ret = 1;

        printf( USAGE );

        list = ssl_list_ciphersuites();
        while( *list )
        {
            printf(" %-42s", ssl_get_ciphersuite_name( *list ) );
            list++;
            if( !*list )
                break;
            printf(" %s\n", ssl_get_ciphersuite_name( *list ) );
            list++;
        }
        printf("\n");
        goto exit;
    }

    opt.server_name         = DFL_SERVER_NAME;
    opt.server_addr         = DFL_SERVER_ADDR;
    opt.server_port         = DFL_SERVER_PORT;
    opt.debug_level         = DFL_DEBUG_LEVEL;
    opt.nbio                = DFL_NBIO;
    opt.request_page        = DFL_REQUEST_PAGE;
    opt.request_size        = DFL_REQUEST_SIZE;
    opt.ca_file             = DFL_CA_FILE;
    opt.ca_path             = DFL_CA_PATH;
    opt.crt_file            = DFL_CRT_FILE;
    opt.key_file            = DFL_KEY_FILE;
    opt.psk                 = DFL_PSK;
    opt.psk_identity        = DFL_PSK_IDENTITY;
    opt.force_ciphersuite[0]= DFL_FORCE_CIPHER;
    opt.renegotiation       = DFL_RENEGOTIATION;
    opt.allow_legacy        = DFL_ALLOW_LEGACY;
    opt.renegotiate         = DFL_RENEGOTIATE;
    opt.min_version         = DFL_MIN_VERSION;
    opt.max_version         = DFL_MAX_VERSION;
    opt.auth_mode           = DFL_AUTH_MODE;
    opt.mfl_code            = DFL_MFL_CODE;
    opt.trunc_hmac          = DFL_TRUNC_HMAC;
    opt.reconnect           = DFL_RECONNECT;
    opt.reco_delay          = DFL_RECO_DELAY;
    opt.tickets             = DFL_TICKETS;
    opt.alpn_string         = DFL_ALPN_STRING;

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

        if( strcmp( p, "server_name" ) == 0 )
            opt.server_name = q;
        else if( strcmp( p, "server_addr" ) == 0 )
            opt.server_addr = 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 if( strcmp( p, "nbio" ) == 0 )
        {
            opt.nbio = atoi( q );
            if( opt.nbio < 0 || opt.nbio > 2 )
                goto usage;
        }
        else if( strcmp( p, "request_page" ) == 0 )
            opt.request_page = q;
        else if( strcmp( p, "request_size" ) == 0 )
        {
            opt.request_size = atoi( q );
            if( opt.request_size < 0 || opt.request_size > SSL_MAX_CONTENT_LEN )
                goto usage;
        }
        else if( strcmp( p, "ca_file" ) == 0 )
            opt.ca_file = q;
        else if( strcmp( p, "ca_path" ) == 0 )
            opt.ca_path = q;
        else if( strcmp( p, "crt_file" ) == 0 )
            opt.crt_file = q;
        else if( strcmp( p, "key_file" ) == 0 )
            opt.key_file = q;
        else if( strcmp( p, "psk" ) == 0 )
            opt.psk = q;
        else if( strcmp( p, "psk_identity" ) == 0 )
            opt.psk_identity = q;
        else if( strcmp( p, "force_ciphersuite" ) == 0 )
        {
            opt.force_ciphersuite[0] = ssl_get_ciphersuite_id( q );

            if( opt.force_ciphersuite[0] == 0 )
            {
                ret = 2;
                goto usage;
            }
            opt.force_ciphersuite[1] = 0;
        }
        else if( strcmp( p, "renegotiation" ) == 0 )
        {
            opt.renegotiation = (atoi( q )) ? SSL_RENEGOTIATION_ENABLED :
                                              SSL_RENEGOTIATION_DISABLED;
        }
        else if( strcmp( p, "allow_legacy" ) == 0 )
        {
            opt.allow_legacy = atoi( q );
            if( opt.allow_legacy < 0 || opt.allow_legacy > 1 )
                goto usage;
        }
        else if( strcmp( p, "renegotiate" ) == 0 )
        {
            opt.renegotiate = atoi( q );
            if( opt.renegotiate < 0 || opt.renegotiate > 1 )
                goto usage;
        }
        else if( strcmp( p, "reconnect" ) == 0 )
        {
            opt.reconnect = atoi( q );
            if( opt.reconnect < 0 || opt.reconnect > 2 )
                goto usage;
        }
        else if( strcmp( p, "reco_delay" ) == 0 )
        {
            opt.reco_delay = atoi( q );
            if( opt.reco_delay < 0 )
                goto usage;
        }
        else if( strcmp( p, "tickets" ) == 0 )
        {
            opt.tickets = atoi( q );
            if( opt.tickets < 0 || opt.tickets > 2 )
                goto usage;
        }
        else if( strcmp( p, "alpn" ) == 0 )
        {
            opt.alpn_string = q;
        }
        else if( strcmp( p, "min_version" ) == 0 )
        {
            if( strcmp( q, "ssl3" ) == 0 )
                opt.min_version = SSL_MINOR_VERSION_0;
            else if( strcmp( q, "tls1" ) == 0 )
                opt.min_version = SSL_MINOR_VERSION_1;
            else if( strcmp( q, "tls1_1" ) == 0 )
                opt.min_version = SSL_MINOR_VERSION_2;
            else if( strcmp( q, "tls1_2" ) == 0 )
                opt.min_version = SSL_MINOR_VERSION_3;
            else
                goto usage;
        }
        else if( strcmp( p, "max_version" ) == 0 )
        {
            if( strcmp( q, "ssl3" ) == 0 )
                opt.max_version = SSL_MINOR_VERSION_0;
            else if( strcmp( q, "tls1" ) == 0 )
                opt.max_version = SSL_MINOR_VERSION_1;
            else if( strcmp( q, "tls1_1" ) == 0 )
                opt.max_version = SSL_MINOR_VERSION_2;
            else if( strcmp( q, "tls1_2" ) == 0 )
                opt.max_version = SSL_MINOR_VERSION_3;
            else
                goto usage;
        }
        else if( strcmp( p, "force_version" ) == 0 )
        {
            if( strcmp( q, "ssl3" ) == 0 )
            {
                opt.min_version = SSL_MINOR_VERSION_0;
                opt.max_version = SSL_MINOR_VERSION_0;
            }
            else if( strcmp( q, "tls1" ) == 0 )
            {
                opt.min_version = SSL_MINOR_VERSION_1;
                opt.max_version = SSL_MINOR_VERSION_1;
            }
            else if( strcmp( q, "tls1_1" ) == 0 )
            {
                opt.min_version = SSL_MINOR_VERSION_2;
                opt.max_version = SSL_MINOR_VERSION_2;
            }
            else if( strcmp( q, "tls1_2" ) == 0 )
            {
                opt.min_version = SSL_MINOR_VERSION_3;
                opt.max_version = SSL_MINOR_VERSION_3;
            }
            else
                goto usage;
        }
        else if( strcmp( p, "auth_mode" ) == 0 )
        {
            if( strcmp( q, "none" ) == 0 )
                opt.auth_mode = SSL_VERIFY_NONE;
            else if( strcmp( q, "optional" ) == 0 )
                opt.auth_mode = SSL_VERIFY_OPTIONAL;
            else if( strcmp( q, "required" ) == 0 )
                opt.auth_mode = SSL_VERIFY_REQUIRED;
            else
                goto usage;
        }
        else if( strcmp( p, "max_frag_len" ) == 0 )
        {
            if( strcmp( q, "512" ) == 0 )
                opt.mfl_code = SSL_MAX_FRAG_LEN_512;
            else if( strcmp( q, "1024" ) == 0 )
                opt.mfl_code = SSL_MAX_FRAG_LEN_1024;
            else if( strcmp( q, "2048" ) == 0 )
                opt.mfl_code = SSL_MAX_FRAG_LEN_2048;
            else if( strcmp( q, "4096" ) == 0 )
                opt.mfl_code = SSL_MAX_FRAG_LEN_4096;
            else
                goto usage;
        }
        else if( strcmp( p, "trunc_hmac" ) == 0 )
        {
            opt.trunc_hmac = atoi( q );
            if( opt.trunc_hmac < 0 || opt.trunc_hmac > 1 )
                goto usage;
        }
        else
            goto usage;
    }

#if defined(POLARSSL_DEBUG_C)
    debug_set_threshold( opt.debug_level );
#endif

    if( opt.force_ciphersuite[0] > 0 )
    {
        const ssl_ciphersuite_t *ciphersuite_info;
        ciphersuite_info = ssl_ciphersuite_from_id( opt.force_ciphersuite[0] );

        if( opt.max_version != -1 &&
            ciphersuite_info->min_minor_ver > opt.max_version )
        {
            printf("forced ciphersuite not allowed with this protocol version\n");
            ret = 2;
            goto usage;
        }
        if( opt.min_version != -1 &&
            ciphersuite_info->max_minor_ver < opt.min_version )
        {
            printf("forced ciphersuite not allowed with this protocol version\n");
            ret = 2;
            goto usage;
        }
        if( opt.max_version > ciphersuite_info->max_minor_ver )
            opt.max_version = ciphersuite_info->max_minor_ver;
        if( opt.min_version < ciphersuite_info->min_minor_ver )
            opt.min_version = ciphersuite_info->min_minor_ver;
    }

#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
    /*
     * Unhexify the pre-shared key if any is given
     */
    if( strlen( opt.psk ) )
    {
        unsigned char c;
        size_t j;

        if( strlen( opt.psk ) % 2 != 0 )
        {
            printf("pre-shared key not valid hex\n");
            goto exit;
        }

        psk_len = strlen( opt.psk ) / 2;

        for( j = 0; j < strlen( opt.psk ); j += 2 )
        {
            c = opt.psk[j];
            if( c >= '0' && c <= '9' )
                c -= '0';
            else if( c >= 'a' && c <= 'f' )
                c -= 'a' - 10;
            else if( c >= 'A' && c <= 'F' )
                c -= 'A' - 10;
            else
            {
                printf("pre-shared key not valid hex\n");
                goto exit;
            }
            psk[ j / 2 ] = c << 4;

            c = opt.psk[j + 1];
            if( c >= '0' && c <= '9' )
                c -= '0';
            else if( c >= 'a' && c <= 'f' )
                c -= 'a' - 10;
            else if( c >= 'A' && c <= 'F' )
                c -= 'A' - 10;
            else
            {
                printf("pre-shared key not valid hex\n");
                goto exit;
            }
            psk[ j / 2 ] |= c;
        }
    }
#endif /* POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED */

#if defined(POLARSSL_SSL_ALPN)
    if( opt.alpn_string != NULL )
    {
        p = (char *) opt.alpn_string;
        i = 0;

        /* Leave room for a final NULL in alpn_list */
        while( i < (int) sizeof alpn_list - 1 && *p != '\0' )
        {
            alpn_list[i++] = p;

            /* Terminate the current string and move on to next one */
            while( *p != ',' && *p != '\0' )
                p++;
            if( *p == ',' )
                *p++ = '\0';
        }
    }
#endif /* POLARSSL_SSL_ALPN */

    /*
     * 0. Initialize the RNG and the session data
     */
    printf( "\n  . Seeding the random number generator..." );
    fflush( stdout );

    entropy_init( &entropy );
    if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy,
                               (const unsigned char *) pers,
                               strlen( pers ) ) ) != 0 )
    {
        printf( " failed\n  ! ctr_drbg_init returned -0x%x\n", -ret );
        goto exit;
    }

    printf( " ok\n" );

#if defined(POLARSSL_X509_CRT_PARSE_C)
    /*
     * 1.1. Load the trusted CA
     */
    printf( "  . Loading the CA root certificate ..." );
    fflush( stdout );

#if defined(POLARSSL_FS_IO)
    if( strlen( opt.ca_path ) )
        if( strcmp( opt.ca_path, "none" ) == 0 )
            ret = 0;
        else
            ret = x509_crt_parse_path( &cacert, opt.ca_path );
    else if( strlen( opt.ca_file ) )
        if( strcmp( opt.ca_file, "none" ) == 0 )
            ret = 0;
        else
            ret = x509_crt_parse_file( &cacert, opt.ca_file );
    else
#endif
#if defined(POLARSSL_CERTS_C)
        ret = x509_crt_parse( &cacert, (const unsigned char *) test_ca_list,
                strlen( test_ca_list ) );
#else
    {
        ret = 1;
        printf("POLARSSL_CERTS_C not defined.");
    }
#endif
    if( ret < 0 )
    {
        printf( " failed\n  !  x509_crt_parse returned -0x%x\n\n", -ret );
        goto exit;
    }

    printf( " ok (%d skipped)\n", ret );

    /*
     * 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 );

#if defined(POLARSSL_FS_IO)
    if( strlen( opt.crt_file ) )
        if( strcmp( opt.crt_file, "none" ) == 0 )
            ret = 0;
        else
            ret = x509_crt_parse_file( &clicert, opt.crt_file );
    else
#endif
#if defined(POLARSSL_CERTS_C)
        ret = x509_crt_parse( &clicert, (const unsigned char *) test_cli_crt,
                strlen( test_cli_crt ) );
#else
    {
        ret = 1;
        printf("POLARSSL_CERTS_C not defined.");
    }
#endif
    if( ret != 0 )
    {
        printf( " failed\n  !  x509_crt_parse returned -0x%x\n\n", -ret );
        goto exit;
    }

#if defined(POLARSSL_FS_IO)
    if( strlen( opt.key_file ) )
        if( strcmp( opt.key_file, "none" ) == 0 )
            ret = 0;
        else
            ret = pk_parse_keyfile( &pkey, opt.key_file, "" );
    else
#endif
#if defined(POLARSSL_CERTS_C)
        ret = pk_parse_key( &pkey, (const unsigned char *) test_cli_key,
                strlen( test_cli_key ), NULL, 0 );
#else
    {
        ret = 1;
        printf("POLARSSL_CERTS_C not defined.");
    }
#endif
    if( ret != 0 )
    {
        printf( " failed\n  !  pk_parse_key returned -0x%x\n\n", -ret );
        goto exit;
    }

    printf( " ok\n" );
#endif /* POLARSSL_X509_CRT_PARSE_C */

    /*
     * 2. Start the connection
     */
    if( opt.server_addr == NULL)
        opt.server_addr = opt.server_name;

    printf( "  . Connecting to tcp/%s/%-4d...", opt.server_addr,
                                                opt.server_port );
    fflush( stdout );

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

    if( opt.nbio > 0 )
        ret = net_set_nonblock( server_fd );
    else
        ret = net_set_block( server_fd );
    if( ret != 0 )
    {
        printf( " failed\n  ! net_set_(non)block() returned -0x%x\n\n", -ret );
        goto exit;
    }

    printf( " ok\n" );

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

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

    printf( " ok\n" );

#if defined(POLARSSL_X509_CRT_PARSE_C)
    if( opt.debug_level > 0 )
        ssl_set_verify( &ssl, my_verify, NULL );
#endif

    ssl_set_endpoint( &ssl, SSL_IS_CLIENT );
    ssl_set_authmode( &ssl, opt.auth_mode );

#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH)
    if( ( ret = ssl_set_max_frag_len( &ssl, opt.mfl_code ) ) != 0 )
    {
        printf( " failed\n  ! ssl_set_max_frag_len returned %d\n\n", ret );
        goto exit;
    }
#endif

#if defined(POLARSSL_SSL_TRUNCATED_HMAC)
    if( opt.trunc_hmac != 0 )
        if( ( ret = ssl_set_truncated_hmac( &ssl, SSL_TRUNC_HMAC_ENABLED ) ) != 0 )
        {
            printf( " failed\n  ! ssl_set_truncated_hmac returned %d\n\n", ret );
            goto exit;
        }
#endif

#if defined(POLARSSL_SSL_ALPN)
    if( opt.alpn_string != NULL )
        if( ( ret = ssl_set_alpn_protocols( &ssl, alpn_list ) ) != 0 )
        {
            printf( " failed\n  ! ssl_set_alpn_protocols returned %d\n\n", ret );
            goto exit;
        }
#endif

    ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg );
    ssl_set_dbg( &ssl, my_debug, stdout );

    if( opt.nbio == 2 )
        ssl_set_bio( &ssl, my_recv, &server_fd, my_send, &server_fd );
    else
        ssl_set_bio( &ssl, net_recv, &server_fd, net_send, &server_fd );

#if defined(POLARSSL_SSL_SESSION_TICKETS)
    if( ( ret = ssl_set_session_tickets( &ssl, opt.tickets ) ) != 0 )
    {
        printf( " failed\n  ! ssl_set_session_tickets returned %d\n\n", ret );
        goto exit;
    }
#endif

    if( opt.force_ciphersuite[0] != DFL_FORCE_CIPHER )
        ssl_set_ciphersuites( &ssl, opt.force_ciphersuite );

    ssl_set_renegotiation( &ssl, opt.renegotiation );
    ssl_legacy_renegotiation( &ssl, opt.allow_legacy );

#if defined(POLARSSL_X509_CRT_PARSE_C)
    if( strcmp( opt.ca_path, "none" ) != 0 &&
        strcmp( opt.ca_file, "none" ) != 0 )
    {
        ssl_set_ca_chain( &ssl, &cacert, NULL, opt.server_name );
    }
    if( strcmp( opt.crt_file, "none" ) != 0 &&
        strcmp( opt.key_file, "none" ) != 0 )
    {
        if( ( ret = ssl_set_own_cert( &ssl, &clicert, &pkey ) ) != 0 )
        {
            printf( " failed\n  ! ssl_set_own_cert returned %d\n\n", ret );
            goto exit;
        }
    }
#endif

#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
    if( ( ret = ssl_set_psk( &ssl, psk, psk_len,
                             (const unsigned char *) opt.psk_identity,
                             strlen( opt.psk_identity ) ) ) != 0 )
    {
        printf( " failed\n  ! ssl_set_psk returned %d\n\n", ret );
        goto exit;
    }
#endif

#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
    if( ( ret = ssl_set_hostname( &ssl, opt.server_name ) ) != 0 )
    {
        printf( " failed\n  ! ssl_set_hostname returned %d\n\n", ret );
        goto exit;
    }
#endif

    if( opt.min_version != -1 )
        ssl_set_min_version( &ssl, SSL_MAJOR_VERSION_3, opt.min_version );
    if( opt.max_version != -1 )
        ssl_set_max_version( &ssl, SSL_MAJOR_VERSION_3, opt.max_version );

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

    while( ( ret = ssl_handshake( &ssl ) ) != 0 )
    {
        if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
        {
            printf( " failed\n  ! ssl_handshake returned -0x%x\n", -ret );
            if( ret == POLARSSL_ERR_X509_CERT_VERIFY_FAILED )
                printf(
                    "    Unable to verify the server's certificate. "
                        "Either it is invalid,\n"
                    "    or you didn't set ca_file or ca_path "
                        "to an appropriate value.\n"
                    "    Alternatively, you may want to use "
                        "auth_mode=optional for testing purposes.\n" );
            printf( "\n" );
            goto exit;
        }
    }

    printf( " ok\n    [ Protocol is %s ]\n    [ Ciphersuite is %s ]\n",
            ssl_get_version( &ssl ), ssl_get_ciphersuite( &ssl ) );

#if defined(POLARSSL_SSL_ALPN)
    if( opt.alpn_string != NULL )
    {
        const char *alp = ssl_get_alpn_protocol( &ssl );
        printf( "    [ Application Layer Protocol is %s ]\n",
                alp ? alp : "(none)" );
    }
#endif

    if( opt.reconnect != 0 )
    {
        printf("  . Saving session for reuse..." );
        fflush( stdout );

        if( ( ret = ssl_get_session( &ssl, &saved_session ) ) != 0 )
        {
            printf( " failed\n  ! ssl_get_session returned -0x%x\n\n", -ret );
            goto exit;
        }

        printf( " ok\n" );
    }

#if defined(POLARSSL_X509_CRT_PARSE_C)
    /*
     * 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", opt.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" );

    if( ssl_get_peer_cert( &ssl ) != NULL )
    {
        printf( "  . Peer certificate information    ...\n" );
        x509_crt_info( (char *) buf, sizeof( buf ) - 1, "      ",
                       ssl_get_peer_cert( &ssl ) );
        printf( "%s\n", buf );
    }
#endif /* POLARSSL_X509_CRT_PARSE_C */

    if( opt.renegotiate )
    {
        /*
         * Perform renegotiation (this must be done when the server is waiting
         * for input from our side).
         */
        printf( "  . Performing renegotiation..." );
        fflush( stdout );
        while( ( ret = ssl_renegotiate( &ssl ) ) != 0 )
        {
            if( ret != POLARSSL_ERR_NET_WANT_READ &&
                ret != POLARSSL_ERR_NET_WANT_WRITE )
            {
                printf( " failed\n  ! ssl_renegotiate returned %d\n\n", ret );
                goto exit;
            }
        }
        printf( " ok\n" );
    }

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

    if( strcmp( opt.request_page, "SERVERQUIT" ) == 0 )
        len = sprintf( (char *) buf, "%s", opt.request_page );
    else
    {
        size_t tail_len = strlen( GET_REQUEST_END );

        len = snprintf( (char *) buf, sizeof(buf) - 1, GET_REQUEST,
                        opt.request_page );

        /* Add padding to GET request to reach opt.request_size in length */
        if( opt.request_size != DFL_REQUEST_SIZE &&
            len + tail_len < (size_t) opt.request_size )
        {
            memset( buf + len, 'A', opt.request_size - len - tail_len );
            len += opt.request_size - len - tail_len;
        }

        strncpy( (char *) buf + len, GET_REQUEST_END, sizeof(buf) - len - 1 );
        len += tail_len;
    }

    /* Truncate if request size is smaller than the "natural" size */
    if( opt.request_size != DFL_REQUEST_SIZE &&
        len > opt.request_size )
    {
        len = opt.request_size;

        /* Still end with \r\n unless that's really not possible */
        if( len >= 2 ) buf[len - 2] = '\r';
        if( len >= 1 ) buf[len - 1] = '\n';
    }

    for( written = 0, frags = 0; written < len; written += ret, frags++ )
    {
        while( ( ret = ssl_write( &ssl, buf + written, len - written ) ) <= 0 )
        {
            if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
            {
                printf( " failed\n  ! ssl_write returned -0x%x\n\n", -ret );
                goto exit;
            }
        }
    }

    buf[written] = '\0';
    printf( " %d bytes written in %d fragments\n\n%s\n", written, frags, (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_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE )
            continue;

        if( ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY )
            break;

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

        if( ret == 0 )
        {
            printf("\n\nEOF\n\n");
            ssl_close_notify( &ssl );
            break;
        }

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

    if( opt.reconnect != 0 )
    {
        --opt.reconnect;

        net_close( server_fd );

#if defined(POLARSSL_TIMING_C)
        if( opt.reco_delay > 0 )
            m_sleep( 1000 * opt.reco_delay );
#endif

        printf( "  . Reconnecting with saved session..." );
        fflush( stdout );

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

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

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

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

        printf( " ok\n" );

        goto send_request;
    }

exit:
    if( ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY )
        ret = 0;

#ifdef POLARSSL_ERROR_C
    if( ret != 0 )
    {
        char error_buf[100];
        polarssl_strerror( ret, error_buf, 100 );
        printf("Last error was: -0x%X - %s\n\n", -ret, error_buf );
    }
#endif

    if( server_fd )
        net_close( server_fd );
#if defined(POLARSSL_X509_CRT_PARSE_C)
    x509_crt_free( &clicert );
    x509_crt_free( &cacert );
    pk_free( &pkey );
#endif
    ssl_session_free( &saved_session );
    ssl_free( &ssl );
    ctr_drbg_free( &ctr_drbg );
    entropy_free( &entropy );

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

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

    // Shell can not handle large exit numbers -> 1 for errors
    if( ret < 0 )
        ret = 1;

    return( ret );
}
Esempio n. 20
0
static CURLcode
polarssl_connect_step2(struct connectdata *conn,
                     int sockindex)
{
  int ret;
  struct SessionHandle *data = conn->data;
  struct ssl_connect_data* connssl = &conn->ssl[sockindex];
  char buffer[1024];

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

  conn->recv[sockindex] = polarssl_recv;
  conn->send[sockindex] = polarssl_send;

  for(;;) {
    if(!(ret = ssl_handshake(&connssl->ssl)))
      break;
    else if(ret != POLARSSL_ERR_NET_WANT_READ &&
            ret != POLARSSL_ERR_NET_WANT_WRITE) {
#ifdef POLARSSL_ERROR_C
     error_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* POLARSSL_ERROR_C */
     failf(data, "ssl_handshake returned - PolarSSL: (-0x%04X) %s",
                                                    -ret, errorbuf);

     return CURLE_SSL_CONNECT_ERROR;
    }
    else {
      if(ret == POLARSSL_ERR_NET_WANT_READ) {
        connssl->connecting_state = ssl_connect_2_reading;
        return CURLE_OK;
      }
      if(ret == POLARSSL_ERR_NET_WANT_WRITE) {
        connssl->connecting_state = ssl_connect_2_writing;
        return CURLE_OK;
      }
      failf(data, "SSL_connect failed with error %d.", ret);
      return CURLE_SSL_CONNECT_ERROR;

    }
  }

  infof(data, "PolarSSL: Handshake complete, cipher is %s\n",
        ssl_get_ciphersuite(&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");

    if(ret & BADCERT_REVOKED) {
      failf(data, "Cert verify failed: BADCERT_REVOKED");
      return CURLE_SSL_CACERT;
    }

    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_PEER_FAILED_VERIFICATION;
  }

  if(ssl_get_peer_cert(&(connssl->ssl))) {
    /* If the session was resumed, there will be no peer certs */
    memset(buffer, 0, sizeof(buffer));

    if(x509_crt_info(buffer, sizeof(buffer), (char *)"* ",
                     ssl_get_peer_cert(&(connssl->ssl))) != -1)
      infof(data, "Dumping cert info:\n%s\n", buffer);
  }

  connssl->connecting_state = ssl_connect_3;
  infof(data, "SSL connected\n");

  return CURLE_OK;
}
Esempio n. 21
0
/**
  * @brief  SSL client task.
  * @param  pvParameters not used
  * @retval None
  */
void ssl_client(void const * argument)
{
  int ret, len, server_fd;
  unsigned char buf[1024];
  ssl_context ssl;
  x509_cert cacert;
  
  memset( &ssl, 0, sizeof( ssl_context ) );
  memset( &cacert, 0, sizeof( x509_cert ) );
  
  /*
  *  Initialize certificates
  */
  printf( "  . Loading the CA root certificate ..." );
  
#if defined(POLARSSL_CERTS_C)
  ret = x509parse_crt( &cacert, (const unsigned char *) test_ca_crt,
                      strlen( test_ca_crt ) );
#else
  ret = 1;
  printf("POLARSSL_CERTS_C not defined.");
#endif
  
  if( ret < 0 )
  {
    printf( " failed\n  !  x509parse_crt returned -0x%x\n\n", -ret );
    goto exit;
  }
  
  printf( " ok (%d skipped)\n", ret );
  
  /* Start the connection */
  do
  {
    printf(( "\n\rSSL : Start the connection \n\r"));
    printf("\n\rConnecting to tcp/%s/ Port:%4d...", SSL_SERVER_NAME, SSL_SERVER_PORT); 
    
    /* Bint the connection to SSL server port */
    ret = net_connect(&server_fd, SSL_SERVER_NAME, SSL_SERVER_PORT);
    if(ret != 0)
    {
      /* Connection to SSL server failed */
      printf(" failed \n\r ! net_connect returned %d\n\r", -ret);
      
      /* Wait 500 ms until next retry */
      vTaskDelay(500);
    } 
  }while(ret!=0);
  
  printf( " ok\n\r" );
  
  /*
  * 2. Setup stuff
  */
  printf( "  . Setting up the SSL/TLS structure..." );
  
  if( ( ret = ssl_init( &ssl ) ) != 0 )
  {
    printf( " failed\n  ! ssl_init returned %d\n\n\r", ret );
    goto exit;
  }
  
  printf( " ok\n\r" );
  
  ssl_set_endpoint( &ssl, SSL_IS_CLIENT );
  ssl_set_authmode( &ssl, SSL_VERIFY_OPTIONAL );
  ssl_set_ca_chain( &ssl, &cacert, NULL, "PolarSSL Server 1" );
  
  ssl_set_rng( &ssl, RandVal , NULL );
  ssl_set_dbg( &ssl, my_debug, NULL);
  ssl_set_bio( &ssl, net_recv, &server_fd,
              net_send, &server_fd );
  
  /* Set max ssl version to TLS v1.1 because TLS v1.2 needs SHA-256 for HASH
     which is not supported by STM32F417xx Hardware*/
  ssl_set_max_version( &ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_2);
  
  /*
  * Handshake
  */
  printf( "  . Performing the SSL/TLS handshake..." );
  
  while( ( ret = ssl_handshake( &ssl ) ) != 0 )
  {
    if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
    {
      printf( " failed\n  ! ssl_handshake returned -0x%x\n\n\r", -ret );
      goto exit;
    }
  }
  
  printf( " ok\n\r" );
  
  /*
  * Verify the server certificate
  */
  printf( "\n\r  . Verifying peer X.509 certificate..." );
  
  if( ( ret = ssl_get_verify_result( &ssl ) ) != 0 )
  {
    printf( " failed\n\r" );
    
    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", "PolarSSL Server 1" );
    
    if( ( ret & BADCERT_NOT_TRUSTED ) != 0 )
      printf( "  ! self-signed or not signed by a trusted CA\n" );
    
    printf( "\n\r" );
  }
  else
    printf( " ok\n\r" );
  
  /*
  * Write the GET request
  */
  printf( "  > Write to server:" );
  
  len = sprintf( (char *) buf, GET_REQUEST );
  
  while( ( ret = ssl_write( &ssl, buf, len ) ) <= 0 )
  {
    if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
    {
      printf( " failed\n  ! ssl_write returned %d\n\n\r", ret );
      goto exit;
    }
  }
  
  len = ret;
  printf( " %d bytes written\n\n\r%s", len, (char *) buf );
  
  /*
  * Read the HTTP response
  */
  printf( "  < Read from server:" );
  
  do
  {
    len = sizeof( buf ) - 1;
    memset( buf, 0, sizeof( buf ) );
    ret = ssl_read( &ssl, buf, len );
    
    if( ret == POLARSSL_ERR_NET_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE )
      continue;
    
    if( ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY )
      break;
    
    if( ret < 0 )
    {
      printf( "failed\n\r  ! ssl_read returned %d\n\n\r", ret );
      break;
    }
    
    if( ret == 0 )
    {
      printf( "\n\nEOF\n\n\r" );
      break;
    }
    
    len = ret;
    printf( " %d bytes read\n\n\r%s", len, (char *) buf );
  }
  while( 1 );
  
exit:

#ifdef POLARSSL_ERROR_C
  if( ret != 0 )
  {
    char error_buf[100];
    error_strerror( ret, error_buf, 100 );
    printf("Last error was: %d - %s\n\n\r", ret, error_buf );
  }
#endif
  
  x509_free( &cacert );
  net_close( server_fd );
  ssl_free( &ssl );
  
  memset( &ssl, 0, sizeof( ssl ) );
  
  /* Infinite loop */
  for( ;; ) 
  {
    /* Toggle LED1 */
    BSP_LED_Toggle(LED1);
    
    /* Insert 400 ms delay */
    osDelay(400);
  }
}
Esempio n. 22
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;
}
Esempio n. 23
0
int main( int argc, char *argv[] )
{
    int ret = 0, len, written, frags;
    int listen_fd;
    int client_fd = -1;
    unsigned char buf[1024];
#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
    unsigned char psk[256];
    size_t psk_len = 0;
#endif
    const char *pers = "ssl_server2";

    entropy_context entropy;
    ctr_drbg_context ctr_drbg;
    ssl_context ssl;
#if defined(POLARSSL_X509_CRT_PARSE_C)
    x509_crt cacert;
    x509_crt srvcert;
    pk_context pkey;
    x509_crt srvcert2;
    pk_context pkey2;
    int key_cert_init = 0, key_cert_init2 = 0;
#endif
#if defined(POLARSSL_SSL_CACHE_C)
    ssl_cache_context cache;
#endif
#if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C)
    unsigned char alloc_buf[100000];
#endif

    int i;
    char *p, *q;
    const int *list;

#if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C)
    memory_buffer_alloc_init( alloc_buf, sizeof(alloc_buf) );
#endif

    /*
     * Make sure memory references are valid in case we exit early.
     */
    listen_fd = 0;
    memset( &ssl, 0, sizeof( ssl_context ) );
#if defined(POLARSSL_X509_CRT_PARSE_C)
    x509_crt_init( &cacert );
    x509_crt_init( &srvcert );
    pk_init( &pkey );
    x509_crt_init( &srvcert2 );
    pk_init( &pkey2 );
#endif
#if defined(POLARSSL_SSL_CACHE_C)
    ssl_cache_init( &cache );
#endif

    if( argc == 0 )
    {
    usage:
        if( ret == 0 )
            ret = 1;

        printf( USAGE );

        list = ssl_list_ciphersuites();
        while( *list )
        {
            printf(" %-42s", ssl_get_ciphersuite_name( *list ) );
            list++;
            if( !*list )
                break;
            printf(" %s\n", ssl_get_ciphersuite_name( *list ) );
            list++;
        }
        printf("\n");
        goto exit;
    }

    opt.server_addr         = DFL_SERVER_ADDR;
    opt.server_port         = DFL_SERVER_PORT;
    opt.debug_level         = DFL_DEBUG_LEVEL;
    opt.ca_file             = DFL_CA_FILE;
    opt.ca_path             = DFL_CA_PATH;
    opt.crt_file            = DFL_CRT_FILE;
    opt.key_file            = DFL_KEY_FILE;
    opt.crt_file2           = DFL_CRT_FILE2;
    opt.key_file2           = DFL_KEY_FILE2;
    opt.psk                 = DFL_PSK;
    opt.psk_identity        = DFL_PSK_IDENTITY;
    opt.force_ciphersuite[0]= DFL_FORCE_CIPHER;
    opt.renegotiation       = DFL_RENEGOTIATION;
    opt.allow_legacy        = DFL_ALLOW_LEGACY;
    opt.min_version         = DFL_MIN_VERSION;
    opt.max_version         = DFL_MAX_VERSION;
    opt.auth_mode           = DFL_AUTH_MODE;
    opt.mfl_code            = DFL_MFL_CODE;
    opt.tickets             = DFL_TICKETS;

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

        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, "server_addr" ) == 0 )
            opt.server_addr = q;
        else if( strcmp( p, "debug_level" ) == 0 )
        {
            opt.debug_level = atoi( q );
            if( opt.debug_level < 0 || opt.debug_level > 65535 )
                goto usage;
        }
        else if( strcmp( p, "ca_file" ) == 0 )
            opt.ca_file = q;
        else if( strcmp( p, "ca_path" ) == 0 )
            opt.ca_path = q;
        else if( strcmp( p, "crt_file" ) == 0 )
            opt.crt_file = q;
        else if( strcmp( p, "key_file" ) == 0 )
            opt.key_file = q;
        else if( strcmp( p, "crt_file2" ) == 0 )
            opt.crt_file2 = q;
        else if( strcmp( p, "key_file2" ) == 0 )
            opt.key_file2 = q;
        else if( strcmp( p, "psk" ) == 0 )
            opt.psk = q;
        else if( strcmp( p, "psk_identity" ) == 0 )
            opt.psk_identity = q;
        else if( strcmp( p, "force_ciphersuite" ) == 0 )
        {
            opt.force_ciphersuite[0] = -1;

            opt.force_ciphersuite[0] = ssl_get_ciphersuite_id( q );

            if( opt.force_ciphersuite[0] <= 0 )
            {
                ret = 2;
                goto usage;
            }
            opt.force_ciphersuite[1] = 0;
        }
        else if( strcmp( p, "renegotiation" ) == 0 )
        {
            opt.renegotiation = (atoi( q )) ? SSL_RENEGOTIATION_ENABLED :
                                              SSL_RENEGOTIATION_DISABLED;
        }
        else if( strcmp( p, "allow_legacy" ) == 0 )
        {
            opt.allow_legacy = atoi( q );
            if( opt.allow_legacy < 0 || opt.allow_legacy > 1 )
                goto usage;
        }
        else if( strcmp( p, "min_version" ) == 0 )
        {
            if( strcmp( q, "ssl3" ) == 0 )
                opt.min_version = SSL_MINOR_VERSION_0;
            else if( strcmp( q, "tls1" ) == 0 )
                opt.min_version = SSL_MINOR_VERSION_1;
            else if( strcmp( q, "tls1_1" ) == 0 )
                opt.min_version = SSL_MINOR_VERSION_2;
            else if( strcmp( q, "tls1_2" ) == 0 )
                opt.min_version = SSL_MINOR_VERSION_3;
            else
                goto usage;
        }
        else if( strcmp( p, "max_version" ) == 0 )
        {
            if( strcmp( q, "ssl3" ) == 0 )
                opt.max_version = SSL_MINOR_VERSION_0;
            else if( strcmp( q, "tls1" ) == 0 )
                opt.max_version = SSL_MINOR_VERSION_1;
            else if( strcmp( q, "tls1_1" ) == 0 )
                opt.max_version = SSL_MINOR_VERSION_2;
            else if( strcmp( q, "tls1_2" ) == 0 )
                opt.max_version = SSL_MINOR_VERSION_3;
            else
                goto usage;
        }
        else if( strcmp( p, "force_version" ) == 0 )
        {
            if( strcmp( q, "ssl3" ) == 0 )
            {
                opt.min_version = SSL_MINOR_VERSION_0;
                opt.max_version = SSL_MINOR_VERSION_0;
            }
            else if( strcmp( q, "tls1" ) == 0 )
            {
                opt.min_version = SSL_MINOR_VERSION_1;
                opt.max_version = SSL_MINOR_VERSION_1;
            }
            else if( strcmp( q, "tls1_1" ) == 0 )
            {
                opt.min_version = SSL_MINOR_VERSION_2;
                opt.max_version = SSL_MINOR_VERSION_2;
            }
            else if( strcmp( q, "tls1_2" ) == 0 )
            {
                opt.min_version = SSL_MINOR_VERSION_3;
                opt.max_version = SSL_MINOR_VERSION_3;
            }
            else
                goto usage;
        }
        else if( strcmp( p, "auth_mode" ) == 0 )
        {
            if( strcmp( q, "none" ) == 0 )
                opt.auth_mode = SSL_VERIFY_NONE;
            else if( strcmp( q, "optional" ) == 0 )
                opt.auth_mode = SSL_VERIFY_OPTIONAL;
            else if( strcmp( q, "required" ) == 0 )
                opt.auth_mode = SSL_VERIFY_REQUIRED;
            else
                goto usage;
        }
        else if( strcmp( p, "max_frag_len" ) == 0 )
        {
            if( strcmp( q, "512" ) == 0 )
                opt.mfl_code = SSL_MAX_FRAG_LEN_512;
            else if( strcmp( q, "1024" ) == 0 )
                opt.mfl_code = SSL_MAX_FRAG_LEN_1024;
            else if( strcmp( q, "2048" ) == 0 )
                opt.mfl_code = SSL_MAX_FRAG_LEN_2048;
            else if( strcmp( q, "4096" ) == 0 )
                opt.mfl_code = SSL_MAX_FRAG_LEN_4096;
            else
                goto usage;
        }
        else if( strcmp( p, "tickets" ) == 0 )
        {
            opt.tickets = atoi( q );
            if( opt.tickets < 0 || opt.tickets > 1 )
                goto usage;
        }
        else
            goto usage;
    }

    if( opt.force_ciphersuite[0] > 0 )
    {
        const ssl_ciphersuite_t *ciphersuite_info;
        ciphersuite_info = ssl_ciphersuite_from_id( opt.force_ciphersuite[0] );

        if( opt.max_version != -1 &&
            ciphersuite_info->min_minor_ver > opt.max_version )
        {
            printf("forced ciphersuite not allowed with this protocol version\n");
            ret = 2;
            goto usage;
        }
        if( opt.min_version != -1 &&
            ciphersuite_info->max_minor_ver < opt.min_version )
        {
            printf("forced ciphersuite not allowed with this protocol version\n");
            ret = 2;
            goto usage;
        }
        if( opt.max_version > ciphersuite_info->max_minor_ver )
            opt.max_version = ciphersuite_info->max_minor_ver;
        if( opt.min_version < ciphersuite_info->min_minor_ver )
            opt.min_version = ciphersuite_info->min_minor_ver;
    }

#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
    /*
     * Unhexify the pre-shared key if any is given
     */
    if( strlen( opt.psk ) )
    {
        unsigned char c;
        size_t j;

        if( strlen( opt.psk ) % 2 != 0 )
        {
            printf("pre-shared key not valid hex\n");
            goto exit;
        }

        psk_len = strlen( opt.psk ) / 2;

        for( j = 0; j < strlen( opt.psk ); j += 2 )
        {
            c = opt.psk[j];
            if( c >= '0' && c <= '9' )
                c -= '0';
            else if( c >= 'a' && c <= 'f' )
                c -= 'a' - 10;
            else if( c >= 'A' && c <= 'F' )
                c -= 'A' - 10;
            else
            {
                printf("pre-shared key not valid hex\n");
                goto exit;
            }
            psk[ j / 2 ] = c << 4;

            c = opt.psk[j + 1];
            if( c >= '0' && c <= '9' )
                c -= '0';
            else if( c >= 'a' && c <= 'f' )
                c -= 'a' - 10;
            else if( c >= 'A' && c <= 'F' )
                c -= 'A' - 10;
            else
            {
                printf("pre-shared key not valid hex\n");
                goto exit;
            }
            psk[ j / 2 ] |= c;
        }
    }
#endif /* POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED */

    /*
     * 0. Initialize the RNG and the session data
     */
    printf( "\n  . Seeding the random number generator..." );
    fflush( stdout );

    entropy_init( &entropy );
    if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy,
                               (const unsigned char *) pers,
                               strlen( pers ) ) ) != 0 )
    {
        printf( " failed\n  ! ctr_drbg_init returned -0x%x\n", -ret );
        goto exit;
    }

    printf( " ok\n" );

#if defined(POLARSSL_X509_CRT_PARSE_C)
    /*
     * 1.1. Load the trusted CA
     */
    printf( "  . Loading the CA root certificate ..." );
    fflush( stdout );

#if defined(POLARSSL_FS_IO)
    if( strlen( opt.ca_path ) )
        ret = x509_crt_parse_path( &cacert, opt.ca_path );
    else if( strlen( opt.ca_file ) )
        ret = x509_crt_parse_file( &cacert, opt.ca_file );
    else
#endif
#if defined(POLARSSL_CERTS_C)
        ret = x509_crt_parse( &cacert, (const unsigned char *) test_ca_list,
                              strlen( test_ca_list ) );
#else
    {
        ret = 1;
        printf("POLARSSL_CERTS_C not defined.");
    }
#endif
    if( ret < 0 )
    {
        printf( " failed\n  !  x509_crt_parse returned -0x%x\n\n", -ret );
        goto exit;
    }

    printf( " ok (%d skipped)\n", ret );

    /*
     * 1.2. Load own certificate and private key
     */
    printf( "  . Loading the server cert. and key..." );
    fflush( stdout );

#if defined(POLARSSL_FS_IO)
    if( strlen( opt.crt_file ) )
    {
        key_cert_init++;
        if( ( ret = x509_crt_parse_file( &srvcert, opt.crt_file ) ) != 0 )
        {
            printf( " failed\n  !  x509_crt_parse_file returned -0x%x\n\n",
                    -ret );
            goto exit;
        }
    }
    if( strlen( opt.key_file ) )
    {
        key_cert_init++;
        if( ( ret = pk_parse_keyfile( &pkey, opt.key_file, "" ) ) != 0 )
        {
            printf( " failed\n  !  pk_parse_keyfile returned -0x%x\n\n", -ret );
            goto exit;
        }
    }
    if( key_cert_init == 1 )
    {
        printf( " failed\n  !  crt_file without key_file or vice-versa\n\n" );
        goto exit;
    }

    if( strlen( opt.crt_file2 ) )
    {
        key_cert_init2++;
        if( ( ret = x509_crt_parse_file( &srvcert2, opt.crt_file2 ) ) != 0 )
        {
            printf( " failed\n  !  x509_crt_parse_file(2) returned -0x%x\n\n",
                    -ret );
            goto exit;
        }
    }
    if( strlen( opt.key_file2 ) )
    {
        key_cert_init2++;
        if( ( ret = pk_parse_keyfile( &pkey2, opt.key_file2, "" ) ) != 0 )
        {
            printf( " failed\n  !  pk_parse_keyfile(2) returned -0x%x\n\n",
                    -ret );
            goto exit;
        }
    }
    if( key_cert_init2 == 1 )
    {
        printf( " failed\n  !  crt_file2 without key_file2 or vice-versa\n\n" );
        goto exit;
    }
#endif
    if( key_cert_init == 0 && key_cert_init2 == 0 )
    {
#if !defined(POLARSSL_CERTS_C)
        printf( "Not certificated or key provided, and \n"
                "POLARSSL_CERTS_C not defined!\n" );
        goto exit;
#else
#if defined(POLARSSL_RSA_C)
        if( ( ret = x509_crt_parse( &srvcert,
                                    (const unsigned char *) test_srv_crt_rsa,
                                    strlen( test_srv_crt_rsa ) ) ) != 0 )
        {
            printf( " failed\n  !  x509_crt_parse returned -0x%x\n\n", -ret );
            goto exit;
        }
        if( ( ret = pk_parse_key( &pkey,
                                  (const unsigned char *) test_srv_key_rsa,
                                  strlen( test_srv_key_rsa ), NULL, 0 ) ) != 0 )
        {
            printf( " failed\n  !  pk_parse_key returned -0x%x\n\n", -ret );
            goto exit;
        }
        key_cert_init = 2;
#endif /* POLARSSL_RSA_C */
#if defined(POLARSSL_ECDSA_C)
        if( ( ret = x509_crt_parse( &srvcert2,
                                    (const unsigned char *) test_srv_crt_ec,
                                    strlen( test_srv_crt_ec ) ) ) != 0 )
        {
            printf( " failed\n  !  x509_crt_parse2 returned -0x%x\n\n", -ret );
            goto exit;
        }
        if( ( ret = pk_parse_key( &pkey2,
                                  (const unsigned char *) test_srv_key_ec,
                                  strlen( test_srv_key_ec ), NULL, 0 ) ) != 0 )
        {
            printf( " failed\n  !  pk_parse_key2 returned -0x%x\n\n", -ret );
            goto exit;
        }
        key_cert_init2 = 2;
#endif /* POLARSSL_ECDSA_C */
#endif /* POLARSSL_CERTS_C */
    }

    printf( " ok\n" );
#endif /* POLARSSL_X509_CRT_PARSE_C */

    /*
     * 2. Setup the listening TCP socket
     */
    printf( "  . Bind on tcp://localhost:%-4d/ ...", opt.server_port );
    fflush( stdout );

    if( ( ret = net_bind( &listen_fd, opt.server_addr,
                                      opt.server_port ) ) != 0 )
    {
        printf( " failed\n  ! net_bind returned -0x%x\n\n", -ret );
        goto exit;
    }

    printf( " ok\n" );

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

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

    ssl_set_endpoint( &ssl, SSL_IS_SERVER );
    ssl_set_authmode( &ssl, opt.auth_mode );

#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH)
    ssl_set_max_frag_len( &ssl, opt.mfl_code );
#endif

    ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg );
    ssl_set_dbg( &ssl, my_debug, stdout );

#if defined(POLARSSL_SSL_CACHE_C)
    ssl_set_session_cache( &ssl, ssl_cache_get, &cache,
                                 ssl_cache_set, &cache );
#endif

#if defined(POLARSSL_SSL_SESSION_TICKETS)
    ssl_set_session_tickets( &ssl, opt.tickets );
#endif

    if( opt.force_ciphersuite[0] != DFL_FORCE_CIPHER )
        ssl_set_ciphersuites( &ssl, opt.force_ciphersuite );

    ssl_set_renegotiation( &ssl, opt.renegotiation );
    ssl_legacy_renegotiation( &ssl, opt.allow_legacy );

#if defined(POLARSSL_X509_CRT_PARSE_C)
    ssl_set_ca_chain( &ssl, &cacert, NULL, NULL );
    if( key_cert_init )
        ssl_set_own_cert( &ssl, &srvcert, &pkey );
    if( key_cert_init2 )
        ssl_set_own_cert( &ssl, &srvcert2, &pkey2 );
#endif

#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
    ssl_set_psk( &ssl, psk, psk_len, (const unsigned char *) opt.psk_identity,
                 strlen( opt.psk_identity ) );
#endif

#if defined(POLARSSL_DHM_C)
    /*
     * Use different group than default DHM group
     */
    ssl_set_dh_param( &ssl, POLARSSL_DHM_RFC5114_MODP_2048_P,
                            POLARSSL_DHM_RFC5114_MODP_2048_G );
#endif

    if( opt.min_version != -1 )
        ssl_set_min_version( &ssl, SSL_MAJOR_VERSION_3, opt.min_version );

    if( opt.max_version != -1 )
        ssl_set_max_version( &ssl, SSL_MAJOR_VERSION_3, opt.max_version );

    printf( " ok\n" );

reset:
#ifdef POLARSSL_ERROR_C
    if( ret != 0 )
    {
        char error_buf[100];
        polarssl_strerror( ret, error_buf, 100 );
        printf("Last error was: %d - %s\n\n", ret, error_buf );
    }
#endif

    if( client_fd != -1 )
        net_close( client_fd );

    ssl_session_reset( &ssl );

    /*
     * 3. Wait until a client connects
     */
    client_fd = -1;

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

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

    ssl_set_bio( &ssl, net_recv, &client_fd,
                       net_send, &client_fd );

    printf( " ok\n" );

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

    while( ( ret = ssl_handshake( &ssl ) ) != 0 )
    {
        if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
        {
            printf( " failed\n  ! ssl_handshake returned -0x%x\n\n", -ret );
            goto reset;
        }
    }

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

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

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

        if( !ssl_get_peer_cert( &ssl ) )
            printf( "  ! no client certificate sent\n" );

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

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

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

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

    if( ssl_get_peer_cert( &ssl ) )
    {
        printf( "  . Peer certificate information    ...\n" );
        x509_crt_info( (char *) buf, sizeof( buf ) - 1, "      ",
                       ssl_get_peer_cert( &ssl ) );
        printf( "%s\n", buf );
    }
#endif /* POLARSSL_X509_CRT_PARSE_C */

    /*
     * 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_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE )
            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 -0x%x\n", -ret );
                    break;
            }

            break;
        }

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

        if( memcmp( buf, "SERVERQUIT", 10 ) == 0 )
        {
            ret = 0;
            goto exit;
        }

        if( ret > 0 )
            break;
    }
    while( 1 );

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

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

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

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

    buf[written] = '\0';
    printf( " %d bytes written in %d fragments\n\n%s\n", written, frags, (char *) buf );

#ifdef TEST_RENEGO
    /*
     * Request renegotiation (this must be done when the client is still
     * waiting for input from our side).
     */
    printf( "  . Requestion renegotiation..." );
    fflush( stdout );
    while( ( ret = ssl_renegotiate( &ssl ) ) != 0 )
    {
        if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
        {
            printf( " failed\n  ! ssl_renegotiate returned %d\n\n", ret );
            goto exit;
        }
    }

    /*
     * Should be a while loop, not an if, but here we're not actually
     * expecting data from the client, and since we're running tests locally,
     * we can just hope the handshake will finish the during the first call.
     */
    if( ( ret = ssl_read( &ssl, buf, 0 ) ) != 0 )
    {
        if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
        {
            printf( " failed\n  ! ssl_read returned %d\n\n", ret );

            /* Unexpected message probably means client didn't renegotiate */
            if( ret == POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE )
                goto reset;
            else
                goto exit;
        }
    }

    printf( " ok\n" );
#endif

    ret = 0;
    goto reset;

exit:

#ifdef POLARSSL_ERROR_C
    if( ret != 0 )
    {
        char error_buf[100];
        polarssl_strerror( ret, error_buf, 100 );
        printf("Last error was: -0x%X - %s\n\n", -ret, error_buf );
    }
#endif

    net_close( client_fd );
#if defined(POLARSSL_X509_CRT_PARSE_C)
    x509_crt_free( &cacert );
    x509_crt_free( &srvcert );
    pk_free( &pkey );
    x509_crt_free( &srvcert2 );
    pk_free( &pkey2 );
#endif

    ssl_free( &ssl );
    entropy_free( &entropy );

#if defined(POLARSSL_SSL_CACHE_C)
    ssl_cache_free( &cache );
#endif

#if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C)
#if defined(POLARSSL_MEMORY_DEBUG)
    memory_buffer_alloc_status();
#endif
    memory_buffer_alloc_free();
#endif

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

    // Shell can not handle large exit numbers -> 1 for errors
    if( ret < 0 )
        ret = 1;

    return( ret );
}
Esempio n. 24
0
char *mlsc_network_request(char *request, int debug_level) {
    int ret, len, server_fd = -1;
    char tmpbuf[BUFFER_SIZE];
    char *buf = malloc(BUFFER_SIZE);
    const char *pers = "ssl_client1";

    entropy_context entropy;
    ctr_drbg_context ctr_drbg;
    ssl_context ssl;
    x509_crt cacert;

#if defined(POLARSSL_DEBUG_C)
    if (debug_level) debug_set_threshold(1);
#endif

    /*
     * 0. Initialize the RNG and the session data
     */
    memset(&ssl, 0, sizeof(ssl_context));
    x509_crt_init(&cacert);

    if (debug_level) fprintf(stderr, "\n  . Seeding the random number generator...");


    entropy_init(&entropy);
    if ((ret = ctr_drbg_init(&ctr_drbg, entropy_func, &entropy,
                             (const unsigned char *) pers,
                             strlen(pers))) != 0) {
        if (debug_level) fprintf(stderr, " failed\n  ! ctr_drbg_init returned %d\n", ret);
        goto exit;
    }

    if (debug_level) fprintf(stderr, " ok\n");

    /*
     * 0. Initialize certificates
     */
    if (debug_level) fprintf(stderr, "  . Loading the CA root certificate ...");
    fflush(stdout);

#if defined(POLARSSL_CERTS_C)
    ret = x509_crt_parse(&cacert, (const unsigned char *) test_ca_list,
                         strlen(test_ca_list));
#else
    ret = 1;
    if (debug_level) fprintf(stderr, "POLARSSL_CERTS_C not defined.");
#endif

    if (ret < 0) {
        if (debug_level) fprintf(stderr, " failed\n  !  x509_crt_parse returned -0x%x\n\n", -ret);
        goto exit;
    }

    if (debug_level) fprintf(stderr, " ok (%d skipped)\n", ret);

    /*
     * 1. Start the connection
     */
    if (debug_level)
        fprintf(stderr, "  . Connecting to tcp/%s/%4d...", SERVER_NAME,
                SERVER_PORT);

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

    if (debug_level) fprintf(stderr, " ok\n");

    /*
     * 2. Setup stuff
     */
    if (debug_level) fprintf(stderr, "  . Setting up the SSL/TLS structure...");

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

    if (debug_level) fprintf(stderr, " ok\n");

    ssl_set_endpoint(&ssl, SSL_IS_CLIENT);
    /* OPTIONAL is not optimal for security,
     * but makes interop easier in this simplified example */
    ssl_set_authmode(&ssl, SSL_VERIFY_OPTIONAL);
    ssl_set_ca_chain(&ssl, &cacert, NULL, SERVER_NAME);

    ssl_set_rng(&ssl, ctr_drbg_random, &ctr_drbg);
    ssl_set_bio(&ssl, net_recv, &server_fd,
                net_send, &server_fd);

    /*
     * 4. Handshake
     */
    if (debug_level) fprintf(stderr, "  . Performing the SSL/TLS handshake...");

    while ((ret = ssl_handshake(&ssl)) != 0) {
        if (ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE) {
            fprintf(stderr, " failed\n  ! ssl_handshake returned -0x%x\n\n", -ret);
            goto exit;
        }
    }

    if (debug_level) fprintf(stderr, " ok\n");

    /*
     * 5. Verify the server certificate
     */
    if (debug_level) fprintf(stderr, "  . Verifying peer X.509 certificate...");

    /* In real life, we may want to bail out when ret != 0 */
    if ((ret = ssl_get_verify_result(&ssl)) != 0) {
        if (debug_level) fprintf(stderr, " failed\n");

        if ((ret & BADCERT_EXPIRED) != 0 && debug_level) fprintf(stderr, "  ! server certificate has expired\n");

        if ((ret & BADCERT_REVOKED) != 0 && debug_level) fprintf(stderr, "  ! server certificate has been revoked\n");

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

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

        if (debug_level) fprintf(stderr, "\n");
    }
    else if (debug_level) fprintf(stderr, " ok\n");

    /*
     * 3. Write the GET request
     */
    if (debug_level) fprintf(stderr, "  > Write to server:");

    len = sprintf((char *) tmpbuf, POST_REQUEST, strlen(request), request);

    while ((ret = ssl_write(&ssl, tmpbuf, len)) <= 0) {
        if (ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE) {
            if (debug_level) fprintf(stderr, " failed\n  ! ssl_write returned %d\n\n", ret);
            goto exit;
        }
    }

    len = ret;
    if (debug_level) fprintf(stderr, " %d bytes written\n\n%s", len, (char *) tmpbuf);

    /*
     * 7. Read the HTTP response
     */
    if (debug_level) fprintf(stderr, "  < Read from server:");

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

        if (ret == POLARSSL_ERR_NET_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE)
            continue;

        if (ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY)
            break;

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

        if (ret == 0) {
            if (debug_level) fprintf(stderr, "\n\nEOF\n\n");
            break;
        }

        len = ret;
        if (debug_level) fprintf(stderr, " %d bytes read\n\n%s\n", len, (char *) tmpbuf);
        strcpy(buf, tmpbuf);
    }
    while (1);

    ssl_close_notify(&ssl);

    exit:

#ifdef POLARSSL_ERROR_C
    if (ret != 0) {
        char error_buf[100];
        polarssl_strerror(ret, error_buf, 100);
        if (debug_level) fprintf(stderr, "Last error was: %d - %s\n\n", ret, error_buf);
    }
#endif

    if (server_fd != -1)
        net_close(server_fd);

    x509_crt_free(&cacert);
    ssl_free(&ssl);
    ctr_drbg_free(&ctr_drbg);
    entropy_free(&entropy);

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

    return (buf);
}
Esempio n. 25
0
static CURLcode
polarssl_connect_step2(struct connectdata *conn,
                       int sockindex)
{
  int ret;
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data* connssl = &conn->ssl[sockindex];
  char buffer[1024];
  const char * const pinnedpubkey = SSL_IS_PROXY() ?
            data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
            data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];


  char errorbuf[128];
  errorbuf[0] = 0;

  conn->recv[sockindex] = polarssl_recv;
  conn->send[sockindex] = polarssl_send;

  ret = ssl_handshake(&BACKEND->ssl);

  switch(ret) {
  case 0:
    break;

  case POLARSSL_ERR_NET_WANT_READ:
    connssl->connecting_state = ssl_connect_2_reading;
    return CURLE_OK;

  case POLARSSL_ERR_NET_WANT_WRITE:
    connssl->connecting_state = ssl_connect_2_writing;
    return CURLE_OK;

  default:
    error_strerror(ret, errorbuf, sizeof(errorbuf));
    failf(data, "ssl_handshake returned - PolarSSL: (-0x%04X) %s",
          -ret, errorbuf);
    return CURLE_SSL_CONNECT_ERROR;
  }

  infof(data, "PolarSSL: Handshake complete, cipher is %s\n",
        ssl_get_ciphersuite(&BACKEND->ssl) );

  ret = ssl_get_verify_result(&BACKEND->ssl);

  if(ret && SSL_CONN_CONFIG(verifypeer)) {
    if(ret & BADCERT_EXPIRED)
      failf(data, "Cert verify failed: BADCERT_EXPIRED");

    if(ret & BADCERT_REVOKED) {
      failf(data, "Cert verify failed: BADCERT_REVOKED");
      return CURLE_SSL_CACERT;
    }

    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_PEER_FAILED_VERIFICATION;
  }

  if(ssl_get_peer_cert(&(BACKEND->ssl))) {
    /* If the session was resumed, there will be no peer certs */
    memset(buffer, 0, sizeof(buffer));

    if(x509_crt_info(buffer, sizeof(buffer), (char *)"* ",
                     ssl_get_peer_cert(&(BACKEND->ssl))) != -1)
      infof(data, "Dumping cert info:\n%s\n", buffer);
  }

  /* adapted from mbedtls.c */
  if(pinnedpubkey) {
    int size;
    CURLcode result;
    x509_crt *p;
    unsigned char pubkey[PUB_DER_MAX_BYTES];
    const x509_crt *peercert;

    peercert = ssl_get_peer_cert(&BACKEND->ssl);

    if(!peercert || !peercert->raw.p || !peercert->raw.len) {
      failf(data, "Failed due to missing peer certificate");
      return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
    }

    p = calloc(1, sizeof(*p));

    if(!p)
      return CURLE_OUT_OF_MEMORY;

    x509_crt_init(p);

    /* Make a copy of our const peercert because pk_write_pubkey_der
       needs a non-const key, for now.
       https://github.com/ARMmbed/mbedtls/issues/396 */
    if(x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) {
      failf(data, "Failed copying peer certificate");
      x509_crt_free(p);
      free(p);
      return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
    }

    size = pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES);

    if(size <= 0) {
      failf(data, "Failed copying public key from peer certificate");
      x509_crt_free(p);
      free(p);
      return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
    }

    /* pk_write_pubkey_der writes data at the end of the buffer. */
    result = Curl_pin_peer_pubkey(data,
                                  pinnedpubkey,
                                  &pubkey[PUB_DER_MAX_BYTES - size], size);
    if(result) {
      x509_crt_free(p);
      free(p);
      return result;
    }

    x509_crt_free(p);
    free(p);
  }

#ifdef HAS_ALPN
  if(conn->bits.tls_enable_alpn) {
    const char *next_protocol = ssl_get_alpn_protocol(&BACKEND->ssl);

    if(next_protocol != NULL) {
      infof(data, "ALPN, server accepted to use %s\n", next_protocol);

#ifdef USE_NGHTTP2
      if(!strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID,
                  NGHTTP2_PROTO_VERSION_ID_LEN)) {
        conn->negnpn = CURL_HTTP_VERSION_2;
      }
      else
#endif
        if(!strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH)) {
          conn->negnpn = CURL_HTTP_VERSION_1_1;
        }
    }
    else
      infof(data, "ALPN, server did not agree to a protocol\n");
  }
#endif

  connssl->connecting_state = ssl_connect_3;
  infof(data, "SSL connected\n");

  return CURLE_OK;
}
Esempio n. 26
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 );
}