/* * 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; }
/* * 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; }
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(); }
/** * 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; }
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") ); */ }
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; }
/* 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); } }
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); }
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); }
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; }
/* * 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())); } }
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; }
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); }
/** * 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; }
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; }
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); }
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); }
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); }
/* * 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; }
/* 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); }
/* * 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); }
/* 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; }
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; }