diff --git a/Configurations/10-main.conf b/Configurations/10-main.conf index 859e3d9d..1e491184 100644 --- a/Configurations/10-main.conf +++ b/Configurations/10-main.conf @@ -1100,8 +1100,7 @@ my %targets = ( module_ldflags => "-Wl,-G,-bsymbolic,-bexpall", shared_ldflag => "-Wl,-G,-bsymbolic", shared_defflag => "-Wl,-bE:", - lib_extension => shared("_a.a"), - shared_extension_simple => shared(".a"), + perl_platform => 'AIX', }, "aix-gcc" => { inherit_from => [ "aix-common", asm("ppc32_asm") ], diff --git a/Configurations/README b/Configurations/README index a106f8c8..8efabb37 100644 --- a/Configurations/README +++ b/Configurations/README @@ -159,7 +159,7 @@ In each table entry, the following keys are significant: below [2]. dso_scheme => The type of dynamic shared objects to build for. This mostly comes into play with - engines, but can be used for other purposes + modules, but can be used for other purposes as well. Valid values are "DLFCN" (dlopen() et al), "DLFCN_NO_H" (for systems that use dlopen() et al but do not have @@ -350,7 +350,7 @@ In each table entry, the following keys are significant: - shared libraries; that would be libcrypto and libssl. - shared objects (sometimes called dynamic libraries); that would - be the engines. + be the modules. - applications; those are apps/openssl and all the test apps. Very roughly speaking, linking is done like this (words in braces @@ -411,10 +411,10 @@ variables: PROGRAMS=foo bar LIBS=libsomething - ENGINES=libeng + MODULES=libeng SCRIPTS=myhack -Note that the files mentioned for PROGRAMS, LIBS and ENGINES *must* be +Note that the files mentioned for PROGRAMS, LIBS and MODULES *must* be without extensions. The build file templates will figure them out. For each thing to be built, it is then possible to say what sources diff --git a/Configurations/README.design b/Configurations/README.design index 75c19a68..b79d0b2e 100644 --- a/Configurations/README.design +++ b/Configurations/README.design @@ -36,7 +36,7 @@ in build.info. Their file name extensions will be inferred by the build-file templates, adapted for the platform they are meant for (see sections on %unified_info and build-file templates further down). -The variables PROGRAMS, LIBS, ENGINES and SCRIPTS are used to declare +The variables PROGRAMS, LIBS, MODULES and SCRIPTS are used to declare end products. There are variants for them with '_NO_INST' as suffix (PROGRAM_NO_INST etc) to specify end products that shouldn't get installed. @@ -47,12 +47,12 @@ particular produced file, extra dependencies, include directories needed, or C macros to be defined. All their values in all the build.info throughout the source tree are -collected together and form a set of programs, libraries, engines and +collected together and form a set of programs, libraries, modules and scripts to be produced, source files, dependencies, etc etc etc. Let's have a pretend example, a very limited contraption of OpenSSL, composed of the program 'apps/openssl', the libraries 'libssl' and -'libcrypto', an engine 'engines/ossltest' and their sources and +'libcrypto', an module 'engines/ossltest' and their sources and dependencies. # build.info @@ -120,22 +120,22 @@ This is the build.info file in 'ssl/', and it tells us that the library 'libssl' is built from the source file 'ssl/tls.c'. # engines/build.info - ENGINES=dasync + MODULES=dasync SOURCE[dasync]=e_dasync.c DEPEND[dasync]=../libcrypto INCLUDE[dasync]=../include - ENGINES_NO_INST=ossltest + MODULES_NO_INST=ossltest SOURCE[ossltest]=e_ossltest.c DEPEND[ossltest]=../libcrypto.a INCLUDE[ossltest]=../include -This is the build.info file in 'engines/', telling us that two engines +This is the build.info file in 'engines/', telling us that two modules called 'engines/dasync' and 'engines/ossltest' shall be built, that dasync's source is 'engines/e_dasync.c' and ossltest's source is 'engines/e_ossltest.c' and that the include directory 'include/' may -be used when building anything that will be part of these engines. -Also, both engines depend on the library 'libcrypto' to function +be used when building anything that will be part of these modules. +Also, both modules depend on the library 'libcrypto' to function properly. ossltest is explicitly linked with the static variant of the library 'libcrypto'. Finally, only dasync is being installed, as ossltest is only for internal testing. @@ -156,12 +156,12 @@ information comes down to this: INCLUDE[apps/openssl]=. include DEPEND[apps/openssl]=libssl - ENGINES=engines/dasync + MODULES=engines/dasync SOURCE[engines/dasync]=engines/e_dasync.c DEPEND[engines/dasync]=libcrypto INCLUDE[engines/dasync]=include - ENGINES_NO_INST=engines/ossltest + MODULES_NO_INST=engines/ossltest SOURCE[engines/ossltest]=engines/e_ossltest.c DEPEND[engines/ossltest]=libcrypto.a INCLUDE[engines/ossltest]=include @@ -177,10 +177,10 @@ LIBS may be used to declare routine libraries only. PROGRAMS may be used to declare programs only. -ENGINES may be used to declare engines only. +MODULES may be used to declare modules only. The indexes for SOURCE must only be end product files, such as -libraries, programs or engines. The values of SOURCE variables must +libraries, programs or modules. The values of SOURCE variables must only be source files (possibly generated). INCLUDE and DEPEND shows a relationship between different files @@ -209,8 +209,8 @@ indexes: pairs. These are directly inferred from the DEPEND variables in build.info files. - engines => a list of engines. These are directly inferred from - the ENGINES variable in build.info files. + modules => a list of modules. These are directly inferred from + the MODULES variable in build.info files. generate => a hash table containing 'file' => [ 'generator' ... ] pairs. These are directly inferred from the GENERATE @@ -221,7 +221,7 @@ indexes: variables in build.info files. install => a hash table containing 'type' => [ 'file' ... ] pairs. - The types are 'programs', 'libraries', 'engines' and + The types are 'programs', 'libraries', 'modules' and 'scripts', and the array of files list the files of that type that should be installed. @@ -280,7 +280,7 @@ section above would be digested into a %unified_info table: "util/Foo.pm", ], }, - "engines" => + "modules" => [ "engines/dasync", "engines/ossltest", @@ -321,7 +321,7 @@ section above would be digested into a %unified_info table: } "install" => { - "engines" => + "modules" => [ "engines/dasync", ], @@ -556,7 +556,7 @@ etc. 'sources' has the list of source files to build the resulting script from. -Along with the build-file templates is the driving engine +Along with the build-file templates is the driving template Configurations/common.tmpl, which looks through all the information in %unified_info and generates all the rulesets to build libraries, programs and all intermediate files, using the rule generating diff --git a/Configurations/common.tmpl b/Configurations/common.tmpl index a15971ef..5ca0d562 100644 --- a/Configurations/common.tmpl +++ b/Configurations/common.tmpl @@ -143,10 +143,10 @@ $cache{$lib} = 1; } - # doengine is responsible for building engines. It will call + # domodule is responsible for building modules. It will call # obj2dso, and also makes sure all object files for the library # are built. - sub doengine { + sub domodule { my $lib = shift; return "" if $cache{$lib}; $OUT .= obj2dso(lib => $lib, @@ -209,10 +209,10 @@ # Build mandatory generated headers foreach (@{$unified_info{depends}->{""}}) { dogenerate($_); } - # Build all known libraries, engines, programs and scripts. + # Build all known libraries, modules, programs and scripts. # Everything else will be handled as a consequence. foreach (@{$unified_info{libraries}}) { dolib($_); } - foreach (@{$unified_info{engines}}) { doengine($_); } + foreach (@{$unified_info{modules}}) { domodule($_); } foreach (@{$unified_info{programs}}) { dobin($_); } foreach (@{$unified_info{scripts}}) { doscript($_); } diff --git a/Configurations/descrip.mms.tmpl b/Configurations/descrip.mms.tmpl index ae365c6f..8efdeb7b 100644 --- a/Configurations/descrip.mms.tmpl +++ b/Configurations/descrip.mms.tmpl @@ -55,8 +55,9 @@ grep { !$unified_info{attributes}->{$_}->{noinst} } @{$unified_info{libraries}}; our @install_engines = - grep { !$unified_info{attributes}->{$_}->{noinst} } - @{$unified_info{engines}}; + grep { !$unified_info{attributes}->{$_}->{noinst} + && $unified_info{attributes}->{$_}->{engine} } + @{$unified_info{modules}}; our @install_programs = grep { !$unified_info{attributes}->{$_}->{noinst} } @{$unified_info{programs}}; @@ -122,7 +123,7 @@ SHLIB_TARGET={- $target{shared_target} -} LIBS={- join(", ", map { "-\n\t".$_.".OLB" } @libs) -} SHLIBS={- join(", ", map { "-\n\t".$_.".EXE" } @shlibs) -} -ENGINES={- join(", ", map { "-\n\t".$_.".EXE" } @{$unified_info{engines}}) -} +MODULES={- join(", ", map { "-\n\t".$_.".EXE" } @{$unified_info{modules}}) -} PROGRAMS={- join(", ", map { "-\n\t".$_.".EXE" } @{$unified_info{programs}}) -} SCRIPTS={- join(", ", map { "-\n\t".$_ } @{$unified_info{scripts}}) -} {- output_off() if $disabled{makedepend}; "" -} @@ -164,7 +165,7 @@ OPENSSLDIR={- catdir($config{openssldir}) or : "SYS\$COMMON:[OPENSSL-COMMON]" -} # The same, but for C OPENSSLDIR_C={- platform->osslprefix() -}DATAROOT:[000000] -# Where installed engines reside, for C +# Where installed ENGINE modules reside, for C ENGINESDIR_C={- platform->osslprefix() -}ENGINES{- $sover_dirname.$target{pointer_size} -}: ##### User defined commands and flags ################################ @@ -400,14 +401,14 @@ NODEBUG=@ # The main targets ################################################### -{- dependmagic('all'); -} : build_libs_nodep, build_engines_nodep, build_programs_nodep +{- dependmagic('all'); -} : build_libs_nodep, build_modules_nodep, build_programs_nodep {- dependmagic('build_libs'); -} : build_libs_nodep -{- dependmagic('build_engines'); -} : build_engines_nodep +{- dependmagic('build_modules'); -} : build_modules_nodep {- dependmagic('build_programs'); -} : build_programs_nodep build_generated : $(GENERATED_MANDATORY) build_libs_nodep : $(LIBS), $(SHLIBS) -build_engines_nodep : $(ENGINES) +build_modules_nodep : $(MODULES) build_programs_nodep : $(PROGRAMS), $(SCRIPTS) # Kept around for backward compatibility @@ -423,7 +424,7 @@ build_all_generated : $(GENERATED_MANDATORY) $(GENERATED) @ ! {- output_on() if $disabled{makedepend}; "" -} test : tests -{- dependmagic('tests'); -} : build_programs_nodep, build_engines_nodep +{- dependmagic('tests'); -} : build_programs_nodep, build_modules_nodep @ ! {- output_off() if $disabled{tests}; "" -} SET DEFAULT [.test]{- move("test") -} CREATE/DIR [.test-runs] @@ -483,14 +484,14 @@ check_install : uninstall : uninstall_docs uninstall_sw # Because VMS wants the generation number (or *) to delete files, we can't -# use $(LIBS), $(PROGRAMS), $(GENERATED) and $(ENGINES)directly. +# use $(LIBS), $(PROGRAMS), $(GENERATED) and $(MODULES) directly. libclean : {- join("\n\t", map { "- DELETE $_.OLB;*" } @libs) || "@ !" -} {- join("\n\t", map { "- DELETE $_.EXE;*,$_.MAP;*" } @shlibs) || "@ !" -} clean : libclean {- join("\n\t", map { "- DELETE $_.EXE;*,$_.OPT;*" } @{$unified_info{programs}}) || "@ !" -} - {- join("\n\t", map { "- DELETE $_.EXE;*,$_.OPT;*" } @{$unified_info{engines}}) || "@ !" -} + {- join("\n\t", map { "- DELETE $_.EXE;*,$_.OPT;*" } @{$unified_info{modules}}) || "@ !" -} {- join("\n\t", map { "- DELETE $_;*" } @{$unified_info{scripts}}) || "@ !" -} {- join("\n\t", map { "- DELETE $_;*" } @{$unified_info{depends}->{""}}) || "@ !" -} {- join("\n\t", map { "- DELETE $_;*" } @generated) || "@ !" -} @@ -557,14 +558,14 @@ install_dev : check_INSTALLTOP install_runtime_libs map { "COPY/PROT=W:R $_.OLB ossl_installroot:[LIB.'arch']" } @install_libs) -} -install_engines : check_INSTALLTOP install_runtime_libs build_engines - @ {- output_off() unless scalar @{$unified_info{engines}}; "" -} ! - @ WRITE SYS$OUTPUT "*** Installing engines" +install_engines : check_INSTALLTOP install_runtime_libs build_modules + @ {- output_off() unless scalar @install_engines; "" -} ! + @ WRITE SYS$OUTPUT "*** Installing ENGINE modules" - CREATE/DIR ossl_installroot:[ENGINES{- $sover_dirname.$target{pointer_size} -}.'arch'] {- join("\n ", map { "COPY/PROT=W:RE $_.EXE ossl_installroot:[ENGINES$sover_dirname$target{pointer_size}.'arch']" } @install_engines) -} - @ {- output_on() unless scalar @{$unified_info{engines}}; "" -} ! + @ {- output_on() unless scalar @install_engines; "" -} ! install_runtime : install_programs diff --git a/Configurations/platform/AIX.pm b/Configurations/platform/AIX.pm new file mode 100644 index 00000000..f441c157 --- /dev/null +++ b/Configurations/platform/AIX.pm @@ -0,0 +1,27 @@ +package platform::AIX; + +use strict; +use warnings; +use Carp; + +use vars qw(@ISA); + +require platform::Unix; +@ISA = qw(platform::Unix); + +# Assume someone set @INC right before loading this module +use configdata; + +sub shlibextsimple { '.a' } + +# In shared mode, the default static library names clashes with the final +# "simple" full shared library name, so we add '_a' to the basename of the +# static libraries in that case. +sub staticname { + # Non-installed libraries are *always* static, and their names remain + # the same, except for the mandatory extension + my $in_libname = platform::BASE->staticname($_[1]); + return $in_libname if $unified_info{attributes}->{$_[1]}->{noinst}; + + return platform::BASE->staticname($_[1]) . '_a'; +} diff --git a/Configurations/platform/BASE.pm b/Configurations/platform/BASE.pm index b7fec110..fcd7b70c 100644 --- a/Configurations/platform/BASE.pm +++ b/Configurations/platform/BASE.pm @@ -28,8 +28,8 @@ sub sharedname { return __isshared($_[1]) ? $_[1] : undef } # Name of shared li sub staticname { return __base($_[1], '.a') } # Name of static lib # Convenience function to convert the shlib version to an acceptable part -# of a file or directory name. -sub shlib_version_as_filename { return $_[1] } +# of a file or directory name. By default, we consider it acceptable as is. +sub shlib_version_as_filename { return $config{shlib_version} } # Convenience functions to convert the possible extension of an input file name sub bin { return $_[0]->binname($_[1]) . $_[0]->binext() } diff --git a/Configurations/unix-Makefile.tmpl b/Configurations/unix-Makefile.tmpl index 36286f68..7705b03b 100644 --- a/Configurations/unix-Makefile.tmpl +++ b/Configurations/unix-Makefile.tmpl @@ -40,7 +40,7 @@ SHLIB_INFO={- join(" ", map { my $x = platform->sharedlib($_); my $y = platform->sharedlib_simple($_); $x ? "\"$x;$y\"" : () } @{$unified_info{libraries}}) -} -ENGINES={- join(" ", map { platform->dso($_) } @{$unified_info{engines}}) -} +MODULES={- join(" ", map { platform->dso($_) } @{$unified_info{modules}}) -} PROGRAMS={- join(" ", map { platform->bin($_) } @{$unified_info{programs}}) -} SCRIPTS={- join(" ", @{$unified_info{scripts}}) -} {- output_off() if $disabled{makedepend}; "" -} @@ -71,8 +71,9 @@ INSTALL_SHLIB_INFO={- -} INSTALL_ENGINES={- join(" ", map { platform->dso($_) } - grep { !$unified_info{attributes}->{$_}->{noinst} } - @{$unified_info{engines}}) + grep { !$unified_info{attributes}->{$_}->{noinst} + && $unified_info{attributes}->{$_}->{engine} } + @{$unified_info{modules}}) -} INSTALL_PROGRAMS={- join(" ", map { platform->bin($_) } @@ -312,14 +313,14 @@ LANG=C # The main targets ################################################### -{- dependmagic('all'); -}: build_libs_nodep build_engines_nodep build_programs_nodep link-utils +{- dependmagic('all'); -}: build_libs_nodep build_modules_nodep build_programs_nodep link-utils {- dependmagic('build_libs'); -}: build_libs_nodep -{- dependmagic('build_engines'); -}: build_engines_nodep +{- dependmagic('build_modules'); -}: build_modules_nodep {- dependmagic('build_programs'); -}: build_programs_nodep build_generated: $(GENERATED_MANDATORY) build_libs_nodep: libcrypto.pc libssl.pc openssl.pc -build_engines_nodep: $(ENGINES) +build_modules_nodep: $(MODULES) build_programs_nodep: $(PROGRAMS) $(SCRIPTS) # Kept around for backward compatibility @@ -335,7 +336,7 @@ build_all_generated: $(GENERATED_MANDATORY) $(GENERATED) @ : {- output_on() if $disabled{makedepend}; "" -} test: tests -{- dependmagic('tests'); -}: build_programs_nodep build_engines_nodep link-utils +{- dependmagic('tests'); -}: build_programs_nodep build_modules_nodep link-utils @ : {- output_off() if $disabled{tests}; "" -} ( cd test; \ mkdir -p test-runs; \ @@ -382,7 +383,7 @@ libclean: $(RM) *{- platform->defext() -} clean: libclean - $(RM) $(PROGRAMS) $(TESTPROGS) $(ENGINES) $(SCRIPTS) + $(RM) $(PROGRAMS) $(TESTPROGS) $(MODULES) $(SCRIPTS) $(RM) $(GENERATED_MANDATORY) $(GENERATED) -$(RM) `find . -name .git -prune -o -name '*{- platform->depext() -}' -print` -$(RM) `find . -name .git -prune -o -name '*{- platform->objext() -}' -print` @@ -578,10 +579,10 @@ uninstall_dev: uninstall_runtime_libs -$(RMDIR) $(DESTDIR)$(libdir)/pkgconfig -$(RMDIR) $(DESTDIR)$(libdir) -install_engines: install_runtime_libs build_engines +install_engines: install_runtime_libs build_modules @[ -n "$(INSTALLTOP)" ] || (echo INSTALLTOP should not be empty; exit 1) @$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(ENGINESDIR)/ - @$(ECHO) "*** Installing engines" + @$(ECHO) "*** Installing ENGINE modules" @set -e; for e in dummy $(INSTALL_ENGINES); do \ if [ "$$e" = "dummy" ]; then continue; fi; \ fn=`basename $$e`; \ @@ -593,7 +594,7 @@ install_engines: install_runtime_libs build_engines done uninstall_engines: - @$(ECHO) "*** Uninstalling engines" + @$(ECHO) "*** Uninstalling ENGINE modules" @set -e; for e in dummy $(INSTALL_ENGINES); do \ if [ "$$e" = "dummy" ]; then continue; fi; \ fn=`basename $$e`; \ @@ -1193,7 +1194,7 @@ EOF push @linkdirs, $d unless grep { $d eq $_ } @linkdirs; } my $linkflags = join("", map { "-L$_ " } @linkdirs); - my $linklibs = join("", map { if ($_ =~ s/\.a$//) { + my $linklibs = join("", map { if ($_ =~ m/\.a$/) { " ".platform->staticlib($_); } else { my $f = basename($_); diff --git a/Configurations/windows-makefile.tmpl b/Configurations/windows-makefile.tmpl index 0cd1e863..6d38cfe1 100644 --- a/Configurations/windows-makefile.tmpl +++ b/Configurations/windows-makefile.tmpl @@ -45,8 +45,8 @@ SHLIB_VERSION_NUMBER={- $config{shlib_version} -} LIBS={- join(" ", map { ( platform->sharedlib_import($_), platform->staticlib($_) ) } @{$unified_info{libraries}}) -} SHLIBS={- join(" ", map { platform->sharedlib($_) // () } @{$unified_info{libraries}}) -} SHLIBPDBS={- join(" ", map { platform->sharedlibpdb($_) // () } @{$unified_info{libraries}}) -} -ENGINES={- join(" ", map { platform->dso($_) } @{$unified_info{engines}}) -} -ENGINEPDBS={- join(" ", map { platform->dsopdb($_) } @{$unified_info{engines}}) -} +MODULES={- join(" ", map { platform->dso($_) } @{$unified_info{modules}}) -} +MODULEPDBS={- join(" ", map { platform->dsopdb($_) } @{$unified_info{modules}}) -} PROGRAMS={- our @PROGRAMS = map { platform->bin($_) } @{$unified_info{programs}}; join(" ", @PROGRAMS) -} PROGRAMPDBS={- join(" ", map { $_.".pdb" } @{$unified_info{programs}}) -} SCRIPTS={- join(" ", @{$unified_info{scripts}}) -} @@ -79,13 +79,15 @@ INSTALL_SHLIBPDBS={- -} INSTALL_ENGINES={- join(" ", map { quotify1(platform->dso($_)) } - grep { !$unified_info{attributes}->{$_}->{noinst} } - @{$unified_info{engines}}) + grep { !$unified_info{attributes}->{$_}->{noinst} + && $unified_info{attributes}->{$_}->{engine} } + @{$unified_info{modules}}) -} INSTALL_ENGINEPDBS={- join(" ", map { quotify1(platform->dsopdb($_)) } - grep { !$unified_info{attributes}->{$_}->{noinst} } - @{$unified_info{engines}}) + grep { !$unified_info{attributes}->{$_}->{noinst} + && $unified_info{attributes}->{$_}->{engine} } + @{$unified_info{modules}}) -} INSTALL_PROGRAMS={- join(" ", map { quotify1(platform->bin($_)) } @@ -311,14 +313,14 @@ PROCESSOR= {- $config{processor} -} # The main targets ################################################### -{- dependmagic('all'); -}: build_libs_nodep build_engines_nodep build_programs_nodep +{- dependmagic('all'); -}: build_libs_nodep build_modules_nodep build_programs_nodep {- dependmagic('build_libs'); -}: build_libs_nodep -{- dependmagic('build_engines'); -}: build_engines_nodep +{- dependmagic('build_modules'); -}: build_modules_nodep {- dependmagic('build_programs'); -}: build_programs_nodep build_generated: $(GENERATED_MANDATORY) build_libs_nodep: $(LIBS) {- join(" ",map { platform->sharedlib_import($_) // () } @{$unified_info{libraries}}) -} -build_engines_nodep: $(ENGINES) +build_modules_nodep: $(MODULES) build_programs_nodep: $(PROGRAMS) $(SCRIPTS) # Kept around for backward compatibility @@ -334,7 +336,7 @@ build_all_generated: $(GENERATED_MANDATORY) $(GENERATED) @{- output_on() if $disabled{makedepend}; "" -} test: tests -{- dependmagic('tests'); -}: build_programs_nodep build_engines_nodep +{- dependmagic('tests'); -}: build_programs_nodep build_modules_nodep @{- output_off() if $disabled{tests}; "" -} -mkdir $(BLDDIR)\test\test-runs set SRCTOP=$(SRCDIR) @@ -366,7 +368,7 @@ libclean: clean: libclean {- join("\n\t", map { "-del /Q /F $_" } @PROGRAMS) -} - -del /Q /F $(ENGINES) + -del /Q /F $(MODULES) -del /Q /F $(SCRIPTS) -del /Q /F $(GENERATED_MANDATORY) -del /Q /F $(GENERATED) @@ -432,13 +434,13 @@ install_dev: install_runtime_libs uninstall_dev: -install_engines: install_runtime_libs build_engines +install_engines: install_runtime_libs build_modules @if "$(INSTALLTOP)"=="" ( $(ECHO) "INSTALLTOP should not be empty" & exit 1 ) - @$(ECHO) "*** Installing engines" + @$(ECHO) "*** Installing ENGINE modules" @"$(PERL)" "$(SRCDIR)\util\mkdir-p.pl" "$(ENGINESDIR)" - @if not "$(ENGINES)"=="" \ + @if not "$(INSTALL_ENGINES)"=="" \ "$(PERL)" "$(SRCDIR)\util\copy.pl" $(INSTALL_ENGINES) "$(ENGINESDIR)" - @if not "$(ENGINES)"=="" \ + @if not "$(INSTALL_ENGINES)"=="" \ "$(PERL)" "$(SRCDIR)\util\copy.pl" $(INSTALL_ENGINEPDBS) "$(ENGINESDIR)" uninstall_engines: diff --git a/Configure b/Configure index 8a178dfb..d6ae2bee 100755 --- a/Configure +++ b/Configure @@ -1711,7 +1711,7 @@ if ($builder eq "unified") { # The basic things we're trying to build my @programs = (); my @libraries = (); - my @engines = (); + my @modules = (); my @scripts = (); my %attributes = (); @@ -1823,12 +1823,12 @@ if ($builder eq "unified") { } } }, - qr/^\s*ENGINES(?:{([\w=]+(?:\s*,\s*[\w=]+)*)})?\s*=\s*(.*)\s*$/ + qr/^\s*MODULES(?:{([\w=]+(?:\s*,\s*[\w=]+)*)})?\s*=\s*(.*)\s*$/ => sub { if (!@skip || $skip[$#skip] > 0) { my @a = tokenize($1, qr|\s*,\s*|); - my @e = tokenize($2); - push @engines, @e; + my @m = tokenize($2); + push @modules, @m; foreach my $a (@a) { my $ak = $a; my $av = 1; @@ -1836,8 +1836,8 @@ if ($builder eq "unified") { $ak = $1; $av = $2; } - foreach my $e (@e) { - $attributes{$e}->{$ak} = $av; + foreach my $m (@m) { + $attributes{$m}->{$ak} = $av; } } } @@ -1899,10 +1899,13 @@ if ($builder eq "unified") { ); die "runaway IF?" if (@skip); - die <<"EOF" if scalar @engines and !$config{dynamic_engines}; + if (grep { defined $attributes{$_}->{engine} } keys %attributes + and !$config{dynamic_engines}) { + die <<"EOF" ENGINES can only be used if configured with 'dynamic-engine'. This is usually a fault in a build.info file. EOF + } foreach (keys %attributes) { my $dest = $_; @@ -1916,7 +1919,7 @@ EOF { my %infos = ( programs => [ @programs ], libraries => [ @libraries ], - engines => [ @engines ], + modules => [ @modules ], scripts => [ @scripts ] ); foreach my $k (keys %infos) { foreach (@{$infos{$k}}) { @@ -2142,7 +2145,7 @@ EOF if defined($unified_info{$_}); delete $unified_info{$_}; } - foreach my $prodtype (('programs', 'libraries', 'engines', 'scripts')) { + foreach my $prodtype (('programs', 'libraries', 'modules', 'scripts')) { # $intent serves multi purposes: # - give a prefix for the new object files names # - in the case of libraries, rearrange the object files so static @@ -2158,7 +2161,7 @@ EOF src => [ 'sources', 'shared_sources' ], dst => 'shared_sources' } }, - engines => { dso => { src => [ 'sources', + modules => { dso => { src => [ 'sources', 'shared_sources' ], dst => 'shared_sources' } }, scripts => { script => { src => [ 'sources' ], @@ -2220,7 +2223,7 @@ EOF ### Make unified_info a bit more efficient # One level structures - foreach (("programs", "libraries", "engines", "scripts")) { + foreach (("programs", "libraries", "modules", "scripts")) { $unified_info{$_} = [ sort keys %{$unified_info{$_}} ]; } # Two level structures @@ -2268,7 +2271,7 @@ EOF # they end up in where applicable. Then, add build rules for those # directories my %loopinfo = ( "lib" => [ @{$unified_info{libraries}} ], - "dso" => [ @{$unified_info{engines}} ], + "dso" => [ @{$unified_info{modules}} ], "bin" => [ @{$unified_info{programs}} ], "script" => [ @{$unified_info{scripts}} ] ); foreach my $type (keys %loopinfo) { diff --git a/apps/apps.c b/apps/apps.c index 39535e9e..44a90a33 100644 --- a/apps/apps.c +++ b/apps/apps.c @@ -54,9 +54,6 @@ typedef struct { unsigned long mask; } NAME_EX_TBL; -static UI_METHOD *ui_method = NULL; -static const UI_METHOD *ui_fallback_method = NULL; - 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, @@ -173,179 +170,12 @@ int dump_cert_text(BIO *out, X509 *x) return 0; } -static int ui_open(UI *ui) -{ - int (*opener)(UI *ui) = UI_method_get_opener(ui_fallback_method); - - if (opener) - return opener(ui); - return 1; -} - -static int ui_read(UI *ui, UI_STRING *uis) -{ - int (*reader)(UI *ui, UI_STRING *uis) = NULL; - - if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD - && UI_get0_user_data(ui)) { - switch (UI_get_string_type(uis)) { - case UIT_PROMPT: - case UIT_VERIFY: - { - const char *password = - ((PW_CB_DATA *)UI_get0_user_data(ui))->password; - if (password && password[0] != '\0') { - UI_set_result(ui, uis, password); - return 1; - } - } - break; - case UIT_NONE: - case UIT_BOOLEAN: - case UIT_INFO: - case UIT_ERROR: - break; - } - } - - reader = UI_method_get_reader(ui_fallback_method); - if (reader) - return reader(ui, uis); - return 1; -} - -static int ui_write(UI *ui, UI_STRING *uis) -{ - int (*writer)(UI *ui, UI_STRING *uis) = NULL; - - if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD - && UI_get0_user_data(ui)) { - switch (UI_get_string_type(uis)) { - case UIT_PROMPT: - case UIT_VERIFY: - { - const char *password = - ((PW_CB_DATA *)UI_get0_user_data(ui))->password; - if (password && password[0] != '\0') - return 1; - } - break; - case UIT_NONE: - case UIT_BOOLEAN: - case UIT_INFO: - case UIT_ERROR: - break; - } - } - - writer = UI_method_get_writer(ui_fallback_method); - if (writer) - return writer(ui, uis); - return 1; -} - -static int ui_close(UI *ui) -{ - int (*closer)(UI *ui) = UI_method_get_closer(ui_fallback_method); - - if (closer) - return closer(ui); - return 1; -} - -int setup_ui_method(void) -{ - ui_fallback_method = UI_null(); -#ifndef OPENSSL_NO_UI_CONSOLE - ui_fallback_method = UI_OpenSSL(); -#endif - ui_method = UI_create_method("OpenSSL application user interface"); - UI_method_set_opener(ui_method, ui_open); - UI_method_set_reader(ui_method, ui_read); - UI_method_set_writer(ui_method, ui_write); - UI_method_set_closer(ui_method, ui_close); - return 0; -} - -void destroy_ui_method(void) -{ - if (ui_method) { - UI_destroy_method(ui_method); - ui_method = NULL; - } -} - -const UI_METHOD *get_ui_method(void) -{ - return ui_method; -} - -int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_data) -{ - int res = 0; - UI *ui; - int ok = 0; - char *buff = NULL; - int ui_flags = 0; - const char *prompt_info = NULL; - char *prompt; - - if ((ui = UI_new_method(ui_method)) == NULL) - return 0; - - if (cb_data != NULL && cb_data->prompt_info != NULL) - prompt_info = cb_data->prompt_info; - prompt = UI_construct_prompt(ui, "pass phrase", prompt_info); - if (prompt == NULL) { - BIO_printf(bio_err, "Out of memory\n"); - UI_free(ui); - return 0; - } - - ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD; - UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0); - - /* We know that there is no previous user data to return to us */ - (void)UI_add_user_data(ui, cb_data); - - ok = UI_add_input_string(ui, prompt, ui_flags, buf, - PW_MIN_LENGTH, bufsiz - 1); - - if (ok >= 0 && verify) { - buff = app_malloc(bufsiz, "password buffer"); - ok = UI_add_verify_string(ui, prompt, ui_flags, buff, - PW_MIN_LENGTH, bufsiz - 1, buf); - } - if (ok >= 0) - do { - ok = UI_process(ui); - } while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0)); - - OPENSSL_clear_free(buff, (unsigned int)bufsiz); - - if (ok >= 0) - res = strlen(buf); - if (ok == -1) { - BIO_printf(bio_err, "User interface error\n"); - ERR_print_errors(bio_err); - OPENSSL_cleanse(buf, (unsigned int)bufsiz); - res = 0; - } - if (ok == -2) { - BIO_printf(bio_err, "aborted!\n"); - OPENSSL_cleanse(buf, (unsigned int)bufsiz); - res = 0; - } - UI_free(ui); - OPENSSL_free(prompt); - return res; -} - int wrap_password_callback(char *buf, int bufsiz, int verify, void *userdata) { return password_callback(buf, bufsiz, verify, (PW_CB_DATA *)userdata); } + static char *app_get_pass(const char *arg, int keepbio); int app_passwd(const char *arg1, const char *arg2, char **pass1, char **pass2) @@ -725,7 +555,9 @@ EVP_PKEY *load_key(const char *file, int format, int maybe_stdin, } else { #ifndef OPENSSL_NO_ENGINE if (ENGINE_init(e)) { - pkey = ENGINE_load_private_key(e, file, ui_method, &cb_data); + pkey = ENGINE_load_private_key(e, file, + (UI_METHOD *)get_ui_method(), + &cb_data); ENGINE_finish(e); } if (pkey == NULL) { @@ -792,7 +624,8 @@ EVP_PKEY *load_pubkey(const char *file, int format, int maybe_stdin, BIO_printf(bio_err, "no engine specified\n"); } else { #ifndef OPENSSL_NO_ENGINE - pkey = ENGINE_load_public_key(e, file, ui_method, &cb_data); + pkey = ENGINE_load_public_key(e, file, (UI_METHOD *)get_ui_method(), + &cb_data); if (pkey == NULL) { BIO_printf(bio_err, "cannot load %s from engine\n", key_descrip); ERR_print_errors(bio_err); @@ -1295,7 +1128,8 @@ ENGINE *setup_engine(const char *engine, int debug) if (debug) { ENGINE_ctrl(e, ENGINE_CTRL_SET_LOGSTREAM, 0, bio_err, 0); } - ENGINE_ctrl_cmd(e, "SET_USER_INTERFACE", 0, ui_method, 0, 1); + ENGINE_ctrl_cmd(e, "SET_USER_INTERFACE", 0, (void *)get_ui_method(), + 0, 1); if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) { BIO_printf(bio_err, "can't use that engine\n"); ERR_print_errors(bio_err); @@ -2321,56 +2155,10 @@ int app_access(const char* name, int flag) #endif } -/* app_isdir section */ -#ifdef _WIN32 int app_isdir(const char *name) { - DWORD attr; -# if defined(UNICODE) || defined(_UNICODE) - size_t i, len_0 = strlen(name) + 1; - WCHAR tempname[MAX_PATH]; - - if (len_0 > MAX_PATH) - return -1; - -# if !defined(_WIN32_WCE) || _WIN32_WCE>=101 - if (!MultiByteToWideChar(CP_ACP, 0, name, len_0, tempname, MAX_PATH)) -# endif - for (i = 0; i < len_0; i++) - tempname[i] = (WCHAR)name[i]; - - attr = GetFileAttributes(tempname); -# else - attr = GetFileAttributes(name); -# endif - if (attr == INVALID_FILE_ATTRIBUTES) - return -1; - return ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0); + return opt_isdir(name); } -#else -# include -# ifndef S_ISDIR -# if defined(_S_IFMT) && defined(_S_IFDIR) -# define S_ISDIR(a) (((a) & _S_IFMT) == _S_IFDIR) -# else -# define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR) -# endif -# endif - -int app_isdir(const char *name) -{ -# if defined(S_ISDIR) - struct stat st; - - if (stat(name, &st) == 0) - return S_ISDIR(st.st_mode); - else - return -1; -# else - return -1; -# endif -} -#endif /* raw_read|write section */ #if defined(__VMS) @@ -2443,21 +2231,16 @@ int raw_write_stdout(const void *buf, int siz) #endif /* - * Centralized handling if input and output files with format specification + * Centralized handling of input and output files with format specification * The format is meant to show what the input and output is supposed to be, * and is therefore a show of intent more than anything else. However, it - * does impact behavior on some platform, such as differentiating between + * does impact behavior on some platforms, such as differentiating between * text and binary input/output on non-Unix platforms */ -static int istext(int format) -{ - return (format & B_FORMAT_TEXT) == B_FORMAT_TEXT; -} - BIO *dup_bio_in(int format) { return BIO_new_fp(stdin, - BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0)); + BIO_NOCLOSE | (FMT_istext(format) ? BIO_FP_TEXT : 0)); } static BIO_METHOD *prefix_method = NULL; @@ -2465,15 +2248,15 @@ 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_NOCLOSE | (FMT_istext(format) ? BIO_FP_TEXT : 0)); void *prefix = NULL; #ifdef OPENSSL_SYS_VMS - if (istext(format)) + if (FMT_istext(format)) b = BIO_push(BIO_new(BIO_f_linebuffer()), b); #endif - if (istext(format) && (prefix = getenv("HARNESS_OSSL_PREFIX")) != NULL) { + if (FMT_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); @@ -2486,9 +2269,9 @@ BIO *dup_bio_out(int format) BIO *dup_bio_err(int format) { BIO *b = BIO_new_fp(stderr, - BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0)); + BIO_NOCLOSE | (FMT_istext(format) ? BIO_FP_TEXT : 0)); #ifdef OPENSSL_SYS_VMS - if (istext(format)) + if (FMT_istext(format)) b = BIO_push(BIO_new(BIO_f_linebuffer()), b); #endif return b; @@ -2525,11 +2308,11 @@ static const char *modestr(char mode, int format) switch (mode) { case 'a': - return istext(format) ? "a" : "ab"; + return FMT_istext(format) ? "a" : "ab"; case 'r': - return istext(format) ? "r" : "rb"; + return FMT_istext(format) ? "r" : "rb"; case 'w': - return istext(format) ? "w" : "wb"; + return FMT_istext(format) ? "w" : "wb"; } /* The assert above should make sure we never reach this point */ return NULL; @@ -2567,7 +2350,7 @@ BIO *bio_open_owner(const char *filename, int format, int private) #ifdef O_TRUNC mode |= O_TRUNC; #endif - textmode = istext(format); + textmode = FMT_istext(format); if (!textmode) { #ifdef O_BINARY mode |= O_BINARY; @@ -2746,3 +2529,14 @@ void make_uppercase(char *string) for (i = 0; string[i] != '\0'; i++) string[i] = toupper((unsigned char)string[i]); } + +int opt_printf_stderr(const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, fmt); + ret = BIO_vprintf(bio_err, fmt, ap); + va_end(ap); + return ret; +} diff --git a/apps/apps.h b/apps/apps.h index 460188df..da8eae2d 100644 --- a/apps/apps.h +++ b/apps/apps.h @@ -29,6 +29,9 @@ # include # include # include +# include "apps_ui.h" +# include "opt.h" +# include "fmt.h" # if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WINCE) # define openssl_fdset(a,b) FD_SET((unsigned int)a, b) @@ -88,330 +91,6 @@ void corrupt_signature(const ASN1_STRING *signature); int set_cert_times(X509 *x, const char *startdate, const char *enddate, int days); -/* - * Common verification options. - */ -# define OPT_V_ENUM \ - OPT_V__FIRST=2000, \ - OPT_V_POLICY, OPT_V_PURPOSE, OPT_V_VERIFY_NAME, OPT_V_VERIFY_DEPTH, \ - OPT_V_ATTIME, OPT_V_VERIFY_HOSTNAME, OPT_V_VERIFY_EMAIL, \ - OPT_V_VERIFY_IP, OPT_V_IGNORE_CRITICAL, OPT_V_ISSUER_CHECKS, \ - OPT_V_CRL_CHECK, OPT_V_CRL_CHECK_ALL, OPT_V_POLICY_CHECK, \ - OPT_V_EXPLICIT_POLICY, OPT_V_INHIBIT_ANY, OPT_V_INHIBIT_MAP, \ - OPT_V_X509_STRICT, OPT_V_EXTENDED_CRL, OPT_V_USE_DELTAS, \ - OPT_V_POLICY_PRINT, OPT_V_CHECK_SS_SIG, OPT_V_TRUSTED_FIRST, \ - OPT_V_SUITEB_128_ONLY, OPT_V_SUITEB_128, OPT_V_SUITEB_192, \ - OPT_V_PARTIAL_CHAIN, OPT_V_NO_ALT_CHAINS, OPT_V_NO_CHECK_TIME, \ - OPT_V_VERIFY_AUTH_LEVEL, OPT_V_ALLOW_PROXY_CERTS, \ - OPT_V__LAST - -# define OPT_V_OPTIONS \ - { "policy", OPT_V_POLICY, 's', "adds policy to the acceptable policy set"}, \ - { "purpose", OPT_V_PURPOSE, 's', \ - "certificate chain purpose"}, \ - { "verify_name", OPT_V_VERIFY_NAME, 's', "verification policy name"}, \ - { "verify_depth", OPT_V_VERIFY_DEPTH, 'n', \ - "chain depth limit" }, \ - { "auth_level", OPT_V_VERIFY_AUTH_LEVEL, 'n', \ - "chain authentication security level" }, \ - { "attime", OPT_V_ATTIME, 'M', "verification epoch time" }, \ - { "verify_hostname", OPT_V_VERIFY_HOSTNAME, 's', \ - "expected peer hostname" }, \ - { "verify_email", OPT_V_VERIFY_EMAIL, 's', \ - "expected peer email" }, \ - { "verify_ip", OPT_V_VERIFY_IP, 's', \ - "expected peer IP address" }, \ - { "ignore_critical", OPT_V_IGNORE_CRITICAL, '-', \ - "permit unhandled critical extensions"}, \ - { "issuer_checks", OPT_V_ISSUER_CHECKS, '-', "(deprecated)"}, \ - { "crl_check", OPT_V_CRL_CHECK, '-', "check leaf certificate revocation" }, \ - { "crl_check_all", OPT_V_CRL_CHECK_ALL, '-', "check full chain revocation" }, \ - { "policy_check", OPT_V_POLICY_CHECK, '-', "perform rfc5280 policy checks"}, \ - { "explicit_policy", OPT_V_EXPLICIT_POLICY, '-', \ - "set policy variable require-explicit-policy"}, \ - { "inhibit_any", OPT_V_INHIBIT_ANY, '-', \ - "set policy variable inhibit-any-policy"}, \ - { "inhibit_map", OPT_V_INHIBIT_MAP, '-', \ - "set policy variable inhibit-policy-mapping"}, \ - { "x509_strict", OPT_V_X509_STRICT, '-', \ - "disable certificate compatibility work-arounds"}, \ - { "extended_crl", OPT_V_EXTENDED_CRL, '-', \ - "enable extended CRL features"}, \ - { "use_deltas", OPT_V_USE_DELTAS, '-', \ - "use delta CRLs"}, \ - { "policy_print", OPT_V_POLICY_PRINT, '-', \ - "print policy processing diagnostics"}, \ - { "check_ss_sig", OPT_V_CHECK_SS_SIG, '-', \ - "check root CA self-signatures"}, \ - { "trusted_first", OPT_V_TRUSTED_FIRST, '-', \ - "search trust store first (default)" }, \ - { "suiteB_128_only", OPT_V_SUITEB_128_ONLY, '-', "Suite B 128-bit-only mode"}, \ - { "suiteB_128", OPT_V_SUITEB_128, '-', \ - "Suite B 128-bit mode allowing 192-bit algorithms"}, \ - { "suiteB_192", OPT_V_SUITEB_192, '-', "Suite B 192-bit-only mode" }, \ - { "partial_chain", OPT_V_PARTIAL_CHAIN, '-', \ - "accept chains anchored by intermediate trust-store CAs"}, \ - { "no_alt_chains", OPT_V_NO_ALT_CHAINS, '-', "(deprecated)" }, \ - { "no_check_time", OPT_V_NO_CHECK_TIME, '-', "ignore certificate validity time" }, \ - { "allow_proxy_certs", OPT_V_ALLOW_PROXY_CERTS, '-', "allow the use of proxy certificates" } - -# define OPT_V_CASES \ - OPT_V__FIRST: case OPT_V__LAST: break; \ - case OPT_V_POLICY: \ - case OPT_V_PURPOSE: \ - case OPT_V_VERIFY_NAME: \ - case OPT_V_VERIFY_DEPTH: \ - case OPT_V_VERIFY_AUTH_LEVEL: \ - case OPT_V_ATTIME: \ - case OPT_V_VERIFY_HOSTNAME: \ - case OPT_V_VERIFY_EMAIL: \ - case OPT_V_VERIFY_IP: \ - case OPT_V_IGNORE_CRITICAL: \ - case OPT_V_ISSUER_CHECKS: \ - case OPT_V_CRL_CHECK: \ - case OPT_V_CRL_CHECK_ALL: \ - case OPT_V_POLICY_CHECK: \ - case OPT_V_EXPLICIT_POLICY: \ - case OPT_V_INHIBIT_ANY: \ - case OPT_V_INHIBIT_MAP: \ - case OPT_V_X509_STRICT: \ - case OPT_V_EXTENDED_CRL: \ - case OPT_V_USE_DELTAS: \ - case OPT_V_POLICY_PRINT: \ - case OPT_V_CHECK_SS_SIG: \ - case OPT_V_TRUSTED_FIRST: \ - case OPT_V_SUITEB_128_ONLY: \ - case OPT_V_SUITEB_128: \ - case OPT_V_SUITEB_192: \ - case OPT_V_PARTIAL_CHAIN: \ - case OPT_V_NO_ALT_CHAINS: \ - case OPT_V_NO_CHECK_TIME: \ - case OPT_V_ALLOW_PROXY_CERTS - -/* - * Common "extended validation" options. - */ -# define OPT_X_ENUM \ - OPT_X__FIRST=1000, \ - OPT_X_KEY, OPT_X_CERT, OPT_X_CHAIN, OPT_X_CHAIN_BUILD, \ - OPT_X_CERTFORM, OPT_X_KEYFORM, \ - OPT_X__LAST - -# define OPT_X_OPTIONS \ - { "xkey", OPT_X_KEY, '<', "key for Extended certificates"}, \ - { "xcert", OPT_X_CERT, '<', "cert for Extended certificates"}, \ - { "xchain", OPT_X_CHAIN, '<', "chain for Extended certificates"}, \ - { "xchain_build", OPT_X_CHAIN_BUILD, '-', \ - "build certificate chain for the extended certificates"}, \ - { "xcertform", OPT_X_CERTFORM, 'F', \ - "format of Extended certificate (PEM or DER) PEM default " }, \ - { "xkeyform", OPT_X_KEYFORM, 'F', \ - "format of Extended certificate's key (PEM or DER) PEM default"} - -# define OPT_X_CASES \ - OPT_X__FIRST: case OPT_X__LAST: break; \ - case OPT_X_KEY: \ - case OPT_X_CERT: \ - case OPT_X_CHAIN: \ - case OPT_X_CHAIN_BUILD: \ - case OPT_X_CERTFORM: \ - case OPT_X_KEYFORM - -/* - * Common SSL options. - * Any changes here must be coordinated with ../ssl/ssl_conf.c - */ -# define OPT_S_ENUM \ - OPT_S__FIRST=3000, \ - OPT_S_NOSSL3, OPT_S_NOTLS1, OPT_S_NOTLS1_1, OPT_S_NOTLS1_2, \ - OPT_S_NOTLS1_3, OPT_S_BUGS, OPT_S_NO_COMP, OPT_S_NOTICKET, \ - OPT_S_SERVERPREF, OPT_S_LEGACYRENEG, OPT_S_LEGACYCONN, \ - OPT_S_ONRESUMP, OPT_S_NOLEGACYCONN, OPT_S_ALLOW_NO_DHE_KEX, \ - OPT_S_PRIORITIZE_CHACHA, \ - OPT_S_STRICT, OPT_S_SIGALGS, OPT_S_CLIENTSIGALGS, OPT_S_GROUPS, \ - OPT_S_CURVES, OPT_S_NAMEDCURVE, OPT_S_CIPHER, OPT_S_CIPHERSUITES, \ - OPT_S_RECORD_PADDING, OPT_S_DEBUGBROKE, OPT_S_COMP, \ - OPT_S_MINPROTO, OPT_S_MAXPROTO, \ - OPT_S_NO_RENEGOTIATION, OPT_S_NO_MIDDLEBOX, OPT_S__LAST - -# define OPT_S_OPTIONS \ - {"no_ssl3", OPT_S_NOSSL3, '-',"Just disable SSLv3" }, \ - {"no_tls1", OPT_S_NOTLS1, '-', "Just disable TLSv1"}, \ - {"no_tls1_1", OPT_S_NOTLS1_1, '-', "Just disable TLSv1.1" }, \ - {"no_tls1_2", OPT_S_NOTLS1_2, '-', "Just disable TLSv1.2"}, \ - {"no_tls1_3", OPT_S_NOTLS1_3, '-', "Just disable TLSv1.3"}, \ - {"bugs", OPT_S_BUGS, '-', "Turn on SSL bug compatibility"}, \ - {"no_comp", OPT_S_NO_COMP, '-', "Disable SSL/TLS compression (default)" }, \ - {"comp", OPT_S_COMP, '-', "Use SSL/TLS-level compression" }, \ - {"no_ticket", OPT_S_NOTICKET, '-', \ - "Disable use of TLS session tickets"}, \ - {"serverpref", OPT_S_SERVERPREF, '-', "Use server's cipher preferences"}, \ - {"legacy_renegotiation", OPT_S_LEGACYRENEG, '-', \ - "Enable use of legacy renegotiation (dangerous)"}, \ - {"no_renegotiation", OPT_S_NO_RENEGOTIATION, '-', \ - "Disable all renegotiation."}, \ - {"legacy_server_connect", OPT_S_LEGACYCONN, '-', \ - "Allow initial connection to servers that don't support RI"}, \ - {"no_resumption_on_reneg", OPT_S_ONRESUMP, '-', \ - "Disallow session resumption on renegotiation"}, \ - {"no_legacy_server_connect", OPT_S_NOLEGACYCONN, '-', \ - "Disallow initial connection to servers that don't support RI"}, \ - {"allow_no_dhe_kex", OPT_S_ALLOW_NO_DHE_KEX, '-', \ - "In TLSv1.3 allow non-(ec)dhe based key exchange on resumption"}, \ - {"prioritize_chacha", OPT_S_PRIORITIZE_CHACHA, '-', \ - "Prioritize ChaCha ciphers when preferred by clients"}, \ - {"strict", OPT_S_STRICT, '-', \ - "Enforce strict certificate checks as per TLS standard"}, \ - {"sigalgs", OPT_S_SIGALGS, 's', \ - "Signature algorithms to support (colon-separated list)" }, \ - {"client_sigalgs", OPT_S_CLIENTSIGALGS, 's', \ - "Signature algorithms to support for client certificate" \ - " authentication (colon-separated list)" }, \ - {"groups", OPT_S_GROUPS, 's', \ - "Groups to advertise (colon-separated list)" }, \ - {"curves", OPT_S_CURVES, 's', \ - "Groups to advertise (colon-separated list)" }, \ - {"named_curve", OPT_S_NAMEDCURVE, 's', \ - "Elliptic curve used for ECDHE (server-side only)" }, \ - {"cipher", OPT_S_CIPHER, 's', "Specify TLSv1.2 and below cipher list to be used"}, \ - {"ciphersuites", OPT_S_CIPHERSUITES, 's', "Specify TLSv1.3 ciphersuites to be used"}, \ - {"min_protocol", OPT_S_MINPROTO, 's', "Specify the minimum protocol version to be used"}, \ - {"max_protocol", OPT_S_MAXPROTO, 's', "Specify the maximum protocol version to be used"}, \ - {"record_padding", OPT_S_RECORD_PADDING, 's', \ - "Block size to pad TLS 1.3 records to."}, \ - {"debug_broken_protocol", OPT_S_DEBUGBROKE, '-', \ - "Perform all sorts of protocol violations for testing purposes"}, \ - {"no_middlebox", OPT_S_NO_MIDDLEBOX, '-', \ - "Disable TLSv1.3 middlebox compat mode" } - -# define OPT_S_CASES \ - OPT_S__FIRST: case OPT_S__LAST: break; \ - case OPT_S_NOSSL3: \ - case OPT_S_NOTLS1: \ - case OPT_S_NOTLS1_1: \ - case OPT_S_NOTLS1_2: \ - case OPT_S_NOTLS1_3: \ - case OPT_S_BUGS: \ - case OPT_S_NO_COMP: \ - case OPT_S_COMP: \ - case OPT_S_NOTICKET: \ - case OPT_S_SERVERPREF: \ - case OPT_S_LEGACYRENEG: \ - case OPT_S_LEGACYCONN: \ - case OPT_S_ONRESUMP: \ - case OPT_S_NOLEGACYCONN: \ - case OPT_S_ALLOW_NO_DHE_KEX: \ - case OPT_S_PRIORITIZE_CHACHA: \ - case OPT_S_STRICT: \ - case OPT_S_SIGALGS: \ - case OPT_S_CLIENTSIGALGS: \ - case OPT_S_GROUPS: \ - case OPT_S_CURVES: \ - case OPT_S_NAMEDCURVE: \ - case OPT_S_CIPHER: \ - case OPT_S_CIPHERSUITES: \ - case OPT_S_RECORD_PADDING: \ - case OPT_S_NO_RENEGOTIATION: \ - case OPT_S_MINPROTO: \ - case OPT_S_MAXPROTO: \ - case OPT_S_DEBUGBROKE: \ - case OPT_S_NO_MIDDLEBOX - -#define IS_NO_PROT_FLAG(o) \ - (o == OPT_S_NOSSL3 || o == OPT_S_NOTLS1 || o == OPT_S_NOTLS1_1 \ - || o == OPT_S_NOTLS1_2 || o == OPT_S_NOTLS1_3) - -/* - * Random state options. - */ -# define OPT_R_ENUM \ - OPT_R__FIRST=1500, OPT_R_RAND, OPT_R_WRITERAND, OPT_R__LAST - -# define OPT_R_OPTIONS \ - {"rand", OPT_R_RAND, 's', "Load the file(s) into the random number generator"}, \ - {"writerand", OPT_R_WRITERAND, '>', "Write random data to the specified file"} - -# define OPT_R_CASES \ - OPT_R__FIRST: case OPT_R__LAST: break; \ - case OPT_R_RAND: case OPT_R_WRITERAND - -/* - * Option parsing. - */ -extern const char OPT_HELP_STR[]; -extern const char OPT_MORE_STR[]; -typedef struct options_st { - const char *name; - int retval; - /* - * value type: - no value (also the value zero), n number, p positive - * number, u unsigned, l long, s string, < input file, > output file, - * f any format, F der/pem format, E der/pem/engine format identifier. - * l, n and u include zero; p does not. - */ - int valtype; - const char *helpstr; -} OPTIONS; - -/* - * A string/int pairing; widely use for option value lookup, hence the - * name OPT_PAIR. But that name is misleading in s_cb.c, so we also use - * the "generic" name STRINT_PAIR. - */ -typedef struct string_int_pair_st { - const char *name; - int retval; -} OPT_PAIR, STRINT_PAIR; - -/* Flags to pass into opt_format; see FORMAT_xxx, below. */ -# define OPT_FMT_PEMDER (1L << 1) -# define OPT_FMT_PKCS12 (1L << 2) -# define OPT_FMT_SMIME (1L << 3) -# define OPT_FMT_ENGINE (1L << 4) -# define OPT_FMT_MSBLOB (1L << 5) -/* (1L << 6) was OPT_FMT_NETSCAPE, but wasn't used */ -# define OPT_FMT_NSS (1L << 7) -# define OPT_FMT_TEXT (1L << 8) -# define OPT_FMT_HTTP (1L << 9) -# define OPT_FMT_PVK (1L << 10) -# define OPT_FMT_PDE (OPT_FMT_PEMDER | OPT_FMT_ENGINE) -# define OPT_FMT_PDS (OPT_FMT_PEMDER | OPT_FMT_SMIME) -# define OPT_FMT_ANY ( \ - OPT_FMT_PEMDER | OPT_FMT_PKCS12 | OPT_FMT_SMIME | \ - OPT_FMT_ENGINE | OPT_FMT_MSBLOB | OPT_FMT_NSS | \ - OPT_FMT_TEXT | OPT_FMT_HTTP | OPT_FMT_PVK) - -char *opt_progname(const char *argv0); -char *opt_getprog(void); -char *opt_init(int ac, char **av, const OPTIONS * o); -int opt_next(void); -int opt_format(const char *s, unsigned long flags, int *result); -int opt_int(const char *arg, int *result); -int opt_ulong(const char *arg, unsigned long *result); -int opt_long(const char *arg, long *result); -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \ - defined(INTMAX_MAX) && defined(UINTMAX_MAX) -int opt_imax(const char *arg, intmax_t *result); -int opt_umax(const char *arg, uintmax_t *result); -#else -# define opt_imax opt_long -# define opt_umax opt_ulong -# define intmax_t long -# define uintmax_t unsigned long -#endif -int opt_pair(const char *arg, const OPT_PAIR * pairs, int *result); -int opt_cipher(const char *name, const EVP_CIPHER **cipherp); -int opt_md(const char *name, const EVP_MD **mdp); -char *opt_arg(void); -char *opt_flag(void); -char *opt_unknown(void); -char **opt_rest(void); -int opt_num_rest(void); -int opt_verify(int i, X509_VERIFY_PARAM *vpm); -int opt_rand(int i); -void opt_help(const OPTIONS * list); -int opt_format_error(const char *s, unsigned long flags); - typedef struct args_st { int size; int argc; @@ -430,20 +109,8 @@ char **copy_argv(int *argc, char *argv[]); */ void win32_utf8argv(int *argc, char **argv[]); - -# define PW_MIN_LENGTH 4 -typedef struct pw_cb_data { - const void *password; - const char *prompt_info; -} PW_CB_DATA; - /* We need both wrap and the "real" function because libcrypto uses both. */ int wrap_password_callback(char *buf, int bufsiz, int verify, void *cb_data); -int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_data); - -int setup_ui_method(void); -void destroy_ui_method(void); -const UI_METHOD *get_ui_method(void); int chopup_args(ARGS *arg, char *buf); # ifdef HEADER_X509_H @@ -573,29 +240,6 @@ void print_cert_checks(BIO *bio, X509 *x, void store_setup_crl_download(X509_STORE *st); -/* See OPT_FMT_xxx, above. */ -/* On some platforms, it's important to distinguish between text and binary - * files. On some, there might even be specific file formats for different - * contents. The FORMAT_xxx macros are meant to express an intent with the - * file being read or created. - */ -# define B_FORMAT_TEXT 0x8000 -# define FORMAT_UNDEF 0 -# define FORMAT_TEXT (1 | B_FORMAT_TEXT) /* Generic text */ -# define FORMAT_BINARY 2 /* Generic binary */ -# define FORMAT_BASE64 (3 | B_FORMAT_TEXT) /* Base64 */ -# define FORMAT_ASN1 4 /* ASN.1/DER */ -# define FORMAT_PEM (5 | B_FORMAT_TEXT) -# define FORMAT_PKCS12 6 -# define FORMAT_SMIME (7 | B_FORMAT_TEXT) -# define FORMAT_ENGINE 8 /* Not really a file format */ -# define FORMAT_PEMRSA (9 | B_FORMAT_TEXT) /* PEM RSAPubicKey format */ -# define FORMAT_ASN1RSA 10 /* DER RSAPubicKey format */ -# define FORMAT_MSBLOB 11 /* MS Key blob format */ -# define FORMAT_PVK 12 /* MS PVK file format */ -# define FORMAT_HTTP 13 /* Download using HTTP */ -# define FORMAT_NSS 14 /* NSS keylog format */ - # define EXT_COPY_NONE 0 # define EXT_COPY_ADD 1 # define EXT_COPY_ALL 2 diff --git a/apps/apps_ui.c b/apps/apps_ui.c new file mode 100644 index 00000000..bcfe5554 --- /dev/null +++ b/apps/apps_ui.c @@ -0,0 +1,197 @@ +/* + * 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 + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include "apps_ui.h" + +static UI_METHOD *ui_method = NULL; +static const UI_METHOD *ui_fallback_method = NULL; + + +static int ui_open(UI *ui) +{ + int (*opener)(UI *ui) = UI_method_get_opener(ui_fallback_method); + + if (opener) + return opener(ui); + return 1; +} + +static int ui_read(UI *ui, UI_STRING *uis) +{ + int (*reader)(UI *ui, UI_STRING *uis) = NULL; + + if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD + && UI_get0_user_data(ui)) { + switch (UI_get_string_type(uis)) { + case UIT_PROMPT: + case UIT_VERIFY: + { + const char *password = + ((PW_CB_DATA *)UI_get0_user_data(ui))->password; + if (password && password[0] != '\0') { + UI_set_result(ui, uis, password); + return 1; + } + } + break; + case UIT_NONE: + case UIT_BOOLEAN: + case UIT_INFO: + case UIT_ERROR: + break; + } + } + + reader = UI_method_get_reader(ui_fallback_method); + if (reader) + return reader(ui, uis); + return 1; +} + +static int ui_write(UI *ui, UI_STRING *uis) +{ + int (*writer)(UI *ui, UI_STRING *uis) = NULL; + + if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD + && UI_get0_user_data(ui)) { + switch (UI_get_string_type(uis)) { + case UIT_PROMPT: + case UIT_VERIFY: + { + const char *password = + ((PW_CB_DATA *)UI_get0_user_data(ui))->password; + if (password && password[0] != '\0') + return 1; + } + break; + case UIT_NONE: + case UIT_BOOLEAN: + case UIT_INFO: + case UIT_ERROR: + break; + } + } + + writer = UI_method_get_writer(ui_fallback_method); + if (writer) + return writer(ui, uis); + return 1; +} + +static int ui_close(UI *ui) +{ + int (*closer)(UI *ui) = UI_method_get_closer(ui_fallback_method); + + if (closer) + return closer(ui); + return 1; +} + +int setup_ui_method(void) +{ + ui_fallback_method = UI_null(); +#ifndef OPENSSL_NO_UI_CONSOLE + ui_fallback_method = UI_OpenSSL(); +#endif + ui_method = UI_create_method("OpenSSL application user interface"); + UI_method_set_opener(ui_method, ui_open); + UI_method_set_reader(ui_method, ui_read); + UI_method_set_writer(ui_method, ui_write); + UI_method_set_closer(ui_method, ui_close); + return 0; +} + +void destroy_ui_method(void) +{ + if (ui_method) { + UI_destroy_method(ui_method); + ui_method = NULL; + } +} + +const UI_METHOD *get_ui_method(void) +{ + return ui_method; +} + +static void *ui_malloc(int sz, const char *what) +{ + void *vp = OPENSSL_malloc(sz); + + if (vp == NULL) { + BIO_printf(bio_err, "Could not allocate %d bytes for %s\n", sz, what); + ERR_print_errors(bio_err); + exit(1); + } + return vp; +} + +int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_data) +{ + int res = 0; + UI *ui; + int ok = 0; + char *buff = NULL; + int ui_flags = 0; + const char *prompt_info = NULL; + char *prompt; + + if ((ui = UI_new_method(ui_method)) == NULL) + return 0; + + if (cb_data != NULL && cb_data->prompt_info != NULL) + prompt_info = cb_data->prompt_info; + prompt = UI_construct_prompt(ui, "pass phrase", prompt_info); + if (prompt == NULL) { + BIO_printf(bio_err, "Out of memory\n"); + UI_free(ui); + return 0; + } + + ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD; + UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0); + + /* We know that there is no previous user data to return to us */ + (void)UI_add_user_data(ui, cb_data); + + ok = UI_add_input_string(ui, prompt, ui_flags, buf, + PW_MIN_LENGTH, bufsiz - 1); + + if (ok >= 0 && verify) { + buff = ui_malloc(bufsiz, "password buffer"); + ok = UI_add_verify_string(ui, prompt, ui_flags, buff, + PW_MIN_LENGTH, bufsiz - 1, buf); + } + if (ok >= 0) + do { + ok = UI_process(ui); + } while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0)); + + OPENSSL_clear_free(buff, (unsigned int)bufsiz); + + if (ok >= 0) + res = strlen(buf); + if (ok == -1) { + BIO_printf(bio_err, "User interface error\n"); + ERR_print_errors(bio_err); + OPENSSL_cleanse(buf, (unsigned int)bufsiz); + res = 0; + } + if (ok == -2) { + BIO_printf(bio_err, "aborted!\n"); + OPENSSL_cleanse(buf, (unsigned int)bufsiz); + res = 0; + } + UI_free(ui); + OPENSSL_free(prompt); + return res; +} diff --git a/apps/apps_ui.h b/apps/apps_ui.h new file mode 100644 index 00000000..36e0864a --- /dev/null +++ b/apps/apps_ui.h @@ -0,0 +1,28 @@ +/* + * Copyright 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 + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef HEADER_APPS_UI_H +# define HEADER_APPS_UI_H + + +# define PW_MIN_LENGTH 4 +typedef struct pw_cb_data { + const void *password; + const char *prompt_info; +} PW_CB_DATA; + +int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_data); + +int setup_ui_method(void); +void destroy_ui_method(void); +const UI_METHOD *get_ui_method(void); + +extern BIO *bio_err; + +#endif diff --git a/apps/build.info b/apps/build.info index 0577f76c..7a5e8762 100644 --- a/apps/build.info +++ b/apps/build.info @@ -7,7 +7,8 @@ s_client.c s_server.c s_time.c sess_id.c smime.c speed.c spkac.c srp.c ts.c verify.c version.c x509.c rehash.c storeutl.c); our @apps_lib_src = - ( qw(apps.c opt.c s_cb.c s_socket.c app_rand.c bf_prefix.c), + ( qw(apps.c apps_ui.c opt.c fmt.c s_cb.c s_socket.c app_rand.c + bf_prefix.c), split(/\s+/, $target{apps_aux_src}) ); our @apps_init_src = split(/\s+/, $target{apps_init_src}); "" -} diff --git a/apps/fmt.c b/apps/fmt.c new file mode 100644 index 00000000..5cb4c041 --- /dev/null +++ b/apps/fmt.c @@ -0,0 +1,15 @@ +/* + * Copyright 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 + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "fmt.h" + +int FMT_istext(int format) +{ + return (format & B_FORMAT_TEXT) == B_FORMAT_TEXT; +} diff --git a/apps/fmt.h b/apps/fmt.h new file mode 100644 index 00000000..538a20a5 --- /dev/null +++ b/apps/fmt.h @@ -0,0 +1,44 @@ +/* + * Copyright 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 + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Options are shared by apps (see apps.h) and the test system + * (see test/testutil.h'). + * In order to remove the dependency between apps and options, the following + * shared fields have been moved into this file. + */ + +#ifndef HEADER_FMT_H +#define HEADER_FMT_H + +/* On some platforms, it's important to distinguish between text and binary + * files. On some, there might even be specific file formats for different + * contents. The FORMAT_xxx macros are meant to express an intent with the + * file being read or created. + */ +# define B_FORMAT_TEXT 0x8000 +# define FORMAT_UNDEF 0 +# define FORMAT_TEXT (1 | B_FORMAT_TEXT) /* Generic text */ +# define FORMAT_BINARY 2 /* Generic binary */ +# define FORMAT_BASE64 (3 | B_FORMAT_TEXT) /* Base64 */ +# define FORMAT_ASN1 4 /* ASN.1/DER */ +# define FORMAT_PEM (5 | B_FORMAT_TEXT) +# define FORMAT_PKCS12 6 +# define FORMAT_SMIME (7 | B_FORMAT_TEXT) +# define FORMAT_ENGINE 8 /* Not really a file format */ +# define FORMAT_PEMRSA (9 | B_FORMAT_TEXT) /* PEM RSAPubicKey format */ +# define FORMAT_ASN1RSA 10 /* DER RSAPubicKey format */ +# define FORMAT_MSBLOB 11 /* MS Key blob format */ +# define FORMAT_PVK 12 /* MS PVK file format */ +# define FORMAT_HTTP 13 /* Download using HTTP */ +# define FORMAT_NSS 14 /* NSS keylog format */ + +int FMT_istext(int format); + +#endif /* HEADER_FMT_H_ */ diff --git a/apps/ocsp.c b/apps/ocsp.c index 7c2a9046..09eeb9cf 100644 --- a/apps/ocsp.c +++ b/apps/ocsp.c @@ -36,7 +36,21 @@ NON_EMPTY_TRANSLATION_UNIT # include # include -# if defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_NO_SOCK) \ +#ifndef HAVE_FORK +# if defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_WINDOWS) +# define HAVE_FORK 0 +# else +# define HAVE_FORK 1 +# endif +#endif + +#if HAVE_FORK +# undef NO_FORK +#else +# define NO_FORK +#endif + +# if !defined(NO_FORK) && !defined(OPENSSL_NO_SOCK) \ && !defined(OPENSSL_NO_POSIX_IO) # define OCSP_DAEMON # include diff --git a/apps/opt.c b/apps/opt.c index c6ccceeb..439f271f 100644 --- a/apps/opt.c +++ b/apps/opt.c @@ -6,7 +6,13 @@ * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html */ -#include "apps.h" + +/* + * This file is also used by the test suite. Do not #include "apps.h". + */ +#include "opt.h" +#include "fmt.h" +#include "internal/nelem.h" #include #if !defined(OPENSSL_SYS_MSDOS) # include OPENSSL_UNISTD @@ -116,7 +122,7 @@ char *opt_init(int ac, char **av, const OPTIONS *o) /* Store state. */ argc = ac; argv = av; - opt_index = 1; + opt_begin(); opts = o; opt_progname(av[0]); unknown = NULL; @@ -133,15 +139,15 @@ char *opt_init(int ac, char **av, const OPTIONS *o) i = o->valtype; /* Make sure options are legit. */ - assert(o->name[0] != '-'); - assert(o->retval > 0); + OPENSSL_assert(o->name[0] != '-'); + OPENSSL_assert(o->retval > 0); switch (i) { case 0: case '-': case '/': case '<': case '>': case 'E': case 'F': case 'M': case 'U': case 'f': case 'l': case 'n': case 'p': case 's': case 'u': case 'c': break; default: - assert(0); + OPENSSL_assert(0); } /* Make sure there are no duplicates. */ @@ -150,13 +156,13 @@ char *opt_init(int ac, char **av, const OPTIONS *o) * Some compilers inline strcmp and the assert string is too long. */ duplicated = strcmp(o->name, next->name) == 0; - assert(!duplicated); + OPENSSL_assert(!duplicated); } #endif if (o->name[0] == '\0') { - assert(unknown == NULL); + OPENSSL_assert(unknown == NULL); unknown = o; - assert(unknown->valtype == 0 || unknown->valtype == '-'); + OPENSSL_assert(unknown->valtype == 0 || unknown->valtype == '-'); } } return prog; @@ -181,14 +187,14 @@ int opt_format_error(const char *s, unsigned long flags) OPT_PAIR *ap; if (flags == OPT_FMT_PEMDER) { - BIO_printf(bio_err, "%s: Bad format \"%s\"; must be pem or der\n", - prog, s); + opt_printf_stderr("%s: Bad format \"%s\"; must be pem or der\n", + prog, s); } else { - BIO_printf(bio_err, "%s: Bad format \"%s\"; must be one of:\n", - prog, s); + opt_printf_stderr("%s: Bad format \"%s\"; must be one of:\n", + prog, s); for (ap = formats; ap->name; ap++) if (flags & ap->retval) - BIO_printf(bio_err, " %s\n", ap->name); + opt_printf_stderr(" %s\n", ap->name); } return 0; } @@ -277,7 +283,7 @@ int opt_cipher(const char *name, const EVP_CIPHER **cipherp) *cipherp = EVP_get_cipherbyname(name); if (*cipherp != NULL) return 1; - BIO_printf(bio_err, "%s: Unrecognized flag %s\n", prog, name); + opt_printf_stderr("%s: Unrecognized flag %s\n", prog, name); return 0; } @@ -289,7 +295,7 @@ int opt_md(const char *name, const EVP_MD **mdp) *mdp = EVP_get_digestbyname(name); if (*mdp != NULL) return 1; - BIO_printf(bio_err, "%s: Unrecognized flag %s\n", prog, name); + opt_printf_stderr("%s: Unrecognized flag %s\n", prog, name); return 0; } @@ -303,9 +309,9 @@ int opt_pair(const char *name, const OPT_PAIR* pairs, int *result) *result = pp->retval; return 1; } - BIO_printf(bio_err, "%s: Value must be one of:\n", prog); + opt_printf_stderr("%s: Value must be one of:\n", prog); for (pp = pairs; pp->name; pp++) - BIO_printf(bio_err, "\t%s\n", pp->name); + opt_printf_stderr("\t%s\n", pp->name); return 0; } @@ -318,8 +324,8 @@ int opt_int(const char *value, int *result) return 0; *result = (int)l; if (*result != l) { - BIO_printf(bio_err, "%s: Value \"%s\" outside integer range\n", - prog, value); + opt_printf_stderr("%s: Value \"%s\" outside integer range\n", + prog, value); return 0; } return 1; @@ -339,13 +345,12 @@ static void opt_number_error(const char *v) for (i = 0; i < OSSL_NELEM(b); i++) { if (strncmp(v, b[i].prefix, strlen(b[i].prefix)) == 0) { - BIO_printf(bio_err, - "%s: Can't parse \"%s\" as %s number\n", - prog, v, b[i].name); + opt_printf_stderr("%s: Can't parse \"%s\" as %s number\n", + prog, v, b[i].name); return; } } - BIO_printf(bio_err, "%s: Can't parse \"%s\" as a number\n", prog, v); + opt_printf_stderr("%s: Can't parse \"%s\" as a number\n", prog, v); return; } @@ -458,9 +463,9 @@ int opt_verify(int opt, X509_VERIFY_PARAM *vpm) X509_PURPOSE *xptmp; const X509_VERIFY_PARAM *vtmp; - assert(vpm != NULL); - assert(opt > OPT_V__FIRST); - assert(opt < OPT_V__LAST); + OPENSSL_assert(vpm != NULL); + OPENSSL_assert(opt > OPT_V__FIRST); + OPENSSL_assert(opt < OPT_V__LAST); switch ((enum range)opt) { case OPT_V__FIRST: @@ -469,7 +474,7 @@ int opt_verify(int opt, X509_VERIFY_PARAM *vpm) case OPT_V_POLICY: otmp = OBJ_txt2obj(opt_arg(), 0); if (otmp == NULL) { - BIO_printf(bio_err, "%s: Invalid Policy %s\n", prog, opt_arg()); + opt_printf_stderr("%s: Invalid Policy %s\n", prog, opt_arg()); return 0; } X509_VERIFY_PARAM_add0_policy(vpm, otmp); @@ -478,7 +483,7 @@ int opt_verify(int opt, X509_VERIFY_PARAM *vpm) /* purpose name -> purpose index */ i = X509_PURPOSE_get_by_sname(opt_arg()); if (i < 0) { - BIO_printf(bio_err, "%s: Invalid purpose %s\n", prog, opt_arg()); + opt_printf_stderr("%s: Invalid purpose %s\n", prog, opt_arg()); return 0; } @@ -489,17 +494,16 @@ int opt_verify(int opt, X509_VERIFY_PARAM *vpm) i = X509_PURPOSE_get_id(xptmp); if (!X509_VERIFY_PARAM_set_purpose(vpm, i)) { - BIO_printf(bio_err, - "%s: Internal error setting purpose %s\n", - prog, opt_arg()); + opt_printf_stderr("%s: Internal error setting purpose %s\n", + prog, opt_arg()); return 0; } break; case OPT_V_VERIFY_NAME: vtmp = X509_VERIFY_PARAM_lookup(opt_arg()); if (vtmp == NULL) { - BIO_printf(bio_err, "%s: Invalid verify name %s\n", - prog, opt_arg()); + opt_printf_stderr("%s: Invalid verify name %s\n", + prog, opt_arg()); return 0; } X509_VERIFY_PARAM_set1(vpm, vtmp); @@ -518,8 +522,8 @@ int opt_verify(int opt, X509_VERIFY_PARAM *vpm) if (!opt_imax(opt_arg(), &t)) return 0; if (t != (time_t)t) { - BIO_printf(bio_err, "%s: epoch time out of range %s\n", - prog, opt_arg()); + opt_printf_stderr("%s: epoch time out of range %s\n", + prog, opt_arg()); return 0; } X509_VERIFY_PARAM_set_time(vpm, (time_t)t); @@ -606,6 +610,13 @@ int opt_verify(int opt, X509_VERIFY_PARAM *vpm) } +void opt_begin(void) +{ + opt_index = 1; + arg = NULL; + flag = NULL; +} + /* * Parse the next flag (and value if specified), return 0 if done, -1 on * error, otherwise the flag's retval. @@ -651,8 +662,8 @@ int opt_next(void) /* If it doesn't take a value, make sure none was given. */ if (o->valtype == 0 || o->valtype == '-') { if (arg) { - BIO_printf(bio_err, - "%s: Option -%s does not take a value\n", prog, p); + opt_printf_stderr("%s: Option -%s does not take a value\n", + prog, p); return -1; } return o->retval; @@ -661,8 +672,8 @@ int opt_next(void) /* Want a value; get the next param if =foo not used. */ if (arg == NULL) { if (argv[opt_index] == NULL) { - BIO_printf(bio_err, - "%s: Option -%s needs a value\n", prog, o->name); + opt_printf_stderr("%s: Option -%s needs a value\n", + prog, o->name); return -1; } arg = argv[opt_index++]; @@ -675,9 +686,9 @@ int opt_next(void) /* Just a string. */ break; case '/': - if (app_isdir(arg) > 0) + if (opt_isdir(arg) > 0) break; - BIO_printf(bio_err, "%s: Not a directory: %s\n", prog, arg); + opt_printf_stderr("%s: Not a directory: %s\n", prog, arg); return -1; case '<': /* Input file. */ @@ -689,41 +700,36 @@ int opt_next(void) case 'n': if (!opt_int(arg, &ival) || (o->valtype == 'p' && ival <= 0)) { - BIO_printf(bio_err, - "%s: Non-positive number \"%s\" for -%s\n", - prog, arg, o->name); + opt_printf_stderr("%s: Non-positive number \"%s\" for -%s\n", + prog, arg, o->name); return -1; } break; case 'M': if (!opt_imax(arg, &imval)) { - BIO_printf(bio_err, - "%s: Invalid number \"%s\" for -%s\n", - prog, arg, o->name); + opt_printf_stderr("%s: Invalid number \"%s\" for -%s\n", + prog, arg, o->name); return -1; } break; case 'U': if (!opt_umax(arg, &umval)) { - BIO_printf(bio_err, - "%s: Invalid number \"%s\" for -%s\n", - prog, arg, o->name); + opt_printf_stderr("%s: Invalid number \"%s\" for -%s\n", + prog, arg, o->name); return -1; } break; case 'l': if (!opt_long(arg, &lval)) { - BIO_printf(bio_err, - "%s: Invalid number \"%s\" for -%s\n", - prog, arg, o->name); + opt_printf_stderr("%s: Invalid number \"%s\" for -%s\n", + prog, arg, o->name); return -1; } break; case 'u': if (!opt_ulong(arg, &ulval)) { - BIO_printf(bio_err, - "%s: Invalid number \"%s\" for -%s\n", - prog, arg, o->name); + opt_printf_stderr("%s: Invalid number \"%s\" for -%s\n", + prog, arg, o->name); return -1; } break; @@ -737,9 +743,8 @@ int opt_next(void) o->valtype == 'F' ? OPT_FMT_PEMDER : OPT_FMT_ANY, &ival)) break; - BIO_printf(bio_err, - "%s: Invalid format \"%s\" for -%s\n", - prog, arg, o->name); + opt_printf_stderr("%s: Invalid format \"%s\" for -%s\n", + prog, arg, o->name); return -1; } @@ -750,7 +755,7 @@ int opt_next(void) dunno = p; return unknown->retval; } - BIO_printf(bio_err, "%s: Option unknown option -%s\n", prog, p); + opt_printf_stderr("%s: Option unknown option -%s\n", prog, p); return -1; } @@ -848,18 +853,17 @@ void opt_help(const OPTIONS *list) i += 1 + strlen(valtype2param(o)); if (i < MAX_OPT_HELP_WIDTH && i > width) width = i; - assert(i < (int)sizeof(start)); + OPENSSL_assert(i < (int)sizeof(start)); } if (standard_prolog) - BIO_printf(bio_err, "Usage: %s [options]\nValid options are:\n", - prog); + opt_printf_stderr("Usage: %s [options]\nValid options are:\n", prog); /* Now let's print. */ for (o = list; o->name; o++) { help = o->helpstr ? o->helpstr : "(No additional info)"; if (o->name == OPT_HELP_STR) { - BIO_printf(bio_err, help, prog); + opt_printf_stderr(help, prog); continue; } @@ -870,7 +874,7 @@ void opt_help(const OPTIONS *list) if (o->name == OPT_MORE_STR) { /* Continuation of previous line; pad and print. */ start[width] = '\0'; - BIO_printf(bio_err, "%s %s\n", start, help); + opt_printf_stderr("%s %s\n", start, help); continue; } @@ -889,10 +893,62 @@ void opt_help(const OPTIONS *list) *p = ' '; if ((int)(p - start) >= MAX_OPT_HELP_WIDTH) { *p = '\0'; - BIO_printf(bio_err, "%s\n", start); + opt_printf_stderr("%s\n", start); memset(start, ' ', sizeof(start)); } start[width] = '\0'; - BIO_printf(bio_err, "%s %s\n", start, help); + opt_printf_stderr("%s %s\n", start, help); } } + +/* opt_isdir section */ +#ifdef _WIN32 +# include +int opt_isdir(const char *name) +{ + DWORD attr; +# if defined(UNICODE) || defined(_UNICODE) + size_t i, len_0 = strlen(name) + 1; + WCHAR tempname[MAX_PATH]; + + if (len_0 > MAX_PATH) + return -1; + +# if !defined(_WIN32_WCE) || _WIN32_WCE>=101 + if (!MultiByteToWideChar(CP_ACP, 0, name, len_0, tempname, MAX_PATH)) +# endif + for (i = 0; i < len_0; i++) + tempname[i] = (WCHAR)name[i]; + + attr = GetFileAttributes(tempname); +# else + attr = GetFileAttributes(name); +# endif + if (attr == INVALID_FILE_ATTRIBUTES) + return -1; + return ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0); +} +#else +# include +# ifndef S_ISDIR +# if defined(_S_IFMT) && defined(_S_IFDIR) +# define S_ISDIR(a) (((a) & _S_IFMT) == _S_IFDIR) +# else +# define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR) +# endif +# endif + +int opt_isdir(const char *name) +{ +# if defined(S_ISDIR) + struct stat st; + + if (stat(name, &st) == 0) + return S_ISDIR(st.st_mode); + else + return -1; +# else + return -1; +# endif +} +#endif diff --git a/apps/opt.h b/apps/opt.h new file mode 100644 index 00000000..ecfa06e0 --- /dev/null +++ b/apps/opt.h @@ -0,0 +1,344 @@ +/* + * Copyright 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 + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ +#ifndef HEADER_OPT_H +#define HEADER_OPT_H + +#include +#include +#include +#include + +/* + * Common verification options. + */ +# define OPT_V_ENUM \ + OPT_V__FIRST=2000, \ + OPT_V_POLICY, OPT_V_PURPOSE, OPT_V_VERIFY_NAME, OPT_V_VERIFY_DEPTH, \ + OPT_V_ATTIME, OPT_V_VERIFY_HOSTNAME, OPT_V_VERIFY_EMAIL, \ + OPT_V_VERIFY_IP, OPT_V_IGNORE_CRITICAL, OPT_V_ISSUER_CHECKS, \ + OPT_V_CRL_CHECK, OPT_V_CRL_CHECK_ALL, OPT_V_POLICY_CHECK, \ + OPT_V_EXPLICIT_POLICY, OPT_V_INHIBIT_ANY, OPT_V_INHIBIT_MAP, \ + OPT_V_X509_STRICT, OPT_V_EXTENDED_CRL, OPT_V_USE_DELTAS, \ + OPT_V_POLICY_PRINT, OPT_V_CHECK_SS_SIG, OPT_V_TRUSTED_FIRST, \ + OPT_V_SUITEB_128_ONLY, OPT_V_SUITEB_128, OPT_V_SUITEB_192, \ + OPT_V_PARTIAL_CHAIN, OPT_V_NO_ALT_CHAINS, OPT_V_NO_CHECK_TIME, \ + OPT_V_VERIFY_AUTH_LEVEL, OPT_V_ALLOW_PROXY_CERTS, \ + OPT_V__LAST + +# define OPT_V_OPTIONS \ + { "policy", OPT_V_POLICY, 's', "adds policy to the acceptable policy set"}, \ + { "purpose", OPT_V_PURPOSE, 's', \ + "certificate chain purpose"}, \ + { "verify_name", OPT_V_VERIFY_NAME, 's', "verification policy name"}, \ + { "verify_depth", OPT_V_VERIFY_DEPTH, 'n', \ + "chain depth limit" }, \ + { "auth_level", OPT_V_VERIFY_AUTH_LEVEL, 'n', \ + "chain authentication security level" }, \ + { "attime", OPT_V_ATTIME, 'M', "verification epoch time" }, \ + { "verify_hostname", OPT_V_VERIFY_HOSTNAME, 's', \ + "expected peer hostname" }, \ + { "verify_email", OPT_V_VERIFY_EMAIL, 's', \ + "expected peer email" }, \ + { "verify_ip", OPT_V_VERIFY_IP, 's', \ + "expected peer IP address" }, \ + { "ignore_critical", OPT_V_IGNORE_CRITICAL, '-', \ + "permit unhandled critical extensions"}, \ + { "issuer_checks", OPT_V_ISSUER_CHECKS, '-', "(deprecated)"}, \ + { "crl_check", OPT_V_CRL_CHECK, '-', "check leaf certificate revocation" }, \ + { "crl_check_all", OPT_V_CRL_CHECK_ALL, '-', "check full chain revocation" }, \ + { "policy_check", OPT_V_POLICY_CHECK, '-', "perform rfc5280 policy checks"}, \ + { "explicit_policy", OPT_V_EXPLICIT_POLICY, '-', \ + "set policy variable require-explicit-policy"}, \ + { "inhibit_any", OPT_V_INHIBIT_ANY, '-', \ + "set policy variable inhibit-any-policy"}, \ + { "inhibit_map", OPT_V_INHIBIT_MAP, '-', \ + "set policy variable inhibit-policy-mapping"}, \ + { "x509_strict", OPT_V_X509_STRICT, '-', \ + "disable certificate compatibility work-arounds"}, \ + { "extended_crl", OPT_V_EXTENDED_CRL, '-', \ + "enable extended CRL features"}, \ + { "use_deltas", OPT_V_USE_DELTAS, '-', \ + "use delta CRLs"}, \ + { "policy_print", OPT_V_POLICY_PRINT, '-', \ + "print policy processing diagnostics"}, \ + { "check_ss_sig", OPT_V_CHECK_SS_SIG, '-', \ + "check root CA self-signatures"}, \ + { "trusted_first", OPT_V_TRUSTED_FIRST, '-', \ + "search trust store first (default)" }, \ + { "suiteB_128_only", OPT_V_SUITEB_128_ONLY, '-', "Suite B 128-bit-only mode"}, \ + { "suiteB_128", OPT_V_SUITEB_128, '-', \ + "Suite B 128-bit mode allowing 192-bit algorithms"}, \ + { "suiteB_192", OPT_V_SUITEB_192, '-', "Suite B 192-bit-only mode" }, \ + { "partial_chain", OPT_V_PARTIAL_CHAIN, '-', \ + "accept chains anchored by intermediate trust-store CAs"}, \ + { "no_alt_chains", OPT_V_NO_ALT_CHAINS, '-', "(deprecated)" }, \ + { "no_check_time", OPT_V_NO_CHECK_TIME, '-', "ignore certificate validity time" }, \ + { "allow_proxy_certs", OPT_V_ALLOW_PROXY_CERTS, '-', "allow the use of proxy certificates" } + +# define OPT_V_CASES \ + OPT_V__FIRST: case OPT_V__LAST: break; \ + case OPT_V_POLICY: \ + case OPT_V_PURPOSE: \ + case OPT_V_VERIFY_NAME: \ + case OPT_V_VERIFY_DEPTH: \ + case OPT_V_VERIFY_AUTH_LEVEL: \ + case OPT_V_ATTIME: \ + case OPT_V_VERIFY_HOSTNAME: \ + case OPT_V_VERIFY_EMAIL: \ + case OPT_V_VERIFY_IP: \ + case OPT_V_IGNORE_CRITICAL: \ + case OPT_V_ISSUER_CHECKS: \ + case OPT_V_CRL_CHECK: \ + case OPT_V_CRL_CHECK_ALL: \ + case OPT_V_POLICY_CHECK: \ + case OPT_V_EXPLICIT_POLICY: \ + case OPT_V_INHIBIT_ANY: \ + case OPT_V_INHIBIT_MAP: \ + case OPT_V_X509_STRICT: \ + case OPT_V_EXTENDED_CRL: \ + case OPT_V_USE_DELTAS: \ + case OPT_V_POLICY_PRINT: \ + case OPT_V_CHECK_SS_SIG: \ + case OPT_V_TRUSTED_FIRST: \ + case OPT_V_SUITEB_128_ONLY: \ + case OPT_V_SUITEB_128: \ + case OPT_V_SUITEB_192: \ + case OPT_V_PARTIAL_CHAIN: \ + case OPT_V_NO_ALT_CHAINS: \ + case OPT_V_NO_CHECK_TIME: \ + case OPT_V_ALLOW_PROXY_CERTS + +/* + * Common "extended validation" options. + */ +# define OPT_X_ENUM \ + OPT_X__FIRST=1000, \ + OPT_X_KEY, OPT_X_CERT, OPT_X_CHAIN, OPT_X_CHAIN_BUILD, \ + OPT_X_CERTFORM, OPT_X_KEYFORM, \ + OPT_X__LAST + +# define OPT_X_OPTIONS \ + { "xkey", OPT_X_KEY, '<', "key for Extended certificates"}, \ + { "xcert", OPT_X_CERT, '<', "cert for Extended certificates"}, \ + { "xchain", OPT_X_CHAIN, '<', "chain for Extended certificates"}, \ + { "xchain_build", OPT_X_CHAIN_BUILD, '-', \ + "build certificate chain for the extended certificates"}, \ + { "xcertform", OPT_X_CERTFORM, 'F', \ + "format of Extended certificate (PEM or DER) PEM default " }, \ + { "xkeyform", OPT_X_KEYFORM, 'F', \ + "format of Extended certificate's key (PEM or DER) PEM default"} + +# define OPT_X_CASES \ + OPT_X__FIRST: case OPT_X__LAST: break; \ + case OPT_X_KEY: \ + case OPT_X_CERT: \ + case OPT_X_CHAIN: \ + case OPT_X_CHAIN_BUILD: \ + case OPT_X_CERTFORM: \ + case OPT_X_KEYFORM + +/* + * Common SSL options. + * Any changes here must be coordinated with ../ssl/ssl_conf.c + */ +# define OPT_S_ENUM \ + OPT_S__FIRST=3000, \ + OPT_S_NOSSL3, OPT_S_NOTLS1, OPT_S_NOTLS1_1, OPT_S_NOTLS1_2, \ + OPT_S_NOTLS1_3, OPT_S_BUGS, OPT_S_NO_COMP, OPT_S_NOTICKET, \ + OPT_S_SERVERPREF, OPT_S_LEGACYRENEG, OPT_S_LEGACYCONN, \ + OPT_S_ONRESUMP, OPT_S_NOLEGACYCONN, OPT_S_ALLOW_NO_DHE_KEX, \ + OPT_S_PRIORITIZE_CHACHA, \ + OPT_S_STRICT, OPT_S_SIGALGS, OPT_S_CLIENTSIGALGS, OPT_S_GROUPS, \ + OPT_S_CURVES, OPT_S_NAMEDCURVE, OPT_S_CIPHER, OPT_S_CIPHERSUITES, \ + OPT_S_RECORD_PADDING, OPT_S_DEBUGBROKE, OPT_S_COMP, \ + OPT_S_MINPROTO, OPT_S_MAXPROTO, \ + OPT_S_NO_RENEGOTIATION, OPT_S_NO_MIDDLEBOX, OPT_S__LAST + +# define OPT_S_OPTIONS \ + {"no_ssl3", OPT_S_NOSSL3, '-',"Just disable SSLv3" }, \ + {"no_tls1", OPT_S_NOTLS1, '-', "Just disable TLSv1"}, \ + {"no_tls1_1", OPT_S_NOTLS1_1, '-', "Just disable TLSv1.1" }, \ + {"no_tls1_2", OPT_S_NOTLS1_2, '-', "Just disable TLSv1.2"}, \ + {"no_tls1_3", OPT_S_NOTLS1_3, '-', "Just disable TLSv1.3"}, \ + {"bugs", OPT_S_BUGS, '-', "Turn on SSL bug compatibility"}, \ + {"no_comp", OPT_S_NO_COMP, '-', "Disable SSL/TLS compression (default)" }, \ + {"comp", OPT_S_COMP, '-', "Use SSL/TLS-level compression" }, \ + {"no_ticket", OPT_S_NOTICKET, '-', \ + "Disable use of TLS session tickets"}, \ + {"serverpref", OPT_S_SERVERPREF, '-', "Use server's cipher preferences"}, \ + {"legacy_renegotiation", OPT_S_LEGACYRENEG, '-', \ + "Enable use of legacy renegotiation (dangerous)"}, \ + {"no_renegotiation", OPT_S_NO_RENEGOTIATION, '-', \ + "Disable all renegotiation."}, \ + {"legacy_server_connect", OPT_S_LEGACYCONN, '-', \ + "Allow initial connection to servers that don't support RI"}, \ + {"no_resumption_on_reneg", OPT_S_ONRESUMP, '-', \ + "Disallow session resumption on renegotiation"}, \ + {"no_legacy_server_connect", OPT_S_NOLEGACYCONN, '-', \ + "Disallow initial connection to servers that don't support RI"}, \ + {"allow_no_dhe_kex", OPT_S_ALLOW_NO_DHE_KEX, '-', \ + "In TLSv1.3 allow non-(ec)dhe based key exchange on resumption"}, \ + {"prioritize_chacha", OPT_S_PRIORITIZE_CHACHA, '-', \ + "Prioritize ChaCha ciphers when preferred by clients"}, \ + {"strict", OPT_S_STRICT, '-', \ + "Enforce strict certificate checks as per TLS standard"}, \ + {"sigalgs", OPT_S_SIGALGS, 's', \ + "Signature algorithms to support (colon-separated list)" }, \ + {"client_sigalgs", OPT_S_CLIENTSIGALGS, 's', \ + "Signature algorithms to support for client certificate" \ + " authentication (colon-separated list)" }, \ + {"groups", OPT_S_GROUPS, 's', \ + "Groups to advertise (colon-separated list)" }, \ + {"curves", OPT_S_CURVES, 's', \ + "Groups to advertise (colon-separated list)" }, \ + {"named_curve", OPT_S_NAMEDCURVE, 's', \ + "Elliptic curve used for ECDHE (server-side only)" }, \ + {"cipher", OPT_S_CIPHER, 's', "Specify TLSv1.2 and below cipher list to be used"}, \ + {"ciphersuites", OPT_S_CIPHERSUITES, 's', "Specify TLSv1.3 ciphersuites to be used"}, \ + {"min_protocol", OPT_S_MINPROTO, 's', "Specify the minimum protocol version to be used"}, \ + {"max_protocol", OPT_S_MAXPROTO, 's', "Specify the maximum protocol version to be used"}, \ + {"record_padding", OPT_S_RECORD_PADDING, 's', \ + "Block size to pad TLS 1.3 records to."}, \ + {"debug_broken_protocol", OPT_S_DEBUGBROKE, '-', \ + "Perform all sorts of protocol violations for testing purposes"}, \ + {"no_middlebox", OPT_S_NO_MIDDLEBOX, '-', \ + "Disable TLSv1.3 middlebox compat mode" } + +# define OPT_S_CASES \ + OPT_S__FIRST: case OPT_S__LAST: break; \ + case OPT_S_NOSSL3: \ + case OPT_S_NOTLS1: \ + case OPT_S_NOTLS1_1: \ + case OPT_S_NOTLS1_2: \ + case OPT_S_NOTLS1_3: \ + case OPT_S_BUGS: \ + case OPT_S_NO_COMP: \ + case OPT_S_COMP: \ + case OPT_S_NOTICKET: \ + case OPT_S_SERVERPREF: \ + case OPT_S_LEGACYRENEG: \ + case OPT_S_LEGACYCONN: \ + case OPT_S_ONRESUMP: \ + case OPT_S_NOLEGACYCONN: \ + case OPT_S_ALLOW_NO_DHE_KEX: \ + case OPT_S_PRIORITIZE_CHACHA: \ + case OPT_S_STRICT: \ + case OPT_S_SIGALGS: \ + case OPT_S_CLIENTSIGALGS: \ + case OPT_S_GROUPS: \ + case OPT_S_CURVES: \ + case OPT_S_NAMEDCURVE: \ + case OPT_S_CIPHER: \ + case OPT_S_CIPHERSUITES: \ + case OPT_S_RECORD_PADDING: \ + case OPT_S_NO_RENEGOTIATION: \ + case OPT_S_MINPROTO: \ + case OPT_S_MAXPROTO: \ + case OPT_S_DEBUGBROKE: \ + case OPT_S_NO_MIDDLEBOX + +#define IS_NO_PROT_FLAG(o) \ + (o == OPT_S_NOSSL3 || o == OPT_S_NOTLS1 || o == OPT_S_NOTLS1_1 \ + || o == OPT_S_NOTLS1_2 || o == OPT_S_NOTLS1_3) + +/* + * Random state options. + */ +# define OPT_R_ENUM \ + OPT_R__FIRST=1500, OPT_R_RAND, OPT_R_WRITERAND, OPT_R__LAST + +# define OPT_R_OPTIONS \ + {"rand", OPT_R_RAND, 's', "Load the file(s) into the random number generator"}, \ + {"writerand", OPT_R_WRITERAND, '>', "Write random data to the specified file"} + +# define OPT_R_CASES \ + OPT_R__FIRST: case OPT_R__LAST: break; \ + case OPT_R_RAND: case OPT_R_WRITERAND + +/* + * Option parsing. + */ +extern const char OPT_HELP_STR[]; +extern const char OPT_MORE_STR[]; +typedef struct options_st { + const char *name; + int retval; + /* + * value type: - no value (also the value zero), n number, p positive + * number, u unsigned, l long, s string, < input file, > output file, + * f any format, F der/pem format, E der/pem/engine format identifier. + * l, n and u include zero; p does not. + */ + int valtype; + const char *helpstr; +} OPTIONS; + +/* + * A string/int pairing; widely use for option value lookup, hence the + * name OPT_PAIR. But that name is misleading in s_cb.c, so we also use + * the "generic" name STRINT_PAIR. + */ +typedef struct string_int_pair_st { + const char *name; + int retval; +} OPT_PAIR, STRINT_PAIR; + +/* Flags to pass into opt_format; see FORMAT_xxx, below. */ +# define OPT_FMT_PEMDER (1L << 1) +# define OPT_FMT_PKCS12 (1L << 2) +# define OPT_FMT_SMIME (1L << 3) +# define OPT_FMT_ENGINE (1L << 4) +# define OPT_FMT_MSBLOB (1L << 5) +/* (1L << 6) was OPT_FMT_NETSCAPE, but wasn't used */ +# define OPT_FMT_NSS (1L << 7) +# define OPT_FMT_TEXT (1L << 8) +# define OPT_FMT_HTTP (1L << 9) +# define OPT_FMT_PVK (1L << 10) +# define OPT_FMT_PDE (OPT_FMT_PEMDER | OPT_FMT_ENGINE) +# define OPT_FMT_PDS (OPT_FMT_PEMDER | OPT_FMT_SMIME) +# define OPT_FMT_ANY ( \ + OPT_FMT_PEMDER | OPT_FMT_PKCS12 | OPT_FMT_SMIME | \ + OPT_FMT_ENGINE | OPT_FMT_MSBLOB | OPT_FMT_NSS | \ + OPT_FMT_TEXT | OPT_FMT_HTTP | OPT_FMT_PVK) + +char *opt_progname(const char *argv0); +char *opt_getprog(void); +char *opt_init(int ac, char **av, const OPTIONS * o); +int opt_next(void); +void opt_begin(void); +int opt_format(const char *s, unsigned long flags, int *result); +int opt_int(const char *arg, int *result); +int opt_ulong(const char *arg, unsigned long *result); +int opt_long(const char *arg, long *result); +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \ + defined(INTMAX_MAX) && defined(UINTMAX_MAX) +int opt_imax(const char *arg, intmax_t *result); +int opt_umax(const char *arg, uintmax_t *result); +#else +# define opt_imax opt_long +# define opt_umax opt_ulong +# define intmax_t long +# define uintmax_t unsigned long +#endif +int opt_pair(const char *arg, const OPT_PAIR * pairs, int *result); +int opt_cipher(const char *name, const EVP_CIPHER **cipherp); +int opt_md(const char *name, const EVP_MD **mdp); +char *opt_arg(void); +char *opt_flag(void); +char *opt_unknown(void); +char **opt_rest(void); +int opt_num_rest(void); +int opt_verify(int i, X509_VERIFY_PARAM *vpm); +int opt_rand(int i); +void opt_help(const OPTIONS * list); +int opt_format_error(const char *s, unsigned long flags); +int opt_isdir(const char *name); +int opt_printf_stderr(const char *fmt, ...); + +#endif /* HEADER_OPT_H */ diff --git a/crypto/conf/conf_def.c b/crypto/conf/conf_def.c index 8a342187..594f7c5e 100644 --- a/crypto/conf/conf_def.c +++ b/crypto/conf/conf_def.c @@ -348,10 +348,15 @@ static int def_load_bio(CONF *conf, BIO *in, long *line) psection = section; } p = eat_ws(conf, end); - if (strncmp(pname, ".include", 8) == 0 && p != pname + 8) { + if (strncmp(pname, ".include", 8) == 0 + && (p != pname + 8 || *p == '=')) { char *include = NULL; BIO *next; + if (*p == '=') { + p++; + p = eat_ws(conf, p); + } trim_ws(conf, p); if (!str_copy(conf, psection, &include, p)) goto err; diff --git a/crypto/conf/conf_ssl.c b/crypto/conf/conf_ssl.c index a1b24b22..d703f736 100644 --- a/crypto/conf/conf_ssl.c +++ b/crypto/conf/conf_ssl.c @@ -78,6 +78,8 @@ static int ssl_module_init(CONF_IMODULE *md, const CONF *cnf) cnt = sk_CONF_VALUE_num(cmd_lists); ssl_module_free(md); ssl_names = OPENSSL_zalloc(sizeof(*ssl_names) * cnt); + if (ssl_names == NULL) + goto err; ssl_names_count = cnt; for (i = 0; i < ssl_names_count; i++) { struct ssl_conf_name_st *ssl_name = ssl_names + i; diff --git a/crypto/rsa/rsa_lib.c b/crypto/rsa/rsa_lib.c index 994978b1..0848936b 100644 --- a/crypto/rsa/rsa_lib.c +++ b/crypto/rsa/rsa_lib.c @@ -181,7 +181,7 @@ static const unsigned int c1_923 = 0x07b126; /* scale * 1.923 */ static const unsigned int c4_690 = 0x12c28f; /* scale * 4.690 */ /* - * Multiply two scale integers together and rescale the result. + * Multiply two scaled integers together and rescale the result. */ static ossl_inline uint64_t mul2(uint64_t a, uint64_t b) { diff --git a/doc/man1/ciphers.pod b/doc/man1/ciphers.pod index b5bca974..7d795c39 100644 --- a/doc/man1/ciphers.pod +++ b/doc/man1/ciphers.pod @@ -411,7 +411,7 @@ based on client preferences. An equal-preference is specified with square brackets, combining multiple selectors separated by |. For example: [ECDHE-ECDSA-CHACHA20-POLY1305|ECDHE-ECDSA-AES128-GCM-SHA256] - + Once an equal-preference group is used, future directives must be opcode-less. diff --git a/doc/man1/version.pod b/doc/man1/version.pod index 2d2e4aab..6d58f9de 100644 --- a/doc/man1/version.pod +++ b/doc/man1/version.pod @@ -60,7 +60,7 @@ OPENSSLDIR setting. =item B<-e> -ENGINESDIR setting. +ENGINESDIR settings. =back diff --git a/doc/man5/config.pod b/doc/man5/config.pod index 275d96c2..3d0842c4 100644 --- a/doc/man5/config.pod +++ b/doc/man5/config.pod @@ -42,6 +42,13 @@ working directory so unless the configuration file containing the B<.include> directive is application specific the inclusion will not work as expected. +There can be optional B<=> character and whitespace characters between +B<.include> directive and the path which can be useful in cases the +configuration file needs to be loaded by old OpenSSL versions which do +not support the B<.include> syntax. They would bail out with error +if the B<=> character is not present but with it they just ignore +the include. + Each section in a configuration file consists of a number of name and value pairs of the form B diff --git a/engines/build.info b/engines/build.info index a4a4d930..27f1cecf 100644 --- a/engines/build.info +++ b/engines/build.info @@ -11,7 +11,7 @@ IF[{- !$disabled{"engine"} -}] SOURCE[../libcrypto]=e_afalg.c ENDIF ELSE - ENGINES=padlock + MODULES{engine}=padlock SOURCE[padlock]=e_padlock.c {- $target{padlock_asm_src} -} DEPEND[padlock]=../libcrypto INCLUDE[padlock]=../include @@ -20,7 +20,7 @@ IF[{- !$disabled{"engine"} -}] GENERATE[padlock.ld]=../util/engines.num ENDIF IF[{- !$disabled{capieng} -}] - ENGINES=capi + MODULES{engine}=capi SOURCE[capi]=e_capi.c DEPEND[capi]=../libcrypto INCLUDE[capi]=../include @@ -30,7 +30,7 @@ IF[{- !$disabled{"engine"} -}] ENDIF ENDIF IF[{- !$disabled{afalgeng} -}] - ENGINES=afalg + MODULES{engine}=afalg SOURCE[afalg]=e_afalg.c DEPEND[afalg]=../libcrypto INCLUDE[afalg]= ../include @@ -40,7 +40,7 @@ IF[{- !$disabled{"engine"} -}] ENDIF ENDIF - ENGINES{noinst}=ossltest dasync + MODULES{noinst,engine}=ossltest dasync SOURCE[dasync]=e_dasync.c DEPEND[dasync]=../libcrypto INCLUDE[dasync]=../include diff --git a/test/asynciotest.c b/test/asynciotest.c index 1085b4af..3bba098a 100644 --- a/test/asynciotest.c +++ b/test/asynciotest.c @@ -393,6 +393,8 @@ static int test_asyncio(int test) return testresult; } +OPT_TEST_DECLARE_USAGE("certname privkey\n") + int setup_tests(void) { if (!TEST_ptr(cert = test_get_argument(0)) diff --git a/test/bftest.c b/test/bftest.c index 2f9b2938..5b489251 100644 --- a/test/bftest.c +++ b/test/bftest.c @@ -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 Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -434,28 +434,53 @@ static int test_bf_ofb64(void) } #endif +typedef enum OPTION_choice { + OPT_ERR = -1, + OPT_EOF = 0, + OPT_PRINT, + OPT_TEST_ENUM +} OPTION_CHOICE; + +const OPTIONS *test_get_options(void) +{ + static const OPTIONS test_options[] = { + OPT_TEST_OPTIONS_DEFAULT_USAGE, + { "print", OPT_PRINT, '-', "Output test tables instead of running tests"}, + { NULL } + }; + return test_options; +} + int setup_tests(void) { #ifndef OPENSSL_NO_BF + OPTION_CHOICE o; # ifdef CHARSET_EBCDIC int n; - ebcdic2ascii(cbc_data, cbc_data, strlen(cbc_data)); for (n = 0; n < 2; n++) { ebcdic2ascii(bf_key[n], bf_key[n], strlen(bf_key[n])); } # endif - if (test_get_argument(0) != NULL) { - print_test_data(); - } else { - ADD_ALL_TESTS(test_bf_ecb_raw, 2); - ADD_ALL_TESTS(test_bf_ecb, NUM_TESTS); - ADD_ALL_TESTS(test_bf_set_key, KEY_TEST_NUM-1); - ADD_TEST(test_bf_cbc); - ADD_TEST(test_bf_cfb64); - ADD_TEST(test_bf_ofb64); + while ((o = opt_next()) != OPT_EOF) { + switch(o) { + case OPT_PRINT: + print_test_data(); + return 1; + case OPT_TEST_CASES: + break; + default: + return 0; + } } + + ADD_ALL_TESTS(test_bf_ecb_raw, 2); + ADD_ALL_TESTS(test_bf_ecb, NUM_TESTS); + ADD_ALL_TESTS(test_bf_set_key, KEY_TEST_NUM-1); + ADD_TEST(test_bf_cbc); + ADD_TEST(test_bf_cfb64); + ADD_TEST(test_bf_ofb64); #endif return 1; } diff --git a/test/bioprinttest.c b/test/bioprinttest.c index aa06039e..97151cdf 100644 --- a/test/bioprinttest.c +++ b/test/bioprinttest.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -252,10 +252,38 @@ static int test_big(void) return 1; } +typedef enum OPTION_choice { + OPT_ERR = -1, + OPT_EOF = 0, + OPT_PRINT, + OPT_TEST_ENUM +} OPTION_CHOICE; + +const OPTIONS *test_get_options(void) +{ + static const OPTIONS options[] = { + OPT_TEST_OPTIONS_DEFAULT_USAGE, + { "expected", OPT_PRINT, '-', "Output values" }, + { NULL } + }; + return options; +} int setup_tests(void) { - justprint = test_has_option("-expected"); + OPTION_CHOICE o; + + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_PRINT: + justprint = 1; + break; + case OPT_TEST_CASES: + break; + default: + return 0; + } + } ADD_TEST(test_big); ADD_ALL_TESTS(test_fp, nelem(pw_params)); @@ -300,3 +328,4 @@ int test_flush_stderr(void) { return fflush(stderr); } + diff --git a/test/bntest.c b/test/bntest.c index d042a3e2..e4b71e26 100644 --- a/test/bntest.c +++ b/test/bntest.c @@ -2261,6 +2261,17 @@ static int run_file_tests(int i) return c == 0; } +const OPTIONS *test_get_options(void) +{ + enum { OPT_TEST_ENUM }; + static const OPTIONS test_options[] = { + OPT_TEST_OPTIONS_WITH_EXTRA_USAGE("[file...]\n"), + { OPT_HELP_STR, 1, '-', + "file\tFile to run tests on. Normal tests are not run\n" }, + { NULL } + }; + return test_options; +} int setup_tests(void) { diff --git a/test/build.info b/test/build.info index 0ac2fa76..4c29beb2 100644 --- a/test/build.info +++ b/test/build.info @@ -13,8 +13,9 @@ IF[{- !$disabled{tests} -}] SOURCE[libtestutil.a]=testutil/basic_output.c testutil/output_helpers.c \ testutil/driver.c testutil/tests.c testutil/cb.c testutil/stanza.c \ testutil/format_output.c testutil/tap_bio.c \ - testutil/test_cleanup.c testutil/main.c testutil/init.c - INCLUDE[libtestutil.a]=../include + testutil/test_cleanup.c testutil/main.c testutil/init.c \ + testutil/options.c testutil/test_options.c ../apps/opt.c + INCLUDE[libtestutil.a]=../include .. DEPEND[libtestutil.a]=../libcrypto PROGRAMS{noinst}=\ @@ -398,11 +399,9 @@ IF[{- !$disabled{tests} -}] DEPEND[cipher_overhead_test]=../libcrypto ../libssl libtestutil.a ENDIF - SOURCE[uitest]=uitest.c \ - {- rebase_files("../apps", - split(/\s+/, $target{apps_init_src})) -} + SOURCE[uitest]=uitest.c ../apps/apps_ui.c INCLUDE[uitest]=.. ../include ../apps - DEPEND[uitest]=../apps/libapps.a ../libcrypto ../libssl libtestutil.a + DEPEND[uitest]=../libcrypto ../libssl libtestutil.a SOURCE[cipherbytes_test]=cipherbytes_test.c INCLUDE[cipherbytes_test]=../include diff --git a/test/clienthellotest.c b/test/clienthellotest.c index 6c778315..2c1110b1 100644 --- a/test/clienthellotest.c +++ b/test/clienthellotest.c @@ -240,6 +240,8 @@ end: return testresult; } +OPT_TEST_DECLARE_USAGE("sessionfile\n") + int setup_tests(void) { if (!TEST_ptr(sessionfile = test_get_argument(0))) diff --git a/test/cmsapitest.c b/test/cmsapitest.c index a79ae8c0..2ea8af58 100644 --- a/test/cmsapitest.c +++ b/test/cmsapitest.c @@ -1,3 +1,12 @@ +/* + * Copyright 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 + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + #include #include @@ -49,6 +58,8 @@ static int test_encrypt_decrypt(void) return testresult; } +OPT_TEST_DECLARE_USAGE("certfile privkeyfile\n") + int setup_tests(void) { char *certin = NULL, *privkeyin = NULL; diff --git a/test/conf_include_test.c b/test/conf_include_test.c index 16939ed4..ba40aa1b 100644 --- a/test/conf_include_test.c +++ b/test/conf_include_test.c @@ -178,26 +178,50 @@ static int test_check_overflow(void) return 1; } +typedef enum OPTION_choice { + OPT_ERR = -1, + OPT_EOF = 0, + OPT_FAIL, + OPT_TEST_ENUM +} OPTION_CHOICE; + +const OPTIONS *test_get_options(void) +{ + static const OPTIONS test_options[] = { + OPT_TEST_OPTIONS_WITH_EXTRA_USAGE("conf_file\n"), + { "f", OPT_FAIL, '-', "A failure is expected" }, + { NULL } + }; + return test_options; +} + int setup_tests(void) { const char *conf_file; - const char *arg2; + OPTION_CHOICE o; if (!TEST_ptr(conf = NCONF_new(NULL))) return 0; - conf_file = test_get_argument(0); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_FAIL: + expect_failure = 1; + break; + case OPT_TEST_CASES: + break; + default: + return 0; + } + } + conf_file = test_get_argument(0); if (!TEST_ptr(conf_file) || !TEST_ptr(in = BIO_new_file(conf_file, "r"))) { TEST_note("Unable to open the file argument"); return 0; } - if ((arg2 = test_get_argument(1)) != NULL && *arg2 == 'f') { - expect_failure = 1; - } - /* * For this test we need to chdir as we use relative * path names in the config files. diff --git a/test/curve448_internal_test.c b/test/curve448_internal_test.c index 92332b3b..85c0b0e8 100644 --- a/test/curve448_internal_test.c +++ b/test/curve448_internal_test.c @@ -682,19 +682,49 @@ static int test_x448(void) return 1; } +typedef enum OPTION_choice { + OPT_ERR = -1, + OPT_EOF = 0, + OPT_PROGRESS, + OPT_SLOW, + OPT_TEST_ENUM +} OPTION_CHOICE; + +const OPTIONS *test_get_options(void) +{ + static const OPTIONS test_options[] = { + OPT_TEST_OPTIONS_WITH_EXTRA_USAGE("conf_file\n"), + { "f", OPT_SLOW, '-', "Enables a slow test" }, + { "v", OPT_PROGRESS, '-', + "Enables verbose mode (prints progress dots)" }, + { NULL } + }; + return test_options; +} + int setup_tests(void) { - /* - * The test vectors contain one test which takes a very long time to run, - * so we don't do that be default. Using the -f option will cause it to be - * run. - */ - if (test_has_option("-f")) - max = 1000000; + OPTION_CHOICE o; - /* Print progress dots */ - if (test_has_option("-v")) - verbose = 1; + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_TEST_CASES: + break; + default: + return 0; + /* + * The test vectors contain one test which takes a very long time to run + * so we don't do that be default. Using the -f option will cause it to + * be run. + */ + case OPT_SLOW: + max = 1000000; + break; + case OPT_PROGRESS: + verbose = 1; /* Print progress dots */ + break; + } + } ADD_TEST(test_x448); ADD_TEST(test_ed448); diff --git a/test/d2i_test.c b/test/d2i_test.c index 13f6c0ca..3ce38485 100644 --- a/test/d2i_test.c +++ b/test/d2i_test.c @@ -106,6 +106,8 @@ static int test_bad_asn1(void) return ret; } +OPT_TEST_DECLARE_USAGE("item_name expected_error test_file.der\n") + /* * Usage: d2i_test , e.g. * d2i_test generalname bad_generalname.der @@ -127,10 +129,8 @@ int setup_tests(void) if (!TEST_ptr(test_type_name = test_get_argument(0)) || !TEST_ptr(expected_error_string = test_get_argument(1)) - || !TEST_ptr(test_file = test_get_argument(2))) { - TEST_note("Usage: d2i_test item_name expected_error file.der"); + || !TEST_ptr(test_file = test_get_argument(2))) return 0; - } item_type = ASN1_ITEM_lookup(test_type_name); diff --git a/test/danetest.c b/test/danetest.c index 04966185..26745f90 100644 --- a/test/danetest.c +++ b/test/danetest.c @@ -409,14 +409,14 @@ end: return ret; } +OPT_TEST_DECLARE_USAGE("basedomain CAfile tlsafile\n") + int setup_tests(void) { if (!TEST_ptr(basedomain = test_get_argument(0)) || !TEST_ptr(CAfile = test_get_argument(1)) - || !TEST_ptr(tlsafile = test_get_argument(2))) { - TEST_error("Usage error: danetest basedomain CAfile tlsafile"); + || !TEST_ptr(tlsafile = test_get_argument(2))) return 0; - } ADD_TEST(run_tlsatest); return 1; diff --git a/test/dtlstest.c b/test/dtlstest.c index d196fb55..98a23f85 100644 --- a/test/dtlstest.c +++ b/test/dtlstest.c @@ -328,6 +328,8 @@ static int test_dtls_duplicate_records(void) return testresult; } +OPT_TEST_DECLARE_USAGE("certfile privkeyfile\n") + int setup_tests(void) { if (!TEST_ptr(cert = test_get_argument(0)) diff --git a/test/ecstresstest.c b/test/ecstresstest.c index 8cb43e6a..a589103f 100644 --- a/test/ecstresstest.c +++ b/test/ecstresstest.c @@ -18,7 +18,7 @@ #define NUM_REPEATS "1000000" -static int64_t num_repeats; +static intmax_t num_repeats; static int print_mode = 0; #ifndef OPENSSL_NO_EC @@ -39,10 +39,10 @@ static const char *kP256DefaultResult = * point multiplication. * Returns the X-coordinate of the end result or NULL on error. */ -static BIGNUM *walk_curve(const EC_GROUP *group, EC_POINT *point, int64_t num) +static BIGNUM *walk_curve(const EC_GROUP *group, EC_POINT *point, intmax_t num) { BIGNUM *scalar = NULL; - int64_t i; + intmax_t i; if (!TEST_ptr(scalar = BN_new()) || !TEST_true(EC_POINT_get_affine_coordinates(group, point, scalar, @@ -101,20 +101,21 @@ err: } #endif -static int atoi64(const char *in, int64_t *result) +typedef enum OPTION_choice { + OPT_ERR = -1, + OPT_EOF = 0, + OPT_NUM_REPEATS, + OPT_TEST_ENUM +} OPTION_CHOICE; + +const OPTIONS *test_get_options(void) { - int64_t ret = 0; - - for ( ; *in != '\0'; in++) { - char c = *in; - - if (!isdigit((unsigned char)c)) - return 0; - ret *= 10; - ret += (c - '0'); - } - *result = ret; - return 1; + static const OPTIONS test_options[] = { + OPT_TEST_OPTIONS_DEFAULT_USAGE, + { "num", OPT_NUM_REPEATS, 'M', "Number of repeats" }, + { NULL } + }; + return test_options; } /* @@ -124,22 +125,27 @@ static int atoi64(const char *in, int64_t *result) */ int setup_tests(void) { - const char *p; + OPTION_CHOICE o; - if (!atoi64(NUM_REPEATS, &num_repeats)) { + if (!opt_imax(NUM_REPEATS, &num_repeats)) { TEST_error("Cannot parse " NUM_REPEATS); return 0; } - /* - * TODO(openssl-team): code under test/ should be able to reuse the option - * parsing framework currently in apps/. - */ - p = test_get_option_argument("-num"); - if (p != NULL) { - if (!atoi64(p, &num_repeats) - || num_repeats < 0) - return 0; - print_mode = 1; + + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_NUM_REPEATS: + if (!opt_imax(opt_arg(), &num_repeats) + || num_repeats < 0) + return 0; + print_mode = 1; + break; + case OPT_TEST_CASES: + break; + default: + case OPT_ERR: + return 0; + } } #ifndef OPENSSL_NO_EC diff --git a/test/evp_test.c b/test/evp_test.c index 932b03c6..49d254dc 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -2901,14 +2901,14 @@ static int run_file_tests(int i) return c == 0; } +OPT_TEST_DECLARE_USAGE("file...\n") + int setup_tests(void) { size_t n = test_get_argument_count(); - if (n == 0) { - TEST_error("Usage: %s file...", test_get_program_name()); + if (n == 0) return 0; - } ADD_ALL_TESTS(run_file_tests, n); return 1; diff --git a/test/fatalerrtest.c b/test/fatalerrtest.c index 32919144..0f18c1b6 100644 --- a/test/fatalerrtest.c +++ b/test/fatalerrtest.c @@ -82,6 +82,8 @@ static int test_fatalerr(void) return ret; } +OPT_TEST_DECLARE_USAGE("certfile privkeyfile\n") + int setup_tests(void) { if (!TEST_ptr(cert = test_get_argument(0)) diff --git a/test/gosttest.c b/test/gosttest.c index 398effa0..a03521d8 100644 --- a/test/gosttest.c +++ b/test/gosttest.c @@ -78,6 +78,8 @@ static int test_tls13(int idx) return testresult; } +OPT_TEST_DECLARE_USAGE("certfile1 privkeyfile1 certfile2 privkeyfile2\n") + int setup_tests(void) { if (!TEST_ptr(cert1 = test_get_argument(0)) diff --git a/test/ocspapitest.c b/test/ocspapitest.c index 5525f925..03b88e06 100644 --- a/test/ocspapitest.c +++ b/test/ocspapitest.c @@ -1,5 +1,5 @@ /* - * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -133,6 +133,8 @@ static int test_resp_signer(void) } #endif +OPT_TEST_DECLARE_USAGE("certfile privkeyfile\n") + int setup_tests(void) { if (!TEST_ptr(certstr = test_get_argument(0)) diff --git a/test/recipes/02-test_errstr.t b/test/recipes/02-test_errstr.t index ce2792b4..a9e8ed46 100644 --- a/test/recipes/02-test_errstr.t +++ b/test/recipes/02-test_errstr.t @@ -38,6 +38,43 @@ plan skip_all => 'OpenSSL is configured "no-autoerrinit" or "no-err"' # (this is documented) my @posix_errors = @{$Errno::EXPORT_TAGS{POSIX}}; +if ($^O eq 'MSWin32') { + # On Windows, these errors have been observed to not always be loaded by + # apps/openssl, while they are in perl, which causes a difference that we + # consider a false alarm. So we skip checking these errors. + # Because we can't know exactly what symbols exist in a perticular perl + # version, we resort to discovering them directly in the Errno package + # symbol table. + my @error_skiplist = qw( + ENETDOWN + ENETUNREACH + ENETRESET + ECONNABORTED + EISCONN + ENOTCONN + ESHUTDOWN + ETOOMANYREFS + ETIMEDOUT + EHOSTDOWN + EHOSTUNREACH + EALREADY + EINPROGRESS + ESTALE + EUCLEAN + ENOTNAM + ENAVAIL + ENOMEDIUM + ENOKEY + ); + @posix_errors = + grep { + my $x = $_; + ! grep { + exists $Errno::{$_} && $x == $Errno::{$_} + } @error_skiplist + } @posix_errors; +} + plan tests => scalar @posix_errors +1 # Checking that error 128 gives 'reason(128)' +1 # Checking that error 0 gives the library name diff --git a/test/recipes/90-test_includes.t b/test/recipes/90-test_includes.t index 5169700c..301f6c15 100644 --- a/test/recipes/90-test_includes.t +++ b/test/recipes/90-test_includes.t @@ -11,15 +11,17 @@ plan skip_all => "test_includes doesn't work without posix-io" if disabled("posix-io"); plan tests => # The number of tests being performed - 3 + 5 + ($^O eq "VMS" ? 2 : 0); ok(run(test(["conf_include_test", data_file("includes.cnf")])), "test directory includes"); ok(run(test(["conf_include_test", data_file("includes-file.cnf")])), "test file includes"); +ok(run(test(["conf_include_test", data_file("includes-eq.cnf")])), "test includes with equal character"); +ok(run(test(["conf_include_test", data_file("includes-eq-ws.cnf")])), "test includes with equal and whitespaces"); if ($^O eq "VMS") { ok(run(test(["conf_include_test", data_file("vms-includes.cnf")])), "test directory includes, VMS syntax"); ok(run(test(["conf_include_test", data_file("vms-includes-file.cnf")])), "test file includes, VMS syntax"); } -ok(run(test(["conf_include_test", data_file("includes-broken.cnf"), "f"])), "test broken includes"); +ok(run(test(["conf_include_test", "-f", data_file("includes-broken.cnf")])), "test broken includes"); diff --git a/test/recipes/90-test_includes_data/includes-eq-ws.cnf b/test/recipes/90-test_includes_data/includes-eq-ws.cnf new file mode 100644 index 00000000..38109a7a --- /dev/null +++ b/test/recipes/90-test_includes_data/includes-eq-ws.cnf @@ -0,0 +1,5 @@ +# +# Example configuration file using includes. +# + +.include = conf-includes diff --git a/test/recipes/90-test_includes_data/includes-eq.cnf b/test/recipes/90-test_includes_data/includes-eq.cnf new file mode 100644 index 00000000..9d371585 --- /dev/null +++ b/test/recipes/90-test_includes_data/includes-eq.cnf @@ -0,0 +1,5 @@ +# +# Example configuration file using includes. +# + +.include=conf-includes diff --git a/test/recordlentest.c b/test/recordlentest.c index a73e4436..9be354be 100644 --- a/test/recordlentest.c +++ b/test/recordlentest.c @@ -181,6 +181,8 @@ static int test_record_overflow(int idx) return testresult; } +OPT_TEST_DECLARE_USAGE("certfile privkeyfile\n") + int setup_tests(void) { if (!TEST_ptr(cert = test_get_argument(0)) diff --git a/test/ssl_test.c b/test/ssl_test.c index 4f82bf72..e54e8418 100644 --- a/test/ssl_test.c +++ b/test/ssl_test.c @@ -500,6 +500,8 @@ err: return ret; } +OPT_TEST_DECLARE_USAGE("conf_file\n") + int setup_tests(void) { long num_tests; diff --git a/test/ssl_test_ctx_test.c b/test/ssl_test_ctx_test.c index fef6166f..5f54d1ef 100644 --- a/test/ssl_test_ctx_test.c +++ b/test/ssl_test_ctx_test.c @@ -240,15 +240,15 @@ static int test_bad_configuration(int idx) return 1; } +OPT_TEST_DECLARE_USAGE("conf_file\n") + int setup_tests(void) { if (!TEST_ptr(conf = NCONF_new(NULL))) return 0; /* argument should point to test/ssl_test_ctx_test.conf */ - if (!TEST_int_gt(NCONF_load(conf, test_get_argument(0), NULL), 0)) { - TEST_note("Missing file argument"); + if (!TEST_int_gt(NCONF_load(conf, test_get_argument(0), NULL), 0)) return 0; - } ADD_TEST(test_empty_configuration); ADD_TEST(test_good_configuration); diff --git a/test/sslapitest.c b/test/sslapitest.c index 69520d74..6b44c160 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -6030,6 +6030,9 @@ static int test_ca_names(int tst) return testresult; } + +OPT_TEST_DECLARE_USAGE("certfile privkeyfile srpvfile tmpfile\n") + int setup_tests(void) { if (!TEST_ptr(cert = test_get_argument(0)) diff --git a/test/sslbuffertest.c b/test/sslbuffertest.c index 0ee7bdba..9a5ec2b9 100644 --- a/test/sslbuffertest.c +++ b/test/sslbuffertest.c @@ -157,6 +157,8 @@ int global_init(void) return 1; } +OPT_TEST_DECLARE_USAGE("certfile privkeyfile\n") + int setup_tests(void) { char *cert, *pkey; diff --git a/test/sslcorrupttest.c b/test/sslcorrupttest.c index 1ca899db..bffccc86 100644 --- a/test/sslcorrupttest.c +++ b/test/sslcorrupttest.c @@ -244,15 +244,15 @@ static int test_ssl_corrupt(int testidx) return testresult; } +OPT_TEST_DECLARE_USAGE("certfile privkeyfile\n") + int setup_tests(void) { int n; if (!TEST_ptr(cert = test_get_argument(0)) - || !TEST_ptr(privkey = test_get_argument(1))) { - TEST_note("Usage error: require cert and private key files"); + || !TEST_ptr(privkey = test_get_argument(1))) return 0; - } n = setup_cipher_list(); if (n > 0) diff --git a/test/testutil.h b/test/testutil.h index 10a4b6a7..9e08a42e 100644 --- a/test/testutil.h +++ b/test/testutil.h @@ -1,5 +1,5 @@ /* - * Copyright 2014-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -15,6 +15,7 @@ #include #include #include +#include "../apps/opt.h" /*- * Simple unit tests should implement setup_tests(). @@ -117,22 +118,80 @@ # define TEST_CASE_NAME __func__ # endif /* __STDC_VERSION__ */ + +/* The default test enum which should be common to all tests */ +#define OPT_TEST_ENUM \ + OPT_TEST_HELP = 500, \ + OPT_TEST_LIST, \ + OPT_TEST_SINGLE, \ + OPT_TEST_ITERATION, \ + OPT_TEST_INDENT, \ + OPT_TEST_SEED + +/* The Default test OPTIONS common to all tests (without a usage string) */ +#define OPT_TEST_OPTIONS \ + { OPT_HELP_STR, 1, '-', "Valid options are:\n" }, \ + { "help", OPT_TEST_HELP, '-', "Display this summary" }, \ + { "list", OPT_TEST_LIST, '-', "Display the list of tests available" }, \ + { "test", OPT_TEST_SINGLE, 's', "Run a single test by id or name" }, \ + { "iter", OPT_TEST_ITERATION, 'n', "Run a single iteration of a test" }, \ + { "indent", OPT_TEST_INDENT,'p', "Number of tabs added to output" }, \ + { "seed", OPT_TEST_SEED, 'n', "Seed value to randomize tests with" } + +/* The Default test OPTIONS common to all tests starting with an additional usage string */ +#define OPT_TEST_OPTIONS_WITH_EXTRA_USAGE(usage) \ + { OPT_HELP_STR, 1, '-', "Usage: %s [options] " usage }, \ + OPT_TEST_OPTIONS + +/* The Default test OPTIONS common to all tests with an default usage string */ +#define OPT_TEST_OPTIONS_DEFAULT_USAGE \ + { OPT_HELP_STR, 1, '-', "Usage: %s [options]\n" }, \ + OPT_TEST_OPTIONS + /* - * Tests that need access to command line arguments should use the functions: - * test_get_argument(int n) to get the nth argument, the first argument is - * argument 0. This function returns NULL on error. - * test_get_argument_count() to get the count of the arguments. - * test_has_option(const char *) to check if the specified option was passed. - * test_get_option_argument(const char *) to get an option which includes an - * argument. NULL is returns if the option is not found. - * const char *test_get_program_name(void) returns the name of the test program - * being executed. + * Optional Cases that need to be ignored by the test app when using opt_next(), + * (that are handled internally). + */ +#define OPT_TEST_CASES \ + OPT_TEST_HELP: \ + case OPT_TEST_LIST: \ + case OPT_TEST_SINGLE: \ + case OPT_TEST_ITERATION: \ + case OPT_TEST_INDENT: \ + case OPT_TEST_SEED + +/* + * Tests that use test_get_argument() that dont have any additional options + * (i.e- dont use opt_next()) can use this to set the usage string. + * It embeds test_get_options() which gives default command line options for + * the test system. + * + * Tests that need to use opt_next() need to specify + * (1) test_get_options() containing an options[] (Which should include either + * OPT_TEST_OPTIONS_DEFAULT_USAGE OR + * OPT_TEST_OPTIONS_WITH_EXTRA_USAGE). + * (2) An enum outside the test_get_options() which contains OPT_TEST_ENUM, as + * well as the additional options that need to be handled. + * (3) case OPT_TEST_CASES: break; inside the opt_next() handling code. + */ +#define OPT_TEST_DECLARE_USAGE(usage_str) \ +const OPTIONS *test_get_options(void) \ +{ \ + enum { OPT_TEST_ENUM }; \ + static const OPTIONS options[] = { \ + OPT_TEST_OPTIONS_WITH_EXTRA_USAGE(usage_str), \ + { NULL } \ + }; \ + return options; \ +} + +/* + * Used to read non optional command line values that follow after the options. + * Returns NULL if there is no argument. */ -const char *test_get_program_name(void); char *test_get_argument(size_t n); +/* Return the number of additional non optional command line arguments */ size_t test_get_argument_count(void); -int test_has_option(const char *option); -const char *test_get_option_argument(const char *option); /* * Internal helpers. Test programs shouldn't use these directly, but should @@ -150,6 +209,16 @@ void add_all_tests(const char *test_case_name, int (*test_fn)(int idx), int num, int global_init(void); int setup_tests(void); void cleanup_tests(void); +/* + * Used to supply test specific command line options, + * If non optional parameters are used, then the first entry in the OPTIONS[] + * should contain: + * { OPT_HELP_STR, 1, '-', "list of non optional commandline params\n"}, + * The last entry should always be { NULL }. + * + * Run the test locally using './test/test_name -help' to check the usage. + */ +const OPTIONS *test_get_options(void); /* * Test assumption verification helpers. diff --git a/test/testutil/driver.c b/test/testutil/driver.c index 3e80a7cb..df62625f 100644 --- a/test/testutil/driver.c +++ b/test/testutil/driver.c @@ -21,6 +21,7 @@ # define strdup _strdup #endif + /* * Declares the structures needed to register each test case function. */ @@ -36,14 +37,21 @@ typedef struct test_info { static TEST_INFO all_tests[1024]; static int num_tests = 0; +static int show_list = 0; +static int single_test = -1; +static int single_iter = -1; +static int level = 0; static int seed = 0; /* - * A parameterised tests runs a loop of test cases. + * A parameterised test runs a loop of test cases. * |num_test_cases| counts the total number of test cases * across all tests. */ static int num_test_cases = 0; +static int process_shared_options(void); + + void add_test(const char *test_case_name, int (*test_fn) (void)) { assert(num_tests != OSSL_NELEM(all_tests)); @@ -66,8 +74,6 @@ void add_all_tests(const char *test_case_name, int(*test_fn)(int idx), num_test_cases += num; } -static int level = 0; - int subtest_level(void) { return level; @@ -99,21 +105,26 @@ static int gcd(int a, int b) return a; } -void setup_test_framework(void) +static void set_seed(int s) +{ + seed = s; + if (seed <= 0) + seed = (int)time(NULL); + test_printf_stdout("%*s# RAND SEED %d\n", subtest_level(), "", seed); + test_flush_stdout(); + srand(seed); +} + + +int setup_test_framework(int argc, char *argv[]) { - char *TAP_levels = getenv("HARNESS_OSSL_LEVEL"); char *test_seed = getenv("OPENSSL_TEST_RAND_ORDER"); + char *TAP_levels = getenv("HARNESS_OSSL_LEVEL"); - level = TAP_levels != NULL ? 4 * atoi(TAP_levels) : 0; - - if (test_seed != NULL) { - seed = atoi(test_seed); - if (seed <= 0) - seed = (int)time(NULL); - test_printf_stdout("%*s# RAND SEED %d\n", subtest_level(), "", seed); - test_flush_stdout(); - srand(seed); - } + if (TAP_levels != NULL) + level = 4 * atoi(TAP_levels); + if (test_seed != NULL) + set_seed(atoi(test_seed)); #ifndef OPENSSL_NO_CRYPTO_MDEBUG if (should_report_leaks()) { @@ -121,8 +132,115 @@ void setup_test_framework(void) CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); } #endif + if (!opt_init(argc, argv, test_get_options())) + return 0; + return 1; } + +/* + * This can only be called after setup() has run, since num_tests and + * all_tests[] are setup at this point + */ +static int check_single_test_params(char *name, char *testname, char *itname) +{ + if (name != NULL) { + int i; + for (i = 0; i < num_tests; ++i) { + if (strcmp(name, all_tests[i].test_case_name) == 0) { + single_test = 1 + i; + break; + } + } + if (i >= num_tests) + single_test = atoi(name); + } + + + /* if only iteration is specified, assume we want the first test */ + if (single_test == -1 && single_iter != -1) + single_test = 1; + + if (single_test != -1) { + if (single_test < 1 || single_test > num_tests) { + test_printf_stderr("Invalid -%s value " + "(Value must be a valid test name OR a value between %d..%d)\n", + testname, 1, num_tests); + return 0; + } + } + if (single_iter != -1) { + if (all_tests[single_test - 1].num == -1) { + test_printf_stderr("-%s option is not valid for test %d:%s\n", + itname, + single_test, + all_tests[single_test - 1].test_case_name); + return 0; + } else if (single_iter < 1 + || single_iter > all_tests[single_test - 1].num) { + test_printf_stderr("Invalid -%s value for test %d:%s\t" + "(Value must be in the range %d..%d)\n", + itname, single_test, + all_tests[single_test - 1].test_case_name, + 1, all_tests[single_test - 1].num); + return 0; + } + } + return 1; +} + +static int process_shared_options(void) +{ + OPTION_CHOICE_DEFAULT o; + int value; + int ret = -1; + char *flag_test = ""; + char *flag_iter = ""; + char *testname = NULL; + + opt_begin(); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + /* Ignore any test options at this level */ + default: + break; + case OPT_ERR: + return ret; + case OPT_TEST_HELP: + opt_help(test_get_options()); + return 0; + case OPT_TEST_LIST: + show_list = 1; + break; + case OPT_TEST_SINGLE: + flag_test = opt_flag(); + testname = opt_arg(); + break; + case OPT_TEST_ITERATION: + flag_iter = opt_flag(); + if (!opt_int(opt_arg(), &single_iter)) + goto end; + break; + case OPT_TEST_INDENT: + if (!opt_int(opt_arg(), &value)) + goto end; + level = 4 * value; + break; + case OPT_TEST_SEED: + if (!opt_int(opt_arg(), &value)) + goto end; + set_seed(value); + break; + } + } + if (!check_single_test_params(testname, flag_test, flag_iter)) + goto end; + ret = 1; +end: + return ret; +} + + int pulldown_test_framework(int ret) { set_test_title(NULL); @@ -131,7 +249,6 @@ int pulldown_test_framework(int ret) && CRYPTO_mem_leaks_cb(openssl_error_cb, NULL) <= 0) return EXIT_FAILURE; #endif - return ret; } @@ -176,14 +293,21 @@ int run_tests(const char *test_prog_name) int ii, i, jj, j, jstep; int permute[OSSL_NELEM(all_tests)]; + i = process_shared_options(); + if (i == 0) + return EXIT_SUCCESS; + if (i == -1) + return EXIT_FAILURE; + if (num_tests < 1) { test_printf_stdout("%*s1..0 # Skipped: %s\n", level, "", test_prog_name); - } else { + } else if (show_list == 0 && single_test == -1) { if (level > 0) test_printf_stdout("%*s# Subtest: %s\n", level, "", test_prog_name); test_printf_stdout("%*s1..%d\n", level, "", num_tests); } + test_flush_stdout(); for (i = 0; i < num_tests; i++) @@ -198,12 +322,25 @@ int run_tests(const char *test_prog_name) for (ii = 0; ii != num_tests; ++ii) { i = permute[ii]; - if (all_tests[i].num == -1) { + + if (single_test != -1 && ((i+1) != single_test)) { + continue; + } + else if (show_list) { + if (all_tests[i].num != -1) { + test_printf_stdout("%d - %s (%d..%d)\n", ii + 1, + all_tests[i].test_case_name, 1, + all_tests[i].num); + } else { + test_printf_stdout("%d - %s\n", ii + 1, + all_tests[i].test_case_name); + } + test_flush_stdout(); + } else if (all_tests[i].num == -1) { int ret = 0; set_test_title(all_tests[i].test_case_name); ret = all_tests[i].test_fn(); - verdict = 1; if (!ret) { verdict = 0; @@ -215,7 +352,7 @@ int run_tests(const char *test_prog_name) int num_failed_inner = 0; level += 4; - if (all_tests[i].subtest) { + if (all_tests[i].subtest && single_iter == -1) { test_printf_stdout("%*s# Subtest: %s\n", level, "", all_tests[i].test_case_name); test_printf_stdout("%*s%d..%d\n", level, "", 1, @@ -235,6 +372,8 @@ int run_tests(const char *test_prog_name) int ret; j = (j + jstep) % all_tests[i].num; + if (single_iter != -1 && ((jj + 1) != single_iter)) + continue; set_test_title(NULL); ret = all_tests[i].param_test_fn(j); diff --git a/test/testutil/main.c b/test/testutil/main.c index 8b30ac60..6716750a 100644 --- a/test/testutil/main.c +++ b/test/testutil/main.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -8,28 +8,9 @@ */ #include "../testutil.h" -#include "internal/nelem.h" #include "output.h" #include "tu_local.h" -#include - -static size_t arg_count; -static char **args; -static unsigned char arg_used[1000]; - -static void check_arg_usage(void) -{ - size_t i, n = arg_count < OSSL_NELEM(arg_used) ? arg_count - : OSSL_NELEM(arg_used); - - for (i = 0; i < n; i++) - if (!arg_used[i+1]) - test_printf_stderr("Warning ignored command-line argument %zu: %s\n", - i, args[i+1]); - if (i < arg_count) - test_printf_stderr("Warning arguments %zu and later unchecked\n", i); -} int main(int argc, char *argv[]) { @@ -42,65 +23,18 @@ int main(int argc, char *argv[]) return ret; } - arg_count = argc - 1; - args = argv; + if (!setup_test_framework(argc, argv)) + goto end; - setup_test_framework(); - - if (setup_tests()) + if (setup_tests()) { ret = run_tests(argv[0]); - cleanup_tests(); - check_arg_usage(); - + cleanup_tests(); + opt_check_usage(); + } else { + opt_help(test_get_options()); + } +end: ret = pulldown_test_framework(ret); test_close_streams(); return ret; } - -const char *test_get_program_name(void) -{ - return args[0]; -} - -char *test_get_argument(size_t n) -{ - if (n > arg_count) - return NULL; - if (n + 1 < OSSL_NELEM(arg_used)) - arg_used[n + 1] = 1; - return args[n + 1]; -} - -size_t test_get_argument_count(void) -{ - return arg_count; -} - -int test_has_option(const char *option) -{ - size_t i; - - for (i = 1; i <= arg_count; i++) - if (strcmp(args[i], option) == 0) { - arg_used[i] = 1; - return 1; - } - return 0; -} - -const char *test_get_option_argument(const char *option) -{ - size_t i, n = strlen(option); - - for (i = 1; i <= arg_count; i++) - if (strncmp(args[i], option, n) == 0) { - arg_used[i] = 1; - if (args[i][n] == '\0' && i + 1 < arg_count) { - arg_used[++i] = 1; - return args[i]; - } - return args[i] + n; - } - return NULL; -} - diff --git a/test/testutil/options.c b/test/testutil/options.c new file mode 100644 index 00000000..9a32d1fb --- /dev/null +++ b/test/testutil/options.c @@ -0,0 +1,64 @@ +/* + * Copyright 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 + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "../testutil.h" +#include "internal/nelem.h" +#include "tu_local.h" +#include "output.h" + + +static int used[100] = { 0 }; + + +size_t test_get_argument_count(void) +{ + return opt_num_rest(); +} + +char *test_get_argument(size_t n) +{ + char **argv = opt_rest(); + + OPENSSL_assert(n < sizeof(used)); + if ((int)n >= opt_num_rest() || argv == NULL) + return NULL; + used[n] = 1; + return argv[n]; +} + +void opt_check_usage(void) +{ + int i; + char **argv = opt_rest(); + int n, arg_count = opt_num_rest(); + + if (arg_count > (int)OSSL_NELEM(used)) + n = (int)OSSL_NELEM(used); + else + n = arg_count; + for (i = 0; i < n; i++) { + if (used[i] == 0) + test_printf_stderr("Warning ignored command-line argument %d: %s\n", + i, argv[i]); + } + if (i < arg_count) + test_printf_stderr("Warning arguments %d and later unchecked\n", i); +} + +int opt_printf_stderr(const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, fmt); + ret = test_vprintf_stderr(fmt, ap); + va_end(ap); + return ret; +} + diff --git a/test/testutil/test_options.c b/test/testutil/test_options.c new file mode 100644 index 00000000..99e6d294 --- /dev/null +++ b/test/testutil/test_options.c @@ -0,0 +1,21 @@ +/* + * Copyright 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 + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "../testutil.h" +#include "tu_local.h" + +/* An overridable list of command line options */ +const OPTIONS *test_get_options(void) +{ + static const OPTIONS default_options[] = { + OPT_TEST_OPTIONS_DEFAULT_USAGE, + { NULL } + }; + return default_options; +} diff --git a/test/testutil/tu_local.h b/test/testutil/tu_local.h index 98cfae65..049d7b1b 100644 --- a/test/testutil/tu_local.h +++ b/test/testutil/tu_local.h @@ -1,5 +1,5 @@ /* - * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -44,8 +44,16 @@ void test_fail_memory_message(const char *prefix, const char *file, const unsigned char *m1, size_t l1, const unsigned char *m2, size_t l2); -void setup_test_framework(void); +__owur int setup_test_framework(int argc, char *argv[]); __owur int pulldown_test_framework(int ret); __owur int run_tests(const char *test_prog_name); void set_test_title(const char *title); + +typedef enum OPTION_choice_default { + OPT_ERR = -1, + OPT_EOF = 0, + OPT_TEST_ENUM +} OPTION_CHOICE_DEFAULT; +void opt_check_usage(void); + diff --git a/test/tls13ccstest.c b/test/tls13ccstest.c index 521a992c..d89354c1 100644 --- a/test/tls13ccstest.c +++ b/test/tls13ccstest.c @@ -481,6 +481,8 @@ static int test_tls13ccs(int tst) return ret; } +OPT_TEST_DECLARE_USAGE("certfile privkeyfile\n") + int setup_tests(void) { if (!TEST_ptr(cert = test_get_argument(0)) diff --git a/test/uitest.c b/test/uitest.c index ba40f52d..289f32b6 100644 --- a/test/uitest.c +++ b/test/uitest.c @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,11 +11,9 @@ #include #include #include -#include "apps.h" +#include "apps_ui.h" #include "testutil.h" -/* apps/apps.c depend on these */ -char *default_config_file = NULL; #include diff --git a/test/v3ext.c b/test/v3ext.c index 80e81e57..2c8ac6bb 100644 --- a/test/v3ext.c +++ b/test/v3ext.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -37,6 +37,8 @@ end: return ret; } +OPT_TEST_DECLARE_USAGE("cert.pem\n") + int setup_tests(void) { if (!TEST_ptr(infile = test_get_argument(0))) diff --git a/test/verify_extra_test.c b/test/verify_extra_test.c index 25212ddb..468de620 100644 --- a/test/verify_extra_test.c +++ b/test/verify_extra_test.c @@ -175,14 +175,14 @@ static int test_store_ctx(void) return testresult; } +OPT_TEST_DECLARE_USAGE("roots.pem untrusted.pem bad.pem\n") + int setup_tests(void) { if (!TEST_ptr(roots_f = test_get_argument(0)) || !TEST_ptr(untrusted_f = test_get_argument(1)) - || !TEST_ptr(bad_f = test_get_argument(2))) { - TEST_error("usage: verify_extra_test roots.pem untrusted.pem bad.pem\n"); + || !TEST_ptr(bad_f = test_get_argument(2))) return 0; - } ADD_TEST(test_alt_chains_cert_forgery); ADD_TEST(test_store_ctx); diff --git a/test/x509_check_cert_pkey_test.c b/test/x509_check_cert_pkey_test.c index 92a77770..434054f8 100644 --- a/test/x509_check_cert_pkey_test.c +++ b/test/x509_check_cert_pkey_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -106,14 +106,25 @@ failed: return ret; } +const OPTIONS *test_get_options(void) +{ + enum { OPT_TEST_ENUM }; + static const OPTIONS test_options[] = { + OPT_TEST_OPTIONS_WITH_EXTRA_USAGE("certname key.pem type expected\n"), + { OPT_HELP_STR, 1, '-', "certname\tCertificate filename .pem/.req\n" }, + { OPT_HELP_STR, 1, '-', "type\t\tvalue must be 'pem' or 'req'\n" }, + { OPT_HELP_STR, 1, '-', "expected\tthe expected return value\n" }, + { NULL } + }; + return test_options; +} + int setup_tests(void) { if (!TEST_ptr(c = test_get_argument(0)) || !TEST_ptr(k = test_get_argument(1)) || !TEST_ptr(t = test_get_argument(2)) || !TEST_ptr(e = test_get_argument(3))) { - TEST_note("usage: x509_check_cert_pkey cert.pem|cert.req" - " key.pem cert|req "); return 0; } diff --git a/test/x509_dup_cert_test.c b/test/x509_dup_cert_test.c index 6f766b9d..ebea488b 100644 --- a/test/x509_dup_cert_test.c +++ b/test/x509_dup_cert_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use @@ -33,14 +33,14 @@ static int test_509_dup_cert(int n) return ret; } +OPT_TEST_DECLARE_USAGE("cert.pem...\n") + int setup_tests(void) { size_t n = test_get_argument_count(); - if (!TEST_int_gt(n, 0)) { - TEST_note("usage: x509_dup_cert_test cert.pem..."); + if (!TEST_int_gt(n, 0)) return 0; - } ADD_ALL_TESTS(test_509_dup_cert, n); return 1; diff --git a/test/x509aux.c b/test/x509aux.c index 4488aa68..ec2618d7 100644 --- a/test/x509aux.c +++ b/test/x509aux.c @@ -161,14 +161,13 @@ static int test_certs(int num) return 0; } +OPT_TEST_DECLARE_USAGE("certfile...\n") + int setup_tests(void) { size_t n = test_get_argument_count(); - - if (n == 0) { - TEST_error("usage: %s certfile...", test_get_program_name()); + if (n == 0) return 0; - } ADD_ALL_TESTS(test_certs, (int)n); return 1;