cfengine  3.15.4
About: CFEngine is a configuration management system for configuring and maintaining Unix-like computers (using an own high level policy language). Community version.
  Fossies Dox: cfengine-3.15.4.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

cf-key.c
Go to the documentation of this 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 {
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  {
159  return 0;
160  }
161 
162  if (print_digest_arg)
163  {
166  }
167 
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  {
179  }
180  else
181  {
183  }
184  }
185  else
186  {
187  status = RemoveKeys(remove_keys_host, true);
188  if (status == 0 || status == 1)
189  {
191  "Forced removal of entry '%s' was successful",
194  return 0;
195  }
196  }
198  return status;
199  }
200 
201  if(LICENSE_INSTALL)
202  {
203  bool success = LicenseInstall(LICENSE_SOURCE);
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);
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 
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;
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':
283  break;
284 
285  case 'd':
287  break;
288 
289  case 'V':
290  {
291  Writer *w = FileWriter(stdout);
293  FileWriterDetach(w);
294  }
295  DoCleanupAndExit(EXIT_SUCCESS);
296 
297  case 'v':
299  break;
300 
301  case 'g':
303  break;
304 
305  case 'I':
307  break;
308 
309  case 'p': /* print digest */
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;
328  break;
329 
330  case 'l':
331  LICENSE_INSTALL = true;
333  break;
334 
335  case 't':
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),
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:
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 }
char * xstrdup(const char *str)
Definition: alloc-mini.c:56
int xasprintf(char **strp, const char *fmt,...)
Definition: alloc.c:71
int ForceKeyRemoval(const char *hash)
int PrintDigest(const char *pubkey)
void ShowLastSeenHosts(bool truncate)
void ParseKeyArg(char *keyarg, char **filename, char **ipaddr, char **username)
bool LicenseInstall(char *path_source)
int ForceIpAddressRemoval(const char *ip)
bool KeepKeyPromises(const char *public_key_file, const char *private_key_file, const int key_size)
int RemoveKeys(const char *input, bool must_be_coherent)
removes all traces of entry 'input' from lastseen and filesystem
static const char *const CF_KEY_SHORT_DESCRIPTION
Definition: cf-key.c:65
int main(int argc, char *argv[])
Definition: cf-key.c:141
bool cf_key_interrupted
Definition: cf-key.c:121
bool REMOVEKEYS
Definition: cf-key.c:49
static char * trust_key_arg
Definition: cf-key.c:54
char LICENSE_SOURCE[254]
Definition: cf-key.c:51
static char * print_digest_arg
Definition: cf-key.c:53
bool LICENSE_INSTALL
Definition: cf-key.c:50
static void SetupSignalsForCfKey(CfKeySigHandler sighandler)
Definition: cf-key.c:130
static const char *const CF_KEY_MANPAGE_LONG_DESCRIPTION
Definition: cf-key.c:68
static GenericAgentConfig * CheckOpts(int argc, char **argv)
Definition: cf-key.c:265
static const char *const HINTS[]
Definition: cf-key.c:95
bool FORCEREMOVAL
Definition: cf-key.c:48
#define TIMESTAMP_VAL
Definition: cf-key.c:71
static void handleShowKeysSignal(int signum)
Definition: cf-key.c:123
bool NO_TRUNCATE
Definition: cf-key.c:47
static void PrintHelp()
Definition: cf-key.c:258
static int KEY_SIZE
Definition: cf-key.c:56
void(* CfKeySigHandler)(int signum)
Definition: cf-key.c:120
static const struct option OPTIONS[]
Definition: cf-key.c:72
bool LOOKUP_HOSTS
Definition: cf-key.c:57
const char * remove_keys_host
Definition: cf-key.c:52
static char * KEY_PATH
Definition: cf-key.c:55
bool SHOWHOSTS
Definition: cf-key.c:46
@ AGENT_TYPE_KEYGEN
Definition: cf3.defs.h:407
void free(void *)
void CallCleanupFunctions(void)
Definition: cleanup.c:39
void DoCleanupAndExit(int ret)
Definition: cleanup.c:57
bool TrustKey(const char *filename, const char *ipaddress, const char *username)
Definition: crypto.c:560
char * PublicKeyFile(const char *workdir)
Definition: crypto.c:749
char * PrivateKeyFile(const char *workdir)
Definition: crypto.c:757
EvalContext * EvalContextNew(void)
#define FILE_SEPARATOR
Definition: file_lib.h:102
GenericAgentConfig * GenericAgentConfigNewDefault(AgentType agent_type, bool tty_interactive)
bool GenericAgentPostLoadInit(const EvalContext *ctx)
void GenericAgentFinalize(EvalContext *ctx, GenericAgentConfig *config)
void GenericAgentDiscoverContext(EvalContext *ctx, GenericAgentConfig *config, const char *program_name)
bool GetTTYInteractive(void)
bool GenericAgentConfigParseColor(GenericAgentConfig *config, const char *mode)
void GenericAgentConfigApply(EvalContext *ctx, const GenericAgentConfig *config)
void GenericAgentWriteVersion(Writer *w)
#define NULL
Definition: getopt1.c:56
char * optarg
Definition: getopt.c:87
#define no_argument
Definition: getopt.h:98
#define required_argument
Definition: getopt.h:99
int getopt_long()
#define optional_argument
Definition: getopt.h:100
const char * GetWorkDir(void)
Definition: known_dirs.c:114
void LogSetGlobalLevelArgOrExit(const char *const arg)
Definition: logging.c:567
void LoggingEnableTimestamps(bool enable)
Definition: logging.c:88
void LogSetGlobalLevel(LogLevel level)
Definition: logging.c:561
void Log(LogLevel level, const char *fmt,...)
Definition: logging.c:409
@ LOG_LEVEL_ERR
Definition: logging.h:42
@ LOG_LEVEL_NOTICE
Definition: logging.h:44
@ LOG_LEVEL_DEBUG
Definition: logging.h:47
@ LOG_LEVEL_VERBOSE
Definition: logging.h:46
@ LOG_LEVEL_INFO
Definition: logging.h:45
void ManPageWrite(Writer *out, const char *program, time_t last_modified, const char *short_description, const char *long_description, const struct option options[], const char *const option_hints[], const Description *commands, bool command_first, bool accepts_file_argument)
Definition: man.c:226
#define MAX_FILENAME
Definition: platform.h:51
void HandleSignalsForAgent(int signum)
Definition: signals.c:145
long StringToLongExitOnError(const char *str)
Converts a string of numerals in base 10 to a long integer, exits on error.
Definition: string_lib.c:584
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:34
Definition: writer.c:45
Definition: getopt.h:83
void WriterWriteHelp(Writer *w, const char *component, const struct option options[], const char *const hints[], const Description *commands, bool command_first, bool accepts_file_argument)
Definition: writer.c:331
Writer * FileWriter(FILE *file)
Definition: writer.c:56
FILE * FileWriterDetach(Writer *writer)
Definition: writer.c:277