merged master 2.0.3 changes

This commit is contained in:
Michael Rash
2012-08-31 21:43:55 -04:00
27 changed files with 846 additions and 133 deletions
+96 -22
View File
@@ -213,7 +213,7 @@ add_acc_force_nat(fko_srv_options_t *opts, acc_stanza_t *curr_acc, const char *v
/* Take an IP or Subnet/Mask and convert it to mask for later
* comparisons of incoming source IPs against this mask.
*/
static void
static int
add_source_mask(fko_srv_options_t *opts, acc_stanza_t *acc, const char *ip)
{
char *ndx;
@@ -278,7 +278,11 @@ add_source_mask(fko_srv_options_t *opts, acc_stanza_t *acc, const char *ip)
log_msg(LOG_ERR,
"Fatal error parsing IP to int for: %s", ip_str
);
clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
free(new_sle);
new_sle = NULL;
return 0;
}
/* Store our mask converted from CIDR to a 32-bit value.
@@ -290,15 +294,17 @@ add_source_mask(fko_srv_options_t *opts, acc_stanza_t *acc, const char *ip)
*/
new_sle->maddr = ntohl(in.s_addr) & new_sle->mask;
}
return 1;
}
/* Expand the access SOURCE string to a list of masks.
*/
void
static int
expand_acc_source(fko_srv_options_t *opts, acc_stanza_t *acc)
{
char *ndx, *start;
char buf[32];
char buf[ACCESS_BUF_LEN];
int res = 1;
start = acc->source;
@@ -311,8 +317,15 @@ expand_acc_source(fko_srv_options_t *opts, acc_stanza_t *acc)
while(isspace(*start))
start++;
if(((ndx-start)+1) >= ACCESS_BUF_LEN)
return 0;
strlcpy(buf, start, (ndx-start)+1);
add_source_mask(opts, acc, buf);
res = add_source_mask(opts, acc, buf);
if(res == 0)
return res;
start = ndx+1;
}
}
@@ -322,15 +335,21 @@ expand_acc_source(fko_srv_options_t *opts, acc_stanza_t *acc)
while(isspace(*start))
start++;
if(((ndx-start)+1) >= ACCESS_BUF_LEN)
return 0;
strlcpy(buf, start, (ndx-start)+1);
add_source_mask(opts, acc, buf);
res = add_source_mask(opts, acc, buf);
return res;
}
static int
parse_proto_and_port(char *pstr, int *proto, int *port)
{
char *ndx;
char proto_str[32];
char proto_str[ACCESS_BUF_LEN];
/* Parse the string into its components.
*/
@@ -342,10 +361,24 @@ parse_proto_and_port(char *pstr, int *proto, int *port)
return(-1);
}
strlcpy(proto_str, pstr, (ndx - pstr)+1);
if(((ndx - pstr)+1) >= ACCESS_BUF_LEN)
{
log_msg(LOG_ERR,
"Parse error on access port entry: %s", pstr);
return(-1);
}
strlcpy(proto_str, pstr, (ndx - pstr)+1);
*port = atoi(ndx+1);
if((*port < 0) || (*port > MAX_PORT))
{
log_msg(LOG_ERR,
"Invalid port in access request: %s", pstr);
return(-1);
}
if(strcasecmp(proto_str, "tcp") == 0)
*proto = PROTO_TCP;
else if(strcasecmp(proto_str, "udp") == 0)
@@ -354,7 +387,6 @@ parse_proto_and_port(char *pstr, int *proto, int *port)
{
log_msg(LOG_ERR,
"Invalid protocol in access port entry: %s", pstr);
return(-1);
}
@@ -457,15 +489,15 @@ add_string_list_ent(acc_string_list_t **stlist, const char *str_str)
/* Expand a proto/port access string to a list of access proto-port struct.
*/
void
int
expand_acc_port_list(acc_port_list_t **plist, char *plist_str)
{
char *ndx, *start;
char buf[32];
char buf[ACCESS_BUF_LEN];
start = plist_str;
for(ndx = start; *ndx; ndx++)
for(ndx = start; *ndx != '\0'; ndx++)
{
if(*ndx == ',')
{
@@ -474,6 +506,9 @@ expand_acc_port_list(acc_port_list_t **plist, char *plist_str)
while(isspace(*start))
start++;
if(((ndx-start)+1) >= ACCESS_BUF_LEN)
return 0;
strlcpy(buf, start, (ndx-start)+1);
add_port_list_ent(plist, buf);
start = ndx+1;
@@ -485,9 +520,14 @@ expand_acc_port_list(acc_port_list_t **plist, char *plist_str)
while(isspace(*start))
start++;
if(((ndx-start)+1) >= ACCESS_BUF_LEN)
return 0;
strlcpy(buf, start, (ndx-start)+1);
add_port_list_ent(plist, buf);
return 1;
}
/* Expand a comma-separated string into a simple acc_string_list.
@@ -652,7 +692,11 @@ expand_acc_ent_lists(fko_srv_options_t *opts)
{
/* Expand the source string to 32-bit integer masks foreach entry.
*/
expand_acc_source(opts, acc);
if(expand_acc_source(opts, acc) == 0)
{
acc = acc->next;
continue;
}
/* Now expand the open_ports string.
*/
@@ -782,8 +826,9 @@ set_acc_defaults(fko_srv_options_t *opts)
static int
acc_data_is_valid(const acc_stanza_t *acc)
{
if(acc->key_len < 0 || ((acc->key == NULL && acc->key_base64 == NULL)
&& (acc->gpg_decrypt_pw == NULL || !strlen(acc->gpg_decrypt_pw))))
if(((acc->key == NULL || !strlen(acc->key))
&& (acc->gpg_decrypt_pw == NULL || !strlen(acc->gpg_decrypt_pw)))
|| (acc->use_rijndael == 0 && acc->use_gpg == 0 && acc->gpg_allow_no_pw == 0))
{
fprintf(stderr,
"[*] No keys found for access stanza source: '%s'\n", acc->source
@@ -824,6 +869,8 @@ parse_access_file(fko_srv_options_t *opts)
clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
}
verify_file_perms_ownership(opts->config[CONF_ACCESS_FILE]);
if ((file_ptr = fopen(opts->config[CONF_ACCESS_FILE], "r")) == NULL)
{
fprintf(stderr, "[*] Could not open access file: %s\n",
@@ -934,6 +981,7 @@ parse_access_file(fko_srv_options_t *opts)
}
add_acc_string(&(curr_acc->key), val);
curr_acc->key_len = strlen(curr_acc->key);
add_acc_bool(&(curr_acc->use_rijndael), "Y");
}
else if(CONF_VAR_IS(var, "KEY_BASE64"))
{
@@ -954,6 +1002,7 @@ parse_access_file(fko_srv_options_t *opts)
add_acc_string(&(curr_acc->key_base64), val);
add_acc_b64_string(&(curr_acc->key),
&(curr_acc->key_len), curr_acc->key_base64);
add_acc_bool(&(curr_acc->use_rijndael), "Y");
}
else if(CONF_VAR_IS(var, "HMAC_KEY_BASE64"))
{
@@ -1049,13 +1098,18 @@ parse_access_file(fko_srv_options_t *opts)
clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
}
add_acc_string(&(curr_acc->gpg_decrypt_pw), val);
add_acc_bool(&(curr_acc->use_gpg), "Y");
}
else if(CONF_VAR_IS(var, "GPG_ALLOW_NO_PW"))
{
if(curr_acc->gpg_decrypt_pw != NULL && curr_acc->gpg_decrypt_pw[0] != '\0')
free(curr_acc->gpg_decrypt_pw);
add_acc_string(&(curr_acc->gpg_decrypt_pw), "");
add_acc_bool(&(curr_acc->gpg_allow_no_pw), val);
if(curr_acc->gpg_allow_no_pw == 1)
{
add_acc_bool(&(curr_acc->use_gpg), "Y");
if(curr_acc->gpg_decrypt_pw != NULL && curr_acc->gpg_decrypt_pw[0] != '\0')
free(curr_acc->gpg_decrypt_pw);
add_acc_string(&(curr_acc->gpg_decrypt_pw), "");
}
}
else if(CONF_VAR_IS(var, "GPG_REQUIRE_SIG"))
{
@@ -1199,9 +1253,9 @@ compare_port_list(acc_port_list_t *in, acc_port_list_t *ac, const int match_any)
int
acc_check_port_access(acc_stanza_t *acc, char *port_str)
{
int res = 1;
int res = 1, ctr = 0;
char buf[32];
char buf[ACCESS_BUF_LEN];
char *ndx, *start;
acc_port_list_t *o_pl = acc->oport_list;
@@ -1214,14 +1268,34 @@ acc_check_port_access(acc_stanza_t *acc, char *port_str)
/* Create our own internal port_list from the incoming SPA data
* for comparison.
*/
for(ndx = start; *ndx; ndx++)
for(ndx = start; *ndx != '\0'; ndx++)
{
if(*ndx == ',')
{
if((ctr >= ACCESS_BUF_LEN)
|| (((ndx-start)+1) >= ACCESS_BUF_LEN))
{
log_msg(LOG_ERR,
"Unable to create acc_port_list from incoming data: %s",
port_str
);
return(0);
}
strlcpy(buf, start, (ndx-start)+1);
add_port_list_ent(&in_pl, buf);
start = ndx+1;
ctr = 0;
}
ctr++;
}
if((ctr >= ACCESS_BUF_LEN)
|| (((ndx-start)+1) >= ACCESS_BUF_LEN))
{
log_msg(LOG_ERR,
"Unable to create acc_port_list from incoming data: %s",
port_str
);
return(0);
}
strlcpy(buf, start, (ndx-start)+1);
add_port_list_ent(&in_pl, buf);
+3 -1
View File
@@ -34,6 +34,8 @@
#define PROTO_TCP 6
#define PROTO_UDP 17
#define ACCESS_BUF_LEN 32
/* Function Prototypes
*/
void parse_access_file(fko_srv_options_t *opts);
@@ -41,7 +43,7 @@ int compare_addr_list(acc_int_list_t *source_list, const uint32_t ip);
int acc_check_port_access(acc_stanza_t *acc, char *port_str);
int acc_check_gpg_remote_id(acc_stanza_t *acc, const char *gpg_id);
void dump_access_list(const fko_srv_options_t *opts);
void expand_acc_port_list(acc_port_list_t **plist, char *plist_str);
int expand_acc_port_list(acc_port_list_t **plist, char *plist_str);
void free_acc_stanzas(fko_srv_options_t *opts);
void free_acc_port_list(acc_port_list_t *plist);
+2
View File
@@ -200,6 +200,8 @@ parse_config_file(fko_srv_options_t *opts, const char *config_file)
clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
}
verify_file_perms_ownership(config_file);
if ((cfile_ptr = fopen(config_file, "r")) == NULL)
{
fprintf(stderr, "[*] Could not open config file: %s\n",
+2 -1
View File
@@ -582,7 +582,8 @@ process_spa_request(const fko_srv_options_t *opts, const acc_stanza_t *acc, spa_
/* Parse and expand our access message.
*/
expand_acc_port_list(&port_list, spadat->spa_message_remain);
if(expand_acc_port_list(&port_list, spadat->spa_message_remain) != 1)
return res;
/* Start at the top of the proto-port list...
*/
+16 -2
View File
@@ -496,10 +496,22 @@ make_dir_path(const char *run_dir)
if(stat(tmp_path, &st) != 0)
{
if(errno == ENOENT)
{
res = mkdir(tmp_path, S_IRWXU);
if(res != 0)
return res;
if(res != 0)
return res;
/* run stat() against the component since we just
* created it
*/
if(stat(tmp_path, &st) != 0)
{
log_msg(LOG_ERR,
"Could not create component: %s of %s\n\n", tmp_path, run_dir
);
return(ENOTDIR);
}
}
}
if(! S_ISDIR(st.st_mode))
@@ -664,10 +676,12 @@ get_running_pid(const fko_srv_options_t *opts)
char buf[PID_BUFLEN] = {0};
pid_t rpid = 0;
op_fd = open(opts->config[CONF_FWKNOP_PID_FILE], O_RDONLY);
if(op_fd > 0)
{
verify_file_perms_ownership(opts->config[CONF_FWKNOP_PID_FILE]);
if (read(op_fd, buf, PID_BUFLEN) > 0)
{
buf[PID_BUFLEN-1] = '\0';
+3
View File
@@ -278,6 +278,7 @@ typedef struct acc_stanza
char *hmac_key;
int hmac_key_len;
char *hmac_key_base64;
unsigned char use_rijndael;
int fw_access_timeout;
unsigned char enable_cmd_exec;
char *cmd_exec_user;
@@ -289,6 +290,8 @@ typedef struct acc_stanza
char *gpg_decrypt_pw;
unsigned char gpg_require_sig;
unsigned char gpg_ignore_sig_error;
unsigned char use_gpg;
unsigned char gpg_allow_no_pw;
char *gpg_remote_id;
acc_string_list_t *gpg_remote_id_list;
time_t access_expire_time;
+5 -13
View File
@@ -363,7 +363,7 @@ incoming_spa(fko_srv_options_t *opts)
*/
enc_type = fko_encryption_type((char *)spa_pkt->packet_data);
if(enc_type == FKO_ENCRYPTION_RIJNDAEL)
if(acc->use_rijndael && enc_type == FKO_ENCRYPTION_RIJNDAEL)
{
if (acc->key == NULL)
{
@@ -379,12 +379,12 @@ incoming_spa(fko_srv_options_t *opts)
acc->key, acc->key_len, acc->encryption_mode, acc->hmac_key,
acc->hmac_key_len);
}
else if(enc_type == FKO_ENCRYPTION_GPG)
else if(acc->use_gpg && enc_type == FKO_ENCRYPTION_GPG)
{
/* For GPG we create the new context without decrypting on the fly
* so we can set some GPG parameters first.
*/
if(acc->gpg_decrypt_pw != NULL)
if(acc->gpg_decrypt_pw != NULL || acc->gpg_allow_no_pw)
{
res = fko_new_with_data(&ctx, (char *)spa_pkt->packet_data, NULL,
0, acc->encryption_mode, NULL, 0);
@@ -443,19 +443,11 @@ incoming_spa(fko_srv_options_t *opts)
res = fko_decrypt_spa_data(ctx, acc->gpg_decrypt_pw, 0);
}
else
{
log_msg(LOG_ERR,
"(stanza #%d) No GPG_DECRYPT_PW for GPG encrypted messages, set GPG_ALLOW_NO_PW",
stanza_num
);
acc = acc->next;
continue;
}
}
else
{
log_msg(LOG_ERR, "(stanza #%d) Unable to determing encryption type. Got type=%i.",
log_msg(LOG_ERR,
"(stanza #%d) No stanza encryption mode match for encryption type: %i.",
stanza_num, enc_type);
acc = acc->next;
continue;
+5 -1
View File
@@ -261,10 +261,14 @@ replay_file_cache_init(fko_srv_options_t *opts)
fprintf(digest_file_ptr,
"# <digest> <proto> <src_ip> <src_port> <dst_ip> <dst_port> <time>\n");
fclose(digest_file_ptr);
set_file_perms(opts->config[CONF_DIGEST_FILE]);
return(0);
}
/* File exist, and we have access - create in-memory digest cache
verify_file_perms_ownership(opts->config[CONF_DIGEST_FILE]);
/* File exists, and we have access - create in-memory digest cache
*/
if ((digest_file_ptr = fopen(opts->config[CONF_DIGEST_FILE], "r")) == NULL)
{
+70 -2
View File
@@ -147,19 +147,87 @@ dump_ctx(fko_ctx_t ctx)
int
is_valid_dir(const char *path)
{
struct stat st;
#if HAVE_STAT
struct stat st;
/* If we are unable to stat the given dir, then return with error.
*/
if(stat(path, &st) != 0)
return(0);
{
fprintf(stderr, "[-] unable to stat() directory: %s: %s\n",
path, strerror(errno));
exit(EXIT_FAILURE);
}
if(!S_ISDIR(st.st_mode))
return(0);
#endif /* HAVE_STAT */
return(1);
}
int
set_file_perms(const char *file)
{
int res = 0;
res = chmod(file, S_IRUSR | S_IWUSR);
if(res != 0)
{
fprintf(stderr, "[-] unable to chmod file %s to user read/write: %s\n",
file, strerror(errno));
}
return res;
}
int
verify_file_perms_ownership(const char *file)
{
#if HAVE_STAT
struct stat st;
/* Every file that the fwknop client deals with should be owned
* by the user and permissions set to 600 (user read/write)
*/
if((stat(file, &st)) != 0)
{
fprintf(stderr, "[-] unable to stat() file: %s: %s\n",
file, strerror(errno));
exit(EXIT_FAILURE);
}
/* Make sure it is a regular file
*/
if(S_ISREG(st.st_mode) != 1 && S_ISLNK(st.st_mode) != 1)
{
fprintf(stderr,
"[-] file: %s is not a regular file or symbolic link.\n",
file
);
return 0;
}
if((st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) != (S_IRUSR|S_IWUSR))
{
fprintf(stderr,
"[-] file: %s permissions should only be user read/write (0600, -rw-------)\n",
file
);
return 0;
}
if(st.st_uid != getuid())
{
fprintf(stderr, "[-] file: %s not owned by current effective user id\n",
file);
return 0;
}
#endif
return 1;
}
/* Determine if a buffer contains only characters from the base64
* encoding set
*/
+2
View File
@@ -62,6 +62,8 @@ void hex_dump(const unsigned char *data, const int size);
char* dump_ctx(fko_ctx_t ctx);
int is_base64(const unsigned char *buf, const unsigned short int len);
int is_valid_dir(const char *path);
int set_file_perms(const char *file);
int verify_file_perms_ownership(const char *file);
size_t strlcat(char *dst, const char *src, size_t siz);
size_t strlcpy(char *dst, const char *src, size_t siz);