mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-29 18:19:30 +00:00
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:
2
Makefile
2
Makefile
@@ -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
12
acl.c
@@ -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";
|
||||
|
19
astobj2.c
19
astobj2.c
@@ -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;
|
||||
|
1348
channels/chan_iax2.c
1348
channels/chan_iax2.c
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
@@ -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.
|
||||
;
|
||||
|
@@ -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);
|
||||
|
@@ -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
81
include/asterisk/sha1.h
Normal 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
|
@@ -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
385
sha1.c
Normal 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
19
utils.c
@@ -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;
|
||||
|
Reference in New Issue
Block a user