2 ******************************************************************************
6 * Author: Damien Stuart
8 * Purpose: Access.conf file processing for fwknop server.
10 * Copyright 2010 Damien Stuart (dstuart@dstuart.org)
12 * License (GNU Public License):
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
29 ******************************************************************************
34 #include <sys/socket.h>
37 #include "fwknopd_common.h"
38 #include <arpa/inet.h>
44 /* Add an access string entry
47 add_acc_string(char **var, const char *val)
52 if((*var = strdup(val)) == NULL)
55 "Fatal memory allocation error adding access list entry: %s", var
61 /* Add an access int entry
64 add_acc_int(int *var, const char *val)
66 return(*var = atoi(val));
69 /* Add an access bool entry (unsigned char of 1 or 0)
72 add_acc_bool(unsigned char *var, const char *val)
74 return(*var = (strncasecmp(val, "Y", 1) == 0) ? 1 : 0);
77 /* Add expiration time - convert date to epoch seconds
80 add_acc_expire_time(fko_srv_options_t *opts, time_t *access_expire_time, const char *val)
84 memset(&tm, 0, sizeof(struct tm));
86 if (sscanf(val, "%2d/%2d/%4d", &tm.tm_mon, &tm.tm_mday, &tm.tm_year) != 3)
90 "Fatal: invalid date value '%s' (need MM/DD/YYYY) for access stanza expiration time",
93 clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
97 tm.tm_mon -= 1; /* 0-11 */
99 /* number of years since 1900
101 if(tm.tm_year > 1900)
107 *access_expire_time = mktime(&tm);
112 /* Add expiration time via epoch seconds defined in access.conf
115 add_acc_expire_time_epoch(fko_srv_options_t *opts, time_t *access_expire_time, const char *val)
118 unsigned long expire_time = 0;
122 expire_time = (time_t) strtoul(val, &endptr, 10);
124 if (errno == ERANGE || (errno != 0 && expire_time == 0))
127 "Fatal: invalid epoch seconds value '%s' for access stanza expiration time",
130 clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
133 *access_expire_time = (time_t) expire_time;
138 #if FIREWALL_IPTABLES
140 add_acc_force_nat(fko_srv_options_t *opts, acc_stanza_t *curr_acc, const char *val)
142 char ip_str[MAX_IPV4_STR_LEN] = {0};
144 if (sscanf(val, "%15s %5u", ip_str, &curr_acc->force_nat_port) != 2)
148 "Fatal: invalid FORCE_NAT arg '%s', need <IP> <PORT>",
151 clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
154 if (curr_acc->force_nat_port > MAX_PORT)
157 "Fatal: invalid FORCE_NAT port '%d'", curr_acc->force_nat_port);
158 clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
161 curr_acc->force_nat = 1;
162 add_acc_string(&(curr_acc->force_nat_ip), ip_str);
168 /* Take an IP or Subnet/Mask and convert it to mask for later
169 * comparisons of incoming source IPs against this mask.
172 add_source_mask(acc_stanza_t *acc, const char *ip)
175 char ip_str[MAX_IPV4_STR_LEN] = {0};
180 acc_int_list_t *last_sle, *new_sle, *tmp_sle;
182 if((new_sle = calloc(1, sizeof(acc_int_list_t))) == NULL)
185 "Fatal memory allocation error adding stanza source_list entry"
190 /* Convert the IP data into the appropriate mask
192 if(strcasecmp(ip, "ANY") == 0)
194 new_sle->maddr = 0x0;
199 /* See if we have a subnet component. If so pull out the IP and
200 * mask values, then create the final mask value.
202 if((ndx = strchr(ip, '/')) != NULL)
204 if(((ndx-ip)) >= MAX_IPV4_STR_LEN)
206 log_msg(LOG_ERR, "Error parsing string to IP");
213 strlcpy(ip_str, ip, (ndx-ip)+1);
218 if(strnlen(ip, MAX_IPV4_STR_LEN+1) >= MAX_IPV4_STR_LEN)
220 log_msg(LOG_ERR, "Error parsing string to IP");
225 strlcpy(ip_str, ip, strlen(ip)+1);
228 if(inet_aton(ip_str, &in) == 0)
231 "Error parsing IP to int for: %s", ip_str
240 /* Store our mask converted from CIDR to a 32-bit value.
242 new_sle->mask = (0xFFFFFFFF << (32 - mask));
244 /* Store our masked address for comparisons with future incoming
247 new_sle->maddr = ntohl(in.s_addr) & new_sle->mask;
250 /* If this is not the first entry, we walk our pointer to the
253 if(acc->source_list == NULL)
255 acc->source_list = new_sle;
259 tmp_sle = acc->source_list;
263 } while((tmp_sle = tmp_sle->next));
265 last_sle->next = new_sle;
271 /* Expand the access SOURCE string to a list of masks.
274 expand_acc_source(acc_stanza_t *acc)
277 char buf[ACCESS_BUF_LEN];
282 for(ndx = start; *ndx; ndx++)
286 /* Skip over any leading whitespace.
288 while(isspace(*start))
291 if(((ndx-start)+1) >= ACCESS_BUF_LEN)
294 strlcpy(buf, start, (ndx-start)+1);
295 res = add_source_mask(acc, buf);
302 /* Skip over any leading whitespace (once again for the last in the list).
304 while(isspace(*start))
307 if(((ndx-start)+1) >= ACCESS_BUF_LEN)
310 strlcpy(buf, start, (ndx-start)+1);
311 res = add_source_mask(acc, buf);
317 parse_proto_and_port(char *pstr, int *proto, int *port)
320 char proto_str[ACCESS_BUF_LEN];
322 /* Parse the string into its components.
324 if((ndx = strchr(pstr, '/')) == NULL)
327 "Parse error on access port entry: %s", pstr);
332 if(((ndx - pstr)+1) >= ACCESS_BUF_LEN)
335 "Parse error on access port entry: %s", pstr);
339 strlcpy(proto_str, pstr, (ndx - pstr)+1);
343 if((*port < 0) || (*port > MAX_PORT))
346 "Invalid port in access request: %s", pstr);
350 if(strcasecmp(proto_str, "tcp") == 0)
352 else if(strcasecmp(proto_str, "udp") == 0)
357 "Invalid protocol in access port entry: %s", pstr);
364 /* Take a proto/port string and convert it to appropriate integer values
365 * for comparisons of incoming SPA requests.
368 add_port_list_ent(acc_port_list_t **plist, char *port_str)
372 acc_port_list_t *last_plist, *new_plist, *tmp_plist;
374 /* Parse the string into its components and continue only if there
375 * are no problems with the incoming string.
377 if(parse_proto_and_port(port_str, &proto_int, &port) != 0)
380 if((new_plist = calloc(1, sizeof(acc_port_list_t))) == NULL)
383 "Fatal memory allocation error adding stanza source_list entry"
388 /* If this is not the first entry, we walk our pointer to the
400 last_plist = tmp_plist;
401 } while((tmp_plist = tmp_plist->next));
403 last_plist->next = new_plist;
406 new_plist->proto = proto_int;
407 new_plist->port = port;
412 /* Add a string list entry to the given acc_string_list.
415 add_string_list_ent(acc_string_list_t **stlist, const char *str_str)
417 acc_string_list_t *last_stlist, *new_stlist, *tmp_stlist;
419 if((new_stlist = calloc(1, sizeof(acc_string_list_t))) == NULL)
422 "Fatal memory allocation error creating string list entry"
427 /* If this is not the first entry, we walk our pointer to the
432 *stlist = new_stlist;
436 tmp_stlist = *stlist;
439 last_stlist = tmp_stlist;
440 } while((tmp_stlist = tmp_stlist->next));
442 last_stlist->next = new_stlist;
445 if(new_stlist->str != NULL)
446 free(new_stlist->str);
448 new_stlist->str = strdup(str_str);
450 if(new_stlist->str == NULL)
453 "Fatal memory allocation error adding string list entry item"
460 /* Expand a proto/port access string to a list of access proto-port struct.
463 expand_acc_port_list(acc_port_list_t **plist, char *plist_str)
466 char buf[ACCESS_BUF_LEN];
470 for(ndx = start; *ndx != '\0'; ndx++)
474 /* Skip over any leading whitespace.
476 while(isspace(*start))
479 if(((ndx-start)+1) >= ACCESS_BUF_LEN)
482 strlcpy(buf, start, (ndx-start)+1);
484 if(add_port_list_ent(plist, buf) == 0)
491 /* Skip over any leading whitespace (once again for the last in the list).
493 while(isspace(*start))
496 if(((ndx-start)+1) >= ACCESS_BUF_LEN)
499 strlcpy(buf, start, (ndx-start)+1);
501 if(add_port_list_ent(plist, buf) == 0)
507 /* Expand a comma-separated string into a simple acc_string_list.
510 expand_acc_string_list(acc_string_list_t **stlist, char *stlist_str)
517 for(ndx = start; *ndx; ndx++)
521 /* Skip over any leading whitespace.
523 while(isspace(*start))
526 if(((ndx-start)+1) >= 1024)
529 strlcpy(buf, start, (ndx-start)+1);
530 add_string_list_ent(stlist, buf);
535 /* Skip over any leading whitespace (once again for the last in the list).
537 while(isspace(*start))
540 if(((ndx-start)+1) >= 1024)
543 strlcpy(buf, start, (ndx-start)+1);
545 add_string_list_ent(stlist, buf);
550 /* Free the acc source_list
553 free_acc_source_list(acc_int_list_t *sle)
555 acc_int_list_t *last_sle;
560 sle = last_sle->next;
569 free_acc_port_list(acc_port_list_t *ple)
571 acc_port_list_t *last_ple;
576 ple = last_ple->next;
582 /* Free a string_list
585 free_acc_string_list(acc_string_list_t *stl)
587 acc_string_list_t *last_stl;
592 stl = last_stl->next;
599 /* Free any allocated content of an access stanza.
601 * NOTE: If a new access.conf parameter is created, and it is a string
602 * value, it also needs to be added to the list of items to check
606 free_acc_stanza_data(acc_stanza_t *acc)
609 if(acc->source != NULL)
612 free_acc_source_list(acc->source_list);
615 if(acc->open_ports != NULL)
617 free(acc->open_ports);
618 free_acc_port_list(acc->oport_list);
621 if(acc->restrict_ports != NULL)
623 free(acc->restrict_ports);
624 free_acc_port_list(acc->rport_list);
627 if(acc->force_nat_ip != NULL)
628 free(acc->force_nat_ip);
633 if(acc->cmd_exec_user != NULL)
634 free(acc->cmd_exec_user);
636 if(acc->require_username != NULL)
637 free(acc->require_username);
639 if(acc->gpg_home_dir != NULL)
640 free(acc->gpg_home_dir);
642 if(acc->gpg_decrypt_id != NULL)
643 free(acc->gpg_decrypt_id);
645 if(acc->gpg_decrypt_pw != NULL)
646 free(acc->gpg_decrypt_pw);
648 if(acc->gpg_remote_id != NULL)
650 free(acc->gpg_remote_id);
651 free_acc_string_list(acc->gpg_remote_id_list);
655 /* Expand any access entries that may be multi-value.
658 expand_acc_ent_lists(fko_srv_options_t *opts)
660 acc_stanza_t *acc = opts->acc_stanzas;
662 /* We need to do this for each stanza.
666 /* Expand the source string to 32-bit integer masks foreach entry.
668 if(expand_acc_source(acc) == 0)
670 log_msg(LOG_ERR, "Fatal invalid SOURCE in access stanza");
671 clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
674 /* Now expand the open_ports string.
676 if(acc->open_ports != NULL && strlen(acc->open_ports))
678 if(expand_acc_port_list(&(acc->oport_list), acc->open_ports) == 0)
680 log_msg(LOG_ERR, "Fatal invalid OPEN_PORTS in access stanza");
681 clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
685 if(acc->restrict_ports != NULL && strlen(acc->restrict_ports))
687 if(expand_acc_port_list(&(acc->rport_list), acc->restrict_ports) == 0)
689 log_msg(LOG_ERR, "Fatal invalid RESTRICT_PORTS in access stanza");
690 clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
694 /* Expand the GPG_REMOTE_ID string.
696 if(acc->gpg_remote_id != NULL && strlen(acc->gpg_remote_id))
697 expand_acc_string_list(&(acc->gpg_remote_id_list), acc->gpg_remote_id);
704 free_acc_stanzas(fko_srv_options_t *opts)
706 acc_stanza_t *acc, *last_acc;
708 /* Free any resources first (in case of reconfig). Assume non-NULL
709 * entry needs to be freed.
711 acc = opts->acc_stanzas;
716 acc = last_acc->next;
718 free_acc_stanza_data(last_acc);
725 /* Wrapper for free_acc_stanzas(), we may put additional initialization
729 acc_stanza_init(fko_srv_options_t *opts)
731 /* Free any resources first (in case of reconfig). Assume non-NULL
732 * entry needs to be freed.
734 free_acc_stanzas(opts);
739 /* Add a new stanza bay allocating the required memory at the required
740 * location, yada-yada-yada.
743 acc_stanza_add(fko_srv_options_t *opts)
745 acc_stanza_t *acc = opts->acc_stanzas;
746 acc_stanza_t *new_acc = calloc(1, sizeof(acc_stanza_t));
747 acc_stanza_t *last_acc;
752 "Fatal memory allocation error adding access stanza"
754 clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
757 /* If this is not the first acc entry, we walk our acc pointer to the
758 * end of the existing list.
762 opts->acc_stanzas = new_acc;
768 } while((acc = acc->next));
770 last_acc->next = new_acc;
776 /* Scan the access options for entries that have not bees set, but need
780 set_acc_defaults(fko_srv_options_t *opts)
782 acc_stanza_t *acc = opts->acc_stanzas;
789 /* set default fw_access_timeout if necessary
791 if(acc->fw_access_timeout < 1)
792 acc->fw_access_timeout = DEF_FW_ACCESS_TIMEOUT;
794 /* set default gpg keyring path if necessary
796 if(acc->gpg_decrypt_pw != NULL && acc->gpg_home_dir == NULL)
797 add_acc_string(&(acc->gpg_home_dir), opts->config[CONF_GPG_HOME_DIR]);
803 /* Perform some sanity checks on an acc stanza data.
806 acc_data_is_valid(const acc_stanza_t *acc)
808 if(((acc->key == NULL || !strlen(acc->key))
809 && (acc->gpg_decrypt_pw == NULL || !strlen(acc->gpg_decrypt_pw)))
810 || (acc->use_rijndael == 0 && acc->use_gpg == 0 && acc->gpg_allow_no_pw == 0))
813 "[*] No keys found for access stanza source: '%s'\n", acc->source
821 /* Read and parse the access file, popluating the access data as we go.
824 parse_access_file(fko_srv_options_t *opts)
829 unsigned int num_lines = 0;
831 char access_line_buf[MAX_LINE_LEN] = {0};
832 char var[MAX_LINE_LEN] = {0};
833 char val[MAX_LINE_LEN] = {0};
838 acc_stanza_t *curr_acc = NULL;
840 /* First see if the access file exists. If it doesn't, complain
843 if(stat(opts->config[CONF_ACCESS_FILE], &st) != 0)
845 fprintf(stderr, "[*] Access file: '%s' was not found.\n",
846 opts->config[CONF_ACCESS_FILE]);
848 clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
851 verify_file_perms_ownership(opts->config[CONF_ACCESS_FILE]);
853 if ((file_ptr = fopen(opts->config[CONF_ACCESS_FILE], "r")) == NULL)
855 fprintf(stderr, "[*] Could not open access file: %s\n",
856 opts->config[CONF_ACCESS_FILE]);
859 clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
862 /* Initialize the access list.
864 acc_stanza_init(opts);
866 /* Now walk through access file pulling the access entries into the
869 while ((fgets(access_line_buf, MAX_LINE_LEN, file_ptr)) != NULL)
872 access_line_buf[MAX_LINE_LEN-1] = '\0';
874 /* Get past comments and empty lines (note: we only look at the
877 if(IS_EMPTY_LINE(access_line_buf[0]))
880 if(sscanf(access_line_buf, "%s %[^;\n\r]", var, val) != 2)
883 "*Invalid access file entry in %s at line %i.\n - '%s'",
884 opts->config[CONF_ACCESS_FILE], num_lines, access_line_buf
889 /* Remove any colon that may be on the end of the var
891 if((ndx = strrchr(var, ':')) != NULL)
896 if(opts->verbose > 3)
898 "ACCESS FILE: %s, LINE: %s\tVar: %s, Val: '%s'\n",
899 opts->config[CONF_ACCESS_FILE], access_line_buf, var, val
902 /* Process the entry.
904 * NOTE: If a new access.conf parameter is created. It also needs
905 * to be accounted for in the following if/if else construct.
908 if(CONF_VAR_IS(var, "SOURCE"))
910 /* If this is not the first stanza, sanity check the previous
911 * stanza for the minimum required data.
913 if(curr_acc != NULL) {
914 if(!acc_data_is_valid(curr_acc))
917 "[*] Data error in access file: '%s'\n",
918 opts->config[CONF_ACCESS_FILE]);
919 clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
925 curr_acc = acc_stanza_add(opts);
927 add_acc_string(&(curr_acc->source), val);
931 else if (curr_acc == NULL)
933 /* The stanza must start with the "SOURCE" variable
937 else if(CONF_VAR_IS(var, "OPEN_PORTS"))
939 add_acc_string(&(curr_acc->open_ports), val);
941 else if(CONF_VAR_IS(var, "RESTRICT_PORTS"))
943 add_acc_string(&(curr_acc->restrict_ports), val);
945 else if(CONF_VAR_IS(var, "KEY"))
947 if(strcasecmp(val, "__CHANGEME__") == 0)
950 "[*] KEY value is not properly set in stanza source '%s' in access file: '%s'\n",
951 curr_acc->source, opts->config[CONF_ACCESS_FILE]);
952 clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
954 add_acc_string(&(curr_acc->key), val);
955 add_acc_bool(&(curr_acc->use_rijndael), "Y");
957 else if(CONF_VAR_IS(var, "FW_ACCESS_TIMEOUT"))
959 add_acc_int(&(curr_acc->fw_access_timeout), val);
961 else if(CONF_VAR_IS(var, "ENABLE_CMD_EXEC"))
963 add_acc_bool(&(curr_acc->enable_cmd_exec), val);
965 else if(CONF_VAR_IS(var, "CMD_EXEC_USER"))
967 add_acc_string(&(curr_acc->cmd_exec_user), val);
974 fprintf(stderr, "Unable to determine UID for CMD_EXEC_USER: %s.\n",
975 errno ? strerror(errno) : "Not a user on this system");
976 clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
979 curr_acc->cmd_exec_uid = pw->pw_uid;
981 else if(CONF_VAR_IS(var, "REQUIRE_USERNAME"))
983 add_acc_string(&(curr_acc->require_username), val);
985 else if(CONF_VAR_IS(var, "REQUIRE_SOURCE_ADDRESS"))
987 add_acc_bool(&(curr_acc->require_source_address), val);
989 else if(CONF_VAR_IS(var, "REQUIRE_SOURCE")) /* synonym for REQUIRE_SOURCE_ADDRESS */
991 add_acc_bool(&(curr_acc->require_source_address), val);
993 else if(CONF_VAR_IS(var, "GPG_HOME_DIR"))
995 if (is_valid_dir(val))
997 add_acc_string(&(curr_acc->gpg_home_dir), val);
1002 "[*] GPG_HOME_DIR directory '%s' stat()/existence problem in stanza source '%s' in access file: '%s'\n",
1003 val, curr_acc->source, opts->config[CONF_ACCESS_FILE]);
1004 clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
1007 else if(CONF_VAR_IS(var, "GPG_DECRYPT_ID"))
1009 add_acc_string(&(curr_acc->gpg_decrypt_id), val);
1011 else if(CONF_VAR_IS(var, "GPG_DECRYPT_PW"))
1013 if(strcasecmp(val, "__CHANGEME__") == 0)
1016 "[*] GPG_DECRYPT_PW value is not properly set in stanza source '%s' in access file: '%s'\n",
1017 curr_acc->source, opts->config[CONF_ACCESS_FILE]);
1018 clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
1020 add_acc_string(&(curr_acc->gpg_decrypt_pw), val);
1021 add_acc_bool(&(curr_acc->use_gpg), "Y");
1023 else if(CONF_VAR_IS(var, "GPG_ALLOW_NO_PW"))
1025 add_acc_bool(&(curr_acc->gpg_allow_no_pw), val);
1026 if(curr_acc->gpg_allow_no_pw == 1)
1028 add_acc_bool(&(curr_acc->use_gpg), "Y");
1029 if(curr_acc->gpg_decrypt_pw != NULL && curr_acc->gpg_decrypt_pw[0] != '\0')
1030 free(curr_acc->gpg_decrypt_pw);
1031 add_acc_string(&(curr_acc->gpg_decrypt_pw), "");
1034 else if(CONF_VAR_IS(var, "GPG_REQUIRE_SIG"))
1036 add_acc_bool(&(curr_acc->gpg_require_sig), val);
1038 else if(CONF_VAR_IS(var, "GPG_IGNORE_SIG_VERIFY_ERROR"))
1040 add_acc_bool(&(curr_acc->gpg_ignore_sig_error), val);
1042 else if(CONF_VAR_IS(var, "GPG_REMOTE_ID"))
1044 add_acc_string(&(curr_acc->gpg_remote_id), val);
1046 else if(CONF_VAR_IS(var, "ACCESS_EXPIRE"))
1048 add_acc_expire_time(opts, &(curr_acc->access_expire_time), val);
1050 else if(CONF_VAR_IS(var, "ACCESS_EXPIRE_EPOCH"))
1052 add_acc_expire_time_epoch(opts, &(curr_acc->access_expire_time), val);
1054 else if(CONF_VAR_IS(var, "FORCE_NAT"))
1056 #if FIREWALL_IPTABLES
1057 if(strncasecmp(opts->config[CONF_ENABLE_IPT_FORWARDING], "Y", 1) !=0 )
1060 "[*] FORCE_NAT requires ENABLE_IPT_FORWARDING to be enabled in fwknopd.conf\n");
1061 clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
1063 add_acc_force_nat(opts, curr_acc, val);
1066 "[*] FORCE_NAT not supported.\n");
1067 clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
1073 "*Ignoring unknown access parameter: '%s' in %s\n",
1074 var, opts->config[CONF_ACCESS_FILE]
1081 /* Basic check to ensure that we got at least one SOURCE stanza with
1082 * a valid KEY defined (valid meaning it has a value that is not
1085 if (got_source == 0)
1088 "[*] Could not find valid SOURCE stanza in access file: '%s'\n",
1089 opts->config[CONF_ACCESS_FILE]);
1090 clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
1093 /* Sanity check the last stanza
1095 if(!acc_data_is_valid(curr_acc))
1098 "[*] Data error in access file: '%s'\n",
1099 opts->config[CONF_ACCESS_FILE]);
1100 clean_exit(opts, NO_FW_CLEANUP, EXIT_FAILURE);
1103 /* Expand our the expandable fields into their respective data buckets.
1105 expand_acc_ent_lists(opts);
1107 /* Make sure default values are set where needed.
1110 set_acc_defaults(opts);
1116 compare_addr_list(acc_int_list_t *source_list, const uint32_t ip)
1122 if((ip & source_list->mask) == (source_list->maddr & source_list->mask))
1128 source_list = source_list->next;
1134 /* Compare the contents of 2 port lists. Return true on a match.
1135 * Match depends on the match_any flag. if match_any is 1 then any
1136 * entry in the incoming data need only match one item to return true.
1137 * Otherwise all entries in the incoming data must have a corresponding
1138 * match in the access port_list.
1141 compare_port_list(acc_port_list_t *in, acc_port_list_t *ac, const int match_any)
1146 acc_port_list_t *tlist;
1154 if(in->proto == tlist->proto && in->port == tlist->port)
1160 tlist = tlist->next;
1165 return(i_cnt == a_cnt);
1168 /* Take a proto/port string (or mulitple comma-separated strings) and check
1169 * them against the list for the given access stanza.
1171 * Return 1 if we are allowed
1174 acc_check_port_access(acc_stanza_t *acc, char *port_str)
1176 int res = 1, ctr = 0;
1178 char buf[ACCESS_BUF_LEN];
1181 acc_port_list_t *o_pl = acc->oport_list;
1182 acc_port_list_t *r_pl = acc->rport_list;
1184 acc_port_list_t *in_pl = NULL;
1188 /* Create our own internal port_list from the incoming SPA data
1191 for(ndx = start; *ndx != '\0'; ndx++)
1195 if((ctr >= ACCESS_BUF_LEN)
1196 || (((ndx-start)+1) >= ACCESS_BUF_LEN))
1199 "Unable to create acc_port_list from incoming data: %s",
1204 strlcpy(buf, start, (ndx-start)+1);
1205 if(add_port_list_ent(&in_pl, buf) == 0)
1207 log_msg(LOG_ERR, "Invalid proto/port string");
1216 if((ctr >= ACCESS_BUF_LEN)
1217 || (((ndx-start)+1) >= ACCESS_BUF_LEN))
1220 "Unable to create acc_port_list from incoming data: %s",
1225 strlcpy(buf, start, (ndx-start)+1);
1226 if(add_port_list_ent(&in_pl, buf) == 0)
1228 log_msg(LOG_ERR, "Invalid proto/port string");
1235 "Unable to create acc_port_list from incoming data: %s", port_str
1240 /* Start with restricted ports (if any). Any match (even if only one
1241 * entry) means not allowed.
1243 if((acc->rport_list != NULL) && (compare_port_list(in_pl, r_pl, 1)))
1246 goto cleanup_and_bail;
1249 /* For open port list, all must match.
1251 if((acc->oport_list != NULL) && (!compare_port_list(in_pl, o_pl, 0)))
1255 free_acc_port_list(in_pl);
1259 /* Take a GPG ID string and check it against the list of allowed
1262 * Return 1 if we are allowed
1265 acc_check_gpg_remote_id(acc_stanza_t *acc, const char *gpg_id)
1267 acc_string_list_t *ndx;
1269 for(ndx = acc->gpg_remote_id_list; ndx != NULL; ndx=ndx->next)
1270 if(strcasecmp(ndx->str, gpg_id) == 0)
1276 /* Dump the configuration
1279 dump_access_list(const fko_srv_options_t *opts)
1283 acc_stanza_t *acc = opts->acc_stanzas;
1285 fprintf(stdout, "Current fwknopd access settings:\n");
1289 fprintf(stderr, "\n ** No Access Settings Defined **\n\n");
1297 "==============================================================\n"
1299 " RESTRICT_PORTS: %s\n"
1300 " KEY: <see the access.conf file>\n"
1301 " FW_ACCESS_TIMEOUT: %i\n"
1302 " ENABLE_CMD_EXEC: %s\n"
1303 " CMD_EXEC_USER: %s\n"
1304 " REQUIRE_USERNAME: %s\n"
1305 " REQUIRE_SOURCE_ADDRESS: %s\n"
1306 " FORCE_NAT (ip): %s\n"
1307 " FORCE_NAT (proto): %s\n"
1308 " FORCE_NAT (port): %d\n"
1309 " ACCESS_EXPIRE: %s" /* asctime() adds a newline */
1310 " GPG_HOME_DIR: %s\n"
1311 " GPG_DECRYPT_ID: %s\n"
1312 " GPG_DECRYPT_PW: <see the access.conf file>\n"
1313 " GPG_REQUIRE_SIG: %s\n"
1314 "GPG_IGNORE_SIG_VERIFY_ERROR: %s\n"
1315 " GPG_REMOTE_ID: %s\n",
1318 (acc->open_ports == NULL) ? "<not set>" : acc->open_ports,
1319 (acc->restrict_ports == NULL) ? "<not set>" : acc->restrict_ports,
1320 //(acc->key == NULL) ? "<not set>" : acc->key,
1321 acc->fw_access_timeout,
1322 acc->enable_cmd_exec ? "Yes" : "No",
1323 (acc->cmd_exec_user == NULL) ? "<not set>" : acc->cmd_exec_user,
1324 (acc->require_username == NULL) ? "<not set>" : acc->require_username,
1325 acc->require_source_address ? "Yes" : "No",
1326 acc->force_nat ? acc->force_nat_ip : "<not set>",
1327 acc->force_nat && acc->force_nat_proto != NULL ? acc->force_nat_proto : "<not set>",
1328 acc->force_nat ? acc->force_nat_port : 0,
1329 (acc->access_expire_time > 0) ? asctime(localtime(&acc->access_expire_time)) : "<not set>\n",
1330 (acc->gpg_home_dir == NULL) ? "<not set>" : acc->gpg_home_dir,
1331 (acc->gpg_decrypt_id == NULL) ? "<not set>" : acc->gpg_decrypt_id,
1332 //(acc->gpg_decrypt_pw == NULL) ? "<not set>" : acc->gpg_decrypt_pw,
1333 acc->gpg_require_sig ? "Yes" : "No",
1334 acc->gpg_ignore_sig_error ? "Yes" : "No",
1335 (acc->gpg_remote_id == NULL) ? "<not set>" : acc->gpg_remote_id
1338 fprintf(stdout, "\n");
1343 fprintf(stdout, "\n");