Support EVP_PKEY_sign() and EVP_PKEY_verify() for EdDSA
[openssl.git] / apps / apps.c
index fd8156744efc951eead557db98a96fc356d6f384..5a32dc0a02ef0a96199273fb30309c1e9952e3c2 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
 #endif
 #include <ctype.h>
 #include <errno.h>
 #endif
 #include <ctype.h>
 #include <errno.h>
+#ifdef __VMS
+# include <descrip.h>
+# include <iledef.h>
+# include <fscndef.h>
+# include <starlet.h>
+#endif
 #include <openssl/err.h>
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
 #include <openssl/err.h>
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
@@ -442,7 +448,7 @@ static char *app_get_pass(const char *arg, int keepbio)
     return OPENSSL_strdup(tpass);
 }
 
     return OPENSSL_strdup(tpass);
 }
 
-static CONF *app_load_config_(BIO *in, const char *filename)
+CONF *app_load_config_bio(BIO *in, const char *filename)
 {
     long errorline = -1;
     CONF *conf;
 {
     long errorline = -1;
     CONF *conf;
@@ -453,12 +459,17 @@ static CONF *app_load_config_(BIO *in, const char *filename)
     if (i > 0)
         return conf;
 
     if (i > 0)
         return conf;
 
-    if (errorline <= 0)
-        BIO_printf(bio_err, "%s: Can't load config file \"%s\"\n",
-                   opt_getprog(), filename);
+    if (errorline <= 0) {
+        BIO_printf(bio_err, "%s: Can't load ", opt_getprog());
+    } else {
+        BIO_printf(bio_err, "%s: Error on line %ld of ", opt_getprog(),
+                   errorline);
+    }
+    if (filename != NULL)
+        BIO_printf(bio_err, "config file \"%s\"\n", filename);
     else
     else
-        BIO_printf(bio_err, "%s: Error on line %ld of config file \"%s\"\n",
-                   opt_getprog(), errorline, filename);
+        BIO_printf(bio_err, "config input");
+
     NCONF_free(conf);
     return NULL;
 }
     NCONF_free(conf);
     return NULL;
 }
@@ -472,7 +483,7 @@ CONF *app_load_config(const char *filename)
     if (in == NULL)
         return NULL;
 
     if (in == NULL)
         return NULL;
 
-    conf = app_load_config_(in, filename);
+    conf = app_load_config_bio(in, filename);
     BIO_free(in);
     return conf;
 }
     BIO_free(in);
     return conf;
 }
@@ -486,7 +497,7 @@ CONF *app_load_config_quiet(const char *filename)
     if (in == NULL)
         return NULL;
 
     if (in == NULL)
         return NULL;
 
-    conf = app_load_config_(in, filename);
+    conf = app_load_config_bio(in, filename);
     BIO_free(in);
     return conf;
 }
     BIO_free(in);
     return conf;
 }
@@ -1425,9 +1436,9 @@ int save_serial(const char *serialfile, const char *suffix, const BIGNUM *serial
         OPENSSL_strlcpy(buf[0], serialfile, BSIZE);
     else {
 #ifndef OPENSSL_SYS_VMS
         OPENSSL_strlcpy(buf[0], serialfile, BSIZE);
     else {
 #ifndef OPENSSL_SYS_VMS
-        j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s", serialfile, suffix);
+        j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", serialfile, suffix);
 #else
 #else
-        j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s", serialfile, suffix);
+        j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", serialfile, suffix);
 #endif
     }
     out = BIO_new_file(buf[0], "w");
 #endif
     }
     out = BIO_new_file(buf[0], "w");
@@ -1468,11 +1479,11 @@ int rotate_serial(const char *serialfile, const char *new_suffix,
         goto err;
     }
 #ifndef OPENSSL_SYS_VMS
         goto err;
     }
 #ifndef OPENSSL_SYS_VMS
-    j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s", serialfile, new_suffix);
-    j = BIO_snprintf(buf[1], sizeof buf[1], "%s.%s", serialfile, old_suffix);
+    j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", serialfile, new_suffix);
+    j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.%s", serialfile, old_suffix);
 #else
 #else
-    j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s", serialfile, new_suffix);
-    j = BIO_snprintf(buf[1], sizeof buf[1], "%s-%s", serialfile, old_suffix);
+    j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", serialfile, new_suffix);
+    j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-%s", serialfile, old_suffix);
 #endif
     if (rename(serialfile, buf[1]) < 0 && errno != ENOENT
 #ifdef ENOTDIR
 #endif
     if (rename(serialfile, buf[1]) < 0 && errno != ENOENT
 #ifdef ENOTDIR
@@ -1527,19 +1538,34 @@ CA_DB *load_index(const char *dbfile, DB_ATTR *db_attr)
     BIO *in;
     CONF *dbattr_conf = NULL;
     char buf[BSIZE];
     BIO *in;
     CONF *dbattr_conf = NULL;
     char buf[BSIZE];
+#ifndef OPENSSL_NO_POSIX_IO
+    FILE *dbfp;
+    struct stat dbst;
+#endif
 
     in = BIO_new_file(dbfile, "r");
     if (in == NULL) {
         ERR_print_errors(bio_err);
         goto err;
     }
 
     in = BIO_new_file(dbfile, "r");
     if (in == NULL) {
         ERR_print_errors(bio_err);
         goto err;
     }
+
+#ifndef OPENSSL_NO_POSIX_IO
+    BIO_get_fp(in, &dbfp);
+    if (fstat(fileno(dbfp), &dbst) == -1) {
+        SYSerr(SYS_F_FSTAT, errno);
+        ERR_add_error_data(3, "fstat('", dbfile, "')");
+        ERR_print_errors(bio_err);
+        goto err;
+    }
+#endif
+
     if ((tmpdb = TXT_DB_read(in, DB_NUMBER)) == NULL)
         goto err;
 
 #ifndef OPENSSL_SYS_VMS
     if ((tmpdb = TXT_DB_read(in, DB_NUMBER)) == NULL)
         goto err;
 
 #ifndef OPENSSL_SYS_VMS
-    BIO_snprintf(buf, sizeof buf, "%s.attr", dbfile);
+    BIO_snprintf(buf, sizeof(buf), "%s.attr", dbfile);
 #else
 #else
-    BIO_snprintf(buf, sizeof buf, "%s-attr", dbfile);
+    BIO_snprintf(buf, sizeof(buf), "%s-attr", dbfile);
 #endif
     dbattr_conf = app_load_config(buf);
 
 #endif
     dbattr_conf = app_load_config(buf);
 
@@ -1559,6 +1585,11 @@ CA_DB *load_index(const char *dbfile, DB_ATTR *db_attr)
         }
     }
 
         }
     }
 
+    retdb->dbfname = OPENSSL_strdup(dbfile);
+#ifndef OPENSSL_NO_POSIX_IO
+    retdb->dbst = dbst;
+#endif
+
  err:
     NCONF_free(dbattr_conf);
     TXT_DB_free(tmpdb);
  err:
     NCONF_free(dbattr_conf);
     TXT_DB_free(tmpdb);
@@ -1600,13 +1631,13 @@ int save_index(const char *dbfile, const char *suffix, CA_DB *db)
         goto err;
     }
 #ifndef OPENSSL_SYS_VMS
         goto err;
     }
 #ifndef OPENSSL_SYS_VMS
-    j = BIO_snprintf(buf[2], sizeof buf[2], "%s.attr", dbfile);
-    j = BIO_snprintf(buf[1], sizeof buf[1], "%s.attr.%s", dbfile, suffix);
-    j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s", dbfile, suffix);
+    j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s.attr", dbfile);
+    j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.attr.%s", dbfile, suffix);
+    j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", dbfile, suffix);
 #else
 #else
-    j = BIO_snprintf(buf[2], sizeof buf[2], "%s-attr", dbfile);
-    j = BIO_snprintf(buf[1], sizeof buf[1], "%s-attr-%s", dbfile, suffix);
-    j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s", dbfile, suffix);
+    j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s-attr", dbfile);
+    j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-attr-%s", dbfile, suffix);
+    j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", dbfile, suffix);
 #endif
     out = BIO_new_file(buf[0], "w");
     if (out == NULL) {
 #endif
     out = BIO_new_file(buf[0], "w");
     if (out == NULL) {
@@ -1649,17 +1680,17 @@ int rotate_index(const char *dbfile, const char *new_suffix,
         goto err;
     }
 #ifndef OPENSSL_SYS_VMS
         goto err;
     }
 #ifndef OPENSSL_SYS_VMS
-    j = BIO_snprintf(buf[4], sizeof buf[4], "%s.attr", dbfile);
-    j = BIO_snprintf(buf[3], sizeof buf[3], "%s.attr.%s", dbfile, old_suffix);
-    j = BIO_snprintf(buf[2], sizeof buf[2], "%s.attr.%s", dbfile, new_suffix);
-    j = BIO_snprintf(buf[1], sizeof buf[1], "%s.%s", dbfile, old_suffix);
-    j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s", dbfile, new_suffix);
+    j = BIO_snprintf(buf[4], sizeof(buf[4]), "%s.attr", dbfile);
+    j = BIO_snprintf(buf[3], sizeof(buf[3]), "%s.attr.%s", dbfile, old_suffix);
+    j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s.attr.%s", dbfile, new_suffix);
+    j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.%s", dbfile, old_suffix);
+    j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", dbfile, new_suffix);
 #else
 #else
-    j = BIO_snprintf(buf[4], sizeof buf[4], "%s-attr", dbfile);
-    j = BIO_snprintf(buf[3], sizeof buf[3], "%s-attr-%s", dbfile, old_suffix);
-    j = BIO_snprintf(buf[2], sizeof buf[2], "%s-attr-%s", dbfile, new_suffix);
-    j = BIO_snprintf(buf[1], sizeof buf[1], "%s-%s", dbfile, old_suffix);
-    j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s", dbfile, new_suffix);
+    j = BIO_snprintf(buf[4], sizeof(buf[4]), "%s-attr", dbfile);
+    j = BIO_snprintf(buf[3], sizeof(buf[3]), "%s-attr-%s", dbfile, old_suffix);
+    j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s-attr-%s", dbfile, new_suffix);
+    j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-%s", dbfile, old_suffix);
+    j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", dbfile, new_suffix);
 #endif
     if (rename(dbfile, buf[1]) < 0 && errno != ENOENT
 #ifdef ENOTDIR
 #endif
     if (rename(dbfile, buf[1]) < 0 && errno != ENOENT
 #ifdef ENOTDIR
@@ -1704,6 +1735,7 @@ void free_index(CA_DB *db)
 {
     if (db) {
         TXT_DB_free(db->db);
 {
     if (db) {
         TXT_DB_free(db->db);
+        OPENSSL_free(db->dbfname);
         OPENSSL_free(db);
     }
 }
         OPENSSL_free(db);
     }
 }
@@ -2335,6 +2367,116 @@ int app_isdir(const char *name)
 }
 #endif
 
 }
 #endif
 
+/* app_dirname section */
+
+/*
+ * This exactly follows what POSIX's
+ * dirname does, but is implemented
+ * in a more platform independent way.
+ *
+ * path        dirname
+ * /usr/lib    /usr
+ * /usr/       /
+ * usr         .
+ * /           /
+ * .           .
+ * ..          .
+ * ""          .
+ *
+ * Note: this function also keeps the
+ * possibility of modifying the 'path'
+ * string same as POSIX dirname.
+ */
+static char *posix_dirname(char *path)
+{
+    size_t l;
+    char *ret = ".";
+
+    l = strlen(path);
+    if (l == 0)
+        goto out;
+    if (strcmp(path, ".") == 0)
+        goto out;
+    if (strcmp(path, "..") == 0)
+        goto out;
+    if (strcmp(path, "/") == 0) {
+        ret = "/";
+        goto out;
+    }
+    if (path[l - 1] == '/') {
+        /* /usr/ */
+        path[l - 1] = '\0';
+    }
+    if ((ret = strrchr(path, '/')) == NULL) {
+        /* usr */
+        ret = ".";
+    } else if (ret == path) {
+        /* /usr */
+        *++ret = '\0';
+        ret = path;
+    } else {
+        /* /usr/lib */
+        *ret = '\0';
+        ret = path;
+    }
+ out:
+    return ret;
+}
+
+/*
+ * TODO: implement app_dirname for Windows.
+ */
+#if !defined(_WIN32)
+char *app_dirname(char *path)
+{
+    return posix_dirname(path);
+}
+#elif defined(__VMS)
+/*
+ * sys$filescan fills the given item list with pointers into the original
+ * path string, so all we need to do is to find the file name and simply
+ * put a NUL byte wherever the FSCN$_NAME pointer points.  If there is no
+ * file name part and the path string isn't the empty string, we know for
+ * a fact that the whole string is a directory spec and return it as is.
+ * Otherwise or if that pointer is the starting address of the original
+ * path string, we know to return "sys$disk:[]", which corresponds to the
+ * Unixly ".".
+ *
+ * If sys$filescan returns an error status, we know that this is not
+ * parsable as a VMS file spec, and then use the fallback, in case we
+ * have a Unix type path.
+ */
+char *app_dirname(char *path)
+{
+    char *ret = "sys$disk:[]";
+    struct dsc$descriptor_s dsc_path = { 0 };
+    ile2 itemlist[] = {
+        {0, FSCN$_NAME, 0},
+        {0, 0, 0}
+    };
+    int fields;
+    int status;
+
+    dsc_path.dsc$a_pointer = path;
+    dsc_path.dsc$w_length = strlen(path);
+    status = sys$filescan(&dsc_path, itemlist, &fields, 0, 0);
+
+    if (!(status & 1))
+        return posix_dirname(path);
+
+    if ((fields & (1 << FSCN$_NAME)) == 0) {
+        if (dsc_path.dsc$w_length != 0)
+            ret = path;
+    } else if (itemlist[0].ile2$ps_bufaddr != path) {
+        if (itemlist[0].ile2$ps_bufaddr != path) {
+            *itemlist[0].ile2$ps_bufaddr = '\0';
+            ret = path;
+        }
+    }
+    return ret;
+}
+#endif
+
 /* raw_read|write section */
 #if defined(__VMS)
 # include "vms_term_sock.h"
 /* raw_read|write section */
 #if defined(__VMS)
 # include "vms_term_sock.h"
@@ -2423,14 +2565,26 @@ BIO *dup_bio_in(int format)
                       BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0));
 }
 
                       BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0));
 }
 
+static BIO_METHOD *prefix_method = NULL;
+
 BIO *dup_bio_out(int format)
 {
     BIO *b = BIO_new_fp(stdout,
                         BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0));
 BIO *dup_bio_out(int format)
 {
     BIO *b = BIO_new_fp(stdout,
                         BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0));
+    void *prefix = NULL;
+
 #ifdef OPENSSL_SYS_VMS
     if (istext(format))
         b = BIO_push(BIO_new(BIO_f_linebuffer()), b);
 #endif
 #ifdef OPENSSL_SYS_VMS
     if (istext(format))
         b = BIO_push(BIO_new(BIO_f_linebuffer()), b);
 #endif
+
+    if (istext(format) && (prefix = getenv("HARNESS_OSSL_PREFIX")) != NULL) {
+        if (prefix_method == NULL)
+            prefix_method = apps_bf_prefix();
+        b = BIO_push(BIO_new(prefix_method), b);
+        BIO_ctrl(b, PREFIX_CTRL_SET_PREFIX, 0, prefix);
+    }
+
     return b;
 }
 
     return b;
 }
 
@@ -2445,6 +2599,12 @@ BIO *dup_bio_err(int format)
     return b;
 }
 
     return b;
 }
 
+void destroy_prefix_method()
+{
+    BIO_meth_free(prefix_method);
+    prefix_method = NULL;
+}
+
 void unbuffer(FILE *fp)
 {
 /*
 void unbuffer(FILE *fp)
 {
 /*