#include "config.h" #include #include #include #include #include "global.h" #include "libstr.h" #include "liblist.h" #include "libip.h" void sfree(void *ptr) { if (ptr != NULL) { free(ptr); } } /*---< charlist >-------------------------------------------------------------*/ void init_charlist(t_charlist *list) { list->size = 0; list->item = NULL; } int parse_charlist(char *value, t_charlist *list) { char *scan; int add = 1, i; scan = value; while (*scan != '\0') { if (*scan == ',') { *scan = '\0'; add++; } scan++; } if ((list->item = (char**)realloc(list->item, (list->size + add) * sizeof(char*))) == NULL) { return -1; } for (i = 0; i < add; i++) { *(list->item + list->size + i) = NULL; } for (i = 0; i < add; i++) { if ((*(list->item + list->size + i) = strdup(remove_spaces(value))) == NULL) { remove_charlist(list); init_charlist(list); return -1; } value = value + strlen(value) + 1; } list->size += add; return 0; } void copy_charlist(t_charlist *dest, t_charlist *src) { dest->size = src->size; dest->item = src->item; } bool in_charlist(char *item, t_charlist *list) { int i; if (((i = list->size) > 0) && (item != NULL)) { while (i-- > 0) { if (strcmp(*(list->item + i), item) == 0) { return true; } } } return false; } void print_charlist(t_charlist *list) { int i; printf("print_charlist()::start\n"); for (i = 0; i < list->size; i++) { printf("[%s]\n", *(list->item + i)); } printf("print_charlist()::stop\n"); } void remove_charlist(t_charlist *list) { if (list->size > 0) { do { (list->size)--; sfree(*(list->item + list->size)); } while (list->size > 0); sfree(list->item); list->item = NULL; } } /*---< accesslist >-----------------------------------------------------------*/ /* Parse a list of access levels. */ t_accesslist *parse_accesslist(char *line, bool pwd_allowed, t_accesslist *list) { t_accesslist *new = NULL; char *rule, *ip, *mask; bool error = false; if (line == NULL) { return list; } if (list != NULL) { new = list; while (new->next != NULL) { new = new->next; } } while (line != NULL) { split_string(line, &ip, &line, ','); if (split_string(ip, &rule, &ip, ' ') == 0) { if (list == NULL) { if ((list = new = (t_accesslist*)malloc(sizeof(t_accesslist))) == NULL) { break; } } else { if ((new->next = (t_accesslist*)malloc(sizeof(t_accesslist))) == NULL) { error = true; break; } new = new->next; } new->next = NULL; if (strcmp(rule, "allow") == 0) { new->access = allow; } else if (strcmp(rule, "deny") == 0) { new->access = deny; } else if (pwd_allowed && (strcmp(rule, "pwd") == 0)) { new->access = pwd; } else { error = true; break; } if (strcmp(ip, "all") == 0) { default_ipv4(&(new->ip)); new->netmask = 0; new->all_ip = true; } else { new->all_ip = false; if (split_string(ip, &ip, &mask, '/') == 0) { if ((new->netmask = str2int(mask)) == -1) { error = true; break; } } else { new->netmask = -1; } if (parse_ip(ip, &(new->ip)) == -1) { error = true; break; } if (new->netmask == -1) { /* Set netmask */ if (new->ip.family == AF_INET) { new->netmask = 8 * IPv4_LEN; #ifdef HAVE_IPV6 } else if (new->ip.family == AF_INET6) { new->netmask = 8 * IPv6_LEN; #endif } else { error = true; break; } } else { /* Check netmask */ if (new->ip.family == AF_INET) { if (new->netmask > 8 * IPv4_LEN) { error = true; break; } #ifdef HAVE_IPV6 } else if (new->ip.family == AF_INET6) { if (new->netmask > 8 * IPv6_LEN) { error = true; break; } #endif } else { error = true; break; } } /* Apply subnetmask */ if (apply_netmask(&(new->ip), new->netmask) == -1) { error = true; break; } } } else { error = true; break; } } if (error) { list = remove_accesslist(list); } return list; } /* Remove an accesslist. */ t_accesslist *remove_accesslist(t_accesslist *list) { t_accesslist *item; while (list != NULL) { item = list; list = list->next; free(item); } return NULL; } /* Return the access status of an IP address. */ t_access ip_allowed(t_ip_addr *ip, t_accesslist *list) { while (list != NULL) { if (list->all_ip) { return list->access; } else if (ip_in_subnet(ip, &(list->ip), list->netmask)) { return list->access; } list = list->next; } return unknown; } /*---< key/valuelist >-------------------------------------------------------*/ /* Parse a list of key/value combinations. */ int parse_keyvaluelist(char *line, t_keyvalue **kvlist, char *delimiter) { char *value; t_keyvalue *prev; if (line != NULL) { if ((value = strstr(line, delimiter)) != NULL) { *value = '\0'; value += strlen(delimiter); prev = *kvlist; if ((*kvlist = (t_keyvalue*)malloc(sizeof(t_keyvalue))) == NULL) { return -1; } (*kvlist)->next = prev; (*kvlist)->value = NULL; if (((*kvlist)->key = strdup(remove_spaces(line))) == NULL) { free(*kvlist); return -1; } if (((*kvlist)->value = strdup(remove_spaces(value))) == NULL) { free((*kvlist)->key); free(*kvlist); return -1; } } else { return -1; } } return 0; } t_keyvalue *remove_keyvaluelist(t_keyvalue *list) { t_keyvalue *remove; while (list != NULL) { remove = list; list = list->next; sfree(remove->key); sfree(remove->value); free(remove); } return NULL; } /*---< temporary data >------------------------------------------------------*/ int register_tempdata(t_tempdata **tempdata, void *data, t_tempdata_type type) { t_tempdata *tdata; if ((tempdata != NULL) && (data != NULL)) { if ((tdata = (t_tempdata*)malloc(sizeof(t_tempdata))) == NULL) { return -1; } tdata->content = data; tdata->type = type; tdata->next = *tempdata; *tempdata = tdata; } return 0; } void remove_tempdata(t_tempdata *tempdata) { t_tempdata *tdata; while (tempdata != NULL) { tdata = tempdata; tempdata = tempdata->next; switch (tdata->type) { case tc_data: sfree(tdata->content); break; case tc_accesslist: remove_accesslist((t_accesslist*)tdata->content); break; case tc_keyvalue: free(((t_keyvalue*)(tdata->content))->key); free(((t_keyvalue*)(tdata->content))->value); free(tdata->content); break; case tc_charlist: remove_charlist((t_charlist*)tdata->content); break; } free(tdata); } }