#ifndef OPENSSL_NO_TLSEXT
static BIO *authz_in = NULL;
static const char *s_authz_file = NULL;
-static unsigned char *authz = NULL;
-static size_t authz_length;
#endif
#ifndef OPENSSL_NO_PSK
next_proto.data = NULL;
}
# endif
- if (s_authz_file != NULL)
- {
- /* Allow authzs up to 64KB bytes. */
- static const size_t authz_limit = 65536;
-
- authz_in = BIO_new(BIO_s_file_internal());
- if (authz_in == NULL)
- {
- ERR_print_errors(bio_err);
- goto end;
- }
-
- if (BIO_read_filename(authz_in, s_authz_file) <= 0)
- {
- ERR_print_errors(bio_err);
- goto end;
- }
- authz = OPENSSL_malloc(authz_limit);
- authz_length = BIO_read(authz_in, authz, authz_limit);
- if (authz_length == authz_limit || authz_length <= 0)
- {
- BIO_printf(bio_err, "authz too large\n");
- goto end;
- }
- BIO_free(authz_in);
- authz_in = NULL;
- }
#endif /* OPENSSL_NO_TLSEXT */
}
if (!set_cert_key_stuff(ctx, s_cert, s_key, s_chain))
goto end;
#ifndef OPENSSL_NO_TLSEXT
- if (authz != NULL && !SSL_CTX_use_authz(ctx, authz, authz_length))
+ if (s_authz_file != NULL && !SSL_CTX_use_authz_file(ctx, s_authz_file))
goto end;
#endif
#ifndef OPENSSL_NO_TLSEXT
X509_free(s_cert2);
if (s_key2)
EVP_PKEY_free(s_key2);
- if (authz != NULL)
- OPENSSL_free(authz);
if (authz_in != NULL)
BIO_free(authz_in);
#endif
int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len);
#ifndef OPENSSL_NO_TLSEXT
+/* Set authz data for the current active cert. */
int SSL_CTX_use_authz(SSL_CTX *ctx, unsigned char *authz, size_t authz_length);
int SSL_use_authz(SSL *ssl, unsigned char *authz, size_t authz_length);
+/* Get the authz of type 'type' associated with the current active cert. */
+const unsigned char *SSL_CTX_get_authz_data(SSL_CTX *ctx, unsigned char type,
+ size_t *data_length);
+#ifndef OPENSSL_NO_STDIO
+int SSL_CTX_use_authz_file(SSL_CTX *ctx, const char *file);
+int SSL_use_authz_file(SSL *ssl, const char *file);
+#endif
#endif
#ifndef OPENSSL_NO_STDIO
/* Error codes for the SSL functions. */
/* Function codes. */
+#define SSL_F_AUTHZ_FIND_DATA 330
#define SSL_F_AUTHZ_VALIDATE 323
#define SSL_F_CLIENT_CERTIFICATE 100
#define SSL_F_CLIENT_FINISHED 167
#define SSL_F_GET_SERVER_HELLO 109
#define SSL_F_GET_SERVER_VERIFY 110
#define SSL_F_I2D_SSL_SESSION 111
+#define SSL_F_READ_AUTHZ 329
#define SSL_F_READ_N 112
#define SSL_F_REQUEST_CERTIFICATE 113
#define SSL_F_SERVER_FINISH 239
static ERR_STRING_DATA SSL_str_functs[]=
{
+{ERR_FUNC(SSL_F_AUTHZ_FIND_DATA), "AUTHZ_FIND_DATA"},
{ERR_FUNC(SSL_F_AUTHZ_VALIDATE), "AUTHZ_VALIDATE"},
{ERR_FUNC(SSL_F_CLIENT_CERTIFICATE), "CLIENT_CERTIFICATE"},
{ERR_FUNC(SSL_F_CLIENT_FINISHED), "CLIENT_FINISHED"},
{ERR_FUNC(SSL_F_GET_SERVER_HELLO), "GET_SERVER_HELLO"},
{ERR_FUNC(SSL_F_GET_SERVER_VERIFY), "GET_SERVER_VERIFY"},
{ERR_FUNC(SSL_F_I2D_SSL_SESSION), "i2d_SSL_SESSION"},
+{ERR_FUNC(SSL_F_READ_AUTHZ), "READ_AUTHZ"},
{ERR_FUNC(SSL_F_READ_N), "READ_N"},
{ERR_FUNC(SSL_F_REQUEST_CERTIFICATE), "REQUEST_CERTIFICATE"},
{ERR_FUNC(SSL_F_SERVER_FINISH), "SERVER_FINISH"},
}
}
+static const unsigned char *authz_find_data(const unsigned char *authz,
+ size_t authz_length,
+ unsigned char data_type,
+ size_t *data_length)
+ {
+ if (authz == NULL) return NULL;
+ if (!authz_validate(authz, authz_length))
+ {
+ SSLerr(SSL_F_AUTHZ_FIND_DATA,SSL_R_INVALID_AUTHZ_DATA);
+ return NULL;
+ }
+
+ for (;;)
+ {
+ unsigned char type;
+ unsigned short len;
+ if (!authz_length)
+ return NULL;
+
+ type = *(authz++);
+ authz_length--;
+
+ /* We've validated the authz data, so we don't have to
+ * check again that we have enough bytes left. */
+ len = ((unsigned short) authz[0]) << 8 |
+ ((unsigned short) authz[1]);
+ authz += 2;
+ authz_length -= 2;
+ if (type == data_type)
+ {
+ *data_length = len;
+ return authz;
+ }
+ authz += len;
+ authz_length -= len;
+ }
+ /* No match */
+ return NULL;
+ }
+
static int ssl_set_authz(CERT *c, unsigned char *authz, size_t authz_length)
{
CERT_PKEY *current_key = c->key;
}
return ssl_set_authz(ssl->cert, authz, authz_length);
}
+
+const unsigned char *SSL_CTX_get_authz_data(SSL_CTX *ctx, unsigned char type,
+ size_t *data_length)
+ {
+ CERT_PKEY *current_key;
+
+ if (ctx->cert == NULL)
+ return NULL;
+ current_key = ctx->cert->key;
+ if (current_key->authz == NULL)
+ return NULL;
+ return authz_find_data(current_key->authz,
+ current_key->authz_length, type, data_length);
+ }
+
+#ifndef OPENSSL_NO_STDIO
+/* read_authz returns a newly allocated buffer with authz data */
+static unsigned char *read_authz(const char *file, size_t *authz_length)
+ {
+ BIO *authz_in = NULL;
+ unsigned char *authz = NULL;
+ /* Allow authzs up to 64KB. */
+ static const size_t authz_limit = 65536;
+ size_t read_length;
+ unsigned char *ret = NULL;
+
+ authz_in = BIO_new(BIO_s_file_internal());
+ if (authz_in == NULL)
+ {
+ SSLerr(SSL_F_READ_AUTHZ,ERR_R_BUF_LIB);
+ goto end;
+ }
+
+ if (BIO_read_filename(authz_in,file) <= 0)
+ {
+ SSLerr(SSL_F_READ_AUTHZ,ERR_R_SYS_LIB);
+ goto end;
+ }
+
+ authz = OPENSSL_malloc(authz_limit);
+ read_length = BIO_read(authz_in, authz, authz_limit);
+ if (read_length == authz_limit || read_length <= 0)
+ {
+ SSLerr(SSL_F_READ_AUTHZ,SSL_R_AUTHZ_DATA_TOO_LARGE);
+ OPENSSL_free(authz);
+ goto end;
+ }
+ *authz_length = read_length;
+ ret = authz;
+end:
+ if (authz_in != NULL) BIO_free(authz_in);
+ return ret;
+ }
+
+int SSL_CTX_use_authz_file(SSL_CTX *ctx, const char *file)
+ {
+ unsigned char *authz = NULL;
+ size_t authz_length = 0;
+ int ret;
+
+ authz = read_authz(file, &authz_length);
+ if (authz == NULL)
+ return 0;
+
+ ret = SSL_CTX_use_authz(ctx, authz, authz_length);
+ /* SSL_CTX_use_authz makes a local copy of the authz. */
+ OPENSSL_free(authz);
+ return ret;
+ }
+
+int SSL_use_authz_file(SSL *ssl, const char *file)
+ {
+ unsigned char *authz = NULL;
+ size_t authz_length = 0;
+ int ret;
+
+ authz = read_authz(file, &authz_length);
+ if (authz == NULL)
+ return 0;
+
+ ret = SSL_use_authz(ssl, authz, authz_length);
+ /* SSL_use_authz makes a local copy of the authz. */
+ OPENSSL_free(authz);
+ return ret;
+ }
+#endif /* OPENSSL_NO_STDIO */
#endif /* OPENSSL_NO_TLSEXT */
" (default is sect163r2).\n");
#endif
fprintf(stderr," -test_cipherlist - verifies the order of the ssl cipher lists\n");
+#ifndef OPENSSL_NO_TLSEXT
+ fprintf(stderr," -server_authz arg - binary authz file for certificate\n");
+ fprintf(stderr," -c_support_proof - indicate client support for server_authz audit proofs\n");
+ fprintf(stderr," -c_require_proof - fail if no audit proof is sent\n");
+#endif
}
static void print_details(SSL *c_ssl, const char *prefix)
}
#endif
+#ifndef OPENSSL_NO_TLSEXT
+struct audit_proof_cb_arg_st
+ {
+ unsigned char *expected_proof;
+ size_t expected_proof_length;
+ int require;
+ };
+
+struct audit_proof_cb_arg_st c_expected = { NULL, 0, 0 };
+
+static int audit_proof_cb(SSL *s, void *arg)
+ {
+ const unsigned char *proof;
+ size_t proof_len;
+ SSL_SESSION *sess = SSL_get_session(s);
+ struct audit_proof_cb_arg_st *cb_arg = (struct audit_proof_cb_arg_st*)arg;
+
+ proof = SSL_SESSION_get_tlsext_authz_server_audit_proof(sess,
+ &proof_len);
+ if (proof != NULL)
+ {
+ if (proof_len == cb_arg->expected_proof_length &&
+ cb_arg->expected_proof != NULL &&
+ memcmp(proof, cb_arg->expected_proof, proof_len) == 0)
+ {
+ BIO_printf(bio_stdout, "Audit proof OK (%lu bytes).\n",
+ (long)proof_len);
+ return 1;
+ }
+ else
+ {
+ BIO_printf(bio_stdout, "Audit proof mismatch.\n");
+ /* Cause handshake failure. */
+ return 0;
+ }
+ }
+
+ else /* proof == NULL */
+ {
+ BIO_printf(bio_stdout, "No audit proof found.\n");
+ if (cb_arg->require)
+ {
+ /* Cause handshake failure. */
+ return 0;
+ }
+ return 1;
+ }
+ }
+#endif
+
int main(int argc, char *argv[])
{
char *CApath=NULL,*CAfile=NULL;
#ifdef OPENSSL_FIPS
int fips_mode=0;
#endif
+#ifndef OPENSSL_NO_TLSEXT
+ char *s_authz_file = NULL;
+ int c_support_proof = 0;
+ int c_require_proof = 0;
+#endif
verbose = 0;
debug = 0;
{
test_cipherlist = 1;
}
+#ifndef OPENSSL_NO_TLSEXT
+ else if(strcmp(*argv,"-server_authz") == 0)
+ {
+ if (--argc < 1) goto bad;
+ s_authz_file = *(++argv);
+ tls1 = 1;
+ }
+ else if (strcmp(*argv,"-c_support_proof") == 0)
+ {
+ c_support_proof = 1;
+ tls1 = 1;
+ }
+ else if (strcmp(*argv,"-c_require_proof") == 0)
+ {
+ c_require_proof = 1;
+ tls1 = 1;
+ }
+#endif
else
{
fprintf(stderr,"unknown option %s\n",*argv);
"to avoid protocol mismatch.\n");
EXIT(1);
}
+ if (c_require_proof && s_authz_file == NULL && !force)
+ {
+ fprintf(stderr, "This case cannot work. -c_require_proof "
+ "requires an audit proof, but none was supplied. "
+ "Use -f to perform the test anyway (and\n-d to see "
+ "what happens), or use -server_authz to supply an "
+ "audit proof.\n");
+ EXIT(1);
+ }
#ifdef OPENSSL_FIPS
if(fips_mode)
SSL_CTX_set_srp_username_callback(s_ctx, ssl_srp_server_param_cb);
}
#endif
+#ifndef OPENSSL_NO_TLSEXT
+ if (s_authz_file != NULL)
+ {
+ if(!SSL_CTX_use_authz_file(s_ctx, s_authz_file))
+ {
+ BIO_printf(bio_err, "Unable to set authz data\n");
+ goto end;
+ }
+ }
+ if (c_support_proof || c_require_proof)
+ {
+ size_t proof_length;
+ const unsigned char *proof = SSL_CTX_get_authz_data(s_ctx,
+ TLSEXT_AUTHZDATAFORMAT_audit_proof, &proof_length);
+ if (proof != NULL)
+ {
+ /* Store a local copy. */
+ c_expected.expected_proof = OPENSSL_malloc(proof_length);
+ c_expected.expected_proof_length = proof_length;
+ memcpy(c_expected.expected_proof, proof, proof_length);
+ }
+ c_expected.require = c_require_proof;
+ SSL_CTX_set_tlsext_authz_server_audit_proof_cb(c_ctx,
+ audit_proof_cb);
+ SSL_CTX_set_tlsext_authz_server_audit_proof_cb_arg(c_ctx,
+ &c_expected);
+ }
+#endif
c_ssl=SSL_new(c_ctx);
s_ssl=SSL_new(s_ctx);
#endif
#ifndef OPENSSL_NO_ENGINE
ENGINE_cleanup();
+#endif
+#ifndef OPENSSL_NO_TLSEXT
+ if (c_expected.expected_proof != NULL)
+ OPENSSL_free(c_expected.expected_proof);
#endif
CRYPTO_cleanup_all_ex_data();
ERR_free_strings();