Better SPA message validation upon SPA decrypt/decode.

Added SPA message validation calls to fko decoding routines to help
ensure that SPA messages conform to expected values.
This commit is contained in:
Michael Rash 2012-07-21 15:32:15 -04:00
parent 4c25aa17f3
commit 5ef07c73e2
11 changed files with 84 additions and 21 deletions

View File

@ -9,8 +9,10 @@ fwknop-2.0.1 (07//2012):
digest list right after the first access.conf stanza match, so when SPA digest list right after the first access.conf stanza match, so when SPA
packet data matched the second access.conf stanza a matching replay packet data matched the second access.conf stanza a matching replay
digest would already be there. digest would already be there.
- Added SPA message validation calls to fko decoding routines to help
ensure that SPA messages conform to expected values.
- Bug fix for PF firewalls: updated the PF anchor check to not rely on - Bug fix for PF firewalls: updated the PF anchor check to not rely on
listing the PF policy - use 'pfctl -s Anchor' instead. listing the PF policy - fwknopd now uses 'pfctl -s Anchor' instead.
- [test suite] Added parsing of valgrind output to produce a listing of - [test suite] Added parsing of valgrind output to produce a listing of
functions that have been flagged - this assists in the development functions that have been flagged - this assists in the development
process to ensure that fwknop is not leaking memory. process to ensure that fwknop is not leaking memory.

View File

@ -103,10 +103,10 @@ EXTRA_DIST = \
perl/FKO/lib/FKO.pm \ perl/FKO/lib/FKO.pm \
perl/FKO/lib/FKO_Constants.pl \ perl/FKO/lib/FKO_Constants.pl \
perl/FKO/Changes \ perl/FKO/Changes \
python/README \ python/README \
python/setup.py \ python/setup.py \
python/fkomodule.c \ python/fkomodule.c \
python/fko.py \ python/fko.py \
ShortLog* \ ShortLog* \
test/conf/client-gpg/pubring.gpg \ test/conf/client-gpg/pubring.gpg \
test/conf/client-gpg/secring.gpg \ test/conf/client-gpg/secring.gpg \

View File

@ -104,8 +104,6 @@ enum {
#define MAX_PORT 65535 #define MAX_PORT 65535
#define MAX_PORT_STR_LEN 6 #define MAX_PORT_STR_LEN 6
#define MAX_PROTO_STR_LEN 6 #define MAX_PROTO_STR_LEN 6
#define MAX_IPV4_STR_LEN 16
#define MIN_IPV4_STR_LEN 9
#define MAX_SERVER_STR_LEN 50 #define MAX_SERVER_STR_LEN 50
#define MAX_LINE_LEN 1024 #define MAX_LINE_LEN 1024

View File

@ -4,8 +4,8 @@ libfko_source_files = \
base64.c base64.h cipher_funcs.c cipher_funcs.h digest.c digest.h \ base64.c base64.h cipher_funcs.c cipher_funcs.h digest.c digest.h \
fko_client_timeout.c fko_common.h fko_digest.c fko_encode.c \ fko_client_timeout.c fko_common.h fko_digest.c fko_encode.c \
fko_decode.c fko_encryption.c fko_error.c fko_funcs.c fko_message.c \ fko_decode.c fko_encryption.c fko_error.c fko_funcs.c fko_message.c \
fko_nat_access.c fko_rand_value.c fko_server_auth.c fko.h fko_limits.h \ fko_message.h fko_nat_access.c fko_rand_value.c fko_server_auth.c \
fko_timestamp.c fko_user.c fko_util.h md5.c md5.h \ fko.h fko_limits.h fko_timestamp.c fko_user.c fko_util.h md5.c md5.h \
rijndael.c rijndael.h sha1.c sha1.h sha2.c sha2.h strlcat.c \ rijndael.c rijndael.h sha1.c sha1.h sha2.c sha2.h strlcat.c \
strlcpy.c fko_state.h fko_context.h gpgme_funcs.c gpgme_funcs.h strlcpy.c fko_state.h fko_context.h gpgme_funcs.c gpgme_funcs.h

View File

@ -32,6 +32,7 @@
#define FKO_H 1 #define FKO_H 1
#include <time.h> #include <time.h>
#include "fko_limits.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@ -120,6 +120,7 @@
#include "fko_limits.h" #include "fko_limits.h"
#include "fko_state.h" #include "fko_state.h"
#include "fko_context.h" #include "fko_context.h"
#include "fko_message.h"
/* Try to cover for those that do not have bzero. /* Try to cover for those that do not have bzero.
*/ */

View File

@ -281,6 +281,14 @@ fko_decode_spa_data(fko_ctx_t ctx)
b64_decode(tbuf, (unsigned char*)ctx->message); b64_decode(tbuf, (unsigned char*)ctx->message);
/* Require a message similar to: 1.2.3.4,tcp/22
*/
if(validate_access_msg(ctx->message) != FKO_SUCCESS)
{
free(tbuf);
return(FKO_ERROR_INVALID_DATA);
}
/* Extract nat_access string if the message_type indicates so. /* Extract nat_access string if the message_type indicates so.
*/ */
if( ctx->message_type == FKO_NAT_ACCESS_MSG if( ctx->message_type == FKO_NAT_ACCESS_MSG

View File

@ -48,6 +48,9 @@
#define MIN_SPA_FIELDS 6 #define MIN_SPA_FIELDS 6
#define MAX_SPA_FIELDS 10 #define MAX_SPA_FIELDS 10
#define MAX_IPV4_STR_LEN 16
#define MIN_IPV4_STR_LEN 7
/* Misc. /* Misc.
*/ */
#define FKO_ENCODE_TMP_BUF_SIZE 1024 #define FKO_ENCODE_TMP_BUF_SIZE 1024

View File

@ -32,15 +32,6 @@
#include "fko_common.h" #include "fko_common.h"
#include "fko.h" #include "fko.h"
/* SPA message format validation functions.
* (These called from the spa_message function here only).
*/
int validate_cmd_msg(const char *msg);
int validate_access_msg(const char *msg);
int validate_proto_port_spec(const char *msg);
int validate_nat_access_msg(const char *msg);
int got_allow_ip(const char *msg);
/* Set the SPA message type. /* Set the SPA message type.
*/ */
int int
@ -90,13 +81,13 @@ fko_set_spa_message(fko_ctx_t ctx, const char *msg)
/* Gotta have a valid string. /* Gotta have a valid string.
*/ */
if(msg == NULL || strlen(msg) == 0) if(msg == NULL || strnlen(msg, MAX_SPA_MESSAGE_SIZE) == 0)
return(FKO_ERROR_INVALID_DATA); return(FKO_ERROR_INVALID_DATA);
/* --DSS XXX: Bail out for now. But consider just /* --DSS XXX: Bail out for now. But consider just
* truncating in the future... * truncating in the future...
*/ */
if(strlen(msg) > MAX_SPA_MESSAGE_SIZE) if(strnlen(msg, MAX_SPA_MESSAGE_SIZE) == MAX_SPA_MESSAGE_SIZE)
return(FKO_ERROR_DATA_TOO_LARGE); return(FKO_ERROR_DATA_TOO_LARGE);
/* Basic message type and format checking... /* Basic message type and format checking...

45
lib/fko_message.h Normal file
View File

@ -0,0 +1,45 @@
/*
*****************************************************************************
*
* File: fko_message.h
*
* Author: Michael Rash
*
* Purpose: Provide validation functions for SPA messages
*
* Copyright 2012 Michael Rash (mbr@cipherdyne.org)
*
* License (GNU Public License):
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
*****************************************************************************
*/
#ifndef FKO_MESSAGE_H
#define FKO_MESSAGE_H 1
/* SPA message format validation functions.
*/
int validate_cmd_msg(const char *msg);
int validate_access_msg(const char *msg);
int validate_proto_port_spec(const char *msg);
int validate_nat_access_msg(const char *msg);
int got_allow_ip(const char *msg);
#endif /* FKO_MESSAGE_H */
/***EOF***/

View File

@ -569,7 +569,21 @@ incoming_spa(fko_srv_options_t *opts)
continue; continue;
} }
strlcpy(spadat.spa_message_src_ip, spadat.spa_message, (spa_ip_demark-spadat.spa_message)+1); strlcpy(spadat.spa_message_src_ip,
spadat.spa_message, (spa_ip_demark-spadat.spa_message)+1);
if(strnlen(spadat.spa_message_src_ip,
MIN_IPV4_STR_LEN) < MIN_IPV4_STR_LEN)
{
log_msg(LOG_WARNING, "(stanza #%d) Invalid source IP in SPA message, ignoring SPA packet",
stanza_num, fko_errstr(res));
if(ctx != NULL)
fko_destroy(ctx);
acc = acc->next;
break;
}
strlcpy(spadat.spa_message_remain, spa_ip_demark+1, 1024); strlcpy(spadat.spa_message_remain, spa_ip_demark+1, 1024);
/* If use source IP was requested (embedded IP of 0.0.0.0), make sure it /* If use source IP was requested (embedded IP of 0.0.0.0), make sure it