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)  

crypto.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 <crypto.h>
26 
27 #include <openssl/err.h> /* ERR_* */
28 #include <openssl/rand.h> /* RAND_* */
29 #include <openssl/bn.h> /* BN_* */
30 #include <libcrypto-compat.h>
31 
32 #include <cf3.defs.h>
33 #include <lastseen.h>
34 #include <files_interfaces.h>
35 #include <hash.h>
36 #include <pipes.h>
37 #include <mutex.h>
38 #include <known_dirs.h>
39 #include <bootstrap.h>
40 #include <misc_lib.h> /* UnexpectedError,ProgrammingError */
41 #include <file_lib.h>
42 
43 #ifdef DARWIN
44 // On Mac OSX 10.7 and later, majority of functions in /usr/include/openssl/crypto.h
45 // are deprecated. No known replacement, so shutting up compiler warnings
46 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
47 #endif
48 
49 #if OPENSSL_VERSION_NUMBER < 0x10100000
50 /* The deprecated is the easy way to setup threads for OpenSSL. */
51 #ifdef OPENSSL_NO_DEPRECATED
52 void CRYPTO_set_id_callback(unsigned long (*func)(void));
53 #endif
54 #endif
55 
56 static void RandomSeed(void);
57 static void SetupOpenSSLThreadLocks(void);
58 static void CleanupOpenSSLThreadLocks(void);
59 
60 /* TODO move crypto.[ch] to libutils. Will need to remove all manipulation of
61  * lastseen db. */
62 
63 static bool crypto_initialized = false; /* GLOBAL_X */
64 
65 const char *CryptoLastErrorString()
66 {
67  const char *errmsg = ERR_reason_error_string(ERR_get_error());
68  return (errmsg != NULL) ? errmsg : "no error message";
69 }
70 
72 {
73  if (!crypto_initialized)
74  {
76  OpenSSL_add_all_algorithms();
77  OpenSSL_add_all_digests();
78  ERR_load_crypto_strings();
79 
80  RandomSeed();
81 
82  crypto_initialized = true;
83  }
84 }
85 
87 {
89  {
90  char randfile[CF_BUFSIZE];
91  snprintf(randfile, CF_BUFSIZE, "%s%crandseed",
93 
94  /* Only write out a seed if the file doesn't exist
95  * and we have enough entropy to do so. If RAND_write_File
96  * returns a bad value, delete the poor seed.
97  */
98  if (access(randfile, R_OK) && errno == ENOENT && RAND_write_file(randfile) != 1024)
99  {
101  "Could not write randomness to '%s'", randfile);
102  unlink(randfile); /* do not reuse entropy */
103  }
104 
105  chmod(randfile, 0600);
106  EVP_cleanup();
108  ERR_free_strings();
109  crypto_initialized = false;
110  }
111 }
112 
113 static void RandomSeed(void)
114 {
115  /* 1. Seed the weak C PRNGs. */
116 
117  /* Mix various stuff. */
118  pid_t pid = getpid();
119  size_t fqdn_len = strlen(VFQNAME) > 0 ? strlen(VFQNAME) : 1;
120  time_t start_time = CFSTARTTIME;
121  time_t now = time(NULL);
122 
123  srand((unsigned) pid * start_time ^
124  (unsigned) fqdn_len * now);
125  srand48((long) pid * start_time ^
126  (long) fqdn_len * now);
127 
128  /* 2. Seed the strong OpenSSL PRNG. */
129 
130 #ifndef __MINGW32__
131  RAND_poll(); /* windows may hang */
132 #else
133  RAND_screen(); /* noop unless openssl is very old */
134 #endif
135 
136  if (RAND_status() != 1)
137  {
138  /* randseed file is written on deinitialization of crypto system */
139  char randfile[CF_BUFSIZE];
140  snprintf(randfile, CF_BUFSIZE, "%s%crandseed",
142  Log(LOG_LEVEL_VERBOSE, "Looking for a source of entropy in '%s'",
143  randfile);
144 
145  if (RAND_load_file(randfile, -1) != 1024)
146  {
148  "Could not read randomness from '%s'", randfile);
149  unlink(randfile); /* kill randseed if error reading it */
150  }
151 
152  /* If we've used the random seed, then delete */
153  unlink(randfile);
154  }
155 }
156 
157 /* PEM functions need the const cast away, but hopefully the default
158  * call-back doesn't actually modify its user-data. */
159 static const char priv_passphrase[] = PRIVKEY_PASSPHRASE;
160 
161 /**
162  * @param[in] priv_key_path path to the private key to use (%NULL to use the default)
163  * @param[in] pub_key_path path to the private key to use (%NULL to use the default)
164  * @param[out] priv_key a place to store the loaded private key (or %NULL to
165  * use the global PRIVKEY variable)
166  * @param[out] pub_key a place to store the loaded public key (or %NULL to
167  * use the global PUBKEY variable)
168  * @return true the error is not so severe that we must stop
169  */
170 bool LoadSecretKeys(const char *const priv_key_path,
171  const char *const pub_key_path,
172  RSA **priv_key, RSA **pub_key)
173 {
174  {
175  char *privkeyfile = NULL;
176  if (priv_key_path == NULL)
177  {
178  privkeyfile = PrivateKeyFile(GetWorkDir());
179  }
180  FILE *fp = safe_fopen(privkeyfile != NULL ? privkeyfile : priv_key_path, "r");
181  if (!fp)
182  {
183  /* VERBOSE in case it's a custom, local-only installation. */
185  "Couldn't find a private key at '%s', use cf-key to get one. (fopen: %s)",
186  privkeyfile != NULL ? privkeyfile : priv_key_path, GetErrorStr());
187  free(privkeyfile);
188  return false;
189  }
190 
191  if (priv_key == NULL)
192  {
193  /* if no place to store the private key was specified, use the
194  * global variable PRIVKEY */
195  priv_key = &PRIVKEY;
196  }
197  if (*priv_key != NULL)
198  {
199  DESTROY_AND_NULL(RSA_free, *priv_key);
200  }
201 
202  // Can read both encrypted (old) and unencrypted(new) key files:
203  *priv_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, (void*) priv_passphrase);
204  if (*priv_key == NULL)
205  {
207  "Error reading private key. (PEM_read_RSAPrivateKey: %s)",
209  *priv_key = NULL;
210  fclose(fp);
211  return false;
212  }
213 
214  fclose(fp);
215  Log(LOG_LEVEL_VERBOSE, "Loaded private key at '%s'", privkeyfile);
216  free(privkeyfile);
217  }
218 
219  {
220  char *pubkeyfile = NULL;
221  if (pub_key_path == NULL)
222  {
223  pubkeyfile = PublicKeyFile(GetWorkDir());
224  }
225  FILE *fp = safe_fopen(pubkeyfile != NULL ? pubkeyfile : pub_key_path, "r");
226  if (!fp)
227  {
228  /* VERBOSE in case it's a custom, local-only installation. */
230  "Couldn't find a public key at '%s', use cf-key to get one (fopen: %s)",
231  pubkeyfile != NULL ? pubkeyfile : pub_key_path, GetErrorStr());
232  free(pubkeyfile);
233  return false;
234  }
235 
236  if (pub_key == NULL)
237  {
238  /* if no place to store the public key was specified, use the
239  * global variable PUBKEY */
240  pub_key = &PUBKEY;
241  }
242  if (*pub_key != NULL)
243  {
244  DESTROY_AND_NULL(RSA_free, *pub_key);
245  }
246  *pub_key = PEM_read_RSAPublicKey(fp, NULL, NULL, (void*) priv_passphrase);
247  if (*pub_key == NULL)
248  {
250  "Error reading public key at '%s'. (PEM_read_RSAPublicKey: %s)",
251  pubkeyfile, CryptoLastErrorString());
252  fclose(fp);
253  free(pubkeyfile);
254  return false;
255  }
256 
257  Log(LOG_LEVEL_VERBOSE, "Loaded public key '%s'", pubkeyfile);
258  free(pubkeyfile);
259  fclose(fp);
260  }
261 
262  if (*pub_key != NULL)
263  {
264  const BIGNUM *n, *e;
265  RSA_get0_key(*pub_key, &n, &e, NULL);
266  if ((BN_num_bits(e) < 2) || (!BN_is_odd(e)))
267  {
268  Log(LOG_LEVEL_ERR, "The public key RSA exponent is too small or not odd");
269  return false;
270  }
271  }
272 
273  return true;
274 }
275 
276 void PolicyHubUpdateKeys(const char *policy_server)
277 {
278  if (GetAmPolicyHub() && PUBKEY != NULL)
279  {
280  unsigned char digest[EVP_MAX_MD_SIZE + 1];
281  const char* const workdir = GetWorkDir();
282 
283  char dst_public_key_filename[CF_BUFSIZE] = "";
284  {
285  char buffer[CF_HOSTKEY_STRING_SIZE];
287  snprintf(dst_public_key_filename, sizeof(dst_public_key_filename),
288  "%s/ppkeys/%s-%s.pub",
289  workdir, "root",
290  HashPrintSafe(buffer, sizeof(buffer), digest,
291  CF_DEFAULT_DIGEST, true));
292  MapName(dst_public_key_filename);
293  }
294 
295  struct stat sb;
296  if ((stat(dst_public_key_filename, &sb) == -1))
297  {
298  char src_public_key_filename[CF_BUFSIZE] = "";
299  snprintf(src_public_key_filename, CF_MAXVARSIZE, "%s/ppkeys/localhost.pub", workdir);
300  MapName(src_public_key_filename);
301 
302  // copy localhost.pub to root-HASH.pub on policy server
303  if (!LinkOrCopy(src_public_key_filename, dst_public_key_filename, false))
304  {
305  Log(LOG_LEVEL_ERR, "Unable to copy policy server's own public key from '%s' to '%s'", src_public_key_filename, dst_public_key_filename);
306  }
307 
308  if (policy_server)
309  {
310  LastSaw(policy_server, digest, LAST_SEEN_ROLE_CONNECT);
311  }
312  }
313  }
314 }
315 
316 /*********************************************************************/
317 
318 /**
319  * @brief Search for a key given an IP address, by getting the
320  * key hash value from lastseen db.
321  * @return NULL if the key was not found in any form.
322  */
323 RSA *HavePublicKeyByIP(const char *username, const char *ipaddress)
324 {
325  char hash[CF_HOSTKEY_STRING_SIZE];
326 
327  /* Get the key hash for that address from lastseen db. */
328  bool found = Address2Hostkey(hash, sizeof(hash), ipaddress);
329 
330  /* If not found, by passing "" as digest, we effectively look only for
331  * the old-style key file, e.g. root-1.2.3.4.pub. */
332  return HavePublicKey(username, ipaddress,
333  found ? hash : "");
334 }
335 
336 static const char *const pub_passphrase = "public";
337 
338 /**
339  * @brief Search for a key:
340  * 1. username-hash.pub
341  * 2. username-ip.pub
342  * @return NULL if key not found in any form
343  */
344 RSA *HavePublicKey(const char *username, const char *ipaddress, const char *digest)
345 {
346  char keyname[CF_MAXVARSIZE], newname[CF_BUFSIZE], oldname[CF_BUFSIZE];
347  struct stat statbuf;
348  RSA *newkey = NULL;
349  const char* const workdir = GetWorkDir();
350 
351  snprintf(keyname, CF_MAXVARSIZE, "%s-%s", username, digest);
352 
353  snprintf(newname, CF_BUFSIZE, "%s/ppkeys/%s.pub", workdir, keyname);
354  MapName(newname);
355 
356  if (stat(newname, &statbuf) == -1)
357  {
358  Log(LOG_LEVEL_VERBOSE, "Did not find new key format '%s'", newname);
359 
360  snprintf(oldname, CF_BUFSIZE, "%s/ppkeys/%s-%s.pub",
361  workdir, username, ipaddress);
362  MapName(oldname);
363  Log(LOG_LEVEL_VERBOSE, "Trying old style '%s'", oldname);
364 
365  if (stat(oldname, &statbuf) == -1)
366  {
367  Log(LOG_LEVEL_DEBUG, "Did not have old-style key '%s'", oldname);
368  return NULL;
369  }
370 
371  if (strlen(digest) > 0)
372  {
373  Log(LOG_LEVEL_INFO, "Renaming old key from '%s' to '%s'", oldname, newname);
374 
375  if (rename(oldname, newname) != 0)
376  {
377  Log(LOG_LEVEL_ERR, "Could not rename from old key format '%s' to new '%s'. (rename: %s)", oldname, newname, GetErrorStr());
378  }
379  }
380  else
381  {
382  /* We don't know the digest (e.g. because we are a client and have
383  no lastseen-map yet), so we're using old file format
384  (root-IP.pub). */
386  "We have no digest yet, using old keyfile name: %s",
387  oldname);
388  snprintf(newname, sizeof(newname), "%s", oldname);
389  }
390  }
391 
392  FILE *fp = safe_fopen(newname, "r");
393  if (fp == NULL)
394  {
395  Log(LOG_LEVEL_ERR, "Couldn't open public key file '%s' (fopen: %s)",
396  newname, GetErrorStr());
397  return NULL;
398  }
399 
400  if ((newkey = PEM_read_RSAPublicKey(fp, NULL, NULL,
401  (void *)pub_passphrase)) == NULL)
402  {
404  "Error reading public key from '%s' (PEM_read_RSAPublicKey: %s)",
405  newname, CryptoLastErrorString());
406  fclose(fp);
407  return NULL;
408  }
409 
410  fclose(fp);
411 
412  {
413  const BIGNUM *n, *e;
414  RSA_get0_key(newkey, &n, &e, NULL);
415  if ((BN_num_bits(e) < 2) || (!BN_is_odd(e)))
416  {
417  Log(LOG_LEVEL_ERR, "RSA Exponent too small or not odd for key: %s",
418  newname);
419  RSA_free(newkey);
420  return NULL;
421  }
422  }
423 
424  return newkey;
425 }
426 
427 /*********************************************************************/
428 
429 bool SavePublicKey(const char *user, const char *digest, const RSA *key)
430 {
431  char keyname[CF_MAXVARSIZE], filename[CF_BUFSIZE];
432  struct stat statbuf;
433  int ret;
434 
435  ret = snprintf(keyname, sizeof(keyname), "%s-%s", user, digest);
436  if (ret >= sizeof(keyname))
437  {
438  Log(LOG_LEVEL_ERR, "USERNAME-KEY (%s-%s) string too long!",
439  user, digest);
440  return false;
441  }
442 
443  ret = snprintf(filename, sizeof(filename), "%s/ppkeys/%s.pub",
444  GetWorkDir(), keyname);
445  if (ret >= sizeof(filename))
446  {
447  Log(LOG_LEVEL_ERR, "Filename too long!");
448  return false;
449  }
450 
451  MapName(filename);
452  if (stat(filename, &statbuf) != -1)
453  {
455  "Public key file '%s' already exists, not rewriting",
456  filename);
457  return true;
458  }
459 
460  Log(LOG_LEVEL_VERBOSE, "Saving public key to file '%s'", filename);
461 
462  FILE *fp = safe_fopen_create_perms(filename, "w", CF_PERMS_DEFAULT);
463  if (fp == NULL)
464  {
465  Log(LOG_LEVEL_ERR, "Unable to write a public key '%s'. (fopen: %s)", filename, GetErrorStr());
466  return false;
467  }
468 
469  if (!PEM_write_RSAPublicKey(fp, key))
470  {
472  "Error saving public key to '%s'. (PEM_write_RSAPublicKey: %s)",
473  filename, CryptoLastErrorString());
474  fclose(fp);
475  return false;
476  }
477 
478  fclose(fp);
479  return true;
480 }
481 
482 RSA *LoadPublicKey(const char *filename)
483 {
484  FILE *fp;
485  RSA *key;
486  const BIGNUM *n, *e;
487 
488  fp = safe_fopen(filename, "r");
489  if (fp == NULL)
490  {
491  Log(LOG_LEVEL_ERR, "Cannot open public key file '%s' (fopen: %s)", filename, GetErrorStr());
492  return NULL;
493  };
494 
495  if ((key = PEM_read_RSAPublicKey(fp, NULL, NULL,
496  (void *)priv_passphrase)) == NULL)
497  {
499  "Error while reading public key '%s' (PEM_read_RSAPublicKey: %s)",
500  filename,
502  fclose(fp);
503  return NULL;
504  };
505 
506  fclose(fp);
507 
508  RSA_get0_key(key, &n, &e, NULL);
509 
510  if (BN_num_bits(e) < 2 || !BN_is_odd(e))
511  {
512  Log(LOG_LEVEL_ERR, "Error while reading public key '%s' - RSA Exponent is too small or not odd. (BN_num_bits: %s)",
513  filename, GetErrorStr());
514  return NULL;
515  };
516 
517  return key;
518 }
519 
520 /** Return a string with the printed digest of the given key file,
521  or NULL if an error occurred. */
522 char *LoadPubkeyDigest(const char *filename)
523 {
524  unsigned char digest[EVP_MAX_MD_SIZE + 1];
525  RSA *key = NULL;
526  char *buffer = xmalloc(CF_HOSTKEY_STRING_SIZE);
527 
528  key = LoadPublicKey(filename);
529  if (key == NULL)
530  {
531  return NULL;
532  }
533 
534  HashPubKey(key, digest, CF_DEFAULT_DIGEST);
536  digest, CF_DEFAULT_DIGEST, true);
537  RSA_free(key);
538  return buffer;
539 }
540 
541 /** Return a string with the printed digest of the given key file. */
542 char *GetPubkeyDigest(RSA *pubkey)
543 {
544  unsigned char digest[EVP_MAX_MD_SIZE + 1];
545  char *buffer = xmalloc(CF_HOSTKEY_STRING_SIZE);
546 
547  HashPubKey(pubkey, digest, CF_DEFAULT_DIGEST);
549  digest, CF_DEFAULT_DIGEST, true);
550  return buffer;
551 }
552 
553 
554 /**
555  * Trust the given key. If #ipaddress is not NULL, then also
556  * update the "last seen" database. The IP address is required for
557  * trusting a server key (on the client); it is -currently- optional
558  * for trusting a client key (on the server).
559  */
560 bool TrustKey(const char *filename, const char *ipaddress, const char *username)
561 {
562  RSA* key;
563  char *digest;
564 
565  key = LoadPublicKey(filename);
566  if (key == NULL)
567  {
568  return false;
569  }
570 
571  digest = GetPubkeyDigest(key);
572  if (digest == NULL)
573  {
574  RSA_free(key);
575  return false;
576  }
577 
578  if (ipaddress != NULL)
579  {
581  "Adding a CONNECT entry in lastseen db: IP '%s', key '%s'",
582  ipaddress, digest);
583  LastSaw1(ipaddress, digest, LAST_SEEN_ROLE_CONNECT);
584  }
585 
586  bool ret = SavePublicKey(username, digest, key);
587  RSA_free(key);
588  free(digest);
589 
590  return ret;
591 }
592 
593 int EncryptString(char *out, size_t out_size, const char *in, int plainlen,
594  char type, unsigned char *key)
595 {
596  int cipherlen = 0, tmplen;
597  unsigned char iv[32] =
598  { 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 };
599 
600  if (key == NULL)
601  ProgrammingError("EncryptString: session key == NULL");
602 
603  size_t max_ciphertext_size = CipherTextSizeMax(CfengineCipher(type), plainlen);
604 
605  if(max_ciphertext_size > out_size)
606  {
607  ProgrammingError("EncryptString: output buffer too small: max_ciphertext_size (%zd) > out_size (%zd)",
608  max_ciphertext_size, out_size);
609  }
610 
611  EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
612  EVP_EncryptInit_ex(ctx, CfengineCipher(type), NULL, key, iv);
613 
614  if (!EVP_EncryptUpdate(ctx, out, &cipherlen, in, plainlen))
615  {
616  EVP_CIPHER_CTX_free(ctx);
617  return -1;
618  }
619 
620  if (!EVP_EncryptFinal_ex(ctx, out + cipherlen, &tmplen))
621  {
622  EVP_CIPHER_CTX_free(ctx);
623  return -1;
624  }
625 
626  cipherlen += tmplen;
627 
628  if(cipherlen > max_ciphertext_size)
629  {
630  ProgrammingError("EncryptString: too large ciphertext written: cipherlen (%d) > max_ciphertext_size (%zd)",
631  cipherlen, max_ciphertext_size);
632  }
633 
634  EVP_CIPHER_CTX_free(ctx);
635  return cipherlen;
636 }
637 
638 size_t CipherBlockSizeBytes(const EVP_CIPHER *cipher)
639 {
640  return EVP_CIPHER_block_size(cipher);
641 }
642 
643 size_t CipherTextSizeMax(const EVP_CIPHER* cipher, size_t plaintext_size)
644 {
645  // see man EVP_DecryptUpdate() and EVP_DecryptFinal_ex()
646  size_t padding_size = (CipherBlockSizeBytes(cipher) * 2) - 1;
647 
648  // check for potential integer overflow, leave some buffer
649  if(plaintext_size > SIZE_MAX - padding_size)
650  {
651  ProgrammingError("CipherTextSizeMax: plaintext_size is too large (%zu)",
652  plaintext_size);
653  }
654 
655  return plaintext_size + padding_size;
656 }
657 
658 size_t PlainTextSizeMax(const EVP_CIPHER* cipher, size_t ciphertext_size)
659 {
660  // see man EVP_DecryptUpdate() and EVP_DecryptFinal_ex()
661  size_t padding_size = (CipherBlockSizeBytes(cipher) * 2);
662 
663  // check for potential integer overflow, leave some buffer
664  if(ciphertext_size > SIZE_MAX - padding_size)
665  {
666  ProgrammingError("PlainTextSizeMax: ciphertext_size is too large (%zu)",
667  ciphertext_size);
668  }
669 
670  return ciphertext_size + padding_size;
671 }
672 
673 /*********************************************************************/
674 
675 int DecryptString(char *out, size_t out_size, const char *in, int cipherlen,
676  char type, unsigned char *key)
677 {
678  int plainlen = 0, tmplen;
679  unsigned char iv[32] =
680  { 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 };
681 
682  if (key == NULL)
683  ProgrammingError("DecryptString: session key == NULL");
684 
685  size_t max_plaintext_size = PlainTextSizeMax(CfengineCipher(type), cipherlen);
686 
687  if(max_plaintext_size > out_size)
688  {
689  ProgrammingError("DecryptString: output buffer too small: max_plaintext_size (%zd) > out_size (%zd)",
690  max_plaintext_size, out_size);
691  }
692 
693  EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
694  EVP_DecryptInit_ex(ctx, CfengineCipher(type), NULL, key, iv);
695 
696  if (!EVP_DecryptUpdate(ctx, out, &plainlen, in, cipherlen))
697  {
698  Log(LOG_LEVEL_ERR, "Failed to decrypt string");
699  EVP_CIPHER_CTX_free(ctx);
700  return -1;
701  }
702 
703  if (!EVP_DecryptFinal_ex(ctx, out + plainlen, &tmplen))
704  {
705  unsigned long err = ERR_get_error();
706 
707  Log(LOG_LEVEL_ERR, "Failed to decrypt at final of cipher length %d. (EVP_DecryptFinal_ex: %s)", cipherlen, ERR_error_string(err, NULL));
708  EVP_CIPHER_CTX_free(ctx);
709  return -1;
710  }
711 
712  plainlen += tmplen;
713 
714  if(plainlen > max_plaintext_size)
715  {
716  ProgrammingError("DecryptString: too large plaintext written: plainlen (%d) > max_plaintext_size (%zd)",
717  plainlen, max_plaintext_size);
718  }
719 
720  EVP_CIPHER_CTX_free(ctx);
721  return plainlen;
722 }
723 
724 /*********************************************************************/
725 
726 void DebugBinOut(char *buffer, int len, char *comment)
727 {
728  unsigned char *sp;
729  char buf[CF_BUFSIZE];
730  char hexStr[3]; // one byte as hex
731 
732  if (len >= (sizeof(buf) / 2)) // hex uses two chars per byte
733  {
734  Log(LOG_LEVEL_DEBUG, "Debug binary print is too large (len = %d)", len);
735  return;
736  }
737 
738  memset(buf, 0, sizeof(buf));
739 
740  for (sp = buffer; sp < (unsigned char *) (buffer + len); sp++)
741  {
742  xsnprintf(hexStr, sizeof(hexStr), "%2.2x", (int) *sp);
743  strcat(buf, hexStr);
744  }
745 
746  Log(LOG_LEVEL_VERBOSE, "BinaryBuffer, %d bytes, comment '%s', buffer '%s'", len, comment, buf);
747 }
748 
749 char *PublicKeyFile(const char *workdir)
750 {
751  char *keyfile;
752  xasprintf(&keyfile,
753  "%s" FILE_SEPARATOR_STR "ppkeys" FILE_SEPARATOR_STR "localhost.pub", workdir);
754  return keyfile;
755 }
756 
757 char *PrivateKeyFile(const char *workdir)
758 {
759  char *keyfile;
760  xasprintf(&keyfile,
761  "%s" FILE_SEPARATOR_STR "ppkeys" FILE_SEPARATOR_STR "localhost.priv", workdir);
762  return keyfile;
763 }
764 
765 
766 /*********************************************************************
767  * Functions for threadsafe OpenSSL usage *
768  * Only pthread support - we don't create threads with any other API *
769  *********************************************************************/
770 
771 static pthread_mutex_t *cf_openssl_locks = NULL;
772 
773 
774 #ifndef __MINGW32__
775 #if OPENSSL_VERSION_NUMBER < 0x10100000
776 unsigned long ThreadId_callback(void)
777 {
778  return (unsigned long) pthread_self();
779 }
780 #endif
781 #endif
782 
783 #if OPENSSL_VERSION_NUMBER < 0x10100000
784 
785 static void OpenSSLLock_callback(int mode, int index, char *file, int line)
786 {
787  if (mode & CRYPTO_LOCK)
788  {
789  int ret = pthread_mutex_lock(&(cf_openssl_locks[index]));
790  if (ret != 0)
791  {
793  "OpenSSL locking failure at %s:%d! (pthread_mutex_lock: %s)",
794  file, line, GetErrorStrFromCode(ret));
795  }
796  }
797  else
798  {
799  int ret = pthread_mutex_unlock(&(cf_openssl_locks[index]));
800  if (ret != 0)
801  {
803  "OpenSSL locking failure at %s:%d! (pthread_mutex_unlock: %s)",
804  file, line, GetErrorStrFromCode(ret));
805  }
806  }
807 }
808 
809 #endif // Callback only for openssl < 1.1.0
810 
811 static void SetupOpenSSLThreadLocks(void)
812 {
813  const int num_locks = CRYPTO_num_locks();
814  assert(cf_openssl_locks == NULL);
815  cf_openssl_locks = xmalloc(num_locks * sizeof(*cf_openssl_locks));
816 
817  for (int i = 0; i < num_locks; i++)
818  {
819  pthread_mutexattr_t attr;
820  pthread_mutexattr_init(&attr);
821  int ret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
822  if (ret != 0)
823  {
825  "Failed to use error-checking mutexes for openssl,"
826  " falling back to normal ones (pthread_mutexattr_settype: %s)",
827  GetErrorStrFromCode(ret));
828  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
829  }
830  ret = pthread_mutex_init(&cf_openssl_locks[i], &attr);
831  if (ret != 0)
832  {
834  "Failed to use initialise mutexes for openssl"
835  " (pthread_mutex_init: %s)!",
836  GetErrorStrFromCode(ret));
837  }
838  pthread_mutexattr_destroy(&attr);
839  }
840 
841 #ifndef __MINGW32__
842  CRYPTO_set_id_callback((unsigned long (*)())ThreadId_callback);
843 #endif
844  // This is a no-op macro for OpenSSL >= 1.1.0
845  // The callback function is not used (or defined) then
846  CRYPTO_set_locking_callback((void (*)())OpenSSLLock_callback);
847 }
848 
849 static void CleanupOpenSSLThreadLocks(void)
850 {
851  const int numLocks = CRYPTO_num_locks();
852  CRYPTO_set_locking_callback(NULL);
853 #ifndef __MINGW32__
854  CRYPTO_set_id_callback(NULL);
855 #endif
856 
857  for (int i = 0; i < numLocks; i++)
858  {
859  pthread_mutex_destroy(&(cf_openssl_locks[i]));
860  }
861 
864 }
void * xmalloc(size_t size)
Definition: alloc-mini.c:46
int xasprintf(char **strp, const char *fmt,...)
Definition: alloc.c:71
#define DESTROY_AND_NULL(destroy, ptr)
Definition: alloc.h:42
bool GetAmPolicyHub(void)
Definition: bootstrap.c:191
HashMethod CF_DEFAULT_DIGEST
Definition: cf3globals.c:88
time_t CFSTARTTIME
Definition: cf3globals.c:99
void free(void *)
char VFQNAME[]
Definition: cf3globals.c:58
bool TrustKey(const char *filename, const char *ipaddress, const char *username)
Definition: crypto.c:560
static void SetupOpenSSLThreadLocks(void)
Definition: crypto.c:811
RSA * HavePublicKey(const char *username, const char *ipaddress, const char *digest)
Search for a key:
Definition: crypto.c:344
static const char *const pub_passphrase
Definition: crypto.c:336
void DebugBinOut(char *buffer, int len, char *comment)
Definition: crypto.c:726
const char * CryptoLastErrorString()
Definition: crypto.c:65
char * GetPubkeyDigest(RSA *pubkey)
Definition: crypto.c:542
char * PublicKeyFile(const char *workdir)
Definition: crypto.c:749
bool LoadSecretKeys(const char *const priv_key_path, const char *const pub_key_path, RSA **priv_key, RSA **pub_key)
Definition: crypto.c:170
RSA * LoadPublicKey(const char *filename)
Definition: crypto.c:482
unsigned long ThreadId_callback(void)
Definition: crypto.c:776
int EncryptString(char *out, size_t out_size, const char *in, int plainlen, char type, unsigned char *key)
Definition: crypto.c:593
RSA * HavePublicKeyByIP(const char *username, const char *ipaddress)
Search for a key given an IP address, by getting the key hash value from lastseen db.
Definition: crypto.c:323
size_t CipherTextSizeMax(const EVP_CIPHER *cipher, size_t plaintext_size)
Definition: crypto.c:643
bool SavePublicKey(const char *user, const char *digest, const RSA *key)
Definition: crypto.c:429
static bool crypto_initialized
Definition: crypto.c:63
static pthread_mutex_t * cf_openssl_locks
Definition: crypto.c:771
static const char priv_passphrase[]
Definition: crypto.c:159
static void OpenSSLLock_callback(int mode, int index, char *file, int line)
Definition: crypto.c:785
void CryptoInitialize()
Definition: crypto.c:71
void PolicyHubUpdateKeys(const char *policy_server)
Definition: crypto.c:276
static void CleanupOpenSSLThreadLocks(void)
Definition: crypto.c:849
void CryptoDeInitialize()
Definition: crypto.c:86
char * PrivateKeyFile(const char *workdir)
Definition: crypto.c:757
int DecryptString(char *out, size_t out_size, const char *in, int cipherlen, char type, unsigned char *key)
Definition: crypto.c:675
size_t CipherBlockSizeBytes(const EVP_CIPHER *cipher)
Definition: crypto.c:638
static void RandomSeed(void)
Definition: crypto.c:113
char * LoadPubkeyDigest(const char *filename)
Definition: crypto.c:522
size_t PlainTextSizeMax(const EVP_CIPHER *cipher, size_t ciphertext_size)
Definition: crypto.c:658
#define PRIVKEY_PASSPHRASE
Definition: crypto.h:37
#define CF_PERMS_DEFAULT
Definition: definitions.h:58
#define CF_BUFSIZE
Definition: definitions.h:50
#define CF_MAXVARSIZE
Definition: definitions.h:36
const EVP_CIPHER * CfengineCipher(char type)
FILE * safe_fopen_create_perms(const char *const path, const char *const mode, const mode_t create_perms)
Definition: file_lib.c:832
FILE * safe_fopen(const char *const path, const char *const mode)
Definition: file_lib.c:812
char * MapName(char *s)
Definition: file_lib.c:441
#define FILE_SEPARATOR_STR
Definition: file_lib.h:103
#define FILE_SEPARATOR
Definition: file_lib.h:102
int errno
#define NULL
Definition: getopt1.c:56
void HashPubKey(const RSA *const key, unsigned char digest[EVP_MAX_MD_SIZE+1], const HashMethod type)
Definition: hash.c:530
char * HashPrintSafe(char *dst, size_t dst_size, const unsigned char *digest, HashMethod type, bool use_prefix)
Definition: hash.c:612
#define CF_HOSTKEY_STRING_SIZE
Definition: hash.h:151
const char * GetWorkDir(void)
Definition: known_dirs.c:114
void LastSaw(const char *ipaddress, const char *digest, LastSeenRole role)
Definition: lastseen.c:90
void LastSaw1(const char *ipaddress, const char *hashstr, LastSeenRole role)
Same as LastSaw() but the digest parameter is the hash as a "SHA=..." string, to avoid converting twi...
Definition: lastseen.c:83
bool Address2Hostkey(char *dst, size_t dst_size, const char *address)
Definition: lastseen.c:196
@ LAST_SEEN_ROLE_CONNECT
Definition: lastseen.h:38
void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
const char * GetErrorStrFromCode(int error_code)
Definition: logging.c:270
const char * GetErrorStr(void)
Definition: logging.c:275
void Log(LogLevel level, const char *fmt,...)
Definition: logging.c:409
@ LOG_LEVEL_ERR
Definition: logging.h:42
@ LOG_LEVEL_DEBUG
Definition: logging.h:47
@ LOG_LEVEL_WARNING
Definition: logging.h:43
@ LOG_LEVEL_CRIT
Definition: logging.h:41
@ LOG_LEVEL_VERBOSE
Definition: logging.h:46
@ LOG_LEVEL_INFO
Definition: logging.h:45
void xsnprintf(char *str, size_t str_size, const char *format,...)
Definition: misc_lib.c:114
#define ProgrammingError(...)
Definition: misc_lib.h:33
bool LinkOrCopy(const char *from, const char *to, int sym)
Definition: patches.c:182
int chmod(const char *path, mode_t mode)
void srand48(long seed)
Definition: srand48.c:35
RSA * PRIVKEY
Definition: cf3globals.c:72
RSA * PUBKEY
Definition: tls_client.c:44