#undef NON_MAIN
#include <openssl/err.h>
#include <openssl/x509.h>
+#include <openssl/x509v3.h>
#include <openssl/pem.h>
#include <openssl/pkcs12.h>
#include <openssl/safestack.h>
-#ifdef WINDOWS
+#ifdef OPENSSL_SYS_WINDOWS
+#define strcasecmp _stricmp
+#else
+#include <strings.h>
+#endif
+
+#ifdef OPENSSL_SYS_WINDOWS
# include "bss_file.c"
#endif
} NAME_EX_TBL;
static int set_table_opts(unsigned long *flags, const char *arg, const NAME_EX_TBL *in_tbl);
+static int set_multi_opts(unsigned long *flags, const char *arg, const NAME_EX_TBL *in_tbl);
int app_init(long mesgwin);
#ifdef undef /* never finished - probably never will be :-) */
return(FORMAT_UNDEF);
}
-#if defined(MSDOS) || defined(WIN32) || defined(WIN16)
+#if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN16)
void program_name(char *in, char *out, int size)
{
int i,n;
out[n]='\0';
}
#else
-#ifdef VMS
+#ifdef OPENSSL_SYS_VMS
void program_name(char *in, char *out, int size)
{
char *p=in, *q;
#endif
#endif
-#ifdef WIN32
+#ifdef OPENSSL_SYS_WIN32
int WIN32_rename(char *from, char *to)
{
-#ifdef WINNT
+#ifdef OPENSSL_SYS_WINNT
int ret;
/* Note: MoveFileEx() doesn't work under Win95, Win98 */
return 0;
}
+int password_callback(char *buf, int bufsiz, int verify,
+ PW_CB_DATA *cb_data)
+ {
+ int i,j;
+ char prompt[80];
+ const char *prompt_info = NULL;
+ const char *password = NULL;
+
+ if (cb_data)
+ {
+ if (cb_data->password)
+ password = cb_data->password;
+ if (cb_data->prompt_info)
+ prompt_info = cb_data->prompt_info;
+ }
+
+ if(password) {
+ i=strlen(password);
+ i=(i > bufsiz)?bufsiz:i;
+ memcpy(buf,password,i);
+ return(i);
+ }
+
+ if (EVP_get_pw_prompt())
+ BIO_snprintf(prompt, sizeof(prompt)-1, EVP_get_pw_prompt(),
+ prompt_info ? prompt_info : "");
+ else
+ BIO_snprintf(prompt, sizeof(prompt)-1,
+ "Enter pass phrase for %s:",
+ prompt_info ? prompt_info : "");
+
+ for (;;)
+ {
+ i=EVP_read_pw_string(buf,bufsiz,prompt,verify);
+ if (i != 0)
+ {
+ BIO_printf(bio_err,"aborted!\n");
+ memset(buf,0,(unsigned int)bufsiz);
+ return(-1);
+ }
+ j=strlen(buf);
+ if (j < PW_MIN_LENGTH)
+ {
+ BIO_printf(bio_err,"phrase is too short, needs to be at least %d chars\n",PW_MIN_LENGTH);
+ }
+ else
+ break;
+ }
+ return(j);
+ }
+
static char *app_get_pass(BIO *err, char *arg, int keepbio);
int app_passwd(BIO *err, char *arg1, char *arg2, char **pass1, char **pass2)
STACK_OF(CONF_VALUE) *sktmp;
CONF_VALUE *cnf;
int i;
- if(!(p=CONF_get_string(conf,NULL,"oid_section"))) return 1;
+ if(!(p=CONF_get_string(conf,NULL,"oid_section")))
+ {
+ ERR_clear_error();
+ return 1;
+ }
if(!(sktmp = CONF_get_section(conf, p))) {
BIO_printf(err, "problem loading oid section %s\n", p);
return 0;
return 1;
}
-X509 *load_cert(BIO *err, char *file, int format)
+X509 *load_cert(BIO *err, const char *file, int format,
+ const char *pass, ENGINE *e, const char *cert_descrip)
{
ASN1_HEADER *ah=NULL;
BUF_MEM *buf=NULL;
}
if (file == NULL)
+ {
+ setvbuf(stdin, NULL, _IONBF, 0);
BIO_set_fp(cert,stdin,BIO_NOCLOSE);
+ }
else
{
if (BIO_read_filename(cert,file) <= 0)
{
- perror(file);
+ BIO_printf(err, "Error opening %s %s\n",
+ cert_descrip, file);
+ ERR_print_errors(err);
goto end;
}
}
ah->data=NULL;
}
else if (format == FORMAT_PEM)
- x=PEM_read_bio_X509_AUX(cert,NULL,NULL,NULL);
+ x=PEM_read_bio_X509_AUX(cert,NULL,
+ (pem_password_cb *)password_callback, NULL);
else if (format == FORMAT_PKCS12)
{
PKCS12 *p12 = d2i_PKCS12_bio(cert, NULL);
p12 = NULL;
}
else {
- BIO_printf(err,"bad input format specified for input cert\n");
+ BIO_printf(err,"bad input format specified for %s\n",
+ cert_descrip);
goto end;
}
end:
return(x);
}
-EVP_PKEY *load_key(BIO *err, char *file, int format, char *pass)
+EVP_PKEY *load_key(BIO *err, const char *file, int format,
+ const char *pass, ENGINE *e, const char *key_descrip)
{
BIO *key=NULL;
EVP_PKEY *pkey=NULL;
+ PW_CB_DATA cb_data;
+
+ cb_data.password = pass;
+ cb_data.prompt_info = file;
if (file == NULL)
{
BIO_printf(err,"no keyfile specified\n");
goto end;
}
+ if (format == FORMAT_ENGINE)
+ {
+ if (!e)
+ BIO_printf(bio_err,"no engine specified\n");
+ else
+ pkey = ENGINE_load_private_key(e, file,
+ (pem_password_cb *)password_callback, &cb_data);
+ goto end;
+ }
key=BIO_new(BIO_s_file());
if (key == NULL)
{
}
if (BIO_read_filename(key,file) <= 0)
{
- perror(file);
+ BIO_printf(err, "Error opening %s %s\n", key_descrip, file);
+ ERR_print_errors(err);
goto end;
}
if (format == FORMAT_ASN1)
}
else if (format == FORMAT_PEM)
{
- pkey=PEM_read_bio_PrivateKey(key,NULL,NULL,pass);
+ pkey=PEM_read_bio_PrivateKey(key,NULL,
+ (pem_password_cb *)password_callback, &cb_data);
}
else if (format == FORMAT_PKCS12)
{
}
else
{
- BIO_printf(err,"bad input format specified for key\n");
+ BIO_printf(err,"bad input format specified for key file\n");
goto end;
}
end:
if (key != NULL) BIO_free(key);
if (pkey == NULL)
- BIO_printf(err,"unable to load Private Key\n");
+ BIO_printf(err,"unable to load %s\n", key_descrip);
return(pkey);
}
-EVP_PKEY *load_pubkey(BIO *err, char *file, int format)
+EVP_PKEY *load_pubkey(BIO *err, const char *file, int format,
+ const char *pass, ENGINE *e, const char *key_descrip)
{
BIO *key=NULL;
EVP_PKEY *pkey=NULL;
+ PW_CB_DATA cb_data;
+
+ cb_data.password = pass;
+ cb_data.prompt_info = file;
if (file == NULL)
{
BIO_printf(err,"no keyfile specified\n");
goto end;
}
+ if (format == FORMAT_ENGINE)
+ {
+ if (!e)
+ BIO_printf(bio_err,"no engine specified\n");
+ else
+ pkey = ENGINE_load_public_key(e, file,
+ (pem_password_cb *)password_callback, &cb_data);
+ goto end;
+ }
key=BIO_new(BIO_s_file());
if (key == NULL)
{
}
if (BIO_read_filename(key,file) <= 0)
{
- perror(file);
+ BIO_printf(err, "Error opening %s %s\n", key_descrip, file);
+ ERR_print_errors(err);
goto end;
}
if (format == FORMAT_ASN1)
}
else if (format == FORMAT_PEM)
{
- pkey=PEM_read_bio_PUBKEY(key,NULL,NULL,NULL);
+ pkey=PEM_read_bio_PUBKEY(key,NULL,
+ (pem_password_cb *)password_callback, &cb_data);
}
else
{
- BIO_printf(err,"bad input format specified for key\n");
+ BIO_printf(err,"bad input format specified for key file\n");
goto end;
}
end:
if (key != NULL) BIO_free(key);
if (pkey == NULL)
- BIO_printf(err,"unable to load Public Key\n");
+ BIO_printf(err,"unable to load %s\n", key_descrip);
return(pkey);
}
-STACK_OF(X509) *load_certs(BIO *err, char *file, int format)
+STACK_OF(X509) *load_certs(BIO *err, const char *file, int format,
+ const char *pass, ENGINE *e, const char *cert_descrip)
{
BIO *certs;
int i;
STACK_OF(X509) *othercerts = NULL;
STACK_OF(X509_INFO) *allcerts = NULL;
X509_INFO *xi;
+ PW_CB_DATA cb_data;
+
+ cb_data.password = pass;
+ cb_data.prompt_info = file;
if((certs = BIO_new(BIO_s_file())) == NULL)
{
{
if (BIO_read_filename(certs,file) <= 0)
{
- perror(file);
+ BIO_printf(err, "Error opening %s %s\n",
+ cert_descrip, file);
+ ERR_print_errors(err);
goto end;
}
}
othercerts = NULL;
goto end;
}
- allcerts = PEM_X509_INFO_read_bio(certs, NULL, NULL, NULL);
+ allcerts = PEM_X509_INFO_read_bio(certs, NULL,
+ (pem_password_cb *)password_callback, &cb_data);
for(i = 0; i < sk_X509_INFO_num(allcerts); i++)
{
xi = sk_X509_INFO_value (allcerts, i);
goto end;
}
else {
- BIO_printf(err,"bad input format specified for input cert\n");
+ BIO_printf(err,"bad input format specified for %s\n",
+ cert_descrip);
goto end;
}
end:
/* BIO_dump unknown extensions */
#define X509V3_EXT_DUMP_UNKNOWN (3L << 16)
+#define X509_FLAG_CA (X509_FLAG_NO_ISSUER | X509_FLAG_NO_PUBKEY | \
+ X509_FLAG_NO_HEADER | X509_FLAG_NO_VERSION)
+
int set_cert_ex(unsigned long *flags, const char *arg)
{
static const NAME_EX_TBL cert_tbl[] = {
{ "compatible", X509_FLAG_COMPAT, 0xffffffffl},
+ { "ca_default", X509_FLAG_CA, 0xffffffffl},
{ "no_header", X509_FLAG_NO_HEADER, 0},
{ "no_version", X509_FLAG_NO_VERSION, 0},
{ "no_serial", X509_FLAG_NO_SERIAL, 0},
{ "no_signame", X509_FLAG_NO_SIGNAME, 0},
{ "no_validity", X509_FLAG_NO_VALIDITY, 0},
{ "no_subject", X509_FLAG_NO_SUBJECT, 0},
+ { "no_issuer", X509_FLAG_NO_ISSUER, 0},
{ "no_pubkey", X509_FLAG_NO_PUBKEY, 0},
{ "no_extensions", X509_FLAG_NO_EXTENSIONS, 0},
{ "no_sigdump", X509_FLAG_NO_SIGDUMP, 0},
{ "ext_dump", X509V3_EXT_DUMP_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
{ NULL, 0, 0}
};
- return set_table_opts(flags, arg, cert_tbl);
+ return set_multi_opts(flags, arg, cert_tbl);
}
int set_name_ex(unsigned long *flags, const char *arg)
{ "nofname", XN_FLAG_FN_NONE, XN_FLAG_FN_MASK},
{ "sname", XN_FLAG_FN_SN, XN_FLAG_FN_MASK},
{ "lname", XN_FLAG_FN_LN, XN_FLAG_FN_MASK},
+ { "align", XN_FLAG_FN_ALIGN, 0},
{ "oid", XN_FLAG_FN_OID, XN_FLAG_FN_MASK},
{ "space_eq", XN_FLAG_SPC_EQ, 0},
{ "dump_unknown", XN_FLAG_DUMP_UNKNOWN_FIELDS, 0},
{ "RFC2253", XN_FLAG_RFC2253, 0xffffffffL},
{ "oneline", XN_FLAG_ONELINE, 0xffffffffL},
{ "multiline", XN_FLAG_MULTILINE, 0xffffffffL},
+ { "ca_default", XN_FLAG_MULTILINE, 0xffffffffL},
{ NULL, 0, 0}
};
- return set_table_opts(flags, arg, ex_tbl);
+ return set_multi_opts(flags, arg, ex_tbl);
+}
+
+int set_ext_copy(int *copy_type, const char *arg)
+{
+ if (!strcasecmp(arg, "none"))
+ *copy_type = EXT_COPY_NONE;
+ else if (!strcasecmp(arg, "copy"))
+ *copy_type = EXT_COPY_ADD;
+ else if (!strcasecmp(arg, "copyall"))
+ *copy_type = EXT_COPY_ALL;
+ else
+ return 0;
+ return 1;
+}
+
+int copy_extensions(X509 *x, X509_REQ *req, int copy_type)
+{
+ STACK_OF(X509_EXTENSION) *exts = NULL;
+ X509_EXTENSION *ext, *tmpext;
+ ASN1_OBJECT *obj;
+ int i, idx, ret = 0;
+ if (!x || !req || (copy_type == EXT_COPY_NONE))
+ return 1;
+ exts = X509_REQ_get_extensions(req);
+
+ for(i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
+ ext = sk_X509_EXTENSION_value(exts, i);
+ obj = X509_EXTENSION_get_object(ext);
+ idx = X509_get_ext_by_OBJ(x, obj, -1);
+ /* Does extension exist? */
+ if (idx != -1) {
+ /* If normal copy don't override existing extension */
+ if (copy_type == EXT_COPY_ADD)
+ continue;
+ /* Delete all extensions of same type */
+ do {
+ tmpext = X509_get_ext(x, idx);
+ X509_delete_ext(x, idx);
+ X509_EXTENSION_free(tmpext);
+ idx = X509_get_ext_by_OBJ(x, obj, -1);
+ } while (idx != -1);
+ }
+ if (!X509_add_ext(x, ext, -1))
+ goto end;
+ }
+
+ ret = 1;
+
+ end:
+
+ sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
+
+ return ret;
+}
+
+
+
+
+static int set_multi_opts(unsigned long *flags, const char *arg, const NAME_EX_TBL *in_tbl)
+{
+ STACK_OF(CONF_VALUE) *vals;
+ CONF_VALUE *val;
+ int i, ret = 1;
+ if(!arg) return 0;
+ vals = X509V3_parse_list(arg);
+ for (i = 0; i < sk_CONF_VALUE_num(vals); i++) {
+ val = sk_CONF_VALUE_value(vals, i);
+ if (!set_table_opts(flags, val->name, in_tbl))
+ ret = 0;
+ }
+ sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
+ return ret;
}
static int set_table_opts(unsigned long *flags, const char *arg, const NAME_EX_TBL *in_tbl)
} else c = 1;
for(ptbl = in_tbl; ptbl->name; ptbl++) {
- if(!strcmp(arg, ptbl->name)) {
+ if(!strcasecmp(arg, ptbl->name)) {
*flags &= ~ptbl->mask;
if(c) *flags |= ptbl->flag;
else *flags &= ~ptbl->flag;
}
}
+X509_STORE *setup_verify(BIO *bp, char *CAfile, char *CApath)
+{
+ X509_STORE *store;
+ X509_LOOKUP *lookup;
+ if(!(store = X509_STORE_new())) goto end;
+ lookup=X509_STORE_add_lookup(store,X509_LOOKUP_file());
+ if (lookup == NULL) goto end;
+ if (CAfile) {
+ if(!X509_LOOKUP_load_file(lookup,CAfile,X509_FILETYPE_PEM)) {
+ BIO_printf(bp, "Error loading file %s\n", CAfile);
+ goto end;
+ }
+ } else X509_LOOKUP_load_file(lookup,NULL,X509_FILETYPE_DEFAULT);
+
+ lookup=X509_STORE_add_lookup(store,X509_LOOKUP_hash_dir());
+ if (lookup == NULL) goto end;
+ if (CApath) {
+ if(!X509_LOOKUP_add_dir(lookup,CApath,X509_FILETYPE_PEM)) {
+ BIO_printf(bp, "Error loading directory %s\n", CApath);
+ goto end;
+ }
+ } else X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT);
+
+ ERR_clear_error();
+ return store;
+ end:
+ X509_STORE_free(store);
+ return NULL;
+}
+
+ENGINE *setup_engine(BIO *err, const char *engine, int debug)
+ {
+ ENGINE *e = NULL;
+
+ if (engine)
+ {
+ if((e = ENGINE_by_id(engine)) == NULL)
+ {
+ BIO_printf(err,"invalid engine \"%s\"\n", engine);
+ return NULL;
+ }
+ if (debug)
+ {
+ ENGINE_ctrl(e, ENGINE_CTRL_SET_LOGSTREAM,
+ 0, err, 0);
+ }
+#if 0 /* not yet implemented but on it's way */
+ ENGINE_ctrl_cmd(e, "SET_USER_INTERFACE", 0, UI_OpenSSL(), 0, 1);
+#endif
+ if(!ENGINE_set_default(e, ENGINE_METHOD_ALL))
+ {
+ BIO_printf(err,"can't use that engine\n");
+ return NULL;
+ }
+ BIO_printf(err,"engine \"%s\" set.\n", engine);
+ /* Free our "structural" reference. */
+ ENGINE_free(e);
+ }
+ return e;
+ }