Beispiel #1
0
static int 
compare_subject(X509 * cert)
{
	int rc = X509_NAME_cmp(X509_get_subject_name(cert), X509_REQ_get_subject_name(request));
	
	if (rc)
	{
		/* X509_NAME_cmp should return 0 when X509_get_subject_name()
                 * and X509_REQ_get_subject_name() match. There is a bug
		 * report on that issue (1422).
                 * 
		 * Assume we cannot trust X509_NAME_cmp() and perform a strcmp()
		 * when X509_NAME_cmp returns true (which is in fact false ;-))
		 */
		char cert_buf[1024];
		char req_buf[1024];
		X509_NAME_oneline(X509_get_subject_name(cert), cert_buf, sizeof(cert_buf));
		X509_NAME_oneline(X509_REQ_get_subject_name(request), req_buf, sizeof(req_buf));
		if (v_flag)
			printf (" X509_NAME_cmp() workaround: strcmp request subject (%s) to cert subject (%s)\n", req_buf, cert_buf);
		rc = strcmp (cert_buf, req_buf);
	}

	return rc;
} /* is_same_cn */
Beispiel #2
0
static X509 *
GenerateX509Cert(X509_REQ *req,                  // IN
                 CONF *config,                   // IN
                 int days)                       // IN
{
   X509 *cert;
   X509V3_CTX ctx;
   char *extensions;
   gboolean ret = FALSE;
   gchar *err = NULL;

   cert = X509_new();
   if (!cert) {
      Error("Failed to allocate a X509 certificate: %s.\n",
            GetSSLError(&err));
      goto exit;
   }

   if (!SetCertSerialNumber(cert)) {
      goto exit;
   }

   if (!X509_set_issuer_name(cert, X509_REQ_get_subject_name(req))    ||
       !X509_gmtime_adj(X509_get_notBefore(cert), 0)                  ||
       !X509_gmtime_adj(X509_get_notAfter(cert), (long)60*60*24*days) ||
       !X509_set_subject_name(cert, X509_REQ_get_subject_name(req))) {
      Error("Failed to configure the X509 certificate: %s.\n",
            GetSSLError(&err));
      goto exit;
   }

   X509V3_set_ctx(&ctx, cert, cert, NULL, NULL, 0);
   X509V3_set_nconf(&ctx, config);

   extensions = NCONF_get_string(config, "req", "x509_extensions");
   if (extensions) {
      if (!X509_set_version(cert, 2)) {
         Error("Failed to set the certificate version: %s.\n",
               GetSSLError(&err));
         goto exit;
      }

      if (!X509V3_EXT_add_nconf(config, &ctx, extensions, cert)) {
         Error("Error loading extension section %s: %s.\n",
               extensions, GetSSLError(&err));
         goto exit;
      }
   }

   ret = TRUE;

exit:
   if (!ret) {
      X509_free(cert);
      cert = NULL;
   }
   g_free(err);

   return cert;
}
Beispiel #3
0
/*
 * Routine used to CSR for est_client_enroll_csr testcases
 */
static int populate_x509_csr (X509_REQ *req, EVP_PKEY *pkey, char *cn)
{
    X509_NAME *subj;

    /* Setup version number */
    if (!X509_REQ_set_version(req, 0L)) {
        printf("\nUnable to set X509 version#\n");
        return (-1);
    }

    /*
     * Add Common Name entry
     */
    subj = X509_REQ_get_subject_name(req);
    if (!X509_NAME_add_entry_by_txt(subj, "CN", MBSTRING_ASC,
                                    (unsigned char*)cn, -1, -1, 0)) {
        printf("\nUnable to create X509 Common Name entry\n");
        return (-1);
    }

    /*
     * Set the public key on the request
     */
    if (!X509_REQ_set_pubkey(req, pkey)) {
        printf("\nUnable to set X509 public key\n");
        return (-1);
    }

    return (0);
}
Beispiel #4
0
void mkreq(X509_REQ** reqp, EVP_PKEY** pkeyp, int bits, int serial, int days)
{
	X509_REQ* req = X509_REQ_new();
	assert(req != NULL);

	EVP_PKEY* userpkey = EVP_PKEY_new();
	assert(userpkey != NULL);

	RSA* rsa;
	X509_NAME* name = NULL;

	rsa = RSA_generate_key(bits, RSA_F4, NULL, NULL);
	assert(EVP_PKEY_assign_RSA(userpkey, rsa) > 0);

	rsa = NULL;

	X509_REQ_set_pubkey(req, userpkey);

	name = X509_REQ_get_subject_name(req);
	X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (const unsigned char*)"UK", -1, -1, 0);
	X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (const unsigned char*)"OpenSSL Group", -1, -1, 0);

	assert(X509_REQ_sign(req, userpkey, EVP_sha1()) > 0);

	*reqp = req;
	*pkeyp = userpkey;
}
Beispiel #5
0
static LUA_FUNCTION(openssl_csr_parse)
{
  X509_REQ * csr = CHECK_OBJECT(1, X509_REQ, "openssl.x509_req");

  X509_NAME * subject = X509_REQ_get_subject_name(csr);
  STACK_OF(X509_EXTENSION) *exts  = X509_REQ_get_extensions(csr);

  lua_newtable(L);

  openssl_push_asn1(L, csr->signature, V_ASN1_BIT_STRING);
  lua_setfield(L, -2, "signature");

  openssl_push_x509_algor(L, csr->sig_alg);
  lua_setfield(L, -2, "sig_alg");

  lua_newtable(L);
  AUXILIAR_SET(L, -1, "version", X509_REQ_get_version(csr), integer);
  openssl_push_xname_asobject(L, subject);
  lua_setfield(L, -2, "subject");
  if (exts)
  {
    lua_pushstring(L, "extensions");
    openssl_sk_x509_extension_totable(L, exts);
    lua_rawset(L, -3);
    sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
  }

  {
    X509_REQ_INFO* ri = csr->req_info;
    int i, c;
    EVP_PKEY *pubkey = X509_REQ_get_pubkey(csr);

    lua_newtable(L);
    c = X509_REQ_get_attr_count(csr);
    if (c > 0)
    {
      lua_newtable(L);
      for (i = 0; i < c ; i++)
      {
        X509_ATTRIBUTE *attr = X509_REQ_get_attr(csr, i);
        attr = X509_ATTRIBUTE_dup(attr);
        PUSH_OBJECT(attr, "openssl.x509_attribute");
        lua_rawseti(L, -2, i + 1);
      }
      lua_setfield(L, -2, "attributes");
    }

    lua_newtable(L);
    openssl_push_asn1object(L, ri->pubkey->algor->algorithm);
    lua_setfield(L, -2, "algorithm");

    AUXILIAR_SETOBJECT(L, pubkey , "openssl.evp_pkey", -1, "pubkey");
    lua_setfield(L, -2, "pubkey");

    lua_setfield(L, -2, "req_info");
  }

  return 1;
}
Beispiel #6
0
static X509 *X509_REQ_to_X509_ex(X509_REQ *r, int days, EVP_PKEY *pkey, const EVP_MD* md)
{
  X509 *ret = NULL;
  X509_CINF *xi = NULL;
  X509_NAME *xn;
  EVP_PKEY *pubkey = NULL;
  int res;

  if ((ret = X509_new()) == NULL)
  {
    X509err(X509_F_X509_REQ_TO_X509, ERR_R_MALLOC_FAILURE);
    return NULL;
  }

  /* duplicate the request */
  xi = ret->cert_info;

  if (sk_X509_ATTRIBUTE_num(r->req_info->attributes) != 0)
  {
    if ((xi->version = M_ASN1_INTEGER_new()) == NULL)
      goto err;
    if (!ASN1_INTEGER_set(xi->version, 2))
      goto err;
    /*-     xi->extensions=ri->attributes; <- bad, should not ever be done
    ri->attributes=NULL; */
  }

  xn = X509_REQ_get_subject_name(r);
  if (X509_set_subject_name(ret, xn) == 0)
    goto err;
  if (X509_set_issuer_name(ret, xn) == 0)
    goto err;

  if (X509_gmtime_adj(xi->validity->notBefore, 0) == NULL)
    goto err;
  if (X509_gmtime_adj(xi->validity->notAfter, (long)60 * 60 * 24 * days) ==
      NULL)
    goto err;

  pubkey = X509_REQ_get_pubkey(r);
  res = X509_set_pubkey(ret, pubkey);
  EVP_PKEY_free(pubkey);

  if (!md)
    goto err;
  if (!res || !X509_sign(ret, pkey, md))
    goto err;
  if (0)
  {
err:
    X509_free(ret);
    ret = NULL;
  }
  return (ret);
}
Beispiel #7
0
static void	display_req(scepitem_t *ip) {
	char	subject[1024];
	char	*fingerprint = "";
	X509_NAME_oneline(X509_REQ_get_subject_name(ip->data.req), subject,
		sizeof(subject));
	if (html) {
		printf("<tr>\n"
			"<td>%s</td>\n"
			"<td>%s</td>\n"
			"</tr>\n", subject, fingerprint);
	} else {
		printf("%s\t%s\n", subject, fingerprint);
	}
}
Beispiel #8
0
static gboolean
ConfigX509CertReq(X509_REQ *req,                 // OUT
                  CONF *config)                  // IN
{
   int idx;
   X509_NAME *subject;
   gboolean ret = FALSE;
   const char *dname;
   gchar *err = NULL;

   if (!X509_REQ_set_version(req, 0L)) {
      Error("Failed to set the certificate request version: %s.\n",
            GetSSLError(&err));
      goto exit;
   }

   subject = X509_REQ_get_subject_name(req);
   if (!subject) {
      Error("Failed to get the certificate request subject name: %s.\n",
            GetSSLError(&err));
      goto exit;
   }

   dname = NCONF_get_string(config, "req", "distinguished_name");
   if (dname) {
      STACK_OF(CONF_VALUE) *dn_sk = NCONF_get_section(config, dname);
      if (!dn_sk) {
         Error("Failed to get section %s: %s.\n",
               dname, GetSSLError(&err));
         goto exit;
      }

      for (idx = 0; idx < sk_CONF_VALUE_num(dn_sk); idx++) {
         CONF_VALUE *v = sk_CONF_VALUE_value(dn_sk, idx);

         if (!X509_NAME_add_entry_by_txt(subject, v->name, MBSTRING_ASC,
                                         v->value, -1, -1, 0)) {
            Error("Failed to set certificate request pair %s/%s: %s.\n",
                  v->name, v->value, GetSSLError(&err));
            goto exit;
         }
      }
   }

   ret = TRUE;

exit:
   g_free(err);
   return ret;
}
Beispiel #9
0
static X509 *pki_certificate(X509_NAME *issuer, EVP_PKEY *keyring, X509_REQ *cert_req,
				uint8_t is_cert_authority, uint32_t serial, uint32_t expiration_delay)
{
	jlog(L_DEBUG, "pki_certificate");

	X509 *certificate;
	X509_NAME *subject;

	X509V3_CTX ctx;
	X509_EXTENSION *ext;

	// create a new certificate
	certificate = X509_new();

	// set certificate unique serial number
	ASN1_INTEGER_set(X509_get_serialNumber(certificate), serial);

	// set certificate 'Subject:'
	subject = X509_REQ_get_subject_name(cert_req);
	X509_set_subject_name(certificate, subject);

	// set certificate 'Issuer:'
	X509_set_issuer_name(certificate, issuer);

	// set X509v3 extension "basicConstraints" CA:TRUE/FALSE
	X509V3_set_ctx(&ctx, NULL, certificate, cert_req, NULL, 0);

	if (is_cert_authority == true)
		ext = X509V3_EXT_conf(NULL, &ctx, "basicConstraints", "CA:TRUE");
	else
		ext = X509V3_EXT_conf(NULL, &ctx, "basicConstraints", "CA:FALSE");

	X509_add_ext(certificate, ext, -1);
	X509_EXTENSION_free(ext);

	// set certificate version 3
	X509_set_version(certificate, 0x2);

	// set certificate public key
	X509_set_pubkey(certificate, keyring);

	// set the 'notBefore' to yersterday
	X509_gmtime_adj(X509_get_notBefore(certificate), -(24*60*60));
	// set certificate expiration delay
	X509_gmtime_adj(X509_get_notAfter(certificate), expiration_delay);

	return certificate;
}
Beispiel #10
0
X509 *X509_REQ_to_X509(X509_REQ *r, int days, EVP_PKEY *pkey)
{
    X509 *ret = NULL;
    X509_CINF *xi = NULL;
    X509_NAME *xn;

    if ((ret = X509_new()) == NULL) {
        OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
        goto err;
    }

    /* duplicate the request */
    xi = ret->cert_info;

    if (sk_X509_ATTRIBUTE_num(r->req_info->attributes) != 0) {
        if ((xi->version = M_ASN1_INTEGER_new()) == NULL)
            goto err;
        if (!ASN1_INTEGER_set(xi->version, 2))
            goto err;
        /*
         * xi->extensions=ri->attributes; <- bad, should not ever be done
         * ri->attributes=NULL;
         */
    }

    xn = X509_REQ_get_subject_name(r);
    if (X509_set_subject_name(ret, X509_NAME_dup(xn)) == 0)
        goto err;
    if (X509_set_issuer_name(ret, X509_NAME_dup(xn)) == 0)
        goto err;

    if (X509_gmtime_adj(xi->validity->notBefore, 0) == NULL)
        goto err;
    if (X509_gmtime_adj(xi->validity->notAfter, (long)60 * 60 * 24 * days) ==
        NULL)
        goto err;

    X509_set_pubkey(ret, X509_REQ_get_pubkey(r));

    if (!X509_sign(ret, pkey, EVP_md5()))
        goto err;
    if (0) {
 err:
        X509_free(ret);
        ret = NULL;
    }
    return (ret);
}
Beispiel #11
0
void mkcert(X509_REQ* req, const char* rootkey, const char* rootcert, const char* passwd)
{
	RSA* rsa_key = EVP_PKEY_get1_RSA(X509_PUBKEY_get(req->req_info->pubkey));
	int key_length = RSA_size(rsa_key);
	if (key_len != 128) {
		fprintf(stderr, "CA::key length of req is %d, not long enough\n");      
		return NULL;
	}

	X509* cacert = X509_new();
	assert(cacert != NULL);

	load_cacert(&cacert, rootcert);

	EVP_PKEY* cakey = EVP_PKEY_new();
	load_cakey(&cakey, rootkey, passwd);

	PEM_write_PrivateKey(stdout, cakey, NULL, NULL, 0, NULL, NULL);
	PEM_write_PUBKEY(stdout, cakey);

	X509* x = X509_new();
	X509_set_version(x, 3);
	ASN1_INTEGER_set(X509_get_serialNumber(x), 1024);
	X509_gmtime_adj(X509_get_notBefore(x), 0);
	X509_gmtime_adj(X509_get_notAfter(x), (long)60 * 60 * 24 * 365);

	X509_set_pubkey(x, X509_PUBKEY_get(req->req_info->pubkey));

	X509_set_subject_name(x, X509_REQ_get_subject_name(req));
	X509_set_issuer_name(x, X509_get_subject_name(cacert));

	assert(X509_sign(x, cakey, EVP_sha1()) > 0);

	FILE* f = fopen("usercert.pem", "wb");
	PEM_write_X509(f, x);
	fclose(f);

	X509_print_fp(stdout, x);
	PEM_write_X509(stdout, x);

	X509_free(cacert);
	EVP_PKEY_free(cakey);
}
Beispiel #12
0
static LUA_FUNCTION(openssl_csr_subject)
{
  X509_REQ *csr = CHECK_OBJECT(1, X509_REQ, "openssl.x509_req");
  if (lua_isnone(L, 2))
  {
    X509_NAME *xn = X509_REQ_get_subject_name(csr);
    if (xn)
      openssl_push_xname_asobject(L, xn);
    else
      lua_pushnil(L);
    return 1;
  }
  else
  {
    X509_NAME* xn = CHECK_OBJECT(2, X509_NAME, "openssl.x509_name");
    int ret = X509_REQ_set_subject_name(csr, xn);
    return openssl_pushresult(L, ret);
  }
}
Beispiel #13
0
UString UPKCS10::getSubject(X509_REQ* _request)
{
   U_TRACE(1, "UPKCS10::getSubject(%p)", _request)

   U_INTERNAL_ASSERT_POINTER(_request)

   X509_NAME* name = X509_REQ_get_subject_name(_request);
   unsigned len    = U_SYSCALL(i2d_X509_NAME, "%p,%p", name, 0);

   UString subject(len);
   char* ptr = subject.data();

   (void) U_SYSCALL(X509_NAME_oneline, "%p,%p,%d", name, ptr, subject.capacity());

   len = u__strlen(ptr, __PRETTY_FUNCTION__);

   subject.size_adjust(len);

   U_RETURN_STRING(subject);
}
Beispiel #14
0
static bool GenerateCertRequest(RsaDevice d, X509_REQ* req)
{
  // Create key in EVP format
  EVP_PKEY* key = CreateRsaKey(d);
  CHECK_CALL(key);
  
  // Create x509 cert signing request (CSR)
  CHECK_CALL(X509_REQ_set_pubkey(req, key));

  // Add subject name to the CSR
  X509_NAME* subj = X509_REQ_get_subject_name(req);
  CHECK_CALL(X509_NAME_add_entry_by_txt(
      subj, "O", MBSTRING_ASC, 
      (const unsigned char *)"RSA Device", -1, -1, 0)); 
  CHECK_CALL(X509_REQ_set_subject_name(req, subj));

  //X509_REQ_print_fp(stderr, req);
  CHECK_CALL(X509_REQ_sign(req, key, EVP_sha1()));

  EVP_PKEY_free(key);
  return true;
}
Beispiel #15
0
embassy_t *pki_embassy_new(digital_id_t *digital_id, uint32_t expiration_delay)
{
	jlog(L_NOTICE, "pki_embassy_new");

	embassy_t *embassy;
	embassy = calloc(1, sizeof(embassy_t));

	EVP_PKEY *keyring;
	X509_REQ *cert_req;
	X509 *certificate;
	X509_NAME *issuer;
	uint32_t serial = 0;

	// generate RSA public and private keys
	keyring = pki_generate_keyring();

	// create a certificate signing request
	cert_req = pki_certificate_request(keyring, digital_id);

	// fetch the 'Subject:' name from the certificate request
	// note that this is a self-signed certificate therefore
	// the 'Subject:' and 'Issuer:' are the same
	issuer = X509_REQ_get_subject_name(cert_req);

	// create the certificate from the certificate request and keyring
	certificate = pki_certificate(issuer, keyring, cert_req, true, serial++, expiration_delay);

	// self-sign the certificate with our own keyring
	pki_sign_certificate(keyring, certificate);

	// create the new embassy
	embassy->certificate = certificate;
	embassy->keyring = keyring;
	embassy->serial = serial;

	return embassy;
}
Beispiel #16
0
int MakeX509CSR(const char *cn, const char *keyfile, const char *csrfile)
{
	InitializeOpenSSL(); 
	
	RSA *rsa = RSA_generate_key(4096, RSA_F4, NULL, NULL);

	BIO *bio = BIO_new(BIO_s_file());
	BIO_write_filename(bio, const_cast<char *>(keyfile));
	PEM_write_bio_RSAPrivateKey(bio, rsa, NULL, NULL, 0, NULL, NULL);
	BIO_free(bio);

	X509_REQ *req = X509_REQ_new();

	if (!req)
		return 0;

	EVP_PKEY *key = EVP_PKEY_new();
	EVP_PKEY_assign_RSA(key, rsa);
	X509_REQ_set_version(req, 0);
	X509_REQ_set_pubkey(req, key);

	X509_NAME *name = X509_REQ_get_subject_name(req);
	X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char *)cn, -1, -1, 0);

	X509_REQ_sign(req, key, EVP_sha1());

	EVP_PKEY_free(key);

	bio = BIO_new(BIO_s_file());
	BIO_write_filename(bio, const_cast<char *>(csrfile));
	PEM_write_bio_X509_REQ(bio, req);
	BIO_free(bio);

	X509_REQ_free(req);

	return 1;
}
Beispiel #17
0
int MAIN(int argc, char **argv)
	{
	ENGINE *e = NULL;
	int ret=1;
	X509_REQ *req=NULL;
	X509 *x=NULL,*xca=NULL;
	ASN1_OBJECT *objtmp;
	STACK_OF(OPENSSL_STRING) *sigopts = NULL;
	EVP_PKEY *Upkey=NULL,*CApkey=NULL;
	ASN1_INTEGER *sno = NULL;
	int i,num,badops=0;
	BIO *out=NULL;
	BIO *STDout=NULL;
	STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL;
	int informat,outformat,keyformat,CAformat,CAkeyformat;
	char *infile=NULL,*outfile=NULL,*keyfile=NULL,*CAfile=NULL;
	char *CAkeyfile=NULL,*CAserial=NULL;
	char *alias=NULL;
	int text=0,serial=0,subject=0,issuer=0,startdate=0,enddate=0;
	int next_serial=0;
	int subject_hash=0,issuer_hash=0,ocspid=0;
#ifndef OPENSSL_NO_MD5
	int subject_hash_old=0,issuer_hash_old=0;
#endif
	int noout=0,sign_flag=0,CA_flag=0,CA_createserial=0,email=0;
	int ocsp_uri=0;
	int trustout=0,clrtrust=0,clrreject=0,aliasout=0,clrext=0;
	int C=0;
	int x509req=0,days=DEF_DAYS,modulus=0,pubkey=0;
	int pprint = 0;
	const char **pp;
	X509_STORE *ctx=NULL;
	X509_REQ *rq=NULL;
	int fingerprint=0;
	char buf[256];
	const EVP_MD *md_alg,*digest=NULL;
	CONF *extconf = NULL;
	char *extsect = NULL, *extfile = NULL, *passin = NULL, *passargin = NULL;
	int need_rand = 0;
	int checkend=0,checkoffset=0;
	unsigned long nmflag = 0, certflag = 0;
#ifndef OPENSSL_NO_ENGINE
	char *engine=NULL;
#endif

	reqfile=0;

	apps_startup();

	if (bio_err == NULL)
		bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);

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

	informat=FORMAT_PEM;
	outformat=FORMAT_PEM;
	keyformat=FORMAT_PEM;
	CAformat=FORMAT_PEM;
	CAkeyformat=FORMAT_PEM;

	ctx=X509_STORE_new();
	if (ctx == NULL) goto end;
	X509_STORE_set_verify_cb(ctx,callb);

	argc--;
	argv++;
	num=0;
	while (argc >= 1)
		{
		if 	(strcmp(*argv,"-inform") == 0)
			{
			if (--argc < 1) goto bad;
			informat=str2fmt(*(++argv));
			}
		else if (strcmp(*argv,"-outform") == 0)
			{
			if (--argc < 1) goto bad;
			outformat=str2fmt(*(++argv));
			}
		else if (strcmp(*argv,"-keyform") == 0)
			{
			if (--argc < 1) goto bad;
			keyformat=str2fmt(*(++argv));
			}
		else if (strcmp(*argv,"-req") == 0)
			{
			reqfile=1;
			need_rand = 1;
			}
		else if (strcmp(*argv,"-CAform") == 0)
			{
			if (--argc < 1) goto bad;
			CAformat=str2fmt(*(++argv));
			}
		else if (strcmp(*argv,"-CAkeyform") == 0)
			{
			if (--argc < 1) goto bad;
			CAkeyformat=str2fmt(*(++argv));
			}
		else if (strcmp(*argv,"-sigopt") == 0)
			{
			if (--argc < 1)
				goto bad;
			if (!sigopts)
				sigopts = sk_OPENSSL_STRING_new_null();
			if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv)))
				goto bad;
			}
		else if (strcmp(*argv,"-days") == 0)
			{
			if (--argc < 1) goto bad;
			days=atoi(*(++argv));
			if (days == 0)
				{
				BIO_printf(STDout,"bad number of days\n");
				goto bad;
				}
			}
		else if (strcmp(*argv,"-passin") == 0)
			{
			if (--argc < 1) goto bad;
			passargin= *(++argv);
			}
		else if (strcmp(*argv,"-extfile") == 0)
			{
			if (--argc < 1) goto bad;
			extfile= *(++argv);
			}
		else if (strcmp(*argv,"-extensions") == 0)
			{
			if (--argc < 1) goto bad;
			extsect= *(++argv);
			}
		else if (strcmp(*argv,"-in") == 0)
			{
			if (--argc < 1) goto bad;
			infile= *(++argv);
			}
		else if (strcmp(*argv,"-out") == 0)
			{
			if (--argc < 1) goto bad;
			outfile= *(++argv);
			}
		else if (strcmp(*argv,"-signkey") == 0)
			{
			if (--argc < 1) goto bad;
			keyfile= *(++argv);
			sign_flag= ++num;
			need_rand = 1;
			}
		else if (strcmp(*argv,"-CA") == 0)
			{
			if (--argc < 1) goto bad;
			CAfile= *(++argv);
			CA_flag= ++num;
			need_rand = 1;
			}
		else if (strcmp(*argv,"-CAkey") == 0)
			{
			if (--argc < 1) goto bad;
			CAkeyfile= *(++argv);
			}
		else if (strcmp(*argv,"-CAserial") == 0)
			{
			if (--argc < 1) goto bad;
			CAserial= *(++argv);
			}
		else if (strcmp(*argv,"-set_serial") == 0)
			{
			if (--argc < 1) goto bad;
			if (!(sno = s2i_ASN1_INTEGER(NULL, *(++argv))))
				goto bad;
			}
		else if (strcmp(*argv,"-addtrust") == 0)
			{
			if (--argc < 1) goto bad;
			if (!(objtmp = OBJ_txt2obj(*(++argv), 0)))
				{
				BIO_printf(bio_err,
					"Invalid trust object value %s\n", *argv);
				goto bad;
				}
			if (!trust) trust = sk_ASN1_OBJECT_new_null();
			sk_ASN1_OBJECT_push(trust, objtmp);
			trustout = 1;
			}
		else if (strcmp(*argv,"-addreject") == 0)
			{
			if (--argc < 1) goto bad;
			if (!(objtmp = OBJ_txt2obj(*(++argv), 0)))
				{
				BIO_printf(bio_err,
					"Invalid reject object value %s\n", *argv);
				goto bad;
				}
			if (!reject) reject = sk_ASN1_OBJECT_new_null();
			sk_ASN1_OBJECT_push(reject, objtmp);
			trustout = 1;
			}
		else if (strcmp(*argv,"-setalias") == 0)
			{
			if (--argc < 1) goto bad;
			alias= *(++argv);
			trustout = 1;
			}
		else if (strcmp(*argv,"-certopt") == 0)
			{
			if (--argc < 1) goto bad;
			if (!set_cert_ex(&certflag, *(++argv))) goto bad;
			}
		else if (strcmp(*argv,"-nameopt") == 0)
			{
			if (--argc < 1) goto bad;
			if (!set_name_ex(&nmflag, *(++argv))) goto bad;
			}
#ifndef OPENSSL_NO_ENGINE
		else if (strcmp(*argv,"-engine") == 0)
			{
			if (--argc < 1) goto bad;
			engine= *(++argv);
			}
#endif
		else if (strcmp(*argv,"-C") == 0)
			C= ++num;
		else if (strcmp(*argv,"-email") == 0)
			email= ++num;
		else if (strcmp(*argv,"-ocsp_uri") == 0)
			ocsp_uri= ++num;
		else if (strcmp(*argv,"-serial") == 0)
			serial= ++num;
		else if (strcmp(*argv,"-next_serial") == 0)
			next_serial= ++num;
		else if (strcmp(*argv,"-modulus") == 0)
			modulus= ++num;
		else if (strcmp(*argv,"-pubkey") == 0)
			pubkey= ++num;
		else if (strcmp(*argv,"-x509toreq") == 0)
			x509req= ++num;
		else if (strcmp(*argv,"-text") == 0)
			text= ++num;
		else if (strcmp(*argv,"-hash") == 0
			|| strcmp(*argv,"-subject_hash") == 0)
			subject_hash= ++num;
#ifndef OPENSSL_NO_MD5
		else if (strcmp(*argv,"-subject_hash_old") == 0)
			subject_hash_old= ++num;
#endif
		else if (strcmp(*argv,"-issuer_hash") == 0)
			issuer_hash= ++num;
#ifndef OPENSSL_NO_MD5
		else if (strcmp(*argv,"-issuer_hash_old") == 0)
			issuer_hash_old= ++num;
#endif
		else if (strcmp(*argv,"-subject") == 0)
			subject= ++num;
		else if (strcmp(*argv,"-issuer") == 0)
			issuer= ++num;
		else if (strcmp(*argv,"-fingerprint") == 0)
			fingerprint= ++num;
		else if (strcmp(*argv,"-dates") == 0)
			{
			startdate= ++num;
			enddate= ++num;
			}
		else if (strcmp(*argv,"-purpose") == 0)
			pprint= ++num;
		else if (strcmp(*argv,"-startdate") == 0)
			startdate= ++num;
		else if (strcmp(*argv,"-enddate") == 0)
			enddate= ++num;
		else if (strcmp(*argv,"-checkend") == 0)
			{
			if (--argc < 1) goto bad;
			checkoffset=atoi(*(++argv));
			checkend=1;
			}
		else if (strcmp(*argv,"-noout") == 0)
			noout= ++num;
		else if (strcmp(*argv,"-trustout") == 0)
			trustout= 1;
		else if (strcmp(*argv,"-clrtrust") == 0)
			clrtrust= ++num;
		else if (strcmp(*argv,"-clrreject") == 0)
			clrreject= ++num;
		else if (strcmp(*argv,"-alias") == 0)
			aliasout= ++num;
		else if (strcmp(*argv,"-CAcreateserial") == 0)
			CA_createserial= ++num;
		else if (strcmp(*argv,"-clrext") == 0)
			clrext = 1;
#if 1 /* stay backwards-compatible with 0.9.5; this should go away soon */
		else if (strcmp(*argv,"-crlext") == 0)
			{
			BIO_printf(bio_err,"use -clrext instead of -crlext\n");
			clrext = 1;
			}
#endif
		else if (strcmp(*argv,"-ocspid") == 0)
			ocspid= ++num;
		else if ((md_alg=EVP_get_digestbyname(*argv + 1)))
			{
			/* ok */
			digest=md_alg;
			}
		else
			{
			BIO_printf(bio_err,"unknown option %s\n",*argv);
			badops=1;
			break;
			}
		argc--;
		argv++;
		}

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

#ifndef OPENSSL_NO_ENGINE
        e = setup_engine(bio_err, engine, 0);
#endif

	if (need_rand)
		app_RAND_load_file(NULL, bio_err, 0);

	ERR_load_crypto_strings();

	if (!app_passwd(bio_err, passargin, NULL, &passin, NULL))
		{
		BIO_printf(bio_err, "Error getting password\n");
		goto end;
		}

	if (!X509_STORE_set_default_paths(ctx))
		{
		ERR_print_errors(bio_err);
		goto end;
		}

	if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM))
		{ CAkeyfile=CAfile; }
	else if ((CA_flag) && (CAkeyfile == NULL))
		{
		BIO_printf(bio_err,"need to specify a CAkey if using the CA command\n");
		goto end;
		}

	if (extfile)
		{
		long errorline = -1;
		X509V3_CTX ctx2;
		extconf = NCONF_new(NULL);
		if (!NCONF_load(extconf, extfile,&errorline))
			{
			if (errorline <= 0)
				BIO_printf(bio_err,
					"error loading the config file '%s'\n",
								extfile);
                	else
                        	BIO_printf(bio_err,
				       "error on line %ld of config file '%s'\n"
							,errorline,extfile);
			goto end;
			}
		if (!extsect)
			{
			extsect = NCONF_get_string(extconf, "default", "extensions");
			if (!extsect)
				{
				ERR_clear_error();
				extsect = "default";
				}
			}
		X509V3_set_ctx_test(&ctx2);
		X509V3_set_nconf(&ctx2, extconf);
		if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL))
			{
			BIO_printf(bio_err,
				"Error Loading extension section %s\n",
								 extsect);
			ERR_print_errors(bio_err);
			goto end;
			}
		}


	if (reqfile)
		{
		EVP_PKEY *pkey;
		BIO *in;

		if (!sign_flag && !CA_flag)
			{
			BIO_printf(bio_err,"We need a private key to sign with\n");
			goto end;
			}
		in=BIO_new(BIO_s_file());
		if (in == NULL)
			{
			ERR_print_errors(bio_err);
			goto end;
			}

		if (infile == NULL)
			BIO_set_fp(in,stdin,BIO_NOCLOSE|BIO_FP_TEXT);
		else
			{
			if (BIO_read_filename(in,infile) <= 0)
				{
				perror(infile);
				BIO_free(in);
				goto end;
				}
			}
		req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL);
		BIO_free(in);

		if (req == NULL)
			{
			ERR_print_errors(bio_err);
			goto end;
			}

		if (	(req->req_info == NULL) ||
			(req->req_info->pubkey == NULL) ||
			(req->req_info->pubkey->public_key == NULL) ||
			(req->req_info->pubkey->public_key->data == NULL))
			{
			BIO_printf(bio_err,"The certificate request appears to corrupted\n");
			BIO_printf(bio_err,"It does not contain a public key\n");
			goto end;
			}
		if ((pkey=X509_REQ_get_pubkey(req)) == NULL)
	                {
	                BIO_printf(bio_err,"error unpacking public key\n");
	                goto end;
	                }
		i=X509_REQ_verify(req,pkey);
		EVP_PKEY_free(pkey);
		if (i < 0)
			{
			BIO_printf(bio_err,"Signature verification error\n");
			ERR_print_errors(bio_err);
			goto end;
			}
	        if (i == 0)
			{
			BIO_printf(bio_err,"Signature did not match the certificate request\n");
			goto end;
			}
		else
			BIO_printf(bio_err,"Signature ok\n");

		print_name(bio_err, "subject=", X509_REQ_get_subject_name(req), nmflag);

		if ((x=X509_new()) == NULL) goto end;

		if (sno == NULL)
			{
			sno = ASN1_INTEGER_new();
			if (!sno || !rand_serial(NULL, sno))
				goto end;
			if (!X509_set_serialNumber(x, sno)) 
				goto end;
			ASN1_INTEGER_free(sno);
			sno = NULL;
			}
		else if (!X509_set_serialNumber(x, sno)) 
			goto end;

		if (!X509_set_issuer_name(x,req->req_info->subject)) goto end;
		if (!X509_set_subject_name(x,req->req_info->subject)) goto end;

		X509_gmtime_adj(X509_get_notBefore(x),0);
	        X509_time_adj_ex(X509_get_notAfter(x),days, 0, NULL);

		pkey = X509_REQ_get_pubkey(req);
		X509_set_pubkey(x,pkey);
		EVP_PKEY_free(pkey);
		}
	else
		x=load_cert(bio_err,infile,informat,NULL,e,"Certificate");

	if (x == NULL) goto end;
	if (CA_flag)
		{
		xca=load_cert(bio_err,CAfile,CAformat,NULL,e,"CA Certificate");
		if (xca == NULL) goto end;
		}

	if (!noout || text || next_serial)
		{
		OBJ_create("2.99999.3",
			"SET.ex3","SET x509v3 extension 3");

		out=BIO_new(BIO_s_file());
		if (out == NULL)
			{
			ERR_print_errors(bio_err);
			goto end;
			}
		if (outfile == NULL)
			{
			BIO_set_fp(out,stdout,BIO_NOCLOSE);
#ifdef OPENSSL_SYS_VMS
			{
			BIO *tmpbio = BIO_new(BIO_f_linebuffer());
			out = BIO_push(tmpbio, out);
			}
#endif
			}
		else
			{
			if (BIO_write_filename(out,outfile) <= 0)
				{
				perror(outfile);
				goto end;
				}
			}
		}

	if (alias) X509_alias_set1(x, (unsigned char *)alias, -1);

	if (clrtrust) X509_trust_clear(x);
	if (clrreject) X509_reject_clear(x);

	if (trust)
		{
		for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++)
			{
			objtmp = sk_ASN1_OBJECT_value(trust, i);
			X509_add1_trust_object(x, objtmp);
			}
		}

	if (reject)
		{
		for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++)
			{
			objtmp = sk_ASN1_OBJECT_value(reject, i);
			X509_add1_reject_object(x, objtmp);
			}
		}

	if (num)
		{
		for (i=1; i<=num; i++)
			{
			if (issuer == i)
				{
				print_name(STDout, "issuer= ",
					X509_get_issuer_name(x), nmflag);
				}
			else if (subject == i) 
				{
				print_name(STDout, "subject= ",
					X509_get_subject_name(x), nmflag);
				}
			else if (serial == i)
				{
				BIO_printf(STDout,"serial=");
				i2a_ASN1_INTEGER(STDout,
					X509_get_serialNumber(x));
				BIO_printf(STDout,"\n");
				}
			else if (next_serial == i)
				{
				BIGNUM *bnser;
				ASN1_INTEGER *ser;
				ser = X509_get_serialNumber(x);
				bnser = ASN1_INTEGER_to_BN(ser, NULL);
				if (!bnser)
					goto end;
				if (!BN_add_word(bnser, 1))
					goto end;
				ser = BN_to_ASN1_INTEGER(bnser, NULL);
				if (!ser)
					goto end;
				BN_free(bnser);
				i2a_ASN1_INTEGER(out, ser);
				ASN1_INTEGER_free(ser);
				BIO_puts(out, "\n");
				}
			else if ((email == i) || (ocsp_uri == i))
				{
				int j;
				STACK_OF(OPENSSL_STRING) *emlst;
				if (email == i)
					emlst = X509_get1_email(x);
				else
					emlst = X509_get1_ocsp(x);
				for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
					BIO_printf(STDout, "%s\n",
						   sk_OPENSSL_STRING_value(emlst, j));
				X509_email_free(emlst);
				}
			else if (aliasout == i)
				{
				unsigned char *alstr;
				alstr = X509_alias_get0(x, NULL);
				if (alstr) BIO_printf(STDout,"%s\n", alstr);
				else BIO_puts(STDout,"<No Alias>\n");
				}
			else if (subject_hash == i)
				{
				BIO_printf(STDout,"%08lx\n",X509_subject_name_hash(x));
				}
#ifndef OPENSSL_NO_MD5
			else if (subject_hash_old == i)
				{
				BIO_printf(STDout,"%08lx\n",X509_subject_name_hash_old(x));
				}
#endif
			else if (issuer_hash == i)
				{
				BIO_printf(STDout,"%08lx\n",X509_issuer_name_hash(x));
				}
#ifndef OPENSSL_NO_MD5
			else if (issuer_hash_old == i)
				{
				BIO_printf(STDout,"%08lx\n",X509_issuer_name_hash_old(x));
				}
#endif
			else if (pprint == i)
				{
				X509_PURPOSE *ptmp;
				int j;
				BIO_printf(STDout, "Certificate purposes:\n");
				for (j = 0; j < X509_PURPOSE_get_count(); j++)
					{
					ptmp = X509_PURPOSE_get0(j);
					purpose_print(STDout, x, ptmp);
					}
				}
			else
				if (modulus == i)
				{
				EVP_PKEY *pkey;

				pkey=X509_get_pubkey(x);
				if (pkey == NULL)
					{
					BIO_printf(bio_err,"Modulus=unavailable\n");
					ERR_print_errors(bio_err);
					goto end;
					}
				BIO_printf(STDout,"Modulus=");
#ifndef OPENSSL_NO_RSA
				if (pkey->type == EVP_PKEY_RSA)
					BN_print(STDout,pkey->pkey.rsa->n);
				else
#endif
#ifndef OPENSSL_NO_DSA
				if (pkey->type == EVP_PKEY_DSA)
					BN_print(STDout,pkey->pkey.dsa->pub_key);
				else
#endif
					BIO_printf(STDout,"Wrong Algorithm type");
				BIO_printf(STDout,"\n");
				EVP_PKEY_free(pkey);
				}
			else
				if (pubkey == i)
				{
				EVP_PKEY *pkey;

				pkey=X509_get_pubkey(x);
				if (pkey == NULL)
					{
					BIO_printf(bio_err,"Error getting public key\n");
					ERR_print_errors(bio_err);
					goto end;
					}
				PEM_write_bio_PUBKEY(STDout, pkey);
				EVP_PKEY_free(pkey);
				}
			else
				if (C == i)
				{
				unsigned char *d;
				char *m;
				int y,z;

				X509_NAME_oneline(X509_get_subject_name(x),
					buf,sizeof buf);
				BIO_printf(STDout,"/* subject:%s */\n",buf);
				m=X509_NAME_oneline(
					X509_get_issuer_name(x),buf,
					sizeof buf);
				BIO_printf(STDout,"/* issuer :%s */\n",buf);

				z=i2d_X509(x,NULL);
				m=OPENSSL_malloc(z);

				d=(unsigned char *)m;
				z=i2d_X509_NAME(X509_get_subject_name(x),&d);
				BIO_printf(STDout,"unsigned char XXX_subject_name[%d]={\n",z);
				d=(unsigned char *)m;
				for (y=0; y<z; y++)
					{
					BIO_printf(STDout,"0x%02X,",d[y]);
					if ((y & 0x0f) == 0x0f) BIO_printf(STDout,"\n");
					}
				if (y%16 != 0) BIO_printf(STDout,"\n");
				BIO_printf(STDout,"};\n");

				z=i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x),&d);
				BIO_printf(STDout,"unsigned char XXX_public_key[%d]={\n",z);
				d=(unsigned char *)m;
				for (y=0; y<z; y++)
					{
					BIO_printf(STDout,"0x%02X,",d[y]);
					if ((y & 0x0f) == 0x0f)
						BIO_printf(STDout,"\n");
					}
				if (y%16 != 0) BIO_printf(STDout,"\n");
				BIO_printf(STDout,"};\n");

				z=i2d_X509(x,&d);
				BIO_printf(STDout,"unsigned char XXX_certificate[%d]={\n",z);
				d=(unsigned char *)m;
				for (y=0; y<z; y++)
					{
					BIO_printf(STDout,"0x%02X,",d[y]);
					if ((y & 0x0f) == 0x0f)
						BIO_printf(STDout,"\n");
					}
				if (y%16 != 0) BIO_printf(STDout,"\n");
				BIO_printf(STDout,"};\n");

				OPENSSL_free(m);
				}
			else if (text == i)
				{
				X509_print_ex(out,x,nmflag, certflag);
				}
			else if (startdate == i)
				{
				BIO_puts(STDout,"notBefore=");
				ASN1_TIME_print(STDout,X509_get_notBefore(x));
				BIO_puts(STDout,"\n");
				}
			else if (enddate == i)
				{
				BIO_puts(STDout,"notAfter=");
				ASN1_TIME_print(STDout,X509_get_notAfter(x));
				BIO_puts(STDout,"\n");
				}
			else if (fingerprint == i)
				{
				int j;
				unsigned int n;
				unsigned char md[EVP_MAX_MD_SIZE];
				const EVP_MD *fdig = digest;

				if (!fdig)
					fdig = EVP_sha1();

				if (!X509_digest(x,fdig,md,&n))
					{
					BIO_printf(bio_err,"out of memory\n");
					goto end;
					}
				BIO_printf(STDout,"%s Fingerprint=",
						OBJ_nid2sn(EVP_MD_type(fdig)));
				for (j=0; j<(int)n; j++)
					{
					BIO_printf(STDout,"%02X%c",md[j],
						(j+1 == (int)n)
						?'\n':':');
					}
				}

			/* should be in the library */
			else if ((sign_flag == i) && (x509req == 0))
				{
				BIO_printf(bio_err,"Getting Private key\n");
				if (Upkey == NULL)
					{
					Upkey=load_key(bio_err,
						keyfile, keyformat, 0,
						passin, e, "Private key");
					if (Upkey == NULL) goto end;
					}

				assert(need_rand);
				if (!sign(x,Upkey,days,clrext,digest,
						 extconf, extsect)) goto end;
				}
			else if (CA_flag == i)
				{
				BIO_printf(bio_err,"Getting CA Private Key\n");
				if (CAkeyfile != NULL)
					{
					CApkey=load_key(bio_err,
						CAkeyfile, CAkeyformat,
						0, passin, e,
						"CA Private Key");
					if (CApkey == NULL) goto end;
					}
				
				assert(need_rand);
				if (!x509_certify(ctx,CAfile,digest,x,xca,
					CApkey, sigopts,
					CAserial,CA_createserial,days, clrext,
					extconf, extsect, sno))
					goto end;
				}
			else if (x509req == i)
				{
				EVP_PKEY *pk;

				BIO_printf(bio_err,"Getting request Private Key\n");
				if (keyfile == NULL)
					{
					BIO_printf(bio_err,"no request key file specified\n");
					goto end;
					}
				else
					{
					pk=load_key(bio_err,
						keyfile, keyformat, 0,
						passin, e, "request key");
					if (pk == NULL) goto end;
					}

				BIO_printf(bio_err,"Generating certificate request\n");

				rq=X509_to_X509_REQ(x,pk,digest);
				EVP_PKEY_free(pk);
				if (rq == NULL)
					{
					ERR_print_errors(bio_err);
					goto end;
					}
				if (!noout)
					{
					X509_REQ_print(out,rq);
					PEM_write_bio_X509_REQ(out,rq);
					}
				noout=1;
				}
			else if (ocspid == i)
				{
				X509_ocspid_print(out, x);
				}
			}
		}

	if (checkend)
		{
		time_t tcheck=time(NULL) + checkoffset;

		if (X509_cmp_time(X509_get_notAfter(x), &tcheck) < 0)
			{
			BIO_printf(out,"Certificate will expire\n");
			ret=1;
			}
		else
			{
			BIO_printf(out,"Certificate will not expire\n");
			ret=0;
			}
		goto end;
		}

	if (noout)
		{
		ret=0;
		goto end;
		}

	if 	(outformat == FORMAT_ASN1)
		i=i2d_X509_bio(out,x);
	else if (outformat == FORMAT_PEM)
		{
		if (trustout) i=PEM_write_bio_X509_AUX(out,x);
		else i=PEM_write_bio_X509(out,x);
		}
	else if (outformat == FORMAT_NETSCAPE)
		{
		NETSCAPE_X509 nx;
		ASN1_OCTET_STRING hdr;

		hdr.data=(unsigned char *)NETSCAPE_CERT_HDR;
		hdr.length=strlen(NETSCAPE_CERT_HDR);
		nx.header= &hdr;
		nx.cert=x;

		i=ASN1_item_i2d_bio(ASN1_ITEM_rptr(NETSCAPE_X509),out,&nx);
		}
	else	{
		BIO_printf(bio_err,"bad output format specified for outfile\n");
		goto end;
		}
	if (!i)
		{
		BIO_printf(bio_err,"unable to write certificate\n");
		ERR_print_errors(bio_err);
		goto end;
		}
	ret=0;
end:
	if (need_rand)
		app_RAND_write_file(NULL, bio_err);
	OBJ_cleanup();
	NCONF_free(extconf);
	BIO_free_all(out);
	BIO_free_all(STDout);
	X509_STORE_free(ctx);
	X509_REQ_free(req);
	X509_free(x);
	X509_free(xca);
	EVP_PKEY_free(Upkey);
	EVP_PKEY_free(CApkey);
	if (sigopts)
		sk_OPENSSL_STRING_free(sigopts);
	X509_REQ_free(rq);
	ASN1_INTEGER_free(sno);
	sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free);
	sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free);
	if (passin) OPENSSL_free(passin);
	apps_shutdown();
	OPENSSL_EXIT(ret);
	}
Beispiel #18
0
int x509_main(int argc, char **argv)
{
    ASN1_INTEGER *sno = NULL;
    ASN1_OBJECT *objtmp;
    BIO *out = NULL;
    CONF *extconf = NULL;
    EVP_PKEY *Upkey = NULL, *CApkey = NULL, *fkey = NULL;
    STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL;
    STACK_OF(OPENSSL_STRING) *sigopts = NULL;
    X509 *x = NULL, *xca = NULL;
    X509_REQ *req = NULL, *rq = NULL;
    X509_STORE *ctx = NULL;
    const EVP_MD *digest = NULL;
    char *CAkeyfile = NULL, *CAserial = NULL, *fkeyfile = NULL, *alias = NULL;
    char *checkhost = NULL, *checkemail = NULL, *checkip = NULL;
    char *extsect = NULL, *extfile = NULL, *passin = NULL, *passinarg = NULL;
    char *infile = NULL, *outfile = NULL, *keyfile = NULL, *CAfile = NULL;
    char buf[256], *prog;
    int x509req = 0, days = DEF_DAYS, modulus = 0, pubkey = 0, pprint = 0;
    int C = 0, CAformat = FORMAT_PEM, CAkeyformat = FORMAT_PEM;
    int fingerprint = 0, reqfile = 0, need_rand = 0, checkend = 0;
    int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM;
    int next_serial = 0, subject_hash = 0, issuer_hash = 0, ocspid = 0;
    int noout = 0, sign_flag = 0, CA_flag = 0, CA_createserial = 0, email = 0;
    int ocsp_uri = 0, trustout = 0, clrtrust = 0, clrreject = 0, aliasout = 0;
    int ret = 1, i, num = 0, badsig = 0, clrext = 0, nocert = 0;
    int text = 0, serial = 0, subject = 0, issuer = 0, startdate = 0;
    int checkoffset = 0, enddate = 0;
    unsigned long nmflag = 0, certflag = 0;
    OPTION_CHOICE o;
    ENGINE *e = NULL;
#ifndef OPENSSL_NO_MD5
    int subject_hash_old = 0, issuer_hash_old = 0;
#endif

    ctx = X509_STORE_new();
    if (ctx == NULL)
        goto end;
    X509_STORE_set_verify_cb(ctx, callb);

    prog = opt_init(argc, argv, x509_options);
    while ((o = opt_next()) != OPT_EOF) {
        switch (o) {
        case OPT_EOF:
        case OPT_ERR:
 opthelp:
            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
            goto end;
        case OPT_HELP:
            opt_help(x509_options);
            ret = 0;
            goto end;
        case OPT_INFORM:
            if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat))
                goto opthelp;
            break;
        case OPT_IN:
            infile = opt_arg();
            break;
        case OPT_OUTFORM:
            if (!opt_format(opt_arg(), OPT_FMT_ANY, &outformat))
                goto opthelp;
            break;
        case OPT_KEYFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &keyformat))
                goto opthelp;
            break;
        case OPT_CAFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &CAformat))
                goto opthelp;
            break;
        case OPT_CAKEYFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &CAkeyformat))
                goto opthelp;
            break;
        case OPT_OUT:
            outfile = opt_arg();
            break;
        case OPT_REQ:
            reqfile = need_rand = 1;
            break;

        case OPT_SIGOPT:
            if (!sigopts)
                sigopts = sk_OPENSSL_STRING_new_null();
            if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg()))
                goto opthelp;
            break;
#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
        case OPT_FORCE_VERSION:
            force_version = atoi(opt_arg()) - 1;
            break;
#endif
        case OPT_DAYS:
            days = atoi(opt_arg());
            break;
        case OPT_PASSIN:
            passinarg = opt_arg();
            break;
        case OPT_EXTFILE:
            extfile = opt_arg();
            break;
        case OPT_EXTENSIONS:
            extsect = opt_arg();
            break;
        case OPT_SIGNKEY:
            keyfile = opt_arg();
            sign_flag = ++num;
            need_rand = 1;
            break;
        case OPT_CA:
            CAfile = opt_arg();
            CA_flag = ++num;
            need_rand = 1;
            break;
        case OPT_CAKEY:
            CAkeyfile = opt_arg();
            break;
        case OPT_CASERIAL:
            CAserial = opt_arg();
            break;
        case OPT_SET_SERIAL:
            if ((sno = s2i_ASN1_INTEGER(NULL, opt_arg())) == NULL)
                goto opthelp;
            break;
        case OPT_FORCE_PUBKEY:
            fkeyfile = opt_arg();
            break;
        case OPT_ADDTRUST:
            if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) {
                BIO_printf(bio_err,
                           "%s: Invalid trust object value %s\n",
                           prog, opt_arg());
                goto opthelp;
            }
            if (trust == NULL && (trust = sk_ASN1_OBJECT_new_null()) == NULL)
                goto end;
            sk_ASN1_OBJECT_push(trust, objtmp);
            trustout = 1;
            break;
        case OPT_ADDREJECT:
            if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) {
                BIO_printf(bio_err,
                           "%s: Invalid reject object value %s\n",
                           prog, opt_arg());
                goto opthelp;
            }
            if (reject == NULL
                && (reject = sk_ASN1_OBJECT_new_null()) == NULL)
                goto end;
            sk_ASN1_OBJECT_push(reject, objtmp);
            trustout = 1;
            break;
        case OPT_SETALIAS:
            alias = opt_arg();
            trustout = 1;
            break;
        case OPT_CERTOPT:
            if (!set_cert_ex(&certflag, opt_arg()))
                goto opthelp;
            break;
        case OPT_NAMEOPT:
            if (!set_name_ex(&nmflag, opt_arg()))
                goto opthelp;
            break;
        case OPT_ENGINE:
            e = setup_engine(opt_arg(), 0);
            break;
        case OPT_C:
            C = ++num;
            break;
        case OPT_EMAIL:
            email = ++num;
            break;
        case OPT_OCSP_URI:
            ocsp_uri = ++num;
            break;
        case OPT_SERIAL:
            serial = ++num;
            break;
        case OPT_NEXT_SERIAL:
            next_serial = ++num;
            break;
        case OPT_MODULUS:
            modulus = ++num;
            break;
        case OPT_PUBKEY:
            pubkey = ++num;
            break;
        case OPT_X509TOREQ:
            x509req = ++num;
            break;
        case OPT_TEXT:
            text = ++num;
            break;
        case OPT_SUBJECT:
            subject = ++num;
            break;
        case OPT_ISSUER:
            issuer = ++num;
            break;
        case OPT_FINGERPRINT:
            fingerprint = ++num;
            break;
        case OPT_HASH:
            subject_hash = ++num;
            break;
        case OPT_ISSUER_HASH:
            issuer_hash = ++num;
            break;
        case OPT_PURPOSE:
            pprint = ++num;
            break;
        case OPT_STARTDATE:
            startdate = ++num;
            break;
        case OPT_ENDDATE:
            enddate = ++num;
            break;
        case OPT_NOOUT:
            noout = ++num;
            break;
        case OPT_NOCERT:
            nocert = 1;
            break;
        case OPT_TRUSTOUT:
            trustout = 1;
            break;
        case OPT_CLRTRUST:
            clrtrust = ++num;
            break;
        case OPT_CLRREJECT:
            clrreject = ++num;
            break;
        case OPT_ALIAS:
            aliasout = ++num;
            break;
        case OPT_CACREATESERIAL:
            CA_createserial = ++num;
            break;
        case OPT_CLREXT:
            clrext = 1;
            break;
        case OPT_OCSPID:
            ocspid = ++num;
            break;
        case OPT_BADSIG:
            badsig = 1;
            break;
#ifndef OPENSSL_NO_MD5
        case OPT_SUBJECT_HASH_OLD:
            subject_hash_old = ++num;
            break;
        case OPT_ISSUER_HASH_OLD:
            issuer_hash_old = ++num;
            break;
#endif
        case OPT_DATES:
            startdate = ++num;
            enddate = ++num;
            break;
        case OPT_CHECKEND:
            checkoffset = atoi(opt_arg());
            checkend = 1;
            break;
        case OPT_CHECKHOST:
            checkhost = opt_arg();
            break;
        case OPT_CHECKEMAIL:
            checkemail = opt_arg();
            break;
        case OPT_CHECKIP:
            checkip = opt_arg();
            break;
        case OPT_MD:
            if (!opt_md(opt_unknown(), &digest))
                goto opthelp;
        }
    }
    argc = opt_num_rest();
    argv = opt_rest();
    if (argc != 0) {
        BIO_printf(bio_err, "%s: Unknown parameter %s\n", prog, argv[0]);
        goto opthelp;
    }

    out = bio_open_default(outfile, "w");
    if (out == NULL)
        goto end;

    if (need_rand)
        app_RAND_load_file(NULL, 0);

    if (!app_passwd(passinarg, NULL, &passin, NULL)) {
        BIO_printf(bio_err, "Error getting password\n");
        goto end;
    }

    if (!X509_STORE_set_default_paths(ctx)) {
        ERR_print_errors(bio_err);
        goto end;
    }

    if (fkeyfile) {
        fkey = load_pubkey(fkeyfile, keyformat, 0, NULL, e, "Forced key");
        if (fkey == NULL)
            goto end;
    }

    if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM)) {
        CAkeyfile = CAfile;
    } else if ((CA_flag) && (CAkeyfile == NULL)) {
        BIO_printf(bio_err,
                   "need to specify a CAkey if using the CA command\n");
        goto end;
    }

    if (extfile) {
        long errorline = -1;
        X509V3_CTX ctx2;
        extconf = NCONF_new(NULL);
        if (!NCONF_load(extconf, extfile, &errorline)) {
            if (errorline <= 0)
                BIO_printf(bio_err,
                           "error loading the config file '%s'\n", extfile);
            else
                BIO_printf(bio_err,
                           "error on line %ld of config file '%s'\n",
                           errorline, extfile);
            goto end;
        }
        if (!extsect) {
            extsect = NCONF_get_string(extconf, "default", "extensions");
            if (!extsect) {
                ERR_clear_error();
                extsect = "default";
            }
        }
        X509V3_set_ctx_test(&ctx2);
        X509V3_set_nconf(&ctx2, extconf);
        if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL)) {
            BIO_printf(bio_err,
                       "Error Loading extension section %s\n", extsect);
            ERR_print_errors(bio_err);
            goto end;
        }
    }

    if (reqfile) {
        EVP_PKEY *pkey;
        BIO *in;

        if (!sign_flag && !CA_flag) {
            BIO_printf(bio_err, "We need a private key to sign with\n");
            goto end;
        }
        in = bio_open_default(infile, "r");
        if (in == NULL)
            goto end;
        req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
        BIO_free(in);

        if (req == NULL) {
            ERR_print_errors(bio_err);
            goto end;
        }

        if ((req->req_info == NULL) ||
            (req->req_info->pubkey == NULL) ||
            (req->req_info->pubkey->public_key == NULL) ||
            (req->req_info->pubkey->public_key->data == NULL)) {
            BIO_printf(bio_err,
                       "The certificate request appears to corrupted\n");
            BIO_printf(bio_err, "It does not contain a public key\n");
            goto end;
        }
        if ((pkey = X509_REQ_get_pubkey(req)) == NULL) {
            BIO_printf(bio_err, "error unpacking public key\n");
            goto end;
        }
        i = X509_REQ_verify(req, pkey);
        EVP_PKEY_free(pkey);
        if (i < 0) {
            BIO_printf(bio_err, "Signature verification error\n");
            ERR_print_errors(bio_err);
            goto end;
        }
        if (i == 0) {
            BIO_printf(bio_err,
                       "Signature did not match the certificate request\n");
            goto end;
        } else
            BIO_printf(bio_err, "Signature ok\n");

        print_name(bio_err, "subject=", X509_REQ_get_subject_name(req),
                   nmflag);

        if ((x = X509_new()) == NULL)
            goto end;

        if (sno == NULL) {
            sno = ASN1_INTEGER_new();
            if (!sno || !rand_serial(NULL, sno))
                goto end;
            if (!X509_set_serialNumber(x, sno))
                goto end;
            ASN1_INTEGER_free(sno);
            sno = NULL;
        } else if (!X509_set_serialNumber(x, sno))
            goto end;

        if (!X509_set_issuer_name(x, req->req_info->subject))
            goto end;
        if (!X509_set_subject_name(x, req->req_info->subject))
            goto end;

        X509_gmtime_adj(X509_get_notBefore(x), 0);
        X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL);
        if (fkey)
            X509_set_pubkey(x, fkey);
        else {
            pkey = X509_REQ_get_pubkey(req);
            X509_set_pubkey(x, pkey);
            EVP_PKEY_free(pkey);
        }
    } else
        x = load_cert(infile, informat, NULL, e, "Certificate");

    if (x == NULL)
        goto end;
    if (CA_flag) {
        xca = load_cert(CAfile, CAformat, NULL, e, "CA Certificate");
        if (xca == NULL)
            goto end;
    }

    if (!noout || text || next_serial) {
        OBJ_create("2.99999.3", "SET.ex3", "SET x509v3 extension 3");

    }

    if (alias)
        X509_alias_set1(x, (unsigned char *)alias, -1);

    if (clrtrust)
        X509_trust_clear(x);
    if (clrreject)
        X509_reject_clear(x);

    if (trust) {
        for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) {
            objtmp = sk_ASN1_OBJECT_value(trust, i);
            X509_add1_trust_object(x, objtmp);
        }
    }

    if (reject) {
        for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) {
            objtmp = sk_ASN1_OBJECT_value(reject, i);
            X509_add1_reject_object(x, objtmp);
        }
    }

    if (num) {
        for (i = 1; i <= num; i++) {
            if (issuer == i) {
                print_name(out, "issuer= ", X509_get_issuer_name(x), nmflag);
            } else if (subject == i) {
                print_name(out, "subject= ",
                           X509_get_subject_name(x), nmflag);
            } else if (serial == i) {
                BIO_printf(out, "serial=");
                i2a_ASN1_INTEGER(out, X509_get_serialNumber(x));
                BIO_printf(out, "\n");
            } else if (next_serial == i) {
                BIGNUM *bnser;
                ASN1_INTEGER *ser;
                ser = X509_get_serialNumber(x);
                bnser = ASN1_INTEGER_to_BN(ser, NULL);
                if (!bnser)
                    goto end;
                if (!BN_add_word(bnser, 1))
                    goto end;
                ser = BN_to_ASN1_INTEGER(bnser, NULL);
                if (!ser)
                    goto end;
                BN_free(bnser);
                i2a_ASN1_INTEGER(out, ser);
                ASN1_INTEGER_free(ser);
                BIO_puts(out, "\n");
            } else if ((email == i) || (ocsp_uri == i)) {
                int j;
                STACK_OF(OPENSSL_STRING) *emlst;
                if (email == i)
                    emlst = X509_get1_email(x);
                else
                    emlst = X509_get1_ocsp(x);
                for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
                    BIO_printf(out, "%s\n",
                               sk_OPENSSL_STRING_value(emlst, j));
                X509_email_free(emlst);
            } else if (aliasout == i) {
                unsigned char *alstr;
                alstr = X509_alias_get0(x, NULL);
                if (alstr)
                    BIO_printf(out, "%s\n", alstr);
                else
                    BIO_puts(out, "<No Alias>\n");
            } else if (subject_hash == i) {
                BIO_printf(out, "%08lx\n", X509_subject_name_hash(x));
            }
#ifndef OPENSSL_NO_MD5
            else if (subject_hash_old == i) {
                BIO_printf(out, "%08lx\n", X509_subject_name_hash_old(x));
            }
#endif
            else if (issuer_hash == i) {
                BIO_printf(out, "%08lx\n", X509_issuer_name_hash(x));
            }
#ifndef OPENSSL_NO_MD5
            else if (issuer_hash_old == i) {
                BIO_printf(out, "%08lx\n", X509_issuer_name_hash_old(x));
            }
#endif
            else if (pprint == i) {
                X509_PURPOSE *ptmp;
                int j;
                BIO_printf(out, "Certificate purposes:\n");
                for (j = 0; j < X509_PURPOSE_get_count(); j++) {
                    ptmp = X509_PURPOSE_get0(j);
                    purpose_print(out, x, ptmp);
                }
            } else if (modulus == i) {
                EVP_PKEY *pkey;

                pkey = X509_get_pubkey(x);
                if (pkey == NULL) {
                    BIO_printf(bio_err, "Modulus=unavailable\n");
                    ERR_print_errors(bio_err);
                    goto end;
                }
                BIO_printf(out, "Modulus=");
#ifndef OPENSSL_NO_RSA
                if (pkey->type == EVP_PKEY_RSA)
                    BN_print(out, pkey->pkey.rsa->n);
                else
#endif
#ifndef OPENSSL_NO_DSA
                if (pkey->type == EVP_PKEY_DSA)
                    BN_print(out, pkey->pkey.dsa->pub_key);
                else
#endif
                    BIO_printf(out, "Wrong Algorithm type");
                BIO_printf(out, "\n");
                EVP_PKEY_free(pkey);
            } else if (pubkey == i) {
                EVP_PKEY *pkey;

                pkey = X509_get_pubkey(x);
                if (pkey == NULL) {
                    BIO_printf(bio_err, "Error getting public key\n");
                    ERR_print_errors(bio_err);
                    goto end;
                }
                PEM_write_bio_PUBKEY(out, pkey);
                EVP_PKEY_free(pkey);
            } else if (C == i) {
                unsigned char *d;
                char *m;
                int len;

                X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof buf);
                BIO_printf(out, "/*\n"
                                " * Subject: %s\n", buf);

                m = X509_NAME_oneline(X509_get_issuer_name(x), buf, sizeof buf);
                BIO_printf(out, " * Issuer:  %s\n"
                                " */\n", buf);

                len = i2d_X509(x, NULL);
                m = app_malloc(len, "x509 name buffer");
                d = (unsigned char *)m;
                len = i2d_X509_NAME(X509_get_subject_name(x), &d);
                print_array(out, "the_subject_name", len, (unsigned char *)m);
                d = (unsigned char *)m;
                len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d);
                print_array(out, "the_public_key", len, (unsigned char *)m);
                d = (unsigned char *)m;
                len = i2d_X509(x, &d);
                print_array(out, "the_certificate", len, (unsigned char *)m);
                OPENSSL_free(m);
            } else if (text == i) {
                X509_print_ex(out, x, nmflag, certflag);
            } else if (startdate == i) {
                BIO_puts(out, "notBefore=");
                ASN1_TIME_print(out, X509_get_notBefore(x));
                BIO_puts(out, "\n");
            } else if (enddate == i) {
                BIO_puts(out, "notAfter=");
                ASN1_TIME_print(out, X509_get_notAfter(x));
                BIO_puts(out, "\n");
            } else if (fingerprint == i) {
                int j;
                unsigned int n;
                unsigned char md[EVP_MAX_MD_SIZE];
                const EVP_MD *fdig = digest;

                if (!fdig)
                    fdig = EVP_sha1();

                if (!X509_digest(x, fdig, md, &n)) {
                    BIO_printf(bio_err, "out of memory\n");
                    goto end;
                }
                BIO_printf(out, "%s Fingerprint=",
                           OBJ_nid2sn(EVP_MD_type(fdig)));
                for (j = 0; j < (int)n; j++) {
                    BIO_printf(out, "%02X%c", md[j], (j + 1 == (int)n)
                               ? '\n' : ':');
                }
            }

            /* should be in the library */
            else if ((sign_flag == i) && (x509req == 0)) {
                BIO_printf(bio_err, "Getting Private key\n");
                if (Upkey == NULL) {
                    Upkey = load_key(keyfile, keyformat, 0,
                                     passin, e, "Private key");
                    if (Upkey == NULL)
                        goto end;
                }

                assert(need_rand);
                if (!sign(x, Upkey, days, clrext, digest, extconf, extsect))
                    goto end;
            } else if (CA_flag == i) {
                BIO_printf(bio_err, "Getting CA Private Key\n");
                if (CAkeyfile != NULL) {
                    CApkey = load_key(CAkeyfile, CAkeyformat,
                                      0, passin, e, "CA Private Key");
                    if (CApkey == NULL)
                        goto end;
                }

                assert(need_rand);
                if (!x509_certify(ctx, CAfile, digest, x, xca,
                                  CApkey, sigopts,
                                  CAserial, CA_createserial, days, clrext,
                                  extconf, extsect, sno, reqfile))
                    goto end;
            } else if (x509req == i) {
                EVP_PKEY *pk;

                BIO_printf(bio_err, "Getting request Private Key\n");
                if (keyfile == NULL) {
                    BIO_printf(bio_err, "no request key file specified\n");
                    goto end;
                } else {
                    pk = load_key(keyfile, keyformat, 0,
                                  passin, e, "request key");
                    if (pk == NULL)
                        goto end;
                }

                BIO_printf(bio_err, "Generating certificate request\n");

                rq = X509_to_X509_REQ(x, pk, digest);
                EVP_PKEY_free(pk);
                if (rq == NULL) {
                    ERR_print_errors(bio_err);
                    goto end;
                }
                if (!noout) {
                    X509_REQ_print(out, rq);
                    PEM_write_bio_X509_REQ(out, rq);
                }
                noout = 1;
            } else if (ocspid == i) {
                X509_ocspid_print(out, x);
            }
        }
    }

    if (checkend) {
        time_t tcheck = time(NULL) + checkoffset;

        if (X509_cmp_time(X509_get_notAfter(x), &tcheck) < 0) {
            BIO_printf(out, "Certificate will expire\n");
            ret = 1;
        } else {
            BIO_printf(out, "Certificate will not expire\n");
            ret = 0;
        }
        goto end;
    }

    print_cert_checks(out, x, checkhost, checkemail, checkip);

    if (noout || nocert) {
        ret = 0;
        goto end;
    }

    if (badsig)
        x->signature->data[x->signature->length - 1] ^= 0x1;

    if (outformat == FORMAT_ASN1)
        i = i2d_X509_bio(out, x);
    else if (outformat == FORMAT_PEM) {
        if (trustout)
            i = PEM_write_bio_X509_AUX(out, x);
        else
            i = PEM_write_bio_X509(out, x);
    } else if (outformat == FORMAT_NETSCAPE) {
        NETSCAPE_X509 nx;
        ASN1_OCTET_STRING hdr;

        hdr.data = (unsigned char *)NETSCAPE_CERT_HDR;
        hdr.length = strlen(NETSCAPE_CERT_HDR);
        nx.header = &hdr;
        nx.cert = x;

        i = ASN1_item_i2d_bio(ASN1_ITEM_rptr(NETSCAPE_X509), out, &nx);
    } else {
        BIO_printf(bio_err, "bad output format specified for outfile\n");
        goto end;
    }
    if (!i) {
        BIO_printf(bio_err, "unable to write certificate\n");
        ERR_print_errors(bio_err);
        goto end;
    }
    ret = 0;
 end:
    if (need_rand)
        app_RAND_write_file(NULL);
    OBJ_cleanup();
    NCONF_free(extconf);
    BIO_free_all(out);
    X509_STORE_free(ctx);
    X509_REQ_free(req);
    X509_free(x);
    X509_free(xca);
    EVP_PKEY_free(Upkey);
    EVP_PKEY_free(CApkey);
    EVP_PKEY_free(fkey);
    sk_OPENSSL_STRING_free(sigopts);
    X509_REQ_free(rq);
    ASN1_INTEGER_free(sno);
    sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free);
    sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free);
    OPENSSL_free(passin);
    return (ret);
}
// reads the request req_filename and creates a modified creq_filename with the commitment extension added
void writeCommitmentCSR(BIGNUM *commitment_c, char *privkey_filename, char *req_filename, char *creq_filename) {
	FILE *fp;

	/* read in the request */
	X509_REQ *req;
	if (!(fp = fopen(req_filename, "r")))
		critical_error("Error reading request file");
	if (!(req = PEM_read_X509_REQ(fp, NULL, NULL, NULL)))
		critical_error("Error reading request in file");
	fclose(fp);

	/*  read in the private key */
	EVP_PKEY *pkey;
	if (!(fp = fopen(privkey_filename, "r")))
		critical_error("Error reading private key file");
	if (!(pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL)))
		critical_error("Error reading private key in file");
	fclose(fp);

	/* create the new request */
	X509_REQ *creq;
	if (!(creq = X509_REQ_new()))
		critical_error("Failed to create X509_REQ object");

	X509_REQ_set_pubkey(creq, pkey);

	// gets subj from initial requests and adds it to new one
	X509_NAME *subj = X509_REQ_get_subject_name(req);
	if (X509_REQ_set_subject_name(creq, subj) != 1)
			critical_error("Error adding subject to request");

	// enable the commitment extension handling (retrieve/print as string)
	int nid = _commitmentExt_start();

	// get extensions stack of original request
	STACK_OF(X509_EXTENSION) *extlist = X509_REQ_get_extensions(req);

	// if no extensions, create new stack
	if (extlist==NULL) {
		extlist = sk_X509_EXTENSION_new_null();
	} else { // else check that the extension isn't already there (error!)
		X509_EXTENSION *tmp = (X509_EXTENSION*) X509V3_get_d2i(extlist, nid, NULL, NULL);
		if (tmp!=NULL)
			critical_error("Aborting process: CSR already contains commitment extension!\n");		
	}

	// create commitment extension storing C value as a hex string
	X509_EXTENSION *exCommitment = (X509_EXTENSION*) X509V3_EXT_conf_nid(NULL, NULL, nid, BN_bn2hex(commitment_c));
	if (!exCommitment)
		critical_error("error creating commitment extension");

	// push commitment extension into stack
	sk_X509_EXTENSION_push(extlist, exCommitment);

	// assign extensions to the new request
	if (!X509_REQ_add_extensions(creq, extlist))
		critical_error("Error adding extensions to the request");

	sk_X509_EXTENSION_pop_free(extlist, X509_EXTENSION_free);
	/////////////////////////////////////////////////////////////////////

	/* pick the correct digest and sign the new request */
	EVP_MD *digest;
	if (EVP_PKEY_type(pkey->type) == EVP_PKEY_DSA)
		digest = (EVP_MD*) EVP_dss1();
	else if (EVP_PKEY_type(pkey->type) == EVP_PKEY_RSA)
		digest = (EVP_MD*) EVP_sha1();
	else
		critical_error("Error checking public key for a valid digest");

	if (!(X509_REQ_sign(creq, pkey, digest)))
		critical_error("Error signing request");

	/* write the modified request */
	if (!(fp = fopen(creq_filename, "w")))
		critical_error("Error writing to request file");
	if (PEM_write_X509_REQ(fp, creq) != 1)
		critical_error("Error while writing request");
	fclose(fp);

	// cleanup
	_commitmentExt_end();
	EVP_PKEY_free(pkey);
	X509_REQ_free(req);
	X509_REQ_free(creq);
}
Beispiel #20
0
int generate_csr(char** pem_csr) {
	FILE* fp;
	RSA * rsa_priv_key;
	int ret = 0;
	int nVersion = 0;
	int keylen = 0;

	X509_REQ *x509_req = NULL;
	X509_NAME *x509_name = NULL;
	EVP_PKEY *pKey = NULL;
	BIO *bio = NULL;

	// 2. set version of x509 req
	x509_req = X509_REQ_new();
	ret = X509_REQ_set_version(x509_req, nVersion);
	if (ret != 1) {
		goto free_all;
	}

	// 3. set subject of x509 req
	x509_name = X509_REQ_get_subject_name(x509_req);

	ret = X509_NAME_add_entry_by_txt(x509_name, "C", V_ASN1_PRINTABLESTRING,
			(const unsigned char*) szCountry, -1, -1, 0);
	if (ret != 1) {
		goto free_all;
	}

	ret = X509_NAME_add_entry_by_txt(x509_name, "ST", V_ASN1_PRINTABLESTRING,
			(const unsigned char*) szProvince, -1, -1, 0);
	if (ret != 1) {
		goto free_all;
	}

	ret = X509_NAME_add_entry_by_txt(x509_name, "L", V_ASN1_PRINTABLESTRING,
			(const unsigned char*) szCity, -1, -1, 0);
	if (ret != 1) {
		goto free_all;
	}

	ret = X509_NAME_add_entry_by_txt(x509_name, "O", V_ASN1_PRINTABLESTRING,
			(const unsigned char*) api_company, -1, -1, 0);
	if (ret != 1) {
		goto free_all;
	}

	ret = X509_NAME_add_entry_by_txt(x509_name, "OU", V_ASN1_PRINTABLESTRING,
			(const unsigned char*) szOrganization, -1, -1, 0);
	if (ret != 1) {
		goto free_all;
	}

	ret = X509_NAME_add_entry_by_txt(x509_name, "CN", V_ASN1_PRINTABLESTRING,
			(const unsigned char*) szCommon, -1, -1, 0);
	if (ret != 1) {
		goto free_all;
	}

	ret = X509_NAME_add_entry_by_txt(x509_name, "emailAddress", V_ASN1_IA5STRING,
			(const unsigned char*) szEmail, -1, -1, 0);
	if (ret != 1) {
		goto free_all;
	}

	ret = X509_NAME_add_entry_by_txt(x509_name, "challengePassword", V_ASN1_PRINTABLESTRING,
			(const unsigned char*) szChallengePassword, -1, -1, 0);
	if (ret != 1) {
		goto free_all;
	}

	// 4. set public key of x509 req
	if (load_rsa_pkey(&rsa_priv_key) < 0)
		goto free_all;

	pKey = EVP_PKEY_new();
	EVP_PKEY_assign_RSA(pKey, rsa_priv_key);

	ret = X509_REQ_set_pubkey(x509_req, pKey);
	if (ret != 1) {
		goto free_all;
	}

	// 5. set sign key of x509 req
	ret = X509_REQ_sign(x509_req, pKey, EVP_sha1()); // return x509_req->signature->length
	if (ret <= 0) {
		goto free_all;
	}

	/* To get the C-string PEM form: */
	bio = BIO_new(BIO_s_mem());
	PEM_write_bio_X509_REQ(bio, x509_req);
	keylen = BIO_pending(bio);
	*pem_csr = malloc(keylen + 1); /* Null-terminate */

	BIO_read(bio, *pem_csr, keylen);

	/* Write to file */
	fp = fopen(f_csr, "w");
	if (fp) {
		fwrite(*pem_csr, keylen, 1, fp);
		fclose(fp);
	}

	LOG(VERBOSE, "[API] CSR created:%s", *pem_csr);
	// 6. free
	free_all: X509_REQ_free(x509_req);
	BIO_free_all(bio);
	return (keylen);
}
Beispiel #21
0
TokenError _backend_createRequest(const RegutilInfo *info,
                                  const char *hostname,
                                  const char *password,
                                  char **request, size_t *reqlen) {
    // OpenSSL seeds the PRNG automatically, see the manual page for RAND_add.
    if (!RAND_status()) {
        fprintf(stderr, BINNAME ": no random state!\n");
        return TokenError_NoRandomState;
    }
    
    // Abort if there are no requests
    *request = NULL;
    if (!info->pkcs10) return TokenError_Unknown;
    
    // Create certificate requests
    bool ok = true;
    CertReq *reqs = NULL;
    STACK *x509reqs = sk_new_null();
    for (const RegutilPKCS10 *pkcs10 = info->pkcs10; pkcs10 != NULL;
         pkcs10 = pkcs10->next) {
        
        RSA *rsa = NULL;
        EVP_PKEY *privkey = NULL;
        X509_NAME *subject = NULL;
        X509_REQ *x509req = NULL;
        STACK_OF(X509_EXTENSION) *exts = NULL;
        
        // Check the parameters.
        // Maximum key size in OpenSSL:
        // http://www.mail-archive.com/[email protected]/msg58229.html
        if (!pkcs10->subjectDN || pkcs10->keySize < 1024 ||
            pkcs10->keySize > 16384)
            goto req_error;
        
        // Generate key pair
        // FIXME deprecated function
        // TODO use OPENSSL_NO_DEPRECATED
        rsa = RSA_generate_key(pkcs10->keySize, RSA_F4, NULL, NULL);
        if (!rsa) goto req_error;
        privkey = EVP_PKEY_new();
        if (!privkey) goto req_error;
        EVP_PKEY_assign_RSA(privkey, rsa);
        
        // Subject name
        subject = certutil_parse_dn(pkcs10->subjectDN, pkcs10->includeFullDN);
        if (!subject) goto req_error;
        
        // Create request
        x509req = X509_REQ_new();
        if (!x509req ||
            !X509_REQ_set_version(x509req, 0) ||
            !X509_REQ_set_subject_name(x509req, subject) ||
            !X509_REQ_set_pubkey(x509req, privkey)) { // yes this is correct(!)
            
            certutil_updateErrorString();
            goto req_error;
        }
        
        // Set attributes
        exts = sk_X509_EXTENSION_new_null();
        if (!exts) goto req_error;
        
        X509_EXTENSION *ext = makeKeyUsageExt(pkcs10->keyUsage);
        if (!ext || !sk_X509_EXTENSION_push(exts, ext))
            goto req_error;
        
        if (!X509_REQ_add_extensions(x509req, exts)) {
            certutil_updateErrorString();
            goto req_error;
        }
        exts = NULL;
        
        // Add signature
        if (!X509_REQ_sign(x509req, privkey, EVP_sha1())) {
            certutil_updateErrorString();
            goto req_error;
        }
        
        // Store in list
        CertReq *req = malloc(sizeof(CertReq));
        req->pkcs10 = pkcs10;
        req->privkey = privkey;
        req->rsa = rsa;
        req->x509 = x509req;
        req->next = reqs;
        reqs = req;
        
        sk_push(x509reqs, (char*)x509req);
        
        continue;
        
      req_error:
        // Clean up and set error flag
        if (privkey) EVP_PKEY_free(privkey);
        else if (rsa) RSA_free(rsa);
        
        X509_NAME_free(subject);
        sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
        X509_REQ_free(x509req);
        
        ok = false;
    }
    
    TokenError error = TokenError_Unknown;
    
    if (ok) {
        // Determine filename from certificate name
        char *filename = certutil_makeFilename(X509_REQ_get_subject_name(reqs->x509));
        
        // Build the certificate request
        request_wrap(x509reqs, request, reqlen);
        
        if (*request && filename) {
            // Create the key file in ~/cbt/name.p12
            FILE *keyfile = platform_openLocked(filename, Platform_OpenCreate);
            if (!keyfile) {
                error = TokenError_CantCreateFile;
            } else {
                error = saveKeys(reqs, hostname, password, keyfile);
                if (!platform_closeLocked(keyfile) && !error)
                    error = TokenError_CantCreateFile;
            }
            
        }
        
        if (filename) free(filename);
        if (error && *request) free(*request);
    }
    
    // Free reqs
    while (reqs) {
        RSA_free(reqs->rsa); // This free's privkey too
        X509_REQ_free(reqs->x509);
        
        CertReq *next = reqs->next;
        free(reqs);
        reqs = next;
    }
    sk_free(x509reqs);
    
    return error;
}
Beispiel #22
0
/* Creates an X509 certificate from a certificate request. */
EXPORT int IssueUserCertificate(unsigned char *certbuf, int *certlen, unsigned char *reqbuf, int reqlen)
{
	X509_REQ *req = NULL;
	EVP_PKEY *cakey = NULL, *rakey = NULL, *usrkey = NULL;
	X509 *cacert = NULL, *racert = NULL, *usrcert = NULL;
	X509_NAME *subject = NULL, *issuer = NULL;
	unsigned char *p = NULL;
	int ret = OPENSSLCA_NO_ERR, len;

	if (certbuf == NULL || certlen == NULL || reqbuf == NULL || reqlen == 0)
		return OPENSSLCA_ERR_ARGS;

	/* Decode request */
	if ((req = X509_REQ_new()) == NULL) {
		ret = OPENSSLCA_ERR_REQ_NEW;
		goto err;
	}
	p = reqbuf;
	if (d2i_X509_REQ(&req, &p, reqlen) == NULL) {
		ret = OPENSSLCA_ERR_REQ_DECODE;
		goto err;
	}

	/* Get public key from request */
	if ((usrkey = X509_REQ_get_pubkey(req)) == NULL) {
		ret = OPENSSLCA_ERR_REQ_GET_PUBKEY;
		goto err;
	}

	if (caIni.verifyRequests) {
		/* Get RA's public key */
		/* TODO: Validate RA certificate */
		ret = read_cert(&racert, CA_PATH(caIni.raCertFile));
		if (ret != OPENSSLCA_NO_ERR)
			goto err;
		if ((rakey = X509_get_pubkey(racert)) == NULL) {
			ret = OPENSSLCA_ERR_CERT_GET_PUBKEY;
			goto err;
		}

		/* Verify signature on request */
		if (X509_REQ_verify(req, rakey) != 1) {
			ret = OPENSSLCA_ERR_REQ_VERIFY;
			goto err;
		}
	}

	/* Get CA certificate */
	/* TODO: Validate CA certificate */
	ret = read_cert(&cacert, CA_PATH(caIni.caCertFile));
	if (ret != OPENSSLCA_NO_ERR)
		goto err;

	/* Get CA private key */
	ret = read_key(&cakey, CA_PATH(caIni.caKeyFile), caIni.caKeyPasswd);
	if (ret != OPENSSLCA_NO_ERR)
		goto err;

	/* Create user certificate */
	if ((usrcert = X509_new()) == NULL)
		return OPENSSLCA_ERR_CERT_NEW;

	/* Set version and serial number for certificate */
	if (X509_set_version(usrcert, 2) != 1) { /* V3 */
		ret = OPENSSLCA_ERR_CERT_SET_VERSION;
		goto err;
	}
	if (ASN1_INTEGER_set(X509_get_serialNumber(usrcert), get_serial()) != 1) {
		ret = OPENSSLCA_ERR_CERT_SET_SERIAL;
		goto err;
	}

	/* Set duration for certificate */
	if (X509_gmtime_adj(X509_get_notBefore(usrcert), 0) == NULL) {
		ret = OPENSSLCA_ERR_CERT_SET_NOTBEFORE;
		goto err;
	}
	if (X509_gmtime_adj(X509_get_notAfter(usrcert), EXPIRE_SECS(caIni.daysTillExpire)) == NULL) {
		ret = OPENSSLCA_ERR_CERT_SET_NOTAFTER;
		goto err;
	}

	/* Set public key */
	if (X509_set_pubkey(usrcert, usrkey) != 1) {
		ret = OPENSSLCA_ERR_CERT_SET_PUBKEY;
		goto err;
	}

	/* Set subject name */
	subject = X509_REQ_get_subject_name(req);
	if (subject == NULL) {
		ret = OPENSSLCA_ERR_REQ_GET_SUBJECT;
		goto err;
	}
	if (X509_set_subject_name(usrcert, subject) != 1) {
		ret = OPENSSLCA_ERR_CERT_SET_SUBJECT;
		goto err;
	}

	/* Set issuer name */
	issuer = X509_get_issuer_name(cacert);
	if (issuer == NULL) {
		ret = OPENSSLCA_ERR_CERT_GET_ISSUER;
		goto err;
	}
	if (X509_set_issuer_name(usrcert, issuer) != 1) {
		ret = OPENSSLCA_ERR_CERT_SET_ISSUER;
		goto err;
	}

	/* Add extensions */
	ret = add_ext(cacert, usrcert);
	if (ret != OPENSSLCA_NO_ERR)
		goto err;

	/* Sign user certificate with CA's private key */
	if (!X509_sign(usrcert, cakey, EVP_sha1()))
		return OPENSSLCA_ERR_CERT_SIGN;

	if (caIni.verifyAfterSign) {
		if (X509_verify(usrcert, cakey) != 1) {
			ret = OPENSSLCA_ERR_CERT_VERIFY;
			goto err;
		}
	}

#ifdef _DEBUG /* Output certificate in DER and PEM format */
	{
		FILE *fp = fopen(DBG_PATH("usrcert.der"), "wb");
		if (fp != NULL) {
			i2d_X509_fp(fp, usrcert);
			fclose(fp);
		}
		fp = fopen(DBG_PATH("usrcert.pem"), "w");
		if (fp != NULL) {
			X509_print_fp(fp, usrcert);
			PEM_write_X509(fp, usrcert);
			fclose(fp);
		}
	}
#endif

	/* Encode user certificate into DER format */
	len = i2d_X509(usrcert, NULL);
	if (len < 0) {
		ret = OPENSSLCA_ERR_CERT_ENCODE;
		goto err;
	}
	if (len > *certlen) {
		ret = OPENSSLCA_ERR_BUF_TOO_SMALL;
		goto err;
	}
	*certlen = len;
	p = certbuf;
	i2d_X509(usrcert, &p);

	if (caIni.addToIndex)
		add_to_index(usrcert);

	if (caIni.addToNewCerts)
		write_cert(usrcert);

err:
	print_err("IssueUserCertificate()", ret);

	/* Clean up */
	if (cacert)
		X509_free(cacert);
	if (cakey)
		EVP_PKEY_free(cakey);
	if (racert)
		X509_free(racert);
	if (rakey)
		EVP_PKEY_free(rakey);
	if (req)
		X509_REQ_free(req);
	if (usrcert != NULL)
		X509_free(usrcert);
	if (usrkey)
		EVP_PKEY_free(usrkey);

	return ret;
}
Beispiel #23
0
wi_x509_t * wi_x509_init_with_common_name(wi_x509_t *x509, wi_rsa_t *rsa, wi_string_t *common_name) {
	X509_REQ		*req;
	EVP_PKEY		*pkey = NULL;
	X509_NAME		*name = NULL;
	BIGNUM			*bn = NULL;
	
	req = X509_REQ_new();
	
	if(!req)
		goto err;

	if(X509_REQ_set_version(req, 0) != 1)
		goto err;
	
	name = X509_NAME_new();
	
	if(X509_NAME_add_entry_by_NID(name,
								  NID_commonName,
								  MBSTRING_ASC,
								  (unsigned char *) wi_string_cstring(common_name),
								  -1,
								  -1,
								  0) != 1)
		goto err;

	if(X509_REQ_set_subject_name(req, name) != 1)
		goto err;

	pkey = EVP_PKEY_new();
	EVP_PKEY_set1_RSA(pkey, wi_rsa_rsa(rsa));
	
	if(X509_REQ_set_pubkey(req, pkey) != 1)
		goto err;
	
	x509->x509 = X509_new();
	
	if(!x509->x509)
		goto err;
	
	bn = BN_new();
	
	if(!bn)
		goto err;
	
	if(BN_pseudo_rand(bn, 64, 0, 0) != 1)
		goto err;
	
	if(!BN_to_ASN1_INTEGER(bn, X509_get_serialNumber(x509->x509)))
		goto err;
	
	if(X509_set_issuer_name(x509->x509, X509_REQ_get_subject_name(req)) != 1)
		goto err;

	if(!X509_gmtime_adj(X509_get_notBefore(x509->x509), 0))
		goto err;

	if(!X509_gmtime_adj(X509_get_notAfter(x509->x509), 3600 * 24 * 365))
		goto err;

	if(X509_set_subject_name(x509->x509, X509_REQ_get_subject_name(req)) != 1)
		goto end;

	if(X509_set_pubkey(x509->x509, pkey) != 1)
		goto err;
	
	if(X509_sign(x509->x509, pkey, EVP_sha1()) == 0)
		goto err;
	
	goto end;
	
err:
	wi_error_set_openssl_error();

	wi_release(x509);

	x509 = NULL;
	
end:
	if(req)
		X509_REQ_free(req);
	
	if(pkey)
		EVP_PKEY_free(pkey);
	
	if(name)
		X509_NAME_free(name);

	if(bn)
		BN_free(bn);
	
	return x509;
}
Beispiel #24
0
int
main(int argc, char **argv) {
	//ENGINE *e = NULL;
	int			c, host_port = 80, count = 1;
	char			*host_name, *p, *dir_name = NULL;
	char			http_string[16384];
	struct http_reply	reply;
	unsigned int		n;
	unsigned char		md[EVP_MAX_MD_SIZE];
	struct scep		scep_t;
	FILE			*fp = NULL;
	BIO			*bp;
	STACK_OF(X509)		*nextcara = NULL;
	X509 				*cert=NULL;
	PKCS7 p7;
	int i;
	int required_option_space;
	


#ifdef WIN32
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
	//printf("Starting sscep\n");
	//fprintf(stdout, "%s: starting sscep on WIN32, sscep version %s\n",	pname, VERSION);
       
	wVersionRequested = MAKEWORD( 2, 2 );
 
	err = WSAStartup( wVersionRequested, &wsaData );
	if ( err != 0 )
	{
	  /* Tell the user that we could not find a usable */
	  /* WinSock DLL.                                  */
	  return;
	}
 
	/* Confirm that the WinSock DLL supports 2.2.*/
	/* Note that if the DLL supports versions greater    */
	/* than 2.2 in addition to 2.2, it will still return */
	/* 2.2 in wVersion since that is the version we      */
	/* requested.                                        */
 
	if ( LOBYTE( wsaData.wVersion ) != 2 ||
	        HIBYTE( wsaData.wVersion ) != 2 )
	{
	    /* Tell the user that we could not find a usable */
	    /* WinSock DLL.                                  */
	    WSACleanup( );
	    return; 
	}

#endif
	/* Initialize scep layer */
	init_scep();

	/* Set program name */
	pname = argv[0];

	/* Set timeout */
	timeout = TIMEOUT;


	/* Check operation parameter */
	if (!argv[1]) {
		usage();
	} else if (!strncmp(argv[1], "getca", 5)) {
		operation_flag = SCEP_OPERATION_GETCA;
	} else if (!strncmp(argv[1], "enroll", 6)) {
		operation_flag = SCEP_OPERATION_ENROLL;
	} else if (!strncmp(argv[1], "getcert", 7)) {
		operation_flag = SCEP_OPERATION_GETCERT;
	} else if (!strncmp(argv[1], "getcrl", 6)) {
		operation_flag = SCEP_OPERATION_GETCRL;
	} else if (!strncmp(argv[1], "getnextca", 9)) {
		operation_flag = SCEP_OPERATION_GETNEXTCA;
	} else {
		fprintf(stderr, "%s: missing or illegal operation parameter\n",
				argv[0]);
		usage();
	}
	/* Skip first parameter and parse the rest of the command */
	optind++;
	while ((c = getopt(argc, argv, "c:C:de:E:f:g:hF:i:k:K:l:L:n:O:p:r:Rs:S:t:T:u:vw:m:HM:")) != -1)
                switch(c) {
			case 'c':
				c_flag = 1;
				c_char = optarg;
				break;
			case 'C':
				C_flag = 1;
				C_char = optarg;
				break;
			case 'd':
				d_flag = 1;
				break;
			case 'e':
				e_flag = 1;
				e_char = optarg;
				break;
			case 'E':
				E_flag = 1;
				E_char = optarg;
				break;
			case 'F':
				F_flag = 1;
				F_char = optarg;
				break;
			case 'f':
				f_flag = 1;
				f_char = optarg;
				break;
			case 'g':
				g_flag = 1;
				g_char = optarg;
				break;
			case 'h'://TODO change to eg. ID --inform=ID
				h_flag = 1;
				break;
			case 'H':
				H_flag = 1;
				break;
			case 'i':
				i_flag = 1;
				i_char = optarg;
				break;
			case 'k':
				k_flag = 1;
				k_char = optarg;
				break;
			case 'K':
				K_flag = 1;
				K_char = optarg;
				break;
			case 'l':
				l_flag = 1;
				l_char = optarg;
				break;
			case 'L':
				L_flag = 1;
				L_char = optarg;
				break;
			case 'm':
				m_flag = 1;
				m_char = optarg;
				break;
			case 'M':
				if(!M_flag) {
					/* if this is the first time the option appears, create a
					 * new string.
					 */
					required_option_space = strlen(optarg) + 1;
					M_char = malloc(required_option_space);
					if(!M_char)
						error_memory();
					strncpy(M_char, optarg, required_option_space);
					// set the flag, so we already have a string
					M_flag = 1;
				} else {
					/* we already have a string, just extend it. */
					// old part + new part + &-sign + null byte
					required_option_space = strlen(M_char) + strlen(optarg) + 2;
					M_char = realloc(M_char, required_option_space);
					if(!M_char)
						error_memory();
					strncat(M_char, "&", 1);
					strncat(M_char, optarg, strlen(optarg));
				}
				break;
			case 'n':
				n_flag = 1;
				n_num = atoi(optarg);
				break;
			case 'O':
				O_flag = 1;
				O_char = optarg;
				break;
			case 'p':
				p_flag = 1;
				p_char = optarg;
				break;
			case 'r':
				r_flag = 1;
				r_char = optarg;
				break;
			case 'R':
				R_flag = 1;
				break;
			case 's':
				s_flag = 1;
				/*s_char = optarg;*/
				s_char = handle_serial(optarg);
				break;
			case 'S':
				S_flag = 1;
				S_char = optarg;
				break;
			case 't':
				t_flag = 1;
				t_num = atoi(optarg);
				break;
			case 'T':
				T_flag = 1;
				T_num = atoi(optarg);
				break;
			case 'u':
				u_flag = 1;
				url_char = optarg;
				break;
			case 'v':
				v_flag = 1;
				break;
			case 'w':
				w_flag = 1;
				w_char = optarg;
				break;
			default:
			  printf("argv: %s\n", argv[optind]);
				usage();
                }
	argc -= optind;
	argv += optind;

	/* If we debug, include verbose messages also */
	if (d_flag)
		v_flag = 1;
	
	if(f_char){
		scep_conf_init(f_char);
	}else{
		scep_conf = NULL;    //moved init to here otherwise compile error on windows
	}
	/* Read in the configuration file: */
	/*if (f_char) {
	#ifdef WIN32
		if ((fopen_s(&fp, f_char, "r")))
	#else
		if (!(fp = fopen(f_char, "r")))
	#endif
			fprintf(stderr, "%s: cannot open %s\n", pname, f_char);
		else {
			init_config(fp);
			(void)fclose(fp);
		}
	}*/
	if (v_flag)
		fprintf(stdout, "%s: starting sscep, version %s\n",
			pname, VERSION);

	/*
	* Create a new SCEP transaction and self-signed
	* certificate based on cert request
	*/
	if (v_flag)
		fprintf(stdout, "%s: new transaction\n", pname);
	new_transaction(&scep_t);

	/*enable Engine Support */
	if (g_flag) {
		scep_t.e = scep_engine_init(scep_t.e);
	}
	
	/*
	 * Check argument logic.
	 */
	if (!c_flag) {
		if (operation_flag == SCEP_OPERATION_GETCA) {
			fprintf(stderr,
			  "%s: missing CA certificate filename (-c)\n", pname);
			exit (SCEP_PKISTATUS_ERROR);
		} else {
			fprintf(stderr,
				"%s: missing CA certificate (-c)\n", pname);
			exit (SCEP_PKISTATUS_ERROR);
		}
		if (operation_flag == SCEP_OPERATION_GETNEXTCA) {
			fprintf(stderr,
			  "%s: missing nextCA certificate target filename (-c)\n", pname);
			exit (SCEP_PKISTATUS_ERROR);
		} else {
			fprintf(stderr,
				"%s: missing nextCA certificate target filename(-c)\n", pname);
			exit (SCEP_PKISTATUS_ERROR);
		}
	}
	if (!C_flag) {
		if (operation_flag == SCEP_OPERATION_GETNEXTCA) {
			fprintf(stderr,
			  "%s: missing nextCA certificate chain filename (-C)\n", pname);
			exit (SCEP_PKISTATUS_ERROR);
		}
	}
	if (operation_flag == SCEP_OPERATION_ENROLL) {
		if (!k_flag) {
			fprintf(stderr, "%s: missing private key (-k)\n",pname);
			exit (SCEP_PKISTATUS_ERROR);
		}
		if (!r_flag) {
			fprintf(stderr, "%s: missing request (-r)\n",pname);
			exit (SCEP_PKISTATUS_ERROR);

		}
		if (!l_flag) {
			fprintf(stderr, "%s: missing local cert (-l)\n",pname);
			exit (SCEP_PKISTATUS_ERROR);
		}
		/* Set polling limits */
		if (!n_flag)
			n_num = MAX_POLL_COUNT;
		if (!t_flag)
			t_num = POLL_TIME;
		if (!T_flag)
			T_num = MAX_POLL_TIME;
	}
	if (operation_flag == SCEP_OPERATION_GETCERT) {
		if (!l_flag) {
			fprintf(stderr, "%s: missing local cert (-l)\n",pname);
			exit (SCEP_PKISTATUS_ERROR);
		}
		if (!s_flag) {
			fprintf(stderr, "%s: missing serial no (-s)\n", pname);
			exit (SCEP_PKISTATUS_ERROR);
		}
		if (!w_flag) {
			fprintf(stderr, "%s: missing cert file (-w)\n",pname);
			exit (SCEP_PKISTATUS_ERROR);
		}
		if (!k_flag) {
			fprintf(stderr, "%s: missing private key (-k)\n",pname);
			exit (SCEP_PKISTATUS_ERROR);
		}
	}
	if (operation_flag == SCEP_OPERATION_GETCRL) {
		if (!l_flag) {
			fprintf(stderr, "%s: missing local cert (-l)\n",pname);
			exit (SCEP_PKISTATUS_ERROR);
		}
		if (!w_flag) {
			fprintf(stderr, "%s: missing crl file (-w)\n",pname);
			exit (SCEP_PKISTATUS_ERROR);
		}
		if (!k_flag) {
			fprintf(stderr, "%s: missing private key (-k)\n",pname);
			exit (SCEP_PKISTATUS_ERROR);
		}
	}

	/* Break down the URL */
	if (!u_flag) {
		fprintf(stderr, "%s: missing URL (-u)\n", pname);
		exit (SCEP_PKISTATUS_ERROR);
	}
	if (strncmp(url_char, "http://", 7) && !p_flag) {
		fprintf(stderr, "%s: illegal URL %s\n", pname, url_char);
		exit (SCEP_PKISTATUS_ERROR);
	}
	if (p_flag) {
		#ifdef WIN32
		host_name = _strdup(p_char);
		#else
		host_name = strdup(p_char);
		#endif
		dir_name = url_char;
	}

	/* Break down the URL */
	if (!u_flag) {
		fprintf(stderr, "%s: missing URL (-u)\n", pname);
		exit (SCEP_PKISTATUS_ERROR);
	}
	if (strncmp(url_char, "http://", 7) && !p_flag) {
		fprintf(stderr, "%s: illegal URL %s\n", pname, url_char);
		exit (SCEP_PKISTATUS_ERROR);
	}
	if (p_flag) {
		#ifdef WIN32
		host_name = _strdup(p_char);
		#else
		host_name = strdup(p_char);
		#endif
		dir_name = url_char;
	}
	#ifdef WIN32
	else if (!(host_name = _strdup(url_char + 7)))
	#else
	else if (!(host_name = strdup(url_char + 7)))
	#endif
		error_memory();
	p = host_name;
	c = 0;
	while (*p != '\0') {
		if (*p == '/' && !p_flag && !c) {
			*p = '\0';
			if (*(p+1)) dir_name = p + 1;
			c = 1;
		}
		if (*p == ':') {
			*p = '\0';
			if (*(p+1)) host_port = atoi(p+1);
		}
		p++;
	}
	if (!dir_name) {
		fprintf(stderr, "%s: illegal URL %s\n", pname, url_char);
		exit (SCEP_PKISTATUS_ERROR);
	}
	if (host_port < 1 || host_port > 65550) {
		fprintf(stderr, "%s: illegal port number %d\n", pname,
				host_port);
		exit (SCEP_PKISTATUS_ERROR);
	}
	if (v_flag) {
		fprintf(stdout, "%s: hostname: %s\n", pname, host_name);
		fprintf(stdout, "%s: directory: %s\n", pname, dir_name);
		fprintf(stdout, "%s: port: %d\n", pname, host_port);
	}

	/* Check algorithms */
	if (!E_flag) {
		enc_alg = (EVP_CIPHER *)EVP_des_cbc();
	} else if (!strncmp(E_char, "blowfish", 8)) {
		enc_alg = (EVP_CIPHER *)EVP_bf_cbc();
	} else if (!strncmp(E_char, "des", 3)) {
		enc_alg = (EVP_CIPHER *)EVP_des_cbc();
	} else if (!strncmp(E_char, "3des", 4)) {
		enc_alg = (EVP_CIPHER *)EVP_des_ede3_cbc();
	} else if (!strncmp(E_char, "aes", 3)) {
		enc_alg = (EVP_CIPHER *)EVP_aes_256_cbc();
	} else {
		fprintf(stderr, "%s: unsupported algorithm: %s\n",
			pname, E_char);
		exit (SCEP_PKISTATUS_ERROR);
	}
	if (!S_flag) {
		sig_alg = (EVP_MD *)EVP_md5();
	} else if (!strncmp(S_char, "md5", 3)) {
		sig_alg = (EVP_MD *)EVP_md5();
	} else if (!strncmp(S_char, "sha1", 4)) {
		sig_alg = (EVP_MD *)EVP_sha1();
	} else {
		fprintf(stderr, "%s: unsupported algorithm: %s\n",
			pname, S_char);
		exit (SCEP_PKISTATUS_ERROR);
	}
	/* Fingerprint algorithm */
	if (!F_flag) {
		fp_alg = (EVP_MD *)EVP_md5();
	} else if (!strncmp(F_char, "md5", 3)) {
		fp_alg = (EVP_MD *)EVP_md5();
	} else if (!strncmp(F_char, "sha1", 4)) {
		fp_alg = (EVP_MD *)EVP_sha1();
	} else {
		fprintf(stderr, "%s: unsupported algorithm: %s\n",
			pname, F_char);
		exit (SCEP_PKISTATUS_ERROR);
	}

	/*
	 * Switch to operation specific code
	 */
	switch(operation_flag) {
		case SCEP_OPERATION_GETCA:
			if (v_flag)
				fprintf(stdout, "%s: SCEP_OPERATION_GETCA\n",
					pname);

			/* Set CA identifier */
			if (!i_flag)
				i_char = CA_IDENTIFIER;

			/* Forge the HTTP message */

			if(!M_flag){
				snprintf(http_string, sizeof(http_string),
				 "GET %s%s?operation=GetCACert&message=%s "
				 "HTTP/1.0\r\n\r\n", p_flag ? "" : "/", dir_name,
						i_char);

			}else{
				snprintf(http_string, sizeof(http_string),
					"GET %s%s?operation=GetCACert&message=%s&%s "
					"HTTP/1.0\r\n\r\n", p_flag ? "" : "/", dir_name,
						i_char, M_char);

			}



			if (d_flag){
				printf("%s: requesting CA certificate\n", pname);
				fprintf(stdout, "%s: scep msg: %s", pname,
									http_string);
			}

			/*
			 * Send http message.
			 * Response is written to http_response struct "reply".
			 */
			reply.payload = NULL;
			if ((c = send_msg (&reply, http_string, host_name,
					host_port, operation_flag)) == 1) {
				fprintf(stderr, "%s: error while sending "
					"message\n", pname);
				exit (SCEP_PKISTATUS_NET);
			}
			if (reply.payload == NULL) {
				fprintf(stderr, "%s: no data, perhaps you "
				   "should define CA identifier (-i)\n", pname);
				exit (SCEP_PKISTATUS_SUCCESS);
			}
			if (v_flag){
				printf("%s: valid response from server\n", pname);
			}
			if (reply.type == SCEP_MIME_GETCA_RA) {
				/* XXXXXXXXXXXXXXXXXXXXX chain not verified */
				write_ca_ra(&reply);
			}
			/* Read payload as DER X.509 object: */
			bp = BIO_new_mem_buf(reply.payload, reply.bytes);
			cacert = d2i_X509_bio(bp, NULL);

			/* Read and print certificate information */
			if (!X509_digest(cacert, fp_alg, md, &n)) {
				ERR_print_errors_fp(stderr);
				exit (SCEP_PKISTATUS_ERROR);
			}
			if (v_flag){
				printf("%s: %s fingerprint: ", pname,
					OBJ_nid2sn(EVP_MD_type(fp_alg)));
				for (c = 0; c < (int)n; c++) {
					printf("%02X%c",md[c],
						(c + 1 == (int)n) ?'\n':':');
				}

			}

			/* Write PEM-formatted file: */
			#ifdef WIN32
			if ((fopen_s(&fp,c_char , "w")))
			#else
			if (!(fp = fopen(c_char, "w")))
			#endif
			{
				fprintf(stderr, "%s: cannot open CA file for "
					"writing\n", pname);
				exit (SCEP_PKISTATUS_ERROR);
			}
			if (PEM_write_X509(fp, c_char) != 1) {
				fprintf(stderr, "%s: error while writing CA "
					"file\n", pname);
				ERR_print_errors_fp(stderr);
				exit (SCEP_PKISTATUS_ERROR);
			}
			if (v_flag)
			printf("%s: CA certificate written as %s\n",
				pname, c_char);
			(void)fclose(fp);
			pkistatus = SCEP_PKISTATUS_SUCCESS;
			break;

		case SCEP_OPERATION_GETNEXTCA:
				if (v_flag)
					fprintf(stdout, "%s: SCEP_OPERATION_GETNEXTCA\n",
						pname);

				/* Set CA identifier */
				if (!i_flag)
					i_char = CA_IDENTIFIER;

				/* Forge the HTTP message */
				if(!M_flag){
					snprintf(http_string, sizeof(http_string),
					 "GET %s%s?operation=GetNextCACert&message=%s "
					 "HTTP/1.0\r\n\r\n", p_flag ? "" : "/", dir_name,
							i_char);

				}else{
					snprintf(http_string, sizeof(http_string),
						"GET %s%s?operation=GetNextCACert&message=%s&%s "
						"HTTP/1.0\r\n\r\n", p_flag ? "" : "/", dir_name,
							i_char, M_char);

				}


				if (d_flag){
					printf("%s: requesting nextCA certificate\n", pname);
					fprintf(stdout, "%s: scep msg: %s", pname,
						http_string);
				}

				/*
				 * Send http message.
				 * Response is written to http_response struct "reply".
				 */
				reply.payload = NULL;
				if ((c = send_msg (&reply, http_string, host_name,
						host_port, operation_flag)) == 1) {
					if(v_flag){
					fprintf(stderr, "%s: error while sending "
						"message\n", pname);
					fprintf(stderr, "%s: getnextCA might be not available"
											"\n", pname);
					}
					exit (SCEP_PKISTATUS_NET);
				}
				if (reply.payload == NULL) {
					fprintf(stderr, "%s: no data, perhaps you "
					   "there is no nextCA available\n", pname);
					exit (SCEP_PKISTATUS_SUCCESS);
				}

				if(d_flag)
				printf("%s: valid response from server\n", pname);

				if (reply.type == SCEP_MIME_GETNEXTCA) {
					/* XXXXXXXXXXXXXXXXXXXXX chain not verified */

					//write_ca_ra(&reply);

					/* Set the whole struct as 0 */
					memset(&scep_t, 0, sizeof(scep_t));

					scep_t.reply_payload = reply.payload;
					scep_t.reply_len = reply.bytes;
					scep_t.request_type = SCEP_MIME_GETNEXTCA;

					pkcs7_verify_unwrap(&scep_t , C_char);

					//pkcs7_unwrap(&scep_t);
				}


				/* Get certs */
				p7 = *(scep_t.reply_p7);
				nextcara = scep_t.reply_p7->d.sign->cert;

			    if (v_flag) {
					printf ("verify and unwrap: found %d cert(s)\n", sk_X509_num(nextcara));
			        }

			    for (i = 0; i < sk_X509_num(nextcara); i++) {
			    		char buffer[1024];
			    		char name[1024];
			    		memset(buffer, 0, 1024);
			    		memset(name, 0, 1024);

			    		cert = sk_X509_value(nextcara, i);
			    		if (v_flag) {
			    			printf("%s: found certificate with\n"
			    				"  subject: '%s'\n", pname,
			    				X509_NAME_oneline(X509_get_subject_name(cert),
			    					buffer, sizeof(buffer)));
			    			printf("  issuer: %s\n",
			    				X509_NAME_oneline(X509_get_issuer_name(cert),
			    					buffer, sizeof(buffer)));
			    		}

			    		/* Create name */
			    		snprintf(name, 1024, "%s-%d", c_char, i);


			    		/* Write PEM-formatted file: */
			    		if (!(fp = fopen(name, "w"))) {
			    			fprintf(stderr, "%s: cannot open cert file for writing\n",
			    					pname);
			    			exit (SCEP_PKISTATUS_FILE);
			    		}
			    		if (v_flag)
			    			printf("%s: writing cert\n", pname);
			    		if (d_flag)
			    			PEM_write_X509(stdout, cert);
			    		if (PEM_write_X509(fp, cert) != 1) {
			    			fprintf(stderr, "%s: error while writing certificate "
			    				"file\n", pname);
			    			ERR_print_errors_fp(stderr);
			    			exit (SCEP_PKISTATUS_FILE);
			    		}
			    		if(v_flag)
			    		printf("%s: certificate written as %s\n", pname, name);
			    		(void)fclose(fp);
			    }



				pkistatus = SCEP_PKISTATUS_SUCCESS;
				break;

		case SCEP_OPERATION_GETCERT:
		case SCEP_OPERATION_GETCRL:
			/* Read local certificate */
			if (!l_flag) {
			  fprintf(stderr, "%s: missing local cert (-l)\n", pname);
			  exit (SCEP_PKISTATUS_FILE);
			}
			read_cert(&localcert, l_char);

		case SCEP_OPERATION_ENROLL:
			/*
			 * Read in CA cert, private key and certificate
			 * request in global variables.
			 */

		        read_ca_cert();

			if (!k_flag) {
			  fprintf(stderr, "%s: missing private key (-k)\n", pname);
			  exit (SCEP_PKISTATUS_FILE);
			}
			
			if(scep_conf != NULL) {
				sscep_engine_read_key_new(&rsa, k_char, scep_t.e);
			} else {
				read_key(&rsa, k_char);
			}


			if ((K_flag && !O_flag) || (!K_flag && O_flag)) {
			  fprintf(stderr, "%s: -O also requires -K (and vice-versa)\n", pname);
			  exit (SCEP_PKISTATUS_FILE);
			}

			if (K_flag) {
				//TODO auf hwcrhk prfen?
				if(scep_conf != NULL) {
					sscep_engine_read_key_old(&renewal_key, K_char, scep_t.e);
				} else {
					read_key(&renewal_key, K_char);
				}
			}

			if (O_flag) {
				read_cert(&renewal_cert, O_char);
			}

			if (operation_flag == SCEP_OPERATION_ENROLL) {
				read_request();
				scep_t.transaction_id = key_fingerprint(request);			
				if (v_flag) {
					printf("%s:  Read request with transaction id: %s\n", pname, scep_t.transaction_id);
				}
			}

			
			if (operation_flag != SCEP_OPERATION_ENROLL)
				goto not_enroll;
			
			if (! O_flag) {
				if (v_flag)
					fprintf(stdout, "%s: generating selfsigned "
					"certificate\n", pname);
			  new_selfsigned(&scep_t);
			}
			else {
			  /* Use existing certificate */
			  scep_t.signercert = renewal_cert;
			  scep_t.signerkey = renewal_key;
			}

			/* Write the selfsigned certificate if requested */
			if (L_flag) {
				/* Write PEM-formatted file: */
				#ifdef WIN32
				if ((fopen_s(&fp, L_char, "w"))) {
				#else
				if (!(fp = fopen(L_char, "w"))) {
				#endif
					fprintf(stderr, "%s: cannot open "
					  "file for writing\n", pname);
					exit (SCEP_PKISTATUS_ERROR);
				}
				if (PEM_write_X509(fp,scep_t.signercert) != 1) {
					fprintf(stderr, "%s: error while "
					  "writing certificate file\n", pname);
					ERR_print_errors_fp(stderr);
					exit (SCEP_PKISTATUS_ERROR);
				}
				printf("%s: selfsigned certificate written "
					"as %s\n", pname, L_char);
				(void)fclose(fp);
			}
			/* Write issuer name and subject (GetCertInitial): */
			if (!(scep_t.ias_getcertinit->subject =
					X509_REQ_get_subject_name(request))) {
				fprintf(stderr, "%s: error getting subject "
					"for GetCertInitial\n", pname);
				ERR_print_errors_fp(stderr);
				exit (SCEP_PKISTATUS_ERROR);
			}
not_enroll:
			if (!(scep_t.ias_getcertinit->issuer =
					 X509_get_issuer_name(cacert))) {
				fprintf(stderr, "%s: error getting issuer "
					"for GetCertInitial\n", pname);
				ERR_print_errors_fp(stderr);
				exit (SCEP_PKISTATUS_ERROR);
			}
			/* Write issuer name and serial (GETC{ert,rl}): */
			scep_t.ias_getcert->issuer =
				 scep_t.ias_getcertinit->issuer;
			scep_t.ias_getcrl->issuer =
				 scep_t.ias_getcertinit->issuer;
			if (!(scep_t.ias_getcrl->serial =
					X509_get_serialNumber(cacert))) {
				fprintf(stderr, "%s: error getting serial "
					"for GetCertInitial\n", pname);
				ERR_print_errors_fp(stderr);
				exit (SCEP_PKISTATUS_ERROR);
			}
			/* User supplied serial number */
			if (s_flag) {
				BIGNUM *bn;
				ASN1_INTEGER *ai;
				int len = BN_dec2bn(&bn , s_char);
				if (!len || !(ai = BN_to_ASN1_INTEGER(bn, NULL))) {
					fprintf(stderr, "%s: error converting serial\n", pname);
					ERR_print_errors_fp(stderr);
					exit (SCEP_PKISTATUS_SS);
				 }
				 scep_t.ias_getcert->serial = ai;
			}
		break;
	}

	switch(operation_flag) {
		case SCEP_OPERATION_ENROLL:
			if (v_flag)
				fprintf(stdout,
					"%s: SCEP_OPERATION_ENROLL\n", pname);
			/* Resum mode: set GetCertInitial */
			if (R_flag) {
				if (n_num == 0)
					exit (SCEP_PKISTATUS_SUCCESS);
				printf("%s: requesting certificate (#1)\n",
					pname);
				scep_t.request_type = SCEP_REQUEST_GETCERTINIT;
				count++;
			} else {
				printf("%s: sending certificate request\n",
					pname);
				scep_t.request_type = SCEP_REQUEST_PKCSREQ;
			}
			break;

		case SCEP_OPERATION_GETCERT:
			if (v_flag)
				fprintf(stdout,
					"%s: SCEP_OPERATION_GETCERT\n", pname);

			scep_t.request_type = SCEP_REQUEST_GETCERT;
			printf("%s: requesting certificate\n",pname);
			break;

		case SCEP_OPERATION_GETCRL:
			if (v_flag)
				fprintf(stdout,
					"%s: SCEP_OPERATION_GETCRL\n", pname);

			scep_t.request_type = SCEP_REQUEST_GETCRL;
			printf("%s: requesting crl\n",pname);
			break;
		}

		/* Enter polling loop */
		while (scep_t.pki_status != SCEP_PKISTATUS_SUCCESS) {
			/* create payload */
			pkcs7_wrap(&scep_t);

			/* URL-encode */
			p = url_encode((char *)scep_t.request_payload,
				scep_t.request_len);

			/*Test mode print SCEP request and don't send it*/
			if(m_flag){

				/* Write output file : */
#ifdef WIN32
				if ((fopen_s(&fp, m_char, "w")))
#else
				if (!(fp = fopen(m_char, "w")))
#endif
				{
					fprintf(stderr, "%s: cannot open output file for "
						"writing\n", m_char);
				}else
				{
					printf("%s: writing PEM fomatted PKCS#7\n", pname);
							PEM_write_PKCS7(fp, scep_t.request_p7);
				}

				//printf("Print SCEP Request:\n %s\n",scep_t.request_payload);
				return 0;
			}

			/* Forge the HTTP message */
		/*	snprintf(http_string, sizeof(http_string),
				"GET %s%s?operation="
				"PKIOperation&message="
				"%s HTTP/1.0\r\n\r\n",
				p_flag ? "" : "/", dir_name, p);*/

			if(!M_flag){
				snprintf(http_string, sizeof(http_string),
				 "GET %s%s?operation=PKIOperation&message=%s "
				 "HTTP/1.0\r\n\r\n", p_flag ? "" : "/", dir_name, p);

			}else{
				snprintf(http_string, sizeof(http_string),
					"GET %s%s?operation=PKIOperation&message=%s&%s "
					"HTTP/1.0\r\n\r\n", p_flag ? "" : "/", dir_name,p, M_char);

			}

			if (d_flag)
				fprintf(stdout, "%s: scep msg: %s",
					pname, http_string);

			/* send http */
			reply.payload = NULL;
			if ((c = send_msg (&reply, http_string, host_name,
					host_port, operation_flag)) == 1) {
				fprintf(stderr, "%s: error while sending "
					"message\n", pname);
				exit (SCEP_PKISTATUS_NET);
			}
			/* Verisign Onsite returns strange reply...
			 * XXXXXXXXXXXXXXXXXXX */
			if ((reply.status == 200) && (reply.payload == NULL)) {
				/*
				scep_t.pki_status = SCEP_PKISTATUS_PENDING;
				break;
				*/
				exit (SCEP_PKISTATUS_ERROR);
			}
			printf("%s: valid response from server\n", pname);

			/* Check payload */
			scep_t.reply_len = reply.bytes;
			scep_t.reply_payload = (unsigned char *)reply.payload;
			pkcs7_unwrap(&scep_t);
			pkistatus = scep_t.pki_status;

			switch(scep_t.pki_status) {
				case SCEP_PKISTATUS_SUCCESS:
					break;
				case SCEP_PKISTATUS_PENDING:
					/* Check time limits */
					if (((t_num * count) >= T_num) ||
					    (count > n_num)) {
						exit (pkistatus);
					}
					scep_t.request_type =
						SCEP_REQUEST_GETCERTINIT;

					/* Wait for poll interval */
					if (v_flag)
					  printf("%s: waiting for %d secs\n",
						pname, t_num);
					sleep(t_num);
					printf("%s: requesting certificate "
						"(#%d)\n", pname, count);

					/* Add counter */
					count++;
					break;

				case SCEP_PKISTATUS_FAILURE:

					/* Handle failure */
					switch (scep_t.fail_info) {
						case SCEP_FAILINFO_BADALG:
						  exit (SCEP_PKISTATUS_BADALG);
						case SCEP_FAILINFO_BADMSGCHK:
						  exit (SCEP_PKISTATUS_BADMSGCHK);
						case SCEP_FAILINFO_BADREQ:
						  exit (SCEP_PKISTATUS_BADREQ);
						case SCEP_FAILINFO_BADTIME:
						  exit (SCEP_PKISTATUS_BADTIME);
						case SCEP_FAILINFO_BADCERTID:
						  exit (SCEP_PKISTATUS_BADCERTID);
						/* Shouldn't be there... */
						default:
						  exit (SCEP_PKISTATUS_ERROR);
					}
				default:
					fprintf(stderr, "%s: unknown "
						"pkiStatus\n", pname);
					exit (SCEP_PKISTATUS_ERROR);
			}
	}
	/* We got SUCCESS, analyze the reply */
	switch (scep_t.request_type) {

		/* Local certificate */
		case SCEP_REQUEST_PKCSREQ:
		case SCEP_REQUEST_GETCERTINIT:
			write_local_cert(&scep_t);
			break;

		/* Other end entity certificate */
		case SCEP_REQUEST_GETCERT:
			write_other_cert(&scep_t);
			break;

			break;
		/* CRL */
		case SCEP_REQUEST_GETCRL:
			write_crl(&scep_t);
			break;
	}
	//TODO
	//richtiger ort für disable??
//	if(e){
//		ENGINE_finish(*e);
//		ENGINE_free(*e);
//	    hwEngine = NULL;
//	    ENGINE_cleanup();
//	}
//




	return (pkistatus);
}

void
usage() {
	fprintf(stdout, "\nsscep version %s\n\n" , VERSION);
	fprintf(stdout, "Usage: %s OPERATION [OPTIONS]\n"
	"\nAvailable OPERATIONs are\n"
	"  getca             Get CA/RA certificate(s)\n"
	"  getnextca         Get next CA/RA certificate(s)\n"
	"  enroll            Enroll certificate\n"
	"  getcert           Query certificate\n"
	"  getcrl            Query CRL\n"
	"\nGeneral OPTIONS\n"
	"  -u <url>          SCEP server URL\n"
	"  -p <host:port>    Use proxy server at host:port\n"
	"  -M <string>		 Monitor Information String name=value&name=value ...\n"
	"  -g                Enable Engine support\n"
	"  -h				 Keyforme=ID. \n"//TODO
	"  -f <file>         Use configuration file\n"
	"  -c <file>         CA certificate file (write if OPERATION is getca or getnextca)\n"
	"  -E <name>         PKCS#7 encryption algorithm (des|3des|blowfish|aes)\n"
	"  -S <name>         PKCS#7 signature algorithm (md5|sha1)\n"
	"  -v                Verbose operation\n"
	"  -d                Debug (even more verbose operation)\n"
	"\nOPTIONS for OPERATION getca are\n"
	"  -i <string>       CA identifier string\n"
	"  -F <name>         Fingerprint algorithm\n"
	"\nOPTIONS for OPERATION getnextca are\n"
	"  -C <file>         Local certificate chain file for signature verification in PEM format \n"
	"  -F <name>         Fingerprint algorithm\n"
	"  -c <file>         CA certificate file (write if OPERATION is getca or getnextca)\n"
	"  -w <file>         Write signer certificate in file (optional) \n"
	"\nOPTIONS for OPERATION enroll are\n"
 	"  -k <file>         Private key file\n"
	"  -r <file>         Certificate request file\n"
 	"  -K <file>         Signature private key file, use with -O\n"
 	"  -O <file>         Signature certificate (used instead of self-signed)\n"
	"  -l <file>         Write enrolled certificate in file\n"
	"  -e <file>         Use different CA cert for encryption\n"
	"  -L <file>         Write selfsigned certificate in file\n"
	"  -t <secs>         Polling interval in seconds\n"
	"  -T <secs>         Max polling time in seconds\n"
	"  -n <count>        Max number of GetCertInitial requests\n"
 	"  -R                Resume interrupted enrollment\n"
	"\nOPTIONS for OPERATION getcert are\n"
 	"  -k <file>         Private key file\n"
	"  -l <file>         Local certificate file\n"
	"  -s <number>       Certificate serial number\n"
	"  -w <file>         Write certificate in file\n"
	"\nOPTIONS for OPERATION getcrl are\n"
 	"  -k <file>         Private key file\n"
	"  -l <file>         Local certificate file\n"
	"  -w <file>         Write CRL in file\n\n", pname);
	exit(0);
}
Beispiel #25
0
/*
 * initialize ssl engine, load certs and initialize openssl internals
 */
void init_ssl(void)
{
	const SSL_METHOD *ssl_method;
	RSA *rsa=NULL;
	X509_REQ *req = NULL;
	X509 *cer = NULL;
	EVP_PKEY *pk = NULL;
	EVP_PKEY *req_pkey = NULL;
	X509_NAME *name = NULL;
	FILE *fp;
	char buf[SIZ];
	int rv = 0;

	if (!access("/var/run/egd-pool", F_OK)) {
		RAND_egd("/var/run/egd-pool");
	}

	if (!RAND_status()) {
		syslog(LOG_WARNING, "PRNG not adequately seeded, won't do SSL/TLS\n");
		return;
	}
	SSLCritters = malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t *));
	if (!SSLCritters) {
		syslog(LOG_ERR, "citserver: can't allocate memory!!\n");
		/* Nothing's been initialized, just die */
		ShutDownWebcit();
		exit(WC_EXIT_SSL);
	} else {
		int a;

		for (a = 0; a < CRYPTO_num_locks(); a++) {
			SSLCritters[a] = malloc(sizeof(pthread_mutex_t));
			if (!SSLCritters[a]) {
				syslog(LOG_EMERG,
					"citserver: can't allocate memory!!\n");
				/** Nothing's been initialized, just die */
				ShutDownWebcit();
				exit(WC_EXIT_SSL);
			}
			pthread_mutex_init(SSLCritters[a], NULL);
		}
	}

	/*
	 * Initialize SSL transport layer
	 */
	SSL_library_init();
	SSL_load_error_strings();
	ssl_method = SSLv23_server_method();
	if (!(ssl_ctx = SSL_CTX_new(ssl_method))) {
		syslog(LOG_WARNING, "SSL_CTX_new failed: %s\n", ERR_reason_error_string(ERR_get_error()));
		return;
	}

	syslog(LOG_INFO, "Requesting cipher list: %s\n", ssl_cipher_list);
	if (!(SSL_CTX_set_cipher_list(ssl_ctx, ssl_cipher_list))) {
		syslog(LOG_WARNING, "SSL_CTX_set_cipher_list failed: %s\n", ERR_reason_error_string(ERR_get_error()));
		return;
	}

	CRYPTO_set_locking_callback(ssl_lock);
	CRYPTO_set_id_callback(id_callback);

	/*
	 * Get our certificates in order. (FIXME: dirify. this is a setup job.)
	 * First, create the key/cert directory if it's not there already...
	 */
	mkdir(CTDL_CRYPTO_DIR, 0700);

	/*
	 * Before attempting to generate keys/certificates, first try
	 * link to them from the Citadel server if it's on the same host.
	 * We ignore any error return because it either meant that there
	 * was nothing in Citadel to link from (in which case we just
	 * generate new files) or the target files already exist (which
	 * is not fatal either).
	 */
	if (!strcasecmp(ctdlhost, "uds")) {
		sprintf(buf, "%s/keys/citadel.key", ctdlport);
		rv = symlink(buf, CTDL_KEY_PATH);
		if (!rv) syslog(LOG_DEBUG, "%s\n", strerror(errno));
		sprintf(buf, "%s/keys/citadel.csr", ctdlport);
		rv = symlink(buf, CTDL_CSR_PATH);
		if (!rv) syslog(LOG_DEBUG, "%s\n", strerror(errno));
		sprintf(buf, "%s/keys/citadel.cer", ctdlport);
		rv = symlink(buf, CTDL_CER_PATH);
		if (!rv) syslog(LOG_DEBUG, "%s\n", strerror(errno));
	}

	/*
	 * If we still don't have a private key, generate one.
	 */
	if (access(CTDL_KEY_PATH, R_OK) != 0) {
		syslog(LOG_INFO, "Generating RSA key pair.\n");
		rsa = RSA_generate_key(1024,	/* modulus size */
					65537,	/* exponent */
					NULL,	/* no callback */
					NULL	/* no callback */
		);
		if (rsa == NULL) {
			syslog(LOG_WARNING, "Key generation failed: %s\n", ERR_reason_error_string(ERR_get_error()));
		}
		if (rsa != NULL) {
			fp = fopen(CTDL_KEY_PATH, "w");
			if (fp != NULL) {
				chmod(CTDL_KEY_PATH, 0600);
				if (PEM_write_RSAPrivateKey(fp,	/* the file */
							rsa,	/* the key */
							NULL,	/* no enc */
							NULL,	/* no passphr */
							0,	/* no passphr */
							NULL,	/* no callbk */
							NULL	/* no callbk */
				) != 1) {
					syslog(LOG_WARNING, "Cannot write key: %s\n",
						ERR_reason_error_string(ERR_get_error()));
					unlink(CTDL_KEY_PATH);
				}
				fclose(fp);
			}
			else {
				syslog(LOG_WARNING, "Cannot write key: %s\n", CTDL_KEY_PATH);
				ShutDownWebcit();
				exit(0);
			}
			RSA_free(rsa);
		}
	}

	/*
	 * If there is no certificate file on disk, we will be generating a self-signed certificate
	 * in the next step.  Therefore, if we have neither a CSR nor a certificate, generate
	 * the CSR in this step so that the next step may commence.
	 */
	if ( (access(CTDL_CER_PATH, R_OK) != 0) && (access(CTDL_CSR_PATH, R_OK) != 0) ) {
		syslog(LOG_INFO, "Generating a certificate signing request.\n");

		/*
		 * Read our key from the file.  No, we don't just keep this
		 * in memory from the above key-generation function, because
		 * there is the possibility that the key was already on disk
		 * and we didn't just generate it now.
		 */
		fp = fopen(CTDL_KEY_PATH, "r");
		if (fp) {
			rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
			fclose(fp);
		}

		if (rsa) {

			/** Create a public key from the private key */
			if (pk=EVP_PKEY_new(), pk != NULL) {
				EVP_PKEY_assign_RSA(pk, rsa);
				if (req = X509_REQ_new(), req != NULL) {
					const char *env;
					/* Set the public key */
					X509_REQ_set_pubkey(req, pk);
					X509_REQ_set_version(req, 0L);

					name = X509_REQ_get_subject_name(req);

					/* Tell it who we are */

					/*
					 * We used to add these fields to the subject, but
					 * now we don't.  Someone doing this for real isn't
					 * going to use the webcit-generated CSR anyway.
					 *
					X509_NAME_add_entry_by_txt(name, "C",
						MBSTRING_ASC, "US", -1, -1, 0);
					*
					X509_NAME_add_entry_by_txt(name, "ST",
						MBSTRING_ASC, "New York", -1, -1, 0);
					*
					X509_NAME_add_entry_by_txt(name, "L",
						MBSTRING_ASC, "Mount Kisco", -1, -1, 0);
					*/

					env = getenv("O");
					if (env == NULL)
						env = "Organization name",

					X509_NAME_add_entry_by_txt(
						name, "O",
						MBSTRING_ASC, 
						(unsigned char*)env, 
						-1, -1, 0
					);

					env = getenv("OU");
					if (env == NULL)
						env = "Citadel server";

					X509_NAME_add_entry_by_txt(
						name, "OU",
						MBSTRING_ASC, 
						(unsigned char*)env, 
						-1, -1, 0
					);

					env = getenv("CN");
					if (env == NULL)
						env = "*";

					X509_NAME_add_entry_by_txt(
						name, "CN",
						MBSTRING_ASC, 
						(unsigned char*)env,
						-1, -1, 0
					);
				
					X509_REQ_set_subject_name(req, name);

					/* Sign the CSR */
					if (!X509_REQ_sign(req, pk, EVP_md5())) {
						syslog(LOG_WARNING, "X509_REQ_sign(): error\n");
					}
					else {
						/* Write it to disk. */	
						fp = fopen(CTDL_CSR_PATH, "w");
						if (fp != NULL) {
							chmod(CTDL_CSR_PATH, 0600);
							PEM_write_X509_REQ(fp, req);
							fclose(fp);
						}
						else {
							syslog(LOG_WARNING, "Cannot write key: %s\n", CTDL_CSR_PATH);
							ShutDownWebcit();
							exit(0);
						}
					}

					X509_REQ_free(req);
				}
			}

			RSA_free(rsa);
		}

		else {
			syslog(LOG_WARNING, "Unable to read private key.\n");
		}
	}



	/*
	 * Generate a self-signed certificate if we don't have one.
	 */
	if (access(CTDL_CER_PATH, R_OK) != 0) {
		syslog(LOG_INFO, "Generating a self-signed certificate.\n");

		/* Same deal as before: always read the key from disk because
		 * it may or may not have just been generated.
		 */
		fp = fopen(CTDL_KEY_PATH, "r");
		if (fp) {
			rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
			fclose(fp);
		}

		/* This also holds true for the CSR. */
		req = NULL;
		cer = NULL;
		pk = NULL;
		if (rsa) {
			if (pk=EVP_PKEY_new(), pk != NULL) {
				EVP_PKEY_assign_RSA(pk, rsa);
			}

			fp = fopen(CTDL_CSR_PATH, "r");
			if (fp) {
				req = PEM_read_X509_REQ(fp, NULL, NULL, NULL);
				fclose(fp);
			}

			if (req) {
				if (cer = X509_new(), cer != NULL) {

					ASN1_INTEGER_set(X509_get_serialNumber(cer), 0);
					X509_set_issuer_name(cer, req->req_info->subject);
					X509_set_subject_name(cer, req->req_info->subject);
					X509_gmtime_adj(X509_get_notBefore(cer), 0);
					X509_gmtime_adj(X509_get_notAfter(cer),(long)60*60*24*SIGN_DAYS);

					req_pkey = X509_REQ_get_pubkey(req);
					X509_set_pubkey(cer, req_pkey);
					EVP_PKEY_free(req_pkey);
					
					/* Sign the cert */
					if (!X509_sign(cer, pk, EVP_md5())) {
						syslog(LOG_WARNING, "X509_sign(): error\n");
					}
					else {
						/* Write it to disk. */	
						fp = fopen(CTDL_CER_PATH, "w");
						if (fp != NULL) {
							chmod(CTDL_CER_PATH, 0600);
							PEM_write_X509(fp, cer);
							fclose(fp);
						}
						else {
							syslog(LOG_WARNING, "Cannot write key: %s\n", CTDL_CER_PATH);
							ShutDownWebcit();
							exit(0);
						}
					}
					X509_free(cer);
				}
			}

			RSA_free(rsa);
		}
	}

	/*
	 * Now try to bind to the key and certificate.
	 * Note that we use SSL_CTX_use_certificate_chain_file() which allows
	 * the certificate file to contain intermediate certificates.
	 */
	SSL_CTX_use_certificate_chain_file(ssl_ctx, CTDL_CER_PATH);
	SSL_CTX_use_PrivateKey_file(ssl_ctx, CTDL_KEY_PATH, SSL_FILETYPE_PEM);
	if ( !SSL_CTX_check_private_key(ssl_ctx) ) {
		syslog(LOG_WARNING, "Cannot install certificate: %s\n",
				ERR_reason_error_string(ERR_get_error()));
	}
	
}
Beispiel #26
0
int mkreq(X509_REQ **req, EVP_PKEY **pkeyp, int bits, int serial, int days)
	{
	X509_REQ *x;
	EVP_PKEY *pk;
	RSA *rsa;
	X509_NAME *name=NULL;
	STACK_OF(X509_EXTENSION) *exts = NULL;
	
	if ((pk=EVP_PKEY_new()) == NULL)
		goto err;

	if ((x=X509_REQ_new()) == NULL)
		goto err;

	rsa=RSA_generate_key(bits,RSA_F4,callback,NULL);
	if (!EVP_PKEY_assign_RSA(pk,rsa))
		goto err;

	rsa=NULL;

	X509_REQ_set_pubkey(x,pk);

	name=X509_REQ_get_subject_name(x);

	/* This function creates and adds the entry, working out the
	 * correct string type and performing checks on its length.
	 * Normally we'd check the return value for errors...
	 */
	X509_NAME_add_entry_by_txt(name,"C",
				MBSTRING_ASC, "UK", -1, -1, 0);
	X509_NAME_add_entry_by_txt(name,"CN",
				MBSTRING_ASC, "OpenSSL Group", -1, -1, 0);

#ifdef REQUEST_EXTENSIONS
	/* Certificate requests can contain extensions, which can be used
	 * to indicate the extensions the requestor would like added to 
	 * their certificate. CAs might ignore them however or even choke
	 * if they are present.
	 */

	/* For request extensions they are all packed in a single attribute.
	 * We save them in a STACK and add them all at once later...
	 */

	exts = sk_X509_EXTENSION_new_null();
	/* Standard extenions */

	add_ext(exts, NID_key_usage, "critical,digitalSignature,keyEncipherment");

	/* This is a typical use for request extensions: requesting a value for
	 * subject alternative name.
	 */

	add_ext(exts, NID_subject_alt_name, "email:[email protected]");

	/* Some Netscape specific extensions */
	add_ext(exts, NID_netscape_cert_type, "client,email");



#ifdef CUSTOM_EXT
	/* Maybe even add our own extension based on existing */
	{
		int nid;
		nid = OBJ_create("1.2.3.4", "MyAlias", "My Test Alias Extension");
		X509V3_EXT_add_alias(nid, NID_netscape_comment);
		add_ext(x, nid, "example comment alias");
	}
#endif

	/* Now we've created the extensions we add them to the request */

	X509_REQ_add_extensions(x, exts);

	sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);

#endif
	
	if (!X509_REQ_sign(x,pk,EVP_md5()))
		goto err;

	*req=x;
	*pkeyp=pk;
	return(1);
err:
	return(0);
	}
Beispiel #27
0
x509name pki_x509req::getSubject() const
{
	x509name x(X509_REQ_get_subject_name(request));
	pki_openssl_error();
	return x;
}
Beispiel #28
0
int	main(int argc, char *argv[]) {
	int		c, poll = 0, reqversion = 0, rc = -1;
	char		*cacertfile = NULL, *keyfile = NULL, *challenge = NULL,
			*savedrequestfile = NULL, *requestfile = NULL,
			*dn = NULL, *spkacfile = NULL, *endrequest = NULL;
	scep_t		scep;
	BIO		*repbio;
	char		*url = "http://localhost/cgi-bin";
	scepmsg_t	*msg;
	unsigned char	*checkNonce = NULL;

	/* initialize what you can					*/
	scepinit();
	scep_clear(&scep);

	/* we are a client 						*/
	scep.client = 1;

	/* parse command line						*/
	while (EOF != (c = getopt(argc, argv, "dc:e:r:s:k:w:pu:2a:q:")))
		switch (c) {
		case 'd':
			debug++;
			break;
		case 'e':
			endrequest = optarg;
			break;
		case 'c':
			cacertfile = optarg;
			break;
		case 's':
			savedrequestfile = optarg;
		case 'r':
			/* the request file will also contain the self	*/
			/* signed certificate				*/
			requestfile = optarg;
			break;
		case 'k':
			keyfile = optarg;
			break;
		case 'w':
			challenge = optarg;
			break;
		case 'p':
			poll = 1;
			break;
		case 'q':
			scep.community = optarg;
			break;
		case 'u':
			url = optarg;
			break;
		case '2':
			reqversion = 1;
			break;
		case 'a':
			spkacfile = optarg;
			break;
		}

	/* stop immediately if request or key is missing		*/
	/* (even in the case of a version 2 proxied request, we need	*/
	/* a request as the carrier of the proxy entities public key)	*/
	if (keyfile == NULL) {
		BIO_printf(bio_err, "%s:%d: key file is required argument\n",
			__FILE__, __LINE__);
		goto err;
	}
	if (requestfile == NULL) {
		BIO_printf(bio_err, "%s:%d: request file is required "
			"argument\n", __FILE__, __LINE__);
		goto err;
	}

	/* we are preparing the request message				*/
	msg = &scep.request;

	/* decode the URL						*/
	if (parseurl(&scep, url) < 0) {
		BIO_printf(bio_err, "%s:%d: cannot parse url\n", __FILE__,
			__LINE__);
		goto err;
	}
	if (debug)
		BIO_printf(bio_err, "%s:%d: decoded URL %s|%d|%s\n", __FILE__,
			__LINE__, scep.h.httphost, scep.h.httpport,
			scep.h.httppath);

	/* read the client key and request information			*/
	if (read_clientstuff(&scep, requestfile, keyfile) < 0) {
		BIO_printf(bio_err, "%s:%d: failed to read client stuff\n",
			__FILE__, __LINE__);
		goto err;
	}

	/* now we have to decide about the payload we want to have	*/
	/* with our scep request:					*/
	/*  - for a version 1 request, this will always be the original	*/
	/*    certificate signing request				*/
	/*  - for a version 2 request, it will be a payload structure	*/
	switch (reqversion) {
	case 0:
		/* for a version 1 client, client pubkey and client req	*/
		/* coincide						*/
		scep.requestorpubkey = scep.clientpubkey;
		scep.requestorreq = scep.clientreq;
		if (debug)
			BIO_printf(bio_err, "%s:%d: end request coincides "
				"with SCEP client\n", __FILE__, __LINE__);
		break;
	case 1:
		msg->rd.payload = payload_new();
		rc = -1;
		if (spkacfile) {
			if (debug)
				BIO_printf(bio_err, "%s:%d: reading spki "
					"from %s\n", __FILE__, __LINE__,
					spkacfile);
			rc = read_requestorstuff(&scep, 1, spkacfile);
		} else if (endrequest) {
			if (debug)
				BIO_printf(bio_err, "%s:%d: reading X509 req "
					"from %s\n", __FILE__, __LINE__,
					endrequest);
			rc = read_requestorstuff(&scep, 0, endrequest);
		}
		if (rc < 0) {
			BIO_printf(bio_err, "%s:%d: could not read end "
				"request data\n", __FILE__, __LINE__);
			goto err;
		}
		if (debug)
			BIO_printf(bio_err, "%s:%d: end request read\n",
				__FILE__, __LINE__);
		break;
	}

	/* set the transaction id value					*/
	scep.transId = key_fingerprint(scep.requestorpubkey);
	if (debug)
		BIO_printf(bio_err, "%s:%d: transaction ID is %s\n",
			__FILE__, __LINE__, scep.transId);

	/* read the CA certificate file					*/
	if (read_castuff(&scep, cacertfile) < 0) {
		BIO_printf(bio_err, "%s:%d: read CA certificate info\n",
			__FILE__, __LINE__);
	}
	if (debug)
		BIO_printf(bio_err, "%s:%d: CA certificate read\n",
			__FILE__, __LINE__);

	/* for SPKI requests, there should be exactly one more argument	*/
	/* namely the distinguished name				*/
	if (spkacfile) {
		if ((argc - optind) != 1) {
			BIO_printf(bio_err, "%s:%d: DN argument needed\n",
				__FILE__, __LINE__);
			goto err;
		}
		dn = argv[optind];
		if (debug)
			BIO_printf(bio_err, "%s:%d: DN argument is '%s'\n",
				__FILE__, __LINE__, dn);

		/* convert the DN into attributes and add them to the	*/
		/* payload						*/
		if (payload_dn_to_attrs(msg->rd.payload, dn) < 0) {
			BIO_printf(bio_err, "%s:%d: failed to add DN attrs\n",
				__FILE__, __LINE__);
			goto err;
		}
	}

	/* skip creation of a request message when polling		*/
	if (poll)
		goto pollinginit;

	/* pack the request as a PKSCReq message, of type PKCSReq 	*/
	switch (reqversion) {
	case 0:
		msg->messageType = SCEP_MESSAGE_TYPE_PKCSREQ;
		msg->rd.req = scep.clientreq;
		break;
	case 1:
		/* build a version 2 payload				*/
		if (debug)
			BIO_printf(bio_err, "%s:%d: building version 2 "
				"payload\n", __FILE__, __LINE__);
		if (scep.requestorreq)
			payload_set_req(msg->rd.payload, scep.requestorreq);
		if (scep.requestorspki)
			payload_set_spki(msg->rd.payload, scep.requestorspki);

		/* set the correct message type				*/
		if (scep.community) {
			/* compute the authenticator from the original 	*/
			/* request and the community			*/
			msg->messageType = SCEP_MESSAGE_TYPE_V2PROXY;
		} else {
			msg->messageType = SCEP_MESSAGE_TYPE_V2REQUEST;
		}
		break;
	}

	/* write the request to the request file, for later perusal	*/
	if (savedrequestfile) {
		BIO	*reqbio;
		reqbio = BIO_new(BIO_s_file());
		BIO_write_filename(reqbio, savedrequestfile);
		switch (reqversion) {
		case 0:
			/* version 1 request has a X509_REQ payload	*/
			PEM_write_bio_X509_REQ(reqbio, msg->rd.req);
			break;
		case 1:
			/* version 2 requests have a "real" payload	*/
			i2d_payload_bio(reqbio, msg->rd.payload);
			break;
		}
		BIO_free(reqbio);
	}

	goto common;

pollinginit:
	/* when polling, the request is a GetCertInitial message	*/
	msg->messageType = SCEP_MESSAGE_TYPE_GETCERTINITIAL;

	/* the contents is the pair issuer and subject			*/
	msg->rd.is = (issuer_and_subject_t *)malloc(
		sizeof(issuer_and_subject_t));
	msg->rd.is->issuer = X509_get_subject_name(scep.cacert);
	msg->rd.is->subject = NULL;

	/* when polling we should read the request from request file	*/
	/* (only needed for the distinguished name of the client)	*/
	if (debug)
		BIO_printf(bio_err, "%s:%d: getting subject X509_NAME\n",
			__FILE__, __LINE__);
	switch (reqversion) {
	case 0:
		msg->rd.is->subject = X509_REQ_get_subject_name(scep.clientreq);
		break;
	case 1:
		if (scep.requestorreq)
			msg->rd.is->subject
				= X509_REQ_get_subject_name(scep.requestorreq);
		if (scep.requestorspki) {
			if (debug)
				BIO_printf(bio_err, "%s:%d: converting DN '%s' "
					"to X509_NAME\n",
					__FILE__, __LINE__, dn);
			msg->rd.is->subject = ldap_to_x509(dn);
		}
		break;
	}
	if (msg->rd.is->subject == NULL) {
		BIO_printf(bio_err, "%s:%d: no subject found\n", 
			__FILE__, __LINE__);
		goto err;
	}
	if (debug)
		BIO_printf(bio_err, "%s:%d: issuer and subject found\n",
			__FILE__, __LINE__);

common:
	/* create a self signed certificate for use with SCEP		*/
	if (selfsigned(&scep) < 0) {
		BIO_printf(bio_err, "%s:%d: failed to create self signed "
			"certificate\n", __FILE__, __LINE__);
		goto err;
	}
	if (debug)
		BIO_printf(bio_err, "%s:%d: self signed certificate created\n",
			__FILE__, __LINE__);

	/* set the senderNonce						*/
	scep.senderNonceLength = 16;
	scep.senderNonce = (unsigned char *)malloc(scep.senderNonceLength);
	RAND_bytes(scep.senderNonce, scep.senderNonceLength);
	if (debug)
		BIO_printf(bio_err, "%s:%d: senderNonce set\n", __FILE__,
			__LINE__);
	checkNonce = scep.senderNonce;

	/* all messages sent from the client are base 64 encoded	*/
	msg->base64 = 1;

	/* encode							*/
	if (encode(&scep) < 0) {
		BIO_printf(bio_err, "%s:%d: encoding the request failed\n",
			__FILE__, __LINE__);
		goto err;
	}
	if (debug)
		BIO_printf(bio_err, "%s:%d: encoded bytes: %d\n", 
			__FILE__, __LINE__, scep.request.length);

	/* send the request to the server, read the reply		*/
	repbio = getrequest(&scep);
	if (repbio == NULL) {
		BIO_printf(bio_err, "%s:%d: failed to read correct reply\n",
			__FILE__, __LINE__);
		goto err;
	}

	/* analyze  the reply						*/
	if (decode(&scep, repbio) < 0) {
		BIO_printf(bio_err, "%s:%d: decoding the reply failed\n",
			__FILE__, __LINE__);
		goto err;
	}

	/* display some information about the reply			*/
	printf("transaction id: %s\n", scep.transId);
	printf("PKIstatus: %s\n", (scep.reply.pkiStatus)
		? scep.reply.pkiStatus : "(null)");
	printf("reply message type: %s\n", scep.reply.messageType);
	if (scep.reply.failinfo) {
		printf("failinfo: %s\n", scep.reply.failinfo);
	}

	/* make sure we get a CertRep message back			*/
	if (strcmp(scep.reply.messageType, SCEP_MESSAGE_TYPE_CERTREP)) {
		BIO_printf(bio_err, "%s:%d: only CertRep message acceptable "
			" in response to PKCSReq/GetCertInitial\n",
			__FILE__, __LINE__);
		goto err;
	}

	/* check for the Nonces						*/
	if (memcmp(checkNonce, scep.recipientNonce, 16)) {
		BIO_printf(bio_err, "%s:%d: recipientNonce != sent "
			"senderNonce\n", __FILE__, __LINE__);
		goto err;
	}
	if (debug)
		BIO_printf(bio_err, "%s:%d: Nonce check OK\n", __FILE__, 
			__LINE__);

	if (scep.reply.pkiStatus == NULL) {
		BIO_printf(bio_err, "no pkiStatus returned\n");
		exit(1);
	}

	switch (atoi(scep.reply.pkiStatus)) {
	case PKI_SUCCESS:
		/* Success						*/
		scep.clientcert = extract_cert(&scep);
		if (debug)
			BIO_printf(bio_err, "%s:%d: certificate returned %p\n",
				__FILE__, __LINE__, scep.clientcert);
		if (scep.clientcert) {
			BIO	*cb;
			cb = BIO_new(BIO_s_file());
			BIO_set_fp(cb, stdout, BIO_NOCLOSE);
			PEM_write_bio_X509(cb, scep.clientcert);
			BIO_free(cb);
		}
		exit(EXIT_SUCCESS);
		break;
	case PKI_FAILURE:	/* Failure				*/
		if (debug)
			BIO_printf(bio_err, "%s:%d: request failed: %s\n",
				__FILE__, __LINE__, scep.reply.failinfo);
		exit(1);
		break;
	case PKI_PENDING:	/* Pending				*/
		if (debug)
			BIO_printf(bio_err, "%s:%d: request still pending\n",
				__FILE__, __LINE__);
		exit(2);
		break;
	}

	/* error return							*/
err:
	ERR_print_errors(bio_err);
	exit(EXIT_FAILURE);
}
Beispiel #29
0
X509_NAME* HsOpenSSL_X509_REQ_get_subject_name(X509_REQ* req) {
    return X509_REQ_get_subject_name(req);
}
Beispiel #30
0
static scepitem_t	*readitem(char *transid) {
	scepitem_t	*si;
	BIO		*bio;
	char		filename[1024];
	char		oneline[1024];
	X509_NAME	*name;

	/* allocate a new structure					*/
	si = (scepitem_t *)malloc(sizeof(scepitem_t));

	/* first create a copy of the transid				*/
	si->transid = strdup(transid);

	/* make sure that it has the right length			*/
	si->transid[32] = '\0';

	/* find the appropriate file: request or certificate		*/
	switch (itemselect) {
	case SELECT_PENDING:
	case SELECT_REJECTED:
		si->type = ITEM_TYPE_REQ;
		break;
	case SELECT_GRANTED:
	case SELECT_REVOKED:
		si->type = ITEM_TYPE_CERT;
		break;
	}

	/* create the filename for the item				*/
	snprintf(filename, sizeof(filename), "%s/%s/%s.der", OPENSCEPDIR,
		selectname[itemselect], si->transid);
	if (debug)
		fprintf(stderr, "%s:%d: trying file '%s'\n", __FILE__, __LINE__,
			filename);

	/* open the file and read the contents				*/
	bio = BIO_new(BIO_s_file());
	if (BIO_read_filename(bio, filename) < 0) {
		fprintf(stderr, "%s:%d: cannot open file %s\n", __FILE__,
			__LINE__, filename);
		return NULL;
	}
	switch (si->type) {
	case ITEM_TYPE_REQ:
		si->data.req = d2i_X509_REQ_bio(bio, NULL);
		break;
	case ITEM_TYPE_CERT:
		si->data.x509 = d2i_X509_bio(bio, NULL);
		break;
	}
	if (si->data.any == NULL) {
		fprintf(stderr, "%s:%d: cannot decode item, trans id %s\n",
			__FILE__, __LINE__, si->transid);
		ERR_print_errors(bio_err);
		return NULL;
	} else {
		if (debug)
			BIO_printf(bio_err, "%s:%d: got new item\n", __FILE__,
				__LINE__);
	}

	/* extract key information from request or certificate		*/
	switch (sortorder) {
	case SORT_TRANSID:
		si->key = strdup(si->transid);
		break;
	case SORT_NAME:
		name = (si->type == ITEM_TYPE_REQ)
			? X509_REQ_get_subject_name(si->data.req)
			: X509_get_subject_name(si->data.x509);
		X509_NAME_oneline(name, oneline, sizeof(oneline));
		si->key = strdup(oneline);
		break;
	case SORT_NOTBEFORE:
		si->key = asn1_time_to_string(X509_get_notBefore(
			si->data.x509));
		break;
	case SORT_NOTAFTER:
		si->key = asn1_time_to_string(X509_get_notAfter(si->data.x509));
		break;
	case SORT_SERIAL:
		si->key = X509_get_serialNumber(si->data.x509);
		break;
	}

	/* return the completely filled in item				*/
	return si;
}