Пример #1
0
static int test_v2(void)
{
    STACK_OF(SSL_CIPHER) *sk, *scsv;
    /* ECDHE-ECDSA-AES256GCM, SSL2_RC4_1238_WITH_MD5,
     * ECDHE-ECDSA-CHACHA20-POLY1305 */
    const unsigned char bytes[] = {0x00, 0x00, 0x35, 0x01, 0x00, 0x80,
                                   0x00, 0x00, 0x33};
    int ret = 0;

    if (!TEST_true(SSL_bytes_to_cipher_list(s, bytes, sizeof(bytes), 1,
                                            &sk, &scsv))
            || !TEST_ptr(sk)
            || !TEST_int_eq(sk_SSL_CIPHER_num(sk), 2)
            || !TEST_ptr(scsv)
            || !TEST_int_eq(sk_SSL_CIPHER_num(scsv), 0))
        goto err;
    if (strcmp(SSL_CIPHER_get_name(sk_SSL_CIPHER_value(sk, 0)),
               "AES256-SHA") != 0 ||
        strcmp(SSL_CIPHER_get_name(sk_SSL_CIPHER_value(sk, 1)),
               "DHE-RSA-AES128-SHA") != 0)
        goto err;

    ret = 1;

err:
    sk_SSL_CIPHER_free(sk);
    sk_SSL_CIPHER_free(scsv);
    return ret;
}
Пример #2
0
char *SSL_make_ciphersuite(pool *p, SSL *ssl)
{
    STACK_OF(SSL_CIPHER) *sk;
    SSL_CIPHER *c;
    int i;
    int l;
    char *cpCipherSuite;
    char *cp;

    if (ssl == NULL) 
        return "";
    if ((sk = SSL_get_ciphers(ssl)) == NULL)
        return "";
    l = 0;
    for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
        c = sk_SSL_CIPHER_value(sk, i);
        l += strlen(c->name)+2+1;
    }
    if (l == 0)
        return "";
    cpCipherSuite = (char *)ap_palloc(p, l+1);
    cp = cpCipherSuite;
    for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
        c = sk_SSL_CIPHER_value(sk, i);
        l = strlen(c->name);
        memcpy(cp, c->name, l);
        cp += l;
        *cp++ = '/';
        *cp++ = (c->valid == 1 ? '1' : '0');
        *cp++ = ':';
    }
    *(cp-1) = NUL;
    return cpCipherSuite;
}
Пример #3
0
static int test_v3(void)
{
    STACK_OF(SSL_CIPHER) *sk = NULL, *scsv = NULL;
    /* ECDHE-ECDSA-AES256GCM, ECDHE-ECDSA-CHACHAPOLY, DHE-RSA-AES256GCM,
     * EMPTY-RENEGOTIATION-INFO-SCSV, FALLBACK-SCSV */
    const unsigned char bytes[] = {0x00, 0x2f, 0x00, 0x33, 0x00, 0x9f, 0x00, 0xff,
                                   0x56, 0x00};
    int ret = 0;

    if (!SSL_bytes_to_cipher_list(s, bytes, sizeof(bytes), 0, &sk, &scsv)
            || !TEST_ptr(sk)
            || !TEST_int_eq(sk_SSL_CIPHER_num(sk), 3)
            || !TEST_ptr(scsv)
            || !TEST_int_eq(sk_SSL_CIPHER_num(scsv), 2)
            || !TEST_str_eq(SSL_CIPHER_get_name(sk_SSL_CIPHER_value(sk, 0)),
                            "AES128-SHA")
            || !TEST_str_eq(SSL_CIPHER_get_name(sk_SSL_CIPHER_value(sk, 1)),
                            "DHE-RSA-AES128-SHA")
            || !TEST_str_eq(SSL_CIPHER_get_name(sk_SSL_CIPHER_value(sk, 2)),
                            "DHE-RSA-AES256-GCM-SHA384")
            || !TEST_str_eq(SSL_CIPHER_get_name(sk_SSL_CIPHER_value(scsv, 0)),
                            "TLS_EMPTY_RENEGOTIATION_INFO_SCSV")
            || !TEST_str_eq(SSL_CIPHER_get_name(sk_SSL_CIPHER_value(scsv, 1)),
                            "TLS_FALLBACK_SCSV"))
        goto err;

    ret = 1;
err:
    sk_SSL_CIPHER_free(sk);
    sk_SSL_CIPHER_free(scsv);
    return ret;
}
Пример #4
0
/** Return true iff the cipher list suggested by the client for <b>ssl</b> is
 * a list that indicates that the client knows how to do the v2 TLS connection
 * handshake. */
static int
tor_tls_client_is_using_v2_ciphers(const SSL *ssl, const char *address)
{
  int i;
  SSL_SESSION *session;
  /* If we reached this point, we just got a client hello.  See if there is
   * a cipher list. */
  if (!(session = SSL_get_session((SSL *)ssl))) {
    log_warn(LD_NET, "No session on TLS?");
    return 0;
  }
  if (!session->ciphers) {
    log_warn(LD_NET, "No ciphers on session");
    return 0;
  }
  /* Now we need to see if there are any ciphers whose presence means we're
   * dealing with an updated Tor. */
  for (i = 0; i < sk_SSL_CIPHER_num(session->ciphers); ++i) {
    SSL_CIPHER *cipher = sk_SSL_CIPHER_value(session->ciphers, i);
    const char *ciphername = SSL_CIPHER_get_name(cipher);
    if (strcmp(ciphername, TLS1_TXT_DHE_RSA_WITH_AES_128_SHA) &&
        strcmp(ciphername, TLS1_TXT_DHE_RSA_WITH_AES_256_SHA) &&
        strcmp(ciphername, SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA) &&
        strcmp(ciphername, "(NONE)")) {
      /* XXXX should be ld_debug */
      log_info(LD_NET, "Got a non-version-1 cipher called '%s'", ciphername);
      // return 1;
      goto dump_list;
    }
  }
  return 0;
 dump_list:
  {
    smartlist_t *elts = smartlist_create();
    char *s;
    for (i = 0; i < sk_SSL_CIPHER_num(session->ciphers); ++i) {
      SSL_CIPHER *cipher = sk_SSL_CIPHER_value(session->ciphers, i);
      const char *ciphername = SSL_CIPHER_get_name(cipher);
      smartlist_add(elts, (char*)ciphername);
    }
    s = smartlist_join_strings(elts, ":", 0, NULL);
    log_info(LD_NET, "Got a non-version-1 cipher list from %s.  It is: '%s'",
             address, s);
    tor_free(s);
    smartlist_free(elts);
  }
  return 1;
}
Пример #5
0
static void print_ciphersuite_data(BIO *io, SSL *ssl, int js)
{
	SSL_SESSION* session = SSL_get_session(ssl);
	long protocol = SSL_version(ssl);
	const char *protocol_name = get_protocol_name(protocol);

	const char *eol = js ? "\\n\\\n" : "\n";
	if(BIO_printf(io, "Version: 0x%lx %s%s", protocol, protocol_name, eol) <= 0)
		err_exit("Write error");

	if(BIO_printf(io, "Current cipher: %s%s", SSL_CIPHER_get_name(SSL_get_current_cipher(ssl)), eol) <= 0)
		err_exit("Write error");

	STACK_OF(SSL_CIPHER) *ciphers = session->ciphers;
	SSL_CIPHER *c;
	int n = sk_SSL_CIPHER_num(ciphers);
	if(BIO_printf(io, "client sent %d ciphers%s", n, eol) <= 0)
		err_exit("Write error");

	int i;
	for (i = 0; i < n; i++)
	{
		c = sk_SSL_CIPHER_value(ciphers, i);
		if(BIO_printf(io, "client [%2d of %2d]: %s%s", i, n, SSL_CIPHER_get_name(c), eol) <= 0)
			err_exit("Write error");
	}
}
Пример #6
0
MONO_API int
mono_btls_ssl_get_ciphers (MonoBtlsSsl *ptr, uint16_t **data)
{
	STACK_OF(SSL_CIPHER) *ciphers;
	int count, i;

	*data = NULL;

	ciphers = SSL_get_ciphers (ptr->ssl);
	if (!ciphers)
		return 0;

	count = (int)sk_SSL_CIPHER_num (ciphers);

	*data = OPENSSL_malloc (2 * count);
	if (!*data)
		return 0;

	for (i = 0; i < count; i++) {
		const SSL_CIPHER *cipher = sk_SSL_CIPHER_value (ciphers, i);
		(*data) [i] = (uint16_t) SSL_CIPHER_get_id (cipher);
	}

	return count;
}
Пример #7
0
static int test_default_cipherlist(SSL_CTX *ctx)
{
    STACK_OF(SSL_CIPHER) *ciphers = NULL;
    SSL *ssl = NULL;
    int i, ret = 0, num_expected_ciphers, num_ciphers;
    uint32_t expected_cipher_id, cipher_id;

    if (ctx == NULL)
        return 0;

    if (!TEST_ptr(ssl = SSL_new(ctx))
            || !TEST_ptr(ciphers = SSL_get1_supported_ciphers(ssl)))
        goto err;

    num_expected_ciphers = OSSL_NELEM(default_ciphers_in_order);
    num_ciphers = sk_SSL_CIPHER_num(ciphers);
    if (!TEST_int_eq(num_ciphers, num_expected_ciphers))
        goto err;

    for (i = 0; i < num_ciphers; i++) {
        expected_cipher_id = default_ciphers_in_order[i];
        cipher_id = SSL_CIPHER_get_id(sk_SSL_CIPHER_value(ciphers, i));
        if (!TEST_int_eq(cipher_id, expected_cipher_id)) {
            TEST_info("Wrong cipher at position %d", i);
            goto err;
        }
    }

    ret = 1;

 err:
    sk_SSL_CIPHER_free(ciphers);
    SSL_free(ssl);
    return ret;
}
Пример #8
0
/*
 * call-seq:
 *    ctx.ciphers => [[name, version, bits, alg_bits], ...]
 */
static VALUE
ossl_sslctx_get_ciphers(VALUE self)
{
    SSL_CTX *ctx;
    STACK_OF(SSL_CIPHER) *ciphers;
    SSL_CIPHER *cipher;
    VALUE ary;
    int i, num;

    Data_Get_Struct(self, SSL_CTX, ctx);
    if(!ctx){
        rb_warning("SSL_CTX is not initialized.");
        return Qnil;
    }
    ciphers = ctx->cipher_list;

    if (!ciphers)
        return rb_ary_new();

    num = sk_SSL_CIPHER_num(ciphers);
    ary = rb_ary_new2(num);
    for(i = 0; i < num; i++){
        cipher = sk_SSL_CIPHER_value(ciphers, i);
        rb_ary_push(ary, ossl_ssl_cipher_to_ary(cipher));
    }
    return ary;
}
Пример #9
0
static int use_ecc(SSL *s)
{
    int i, end;
    unsigned long alg_k, alg_a;
    STACK_OF(SSL_CIPHER) *cipher_stack = NULL;

    /* See if we support any ECC ciphersuites */
    if (s->version == SSL3_VERSION)
        return 0;

    cipher_stack = SSL_get_ciphers(s);
    end = sk_SSL_CIPHER_num(cipher_stack);
    for (i = 0; i < end; i++) {
        const SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i);

        alg_k = c->algorithm_mkey;
        alg_a = c->algorithm_auth;
        if ((alg_k & (SSL_kECDHE | SSL_kECDHEPSK))
                || (alg_a & SSL_aECDSA)
                || c->min_tls >= TLS1_3_VERSION)
            break;
    }

    return i < end;
}
Пример #10
0
static std::unordered_map<uint16_t, std::string> getOpenSSLCipherNames() {
  std::unordered_map<uint16_t, std::string> ret;
  SSL_CTX* ctx = nullptr;
  SSL* ssl = nullptr;

  const SSL_METHOD* meth = SSLv23_server_method();
  OpenSSL_add_ssl_algorithms();

  if ((ctx = SSL_CTX_new(meth)) == nullptr) {
    return ret;
  }
  SCOPE_EXIT {
    SSL_CTX_free(ctx);
  };

  if ((ssl = SSL_new(ctx)) == nullptr) {
    return ret;
  }
  SCOPE_EXIT {
    SSL_free(ssl);
  };

  STACK_OF(SSL_CIPHER)* sk = SSL_get_ciphers(ssl);
  for (int i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
    const SSL_CIPHER* c = sk_SSL_CIPHER_value(sk, i);
    unsigned long id = SSL_CIPHER_get_id(c);
    // OpenSSL 1.0.2 and prior does weird things such as stuff the SSL/TLS
    // version into the top 16 bits. Let's ignore those for now. This is
    // BoringSSL compatible (their id can be cast as uint16_t)
    uint16_t cipherCode = id & 0xffffL;
    ret[cipherCode] = SSL_CIPHER_get_name(c);
  }
  return ret;
}
Пример #11
0
/**
 * Adds Ciphers to the Cipher List structure
 *
 * @param options Options for this run
 * @param ssl_method SSL method to populate ciphers for.
 * @return Boolean: true = success | false = error
 */
int populate_ciphers(struct sslCheckOptions *options, const SSL_METHOD *ssl_method)
{
	struct sslCipher *cipher_ptr;
	int i;
	// STACK_OF is a sign that you should be using C++ :)
	STACK_OF(SSL_CIPHER) *cipher_list;
	SSL_CTX *ctx;
	SSL *ssl = NULL;

	ctx = SSL_CTX_new(ssl_method);
	if (ctx == NULL) {
		printf("%sERROR: Could not create CTX object.%s\n", COL_RED, RESET);
		return false;
	}

	SSL_CTX_set_cipher_list(ctx, "ALL:COMPLEMENTOFALL");

	ssl = SSL_new(ctx);
	if (ssl == NULL) {
		printf("%sERROR: Could not create SSL object.%s\n", COL_RED, RESET);
		SSL_CTX_free(ctx);
		return false;
	}

	cipher_list = SSL_get_ciphers(ssl);

	if (options->ciphers != NULL) {
		cipher_ptr = options->ciphers;
		while (cipher_ptr->next != NULL)
			cipher_ptr = cipher_ptr->next;
	}

	// Create Cipher Struct Entries...
	for (i = 0; i < sk_SSL_CIPHER_num(cipher_list); i++) {
		if (options->ciphers == NULL) {
			options->ciphers = malloc(sizeof(struct sslCipher));
			cipher_ptr = options->ciphers;
		} else {
			cipher_ptr->next = malloc(sizeof(struct sslCipher));
			cipher_ptr = cipher_ptr->next;
		}

		memset(cipher_ptr, 0, sizeof(struct sslCipher));
		cipher_ptr->next = NULL;

		// Add cipher information...
		cipher_ptr->sslMethod = ssl_method;
		cipher_ptr->name = SSL_CIPHER_get_name(sk_SSL_CIPHER_value(cipher_list, i));
		cipher_ptr->version = SSL_CIPHER_get_version(sk_SSL_CIPHER_value(cipher_list, i));
		SSL_CIPHER_description(sk_SSL_CIPHER_value(cipher_list, i), cipher_ptr->description, sizeof(cipher_ptr->description) - 1);
		cipher_ptr->bits = SSL_CIPHER_get_bits(sk_SSL_CIPHER_value(cipher_list, i), &cipher_ptr->alg_bits);
	}

	SSL_free(ssl);
	SSL_CTX_free(ctx);

	return true;
}
Пример #12
0
static int test_unsupported(void)
{
    STACK_OF(SSL_CIPHER) *sk, *scsv;
    /* ECDH-RSA-AES256 (unsupported), ECDHE-ECDSA-AES128, <unassigned> */
    const unsigned char bytes[] = {0xc0, 0x0f, 0x00, 0x2f, 0x01, 0x00};
    int ret = 0;

    if (!TEST_true(SSL_bytes_to_cipher_list(s, bytes, sizeof(bytes),
                                            0, &sk, &scsv))
            || !TEST_ptr(sk)
            || !TEST_int_eq(sk_SSL_CIPHER_num(sk), 1)
            || !TEST_ptr(scsv)
            || !TEST_int_eq(sk_SSL_CIPHER_num(scsv), 0)
            || !TEST_str_eq(SSL_CIPHER_get_name(sk_SSL_CIPHER_value(sk, 0)),
                            "AES128-SHA"))
        goto err;

    ret = 1;
err:
    sk_SSL_CIPHER_free(sk);
    sk_SSL_CIPHER_free(scsv);
    return ret;
}
Пример #13
0
static int ssl23_no_ssl2_ciphers(SSL *s)
	{
	SSL_CIPHER *cipher;
	STACK_OF(SSL_CIPHER) *ciphers;
	int i;
	ciphers = SSL_get_ciphers(s);
	for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++)
		{
		cipher = sk_SSL_CIPHER_value(ciphers, i);
		if (cipher->algorithm_ssl == SSL_SSLV2)
			return 0;
		}
	return 1;
	}
Пример #14
0
int main(void)
{
    SSL_CTX *ctx = SSL_CTX_new(DTLS_method());
    STACK_OF(SSL_CIPHER) *ciphers;
    int i, rv = 0;

    SSL_CTX_set_psk_server_callback(ctx, srvr_psk_callback);
    SSL_CTX_set_psk_client_callback(ctx, clnt_psk_callback);
    SSL_CTX_set_security_level(ctx, 0);

    /* We only care about iterating over each enc/mac; we don't
     * want to repeat the test for each auth/kx variant.
     * So keep life simple and only do (non-DH) PSK. */
    if (!SSL_CTX_set_cipher_list(ctx, "PSK")) {
        fprintf(stderr, "Failed to set PSK cipher list\n");
        goto out;
    }

    ciphers = SSL_CTX_get_ciphers(ctx);
    for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
        const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(ciphers, i);
        const char *cipher_name = SSL_CIPHER_get_name(cipher);

        /* As noted above, only one test for each enc/mac variant. */
        if (strncmp(cipher_name, "PSK-", 4))
            continue;

        rv = mtu_test(ctx, cipher_name, 0);
        if (!rv)
            break;

        printf("DTLS MTU test OK for %s\n", cipher_name);
        if (rv == 1)
            continue;

        /* mtu_test() returns 2 if it used Encrypt-then-MAC */
        rv = mtu_test(ctx, cipher_name, 1);
        if (!rv)
            break;

        printf("DTLS MTU test OK for %s without Encrypt-then-MAC\n", cipher_name);
    }
 out:
    SSL_CTX_free(ctx);

    return !rv;
}
Пример #15
0
static int check_for_krb(void)
{
	SSL_CTX *xx;
	int j;

	xx = SSL_CTX_new(ssl_methods[tls_method - 1]);
	if (xx==NULL)
		return -1;

	for( j=0 ; j<sk_SSL_CIPHER_num(xx->cipher_list) ; j++) {
		SSL_CIPHER *yy = sk_SSL_CIPHER_value(xx->cipher_list,j);
		if ( yy->id>=SSL3_CK_KRB5_DES_64_CBC_SHA &&
		 yy->id<=SSL3_CK_KRB5_RC4_40_MD5 ) {
			LM_INFO("KRB5 cipher %s found\n", yy->name);
			SSL_CTX_free(xx);
			return 1;
		}
	}

	SSL_CTX_free(xx);
	return 0;
}
Пример #16
0
static int test_default_cipherlist(SSL_CTX *ctx)
{
    STACK_OF(SSL_CIPHER) *ciphers;
    SSL *ssl;
    int i, ret = 0, num_expected_ciphers, num_ciphers;
    uint32_t expected_cipher_id, cipher_id;

    ssl = SSL_new(ctx);
    OPENSSL_assert(ssl != NULL);

    ciphers = SSL_get1_supported_ciphers(ssl);
    OPENSSL_assert(ciphers != NULL);
    num_expected_ciphers = OSSL_NELEM(default_ciphers_in_order);
    num_ciphers = sk_SSL_CIPHER_num(ciphers);
    if (num_ciphers != num_expected_ciphers) {
        fprintf(stderr, "Expected %d supported ciphers, got %d.\n",
                num_expected_ciphers, num_ciphers);
        goto err;
    }

    for (i = 0; i < num_ciphers; i++) {
        expected_cipher_id = default_ciphers_in_order[i];
        cipher_id = SSL_CIPHER_get_id(sk_SSL_CIPHER_value(ciphers, i));
        if (cipher_id != expected_cipher_id) {
            fprintf(stderr, "Wrong cipher at position %d: expected %x, "
                    "got %x\n", i, expected_cipher_id, cipher_id);
            goto err;
        }
    }

    ret = 1;

 err:
    sk_SSL_CIPHER_free(ciphers);
    SSL_free(ssl);
    return ret;
}
Пример #17
0
static int test_cipher_name(void)
{
    SSL_CTX *ctx = NULL;
    SSL *ssl = NULL;
    const SSL_CIPHER *c;
    STACK_OF(SSL_CIPHER) *sk = NULL;
    const char *ciphers = "ALL:eNULL", *p, *q, *r;
    int i, id = 0, ret = 0;

    /* tests for invalid input */
    p = SSL_CIPHER_standard_name(NULL);
    if (!TEST_str_eq(p, "(NONE)")) {
        TEST_info("test_cipher_name(std) failed: NULL input doesn't return \"(NONE)\"\n");
        goto err;
    }

    p = OPENSSL_cipher_name(NULL);
    if (!TEST_str_eq(p, "(NONE)")) {
        TEST_info("test_cipher_name(ossl) failed: NULL input doesn't return \"(NONE)\"\n");
        goto err;
    }

    p = OPENSSL_cipher_name("This is not a valid cipher");
    if (!TEST_str_eq(p, "(NONE)")) {
        TEST_info("test_cipher_name(ossl) failed: invalid input doesn't return \"(NONE)\"\n");
        goto err;
    }

    /* tests for valid input */
    ctx = SSL_CTX_new(TLS_server_method());
    if (ctx == NULL) {
        TEST_info("test_cipher_name failed: internal error\n");
        goto err;
    }

    if (!SSL_CTX_set_cipher_list(ctx, ciphers)) {
        TEST_info("test_cipher_name failed: internal error\n");
        goto err;
    }

    ssl = SSL_new(ctx);
    if (ssl == NULL) {
        TEST_info("test_cipher_name failed: internal error\n");
        goto err;
    }

    sk = SSL_get_ciphers(ssl);
    if (sk == NULL) {
        TEST_info("test_cipher_name failed: internal error\n");
        goto err;
    }

    for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
        c = sk_SSL_CIPHER_value(sk, i);
        id = SSL_CIPHER_get_id(c) & 0xFFFF;
        if ((id == 0xFF85) || (id == 0xFF87))
            /* skip GOST2012-GOST8912-GOST891 and GOST2012-NULL-GOST12 */
            continue;
        p = SSL_CIPHER_standard_name(c);
        q = get_std_name_by_id(id);
        if (!TEST_ptr(p)) {
            TEST_info("test_cipher_name failed: expected %s, got NULL, cipher %x\n",
                      q, id);
            goto err;
        }
        /* check if p is a valid standard name */
        if (!TEST_str_eq(p, q)) {
            TEST_info("test_cipher_name(std) failed: expected %s, got %s, cipher %x\n",
                       q, p, id);
            goto err;
        }
        /* test OPENSSL_cipher_name */
        q = SSL_CIPHER_get_name(c);
        r = OPENSSL_cipher_name(p);
        if (!TEST_str_eq(r, q)) {
            TEST_info("test_cipher_name(ossl) failed: expected %s, got %s, cipher %x\n",
                       q, r, id);
            goto err;
        }
    }
    ret = 1;
err:
    SSL_CTX_free(ctx);
    SSL_free(ssl);
    return ret;
}
Пример #18
0
int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
{
	STACK_OF(SSL_CIPHER) *ciphers;
	method_const SSL_METHOD *dtls_method;
	SSL_SESSION *dtls_session;
	SSL *dtls_ssl;
	BIO *dtls_bio;
	int dtlsver = DTLS1_BAD_VER;
	const char *cipher = vpninfo->dtls_cipher;

#ifdef HAVE_DTLS12
	if (!strcmp(cipher, "OC-DTLS1_2-AES128-GCM")) {
		dtlsver = DTLS1_2_VERSION;
		cipher = "AES128-GCM-SHA256";
	} else if (!strcmp(cipher, "OC-DTLS1_2-AES256-GCM")) {
		dtlsver = DTLS1_2_VERSION;
		cipher = "AES256-GCM-SHA384";
#ifndef OPENSSL_NO_PSK
	} else if (!strcmp(cipher, "PSK-NEGOTIATE")) {
		dtlsver = 0; /* Let it negotiate */
#endif
	}
#endif

	if (!vpninfo->dtls_ctx) {
#ifdef HAVE_DTLS12
		dtls_method = DTLS_client_method();
#endif
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
		if (dtlsver == DTLS1_BAD_VER)
			dtls_method = DTLSv1_client_method();
#ifdef HAVE_DTLS12
		else if (dtlsver == DTLS1_2_VERSION)
			dtls_method = DTLSv1_2_client_method();
#endif
#endif
		vpninfo->dtls_ctx = SSL_CTX_new(dtls_method);
		if (!vpninfo->dtls_ctx) {
			vpn_progress(vpninfo, PRG_ERR,
				     _("Initialise DTLSv1 CTX failed\n"));
			openconnect_report_ssl_errors(vpninfo);
			vpninfo->dtls_attempt_period = 0;
			return -EINVAL;
		}
		if (dtlsver) {
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
			if (dtlsver == DTLS1_BAD_VER)
				SSL_CTX_set_options(vpninfo->dtls_ctx, SSL_OP_CISCO_ANYCONNECT);
#else
			if (!SSL_CTX_set_min_proto_version(vpninfo->dtls_ctx, dtlsver) ||
			    !SSL_CTX_set_max_proto_version(vpninfo->dtls_ctx, dtlsver)) {
				vpn_progress(vpninfo, PRG_ERR,
					     _("Set DTLS CTX version failed\n"));
				openconnect_report_ssl_errors(vpninfo);
				SSL_CTX_free(vpninfo->dtls_ctx);
				vpninfo->dtls_ctx = NULL;
				vpninfo->dtls_attempt_period = 0;
				return -EINVAL;
			}
#endif
#if defined (HAVE_DTLS12) && !defined(OPENSSL_NO_PSK)
		} else {
			SSL_CTX_set_psk_client_callback(vpninfo->dtls_ctx, psk_callback);
			/* For PSK we override the DTLS master secret with one derived
			 * from the HTTPS session. */
			if (!SSL_export_keying_material(vpninfo->https_ssl,
							vpninfo->dtls_secret, PSK_KEY_SIZE,
							PSK_LABEL, PSK_LABEL_SIZE, NULL, 0, 0)) {
				vpn_progress(vpninfo, PRG_ERR,
					     _("Failed to generate DTLS key\n"));
				openconnect_report_ssl_errors(vpninfo);
				SSL_CTX_free(vpninfo->dtls_ctx);
				vpninfo->dtls_ctx = NULL;
				vpninfo->dtls_attempt_period = 0;
				return -EINVAL;
			}
			SSL_CTX_add_client_custom_ext(vpninfo->dtls_ctx, DTLS_APP_ID_EXT,
						      pskident_add, pskident_free, vpninfo,
						      pskident_parse, vpninfo);
			/* For SSL_CTX_set_cipher_list() */
			cipher = "PSK";
#endif
		}
		/* If we don't readahead, then we do short reads and throw
		   away the tail of data packets. */
		SSL_CTX_set_read_ahead(vpninfo->dtls_ctx, 1);

		if (!SSL_CTX_set_cipher_list(vpninfo->dtls_ctx, cipher)) {
			vpn_progress(vpninfo, PRG_ERR,
				     _("Set DTLS cipher list failed\n"));
			SSL_CTX_free(vpninfo->dtls_ctx);
			vpninfo->dtls_ctx = NULL;
			vpninfo->dtls_attempt_period = 0;
			return -EINVAL;
		}
	}

	dtls_ssl = SSL_new(vpninfo->dtls_ctx);
	SSL_set_connect_state(dtls_ssl);
	SSL_set_app_data(dtls_ssl, vpninfo);

	if (dtlsver) {
		ciphers = SSL_get_ciphers(dtls_ssl);
		if (dtlsver != 0 && sk_SSL_CIPHER_num(ciphers) != 1) {
			vpn_progress(vpninfo, PRG_ERR, _("Not precisely one DTLS cipher\n"));
			SSL_CTX_free(vpninfo->dtls_ctx);
			SSL_free(dtls_ssl);
			vpninfo->dtls_ctx = NULL;
			vpninfo->dtls_attempt_period = 0;
			return -EINVAL;
		}

		/* We're going to "resume" a session which never existed. Fake it... */
		dtls_session = generate_dtls_session(vpninfo, dtlsver,
						     sk_SSL_CIPHER_value(ciphers, 0));
		if (!dtls_session) {
			SSL_CTX_free(vpninfo->dtls_ctx);
			SSL_free(dtls_ssl);
			vpninfo->dtls_ctx = NULL;
			vpninfo->dtls_attempt_period = 0;
			return -EINVAL;
		}

		/* Add the generated session to the SSL */
		if (!SSL_set_session(dtls_ssl, dtls_session)) {
			vpn_progress(vpninfo, PRG_ERR,
				     _("SSL_set_session() failed with old protocol version 0x%x\n"
				       "Are you using a version of OpenSSL older than 0.9.8m?\n"
				       "See http://rt.openssl.org/Ticket/Display.html?id=1751\n"
				       "Use the --no-dtls command line option to avoid this message\n"),
				     DTLS1_BAD_VER);
			SSL_CTX_free(vpninfo->dtls_ctx);
			SSL_free(dtls_ssl);
			vpninfo->dtls_ctx = NULL;
			vpninfo->dtls_attempt_period = 0;
			SSL_SESSION_free(dtls_session);
			return -EINVAL;
		}

		/* We don't need our own refcount on it any more */
		SSL_SESSION_free(dtls_session);
	}

	dtls_bio = BIO_new_socket(dtls_fd, BIO_NOCLOSE);
	/* Set non-blocking */
	BIO_set_nbio(dtls_bio, 1);
	SSL_set_bio(dtls_ssl, dtls_bio, dtls_bio);

	vpninfo->dtls_ssl = dtls_ssl;

	return 0;
}
Пример #19
0
static int get_server_hello(SSL *s)
	{
	unsigned char *buf;
	unsigned char *p;
	int i,j;
	unsigned long len;
	STACK_OF(SSL_CIPHER) *sk=NULL,*cl, *prio, *allow;

	buf=(unsigned char *)s->init_buf->data;
	p=buf;
	if (s->state == SSL2_ST_GET_SERVER_HELLO_A)
		{
		i=ssl2_read(s,(char *)&(buf[s->init_num]),11-s->init_num);
		if (i < (11-s->init_num)) 
			return(ssl2_part_read(s,SSL_F_GET_SERVER_HELLO,i));
		s->init_num = 11;

		if (*(p++) != SSL2_MT_SERVER_HELLO)
			{
			if (p[-1] != SSL2_MT_ERROR)
				{
				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
				SSLerr(SSL_F_GET_SERVER_HELLO,
					SSL_R_READ_WRONG_PACKET_TYPE);
				}
			else
				SSLerr(SSL_F_GET_SERVER_HELLO,
					SSL_R_PEER_ERROR);
			return(-1);
			}
#ifdef __APPLE_CC__
		/* The Rhapsody 5.5 (a.k.a. MacOS X) compiler bug
		 * workaround. <*****@*****.**> */
		s->hit=(i=*(p++))?1:0;
#else
		s->hit=(*(p++))?1:0;
#endif
		s->s2->tmp.cert_type= *(p++);
		n2s(p,i);
		if (i < s->version) s->version=i;
		n2s(p,i); s->s2->tmp.cert_length=i;
		n2s(p,i); s->s2->tmp.csl=i;
		n2s(p,i); s->s2->tmp.conn_id_length=i;
		s->state=SSL2_ST_GET_SERVER_HELLO_B;
		}

	/* SSL2_ST_GET_SERVER_HELLO_B */
	len = 11 + (unsigned long)s->s2->tmp.cert_length + (unsigned long)s->s2->tmp.csl + (unsigned long)s->s2->tmp.conn_id_length;
	if (len > SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER)
		{
		SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_MESSAGE_TOO_LONG);
		return -1;
		}
	j = (int)len - s->init_num;
	i = ssl2_read(s,(char *)&(buf[s->init_num]),j);
	if (i != j) return(ssl2_part_read(s,SSL_F_GET_SERVER_HELLO,i));
	if (s->msg_callback)
		s->msg_callback(0, s->version, 0, buf, (size_t)len, s, s->msg_callback_arg); /* SERVER-HELLO */

	/* things are looking good */

	p = buf + 11;
	if (s->hit)
		{
		if (s->s2->tmp.cert_length != 0) 
			{
			SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_REUSE_CERT_LENGTH_NOT_ZERO);
			return(-1);
			}
		if (s->s2->tmp.cert_type != 0)
			{
			if (!(s->options &
				SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG))
				{
				SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_REUSE_CERT_TYPE_NOT_ZERO);
				return(-1);
				}
			}
		if (s->s2->tmp.csl != 0)
			{
			SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_REUSE_CIPHER_LIST_NOT_ZERO);
			return(-1);
			}
		}
	else
		{
#ifdef undef
		/* very bad */
		memset(s->session->session_id,0,
			SSL_MAX_SSL_SESSION_ID_LENGTH_IN_BYTES);
		s->session->session_id_length=0;
		*/
#endif

		/* we need to do this in case we were trying to reuse a 
		 * client session but others are already reusing it.
		 * If this was a new 'blank' session ID, the session-id
		 * length will still be 0 */
		if (s->session->session_id_length > 0)
			{
			if (!ssl_get_new_session(s,0))
				{
				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
				return(-1);
				}
			}

		if (ssl2_set_certificate(s,s->s2->tmp.cert_type,
			s->s2->tmp.cert_length,p) <= 0)
			{
			ssl2_return_error(s,SSL2_PE_BAD_CERTIFICATE);
			return(-1);
			}
		p+=s->s2->tmp.cert_length;

		if (s->s2->tmp.csl == 0)
			{
			ssl2_return_error(s,SSL2_PE_NO_CIPHER);
			SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_NO_CIPHER_LIST);
			return(-1);
			}

		/* We have just received a list of ciphers back from the
		 * server.  We need to get the ones that match, then select
		 * the one we want the most :-). */

		/* load the ciphers */
		sk=ssl_bytes_to_cipher_list(s,p,s->s2->tmp.csl,
					    &s->session->ciphers);
		p+=s->s2->tmp.csl;
		if (sk == NULL)
			{
			ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
			SSLerr(SSL_F_GET_SERVER_HELLO,ERR_R_MALLOC_FAILURE);
			return(-1);
			}

		(void)sk_SSL_CIPHER_set_cmp_func(sk,ssl_cipher_ptr_id_cmp);

		/* get the array of ciphers we will accept */
		cl=SSL_get_ciphers(s);
		(void)sk_SSL_CIPHER_set_cmp_func(cl,ssl_cipher_ptr_id_cmp);

		/*
		 * If server preference flag set, choose the first
		 * (highest priority) cipher the server sends, otherwise
		 * client preference has priority.
		 */
		if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE)
		    {
		    prio = sk;
		    allow = cl;
		    }
		else
		    {
		    prio = cl;
		    allow = sk;
		    }
		/* In theory we could have ciphers sent back that we
		 * don't want to use but that does not matter since we
		 * will check against the list we originally sent and
		 * for performance reasons we should not bother to match
		 * the two lists up just to check. */
		for (i=0; i<sk_SSL_CIPHER_num(prio); i++)
			{
			if (sk_SSL_CIPHER_find(allow,
					     sk_SSL_CIPHER_value(prio,i)) >= 0)
				break;
			}

		if (i >= sk_SSL_CIPHER_num(prio))
			{
			ssl2_return_error(s,SSL2_PE_NO_CIPHER);
			SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_NO_CIPHER_MATCH);
			return(-1);
			}
		s->session->cipher=sk_SSL_CIPHER_value(prio,i);


		if (s->session->peer != NULL) /* can't happen*/
			{
			ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
			SSLerr(SSL_F_GET_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
			return(-1);
			}

		s->session->peer = s->session->sess_cert->peer_key->x509;
		/* peer_key->x509 has been set by ssl2_set_certificate. */
		CRYPTO_add(&s->session->peer->references, 1, CRYPTO_LOCK_X509);
		}

	if (s->session->sess_cert == NULL 
      || s->session->peer != s->session->sess_cert->peer_key->x509)
		/* can't happen */
		{
		ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
		SSLerr(SSL_F_GET_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
		return(-1);
		}
		
	s->s2->conn_id_length=s->s2->tmp.conn_id_length;
	if (s->s2->conn_id_length > sizeof s->s2->conn_id)
		{
		ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
		SSLerr(SSL_F_GET_SERVER_HELLO, SSL_R_SSL2_CONNECTION_ID_TOO_LONG);
		return -1;
		}
	memcpy(s->s2->conn_id,p,s->s2->tmp.conn_id_length);
	return(1);
	}
Пример #20
0
extern STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,
    const unsigned char *p, int num);
extern int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk,
    unsigned char *p);

static int
ssl_bytes_to_list_alloc(SSL *s, STACK_OF(SSL_CIPHER) **ciphers)
{
	SSL_CIPHER *cipher;
	uint16_t value;
	int i;

	*ciphers = ssl_bytes_to_cipher_list(s, cipher_bytes,
	    sizeof(cipher_bytes));
	CHECK(*ciphers != NULL);
	CHECK(sk_SSL_CIPHER_num(*ciphers) == N_CIPHERS);
	for (i = 0; i < sk_SSL_CIPHER_num(*ciphers); i++) {
		cipher = sk_SSL_CIPHER_value(*ciphers, i);
		CHECK(cipher != NULL);
		value = SSL_CIPHER_get_value(cipher);
		CHECK(value == cipher_values[i]);
	}

	return 1;
}

static int
ssl_list_to_bytes_scsv(SSL *s, STACK_OF(SSL_CIPHER) **ciphers)
{
	unsigned char *buf = NULL;
	size_t buflen;
Пример #21
0
int ssl_prepare_clienthello_tlsext(SSL *s)
	{
#ifndef OPENSSL_NO_EC
	/* If we are client and using an elliptic curve cryptography cipher suite, send the point formats 
	 * and elliptic curves we support.
	 */
	int using_ecc = 0;
	int i;
	unsigned char *j;
	unsigned long alg_k, alg_a;
	STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(s);

	for (i = 0; i < sk_SSL_CIPHER_num(cipher_stack); i++)
		{
		SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i);

		alg_k = c->algorithm_mkey;
		alg_a = c->algorithm_auth;
		if ((alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe) || (alg_a & SSL_aECDSA)))
			{
			using_ecc = 1;
			break;
			}
		}
	using_ecc = using_ecc && (s->version == TLS1_VERSION);
	if (using_ecc)
		{
		if (s->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->tlsext_ecpointformatlist);
		if ((s->tlsext_ecpointformatlist = OPENSSL_malloc(3)) == NULL)
			{
			SSLerr(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT,ERR_R_MALLOC_FAILURE);
			return -1;
			}
		s->tlsext_ecpointformatlist_length = 3;
		s->tlsext_ecpointformatlist[0] = TLSEXT_ECPOINTFORMAT_uncompressed;
		s->tlsext_ecpointformatlist[1] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime;
		s->tlsext_ecpointformatlist[2] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2;

		/* we support all named elliptic curves in draft-ietf-tls-ecc-12 */
		if (s->tlsext_ellipticcurvelist != NULL) OPENSSL_free(s->tlsext_ellipticcurvelist);
		s->tlsext_ellipticcurvelist_length = sizeof(nid_list)/sizeof(nid_list[0]) * 2;
		if ((s->tlsext_ellipticcurvelist = OPENSSL_malloc(s->tlsext_ellipticcurvelist_length)) == NULL)
			{
			s->tlsext_ellipticcurvelist_length = 0;
			SSLerr(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT,ERR_R_MALLOC_FAILURE);
			return -1;
			}
		for (i = 1, j = s->tlsext_ellipticcurvelist; (unsigned int)i <=
				sizeof(nid_list)/sizeof(nid_list[0]); i++)
			s2n(i,j);
		}
#endif /* OPENSSL_NO_EC */

#ifdef TLSEXT_TYPE_opaque_prf_input
 	{
		int r = 1;
	
		if (s->ctx->tlsext_opaque_prf_input_callback != 0)
			{
			r = s->ctx->tlsext_opaque_prf_input_callback(s, NULL, 0, s->ctx->tlsext_opaque_prf_input_callback_arg);
			if (!r)
				return -1;
			}

		if (s->tlsext_opaque_prf_input != NULL)
			{
			if (s->s3->client_opaque_prf_input != NULL) /* shouldn't really happen */
				OPENSSL_free(s->s3->client_opaque_prf_input);

			if (s->tlsext_opaque_prf_input_len == 0)
				s->s3->client_opaque_prf_input = OPENSSL_malloc(1); /* dummy byte just to get non-NULL */
			else
				s->s3->client_opaque_prf_input = BUF_memdup(s->tlsext_opaque_prf_input, s->tlsext_opaque_prf_input_len);
			if (s->s3->client_opaque_prf_input == NULL)
				{
				SSLerr(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT,ERR_R_MALLOC_FAILURE);
				return -1;
				}
			s->s3->client_opaque_prf_input_len = s->tlsext_opaque_prf_input_len;
			}

		if (r == 2)
			/* at callback's request, insist on receiving an appropriate server opaque PRF input */
			s->s3->server_opaque_prf_input_len = s->tlsext_opaque_prf_input_len;
	}
#endif

	return 1;
	}
int
main(int argc, char **argv)
{
  if (argc != 3) {
    usage(argv[0]);
  }

  BIO *bio_err=BIO_new_fp(stderr, BIO_NOCLOSE);
  if (bio_err == NULL) {
    perror("BIO_ne_fp(stderr)");
    exit(1);
  }

  //+ Features TLS-Client-OpenSSL-Init
  // The following call prints an error message and calls exit() if
  // the OpenSSL configuration file is unreadable.
  OPENSSL_config(NULL);
  // Provide human-readable error messages.
  SSL_load_error_strings();
  // Register ciphers.
  SSL_library_init();
  //-

  //+ Features TLS-Client-OpenSSL-CTX
  // Configure a client connection context.  Send a hendshake for the
  // highest supported TLS version, and disable compression.
  const SSL_METHOD *const req_method = SSLv23_client_method();
  SSL_CTX *const ctx = SSL_CTX_new(req_method);
  if (ctx == NULL) {
    ERR_print_errors(bio_err);
    exit(1);
  }
  SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_COMPRESSION);

  // Adjust the ciphers list based on a whitelist.  First enable all
  // ciphers of at least medium strength, to get the list which is
  // compiled into OpenSSL.
  if (SSL_CTX_set_cipher_list(ctx, "HIGH:MEDIUM") != 1) {
    ERR_print_errors(bio_err);
    exit(1);
  }
  {
    // Create a dummy SSL session to obtain the cipher list.
    SSL *ssl = SSL_new(ctx);
    if (ssl == NULL) {
      ERR_print_errors(bio_err);
      exit(1);
    }
    STACK_OF(SSL_CIPHER) *active_ciphers = SSL_get_ciphers(ssl);
    if (active_ciphers == NULL) {
      ERR_print_errors(bio_err);
      exit(1);
    }
    // Whitelist of candidate ciphers.
    static const char *const candidates[] =  {
      "AES128-GCM-SHA256", "AES128-SHA256", "AES256-SHA256", // strong ciphers
      "AES128-SHA", "AES256-SHA", // strong ciphers, also in older versions
      "RC4-SHA", "RC4-MD5", // backwards compatibility, supposed to be weak
      "DES-CBC3-SHA", "DES-CBC3-MD5", // more backwards compatibility
      NULL
    };
    // Actually selected ciphers.
    char ciphers[300];
    ciphers[0] = '\0';
    for (const char *const *c = candidates; *c; ++c) {
      for (int i = 0; i < sk_SSL_CIPHER_num(active_ciphers); ++i) {
	if (strcmp(SSL_CIPHER_get_name(sk_SSL_CIPHER_value(active_ciphers, i)),
		   *c) == 0) {
	  if (*ciphers) {
	    strcat(ciphers, ":");
	  }
	  strcat(ciphers, *c);
	  break;
	}
      }
    }
    SSL_free(ssl);
    // Apply final cipher list.
    if (SSL_CTX_set_cipher_list(ctx, ciphers) != 1) {
      ERR_print_errors(bio_err);
      exit(1);
    }
  }

  // Load the set of trusted root certificates.
  if (!SSL_CTX_set_default_verify_paths(ctx)) {
    ERR_print_errors(bio_err);
    exit(1);
  }
  //-

  const char *host = argv[1];
  const char *service = argv[2];
  // Perform name lookup, create the TCP client socket, and connect to
  // the server.
  int sockfd = tcp_connect(host, service);
  if (sockfd < 0) {
    perror("connect");
    exit(1);
  }
  // Deactivate the Nagle algorithm.
  //+ Features TLS-Nagle
  const int val = 1;
  int ret = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
  if (ret < 0) {
    perror("setsockopt(TCP_NODELAY)");
    exit(1);
  }
  //-
  //+ Features TLS-Client-OpenSSL-Connect
  // Create the connection object.
  SSL *ssl = SSL_new(ctx);
  if (ssl == NULL) {
    ERR_print_errors(bio_err);
    exit(1);
  }
  SSL_set_fd(ssl, sockfd);

  // Enable the ServerNameIndication extension
  if (!SSL_set_tlsext_host_name(ssl, host)) {
    ERR_print_errors(bio_err);
    exit(1);
  }

  // Perform the TLS handshake with the server.
  ret = SSL_connect(ssl);
  if (ret != 1) {
    // Error status can be 0 or negative.
    ssl_print_error_and_exit(ssl, "SSL_connect", ret);
  }

  // Obtain the server certificate.
  X509 *peercert = SSL_get_peer_certificate(ssl);
  if (peercert == NULL) {
    fprintf(stderr, "peer certificate missing");
    exit(1);
  }

  // Check the certificate verification result.  Allow an explicit
  // certificate validation override in case verification fails.
  int verifystatus = SSL_get_verify_result(ssl);
  if (verifystatus != X509_V_OK && !certificate_validity_override(peercert)) {
    fprintf(stderr, "SSL_connect: verify result: %s\n",
	    X509_verify_cert_error_string(verifystatus));
    exit(1);
  }

  // Check if the server certificate matches the host name used to
  // establish the connection.
  // FIXME: Currently needs OpenSSL 1.1.
  if (X509_check_host(peercert, (const unsigned char *)host, strlen(host),
		      0) != 1
      && !certificate_host_name_override(peercert, host)) {
    fprintf(stderr, "SSL certificate does not match host name\n");
    exit(1);
  }

  X509_free(peercert);

  //-
  //+ Features TLS-Client-OpenSSL-Connection-Use
  const char *const req = "GET / HTTP/1.0\r\n\r\n";
  if (SSL_write(ssl, req, strlen(req)) < 0) {
    ssl_print_error_and_exit(ssl, "SSL_write", ret);
  }
  char buf[4096];
  ret = SSL_read(ssl, buf, sizeof(buf));
  if (ret < 0) {
    ssl_print_error_and_exit(ssl, "SSL_read", ret);
  }
  //-
  write(STDOUT_FILENO, buf, ret);
  //+ Features TLS-OpenSSL-Connection-Close
  // Send the close_notify alert.
  ret = SSL_shutdown(ssl);
  switch (ret) {
  case 1:
    // A close_notify alert has already been received.
    break;
  case 0:
    // Wait for the close_notify alert from the peer.
    ret = SSL_shutdown(ssl);
    switch (ret) {
    case 0:
      fprintf(stderr, "info: second SSL_shutdown returned zero\n");
      break;
    case 1:
      break;
    default:
      ssl_print_error_and_exit(ssl, "SSL_shutdown 2", ret);
    }
    break;
  default:
    ssl_print_error_and_exit(ssl, "SSL_shutdown 1", ret);
  }
  SSL_free(ssl);
  close(sockfd);
  //-
  //+ Features TLS-OpenSSL-Context-Close
  SSL_CTX_free(ctx);
  //-
  BIO_free(bio_err);
  return 0;
}
Пример #23
0
int MAIN(int argc, char **argv)
{
    int ret = 1, i;
    int verbose = 0, Verbose = 0;
    const char **pp;
    const char *p;
    int badops = 0;
    SSL_CTX *ctx = NULL;
    SSL *ssl = NULL;
    char *ciphers = NULL;
    const SSL_METHOD *meth = NULL;
    STACK_OF(SSL_CIPHER) *sk;
    char buf[512];
    BIO *STDout = NULL;

    meth = SSLv23_server_method();

    apps_startup();

    if (bio_err == NULL)
        bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
    STDout = BIO_new_fp(stdout, BIO_NOCLOSE);
#ifdef OPENSSL_SYS_VMS
    {
        BIO *tmpbio = BIO_new(BIO_f_linebuffer());
        STDout = BIO_push(tmpbio, STDout);
    }
#endif
    if (!load_config(bio_err, NULL))
        goto end;

    argc--;
    argv++;
    while (argc >= 1) {
        if (strcmp(*argv, "-v") == 0)
            verbose = 1;
        else if (strcmp(*argv, "-V") == 0)
            verbose = Verbose = 1;
#ifndef OPENSSL_NO_SSL2
        else if (strcmp(*argv, "-ssl2") == 0)
            meth = SSLv2_client_method();
#endif
#ifndef OPENSSL_NO_SSL3
        else if (strcmp(*argv, "-ssl3") == 0)
            meth = SSLv3_client_method();
#endif
#ifndef OPENSSL_NO_TLS1
        else if (strcmp(*argv, "-tls1") == 0)
            meth = TLSv1_client_method();
#endif
        else if ((strncmp(*argv, "-h", 2) == 0) || (strcmp(*argv, "-?") == 0)) {
            badops = 1;
            break;
        } else {
            ciphers = *argv;
        }
        argc--;
        argv++;
    }

    if (badops) {
        for (pp = ciphers_usage; (*pp != NULL); pp++)
            BIO_printf(bio_err, "%s", *pp);
        goto end;
    }

    OpenSSL_add_ssl_algorithms();

    ctx = SSL_CTX_new(meth);
    if (ctx == NULL)
        goto err;
    if (ciphers != NULL) {
        if (!SSL_CTX_set_cipher_list(ctx, ciphers)) {
            BIO_printf(bio_err, "Error in cipher list\n");
            goto err;
        }
    }
    ssl = SSL_new(ctx);
    if (ssl == NULL)
        goto err;

    if (!verbose) {
        for (i = 0;; i++) {
            p = SSL_get_cipher_list(ssl, i);
            if (p == NULL)
                break;
            if (i != 0)
                BIO_printf(STDout, ":");
            BIO_printf(STDout, "%s", p);
        }
        BIO_printf(STDout, "\n");
    } else {                    /* verbose */

        sk = SSL_get_ciphers(ssl);

        for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
            SSL_CIPHER *c;

            c = sk_SSL_CIPHER_value(sk, i);

            if (Verbose) {
                unsigned long id = c->id;
                int id0 = (int)(id >> 24);
                int id1 = (int)((id >> 16) & 0xffL);
                int id2 = (int)((id >> 8) & 0xffL);
                int id3 = (int)(id & 0xffL);

                if ((id & 0xff000000L) == 0x02000000L) {
                    /* SSL2 cipher */
                    BIO_printf(STDout, "     0x%02X,0x%02X,0x%02X - ", id1,
                               id2, id3);
                } else if ((id & 0xff000000L) == 0x03000000L) {
                    /* SSL3 cipher */
                    BIO_printf(STDout, "          0x%02X,0x%02X - ", id2,
                               id3);
                } else {
                    /* whatever */
                    BIO_printf(STDout, "0x%02X,0x%02X,0x%02X,0x%02X - ", id0,
                               id1, id2, id3);
                }
            }

            BIO_puts(STDout, SSL_CIPHER_description(c, buf, sizeof buf));
        }
    }

    ret = 0;
    if (0) {
 err:
        SSL_load_error_strings();
        ERR_print_errors(bio_err);
    }
 end:
    if (ctx != NULL)
        SSL_CTX_free(ctx);
    if (ssl != NULL)
        SSL_free(ssl);
    if (STDout != NULL)
        BIO_free_all(STDout);
    apps_shutdown();
    OPENSSL_EXIT(ret);
}
Пример #24
0
const SSL_CIPHER *ssl3_choose_cipher(
    SSL *ssl, const struct ssl_early_callback_ctx *client_hello,
    const struct ssl_cipher_preference_list_st *server_pref) {
  const SSL_CIPHER *c, *ret = NULL;
  STACK_OF(SSL_CIPHER) *srvr = server_pref->ciphers, *prio, *allow;
  int ok;
  size_t cipher_index;
  uint32_t alg_k, alg_a, mask_k, mask_a;
  /* in_group_flags will either be NULL, or will point to an array of bytes
   * which indicate equal-preference groups in the |prio| stack. See the
   * comment about |in_group_flags| in the |ssl_cipher_preference_list_st|
   * struct. */
  const uint8_t *in_group_flags;
  /* group_min contains the minimal index so far found in a group, or -1 if no
   * such value exists yet. */
  int group_min = -1;

  STACK_OF(SSL_CIPHER) *clnt = ssl_parse_client_cipher_list(client_hello);
  if (clnt == NULL) {
    return NULL;
  }

  if (ssl->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
    prio = srvr;
    in_group_flags = server_pref->in_group_flags;
    allow = clnt;
  } else {
    prio = clnt;
    in_group_flags = NULL;
    allow = srvr;
  }

  ssl_get_compatible_server_ciphers(ssl, &mask_k, &mask_a);

  for (size_t i = 0; i < sk_SSL_CIPHER_num(prio); i++) {
    c = sk_SSL_CIPHER_value(prio, i);

    ok = 1;

    /* Check the TLS version. */
    if (SSL_CIPHER_get_min_version(c) > ssl3_protocol_version(ssl) ||
        SSL_CIPHER_get_max_version(c) < ssl3_protocol_version(ssl)) {
      ok = 0;
    }

    alg_k = c->algorithm_mkey;
    alg_a = c->algorithm_auth;

    ok = ok && (alg_k & mask_k) && (alg_a & mask_a);

    if (ok && sk_SSL_CIPHER_find(allow, &cipher_index, c)) {
      if (in_group_flags != NULL && in_group_flags[i] == 1) {
        /* This element of |prio| is in a group. Update the minimum index found
         * so far and continue looking. */
        if (group_min == -1 || (size_t)group_min > cipher_index) {
          group_min = cipher_index;
        }
      } else {
        if (group_min != -1 && (size_t)group_min < cipher_index) {
          cipher_index = group_min;
        }
        ret = sk_SSL_CIPHER_value(allow, cipher_index);
        break;
      }
    }

    if (in_group_flags != NULL && in_group_flags[i] == 0 && group_min != -1) {
      /* We are about to leave a group, but we found a match in it, so that's
       * our answer. */
      ret = sk_SSL_CIPHER_value(allow, group_min);
      break;
    }
  }

  sk_SSL_CIPHER_free(clnt);
  return ret;
}
Пример #25
0
int ciphers_main(int argc, char **argv)
{
    SSL_CTX *ctx = NULL;
    SSL *ssl = NULL;
    STACK_OF(SSL_CIPHER) *sk = NULL;
    const SSL_METHOD *meth = TLS_server_method();
    int ret = 1, i, verbose = 0, Verbose = 0, use_supported = 0;
#ifndef OPENSSL_NO_SSL_TRACE
    int stdname = 0;
#endif
#ifndef OPENSSL_NO_PSK
    int psk = 0;
#endif
#ifndef OPENSSL_NO_SRP
    int srp = 0;
#endif
    const char *p;
    char *ciphers = NULL, *prog;
    char buf[512];
    OPTION_CHOICE o;
    int min_version = 0, max_version = 0;

    prog = opt_init(argc, argv, ciphers_options);
    while ((o = opt_next()) != OPT_EOF) {
        switch (o) {
        case OPT_EOF:
        case OPT_ERR:
 opthelp:
            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
            goto end;
        case OPT_HELP:
            opt_help(ciphers_options);
            ret = 0;
            goto end;
        case OPT_V:
            verbose = 1;
            break;
        case OPT_UPPER_V:
            verbose = Verbose = 1;
            break;
        case OPT_S:
            use_supported = 1;
            break;
        case OPT_STDNAME:
#ifndef OPENSSL_NO_SSL_TRACE
            stdname = verbose = 1;
#endif
            break;
        case OPT_SSL3:
            min_version = SSL3_VERSION;
            max_version = SSL3_VERSION;
            break;
        case OPT_TLS1:
            min_version = TLS1_VERSION;
            max_version = TLS1_VERSION;
            break;
        case OPT_TLS1_1:
            min_version = TLS1_1_VERSION;
            max_version = TLS1_1_VERSION;
            break;
        case OPT_TLS1_2:
            min_version = TLS1_2_VERSION;
            max_version = TLS1_2_VERSION;
            break;
        case OPT_TLS1_3:
            min_version = TLS1_3_VERSION;
            max_version = TLS1_3_VERSION;
            break;
        case OPT_PSK:
#ifndef OPENSSL_NO_PSK
            psk = 1;
#endif
            break;
        case OPT_SRP:
#ifndef OPENSSL_NO_SRP
            srp = 1;
#endif
            break;
        }
    }
    argv = opt_rest();
    argc = opt_num_rest();

    if (argc == 1)
        ciphers = *argv;
    else if (argc != 0)
        goto opthelp;

    ctx = SSL_CTX_new(meth);
    if (ctx == NULL)
        goto err;
    if (SSL_CTX_set_min_proto_version(ctx, min_version) == 0)
        goto err;
    if (SSL_CTX_set_max_proto_version(ctx, max_version) == 0)
        goto err;

#ifndef OPENSSL_NO_PSK
    if (psk)
        SSL_CTX_set_psk_client_callback(ctx, dummy_psk);
#endif
#ifndef OPENSSL_NO_SRP
    if (srp)
        SSL_CTX_set_srp_client_pwd_callback(ctx, dummy_srp);
#endif
    if (ciphers != NULL) {
        if (!SSL_CTX_set_cipher_list(ctx, ciphers)) {
            BIO_printf(bio_err, "Error in cipher list\n");
            goto err;
        }
    }
    ssl = SSL_new(ctx);
    if (ssl == NULL)
        goto err;

    if (use_supported)
        sk = SSL_get1_supported_ciphers(ssl);
    else
        sk = SSL_get_ciphers(ssl);

    if (!verbose) {
        for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
            const SSL_CIPHER *c = sk_SSL_CIPHER_value(sk, i);
            p = SSL_CIPHER_get_name(c);
            if (p == NULL)
                break;
            if (i != 0)
                BIO_printf(bio_out, ":");
            BIO_printf(bio_out, "%s", p);
        }
        BIO_printf(bio_out, "\n");
    } else {

        for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
            const SSL_CIPHER *c;

            c = sk_SSL_CIPHER_value(sk, i);

            if (Verbose) {
                unsigned long id = SSL_CIPHER_get_id(c);
                int id0 = (int)(id >> 24);
                int id1 = (int)((id >> 16) & 0xffL);
                int id2 = (int)((id >> 8) & 0xffL);
                int id3 = (int)(id & 0xffL);

                if ((id & 0xff000000L) == 0x03000000L)
                    BIO_printf(bio_out, "          0x%02X,0x%02X - ", id2, id3); /* SSL3
                                                                                  * cipher */
                else
                    BIO_printf(bio_out, "0x%02X,0x%02X,0x%02X,0x%02X - ", id0, id1, id2, id3); /* whatever */
            }
#ifndef OPENSSL_NO_SSL_TRACE
            if (stdname) {
                const char *nm = SSL_CIPHER_standard_name(c);
                if (nm == NULL)
                    nm = "UNKNOWN";
                BIO_printf(bio_out, "%s - ", nm);
            }
#endif
            BIO_puts(bio_out, SSL_CIPHER_description(c, buf, sizeof buf));
        }
    }

    ret = 0;
    goto end;
 err:
    ERR_print_errors(bio_err);
 end:
    if (use_supported)
        sk_SSL_CIPHER_free(sk);
    SSL_CTX_free(ctx);
    SSL_free(ssl);
    return (ret);
}
Пример #26
0
int MAIN(int argc, char **argv)
	{
	int ret=1,i;
	int verbose=0;
	char **pp;
	const char *p;
	int badops=0;
	SSL_CTX *ctx=NULL;
	SSL *ssl=NULL;
	char *ciphers=NULL;
	SSL_METHOD *meth=NULL;
	STACK_OF(SSL_CIPHER) *sk;
	char buf[512];
	BIO *STDout=NULL;

#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
	meth=SSLv23_server_method();
#elif !defined(OPENSSL_NO_SSL3)
	meth=SSLv3_server_method();
#elif !defined(OPENSSL_NO_SSL2)
	meth=SSLv2_server_method();
#endif

	apps_startup();

	if (bio_err == NULL)
		bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
	STDout=BIO_new_fp(stdout,BIO_NOCLOSE);
#ifdef OPENSSL_SYS_VMS
	{
	BIO *tmpbio = BIO_new(BIO_f_linebuffer());
	STDout = BIO_push(tmpbio, STDout);
	}
#endif

	argc--;
	argv++;
	while (argc >= 1)
		{
		if (strcmp(*argv,"-v") == 0)
			verbose=1;
#ifndef OPENSSL_NO_SSL2
		else if (strcmp(*argv,"-ssl2") == 0)
			meth=SSLv2_client_method();
#endif
#ifndef OPENSSL_NO_SSL3
		else if (strcmp(*argv,"-ssl3") == 0)
			meth=SSLv3_client_method();
#endif
#ifndef OPENSSL_NO_TLS1
		else if (strcmp(*argv,"-tls1") == 0)
			meth=TLSv1_client_method();
#endif
		else if ((strncmp(*argv,"-h",2) == 0) ||
			 (strcmp(*argv,"-?") == 0))
			{
			badops=1;
			break;
			}
		else
			{
			ciphers= *argv;
			}
		argc--;
		argv++;
		}

	if (badops)
		{
		for (pp=ciphers_usage; (*pp != NULL); pp++)
			BIO_printf(bio_err,"%s",*pp);
		goto end;
		}

	OpenSSL_add_ssl_algorithms();

	ctx=SSL_CTX_new(meth);
	if (ctx == NULL) goto err;
	if (ciphers != NULL) {
		if(!SSL_CTX_set_cipher_list(ctx,ciphers)) {
			BIO_printf(bio_err, "Error in cipher list\n");
			goto err;
		}
	}
	ssl=SSL_new(ctx);
	if (ssl == NULL) goto err;


	if (!verbose)
		{
		for (i=0; ; i++)
			{
			p=SSL_get_cipher_list(ssl,i);
			if (p == NULL) break;
			if (i != 0) BIO_printf(STDout,":");
			BIO_printf(STDout,"%s",p);
			}
		BIO_printf(STDout,"\n");
		}
	else
		{
		sk=SSL_get_ciphers(ssl);

		for (i=0; i<sk_SSL_CIPHER_num(sk); i++)
			{
			BIO_puts(STDout,SSL_CIPHER_description(
				sk_SSL_CIPHER_value(sk,i),
				buf,sizeof buf));
			}
		}

	ret=0;
	if (0)
		{
err:
		SSL_load_error_strings();
		ERR_print_errors(bio_err);
		}
end:
	if (ctx != NULL) SSL_CTX_free(ctx);
	if (ssl != NULL) SSL_free(ssl);
	if (STDout != NULL) BIO_free_all(STDout);
	apps_shutdown();
	OPENSSL_EXIT(ret);
	}
Пример #27
0
static void setup_ssl(tcptest_t *item)
{
	static int ssl_init_complete = 0;
	struct servent *sp;
	char portinfo[100];
	X509 *peercert;
	char *certcn, *certstart, *certend;
	int err;
	strbuffer_t *sslinfo;
	char msglin[2048];

	item->sslrunning = 1;

	if (!ssl_init_complete) {
		/* Setup entropy */
		if (RAND_status() != 1) {
			char path[PATH_MAX];	/* Path for the random file */

			/* load entropy from files */
			RAND_load_file(RAND_file_name(path, sizeof (path)), -1);

			/* load entropy from egd sockets */
			RAND_egd("/var/run/egd-pool");
			RAND_egd("/dev/egd-pool");
			RAND_egd("/etc/egd-pool");
			RAND_egd("/var/spool/prngd/pool");

			/* shuffle $RANDFILE (or ~/.rnd if unset) */
			RAND_write_file(RAND_file_name(path, sizeof (path)));
			if (RAND_status() != 1) {
				errprintf("Failed to find enough entropy on your system");
				item->errcode = CONTEST_ESSL;
				return;
			}
		}

		SSL_load_error_strings();
		SSL_library_init();
		ssl_init_complete = 1;
	}

	if (item->sslctx == NULL) {
		switch (item->ssloptions->sslversion) {
		  case SSLVERSION_V2:
			item->sslctx = SSL_CTX_new(SSLv2_client_method()); break;
		  case SSLVERSION_V3:
			item->sslctx = SSL_CTX_new(SSLv3_client_method()); break;
		  case SSLVERSION_TLS1:
			item->sslctx = SSL_CTX_new(TLSv1_client_method()); break;
		  default:
			item->sslctx = SSL_CTX_new(SSLv23_client_method()); break;
		}

		if (!item->sslctx) {
			char sslerrmsg[256];

			ERR_error_string(ERR_get_error(), sslerrmsg);
			errprintf("Cannot create SSL context - IP %s, service %s: %s\n", 
				   inet_ntoa(item->addr.sin_addr), item->svcinfo->svcname, sslerrmsg);
			item->sslrunning = 0;
			item->errcode = CONTEST_ESSL;
			return;
		}

		/* Workaround SSL bugs */
		SSL_CTX_set_options(item->sslctx, SSL_OP_ALL);
		SSL_CTX_set_quiet_shutdown(item->sslctx, 1);

		/* Limit set of ciphers, if user wants to */
		if (item->ssloptions->cipherlist) 
			SSL_CTX_set_cipher_list(item->sslctx, item->ssloptions->cipherlist);

		if (item->ssloptions->clientcert) {
			int status;
			char certfn[PATH_MAX];

			SSL_CTX_set_default_passwd_cb(item->sslctx, cert_password_cb);
			SSL_CTX_set_default_passwd_cb_userdata(item->sslctx, item);

			sprintf(certfn, "%s/certs/%s", xgetenv("XYMONHOME"), item->ssloptions->clientcert);
			status = SSL_CTX_use_certificate_chain_file(item->sslctx, certfn);
			if (status == 1) {
				status = SSL_CTX_use_PrivateKey_file(item->sslctx, certfn, SSL_FILETYPE_PEM);
			}

			if (status != 1) {
				char sslerrmsg[256];

				ERR_error_string(ERR_get_error(), sslerrmsg);
				errprintf("Cannot load SSL client certificate/key %s: %s\n", 
					  item->ssloptions->clientcert, sslerrmsg);
				item->sslrunning = 0;
				item->errcode = CONTEST_ESSL;
				return;
			}
		}
	}

	if (item->ssldata == NULL) {
		item->ssldata = SSL_new(item->sslctx);
		if (!item->ssldata) {
			char sslerrmsg[256];

			ERR_error_string(ERR_get_error(), sslerrmsg);
			errprintf("SSL_new failed - IP %s, service %s: %s\n", 
				   inet_ntoa(item->addr.sin_addr), item->svcinfo->svcname, sslerrmsg);
			item->sslrunning = 0;
			SSL_CTX_free(item->sslctx);
			item->errcode = CONTEST_ESSL;
			return;
		}

		/* Verify that the client certificate is working */
		if (item->ssloptions->clientcert) {
			X509 *x509;

			x509 = SSL_get_certificate(item->ssldata);
			if(x509 != NULL) {
				EVP_PKEY *pktmp = X509_get_pubkey(x509);
				EVP_PKEY_copy_parameters(pktmp,SSL_get_privatekey(item->ssldata));
				EVP_PKEY_free(pktmp);
			}

			if (!SSL_CTX_check_private_key(item->sslctx)) {
				errprintf("Private/public key mismatch for certificate %s\n", item->ssloptions->clientcert);
				item->sslrunning = 0;
				item->errcode = CONTEST_ESSL;
				return;
			}
		}

		/* SSL setup is done. Now attach the socket FD to the SSL protocol handler */
		if (SSL_set_fd(item->ssldata, item->fd) != 1) {
			char sslerrmsg[256];

			ERR_error_string(ERR_get_error(), sslerrmsg);
			errprintf("Could not initiate SSL on connection - IP %s, service %s: %s\n", 
				   inet_ntoa(item->addr.sin_addr), item->svcinfo->svcname, sslerrmsg);
			item->sslrunning = 0;
			SSL_free(item->ssldata); 
			SSL_CTX_free(item->sslctx);
			item->errcode = CONTEST_ESSL;
			return;
		}
	}

	sp = getservbyport(item->addr.sin_port, "tcp");
	if (sp) {
		sprintf(portinfo, "%s (%d/tcp)", sp->s_name, item->addr.sin_port);
	}
	else {
		sprintf(portinfo, "%d/tcp", item->addr.sin_port);
	}
	if ((err = SSL_connect(item->ssldata)) != 1) {
		char sslerrmsg[256];

		switch (SSL_get_error (item->ssldata, err)) {
		  case SSL_ERROR_WANT_READ:
		  case SSL_ERROR_WANT_WRITE:
			item->sslrunning = SSLSETUP_PENDING;
			break;
		  case SSL_ERROR_SYSCALL:
			ERR_error_string(ERR_get_error(), sslerrmsg);
			/* Filter out the bogus SSL error */
			if (strstr(sslerrmsg, "error:00000000:") == NULL) {
				errprintf("IO error in SSL_connect to %s on host %s: %s\n",
					  portinfo, inet_ntoa(item->addr.sin_addr), sslerrmsg);
			}
			item->errcode = CONTEST_ESSL;
			item->sslrunning = 0; SSL_free(item->ssldata); SSL_CTX_free(item->sslctx);
			break;
		  case SSL_ERROR_SSL:
			ERR_error_string(ERR_get_error(), sslerrmsg);
			errprintf("Unspecified SSL error in SSL_connect to %s on host %s: %s\n",
				  portinfo, inet_ntoa(item->addr.sin_addr), sslerrmsg);
			item->errcode = CONTEST_ESSL;
			item->sslrunning = 0; SSL_free(item->ssldata); SSL_CTX_free(item->sslctx);
			break;
		  default:
			ERR_error_string(ERR_get_error(), sslerrmsg);
			errprintf("Unknown error %d in SSL_connect to %s on host %s: %s\n",
				  err, portinfo, inet_ntoa(item->addr.sin_addr), sslerrmsg);
			item->errcode = CONTEST_ESSL;
			item->sslrunning = 0; SSL_free(item->ssldata); SSL_CTX_free(item->sslctx);
			break;
		}

		return;
	}

	/* If we get this far, the SSL handshake has completed. So grab the certificate */
	peercert = SSL_get_peer_certificate(item->ssldata);
	if (!peercert) {
		errprintf("Cannot get peer certificate for %s on host %s\n",
			  portinfo, inet_ntoa(item->addr.sin_addr));
		item->errcode = CONTEST_ESSL;
		item->sslrunning = 0; SSL_free(item->ssldata); SSL_CTX_free(item->sslctx);
		return;
	}

	sslinfo = newstrbuffer(0);

	certcn = X509_NAME_oneline(X509_get_subject_name(peercert), NULL, 0);
	certstart = strdup(xymon_ASN1_UTCTIME(X509_get_notBefore(peercert)));
	certend = strdup(xymon_ASN1_UTCTIME(X509_get_notAfter(peercert)));

	snprintf(msglin, sizeof(msglin),
		"Server certificate:\n\tsubject:%s\n\tstart date: %s\n\texpire date:%s\n", 
		certcn, certstart, certend);
	addtobuffer(sslinfo, msglin);
	item->certsubject = strdup(certcn);
	item->certexpires = sslcert_expiretime(certend);
	xfree(certcn); xfree(certstart); xfree(certend);
	X509_free(peercert);

	/* We list the available ciphers in the SSL cert data */
	{
		int i;
		STACK_OF(SSL_CIPHER) *sk;

		addtobuffer(sslinfo, "\nAvailable ciphers:\n");
		sk = SSL_get_ciphers(item->ssldata);
		for (i=0; i<sk_SSL_CIPHER_num(sk); i++) {
			int b1, b2;
			char *cph;

			b1 = SSL_CIPHER_get_bits(sk_SSL_CIPHER_value(sk,i), &b2);
			cph = SSL_CIPHER_get_name(sk_SSL_CIPHER_value(sk,i));
			snprintf(msglin, sizeof(msglin), "Cipher %d: %s (%d bits)\n", i, cph, b1);
			addtobuffer(sslinfo, msglin);

			if ((item->mincipherbits == 0) || (b1 < item->mincipherbits)) item->mincipherbits = b1;
		}
	}

	item->certinfo = grabstrbuffer(sslinfo);
}
Пример #28
0
int connect_dtls_socket(struct openconnect_info *vpninfo)
{
	STACK_OF(SSL_CIPHER) *ciphers;
	method_const SSL_METHOD *dtls_method;
	SSL_CIPHER *dtls_cipher;
	SSL *dtls_ssl;
	BIO *dtls_bio;
	int dtls_fd;

	if (!vpninfo->dtls_addr) {
		vpn_progress(vpninfo, PRG_ERR, _("No DTLS address\n"));
		vpninfo->dtls_attempt_period = 0;
		return -EINVAL;
	}

	if (!vpninfo->dtls_cipher) {
		/* We probably didn't offer it any ciphers it liked */
		vpn_progress(vpninfo, PRG_ERR, _("Server offered no DTLS cipher option\n"));
		vpninfo->dtls_attempt_period = 0;
		return -EINVAL;
	}

	if (vpninfo->proxy) {
		/* XXX: Theoretically, SOCKS5 proxies can do UDP too */
		vpn_progress(vpninfo, PRG_ERR, _("No DTLS when connected via proxy\n"));
		vpninfo->dtls_attempt_period = 0;
		return -EINVAL;
	}

	dtls_fd = socket(vpninfo->peer_addr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
	if (dtls_fd < 0) {
		perror(_("Open UDP socket for DTLS:"));
		return -EINVAL;
	}

	if (connect(dtls_fd, vpninfo->dtls_addr, vpninfo->peer_addrlen)) {
		perror(_("UDP (DTLS) connect:\n"));
		close(dtls_fd);
		return -EINVAL;
	}

	fcntl(dtls_fd, F_SETFD, FD_CLOEXEC);

	if (!vpninfo->dtls_ctx) {
		dtls_method = DTLSv1_client_method();
		vpninfo->dtls_ctx = SSL_CTX_new(dtls_method);
		if (!vpninfo->dtls_ctx) {
			vpn_progress(vpninfo, PRG_ERR,
				     _("Initialise DTLSv1 CTX failed\n"));
			vpninfo->dtls_attempt_period = 0;
			return -EINVAL;
		}

		/* If we don't readahead, then we do short reads and throw
		   away the tail of data packets. */
		SSL_CTX_set_read_ahead(vpninfo->dtls_ctx, 1);

		if (!SSL_CTX_set_cipher_list(vpninfo->dtls_ctx, vpninfo->dtls_cipher)) {
			vpn_progress(vpninfo, PRG_ERR,
				     _("Set DTLS cipher list failed\n"));
			SSL_CTX_free(vpninfo->dtls_ctx);
			vpninfo->dtls_ctx = NULL;
			vpninfo->dtls_attempt_period = 0;
			return -EINVAL;
		}
	}

	if (!vpninfo->dtls_session) {
		/* We're going to "resume" a session which never existed. Fake it... */
		vpninfo->dtls_session = SSL_SESSION_new();
		if (!vpninfo->dtls_session) {
			vpn_progress(vpninfo, PRG_ERR,
				     _("Initialise DTLSv1 session failed\n"));
			vpninfo->dtls_attempt_period = 0;
			return -EINVAL;
		}
		vpninfo->dtls_session->ssl_version = 0x0100; /* DTLS1_BAD_VER */
	}

	/* Do this every time; it may have changed due to a rekey */
	vpninfo->dtls_session->master_key_length = sizeof(vpninfo->dtls_secret);
	memcpy(vpninfo->dtls_session->master_key, vpninfo->dtls_secret,
	       sizeof(vpninfo->dtls_secret));

	vpninfo->dtls_session->session_id_length = sizeof(vpninfo->dtls_session_id);
	memcpy(vpninfo->dtls_session->session_id, vpninfo->dtls_session_id,
	       sizeof(vpninfo->dtls_session_id));

	dtls_ssl = SSL_new(vpninfo->dtls_ctx);
	SSL_set_connect_state(dtls_ssl);

	ciphers = SSL_get_ciphers(dtls_ssl);
	if (sk_SSL_CIPHER_num(ciphers) != 1) {
		vpn_progress(vpninfo, PRG_ERR, _("Not precisely one DTLS cipher\n"));
		SSL_CTX_free(vpninfo->dtls_ctx);
		SSL_free(dtls_ssl);
		SSL_SESSION_free(vpninfo->dtls_session);
		vpninfo->dtls_ctx = NULL;
		vpninfo->dtls_session = NULL;
		vpninfo->dtls_attempt_period = 0;
		return -EINVAL;
	}
	dtls_cipher = sk_SSL_CIPHER_value(ciphers, 0);

	/* Set the appropriate cipher on our session to be resumed */
	vpninfo->dtls_session->cipher = dtls_cipher;
	vpninfo->dtls_session->cipher_id = dtls_cipher->id;

	/* Add the generated session to the SSL */
	if (!SSL_set_session(dtls_ssl, vpninfo->dtls_session)) {
		vpn_progress(vpninfo, PRG_ERR,
			     _("SSL_set_session() failed with old protocol version 0x%x\n"
			       "Are you using a version of OpenSSL older than 0.9.8m?\n"
			       "See http://rt.openssl.org/Ticket/Display.html?id=1751\n"
			       "Use the --no-dtls command line option to avoid this message\n"),
			     vpninfo->dtls_session->ssl_version);
		vpninfo->dtls_attempt_period = 0;
		return -EINVAL;
	}

	/* Go Go Go! */
	dtls_bio = BIO_new_socket(dtls_fd, BIO_NOCLOSE);
	SSL_set_bio(dtls_ssl, dtls_bio, dtls_bio);

	SSL_set_options(dtls_ssl, SSL_OP_CISCO_ANYCONNECT);

	/* Set non-blocking */
	BIO_set_nbio(SSL_get_rbio(dtls_ssl), 1);
	BIO_set_nbio(SSL_get_wbio(dtls_ssl), 1);

	fcntl(dtls_fd, F_SETFL, fcntl(dtls_fd, F_GETFL) | O_NONBLOCK);

	vpninfo->new_dtls_fd = dtls_fd;
	vpninfo->new_dtls_ssl = dtls_ssl;

	if (vpninfo->select_nfds <= dtls_fd)
		vpninfo->select_nfds = dtls_fd + 1;

	FD_SET(dtls_fd, &vpninfo->select_rfds);
	FD_SET(dtls_fd, &vpninfo->select_efds);

	time(&vpninfo->new_dtls_started);
	return dtls_try_handshake(vpninfo);
}
Пример #29
0
int
ciphers_main(int argc, char **argv)
{
	char *cipherlist = NULL;
	STACK_OF(SSL_CIPHER) *ciphers;
	const SSL_CIPHER *cipher;
	SSL_CTX *ssl_ctx = NULL;
	SSL *ssl = NULL;
	uint16_t value;
	int i, rv = 0;
	char *desc;

	if (single_execution) {
		if (pledge("stdio rpath", NULL) == -1) {
			perror("pledge");
			exit(1);
		}
	}

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

	if (options_parse(argc, argv, ciphers_options, &cipherlist,
	    NULL) != 0) {
		ciphers_usage();
		return (1);
	}

	if (ciphers_config.usage) {
		ciphers_usage();
		return (1);
	}

	if ((ssl_ctx = SSL_CTX_new(TLSv1_client_method())) == NULL)
		goto err;

	if (cipherlist != NULL) {
		if (SSL_CTX_set_cipher_list(ssl_ctx, cipherlist) == 0)
			goto err;
	}

	if ((ssl = SSL_new(ssl_ctx)) == NULL)
		goto err;

	if ((ciphers = SSL_get_ciphers(ssl)) == NULL)
		goto err;

	for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
		cipher = sk_SSL_CIPHER_value(ciphers, i);
		if (ciphers_config.verbose == 0) {
			fprintf(stdout, "%s%s", (i ? ":" : ""),
			    SSL_CIPHER_get_name(cipher));
			continue;
		}
		if (ciphers_config.verbose > 1) {
			value = SSL_CIPHER_get_value(cipher);
			fprintf(stdout, "%-*s0x%02X,0x%02X - ", 10, "",
				((value >> 8) & 0xff), (value & 0xff));
		}
		desc = SSL_CIPHER_description(cipher, NULL, 0);
		if (strcmp(desc, "OPENSSL_malloc Error") == 0) {
			fprintf(stderr, "out of memory\n");
			goto err;
		}
		fprintf(stdout, "%s", desc);
		free(desc);
	}
Пример #30
0
MONO_API int
mono_btls_ssl_ctx_set_ciphers (MonoBtlsSslCtx *ctx, int count, const uint16_t *data,
				   int allow_unsupported)
{
	STACK_OF(SSL_CIPHER) *ciphers = NULL;
	struct ssl_cipher_preference_list_st *pref_list = NULL;
	uint8_t *in_group_flags = NULL;
	int i;

	ciphers = sk_SSL_CIPHER_new_null ();
	if (!ciphers)
		goto err;

	for (i = 0; i < count; i++) {
		const SSL_CIPHER *cipher = SSL_get_cipher_by_value (data [i]);
		if (!cipher) {
			debug_printf (ctx, "mono_btls_ssl_ctx_set_ciphers(): unknown cipher %02x", data [i]);
			if (!allow_unsupported)
				goto err;
			continue;
		}
		if (!sk_SSL_CIPHER_push (ciphers, cipher))
			 goto err;
	}

	pref_list = OPENSSL_malloc (sizeof (struct ssl_cipher_preference_list_st));
	if (!pref_list)
		goto err;

	memset (pref_list, 0, sizeof (struct ssl_cipher_preference_list_st));
	pref_list->ciphers = sk_SSL_CIPHER_dup (ciphers);
	if (!pref_list->ciphers)
		goto err;
	pref_list->in_group_flags = OPENSSL_malloc (sk_SSL_CIPHER_num (ciphers));
	if (!pref_list->in_group_flags)
		goto err;

	if (ctx->ctx->cipher_list)
		ssl_cipher_preference_list_free (ctx->ctx->cipher_list);
	if (ctx->ctx->cipher_list_by_id)
		sk_SSL_CIPHER_free (ctx->ctx->cipher_list_by_id);
	if (ctx->ctx->cipher_list_tls10) {
		ssl_cipher_preference_list_free (ctx->ctx->cipher_list_tls10);
		ctx->ctx->cipher_list_tls10 = NULL;
	}
	if (ctx->ctx->cipher_list_tls11) {
		ssl_cipher_preference_list_free (ctx->ctx->cipher_list_tls11);
		ctx->ctx->cipher_list_tls11 = NULL;
	}

	ctx->ctx->cipher_list = pref_list;
	ctx->ctx->cipher_list_by_id = ciphers;

	return (int)sk_SSL_CIPHER_num (ciphers);

err:
	sk_SSL_CIPHER_free (ciphers);
	OPENSSL_free (pref_list);
	OPENSSL_free (in_group_flags);
	return 0;
}