示例#1
1
文件: cert.c 项目: crshd/imapfilter
/*
 * Write the SSL/TLS certificate after asking the user to accept/reject it.
 */
int
write_cert(X509 *cert)
{
	int n;
	FILE *fd;
	char b, c, buf[64];
	char *certf;

	do {
		printf("(R)eject, accept (t)emporarily or "
		    "accept (p)ermanently? ");
		if (fgets(buf, sizeof(buf), stdin) == NULL)
			return -1;
		c = tolower((int)(*buf));
	} while (c != 'r' && c != 't' && c != 'p');

	if (c == 'r')
		return -1;
	else if (c == 't')
		return 0;

	n = snprintf(&b, 1, "%s/%s", env.home, PATHNAME_CERTS);

	if (env.pathmax != -1 && n > env.pathmax)
		fatal(ERROR_PATHNAME,
		    "pathname limit %ld exceeded: %d\n", env.pathmax, n);

	certf = (char *)xmalloc((n + 1) * sizeof(char));
	snprintf(certf, n + 1, "%s/%s", env.home, PATHNAME_CERTS);

	create_file(certf, S_IRUSR | S_IWUSR);

	fd = fopen(certf, "a");

	xfree(certf);

	if (fd == NULL)
		return -1;

	PEM_write_X509(fd, cert);

	fclose(fd);

	return 0;
}
示例#2
0
文件: cert.c 项目: divdot/imapfilter
/*
 * Store the SSL/TLS certificate after asking the user to accept/reject it.
 */
int
store_cert(X509 *cert)
{
	FILE *fd;
	char c, buf[LINE_MAX];
	char *certf;
	char *s;

	do {
		printf("(R)eject, accept (t)emporarily or "
		    "accept (p)ermanently? ");
		if (fgets(buf, LINE_MAX, stdin) == NULL)
			return -1;
		c = tolower((int)(*buf));
	} while (c != 'r' && c != 't' && c != 'p');

	if (c == 'r')
		return -1;
	else if (c == 't')
		return 0;

	certf = get_filepath("certificates");
	create_file(certf, S_IRUSR | S_IWUSR);
	fd = fopen(certf, "a");
	xfree(certf);
	if (fd == NULL)
		return -1;

	s = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
	fprintf(fd, "Subject: %s\n", s);
	xfree(s);
	s = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0);
	fprintf(fd, "Issuer: %s\n", s);
	xfree(s);
	s = get_serial(cert);
	fprintf(fd, "Serial: %s\n", s);
	xfree(s);

	PEM_write_X509(fd, cert);

	fprintf(fd, "\n");
	fclose(fd);

	return 0;
}
示例#3
0
Try<Nothing> write_certificate_file(X509* x509, const Path& path)
{
  // We use 'FILE*' here because it is an API requirement by openssl.
  FILE* file = fopen(path.value.c_str(), "wb");
  if (file == NULL) {
    return Error("Failed to open file '" + stringify(path) + "' for writing");
  }

  if (PEM_write_X509(file, x509) != 1) {
    fclose(file);
    return Error("Failed to write certificate to file '" + stringify(path) +
      "': PEM_write_X509");
  }

  fclose(file);

  return Nothing();
}
示例#4
0
/**
 * Verify the peer's    certificate, if successfully verified,
 * save the peer's certificate
 */
static gint
ssl_verify_certs(SSL *ssl)
{
    FILE  *f;
    X509  *x;
    gchar *cert_path;
    gchar *cert_file;
    gchar  buf[256];
    gchar *pos;

    hybrid_debug_info("ssl", "verifying the peer's certificate");

    if ((x = SSL_get_peer_certificate(ssl)) != NULL) {
        if (SSL_get_verify_result(ssl)        == X509_V_OK) {

            X509_NAME_oneline(X509_get_subject_name(x), buf, 256);

            hybrid_debug_info("ssl", "client verification succeeded.");

            cert_path = hybrid_config_get_cert_path();

            if ((pos = strstr(buf, "CN="))) {
                cert_file = g_strdup_printf("%s/%s", cert_path, pos + 3);
            } else {
                cert_file = g_strdup_printf("%s/%s", cert_path, buf);
            }

            g_free(cert_path);

            f = fopen(cert_file, "w+");
            PEM_write_X509(f, x);
            fclose(f);
            g_free(cert_file);

        } else {
            hybrid_debug_error("ssl", "client verification failed.");
            return HYBRID_OK;
        }
    } else {
        hybrid_debug_error("ssl", "the peer certificate was not presented.\n");
    }

    return HYBRID_OK;
}
示例#5
0
void CertificateDialog::save()
{
	QString file = QFileDialog::getSaveFileName( this,
                tr("Guardar certificado"),
                QString( "%1%2%3.pem" )
			.arg( QDesktopServices::storageLocation( QDesktopServices::DocumentsLocation ) )
			.arg( QDir::separator() )
                        .arg( "" ),
                tr("Certificados (*.cer *.crt *.pem)") );
	if( file.isEmpty() )
		return;

        //X509 * cert = getSignerCertData(index);
        FILE *fp;
        char *_a = "a", *_w="w", *p = _w;
        //if (append) p=_a;
        fp = fopen(qPrintable(file) , p);
        if (fp != NULL) {
            if (d->internalCert){
                //if (PEM)
                if ((QFileInfo( file ).suffix().toLower() == "pem") || (QFileInfo( file ).suffix().toLower() == "crt"))
                    PEM_write_X509(fp, d->internalCert);
                else
                    i2d_X509_fp(fp, d->internalCert);
                openssl_error("");
            }
        }
        //else fopen_error(file);
        else
            QMessageBox::warning( this, tr("Guardar certificado"), tr("Error al guardar archivo") );
        fclose(fp);

/*
	QFile f( file );
	if( f.open( QIODevice::WriteOnly ) )
	{
		f.write( QFileInfo( file ).suffix().toLower() == "pem" ? d->cert.toPem() : d->cert.toDer() );
		f.close();
	}
	else
                QMessageBox::warning( this, tr("Guardar certificado"), tr("Error al guardar archivo") );
*/
}
示例#6
0
int Certificate::writePEM(FILE *fp)
{
        int res = 0;

        if (!x)
                return -4;
        
        if (!fp)
                return -5;

        res = PEM_write_X509(fp, x);

        if (res == 0) {
                writeErrors("");
                res = -6;
        } else
                res = 0;

        return res;
}
示例#7
0
文件: crypto.c 项目: seuros/VPNPivot
/* cr_load_certs : loads private key and certificates from files 
 * if cert_file and key_file are NULL , the function will generate
 * a dynamic certificate and private key
 */
void cr_load_certs(SSL_CTX *ssl,u_char *cert_file,u_char *key_file)
{
	X509 *cert = NULL;
	EVP_PKEY *pkey = NULL;
	
	if(cert_file == NULL || key_file == NULL) {
		/* generate a public certificate and a private key */
		
		cr_make_cert(&cert,&pkey,2048,0,365);

		SSL_CTX_use_certificate(ssl, cert);
		SSL_CTX_use_PrivateKey(ssl, pkey);

#ifdef CR_MK_CERT	
		RSA_print_fp(stdout,pkey->pkey.rsa,0);
		X509_print_fp(stdout,cert);
		
		PEM_write_PrivateKey(stdout,pkey,NULL,NULL,0,NULL, NULL);
		PEM_write_X509(stdout,cert);
#endif

	} else {
		if (SSL_CTX_use_certificate_file(ssl, (const char*)cert_file,
						 SSL_FILETYPE_PEM) <= 0) {
			ERR_print_errors_fp(stderr);
			exit(3);
		}
		if (SSL_CTX_use_RSAPrivateKey_file(ssl, (const char*)key_file,
						SSL_FILETYPE_PEM) <= 0) {
			ERR_print_errors_fp(stderr);
			exit(4);
		}
	}
	
	if (!SSL_CTX_check_private_key(ssl)) {
		perrx("Private key does not match the certificate public key\n");
		exit(5);
	}
	
}
示例#8
0
CAMLprim value ocaml_ssl_write_certificate(value vfilename, value certificate)
{
  CAMLparam2(vfilename, certificate);
  char *filename = String_val(vfilename);
  X509 *cert = Cert_val(certificate);
  FILE *fh = NULL;

  if((fh = fopen(filename, "w")) == NULL)
    caml_raise_constant(*caml_named_value("ssl_exn_certificate_error"));

  caml_enter_blocking_section();
  if(PEM_write_X509(fh, cert) == 0)
  {
    fclose(fh);
    caml_leave_blocking_section();
    caml_raise_constant(*caml_named_value("ssl_exn_certificate_error"));
  }
  fclose(fh);
  caml_leave_blocking_section();

  CAMLreturn(Val_unit);
}
static void handle_readcert(sc_card_t *card, int cert, char *file)
{
	sc_path_t p;
	sc_file_t *f;
	FILE *fp;
	X509 *c;
	u8 buf[1536];
	const u8 *q;
	int i, len;

	printf("\nReading Card-Certificate %d: ", cert); fflush(stdout);

	sc_format_path(certlist[cert].path,&p);
	if((i=sc_select_file(card,&p,&f))<0){
		printf("cannot select certfile, %s\n", sc_strerror(i));
		return;
	}
	if((len=sc_read_binary(card,0,buf,f->size,0))<0){
		printf("Cannot read Cert, %s\n", sc_strerror(len));
		return;
	}
	q=buf;
	if(q[0]==0x30 && q[1]==0x82 && q[4]==6 && q[5]<10 && q[q[5]+6]==0x30 && q[q[5]+7]==0x82) q+=q[5]+6;
	if((c=d2i_X509(NULL,&q,len))==NULL){
		printf("cardfile contains %d bytes which are not a certificate\n", len);
		return;
	}
	printf("Writing Cert to %s: ", file); fflush(stdout);
	if((fp=fopen(file,"w"))==NULL) printf("Cannot open file, %s\n", strerror(errno));
	else {
		fprintf(fp,"Certificate %d from Netkey E4 card\n\n", cert);
		PEM_write_X509(fp,c);
		printf("OK\n");
	}
	X509_free(c);
}
示例#10
0
文件: dtls.c 项目: cahlbin/rtpengine
static void dump_cert(struct dtls_cert *cert) {
	FILE *fp;
	char *buf;
	size_t len;

	if (get_log_level() < LOG_DEBUG)
		return;

	/* cert */
	fp = open_memstream(&buf, &len);
	PEM_write_X509(fp, cert->x509);
	fclose(fp);

	ilog(LOG_DEBUG, "Dump of DTLS certificate:");
	buf_dump_free(buf, len);

	/* key */
	fp = open_memstream(&buf, &len);
	PEM_write_PrivateKey(fp, cert->pkey, NULL, NULL, 0, 0, NULL);
	fclose(fp);

	ilog(LOG_DEBUG, "Dump of DTLS private key:");
	buf_dump_free(buf, len);
}
示例#11
0
void makersacert(int days, char* commonname, int bits)
{
	RSA *key;
	EVP_PKEY *pkey;
	X509 *x;
	FILE *out;

	key = RSA_generate_key(bits, RSA_F4, NULL, NULL);
	pkey = EVP_PKEY_new();
	EVP_PKEY_set1_RSA(pkey, key);

	x = makeselfcert(pkey, days, commonname, EVP_sha256());

	out = fopen("rsa_cert.pem", "w");
	if (out == NULL)
		exit(-1);
	PEM_write_X509(out, x);
	fclose(out);
	out = fopen("rsa_cert_key.pem", "w");
	if (out == NULL)
		exit(-1);
	PEM_write_RSAPrivateKey(out, key, NULL, NULL, 0, NULL, NULL);
	fclose(out);
}
static int
do_ca_cert_bootstrap(struct vconn *vconn)
{
    struct ssl_vconn *sslv = ssl_vconn_cast(vconn);
    STACK_OF(X509) *chain;
    X509 *ca_cert;
    FILE *file;
    int error;
    int fd;

    chain = SSL_get_peer_cert_chain(sslv->ssl);
    if (!chain || !sk_X509_num(chain)) {
        VLOG_ERR("could not bootstrap CA cert: no certificate presented by "
                 "peer");
        return EPROTO;
    }
    ca_cert = sk_X509_value(chain, sk_X509_num(chain) - 1);

    /* Check that 'ca_cert' is self-signed.  Otherwise it is not a CA
     * certificate and we should not attempt to use it as one. */
    error = X509_check_issued(ca_cert, ca_cert);
    if (error) {
        VLOG_ERR("could not bootstrap CA cert: obtained certificate is "
                 "not self-signed (%s)",
                 X509_verify_cert_error_string(error));
        if (sk_X509_num(chain) < 2) {
            VLOG_ERR("only one certificate was received, so probably the peer "
                     "is not configured to send its CA certificate");
        }
        return EPROTO;
    }

    fd = open(ca_cert_file, O_CREAT | O_EXCL | O_WRONLY, 0444);
    if (fd < 0) {
        VLOG_ERR("could not bootstrap CA cert: creating %s failed: %s",
                 ca_cert_file, strerror(errno));
        return errno;
    }

    file = fdopen(fd, "w");
    if (!file) {
        int error = errno;
        VLOG_ERR("could not bootstrap CA cert: fdopen failed: %s",
                 strerror(error));
        unlink(ca_cert_file);
        return error;
    }

    if (!PEM_write_X509(file, ca_cert)) {
        VLOG_ERR("could not bootstrap CA cert: PEM_write_X509 to %s failed: "
                 "%s", ca_cert_file, ERR_error_string(ERR_get_error(), NULL));
        fclose(file);
        unlink(ca_cert_file);
        return EIO;
    }

    if (fclose(file)) {
        int error = errno;
        VLOG_ERR("could not bootstrap CA cert: writing %s failed: %s",
                 ca_cert_file, strerror(error));
        unlink(ca_cert_file);
        return error;
    }

    VLOG_INFO("successfully bootstrapped CA cert to %s", ca_cert_file);
    log_ca_cert(ca_cert_file, ca_cert);
    bootstrap_ca_cert = false;
    has_ca_cert = true;

    /* SSL_CTX_add_client_CA makes a copy of ca_cert's relevant data. */
    SSL_CTX_add_client_CA(ctx, ca_cert);

    /* SSL_CTX_use_certificate() takes ownership of the certificate passed in.
     * 'ca_cert' is owned by sslv->ssl, so we need to duplicate it. */
    ca_cert = X509_dup(ca_cert);
    if (!ca_cert) {
        out_of_memory();
    }
    if (SSL_CTX_load_verify_locations(ctx, ca_cert_file, NULL) != 1) {
        VLOG_ERR("SSL_CTX_load_verify_locations: %s",
                 ERR_error_string(ERR_get_error(), NULL));
        return EPROTO;
    }
    VLOG_INFO("killing successful connection to retry using CA cert");
    return EPROTO;
}
示例#13
0
文件: crypto.c 项目: henri14/citadel
/*
 * 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()));
	}
	
}
示例#14
0
文件: stream-ssl.c 项目: M3S/ovs-rstp
static int
do_ca_cert_bootstrap(struct stream *stream)
{
    struct ssl_stream *sslv = ssl_stream_cast(stream);
    STACK_OF(X509) *chain;
    X509 *cert;
    FILE *file;
    int error;
    int fd;

    chain = SSL_get_peer_cert_chain(sslv->ssl);
    if (!chain || !sk_X509_num(chain)) {
        VLOG_ERR("could not bootstrap CA cert: no certificate presented by "
                 "peer");
        return EPROTO;
    }
    cert = sk_X509_value(chain, sk_X509_num(chain) - 1);

    /* Check that 'cert' is self-signed.  Otherwise it is not a CA
     * certificate and we should not attempt to use it as one. */
    error = X509_check_issued(cert, cert);
    if (error) {
        VLOG_ERR("could not bootstrap CA cert: obtained certificate is "
                 "not self-signed (%s)",
                 X509_verify_cert_error_string(error));
        if (sk_X509_num(chain) < 2) {
            VLOG_ERR("only one certificate was received, so probably the peer "
                     "is not configured to send its CA certificate");
        }
        return EPROTO;
    }

    fd = open(ca_cert.file_name, O_CREAT | O_EXCL | O_WRONLY, 0444);
    if (fd < 0) {
        if (errno == EEXIST) {
            VLOG_INFO_RL(&rl, "reading CA cert %s created by another process",
                         ca_cert.file_name);
            stream_ssl_set_ca_cert_file__(ca_cert.file_name, true, true);
            return EPROTO;
        } else {
            VLOG_ERR("could not bootstrap CA cert: creating %s failed: %s",
                     ca_cert.file_name, ovs_strerror(errno));
            return errno;
        }
    }

    file = fdopen(fd, "w");
    if (!file) {
        error = errno;
        VLOG_ERR("could not bootstrap CA cert: fdopen failed: %s",
                 ovs_strerror(error));
        unlink(ca_cert.file_name);
        return error;
    }

    if (!PEM_write_X509(file, cert)) {
        VLOG_ERR("could not bootstrap CA cert: PEM_write_X509 to %s failed: "
                 "%s", ca_cert.file_name,
                 ERR_error_string(ERR_get_error(), NULL));
        fclose(file);
        unlink(ca_cert.file_name);
        return EIO;
    }

    if (fclose(file)) {
        error = errno;
        VLOG_ERR("could not bootstrap CA cert: writing %s failed: %s",
                 ca_cert.file_name, ovs_strerror(error));
        unlink(ca_cert.file_name);
        return error;
    }

    VLOG_INFO("successfully bootstrapped CA cert to %s", ca_cert.file_name);
    log_ca_cert(ca_cert.file_name, cert);
    bootstrap_ca_cert = false;
    ca_cert.read = true;

    /* SSL_CTX_add_client_CA makes a copy of cert's relevant data. */
    SSL_CTX_add_client_CA(ctx, cert);

    SSL_CTX_set_cert_store(ctx, X509_STORE_new());
    if (SSL_CTX_load_verify_locations(ctx, ca_cert.file_name, NULL) != 1) {
        VLOG_ERR("SSL_CTX_load_verify_locations: %s",
                 ERR_error_string(ERR_get_error(), NULL));
        return EPROTO;
    }
    VLOG_INFO("killing successful connection to retry using CA cert");
    return EPROTO;
}
示例#15
0
static int interactive_check_cert (X509 *cert, int idx, int len)
{
        static const char * const part[] =
                {"/CN=", "/Email=", "/O=", "/OU=", "/L=", "/ST=", "/C="};
        char helpstr[LONG_STRING];
        char buf[STRING];
        char title[STRING];
        MUTTMENU *menu = mutt_new_menu (-1);
        int done, row, i;
        FILE *fp;
        char *name = NULL, *c;

        dprint (2, (debugfile, "interactive_check_cert: %s\n", cert->name));

        menu->max = 19;
        menu->dialog = (char **) safe_calloc (1, menu->max * sizeof (char *));
        for (i = 0; i < menu->max; i++)
                menu->dialog[i] = (char *) safe_calloc (1, SHORT_STRING * sizeof (char));

        row = 0;
        strfcpy (menu->dialog[row], _("This certificate belongs to:"), SHORT_STRING);
        row++;
        name = X509_NAME_oneline (X509_get_subject_name (cert),
                buf, sizeof (buf));
        dprint (2, (debugfile, "oneline: %s\n", name));

        for (i = 0; i < 5; i++) {
                c = x509_get_part (name, part[i]);
                snprintf (menu->dialog[row++], SHORT_STRING, "   %s", c);
        }

        row++;
        strfcpy (menu->dialog[row], _("This certificate was issued by:"), SHORT_STRING);
        row++;
        name = X509_NAME_oneline (X509_get_issuer_name (cert),
                buf, sizeof (buf));
        for (i = 0; i < 5; i++) {
                c = x509_get_part (name, part[i]);
                snprintf (menu->dialog[row++], SHORT_STRING, "   %s", c);
        }

        row++;
        snprintf (menu->dialog[row++], SHORT_STRING, _("This certificate is valid"));
        snprintf (menu->dialog[row++], SHORT_STRING, _("   from %s"),
                asn1time_to_string (X509_get_notBefore (cert)));
        snprintf (menu->dialog[row++], SHORT_STRING, _("     to %s"),
                asn1time_to_string (X509_get_notAfter (cert)));

        row++;
        buf[0] = '\0';
        x509_fingerprint (buf, sizeof (buf), cert);
        snprintf (menu->dialog[row++], SHORT_STRING, _("Fingerprint: %s"), buf);

        snprintf (title, sizeof (title),
                _("SSL Certificate check (certificate %d of %d in chain)"),
                len - idx, len);
        menu->title = title;
        if (SslCertFile
                && (option (OPTSSLVERIFYDATES) == M_NO
                || (X509_cmp_current_time (X509_get_notAfter (cert)) >= 0
        && X509_cmp_current_time (X509_get_notBefore (cert)) < 0))) {
                menu->prompt = _("(r)eject, accept (o)nce, (a)ccept always");
                menu->keys = _("roa");
        }
        else {
                menu->prompt = _("(r)eject, accept (o)nce");
                menu->keys = _("ro");
        }

        helpstr[0] = '\0';
        mutt_make_help (buf, sizeof (buf), _("Exit  "), MENU_GENERIC, OP_EXIT);
        safe_strcat (helpstr, sizeof (helpstr), buf);
        mutt_make_help (buf, sizeof (buf), _("Help"), MENU_GENERIC, OP_HELP);
        safe_strcat (helpstr, sizeof (helpstr), buf);
        menu->help = helpstr;

        done = 0;
        set_option(OPTUNBUFFEREDINPUT);
        while (!done) {
                switch (mutt_menuLoop (menu)) {
                        case -1:                  /* abort */
                        case OP_MAX + 1:          /* reject */
                        case OP_EXIT:
                                done = 1;
                                break;
                        case OP_MAX + 3:          /* accept always */
                                done = 0;
                                if ((fp = fopen (SslCertFile, "a"))) {
                                        if (PEM_write_X509 (fp, cert))
                                                done = 1;
                                        safe_fclose (&fp);
                                }
                                if (!done) {
                                        mutt_error (_("Warning: Couldn't save certificate"));
                                        mutt_sleep (2);
                                }
                                else {
                                        mutt_message (_("Certificate saved"));
                                        mutt_sleep (0);
                                }
/* fall through */
                        case OP_MAX + 2:          /* accept once */
                                done = 2;
                                ssl_cache_trusted_cert (cert);
                                break;
                }
        }
        unset_option(OPTUNBUFFEREDINPUT);
        mutt_menuDestroy (&menu);
        dprint (2, (debugfile, "ssl interactive_check_cert: done=%d\n", done));
        return (done == 2);
}
示例#16
0
文件: ssl.c 项目: darnir/neomutt
/**
 * interactive_check_cert - Ask the user if a certificate is valid
 * @param cert         Certificate
 * @param idx          Place of certificate in the chain
 * @param len          Length of the certificate chain
 * @param ssl          SSL state
 * @param allow_always If certificate may be always allowed
 * @retval true  User selected 'skip'
 * @retval false Otherwise
 */
static bool interactive_check_cert(X509 *cert, int idx, size_t len, SSL *ssl, bool allow_always)
{
  static const int part[] = {
    NID_commonName,             /* CN */
    NID_pkcs9_emailAddress,     /* Email */
    NID_organizationName,       /* O */
    NID_organizationalUnitName, /* OU */
    NID_localityName,           /* L */
    NID_stateOrProvinceName,    /* ST */
    NID_countryName,            /* C */
  };
  X509_NAME *x509_subject = NULL;
  X509_NAME *x509_issuer = NULL;
  char helpstr[1024];
  char buf[256];
  char title[256];
  struct Menu *menu = mutt_menu_new(MENU_GENERIC);
  int done, row;
  FILE *fp = NULL;
  int ALLOW_SKIP = 0; /* All caps tells Coverity that this is effectively a preproc condition */

  mutt_menu_push_current(menu);

  menu->max = mutt_array_size(part) * 2 + 11;
  menu->dialog = mutt_mem_calloc(1, menu->max * sizeof(char *));
  for (int i = 0; i < menu->max; i++)
    menu->dialog[i] = mutt_mem_calloc(1, dialog_row_len * sizeof(char));

  row = 0;
  mutt_str_strfcpy(menu->dialog[row], _("This certificate belongs to:"), dialog_row_len);
  row++;
  x509_subject = X509_get_subject_name(cert);
  for (unsigned int u = 0; u < mutt_array_size(part); u++)
  {
    snprintf(menu->dialog[row++], dialog_row_len, "   %s",
             x509_get_part(x509_subject, part[u]));
  }

  row++;
  mutt_str_strfcpy(menu->dialog[row], _("This certificate was issued by:"), dialog_row_len);
  row++;
  x509_issuer = X509_get_issuer_name(cert);
  for (unsigned int u = 0; u < mutt_array_size(part); u++)
  {
    snprintf(menu->dialog[row++], dialog_row_len, "   %s",
             x509_get_part(x509_issuer, part[u]));
  }

  row++;
  snprintf(menu->dialog[row++], dialog_row_len, "%s", _("This certificate is valid"));
  snprintf(menu->dialog[row++], dialog_row_len, _("   from %s"),
           asn1time_to_string(X509_getm_notBefore(cert)));
  snprintf(menu->dialog[row++], dialog_row_len, _("     to %s"),
           asn1time_to_string(X509_getm_notAfter(cert)));

  row++;
  buf[0] = '\0';
  x509_fingerprint(buf, sizeof(buf), cert, EVP_sha1);
  snprintf(menu->dialog[row++], dialog_row_len, _("SHA1 Fingerprint: %s"), buf);
  buf[0] = '\0';
  buf[40] = '\0'; /* Ensure the second printed line is null terminated */
  x509_fingerprint(buf, sizeof(buf), cert, EVP_sha256);
  buf[39] = '\0'; /* Divide into two lines of output */
  snprintf(menu->dialog[row++], dialog_row_len, "%s%s", _("SHA256 Fingerprint: "), buf);
  snprintf(menu->dialog[row++], dialog_row_len, "%*s%s",
           (int) mutt_str_strlen(_("SHA256 Fingerprint: ")), "", buf + 40);

  snprintf(title, sizeof(title),
           _("SSL Certificate check (certificate %zu of %zu in chain)"), len - idx, len);
  menu->title = title;

/* The leaf/host certificate can't be skipped. */
#ifdef HAVE_SSL_PARTIAL_CHAIN
  if ((idx != 0) && C_SslVerifyPartialChains)
    ALLOW_SKIP = 1;
#endif

  /* Inside ssl_verify_callback(), this function is guarded by a call to
   * check_certificate_by_digest().  This means if check_certificate_expiration() is
   * true, then check_certificate_file() must be false.  Therefore we don't need
   * to also scan the certificate file here.  */
  allow_always = allow_always && C_CertificateFile &&
                 check_certificate_expiration(cert, true);

  /* L10N: These four letters correspond to the choices in the next four strings:
     (r)eject, accept (o)nce, (a)ccept always, (s)kip.
     These prompts are the interactive certificate confirmation prompts for
     an OpenSSL connection. */
  menu->keys = _("roas");
  if (allow_always)
  {
    if (ALLOW_SKIP)
      menu->prompt = _("(r)eject, accept (o)nce, (a)ccept always, (s)kip");
    else
      menu->prompt = _("(r)eject, accept (o)nce, (a)ccept always");
  }
  else
  {
    if (ALLOW_SKIP)
      menu->prompt = _("(r)eject, accept (o)nce, (s)kip");
    else
      menu->prompt = _("(r)eject, accept (o)nce");
  }

  helpstr[0] = '\0';
  mutt_make_help(buf, sizeof(buf), _("Exit  "), MENU_GENERIC, OP_EXIT);
  mutt_str_strcat(helpstr, sizeof(helpstr), buf);
  mutt_make_help(buf, sizeof(buf), _("Help"), MENU_GENERIC, OP_HELP);
  mutt_str_strcat(helpstr, sizeof(helpstr), buf);
  menu->help = helpstr;

  done = 0;
  OptIgnoreMacroEvents = true;
  while (done == 0)
  {
    switch (mutt_menu_loop(menu))
    {
      case -1:         /* abort */
      case OP_MAX + 1: /* reject */
      case OP_EXIT:
        done = 1;
        break;
      case OP_MAX + 3: /* accept always */
        if (!allow_always)
          break;
        done = 0;
        fp = fopen(C_CertificateFile, "a");
        if (fp)
        {
          if (PEM_write_X509(fp, cert))
            done = 1;
          mutt_file_fclose(&fp);
        }
        if (done == 0)
        {
          mutt_error(_("Warning: Couldn't save certificate"));
        }
        else
        {
          mutt_message(_("Certificate saved"));
          mutt_sleep(0);
        }
      /* fallthrough */
      case OP_MAX + 2: /* accept once */
        done = 2;
        SSL_set_ex_data(ssl, SkipModeExDataIndex, NULL);
        ssl_cache_trusted_cert(cert);
        break;
      case OP_MAX + 4: /* skip */
        if (!ALLOW_SKIP)
          break;
        done = 2;
        SSL_set_ex_data(ssl, SkipModeExDataIndex, &SkipModeExDataIndex);
        break;
    }
  }
  OptIgnoreMacroEvents = false;
  mutt_menu_pop_current(menu);
  mutt_menu_destroy(&menu);
  mutt_debug(LL_DEBUG2, "done=%d\n", done);
  return done == 2;
}
示例#17
0
int ssl_server_init()
{
    /*
     * This is twisted. We can generate the required keys by calling RSA_generate_key,
     * however we cannot put the private part and the public part in the two containers.
     * For that we need to save each part to a file and then load each part from
     * the respective file.
     */
    RSA *key = NULL;
    key = RSA_generate_key(1024, 17, NULL, NULL);
    if (!key)
    {
        correctly_initialized = false;
        return -1;
    }
    char name_template_private[] = "/tmp/tls_test/abcdefXXXXXX";
    int private_key_file = 0;
    FILE *private_key_stream = NULL;
    int ret = 0;

    private_key_file = mkstemp(name_template_private);
    if (private_key_file < 0)
    {
        correctly_initialized = false;
        return -1;
    }
    private_key_stream = fdopen(private_key_file, "w+");
    if (!private_key_stream)
    {
        correctly_initialized = false;
        return -1;
    }
    ret = PEM_write_RSAPrivateKey(private_key_stream, key, NULL, NULL, 0, 0, NULL);
    if (ret == 0)
    {
        correctly_initialized = false;
        return -1;
    }
    fseek(private_key_stream, 0L, SEEK_SET);
    PRIVKEY = PEM_read_RSAPrivateKey(private_key_stream, (RSA **)NULL, NULL, NULL);
    if (!PRIVKEY)
    {
        correctly_initialized = false;
        return -1;
    }
    fclose(private_key_stream);

    int public_key_file = 0;
    FILE *public_key_stream = NULL;
    public_key_file = mkstemp(server_name_template_public);
    if (public_key_file < 0)
    {
        correctly_initialized = false;
        return -1;
    }
    server_public_key_file = public_key_file;
    public_key_stream = fdopen(public_key_file, "w+");
    if (!public_key_stream)
    {
        correctly_initialized = false;
        return -1;
    }
    ret = PEM_write_RSAPublicKey(public_key_stream, key);
    if (ret == 0)
    {
        correctly_initialized = false;
        return -1;
    }
    fflush(public_key_stream);
    fsync(public_key_file);
    fseek(public_key_stream, 0L, SEEK_SET);
    PUBKEY = PEM_read_RSAPublicKey(public_key_stream, (RSA **)NULL, NULL, NULL);
    if (!PUBKEY)
    {
        correctly_initialized = false;
        return -1;
    }
    RSA_free(key);

    assert(SSLSERVERCONTEXT == NULL);
    SSLSERVERCONTEXT = SSL_CTX_new(SSLv23_server_method());
    if (SSLSERVERCONTEXT == NULL)
    {
        Log(LOG_LEVEL_ERR, "SSL_CTX_new: %s",
            ERR_reason_error_string(ERR_get_error()));
        goto err1;
    }

    /* Use only TLS v1 or later.
       TODO option for SSL_OP_NO_TLSv{1,1_1} */
    SSL_CTX_set_options(SSLSERVERCONTEXT,
                        SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);

    /* Never bother with retransmissions, SSL_write() should
     * always either write the whole amount or fail. */
    SSL_CTX_set_mode(SSLSERVERCONTEXT, SSL_MODE_AUTO_RETRY);

    /*
     * Create cert into memory and load it into SSL context.
     */

    if (PRIVKEY == NULL || PUBKEY == NULL)
    {
        Log(LOG_LEVEL_ERR,
            "No public/private key pair is loaded, create one with cf-key");
        goto err2;
    }
    assert(SSLSERVERCERT == NULL);
    /* Generate self-signed cert valid from now to 50 years later. */
    {
        X509 *x509 = X509_new();
        X509_gmtime_adj(X509_get_notBefore(x509), 0);
        X509_time_adj(X509_get_notAfter(x509), 60*60*24*365*50, NULL);
        EVP_PKEY *pkey = EVP_PKEY_new();
        EVP_PKEY_set1_RSA(pkey, PRIVKEY);
        X509_NAME *name = X509_get_subject_name(x509);
        X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
                                   (const char *) "",
                                   -1, -1, 0);
        X509_set_issuer_name(x509, name);
        X509_set_pubkey(x509, pkey);

        const EVP_MD *md = EVP_get_digestbyname("sha384");
        if (md == NULL)
        {
            Log(LOG_LEVEL_ERR, "Uknown digest algorithm %s",
                "sha384");
            correctly_initialized = false;
            return -1;
        }
        ret = X509_sign(x509, pkey, md);

        EVP_PKEY_free(pkey);
        SSLSERVERCERT = x509;

        if (ret <= 0)
        {
            Log(LOG_LEVEL_ERR,
                "Couldn't sign the public key for the TLS handshake: %s",
                ERR_reason_error_string(ERR_get_error()));
            goto err3;
        }
        /*
         * Create a temporary file and save the certificate there
         */
        certificate_file = mkstemp(server_certificate_template_public);
        if (certificate_file < 0)
        {
            correctly_initialized = false;
            return -1;
        }
        FILE *certificate_stream = fdopen(certificate_file, "w+");
        if (!certificate_stream)
        {
            correctly_initialized = false;
            return -1;
        }
        PEM_write_X509(certificate_stream, x509);
        fflush(certificate_stream);
        fsync(certificate_file);
    }

    SSL_CTX_use_certificate(SSLSERVERCONTEXT, SSLSERVERCERT);

    ret = SSL_CTX_use_RSAPrivateKey(SSLSERVERCONTEXT, PRIVKEY);
    if (ret != 1)
    {
        Log(LOG_LEVEL_ERR, "Failed to use RSA private key: %s",
            ERR_reason_error_string(ERR_get_error()));
        goto err3;
    }

    /* Verify cert consistency. */
    ret = SSL_CTX_check_private_key(SSLSERVERCONTEXT);
    if (ret != 1)
    {
        Log(LOG_LEVEL_ERR, "Inconsistent key and TLS cert: %s",
            ERR_reason_error_string(ERR_get_error()));
        goto err3;
    }

    /* Set options to always request a certificate from the peer, either we
     * are client or server. */
    SSL_CTX_set_verify(SSLSERVERCONTEXT, SSL_VERIFY_PEER, NULL);
    /* Always accept that certificate, we do proper checking after TLS
     * connection is established since OpenSSL can't pass a connection
     * specific pointer to the callback (so we would have to lock).  */
    SSL_CTX_set_cert_verify_callback(SSLSERVERCONTEXT, TLSVerifyCallback, NULL);
    correctly_initialized = true;
    return 0;
  err3:
    X509_free(SSLSERVERCERT);
    SSLSERVERCERT = NULL;
  err2:
    SSL_CTX_free(SSLSERVERCONTEXT);
    SSLSERVERCONTEXT = NULL;
  err1:
    correctly_initialized = false;
    return -1;
}
示例#18
0
文件: sscep.c 项目: flomar/sscep
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);
}
示例#19
0
int
main(int argc, char **argv) {
  FILE           *fp   = NULL;
  EVP_PKEY       *pkey = NULL;
  X509           *cert = NULL;
  STACK_OF(X509) *ca   = NULL;
  PKCS12         *p12  = NULL;

  char *pass = strdup("");
  int  i;

  if (argc != 2) {
    fprintf(stderr, "[!] Usage: %s certificate.p12\n", argv[0]);
    exit(1);
  }

  printf("[+] Initializing OpenSSL\n");
  SSLeay_add_all_algorithms();
  ERR_load_crypto_strings();

  printf("[+] Opening PKCS#12 certificate\n");
  if (!(fp = fopen(argv[1], "r"))) {
    fprintf(stderr, "[!] Unable to open certificate `%s'\n", argv[1]);
    goto endpkcs12;
  }

  if (chdir(dirname(argv[1])) == -1) {
    fprintf(stderr, "[!] Unable to change directory to `%s'\n",
	    dirname(argv[1]));
    goto endpkcs12;
  }
  p12 = d2i_PKCS12_fp(fp, NULL);
  fclose(fp); fp = NULL;
  if (!p12) {
    fprintf(stderr, "[!] Unable to parse PKCS#12 certificate: %s\n",
	    ERR_reason_error_string(ERR_get_error()));
    goto endpkcs12;
  }
  while (!PKCS12_parse(p12, pass, &pkey, &cert, &ca)) {
    ca = NULL;
    free(pass);
    if (getpassword("[?] Password: "******"[!] PKCS#12 certificate is incomplete\n");
    goto endpkcs12;
  }

#define PEM_w(path, call) \
  do {									\
    if (!(fp = fopen(path, "w"))) {					\
      fprintf(stderr, "[!] Unable to open `%s'\n", path);		\
      goto endpkcs12;							\
    }									\
    printf("[+] Write certificate to `%s'\n", path);			\
    call;								\
    fclose(fp); fp = NULL;						\
  } while(0)
    
  PEM_w("user.pem", PEM_write_X509(fp, cert));
  PEM_w("user.key",  PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL));
  PEM_w("cacert.pem",
	for (i = 0; i < sk_X509_num(ca); i++)
	  PEM_write_X509(fp, sk_X509_value(ca, i)));
  sk_free(ca); X509_free(cert); EVP_PKEY_free(pkey);
  exit(0);

 endpkcs12:
  if (pass) free(pass);
  if (ca) sk_free(ca);
  if (cert) X509_free(cert);
  if (pkey) EVP_PKEY_free(pkey);
  if (p12) PKCS12_free(p12);
  if (fp) fclose(fp);
  exit(1);
}
示例#20
0
SWITCH_DECLARE(int) switch_core_gen_certs(const char *prefix)
{
	//BIO *bio_err;
	X509 *x509 = NULL;
	EVP_PKEY *pkey = NULL;
	char *rsa = NULL, *pvt = NULL;
	FILE *fp;
	char *pem = NULL;

	if (switch_stristr(".pem", prefix)) {

		if (switch_is_file_path(prefix)) {
			pem = strdup(prefix);
		} else {
			pem = switch_mprintf("%s%s%s", SWITCH_GLOBAL_dirs.certs_dir, SWITCH_PATH_SEPARATOR, prefix);
		}

		if (switch_file_exists(pem, NULL) == SWITCH_STATUS_SUCCESS) {
			goto end;
		}
	} else {
		if (switch_is_file_path(prefix)) {
			pvt = switch_mprintf("%s.key", prefix);
			rsa = switch_mprintf("%s.crt", prefix);
		} else {
			pvt = switch_mprintf("%s%s%s.key", SWITCH_GLOBAL_dirs.certs_dir, SWITCH_PATH_SEPARATOR, prefix);
			rsa = switch_mprintf("%s%s%s.crt", SWITCH_GLOBAL_dirs.certs_dir, SWITCH_PATH_SEPARATOR, prefix);
		}

		if (switch_file_exists(pvt, NULL) == SWITCH_STATUS_SUCCESS || switch_file_exists(rsa, NULL) == SWITCH_STATUS_SUCCESS) {
			goto end;
		}
	}

	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
		
	//bio_err=BIO_new_fp(stderr, BIO_NOCLOSE);
		
	mkcert(&x509, &pkey, 1024, 0, 36500);

	//RSA_print_fp(stdout, pkey->pkey.rsa, 0);
	//X509_print_fp(stdout, x509);

	if (pem) {
		if ((fp = fopen(pem, "w"))) {
			PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL);
			PEM_write_X509(fp, x509);
			fclose(fp);
		}

	} else {
		if (pvt && (fp = fopen(pvt, "w"))) {
			PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL);
			fclose(fp);
		}
		
		if (rsa && (fp = fopen(rsa, "w"))) {
			PEM_write_X509(fp, x509);
			fclose(fp);
		}
	}

	X509_free(x509);
	EVP_PKEY_free(pkey);

#ifndef OPENSSL_NO_ENGINE
	ENGINE_cleanup();
#endif
	CRYPTO_cleanup_all_ex_data();

	//CRYPTO_mem_leaks(bio_err);
	//BIO_free(bio_err);


 end:

	switch_safe_free(pvt);
	switch_safe_free(rsa);
	switch_safe_free(pem);

	return(0);
}
示例#21
0
文件: 2cca.c 项目: randunel/2cca
/*
 * Create identity
 */
int build_identity(void)
{
    EVP_PKEY * pkey ;
    RSA * rsa ;
    EC_KEY * ecc ;
    X509 * cert ;
    X509_NAME * name ;
    identity ca ;
    char filename[FIELD_SZ+5];
    FILE * pem ;

    /* Check before overwriting */
    sprintf(filename, "%s.crt", certinfo.cn);
    if (access(filename, F_OK)!=-1) {
        fprintf(stderr, "identity named %s already exists in this directory. Exiting now\n", filename);
        return -1 ;
    }
    sprintf(filename, "%s.key", certinfo.cn);
    if (access(filename, F_OK)!=-1) {
        fprintf(stderr, "identity named %s already exists in this directory. Exiting now\n", filename);
        return -1 ;
    }

    switch (certinfo.profile) {
        case PROFILE_ROOT_CA:
        strcpy(certinfo.ou, "Root");
        break;

        case PROFILE_SUB_CA:
        strcpy(certinfo.ou, "Sub");
        break;

        case PROFILE_SERVER:
        strcpy(certinfo.ou, "Server");
        break;
        
        case PROFILE_CLIENT:
        strcpy(certinfo.ou, "Client");
        break;

        case PROFILE_WWW:
        strcpy(certinfo.ou, "Server");
        break;

        default:
        fprintf(stderr, "Unknown profile: aborting\n");
        return -1 ;
    }

    if (certinfo.ec_name[0] && certinfo.profile!=PROFILE_CLIENT) {
        fprintf(stderr, "ECC keys are only supported for clients\n");
        return -1 ;
    }

    if (certinfo.profile != PROFILE_ROOT_CA) {
        /* Need to load signing CA */
        if (load_ca(certinfo.signing_ca, &ca)!=0) {
            fprintf(stderr, "Cannot find CA key or certificate\n");
            return -1 ;
        }
        /* Organization is the same as root */
        X509_NAME_get_text_by_NID(X509_get_subject_name(ca.cert),
                                  NID_organizationName,
                                  certinfo.o,
                                  FIELD_SZ);
    }

    /* Generate key pair */
    if (certinfo.ec_name[0]) {
        printf("Generating EC key [%s]\n", certinfo.ec_name);
        ecc = EC_KEY_new_by_curve_name(OBJ_txt2nid(certinfo.ec_name));
        if (!ecc) {
            fprintf(stderr, "Unknown curve: [%s]\n", certinfo.ec_name);
            return -1 ;
        }
        EC_KEY_set_asn1_flag(ecc, OPENSSL_EC_NAMED_CURVE);
        EC_KEY_generate_key(ecc);
        pkey = EVP_PKEY_new();
        EVP_PKEY_assign_EC_KEY(pkey, ecc);
    } else {
        printf("Generating RSA-%d key\n", certinfo.rsa_keysz);
        pkey = EVP_PKEY_new();
        rsa = RSA_generate_key(certinfo.rsa_keysz, RSA_F4, progress, 0);
        EVP_PKEY_assign_RSA(pkey, rsa);
    }

    /* Assign all certificate fields */
    cert = X509_new();
    X509_set_version(cert, 2);
    set_serial128(cert);
    X509_gmtime_adj(X509_get_notBefore(cert), 0);
    X509_gmtime_adj(X509_get_notAfter(cert), certinfo.days * 24*60*60);
    X509_set_pubkey(cert, pkey);

    name = X509_get_subject_name(cert);
    if (certinfo.c[0]) {
        X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char*)certinfo.c, -1, -1, 0);
    }
    X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, (unsigned char*)certinfo.o, -1, -1, 0);
    X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char*)certinfo.cn, -1, -1, 0);
    X509_NAME_add_entry_by_txt(name, "OU", MBSTRING_ASC, (unsigned char*)certinfo.ou, -1, -1, 0);
    if (certinfo.l[0]) {
        X509_NAME_add_entry_by_txt(name, "L", MBSTRING_ASC, (unsigned char *)certinfo.l, -1, -1, 0);
    }
    if (certinfo.st[0]) {
        X509_NAME_add_entry_by_txt(name, "ST", MBSTRING_ASC, (unsigned char *)certinfo.st, -1, -1, 0);
    }

    /* Set extensions according to profile */
    switch (certinfo.profile) {
        case PROFILE_ROOT_CA:
        /* CA profiles can issue certs and sign CRLS */
        set_extension(cert, cert, NID_basic_constraints, "critical,CA:TRUE");
        set_extension(cert, cert, NID_key_usage, "critical,keyCertSign,cRLSign");
        set_extension(cert, cert, NID_subject_key_identifier, "hash");
        set_extension(cert, cert, NID_authority_key_identifier, "keyid:always");
        break ;

        case PROFILE_SUB_CA:
        /* CA profiles can issue certs and sign CRLS */
        set_extension(ca.cert, cert, NID_basic_constraints, "critical,CA:TRUE");
        set_extension(ca.cert, cert, NID_key_usage, "critical,keyCertSign,cRLSign");
        set_extension(ca.cert, cert, NID_subject_key_identifier, "hash");
        set_extension(ca.cert, cert, NID_authority_key_identifier, "keyid:always");
        break;

        case PROFILE_CLIENT:
        if (certinfo.san[0]) {
            set_extension(ca.cert, cert, NID_subject_alt_name, certinfo.san);
        }
        set_extension(ca.cert, cert, NID_basic_constraints, "CA:FALSE");
        set_extension(ca.cert, cert, NID_anyExtendedKeyUsage, "clientAuth");
        set_extension(ca.cert, cert, NID_key_usage, "digitalSignature");
        set_extension(ca.cert, cert, NID_subject_key_identifier, "hash");
        set_extension(ca.cert, cert, NID_authority_key_identifier, "issuer:always,keyid:always");
        break ;

        case PROFILE_SERVER:
        if (certinfo.san[0]) {
            set_extension(ca.cert, cert, NID_subject_alt_name, certinfo.san);
        }
        set_extension(ca.cert, cert, NID_basic_constraints, "CA:FALSE");
        set_extension(ca.cert, cert, NID_netscape_cert_type, "server");
        set_extension(ca.cert, cert, NID_anyExtendedKeyUsage, "serverAuth");
        set_extension(ca.cert, cert, NID_key_usage, "digitalSignature,keyEncipherment");
        set_extension(ca.cert, cert, NID_subject_key_identifier, "hash");
        set_extension(ca.cert, cert, NID_authority_key_identifier, "issuer:always,keyid:always");
        break ;

        case PROFILE_WWW:
        if (certinfo.san[0]) {
            set_extension(ca.cert, cert, NID_subject_alt_name, certinfo.san);
        }
        set_extension(ca.cert, cert, NID_basic_constraints, "CA:FALSE");
        set_extension(ca.cert, cert, NID_netscape_cert_type, "server");
        set_extension(ca.cert, cert, NID_anyExtendedKeyUsage, "serverAuth,clientAuth");
        set_extension(ca.cert, cert, NID_key_usage, "digitalSignature,keyEncipherment");
        set_extension(ca.cert, cert, NID_subject_key_identifier, "hash");
        set_extension(ca.cert, cert, NID_authority_key_identifier, "issuer:always,keyid:always");
        break;

        case PROFILE_UNKNOWN:
        default:
        break ;
    }
    /* Set issuer */
    if (certinfo.profile==PROFILE_ROOT_CA) {
        /* Self-signed */
        X509_set_issuer_name(cert, name);
        X509_sign(cert, pkey, EVP_sha256());
    } else {
        /* Signed by parent CA */
        X509_set_issuer_name(cert, X509_get_subject_name(ca.cert));
        X509_sign(cert, ca.key, EVP_sha256());
    }

    printf("Saving results to %s.[crt|key]\n", certinfo.cn);
    pem = fopen(filename, "wb");
    PEM_write_PrivateKey(pem, pkey, NULL, NULL, 0, NULL, NULL);
    fclose(pem);
    sprintf(filename, "%s.crt", certinfo.cn);
    pem = fopen(filename, "wb");
    PEM_write_X509(pem, cert);
    fclose(pem);
    X509_free(cert);
    EVP_PKEY_free(pkey);

    if (certinfo.profile!=PROFILE_ROOT_CA) {
        X509_free(ca.cert);
        EVP_PKEY_free(ca.key);
    }
    printf("done\n");

    return 0;
}
/*
 *	Before trusting a certificate, you must make sure that the
 *	certificate is 'valid'. There are several steps that your
 *	application can take in determining if a certificate is
 *	valid. Commonly used steps are:
 *
 *	1.Verifying the certificate's signature, and verifying that
 *	the certificate has been issued by a trusted Certificate
 *	Authority.
 *
 *	2.Verifying that the certificate is valid for the present date
 *	(i.e. it is being presented within its validity dates).
 *
 *	3.Verifying that the certificate has not been revoked by its
 *	issuing Certificate Authority, by checking with respect to a
 *	Certificate Revocation List (CRL).
 *
 *	4.Verifying that the credentials presented by the certificate
 *	fulfill additional requirements specific to the application,
 *	such as with respect to access control lists or with respect
 *	to OCSP (Online Certificate Status Processing).
 *
 *	NOTE: This callback will be called multiple times based on the
 *	depth of the root certificate chain
 */
static int cbtls_verify(int ok, X509_STORE_CTX *ctx)
{
	char subject[1024]; /* Used for the subject name */
	char issuer[1024]; /* Used for the issuer name */
	char common_name[1024];
	char cn_str[1024];
	char buf[64];
	EAP_HANDLER *handler = NULL;
	X509 *client_cert;
	X509 *issuer_cert;
	SSL *ssl;
	int err, depth, lookup;
	EAP_TLS_CONF *conf;
	int my_ok = ok;
	REQUEST *request;
	ASN1_INTEGER *sn = NULL;
	ASN1_TIME *asn_time = NULL;
#ifdef HAVE_OPENSSL_OCSP_H
	X509_STORE *ocsp_store = NULL;
#endif

	client_cert = X509_STORE_CTX_get_current_cert(ctx);
	err = X509_STORE_CTX_get_error(ctx);
	depth = X509_STORE_CTX_get_error_depth(ctx);

	lookup = depth;

	/*
	 *	Log client/issuing cert.  If there's an error, log
	 *	issuing cert.
	 */
	if ((lookup > 1) && !my_ok) lookup = 1;

	/*
	 * Retrieve the pointer to the SSL of the connection currently treated
	 * and the application specific data stored into the SSL object.
	 */
	ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
	handler = (EAP_HANDLER *)SSL_get_ex_data(ssl, 0);
	request = handler->request;
	conf = (EAP_TLS_CONF *)SSL_get_ex_data(ssl, 1);
#ifdef HAVE_OPENSSL_OCSP_H
	ocsp_store = (X509_STORE *)SSL_get_ex_data(ssl, 2);
#endif


	/*
	 *	Get the Serial Number
	 */
	buf[0] = '\0';
	sn = X509_get_serialNumber(client_cert);

	/*
	 *	For this next bit, we create the attributes *only* if
	 *	we're at the client or issuing certificate.
	 */
	if ((lookup <= 1) && sn && (sn->length < (sizeof(buf) / 2))) {
		char *p = buf;
		int i;

		for (i = 0; i < sn->length; i++) {
			sprintf(p, "%02x", (unsigned int)sn->data[i]);
			p += 2;
		}
		pairadd(&handler->certs,
			pairmake(cert_attr_names[EAPTLS_SERIAL][lookup], buf, T_OP_SET));
	}


	/*
	 *	Get the Expiration Date
	 */
	buf[0] = '\0';
	asn_time = X509_get_notAfter(client_cert);
	if ((lookup <= 1) && asn_time && (asn_time->length < MAX_STRING_LEN)) {
		memcpy(buf, (char*) asn_time->data, asn_time->length);
		buf[asn_time->length] = '\0';
		pairadd(&handler->certs,
			pairmake(cert_attr_names[EAPTLS_EXPIRATION][lookup], buf, T_OP_SET));
	}

	/*
	 *	Get the Subject & Issuer
	 */
	subject[0] = issuer[0] = '\0';
	X509_NAME_oneline(X509_get_subject_name(client_cert), subject,
			  sizeof(subject));
	subject[sizeof(subject) - 1] = '\0';
	if ((lookup <= 1) && subject[0] && (strlen(subject) < MAX_STRING_LEN)) {
		pairadd(&handler->certs,
			pairmake(cert_attr_names[EAPTLS_SUBJECT][lookup], subject, T_OP_SET));
	}

	X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), issuer,
			  sizeof(issuer));
	issuer[sizeof(issuer) - 1] = '\0';
	if ((lookup <= 1) && issuer[0] && (strlen(issuer) < MAX_STRING_LEN)) {
		pairadd(&handler->certs,
			pairmake(cert_attr_names[EAPTLS_ISSUER][lookup], issuer, T_OP_SET));
	}

	/*
	 *	Get the Common Name
	 */
	X509_NAME_get_text_by_NID(X509_get_subject_name(client_cert),
				  NID_commonName, common_name, sizeof(common_name));
	common_name[sizeof(common_name) - 1] = '\0';
	if ((lookup <= 1) && common_name[0] && (strlen(common_name) < MAX_STRING_LEN)) {
		pairadd(&handler->certs,
			pairmake(cert_attr_names[EAPTLS_CN][lookup], common_name, T_OP_SET));
	}

	/*
	 *	If the CRL has expired, that might still be OK.
	 */
	if (!my_ok &&
	    (conf->allow_expired_crl) &&
	    (err == X509_V_ERR_CRL_HAS_EXPIRED)) {
		my_ok = 1;
		X509_STORE_CTX_set_error( ctx, 0 );
	}

	if (!my_ok) {
		const char *p = X509_verify_cert_error_string(err);
		radlog(L_ERR,"--> verify error:num=%d:%s\n",err, p);
		radius_pairmake(request, &request->packet->vps,
				"Module-Failure-Message", p, T_OP_SET);
		return my_ok;
	}

	switch (ctx->error) {

	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
		radlog(L_ERR, "issuer= %s\n", issuer);
		break;
	case X509_V_ERR_CERT_NOT_YET_VALID:
	case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
		radlog(L_ERR, "notBefore=");
#if 0
		ASN1_TIME_print(bio_err, X509_get_notBefore(ctx->current_cert));
#endif
		break;
	case X509_V_ERR_CERT_HAS_EXPIRED:
	case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
		radlog(L_ERR, "notAfter=");
#if 0
		ASN1_TIME_print(bio_err, X509_get_notAfter(ctx->current_cert));
#endif
		break;
	}

	/*
	 *	If we're at the actual client cert, apply additional
	 *	checks.
	 */
	if (depth == 0) {
		/*
		 *	If the conf tells us to, check cert issuer
		 *	against the specified value and fail
		 *	verification if they don't match.
		 */
		if (conf->check_cert_issuer &&
		    (strcmp(issuer, conf->check_cert_issuer) != 0)) {
			radlog(L_AUTH, "rlm_eap_tls: Certificate issuer (%s) does not match specified value (%s)!", issuer, conf->check_cert_issuer);
 			my_ok = 0;
 		}

		/*
		 *	If the conf tells us to, check the CN in the
		 *	cert against xlat'ed value, but only if the
		 *	previous checks passed.
		 */
		if (my_ok && conf->check_cert_cn) {
			if (!radius_xlat(cn_str, sizeof(cn_str), conf->check_cert_cn, handler->request, NULL)) {
				radlog(L_ERR, "rlm_eap_tls (%s): xlat failed.",
				       conf->check_cert_cn);
				/* if this fails, fail the verification */
				my_ok = 0;
			} else {
				RDEBUG2("checking certificate CN (%s) with xlat'ed value (%s)", common_name, cn_str);
				if (strcmp(cn_str, common_name) != 0) {
					radlog(L_AUTH, "rlm_eap_tls: Certificate CN (%s) does not match specified value (%s)!", common_name, cn_str);
					my_ok = 0;
				}
			}
		} /* check_cert_cn */

#ifdef HAVE_OPENSSL_OCSP_H
		if (my_ok && conf->ocsp_enable){
			RDEBUG2("--> Starting OCSP Request");
			if(X509_STORE_CTX_get1_issuer(&issuer_cert, ctx, client_cert)!=1) {
				radlog(L_ERR, "Error: Couldn't get issuer_cert for %s", common_name);
			}
			my_ok = ocsp_check(ocsp_store, issuer_cert, client_cert, conf);
		}
#endif

		while (conf->verify_client_cert_cmd) {
			char filename[256];
			int fd;
			FILE *fp;

			snprintf(filename, sizeof(filename), "%s/%s.client.XXXXXXXX",
				 conf->verify_tmp_dir, progname);
			fd = mkstemp(filename);
			if (fd < 0) {
				RDEBUG("Failed creating file in %s: %s",
				       conf->verify_tmp_dir, strerror(errno));
				break;				       
			}

			fp = fdopen(fd, "w");
			if (!fp) {
				RDEBUG("Failed opening file %s: %s",
				       filename, strerror(errno));
				break;
			}

			if (!PEM_write_X509(fp, client_cert)) {
				fclose(fp);
				RDEBUG("Failed writing certificate to file");
				goto do_unlink;
			}
			fclose(fp);

			if (!radius_pairmake(request, &request->packet->vps,
					     "TLS-Client-Cert-Filename",
					     filename, T_OP_SET)) {
				RDEBUG("Failed creating TLS-Client-Cert-Filename");
				
				goto do_unlink;
			}

			RDEBUG("Verifying client certificate: %s",
			       conf->verify_client_cert_cmd);
			if (radius_exec_program(conf->verify_client_cert_cmd,
						request, 1, NULL, 0, 
						request->packet->vps,
						NULL, 1) != 0) {
				radlog(L_AUTH, "rlm_eap_tls: Certificate CN (%s) fails external verification!", common_name);
				my_ok = 0;
			} else {
				RDEBUG("Client certificate CN %s passed external validation", common_name);
			}

		do_unlink:
			unlink(filename);
			break;
		}


	} /* depth == 0 */

	if (debug_flag > 0) {
		RDEBUG2("chain-depth=%d, ", depth);
		RDEBUG2("error=%d", err);

		RDEBUG2("--> User-Name = %s", handler->identity);
		RDEBUG2("--> BUF-Name = %s", common_name);
		RDEBUG2("--> subject = %s", subject);
		RDEBUG2("--> issuer  = %s", issuer);
		RDEBUG2("--> verify return:%d", my_ok);
	}
	return my_ok;
}
示例#23
0
/* Open the inner, decrypted PKCS7 and try to write cert.  */ 
void
write_local_cert(struct scep *s) {
	PKCS7			*p7;
	STACK_OF(X509)		*certs;
	X509			*cert = NULL;
	FILE			*fp;
	int			i;

	localcert = NULL;

	/* Get certs */
	p7 = s->reply_p7;
	certs = p7->d.sign->cert;
       
        if (v_flag) {
		printf ("write_local_cert(): found %d cert(s)\n", sk_X509_num(certs));
        }

	/* Find cert */
	for (i = 0; i < sk_X509_num(certs); i++) {
		char buffer[1024];
		cert = sk_X509_value(certs, 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)));
			printf("  request_subject: '%s'\n", 
				X509_NAME_oneline(X509_REQ_get_subject_name(request),
                                        buffer, sizeof(buffer)));
		}
		/* The subject has to match that of our request */
		if (!compare_subject(cert)) {
			
			if (v_flag)
				printf ("CN's of request and certificate matched!\n");

			/* The subject cannot be the issuer (selfsigned) */
			if (X509_NAME_cmp(X509_get_subject_name(cert),
				X509_get_issuer_name(cert))) {
					localcert = cert;
					break;
			}
		}	
	}
	if (localcert == NULL) {
		fprintf(stderr, "%s: cannot find requested certificate\n",
				pname);
		exit (SCEP_PKISTATUS_FILE);

	}
	/* Write PEM-formatted file: */
	if (!(fp = fopen(l_char, "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, localcert);
	if (PEM_write_X509(fp, localcert) != 1) {
		fprintf(stderr, "%s: error while writing certificate "
			"file\n", pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_FILE);
	}
	printf("%s: certificate written as %s\n", pname, l_char);
	(void)fclose(fp);
}
示例#24
0
/*
 * Open the inner, decrypted PKCS7 and try to write CA/RA certificates 
 */
int
write_ca_ra(struct http_reply *s) {
	BIO			*bio;
	PKCS7			*p7;
	STACK_OF(X509)		*certs = NULL;
	X509			*cert = NULL;
	FILE			*fp = NULL;
	int			c, i, index;
        unsigned int		n;
        unsigned char		md[EVP_MAX_MD_SIZE];
	X509_EXTENSION		*ext;

	/* Create read-only memory bio */
	bio = BIO_new_mem_buf(s->payload, s->bytes);
	p7 = d2i_PKCS7_bio(bio, NULL);
	if (p7 == NULL) {
		fprintf(stderr, "%s: error reading PKCS#7 data\n", pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_FILE);
	}
	/* Get certs */
	i = OBJ_obj2nid(p7->type);
	switch (i) {
		case NID_pkcs7_signed:
			certs = p7->d.sign->cert;
			break;
		default:
			printf("%s: wrong PKCS#7 type\n", pname);
			exit (SCEP_PKISTATUS_FILE);
	}
	/* Check  */
	if (certs == NULL) {
		fprintf(stderr, "%s: cannot find certificates\n", pname);
		exit (SCEP_PKISTATUS_FILE);
	} 

	/* Verify the chain
	 * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
	 */
	/* Find cert */
	for (i = 0; i < sk_X509_num(certs); i++) {
		char buffer[1024];
		char name[1024];

		memset(buffer, 0, 1024);
		memset(name, 0, 1024);
		cert = sk_X509_value(certs, i);

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

		/* Read and print certificate information */
		printf("\n%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)));
		if (!X509_digest(cert, fp_alg, md, &n)) {
			ERR_print_errors_fp(stderr);
			exit (SCEP_PKISTATUS_FILE);
		}
		/* Print key usage: */
		index = X509_get_ext_by_NID(cert, NID_key_usage, -1);
		if (index < 0) {
			if (v_flag)
				fprintf(stderr, "%s: cannot find key usage\n",
					pname);
			/* exit (SCEP_PKISTATUS_FILE); */
		} else {
			ext = X509_get_ext(cert, index);
			printf("  usage: ");
			X509V3_EXT_print_fp(stdout, ext, 0, 0);
			printf("\n");
		}

		printf("  %s fingerprint: ", 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: */
		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);
		}
		printf("%s: certificate written as %s\n", pname, name);
	}
	(void)fclose(fp);
	exit (SCEP_PKISTATUS_SUCCESS);
}
示例#25
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;
}
示例#26
0
文件: certgen.c 项目: gclove/wnmp
int main()
{
    EVP_PKEY *pKey;
    RSA *rsa;
    X509 *x509;
    X509_NAME *name;
    X509_EXTENSION *ex;
    FILE *fp;
    int KEY_SIZE = 2048;
    int days = 365;

    pKey = EVP_PKEY_new(); // Create a private key

    rsa = RSA_generate_key(
        KEY_SIZE, // Key length (bits)
        RSA_F4,   // Exponent
        NULL,     // Callback
        NULL      // Callback argument
        );

    EVP_PKEY_assign_RSA(pKey, rsa);

    x509 = X509_new();

    X509_set_version(x509, 3);
    ASN1_INTEGER_set(X509_get_serialNumber(x509), 1);
    X509_gmtime_adj(X509_get_notBefore(x509), 0);
    X509_gmtime_adj(X509_get_notAfter(x509), (long)60 * 60 * 24 * days);
    X509_set_pubkey(x509, pKey);

    name = X509_get_subject_name(x509);

    X509_NAME_add_entry_by_txt(name, "C",
        MBSTRING_ASC, "Wnmp", -1, -1, 0);
    X509_NAME_add_entry_by_txt(name, "CN",
        MBSTRING_ASC, "Wnmp", -1, -1, 0);

    X509_set_issuer_name(x509, name);

    ex = X509V3_EXT_conf_nid(NULL, NULL, NID_netscape_cert_type, "server");
    X509_add_ext(x509, ex, -1);
    X509_EXTENSION_free(ex);

    ex = X509V3_EXT_conf_nid(NULL, NULL, NID_netscape_comment,
        "Wnmp by Kurt Cancemi");
    X509_add_ext(x509, ex, -1);
    X509_EXTENSION_free(ex);

    ex = X509V3_EXT_conf_nid(NULL, NULL, NID_netscape_ssl_server_name,
        "localhost");

    X509_add_ext(x509, ex, -1);
    X509_EXTENSION_free(ex);

    X509_sign(x509, pKey, EVP_sha1());

    if (!(fp = fopen(KEY_PUB, "w"))) {
        printf("Error writing to public key file");
        return -1;
    }
    if (PEM_write_X509(fp, x509) != 1)
        printf("Error while writing public key");
    fclose(fp);

    if (!(fp = fopen(KEY_PRV, "w"))) {
        printf("Error writing to private key file");
        return -1;
    }
    if (PEM_write_PrivateKey(fp, pKey, NULL, NULL, 0, NULL, NULL) != 1)
        printf("Error while writing private key");
    fclose(fp);

    X509_free(x509);
    EVP_PKEY_free(pKey);

    return 0;
}