merged master 2.0.3 changes
This commit is contained in:
+96
-22
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
@@ -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';
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user