#ifdef HAVE_CONFIG_H #include "config.h" #endif #include "srptool-options.h" #include #include #include #include #include #include #include #ifndef _WIN32 #include #endif /* !_WIN32 */ #include struct srptool_options srptool_options; static long parse_number (const char *arg) { char *endptr = NULL; errno = 0; long result; if (strncmp (arg, "0x", 2) == 0) result = strtol (arg + 2, &endptr, 16); else if (strncmp (arg, "0", 1) == 0 && strspn (arg, "012345678") == strlen (optarg)) result = strtol (arg + 1, &endptr, 8); else result = strtol (arg, &endptr, 10); if (errno != 0 || (endptr && *endptr != '\0')) error (EXIT_FAILURE, errno, "'%s' is not a recognizable number.", arg); return result; } /* Long options. */ static const struct option long_options[] = { { "debug", required_argument, 0, 'd' }, { "index", required_argument, 0, 'i' }, { "username", required_argument, 0, 'u' }, { "passwd", required_argument, 0, 'p' }, { "salt", required_argument, 0, 's' }, { "verify", no_argument, 0, CHAR_MAX + 1 }, { "passwd-conf", required_argument, 0, 'v' }, { "create-conf", required_argument, 0, CHAR_MAX + 2 }, { "version", optional_argument, 0, CHAR_MAX + 3 }, { "help", no_argument, 0, 'h' }, { "more-help", no_argument, 0, '!' }, { 0, 0, 0, 0 } }; /* Default options. */ static const char *index_default = "3"; int process_options (int argc, char **argv) { struct srptool_options *opts = &srptool_options; int opt; opts->arg.index = index_default; opts->value.index = 3; while ((opt = getopt_long (argc, argv, "!d:hi:p:s:u:v:", long_options, NULL)) != EOF) switch (opt) { case '\0': /* Long option. */ break; case 'd': opts->present.debug = true; opts->arg.debug = optarg; opts->value.debug = parse_number(optarg); opts->enabled.debug = true; break; case 'i': opts->present.index = true; opts->arg.index = optarg; opts->value.index = parse_number(optarg); opts->enabled.index = true; break; case 'u': opts->present.username = true; opts->arg.username = optarg; opts->enabled.username = true; break; case 'p': opts->present.passwd = true; opts->arg.passwd = optarg; opts->enabled.passwd = true; break; case 's': opts->present.salt = true; opts->arg.salt = optarg; opts->value.salt = parse_number(optarg); opts->enabled.salt = true; break; case CHAR_MAX + 1: /* --verify */ opts->present.verify = true; opts->enabled.verify = true; break; case 'v': opts->present.passwd_conf = true; opts->arg.passwd_conf = optarg; opts->enabled.passwd_conf = true; break; case CHAR_MAX + 2: /* --create-conf */ opts->present.create_conf = true; opts->arg.create_conf = optarg; opts->enabled.create_conf = true; break; case CHAR_MAX + 3: /* --version */ opts->present.version = true; opts->arg.version = optarg; opts->enabled.version = true; break; case 'h': opts->present.help = true; opts->enabled.help = true; break; case '!': opts->present.more_help = true; opts->enabled.more_help = true; break; default: usage (stderr, EXIT_FAILURE); break; } if (HAVE_OPT(DEBUG) && OPT_VALUE_DEBUG < 0) { error (EXIT_FAILURE, 0, "%s option value %d is out of range.", "debug", opts->value.debug); } if (HAVE_OPT(DEBUG) && OPT_VALUE_DEBUG > 9999) { error (EXIT_FAILURE, 0, "%s option value %d is out of range", "debug", opts->value.debug); } if (optind < argc) { error (EXIT_FAILURE, 0, "Command line arguments are not allowed."); } if (HAVE_OPT(HELP)) { USAGE(0); } if (HAVE_OPT(MORE_HELP)) #ifdef _WIN32 { USAGE(0); } #else /* _WIN32 */ { pid_t pid; int pfds[2]; if (pipe (pfds) < 0) error (EXIT_FAILURE, errno, "pipe"); pid = fork (); if (pid < 0) error (EXIT_FAILURE, errno, "fork"); if (pid == 0) { close (pfds[0]); dup2 (pfds[1], STDOUT_FILENO); close (pfds[1]); usage (stdout, 0); } else { const char *args[2]; const char *envvar; close (pfds[1]); dup2 (pfds[0], STDIN_FILENO); close (pfds[0]); envvar = secure_getenv ("PAGER"); if (!envvar || *envvar == '\0') args[0] = "more"; else args[0] = envvar; args[1] = NULL; execvp (args[0], (char * const *)args); exit (EXIT_FAILURE); } } #endif /* !_WIN32 */ if (HAVE_OPT(VERSION)) { if (!OPT_ARG_VERSION || !strcmp (OPT_ARG_VERSION, "c")) { const char str[] = "srptool 3.7.9\n" "Copyright (C) 2000-2021 Free Software Foundation, and others\n" "This is free software. It is licensed for use, modification and\n" "redistribution under the terms of the GNU General Public License,\n" "version 3 or later \n" "\n" "Please send bug reports to: \n"; fprintf (stdout, "%s", str); exit(0); } else if (!strcmp (OPT_ARG_VERSION, "v")) { const char str[] = "srptool 3.7.9\n"; fprintf (stdout, "%s", str); exit(0); } else if (!strcmp (OPT_ARG_VERSION, "n")) { const char str[] = "srptool 3.7.9\n" "Copyright (C) 2000-2021 Free Software Foundation, and others\n" "This is free software. It is licensed for use, modification and\n" "redistribution under the terms of the GNU General Public License,\n" "version 3 or later \n" "\n" "gnutls is free software: you can redistribute it and/or\n" "modify it under the terms of the GNU General Public License\n" "as published by the Free Software Foundation,\n" "either version 3 of the License, or (at your option) any later version.\n" "\n" "gnutls is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty\n" "of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" "See the GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with this program. If not, see .\n" "\n" "Please send bug reports to: \n"; fprintf (stdout, "%s", str); exit(0); } else { error (EXIT_FAILURE, 0, "version option argument 'a' invalid. Use:\n" " 'v' - version only\n" " 'c' - version and copyright\n" " 'n' - version and full copyright notice"); } } return optind; } void usage (FILE *out, int status) { const char str[] = "srptool - GnuTLS SRP tool\n" "Usage: srptool [ - [] | --[{=| }] ]... \n" "\n" "None:\n" "\n" " -d, --debug=num Enable debugging\n" " - it must be in the range:\n" " 0 to 9999\n" " -i, --index=num specify the index of the group parameters in tpasswd.conf to use\n" " -u, --username=str specify a username\n" " -p, --passwd=str specify a password file\n" " -s, --salt=num specify salt size\n" " --verify just verify the password\n" " -v, --passwd-conf=str specify a password conf file\n" " --create-conf=str Generate a password configuration file\n" "\n" "Version, usage and configuration options:\n" "\n" " -v, --version[=arg] output version information and exit\n" " -h, --help display extended usage information and exit\n" " -!, --more-help extended usage information passed thru pager\n" "\n" "Options are specified by doubled hyphens and their name or by a single\n" "hyphen and the flag character.\n" "\n" "Simple program that emulates the programs in the Stanford SRP (Secure\n" "Remote Password) libraries using GnuTLS. It is intended for use in places\n" "where you don't expect SRP authentication to be the used for system users.\n" "\n" "In brief, to use SRP you need to create two files. These are the password\n" "file that holds the users and the verifiers associated with them and the\n" "configuration file to hold the group parameters (called tpasswd.conf).\n" "\n" "Please send bug reports to: \n" "\n"; fprintf (out, "%s", str); exit (status); }