Sat Mar 10 01:55:40 2012

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

Defines

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

Functions

static void __reg_module (void)
static void __unreg_module (void)
void AST_OPTIONAL_API_NAME() ast_aes_decrypt (const unsigned char *in, unsigned char *out, const ast_aes_decrypt_key *ctx)
 AES decrypt data.
void AST_OPTIONAL_API_NAME() ast_aes_encrypt (const unsigned char *in, unsigned char *out, const ast_aes_encrypt_key *ctx)
 AES encrypt data.
int AST_OPTIONAL_API_NAME() ast_aes_set_decrypt_key (const unsigned char *key, ast_aes_decrypt_key *ctx)
 Set a decryption key.
int AST_OPTIONAL_API_NAME() ast_aes_set_encrypt_key (const unsigned char *key, ast_aes_encrypt_key *ctx)
 Set an encryption key.
int AST_OPTIONAL_API_NAME() ast_check_signature (struct ast_key *key, const char *msg, const char *sig)
 Check the authenticity of a message signature using a given public key.
int AST_OPTIONAL_API_NAME() ast_check_signature_bin (struct ast_key *key, const char *msg, int msglen, const unsigned char *dsig)
 Check the authenticity of a message signature using a given public key.
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 using a given private key.
int AST_OPTIONAL_API_NAME() ast_encrypt_bin (unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key)
 Encrypt a message using a given private key.
ast_key *AST_OPTIONAL_API_NAME() ast_key_get (const char *kname, int ktype)
 Retrieve a key.
int AST_OPTIONAL_API_NAME() ast_sign (struct ast_key *key, char *msg, char *sig)
 Sign a message signature using a given private key.
int AST_OPTIONAL_API_NAME() ast_sign_bin (struct ast_key *key, const char *msg, int msglen, unsigned char *dsig)
 Sign a message signature using a given private key.
static int crypto_init (void)
 initialise the res_crypto module
static void crypto_load (int ifd, int ofd)
 refresh RSA keys from file
static char * handle_cli_keys_init (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 initialize all RSA keys
static char * handle_cli_keys_show (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 show the list of RSA keys
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
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
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Cryptographic Digital Signatures" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DEPEND, }
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_cli_entry cli_crypto []


Detailed Description

Provide Cryptographic Signature capability.

Author:
Mark Spencer <markster@digium.com>
ExtRef:
Uses the OpenSSL library, available at http://www.openssl.org/

Definition in file res_crypto.c.


Define Documentation

#define AST_API_MODULE

Definition at line 51 of file res_crypto.c.

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

#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

static void __reg_module ( void   )  [static]

Definition at line 671 of file res_crypto.c.

static void __unreg_module ( void   )  [static]

Definition at line 671 of file res_crypto.c.

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:
in encrypted data
out pointer to a buffer to hold the decrypted output
ctx address of an aes encryption context filled in with ast_aes_set_decrypt_key

Definition at line 477 of file res_crypto.c.

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

00478 {
00479    return AES_decrypt(in, out, ctx);
00480 }

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:
in data to be encrypted
out pointer to a buffer to hold the encrypted output
ctx address of an aes encryption context filled in with ast_aes_set_encrypt_key

Definition at line 472 of file res_crypto.c.

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

00473 {
00474    return AES_encrypt(in, out, ctx);
00475 }

int AST_OPTIONAL_API_NAME() ast_aes_set_decrypt_key ( const unsigned char *  key,
ast_aes_decrypt_key ctx 
)

Set a decryption key.

Parameters:
key a 16 char key
ctx address of an aes encryption context
Return values:
0 success
nonzero failure

Definition at line 467 of file res_crypto.c.

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

00468 {
00469    return AES_set_decrypt_key(key, 128, ctx);
00470 }

int AST_OPTIONAL_API_NAME() ast_aes_set_encrypt_key ( const unsigned char *  key,
ast_aes_encrypt_key ctx 
)

Set an encryption key.

Parameters:
key a 16 char key
ctx address of an aes encryption context
Return values:
0 success
nonzero failure

Definition at line 462 of file res_crypto.c.

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

00463 {
00464    return AES_set_encrypt_key(key, 128, ctx);
00465 }

int AST_OPTIONAL_API_NAME() ast_check_signature ( struct ast_key key,
const char *  msg,
const char *  sig 
)

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

See also:
ast_check_signature

Definition at line 441 of file res_crypto.c.

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

Referenced by authenticate_verify(), and register_verify().

00442 {
00443    unsigned char dsig[128];
00444    int res;
00445 
00446    /* Decode signature */
00447    if ((res = ast_base64decode(dsig, sig, sizeof(dsig))) != sizeof(dsig)) {
00448       ast_log(LOG_WARNING, "Signature improper length (expect %d, got %d)\n", (int)sizeof(dsig), (int)res);
00449       return -1;
00450    }
00451 
00452    res = ast_check_signature_bin(key, msg, strlen(msg), dsig);
00453 
00454    return res;
00455 }

int AST_OPTIONAL_API_NAME() ast_check_signature_bin ( struct ast_key key,
const char *  msg,
int  msglen,
const unsigned char *  dsig 
)

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

See also:
ast_check_signature_bin

Definition at line 412 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().

00413 {
00414    unsigned char digest[20];
00415    int res;
00416 
00417    if (key->ktype != AST_KEY_PUBLIC) {
00418       /* Okay, so of course you really *can* but for our purposes
00419          we're going to say you can't */
00420       ast_log(LOG_WARNING, "Cannot check message signature with a private key\n");
00421       return -1;
00422    }
00423 
00424    /* Calculate digest of message */
00425    SHA1((unsigned char *)msg, msglen, digest);
00426 
00427    /* Verify signature */
00428    if (!(res = RSA_verify(NID_sha1, digest, sizeof(digest), (unsigned char *)dsig, 128, key->rsa))) {
00429       ast_debug(1, "Key failed verification: %s\n", key->name);
00430       return -1;
00431    }
00432 
00433    /* Pass */
00434    return 0;
00435 }

int AST_OPTIONAL_API_NAME() ast_crypto_loaded ( void   ) 

Definition at line 457 of file res_crypto.c.

00458 {
00459    return 1;
00460 }

int AST_OPTIONAL_API_NAME() ast_decrypt_bin ( unsigned char *  dst,
const unsigned char *  src,
int  srclen,
struct ast_key key 
)

Decrypt a message using a given private key.

See also:
ast_decrypt_bin

Definition at line 332 of file res_crypto.c.

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

Referenced by check_key().

00333 {
00334    int res, pos = 0;
00335 
00336    if (key->ktype != AST_KEY_PRIVATE) {
00337       ast_log(LOG_WARNING, "Cannot decrypt with a public key\n");
00338       return -1;
00339    }
00340 
00341    if (srclen % 128) {
00342       ast_log(LOG_NOTICE, "Tried to decrypt something not a multiple of 128 bytes\n");
00343       return -1;
00344    }
00345 
00346    while (srclen) {
00347       /* Process chunks 128 bytes at a time */
00348       if ((res = RSA_private_decrypt(128, src, dst, key->rsa, RSA_PKCS1_OAEP_PADDING)) < 0) {
00349          return -1;
00350       }
00351       pos += res;
00352       src += 128;
00353       srclen -= 128;
00354       dst += res;
00355    }
00356 
00357    return pos;
00358 }

int AST_OPTIONAL_API_NAME() ast_encrypt_bin ( unsigned char *  dst,
const unsigned char *  src,
int  srclen,
struct ast_key key 
)

Encrypt a message using a given private key.

See also:
ast_encrypt_bin

Definition at line 364 of file res_crypto.c.

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

Referenced by update_key().

00365 {
00366    int res, bytes, pos = 0;
00367 
00368    if (key->ktype != AST_KEY_PUBLIC) {
00369       ast_log(LOG_WARNING, "Cannot encrypt with a private key\n");
00370       return -1;
00371    }
00372 
00373    while (srclen) {
00374       bytes = srclen;
00375       if (bytes > 128 - 41) {
00376          bytes = 128 - 41;
00377       }
00378       /* Process chunks 128-41 bytes at a time */
00379       if ((res = RSA_public_encrypt(bytes, src, dst, key->rsa, RSA_PKCS1_OAEP_PADDING)) != 128) {
00380          ast_log(LOG_NOTICE, "How odd, encrypted size is %d\n", res);
00381          return -1;
00382       }
00383       src += bytes;
00384       srclen -= bytes;
00385       pos += res;
00386       dst += res;
00387    }
00388    return pos;
00389 }

struct ast_key* AST_OPTIONAL_API_NAME() ast_key_get ( const char *  kname,
int  ktype 
)

Retrieve a key.

See also:
ast_key_get

Definition at line 137 of file res_crypto.c.

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

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

00138 {
00139    struct ast_key *key;
00140 
00141    AST_RWLIST_RDLOCK(&keys);
00142    AST_RWLIST_TRAVERSE(&keys, key, list) {
00143       if (!strcmp(kname, key->name) &&
00144           (ktype == key->ktype)) {
00145          break;
00146       }
00147    }
00148    AST_RWLIST_UNLOCK(&keys);
00149 
00150    return key;
00151 }

int AST_OPTIONAL_API_NAME() ast_sign ( struct ast_key key,
char *  msg,
char *  sig 
)

Sign a message signature using a given private key.

See also:
ast_sign

Definition at line 395 of file res_crypto.c.

References ast_base64encode(), and ast_sign_bin().

Referenced by authenticate().

00396 {
00397    unsigned char dsig[128];
00398    int siglen = sizeof(dsig), res;
00399 
00400    if (!(res = ast_sign_bin(key, msg, strlen(msg), dsig))) {
00401       /* Success -- encode (256 bytes max as documented) */
00402       ast_base64encode(sig, dsig, siglen, 256);
00403    }
00404 
00405    return res;
00406 }

int AST_OPTIONAL_API_NAME() ast_sign_bin ( struct ast_key key,
const char *  msg,
int  msglen,
unsigned char *  dsig 
)

Sign a message signature using a given private key.

See also:
ast_sign_bin

Definition at line 300 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().

00301 {
00302    unsigned char digest[20];
00303    unsigned int siglen = 128;
00304    int res;
00305 
00306    if (key->ktype != AST_KEY_PRIVATE) {
00307       ast_log(LOG_WARNING, "Cannot sign with a public key\n");
00308       return -1;
00309    }
00310 
00311    /* Calculate digest of message */
00312    SHA1((unsigned char *)msg, msglen, digest);
00313 
00314    /* Verify signature */
00315    if (!(res = RSA_sign(NID_sha1, digest, sizeof(digest), dsig, &siglen, key->rsa))) {
00316       ast_log(LOG_WARNING, "RSA Signature (key %s) failed\n", key->name);
00317       return -1;
00318    }
00319 
00320    if (siglen != 128) {
00321       ast_log(LOG_WARNING, "Unexpected signature length %d, expecting %d\n", (int)siglen, (int)128);
00322       return -1;
00323    }
00324 
00325    return 0;
00326 }

static int crypto_init ( void   )  [static]

initialise the res_crypto module

Definition at line 636 of file res_crypto.c.

References ARRAY_LEN, ast_cli_register_multiple(), and cli_crypto.

Referenced by load_module().

00637 {
00638    ast_cli_register_multiple(cli_crypto, ARRAY_LEN(cli_crypto));
00639    return 0;
00640 }

static void crypto_load ( int  ifd,
int  ofd 
) [static]

refresh RSA keys from file

Parameters:
ifd file descriptor
ofd file descriptor
Returns:
void

Definition at line 488 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, ast_key::list, LOG_NOTICE, LOG_WARNING, ast_key::name, ast_key::rsa, and try_load_key().

Referenced by load_module(), and reload().

00489 {
00490    struct ast_key *key;
00491    DIR *dir = NULL;
00492    struct dirent *ent;
00493    int note = 0;
00494 
00495    AST_RWLIST_WRLOCK(&keys);
00496 
00497    /* Mark all keys for deletion */
00498    AST_RWLIST_TRAVERSE(&keys, key, list) {
00499       key->delme = 1;
00500    }
00501 
00502    /* Load new keys */
00503    if ((dir = opendir(ast_config_AST_KEY_DIR))) {
00504       while ((ent = readdir(dir))) {
00505          try_load_key(ast_config_AST_KEY_DIR, ent->d_name, ifd, ofd, &note);
00506       }
00507       closedir(dir);
00508    } else {
00509       ast_log(LOG_WARNING, "Unable to open key directory '%s'\n", ast_config_AST_KEY_DIR);
00510    }
00511 
00512    if (note) {
00513       ast_log(LOG_NOTICE, "Please run the command 'keys init' to enter the passcodes for the keys\n");
00514    }
00515 
00516    /* Delete any keys that are no longer present */
00517    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&keys, key, list) {
00518       if (key->delme) {
00519          ast_debug(1, "Deleting key %s type %d\n", key->name, key->ktype);
00520          AST_RWLIST_REMOVE_CURRENT(list);
00521          if (key->rsa) {
00522             RSA_free(key->rsa);
00523          }
00524          ast_free(key);
00525       }
00526    }
00527    AST_RWLIST_TRAVERSE_SAFE_END;
00528 
00529    AST_RWLIST_UNLOCK(&keys);
00530 }

static char* handle_cli_keys_init ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

initialize all RSA keys

Parameters:
e CLI command
cmd 
a list of CLI arguments
Returns:
CLI_SUCCESS

Definition at line 593 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, ast_key::list, try_load_key(), and ast_cli_entry::usage.

00594 {
00595    struct ast_key *key;
00596    int ign;
00597    char *kn, tmp[256] = "";
00598 
00599    switch (cmd) {
00600    case CLI_INIT:
00601       e->command = "keys init";
00602       e->usage =
00603          "Usage: keys init\n"
00604          "       Initializes private keys (by reading in pass code from\n"
00605          "       the user)\n";
00606       return NULL;
00607    case CLI_GENERATE:
00608       return NULL;
00609    }
00610 
00611    if (a->argc != 2) {
00612       return CLI_SHOWUSAGE;
00613    }
00614 
00615    AST_RWLIST_WRLOCK(&keys);
00616    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&keys, key, list) {
00617       /* Reload keys that need pass codes now */
00618       if (key->ktype & KEY_NEEDS_PASSCODE) {
00619          kn = key->fn + strlen(ast_config_AST_KEY_DIR) + 1;
00620          ast_copy_string(tmp, kn, sizeof(tmp));
00621          try_load_key(ast_config_AST_KEY_DIR, tmp, a->fd, a->fd, &ign);
00622       }
00623    }
00624    AST_RWLIST_TRAVERSE_SAFE_END
00625    AST_RWLIST_UNLOCK(&keys);
00626 
00627    return CLI_SUCCESS;
00628 }

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:
e CLI command
cmd 
a list of CLI arguments
Returns:
CLI_SUCCESS

Definition at line 547 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, ast_key::list, md52sum(), ast_key::name, and ast_cli_entry::usage.

00548 {
00549 #define FORMAT "%-18s %-8s %-16s %-33s\n"
00550 
00551    struct ast_key *key;
00552    char sum[16 * 2 + 1];
00553    int count_keys = 0;
00554 
00555    switch (cmd) {
00556    case CLI_INIT:
00557       e->command = "keys show";
00558       e->usage =
00559          "Usage: keys show\n"
00560          "       Displays information about RSA keys known by Asterisk\n";
00561       return NULL;
00562    case CLI_GENERATE:
00563       return NULL;
00564    }
00565 
00566    ast_cli(a->fd, FORMAT, "Key Name", "Type", "Status", "Sum");
00567    ast_cli(a->fd, FORMAT, "------------------", "--------", "----------------", "--------------------------------");
00568 
00569    AST_RWLIST_RDLOCK(&keys);
00570    AST_RWLIST_TRAVERSE(&keys, key, list) {
00571       md52sum(sum, key->digest);
00572       ast_cli(a->fd, FORMAT, key->name,
00573          (key->ktype & 0xf) == AST_KEY_PUBLIC ? "PUBLIC" : "PRIVATE",
00574          key->ktype & KEY_NEEDS_PASSCODE ? "[Needs Passcode]" : "[Loaded]", sum);
00575       count_keys++;
00576    }
00577    AST_RWLIST_UNLOCK(&keys);
00578 
00579    ast_cli(a->fd, "\n%d known RSA keys.\n", count_keys);
00580 
00581    return CLI_SUCCESS;
00582 
00583 #undef FORMAT
00584 }

static int load_module ( void   )  [static]

Definition at line 648 of file res_crypto.c.

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

00649 {
00650    crypto_init();
00651    if (ast_opt_init_keys) {
00652       crypto_load(STDIN_FILENO, STDOUT_FILENO);
00653    } else {
00654       crypto_load(-1, -1);
00655    }
00656    return AST_MODULE_LOAD_SUCCESS;
00657 }

static void md52sum ( char *  sum,
unsigned char *  md5 
) [static]

Definition at line 532 of file res_crypto.c.

Referenced by handle_cli_keys_show().

00533 {
00534    int x;
00535    for (x = 0; x < 16; x++) {
00536       sum += sprintf(sum, "%02x", *(md5++));
00537    }
00538 }

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().

00100 {
00101    struct ast_key *key = (struct ast_key *)userdata;
00102    char prompt[256];
00103    int tmp;
00104    int res;
00105 
00106    if (key->infd < 0) {
00107       /* Note that we were at least called */
00108       key->infd = -2;
00109       return -1;
00110    }
00111 
00112    snprintf(prompt, sizeof(prompt), ">>>> passcode for %s key '%s': ",
00113        key->ktype == AST_KEY_PRIVATE ? "PRIVATE" : "PUBLIC", key->name);
00114    if (write(key->outfd, prompt, strlen(prompt)) < 0) {
00115       ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
00116       key->infd = -2;
00117       return -1;
00118    }
00119    memset(buf, 0, sizeof(buf));
00120    tmp = ast_hide_password(key->infd);
00121    memset(buf, 0, size);
00122    res = read(key->infd, buf, size);
00123    if (res == -1) {
00124       ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
00125    }
00126    ast_restore_tty(key->infd, tmp);
00127    if (buf[strlen(buf) -1] == '\n') {
00128       buf[strlen(buf) - 1] = '\0';
00129    }
00130    return strlen(buf);
00131 }

static int reload ( void   )  [static]

Definition at line 642 of file res_crypto.c.

References crypto_load().

00643 {
00644    crypto_load(-1, -1);
00645    return 0;
00646 }

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:
dir directory string
fname name of file
ifd incoming file descriptor
ofd outgoing file descriptor
not2 
Return values:
key on success.
NULL on failure.

Definition at line 163 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, ast_key::list, LOG_NOTICE, LOG_WARNING, md5(), MD5Final(), MD5Init(), MD5Update(), ast_key::name, ast_key::outfd, pw_cb(), and ast_key::rsa.

Referenced by crypto_load(), and handle_cli_keys_init().

00164 {
00165    int ktype = 0, found = 0;
00166    char *c = NULL, ffname[256];
00167    unsigned char digest[16];
00168    FILE *f;
00169    struct MD5Context md5;
00170    struct ast_key *key;
00171    static int notice = 0;
00172 
00173    /* Make sure its name is a public or private key */
00174    if ((c = strstr(fname, ".pub")) && !strcmp(c, ".pub")) {
00175       ktype = AST_KEY_PUBLIC;
00176    } else if ((c = strstr(fname, ".key")) && !strcmp(c, ".key")) {
00177       ktype = AST_KEY_PRIVATE;
00178    } else {
00179       return NULL;
00180    }
00181 
00182    /* Get actual filename */
00183    snprintf(ffname, sizeof(ffname), "%s/%s", dir, fname);
00184 
00185    /* Open file */
00186    if (!(f = fopen(ffname, "r"))) {
00187       ast_log(LOG_WARNING, "Unable to open key file %s: %s\n", ffname, strerror(errno));
00188       return NULL;
00189    }
00190 
00191    MD5Init(&md5);
00192    while (!feof(f)) {
00193       /* Calculate a "whatever" quality md5sum of the key */
00194       char buf[256] = "";
00195       if (!fgets(buf, sizeof(buf), f)) {
00196          continue;
00197       }
00198       if (!feof(f)) {
00199          MD5Update(&md5, (unsigned char *) buf, strlen(buf));
00200       }
00201    }
00202    MD5Final(digest, &md5);
00203 
00204    /* Look for an existing key */
00205    AST_RWLIST_TRAVERSE(&keys, key, list) {
00206       if (!strcasecmp(key->fn, ffname)) {
00207          break;
00208       }
00209    }
00210 
00211    if (key) {
00212       /* If the MD5 sum is the same, and it isn't awaiting a passcode
00213          then this is far enough */
00214       if (!memcmp(digest, key->digest, 16) &&
00215           !(key->ktype & KEY_NEEDS_PASSCODE)) {
00216          fclose(f);
00217          key->delme = 0;
00218          return NULL;
00219       } else {
00220          /* Preserve keytype */
00221          ktype = key->ktype;
00222          /* Recycle the same structure */
00223          found++;
00224       }
00225    }
00226 
00227    /* Make fname just be the normal name now */
00228    *c = '\0';
00229    if (!key) {
00230       if (!(key = ast_calloc(1, sizeof(*key)))) {
00231          fclose(f);
00232          return NULL;
00233       }
00234    }
00235    /* First the filename */
00236    ast_copy_string(key->fn, ffname, sizeof(key->fn));
00237    /* Then the name */
00238    ast_copy_string(key->name, fname, sizeof(key->name));
00239    key->ktype = ktype;
00240    /* Yes, assume we're going to be deleted */
00241    key->delme = 1;
00242    /* Keep the key type */
00243    memcpy(key->digest, digest, 16);
00244    /* Can I/O takes the FD we're given */
00245    key->infd = ifd;
00246    key->outfd = ofd;
00247    /* Reset the file back to the beginning */
00248    rewind(f);
00249    /* Now load the key with the right method */
00250    if (ktype == AST_KEY_PUBLIC) {
00251       key->rsa = PEM_read_RSA_PUBKEY(f, NULL, pw_cb, key);
00252    } else {
00253       key->rsa = PEM_read_RSAPrivateKey(f, NULL, pw_cb, key);
00254    }
00255    fclose(f);
00256    if (key->rsa) {
00257       if (RSA_size(key->rsa) == 128) {
00258          /* Key loaded okay */
00259          key->ktype &= ~KEY_NEEDS_PASSCODE;
00260          ast_verb(3, "Loaded %s key '%s'\n", key->ktype == AST_KEY_PUBLIC ? "PUBLIC" : "PRIVATE", key->name);
00261          ast_debug(1, "Key '%s' loaded OK\n", key->name);
00262          key->delme = 0;
00263       } else {
00264          ast_log(LOG_NOTICE, "Key '%s' is not expected size.\n", key->name);
00265       }
00266    } else if (key->infd != -2) {
00267       ast_log(LOG_WARNING, "Key load %s '%s' failed\n",key->ktype == AST_KEY_PUBLIC ? "PUBLIC" : "PRIVATE", key->name);
00268       if (ofd > -1) {
00269          ERR_print_errors_fp(stderr);
00270       } else {
00271          ERR_print_errors_fp(stderr);
00272       }
00273    } else {
00274       ast_log(LOG_NOTICE, "Key '%s' needs passcode.\n", key->name);
00275       key->ktype |= KEY_NEEDS_PASSCODE;
00276       if (!notice) {
00277          if (!ast_opt_init_keys) {
00278             ast_log(LOG_NOTICE, "Add the '-i' flag to the asterisk command line if you want to automatically initialize passcodes at launch.\n");
00279          }
00280          notice++;
00281       }
00282       /* Keep it anyway */
00283       key->delme = 0;
00284       /* Print final notice about "keys init" when done */
00285       *not2 = 1;
00286    }
00287 
00288    /* If this is a new key add it to the list */
00289    if (!found) {
00290       AST_RWLIST_INSERT_TAIL(&keys, key, list);
00291    }
00292 
00293    return key;
00294 }

static int unload_module ( void   )  [static]

Definition at line 659 of file res_crypto.c.

00660 {
00661    /* Can't unload this once we're loaded */
00662    return -1;
00663 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Cryptographic Digital Signatures" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } [static]

< Since we don't have a config file, we could move up to REALTIME_DEPEND, if necessary

Definition at line 671 of file res_crypto.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 671 of file res_crypto.c.

struct ast_cli_entry cli_crypto[] [static]

Initial value:

 {
   { .handler =  handle_cli_keys_show , .summary =  "Displays RSA key information" ,__VA_ARGS__ },
   { .handler =  handle_cli_keys_init , .summary =  "Initialize RSA key passcodes" ,__VA_ARGS__ }
}

Definition at line 630 of file res_crypto.c.

Referenced by crypto_init().


Generated on Sat Mar 10 01:55:40 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7