int signRequest(char* pemRequest, int days, char* pemCAKey, char* pemCaCert,  int certType, char *url, char* result)  {

  BIO* bioReq = BIO_new_mem_buf(pemRequest, -1);
  BIO* bioCAKey = BIO_new_mem_buf(pemCAKey, -1);

  BIO* bioCert = BIO_new_mem_buf(pemCaCert, -1);
  X509* caCert = PEM_read_bio_X509(bioCert, NULL, NULL, NULL);

  int err = 0;

  X509_REQ *req=NULL;
  if (!(req=PEM_read_bio_X509_REQ(bioReq, NULL, NULL, NULL))) {
    BIO_free(bioReq);
    BIO_free(bioCert);
    BIO_free(bioCAKey);
    return ERR_peek_error();
  }

  EVP_PKEY* caKey = PEM_read_bio_PrivateKey(bioCAKey, NULL, NULL, NULL);
  if (!caKey) {
    BIO_free(bioReq);
    BIO_free(bioCert);
    BIO_free(bioCAKey);
    return ERR_peek_error();
  }

  X509* cert = X509_new();
  EVP_PKEY* reqPub;
  if(!(err =  X509_set_version(cert, 2)))
  {
    BIO_free(bioReq);
    BIO_free(bioCAKey);
    return ERR_peek_error();
  }

  //redo all the certificate details, because OpenSSL wants us to work hard
  X509_set_issuer_name(cert, X509_get_subject_name(caCert));

  ASN1_UTCTIME *s=ASN1_UTCTIME_new();

  // Jira-issue: WP-37
  // This is temp solution for putting pzp validity 5 minutes before current time
  // If there is a small clock difference between machines, it results in cert_not_yet_valid
  // It does set GMT time but is relevant to machine time.
  // A better solution would be to have ntp server contacted to get a proper time.
  if(certType == 2) {
    X509_gmtime_adj(s, long(0-300));
  }
  else {
    X509_gmtime_adj(s, long(0));
  }
  // End of WP-37
  X509_set_notBefore(cert, s);

  X509_gmtime_adj(s, (long)60*60*24*days);
  X509_set_notAfter(cert, s);

  ASN1_UTCTIME_free(s);

  X509_set_subject_name(cert, X509_REQ_get_subject_name(req));
  reqPub = X509_REQ_get_pubkey(req);
  X509_set_pubkey(cert,reqPub);
  EVP_PKEY_free(reqPub);

  //create a serial number at random
  ASN1_INTEGER* serial = getRandomSN();
  X509_set_serialNumber(cert, serial);

  X509_EXTENSION *ex;
  X509V3_CTX ctx;
  X509V3_set_ctx_nodb(&ctx);
  X509V3_set_ctx(&ctx, cert, cert, NULL, NULL, 0);

  char *str = (char*)malloc(strlen("caIssuers;") + strlen(url) + 1);
  if (str == NULL) {
    return -10;
  }
  strcpy(str, "caIssuers;");
  strcat(str, url);

  if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_info_access, (char*)str))) {
    free(str);
    return ERR_peek_error();
  } else {
    X509_add_ext(cert, ex, -1);
  }
  free(str);
  if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_subject_alt_name, (char*)url))) {
    return ERR_peek_error();
  } else {
    X509_add_ext(cert, ex, -1);
  }
  if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_issuer_alt_name, (char*)"issuer:copy"))) {
    return ERR_peek_error();
  } else {
    X509_add_ext(cert, ex, -1);
  }

  if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_subject_key_identifier, (char*)"hash"))) {
    return ERR_peek_error();
  } else {
    X509_add_ext(cert, ex, -1);
  }

  if( certType == 1) {
    if(!(ex = X509V3_EXT_conf_nid(NULL,  &ctx, NID_basic_constraints, (char*)"critical, CA:FALSE"))) {
      return ERR_peek_error();
    } else {
      X509_add_ext(cert, ex, -1);
    }

    if(!(ex = X509V3_EXT_conf_nid(NULL,  &ctx, NID_ext_key_usage, (char*)"critical, clientAuth, serverAuth"))) {
      return ERR_peek_error();
    } else {
      X509_add_ext(cert, ex, -1);
    }
  } else if( certType == 2) {
    if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_basic_constraints, (char*)"critical, CA:FALSE"))) {
      return ERR_peek_error();
    } else {
      X509_add_ext(cert, ex, -1);
    }

    if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_ext_key_usage, (char*)"critical, clientAuth, serverAuth"))) {
      return ERR_peek_error();
    } else {
      X509_add_ext(cert, ex, -1);
    }
  }

  if (!(err = X509_sign(cert,caKey,EVP_sha1())))
  {
    BIO_free(bioReq);
    BIO_free(bioCert);
    BIO_free(bioCAKey);
    return err;
  }

  BIO *mem = BIO_new(BIO_s_mem());
  PEM_write_bio_X509(mem,cert);

  BUF_MEM *bptr;
  BIO_get_mem_ptr(mem, &bptr);
  BIO_read(mem, result, bptr->length);

  BIO_free(mem);
  BIO_free(bioReq);
  BIO_free(bioCert);
  BIO_free(bioCAKey);

  return 0;
}
int selfSignRequest(char* pemRequest, int days, char* pemCAKey, int certType, char *url, char* result)  {
  BIO* bioReq = BIO_new_mem_buf(pemRequest, -1);
  BIO* bioCAKey = BIO_new_mem_buf(pemCAKey, -1);

  int err = 0;

  X509_REQ *req=NULL;
  if (!(req=PEM_read_bio_X509_REQ(bioReq, NULL, NULL, NULL))) {
    BIO_free(bioReq);
    BIO_free(bioCAKey);
    return -5;
  }

  EVP_PKEY* caKey = PEM_read_bio_PrivateKey(bioCAKey, NULL, NULL, NULL);
  if (!caKey) {
    BIO_free(bioReq);
    BIO_free(bioCAKey);
    return -6;
  }

  X509* cert = X509_new();
  EVP_PKEY* reqPub;

  //redo all the certificate details, because OpenSSL wants us to work hard
  if(!(err =  X509_set_version(cert, 2)))
  {
    BIO_free(bioReq);
    BIO_free(bioCAKey);
    return err;
  }

  if(!(err = X509_set_issuer_name(cert, X509_REQ_get_subject_name(req))))
  {
    BIO_free(bioReq);
    BIO_free(bioCAKey);
    return err;
  }

  ASN1_UTCTIME *s=ASN1_UTCTIME_new();
  // Jira-issue: WP-37
  // This is temp solution for putting pzp validity 5 minutes before current time
  // If there is a small clock difference between machines, it results in cert_not_yet_valid
  // It does set GMT time but is relevant to machine time.
  // A better solution would be to have ntp server contacted to get proper time.
  if(certType == 2) {
    X509_gmtime_adj(s, long(0-300));
  }
  else {
    X509_gmtime_adj(s, long(0));
  }
  // End of WP-37
  X509_set_notBefore(cert, s);

  X509_gmtime_adj(s, (long)60*60*24*days);
  X509_set_notAfter(cert, s);

  ASN1_UTCTIME_free(s);

  if(!(err = X509_set_subject_name(cert, X509_REQ_get_subject_name(req)))) {
    BIO_free(bioReq);
    BIO_free(bioCAKey);
    return err;
  }

  if (!(reqPub = X509_REQ_get_pubkey(req))) {
    BIO_free(bioReq);
    BIO_free(bioCAKey);
    return -7;
  }
  err = X509_set_pubkey(cert,reqPub);
  EVP_PKEY_free(reqPub);
  if (!err) {
    return err; // an error occurred, this is terrible style.
  }

  //create a serial number at random
  ASN1_INTEGER* serial = getRandomSN();
  X509_set_serialNumber(cert, serial);

  // V3 extensions
  X509_EXTENSION *ex;
  X509V3_CTX ctx;
  X509V3_set_ctx_nodb(&ctx);
  X509V3_set_ctx(&ctx, cert, cert, NULL, NULL, 0);

  if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_subject_alt_name, (char*)url))) {
    return ERR_peek_error();
  } else {
    X509_add_ext(cert, ex, -1);
  }

  if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_subject_key_identifier, (char*)"hash"))) {
    return ERR_peek_error();
  } else {
    X509_add_ext(cert, ex, -1);
  }

  if( certType == 0) {
    if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_basic_constraints, (char*)"critical, CA:TRUE"))) {
      return ERR_peek_error();
    } else {
      X509_add_ext(cert, ex, -1);
    }

    if(!(ex = X509V3_EXT_conf_nid(NULL,  &ctx, NID_key_usage, (char*)"critical, keyCertSign, digitalSignature, cRLSign"))) { /* critical, keyCertSign,cRLSign, nonRepudiation,*/
      return ERR_peek_error();
    } else {
      X509_add_ext(cert, ex, -1);
    }

    if(!(ex = X509V3_EXT_conf_nid(NULL,  &ctx, NID_ext_key_usage, (char*)"critical, serverAuth"))) {
      return ERR_peek_error();
    } else {
      X509_add_ext(cert, ex, -1);
    }

    if(!(ex = X509V3_EXT_conf_nid(NULL,  &ctx, NID_inhibit_any_policy, (char*)"0"))) {
      return ERR_peek_error();
    } else {
      X509_add_ext(cert, ex, -1);
    }

    if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_crl_distribution_points, (char*)url))) {
      return ERR_peek_error();
    } else {
      X509_add_ext(cert, ex, -1);
    }
  }

  if (!(err = X509_sign(cert,caKey,EVP_sha1()))) {
    BIO_free(bioReq);
    BIO_free(bioCAKey);
    return err;
  }

  BIO *mem = BIO_new(BIO_s_mem());
  PEM_write_bio_X509(mem,cert);

  BUF_MEM *bptr;
  BIO_get_mem_ptr(mem, &bptr);
  BIO_read(mem, result, bptr->length);

  BIO_free(mem);
  BIO_free(bioReq);
  BIO_free(bioCAKey);
  return 0;

}
Ejemplo n.º 3
0
Datum
ssl_extension_info(PG_FUNCTION_ARGS)
{
	X509	   *cert = MyProcPort->peer;
	FuncCallContext *funcctx;
	int			call_cntr;
	int			max_calls;
	MemoryContext oldcontext;
	SSLExtensionInfoContext *fctx;

	if (SRF_IS_FIRSTCALL())
	{

		TupleDesc	tupdesc;

		/* create a function context for cross-call persistence */
		funcctx = SRF_FIRSTCALL_INIT();

		/*
		 * Switch to memory context appropriate for multiple function calls
		 */
		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);

		/* Create a user function context for cross-call persistence */
		fctx = (SSLExtensionInfoContext *) palloc(sizeof(SSLExtensionInfoContext));

		/* Construct tuple descriptor */
		if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
			ereport(ERROR,
					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
					 errmsg("function returning record called in context that cannot accept type record")));
		fctx->tupdesc = BlessTupleDesc(tupdesc);

		/* Set max_calls as a count of extensions in certificate */
		max_calls = cert != NULL ? X509_get_ext_count(cert) : 0;

		if (max_calls > 0)
		{
			/* got results, keep track of them */
			funcctx->max_calls = max_calls;
			funcctx->user_fctx = fctx;
		}
		else
		{
			/* fast track when no results */
			MemoryContextSwitchTo(oldcontext);
			SRF_RETURN_DONE(funcctx);
		}

		MemoryContextSwitchTo(oldcontext);
	}

	/* stuff done on every call of the function */
	funcctx = SRF_PERCALL_SETUP();

	/*
	 * Initialize per-call variables.
	 */
	call_cntr = funcctx->call_cntr;
	max_calls = funcctx->max_calls;
	fctx = funcctx->user_fctx;

	/* do while there are more left to send */
	if (call_cntr < max_calls)
	{
		Datum		values[3];
		bool		nulls[3];
		char	   *buf;
		HeapTuple	tuple;
		Datum		result;
		BIO		   *membuf;
		X509_EXTENSION *ext;
		ASN1_OBJECT *obj;
		int			nid;
		int			len;

		/* need a BIO for this */
		membuf = BIO_new(BIO_s_mem());
		if (membuf == NULL)
			ereport(ERROR,
					(errcode(ERRCODE_OUT_OF_MEMORY),
					 errmsg("could not create OpenSSL BIO structure")));

		/* Get the extension from the certificate */
		ext = X509_get_ext(cert, call_cntr);
		obj = X509_EXTENSION_get_object(ext);

		/* Get the extension name */
		nid = OBJ_obj2nid(obj);
		if (nid == NID_undef)
			ereport(ERROR,
					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
					 errmsg("unknown OpenSSL extension in certificate at position %d",
							call_cntr)));
		values[0] = CStringGetTextDatum(OBJ_nid2sn(nid));
		nulls[0] = false;

		/* Get the extension value */
		if (X509V3_EXT_print(membuf, ext, 0, 0) <= 0)
			ereport(ERROR,
					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
					 errmsg("could not print extension value in certificate at position %d",
							call_cntr)));
		len = BIO_get_mem_data(membuf, &buf);
		values[1] = PointerGetDatum(cstring_to_text_with_len(buf, len));
		nulls[1] = false;

		/* Get critical status */
		values[2] = BoolGetDatum(X509_EXTENSION_get_critical(ext));
		nulls[2] = false;

		/* Build tuple */
		tuple = heap_form_tuple(fctx->tupdesc, values, nulls);
		result = HeapTupleGetDatum(tuple);

		if (BIO_free(membuf) != 1)
			elog(ERROR, "could not free OpenSSL BIO structure");

		SRF_RETURN_NEXT(funcctx, result);
	}

	/* All done */
	SRF_RETURN_DONE(funcctx);
}
Ejemplo n.º 4
0
int main(void)
{
#ifndef OPENSSL_NO_SOCK
    SSL_CTX *ctx = NULL;
    SSL *ssl = NULL;
    BIO *outbio = NULL;
    BIO *inbio = NULL;
    BIO_ADDR *peer = BIO_ADDR_new();
    char *data;
    long datalen;
    int ret, success = 0;
    long i;

    ctx = SSL_CTX_new(DTLS_server_method());
    if (ctx == NULL || peer == NULL)
        goto err;

    SSL_CTX_set_cookie_generate_cb(ctx, cookie_gen);
    SSL_CTX_set_cookie_verify_cb(ctx, cookie_verify);

    /* Create an SSL object for the connection */
    ssl = SSL_new(ctx);
    if (ssl == NULL)
        goto err;

    outbio = BIO_new(BIO_s_mem());
    if (outbio == NULL)
        goto err;
    SSL_set_wbio(ssl, outbio);

    success = 1;
    for (i = 0; i < (long)OSSL_NELEM(testpackets) && success; i++) {
        inbio = BIO_new_mem_buf((char *)testpackets[i].in,
                                testpackets[i].inlen);
        if (inbio == NULL) {
            success = 0;
            goto err;
        }
        /* Set Non-blocking IO behaviour */
        BIO_set_mem_eof_return(inbio, -1);

        SSL_set_rbio(ssl, inbio);

        /* Process the incoming packet */
        ret = DTLSv1_listen(ssl, peer);
        if (ret < 0) {
            success = 0;
            goto err;
        }

        datalen = BIO_get_mem_data(outbio, &data);

        if (testpackets[i].outtype == VERIFY) {
            if (ret == 0) {
                if (datalen != sizeof(verify)
                        || (memcmp(data, verify, sizeof(verify)) != 0)) {
                    printf("Test %ld failure: incorrect HelloVerifyRequest\n", i);
                    success = 0;
                } else {
                    printf("Test %ld success\n", i);
                }
            } else {
                printf ("Test %ld failure: should not have succeeded\n", i);
                success = 0;
            }
        } else if (datalen == 0) {
            if ((ret == 0 && testpackets[i].outtype == DROP)
                    || (ret == 1 && testpackets[i].outtype == GOOD)) {
                printf("Test %ld success\n", i);
            } else {
                printf("Test %ld failure: wrong return value\n", i);
                success = 0;
            }
        } else {
            printf("Test %ld failure: Unexpected data output\n", i);
            success = 0;
        }
        (void)BIO_reset(outbio);
        inbio = NULL;
        /* Frees up inbio */
        SSL_set_rbio(ssl, NULL);
    }

 err:
    if (!success)
        ERR_print_errors_fp(stderr);
    /* Also frees up outbio */
    SSL_free(ssl);
    SSL_CTX_free(ctx);
    BIO_free(inbio);
    OPENSSL_free(peer);
# ifndef OPENSSL_NO_CRYPTO_MDEBUG
    CRYPTO_mem_leaks_fp(stderr);
# endif
    return success ? 0 : 1;
#else
    printf("DTLSv1_listen() is not supported by this build - skipping\n");
    return 0;
#endif
}
void optionally_add_header(HMAC_CTX *ctx, struct http_txn *txn, const char* header_name, int header_len) {
  struct hdr_ctx hdr_ctx = {.idx = 0};
  char *begin = NULL;
  char *end   = NULL;
  if(http_find_header2(header_name, header_len, txn->req.sol, &txn->hdr_idx, &hdr_ctx)) {
    begin = hdr_ctx.line + hdr_ctx.val;
    end   = begin + hdr_ctx.vlen;
  }
  // For Date, haproxy does a silly thing where it considers the ',' to be a field separator
  while(http_find_header2(header_name, header_len, txn->req.sol, &txn->hdr_idx, &hdr_ctx)) {
    end = hdr_ctx.line + hdr_ctx.val + hdr_ctx.vlen;
  }
  if(begin) {
    HMAC_Update(ctx, (unsigned char*)begin, end - begin);
  }
  HMAC_Update(ctx, (unsigned const char*)"\n", 1);
}

void make_aws_signature(char *retval, const char *key, int key_len, struct http_txn *txn) {
  struct http_msg *msg = &txn->req;

  static int loaded_engines = 0;
  if(!loaded_engines) {
    ENGINE_load_builtin_engines();
    ENGINE_register_all_complete();
    loaded_engines = 1;
  }
  static unsigned char raw_sig[SIG_SIZE];

  HMAC_CTX ctx;
  HMAC_CTX_init(&ctx);
  HMAC_Init_ex(&ctx, key, key_len, EVP_sha1(), NULL);

  HMAC_Update(&ctx, (unsigned char*)msg->sol + msg->som, msg->sl.rq.m_l);
  HMAC_Update(&ctx, (unsigned const char*)"\n", 1);

  ADD_HEADER(&ctx, txn, "Content-MD5");
  ADD_HEADER(&ctx, txn, "Content-Type");
  ADD_HEADER(&ctx, txn, "Date");

  void *header_sorter = HeaderSorter_new("x-amz-");
  for_each_header(txn, header_sorter, &HeaderSorter_add);
  HeaderSorter_update(header_sorter, &ctx);
  HeaderSorter_delete(header_sorter);
  header_sorter = NULL;

  char *rel_uri = http_get_path(txn);
  char *uri_end = msg->sol + msg->sl.rq.u + txn->req.sl.rq.u_l;
  CanonicalizeResource(&ctx, rel_uri, uri_end - rel_uri);

  unsigned int sig_len = sizeof(raw_sig);
  HMAC_Final(&ctx, raw_sig, &sig_len);
  HMAC_CTX_cleanup(&ctx);

  BIO *mem_output_stream, *b64_filter;
  BUF_MEM *output_buffer;

  b64_filter = BIO_new(BIO_f_base64());
  mem_output_stream = BIO_new(BIO_s_mem());
  b64_filter = BIO_push(b64_filter, mem_output_stream);
  BIO_write(b64_filter, raw_sig, sig_len);
  (void) BIO_flush(b64_filter);
  BIO_get_mem_ptr(b64_filter, &output_buffer);

  memcpy(retval, output_buffer->data, output_buffer->length-1);

  BIO_free_all(b64_filter);
}

int s3_resign(struct session *s, struct buffer *req, struct proxy *px) {
  // TODO: Enable support for query string signatures?

  static struct hdr_exp *exp = NULL;
  if(!exp) {
    exp = calloc(1, sizeof(struct hdr_exp));
    exp->preg    = calloc(1, sizeof(regex_t));
    exp->replace = strdup(px->s3_auth_header);
    exp->action  = ACT_REPLACE;
    regcomp((regex_t*)exp->preg, "^Authorization:.*$", REG_EXTENDED | REG_ICASE);
  }

  if(!px->s3_auth_header || !px->s3_key) {
    printf("In s3_resign but have null config fields?");
    return 0;
  }

  struct http_txn *txn = &s->txn;

  struct hdr_ctx authorization_header = {.idx = 0};
  int ret = http_find_header2("Authorization", 13, txn->req.sol, &txn->hdr_idx, &authorization_header);
  if(!ret) {
    printf("No Authorization, so pass through unsigned.");
    return 0;
  }

  // Using exp->replace is only OK because haproxy is single-threaded, so the buffer 
  // will only serve 1 request at a time.
  make_aws_signature((char*)exp->replace + px->s3_auth_header_colon,
    px->s3_key, px->s3_key_len, txn);

  apply_filter_to_req_headers(s, req, exp);

  return 0;
}
Ejemplo n.º 6
0
/** Create a new server TLS session
 *
 * Configures a new server TLS session, configuring options, setting callbacks etc...
 *
 * @param ctx		to alloc session data in. Should usually be NULL unless the lifetime of the
 *			session is tied to another talloc'd object.
 * @param conf		values for this TLS session.
 * @param request	The current #REQUEST.
 * @param client_cert	Whether to require a client_cert.
 * @return
 *	- A new session on success.
 *	- NULL on error.
 */
tls_session_t *tls_session_init_server(TALLOC_CTX *ctx, fr_tls_conf_t *conf, REQUEST *request, bool client_cert)
{
	tls_session_t	*session = NULL;
	SSL		*new_tls = NULL;
	int		verify_mode = 0;
	VALUE_PAIR	*vp;
	SSL_CTX		*ssl_ctx;

	rad_assert(request != NULL);
	rad_assert(conf->ctx_count > 0);

	RDEBUG2("Initiating new TLS session");

	ssl_ctx = conf->ctx[(conf->ctx_count == 1) ? 0 : conf->ctx_next++ % conf->ctx_count];	/* mutex not needed */
	rad_assert(ssl_ctx);

	new_tls = SSL_new(ssl_ctx);
	if (new_tls == NULL) {
		tls_log_error(request, "Error creating new TLS session");
		return NULL;
	}

	session = talloc_zero(ctx, tls_session_t);
	if (session == NULL) {
		RERROR("Error allocating memory for TLS session");
		SSL_free(new_tls);

		return NULL;
	}
	session_init(session);
	session->ctx = ssl_ctx;
	session->ssl = new_tls;

	talloc_set_destructor(session, _tls_session_free);

	/*
	 *	Initialize callbacks
	 */
	session->record_init = record_init;
	session->record_close = record_close;
	session->record_from_buff = record_from_buff;
	session->record_to_buff = record_to_buff;

	/*
	 *	Create & hook the BIOs to handle the dirty side of the
	 *	SSL.  This is *very important* as we want to handle
	 *	the transmission part.  Now the only IO interface
	 *	that SSL is aware of, is our defined BIO buffers.
	 *
	 *	This means that all SSL IO is done to/from memory,
	 *	and we can update those BIOs from the packets we've
	 *	received.
	 */
	session->into_ssl = BIO_new(BIO_s_mem());
	session->from_ssl = BIO_new(BIO_s_mem());
	SSL_set_bio(session->ssl, session->into_ssl, session->from_ssl);

	/*
	 *	Add the message callback to identify what type of
	 *	message/handshake is passed
	 */
	SSL_set_msg_callback(new_tls, tls_session_msg_cb);
	SSL_set_msg_callback_arg(new_tls, session);
	SSL_set_info_callback(new_tls, tls_session_info_cb);

	/*
	 *	This sets the context sessions can be resumed in.
	 *	This is to prevent sessions being created by one application
	 *	and used by another.  In our case it prevents sessions being
	 *	reused between modules, or TLS server components such as
	 *	RADSEC.
	 *
	 *	A context must always be set when doing session resumption
	 *	otherwise session resumption will fail.
	 *
	 *	As the context ID must be <= 32, we digest the context
	 *	data with sha256.
	 */
	rad_assert(conf->session_id_name);
	{
		char		*context_id;
		EVP_MD_CTX	*md_ctx;
		uint8_t		digest[SHA256_DIGEST_LENGTH];

		static_assert(sizeof(digest) <= SSL_MAX_SSL_SESSION_ID_LENGTH,
			      "SSL_MAX_SSL_SESSION_ID_LENGTH must be >= SHA256_DIGEST_LENGTH");

		if (tmpl_aexpand(session, &context_id, request, conf->session_id_name, NULL, NULL) < 0) {
			RPEDEBUG("Failed expanding session ID");
			talloc_free(session);
		}

		MEM(md_ctx = EVP_MD_CTX_create());
		EVP_DigestInit_ex(md_ctx, EVP_sha256(), NULL);
		EVP_DigestUpdate(md_ctx, context_id, talloc_array_length(context_id) - 1);
		EVP_DigestFinal_ex(md_ctx, digest, NULL);
		EVP_MD_CTX_destroy(md_ctx);
		talloc_free(context_id);

		if (!fr_cond_assert(SSL_set_session_id_context(session->ssl, digest, sizeof(digest)) == 1)) {
			talloc_free(session);
			return NULL;
		}
	}

	/*
	 *	Add the session certificate to the session.
	 */
	vp = fr_pair_find_by_da(request->control, attr_tls_session_cert_file, TAG_ANY);
	if (vp) {
		RDEBUG2("Loading TLS session certificate \"%s\"", vp->vp_strvalue);

		if (SSL_use_certificate_file(session->ssl, vp->vp_strvalue, SSL_FILETYPE_PEM) != 1) {
			tls_log_error(request, "Failed loading TLS session certificate \"%s\"",
				      vp->vp_strvalue);
			talloc_free(session);
			return NULL;
		}

		if (SSL_use_PrivateKey_file(session->ssl, vp->vp_strvalue, SSL_FILETYPE_PEM) != 1) {
			tls_log_error(request, "Failed loading TLS session certificate \"%s\"",
				      vp->vp_strvalue);
			talloc_free(session);
			return NULL;
		}

		if (SSL_check_private_key(session->ssl) != 1) {
			tls_log_error(request, "Failed validating TLS session certificate \"%s\"",
				      vp->vp_strvalue);
			talloc_free(session);
			return NULL;
		}
	/*
	 *	Better to perform explicit checks, than rely
	 *	on OpenSSL's opaque error messages.
	 */
	} else {
		if (!conf->chains || !conf->chains[0]->private_key_file) {
			ERROR("TLS Server requires a private key file");
			talloc_free(session);
			return NULL;
		}

		if (!conf->chains || !conf->chains[0]->certificate_file) {
			ERROR("TLS Server requires a certificate file");
			talloc_free(session);
			return NULL;
		}
	}

	/*
	 *	In Server mode we only accept.
	 *
	 *	This sets up the SSL session to work correctly with
	 *	tls_session_handhsake.
	 */
	SSL_set_accept_state(session->ssl);

	/*
	 *	Verify the peer certificate, if asked.
	 */
	if (client_cert) {
		RDEBUG2("Setting verify mode to require certificate from client");
		verify_mode = SSL_VERIFY_PEER;
		verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
		verify_mode |= SSL_VERIFY_CLIENT_ONCE;
	}
	SSL_set_verify(session->ssl, verify_mode, tls_validate_cert_cb);

	SSL_set_ex_data(session->ssl, FR_TLS_EX_INDEX_CONF, (void *)conf);
	SSL_set_ex_data(session->ssl, FR_TLS_EX_INDEX_TLS_SESSION, (void *)session);

	/*
	 *	We use default fragment size, unless the Framed-MTU
	 *	tells us it's too big.  Note that we do NOT account
	 *	for the EAP-TLS headers if conf->fragment_size is
	 *	large, because that config item looks to be confusing.
	 *
	 *	i.e. it should REALLY be called MTU, and the code here
	 *	should figure out what that means for TLS fragment size.
	 *	asking the administrator to know the internal details
	 *	of EAP-TLS in order to calculate fragment sizes is
	 *	just too much.
	 */
	session->mtu = conf->fragment_size;
	vp = fr_pair_find_by_da(request->packet->vps, attr_framed_mtu, TAG_ANY);
	if (vp && (vp->vp_uint32 > 100) && (vp->vp_uint32 < session->mtu)) {
		RDEBUG2("Setting fragment_len to %u from &Framed-MTU", vp->vp_uint32);
		session->mtu = vp->vp_uint32;
	}

	if (conf->session_cache_server) session->allow_session_resumption = true; /* otherwise it's false */

	return session;
}
Ejemplo n.º 7
0
char *
ssl_load_key(const char *name, off_t *len, char *pass, mode_t perm, const char *pkiname)
{
	FILE		*fp = NULL;
	EVP_PKEY	*key = NULL;
	BIO		*bio = NULL;
	long		 size;
	char		*data, *buf = NULL;
	struct stat	 st;
	char		 mode[12];
	char		 prompt[2048];

	/* Initialize SSL library once */
	ssl_init();

	/*
	 * Read (possibly) encrypted key from file
	 */
	if ((fp = fopen(name, "r")) == NULL)
		return (NULL);

	if (fstat(fileno(fp), &st) != 0)
		goto fail;
	if (st.st_uid != 0) {
		log_warnx("warn:  %s: not owned by uid 0", name);
		errno = EACCES;
		goto fail;
	}
	if (st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO) & ~perm) {
		strmode(perm, mode);
		log_warnx("warn:  %s: insecure permissions: must be at most %s",
		    name, &mode[1]);
		errno = EACCES;
		goto fail;
	}

	(void)snprintf(prompt, sizeof prompt, "passphrase for %s: ", pkiname);
	key = PEM_read_PrivateKey(fp, NULL, ssl_password_cb, prompt);
	fclose(fp);
	fp = NULL;
	if (key == NULL)
		goto fail;
	/*
	 * Write unencrypted key to memory buffer
	 */
	if ((bio = BIO_new(BIO_s_mem())) == NULL)
		goto fail;
	if (!PEM_write_bio_PrivateKey(bio, key, NULL, NULL, 0, NULL, NULL))
		goto fail;
	if ((size = BIO_get_mem_data(bio, &data)) <= 0)
		goto fail;
	if ((buf = calloc(1, size + 1)) == NULL)
		goto fail;
	memcpy(buf, data, size);

	BIO_free_all(bio);
	EVP_PKEY_free(key);

	*len = (off_t)size + 1;
	return (buf);

fail:
	ssl_error("ssl_load_key");
	free(buf);
	if (bio != NULL)
		BIO_free_all(bio);
	if (key != NULL)
		EVP_PKEY_free(key);
	if (fp)
		fclose(fp);
	return (NULL);
}
Ejemplo n.º 8
0
int FuzzerTestOneInput(const uint8_t *buf, size_t len)
{
    SSL *server;
    BIO *in;
    BIO *out;
    BIO *bio_buf;
    SSL_CTX *ctx;
    int ret;
    RSA *privkey;
    const uint8_t *bufp;
    EVP_PKEY *pkey;
    X509 *cert;
#ifndef OPENSSL_NO_EC
    EC_KEY *ecdsakey = NULL;
#endif
#ifndef OPENSSL_NO_DSA
    DSA *dsakey = NULL;
#endif
    uint8_t opt;

    if (len < 2)
        return 0;

    /*
     * TODO: use the ossltest engine (optionally?) to disable crypto checks.
     */

    /* This only fuzzes the initial flow from the client so far. */
    ctx = SSL_CTX_new(SSLv23_method());

    /* RSA */
    bufp = kRSAPrivateKeyDER;
    privkey = d2i_RSAPrivateKey(NULL, &bufp, sizeof(kRSAPrivateKeyDER));
    OPENSSL_assert(privkey != NULL);
    pkey = EVP_PKEY_new();
    EVP_PKEY_assign_RSA(pkey, privkey);
    ret = SSL_CTX_use_PrivateKey(ctx, pkey);
    OPENSSL_assert(ret == 1);
    EVP_PKEY_free(pkey);

    bufp = kCertificateDER;
    cert = d2i_X509(NULL, &bufp, sizeof(kCertificateDER));
    OPENSSL_assert(cert != NULL);
    ret = SSL_CTX_use_certificate(ctx, cert);
    OPENSSL_assert(ret == 1);
    X509_free(cert);

#ifndef OPENSSL_NO_EC
    /* ECDSA */
    bio_buf = BIO_new(BIO_s_mem());
    OPENSSL_assert((size_t)BIO_write(bio_buf, ECDSAPrivateKeyPEM, sizeof(ECDSAPrivateKeyPEM)) == sizeof(ECDSAPrivateKeyPEM));
    ecdsakey = PEM_read_bio_ECPrivateKey(bio_buf, NULL, NULL, NULL);
    ERR_print_errors_fp(stderr);
    OPENSSL_assert(ecdsakey != NULL);
    BIO_free(bio_buf);
    pkey = EVP_PKEY_new();
    EVP_PKEY_assign_EC_KEY(pkey, ecdsakey);
    ret = SSL_CTX_use_PrivateKey(ctx, pkey);
    OPENSSL_assert(ret == 1);
    EVP_PKEY_free(pkey);

    bio_buf = BIO_new(BIO_s_mem());
    OPENSSL_assert((size_t)BIO_write(bio_buf, ECDSACertPEM, sizeof(ECDSACertPEM)) == sizeof(ECDSACertPEM));
    cert = PEM_read_bio_X509(bio_buf, NULL, NULL, NULL);
    OPENSSL_assert(cert != NULL);
    BIO_free(bio_buf);
    ret = SSL_CTX_use_certificate(ctx, cert);
    OPENSSL_assert(ret == 1);
    X509_free(cert);
#endif

#ifndef OPENSSL_NO_DSA
    /* DSA */
    bio_buf = BIO_new(BIO_s_mem());
    OPENSSL_assert((size_t)BIO_write(bio_buf, DSAPrivateKeyPEM, sizeof(DSAPrivateKeyPEM)) == sizeof(DSAPrivateKeyPEM));
    dsakey = PEM_read_bio_DSAPrivateKey(bio_buf, NULL, NULL, NULL);
    ERR_print_errors_fp(stderr);
    OPENSSL_assert(dsakey != NULL);
    BIO_free(bio_buf);
    pkey = EVP_PKEY_new();
    EVP_PKEY_assign_DSA(pkey, dsakey);
    ret = SSL_CTX_use_PrivateKey(ctx, pkey);
    OPENSSL_assert(ret == 1);
    EVP_PKEY_free(pkey);

    bio_buf = BIO_new(BIO_s_mem());
    OPENSSL_assert((size_t)BIO_write(bio_buf, DSACertPEM, sizeof(DSACertPEM)) == sizeof(DSACertPEM));
    cert = PEM_read_bio_X509(bio_buf, NULL, NULL, NULL);
    OPENSSL_assert(cert != NULL);
    BIO_free(bio_buf);
    ret = SSL_CTX_use_certificate(ctx, cert);
    OPENSSL_assert(ret == 1);
    X509_free(cert);
#endif

    /* TODO: Set up support for SRP and PSK */

    server = SSL_new(ctx);
    ret = SSL_set_cipher_list(server, "ALL:eNULL:@SECLEVEL=0");
    OPENSSL_assert(ret == 1);
    in = BIO_new(BIO_s_mem());
    out = BIO_new(BIO_s_mem());
    SSL_set_bio(server, in, out);
    SSL_set_accept_state(server);

    opt = (uint8_t)buf[len-1];
    len--;

    OPENSSL_assert((size_t)BIO_write(in, buf, len) == len);

    if ((opt & 0x01) != 0)
    {
        do {
            char early_buf[16384];
            size_t early_len;
            ret = SSL_read_early_data(server, early_buf, sizeof(early_buf), &early_len);

            if (ret != SSL_READ_EARLY_DATA_SUCCESS)
                break;
        } while (1);
    }

    if (SSL_do_handshake(server) == 1) {
        /* Keep reading application data until error or EOF. */
        uint8_t tmp[1024];
        for (;;) {
            if (SSL_read(server, tmp, sizeof(tmp)) <= 0) {
                break;
            }
        }
    }
    SSL_free(server);
    ERR_clear_error();
    SSL_CTX_free(ctx);

    return 0;
}
Ejemplo n.º 9
0
int doit(char *ctx[4])
	{
	SSL_CTX *s_ctx,*c_ctx;
	static char cbuf[200],sbuf[200];
	SSL *c_ssl=NULL;
	SSL *s_ssl=NULL;
	BIO *c_to_s=NULL;
	BIO *s_to_c=NULL;
	BIO *c_bio=NULL;
	BIO *s_bio=NULL;
	int c_r,c_w,s_r,s_w;
	int c_want,s_want;
	int i;
	int done=0;
	int c_write,s_write;
	int do_server=0,do_client=0;

	s_ctx=(SSL_CTX *)ctx[0];
	c_ctx=(SSL_CTX *)ctx[1];

	if (ctx[2] != NULL)
		s_ssl=(SSL *)ctx[2];
	else
		s_ssl=SSL_new(s_ctx);

	if (ctx[3] != NULL)
		c_ssl=(SSL *)ctx[3];
	else
		c_ssl=SSL_new(c_ctx);

	if ((s_ssl == NULL) || (c_ssl == NULL)) goto err;

	c_to_s=BIO_new(BIO_s_mem());
	s_to_c=BIO_new(BIO_s_mem());
	if ((s_to_c == NULL) || (c_to_s == NULL)) goto err;

	c_bio=BIO_new(BIO_f_ssl());
	s_bio=BIO_new(BIO_f_ssl());
	if ((c_bio == NULL) || (s_bio == NULL)) goto err;

	SSL_set_connect_state(c_ssl);
	SSL_set_bio(c_ssl,s_to_c,c_to_s);
	BIO_set_ssl(c_bio,c_ssl,(ctx[2] == NULL)?BIO_CLOSE:BIO_NOCLOSE);

	SSL_set_accept_state(s_ssl);
	SSL_set_bio(s_ssl,c_to_s,s_to_c);
	BIO_set_ssl(s_bio,s_ssl,(ctx[3] == NULL)?BIO_CLOSE:BIO_NOCLOSE);

	c_r=0; s_r=1;
	c_w=1; s_w=0;
	c_want=W_WRITE;
	s_want=0;
	c_write=1,s_write=0;

	/* We can always do writes */
	for (;;)
		{
		do_server=0;
		do_client=0;

		i=(int)BIO_pending(s_bio);
		if ((i && s_r) || s_w) do_server=1;

		i=(int)BIO_pending(c_bio);
		if ((i && c_r) || c_w) do_client=1;

		if (do_server && verbose)
			{
			if (SSL_in_init(s_ssl))
				printf("server waiting in SSL_accept - %s\n",
					SSL_state_string_long(s_ssl));
			else if (s_write)
				printf("server:SSL_write()\n");
			else 
				printf("server:SSL_read()\n");
			}

		if (do_client && verbose)
			{
			if (SSL_in_init(c_ssl))
				printf("client waiting in SSL_connect - %s\n",
					SSL_state_string_long(c_ssl));
			else if (c_write)
				printf("client:SSL_write()\n");
			else
				printf("client:SSL_read()\n");
			}

		if (!do_client && !do_server)
			{
			fprintf(stdout,"ERROR IN STARTUP\n");
			break;
			}
		if (do_client && !(done & C_DONE))
			{
			if (c_write)
				{
				i=BIO_write(c_bio,"hello from client\n",18);
				if (i < 0)
					{
					c_r=0;
					c_w=0;
					if (BIO_should_retry(c_bio))
						{
						if (BIO_should_read(c_bio))
							c_r=1;
						if (BIO_should_write(c_bio))
							c_w=1;
						}
					else
						{
						fprintf(stderr,"ERROR in CLIENT\n");
						ERR_print_errors_fp(stderr);
						return(1);
						}
					}
				else if (i == 0)
					{
					fprintf(stderr,"SSL CLIENT STARTUP FAILED\n");
					return(1);
					}
				else
					{
					/* ok */
					c_write=0;
					}
				}
			else
				{
				i=BIO_read(c_bio,cbuf,100);
				if (i < 0)
					{
					c_r=0;
					c_w=0;
					if (BIO_should_retry(c_bio))
						{
						if (BIO_should_read(c_bio))
							c_r=1;
						if (BIO_should_write(c_bio))
							c_w=1;
						}
					else
						{
						fprintf(stderr,"ERROR in CLIENT\n");
						ERR_print_errors_fp(stderr);
						return(1);
						}
					}
				else if (i == 0)
					{
					fprintf(stderr,"SSL CLIENT STARTUP FAILED\n");
					return(1);
					}
				else
					{
					done|=C_DONE;
#ifdef undef
					fprintf(stdout,"CLIENT:from server:");
					fwrite(cbuf,1,i,stdout);
					fflush(stdout);
#endif
					}
				}
			}

		if (do_server && !(done & S_DONE))
			{
			if (!s_write)
				{
				i=BIO_read(s_bio,sbuf,100);
				if (i < 0)
					{
					s_r=0;
					s_w=0;
					if (BIO_should_retry(s_bio))
						{
						if (BIO_should_read(s_bio))
							s_r=1;
						if (BIO_should_write(s_bio))
							s_w=1;
						}
					else
						{
						fprintf(stderr,"ERROR in SERVER\n");
						ERR_print_errors_fp(stderr);
						return(1);
						}
					}
				else if (i == 0)
					{
					fprintf(stderr,"SSL SERVER STARTUP FAILED\n");
					return(1);
					}
				else
					{
					s_write=1;
					s_w=1;
#ifdef undef
					fprintf(stdout,"SERVER:from client:");
					fwrite(sbuf,1,i,stdout);
					fflush(stdout);
#endif
					}
				}
			else
				{
				i=BIO_write(s_bio,"hello from server\n",18);
				if (i < 0)
					{
					s_r=0;
					s_w=0;
					if (BIO_should_retry(s_bio))
						{
						if (BIO_should_read(s_bio))
							s_r=1;
						if (BIO_should_write(s_bio))
							s_w=1;
						}
					else
						{
						fprintf(stderr,"ERROR in SERVER\n");
						ERR_print_errors_fp(stderr);
						return(1);
						}
					}
				else if (i == 0)
					{
					fprintf(stderr,"SSL SERVER STARTUP FAILED\n");
					return(1);
					}
				else
					{
					s_write=0;
					s_r=1;
					done|=S_DONE;
					}
				}
			}

		if ((done & S_DONE) && (done & C_DONE)) break;
#   if defined(OPENSSL_SYS_NETWARE)
        ThreadSwitchWithDelay();
#   endif
		}

	SSL_set_shutdown(c_ssl,SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
	SSL_set_shutdown(s_ssl,SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);

#ifdef undef
	fprintf(stdout,"DONE\n");
#endif
err:
	/* We have to set the BIO's to NULL otherwise they will be
	 * free()ed twice.  Once when th s_ssl is SSL_free()ed and
	 * again when c_ssl is SSL_free()ed.
	 * This is a hack required because s_ssl and c_ssl are sharing the same
	 * BIO structure and SSL_set_bio() and SSL_free() automatically
	 * BIO_free non NULL entries.
	 * You should not normally do this or be required to do this */

	if (s_ssl != NULL)
		{
		s_ssl->rbio=NULL;
		s_ssl->wbio=NULL;
		}
	if (c_ssl != NULL)
		{
		c_ssl->rbio=NULL;
		c_ssl->wbio=NULL;
		}

	/* The SSL's are optionally freed in the following calls */
	if (c_to_s != NULL) BIO_free(c_to_s);
	if (s_to_c != NULL) BIO_free(s_to_c);

	if (c_bio != NULL) BIO_free(c_bio);
	if (s_bio != NULL) BIO_free(s_bio);
	return(0);
	}
Ejemplo n.º 10
0
/*! @brief est_convert_p7b64_to_pem() converts the base64 encoded
    PKCS7 response from the EST server into PEM format.   
 
    @param certs_p7 Points to a buffer containing the base64 encoded pkcs7 data.
    @param certs_len Indicates the size of the *certs_p7 buffer.
    @param pem Double pointer that will receive the PEM encoded data. 
 
    Several of the EST message return data that contains base64 encoded PKCS7
    certificates.  This function is used to convert the data to PEM format.
    This function will allocate memory pointed to by the **pem argument.
    The caller is responsible for releasing this memory.  The return value
    is the length of the PEM buffer, or -1 on error.
 
    @return int.
 */
int est_convert_p7b64_to_pem (unsigned char *certs_p7, int certs_len, unsigned char **pem)
{
    X509 *x;
    STACK_OF(X509) *certs = NULL;
    BIO *b64, *in, *out;
    unsigned char *cacerts_decoded = NULL;
    int  cacerts_decoded_len = 0;
    BIO *p7bio_in = NULL;
    PKCS7 *p7=NULL;
    int i, nid;
    unsigned char *pem_data;
    int pem_len;

    /*
     * Base64 decode the incoming ca certs buffer.  Decoding will
     * always take up no more than the original buffer.
     */
    b64 = BIO_new(BIO_f_base64());
    if (!b64) {
	EST_LOG_ERR("BIO_new failed");
	return (-1);
    }    
    in = BIO_new_mem_buf(certs_p7, certs_len);    
    if (!in) {
	EST_LOG_ERR("BIO_new failed");
	return (-1);
    }
    in = BIO_push(b64, in);    
    cacerts_decoded = malloc(certs_len);
    if (!cacerts_decoded) {
	EST_LOG_ERR("malloc failed");
	return (-1);
    }
    cacerts_decoded_len = BIO_read(in, cacerts_decoded, certs_len);    
    BIO_free_all(in);
    /*
     * Now get the PKCS7 formatted buffer of certificates read into a stack of
     * X509 certs
     */
    p7bio_in = BIO_new_mem_buf(cacerts_decoded, cacerts_decoded_len);
    if (!p7bio_in) {
        EST_LOG_ERR("BIO_new failed while attempting to create mem BIO");
        ossl_dump_ssl_errors();
        free(cacerts_decoded);
        return (-1);
    }
    p7 = d2i_PKCS7_bio(p7bio_in, NULL);
    if (!p7) {
	EST_LOG_ERR("PEM_read_bio_PKCS7 failed");
	ossl_dump_ssl_errors();
        free(cacerts_decoded);
	return (-1);
    }
    BIO_free_all(p7bio_in);
    free(cacerts_decoded);
    
    /*
     * Now that we've decoded the certs, get a reference
     * the the stack of certs
     */
    nid=OBJ_obj2nid(p7->type);
    switch (nid)
        {
        case NID_pkcs7_signed:
            certs = p7->d.sign->cert;
            break;
        case NID_pkcs7_signedAndEnveloped:
            certs = p7->d.signed_and_enveloped->cert;
            break;
        default:
            EST_LOG_ERR("Invalid NID value on PKCS7 structure");
	    PKCS7_free(p7);
	    return (-1);
            break;
        }

    if (!certs) {
        EST_LOG_ERR("Failed to attain X509 cert stack from PKCS7 data");
	PKCS7_free(p7);
	return (-1);
    }

    /*
     * Output the certs to a new BIO using the PEM format 
     */
    out = BIO_new(BIO_s_mem());
    if (!out) {
        EST_LOG_ERR("BIO_new failed");
	PKCS7_free(p7);
	return (-1);
    }
    for (i=0; i<sk_X509_num(certs); i++) {
        x=sk_X509_value(certs, i);
	PEM_write_bio_X509(out, x);
	BIO_puts(out, "\n");
    }
    (void)BIO_flush(out);

    /*
     * Now convert the BIO to char*
     */
    pem_len = (int) BIO_get_mem_data(out, (char**)&pem_data);
    if (pem_len <= 0) {
        EST_LOG_ERR("BIO_get_mem_data failed");
	PKCS7_free(p7);
	return (-1);
    }

    *pem = malloc(pem_len + 1);
    if (!*pem) {
        EST_LOG_ERR("malloc failed");
	PKCS7_free(p7);
	return (-1);
    }
    memcpy_s(*pem, pem_len, pem_data, pem_len);   
    (*pem)[pem_len] = 0;  //Make sure it's null termianted
    BIO_free_all(out);
    PKCS7_free(p7);
    return (pem_len);
}
Ejemplo n.º 11
0
int
lws_x509_jwk_privkey_pem(struct lws_jwk *jwk, void *pem, size_t len,
			 const char *passphrase)
{
	BIO* bio = BIO_new(BIO_s_mem());
	BIGNUM *mpi, *dummy[6];
	EVP_PKEY *pkey = NULL;
	EC_KEY *ecpriv = NULL;
	RSA *rsapriv = NULL;
	const BIGNUM *cmpi;
	int n, m, ret = -1;

	BIO_write(bio, pem, len);
	PEM_read_bio_PrivateKey(bio, &pkey, lws_x509_jwk_privkey_pem_pp_cb,
				(void *)passphrase);
	BIO_free(bio);
	lws_explicit_bzero((void *)pem, len);
	if (!pkey) {
		lwsl_err("%s: unable to parse PEM privkey\n", __func__);
		lws_tls_err_describe();

		return -1;
	}

	/* confirm the key type matches the existing jwk situation */

	switch (jwk->kty) {
	case LWS_GENCRYPTO_KTY_EC:
		if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_EC) {
			lwsl_err("%s: jwk is EC but privkey isn't\n", __func__);

			goto bail;
		}
		ecpriv = EVP_PKEY_get1_EC_KEY(pkey);
		if (!ecpriv) {
			lwsl_notice("%s: missing EC key\n", __func__);

			goto bail;
		}

		cmpi = EC_KEY_get0_private_key(ecpriv);

		/* quick size check first */

		n = BN_num_bytes(cmpi);
		if (jwk->e[LWS_GENCRYPTO_EC_KEYEL_Y].len != (uint32_t)n) {
			lwsl_err("%s: jwk key size doesn't match\n", __func__);

			goto bail1;
		}

		/* TODO.. check public curve / group + point */

		jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].len = n;
		jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].buf = lws_malloc(n, "ec");
		if (!jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].buf)
			goto bail1;

		m = BN_bn2binpad(cmpi, jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].buf,
				      jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].len);
		if (m != BN_num_bytes(cmpi))
			goto bail1;

		break;

	case LWS_GENCRYPTO_KTY_RSA:
		if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_RSA) {
			lwsl_err("%s: RSA jwk, non-RSA privkey\n", __func__);

			goto bail;
		}
		rsapriv = EVP_PKEY_get1_RSA(pkey);
		if (!rsapriv) {
			lwsl_notice("%s: missing RSA key\n", __func__);

			goto bail;
		}

#if defined(LWS_HAVE_RSA_SET0_KEY)
		RSA_get0_key(rsapriv, (const BIGNUM **)&dummy[0], /* n */
				      (const BIGNUM **)&dummy[1], /* e */
				      (const BIGNUM **)&mpi);	  /* d */
		RSA_get0_factors(rsapriv, (const BIGNUM **)&dummy[4],  /* p */
					  (const BIGNUM **)&dummy[5]); /* q */
#else
		dummy[0] = rsapriv->n;
		dummy[1] = rsapriv->e;
		dummy[4] = rsapriv->p;
		dummy[5] = rsapriv->q;
		mpi = rsapriv->d;
#endif

		/* quick size check first */

		n = BN_num_bytes(mpi);
		if (jwk->e[LWS_GENCRYPTO_RSA_KEYEL_N].len != (uint32_t)n) {
			lwsl_err("%s: jwk key size doesn't match\n", __func__);

			goto bail1;
		}

		/* then check that n & e match what we got from the cert */

		dummy[2] = BN_bin2bn(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_N].buf,
				     jwk->e[LWS_GENCRYPTO_RSA_KEYEL_N].len,
				     NULL);
		dummy[3] = BN_bin2bn(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_E].buf,
				     jwk->e[LWS_GENCRYPTO_RSA_KEYEL_E].len,
				     NULL);

		m = BN_cmp(dummy[2], dummy[0]) | BN_cmp(dummy[3], dummy[1]);
		BN_clear_free(dummy[2]);
		BN_clear_free(dummy[3]);
		if (m) {
			lwsl_err("%s: privkey doesn't match jwk pubkey\n",
				 __func__);

			goto bail1;
		}

		/* accept d from the PEM privkey into the JWK */

		jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].len = n;
		jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf = lws_malloc(n, "privjk");
		if (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf)
			goto bail1;

		BN_bn2bin(mpi, jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf);

		/* accept p and q from the PEM privkey into the JWK */

		jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].len = BN_num_bytes(dummy[4]);
		jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf = lws_malloc(n, "privjk");
		if (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf) {
			lws_free_set_NULL(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf);
			goto bail1;
		}
		BN_bn2bin(dummy[4], jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf);

		jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].len = BN_num_bytes(dummy[5]);
		jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf = lws_malloc(n, "privjk");
		if (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf) {
			lws_free_set_NULL(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf);
			lws_free_set_NULL(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf);
			goto bail1;
		}
		BN_bn2bin(dummy[5], jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf);
		break;
	default:
		lwsl_err("%s: JWK has unknown kty %d\n", __func__, jwk->kty);
		return -1;
	}

	ret = 0;

bail1:
	if (jwk->kty == LWS_GENCRYPTO_KTY_EC)
		EC_KEY_free(ecpriv);
	else
		RSA_free(rsapriv);

bail:
	EVP_PKEY_free(pkey);

	return ret;
}
void LFNetConfigLoader::retrieveConfig()
{
    this->notifyStatus("Loading OpenSSL stuff ...");
    OpenSSL_add_all_algorithms();
    ERR_load_BIO_strings();
    ERR_load_crypto_strings();

    this->notifyStatus("Generating private key ...");

    BIGNUM* e = BN_new();
    BN_set_word(e, RSA_F4);

    RSA* key = RSA_new();
    RSA_generate_key_ex(key, 4096, e, NULL);

    this->notifyStatus("Saving private key ...");

    BIO* privateKey = BIO_new_file((_configLocation + "/private.key").toLocal8Bit().data(), "w");
    PEM_write_bio_RSAPrivateKey(privateKey, key, NULL, NULL, 0, NULL, NULL);
    BIO_free(privateKey);

    this->notifyStatus("Generating csr ...");

    EVP_PKEY* pkey = EVP_PKEY_new();
    EVP_PKEY_assign_RSA(pkey, key);

    X509_NAME* name = X509_NAME_new();
    X509_NAME_add_entry_by_txt(name, "O",  MBSTRING_UTF8, (unsigned char*)"LF-Net", -1, -1, 0);
    X509_NAME_add_entry_by_txt(name, "OU", MBSTRING_UTF8, (unsigned char*)"VPN", -1, -1, 0);
    X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_UTF8, (unsigned char*)(_username.toUpper() + "_" + _computerName.toUpper()).toUtf8().data(), -1, -1, 0);

    X509_REQ* req = X509_REQ_new();
    X509_REQ_set_pubkey(req, pkey);
    X509_REQ_set_subject_name(req, name);
    X509_REQ_set_version(req, 1);
    X509_REQ_sign(req, pkey, EVP_sha512());

    BIO* request = BIO_new(BIO_s_mem());
    PEM_write_bio_X509_REQ(request, req);

    BUF_MEM* requestData;
    BIO_get_mem_ptr(request, &requestData);

    this->notifyStatus("Request certificate using generated csr ...");

    QNetworkAccessManager *mgr = new QNetworkAccessManager(this);
    connect(mgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(certificateRequestFinished(QNetworkReply*)));
    connect(mgr, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), this, SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*)));

    QNetworkRequest netRequest(QUrl("https://mokoscha.lf-net.org/request_certificate"));
    netRequest.setHeader(QNetworkRequest::ContentTypeHeader, "text/plain");

    mgr->post(netRequest, QByteArray(requestData->data, requestData->length));

    this->notifyStatus("Cleaning up temporary data ...");
    BIO_free(request);
    X509_REQ_free(req);
    X509_NAME_free(name);
    EVP_PKEY_free(pkey);
    BN_free(e);

    this->notifyStatus("Waiting for certificate ...");
}
int createCertificateRequest(char* result, char* keyToCertify, char * country, char* state, char* loc, char* organisation, char *organisationUnit, char* cname, char* email)
{
  BIO *mem = BIO_new(BIO_s_mem());
  X509_REQ *req=X509_REQ_new();
  X509_NAME *nm = X509_NAME_new();
  int err=0;

  //fill in details
  if (strlen(country) > 0) {
    if(!(err = X509_NAME_add_entry_by_txt(nm,"C",
      MBSTRING_UTF8, (unsigned char*)country, -1, -1, 0))) {
      return err;
    }
  }
  if (strlen(state) > 0) {
    if(!(err = X509_NAME_add_entry_by_txt(nm,"ST",
      MBSTRING_UTF8, (unsigned char*)state, -1, -1, 0))) {
      return err;
    }
  }
  if (strlen(loc) > 0) {
    if(!(err = X509_NAME_add_entry_by_txt(nm,"L",
      MBSTRING_UTF8, (unsigned char*)loc, -1, -1, 0))) {
      return err;
    }
  }
  if (strlen(organisation) > 0) {
    if(!(err = X509_NAME_add_entry_by_txt(nm,"O",
      MBSTRING_UTF8, (unsigned char*)organisation, -1, -1, 0))) {
      return err;
    }
  }

  if (strlen(organisationUnit) > 0) {
    if(!(err = X509_NAME_add_entry_by_txt(nm,"OU",
      MBSTRING_UTF8, (unsigned char*)organisationUnit, -1, -1, 0))) {
      return err;
    }
  }

   // This is mandatory to have, rest are optional
  if(!(err = X509_NAME_add_entry_by_txt(nm,"CN", MBSTRING_UTF8, (unsigned char*) cname, -1, -1, 0))) {
    return err;
  }

  if (strlen(email) > 0) {
    if(!(err = X509_NAME_add_entry_by_txt(nm,"emailAddress",MBSTRING_UTF8, (unsigned char*)email, -1, -1, 0))) {
      return err;
    }
  }

  if(!(err = X509_REQ_set_subject_name(req, nm))) {
    return err;
  }

    //Set the public key
  //...convert PEM private key into a BIO

  BIO* bmem = BIO_new_mem_buf(keyToCertify, -1);
  if (!bmem) {
    BIO_free(bmem);
    return -3;
  }

  // read the private key into an EVP_PKEY structure
  EVP_PKEY* privkey = PEM_read_bio_PrivateKey(bmem, NULL, NULL, NULL);
  if (!privkey) {
    BIO_free(bmem);
    return -4;
  }


  if(!(err = X509_REQ_set_pubkey(req, privkey)))
  {
    BIO_free(bmem);
    return err;
  }

  if(!(err = X509_REQ_set_version(req,3)))
  {
    BIO_free(bmem);
    return err;
  }

  //write it to PEM format
  if (!(err = PEM_write_bio_X509_REQ(mem, req))) {
    BIO_free(mem);
    BIO_free(bmem);
    return err;
  }


  BUF_MEM *bptr;
  BIO_get_mem_ptr(mem, &bptr);
  BIO_read(mem, result, bptr->length);

  BIO_free(bmem);
  BIO_free(mem);
  return 0;
}
int addToCRL(char* pemSigningKey, char* pemOldCrl, char* pemRevokedCert, char* result) {
  int err = 0;

  BIO* bioSigningKey = BIO_new_mem_buf(pemSigningKey, -1);
  if (!bioSigningKey) {
    return ERR_peek_error();
  }
  BIO* bioRevCert = BIO_new_mem_buf(pemRevokedCert, -1);
  if (!bioRevCert) {
    BIO_free(bioSigningKey);
    return ERR_peek_error();
  }
  BIO* bioOldCRL = BIO_new_mem_buf(pemOldCrl, -1);
  if (!bioOldCRL) {
    BIO_free(bioSigningKey);
    BIO_free(bioRevCert);
    return ERR_peek_error();
  }

  X509* badCert = PEM_read_bio_X509(bioRevCert, NULL, NULL, NULL);
  if (!badCert) {
    BIO_free(bioSigningKey);
    BIO_free(bioRevCert);
    return ERR_peek_error();
  }

  EVP_PKEY* caKey = PEM_read_bio_PrivateKey(bioSigningKey, NULL, NULL, NULL);
  if (!caKey) {
    BIO_free(bioSigningKey);
    BIO_free(bioRevCert);
    return -18;
  }

  X509_CRL* crl = PEM_read_bio_X509_CRL(bioOldCRL, NULL, NULL, NULL);
  if (!crl) {
    BIO_free(bioSigningKey);
    BIO_free(bioRevCert);
    return ERR_peek_error();
  }

  X509_REVOKED* revoked = X509_REVOKED_new();
  X509_REVOKED_set_serialNumber(revoked, X509_get_serialNumber(badCert));
  ASN1_TIME* tmptm = ASN1_TIME_new();
  X509_gmtime_adj(tmptm, long(0));
  X509_REVOKED_set_revocationDate(revoked, tmptm);

  //set the reason?  Not yet.
  //    ASN1_ENUMERATED* rtmp = ASN1_ENUMERATED_new();
  //  ASN1_ENUMERATED_set(rtmp, reasonCode);
  //    goto err;
  //  if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0))
  //    goto err;
  //  }

  if(!(err = X509_CRL_add0_revoked(crl,revoked))) {
    BIO_free(bioSigningKey);
    BIO_free(bioRevCert);
    return err;
  }

  X509_CRL_sort(crl);

  if(!(err=X509_CRL_sign(crl,caKey,EVP_sha1()))) {
    BIO_free(bioSigningKey);
    BIO_free(bioRevCert);
    return err;
  }

  BIO *mem = BIO_new(BIO_s_mem());
  PEM_write_bio_X509_CRL(mem,crl);
  BUF_MEM *bptr;
  BIO_get_mem_ptr(mem, &bptr);
  BIO_read(mem, result, bptr->length);


  BIO_free(bioRevCert);
  BIO_free(bioSigningKey);
  BIO_free(bioOldCRL);
  BIO_free(mem);

  return 0;
}
int createEmptyCRL(char* pemSigningKey, char* pemCaCert, int crldays, int crlhours, char* result) {
  int err = 0;

  //convert to BIOs and then keys and x509 structures
  BIO* bioCert = BIO_new_mem_buf(pemCaCert, -1);
  if (!bioCert) {
    BIO_free(bioCert);
    return ERR_peek_error();
  }

  BIO* bioSigningKey = BIO_new_mem_buf(pemSigningKey, -1);
  if (!bioSigningKey) {
    BIO_free(bioCert);
    BIO_free(bioSigningKey);
    return ERR_peek_error();
  }

  X509* caCert = PEM_read_bio_X509(bioCert, NULL, NULL, NULL);
  if (!caCert) {
    BIO_free(bioCert);
    BIO_free(bioSigningKey);
    return ERR_peek_error();
  }

  EVP_PKEY* caKey = PEM_read_bio_PrivateKey(bioSigningKey, NULL, NULL, NULL);
  if (!caKey) {
    BIO_free(bioCert);
    BIO_free(bioSigningKey);
    return ERR_peek_error();
  }

  X509_CRL* crl = X509_CRL_new();

  X509_CRL_set_issuer_name(crl, X509_get_subject_name(caCert));

  //set update times (probably not essential, but why not.
  ASN1_TIME* tmptm = ASN1_TIME_new();
  X509_gmtime_adj(tmptm, long(0));
  X509_CRL_set_lastUpdate(crl, tmptm);
  X509_gmtime_adj(tmptm,(crldays*24+crlhours)*60*60);
  X509_CRL_set_nextUpdate(crl, tmptm);
  ASN1_TIME_free(tmptm);

  X509_CRL_sort(crl);

  //extensions would go here.

  if (!(err = X509_CRL_sign(crl,caKey,EVP_sha1())))
  {
    BIO_free(bioCert);
    BIO_free(bioSigningKey);
    return err;
  }


  BIO *mem = BIO_new(BIO_s_mem());
  PEM_write_bio_X509_CRL(mem,crl);
  BUF_MEM *bptr;
  BIO_get_mem_ptr(mem, &bptr);
  BIO_read(mem, result, bptr->length);


  BIO_free(bioCert);
  BIO_free(bioSigningKey);
  BIO_free(mem);
  return 0;
}
Ejemplo n.º 16
0
int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int port)
{
	int match;
	int index;
	char* common_name = NULL;
	int common_name_length = 0;
	char** alt_names = NULL;
	int alt_names_count = 0;
	int* alt_names_lengths = NULL;
	BOOL certificate_status;
	BOOL hostname_match = FALSE;
	BOOL verification_status = FALSE;
	rdpCertificateData* certificate_data;

	if (tls->settings->ExternalCertificateManagement)
	{
		BIO* bio;
		int status;
		int length;
		int offset;
		BYTE* pemCert;
		freerdp* instance = (freerdp*) tls->settings->instance;

		/**
		 * Don't manage certificates internally, leave it up entirely to the external client implementation
		 */

		bio = BIO_new(BIO_s_mem());
		
		if (!bio)
		{
			WLog_ERR(TAG, "BIO_new() failure");
			return -1;
		}

		status = PEM_write_bio_X509(bio, cert->px509);

		if (status < 0)
		{
			WLog_ERR(TAG, "PEM_write_bio_X509 failure: %d", status);
			return -1;
		}
		
		offset = 0;
		length = 2048;
		pemCert = (BYTE*) malloc(length + 1);

		status = BIO_read(bio, pemCert, length);
		
		if (status < 0)
		{
			WLog_ERR(TAG, "failed to read certificate");
			return -1;
		}
		
		offset += status;

		while (offset >= length)
		{
			length *= 2;
			pemCert = (BYTE*) realloc(pemCert, length + 1);

			status = BIO_read(bio, &pemCert[offset], length);

			if (status < 0)
				break;

			offset += status;
		}

		if (status < 0)
		{
			WLog_ERR(TAG, "failed to read certificate");
			return -1;
		}
		
		length = offset;
		pemCert[length] = '\0';

		status = -1;
		
		if (instance->VerifyX509Certificate)
		{
			status = instance->VerifyX509Certificate(instance, pemCert, length, hostname, port, tls->isGatewayTransport);
		}
		
		WLog_ERR(TAG, "(length = %d) status: %d%s",	length, status, pemCert);

		free(pemCert);
		BIO_free(bio);

		if (status < 0)
			return -1;

		return (status == 0) ? 0 : 1;
	}

	/* ignore certificate verification if user explicitly required it (discouraged) */
	if (tls->settings->IgnoreCertificate)
		return 1;  /* success! */

	/* if user explicitly specified a certificate name, use it instead of the hostname */
	if (tls->settings->CertificateName)
		hostname = tls->settings->CertificateName;

	/* attempt verification using OpenSSL and the ~/.freerdp/certs certificate store */
	certificate_status = x509_verify_certificate(cert, tls->certificate_store->path);

	/* verify certificate name match */
	certificate_data = crypto_get_certificate_data(cert->px509, hostname);

	/* extra common name and alternative names */
	common_name = crypto_cert_subject_common_name(cert->px509, &common_name_length);
	alt_names = crypto_cert_subject_alt_name(cert->px509, &alt_names_count, &alt_names_lengths);

	/* compare against common name */

	if (common_name)
	{
		if (tls_match_hostname(common_name, common_name_length, hostname))
			hostname_match = TRUE;
	}

	/* compare against alternative names */

	if (alt_names)
	{
		for (index = 0; index < alt_names_count; index++)
		{
			if (tls_match_hostname(alt_names[index], alt_names_lengths[index], hostname))
			{
				hostname_match = TRUE;
				break;
			}
		}
	}

	/* if the certificate is valid and the certificate name matches, verification succeeds */
	if (certificate_status && hostname_match)
	{
		if (common_name)
		{
			free(common_name);
			common_name = NULL;
		}

		verification_status = TRUE; /* success! */
	}

	/* if the certificate is valid but the certificate name does not match, warn user, do not accept */
	if (certificate_status && !hostname_match)
		tls_print_certificate_name_mismatch_error(hostname, common_name, alt_names, alt_names_count);

	/* verification could not succeed with OpenSSL, use known_hosts file and prompt user for manual verification */

	if (!certificate_status)
	{
		char* issuer;
		char* subject;
		char* fingerprint;
		freerdp* instance = (freerdp*) tls->settings->instance;
		BOOL accept_certificate = FALSE;

		issuer = crypto_cert_issuer(cert->px509);
		subject = crypto_cert_subject(cert->px509);
		fingerprint = crypto_cert_fingerprint(cert->px509);

		/* search for matching entry in known_hosts file */
		match = certificate_data_match(tls->certificate_store, certificate_data);

		if (match == 1)
		{
			/* no entry was found in known_hosts file, prompt user for manual verification */
			if (!hostname_match)
				tls_print_certificate_name_mismatch_error(hostname, common_name, alt_names, alt_names_count);

			if (instance->VerifyCertificate)
			{
				accept_certificate = instance->VerifyCertificate(instance, subject, issuer, fingerprint);
			}

			if (!accept_certificate)
			{
				/* user did not accept, abort and do not add entry in known_hosts file */
				verification_status = FALSE; /* failure! */
			}
			else
			{
				/* user accepted certificate, add entry in known_hosts file */
				certificate_data_print(tls->certificate_store, certificate_data);
				verification_status = TRUE; /* success! */
			}
		}
		else if (match == -1)
		{
			/* entry was found in known_hosts file, but fingerprint does not match. ask user to use it */
			tls_print_certificate_error(hostname, fingerprint, tls->certificate_store->file);
			
			if (instance->VerifyChangedCertificate)
			{
				accept_certificate = instance->VerifyChangedCertificate(instance, subject, issuer, fingerprint, "");
			}

			if (!accept_certificate)
			{
				/* user did not accept, abort and do not change known_hosts file */
				verification_status = FALSE;  /* failure! */
			}
			else
			{
				/* user accepted new certificate, add replace fingerprint for this host in known_hosts file */
				certificate_data_replace(tls->certificate_store, certificate_data);
				verification_status = TRUE; /* success! */
			}
		}
		else if (match == 0)
		{
			verification_status = TRUE; /* success! */
		}

		free(issuer);
		free(subject);
		free(fingerprint);
	}

	if (certificate_data)
	{
		free(certificate_data->fingerprint);
		free(certificate_data->hostname);
		free(certificate_data);
	}

#ifndef _WIN32
	if (common_name)
		free(common_name);
#endif

	if (alt_names)
		crypto_cert_subject_alt_name_free(alt_names_count, alt_names_lengths,
				alt_names);

	return (verification_status == 0) ? 0 : 1;
}
Ejemplo n.º 17
0
ConnectionInitiator::ConnectionInitiator(QObject *parent) :
    QObject(parent)
{
    this->qSql = DatabaseHandler::getInstance();

    // generate self-signed certificate
    // this bit is inspired by http://stackoverflow.com/questions/256405/programmatically-create-x509-certificate-using-openssl
    EVP_PKEY* pkey;
    pkey = EVP_PKEY_new();

    RSA* rsa = RSA_generate_key(2048, RSA_F4, NULL, NULL);
    if (!EVP_PKEY_assign_RSA(pkey, rsa)) {
        qWarning() << "Unable to generate 2048-bit RSA key";
        UnixSignalHandler::termSignalHandler(0);
    }

    X509* x509 = X509_new();
    ASN1_INTEGER_set(X509_get_serialNumber(x509), 1);
    X509_gmtime_adj(X509_get_notBefore(x509), -2000);
    X509_gmtime_adj(X509_get_notAfter(x509), 31536000L);

    X509_set_pubkey(x509, pkey);

    X509_NAME * name = X509_get_subject_name(x509);
    X509_NAME_add_entry_by_txt(name, "C",  MBSTRING_ASC,
                               (unsigned char *)"BE", -1, -1, 0);
    X509_NAME_add_entry_by_txt(name, "O",  MBSTRING_ASC,
                               (unsigned char *)"FriendsVPN", -1, -1, 0);
    X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
                               (unsigned char *)"facebookApp", -1, -1, 0);
    X509_set_issuer_name(x509, name);

    if (!X509_sign(x509, pkey, EVP_sha1())) {
        qWarning() << "Error signing certificate";
        UnixSignalHandler::termSignalHandler(0);
    }

    // get the PEM string for cert and key

    // cert
    BIO* bio = BIO_new(BIO_s_mem());
    PEM_write_bio_X509(bio, x509);
    BUF_MEM *bptr;
    BIO_get_mem_ptr(bio, &bptr);
    int length = bptr->length;
    char certBuf[length + 1];
    BIO_read(bio, certBuf, length);
    certBuf[length] = '\0';
    BIO_free(bio);

    // key
    bio = BIO_new(BIO_s_mem());
    PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL);
    BIO_get_mem_ptr(bio, &bptr);
    length = bptr->length;

    char keyBuf[length + 1];
    BIO_read(bio, keyBuf, length);
    keyBuf[length] = '\0';
    BIO_free(bio);

    qDebug() << "Printing local key and certificate";
    qDebug() << keyBuf;
    qDebug() << certBuf;

    key = QSslKey(keyBuf, QSsl::Rsa, QSsl::Pem);
    cert = QSslCertificate(certBuf, QSsl::Pem);
    qSql->pushCert(cert);
}
Ejemplo n.º 18
0
// The mint has a different key pair for each denomination.
// Pass the actual denomination such as 5, 10, 20, 50, 100...
bool OTMint_Lucre::AddDenomination(OTPseudonym & theNotary, int64_t lDenomination, int32_t nPrimeLength/*=1024*/)
{
    OT_ASSERT(NULL != m_pKeyPublic);
    
	bool bReturnValue = false;
	
	// Let's make sure it doesn't already exist
	OTASCIIArmor theArmor;
	if (GetPublic(theArmor, lDenomination))
	{
		// it already exists.
		OTLog::Error("Error: Denomination public already exists in OTMint::AddDenomination\n");
		return false;
	}
	if (GetPrivate(theArmor, lDenomination))
	{
		// it already exists.
		OTLog::Error("Error: Denomination private already exists in OTMint::AddDenomination\n");
		return false;
	}
	
	//		OTLog::Error("%s <size of bank prime in bits> <bank data file> <bank public data file>\n",
	
    if ((nPrimeLength/8) < (MIN_COIN_LENGTH+DIGEST_LENGTH))
	{
		OTLog::vError("Prime must be at least %d bits\n",
				(MIN_COIN_LENGTH+DIGEST_LENGTH)*8);
		return false;
	}
	
    if (nPrimeLength%8)
	{
		OTLog::Error("Prime length must be a multiple of 8\n");
		return false;
	}
	
#ifdef _WIN32
	SetMonitor("openssl.dump");
#else
	SetMonitor(stderr);
#endif
	
    OpenSSL_BIO bio		=	BIO_new(BIO_s_mem());
    OpenSSL_BIO bioPublic	=	BIO_new(BIO_s_mem());
	
	// Generate the mint private key information
    Bank bank(nPrimeLength/8);
    bank.WriteBIO(bio);
	
	// Generate the mint public key information
    PublicBank pbank(bank);
    pbank.WriteBIO(bioPublic);	
	
	// Copy from BIO back to a normal OTString or Ascii-Armor  
	char privateBankBuffer[4096], publicBankBuffer[4096];   // todo stop hardcoding these string lengths
	int32_t  privatebankLen	= BIO_read(bio, privateBankBuffer, 4000); // cutting it a little short on purpose, with the buffer.
	int32_t  publicbankLen	= BIO_read(bioPublic, publicBankBuffer, 4000); // Just makes me feel more comfortable for some reason.
	
	if (privatebankLen && publicbankLen)
	{
		// With this, we have the Lucre public and private bank info converted to OTStrings
		OTString strPublicBank;		strPublicBank.Set(publicBankBuffer, publicbankLen);
		OTString strPrivateBank;	strPrivateBank.Set(privateBankBuffer, privatebankLen);
		
		OTASCIIArmor * pPublic	= new OTASCIIArmor();
		OTASCIIArmor * pPrivate	= new OTASCIIArmor();
		
		OT_ASSERT(NULL != pPublic);
		OT_ASSERT(NULL != pPrivate);
		
		// Set the public bank info onto pPublic
		pPublic->SetString(strPublicBank, true); // linebreaks = true
		
		// Seal the private bank info up into an encrypted Envelope 
		// and set it onto pPrivate
		OTEnvelope theEnvelope;
		theEnvelope.Seal(theNotary, strPrivateBank);	// Todo check the return values on these two functions
		theEnvelope.GetAsciiArmoredData(*pPrivate);
		
		// Add the new key pair to the maps, using denomination as the key
		m_mapPublic[lDenomination]	= pPublic;
		m_mapPrivate[lDenomination]	= pPrivate;
		
		// Grab the Server Nym ID and save it with this Mint
		theNotary.GetIdentifier(m_ServerNymID);
        // ---------------------------
		// Grab the Server's public key and save it with this Mint
        //
        const OTAsymmetricKey & theNotaryPubKey = theNotary.GetPublicSignKey();
        delete m_pKeyPublic;
        m_pKeyPublic = theNotaryPubKey.ClonePubKey();
        // ---------------------------
		m_nDenominationCount++;
        // ---------------------------		
		// Success!
		bReturnValue = true;
		OTLog::vOutput(1, "Successfully added denomination: %lld\n", lDenomination);
	}
	
	return bReturnValue;
}
Ejemplo n.º 19
0
static void https_add_ssl_entries(connection *con) {
	X509 *xs;
	X509_NAME *xn;
	X509_NAME_ENTRY *xe;
	int i, nentries;

	if (
		SSL_get_verify_result(con->ssl) != X509_V_OK
		|| !(xs = SSL_get_peer_certificate(con->ssl))
	) {
		return;
	}

	xn = X509_get_subject_name(xs);
	for (i = 0, nentries = X509_NAME_entry_count(xn); i < nentries; ++i) {
		int xobjnid;
		const char * xobjsn;
		data_string *envds;

		if (!(xe = X509_NAME_get_entry(xn, i))) {
			continue;
		}
		xobjnid = OBJ_obj2nid((ASN1_OBJECT*)X509_NAME_ENTRY_get_object(xe));
		xobjsn = OBJ_nid2sn(xobjnid);
		if (!xobjsn) {
			continue;
		}

		if (NULL == (envds = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
			envds = data_string_init();
		}
		buffer_copy_string_len(envds->key, CONST_STR_LEN("SSL_CLIENT_S_DN_"));
		buffer_append_string(envds->key, xobjsn);
		buffer_copy_string_len(
			envds->value,
			(const char *)xe->value->data, xe->value->length
		);
		/* pick one of the exported values as "REMOTE_USER", for example
		 * ssl.verifyclient.username   = "******" or "SSL_CLIENT_S_DN_emailAddress"
		 */
		if (buffer_is_equal(con->conf.ssl_verifyclient_username, envds->key)) {
			data_string *ds;
			if (NULL == (ds = (data_string *)array_get_element(con->environment, "REMOTE_USER"))) {
				if (NULL == (ds = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
					ds = data_string_init();
				}
				buffer_copy_string(ds->key, "REMOTE_USER");
				array_insert_unique(con->environment, (data_unset *)ds);
			}
			buffer_copy_buffer(ds->value, envds->value);
		}
		array_insert_unique(con->environment, (data_unset *)envds);
	}
	if (con->conf.ssl_verifyclient_export_cert) {
		BIO *bio;
		if (NULL != (bio = BIO_new(BIO_s_mem()))) {
			data_string *envds;
			int n;

			PEM_write_bio_X509(bio, xs);
			n = BIO_pending(bio);

			if (NULL == (envds = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
				envds = data_string_init();
			}

			buffer_copy_string_len(envds->key, CONST_STR_LEN("SSL_CLIENT_CERT"));
			buffer_string_prepare_copy(envds->value, n);
			BIO_read(bio, envds->value->ptr, n);
			BIO_free(bio);
			buffer_commit(envds->value, n);
			array_insert_unique(con->environment, (data_unset *)envds);
		}
	}
	X509_free(xs);
}
Ejemplo n.º 20
0
// Lucre step 3: the mint signs the token
// 
bool OTMint_Lucre::SignToken(OTPseudonym & theNotary, OTToken & theToken, OTString & theOutput, int32_t nTokenIndex)
{
	bool bReturnValue = false;
	
	//OTLog::Error("%s <bank file> <coin request> <coin signature> [<signature repeats>]\n",
    _OT_Lucre_Dumper setDumper;
	
//	OTLog::vError("OTMint::SignToken!!\nnTokenIndex: %d\n Denomination: %lld\n", nTokenIndex, theToken.GetDenomination());
	
    OpenSSL_BIO bioBank		= BIO_new(BIO_s_mem()); // input
    OpenSSL_BIO bioRequest		= BIO_new(BIO_s_mem()); // input
    OpenSSL_BIO bioSignature	= BIO_new(BIO_s_mem()); // output
	
	OTASCIIArmor thePrivate;
	GetPrivate(thePrivate, theToken.GetDenomination());
	
	// The Mint private info is encrypted in m_mapPrivates[theToken.GetDenomination()]. 
	// So I need to extract that first before I can use it.
	OTEnvelope theEnvelope(thePrivate);

	OTString strContents; // output from opening the envelope.
	// Decrypt the Envelope into strContents    
	if (!theEnvelope.Open(theNotary, strContents))
		return false;

	// copy strContents to a BIO
	BIO_puts(bioBank, strContents.Get());
	
//	OTLog::vError("BANK CONTENTS:\n%s--------------------------------------\n", strContents.Get());
	
	// Instantiate the Bank with its private key
    Bank bank(bioBank);
//	OTLog::vError("BANK INSTANTIATED.--------------------------------------\n");

	// I need the request. the prototoken.
	OTASCIIArmor ascPrototoken;
	bool bFoundToken = theToken.GetPrototoken(ascPrototoken, nTokenIndex);
	
	if (bFoundToken)
	{
		// base64-Decode the prototoken
		OTString strPrototoken(ascPrototoken);
		
//		OTLog::vError("\n--------------------------------------\nDEBUG:  PROTOTOKEN CONTENTS:\n"
//				"-----------------%s---------------------\n", strPrototoken.Get() );
		
		// copy strPrototoken to a BIO
		BIO_puts(bioRequest, strPrototoken.Get());

		// Load up the coin request from the bio (the prototoken)
		PublicCoinRequest req(bioRequest);
//		OTLog::Error("PROTOTOKEN INSTANTIATED.--------------------------------------\n");

		// Sign it with the bank we previously instantiated.
		// results will be in bnSignature (BIGNUM)
		BIGNUM * bnSignature = bank.SignRequest(req);

		if (NULL == bnSignature)
		{
			OTLog::Error("MAJOR ERROR!: Bank.SignRequest failed in OTMint_Lucre::SignToken\n");
		}
		
		else 
		{
//			OTLog::Error("BANK.SIGNREQUEST SUCCESSFUL.--------------------------------------\n");

			// Write the request contents, followed by the signature contents,
			// to the Signature bio. Then free the BIGNUM.
			req.WriteBIO(bioSignature); // the original request contents
			DumpNumber(bioSignature,"signature=", bnSignature); // the new signature contents
			BN_free(bnSignature);

			// Read the signature bio into a C-style buffer...
			char sig_buf[1024];   // todo stop hardcoding these string lengths
//			memset(sig_buf, 0, 1024); // zero it out. (I had this commented out, but the size was 2048, so maybe it's safe now at 1024.)
			
			int32_t sig_len	= BIO_read(bioSignature, sig_buf, 1000); // cutting it a little short on purpose, with the buffer. Just makes me feel more comfortable for some reason.
			
			
			// Add the null terminator by hand (just in case.)
			sig_buf[sig_len]	= '\0';
			
			if (sig_len)
			{ // ***********************************************
//				OTLog::vError("\n--------------------------------------\n"
//						"*** Siglen is %d. sig_str_len is %d.\nsig buf:\n------------%s------------\nLAST "
//						"CHARACTER IS '%c'  SECOND TO LAST CHARACTER IS '%c'\n", 
//						sig_len, sig_str_len, sig_buf, sig_buf[sig_str_len-1], sig_buf[sig_str_len-2]);
				
				// Copy the original coin request into the spendable field of the token object.
				// (It won't actually be spendable until the client processes it, though.)
				theToken.SetSpendable(ascPrototoken);
				
//				OTLog::vError("*** SPENDABLE:\n-----------%s---------------------\n", ascPrototoken.Get());
						
						
				// Base64-encode the signature contents into theToken.m_Signature.
				OTString	strSignature(sig_buf);
	//			strSignature.Set(sig_buf, sig_len-1); // sig_len includes null terminator, whereas Set() adds 1 for it.
				
//				OTLog::vError("SIGNATURE:\n--------------------%s"
//						"------------------\n", strSignature.Get());

				// Here we pass the signature back to the caller.
				// He will probably set it onto the token.
				theOutput.Set(sig_buf, sig_len);
				bReturnValue = true;
				
				// This is also where we set the expiration date on the token.
				// The client should have already done this, but we are explicitly
				// setting the values here to prevent any funny business.
				theToken.SetSeriesAndExpiration(m_nSeries, m_VALID_FROM, m_VALID_TO);
			}
		}
	}

	return bReturnValue;
}
Ejemplo n.º 21
0
/** Continue a TLS handshake
 *
 * Advance the TLS handshake by feeding OpenSSL data from dirty_in,
 * and reading data from OpenSSL into dirty_out.
 *
 * @param request The current request.
 * @param session The current TLS session.
 * @return
 *	- 0 on error.
 *	- 1 on success.
 */
int tls_session_handshake(REQUEST *request, tls_session_t *session)
{
	int ret;

	/*
	 *	This is a logic error.  tls_session_handshake
	 *	must not be called if the handshake is
	 *	complete tls_session_recv must be
	 *	called instead.
	 */
	if (SSL_is_init_finished(session->ssl)) {
		REDEBUG("Attempted to continue TLS handshake, but handshake has completed");
		return 0;
	}

	if (session->invalid) {
		REDEBUG("Preventing invalid session from continuing");
		return 0;
	}

	/*
	 *	Feed dirty data into OpenSSL, so that is can either
	 *	process it as Application data (decrypting it)
	 *	or continue the TLS handshake.
	 */
	if (session->dirty_in.used) {
		ret = BIO_write(session->into_ssl, session->dirty_in.data, session->dirty_in.used);
		if (ret != (int)session->dirty_in.used) {
			REDEBUG("Failed writing %zd bytes to TLS BIO: %d", session->dirty_in.used, ret);
			record_init(&session->dirty_in);
			return 0;
		}
		record_init(&session->dirty_in);
	}

	/*
	 *	Magic/More magic? Although SSL_read is normally
	 *	used to read application data, it will also
	 *	continue the TLS handshake.  Removing this call will
	 *	cause the handshake to fail.
	 *
	 *	We don't ever expect to actually *receive* application
	 *	data here.
	 *
	 *	The reason why we call SSL_read instead of SSL_accept,
	 *	or SSL_connect, as it allows this function
	 *	to be used, irrespective or whether we're acting
	 *	as a client or a server.
	 *
	 *	If acting as a client SSL_set_connect_state must have
	 *	been called before this function.
	 *
	 *	If acting as a server SSL_set_accept_state must have
	 *	been called before this function.
	 */
	ret = SSL_read(session->ssl, session->clean_out.data + session->clean_out.used,
		       sizeof(session->clean_out.data) - session->clean_out.used);
	if (ret > 0) {
		session->clean_out.used += ret;
		return 1;
	}
	if (!tls_log_io_error(request, session, ret, "Failed in SSL_read")) return 0;

	/*
	 *	This only occurs once per session, where calling
	 *	SSL_read updates the state of the SSL session, setting
	 *	this flag to true.
	 *
	 *	Callbacks provide enough info so we don't need to
	 *	print debug statements when the handshake is in other
	 *	states.
	 */
	if (SSL_is_init_finished(session->ssl)) {
		SSL_CIPHER const *cipher;
		VALUE_PAIR *vp;
		char const *str_version;

		char cipher_desc[256], cipher_desc_clean[256];
		char *p = cipher_desc, *q = cipher_desc_clean;

		cipher = SSL_get_current_cipher(session->ssl);
		SSL_CIPHER_description(cipher, cipher_desc, sizeof(cipher_desc));

		/*
		 *	Cleanup the output from OpenSSL
		 *	Seems to print info in a tabular format.
		 */
		while (*p != '\0') {
			if (isspace(*p)) {
				*q++ = *p;
				while (isspace(*++p));
				continue;
			}
			*q++ = *p++;
		}
		*q = '\0';

		RDEBUG2("Cipher suite: %s", cipher_desc_clean);

		vp = fr_pair_afrom_num(request->state_ctx, 0, FR_TLS_SESSION_CIPHER_SUITE);
		if (vp) {
			fr_pair_value_strcpy(vp,  SSL_CIPHER_get_name(cipher));
			fr_pair_add(&request->state, vp);
			RDEBUG2("    &session-state:TLS-Session-Cipher-Suite := \"%s\"", vp->vp_strvalue);
		}

		switch (session->info.version) {
		case SSL2_VERSION:
			str_version = "SSL 2.0";
			break;
		case SSL3_VERSION:
			str_version = "SSL 3.0";
			break;
		case TLS1_VERSION:
			str_version = "TLS 1.0";
			break;
#ifdef TLS1_1_VERSION
		case TLS1_1_VERSION:
			str_version = "TLS 1.1";
			break;
#endif
#ifdef TLS1_2_VERSION
		case TLS1_2_VERSION:
			str_version = "TLS 1.2";
			break;
#endif
#ifdef TLS1_3_VERSON
		case TLS1_3_VERSION:
			str_version = "TLS 1.3";
			break;
#endif
		default:
			str_version = "UNKNOWN";
			break;
		}

		vp = fr_pair_afrom_num(request->state_ctx, 0, FR_TLS_SESSION_VERSION);
		if (vp) {
			fr_pair_value_strcpy(vp, str_version);
			fr_pair_add(&request->state, vp);
			RDEBUG2("    &session-state:TLS-Session-Version := \"%s\"", str_version);
		}

#if OPENSSL_VERSION_NUMBER >= 0x10001000L
		/*
		 *	Cache the SSL_SESSION pointer.
		 *
		 *	Which contains all the data we need for session resumption.
		 */
		if (!session->ssl_session) {
			session->ssl_session = SSL_get_session(session->ssl);
			if (!session->ssl_session) {
				REDEBUG("Failed getting TLS session");
				return 0;
			}
		}

		if (RDEBUG_ENABLED3) {
			BIO *ssl_log = BIO_new(BIO_s_mem());

			if (ssl_log) {
				if (SSL_SESSION_print(ssl_log, session->ssl_session) == 1) {
					SSL_DRAIN_ERROR_QUEUE(RDEBUG3, "", ssl_log);
				} else {
					RDEBUG3("Failed retrieving session data");
				}
				BIO_free(ssl_log);
			}
		}
#endif

		/*
		 *	Session was resumed, add attribute to mark it as such.
		 */
		if (SSL_session_reused(session->ssl)) {
			/*
			 *	Mark the request as resumed.
			 */
			MEM(pair_update_request(&vp, attr_eap_session_resumed) >= 0);
			vp->vp_bool = true;
		}
	}

	/*
	 *	Get data to pack and send back to the TLS peer.
	 */
	ret = BIO_ctrl_pending(session->from_ssl);
	if (ret > 0) {
		ret = BIO_read(session->from_ssl, session->dirty_out.data,
			       sizeof(session->dirty_out.data));
		if (ret > 0) {
			session->dirty_out.used = ret;
		} else if (BIO_should_retry(session->from_ssl)) {
			record_init(&session->dirty_in);
			RDEBUG2("Asking for more data in tunnel");
			return 1;

		} else {
			tls_log_error(NULL, NULL);
			record_init(&session->dirty_in);
			return 0;
		}
	} else {
		/* Its clean application data, do whatever we want */
		record_init(&session->clean_out);
	}

	/*
	 *	W would prefer to latch on info.content_type but
	 *	(I think its...) tls_session_msg_cb() updates it
	 *	after the call to tls_session_handshake_alert()
	 */
	if (session->handshake_alert.level) {
		/*
		 * FIXME RFC 4851 section 3.6.1 - peer might ACK alert and include a restarted ClientHello
		 *                                 which eap_tls_session_status() will fail on
		 */
		session->info.content_type = SSL3_RT_ALERT;

		session->dirty_out.data[0] = session->info.content_type;
		session->dirty_out.data[1] = 3;
		session->dirty_out.data[2] = 1;
		session->dirty_out.data[3] = 0;
		session->dirty_out.data[4] = 2;
		session->dirty_out.data[5] = session->handshake_alert.level;
		session->dirty_out.data[6] = session->handshake_alert.description;

		session->dirty_out.used = 7;

		session->handshake_alert.level = 0;
	}

	/* We are done with dirty_in, reinitialize it */
	record_init(&session->dirty_in);
	return 1;
}
Ejemplo n.º 22
0
BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
	{
	int i;
	BIO *out=NULL,*btmp=NULL;
	X509_ALGOR *xa = NULL;
	const EVP_CIPHER *evp_cipher=NULL;
	STACK_OF(X509_ALGOR) *md_sk=NULL;
	STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
	X509_ALGOR *xalg=NULL;
	PKCS7_RECIP_INFO *ri=NULL;
	EVP_PKEY *pkey;
	ASN1_OCTET_STRING *os=NULL;

	i=OBJ_obj2nid(p7->type);
	p7->state=PKCS7_S_HEADER;

	switch (i)
		{
	case NID_pkcs7_signed:
		md_sk=p7->d.sign->md_algs;
		os = PKCS7_get_octet_string(p7->d.sign->contents);
		break;
	case NID_pkcs7_signedAndEnveloped:
		rsk=p7->d.signed_and_enveloped->recipientinfo;
		md_sk=p7->d.signed_and_enveloped->md_algs;
		xalg=p7->d.signed_and_enveloped->enc_data->algorithm;
		evp_cipher=p7->d.signed_and_enveloped->enc_data->cipher;
		if (evp_cipher == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATAINIT,
						PKCS7_R_CIPHER_NOT_INITIALIZED);
			goto err;
			}
		break;
	case NID_pkcs7_enveloped:
		rsk=p7->d.enveloped->recipientinfo;
		xalg=p7->d.enveloped->enc_data->algorithm;
		evp_cipher=p7->d.enveloped->enc_data->cipher;
		if (evp_cipher == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATAINIT,
						PKCS7_R_CIPHER_NOT_INITIALIZED);
			goto err;
			}
		break;
	case NID_pkcs7_digest:
		xa = p7->d.digest->md;
		os = PKCS7_get_octet_string(p7->d.digest->contents);
		break;
	default:
		PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
	        goto err;
		}

	for (i=0; i<sk_X509_ALGOR_num(md_sk); i++)
		if (!PKCS7_bio_add_digest(&out, sk_X509_ALGOR_value(md_sk, i)))
			goto err;

	if (xa && !PKCS7_bio_add_digest(&out, xa))
			goto err;

	if (evp_cipher != NULL)
		{
		unsigned char key[EVP_MAX_KEY_LENGTH];
		unsigned char iv[EVP_MAX_IV_LENGTH];
		int keylen,ivlen;
		int jj,max;
		unsigned char *tmp;
		EVP_CIPHER_CTX *ctx;

		if ((btmp=BIO_new(BIO_f_cipher())) == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_BIO_LIB);
			goto err;
			}
		BIO_get_cipher_ctx(btmp, &ctx);
		keylen=EVP_CIPHER_key_length(evp_cipher);
		ivlen=EVP_CIPHER_iv_length(evp_cipher);
		xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher));
		if (ivlen > 0) RAND_pseudo_bytes(iv,ivlen);
		if (EVP_CipherInit_ex(ctx, evp_cipher, NULL, NULL, NULL, 1)<=0)
			goto err;
		if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0)
			goto err;
		if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) <= 0)
			goto err;

		if (ivlen > 0) {
			if (xalg->parameter == NULL) 
						xalg->parameter=ASN1_TYPE_new();
			if(EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0)
								       goto err;
		}

		/* Lets do the pub key stuff :-) */
		max=0;
		for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++)
			{
			ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
			if (ri->cert == NULL)
				{
				PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_MISSING_CERIPEND_INFO);
				goto err;
				}
			pkey=X509_get_pubkey(ri->cert);
			jj=EVP_PKEY_size(pkey);
			EVP_PKEY_free(pkey);
			if (max < jj) max=jj;
			}
		if ((tmp=(unsigned char *)OPENSSL_malloc(max)) == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_MALLOC_FAILURE);
			goto err;
			}
		for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++)
			{
			ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
			pkey=X509_get_pubkey(ri->cert);
			jj=EVP_PKEY_encrypt(tmp,key,keylen,pkey);
			EVP_PKEY_free(pkey);
			if (jj <= 0)
				{
				PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_EVP_LIB);
				OPENSSL_free(tmp);
				goto err;
				}
			if (!M_ASN1_OCTET_STRING_set(ri->enc_key,tmp,jj))
				{
				PKCS7err(PKCS7_F_PKCS7_DATAINIT,
					ERR_R_MALLOC_FAILURE);
				OPENSSL_free(tmp);
				goto err;
				}
			}
		OPENSSL_free(tmp);
		OPENSSL_cleanse(key, keylen);

		if (out == NULL)
			out=btmp;
		else
			BIO_push(out,btmp);
		btmp=NULL;
		}

	if (bio == NULL)
		{
		if (PKCS7_is_detached(p7))
			bio=BIO_new(BIO_s_null());
		else if (os && os->length > 0)
			bio = BIO_new_mem_buf(os->data, os->length);
		if(bio == NULL)
			{
			bio=BIO_new(BIO_s_mem());
			BIO_set_mem_eof_return(bio,0);
			}
		}
	BIO_push(out,bio);
	bio=NULL;
	if (0)
		{
err:
		if (out != NULL)
			BIO_free_all(out);
		if (btmp != NULL)
			BIO_free_all(btmp);
		out=NULL;
		}
	return(out);
	}
Ejemplo n.º 23
0
/** Extract attributes from an X509 certificate
 *
 * @param cursor	to copy attributes to.
 * @param ctx		to allocate attributes in.
 * @param session	current TLS session.
 * @param cert		to validate.
 * @param depth		the certificate is in the certificate chain (0 == leaf).
 * @return
 *	- 0 on success.
 *	- < 0 on failure.
 */
int tls_session_pairs_from_x509_cert(fr_cursor_t *cursor, TALLOC_CTX *ctx,
				     tls_session_t *session, X509 *cert, int depth)
{
	char		buffer[1024];
	char		attribute[256];
	char		**identity;
	int		attr_index, loc;

#if OPENSSL_VERSION_NUMBER >= 0x10100000L
	STACK_OF(X509_EXTENSION) const *ext_list = NULL;
#else
	STACK_OF(X509_EXTENSION) *ext_list = NULL;
#endif

	ASN1_INTEGER	*sn = NULL;
	ASN1_TIME	*asn_time = NULL;

	VALUE_PAIR	*vp = NULL;

	REQUEST		*request;

#define CERT_ATTR_ADD(_attr, _attr_index, _value) tls_session_cert_attr_add(ctx, request, cursor, _attr, _attr_index, _value)

	attr_index = depth;
	if (attr_index > 1) attr_index = 1;

	request = (REQUEST *)SSL_get_ex_data(session->ssl, FR_TLS_EX_INDEX_REQUEST);
	rad_assert(request != NULL);

	identity = (char **)SSL_get_ex_data(session->ssl, FR_TLS_EX_INDEX_IDENTITY);

	if (RDEBUG_ENABLED3) {
		buffer[0] = '\0';
		X509_NAME_oneline(X509_get_subject_name(cert), buffer, sizeof(buffer));
		buffer[sizeof(buffer) - 1] = '\0';
		RDEBUG3("Creating attributes for \"%s\":", buffer[0] ? buffer : "Cert missing subject OID");
	}

	/*
	 *	Get the Serial Number
	 */
	sn = X509_get_serialNumber(cert);
	if (sn && ((size_t) sn->length < (sizeof(buffer) / 2))) {
		char *p = buffer;
		int i;

		for (i = 0; i < sn->length; i++) {
			sprintf(p, "%02x", (unsigned int)sn->data[i]);
			p += 2;
		}

		CERT_ATTR_ADD(IDX_SERIAL, attr_index, buffer);
	}

	/*
	 *	Get the Expiration Date
	 */
	buffer[0] = '\0';
	asn_time = X509_get_notAfter(cert);
	if (identity && asn_time && (asn_time->length < (int)sizeof(buffer))) {
		time_t expires;

		/*
		 *	Add expiration as a time since the epoch
		 */
		if (tls_utils_asn1time_to_epoch(&expires, asn_time) < 0) {
			RPWDEBUG("Failed parsing certificate expiry time");
		} else {
			vp = CERT_ATTR_ADD(IDX_EXPIRATION, attr_index, NULL);
			vp->vp_date = expires;
		}
	}

	/*
	 *	Get the Subject & Issuer
	 */
	buffer[0] = '\0';
	X509_NAME_oneline(X509_get_subject_name(cert), buffer, sizeof(buffer));
	buffer[sizeof(buffer) - 1] = '\0';
	if (identity && buffer[0]) {
		CERT_ATTR_ADD(IDX_SUBJECT, attr_index, buffer);

		/*
		 *	Get the Common Name, if there is a subject.
		 */
		X509_NAME_get_text_by_NID(X509_get_subject_name(cert),
					  NID_commonName, buffer, sizeof(buffer));
		buffer[sizeof(buffer) - 1] = '\0';

		if (buffer[0]) {
			CERT_ATTR_ADD(IDX_COMMON_NAME, attr_index, buffer);
		}
	}

	X509_NAME_oneline(X509_get_issuer_name(cert), buffer, sizeof(buffer));
	buffer[sizeof(buffer) - 1] = '\0';
	if (identity && buffer[0]) {
		CERT_ATTR_ADD(IDX_ISSUER, attr_index, buffer);
	}

	/*
	 *	Get the RFC822 Subject Alternative Name
	 */
	loc = X509_get_ext_by_NID(cert, NID_subject_alt_name, 0);
	if (loc >= 0) {
		X509_EXTENSION	*ext = NULL;
		GENERAL_NAMES	*names = NULL;
		int		i;

		ext = X509_get_ext(cert, loc);
		if (ext && (names = X509V3_EXT_d2i(ext))) {
			for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
				GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);

				switch (name->type) {
#ifdef GEN_EMAIL
				case GEN_EMAIL: {
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
					char const *rfc822Name = (char const *)ASN1_STRING_get0_data(name->d.rfc822Name);
#else
					char *rfc822Name = (char *)ASN1_STRING_data(name->d.rfc822Name);
#endif

					CERT_ATTR_ADD(IDX_SUBJECT_ALT_NAME_EMAIL, attr_index, rfc822Name);
					break;
				}
#endif	/* GEN_EMAIL */
#ifdef GEN_DNS
				case GEN_DNS: {
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
					char const *dNSName = (char const *)ASN1_STRING_get0_data(name->d.dNSName);
#else
					char *dNSName = (char *)ASN1_STRING_data(name->d.dNSName);
#endif
					CERT_ATTR_ADD(IDX_SUBJECT_ALT_NAME_DNS, attr_index, dNSName);
					break;
				}
#endif	/* GEN_DNS */
#ifdef GEN_OTHERNAME
				case GEN_OTHERNAME:
					/* look for a MS UPN */
					if (NID_ms_upn != OBJ_obj2nid(name->d.otherName->type_id)) break;

					/* we've got a UPN - Must be ASN1-encoded UTF8 string */
					if (name->d.otherName->value->type == V_ASN1_UTF8STRING) {
						CERT_ATTR_ADD(IDX_SUBJECT_ALT_NAME_UPN, attr_index,
								  (char *)name->d.otherName->value->value.utf8string);
						break;
					}

					RWARN("Invalid UPN in Subject Alt Name (should be UTF-8)");
					break;
#endif	/* GEN_OTHERNAME */
				default:
					/* XXX TODO handle other SAN types */
					break;
				}
			}
		}
		if (names != NULL) GENERAL_NAMES_free(names);
	}

	/*
	 *	Only add extensions for the actual client certificate
	 */
	if (attr_index == 0) {
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
		ext_list = X509_get0_extensions(cert);
#else
		ext_list = cert->cert_info->extensions;
#endif

		/*
		 *	Grab the X509 extensions, and create attributes out of them.
		 *	For laziness, we re-use the OpenSSL names
		 */
		if (sk_X509_EXTENSION_num(ext_list) > 0) {
			int i, len;
			char *p;
			BIO *out;

			out = BIO_new(BIO_s_mem());
			strlcpy(attribute, "TLS-Client-Cert-", sizeof(attribute));

			for (i = 0; i < sk_X509_EXTENSION_num(ext_list); i++) {
				char			value[1024];
				ASN1_OBJECT		*obj;
				X509_EXTENSION		*ext;
				fr_dict_attr_t const	*da;

				ext = sk_X509_EXTENSION_value(ext_list, i);

				obj = X509_EXTENSION_get_object(ext);
				i2a_ASN1_OBJECT(out, obj);

				len = BIO_read(out, attribute + 16 , sizeof(attribute) - 16 - 1);
				if (len <= 0) continue;

				attribute[16 + len] = '\0';

				for (p = attribute + 16; *p != '\0'; p++) if (*p == ' ') *p = '-';

				X509V3_EXT_print(out, ext, 0, 0);
				len = BIO_read(out, value , sizeof(value) - 1);
				if (len <= 0) continue;

				value[len] = '\0';

				da = fr_dict_attr_by_name(dict_freeradius, attribute);
				if (!da) {
					RWDEBUG3("Skipping attribute %s: "
						 "Add dictionary definition if you want to access it", attribute);
					continue;
				}

				MEM(vp = fr_pair_afrom_da(request, da));
				if (fr_pair_value_from_str(vp, value, -1, '\0', true) < 0) {
					RPWDEBUG3("Skipping: %s += '%s'", attribute, value);
					talloc_free(vp);
					continue;
				}

				fr_cursor_append(cursor, vp);
			}
			BIO_free_all(out);
		}
	}

	return 0;
}
Ejemplo n.º 24
0
/* int */
BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
	{
	int i,j;
	BIO *out=NULL,*btmp=NULL,*etmp=NULL,*bio=NULL;
	unsigned char *tmp=NULL;
	X509_ALGOR *xa;
	ASN1_OCTET_STRING *data_body=NULL;
	const EVP_MD *evp_md;
	const EVP_CIPHER *evp_cipher=NULL;
	EVP_CIPHER_CTX *evp_ctx=NULL;
	X509_ALGOR *enc_alg=NULL;
	STACK_OF(X509_ALGOR) *md_sk=NULL;
	STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
	X509_ALGOR *xalg=NULL;
	PKCS7_RECIP_INFO *ri=NULL;

	i=OBJ_obj2nid(p7->type);
	p7->state=PKCS7_S_HEADER;

	switch (i)
		{
	case NID_pkcs7_signed:
		data_body=PKCS7_get_octet_string(p7->d.sign->contents);
		md_sk=p7->d.sign->md_algs;
		break;
	case NID_pkcs7_signedAndEnveloped:
		rsk=p7->d.signed_and_enveloped->recipientinfo;
		md_sk=p7->d.signed_and_enveloped->md_algs;
		data_body=p7->d.signed_and_enveloped->enc_data->enc_data;
		enc_alg=p7->d.signed_and_enveloped->enc_data->algorithm;
		evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
		if (evp_cipher == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
			goto err;
			}
		xalg=p7->d.signed_and_enveloped->enc_data->algorithm;
		break;
	case NID_pkcs7_enveloped:
		rsk=p7->d.enveloped->recipientinfo;
		enc_alg=p7->d.enveloped->enc_data->algorithm;
		data_body=p7->d.enveloped->enc_data->enc_data;
		evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
		if (evp_cipher == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
			goto err;
			}
		xalg=p7->d.enveloped->enc_data->algorithm;
		break;
	default:
		PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
	        goto err;
		}

	/* We will be checking the signature */
	if (md_sk != NULL)
		{
		for (i=0; i<sk_X509_ALGOR_num(md_sk); i++)
			{
			xa=sk_X509_ALGOR_value(md_sk,i);
			if ((btmp=BIO_new(BIO_f_md())) == NULL)
				{
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
				goto err;
				}

			j=OBJ_obj2nid(xa->algorithm);
			evp_md=EVP_get_digestbynid(j);
			if (evp_md == NULL)
				{
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNKNOWN_DIGEST_TYPE);
				goto err;
				}

			BIO_set_md(btmp,evp_md);
			if (out == NULL)
				out=btmp;
			else
				BIO_push(out,btmp);
			btmp=NULL;
			}
		}

	if (evp_cipher != NULL)
		{
#if 0
		unsigned char key[EVP_MAX_KEY_LENGTH];
		unsigned char iv[EVP_MAX_IV_LENGTH];
		unsigned char *p;
		int keylen,ivlen;
		int max;
		X509_OBJECT ret;
#endif
		int jj;

		if ((etmp=BIO_new(BIO_f_cipher())) == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
			goto err;
			}

		/* It was encrypted, we need to decrypt the secret key
		 * with the private key */

		/* Find the recipientInfo which matches the passed certificate
		 * (if any)
		 */

		if (pcert) {
			for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) {
				ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
				if (!pkcs7_cmp_ri(ri, pcert))
					break;
				ri=NULL;
			}
			if (ri == NULL) {
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,
				      PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE);
				goto err;
			}
		}

		jj=EVP_PKEY_size(pkey);
		tmp=(unsigned char *)OPENSSL_malloc(jj+10);
		if (tmp == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_MALLOC_FAILURE);
			goto err;
			}

		/* If we haven't got a certificate try each ri in turn */

		if (pcert == NULL)
			{
			for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++)
				{
				ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
				jj=EVP_PKEY_decrypt(tmp,
					M_ASN1_STRING_data(ri->enc_key),
					M_ASN1_STRING_length(ri->enc_key),
						pkey);
				if (jj > 0)
					break;
				ERR_clear_error();
				ri = NULL;
				}
			if (ri == NULL)
				{
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,
				      PKCS7_R_NO_RECIPIENT_MATCHES_KEY);
				goto err;
				}
			}
		else
			{
			jj=EVP_PKEY_decrypt(tmp,
				M_ASN1_STRING_data(ri->enc_key),
				M_ASN1_STRING_length(ri->enc_key), pkey);
			if (jj <= 0)
				{
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,
								ERR_R_EVP_LIB);
				goto err;
				}
			}

		evp_ctx=NULL;
		BIO_get_cipher_ctx(etmp,&evp_ctx);
		if (EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0) <= 0)
			goto err;
		if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0)
			goto err;

		if (jj != EVP_CIPHER_CTX_key_length(evp_ctx)) {
			/* Some S/MIME clients don't use the same key
			 * and effective key length. The key length is
			 * determined by the size of the decrypted RSA key.
			 */
			if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, jj))
				{
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,
					PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH);
				goto err;
				}
		} 
		if (EVP_CipherInit_ex(evp_ctx,NULL,NULL,tmp,NULL,0) <= 0)
			goto err;

		OPENSSL_cleanse(tmp,jj);

		if (out == NULL)
			out=etmp;
		else
			BIO_push(out,etmp);
		etmp=NULL;
		}

#if 1
	if (PKCS7_is_detached(p7) || (in_bio != NULL))
		{
		bio=in_bio;
		}
	else 
		{
#if 0
		bio=BIO_new(BIO_s_mem());
		/* We need to set this so that when we have read all
		 * the data, the encrypt BIO, if present, will read
		 * EOF and encode the last few bytes */
		BIO_set_mem_eof_return(bio,0);

		if (data_body->length > 0)
			BIO_write(bio,(char *)data_body->data,data_body->length);
#else
		if (data_body->length > 0)
		      bio = BIO_new_mem_buf(data_body->data,data_body->length);
		else {
			bio=BIO_new(BIO_s_mem());
			BIO_set_mem_eof_return(bio,0);
		}
#endif
		}
	BIO_push(out,bio);
	bio=NULL;
#endif
	if (0)
		{
err:
		if (out != NULL) BIO_free_all(out);
		if (btmp != NULL) BIO_free_all(btmp);
		if (etmp != NULL) BIO_free_all(etmp);
		if (bio != NULL) BIO_free_all(bio);
		out=NULL;
		}
	if (tmp != NULL)
		OPENSSL_free(tmp);
	return(out);
	}
Ejemplo n.º 25
0
/*
 * Sign an assertion.
 */
static char *
keynote_sign_assertion(struct assertion *as, char *sigalg, void *key,
		       int keyalg, int verifyflag)
{
    int slen, i, hashlen = 0, hashtype, alg, encoding, internalenc;
    unsigned char *sig = (char *) NULL, *finalbuf = (char *) NULL;
    unsigned char res2[LARGEST_HASH_SIZE], *sbuf = (char *) NULL;
    BIO *biokey = (BIO *) NULL;
    DSA *dsa = (DSA *) NULL;
    RSA *rsa = (RSA *) NULL;
    SHA_CTX shscontext;
    MD5_CTX md5context;
    int len;

    if ((as->as_signature_string_s == (char *) NULL) ||
	(as->as_startofsignature == (char *) NULL) ||
	(as->as_allbutsignature == (char *) NULL) ||
	(as->as_allbutsignature - as->as_startofsignature <= 0) ||
	(as->as_authorizer == (void *) NULL) ||
	(key == (void *) NULL) ||
	(as->as_signeralgorithm == KEYNOTE_ALGORITHM_NONE))
    {
	keynote_errno = ERROR_SYNTAX;
	return (char *) NULL;
    }

    alg = keynote_get_sig_algorithm(sigalg, &hashtype, &encoding,
				    &internalenc);
    if (((alg != as->as_signeralgorithm) &&
	 !((alg == KEYNOTE_ALGORITHM_RSA) &&
	   (as->as_signeralgorithm == KEYNOTE_ALGORITHM_X509)) &&
	 !((alg == KEYNOTE_ALGORITHM_X509) &&
	   (as->as_signeralgorithm == KEYNOTE_ALGORITHM_RSA))) ||
        ((alg != keyalg) &&
	 !((alg == KEYNOTE_ALGORITHM_RSA) &&
	   (keyalg == KEYNOTE_ALGORITHM_X509)) &&
	 !((alg == KEYNOTE_ALGORITHM_X509) &&
	   (keyalg == KEYNOTE_ALGORITHM_RSA))))
    {
	keynote_errno = ERROR_SYNTAX;
	return (char *) NULL;
    }

    sig = strchr(sigalg, ':');
    if (sig == (unsigned char *) NULL)
    {
	keynote_errno = ERROR_SYNTAX;
	return (char *) NULL;
    }

    sig++;

    switch (hashtype)
    {
	case KEYNOTE_HASH_SHA1:
    	    hashlen = 20;
	    memset(res2, 0, hashlen);
	    SHA1_Init(&shscontext);
	    SHA1_Update(&shscontext, as->as_startofsignature,
			as->as_allbutsignature - as->as_startofsignature);
	    SHA1_Update(&shscontext, sigalg, (char *) sig - sigalg);
	    SHA1_Final(res2, &shscontext);
	    break;
   
	case KEYNOTE_HASH_MD5:
	    hashlen = 16;
	    memset(res2, 0, hashlen);
	    MD5_Init(&md5context);
	    MD5_Update(&md5context, as->as_startofsignature,
		       as->as_allbutsignature - as->as_startofsignature);
	    MD5_Update(&md5context, sigalg, (char *) sig - sigalg);
	    MD5_Final(res2, &md5context);
	    break;

	case KEYNOTE_HASH_NONE:
	    break;
    }

    if ((alg == KEYNOTE_ALGORITHM_DSA) &&
	(hashtype == KEYNOTE_HASH_SHA1) &&
	(internalenc == INTERNAL_ENC_ASN1) &&
	((encoding == ENCODING_HEX) || (encoding == ENCODING_BASE64)))
    {
	dsa = (DSA *) key;
	sbuf = (unsigned char *) calloc(DSA_size(dsa), sizeof(unsigned char));
	if (sbuf == (unsigned char *) NULL)
	{
	    keynote_errno = ERROR_MEMORY;
	    return (char *) NULL;
	}

	if (DSA_sign(0, res2, hashlen, sbuf, &slen, dsa) <= 0)
	{
	    free(sbuf);
	    keynote_errno = ERROR_SYNTAX;
	    return (char *) NULL;
	}
    }
    else
      if ((alg == KEYNOTE_ALGORITHM_RSA) &&
          ((hashtype == KEYNOTE_HASH_SHA1) ||
           (hashtype == KEYNOTE_HASH_MD5)) &&
          (internalenc == INTERNAL_ENC_PKCS1) &&
          ((encoding == ENCODING_HEX) || (encoding == ENCODING_BASE64)))
      {
          rsa = (RSA *) key;
          sbuf = (unsigned char *) calloc(RSA_size(rsa),
                                          sizeof(unsigned char));
          if (sbuf == (unsigned char *) NULL)
          {
              keynote_errno = ERROR_MEMORY;
              return (char *) NULL;
          }

          if (RSA_sign_ASN1_OCTET_STRING(RSA_PKCS1_PADDING, res2, hashlen,
					 sbuf, &slen, rsa) <= 0)
          {
              free(sbuf);
              keynote_errno = ERROR_SYNTAX;
              return (char *) NULL;
          }
      }
    else
      if ((alg == KEYNOTE_ALGORITHM_X509) &&
	  (hashtype == KEYNOTE_HASH_SHA1) &&
	  (internalenc == INTERNAL_ENC_ASN1))
      {
	  if ((biokey = BIO_new(BIO_s_mem())) == (BIO *) NULL)
	  {
	      keynote_errno = ERROR_SYNTAX;
	      return (char *) NULL;
	  }
	  
	  if (BIO_write(biokey, key, strlen(key) + 1) <= 0)
	  {
	      BIO_free(biokey);
	      keynote_errno = ERROR_SYNTAX;
	      return (char *) NULL;
	  }

	  /* RSA-specific */
	  rsa = (RSA *) PEM_read_bio_RSAPrivateKey(biokey, NULL, NULL, NULL);
	  if (rsa == (RSA *) NULL)
	  {
	      BIO_free(biokey);
	      keynote_errno = ERROR_SYNTAX;
	      return (char *) NULL;
	  }

	  sbuf = calloc(RSA_size(rsa), sizeof(char));
	  if (sbuf == (unsigned char *) NULL)
	  {
	      BIO_free(biokey);
	      RSA_free(rsa);
	      keynote_errno = ERROR_MEMORY;
	      return (char *) NULL;
	  }

	  if (RSA_sign(NID_shaWithRSAEncryption, res2, hashlen, sbuf, &slen,
		       rsa) <= 0)
          {
	      BIO_free(biokey);
	      RSA_free(rsa);
	      free(sbuf);
	      keynote_errno = ERROR_SIGN_FAILURE;
	      return NULL;
	  }

	  BIO_free(biokey);
	  RSA_free(rsa);
      }
      else /* Other algorithms here */
      {
	  keynote_errno = ERROR_SYNTAX;
	  return (char *) NULL;
      }

    /* ASCII encoding */
    switch (encoding)
    {
	case ENCODING_HEX:
	    i = kn_encode_hex(sbuf, (char **) &finalbuf, slen);
	    free(sbuf);
	    if (i != 0)
	      return (char *) NULL;
	    break;

	case ENCODING_BASE64:
	    finalbuf = (unsigned char *) calloc(2 * slen,
						sizeof(unsigned char));
	    if (finalbuf == (unsigned char *) NULL)
	    {
		keynote_errno = ERROR_MEMORY;
		free(sbuf);
		return (char *) NULL;
	    }

	    if ((slen = kn_encode_base64(sbuf, slen, finalbuf, 
					 2 * slen)) == -1)
	    {
		free(sbuf);
		return (char *) NULL;
	    }
	    break;

	default:
	    free(sbuf);
	    keynote_errno = ERROR_SYNTAX;
	    return (char *) NULL;
    }

    /* Replace as->as_signature */
    len = strlen(sigalg) + strlen(finalbuf) + 1;
    as->as_signature = (char *) calloc(len, sizeof(char));
    if (as->as_signature == (char *) NULL)
    {
	free(finalbuf);
	keynote_errno = ERROR_MEMORY;
	return (char *) NULL;
    }

    /* Concatenate algorithm name and signature value */
    snprintf(as->as_signature, len, "%s%s", sigalg, finalbuf);
    free(finalbuf);
    finalbuf = as->as_signature;

    /* Verify the newly-created signature if requested */
    if (verifyflag)
    {
	/* Do the signature verification */
	if (keynote_sigverify_assertion(as) != SIGRESULT_TRUE)
	{
	    as->as_signature = (char *) NULL;
	    free(finalbuf);
	    if (keynote_errno == 0)
	      keynote_errno = ERROR_SYNTAX;
	    return (char *) NULL;
	}

	as->as_signature = (char *) NULL;
    }
    else
      as->as_signature = (char *) NULL;

    /* Everything ok */
    return (char *) finalbuf;
}
Ejemplo n.º 26
0
int main(int argc, char* argv[]) 
{ 
PKCS7 *p7, *innerp7; 
FILE *fp = NULL; 
EVP_PKEY *pkey = NULL; 
PKCS7_SIGNER_INFO *p7i; 
PKCS7_RECIP_INFO *pri; 
BIO *mybio, *inbio; 
X509 *user; 
X509_ALGOR *md; 
int ret, len; 
unsigned char data[2048], *p, *buf; 
unsigned char* greet = "hello openssl"; 

unsigned long errorno; 
unsigned char* errordesc; 

OpenSSL_add_all_algorithms(); //必须要显式进行调用 

inbio = BIO_new(BIO_s_mem()); 
ret = BIO_write(inbio, greet, strlen(greet)); 

p7 = PKCS7_new(); 
ret = PKCS7_set_type(p7, NID_pkcs7_signedAndEnveloped); 


//加载用户证书 
fp = fopen("mycert4p12.cer", "rb"); 
if(fp == NULL) return 0; 
len = fread(data, 1, 1024, fp); 
fclose(fp); 
p = data; 
user = d2i_X509(NULL, (const unsigned char**)&p, len); 
ret = PKCS7_add_certificate(p7, user); 
pri = PKCS7_add_recipient(p7, user); 

//读取私钥 
fp = fopen("myprivkey.pem", "rb"); 
if(fp == NULL) return 0; 
len = fread(data, 1, 1024, fp); 
fclose(fp); 
p = data; 
pkey = d2i_PrivateKey(EVP_PKEY_RSA, NULL, (const unsigned char**)&p, len); 

//第一个用户增加SignerInfo到列表中 
p7i = PKCS7_add_signature(p7, user, pkey, EVP_md5()); 

//加载用户证书 
fp = fopen("user2.cer", "rb"); 
if(fp == NULL) return 0; 
len = fread(data, 1, 1024, fp); 
fclose(fp); 
p = data; 
user = d2i_X509(NULL, (const unsigned char**)&p, len); 
ret = PKCS7_add_certificate(p7, user); 
pri = PKCS7_add_recipient(p7, user); 

//读取私钥 
fp = fopen("user2_privatekey.pem", "rb"); 
if(fp == NULL) return 0; 
len = fread(data, 1, 1024, fp); 
fclose(fp); 
p = data; 
pkey = d2i_PrivateKey(EVP_PKEY_RSA, NULL, (const unsigned char**)&p, len); 

//第二个签名者增加到SignerInfo列表中 
p7i = PKCS7_add_signature(p7, user, pkey, EVP_md5()); 

ret = PKCS7_set_cipher(p7, EVP_des_ede3_cbc()); 

ret = PKCS7_final(p7, inbio, 0); //制作数字信封 

len = i2d_PKCS7(p7, NULL); 
p = buf = malloc(len); 
len = i2d_PKCS7(p7, &p); 
printf("in i2d len = %d\n", len); 

fp = fopen("p7signandenv.cer", "wb"); 
fwrite(buf, len, 1, fp); 
fclose(fp); 

PKCS7_free(p7); 
} 
Ejemplo n.º 27
0
/*
 * Generate key
 */
static int westcos_pkcs15init_generate_key(sc_profile_t *profile,
						sc_pkcs15_card_t *p15card,
						sc_pkcs15_object_t *obj,
						sc_pkcs15_pubkey_t *pubkey)
{
#ifndef ENABLE_OPENSSL
	return SC_ERROR_NOT_SUPPORTED;
#else
	int r = SC_ERROR_UNKNOWN;
	long lg;
	u8 *p;
	sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data;
	RSA *rsa = NULL;
	BIGNUM *bn = NULL;
	BIO *mem = NULL;

	sc_file_t *prkf = NULL;

	if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) {
		return SC_ERROR_NOT_SUPPORTED;
	}

#if OPENSSL_VERSION_NUMBER>=0x00908000L
	rsa = RSA_new();
	bn = BN_new();
	mem = BIO_new(BIO_s_mem());

	if(rsa == NULL || bn == NULL || mem == NULL)
	{
		r = SC_ERROR_OUT_OF_MEMORY;
		goto out;
	}

	if(!BN_set_word(bn, RSA_F4) ||
		!RSA_generate_key_ex(rsa, key_info->modulus_length, bn, NULL))
#else
	mem = BIO_new(BIO_s_mem());

	if(mem == NULL)
	{
		r = SC_ERROR_OUT_OF_MEMORY;
		goto out;
	}

	rsa = RSA_generate_key(key_info->modulus_length, RSA_F4, NULL, NULL);
	if (!rsa)
#endif
	{
		r = SC_ERROR_UNKNOWN;
		goto out;
	}

	RSA_set_method(rsa, RSA_PKCS1_OpenSSL());

	if(pubkey != NULL)
	{
		if(!i2d_RSAPublicKey_bio(mem, rsa))
		{
			r = SC_ERROR_UNKNOWN;
			goto out;
		}

		lg = BIO_get_mem_data(mem, &p);

		pubkey->algorithm = SC_ALGORITHM_RSA;

		r = sc_pkcs15_decode_pubkey(p15card->card->ctx, pubkey, p, lg);
		if (r < 0)
			goto out;
	}

	(void) BIO_reset(mem);

	if(!i2d_RSAPrivateKey_bio(mem, rsa))
	{
		r = SC_ERROR_UNKNOWN;
		goto out;
	}

	lg = BIO_get_mem_data(mem, &p);

	/* Get the private key file */
	r = sc_profile_get_file_by_path(profile, &key_info->path, &prkf);
	if (r < 0)
	{
		char pbuf[SC_MAX_PATH_STRING_SIZE];

		r = sc_path_print(pbuf, sizeof(pbuf), &key_info->path);
		if (r != SC_SUCCESS)
			pbuf[0] = '\0';

		goto out;
	}

	prkf->size = lg;

	r = sc_pkcs15init_create_file(profile, p15card, prkf);
	if(r) goto out;

	r = sc_pkcs15init_update_file(profile, p15card, prkf, p, lg);
	if(r) goto out;

out:
	if(mem)
		BIO_free(mem);
	if(bn)
		BN_free(bn);
	if(rsa)
		RSA_free(rsa);
	sc_file_free(prkf);

	return r;
#endif
}
Ejemplo n.º 28
0
int ssl_test_exp(int argc, char *argv[])
	{
	BN_CTX *ctx;
	BIO *out=NULL;
	int i,ret;
	unsigned char c;
	BIGNUM *r_mont,*r_mont_const,*r_recp,*r_simple,*a,*b,*m;

	RAND_seed(rnd_seed, sizeof rnd_seed); /* or BN_rand may fail, and we don't
	                                       * even check its return value
	                                       * (which we should) */

	ERR_load_BN_strings();

	ctx=BN_CTX_new();
	if (ctx == NULL) return(1);
	r_mont=BN_new();
	r_mont_const=BN_new();
	r_recp=BN_new();
	r_simple=BN_new();
	a=BN_new();
	b=BN_new();
	m=BN_new();
	if (	(r_mont == NULL) || (r_recp == NULL) ||
		(a == NULL) || (b == NULL))
		goto err;

#ifndef OPENSSL_SYS_WINDOWS
	out = BIO_new(BIO_s_mem());
	if (out == NULL) return(1);
	
#else
	out=BIO_new(BIO_s_file());

	if (out == NULL) return(1);
	BIO_set_fp(out,OPENSSL_TYPE__FILE_STDOUT,BIO_NOCLOSE);
#endif

	for (i=0; i<200; i++)
		{
		RAND_bytes(&c,1);
		c=(c%BN_BITS)-BN_BITS2;
		BN_rand(a,NUM_BITS+c,0,0);

		RAND_bytes(&c,1);
		c=(c%BN_BITS)-BN_BITS2;
		BN_rand(b,NUM_BITS+c,0,0);

		RAND_bytes(&c,1);
		c=(c%BN_BITS)-BN_BITS2;
		BN_rand(m,NUM_BITS+c,0,1);

		BN_mod(a,a,m,ctx);
		BN_mod(b,b,m,ctx);

		ret=BN_mod_exp_mont(r_mont,a,b,m,ctx,NULL);
		if (ret <= 0)
			{
			TINYCLR_SSL_PRINTF("BN_mod_exp_mont() problems\n");
			ERR_print_errors(out);
			return(1);
			}

		ret=BN_mod_exp_recp(r_recp,a,b,m,ctx);
		if (ret <= 0)
			{
			TINYCLR_SSL_PRINTF("BN_mod_exp_recp() problems\n");
			ERR_print_errors(out);
			return(1);
			}

		ret=BN_mod_exp_simple(r_simple,a,b,m,ctx);
		if (ret <= 0)
			{
			TINYCLR_SSL_PRINTF("BN_mod_exp_simple() problems\n");
			ERR_print_errors(out);
			return(1);
			}

		ret=BN_mod_exp_mont_consttime(r_mont_const,a,b,m,ctx,NULL);
		if (ret <= 0)
			{
			TINYCLR_SSL_PRINTF("BN_mod_exp_mont_consttime() problems\n");
			ERR_print_errors(out);
			return(1);
			}

		if (BN_cmp(r_simple, r_mont) == 0
		    && BN_cmp(r_simple,r_recp) == 0
			&& BN_cmp(r_simple,r_mont_const) == 0)
			{
			TINYCLR_SSL_PRINTF(".");
			}
		else
		  	{
			if (BN_cmp(r_simple,r_mont) != 0)
				TINYCLR_SSL_PRINTF("\nsimple and mont results differ\n");
			if (BN_cmp(r_simple,r_mont_const) != 0)
				TINYCLR_SSL_PRINTF("\nsimple and mont const time results differ\n");
			if (BN_cmp(r_simple,r_recp) != 0)
				TINYCLR_SSL_PRINTF("\nsimple and recp results differ\n");

			TINYCLR_SSL_PRINTF("a (%3d) = ",BN_num_bits(a));   BN_print(out,a);
			TINYCLR_SSL_PRINTF("\nb (%3d) = ",BN_num_bits(b)); BN_print(out,b);
			TINYCLR_SSL_PRINTF("\nm (%3d) = ",BN_num_bits(m)); BN_print(out,m);
			TINYCLR_SSL_PRINTF("\nsimple   =");	BN_print(out,r_simple);
			TINYCLR_SSL_PRINTF("\nrecp     =");	BN_print(out,r_recp);
			TINYCLR_SSL_PRINTF("\nmont     ="); BN_print(out,r_mont);
			TINYCLR_SSL_PRINTF("\nmont_ct  ="); BN_print(out,r_mont_const);
			TINYCLR_SSL_PRINTF("\n");
			return(1);
			}
		}
	BN_free(r_mont);
	BN_free(r_mont_const);
	BN_free(r_recp);
	BN_free(r_simple);
	BN_free(a);
	BN_free(b);
	BN_free(m);
	BN_CTX_free(ctx);
	ERR_remove_thread_state(NULL);
	CRYPTO_mem_leaks(out);
	BIO_free(out);
	TINYCLR_SSL_PRINTF(" done\n");
	return(0);
err:
	ERR_load_crypto_strings();
	ERR_print_errors(out);
#ifdef OPENSSL_SYS_NETWARE
    TINYCLR_SSL_PRINTF("ERROR\n");
#endif
	return(1);
	}
Ejemplo n.º 29
0
int cgiMain() {

  static char      title[]           = "List of existing Certificates";
         char      sorting[16]       = "desc";
         char      certfilestr[225]  = "";
         FILE      *certfile         = NULL;
         BIO       *membio           = NULL;
         BIO       *outbio           = NULL;
         char      membio_buf[128]   = "";
         X509      *cert             = NULL;
         X509_NAME *certsubject      = NULL;
         ASN1_TIME *start_date       = NULL;
         ASN1_TIME *expiration_date  = NULL;
  struct tm        start_tm;
  struct tm        expiration_tm;
         time_t    now               = time(NULL);
         time_t    start             = time(NULL);
         time_t    expiration        = time(NULL);
         double    available_secs    = 0;
         double    remaining_secs    = 0;
  struct dirent    **certstore_files = NULL;
         int       pagenumber        = 1;
         int       certcounter       = 0;
         int       tempcounter       = 0;
         int       pagecounter       = 0;
         int       dispcounter       = 0;
         int       dispmaxlines      = 0;
         int       certvalidity      = 0;
         div_t     disp_calc;
         div_t     oddline_calc;
         double    percent           = 0;

         cert                       = X509_new();
         certsubject                = X509_NAME_new();

/* -------------------------------------------------------------------------- *
 * Get the list of .pem files from the cert directory                         *
 * ---------------------------------------------------------------------------*/
  certcounter = scandir(CACERTSTORE, &certstore_files, file_select, hexsort);
  if(certcounter<=0) int_error("Error: No certificate files found.");

/* -------------------------------------------------------------------------- *
 * calculate how many pages we get with MAXCERTDISPLAY                         *
 * ---------------------------------------------------------------------------*/

  if(certcounter<=MAXCERTDISPLAY) pagecounter = 1;
  else {
    disp_calc = div(certcounter, MAXCERTDISPLAY);
    /* if the count of certs divided by MAXCERTDISPLAY has no remainder */
    if(disp_calc.rem == 0) pagecounter = disp_calc.quot;
    /* with a remainder, we must prepare an extra page for the rest */
    else pagecounter = disp_calc.quot +1;
  }

/* -------------------------------------------------------------------------- *
 * Check if we have been subsequently called with a pagenumber & sort request *
 * ---------------------------------------------------------------------------*/

  if(cgiFormInteger("page", &pagenumber, 1) == cgiFormSuccess)
    if(pagenumber > pagecounter || pagenumber <=0)
      int_error("Error: Page does not exist.");

  if(cgiFormString("sort", sorting, sizeof(sorting)) != cgiFormSuccess)
      strncpy(sorting, "desc", sizeof(sorting));

/* -------------------------------------------------------------------------- *
 * now we know how many certs we have in total and we can build the page(s).  *
 * For every MAXCERTDISPLAY certs we start a new page and cycle through by    *
 * calling ourself with the requested certs in range.                         *
 * ---------------------------------------------------------------------------*/

  if(strcmp(sorting, "asc") == 0) {

    if(certcounter <= MAXCERTDISPLAY) {
       dispmaxlines = certcounter;
       tempcounter = 0;
    }
    else
      if(pagenumber == pagecounter &&
             ( pagecounter * MAXCERTDISPLAY) - certcounter != 0) {

        tempcounter = (pagecounter * MAXCERTDISPLAY) - MAXCERTDISPLAY;
        dispmaxlines = certcounter - ((pagecounter-1) * MAXCERTDISPLAY);
      }
      else {

        tempcounter = (pagenumber * MAXCERTDISPLAY) - MAXCERTDISPLAY;
        dispmaxlines = MAXCERTDISPLAY;
      }
  }

  if(strcmp(sorting, "desc") == 0) {

    if(certcounter <= MAXCERTDISPLAY) {
       dispmaxlines = certcounter;
       tempcounter = certcounter;
    }
    else
      if(pagenumber == pagecounter &&
             ( pagecounter * MAXCERTDISPLAY) - certcounter != 0) {

        tempcounter = certcounter - ((pagecounter-1) * MAXCERTDISPLAY);
        dispmaxlines = certcounter - ((pagecounter-1) * MAXCERTDISPLAY);
      }
      else {

       tempcounter = certcounter - (pagenumber*MAXCERTDISPLAY) + MAXCERTDISPLAY;
       dispmaxlines = MAXCERTDISPLAY;
      }
  }

/* -------------------------------------------------------------------------- *
 * start the html output                                                      *
 * ---------------------------------------------------------------------------*/

  outbio = BIO_new(BIO_s_file());
  BIO_set_fp(outbio, cgiOut, BIO_NOCLOSE);

  pagehead(title);

  //debugging only:
  //printf("Number of certs: %d\n", certcounter);
  //printf("Num tempcounter: %d\n", tempcounter);
  //printf("Number of pages: %d\n", pagecounter);
  //printf("Div Quotient: %d\n", disp_calc.quot);
  //printf("Div Remainder: %d\n", disp_calc.rem);
  //fprintf(cgiOut, "</BODY></HTML>\n");
  //exit(0);

/* -------------------------------------------------------------------------- *
 * start the form output                                                      *
 * ---------------------------------------------------------------------------*/

   fprintf(cgiOut, "<table>\n");
   fprintf(cgiOut, "<tr>\n");
   fprintf(cgiOut, "<th width=\"20\">");
   fprintf(cgiOut, "#");
   fprintf(cgiOut, "</th>\n");
   fprintf(cgiOut, "<th width=\"495\">");
   fprintf(cgiOut, "Certificate Subject Information");
   fprintf(cgiOut, "</th>\n");
   fprintf(cgiOut, "<th colspan=\"2\" width=\"60\">");
   fprintf(cgiOut, "Expiry");
   fprintf(cgiOut, "</th>\n");
   fprintf(cgiOut, "<th width=\"65\">");
   fprintf(cgiOut, "Action");
   fprintf(cgiOut, "</th>\n");
   fprintf(cgiOut, "</tr>\n");

  for(dispcounter=0; dispcounter < dispmaxlines; dispcounter++) {

    /* zero certificate values and flags */
    certvalidity = 0;
    percent = 0;
    available_secs = 0;
    remaining_secs = 0;
    cert = X509_new();
    certsubject = X509_NAME_new();

    if(strcmp(sorting, "desc") == 0) tempcounter--;

    snprintf(certfilestr, sizeof(certfilestr), "%s/%s",
                           CACERTSTORE, certstore_files[tempcounter]->d_name);

    fprintf(cgiOut, "<tr>\n");
    fprintf(cgiOut, "<th rowspan=\"2\">");
    fprintf(cgiOut, "%d", tempcounter+1);
    fprintf(cgiOut, "</th>\n");

    oddline_calc = div(tempcounter+1, 2);
    if(oddline_calc.rem)
      fprintf(cgiOut, "<td rowspan=\"2\" class=\"odd\">");
    else
      fprintf(cgiOut, "<td rowspan=\"2\" class=\"even\">");

    if ( (certfile = fopen(certfilestr, "r")) != NULL) {
      PEM_read_X509(certfile, &cert, NULL, NULL);
      certsubject = X509_get_subject_name(cert);

      /* display the subject data, use the UTF-8 flag to show  *
       * Japanese Kanji, also needs the separator flag to work */
      X509_NAME_print_ex_fp(cgiOut, certsubject, 0,
         ASN1_STRFLGS_UTF8_CONVERT|XN_FLAG_SEP_CPLUS_SPC);

      /* store certificate start date for later eval */
      start_date = X509_get_notBefore(cert);

      /* store certificate expiration date for later eval */
      expiration_date = X509_get_notAfter(cert);

      /* check the start and end dates in the cert */
      if (X509_cmp_current_time (X509_get_notBefore (cert)) >= 0)
        /* flag the certificate as not valid yet */
        certvalidity = 0;
      else
      if (X509_cmp_current_time (X509_get_notAfter (cert)) <= 0)
        /* flag the certificate as expired */
        certvalidity = 0;
      else 
        /* flag the certificate is still valid */
        certvalidity = 1;

      fclose(certfile);
    }
    else 
       fprintf(cgiOut, "Error: Can't open certificate file %s for reading.",
                                                                 certfilestr);
    fprintf(cgiOut, "</td>\n");

    if(certvalidity == 0) {

      /* expiration bar display column */
      fprintf(cgiOut, "<th rowspan=\"2\">\n");
      fprintf(cgiOut, "<table class=\"led\">\n");
      fprintf(cgiOut, "  <tr><td class=\"led-off\"></td></tr>\n");
      fprintf(cgiOut, "  <tr><td class=\"led-off\"></td></tr>\n");
      fprintf(cgiOut, "  <tr><td class=\"led-off\"></td></tr>\n");
      fprintf(cgiOut, "  <tr><td class=\"led-off\"></td></tr>\n");
      fprintf(cgiOut, "  <tr><td class=\"led-off\"></td></tr>\n");
      fprintf(cgiOut, "  <tr><td class=\"led-off\"></td></tr>\n");
      fprintf(cgiOut, "  <tr><td class=\"led-off\"></td></tr>\n");
      fprintf(cgiOut, "  <tr><td class=\"led-off\"></td></tr>\n");
      fprintf(cgiOut, "  <tr><td class=\"led-off\"></td></tr>\n");
      fprintf(cgiOut, "</table>\n");
      fprintf(cgiOut, "</th>\n");

      /* remaining days before expiration column */
      fprintf(cgiOut, "<th class=\"exnok\" rowspan=\"2\">\n");
      fprintf(cgiOut, "Inval<br />Expd");
      fprintf(cgiOut, "</th>\n");
    }

    if(certvalidity == 1) {

      /* ------ START get the certificate lifetime in seconds ------ */
      /* copy the start date into a string */
      membio = BIO_new(BIO_s_mem());
      ASN1_TIME_print(membio, start_date);
      BIO_gets(membio, membio_buf, sizeof(membio_buf));
      BIO_free(membio);

      /* parse the start date string into a time struct */
      memset (&start_tm, '\0', sizeof(start_tm));
      strptime(membio_buf, "%h %d %T %Y %z", &start_tm);
      start = mktime(&start_tm);

      /* ------ START get the certificate remaining time in seconds ------ */
      /* copy the expiration date into a string */
      membio = BIO_new(BIO_s_mem());
      ASN1_TIME_print(membio, expiration_date);
      BIO_gets(membio, membio_buf, sizeof(membio_buf));
      BIO_free(membio);
  
      /* parse the expiration date string into a time struct */
      memset (&expiration_tm, '\0', sizeof(expiration_tm));
      strptime(membio_buf, "%h %d %T %Y %z", &expiration_tm);
  
      /* get the current time */
      now = time(NULL);
      expiration = mktime(&expiration_tm);
  
      /* get the time difference between expiration time and current time */
      remaining_secs = difftime(expiration, now);
      /* ------ END get the certificate remaining time in seconds ------ */

      /* get the time difference between start and expiration time */
      available_secs = difftime(expiration, start);
      /* ------ END get the certificate lifetime in seconds ------ */
  
      /* ------ START calculate percentage of lifetime left ------ */
      /* remaining_secs *100                                       */
      /* ------------------- = X, rounded down with floor()        */
      /* available_secs                                            */
      percent = floor((remaining_secs*100)/available_secs);
      /* ------ END calculate percentage of lifetime left   ------ */
  
      /* expiration bar display column */
      fprintf(cgiOut, "<th rowspan=\"2\">\n");
      fprintf(cgiOut, "<table class=\"led\">\n");
      if (percent >= 90) fprintf(cgiOut, "  <tr><td class=\"led\" bgcolor=\"#00FF00\"></td></tr>\n");
      else fprintf(cgiOut, "  <tr><td class=\"led-off\"></td></tr>\n");
      if (percent >= 80) fprintf(cgiOut, "  <tr><td class=\"led\" bgcolor=\"#00FF33\"></td></tr>\n");
      else fprintf(cgiOut, "  <tr><td class=\"led-off\"></td></tr>\n");
      if (percent >= 70) fprintf(cgiOut, "  <tr><td class=\"led\" bgcolor=\"#99FF33\"></td></tr>\n");
      else fprintf(cgiOut, "  <tr><td class=\"led-off\"></td></tr>\n");
      if (percent >= 60) fprintf(cgiOut, "  <tr><td class=\"led\" bgcolor=\"#FFFF00\"></td></tr>\n");
      else fprintf(cgiOut, "  <tr><td class=\"led-off\"></td></tr>\n");
      if (percent >= 50) fprintf(cgiOut, "  <tr><td class=\"led\" bgcolor=\"#FFCC00\"></td></tr>\n");
      else fprintf(cgiOut, "  <tr><td class=\"led-off\"></td></tr>\n");
      if (percent >= 40) fprintf(cgiOut, "  <tr><td class=\"led\" bgcolor=\"#FF9900\"></td></tr>\n");
      else fprintf(cgiOut, "  <tr><td class=\"led-off\"></td></tr>\n");
      if (percent >= 30) fprintf(cgiOut, "  <tr><td class=\"led\" bgcolor=\"#FF6600\"></td></tr>\n");
      else fprintf(cgiOut, "  <tr><td class=\"led-off\"></td></tr>\n");
      if (percent >= 20) fprintf(cgiOut, "  <tr><td class=\"led\" bgcolor=\"#FF3300\"></td></tr>\n");
      else fprintf(cgiOut, "  <tr><td class=\"led-off\"></td></tr>\n");
      if (percent >= 10) fprintf(cgiOut, "  <tr><td class=\"led\" bgcolor=\"#FF0000\"></td></tr>\n");
      else fprintf(cgiOut, "  <tr><td class=\"led-off\"></td></tr>\n");
      fprintf(cgiOut, "</table>\n");
      fprintf(cgiOut, "</th>\n");
  
      /* remaining days before expiration column */
      //fprintf(cgiOut, membio_buf);
      if (percent < 10) fprintf(cgiOut, "<th class=\"exnok\" rowspan=\"2\">\n");
      else fprintf(cgiOut, "<th class=\"exok\" rowspan=\"2\">\n");
      if(floor(remaining_secs/63072000) > 0) fprintf(cgiOut, "%.f<br />years", remaining_secs/31536000);
      else if(floor(remaining_secs/86400) > 0 ) fprintf(cgiOut, "%.f<br />days", remaining_secs/86400);
      else if(floor(remaining_secs/3600) > 0 ) fprintf(cgiOut, "%.f<br />hours", remaining_secs/3600);
      else if(floor(remaining_secs/60) > 0 ) fprintf(cgiOut, "%.f<br />mins", remaining_secs/60);
      else fprintf(cgiOut, "%.f<br />secs", remaining_secs);
      fprintf(cgiOut, "</th>\n");
    }

    /* action column */
    fprintf(cgiOut, "<th>");
    fprintf(cgiOut, "<form action=\"getcert.cgi\" method=\"post\">\n");
    fprintf(cgiOut, "<input type=\"hidden\" name=\"cfilename\" ");
    fprintf(cgiOut, "value=\"%s\" />\n", certstore_files[tempcounter]->d_name);
    fprintf(cgiOut, "<input type=\"hidden\" name=\"format\" value=\"text\" />\n");
    fprintf(cgiOut, "<input class=\"getcert\" type=\"submit\" value=\"Detail\" />\n");
    fprintf(cgiOut, "</form>\n");
    fprintf(cgiOut, "</th>\n");
    fprintf(cgiOut, "</tr>\n");
    fprintf(cgiOut, "<tr>\n");
    fprintf(cgiOut, "<th>\n");

    fprintf(cgiOut, "<form action=\"certrenew.cgi\" method=\"post\">\n");
    fprintf(cgiOut, "<input type=\"hidden\" name=\"cert-renew\" ");
    fprintf(cgiOut, "value=\"");
    PEM_write_bio_X509(outbio, cert);
    fprintf(cgiOut, "\" />\n");
    fprintf(cgiOut, "<input class=\"getcert\" type=\"submit\" value=\"Renew\" />\n");
    fprintf(cgiOut, "</form>\n");
    fprintf(cgiOut, "</th>\n");
    fprintf(cgiOut, "</tr>\n");

    if(strcmp(sorting, "asc") == 0) tempcounter++;
  }

  fprintf(cgiOut, "<tr>\n");
  fprintf(cgiOut, "<th colspan=\"5\">");
  fprintf(cgiOut, "Total # of certs: %d | ", certcounter);
  fprintf(cgiOut, "Page %d of %d", pagenumber, pagecounter);
  fprintf(cgiOut, "</th>\n");
  fprintf(cgiOut, "</tr>\n");
  fprintf(cgiOut, "</table>\n");

  fprintf(cgiOut, "<p></p>\n");

  fprintf(cgiOut, "<table>\n");

  fprintf(cgiOut, "<tr>\n");
  fprintf(cgiOut, "<th>\n");
  fprintf(cgiOut, "<form action=\"certstore.cgi\" method=\"post\">\n");
  fprintf(cgiOut, "<input type=\"hidden\" name=\"sort\" ");
  fprintf(cgiOut, "value=\"desc\" />\n");
  fprintf(cgiOut, "<input type=\"submit\" name=\"sort\"");
  fprintf(cgiOut, " value=\"Latest Certs first\" />\n");
  fprintf(cgiOut, "</form>\n");
  fprintf(cgiOut, "</th>\n");

  fprintf(cgiOut, "<th>\n");
  fprintf(cgiOut, "<form action=\"certstore.cgi\" method=\"post\">\n");
  fprintf(cgiOut, "<input type=\"hidden\" name=\"sort\" ");
  fprintf(cgiOut, "value=\"asc\" />\n");
  fprintf(cgiOut, "<input type=\"submit\" name=\"sort\"");
  fprintf(cgiOut, " value=\"Oldest Certs first\" />\n");
  fprintf(cgiOut, "</form>\n");
  fprintf(cgiOut, "</th>\n");

  // filler 1
  fprintf(cgiOut, "<th width=\"15\">");
  fprintf(cgiOut, "&nbsp;");
  fprintf(cgiOut, "</th>\n");

  // goto page 1
  fprintf(cgiOut, "<th width=\"5\">\n");
  fprintf(cgiOut, "<form action=\"certstore.cgi\" method=\"post\">\n");
  fprintf(cgiOut, "<input type=\"submit\" value=\"&lt;&lt;\" />\n");
  fprintf(cgiOut, "</form>\n");
  fprintf(cgiOut, "</th>\n");

  // goto page before
  fprintf(cgiOut, "<th width=\"5\">\n");
  fprintf(cgiOut, "<form action=\"certstore.cgi\" method=\"post\">\n");
  fprintf(cgiOut, "<input type=\"hidden\" name=\"certcounter\" ");
  fprintf(cgiOut, "value=\"%d\" />\n", certcounter);
  fprintf(cgiOut, "<input type=\"hidden\" name=\"pagecounter\" ");
  fprintf(cgiOut, "value=\"%d\" />\n", pagecounter);
  fprintf(cgiOut, "<input type=\"hidden\" name=\"page\" ");
  fprintf(cgiOut, "value=\"");
  tempcounter = 0;
  if(pagenumber > 1) tempcounter = pagenumber - 1;
  else tempcounter = 1;
  fprintf(cgiOut, "%d", tempcounter);
  fprintf(cgiOut, "\" />\n");
  fprintf(cgiOut, "<input type=\"submit\" value=\"&lt; 1\" />\n");
  fprintf(cgiOut, "</form>\n");
  fprintf(cgiOut, "</th>\n");

  // goto page after
  fprintf(cgiOut, "<th width=\"5\">\n");
  fprintf(cgiOut, "<form action=\"certstore.cgi\" method=\"post\">\n");
  fprintf(cgiOut, "<input type=\"hidden\" name=\"certcounter\" ");
  fprintf(cgiOut, "value=\"%d\" />\n", certcounter);
  fprintf(cgiOut, "<input type=\"hidden\" name=\"pagecounter\" ");
  fprintf(cgiOut, "value=\"%d\" />\n", pagecounter);
  fprintf(cgiOut, "<input type=\"hidden\" name=\"page\" ");
  fprintf(cgiOut, "value=\"");
  tempcounter = 0;
  if(pagecounter > pagenumber) tempcounter = pagenumber + 1;
  else tempcounter = pagecounter;
  fprintf(cgiOut, "%d", tempcounter);
  fprintf(cgiOut, "\" />\n");
  fprintf(cgiOut, "<input type=\"submit\" value=\"1 &gt;\" />\n");
  fprintf(cgiOut, "</form>\n");
  fprintf(cgiOut, "</th>\n");

  // goto last page
  fprintf(cgiOut, "<th width=\"5\">\n");
  fprintf(cgiOut, "<form action=\"certstore.cgi\" method=\"post\">");
  fprintf(cgiOut, "<input type=\"hidden\" name=\"certcounter\" ");
  fprintf(cgiOut, "value=\"%d\" />\n", certcounter);
  fprintf(cgiOut, "<input type=\"hidden\" name=\"pagecounter\" ");
  fprintf(cgiOut, "value=\"%d\" />\n", pagecounter);
  fprintf(cgiOut, "<input type=\"hidden\" name=\"page\" ");
  fprintf(cgiOut, "value=\"%d\" />\n", pagecounter);
  fprintf(cgiOut, "<input type=\"submit\" value=\"&gt;&gt;\" />\n");
  fprintf(cgiOut, "</form>\n");
  fprintf(cgiOut, "</th>\n");

  // goto page number
  fprintf(cgiOut, "<th width=\"120\">\n");
  fprintf(cgiOut, "<form class=\"setpage\" action=\"certstore.cgi\" method=\"post\">\n");
  fprintf(cgiOut, "<input type=\"hidden\" name=\"certcounter\" ");
  fprintf(cgiOut, "value=\"");
  fprintf(cgiOut, "%d", certcounter);
  fprintf(cgiOut, "\" />\n");
  fprintf(cgiOut, "<input type=\"hidden\" name=\"pagecounter\" ");
  fprintf(cgiOut, "value=\"");
  fprintf(cgiOut, "%d", pagecounter);
  fprintf(cgiOut, "\" />\n");
  fprintf(cgiOut, "<input class=\"goto\" type=\"submit\" value=\"Goto\" />\n");
  fprintf(cgiOut, "<input class=\"page\" type=\"text\" name=\"page\" ");
  fprintf(cgiOut, "value=\"%d\" />\n", pagecounter);
  fprintf(cgiOut, "</form>\n");
  fprintf(cgiOut, "</th>\n");
  fprintf(cgiOut, "</tr>\n");
  fprintf(cgiOut, "</table>\n");

/* ---------------------------------------------------------------------------*
 * end the html output                                                        *
 * ---------------------------------------------------------------------------*/
  pagefoot();

  BIO_free(outbio);
  return(0);
}
Ejemplo n.º 30
0
static ErlDrvSSizeT tls_drv_control(ErlDrvData handle,
			   unsigned int command,
			   char *buf, ErlDrvSizeT len,
			   char **rbuf, ErlDrvSizeT rlen)
{
   tls_data *d = (tls_data *)handle;
   int res;
   int size;
   ErlDrvBinary *b;
   X509 *cert;
   unsigned int flags = command;

   command &= 0xffff;

   ERR_clear_error();
   switch (command)
   {
      case SET_CERTIFICATE_FILE_ACCEPT:
      case SET_CERTIFICATE_FILE_CONNECT: {
	 time_t mtime = 0;
	 SSL_CTX *ssl_ctx = hash_table_lookup(buf, &mtime);
	 if (is_key_file_modified(buf, &mtime) || ssl_ctx == NULL)
	 {
	    SSL_CTX *ctx;

	    hash_table_insert(buf, mtime, NULL);

	    ctx = SSL_CTX_new(SSLv23_method());
	    die_unless(ctx, "SSL_CTX_new failed");

	    res = SSL_CTX_use_certificate_chain_file(ctx, buf);
	    die_unless(res > 0, "SSL_CTX_use_certificate_file failed");

	    res = SSL_CTX_use_PrivateKey_file(ctx, buf, SSL_FILETYPE_PEM);
	    die_unless(res > 0, "SSL_CTX_use_PrivateKey_file failed");

	    res = SSL_CTX_check_private_key(ctx);
	    die_unless(res > 0, "SSL_CTX_check_private_key failed");

	    SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
	    SSL_CTX_set_default_verify_paths(ctx);
#ifdef SSL_MODE_RELEASE_BUFFERS
	    SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
#endif
	    /* SSL_CTX_load_verify_locations(ctx, "/etc/ejabberd/ca_certificates.pem", NULL); */
	    /* SSL_CTX_load_verify_locations(ctx, NULL, "/etc/ejabberd/ca_certs/"); */

	    /* This IF is commented to allow verification in all cases: */
	    /* if (command == SET_CERTIFICATE_FILE_ACCEPT) */
	    /* { */
	       SSL_CTX_set_verify(ctx,
				  SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
				  verify_callback);
	    /* } */

	    ssl_ctx = ctx;
	    hash_table_insert(buf, mtime, ssl_ctx);
	 }

	 d->ssl = SSL_new(ssl_ctx);
	 die_unless(d->ssl, "SSL_new failed");

	 if (flags & VERIFY_NONE)
	    SSL_set_verify(d->ssl, SSL_VERIFY_NONE, verify_callback);

	 d->bio_read = BIO_new(BIO_s_mem());
	 d->bio_write = BIO_new(BIO_s_mem());

	 SSL_set_bio(d->ssl, d->bio_read, d->bio_write);

	 if (command == SET_CERTIFICATE_FILE_ACCEPT) {
	    SSL_set_options(d->ssl, SSL_OP_NO_TICKET);
	    SSL_set_accept_state(d->ssl);
	 } else {
	    SSL_set_options(d->ssl, SSL_OP_NO_SSLv2|SSL_OP_NO_TICKET);
	    SSL_set_connect_state(d->ssl);
	 }
	 break;
      }
      case SET_ENCRYPTED_INPUT:
	 die_unless(d->ssl, "SSL not initialized");
	 BIO_write(d->bio_read, buf, len);
	 break;
      case SET_DECRYPTED_OUTPUT:
	 die_unless(d->ssl, "SSL not initialized");
	 res = SSL_write(d->ssl, buf, len);
	 if (res <= 0)
	 {
	    res = SSL_get_error(d->ssl, res);
	    if (res == SSL_ERROR_WANT_READ || res == SSL_ERROR_WANT_WRITE)
	    {
	       b = driver_alloc_binary(1);
	       b->orig_bytes[0] = 2;
	       *rbuf = (char *)b;
	       return 1;
	    } else {
	       die_unless(0, "SSL_write failed");
	    }
	 }
	 break;
      case GET_ENCRYPTED_OUTPUT:
	 die_unless(d->ssl, "SSL not initialized");
	 size = BUF_SIZE + 1;
	 rlen = 1;
	 b = driver_alloc_binary(size);
	 b->orig_bytes[0] = 0;
	 while ((res = BIO_read(d->bio_write,
				b->orig_bytes + rlen, BUF_SIZE)) > 0)
	 {
	    //printf("%d bytes of encrypted data read from state machine\r\n", res);

	    rlen += res;
	    size += BUF_SIZE;
	    b = driver_realloc_binary(b, size);
	 }
	 b = driver_realloc_binary(b, rlen);
	 *rbuf = (char *)b;
	 return rlen;
      case GET_DECRYPTED_INPUT:
	 if (!SSL_is_init_finished(d->ssl))
	 {
	    res = SSL_do_handshake(d->ssl);
	    if (res <= 0)
	       die_unless(SSL_get_error(d->ssl, res) == SSL_ERROR_WANT_READ,
			  "SSL_do_handshake failed");
	 } else {
	    size = BUF_SIZE + 1;
	    rlen = 1;
	    b = driver_alloc_binary(size);
	    b->orig_bytes[0] = 0;

	    while ((res = SSL_read(d->ssl,
				   b->orig_bytes + rlen, BUF_SIZE)) > 0)
	    {
	       //printf("%d bytes of decrypted data read from state machine\r\n",res);
	       rlen += res;
	       size += BUF_SIZE;
	       b = driver_realloc_binary(b, size);
	    }

	    if (res < 0)
	    {
	       int err = SSL_get_error(d->ssl, res);

	       if (err == SSL_ERROR_WANT_READ)
	       {
		  //printf("SSL_read wants more data\r\n");
		  //return 0;
	       }
	       // TODO
	    }
	    b = driver_realloc_binary(b, rlen);
	    *rbuf = (char *)b;
	    return rlen;
	 }
	 break;
      case GET_PEER_CERTIFICATE:
	 cert = SSL_get_peer_certificate(d->ssl);
	 if (cert == NULL)
	 {
	    b = driver_alloc_binary(1);
	    b->orig_bytes[0] = 1;
	    *rbuf = (char *)b;
	    return 1;
	 } else {
	    unsigned char *tmp_buf;
	    rlen = i2d_X509(cert, NULL);
	    if (rlen >= 0)
	    {
	       rlen++;
	       b = driver_alloc_binary(rlen);
	       b->orig_bytes[0] = 0;
	       tmp_buf = (unsigned char *)&b->orig_bytes[1];
	       i2d_X509(cert, &tmp_buf);
	       X509_free(cert);
	       *rbuf = (char *)b;
	       return rlen;
	    } else
	       X509_free(cert);
	 }
	 break;
      case GET_VERIFY_RESULT:
	 b = driver_alloc_binary(1);
	 b->orig_bytes[0] = SSL_get_verify_result(d->ssl);
	 *rbuf = (char *)b;
	 return 1;
	 break;
   }

   b = driver_alloc_binary(1);
   b->orig_bytes[0] = 0;
   *rbuf = (char *)b;
   return 1;
}