/* WARNING: This file was generated by dkct. Changes you make here will be lost if dkct is run again! You should modify the original source and run dkct on it. Original source: dk-pwgen.ctr */ /* Copyright (C) 2015-2017, Dirk Krause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above opyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file dk-pwgen.c The dk-pwgen module. */ #line 10 "dk-pwgen.ctr" #include "dk4conf.h" #if DK4_ON_WINDOWS /** Allow use of the getenv() function. */ #define _CRT_SECURE_NO_WARNINGS 1 #endif #if DK4_ON_WINDOWS #ifndef WINDOWS_H_INCLUDED #include #define WINDOWS_H_INCLUDED 1 #endif #ifndef WINCRYPT_H_INCLUDED #include #define WINCRYPT_H_INCLUDED 1 #endif #endif #if DK4_HAVE_UNISTD_H #ifndef UNISTD_H_INCLUDED #include #define UNISTD_H_INCLUDED 1 #endif #endif #if DK4_HAVE_SYS_TYPES_H #ifndef SYS_TYPES_H_INCLUDED #include #define SYS_TYPES_H_INCLUDED 1 #endif #endif #if DK4_HAVE_SIGNAL_H #ifndef SIGNAL_H_INCLUDED #include #define SIGNAL_H_INCLUDED 1 #endif #endif #if DK4_HAVE_PROCESS_H #ifndef PROCESS_H_INCLUDED #include #define PROCESS_H_INCLUDED 1 #endif #endif #if DK4_HAVE_IO_H #ifndef IO_H_INCLUDED #include #define IO_H_INCLUDED 1 #endif #endif #if DK4_HAVE_FCNTL_H #ifndef FCNTL_H_INCLUDED #include #define FCNTL_H_INCLUDED 1 #endif #endif #if DK4_HAVE_OPENSSL_RAND_H #ifndef OPENSSL_RAND_H_INCLUDED #include #define OPENSSL_RAND_H_INCLUDED 1 #endif #endif #include "dk4types.h" #include "dk4const.h" #include "dk4mem.h" #include "dk4mema.h" #include "dk4memrs.h" #include "dk4strd.h" #include "dk4app.h" #include "dk4aopt.h" #include "dk4fput.h" #include "dk4vers.h" #include "dk4maiddsz.h" #include "dk4maasz.h" #include "dk4mpl.h" #include "dk4svbufa.h" #line 97 "dk-pwgen.ctr" /** Output mode. */ enum { /** Create normal user password. */ DK_PWGEN_MODE_NORMAL = 0 , /** Create hard password. */ DK_PWGEN_MODE_HARD , /** Create binary data. */ DK_PWGEN_MODE_BINARY , /** Create hexadecimal key, use lower case a to f. */ DK_PWGEN_MODE_HEX_LOWER , /** Create hexadecimal key, use upper case A to F. */ DK_PWGEN_MODE_HEX_UPPER , /** Create numeric PIN. */ DK_PWGEN_MODE_PIN }; /** Constant texts used by program, not localized. */ static const dkChar * const dk_pwgen_kwnl[] = { /* 0 */ dkT("dktools"), /* 1 */ dkT("dk-pwgen.txt"), /* 2 */ dkT("dk-pwgen.str"), /* 3 */ dkT("0123456789abcdef"), /* 4 */ dkT("0123456789ABCDEF"), /* 5 */ dkT("0123456789"), /* 6 */ dkT("-_.:,;<>|#'+*~@^!\"$%&/()=?`{[]}"), /* 7 */ dkT("rand.egd.name"), /* 8 */ dkT("verbose"), NULL #line 167 "dk-pwgen.ctr" }; static const dkChar * const dk_pwgen_help_text[] = { dkT(""), dkT("Generate passwords, PINs and hexadecimal keys"), dkT(""), dkT("dk-pwgen []"), dkT(""), dkT("Options:"), dkT("-h\t\t--hard\t\t\tCreate hard password instead of normal."), dkT("-b\t\t--binary\t\tCreate binary random data"), dkT("\t\t\t\t\t(not on Windows)."), dkT("-p\t\t--pin\t\t\tCreate PIN number."), dkT("-x\t\t--hex\t\t\tCreate hexadecimal key, use `a'...`f'."), dkT("-X\t\t--Hex\t\t\tCreate hexadecimal key, use `A'...`F'."), dkT("-l \t--length=\tLength, i.e. ``8-10''."), dkT("-u \t--upper-case=\tNumber of uppercase chars in passwords."), dkT("-d \t--digits=\tNumber of digits in passwords."), dkT("-s \t--special=\tNumber of special chars in passwords."), dkT("-n\t\t--no-newline\t\tSuppress newline after output."), dkT("\t\t--verbose\t\tShow error message on SIGPIPE."), dkT(""), dkT("\t\t--help\t\t\tShow this short help text."), dkT("\t\t--manual\t\t*** SHOW FULL MANUAL. ***"), dkT("\t\t--version\t\tShow version information."), dkT("\t\t--license\t\tShow license information."), dkT(""), dkT("http://dktools.sourceforge.net"), dkT(""), NULL #line 200 "dk-pwgen.ctr" }; static const dkChar * const dk_pwgen_license_text[] = { dkT("This software uses code from the following projects, either directly or as"), dkT("a library:"), dkT(""), dkT("dktools\t\tDirk Krause's tools and libraries."), dkT("\t\tSee http://dktools.sourceforge.net/ for more information."), #if DK4_HAVE_ZLIB_H dkT(""), dkT("zlib\t\tData compression library."), dkT("\t\tSee http://www.zlib.net/ for more information."), #endif #if DK4_HAVE_BZLIB_H dkT(""), dkT("bzip2\t\tData compression program and library."), dkT("\t\tSee http://www.bzip.org/ for more information."), #endif #if DK4_HAVE_OPENSSL_RAND_H dkT(""), dkT("OpenSSL\t\tCryptographic toolkit, used to build file checksums here."), dkT("\t\tSee http://www.openssl.org/ for more information."), dkT(""), dkT("This product includes software developed by the OpenSSL Project for use in"), dkT("the OpenSSL Toolkit (http://www.openssl.org/)."), dkT("This product includes cryptographic software written by"), dkT("Eric Young (eay@cryptsoft.com)."), dkT("This product includes software written by Tim Hudson (tjh@cryptsoft.com)."), #endif dkT(""), dkT("All the licenses below apply to the program."), dkT("Licenses for used libraries are shown as found on my Scientific Linux 6.x"), dkT("computer in the /usr/share/doc directory on 2015-04-01. Check the project"), dkT("homepages of the used libraries for additional information and/or updated"), dkT("license terms."), dkT(""), dkT(""), dkT("DK tools and libraries license"), dkT("=============================="), dkT("Copyright (c) 2015-2016, Dirk Krause"), dkT("All rights reserved."), dkT(""), dkT("Redistribution and use in source and binary forms, with or without"), dkT("modification, are permitted provided that the following conditions are met:"), dkT(""), dkT("* Redistributions of source code must retain the above copyright notice,"), dkT(" this list of conditions and the following disclaimer."), dkT("* Redistributions in binary form must reproduce the above copyright"), dkT(" notice, this list of conditions and the following disclaimer in the"), dkT(" documentation and/or other materials provided with the distribution."), dkT("* Neither the name of the Dirk Krause nor the names of contributors may be"), dkT(" used to endorse or promote products derived from this software without"), dkT(" specific prior written permission."), dkT(""), dkT("THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\""), dkT("AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE"), dkT("IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE"), dkT("ARE DISCLAIMED."), dkT(""), dkT("IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,"), dkT("INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,"), dkT("BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,"), dkT("DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY"), dkT("OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING"), dkT("NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,"), dkT("EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."), #if DK4_HAVE_ZLIB_H dkT(""), dkT(""), dkT("Zlib license"), dkT("============"), dkT("(C) 1995-2004 Jean-loup Gailly and Mark Adler"), dkT(""), dkT("This software is provided 'as-is', without any express or implied"), dkT("warranty. In no event will the authors be held liable for any damages"), dkT("arising from the use of this software."), dkT(""), dkT("Permission is granted to anyone to use this software for any purpose,"), dkT("including commercial applications, and to alter it and redistribute it"), dkT("freely, subject to the following restrictions:"), dkT(""), dkT("1. The origin of this software must not be misrepresented; you must not"), dkT(" claim that you wrote the original software. If you use this software"), dkT(" in a product, an acknowledgment in the product documentation would be"), dkT(" appreciated but is not required."), dkT("2. Altered source versions must be plainly marked as such, and must not be"), dkT(" misrepresented as being the original software."), dkT("3. This notice may not be removed or altered from any source distribution."), dkT(""), dkT("Jean-loup Gailly Mark Adler"), dkT("jloup@gzip.org madler@alumni.caltech.edu"), #endif #if DK4_HAVE_BZLIB_H dkT(""), dkT(""), dkT("Bzip2 and libbzip2 library license"), dkT("=================================="), dkT("This program, \"bzip2\", the associated library \"libbzip2\", and all"), dkT("documentation, are copyright (C) 1996-2007 Julian R Seward. All"), dkT("rights reserved."), dkT(""), dkT("Redistribution and use in source and binary forms, with or without"), dkT("modification, are permitted provided that the following conditions"), dkT("are met:"), dkT(""), dkT("1. Redistributions of source code must retain the above copyright"), dkT(" notice, this list of conditions and the following disclaimer."), dkT(""), dkT("2. The origin of this software must not be misrepresented; you must "), dkT(" not claim that you wrote the original software. If you use this "), dkT(" software in a product, an acknowledgment in the product "), dkT(" documentation would be appreciated but is not required."), dkT(""), dkT("3. Altered source versions must be plainly marked as such, and must"), dkT(" not be misrepresented as being the original software."), dkT(""), dkT("4. The name of the author may not be used to endorse or promote "), dkT(" products derived from this software without specific prior written "), dkT(" permission."), dkT(""), dkT("THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS"), dkT("OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED"), dkT("WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE"), dkT("ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY"), dkT("DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL"), dkT("DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE"), dkT("GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS"), dkT("INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,"), dkT("WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING"), dkT("NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS"), dkT("SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."), dkT(""), dkT("Julian Seward, jseward@bzip.org"), dkT("bzip2/libbzip2 version 1.0.5 of 10 December 2007"), #endif #if DK4_HAVE_OPENSSL_RAND_H dkT(""), dkT(""), dkT("OpenSSL license"), dkT("==============="), dkT(""), dkT("LICENSE ISSUES"), dkT("--------------"), dkT(""), dkT("The OpenSSL toolkit stays under a dual license, i.e. both the conditions of"), dkT("the OpenSSL License and the original SSLeay license apply to the toolkit."), dkT("See below for the actual license texts. Actually both licenses are BSD-style"), dkT("Open Source licenses. In case of any license issues related to OpenSSL"), dkT("please contact openssl-core@openssl.org."), dkT(""), dkT("OpenSSL License"), dkT("---------------"), dkT(""), dkT("Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved."), dkT(""), dkT("Redistribution and use in source and binary forms, with or without"), dkT("modification, are permitted provided that the following conditions"), dkT("are met:"), dkT(""), dkT("1. Redistributions of source code must retain the above copyright"), dkT(" notice, this list of conditions and the following disclaimer. "), dkT(""), dkT("2. Redistributions in binary form must reproduce the above copyright"), dkT(" notice, this list of conditions and the following disclaimer in"), dkT(" the documentation and/or other materials provided with the"), dkT(" distribution."), dkT(""), dkT("3. All advertising materials mentioning features or use of this"), dkT(" software must display the following acknowledgment:"), dkT(" \"This product includes software developed by the OpenSSL Project"), dkT(" for use in the OpenSSL Toolkit. (http://www.openssl.org/)\""), dkT(""), dkT("4. The names \"OpenSSL Toolkit\" and \"OpenSSL Project\" must not be used to"), dkT(" endorse or promote products derived from this software without"), dkT(" prior written permission. For written permission, please contact"), dkT(" openssl-core@openssl.org."), dkT(""), dkT("5. Products derived from this software may not be called \"OpenSSL\""), dkT(" nor may \"OpenSSL\" appear in their names without prior written"), dkT(" permission of the OpenSSL Project."), dkT(""), dkT("6. Redistributions of any form whatsoever must retain the following"), dkT(" acknowledgment:"), dkT(" \"This product includes software developed by the OpenSSL Project"), dkT(" for use in the OpenSSL Toolkit (http://www.openssl.org/)\""), dkT(""), dkT("THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY"), dkT("EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE"), dkT("IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR"), dkT("PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR"), dkT("ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,"), dkT("SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT"), dkT("NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;"), dkT("LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)"), dkT("HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,"), dkT("STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)"), dkT("ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED"), dkT("OF THE POSSIBILITY OF SUCH DAMAGE."), dkT(""), dkT("This product includes cryptographic software written by Eric Young"), dkT("(eay@cryptsoft.com). This product includes software written by Tim"), dkT("Hudson (tjh@cryptsoft.com)."), dkT(""), dkT(""), dkT("Original SSLeay License"), dkT("-----------------------"), dkT(""), dkT("Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)"), dkT("All rights reserved."), dkT(""), dkT("This package is an SSL implementation written"), dkT("by Eric Young (eay@cryptsoft.com)."), dkT("The implementation was written so as to conform with Netscapes SSL."), dkT(""), dkT("This library is free for commercial and non-commercial use as long as"), dkT("the following conditions are aheared to. The following conditions"), dkT("apply to all code found in this distribution, be it the RC4, RSA,"), dkT("lhash, DES, etc., code; not just the SSL code. The SSL documentation"), dkT("included with this distribution is covered by the same copyright terms"), dkT("except that the holder is Tim Hudson (tjh@cryptsoft.com)."), dkT(""), dkT("Copyright remains Eric Young's, and as such any Copyright notices in"), dkT("the code are not to be removed."), dkT("If this package is used in a product, Eric Young should be given attribution"), dkT("as the author of the parts of the library used."), dkT("This can be in the form of a textual message at program startup or"), dkT("in documentation (online or textual) provided with the package."), dkT(""), dkT("Redistribution and use in source and binary forms, with or without"), dkT("modification, are permitted provided that the following conditions"), dkT("are met:"), dkT("1. Redistributions of source code must retain the copyright"), dkT(" notice, this list of conditions and the following disclaimer."), dkT("2. Redistributions in binary form must reproduce the above copyright"), dkT(" notice, this list of conditions and the following disclaimer in the"), dkT(" documentation and/or other materials provided with the distribution."), dkT("3. All advertising materials mentioning features or use of this software"), dkT(" must display the following acknowledgement:"), dkT(" \"This product includes cryptographic software written by"), dkT(" Eric Young (eay@cryptsoft.com)\""), dkT(" The word 'cryptographic' can be left out if the rouines from the library"), dkT(" being used are not cryptographic related :-)."), dkT("4. If you include any Windows specific code (or a derivative thereof) from "), dkT(" the apps directory (application code) you must include an acknowledgement:"), dkT(" \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\""), dkT(""), dkT("THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND"), dkT("ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE"), dkT("IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE"), dkT("ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE"), dkT("FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL"), dkT("DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS"), dkT("OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)"), dkT("HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT"), dkT("LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY"), dkT("OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF"), dkT("SUCH DAMAGE."), dkT(""), dkT("The licence and distribution terms for any publically available version or"), dkT("derivative of this code cannot be changed. i.e. this code cannot simply be"), dkT("copied and put under another distribution licence"), dkT("[including the GNU Public Licence.]"), dkT(""), #endif dkT(""), NULL #line 469 "dk-pwgen.ctr" }; static const dkChar * const dk_pwgen_kw_def[] = { /* 0 */ dkT("OpenSSL PRNG not available!"), /* 1 */ dkT("Failed to set up signal handlers!"), /* 2 */ dkT("Failed to restore signal handlers!"), /* 3 */ dkT("Numeric overflow while reading a size number!"), /* 4 */ dkT("Not a size specification: \""), /* 5 */ dkT("\"!"), /* 6 */ dkT("Failed to retrieve size from text: \""), /* 7 */ dkT("\"!"), /* 8 */ dkT("Options -h, -x, -X, and -p are mutually exclusive!"), /* 9 */ dkT("Option -u ignored for this output type!"), /* 10 */ dkT("Option -d ignored for this output type!"), /* 11 */ dkT("Option -s ignored for this output type!"), /* 12 */ dkT("Conflicting ranges for -l and -u/-d/-s!"), /* 13 */ dkT("Numeric overflow in password length calculation!"), /* 14 */ dkT("Failed to obtain random data from cryptographic context!"), /* 15 */ dkT("Failed to acquire cryptographic context!"), /* 16 */ dkT("Failed to open /dev/random and /dev/urandom devices!"), /* 17 */ dkT("Failed to obtain random data!"), /* 18 */ dkT("Failed to seed OpenSSL PRNG!"), /* 19 */ dkT("Aborted by SIGTERM signal!"), /* 20 */ dkT("Aborted by SIGINT signal!"), /* 21 */ dkT("Aborted by SIGPIPE signal!"), /* 22 */ dkT("Write attempt to standard output failed!"), /* 23 */ dkT("Seeding PRNG using OpenSSL builtin functions."), /* 24 */ dkT("Seeding PRNG from EGD socket."), /* 25 */ dkT("Seeding PRNG from Windows cryptographic context."), /* 26 */ dkT("Seeding PRNG from screen contents."), /* 27 */ dkT("Seeding PRNG from /dev/random or /dev/urandom device."), /* 28 */ dkT("Seeding PRNG from EGD socket specified by preference."), /* 29 */ dkT("Options -b, -h, -x, -X, and -p are mutually exclusive!"), /* 30 */ dkT("Failed to reset used memory!"), /* 31 */ dkT("The -b option is not supported on Windows!"), NULL #line 586 "dk-pwgen.ctr" }; /** Options understood by program. */ static const dk4_option_specification_t dk_pwgen_options[] = { { dkT('h'), dkT("hard"), DK4_OPT_ARG_NONE }, { dkT('b'), dkT("binary"), DK4_OPT_ARG_NONE }, { dkT('x'), dkT("hex"), DK4_OPT_ARG_NONE }, { dkT('X'), dkT("Hex"), DK4_OPT_ARG_NONE }, { dkT('p'), dkT("pin"), DK4_OPT_ARG_NONE }, { dkT('l'), dkT("length"), DK4_OPT_ARG_STRING }, { dkT('u'), dkT("upper-case"), DK4_OPT_ARG_STRING }, { dkT('d'), dkT("digits"), DK4_OPT_ARG_STRING }, { dkT('s'), dkT("special"), DK4_OPT_ARG_STRING }, { dkT('n'), dkT("no-newline"), DK4_OPT_ARG_NONE }, { dkT('\0'), dkT("verbose"), DK4_OPT_ARG_NONE } }; #ifndef BUFSIZ #define BUFSIZ 8192 #endif /** Use an explicitly specified buffer for stdout operations so we can securely reset the memory before exiting. */ static char stdout_buffer[BUFSIZ]; /** Use an explicitly specified buffer when reading seed file so we can securely reset the memory before exiting. */ static char seed_file_buf[BUFSIZ]; /** Localized version if available, otherwise default texts. */ static const dkChar * const *dk_pwgen_msg = dk_pwgen_kw_def; /** Application structure. */ static dk4_app_t *app = NULL; /** Number of elements in dk_pwgen_msg array. */ static size_t dk_pwgen_sz_msg = sizeof(dk_pwgen_kw_def)/sizeof(DK4_PCDKCHAR) - 1; /** Number of elements in dk_pwgen_options array. */ static const size_t dk_pwgen_sz_options = sizeof(dk_pwgen_options)/sizeof(dk4_option_specification_t); /** Minimum output length. */ static size_t length_min = 8; /** Maximum output length. */ static size_t length_max = 10; /** Output length to produce. */ static size_t length = 8; /** Minimum number of upper case characters. */ static size_t upper_min = 1; /** Maximum number of upper case characters. */ static size_t upper_max = 2; /** Number of upper case characters to produce. */ static size_t upper = 1; /** Minimum number of digits. */ static size_t digit_min = 1; /** Maximum number of digits. */ static size_t digit_max = 2; /** Number of digits to produce. */ static size_t digits = 1; /** Minimum number of special characters. */ static size_t special_min = 1; /** Maximum number of special characters. */ static size_t special_max = 2; /** Number of special characters to produce. */ static size_t specials = 1; /** Flag: Errors occured while writing to stdout. */ static int output_error = 0; /** Flag: Verbose output (report SIGPIPE). */ static int verbose = 1; /** Exit status code. */ static int exval = EXIT_FAILURE; /** Output type to produce. */ static int output_type = DK_PWGEN_MODE_NORMAL; #if DK4_HAVE_OPENSSL_RAND_H #ifdef SIGPIPE /** Indicator: SIGPIPE signal received. */ static DK4_VOLATILE dk4_sig_atomic_t sig_had_pipe = 0; #endif /** Indicator: SIGINT signal received. */ static DK4_VOLATILE dk4_sig_atomic_t sig_had_int = 0; /** Indicator: SIGTERM signal received. */ static DK4_VOLATILE dk4_sig_atomic_t sig_had_term = 0; /** Pass a volatile pointer to an atomic integer. This function is necessary as some compilers mis-optimize direct access to volatile variables (at least if you believe one of the coding standards). @param ptr Address of atomic integer variable. @return The unmodified pointer. */ static DK4_VOLATILE dk4_sig_atomic_t * sig_pass_pointer(DK4_VOLATILE dk4_sig_atomic_t *ptr) { return ptr; } #ifdef SIGPIPE /** Handler for SIGPIPE signal. @param signo Signal number (always SIGPIPE, ignored). */ static void sig_handler_pipe(int signo) { *sig_pass_pointer(&sig_had_pipe) = 1; } #endif /** Handler for SIGINT signal. @param signo Signal number (always SIGINT, ignored). */ static void sig_handler_int(int signo) { *sig_pass_pointer(&sig_had_int) = 1; } /** Handler for SIGTERM signal. @param signo Signal number (always SIGTERM, ignored). */ static void sig_handler_term(int signo) { *sig_pass_pointer(&sig_had_term) = 1; } /** Read value from volatile atomic type. This function is necessary as some compilers mis-optimize direct access to volatile variables (at least if you believe one of the coding standards). @param ap Pointer to volatile atomic variable. @return Contents of the variable. */ static dk4_sig_atomic_t sig_read_atomic(DK4_VOLATILE dk4_sig_atomic_t *ap) { return (*ap); } /** Check whether we can continue or if a signal was received. @param check_pipe Flag: Check for occured SIGPIPE signal too. @return 1 if the program can continue, 0 if a signal was received. */ static int sig_can_continue(int check_pipe) { int back = 1; #ifdef SIGPIPE if (0 != check_pipe) { if (0 != sig_read_atomic(&sig_had_pipe)) { back = 0; } } #endif if (0 != sig_read_atomic(&sig_had_int )) { back = 0; } if (0 != sig_read_atomic(&sig_had_term)) { back = 0; } return back; } /** Check whether we can continue. @return 1 for yes, 0 for no. */ static int dk_pwgen_can_continue(void) { int back = 1; if (0 == sig_can_continue(1)) { back = 0; } return back; } /** Read range from text to size_t variables. @param minptr Address of minimum variable. @param maxptr Address of maximum variable. @param buf Buffer containing the text. @return 1 on success, 0 on error. */ static int dk_pwgen_opt_range(size_t *minptr, size_t *maxptr, dkChar option) { dkChar buf[32*sizeof(dk4_um_t)]; dk4_er_t er; const dkChar *endptr; dkChar *p1; size_t val; int res; int rdf = 0; int back = 0; int passno = 0; #line 894 "dk-pwgen.ctr" if (0 != dk4app_opt_is_set_long(app, dk_pwgen_kwnl[8], NULL)) { verbose = 1; } if (0 != dk4app_opt_is_set_short(app, option, NULL)) { res = dk4app_opt_get_string_short( buf, DK4_SIZEOF(buf,dkChar), app, option, NULL ); if (0 != res) { #line 902 "dk-pwgen.ctr" p1 = dk4str_chr(buf, dkT('-')); if (NULL != p1) { #line 904 "dk-pwgen.ctr" *(p1++) = dkT('\0'); p1 = dk4str_start(p1, NULL); } else { #line 907 "dk-pwgen.ctr" } val = 0; endptr = NULL; dk4error_init(&er); if (0 != dk4ma_input_dk_dec_size_t(&val, buf, &endptr, 1, &er)) { *minptr = val; *maxptr = val; back = 1; if (NULL != p1) { #line 916 "dk-pwgen.ctr" passno = 1; back = 0; val = 0; endptr = NULL; if (0 != dk4ma_input_dk_dec_size_t(&val, p1, &endptr, 1, &er)) { *maxptr = val; back = 1; if (*maxptr < *minptr) { val = *maxptr; *maxptr = *minptr; *minptr = val; } } else { #line 929 "dk-pwgen.ctr" /* ERROR: Failed to read size */ rdf = 1; } } } else { #line 934 "dk-pwgen.ctr" /* ERROR: Failed to read size */ rdf = 1; } } else { #line 938 "dk-pwgen.ctr" /* ERROR: Failed to obtain option argument, probably bug */ } } else { #line 941 "dk-pwgen.ctr" back = 1; } if ((0 == back) && (0 != rdf)) { switch (er.ec) { case DK4_E_MATH_OVERFLOW : { #line 946 "dk-pwgen.ctr" /* ERROR: Numeric overflow while reading number */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 3); } break; case DK4_E_SYNTAX : { #line 950 "dk-pwgen.ctr" /* ERROR: Not a size specification */ dk4app_log_3( app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 4, 5, ((0 == passno) ? buf : p1) ); } break; default: { #line 957 "dk-pwgen.ctr" /* ERROR: Failed to read size */ dk4app_log_3( app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 6, 7, ((0 == passno) ? buf : p1) ); } break; } } #line 965 "dk-pwgen.ctr" return back; } /** Process command line options. @return 1 on success, 0 on error (invalid option combination). */ static int dk_pwgen_check_options(void) { dk4_er_t er; size_t val; int back = 0; #line 981 "dk-pwgen.ctr" if (0 != dk4app_opt_is_set_short(app, dkT('b'), NULL)) { output_type = DK_PWGEN_MODE_BINARY; if ( (0 != dk4app_opt_is_set_short(app, dkT('h'), NULL)) || (0 != dk4app_opt_is_set_short(app, dkT('x'), NULL)) || (0 != dk4app_opt_is_set_short(app, dkT('X'), NULL)) || (0 != dk4app_opt_is_set_short(app, dkT('p'), NULL)) ) { /* ERROR: Options -b, -h, -x, -X and -p are mutually exclusive! */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 29); goto finished; } else { back = 1; } } else { if (0 != dk4app_opt_is_set_short(app, dkT('h'), NULL)) { output_type = DK_PWGEN_MODE_HARD; if ( (0 != dk4app_opt_is_set_short(app, dkT('x'), NULL)) || (0 != dk4app_opt_is_set_short(app, dkT('X'), NULL)) || (0 != dk4app_opt_is_set_short(app, dkT('p'), NULL)) ) { /* ERROR: Options -h, -x, -X and -p are mutually exclusive! */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 8); goto finished; } else { back = 1; } } else { if (0 != dk4app_opt_is_set_short(app, dkT('x'), NULL)) { output_type = DK_PWGEN_MODE_HEX_LOWER; if ( (0 != dk4app_opt_is_set_short(app, dkT('X'), NULL)) || (0 != dk4app_opt_is_set_short(app, dkT('p'), NULL)) ) { /* ERROR: Options -h, -x, -X and -p are mutually exclusive! */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 8); goto finished; } else { back = 1; } } else { if (0 != dk4app_opt_is_set_short(app, dkT('X'), NULL)) { output_type = DK_PWGEN_MODE_HEX_UPPER; if (0 != dk4app_opt_is_set_short(app, dkT('p'), NULL)) { /* ERROR: Options -h, -x, -X and -p are mutually exclusive! */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 8); goto finished; } else { back = 1; } } else { if (0 != dk4app_opt_is_set_short(app, dkT('p'), NULL)) { output_type = DK_PWGEN_MODE_PIN; } back = 1; } } } } if (1 == back) { if (0 == dk_pwgen_opt_range(&length_min, &length_max, dkT('l'))) { back = 0; } if (1 == back) { switch (output_type) { case DK_PWGEN_MODE_HARD : case DK_PWGEN_MODE_HEX_LOWER : case DK_PWGEN_MODE_HEX_UPPER : case DK_PWGEN_MODE_PIN : { if (0 != dk4app_opt_is_set_short(app, dkT('u'), NULL)) { /* WARNING: Option ignored */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 9); } if (0 != dk4app_opt_is_set_short(app, dkT('d'), NULL)) { /* WARNING: Option ignored */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 10); } if (0 != dk4app_opt_is_set_short(app, dkT('s'), NULL)) { /* WARNING: Option ignored */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 11); } } break; default : { if (0 != dk_pwgen_opt_range(&upper_min, &upper_max, dkT('u'))) { if (0 != dk_pwgen_opt_range(&digit_min, &digit_max, dkT('d'))) { if (0 != dk_pwgen_opt_range(&special_min, &special_max, dkT('s'))) { dk4error_init(&er); val = dk4ma_size_t_add(upper_max, digit_max, &er); val = dk4ma_size_t_add(val, special_max, &er); if (DK4_E_NONE == er.ec) { if (val > length_min) { back = 0; /* ERROR: Illegal range combination */ dk4app_log_1( app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 12 ); } } else { /* ERROR: Numeric overflow in size calculation */ dk4app_log_1( app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 13 ); } } else { back = 0; } } else { back = 0; } } else { back = 0; } } break; } } } finished: #line 1112 "dk-pwgen.ctr" return back; } /** Seed PRNG. @return 1 on success, 0 on error (not enough seed data). */ static int dk_pwgen_seed_prng(void) { #if DK4_CHAR_SIZE == 1 dkChar snb[DK4_MAX_PATH]; #endif char buffer[64]; char *envptr; #if DK4_ON_WINDOWS HCRYPTPROV hcp; BOOL res; #else FILE *fipo; size_t rdb; #endif int cc; int rounds = 0; int back = 0; int svbres = 0; #line 1141 "dk-pwgen.ctr" /* Let OpenSSL library functions try to initialize. */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_DEBUG, 23); if (1 == RAND_status()) { back = 1; goto finished; } #if DK4_HAVE_RAND_EGD && DK4_HAVE_STRUCT_SOCKADDR_UN /* Attempt EGD socket if specified in environment. */ envptr = getenv("EGDSOCKET"); if (NULL != envptr) { dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_DEBUG, 24); if (0 < RAND_egd(envptr)) { if (1 == RAND_status()) { back = 1; goto finished; } } } /* Attempt EGD socket defined by preference. The RAND_egd() function accepts char, not dkChar. */ #if DK4_CHAR_SIZE == 1 if (0 != dk4app_pref_get(snb,DK4_SIZEOF(snb,dkChar),app,dk_pwgen_kwnl[7],0)) { dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_DEBUG, 28); if (0 < RAND_egd(snb)) { if (1 == RAND_status()) { back = 1; goto finished; } } } #endif #endif /* Use platform specific mechanisms if available. */ #if DK4_ON_WINDOWS dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_DEBUG, 25); res = CryptAcquireContext( &hcp, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ); if (res) { cc = 1; do { if (0 != dk_pwgen_can_continue()) { res = CryptGenRandom(hcp, (DWORD)sizeof(buffer), buffer); if (res) { RAND_seed(buffer, sizeof(buffer)); if (1 == RAND_status()) { cc = 0; back = 1; } else { rounds++; } } else { cc = -1; /* ERROR: Failed to obtain random bytes from crypto context */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 14); } } else { cc = -1; } } while ((1 == cc) && (128 > rounds)); CryptReleaseContext(hcp, (DWORD)0UL); dk4mem_reset_secure(buffer, sizeof(buffer), NULL); if (0 == back) { if (0 != dk_pwgen_can_continue()) { dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_DEBUG, 25); RAND_screen(); if (1 == RAND_status()) { back = 1; } } } } else { /* ERROR: Failed to acquire crypto context */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 15); } #else dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_DEBUG, 27); fipo = fopen("/dev/random", "rb"); if (NULL == fipo) { fipo = fopen("/dev/urandom", "rb"); } if (NULL != fipo) { dk4mem_reset(seed_file_buf, sizeof(seed_file_buf), NULL); svbres = dk4setvbuf( fipo, DK4_FILE_FULL_BUFFERING, seed_file_buf, sizeof(seed_file_buf), NULL ); if (0 != svbres) { cc = 1; do { if (0 != dk_pwgen_can_continue()) { rdb = fread(buffer, 1, sizeof(buffer), fipo); if (0 < rdb) { RAND_seed(buffer, rdb); if (1 == RAND_status()) { cc = 0; back = 1; } else { rounds++; } } else { cc = -1; } } else { cc = -1; } } while ((1 == cc) && (128 > rounds)); } else { dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 16); } fclose(fipo); dk4mem_reset_secure(seed_file_buf, sizeof(seed_file_buf), NULL); dk4mem_reset_secure(buffer, sizeof(buffer), NULL); } else { /* ERROR: Failed to open both /dev/random and /dev/urandom */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 16); } #endif finished: #line 1269 "dk-pwgen.ctr" return back; } /** Find a random number in a given range. @param dptr Address of destination variable. @param min Minimum value. @param max Maximum value. @return 1 on success, 0 on error. */ static int dk_pwgen_value_in_range(size_t *dptr, size_t min, size_t max) { size_t width; size_t rval; int back = 0; #line 1288 "dk-pwgen.ctr" if (max > min) { width = max - min; if (0 != (width + 1)) { width++ ; } if (0 < RAND_bytes((unsigned char *)(&rval), (int)sizeof(rval))) { #line 1293 "dk-pwgen.ctr" *dptr = min + (rval % width); back = 1; } else { /* ERROR: Failed to obtain random bytes */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 17); } } else { *dptr = min; back = 1; } #line 1304 "dk-pwgen.ctr" return back; } /** Create hexadecimal key and write to standard output. @param upper Flag: Use upper case `a' to `f'. */ static void dk_pwgen_output_hex(int upper) { unsigned char buf[8]; /* Buffer for 8 random bytes */ size_t i; /* Index of current output character */ size_t bi; /* Index in buffer 0 to 7 */ size_t j; /* Index in hexademical digits string */ int cc; /* Flag: Can continue 1=yes,0=no,-1=abort */ dkChar dc; /* Current character to write */ #line 1323 "dk-pwgen.ctr" cc = 1; i = 0; bi = 0; do { if (0 != dk_pwgen_can_continue()) { if (i < length) { if (0 == (i % 16)) { bi = 0; if (0 < RAND_bytes(buf, (int)sizeof(buf))) { cc = 1; } else { cc = -1; exval = EXIT_FAILURE; /* ERROR: Random */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 17); } } if (1 == cc) { j = (size_t)(buf[bi / 2]); j = 0x00FFU & j; if (0 == (i % 2)) { j = j >> 4; } j &= 0x000FU; dc = (dk_pwgen_kwnl[(0 != upper) ? 4 : 3])[j]; if (0 == dk4fputc(dc, stdout, NULL)) { output_error = 1; cc = -1; } } i++; bi++; } else { cc = 0; } } else { cc = -1; } } while (1 == cc); if (0 == dk4mem_reset_secure(buf, sizeof(buf), NULL)) { dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 30); exval = EXIT_FAILURE; } dc = dkT('\0'); j = 0; if ((0 != j) || (dkT('\0') != dc)) { dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 30); exval = EXIT_FAILURE; } #line 1371 "dk-pwgen.ctr" } /** Create hard password and write to standard output. */ static void dk_pwgen_output_hard(void) { dk4_um_t val; size_t i; int cc; dkChar dc; i = 0; cc = 1; do { if (0 != dk_pwgen_can_continue()) { if (i < length) { if (0 < RAND_bytes((unsigned char *)(&val), (int)sizeof(dk4_um_t))) { dc = (dkChar)33 + (dkChar)(val % (dk4_um_t)90U); if (0 == dk4fputc(dc, stdout, NULL)) { output_error = 1; cc = -1; } } else { cc = -1; exval = EXIT_FAILURE; /* ERROR: Random */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 17); } i++; } else { cc = 0; } } else { cc = -1; } } while (1 == cc); val = (dk4_um_t)0UL; dc = dkT('\0'); if ((val != (dk4_um_t)0UL) || (dc != dkT('\0'))) { dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 30); exval = EXIT_FAILURE; } } /** Create binary password and write to standard output. */ static void dk_pwgen_output_binary(void) { #if !DK4_ON_WINDOWS char buf[256]; size_t i; size_t remaining; size_t wrb; int cc; #endif #if DK4_ON_WINDOWS dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 31); exval = EXIT_FAILURE; #else remaining = length; cc = 1; do { if (0 != dk_pwgen_can_continue()) { i = sizeof(buf); if (remaining < i) { i = remaining; } if (0 == i) { cc = 0; } else { if (0 < RAND_bytes((unsigned char *)buf, (int)i)) { wrb = fwrite(buf, 1, i, stdout); if (i == wrb) { if (i >= remaining) { cc = 0; } else { remaining = remaining - i; } } else { cc = -1; exval = EXIT_FAILURE; output_error = 1; } } else { cc = -1; exval = EXIT_FAILURE; /* ERROR: Random */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 17); } } } else { cc = -1; } } while ((1 == cc) && (0 < remaining)); if (0 != fflush(stdout)) { exval = EXIT_FAILURE; output_error = 1; } if (0 == dk4mem_reset_secure(buf, sizeof(buf), NULL)) { dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 30); exval = EXIT_FAILURE; } #endif } /** Create numeric PIN and write to standard output. */ static void dk_pwgen_output_pin(void) { dk4_um_t val; size_t i; int cc; dkChar dc; i = 0; cc = 1; do { if (0 != dk_pwgen_can_continue()) { if (i < length) { if (0 < RAND_bytes((unsigned char *)(&val), (int)sizeof(dk4_um_t))) { dc = dkT('0') + (dkChar)(val % (dk4_um_t)10U); if (0 == dk4fputc(dc, stdout, NULL)) { output_error = 1; cc = -1; } } else { cc = -1; exval = EXIT_FAILURE; /* ERROR: Random */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 17); } i++; } else { cc = 0; } } else { cc = -1; } } while (1 == cc); dc = dkT('\0'); if (dc != dkT('\0')) { dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 30); exval = EXIT_FAILURE; } } /** Create normal password and write to standard output. */ static void dk_pwgen_output_normal(void) { char *ti = NULL; /* Cells */ dk4_um_t val; /* Value */ size_t avail; /* Number of unused cells */ size_t curel; /* Current element within group */ size_t ind_to_set; /* Index of unused cell to set */ size_t i; /* Traverse all cells */ size_t max; /* Number of elements within pass */ size_t speclen; /* Length of string containing special */ int passno; /* Current pass */ int cc; /* Flag: No error yet, can continue */ int res; /* Operation result */ dkChar dc; /* Character to write */ char ic; /* Indicator character */ ti = dk4mem_new_app(char,length,app); if (NULL != ti) { #line 1548 "dk-pwgen.ctr" DK4_MEMRES(ti, length); cc = 1; if (0 == dk_pwgen_value_in_range(&upper, upper_min, upper_max)) { cc = 0; } if (0 == dk_pwgen_value_in_range(&digits, digit_min, digit_max)) { cc = 0; } if (0 == dk_pwgen_value_in_range(&specials, special_min, special_max)) { cc = 0; } if (1 == cc) { passno = 0; avail = length; while (3 > passno) { #line 1563 "dk-pwgen.ctr" switch (passno) { case 2 : { max = specials; ic = 's'; } break; case 1 : { max = digits; ic = 'd'; } break; default : { max = upper; ic = 'u'; } break; } curel = 0; while (curel < max) { #line 1580 "dk-pwgen.ctr" if (0 != dk_pwgen_can_continue()) { res = RAND_bytes( (unsigned char *)(&ind_to_set), (int)sizeof(size_t) ); if (0 < res) { if (0 < avail) { ind_to_set = ind_to_set % avail; #line 1588 "dk-pwgen.ctr" res = 0; i = 0; while (i < length) { #line 1592 "dk-pwgen.ctr" if ('\0' == ti[i]) { if (0 == ind_to_set) { #line 1595 "dk-pwgen.ctr" res = 1; ti[i] = ic; i = length - 1; avail--; } else { ind_to_set--; } } else { #line 1603 "dk-pwgen.ctr" } i++; } curel++; if (0 == res) { #line 1608 "dk-pwgen.ctr" /* No free cell found */ curel = max; passno = 3; cc = 0; dk4app_log_1( app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 12 ); } } else { /* No more cells available */ curel = max; passno = 3; cc = 0; dk4app_log_1( app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 12 ); } } else { /* ERROR: Random data */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 17); curel = max; passno = 3; cc = 0; } } else { curel = max; passno = 3; cc = 0; } } passno++; if (0 == dk_pwgen_can_continue()) { passno = 3; } } if ((1 == cc) && (0 != dk_pwgen_can_continue())) { #line 1634 "dk-pwgen.ctr" i = 0; speclen = dk4str_len(dk_pwgen_kwnl[6]); #line 1637 "dk-pwgen.ctr" while (i < length) { #line 1639 "dk-pwgen.ctr" if (0 != dk_pwgen_can_continue()) { res = RAND_bytes( (unsigned char *)(&val), (int)sizeof(dk4_um_t) ); if (0 < res) { #line 1645 "dk-pwgen.ctr" switch (ti[i]) { case 's': { val = val % (dk4_um_t)speclen; #line 1649 "dk-pwgen.ctr" dc = (dk_pwgen_kwnl[6])[(size_t)val]; } break; case 'd': { val = val % (dk4_um_t)10UL; dc = dkT('0') + (dkChar)val; } break; case 'u': { val = val % (dk4_um_t)26UL; dc = dkT('A') + (dkChar)val; } break; default: { val = val % (dk4_um_t)26UL; dc = dkT('a') + (dkChar)val; } break; } if (0 == dk4fputc(dc, stdout, NULL)) { output_error = 1; } i++; } else { i = length; exval = EXIT_FAILURE; /* ERROR: Random */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 17); } } else { i = length; } } } else { exval = EXIT_FAILURE; } } else { exval = EXIT_FAILURE; /* Failed to obtain random */ } if (0 == dk4mem_reset_secure(ti, length, NULL)) { dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 30); exval = EXIT_FAILURE; } dk4mem_free(ti); dc = dkT('\0'); if (dc != dkT('\0')) { dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 30); exval = EXIT_FAILURE; } } else { #line 1696 "dk-pwgen.ctr" exval = EXIT_FAILURE; /* ERROR: Memory, already reported */ } } /** Create password, PIN or key and write to output. */ static void dk_pwgen_produce_output(void) { #line 1710 "dk-pwgen.ctr" if (0 != dk_pwgen_value_in_range(&length, length_min, length_max)) { exval = EXIT_SUCCESS; switch (output_type) { case DK_PWGEN_MODE_BINARY : { #line 1714 "dk-pwgen.ctr" dk_pwgen_output_binary(); } break; case DK_PWGEN_MODE_HARD : { #line 1717 "dk-pwgen.ctr" dk_pwgen_output_hard(); } break; case DK_PWGEN_MODE_HEX_LOWER : { #line 1720 "dk-pwgen.ctr" dk_pwgen_output_hex(0); } break; case DK_PWGEN_MODE_HEX_UPPER : { #line 1723 "dk-pwgen.ctr" dk_pwgen_output_hex(1); } break; case DK_PWGEN_MODE_PIN : { #line 1726 "dk-pwgen.ctr" dk_pwgen_output_pin(); } break; default : { #line 1729 "dk-pwgen.ctr" dk_pwgen_output_normal(); } break; } if (0 == dk4app_opt_is_set_short(app, dkT('n'), NULL)) { if (DK_PWGEN_MODE_BINARY != output_type) { if (0 == dk4fputc(dkT('\n'), stdout, NULL)) { output_error = 1; } } } } #line 1741 "dk-pwgen.ctr" } /** Run normally with signal handlers installed. */ static void dk_pwgen_normal_run(void) { #line 1752 "dk-pwgen.ctr" if (0 < dk_pwgen_check_options()) { if (0 < dk_pwgen_seed_prng()) { dk_pwgen_produce_output(); } else { /* ERROR: Failed to seed PRNG */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 18); } RAND_cleanup(); } #line 1762 "dk-pwgen.ctr" } #if DK4_HAVE_SIGACTION /** Set signal handlers and run. */ static void dk_pwgen_run_with_signal_handlers(void) { #ifdef SIGPIPE struct sigaction opipe; #endif struct sigaction oint; #ifdef SIGPIPE struct sigaction npipe; #endif struct sigaction nint; struct sigaction oterm; struct sigaction nterm; int success = 0; #ifdef SIGPIPE /* Set up signal handling for SIGPIPE. */ DK4_MEMRES(&npipe, sizeof(npipe)); npipe.sa_handler = sig_handler_pipe; npipe.sa_flags = 0; if (0 != sigemptyset(&npipe.sa_mask)) { /* ERROR: Failed to set up masked signal set for SIGPIPE */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 1); goto finished; } if (0 != sigaddset(&npipe.sa_mask, SIGPIPE)) { /* ERROR: Failed to set up masked signal set for SIGPIPE */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 1); goto finished; } if (0 != sigaction(SIGPIPE, &npipe, &opipe)) { /* ERROR: Failed to set up signal handler for SIGPIPE */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 1); goto finished; } #endif /* Set up signal handling for SIGINT. */ DK4_MEMRES(&nint, sizeof(nint)); nint.sa_handler = sig_handler_int; nint.sa_flags = 0; if (0 != sigemptyset(&nint.sa_mask)) { /* ERROR: Failed to set up masked signal set for SIGINT */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 1); goto restore_old_pipe; } if (0 != sigaddset(&nint.sa_mask, SIGINT)) { /* ERROR: Failed to set up masked signal set for SIGINT */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 1); goto restore_old_pipe; } if (0 != sigaction(SIGINT, &nint, &oint)) { /* ERROR: Failed to set up signal handler for SIGINT */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 1); goto restore_old_pipe; } /* Set up signal handling for SIGTERM */ DK4_MEMRES(&nterm, sizeof(nterm)); nterm.sa_handler = sig_handler_term; nterm.sa_flags = 0; if (0 != sigemptyset(&nterm.sa_mask)) { /* ERROR: Failed to set up masked signal set for SIGTERM */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 1); goto restore_old_int; } if (0 != sigaddset(&nterm.sa_mask, SIGTERM)) { /* ERROR: Failed to set up masked signal set for SIGTERM */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 1); goto restore_old_int; } if (0 != sigaction(SIGTERM, &nterm, &oterm)) { /* ERROR: Failed to set up signal handler for SIGTERM */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 1); goto restore_old_int; } success = 1; dk_pwgen_normal_run(); /* Restore signal handling for SIGTERM. */ if (0 != sigaction(SIGTERM, &oterm, NULL)) { /* ERROR: Failed to restore old SIGTERM settings */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 2); success = 0; } /* Restore signal handling for SIGINT. */ restore_old_int: if (0 != sigaction(SIGINT, &oint, NULL)) { /* ERROR: Failed to restore old SIGPIPE settings */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 2); success = 0; } #ifdef SIGPIPE /* Restore signal handling for SIGPIPE. */ restore_old_pipe: if (0 != sigaction(SIGPIPE, &opipe, NULL)) { /* ERROR: Failed to restore old SIGPIPE settings */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 2); success = 0; } #endif /* Set exit status code if error occured. */ finished: if (0 == success) { exval = EXIT_FAILURE; } } #else #if DK4_HAVE_SIGSET /** Set signal handlers and run. */ static void dk_pwgen_run_with_signal_handlers(void) { #ifdef SIGPIPE dk4_sig_handler_t *oldpipe = NULL; #endif dk4_sig_handler_t *oldint = NULL; dk4_sig_handler_t *oldterm = NULL; #ifdef SIGPIPE oldpipe = sigset(SIGPIPE, sig_handler_pipe); #endif oldint = sigset(SIGINT, sig_handler_int); oldterm = sigset(SIGTERM, sig_handler_term); dk_pwgen_normal_run(); sigset(SIGTERM, oldterm); sigset(SIGINT, oldint); #ifdef SIGPIPE sigset(SIGPIPE, oldpipe); #endif } #else #if DK4_HAVE_SIGNAL /** Set signal handlers and run. */ static void dk_pwgen_run_with_signal_handlers(void) { #ifdef SIGPIPE dk4_sig_handler_t *oldpipe = NULL; #endif dk4_sig_handler_t *oldint = NULL; dk4_sig_handler_t *oldterm = NULL; #ifdef SIGPIPE oldpipe = signal(SIGPIPE, sig_handler_pipe); #endif oldint = signal(SIGINT, sig_handler_int); oldterm = signal(SIGTERM, sig_handler_term); dk_pwgen_normal_run(); signal(SIGTERM, oldterm); signal(SIGINT, oldint); #ifdef SIGPIPE signal(SIGPIPE, oldpipe); #endif } #else /** Set signal handlers and run. */ static void dk_pwgen_run_with_signal_handlers(void) { dk_pwgen_normal_run(); } #endif #endif #endif #endif /* if DK4_HAVE_OPENSSL_RAND_H */ /** Main function. @param argc Number of command line arguments. @param argv Command line arguments array. @return 0 on success, all other values indicate errors. */ #if DK4_CHAR_SIZE > 1 int wmain(int argc, wchar_t *argv[]) #else int main(int argc, char *argv[]) #endif { int shp; int pbso; /* Flag: Private buffer used for stdout */ pbso = dk4setvbuf( stdout, DK4_FILE_LINE_BUFFERING, stdout_buffer, sizeof(stdout_buffer), NULL ); #line 1975 "dk-pwgen.ctr" #line 1976 "dk-pwgen.ctr" dk4fput_initialize_stdout(); dk4fput_initialize_stderr(); app = dk4app_open_cmd( argc, argv, dk_pwgen_options, dk_pwgen_sz_options, dk_pwgen_kwnl[0], DKT_VERSION_DK, dk_pwgen_kwnl[1], dk_pwgen_help_text, dk_pwgen_license_text ); if (NULL != app) { dk_pwgen_sz_msg = dk4app_string_table_size(dk_pwgen_kw_def); dk_pwgen_msg = dk4app_string_table(app,dk_pwgen_kwnl[2],dk_pwgen_kw_def); if (0 != dk4app_can_run_normally(app)) { #if DK4_HAVE_OPENSSL_RAND_H /* Run. */ dk_pwgen_run_with_signal_handlers(); /* Report signals and output errors, if any. */ if (0 != sig_read_atomic(&sig_had_term)) { /* ERROR: SIGTERM signal received */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 19); exval = EXIT_FAILURE; } if (0 != sig_read_atomic(&sig_had_int )) { /* ERROR: SIGINT signal received */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 20); exval = EXIT_FAILURE; } #ifdef SIGPIPE if (0 != sig_read_atomic(&sig_had_pipe)) { /* ERROR: SIGPIPE signal received */ if (0 != verbose) { dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 21); } exval = EXIT_FAILURE; shp = 1; } else { shp = 0; } #else shp = 0; #endif if ((0 == shp) && (0 != output_error)) { /* ERROR: Failed to write to stdout */ dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 22); exval = EXIT_FAILURE; } #else dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 0); #endif if (0 == pbso) { dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 30); exval = EXIT_FAILURE; } else { #ifdef BUFSIZ fflush(stdout); if (0 == dk4mem_reset_secure(stdout_buffer,sizeof(stdout_buffer),NULL)) { dk4app_log_1(app, dk_pwgen_msg, dk_pwgen_sz_msg, DK4_LL_ERROR, 30); exval = EXIT_FAILURE; } #endif } } else { if (0 != dk4app_help_version_license(app)) { exval = EXIT_SUCCESS; } } dk4app_close(app); } else { } fflush(stdout); fflush(stderr); dk4fput_cleanup_stderr(); dk4fput_cleanup_stdout(); #line 2053 "dk-pwgen.ctr" #line 2054 "dk-pwgen.ctr" exit(exval); return exval; }