Wed Jan 8 2020 09:50:18

Asterisk developer's documentation


res_crypto.c File Reference

Provide Cryptographic Signature capability. More...

#include "asterisk.h"
#include "asterisk/paths.h"
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/aes.h>
#include <dirent.h>
#include "asterisk/module.h"
#include "asterisk/md5.h"
#include "asterisk/cli.h"
#include "asterisk/io.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/crypto.h"

Go to the source code of this file.

Data Structures

struct  ast_key
 
struct  keys
 

Macros

#define AST_API_MODULE
 
#define FORMAT   "%-18s %-8s %-16s %-33s\n"
 
#define KEY_NEEDS_PASSCODE   (1 << 16)
 

Functions

void AST_OPTIONAL_API_NAME() ast_aes_decrypt (const unsigned char *in, unsigned char *out, const ast_aes_decrypt_key *ctx)
 AES decrypt data. More...
 
void AST_OPTIONAL_API_NAME() ast_aes_encrypt (const unsigned char *in, unsigned char *out, const ast_aes_encrypt_key *ctx)
 AES encrypt data. More...
 
int AST_OPTIONAL_API_NAME() ast_aes_set_decrypt_key (const unsigned char *key, ast_aes_decrypt_key *ctx)
 Set a decryption key. More...
 
int AST_OPTIONAL_API_NAME() ast_aes_set_encrypt_key (const unsigned char *key, ast_aes_encrypt_key *ctx)
 Set an encryption key. More...
 
int AST_OPTIONAL_API_NAME() ast_check_signature (struct ast_key *key, const char *msg, const char *sig)
 base64 decode then sent to __ast_check_signature_bin More...
 
int AST_OPTIONAL_API_NAME() ast_check_signature_bin (struct ast_key *key, const char *msg, int msglen, const unsigned char *dsig)
 check signature of a message More...
 
int AST_OPTIONAL_API_NAME() ast_crypto_loaded (void)
 
int AST_OPTIONAL_API_NAME() ast_decrypt_bin (unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key)
 decrypt a message More...
 
int AST_OPTIONAL_API_NAME() ast_encrypt_bin (unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key)
 encrypt a message More...
 
struct ast_key
*AST_OPTIONAL_API_NAME() 
ast_key_get (const char *kname, int ktype)
 return the ast_key structure for name More...
 
int AST_OPTIONAL_API_NAME() ast_sign (struct ast_key *key, char *msg, char *sig)
 wrapper for __ast_sign_bin then base64 encode it More...
 
int AST_OPTIONAL_API_NAME() ast_sign_bin (struct ast_key *key, const char *msg, int msglen, unsigned char *dsig)
 signs outgoing message with public key More...
 
static int crypto_init (void)
 initialise the res_crypto module More...
 
static void crypto_load (int ifd, int ofd)
 refresh RSA keys from file More...
 
static char * handle_cli_keys_init (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 initialize all RSA keys More...
 
static char * handle_cli_keys_show (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 show the list of RSA keys More...
 
static int load_module (void)
 
static void md52sum (char *sum, unsigned char *md5)
 
static int pw_cb (char *buf, int size, int rwflag, void *userdata)
 setting of priv key More...
 
static int reload (void)
 
static struct ast_keytry_load_key (const char *dir, const char *fname, int ifd, int ofd, int *not2)
 load RSA key from file More...
 
static int unload_module (void)
 

Variables

static struct ast_cli_entry cli_crypto []
 
static struct keys keys = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 } , }
 

Detailed Description

Provide Cryptographic Signature capability.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m
ExtRef:
Uses the OpenSSL library, available at http://www.openssl.org/

Definition in file res_crypto.c.

Macro Definition Documentation

#define AST_API_MODULE

Definition at line 51 of file res_crypto.c.

#define FORMAT   "%-18s %-8s %-16s %-33s\n"

Referenced by handle_cli_keys_show().

#define KEY_NEEDS_PASSCODE   (1 << 16)

Definition at line 67 of file res_crypto.c.

Referenced by handle_cli_keys_init(), handle_cli_keys_show(), and try_load_key().

Function Documentation

void AST_OPTIONAL_API_NAME() ast_aes_decrypt ( const unsigned char *  in,
unsigned char *  out,
const ast_aes_decrypt_key ctx 
)

AES decrypt data.

Parameters
inencrypted data
outpointer to a buffer to hold the decrypted output
ctxaddress of an aes encryption context filled in with ast_aes_set_decrypt_key

Definition at line 476 of file res_crypto.c.

Referenced by aes_helper(), decrypt_memcpy(), and memcpy_decrypt().

477 {
478  return AES_decrypt(in, out, ctx);
479 }
void AST_OPTIONAL_API_NAME() ast_aes_encrypt ( const unsigned char *  in,
unsigned char *  out,
const ast_aes_encrypt_key ctx 
)

AES encrypt data.

Parameters
indata to be encrypted
outpointer to a buffer to hold the encrypted output
ctxaddress of an aes encryption context filled in with ast_aes_set_encrypt_key

Definition at line 471 of file res_crypto.c.

Referenced by aes_helper(), encrypt_memcpy(), and memcpy_encrypt().

472 {
473  return AES_encrypt(in, out, ctx);
474 }
int AST_OPTIONAL_API_NAME() ast_aes_set_decrypt_key ( const unsigned char *  key,
ast_aes_decrypt_key ctx 
)

Set a decryption key.

Parameters
keya 16 char key
ctxaddress of an aes encryption context
Return values
0success
nonzerofailure

Definition at line 466 of file res_crypto.c.

Referenced by aes_helper(), build_ecx_key(), build_encryption_keys(), check_key(), socket_process(), and update_key().

467 {
468  return AES_set_decrypt_key(key, 128, ctx);
469 }
int AST_OPTIONAL_API_NAME() ast_aes_set_encrypt_key ( const unsigned char *  key,
ast_aes_encrypt_key ctx 
)

Set an encryption key.

Parameters
keya 16 char key
ctxaddress of an aes encryption context
Return values
0success
nonzerofailure

Definition at line 461 of file res_crypto.c.

Referenced by aes_helper(), build_ecx_key(), check_key(), and update_key().

462 {
463  return AES_set_encrypt_key(key, 128, ctx);
464 }
int AST_OPTIONAL_API_NAME() ast_check_signature ( struct ast_key key,
const char *  msg,
const char *  sig 
)

base64 decode then sent to __ast_check_signature_bin

Check the authenticity of a message signature using a given public key.

See Also
ast_check_signature

Definition at line 440 of file res_crypto.c.

References ast_base64decode(), ast_check_signature_bin(), ast_log(), and LOG_WARNING.

Referenced by authenticate_verify(), and register_verify().

441 {
442  unsigned char dsig[128];
443  int res;
444 
445  /* Decode signature */
446  if ((res = ast_base64decode(dsig, sig, sizeof(dsig))) != sizeof(dsig)) {
447  ast_log(LOG_WARNING, "Signature improper length (expect %d, got %d)\n", (int)sizeof(dsig), (int)res);
448  return -1;
449  }
450 
451  res = ast_check_signature_bin(key, msg, strlen(msg), dsig);
452 
453  return res;
454 }
int ast_check_signature_bin(struct ast_key *key, const char *msg, int msglen, const unsigned char *sig)
Check the authenticity of a message signature using a given public key.
Definition: res_crypto.c:411
#define LOG_WARNING
Definition: logger.h:144
int ast_base64decode(unsigned char *dst, const char *src, int max)
Decode data from base64.
Definition: utils.c:279
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int AST_OPTIONAL_API_NAME() ast_check_signature_bin ( struct ast_key key,
const char *  msg,
int  msglen,
const unsigned char *  dsig 
)

check signature of a message

Check the authenticity of a message signature using a given public key.

See Also
ast_check_signature_bin

Definition at line 411 of file res_crypto.c.

References ast_debug, AST_KEY_PUBLIC, ast_log(), ast_key::digest, LOG_WARNING, and SHA1.

Referenced by ast_check_signature(), and check_key().

412 {
413  unsigned char digest[20];
414  int res;
415 
416  if (key->ktype != AST_KEY_PUBLIC) {
417  /* Okay, so of course you really *can* but for our purposes
418  we're going to say you can't */
419  ast_log(LOG_WARNING, "Cannot check message signature with a private key\n");
420  return -1;
421  }
422 
423  /* Calculate digest of message */
424  SHA1((unsigned char *)msg, msglen, digest);
425 
426  /* Verify signature */
427  if (!(res = RSA_verify(NID_sha1, digest, sizeof(digest), (unsigned char *)dsig, 128, key->rsa))) {
428  ast_debug(1, "Key failed verification: %s\n", key->name);
429  return -1;
430  }
431 
432  /* Pass */
433  return 0;
434 }
RSA * rsa
Definition: res_crypto.c:77
int ktype
Definition: res_crypto.c:75
#define LOG_WARNING
Definition: logger.h:144
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
char name[80]
Definition: res_crypto.c:71
Definition: sha1.h:122
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define AST_KEY_PUBLIC
Definition: crypto.h:42
int AST_OPTIONAL_API_NAME() ast_crypto_loaded ( void  )

Definition at line 456 of file res_crypto.c.

457 {
458  return 1;
459 }
int AST_OPTIONAL_API_NAME() ast_decrypt_bin ( unsigned char *  dst,
const unsigned char *  src,
int  srclen,
struct ast_key key 
)

decrypt a message

Decrypt a message using a given private key.

See Also
ast_decrypt_bin

Definition at line 331 of file res_crypto.c.

References AST_KEY_PRIVATE, ast_log(), LOG_NOTICE, and LOG_WARNING.

Referenced by check_key().

332 {
333  int res, pos = 0;
334 
335  if (key->ktype != AST_KEY_PRIVATE) {
336  ast_log(LOG_WARNING, "Cannot decrypt with a public key\n");
337  return -1;
338  }
339 
340  if (srclen % 128) {
341  ast_log(LOG_NOTICE, "Tried to decrypt something not a multiple of 128 bytes\n");
342  return -1;
343  }
344 
345  while (srclen) {
346  /* Process chunks 128 bytes at a time */
347  if ((res = RSA_private_decrypt(128, src, dst, key->rsa, RSA_PKCS1_OAEP_PADDING)) < 0) {
348  return -1;
349  }
350  pos += res;
351  src += 128;
352  srclen -= 128;
353  dst += res;
354  }
355 
356  return pos;
357 }
RSA * rsa
Definition: res_crypto.c:77
int ktype
Definition: res_crypto.c:75
#define LOG_WARNING
Definition: logger.h:144
#define AST_KEY_PRIVATE
Definition: crypto.h:43
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
int AST_OPTIONAL_API_NAME() ast_encrypt_bin ( unsigned char *  dst,
const unsigned char *  src,
int  srclen,
struct ast_key key 
)

encrypt a message

Encrypt a message using a given private key.

See Also
ast_encrypt_bin

Definition at line 363 of file res_crypto.c.

References AST_KEY_PUBLIC, ast_log(), LOG_NOTICE, and LOG_WARNING.

Referenced by update_key().

364 {
365  int res, bytes, pos = 0;
366 
367  if (key->ktype != AST_KEY_PUBLIC) {
368  ast_log(LOG_WARNING, "Cannot encrypt with a private key\n");
369  return -1;
370  }
371 
372  while (srclen) {
373  bytes = srclen;
374  if (bytes > 128 - 41) {
375  bytes = 128 - 41;
376  }
377  /* Process chunks 128-41 bytes at a time */
378  if ((res = RSA_public_encrypt(bytes, src, dst, key->rsa, RSA_PKCS1_OAEP_PADDING)) != 128) {
379  ast_log(LOG_NOTICE, "How odd, encrypted size is %d\n", res);
380  return -1;
381  }
382  src += bytes;
383  srclen -= bytes;
384  pos += res;
385  dst += res;
386  }
387  return pos;
388 }
RSA * rsa
Definition: res_crypto.c:77
int ktype
Definition: res_crypto.c:75
#define LOG_WARNING
Definition: logger.h:144
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
#define AST_KEY_PUBLIC
Definition: crypto.h:42
struct ast_key* AST_OPTIONAL_API_NAME() ast_key_get ( const char *  kname,
int  ktype 
)

return the ast_key structure for name

Retrieve a key.

See Also
ast_key_get

Definition at line 136 of file res_crypto.c.

References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_key::ktype, and ast_key::name.

Referenced by authenticate(), authenticate_verify(), check_key(), register_verify(), and update_key().

137 {
138  struct ast_key *key;
139 
141  AST_RWLIST_TRAVERSE(&keys, key, list) {
142  if (!strcmp(kname, key->name) &&
143  (ktype == key->ktype)) {
144  break;
145  }
146  }
148 
149  return key;
150 }
int ktype
Definition: res_crypto.c:75
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
char name[80]
Definition: res_crypto.c:71
int AST_OPTIONAL_API_NAME() ast_sign ( struct ast_key key,
char *  msg,
char *  sig 
)

wrapper for __ast_sign_bin then base64 encode it

Sign a message signature using a given private key.

See Also
ast_sign

Definition at line 394 of file res_crypto.c.

References ast_base64encode(), and ast_sign_bin().

Referenced by authenticate().

395 {
396  unsigned char dsig[128];
397  int siglen = sizeof(dsig), res;
398 
399  if (!(res = ast_sign_bin(key, msg, strlen(msg), dsig))) {
400  /* Success -- encode (256 bytes max as documented) */
401  ast_base64encode(sig, dsig, siglen, 256);
402  }
403 
404  return res;
405 }
int ast_sign_bin(struct ast_key *key, const char *msg, int msglen, unsigned char *sig)
Sign a message signature using a given private key.
Definition: res_crypto.c:299
int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
Encode data in base64.
Definition: utils.c:357
int AST_OPTIONAL_API_NAME() ast_sign_bin ( struct ast_key key,
const char *  msg,
int  msglen,
unsigned char *  dsig 
)

signs outgoing message with public key

Sign a message signature using a given private key.

See Also
ast_sign_bin

Definition at line 299 of file res_crypto.c.

References AST_KEY_PRIVATE, ast_log(), ast_key::digest, LOG_WARNING, and SHA1.

Referenced by ast_sign(), and update_key().

300 {
301  unsigned char digest[20];
302  unsigned int siglen = 128;
303  int res;
304 
305  if (key->ktype != AST_KEY_PRIVATE) {
306  ast_log(LOG_WARNING, "Cannot sign with a public key\n");
307  return -1;
308  }
309 
310  /* Calculate digest of message */
311  SHA1((unsigned char *)msg, msglen, digest);
312 
313  /* Verify signature */
314  if (!(res = RSA_sign(NID_sha1, digest, sizeof(digest), dsig, &siglen, key->rsa))) {
315  ast_log(LOG_WARNING, "RSA Signature (key %s) failed\n", key->name);
316  return -1;
317  }
318 
319  if (siglen != 128) {
320  ast_log(LOG_WARNING, "Unexpected signature length %d, expecting %d\n", (int)siglen, (int)128);
321  return -1;
322  }
323 
324  return 0;
325 }
RSA * rsa
Definition: res_crypto.c:77
int ktype
Definition: res_crypto.c:75
#define LOG_WARNING
Definition: logger.h:144
#define AST_KEY_PRIVATE
Definition: crypto.h:43
char name[80]
Definition: res_crypto.c:71
Definition: sha1.h:122
unsigned char digest[16]
Definition: res_crypto.c:85
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static int crypto_init ( void  )
static

initialise the res_crypto module

Definition at line 635 of file res_crypto.c.

References ARRAY_LEN, ast_cli_register_multiple(), and cli_crypto.

Referenced by load_module().

636 {
638  return 0;
639 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static struct ast_cli_entry cli_crypto[]
Definition: res_crypto.c:629
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
Definition: cli.c:2167
static void crypto_load ( int  ifd,
int  ofd 
)
static

refresh RSA keys from file

Parameters
ifdfile descriptor
ofdfile descriptor
Returns
void

Definition at line 487 of file res_crypto.c.

References ast_config_AST_KEY_DIR, ast_debug, ast_free, ast_log(), AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_key::delme, ast_key::ktype, LOG_NOTICE, LOG_WARNING, ast_key::name, ast_key::rsa, and try_load_key().

Referenced by load_module(), and reload().

488 {
489  struct ast_key *key;
490  DIR *dir = NULL;
491  struct dirent *ent;
492  int note = 0;
493 
495 
496  /* Mark all keys for deletion */
497  AST_RWLIST_TRAVERSE(&keys, key, list) {
498  key->delme = 1;
499  }
500 
501  /* Load new keys */
502  if ((dir = opendir(ast_config_AST_KEY_DIR))) {
503  while ((ent = readdir(dir))) {
504  try_load_key(ast_config_AST_KEY_DIR, ent->d_name, ifd, ofd, &note);
505  }
506  closedir(dir);
507  } else {
508  ast_log(LOG_WARNING, "Unable to open key directory '%s'\n", ast_config_AST_KEY_DIR);
509  }
510 
511  if (note) {
512  ast_log(LOG_NOTICE, "Please run the command 'keys init' to enter the passcodes for the keys\n");
513  }
514 
515  /* Delete any keys that are no longer present */
516  AST_RWLIST_TRAVERSE_SAFE_BEGIN(&keys, key, list) {
517  if (key->delme) {
518  ast_debug(1, "Deleting key %s type %d\n", key->name, key->ktype);
520  if (key->rsa) {
521  RSA_free(key->rsa);
522  }
523  ast_free(key);
524  }
525  }
527 
529 }
const char * ast_config_AST_KEY_DIR
Definition: asterisk.c:265
RSA * rsa
Definition: res_crypto.c:77
int ktype
Definition: res_crypto.c:75
static struct ast_key * try_load_key(const char *dir, const char *fname, int ifd, int ofd, int *not2)
load RSA key from file
Definition: res_crypto.c:162
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define LOG_WARNING
Definition: logger.h:144
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:565
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:542
char name[80]
Definition: res_crypto.c:71
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
#define ast_free(a)
Definition: astmm.h:97
int delme
Definition: res_crypto.c:79
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:602
static char* handle_cli_keys_init ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

initialize all RSA keys

Parameters
eCLI command
cmd
alist of CLI arguments
Returns
CLI_SUCCESS

Definition at line 592 of file res_crypto.c.

References ast_cli_args::argc, ast_config_AST_KEY_DIR, ast_copy_string(), AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_key::fn, KEY_NEEDS_PASSCODE, ast_key::ktype, try_load_key(), and ast_cli_entry::usage.

593 {
594  struct ast_key *key;
595  int ign;
596  char *kn, tmp[256] = "";
597 
598  switch (cmd) {
599  case CLI_INIT:
600  e->command = "keys init";
601  e->usage =
602  "Usage: keys init\n"
603  " Initializes private keys (by reading in pass code from\n"
604  " the user)\n";
605  return NULL;
606  case CLI_GENERATE:
607  return NULL;
608  }
609 
610  if (a->argc != 2) {
611  return CLI_SHOWUSAGE;
612  }
613 
615  AST_RWLIST_TRAVERSE_SAFE_BEGIN(&keys, key, list) {
616  /* Reload keys that need pass codes now */
617  if (key->ktype & KEY_NEEDS_PASSCODE) {
618  kn = key->fn + strlen(ast_config_AST_KEY_DIR) + 1;
619  ast_copy_string(tmp, kn, sizeof(tmp));
620  try_load_key(ast_config_AST_KEY_DIR, tmp, a->fd, a->fd, &ign);
621  }
622  }
625 
626  return CLI_SUCCESS;
627 }
const char * ast_config_AST_KEY_DIR
Definition: asterisk.c:265
int ktype
Definition: res_crypto.c:75
static struct ast_key * try_load_key(const char *dir, const char *fname, int ifd, int ofd, int *not2)
load RSA key from file
Definition: res_crypto.c:162
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
const int argc
Definition: cli.h:154
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
Definition: cli.h:146
const int fd
Definition: cli.h:153
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:542
#define CLI_SHOWUSAGE
Definition: cli.h:44
#define KEY_NEEDS_PASSCODE
Definition: res_crypto.c:67
char fn[256]
Definition: res_crypto.c:73
char * command
Definition: cli.h:180
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:602
static char* handle_cli_keys_show ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

show the list of RSA keys

Parameters
eCLI command
cmd
alist of CLI arguments
Returns
CLI_SUCCESS

Definition at line 546 of file res_crypto.c.

References ast_cli(), AST_KEY_PUBLIC, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_key::digest, ast_cli_args::fd, FORMAT, KEY_NEEDS_PASSCODE, ast_key::ktype, md52sum(), ast_key::name, and ast_cli_entry::usage.

547 {
548 #define FORMAT "%-18s %-8s %-16s %-33s\n"
549 
550  struct ast_key *key;
551  char sum[16 * 2 + 1];
552  int count_keys = 0;
553 
554  switch (cmd) {
555  case CLI_INIT:
556  e->command = "keys show";
557  e->usage =
558  "Usage: keys show\n"
559  " Displays information about RSA keys known by Asterisk\n";
560  return NULL;
561  case CLI_GENERATE:
562  return NULL;
563  }
564 
565  ast_cli(a->fd, FORMAT, "Key Name", "Type", "Status", "Sum");
566  ast_cli(a->fd, FORMAT, "------------------", "--------", "----------------", "--------------------------------");
567 
569  AST_RWLIST_TRAVERSE(&keys, key, list) {
570  md52sum(sum, key->digest);
571  ast_cli(a->fd, FORMAT, key->name,
572  (key->ktype & 0xf) == AST_KEY_PUBLIC ? "PUBLIC" : "PRIVATE",
573  key->ktype & KEY_NEEDS_PASSCODE ? "[Needs Passcode]" : "[Loaded]", sum);
574  count_keys++;
575  }
577 
578  ast_cli(a->fd, "\n%d known RSA keys.\n", count_keys);
579 
580  return CLI_SUCCESS;
581 
582 #undef FORMAT
583 }
int ktype
Definition: res_crypto.c:75
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
Definition: cli.h:146
#define FORMAT
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
const int fd
Definition: cli.h:153
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
char name[80]
Definition: res_crypto.c:71
unsigned char digest[16]
Definition: res_crypto.c:85
#define KEY_NEEDS_PASSCODE
Definition: res_crypto.c:67
static void md52sum(char *sum, unsigned char *md5)
Definition: res_crypto.c:531
char * command
Definition: cli.h:180
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
#define AST_KEY_PUBLIC
Definition: crypto.h:42
static int load_module ( void  )
static

Definition at line 647 of file res_crypto.c.

References AST_MODULE_LOAD_SUCCESS, ast_opt_init_keys, crypto_init(), and crypto_load().

648 {
649  crypto_init();
650  if (ast_opt_init_keys) {
651  crypto_load(STDIN_FILENO, STDOUT_FILENO);
652  } else {
653  crypto_load(-1, -1);
654  }
656 }
#define ast_opt_init_keys
Definition: options.h:109
static void crypto_load(int ifd, int ofd)
refresh RSA keys from file
Definition: res_crypto.c:487
static int crypto_init(void)
initialise the res_crypto module
Definition: res_crypto.c:635
static void md52sum ( char *  sum,
unsigned char *  md5 
)
static

Definition at line 531 of file res_crypto.c.

Referenced by handle_cli_keys_show().

532 {
533  int x;
534  for (x = 0; x < 16; x++) {
535  sum += sprintf(sum, "%02x", (unsigned)*(md5++));
536  }
537 }
static int md5(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_md5.c:54
static int pw_cb ( char *  buf,
int  size,
int  rwflag,
void *  userdata 
)
static

setting of priv key

Parameters
buf
size
rwflag
userdata
Returns
length of string,-1 on failure

Definition at line 99 of file res_crypto.c.

References ast_hide_password(), AST_KEY_PRIVATE, ast_log(), ast_restore_tty(), errno, ast_key::infd, ast_key::ktype, LOG_WARNING, ast_key::name, ast_key::outfd, and prompt.

Referenced by try_load_key().

100 {
101  struct ast_key *key = (struct ast_key *)userdata;
102  char prompt[256];
103  int tmp;
104  int res;
105 
106  if (key->infd < 0) {
107  /* Note that we were at least called */
108  key->infd = -2;
109  return -1;
110  }
111 
112  snprintf(prompt, sizeof(prompt), ">>>> passcode for %s key '%s': ",
113  key->ktype == AST_KEY_PRIVATE ? "PRIVATE" : "PUBLIC", key->name);
114  if (write(key->outfd, prompt, strlen(prompt)) < 0) {
115  ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
116  key->infd = -2;
117  return -1;
118  }
119  tmp = ast_hide_password(key->infd);
120  memset(buf, 0, size);
121  res = read(key->infd, buf, size);
122  if (res == -1) {
123  ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
124  }
125  ast_restore_tty(key->infd, tmp);
126  if (buf[strlen(buf) -1] == '\n') {
127  buf[strlen(buf) - 1] = '\0';
128  }
129  return strlen(buf);
130 }
int ktype
Definition: res_crypto.c:75
#define LOG_WARNING
Definition: logger.h:144
int ast_hide_password(int fd)
Definition: io.c:332
int ast_restore_tty(int fd, int oldstatus)
Restores TTY mode. Call with result from previous ast_hide_password.
Definition: io.c:351
int outfd
Definition: res_crypto.c:83
#define AST_KEY_PRIVATE
Definition: crypto.h:43
char name[80]
Definition: res_crypto.c:71
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int infd
Definition: res_crypto.c:81
int errno
static struct ast_str * prompt
Definition: asterisk.c:2395
static int reload ( void  )
static

Definition at line 641 of file res_crypto.c.

References crypto_load().

642 {
643  crypto_load(-1, -1);
644  return 0;
645 }
static void crypto_load(int ifd, int ofd)
refresh RSA keys from file
Definition: res_crypto.c:487
static struct ast_key* try_load_key ( const char *  dir,
const char *  fname,
int  ifd,
int  ofd,
int *  not2 
)
static

load RSA key from file

Parameters
dirdirectory string
fnamename of file
ifdincoming file descriptor
ofdoutgoing file descriptor
not2
Return values
keyon success.
NULLon failure.

Definition at line 162 of file res_crypto.c.

References ast_calloc, ast_copy_string(), ast_debug, AST_KEY_PRIVATE, AST_KEY_PUBLIC, ast_log(), ast_opt_init_keys, AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, ast_verb, ast_key::delme, ast_key::digest, errno, f, ast_key::fn, ast_key::infd, KEY_NEEDS_PASSCODE, ast_key::ktype, LOG_NOTICE, LOG_WARNING, MD5Final(), MD5Init(), MD5Update(), ast_key::name, ast_key::outfd, pw_cb(), and ast_key::rsa.

Referenced by crypto_load(), and handle_cli_keys_init().

163 {
164  int ktype = 0, found = 0;
165  char *c = NULL, ffname[256];
166  unsigned char digest[16];
167  FILE *f;
168  struct MD5Context md5;
169  struct ast_key *key;
170  static int notice = 0;
171 
172  /* Make sure its name is a public or private key */
173  if ((c = strstr(fname, ".pub")) && !strcmp(c, ".pub")) {
174  ktype = AST_KEY_PUBLIC;
175  } else if ((c = strstr(fname, ".key")) && !strcmp(c, ".key")) {
176  ktype = AST_KEY_PRIVATE;
177  } else {
178  return NULL;
179  }
180 
181  /* Get actual filename */
182  snprintf(ffname, sizeof(ffname), "%s/%s", dir, fname);
183 
184  /* Open file */
185  if (!(f = fopen(ffname, "r"))) {
186  ast_log(LOG_WARNING, "Unable to open key file %s: %s\n", ffname, strerror(errno));
187  return NULL;
188  }
189 
190  MD5Init(&md5);
191  while (!feof(f)) {
192  /* Calculate a "whatever" quality md5sum of the key */
193  char buf[256] = "";
194  if (!fgets(buf, sizeof(buf), f)) {
195  continue;
196  }
197  if (!feof(f)) {
198  MD5Update(&md5, (unsigned char *) buf, strlen(buf));
199  }
200  }
201  MD5Final(digest, &md5);
202 
203  /* Look for an existing key */
204  AST_RWLIST_TRAVERSE(&keys, key, list) {
205  if (!strcasecmp(key->fn, ffname)) {
206  break;
207  }
208  }
209 
210  if (key) {
211  /* If the MD5 sum is the same, and it isn't awaiting a passcode
212  then this is far enough */
213  if (!memcmp(digest, key->digest, 16) &&
214  !(key->ktype & KEY_NEEDS_PASSCODE)) {
215  fclose(f);
216  key->delme = 0;
217  return NULL;
218  } else {
219  /* Preserve keytype */
220  ktype = key->ktype;
221  /* Recycle the same structure */
222  found++;
223  }
224  }
225 
226  /* Make fname just be the normal name now */
227  *c = '\0';
228  if (!key) {
229  if (!(key = ast_calloc(1, sizeof(*key)))) {
230  fclose(f);
231  return NULL;
232  }
233  }
234  /* First the filename */
235  ast_copy_string(key->fn, ffname, sizeof(key->fn));
236  /* Then the name */
237  ast_copy_string(key->name, fname, sizeof(key->name));
238  key->ktype = ktype;
239  /* Yes, assume we're going to be deleted */
240  key->delme = 1;
241  /* Keep the key type */
242  memcpy(key->digest, digest, 16);
243  /* Can I/O takes the FD we're given */
244  key->infd = ifd;
245  key->outfd = ofd;
246  /* Reset the file back to the beginning */
247  rewind(f);
248  /* Now load the key with the right method */
249  if (ktype == AST_KEY_PUBLIC) {
250  key->rsa = PEM_read_RSA_PUBKEY(f, NULL, pw_cb, key);
251  } else {
252  key->rsa = PEM_read_RSAPrivateKey(f, NULL, pw_cb, key);
253  }
254  fclose(f);
255  if (key->rsa) {
256  if (RSA_size(key->rsa) == 128) {
257  /* Key loaded okay */
258  key->ktype &= ~KEY_NEEDS_PASSCODE;
259  ast_verb(3, "Loaded %s key '%s'\n", key->ktype == AST_KEY_PUBLIC ? "PUBLIC" : "PRIVATE", key->name);
260  ast_debug(1, "Key '%s' loaded OK\n", key->name);
261  key->delme = 0;
262  } else {
263  ast_log(LOG_NOTICE, "Key '%s' is not expected size.\n", key->name);
264  }
265  } else if (key->infd != -2) {
266  ast_log(LOG_WARNING, "Key load %s '%s' failed\n",key->ktype == AST_KEY_PUBLIC ? "PUBLIC" : "PRIVATE", key->name);
267  if (ofd > -1) {
268  ERR_print_errors_fp(stderr);
269  } else {
270  ERR_print_errors_fp(stderr);
271  }
272  } else {
273  ast_log(LOG_NOTICE, "Key '%s' needs passcode.\n", key->name);
274  key->ktype |= KEY_NEEDS_PASSCODE;
275  if (!notice) {
276  if (!ast_opt_init_keys) {
277  ast_log(LOG_NOTICE, "Add the '-i' flag to the asterisk command line if you want to automatically initialize passcodes at launch.\n");
278  }
279  notice++;
280  }
281  /* Keep it anyway */
282  key->delme = 0;
283  /* Print final notice about "keys init" when done */
284  *not2 = 1;
285  }
286 
287  /* If this is a new key add it to the list */
288  if (!found) {
289  AST_RWLIST_INSERT_TAIL(&keys, key, list);
290  }
291 
292  return key;
293 }
RSA * rsa
Definition: res_crypto.c:77
int ktype
Definition: res_crypto.c:75
#define LOG_WARNING
Definition: logger.h:144
void MD5Final(unsigned char digest[16], struct MD5Context *context)
Definition: md5.c:122
#define ast_opt_init_keys
Definition: options.h:109
#define ast_verb(level,...)
Definition: logger.h:243
void MD5Init(struct MD5Context *context)
Definition: md5.c:59
int outfd
Definition: res_crypto.c:83
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
#define AST_KEY_PRIVATE
Definition: crypto.h:43
void MD5Update(struct MD5Context *context, unsigned char const *buf, unsigned len)
Definition: md5.c:74
char name[80]
Definition: res_crypto.c:71
static int md5(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_md5.c:54
unsigned char digest[16]
Definition: res_crypto.c:85
#define KEY_NEEDS_PASSCODE
Definition: res_crypto.c:67
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
int infd
Definition: res_crypto.c:81
int errno
char fn[256]
Definition: res_crypto.c:73
int delme
Definition: res_crypto.c:79
static struct ast_format f[]
Definition: format_g726.c:181
Definition: md5.h:26
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:726
#define ast_calloc(a, b)
Definition: astmm.h:82
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static int pw_cb(char *buf, int size, int rwflag, void *userdata)
setting of priv key
Definition: res_crypto.c:99
#define AST_KEY_PUBLIC
Definition: crypto.h:42
static int unload_module ( void  )
static

Definition at line 658 of file res_crypto.c.

659 {
660  /* Can't unload this once we're loaded */
661  return -1;
662 }

Variable Documentation

struct ast_cli_entry cli_crypto[]
static
Initial value:
= {
AST_CLI_DEFINE(handle_cli_keys_show, "Displays RSA key information"),
AST_CLI_DEFINE(handle_cli_keys_init, "Initialize RSA key passcodes")
}
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:191
static char * handle_cli_keys_init(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
initialize all RSA keys
Definition: res_crypto.c:592
static char * handle_cli_keys_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
show the list of RSA keys
Definition: res_crypto.c:546

Definition at line 629 of file res_crypto.c.

Referenced by crypto_init().

struct keys keys = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 } , }
static

Referenced by misdn_set_opt_exec().