mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-06 12:36:58 +00:00
Fix utils directory breakage.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393675 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -154,7 +154,7 @@ db.o: _ASTCFLAGS+=$(SQLITE3_INCLUDE)
|
||||
asterisk.o: _ASTCFLAGS+=$(LIBEDIT_INCLUDE)
|
||||
cli.o: _ASTCFLAGS+=$(LIBEDIT_INCLUDE)
|
||||
json.o: _ASTCFLAGS+=$(JANSSON_INCLUDE)
|
||||
util.o: _ASTCFLAGS+=$(CRYPT_INCLUDE)
|
||||
crypt.o: _ASTCFLAGS+=$(CRYPT_INCLUDE)
|
||||
uuid.o: _ASTCFLAGS+=$(UUID_INCLUDE)
|
||||
|
||||
ifneq ($(findstring ENABLE_UPLOADS,$(MENUSELECT_CFLAGS)),)
|
||||
|
202
main/crypt.c
Normal file
202
main/crypt.c
Normal file
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 2012 - 2013, Digium, Inc.
|
||||
*
|
||||
* David M. Lee, II <dlee@digium.com>
|
||||
*
|
||||
* See http://www.asterisk.org for more information about
|
||||
* the Asterisk project. Please do not directly contact
|
||||
* any of the maintainers of this project for assistance;
|
||||
* the project provides a web site, mailing lists and IRC
|
||||
* channels for your use.
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License Version 2. See the LICENSE file
|
||||
* at the top of the source tree.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Asterisk wrapper for crypt(3)
|
||||
* \author David M. Lee, II <dlee@digium.com>
|
||||
*/
|
||||
|
||||
/*** MODULEINFO
|
||||
<support_level>core</support_level>
|
||||
***/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include <unistd.h>
|
||||
#if defined(HAVE_CRYPT_R)
|
||||
#include <crypt.h>
|
||||
#endif
|
||||
|
||||
#include "asterisk/utils.h"
|
||||
|
||||
/*!
|
||||
* \brief Max length of a salt string.
|
||||
*
|
||||
* $[1,5,6]$[a–zA–Z0–9./]{1,16}$, plus null terminator
|
||||
*/
|
||||
#define MAX_SALT_LEN 21
|
||||
|
||||
static char salt_chars[] =
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789"
|
||||
"./";
|
||||
|
||||
/*! Randomly select a character for a salt string */
|
||||
static char gen_salt_char(void)
|
||||
{
|
||||
int which = ast_random_double() * 64;
|
||||
return salt_chars[which];
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Generates a salt to try with crypt.
|
||||
*
|
||||
* If given an empty string, will generate a salt for the most secure algorithm
|
||||
* to try with crypt(). If given a previously generated salt, the algorithm will
|
||||
* be lowered by one level of security.
|
||||
*
|
||||
* \param[out] current_salt Output string in which to generate the salt.
|
||||
* This can be an empty string, or the results of a
|
||||
* prior gen_salt call.
|
||||
* \param max_len Length of \a current_salt.
|
||||
* \return 0 on success.
|
||||
* \return Non-zero on error.
|
||||
*/
|
||||
static int gen_salt(char *current_salt, size_t maxlen)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (maxlen < MAX_SALT_LEN || current_salt == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (current_salt[0]) {
|
||||
case '\0':
|
||||
/* Initial generation; $6$ = SHA-512 */
|
||||
*current_salt++ = '$';
|
||||
*current_salt++ = '6';
|
||||
*current_salt++ = '$';
|
||||
for (i = 0; i < 16; ++i) {
|
||||
*current_salt++ = gen_salt_char();
|
||||
}
|
||||
*current_salt++ = '$';
|
||||
*current_salt++ = '\0';
|
||||
return 0;
|
||||
case '$':
|
||||
switch (current_salt[1]) {
|
||||
case '6':
|
||||
/* Downgrade to SHA-256 */
|
||||
current_salt[1] = '5';
|
||||
return 0;
|
||||
case '5':
|
||||
/* Downgrade to MD5 */
|
||||
current_salt[1] = '1';
|
||||
return 0;
|
||||
case '1':
|
||||
/* Downgrade to traditional crypt */
|
||||
*current_salt++ = gen_salt_char();
|
||||
*current_salt++ = gen_salt_char();
|
||||
*current_salt++ = '\0';
|
||||
return 0;
|
||||
default:
|
||||
/* Unrecognized algorithm */
|
||||
return -1;
|
||||
}
|
||||
default:
|
||||
/* Was already as insecure as it gets */
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if defined(HAVE_CRYPT_R)
|
||||
|
||||
char *ast_crypt(const char *key, const char *salt)
|
||||
{
|
||||
struct crypt_data data = {};
|
||||
const char *crypted = crypt_r(key, salt, &data);
|
||||
|
||||
/* Crypt may return success even if it doesn't recognize the salt. But
|
||||
* in those cases it always mangles the salt in some way.
|
||||
*/
|
||||
if (!crypted || !ast_begins_with(crypted, salt)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ast_strdup(crypted);
|
||||
}
|
||||
|
||||
int ast_crypt_validate(const char *key, const char *expected)
|
||||
{
|
||||
struct crypt_data data = {};
|
||||
return strcmp(expected, crypt_r(key, expected, &data)) == 0;
|
||||
}
|
||||
|
||||
#elif defined(HAVE_CRYPT)
|
||||
|
||||
/* crypt is not reentrant. A global mutex is neither ideal nor perfect, but good
|
||||
* enough if crypt_r support is unavailable
|
||||
*/
|
||||
AST_MUTEX_DEFINE_STATIC(crypt_mutex);
|
||||
|
||||
char *ast_crypt(const char *key, const char *salt)
|
||||
{
|
||||
const char *crypted;
|
||||
SCOPED_MUTEX(lock, &crypt_mutex);
|
||||
|
||||
crypted = crypt(key, salt);
|
||||
|
||||
/* Crypt may return success even if it doesn't recognize the salt. But
|
||||
* in those cases it always mangles the salt in some way.
|
||||
*/
|
||||
if (!crypted || !ast_begins_with(crypted, salt)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ast_strdup(crypted);
|
||||
}
|
||||
|
||||
int ast_crypt_validate(const char *key, const char *expected)
|
||||
{
|
||||
SCOPED_MUTEX(lock, &crypt_mutex);
|
||||
return strcmp(expected, crypt(key, expected)) == 0;
|
||||
}
|
||||
|
||||
#else /* No crypt support */
|
||||
|
||||
char *ast_crypt(const char *key, const char *salt)
|
||||
{
|
||||
ast_log(LOG_WARNING,
|
||||
"crypt() support not available; cannot encrypt password\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int ast_crypt_validate(const char *key, const char *expected)
|
||||
{
|
||||
ast_log(LOG_WARNING,
|
||||
"crypt() support not available; cannot validate password\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* No crypt support */
|
||||
|
||||
char *ast_crypt_encrypt(const char *key)
|
||||
{
|
||||
char salt[MAX_SALT_LEN] = {};
|
||||
while (gen_salt(salt, sizeof(salt)) == 0) {
|
||||
char *crypted = ast_crypt(key, salt);
|
||||
if (crypted) {
|
||||
return crypted;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
168
main/utils.c
168
main/utils.c
@@ -37,9 +37,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
#if defined(HAVE_CRYPT_R)
|
||||
#include <crypt.h>
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
#include <mach/mach.h>
|
||||
#elif defined(HAVE_SYS_THR_H)
|
||||
@@ -2367,171 +2364,6 @@ int ast_get_tid(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Max length of a salt string.
|
||||
*
|
||||
* $[1,5,6]$[a–zA–Z0–9./]{1,16}$, plus null terminator
|
||||
*/
|
||||
#define MAX_SALT_LEN 21
|
||||
|
||||
static char salt_chars[] =
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789"
|
||||
"./";
|
||||
|
||||
/*! Randomly select a character for a salt string */
|
||||
static char gen_salt_char(void)
|
||||
{
|
||||
int which = ast_random_double() * 64;
|
||||
return salt_chars[which];
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Generates a salt to try with crypt.
|
||||
*
|
||||
* If given an empty string, will generate a salt for the most secure algorithm
|
||||
* to try with crypt(). If given a previously generated salt, the algorithm will
|
||||
* be lowered by one level of security.
|
||||
*
|
||||
* \param[out] current_salt Output string in which to generate the salt.
|
||||
* This can be an empty string, or the results of a
|
||||
* prior gen_salt call.
|
||||
* \param max_len Length of \a current_salt.
|
||||
* \return 0 on success.
|
||||
* \return Non-zero on error.
|
||||
*/
|
||||
static int gen_salt(char *current_salt, size_t maxlen)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (maxlen < MAX_SALT_LEN || current_salt == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (current_salt[0]) {
|
||||
case '\0':
|
||||
/* Initial generation; $6$ = SHA-512 */
|
||||
*current_salt++ = '$';
|
||||
*current_salt++ = '6';
|
||||
*current_salt++ = '$';
|
||||
for (i = 0; i < 16; ++i) {
|
||||
*current_salt++ = gen_salt_char();
|
||||
}
|
||||
*current_salt++ = '$';
|
||||
*current_salt++ = '\0';
|
||||
return 0;
|
||||
case '$':
|
||||
switch (current_salt[1]) {
|
||||
case '6':
|
||||
/* Downgrade to SHA-256 */
|
||||
current_salt[1] = '5';
|
||||
return 0;
|
||||
case '5':
|
||||
/* Downgrade to MD5 */
|
||||
current_salt[1] = '1';
|
||||
return 0;
|
||||
case '1':
|
||||
/* Downgrade to traditional crypt */
|
||||
*current_salt++ = gen_salt_char();
|
||||
*current_salt++ = gen_salt_char();
|
||||
*current_salt++ = '\0';
|
||||
return 0;
|
||||
default:
|
||||
/* Unrecognized algorithm */
|
||||
return -1;
|
||||
}
|
||||
default:
|
||||
/* Was already as insecure as it gets */
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if defined(HAVE_CRYPT_R)
|
||||
|
||||
char *ast_crypt(const char *key, const char *salt)
|
||||
{
|
||||
struct crypt_data data = {};
|
||||
const char *crypted = crypt_r(key, salt, &data);
|
||||
|
||||
/* Crypt may return success even if it doesn't recognize the salt. But
|
||||
* in those cases it always mangles the salt in some way.
|
||||
*/
|
||||
if (!crypted || !ast_begins_with(crypted, salt)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ast_strdup(crypted);
|
||||
}
|
||||
|
||||
int ast_crypt_validate(const char *key, const char *expected)
|
||||
{
|
||||
struct crypt_data data = {};
|
||||
return strcmp(expected, crypt_r(key, expected, &data)) == 0;
|
||||
}
|
||||
|
||||
#elif defined(HAVE_CRYPT)
|
||||
|
||||
/* crypt is not reentrant. A global mutex is neither ideal nor perfect, but good
|
||||
* enough if crypt_r support is unavailable
|
||||
*/
|
||||
AST_MUTEX_DEFINE_STATIC(crypt_mutex);
|
||||
|
||||
char *ast_crypt(const char *key, const char *salt)
|
||||
{
|
||||
const char *crypted;
|
||||
SCOPED_MUTEX(lock, &crypt_mutex);
|
||||
|
||||
crypted = crypt(key, salt);
|
||||
|
||||
/* Crypt may return success even if it doesn't recognize the salt. But
|
||||
* in those cases it always mangles the salt in some way.
|
||||
*/
|
||||
if (!crypted || !ast_begins_with(crypted, salt)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ast_strdup(crypted);
|
||||
}
|
||||
|
||||
int ast_crypt_validate(const char *key, const char *expected)
|
||||
{
|
||||
SCOPED_MUTEX(lock, &crypt_mutex);
|
||||
return strcmp(expected, crypt(key, expected)) == 0;
|
||||
}
|
||||
|
||||
#else /* No crypt support */
|
||||
|
||||
char *ast_crypt(const char *key, const char *salt)
|
||||
{
|
||||
ast_log(LOG_WARNING,
|
||||
"crypt() support not available; cannot encrypt password\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int ast_crypt_validate(const char *key, const char *expected)
|
||||
{
|
||||
ast_log(LOG_WARNING,
|
||||
"crypt() support not available; cannot validate password\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* No crypt support */
|
||||
|
||||
char *ast_crypt_encrypt(const char *key)
|
||||
{
|
||||
char salt[MAX_SALT_LEN] = {};
|
||||
while (gen_salt(salt, sizeof(salt)) == 0) {
|
||||
char *crypted = ast_crypt(key, salt);
|
||||
if (crypted) {
|
||||
return crypted;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
char *ast_utils_which(const char *binary, char *fullpath, size_t fullpath_size)
|
||||
{
|
||||
const char *envPATH = getenv("PATH");
|
||||
|
Reference in New Issue
Block a user