]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
APPS/storeutl: fix case where uri and outfile are the same
authorDr. David von Oheimb <dev@ddvo.net>
Fri, 27 Sep 2024 06:24:45 +0000 (08:24 +0200)
committerTomas Mraz <tomas@openssl.org>
Wed, 9 Oct 2024 09:10:19 +0000 (11:10 +0200)
Reviewed-by: Viktor Dukhovni <viktor@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/25559)

apps/storeutl.c
doc/man1/openssl-storeutl.pod.in
test/recipes/90-test_store.t

index 249dc75c83acba3ac1f3f8cede5ade0e56e2ea8b..b131278a859299d981048536638deee0e742fe93 100644 (file)
 
 static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
                    int expected, int criterion, OSSL_STORE_SEARCH *search,
-                   int text, int noout, int recursive, int indent, BIO *out,
+                   int text, int noout, int recursive, int indent, const char *outfile,
                    const char *prog, OSSL_LIB_CTX *libctx);
 
+static BIO *out = NULL;
+
 typedef enum OPTION_choice {
     OPT_COMMON,
     OPT_ENGINE, OPT_OUT, OPT_PASSIN,
@@ -71,7 +73,6 @@ int storeutl_main(int argc, char *argv[])
 {
     int ret = 1, noout = 0, text = 0, recursive = 0;
     char *outfile = NULL, *passin = NULL, *passinarg = NULL;
-    BIO *out = NULL;
     ENGINE *e = NULL;
     OPTION_CHOICE o;
     char *prog;
@@ -311,13 +312,9 @@ int storeutl_main(int argc, char *argv[])
     pw_cb_data.password = passin;
     pw_cb_data.prompt_info = argv[0];
 
-    out = bio_open_default(outfile, 'w', FORMAT_TEXT);
-    if (out == NULL)
-        goto end;
-
     ret = process(argv[0], get_ui_method(), &pw_cb_data,
                   expected, criterion, search,
-                  text, noout, recursive, 0, out, prog, libctx);
+                  text, noout, recursive, 0, outfile, prog, libctx);
 
  end:
     EVP_MD_free(digest);
@@ -348,7 +345,7 @@ static int indent_printf(int indent, BIO *bio, const char *format, ...)
 
 static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
                    int expected, int criterion, OSSL_STORE_SEARCH *search,
-                   int text, int noout, int recursive, int indent, BIO *out,
+                   int text, int noout, int recursive, int indent, const char *outfile,
                    const char *prog, OSSL_LIB_CTX *libctx)
 {
     OSSL_STORE_CTX *store_ctx = NULL;
@@ -427,6 +424,13 @@ static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
             indent_printf(indent, bio_out, "%d: %s\n", items, infostr);
         }
 
+        if (out == NULL) {
+            if ((out = bio_open_default(outfile, 'w', FORMAT_TEXT)) == NULL) {
+                ret++;
+                goto end2;
+            }
+        }
+
         /*
          * Unfortunately, PEM_X509_INFO_write_bio() is sorely lacking in
          * functionality, so we must figure out how exactly to write things
@@ -438,7 +442,7 @@ static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
                 const char *suburi = OSSL_STORE_INFO_get0_NAME(info);
                 ret += process(suburi, uimeth, uidata,
                                expected, criterion, search,
-                               text, noout, recursive, indent + 2, out, prog,
+                               text, noout, recursive, indent + 2, outfile, prog,
                                libctx);
             }
             break;
index bdae5995553d74d2e3f54c27e86ad39197973de9..75acb077430c877a080a09dbe622f6d47a15d586 100644 (file)
@@ -45,8 +45,11 @@ Print out a usage message.
 
 =item B<-out> I<filename>
 
-specifies the output filename to write to or standard output by
-default.
+This specifies the output file to write to.
+Standard output is used if this option is not present.
+The output file can be the same as the input,
+which leads to replacing the file contents.
+Note that file I/O is not atomic. The output file is truncated and then written.
 
 =item B<-noout>
 
index 7c5624e5a225ae7b3b591e47772c8aff8050c7a8..f0f9e4d94b1d5e6363cf7b1cd27eac4bb9e7ec81 100644 (file)
@@ -16,6 +16,8 @@ use OpenSSL::Test::Utils;
 my $test_name = "test_store";
 setup($test_name);
 
+require(srctop_file("test", "recipes", "tconversion.pl")); # for test_file_contains()
+
 my $use_md5 = !disabled("md5");
 my $use_des = !(disabled("des") || disabled("legacy")); # also affects 3des and pkcs12 app
 my $use_dsa = !disabled("dsa");
@@ -106,7 +108,7 @@ push @methods, [ @prov_method ];
 push @methods, [qw(-engine loader_attic)]
     unless disabled('loadereng');
 
-my $n = 2 + scalar @methods
+my $n = 4 + scalar @methods
     * ( (3 * scalar @noexist_files)
         + (6 * scalar @src_files)
         + (2 * scalar @data_files)
@@ -172,6 +174,11 @@ indir "store_$$" => sub {
 
         my $rehash = init_rehash();
 
+        ok(run(app(["openssl", "storeutl", "-out", "cacert.pem", "cacert.pem"])),
+            "identical infile and outfile");
+        test_file_contains("storeutl output on same input",
+                           "cacert.pem", "Total found: 1");
+
         foreach my $method (@methods) {
             my @storeutl = ( qw(openssl storeutl), @$method );