Merge code associated with AST-2009-006

(closes issue #12912)
Reported by: rathaus
Tested by: tilghman, russell, dvossel, dbrooks



git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@215958 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
David Vossel
2009-09-03 16:57:35 +00:00
parent cc0350b8ce
commit 6732590f86
14 changed files with 1829 additions and 135 deletions

View File

@@ -354,7 +354,7 @@ OBJS=io.o sched.o logger.o frame.o loader.o config.o channel.o \
astmm.o enum.o srv.o dns.o aescrypt.o aestab.o aeskey.o \
utils.o plc.o jitterbuf.o dnsmgr.o devicestate.o \
netsock.o slinfactory.o ast_expr2.o ast_expr2f.o \
cryptostub.o astobj2.o
cryptostub.o astobj2.o sha1.o
ifeq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/sys/poll.h),)
OBJS+= poll.o

12
acl.c
View File

@@ -74,14 +74,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
AST_MUTEX_DEFINE_STATIC(routeseq_lock);
#endif
struct ast_ha {
/* Host access rule */
struct in_addr netaddr;
struct in_addr netmask;
int sense;
struct ast_ha *next;
};
/* Default IP - if not otherwise set, don't breathe garbage */
static struct in_addr __ourip = { 0x00000000 };
@@ -102,7 +94,7 @@ void ast_free_ha(struct ast_ha *ha)
}
/* Copy HA structure */
static void ast_copy_ha(struct ast_ha *from, struct ast_ha *to)
void ast_copy_ha(const struct ast_ha *from, struct ast_ha *to)
{
memcpy(&to->netaddr, &from->netaddr, sizeof(from->netaddr));
memcpy(&to->netmask, &from->netmask, sizeof(from->netmask));
@@ -141,7 +133,7 @@ struct ast_ha *ast_duplicate_ha_list(struct ast_ha *original)
return ret; /* Return start of list */
}
struct ast_ha *ast_append_ha(char *sense, char *stuff, struct ast_ha *path)
struct ast_ha *ast_append_ha(char *sense, const char *stuff, struct ast_ha *path)
{
struct ast_ha *ha = malloc(sizeof(struct ast_ha));
char *nm = "255.255.255.255";

View File

@@ -413,7 +413,7 @@ void *ao2_callback(struct ao2_container *c,
const enum search_flags flags,
ao2_callback_fn cb_fn, void *arg)
{
int i, last; /* search boundaries */
int i, start, last; /* search boundaries */
void *ret = NULL;
if (INTERNAL_OBJ(c) == NULL) /* safety check on the argument */
@@ -443,13 +443,15 @@ void *ao2_callback(struct ao2_container *c,
* (this only for the time being. We need to optimize this.)
*/
if ((flags & OBJ_POINTER)) /* we know hash can handle this case */
i = c->hash_fn(arg, flags & OBJ_POINTER) % c->n_buckets;
start = i = c->hash_fn(arg, flags & OBJ_POINTER) % c->n_buckets;
else /* don't know, let's scan all buckets */
i = -1; /* XXX this must be fixed later. */
/* determine the search boundaries: i..last-1 */
if (i < 0) {
i = 0;
start = i = 0;
last = c->n_buckets;
} else if ((flags & OBJ_CONTINUE)) {
last = c->n_buckets;
} else {
last = i + 1;
@@ -505,6 +507,17 @@ void *ao2_callback(struct ao2_container *c,
}
}
AST_LIST_TRAVERSE_SAFE_END
if (ret) {
/* This assumes OBJ_MULTIPLE with !OBJ_NODATA is still not implemented */
break;
}
if (i == c->n_buckets - 1 && (flags & OBJ_POINTER) && (flags & OBJ_CONTINUE)) {
/* Move to the beginning to ensure we check every bucket */
i = -1;
last = start;
}
}
ao2_unlock(c);
return ret;

File diff suppressed because it is too large Load Diff

View File

@@ -433,7 +433,10 @@ void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, s
"TRANSFR",
"PROVISN",
"FWDWNLD",
"FWDATA "
"FWDATA ",
"TXMEDIA",
"RTKEY ",
"CTOKEN ",
};
const char *cmds[] = {
"(0?)",
@@ -873,6 +876,12 @@ int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen)
ies->rr_ooo = ntohl(get_unaligned_uint32(data + 2));
}
break;
case IAX_IE_CALLTOKEN:
if (len) {
ies->calltokendata = (unsigned char *) data + 2;
}
ies->calltoken = 1;
break;
default:
snprintf(tmp, (int)sizeof(tmp), "Ignoring unknown information element '%s' (%d) of length %d\n", iax_ie2str(ie), ie, len);
outputf(tmp);

View File

@@ -71,6 +71,8 @@ struct iax_ies {
unsigned short rr_delay;
unsigned int rr_dropped;
unsigned int rr_ooo;
unsigned char calltoken;
unsigned char *calltokendata;
};
#define DIRECTION_INGRESS 1

View File

@@ -67,6 +67,7 @@
#define IAX_COMMAND_PROVISION 35 /* Provision device */
#define IAX_COMMAND_FWDOWNL 36 /* Download firmware */
#define IAX_COMMAND_FWDATA 37 /* Firmware Data */
#define IAX_COMMAND_CALLTOKEN 40 /*! Call number token */
#define IAX_DEFAULT_REG_EXPIRE 60 /* By default require re-registration once per minute */
@@ -127,6 +128,7 @@
#define IAX_IE_RR_DELAY 49 /* Max playout delay for received frames (in ms) u16 */
#define IAX_IE_RR_DROPPED 50 /* Dropped frames (presumably by jitterbuf) u32 */
#define IAX_IE_RR_OOO 51 /* Frames received Out of Order u32 */
#define IAX_IE_CALLTOKEN 54 /* Call number security token */
#define IAX_AUTH_PLAINTEXT (1 << 0)

View File

@@ -286,6 +286,62 @@ autokill=yes
; has expired based on its registration interval, used the stored
; address information regardless. (yes|no)
;
; The following two options are used to disable call token validation for the
; purposes of interoperability with IAX2 endpoints that do not yet support it.
;
; Call token validation can be set as optional for a single IP address or IP
; address range by using the 'calltokenoptional' option. 'calltokenoptional' is
; only a global option.
;
;calltokenoptional=209.16.236.73/255.255.255.0
;
; In a peer/user/friend definition, the 'requirecalltoken' option may be used.
; By setting 'requirecalltoken=no', call token validation becomes optional for
; that peer/user. By setting 'requirecalltoken=auto', call token validation
; is optional until a call token supporting peer registers successfully using
; call token validation. This is used as an indication that from now on, we
; can require it from this peer. So, requirecalltoken is internally set to yes.
; By default, 'requirecalltoken=yes'.
;
;requirecalltoken=no
;
;
; These options are used to limit the amount of call numbers allocated to a
; single IP address. Before changing any of these values, it is highly encouraged
; to read the user guide associated with these options first. In most cases, the
; default values for these options are sufficient.
;
; The 'maxcallnumbers' option limits the amount of call numbers allowed for each
; individual remote IP address. Once an IP address reaches it's call number
; limit, no more new connections are allowed until the previous ones close. This
; option can be used in a peer definition as well, but only takes effect for
; the IP of a dynamic peer after it completes registration.
;
;maxcallnumbers=512
;
; The 'maxcallnumbers_nonvalidated' is used to set the combined number of call
; numbers that can be allocated for connections where call token validation
; has been disabled. Unlike the 'maxcallnumbers' option, this limit is not
; separate for each individual IP address. Any connection resulting in a
; non-call token validated call number being allocated contributes to this
; limit. For use cases, see the call token user guide. This option's
; default value of 8192 should be sufficient in most cases.
;
;maxcallnumbers_nonvalidated=1024
;
; The [callnumberlimits] section allows custom call number limits to be set
; for specific IP addresses and IP address ranges. These limits take precedence
; over the global 'maxcallnumbers' option, but may still be overridden by a
; peer defined 'maxcallnumbers' entry. Note that these limits take effect
; for every individual address within the range, not the range as a whole.
;
;[callnumberlimits]
;10.1.1.0/255.255.255.0 = 24
;10.1.2.0/255.255.255.0 = 32
;
; Guest sections for unauthenticated connection attempts. Just specify an
; empty secret, or provide no secret section.
;

View File

@@ -36,10 +36,17 @@ extern "C" {
/* Host based access control */
struct ast_ha;
struct ast_ha {
/* Host access rule */
struct in_addr netaddr;
struct in_addr netmask;
int sense;
struct ast_ha *next;
};
extern void ast_free_ha(struct ast_ha *ha);
extern struct ast_ha *ast_append_ha(char *sense, char *stuff, struct ast_ha *path);
void ast_free_ha(struct ast_ha *ha);
void ast_copy_ha(const struct ast_ha *from, struct ast_ha *to);
struct ast_ha *ast_append_ha(char *sense, const char *stuff, struct ast_ha *path);
extern int ast_apply_ha(struct ast_ha *ha, struct sockaddr_in *sin);
extern int ast_get_ip(struct sockaddr_in *sin, const char *value);
extern int ast_get_ip_or_srv(struct sockaddr_in *sin, const char *value, const char *service);

View File

@@ -273,6 +273,16 @@ enum search_flags {
* This implies that it can be passed to the object's hash function
* for optimized searching. */
OBJ_POINTER = (1 << 3),
/*!
* \brief Continue if a match is not found in the hashed out bucket
*
* This flag is to be used in combination with OBJ_POINTER. This tells
* the ao2_callback() core to keep searching through the rest of the
* buckets if a match is not found in the starting bucket defined by
* the hash value on the argument.
*/
OBJ_CONTINUE = (1 << 4),
};
/*!

81
include/asterisk/sha1.h Normal file
View File

@@ -0,0 +1,81 @@
/*
* sha1.h
*
* Description:
* This is the header file for code which implements the Secure
* Hashing Algorithm 1 as defined in FIPS PUB 180-1 published
* April 17, 1995.
*
* Many of the variable names in this code, especially the
* single character names, were used because those were the names
* used in the publication.
*
* Please read the file sha1.c for more information.
*
*/
#ifndef _SHA1_H_
#define _SHA1_H_
#if defined(__OpenBSD__) || defined( __FreeBSD__)
#include <inttypes.h>
#else
#include <stdint.h>
#endif
/*
* If you do not have the ISO standard stdint.h header file, then you
* must typdef the following:
* name meaning
* uint32_t unsigned 32 bit integer
* uint8_t unsigned 8 bit integer (i.e., unsigned char)
*
*/
#ifndef _SHA_enum_
#define _SHA_enum_
enum
{
shaSuccess = 0,
shaNull, /* Null pointer parameter */
shaInputTooLong, /* input data too long */
shaStateError /* called Input after Result */
};
#endif
#define SHA1HashSize 20
/*
* This structure will hold context information for the SHA-1
* hashing operation
*/
typedef struct SHA1Context
{
uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */
uint32_t Length_Low; /* Message length in bits */
uint32_t Length_High; /* Message length in bits */
/* Index into message block array */
uint32_t Message_Block_Index; /* 8 bits actually suffice */
uint8_t Message_Block[64]; /* 512-bit message blocks */
int Computed; /* Is the digest computed? */
int Corrupted; /* Is the message digest corrupted? */
} SHA1Context;
/*
* Function Prototypes
*/
int SHA1Reset( SHA1Context *);
int SHA1Input( SHA1Context *,
const uint8_t *,
unsigned int);
int SHA1Result( SHA1Context *,
uint8_t Message_Digest[SHA1HashSize]);
#endif

View File

@@ -144,6 +144,10 @@ struct hostent *ast_gethostbyname(const char *host, struct ast_hostent *hp);
\brief Produces MD5 hash based on input string */
void ast_md5_hash(char *output, char *input);
/* ast_sha1_hash
\brief Produces SHA1 hash based on input string */
void ast_sha1_hash(char *output, char *input);
int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max);
int ast_base64decode(unsigned char *dst, const char *src, int max);

385
sha1.c Normal file
View File

@@ -0,0 +1,385 @@
/*
*
* Based on the RFC 3174
*
* Full Copyright Statement
*
* Copyright (C) The Internet Society (2001). All Rights Reserved.
*
* This document and translations of it may be copied and furnished to
* others, and derivative works that comment on or otherwise explain it
* or assist in its implementation may be prepared, copied, published
* and distributed, in whole or in part, without restriction of any
* kind, provided that the above copyright notice and this paragraph are
* included on all such copies and derivative works. However, this
* document itself may not be modified in any way, such as by removing
* the copyright notice or references to the Internet Society or other
* Internet organizations, except as needed for the purpose of
* developing Internet standards in which case the procedures for
* copyrights defined in the Internet Standards process must be
* followed, or as required to translate it into languages other than
* English.
*
* The limited permissions granted above are perpetual and will not be
* revoked by the Internet Society or its successors or assigns.
* This document and the information contained herein is provided on an
* "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
* TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
* HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
*
*
* Description:
* This file implements the Secure Hashing Algorithm 1 as
* defined in FIPS PUB 180-1 published April 17, 1995.
*
* The SHA-1, produces a 160-bit message digest for a given
* data stream. It should take about 2**n steps to find a
* message with the same digest as a given message and
* 2**(n/2) to find any two messages with the same digest,
* when n is the digest size in bits. Therefore, this
* algorithm can serve as a means of providing a
* "fingerprint" for a message.
*
* Portability Issues:
* SHA-1 is defined in terms of 32-bit "words". This code
* uses <stdint.h> (included via "sha1.h" to define 32 and 8
* bit unsigned integer types. If your C compiler does not
* support 32 bit unsigned integers, this code is not
* appropriate.
*
* Caveats:
* SHA-1 is designed to work with messages less than 2^64 bits
* long. Although SHA-1 allows a message digest to be generated
* for messages of any number of bits less than 2^64, this
* implementation only works with messages with a length that is
* a multiple of the size of an 8-bit character.
*
*/
#include "asterisk/sha1.h"
/*
* Define the SHA1 circular left shift macro
*/
#define SHA1CircularShift(bits,word) \
(((word) << (bits)) | ((word) >> (32-(bits))))
/* Local Function Prototyptes */
void SHA1PadMessage(SHA1Context *);
void SHA1ProcessMessageBlock(SHA1Context *);
/*
* SHA1Reset
*
* Description:
* This function will initialize the SHA1Context in preparation
* for computing a new SHA1 message digest.
*
* Parameters:
* context: [in/out]
* The context to reset.
*
* Returns:
* sha Error Code.
*
*/
int SHA1Reset(SHA1Context *context)
{
if (!context) {
return shaNull;
}
context->Length_Low = 0;
context->Length_High = 0;
context->Message_Block_Index = 0;
context->Intermediate_Hash[0] = 0x67452301;
context->Intermediate_Hash[1] = 0xEFCDAB89;
context->Intermediate_Hash[2] = 0x98BADCFE;
context->Intermediate_Hash[3] = 0x10325476;
context->Intermediate_Hash[4] = 0xC3D2E1F0;
context->Computed = 0;
context->Corrupted = 0;
return shaSuccess;
}
/*
* SHA1Result
*
* Description:
* This function will return the 160-bit message digest into the
* Message_Digest array provided by the caller.
* NOTE: The first octet of hash is stored in the 0th element,
* the last octet of hash in the 19th element.
*
* Parameters:
* context: [in/out]
* The context to use to calculate the SHA-1 hash.
* Message_Digest: [out]
* Where the digest is returned.
*
* Returns:
* sha Error Code.
*
*/
int SHA1Result( SHA1Context *context,
uint8_t Message_Digest[SHA1HashSize])
{
int i;
if (!context || !Message_Digest) {
return shaNull;
}
if (context->Corrupted) {
return context->Corrupted;
}
if (!context->Computed) {
SHA1PadMessage(context);
for (i = 0; i < 64; ++i) {
/* message may be sensitive, clear it out */
context->Message_Block[i] = 0;
}
context->Length_Low = 0; /* and clear length */
context->Length_High = 0;
context->Computed = 1;
}
for (i = 0; i < SHA1HashSize; ++i) {
Message_Digest[i] = context->Intermediate_Hash[i >> 2] >> 8 * ( 3 - ( i & 0x03 ) );
}
return shaSuccess;
}
/*
* SHA1Input
*
* Description:
* This function accepts an array of octets as the next portion
* of the message.
*
* Parameters:
* context: [in/out]
* The SHA context to update
* message_array: [in]
* An array of characters representing the next portion of
* the message.
* length: [in]
* The length of the message in message_array
*
* Returns:
* sha Error Code.
*
*/
int SHA1Input(SHA1Context *context, const uint8_t *message_array, unsigned length)
{
if (!length) {
return shaSuccess;
}
if (!context || !message_array) {
return shaNull;
}
if (context->Computed) {
context->Corrupted = shaStateError;
return shaStateError;
}
if (context->Corrupted) {
return context->Corrupted;
}
while (length-- && !context->Corrupted) {
context->Message_Block[context->Message_Block_Index++] = (*message_array & 0xFF);
context->Length_Low += 8;
if (context->Length_Low == 0) {
context->Length_High++;
if (context->Length_High == 0) {
/* Message is too long */
context->Corrupted = 1;
}
}
if (context->Message_Block_Index == 64) {
SHA1ProcessMessageBlock(context);
}
message_array++;
}
return shaSuccess;
}
/*
* SHA1ProcessMessageBlock
*
* Description:
* This function will process the next 512 bits of the message
* stored in the Message_Block array.
*
* Parameters:
* None.
*
* Returns:
* Nothing.
*
* Comments:
* Many of the variable names in this code, especially the
* single character names, were used because those were the
* names used in the publication.
*
*
*/
void SHA1ProcessMessageBlock(SHA1Context *context)
{
const uint32_t K[] = { /* Constants defined in SHA-1 */
0x5A827999,
0x6ED9EBA1,
0x8F1BBCDC,
0xCA62C1D6
};
int t; /* Loop counter */
uint32_t temp; /* Temporary word value */
uint32_t W[80]; /* Word sequence */
uint32_t A, B, C, D, E; /* Word buffers */
/*
* Initialize the first 16 words in the array W
*/
for (t = 0; t < 16; t++) {
W[t] = context->Message_Block[t * 4] << 24;
W[t] |= context->Message_Block[t * 4 + 1] << 16;
W[t] |= context->Message_Block[t * 4 + 2] << 8;
W[t] |= context->Message_Block[t * 4 + 3];
}
for (t = 16; t < 80; t++) {
W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
}
A = context->Intermediate_Hash[0];
B = context->Intermediate_Hash[1];
C = context->Intermediate_Hash[2];
D = context->Intermediate_Hash[3];
E = context->Intermediate_Hash[4];
for (t = 0; t < 20; t++) {
temp = SHA1CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0];
E = D;
D = C;
C = SHA1CircularShift(30,B);
B = A;
A = temp;
}
for (t = 20; t < 40; t++) {
temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
E = D;
D = C;
C = SHA1CircularShift(30,B);
B = A;
A = temp;
}
for (t = 40; t < 60; t++) {
temp = SHA1CircularShift(5,A) + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
E = D;
D = C;
C = SHA1CircularShift(30,B);
B = A;
A = temp;
}
for (t = 60; t < 80; t++) {
temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
E = D;
D = C;
C = SHA1CircularShift(30,B);
B = A;
A = temp;
}
context->Intermediate_Hash[0] += A;
context->Intermediate_Hash[1] += B;
context->Intermediate_Hash[2] += C;
context->Intermediate_Hash[3] += D;
context->Intermediate_Hash[4] += E;
context->Message_Block_Index = 0;
}
/*
* SHA1PadMessage
*
* Description:
* According to the standard, the message must be padded to an even
* 512 bits. The first padding bit must be a '1'. The last 64
* bits represent the length of the original message. All bits in
* between should be 0. This function will pad the message
* according to those rules by filling the Message_Block array
* accordingly. It will also call the ProcessMessageBlock function
* provided appropriately. When it returns, it can be assumed that
* the message digest has been computed.
*
* Parameters:
* context: [in/out]
* The context to pad
* ProcessMessageBlock: [in]
* The appropriate SHA*ProcessMessageBlock function
* Returns:
* Nothing.
*
*/
void SHA1PadMessage(SHA1Context *context)
{
/*
* Check to see if the current message block is too small to hold
* the initial padding bits and length. If so, we will pad the
* block, process it, and then continue padding into a second
* block.
*/
if (context->Message_Block_Index > 55) {
context->Message_Block[context->Message_Block_Index++] = 0x80;
while (context->Message_Block_Index < 64) {
context->Message_Block[context->Message_Block_Index++] = 0;
}
SHA1ProcessMessageBlock(context);
while (context->Message_Block_Index < 56) {
context->Message_Block[context->Message_Block_Index++] = 0;
}
} else {
context->Message_Block[context->Message_Block_Index++] = 0x80;
while (context->Message_Block_Index < 56) {
context->Message_Block[context->Message_Block_Index++] = 0;
}
}
/*
* Store the message length as the last 8 octets
*/
context->Message_Block[56] = context->Length_High >> 24;
context->Message_Block[57] = context->Length_High >> 16;
context->Message_Block[58] = context->Length_High >> 8;
context->Message_Block[59] = context->Length_High;
context->Message_Block[60] = context->Length_Low >> 24;
context->Message_Block[61] = context->Length_Low >> 16;
context->Message_Block[62] = context->Length_Low >> 8;
context->Message_Block[63] = context->Length_Low;
SHA1ProcessMessageBlock(context);
}

19
utils.c
View File

@@ -45,6 +45,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/io.h"
#include "asterisk/logger.h"
#include "asterisk/md5.h"
#include "asterisk/sha1.h"
#include "asterisk/options.h"
#include "asterisk/compat.h"
@@ -297,6 +298,24 @@ void ast_md5_hash(char *output, char *input)
ptr += sprintf(ptr, "%2.2x", digest[x]);
}
/*! \brief Produce 40 char SHA1 hash of value. */
void ast_sha1_hash(char *output, char *input)
{
struct SHA1Context sha;
char *ptr;
int x;
uint8_t Message_Digest[20];
SHA1Reset(&sha);
SHA1Input(&sha, (const unsigned char *) input, strlen(input));
SHA1Result(&sha, Message_Digest);
ptr = output;
for (x = 0; x < 20; x++)
ptr += sprintf(ptr, "%2.2x", Message_Digest[x]);
}
int ast_base64decode(unsigned char *dst, const char *src, int max)
{
int cnt = 0;