[server] additional work on splitting incoming_spa() loop into functions
This commit is contained in:
@@ -50,7 +50,7 @@
|
||||
* error code value if there is any indication the data is not valid spa data.
|
||||
*/
|
||||
static int
|
||||
preprocess_spa_data(fko_srv_options_t *opts, spa_pkt_info_t *spa_pkt)
|
||||
preprocess_spa_data(const fko_srv_options_t *opts, spa_pkt_info_t *spa_pkt)
|
||||
{
|
||||
|
||||
char *ndx = (char *)&(spa_pkt->packet_data);
|
||||
@@ -269,6 +269,29 @@ get_spa_data_fields(fko_ctx_t ctx, spa_data_t *spdat)
|
||||
return(res);
|
||||
}
|
||||
|
||||
static int
|
||||
check_pkt_age(const fko_srv_options_t *opts, spa_data_t *spadat,
|
||||
const int stanza_num, const int conf_pkt_age)
|
||||
{
|
||||
int ts_diff;
|
||||
time_t now_ts;
|
||||
|
||||
if(strncasecmp(opts->config[CONF_ENABLE_SPA_PACKET_AGING], "Y", 1) == 0)
|
||||
{
|
||||
time(&now_ts);
|
||||
|
||||
ts_diff = labs(now_ts - spadat->timestamp);
|
||||
|
||||
if(ts_diff > conf_pkt_age)
|
||||
{
|
||||
log_msg(LOG_WARNING, "[%s] (stanza #%d) SPA data time difference is too great (%i seconds).",
|
||||
spadat->pkt_source_ip, stanza_num, ts_diff);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
check_stanza_expiration(acc_stanza_t *acc, spa_data_t *spadat,
|
||||
const int stanza_num)
|
||||
@@ -489,173 +512,365 @@ process_cmd_msg(fko_srv_options_t *opts, acc_stanza_t *acc,
|
||||
}
|
||||
|
||||
static int
|
||||
handle_gpg_enc(acc_stanza_t *acc, spa_pkt_info_t *spa_pkt,
|
||||
spa_data_t *spadat, fko_ctx_t *ctx, int *attempted_decrypt,
|
||||
const int stanza_num, int *res)
|
||||
check_mode_ctx(spa_data_t *spadat, fko_ctx_t *ctx, int attempted_decrypt,
|
||||
const int enc_type, const int stanza_num, const int res)
|
||||
{
|
||||
/* 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 || acc->gpg_allow_no_pw)
|
||||
if(attempted_decrypt == 0)
|
||||
{
|
||||
*res = fko_new_with_data(ctx, (char *)spa_pkt->packet_data, NULL,
|
||||
0, FKO_ENC_MODE_ASYMMETRIC, acc->hmac_key,
|
||||
acc->hmac_key_len, acc->hmac_type);
|
||||
log_msg(LOG_ERR,
|
||||
"[%s] (stanza #%d) No stanza encryption mode match for encryption type: %i.",
|
||||
spadat->pkt_source_ip, stanza_num, enc_type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(*res != FKO_SUCCESS)
|
||||
/* Do we have a valid FKO context? Did the SPA decrypt properly?
|
||||
*/
|
||||
if(res != FKO_SUCCESS)
|
||||
{
|
||||
log_msg(LOG_WARNING, "[%s] (stanza #%d) Error creating fko context: %s",
|
||||
spadat->pkt_source_ip, stanza_num, fko_errstr(res));
|
||||
|
||||
if(IS_GPG_ERROR(res))
|
||||
log_msg(LOG_WARNING, "[%s] (stanza #%d) - GPG ERROR: %s",
|
||||
spadat->pkt_source_ip, stanza_num, fko_gpg_errstr(*ctx));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_rijndael_enc(acc_stanza_t *acc, spa_pkt_info_t *spa_pkt,
|
||||
spa_data_t *spadat, fko_ctx_t *ctx, int *attempted_decrypt,
|
||||
int *cmd_exec_success, const int enc_type, const int stanza_num,
|
||||
int *res)
|
||||
{
|
||||
if(acc->use_rijndael)
|
||||
{
|
||||
if(acc->key == NULL)
|
||||
{
|
||||
log_msg(LOG_WARNING,
|
||||
"[%s] (stanza #%d) Error creating fko context (before decryption): %s",
|
||||
spadat->pkt_source_ip, stanza_num, fko_errstr(*res)
|
||||
log_msg(LOG_ERR,
|
||||
"[%s] (stanza #%d) No KEY for RIJNDAEL encrypted messages",
|
||||
spadat->pkt_source_ip, stanza_num
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set whatever GPG parameters we have.
|
||||
/* Command mode messages may be quite long
|
||||
*/
|
||||
if(acc->gpg_exe != NULL)
|
||||
if(acc->enable_cmd_exec || enc_type == FKO_ENCRYPTION_RIJNDAEL)
|
||||
{
|
||||
*res = fko_set_gpg_exe(*ctx, acc->gpg_exe);
|
||||
*res = fko_new_with_data(ctx, (char *)spa_pkt->packet_data,
|
||||
acc->key, acc->key_len, acc->encryption_mode, acc->hmac_key,
|
||||
acc->hmac_key_len, acc->hmac_type);
|
||||
*attempted_decrypt = 1;
|
||||
if(*res == FKO_SUCCESS)
|
||||
*cmd_exec_success = 1;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_gpg_enc(acc_stanza_t *acc, spa_pkt_info_t *spa_pkt,
|
||||
spa_data_t *spadat, fko_ctx_t *ctx, int *attempted_decrypt,
|
||||
const int cmd_exec_success, const int enc_type,
|
||||
const int stanza_num, int *res)
|
||||
{
|
||||
if(acc->use_gpg && enc_type == FKO_ENCRYPTION_GPG && cmd_exec_success == 0)
|
||||
{
|
||||
/* 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 || acc->gpg_allow_no_pw)
|
||||
{
|
||||
*res = fko_new_with_data(ctx, (char *)spa_pkt->packet_data, NULL,
|
||||
0, FKO_ENC_MODE_ASYMMETRIC, acc->hmac_key,
|
||||
acc->hmac_key_len, acc->hmac_type);
|
||||
|
||||
if(*res != FKO_SUCCESS)
|
||||
{
|
||||
log_msg(LOG_WARNING,
|
||||
"[%s] (stanza #%d) Error setting GPG path %s: %s",
|
||||
spadat->pkt_source_ip, stanza_num, acc->gpg_exe,
|
||||
fko_errstr(*res)
|
||||
"[%s] (stanza #%d) Error creating fko context (before decryption): %s",
|
||||
spadat->pkt_source_ip, stanza_num, fko_errstr(*res)
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(acc->gpg_home_dir != NULL)
|
||||
{
|
||||
*res = fko_set_gpg_home_dir(*ctx, acc->gpg_home_dir);
|
||||
if(*res != FKO_SUCCESS)
|
||||
{
|
||||
log_msg(LOG_WARNING,
|
||||
"[%s] (stanza #%d) Error setting GPG keyring path to %s: %s",
|
||||
spadat->pkt_source_ip, stanza_num, acc->gpg_home_dir,
|
||||
fko_errstr(*res)
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(acc->gpg_decrypt_id != NULL)
|
||||
fko_set_gpg_recipient(*ctx, acc->gpg_decrypt_id);
|
||||
|
||||
/* If GPG_REQUIRE_SIG is set for this acc stanza, then set
|
||||
* the FKO context accordingly and check the other GPG Sig-
|
||||
* related parameters. This also applies when REMOTE_ID is
|
||||
* set.
|
||||
*/
|
||||
if(acc->gpg_require_sig)
|
||||
{
|
||||
fko_set_gpg_signature_verify(*ctx, 1);
|
||||
|
||||
/* Set whether or not to ignore signature verification errors.
|
||||
/* Set whatever GPG parameters we have.
|
||||
*/
|
||||
fko_set_gpg_ignore_verify_error(*ctx, acc->gpg_ignore_sig_error);
|
||||
}
|
||||
else
|
||||
{
|
||||
fko_set_gpg_signature_verify(*ctx, 0);
|
||||
fko_set_gpg_ignore_verify_error(*ctx, 1);
|
||||
}
|
||||
if(acc->gpg_exe != NULL)
|
||||
{
|
||||
*res = fko_set_gpg_exe(*ctx, acc->gpg_exe);
|
||||
if(*res != FKO_SUCCESS)
|
||||
{
|
||||
log_msg(LOG_WARNING,
|
||||
"[%s] (stanza #%d) Error setting GPG path %s: %s",
|
||||
spadat->pkt_source_ip, stanza_num, acc->gpg_exe,
|
||||
fko_errstr(*res)
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now decrypt the data.
|
||||
*/
|
||||
*res = fko_decrypt_spa_data(*ctx, acc->gpg_decrypt_pw, 0);
|
||||
*attempted_decrypt = 1;
|
||||
if(acc->gpg_home_dir != NULL)
|
||||
{
|
||||
*res = fko_set_gpg_home_dir(*ctx, acc->gpg_home_dir);
|
||||
if(*res != FKO_SUCCESS)
|
||||
{
|
||||
log_msg(LOG_WARNING,
|
||||
"[%s] (stanza #%d) Error setting GPG keyring path to %s: %s",
|
||||
spadat->pkt_source_ip, stanza_num, acc->gpg_home_dir,
|
||||
fko_errstr(*res)
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(acc->gpg_decrypt_id != NULL)
|
||||
fko_set_gpg_recipient(*ctx, acc->gpg_decrypt_id);
|
||||
|
||||
/* If GPG_REQUIRE_SIG is set for this acc stanza, then set
|
||||
* the FKO context accordingly and check the other GPG Sig-
|
||||
* related parameters. This also applies when REMOTE_ID is
|
||||
* set.
|
||||
*/
|
||||
if(acc->gpg_require_sig)
|
||||
{
|
||||
fko_set_gpg_signature_verify(*ctx, 1);
|
||||
|
||||
/* Set whether or not to ignore signature verification errors.
|
||||
*/
|
||||
fko_set_gpg_ignore_verify_error(*ctx, acc->gpg_ignore_sig_error);
|
||||
}
|
||||
else
|
||||
{
|
||||
fko_set_gpg_signature_verify(*ctx, 0);
|
||||
fko_set_gpg_ignore_verify_error(*ctx, 1);
|
||||
}
|
||||
|
||||
/* Now decrypt the data.
|
||||
*/
|
||||
*res = fko_decrypt_spa_data(*ctx, acc->gpg_decrypt_pw, 0);
|
||||
*attempted_decrypt = 1;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_gpg_sigs(acc_stanza_t *acc, spa_data_t *spadat,
|
||||
fko_ctx_t *ctx, const int stanza_num, int *res)
|
||||
fko_ctx_t *ctx, const int enc_type, const int stanza_num, int *res)
|
||||
{
|
||||
char *gpg_id, *gpg_fpr;
|
||||
acc_string_list_t *gpg_id_ndx;
|
||||
acc_string_list_t *gpg_fpr_ndx;
|
||||
unsigned char is_gpg_match = 0;
|
||||
|
||||
*res = fko_get_gpg_signature_id(*ctx, &gpg_id);
|
||||
if(*res != FKO_SUCCESS)
|
||||
if(enc_type == FKO_ENCRYPTION_GPG && acc->gpg_require_sig)
|
||||
{
|
||||
log_msg(LOG_WARNING,
|
||||
"[%s] (stanza #%d) Error pulling the GPG signature ID from the context: %s",
|
||||
spadat->pkt_source_ip, stanza_num, fko_gpg_errstr(*ctx));
|
||||
return 0;
|
||||
}
|
||||
|
||||
*res = fko_get_gpg_signature_fpr(*ctx, &gpg_fpr);
|
||||
if(*res != FKO_SUCCESS)
|
||||
{
|
||||
log_msg(LOG_WARNING,
|
||||
"[%s] (stanza #%d) Error pulling the GPG fingerprint from the context: %s",
|
||||
spadat->pkt_source_ip, stanza_num, fko_gpg_errstr(*ctx));
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_msg(LOG_INFO, "[%s] (stanza #%d) Incoming SPA data signed by '%s' (fingerprint '%s').",
|
||||
spadat->pkt_source_ip, stanza_num, gpg_id, gpg_fpr);
|
||||
|
||||
/* prefer GnuPG fingerprint match if so configured
|
||||
*/
|
||||
if(acc->gpg_remote_fpr != NULL)
|
||||
{
|
||||
is_gpg_match = 0;
|
||||
for(gpg_fpr_ndx = acc->gpg_remote_fpr_list;
|
||||
gpg_fpr_ndx != NULL; gpg_fpr_ndx=gpg_fpr_ndx->next)
|
||||
{
|
||||
*res = fko_gpg_signature_fpr_match(*ctx,
|
||||
gpg_fpr_ndx->str, &is_gpg_match);
|
||||
if(*res != FKO_SUCCESS)
|
||||
{
|
||||
log_msg(LOG_WARNING,
|
||||
"[%s] (stanza #%d) Error in GPG signature comparision: %s",
|
||||
spadat->pkt_source_ip, stanza_num, fko_gpg_errstr(*ctx));
|
||||
return 0;
|
||||
}
|
||||
if(is_gpg_match)
|
||||
break;
|
||||
}
|
||||
if(! is_gpg_match)
|
||||
*res = fko_get_gpg_signature_id(*ctx, &gpg_id);
|
||||
if(*res != FKO_SUCCESS)
|
||||
{
|
||||
log_msg(LOG_WARNING,
|
||||
"[%s] (stanza #%d) Incoming SPA packet signed by: %s, but that fingerprint is not in the GPG_FINGERPRINT_ID list.",
|
||||
spadat->pkt_source_ip, stanza_num, gpg_fpr);
|
||||
"[%s] (stanza #%d) Error pulling the GPG signature ID from the context: %s",
|
||||
spadat->pkt_source_ip, stanza_num, fko_gpg_errstr(*ctx));
|
||||
return 0;
|
||||
}
|
||||
|
||||
*res = fko_get_gpg_signature_fpr(*ctx, &gpg_fpr);
|
||||
if(*res != FKO_SUCCESS)
|
||||
{
|
||||
log_msg(LOG_WARNING,
|
||||
"[%s] (stanza #%d) Error pulling the GPG fingerprint from the context: %s",
|
||||
spadat->pkt_source_ip, stanza_num, fko_gpg_errstr(*ctx));
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_msg(LOG_INFO,
|
||||
"[%s] (stanza #%d) Incoming SPA data signed by '%s' (fingerprint '%s').",
|
||||
spadat->pkt_source_ip, stanza_num, gpg_id, gpg_fpr);
|
||||
|
||||
/* prefer GnuPG fingerprint match if so configured
|
||||
*/
|
||||
if(acc->gpg_remote_fpr != NULL)
|
||||
{
|
||||
is_gpg_match = 0;
|
||||
for(gpg_fpr_ndx = acc->gpg_remote_fpr_list;
|
||||
gpg_fpr_ndx != NULL; gpg_fpr_ndx=gpg_fpr_ndx->next)
|
||||
{
|
||||
*res = fko_gpg_signature_fpr_match(*ctx,
|
||||
gpg_fpr_ndx->str, &is_gpg_match);
|
||||
if(*res != FKO_SUCCESS)
|
||||
{
|
||||
log_msg(LOG_WARNING,
|
||||
"[%s] (stanza #%d) Error in GPG signature comparision: %s",
|
||||
spadat->pkt_source_ip, stanza_num, fko_gpg_errstr(*ctx));
|
||||
return 0;
|
||||
}
|
||||
if(is_gpg_match)
|
||||
break;
|
||||
}
|
||||
if(! is_gpg_match)
|
||||
{
|
||||
log_msg(LOG_WARNING,
|
||||
"[%s] (stanza #%d) Incoming SPA packet signed by: %s, but that fingerprint is not in the GPG_FINGERPRINT_ID list.",
|
||||
spadat->pkt_source_ip, stanza_num, gpg_fpr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(acc->gpg_remote_id != NULL)
|
||||
{
|
||||
is_gpg_match = 0;
|
||||
for(gpg_id_ndx = acc->gpg_remote_id_list;
|
||||
gpg_id_ndx != NULL; gpg_id_ndx=gpg_id_ndx->next)
|
||||
{
|
||||
*res = fko_gpg_signature_id_match(*ctx,
|
||||
gpg_id_ndx->str, &is_gpg_match);
|
||||
if(*res != FKO_SUCCESS)
|
||||
{
|
||||
log_msg(LOG_WARNING,
|
||||
"[%s] (stanza #%d) Error in GPG signature comparision: %s",
|
||||
spadat->pkt_source_ip, stanza_num, fko_gpg_errstr(*ctx));
|
||||
return 0;
|
||||
}
|
||||
if(is_gpg_match)
|
||||
break;
|
||||
}
|
||||
|
||||
if(! is_gpg_match)
|
||||
{
|
||||
log_msg(LOG_WARNING,
|
||||
"[%s] (stanza #%d) Incoming SPA packet signed by ID: %s, but that ID is not in the GPG_REMOTE_ID list.",
|
||||
spadat->pkt_source_ip, stanza_num, gpg_id);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
check_src_access(acc_stanza_t *acc, spa_data_t *spadat, const int stanza_num)
|
||||
{
|
||||
if(strcmp(spadat->spa_message_src_ip, "0.0.0.0") == 0)
|
||||
{
|
||||
if(acc->require_source_address)
|
||||
{
|
||||
log_msg(LOG_WARNING,
|
||||
"[%s] (stanza #%d) Got 0.0.0.0 when valid source IP was required.",
|
||||
spadat->pkt_source_ip, stanza_num
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
spadat->use_src_ip = spadat->pkt_source_ip;
|
||||
}
|
||||
else
|
||||
spadat->use_src_ip = spadat->spa_message_src_ip;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
check_username(acc_stanza_t *acc, spa_data_t *spadat, const int stanza_num)
|
||||
{
|
||||
if(acc->require_username != NULL)
|
||||
{
|
||||
if(strcmp(spadat->username, acc->require_username) != 0)
|
||||
{
|
||||
log_msg(LOG_WARNING,
|
||||
"[%s] (stanza #%d) Username in SPA data (%s) does not match required username: %s",
|
||||
spadat->pkt_source_ip, stanza_num, spadat->username, acc->require_username
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(acc->gpg_remote_id != NULL)
|
||||
static int
|
||||
check_nat_access_types(fko_srv_options_t *opts, acc_stanza_t *acc,
|
||||
spa_data_t *spadat, const int stanza_num)
|
||||
{
|
||||
if(spadat->message_type == FKO_LOCAL_NAT_ACCESS_MSG
|
||||
|| spadat->message_type == FKO_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MSG
|
||||
|| spadat->message_type == FKO_NAT_ACCESS_MSG
|
||||
|| spadat->message_type == FKO_CLIENT_TIMEOUT_NAT_ACCESS_MSG)
|
||||
{
|
||||
is_gpg_match = 0;
|
||||
for(gpg_id_ndx = acc->gpg_remote_id_list;
|
||||
gpg_id_ndx != NULL; gpg_id_ndx=gpg_id_ndx->next)
|
||||
{
|
||||
*res = fko_gpg_signature_id_match(*ctx,
|
||||
gpg_id_ndx->str, &is_gpg_match);
|
||||
if(*res != FKO_SUCCESS)
|
||||
{
|
||||
log_msg(LOG_WARNING,
|
||||
"[%s] (stanza #%d) Error in GPG signature comparision: %s",
|
||||
spadat->pkt_source_ip, stanza_num, fko_gpg_errstr(*ctx));
|
||||
return 0;
|
||||
}
|
||||
if(is_gpg_match)
|
||||
break;
|
||||
}
|
||||
|
||||
if(! is_gpg_match)
|
||||
#if FIREWALL_FIREWALLD
|
||||
if(strncasecmp(opts->config[CONF_ENABLE_FIREWD_FORWARDING], "Y", 1)!=0)
|
||||
{
|
||||
log_msg(LOG_WARNING,
|
||||
"[%s] (stanza #%d) Incoming SPA packet signed by ID: %s, but that ID is not in the GPG_REMOTE_ID list.",
|
||||
spadat->pkt_source_ip, stanza_num, gpg_id);
|
||||
"(stanza #%d) SPA packet from %s requested NAT access, but is not enabled",
|
||||
stanza_num, spadat->pkt_source_ip
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
#elif FIREWALL_IPTABLES
|
||||
if(strncasecmp(opts->config[CONF_ENABLE_IPT_FORWARDING], "Y", 1)!=0)
|
||||
{
|
||||
log_msg(LOG_WARNING,
|
||||
"(stanza #%d) SPA packet from %s requested NAT access, but is not enabled",
|
||||
stanza_num, spadat->pkt_source_ip
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
log_msg(LOG_WARNING,
|
||||
"(stanza #%d) SPA packet from %s requested unsupported NAT access",
|
||||
stanza_num, spadat->pkt_source_ip
|
||||
);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
add_replay_cache(fko_srv_options_t *opts, acc_stanza_t *acc,
|
||||
spa_data_t *spadat, char *raw_digest, int *added_replay_digest,
|
||||
const int stanza_num, int *res)
|
||||
{
|
||||
if (!opts->test && added_replay_digest == 0
|
||||
&& strncasecmp(opts->config[CONF_ENABLE_DIGEST_PERSISTENCE], "Y", 1) == 0)
|
||||
{
|
||||
|
||||
*res = add_replay(opts, raw_digest);
|
||||
if (*res != SPA_MSG_SUCCESS)
|
||||
{
|
||||
log_msg(LOG_WARNING, "[%s] (stanza #%d) Could not add digest to replay cache",
|
||||
spadat->pkt_source_ip, stanza_num);
|
||||
return 0;
|
||||
}
|
||||
*added_replay_digest = 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
set_timeout(acc_stanza_t *acc, spa_data_t *spadat)
|
||||
{
|
||||
if(spadat->client_timeout > 0)
|
||||
spadat->fw_access_timeout = spadat->client_timeout;
|
||||
else if(acc->fw_access_timeout > 0)
|
||||
spadat->fw_access_timeout = acc->fw_access_timeout;
|
||||
else
|
||||
spadat->fw_access_timeout = DEF_FW_ACCESS_TIMEOUT;
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
check_port_proto(acc_stanza_t *acc, spa_data_t *spadat, const int stanza_num)
|
||||
{
|
||||
if(! acc_check_port_access(acc, spadat->spa_message_remain))
|
||||
{
|
||||
log_msg(LOG_WARNING,
|
||||
"[%s] (stanza #%d) One or more requested protocol/ports was denied per access.conf.",
|
||||
spadat->pkt_source_ip, stanza_num
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -671,8 +886,7 @@ incoming_spa(fko_srv_options_t *opts)
|
||||
fko_ctx_t ctx = NULL;
|
||||
|
||||
char *spa_ip_demark, *raw_digest = NULL;
|
||||
time_t now_ts;
|
||||
int res, ts_diff, enc_type, stanza_num=0;
|
||||
int res, enc_type, stanza_num=0;
|
||||
int added_replay_digest = 0;
|
||||
int is_err, cmd_exec_success = 0, attempted_decrypt = 0;
|
||||
int conf_pkt_age = 0;
|
||||
@@ -761,80 +975,35 @@ incoming_spa(fko_srv_options_t *opts)
|
||||
*/
|
||||
enc_type = fko_encryption_type((char *)spa_pkt->packet_data);
|
||||
|
||||
if(acc->use_rijndael)
|
||||
if(! handle_rijndael_enc(acc, spa_pkt, &spadat, &ctx,
|
||||
&attempted_decrypt, &cmd_exec_success, enc_type,
|
||||
stanza_num, &res))
|
||||
{
|
||||
if (acc->key == NULL)
|
||||
{
|
||||
log_msg(LOG_ERR,
|
||||
"[%s] (stanza #%d) No KEY for RIJNDAEL encrypted messages",
|
||||
spadat.pkt_source_ip, stanza_num
|
||||
);
|
||||
acc = acc->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Command mode messages may be quite long
|
||||
*/
|
||||
if(acc->enable_cmd_exec || enc_type == FKO_ENCRYPTION_RIJNDAEL)
|
||||
{
|
||||
res = fko_new_with_data(&ctx, (char *)spa_pkt->packet_data,
|
||||
acc->key, acc->key_len, acc->encryption_mode, acc->hmac_key,
|
||||
acc->hmac_key_len, acc->hmac_type);
|
||||
attempted_decrypt = 1;
|
||||
if(res == FKO_SUCCESS)
|
||||
cmd_exec_success = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(acc->use_gpg && enc_type == FKO_ENCRYPTION_GPG && cmd_exec_success == 0)
|
||||
{
|
||||
if(! handle_gpg_enc(acc, spa_pkt, &spadat,
|
||||
&ctx, &attempted_decrypt, stanza_num, &res))
|
||||
{
|
||||
acc = acc->next;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(attempted_decrypt == 0)
|
||||
{
|
||||
log_msg(LOG_ERR,
|
||||
"[%s] (stanza #%d) No stanza encryption mode match for encryption type: %i.",
|
||||
spadat.pkt_source_ip, stanza_num, enc_type);
|
||||
acc = acc->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Do we have a valid FKO context? Did the SPA decrypt properly?
|
||||
*/
|
||||
if(res != FKO_SUCCESS)
|
||||
if(! handle_gpg_enc(acc, spa_pkt, &spadat, &ctx, &attempted_decrypt,
|
||||
cmd_exec_success, enc_type, stanza_num, &res))
|
||||
{
|
||||
log_msg(LOG_WARNING, "[%s] (stanza #%d) Error creating fko context: %s",
|
||||
spadat.pkt_source_ip, stanza_num, fko_errstr(res));
|
||||
|
||||
if(IS_GPG_ERROR(res))
|
||||
log_msg(LOG_WARNING, "[%s] (stanza #%d) - GPG ERROR: %s",
|
||||
spadat.pkt_source_ip, stanza_num, fko_gpg_errstr(ctx));
|
||||
acc = acc->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(! check_mode_ctx(&spadat, &ctx, attempted_decrypt,
|
||||
enc_type, stanza_num, res))
|
||||
{
|
||||
acc = acc->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Add this SPA packet into the replay detection cache
|
||||
*/
|
||||
if (!opts->test && added_replay_digest == 0
|
||||
&& strncasecmp(opts->config[CONF_ENABLE_DIGEST_PERSISTENCE], "Y", 1) == 0)
|
||||
if(! add_replay_cache(opts, acc, &spadat, raw_digest,
|
||||
&added_replay_digest, stanza_num, &res))
|
||||
{
|
||||
|
||||
res = add_replay(opts, raw_digest);
|
||||
if (res != SPA_MSG_SUCCESS)
|
||||
{
|
||||
log_msg(LOG_WARNING, "[%s] (stanza #%d) Could not add digest to replay cache",
|
||||
spadat.pkt_source_ip, stanza_num);
|
||||
acc = acc->next;
|
||||
continue;
|
||||
}
|
||||
added_replay_digest = 1;
|
||||
acc = acc->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* At this point the SPA data is authenticated via the HMAC (if used
|
||||
@@ -855,13 +1024,10 @@ incoming_spa(fko_srv_options_t *opts)
|
||||
* an entry in the list.
|
||||
*/
|
||||
|
||||
if(enc_type == FKO_ENCRYPTION_GPG && acc->gpg_require_sig)
|
||||
if(! handle_gpg_sigs(acc, &spadat, &ctx, enc_type, stanza_num, &res))
|
||||
{
|
||||
if(! handle_gpg_sigs(acc, &spadat, &ctx, stanza_num, &res))
|
||||
{
|
||||
acc = acc->next;
|
||||
continue;
|
||||
}
|
||||
acc = acc->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Populate our spa data struct for future reference.
|
||||
@@ -881,29 +1047,14 @@ incoming_spa(fko_srv_options_t *opts)
|
||||
* data, then use that. If not, try the FW_ACCESS_TIMEOUT from the
|
||||
* access.conf file (if there is one). Otherwise use the default.
|
||||
*/
|
||||
if(spadat.client_timeout > 0)
|
||||
spadat.fw_access_timeout = spadat.client_timeout;
|
||||
else if(acc->fw_access_timeout > 0)
|
||||
spadat.fw_access_timeout = acc->fw_access_timeout;
|
||||
else
|
||||
spadat.fw_access_timeout = DEF_FW_ACCESS_TIMEOUT;
|
||||
set_timeout(acc, &spadat);
|
||||
|
||||
/* Check packet age if so configured.
|
||||
*/
|
||||
if(strncasecmp(opts->config[CONF_ENABLE_SPA_PACKET_AGING], "Y", 1) == 0)
|
||||
if(! check_pkt_age(opts, &spadat, stanza_num, conf_pkt_age))
|
||||
{
|
||||
time(&now_ts);
|
||||
|
||||
ts_diff = labs(now_ts - spadat.timestamp);
|
||||
|
||||
if(ts_diff > conf_pkt_age)
|
||||
{
|
||||
log_msg(LOG_WARNING, "[%s] (stanza #%d) SPA data time difference is too great (%i seconds).",
|
||||
spadat.pkt_source_ip, stanza_num, ts_diff);
|
||||
|
||||
acc = acc->next;
|
||||
continue;
|
||||
}
|
||||
acc = acc->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* At this point, we have enough to check the embedded (or packet source)
|
||||
@@ -943,74 +1094,27 @@ incoming_spa(fko_srv_options_t *opts)
|
||||
/* If use source IP was requested (embedded IP of 0.0.0.0), make sure it
|
||||
* is allowed.
|
||||
*/
|
||||
if(strcmp(spadat.spa_message_src_ip, "0.0.0.0") == 0)
|
||||
if(! check_src_access(acc, &spadat, stanza_num))
|
||||
{
|
||||
if(acc->require_source_address)
|
||||
{
|
||||
log_msg(LOG_WARNING,
|
||||
"[%s] (stanza #%d) Got 0.0.0.0 when valid source IP was required.",
|
||||
spadat.pkt_source_ip, stanza_num
|
||||
);
|
||||
acc = acc->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
spadat.use_src_ip = spadat.pkt_source_ip;
|
||||
acc = acc->next;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
spadat.use_src_ip = spadat.spa_message_src_ip;
|
||||
|
||||
/* If REQUIRE_USERNAME is set, make sure the username in this SPA data
|
||||
* matches.
|
||||
*/
|
||||
if(acc->require_username != NULL)
|
||||
if(! check_username(acc, &spadat, stanza_num))
|
||||
{
|
||||
if(strcmp(spadat.username, acc->require_username) != 0)
|
||||
{
|
||||
log_msg(LOG_WARNING,
|
||||
"[%s] (stanza #%d) Username in SPA data (%s) does not match required username: %s",
|
||||
spadat.pkt_source_ip, stanza_num, spadat.username, acc->require_username
|
||||
);
|
||||
acc = acc->next;
|
||||
continue;
|
||||
}
|
||||
acc = acc->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Take action based on SPA message type.
|
||||
*/
|
||||
if(spadat.message_type == FKO_LOCAL_NAT_ACCESS_MSG
|
||||
|| spadat.message_type == FKO_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MSG
|
||||
|| spadat.message_type == FKO_NAT_ACCESS_MSG
|
||||
|| spadat.message_type == FKO_CLIENT_TIMEOUT_NAT_ACCESS_MSG)
|
||||
if(! check_nat_access_types(opts, acc, &spadat, stanza_num))
|
||||
{
|
||||
#if FIREWALL_FIREWALLD
|
||||
if(strncasecmp(opts->config[CONF_ENABLE_FIREWD_FORWARDING], "Y", 1)!=0)
|
||||
{
|
||||
log_msg(LOG_WARNING,
|
||||
"(stanza #%d) SPA packet from %s requested NAT access, but is not enabled",
|
||||
stanza_num, spadat.pkt_source_ip
|
||||
);
|
||||
acc = acc->next;
|
||||
continue;
|
||||
}
|
||||
#elif FIREWALL_IPTABLES
|
||||
if(strncasecmp(opts->config[CONF_ENABLE_IPT_FORWARDING], "Y", 1)!=0)
|
||||
{
|
||||
log_msg(LOG_WARNING,
|
||||
"(stanza #%d) SPA packet from %s requested NAT access, but is not enabled",
|
||||
stanza_num, spadat.pkt_source_ip
|
||||
);
|
||||
acc = acc->next;
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
log_msg(LOG_WARNING,
|
||||
"(stanza #%d) SPA packet from %s requested unsupported NAT access",
|
||||
stanza_num, spadat.pkt_source_ip
|
||||
);
|
||||
acc = acc->next;
|
||||
continue;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Command messages.
|
||||
@@ -1029,7 +1133,6 @@ incoming_spa(fko_srv_options_t *opts)
|
||||
acc = acc->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* From this point forward, we have some kind of access message. So
|
||||
@@ -1038,12 +1141,8 @@ incoming_spa(fko_srv_options_t *opts)
|
||||
*
|
||||
* --DSS TODO: We should add BLACKLIST support here as well.
|
||||
*/
|
||||
if(! acc_check_port_access(acc, spadat.spa_message_remain))
|
||||
if(! check_port_proto(acc, &spadat, stanza_num))
|
||||
{
|
||||
log_msg(LOG_WARNING,
|
||||
"[%s] (stanza #%d) One or more requested protocol/ports was denied per access.conf.",
|
||||
spadat.pkt_source_ip, stanza_num
|
||||
);
|
||||
acc = acc->next;
|
||||
continue;
|
||||
}
|
||||
@@ -1066,6 +1165,9 @@ incoming_spa(fko_srv_options_t *opts)
|
||||
process_spa_request(opts, acc, &spadat);
|
||||
}
|
||||
|
||||
/* If we made it here, then the SPA packet was processed according
|
||||
* to a matching access.conf stanza, so we're done with this packet.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user