#include <sys/types.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include "asterisk.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/logger.h"
#include "asterisk/say.h"
#include "asterisk/module.h"
#include "asterisk/options.h"
#include "asterisk/crypto.h"
#include "asterisk/md5.h"
#include "asterisk/cli.h"
#include "asterisk/io.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
Include dependency graph for res_crypto.c:
Go to the source code of this file.
Data Structures | |
struct | ast_key |
Defines | |
#define | KEY_NEEDS_PASSCODE (1 << 16) |
Functions | |
static int | __ast_check_signature (struct ast_key *key, const char *msg, const char *sig) |
static int | __ast_check_signature_bin (struct ast_key *key, const char *msg, int msglen, const unsigned char *dsig) |
static int | __ast_decrypt_bin (unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key) |
static int | __ast_encrypt_bin (unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key) |
static struct ast_key * | __ast_key_get (const char *kname, int ktype) |
static int | __ast_sign (struct ast_key *key, char *msg, char *sig) |
static int | __ast_sign_bin (struct ast_key *key, const char *msg, int msglen, unsigned char *dsig) |
AST_MUTEX_DEFINE_STATIC (keylock) | |
static int | crypto_init (void) |
static void | crypto_load (int ifd, int ofd) |
char * | description (void) |
Provides a description of the module. | |
static int | init_keys (int fd, int argc, char *argv[]) |
char * | key () |
Returns the ASTERISK_GPL_KEY. | |
int | load_module (void) |
Initialize the module. | |
static void | md52sum (char *sum, unsigned char *md5) |
static int | pw_cb (char *buf, int size, int rwflag, void *userdata) |
int | reload (void) |
Reload stuff. | |
static int | show_keys (int fd, int argc, char *argv[]) |
static struct ast_key * | try_load_key (char *dir, char *fname, int ifd, int ofd, int *not2) |
int | unload_module (void) |
Cleanup all module structures, sockets, etc. | |
int | usecount (void) |
Provides a usecount. | |
Variables | |
static struct ast_cli_entry | cli_init_keys |
static struct ast_cli_entry | cli_show_keys |
static char | init_keys_usage [] |
static struct ast_key * | keys = NULL |
static char | show_key_usage [] |
Definition in file res_crypto.c.
|
Definition at line 76 of file res_crypto.c. Referenced by init_keys(), show_keys(), and try_load_key(). |
|
Definition at line 441 of file res_crypto.c. References ast_base64decode(), ast_check_signature_bin, ast_log(), key(), and LOG_WARNING. Referenced by crypto_init(). 00442 { 00443 unsigned char dsig[128]; 00444 int res; 00445 00446 /* Decode signature */ 00447 res = ast_base64decode(dsig, sig, sizeof(dsig)); 00448 if (res != sizeof(dsig)) { 00449 ast_log(LOG_WARNING, "Signature improper length (expect %d, got %d)\n", (int)sizeof(dsig), (int)res); 00450 return -1; 00451 } 00452 res = ast_check_signature_bin(key, msg, strlen(msg), dsig); 00453 return res; 00454 }
|
|
Definition at line 415 of file res_crypto.c. References AST_KEY_PUBLIC, ast_log(), ast_key::digest, key(), LOG_DEBUG, and LOG_WARNING. Referenced by crypto_init(). 00416 { 00417 unsigned char digest[20]; 00418 int res; 00419 00420 if (key->ktype != AST_KEY_PUBLIC) { 00421 /* Okay, so of course you really *can* but for our purposes 00422 we're going to say you can't */ 00423 ast_log(LOG_WARNING, "Cannot check message signature with a private key\n"); 00424 return -1; 00425 } 00426 00427 /* Calculate digest of message */ 00428 SHA1((unsigned char *)msg, msglen, digest); 00429 00430 /* Verify signature */ 00431 res = RSA_verify(NID_sha1, digest, sizeof(digest), (unsigned char *)dsig, 128, key->rsa); 00432 00433 if (!res) { 00434 ast_log(LOG_DEBUG, "Key failed verification: %s\n", key->name); 00435 return -1; 00436 } 00437 /* Pass */ 00438 return 0; 00439 }
|
|
Definition at line 348 of file res_crypto.c. References AST_KEY_PRIVATE, ast_log(), key(), LOG_NOTICE, and LOG_WARNING. Referenced by crypto_init(). 00349 { 00350 int res; 00351 int pos = 0; 00352 if (key->ktype != AST_KEY_PRIVATE) { 00353 ast_log(LOG_WARNING, "Cannot decrypt with a public key\n"); 00354 return -1; 00355 } 00356 00357 if (srclen % 128) { 00358 ast_log(LOG_NOTICE, "Tried to decrypt something not a multiple of 128 bytes\n"); 00359 return -1; 00360 } 00361 while(srclen) { 00362 /* Process chunks 128 bytes at a time */ 00363 res = RSA_private_decrypt(128, src, dst, key->rsa, RSA_PKCS1_OAEP_PADDING); 00364 if (res < 0) 00365 return -1; 00366 pos += res; 00367 src += 128; 00368 srclen -= 128; 00369 dst += res; 00370 } 00371 return pos; 00372 }
|
|
Definition at line 374 of file res_crypto.c. References AST_KEY_PUBLIC, ast_log(), key(), LOG_NOTICE, and LOG_WARNING. Referenced by crypto_init(). 00375 { 00376 int res; 00377 int bytes; 00378 int pos = 0; 00379 if (key->ktype != AST_KEY_PUBLIC) { 00380 ast_log(LOG_WARNING, "Cannot encrypt with a private key\n"); 00381 return -1; 00382 } 00383 00384 while(srclen) { 00385 bytes = srclen; 00386 if (bytes > 128 - 41) 00387 bytes = 128 - 41; 00388 /* Process chunks 128-41 bytes at a time */ 00389 res = RSA_public_encrypt(bytes, src, dst, key->rsa, RSA_PKCS1_OAEP_PADDING); 00390 if (res != 128) { 00391 ast_log(LOG_NOTICE, "How odd, encrypted size is %d\n", res); 00392 return -1; 00393 } 00394 src += bytes; 00395 srclen -= bytes; 00396 pos += res; 00397 dst += res; 00398 } 00399 return pos; 00400 }
|
|
Definition at line 132 of file res_crypto.c. References ast_mutex_lock(), ast_mutex_unlock(), key(), and keys. Referenced by crypto_init(). 00133 { 00134 struct ast_key *key; 00135 ast_mutex_lock(&keylock); 00136 key = keys; 00137 while(key) { 00138 if (!strcmp(kname, key->name) && 00139 (ktype == key->ktype)) 00140 break; 00141 key = key->next; 00142 } 00143 ast_mutex_unlock(&keylock); 00144 return key; 00145 }
|
|
Definition at line 402 of file res_crypto.c. References ast_base64encode(), ast_sign_bin, and key(). Referenced by crypto_init(). 00403 { 00404 unsigned char dsig[128]; 00405 int siglen = sizeof(dsig); 00406 int res; 00407 res = ast_sign_bin(key, msg, strlen(msg), dsig); 00408 if (!res) 00409 /* Success -- encode (256 bytes max as documented) */ 00410 ast_base64encode(sig, dsig, siglen, 256); 00411 return res; 00412 00413 }
|
|
Definition at line 317 of file res_crypto.c. References AST_KEY_PRIVATE, ast_log(), ast_key::digest, key(), and LOG_WARNING. Referenced by crypto_init(). 00318 { 00319 unsigned char digest[20]; 00320 unsigned int siglen = 128; 00321 int res; 00322 00323 if (key->ktype != AST_KEY_PRIVATE) { 00324 ast_log(LOG_WARNING, "Cannot sign with a public key\n"); 00325 return -1; 00326 } 00327 00328 /* Calculate digest of message */ 00329 SHA1((unsigned char *)msg, msglen, digest); 00330 00331 /* Verify signature */ 00332 res = RSA_sign(NID_sha1, digest, sizeof(digest), dsig, &siglen, key->rsa); 00333 00334 if (!res) { 00335 ast_log(LOG_WARNING, "RSA Signature (key %s) failed\n", key->name); 00336 return -1; 00337 } 00338 00339 if (siglen != 128) { 00340 ast_log(LOG_WARNING, "Unexpected signature length %d, expecting %d\n", (int)siglen, (int)128); 00341 return -1; 00342 } 00343 00344 return 0; 00345 00346 }
|
|
|
|
Definition at line 568 of file res_crypto.c. References __ast_check_signature(), __ast_check_signature_bin(), __ast_decrypt_bin(), __ast_encrypt_bin(), __ast_key_get(), __ast_sign(), __ast_sign_bin(), ast_check_signature, ast_check_signature_bin, ast_cli_register(), ast_decrypt_bin, ast_encrypt_bin, ast_key_get, ast_sign, ast_sign_bin, cli_init_keys, and cli_show_keys. Referenced by load_module(). 00569 { 00570 SSL_library_init(); 00571 ERR_load_crypto_strings(); 00572 ast_cli_register(&cli_show_keys); 00573 ast_cli_register(&cli_init_keys); 00574 00575 /* Install ourselves into stubs */ 00576 ast_key_get = __ast_key_get; 00577 ast_check_signature = __ast_check_signature; 00578 ast_check_signature_bin = __ast_check_signature_bin; 00579 ast_sign = __ast_sign; 00580 ast_sign_bin = __ast_sign_bin; 00581 ast_encrypt_bin = __ast_encrypt_bin; 00582 ast_decrypt_bin = __ast_decrypt_bin; 00583 return 0; 00584 }
|
|
Definition at line 456 of file res_crypto.c. References ast_config_AST_KEY_DIR, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), free, key(), keys, last, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, msglist::next, and try_load_key(). Referenced by load_module(), and reload(). 00457 { 00458 struct ast_key *key, *nkey, *last; 00459 DIR *dir = NULL; 00460 struct dirent *ent; 00461 int note = 0; 00462 /* Mark all keys for deletion */ 00463 ast_mutex_lock(&keylock); 00464 key = keys; 00465 while(key) { 00466 key->delme = 1; 00467 key = key->next; 00468 } 00469 ast_mutex_unlock(&keylock); 00470 /* Load new keys */ 00471 dir = opendir((char *)ast_config_AST_KEY_DIR); 00472 if (dir) { 00473 while((ent = readdir(dir))) { 00474 try_load_key((char *)ast_config_AST_KEY_DIR, ent->d_name, ifd, ofd, ¬e); 00475 } 00476 closedir(dir); 00477 } else 00478 ast_log(LOG_WARNING, "Unable to open key directory '%s'\n", (char *)ast_config_AST_KEY_DIR); 00479 if (note) { 00480 ast_log(LOG_NOTICE, "Please run the command 'init keys' to enter the passcodes for the keys\n"); 00481 } 00482 ast_mutex_lock(&keylock); 00483 key = keys; 00484 last = NULL; 00485 while(key) { 00486 nkey = key->next; 00487 if (key->delme) { 00488 ast_log(LOG_DEBUG, "Deleting key %s type %d\n", key->name, key->ktype); 00489 /* Do the delete */ 00490 if (last) 00491 last->next = nkey; 00492 else 00493 keys = nkey; 00494 if (key->rsa) 00495 RSA_free(key->rsa); 00496 free(key); 00497 } else 00498 last = key; 00499 key = nkey; 00500 } 00501 ast_mutex_unlock(&keylock); 00502 }
|
|
Provides a description of the module.
Definition at line 608 of file res_crypto.c.
|
|
Definition at line 534 of file res_crypto.c. References ast_config_AST_KEY_DIR, key(), KEY_NEEDS_PASSCODE, keys, RESULT_SUCCESS, and try_load_key(). 00535 { 00536 struct ast_key *key; 00537 int ign; 00538 char *kn; 00539 char tmp[256] = ""; 00540 00541 key = keys; 00542 while(key) { 00543 /* Reload keys that need pass codes now */ 00544 if (key->ktype & KEY_NEEDS_PASSCODE) { 00545 kn = key->fn + strlen(ast_config_AST_KEY_DIR) + 1; 00546 ast_copy_string(tmp, kn, sizeof(tmp)); 00547 try_load_key((char *)ast_config_AST_KEY_DIR, tmp, fd, fd, &ign); 00548 } 00549 key = key->next; 00550 } 00551 return RESULT_SUCCESS; 00552 }
|
|
Returns the ASTERISK_GPL_KEY. This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:
char *key(void) { return ASTERISK_GPL_KEY; }
Definition at line 619 of file res_crypto.c. References ASTERISK_GPL_KEY. 00620 { 00621 return ASTERISK_GPL_KEY; 00622 }
|
|
Initialize the module. Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.
Definition at line 592 of file res_crypto.c. References crypto_init(), crypto_load(), and option_initcrypto. 00593 { 00594 crypto_init(); 00595 if (option_initcrypto) 00596 crypto_load(STDIN_FILENO, STDOUT_FILENO); 00597 else 00598 crypto_load(-1, -1); 00599 return 0; 00600 }
|
|
Definition at line 504 of file res_crypto.c. Referenced by show_keys().
|
|
Definition at line 107 of file res_crypto.c. References ast_hide_password(), AST_KEY_PRIVATE, ast_restore_tty(), and key(). Referenced by try_load_key(). 00108 { 00109 struct ast_key *key = (struct ast_key *)userdata; 00110 char prompt[256]; 00111 int res; 00112 int tmp; 00113 if (key->infd > -1) { 00114 snprintf(prompt, sizeof(prompt), ">>>> passcode for %s key '%s': ", 00115 key->ktype == AST_KEY_PRIVATE ? "PRIVATE" : "PUBLIC", key->name); 00116 write(key->outfd, prompt, strlen(prompt)); 00117 memset(buf, 0, sizeof(buf)); 00118 tmp = ast_hide_password(key->infd); 00119 memset(buf, 0, size); 00120 res = read(key->infd, buf, size); 00121 ast_restore_tty(key->infd, tmp); 00122 if (buf[strlen(buf) -1] == '\n') 00123 buf[strlen(buf) - 1] = '\0'; 00124 return strlen(buf); 00125 } else { 00126 /* Note that we were at least called */ 00127 key->infd = -2; 00128 } 00129 return -1; 00130 }
|
|
Reload stuff. This function is where any reload routines take place. Re-read config files, change signalling, whatever is appropriate on a reload.
Definition at line 586 of file res_crypto.c. References crypto_load(). 00587 { 00588 crypto_load(-1, -1); 00589 return 0; 00590 }
|
|
Definition at line 511 of file res_crypto.c. References ast_cli(), AST_KEY_PUBLIC, ast_mutex_lock(), ast_mutex_unlock(), key(), KEY_NEEDS_PASSCODE, keys, md52sum(), and RESULT_SUCCESS. 00512 { 00513 struct ast_key *key; 00514 char sum[16 * 2 + 1]; 00515 int count_keys = 0; 00516 00517 ast_mutex_lock(&keylock); 00518 key = keys; 00519 ast_cli(fd, "%-18s %-8s %-16s %-33s\n", "Key Name", "Type", "Status", "Sum"); 00520 while(key) { 00521 md52sum(sum, key->digest); 00522 ast_cli(fd, "%-18s %-8s %-16s %-33s\n", key->name, 00523 (key->ktype & 0xf) == AST_KEY_PUBLIC ? "PUBLIC" : "PRIVATE", 00524 key->ktype & KEY_NEEDS_PASSCODE ? "[Needs Passcode]" : "[Loaded]", sum); 00525 00526 key = key->next; 00527 count_keys++; 00528 } 00529 ast_mutex_unlock(&keylock); 00530 ast_cli(fd, "%d known RSA keys.\n", count_keys); 00531 return RESULT_SUCCESS; 00532 }
|
|
Definition at line 147 of file res_crypto.c. References AST_KEY_PRIVATE, AST_KEY_PUBLIC, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), ast_key::digest, key(), KEY_NEEDS_PASSCODE, keys, ast_key::ktype, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, malloc, MD5Final(), MD5Init(), MD5Update(), option_debug, option_initcrypto, option_verbose, pw_cb(), and VERBOSE_PREFIX_3. Referenced by crypto_load(), and init_keys(). 00148 { 00149 int ktype = 0; 00150 char *c = NULL; 00151 char ffname[256]; 00152 unsigned char digest[16]; 00153 FILE *f; 00154 struct MD5Context md5; 00155 struct ast_key *key; 00156 static int notice = 0; 00157 int found = 0; 00158 00159 /* Make sure its name is a public or private key */ 00160 00161 if ((c = strstr(fname, ".pub")) && !strcmp(c, ".pub")) { 00162 ktype = AST_KEY_PUBLIC; 00163 } else if ((c = strstr(fname, ".key")) && !strcmp(c, ".key")) { 00164 ktype = AST_KEY_PRIVATE; 00165 } else 00166 return NULL; 00167 00168 /* Get actual filename */ 00169 snprintf(ffname, sizeof(ffname), "%s/%s", dir, fname); 00170 00171 ast_mutex_lock(&keylock); 00172 key = keys; 00173 while(key) { 00174 /* Look for an existing version already */ 00175 if (!strcasecmp(key->fn, ffname)) 00176 break; 00177 key = key->next; 00178 } 00179 ast_mutex_unlock(&keylock); 00180 00181 /* Open file */ 00182 f = fopen(ffname, "r"); 00183 if (!f) { 00184 ast_log(LOG_WARNING, "Unable to open key file %s: %s\n", ffname, strerror(errno)); 00185 return NULL; 00186 } 00187 MD5Init(&md5); 00188 while(!feof(f)) { 00189 /* Calculate a "whatever" quality md5sum of the key */ 00190 char buf[256]; 00191 memset(buf, 0, 256); 00192 fgets(buf, sizeof(buf), f); 00193 if (!feof(f)) { 00194 MD5Update(&md5, (unsigned char *) buf, strlen(buf)); 00195 } 00196 } 00197 MD5Final(digest, &md5); 00198 if (key) { 00199 /* If the MD5 sum is the same, and it isn't awaiting a passcode 00200 then this is far enough */ 00201 if (!memcmp(digest, key->digest, 16) && 00202 !(key->ktype & KEY_NEEDS_PASSCODE)) { 00203 fclose(f); 00204 key->delme = 0; 00205 return NULL; 00206 } else { 00207 /* Preserve keytype */ 00208 ktype = key->ktype; 00209 /* Recycle the same structure */ 00210 found++; 00211 } 00212 } 00213 00214 /* Make fname just be the normal name now */ 00215 *c = '\0'; 00216 if (!key) { 00217 key = (struct ast_key *)malloc(sizeof(struct ast_key)); 00218 if (!key) { 00219 ast_log(LOG_WARNING, "Out of memory\n"); 00220 fclose(f); 00221 return NULL; 00222 } 00223 memset(key, 0, sizeof(struct ast_key)); 00224 } 00225 /* At this point we have a key structure (old or new). Time to 00226 fill it with what we know */ 00227 /* Gotta lock if this one already exists */ 00228 if (found) 00229 ast_mutex_lock(&keylock); 00230 /* First the filename */ 00231 ast_copy_string(key->fn, ffname, sizeof(key->fn)); 00232 /* Then the name */ 00233 ast_copy_string(key->name, fname, sizeof(key->name)); 00234 key->ktype = ktype; 00235 /* Yes, assume we're going to be deleted */ 00236 key->delme = 1; 00237 /* Keep the key type */ 00238 memcpy(key->digest, digest, 16); 00239 /* Can I/O takes the FD we're given */ 00240 key->infd = ifd; 00241 key->outfd = ofd; 00242 /* Reset the file back to the beginning */ 00243 rewind(f); 00244 /* Now load the key with the right method */ 00245 if (ktype == AST_KEY_PUBLIC) 00246 key->rsa = PEM_read_RSA_PUBKEY(f, NULL, pw_cb, key); 00247 else 00248 key->rsa = PEM_read_RSAPrivateKey(f, NULL, pw_cb, key); 00249 fclose(f); 00250 if (key->rsa) { 00251 if (RSA_size(key->rsa) == 128) { 00252 /* Key loaded okay */ 00253 key->ktype &= ~KEY_NEEDS_PASSCODE; 00254 if (option_verbose > 2) 00255 ast_verbose(VERBOSE_PREFIX_3 "Loaded %s key '%s'\n", key->ktype == AST_KEY_PUBLIC ? "PUBLIC" : "PRIVATE", key->name); 00256 if (option_debug) 00257 ast_log(LOG_DEBUG, "Key '%s' loaded OK\n", key->name); 00258 key->delme = 0; 00259 } else 00260 ast_log(LOG_NOTICE, "Key '%s' is not expected size.\n", key->name); 00261 } else if (key->infd != -2) { 00262 ast_log(LOG_WARNING, "Key load %s '%s' failed\n",key->ktype == AST_KEY_PUBLIC ? "PUBLIC" : "PRIVATE", key->name); 00263 if (ofd > -1) { 00264 ERR_print_errors_fp(stderr); 00265 } else 00266 ERR_print_errors_fp(stderr); 00267 } else { 00268 ast_log(LOG_NOTICE, "Key '%s' needs passcode.\n", key->name); 00269 key->ktype |= KEY_NEEDS_PASSCODE; 00270 if (!notice) { 00271 if (!option_initcrypto) 00272 ast_log(LOG_NOTICE, "Add the '-i' flag to the asterisk command line if you want to automatically initialize passcodes at launch.\n"); 00273 notice++; 00274 } 00275 /* Keep it anyway */ 00276 key->delme = 0; 00277 /* Print final notice about "init keys" when done */ 00278 *not2 = 1; 00279 } 00280 if (found) 00281 ast_mutex_unlock(&keylock); 00282 if (!found) { 00283 ast_mutex_lock(&keylock); 00284 key->next = keys; 00285 keys = key; 00286 ast_mutex_unlock(&keylock); 00287 } 00288 return key; 00289 }
|
|
Cleanup all module structures, sockets, etc. Standard module functions ... Definition at line 602 of file res_crypto.c.
|
|
Provides a usecount. This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.
Definition at line 613 of file res_crypto.c.
|
|
Initial value: { { "init", "keys", NULL }, init_keys, "Initialize RSA key passcodes", init_keys_usage } Definition at line 565 of file res_crypto.c. Referenced by crypto_init(). |
|
Initial value: { { "show", "keys", NULL }, show_keys, "Displays RSA key information", show_key_usage } Definition at line 562 of file res_crypto.c. Referenced by crypto_init(). |
|
Initial value: "Usage: init keys\n" " Initializes private keys (by reading in pass code from the user)\n" Definition at line 558 of file res_crypto.c. |
|
Definition at line 98 of file res_crypto.c. Referenced by __ast_key_get(), adsi_delete(), adsi_folders(), adsi_login(), adsi_message(), adsi_password(), adsi_status(), adsi_status2(), ast_db_deltree(), ast_db_gettree(), crypto_load(), database_show(), database_showkey(), init_keys(), reply_digest(), show_keys(), and try_load_key(). |
|
Initial value: "Usage: show keys\n" " Displays information about RSA keys known by Asterisk\n" Definition at line 554 of file res_crypto.c. |