"Fossies" - the Fresh Open Source Software Archive

Member "cfengine-3.15.4/cf-key/cf-key.c" (7 Jun 2021, 12179 Bytes) of package /linux/misc/cfengine-3.15.4.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /*
    2   Copyright 2019 Northern.tech AS
    3 
    4   This file is part of CFEngine 3 - written and maintained by Northern.tech AS.
    5 
    6   This program is free software; you can redistribute it and/or modify it
    7   under the terms of the GNU General Public License as published by the
    8   Free Software Foundation; version 3.
    9 
   10   This program is distributed in the hope that it will be useful,
   11   but WITHOUT ANY WARRANTY; without even the implied warranty of
   12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13   GNU General Public License for more details.
   14 
   15   You should have received a copy of the GNU General Public License
   16   along with this program; if not, write to the Free Software
   17   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
   18 
   19   To the extent this program is licensed as part of the Enterprise
   20   versions of CFEngine, the applicable Commercial Open Source License
   21   (COSL) may apply to this file if you as a licensee so wish it. See
   22   included file COSL.txt.
   23 */
   24 
   25 #include <generic_agent.h>
   26 
   27 #include <dbm_api.h>
   28 #include <lastseen.h>
   29 #include <dir.h>
   30 #include <scope.h>
   31 #include <files_copy.h>
   32 #include <files_interfaces.h>
   33 #include <hash.h>
   34 #include <keyring.h>
   35 #include <eval_context.h>
   36 #include <crypto.h>
   37 #include <known_dirs.h>
   38 #include <man.h>
   39 #include <signals.h>
   40 #include <string_lib.h>
   41 #include <file_lib.h>           /* FILE_SEPARATOR */
   42 #include <cleanup.h>
   43 
   44 #include <cf-key-functions.h>
   45 
   46 bool SHOWHOSTS = false;                                         /* GLOBAL_A */
   47 bool NO_TRUNCATE = false;                                       /* GLOBAL_A */
   48 bool FORCEREMOVAL = false;                                      /* GLOBAL_A */
   49 bool REMOVEKEYS = false;                                        /* GLOBAL_A */
   50 bool LICENSE_INSTALL = false;                                   /* GLOBAL_A */
   51 char LICENSE_SOURCE[MAX_FILENAME] = "";                         /* GLOBAL_A */
   52 const char *remove_keys_host = NULL;                            /* GLOBAL_A */
   53 static char *print_digest_arg = NULL;                           /* GLOBAL_A */
   54 static char *trust_key_arg = NULL;                              /* GLOBAL_A */
   55 static char *KEY_PATH = NULL;                                   /* GLOBAL_A */
   56 static int KEY_SIZE = 2048;                                     /* GLOBAL_A */
   57 bool LOOKUP_HOSTS = true;                                       /* GLOBAL_A */
   58 
   59 static GenericAgentConfig *CheckOpts(int argc, char **argv);
   60 
   61 /*******************************************************************/
   62 /* Command line options                                            */
   63 /*******************************************************************/
   64 
   65 static const char *const CF_KEY_SHORT_DESCRIPTION =
   66     "make private/public key-pairs for CFEngine authentication";
   67 
   68 static const char *const CF_KEY_MANPAGE_LONG_DESCRIPTION =
   69     "The CFEngine key generator makes key pairs for remote authentication.\n";
   70 
   71 #define TIMESTAMP_VAL 1234 // Anything outside ASCII range.
   72 static const struct option OPTIONS[] =
   73 {
   74     {"help", no_argument, 0, 'h'},
   75     {"inform", no_argument, 0, 'I'},
   76     {"debug", no_argument, 0, 'd'},
   77     {"verbose", no_argument, 0, 'v'},
   78     {"version", no_argument, 0, 'V'},
   79     {"log-level", required_argument, 0, 'g'},
   80     {"output-file", required_argument, 0, 'f'},
   81     {"key-type", required_argument, 0, 'T'},
   82     {"show-hosts", no_argument, 0, 's'},
   83     {"no-truncate", no_argument, 0, 'N'},
   84     {"remove-keys", required_argument, 0, 'r'},
   85     {"force-removal", no_argument, 0, 'x'},
   86     {"install-license", required_argument, 0, 'l'},
   87     {"print-digest", required_argument, 0, 'p'},
   88     {"trust-key", required_argument, 0, 't'},
   89     {"color", optional_argument, 0, 'C'},
   90     {"timestamp", no_argument, 0, TIMESTAMP_VAL},
   91     {"numeric", no_argument, 0, 'n'},
   92     {NULL, 0, 0, '\0'}
   93 };
   94 
   95 static const char *const HINTS[] =
   96 {
   97     "Print the help message",
   98     "Print basic information about key generation",
   99     "Enable debugging output",
  100     "Output verbose information about the behaviour of cf-key",
  101     "Output the version of the software",
  102     "Specify how detailed logs should be. Possible values: 'error', 'warning', 'notice', 'info', 'verbose', 'debug'",
  103     "Specify an alternative output file than the default.",
  104     "Specify a RSA key size in bits, the default value is 2048.",
  105     "Show lastseen hostnames and IP addresses",
  106     "Don't truncate -s / --show-hosts output",
  107     "Remove keys for specified hostname/IP/MD5/SHA (cf-key -r SHA=12345, cf-key -r MD5=12345, cf-key -r host001, cf-key -r 203.0.113.1)",
  108     "Force removal of keys",
  109     "Install license file on Enterprise server (CFEngine Enterprise Only)",
  110     "Print digest of the specified public key",
  111     "Make cf-serverd/cf-agent trust the specified public key. Argument value is of the form [[USER@]IPADDR:]FILENAME where FILENAME is the local path of the public key for client at IPADDR address.",
  112     "Enable colorized output. Possible values: 'always', 'auto', 'never'. If option is used, the default value is 'auto'",
  113     "Log timestamps on each line of log output",
  114     "Do not lookup host names",
  115     NULL
  116 };
  117 
  118 /*****************************************************************************/
  119 
  120 typedef void (*CfKeySigHandler)(int signum);
  121 bool cf_key_interrupted = false;
  122 
  123 static void handleShowKeysSignal(int signum)
  124 {
  125     cf_key_interrupted = true;
  126 
  127     signal(signum, handleShowKeysSignal);
  128 }
  129 
  130 static void SetupSignalsForCfKey(CfKeySigHandler sighandler)
  131 {
  132     signal(SIGINT, sighandler);
  133     signal(SIGTERM, sighandler);
  134     signal(SIGHUP, SIG_IGN);
  135     signal(SIGPIPE, SIG_IGN);
  136     signal(SIGBUS, HandleSignalsForAgent);
  137     signal(SIGUSR1, HandleSignalsForAgent);
  138     signal(SIGUSR2, HandleSignalsForAgent);
  139 }
  140 
  141 int main(int argc, char *argv[])
  142 {
  143     SetupSignalsForCfKey(HandleSignalsForAgent);
  144 
  145     GenericAgentConfig *config = CheckOpts(argc, argv);
  146     EvalContext *ctx = EvalContextNew();
  147     GenericAgentConfigApply(ctx, config);
  148 
  149     const char *program_invocation_name = argv[0];
  150     const char *last_dir_sep = strrchr(program_invocation_name, FILE_SEPARATOR);
  151     const char *program_name = (last_dir_sep != NULL ? last_dir_sep + 1 : program_invocation_name);
  152     GenericAgentDiscoverContext(ctx, config, program_name);
  153 
  154     if (SHOWHOSTS)
  155     {
  156         SetupSignalsForCfKey(handleShowKeysSignal);
  157         ShowLastSeenHosts(!NO_TRUNCATE);
  158         CallCleanupFunctions();
  159         return 0;
  160     }
  161 
  162     if (print_digest_arg)
  163     {
  164         CallCleanupFunctions();
  165         return PrintDigest(print_digest_arg);
  166     }
  167 
  168     GenericAgentPostLoadInit(ctx);
  169 
  170     if (REMOVEKEYS)
  171     {
  172         int status;
  173         if (FORCEREMOVAL)
  174         {
  175             if (!strncmp(remove_keys_host, "SHA=", 3) ||
  176                 !strncmp(remove_keys_host, "MD5=", 3))
  177             {
  178                 status = ForceKeyRemoval(remove_keys_host);
  179             }
  180             else
  181             {
  182                 status = ForceIpAddressRemoval(remove_keys_host);
  183             }
  184         }
  185         else
  186         {
  187             status = RemoveKeys(remove_keys_host, true);
  188             if (status == 0 || status == 1)
  189             {
  190                 Log (LOG_LEVEL_VERBOSE,
  191                      "Forced removal of entry '%s' was successful",
  192                      remove_keys_host);
  193                 CallCleanupFunctions();
  194                 return 0;
  195             }
  196         }
  197         CallCleanupFunctions();
  198         return status;
  199     }
  200 
  201     if(LICENSE_INSTALL)
  202     {
  203         bool success = LicenseInstall(LICENSE_SOURCE);
  204         CallCleanupFunctions();
  205         return success ? 0 : 1;
  206     }
  207 
  208     if (trust_key_arg != NULL)
  209     {
  210         char *filename, *ipaddr, *username;
  211         /* We will modify the argument to --trust-key. */
  212         char *arg = xstrdup(trust_key_arg);
  213 
  214         ParseKeyArg(arg, &filename, &ipaddr, &username);
  215 
  216         /* Server IP address required to trust key on the client side. */
  217         if (ipaddr == NULL)
  218         {
  219             Log(LOG_LEVEL_NOTICE, "Establishing trust might be incomplete. "
  220                 "For completeness, use --trust-key IPADDR:filename");
  221         }
  222 
  223         bool ret = TrustKey(filename, ipaddr, username);
  224 
  225         free(arg);
  226         CallCleanupFunctions();
  227         return ret ? EXIT_SUCCESS : EXIT_FAILURE;
  228     }
  229 
  230     char *public_key_file, *private_key_file;
  231 
  232     if (KEY_PATH)
  233     {
  234         xasprintf(&public_key_file, "%s.pub", KEY_PATH);
  235         xasprintf(&private_key_file, "%s.priv", KEY_PATH);
  236     }
  237     else
  238     {
  239         public_key_file = PublicKeyFile(GetWorkDir());
  240         private_key_file = PrivateKeyFile(GetWorkDir());
  241     }
  242 
  243     bool ret = KeepKeyPromises(public_key_file, private_key_file, KEY_SIZE);
  244 
  245     free(public_key_file);
  246     free(private_key_file);
  247 
  248     GenericAgentFinalize(ctx, config);
  249 
  250     CallCleanupFunctions();
  251     return ret ? EXIT_SUCCESS : EXIT_FAILURE;
  252 }
  253 
  254 /*****************************************************************************/
  255 /* Level                                                                     */
  256 /*****************************************************************************/
  257 
  258 static void PrintHelp()
  259 {
  260     Writer *w = FileWriter(stdout);
  261     WriterWriteHelp(w, "cf-key", OPTIONS, HINTS, NULL, false, false);
  262     FileWriterDetach(w);
  263 }
  264 
  265 static GenericAgentConfig *CheckOpts(int argc, char **argv)
  266 {
  267     extern char *optarg;
  268     int c;
  269     GenericAgentConfig *config = GenericAgentConfigNewDefault(AGENT_TYPE_KEYGEN, GetTTYInteractive());
  270 
  271     while ((c = getopt_long(argc, argv, "dvIf:g:T:VMp:sNr:xt:hl:C::n",
  272                             OPTIONS, NULL))
  273            != -1)
  274     {
  275         switch (c)
  276         {
  277         case 'f':
  278             KEY_PATH = optarg;
  279             break;
  280 
  281         case 'T':
  282             KEY_SIZE = StringToLongExitOnError(optarg);
  283             break;
  284 
  285         case 'd':
  286             LogSetGlobalLevel(LOG_LEVEL_DEBUG);
  287             break;
  288 
  289         case 'V':
  290             {
  291                 Writer *w = FileWriter(stdout);
  292                 GenericAgentWriteVersion(w);
  293                 FileWriterDetach(w);
  294             }
  295             DoCleanupAndExit(EXIT_SUCCESS);
  296 
  297         case 'v':
  298             LogSetGlobalLevel(LOG_LEVEL_VERBOSE);
  299             break;
  300 
  301         case 'g':
  302             LogSetGlobalLevelArgOrExit(optarg);
  303             break;
  304 
  305         case 'I':
  306             LogSetGlobalLevel(LOG_LEVEL_INFO);
  307             break;
  308 
  309         case 'p': /* print digest */
  310             print_digest_arg = optarg;
  311             break;
  312 
  313         case 's':
  314             SHOWHOSTS = true;
  315             break;
  316 
  317         case 'N':
  318             NO_TRUNCATE = true;
  319             break;
  320 
  321         case 'x':
  322             FORCEREMOVAL = true;
  323             break;
  324 
  325         case 'r':
  326             REMOVEKEYS = true;
  327             remove_keys_host = optarg;
  328             break;
  329 
  330         case 'l':
  331             LICENSE_INSTALL = true;
  332             strlcpy(LICENSE_SOURCE, optarg, sizeof(LICENSE_SOURCE));
  333             break;
  334 
  335         case 't':
  336             trust_key_arg = optarg;
  337             break;
  338 
  339         case 'h':
  340             PrintHelp();
  341             DoCleanupAndExit(EXIT_SUCCESS);
  342 
  343         case 'M':
  344             {
  345                 Writer *out = FileWriter(stdout);
  346                 ManPageWrite(out, "cf-key", time(NULL),
  347                              CF_KEY_SHORT_DESCRIPTION,
  348                              CF_KEY_MANPAGE_LONG_DESCRIPTION,
  349                              OPTIONS, HINTS,
  350                              NULL, false,
  351                              false);
  352                 FileWriterDetach(out);
  353                 DoCleanupAndExit(EXIT_SUCCESS);
  354             }
  355 
  356         case 'C':
  357             if (!GenericAgentConfigParseColor(config, optarg))
  358             {
  359                 DoCleanupAndExit(EXIT_FAILURE);
  360             }
  361             break;
  362 
  363         case TIMESTAMP_VAL:
  364             LoggingEnableTimestamps(true);
  365             break;
  366 
  367         case 'n':
  368             LOOKUP_HOSTS = false;
  369             break;
  370 
  371         default:
  372             PrintHelp();
  373             DoCleanupAndExit(EXIT_FAILURE);
  374 
  375         }
  376     }
  377 
  378     if (NO_TRUNCATE && !SHOWHOSTS)
  379     {
  380         PrintHelp();
  381         Log(LOG_LEVEL_ERR, "--no-truncate / -N option is only for --show-hosts / -s");
  382         DoCleanupAndExit(EXIT_FAILURE);
  383     }
  384 
  385     return config;
  386 }