END_TEST START_TEST (netacl_dup_test) { pr_netacl_t *acl, *res; res = pr_netacl_dup(NULL, NULL); fail_unless(res == NULL, "Failed to handle NULL arguments"); fail_unless(errno == EINVAL, "Failed to set errno to EINVAL"); res = pr_netacl_dup(p, NULL); fail_unless(res == NULL, "Failed to handle NULL ACL argument"); fail_unless(errno == EINVAL, "Failed to set errno to EINVAL"); acl = pr_netacl_create(p, "ALL"); fail_unless(acl != NULL, "Failed to create ALL ACL"); res = pr_netacl_dup(NULL, acl); fail_unless(res == NULL, "Failed to handle NULL pool"); fail_unless(errno == EINVAL, "Failed to set errno to EINVAL"); res = pr_netacl_dup(p, acl); fail_unless(res != NULL, "Failed to dup ACL: %s", strerror(errno)); fail_unless(strcmp(pr_netacl_get_str(p, res), pr_netacl_get_str(p, acl)) == 0, "Expected '%s', got '%s'", pr_netacl_get_str(p, acl), pr_netacl_get_str(p, res)); }
static bool is_allowed(cmd_rec *cmd, pr_netaddr_t *na) { int i; config_rec *c; array_header *allowed_acls; c = find_config(cmd->server->conf, CONF_PARAM, "LMDBAllow", FALSE); if(NULL == c) return false; allowed_acls = c->argv[0]; if(NULL == allowed_acls) { pr_log_auth(PR_LOG_ERR, "%s: pr_table_t is NULL. something fatal", MODULE_NAME); return false; } #ifdef DEBUG pr_table_do(allowed_acls, walk_table, NULL, 0); #endif pr_netacl_t **elts = allowed_acls->elts; for (i = 0; i < allowed_acls->nelts; i++) { pr_netacl_t *acl = elts[i]; if(pr_netacl_match(acl, na) == 1) { pr_log_auth(PR_LOG_INFO, "%s: client IP matched with LMDBAllow '%s'. Skip last process", MODULE_NAME, pr_netacl_get_str(cmd->tmp_pool, acl)); return true; } } return false; }
pr_class_t *pr_class_match_addr(pr_netaddr_t *addr) { pr_class_t *cls; pool *tmp_pool; if (!addr) { errno = EINVAL; return NULL; } tmp_pool = make_sub_pool(permanent_pool); for (cls = class_list; cls; cls = cls->cls_next) { array_header *acl_list = cls->cls_acls; pr_netacl_t **acls = acl_list->elts; register int i; int next_class = FALSE; /* For each ACL rule in this class, compare the rule against the given * address. The address matches the given class depending on the * Satisfy setting: if "any", the class matches if any rule matches; * if "all", the class matches only if _all_ rules match. */ for (i = 0; i < acl_list->nelts; i++) { int res; if (next_class) break; if (acls[i] == NULL) continue; switch (cls->cls_satisfy) { case PR_CLASS_SATISFY_ANY: pr_trace_msg(trace_channel, 6, "checking addr '%s' (%s) against class '%s' rule: %s " "(requires any ACL matching)", pr_netaddr_get_ipstr(addr), pr_netaddr_get_dnsstr(addr), cls->cls_name, pr_netacl_get_str(tmp_pool, acls[i])); res = pr_netacl_match(acls[i], addr); if (res == 1) { destroy_pool(tmp_pool); return cls; } break; case PR_CLASS_SATISFY_ALL: pr_trace_msg(trace_channel, 6, "checking addr '%s' (%s) against class '%s' ACL: %s " "(requires all ACLs matching)", pr_netaddr_get_ipstr(addr), pr_netaddr_get_dnsstr(addr), cls->cls_name, pr_netacl_get_str(tmp_pool, acls[i])); res = pr_netacl_match(acls[i], addr); if (res <= 0) next_class = TRUE; break; } } /* If this is a "Satisfy all" class, and all rules have matched * (positively or negatively), then it matches the address. */ if (next_class == FALSE && cls->cls_satisfy == PR_CLASS_SATISFY_ALL && i == acl_list->nelts) { destroy_pool(tmp_pool); return cls; } } destroy_pool(tmp_pool); errno = ENOENT; return NULL; }
END_TEST START_TEST (netacl_get_str_test) { pr_netacl_t *acl; char *acl_str, *ok; const char *res; res = pr_netacl_get_str(NULL, NULL); fail_unless(res == NULL, "Failed to handle NULL arguments"); fail_unless(errno == EINVAL, "Failed to set errno to EINVAL"); res = pr_netacl_get_str(p, NULL); fail_unless(res == NULL, "Failed to handle NULL ACL"); fail_unless(errno == EINVAL, "Failed to set errno to EINVAL"); acl_str = "all"; acl = pr_netacl_create(p, acl_str); fail_unless(acl != NULL, "Failed to create ACL: %s", strerror(errno)); res = pr_netacl_get_str(NULL, acl); fail_unless(res == NULL, "Failed to handle NULL pool"); fail_unless(errno == EINVAL, "Failed to set errno to EINVAL"); ok = "all <all>"; res = pr_netacl_get_str(p, acl); fail_unless(res != NULL, "Failed to get ACL string: %s", strerror(errno)); fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res); acl_str = "AlL"; acl = pr_netacl_create(p, acl_str); fail_unless(acl != NULL, "Failed to create ACL: %s", strerror(errno)); res = pr_netacl_get_str(p, acl); fail_unless(res != NULL, "Failed to get ACL string: %s", strerror(errno)); fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res); acl_str = "None"; acl = pr_netacl_create(p, acl_str); fail_unless(acl != NULL, "Failed to create ACL: %s", strerror(errno)); ok = "none <none>"; res = pr_netacl_get_str(p, acl); fail_unless(res != NULL, "Failed to get ACL string: %s", strerror(errno)); fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res); acl_str = pstrdup(p, "127.0.0.1"); acl = pr_netacl_create(p, acl_str); fail_unless(acl != NULL, "Failed to create ACL: %s", strerror(errno)); ok = "127.0.0.1 <IP address match>"; res = pr_netacl_get_str(p, acl); fail_unless(res != NULL, "Failed to get ACL string: %s", strerror(errno)); fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res); acl_str = pstrdup(p, "!127.0.0.1"); acl = pr_netacl_create(p, acl_str); fail_unless(acl != NULL, "Failed to create ACL: %s", strerror(errno)); ok = "!127.0.0.1 <IP address match, inverted>"; res = pr_netacl_get_str(p, acl); fail_unless(res != NULL, "Failed to get ACL string: %s", strerror(errno)); fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res); acl_str = pstrdup(p, "127.0.0."); acl = pr_netacl_create(p, acl_str); fail_unless(acl != NULL, "Failed to create ACL: %s", strerror(errno)); ok = "127.0.0.* <IP address glob>"; res = pr_netacl_get_str(p, acl); fail_unless(res != NULL, "Failed to get ACL string: %s", strerror(errno)); fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res); acl_str = pstrdup(p, "localhost"); acl = pr_netacl_create(p, acl_str); fail_unless(acl != NULL, "Failed to create ACL: %s", strerror(errno)); ok = "localhost <DNS hostname match>"; res = pr_netacl_get_str(p, acl); fail_unless(res != NULL, "Failed to get ACL string: %s", strerror(errno)); fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res); acl_str = pstrdup(p, ".castaglia.org"); acl = pr_netacl_create(p, acl_str); fail_unless(acl != NULL, "Failed to create ACL: %s", strerror(errno)); ok = "*.castaglia.org <DNS hostname glob>"; res = pr_netacl_get_str(p, acl); fail_unless(res != NULL, "Failed to get ACL string: %s", strerror(errno)); fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res); acl_str = pstrdup(p, "127.0.0.1/24"); acl = pr_netacl_create(p, acl_str); fail_unless(acl != NULL, "Failed to create ACL: %s", strerror(errno)); ok = "127.0.0.1/24 <IP address mask, 24-bit mask>"; res = pr_netacl_get_str(p, acl); fail_unless(res != NULL, "Failed to get ACL string: %s", strerror(errno)); fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res); acl_str = pstrdup(p, "127.0.0.1/0"); acl = pr_netacl_create(p, acl_str); fail_unless(acl != NULL, "Failed to create ACL: %s", strerror(errno)); ok = "127.0.0.1/0 <IP address mask, 0-bit mask>"; res = pr_netacl_get_str(p, acl); fail_unless(res != NULL, "Failed to get ACL string: %s", strerror(errno)); fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res); acl_str = pstrdup(p, "!127.0.0.1/24"); acl = pr_netacl_create(p, acl_str); fail_unless(acl != NULL, "Failed to create ACL: %s", strerror(errno)); ok = "!127.0.0.1/24 <IP address mask, 24-bit mask, inverted>"; res = pr_netacl_get_str(p, acl); fail_unless(res != NULL, "Failed to get ACL string: %s", strerror(errno)); fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res); #ifdef PR_USE_IPV6 acl_str = pstrdup(p, "::1/24"); acl = pr_netacl_create(p, acl_str); fail_unless(acl != NULL, "Failed to create ACL: %s", strerror(errno)); ok = "::1/24 <IP address mask, 24-bit mask>"; res = pr_netacl_get_str(p, acl); fail_unless(res != NULL, "Failed to get ACL string: %s", strerror(errno)); fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res); acl_str = pstrdup(p, "::1/127"); acl = pr_netacl_create(p, acl_str); fail_unless(acl != NULL, "Failed to create ACL: %s", strerror(errno)); ok = "::1/127 <IP address mask, 127-bit mask>"; res = pr_netacl_get_str(p, acl); fail_unless(res != NULL, "Failed to get ACL string: %s", strerror(errno)); fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res); acl_str = pstrdup(p, "::ffff:127.0.0.1/127"); acl = pr_netacl_create(p, acl_str); fail_unless(acl != NULL, "Failed to create ACL: %s", strerror(errno)); ok = "::ffff:127.0.0.1/127 <IP address mask, 127-bit mask>"; res = pr_netacl_get_str(p, acl); fail_unless(res != NULL, "Failed to get ACL string: %s", strerror(errno)); fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res); #endif }
/* Returns 1 if there was a positive match, -1 if there was a negative * match, -2 if there was an error, and zero if there was no match at all. */ int pr_netacl_match(const pr_netacl_t *acl, const pr_netaddr_t *addr) { pool *tmp_pool; if (acl == NULL || addr == NULL) { errno = EINVAL; return -2; } tmp_pool = make_sub_pool(permanent_pool); switch (acl->type) { case PR_NETACL_TYPE_ALL: pr_trace_msg(trace_channel, 10, "addr '%s' matched rule 'ALL' ('%s')", pr_netaddr_get_ipstr(addr), pr_netacl_get_str(tmp_pool, acl)); destroy_pool(tmp_pool); return 1; case PR_NETACL_TYPE_NONE: pr_trace_msg(trace_channel, 10, "addr '%s' matched rule 'NONE'", pr_netaddr_get_ipstr(addr)); destroy_pool(tmp_pool); return -1; case PR_NETACL_TYPE_IPMASK: pr_trace_msg(trace_channel, 10, "checking addr '%s' against IP mask rule '%s'", pr_netaddr_get_ipstr(addr), acl->aclstr); if (pr_netaddr_ncmp(addr, acl->addr, acl->masklen) == 0) { pr_trace_msg(trace_channel, 10, "addr '%s' matched IP mask rule '%s'", pr_netaddr_get_ipstr(addr), acl->aclstr); destroy_pool(tmp_pool); if (acl->negated) return -1; return 1; } else { if (acl->negated) { destroy_pool(tmp_pool); return 1; } } break; case PR_NETACL_TYPE_IPMATCH: pr_trace_msg(trace_channel, 10, "checking addr '%s' against IP address rule '%s'", pr_netaddr_get_ipstr(addr), acl->aclstr); if (pr_netaddr_cmp(addr, acl->addr) == 0) { pr_trace_msg(trace_channel, 10, "addr '%s' matched IP address rule '%s'", pr_netaddr_get_ipstr(addr), acl->aclstr); destroy_pool(tmp_pool); if (acl->negated) return -1; return 1; } else { if (acl->negated) { destroy_pool(tmp_pool); return 1; } } break; case PR_NETACL_TYPE_DNSMATCH: pr_trace_msg(trace_channel, 10, "checking addr '%s' against DNS name rule '%s'", pr_netaddr_get_dnsstr(addr), acl->pattern); if (strcmp(pr_netaddr_get_dnsstr(addr), acl->pattern) == 0) { pr_trace_msg(trace_channel, 10, "addr '%s' (%s) matched DNS name rule '%s'", pr_netaddr_get_ipstr(addr), pr_netaddr_get_dnsstr(addr), acl->aclstr); destroy_pool(tmp_pool); if (acl->negated) return -1; return 1; } else { if (acl->negated) { destroy_pool(tmp_pool); return 1; } } break; case PR_NETACL_TYPE_IPGLOB: pr_trace_msg(trace_channel, 10, "checking addr '%s' against IP glob rule '%s'", pr_netaddr_get_ipstr(addr), acl->aclstr); if (pr_netaddr_fnmatch(addr, acl->pattern, PR_NETADDR_MATCH_IP) == TRUE) { pr_trace_msg(trace_channel, 10, "addr '%s' matched IP glob rule '%s'", pr_netaddr_get_ipstr(addr), acl->aclstr); destroy_pool(tmp_pool); if (acl->negated) return -1; return 1; } else { if (acl->negated) { destroy_pool(tmp_pool); return 1; } } break; case PR_NETACL_TYPE_DNSGLOB: if (ServerUseReverseDNS) { pr_trace_msg(trace_channel, 10, "checking addr '%s' against DNS glob rule '%s'", pr_netaddr_get_dnsstr(addr), acl->pattern); if (pr_netaddr_fnmatch(addr, acl->pattern, PR_NETADDR_MATCH_DNS) == TRUE) { pr_trace_msg(trace_channel, 10, "addr '%s' (%s) matched DNS glob rule '%s'", pr_netaddr_get_ipstr(addr), pr_netaddr_get_dnsstr(addr), acl->aclstr); destroy_pool(tmp_pool); if (acl->negated) return -1; return 1; } else { if (acl->negated) { destroy_pool(tmp_pool); return 1; } } } else { pr_trace_msg(trace_channel, 10, "skipping comparing addr '%s' (%s) against DNS glob rule '%s' " "because UseReverseDNS is off", pr_netaddr_get_ipstr(addr), pr_netaddr_get_dnsstr(addr), acl->aclstr); } break; } destroy_pool(tmp_pool); return 0; }