Beispiel #1
0
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));
}
MODRET add_lmd_allow_from(cmd_rec *cmd) {
    config_rec *c;
    int i;
    array_header *allowed_acls;

    if(cmd->argc < 2 )
        CONF_ERROR(cmd, "argument missing");

    CHECK_CONF(cmd, CONF_ROOT|CONF_GLOBAL);

    /* argv => LMDMemcachedHost 127.0.0.1 192.168.0.1 ... */
    c = find_config(main_server->conf, CONF_PARAM, "LMDBAllow", FALSE);
    if(c && c->argv[0]) {
        allowed_acls = c->argv[0];
    } else {
        c = add_config_param(cmd->argv[0], 0, NULL);
        c->argv[0] = allowed_acls =
          make_array(cmd->server->pool, 0, sizeof(char *));
    }

    for(i=1; i < cmd->argc; i++) {
        char *entry = cmd->argv[i];
        if (strcasecmp(entry, "all") == 0 ||
            strcasecmp(entry, "none") == 0) {
            break;
        }
        pr_netacl_t *acl = pr_netacl_create(cmd->server->pool, entry);
        *((pr_netacl_t **) push_array(allowed_acls)) = acl;
        pr_log_debug(DEBUG2,
            "%s: add LMDBAllow[%d] %s", MODULE_NAME, i, entry);
    }

    return PR_HANDLED(cmd);
}
Beispiel #3
0
END_TEST

START_TEST (class_get_test) {
  const pr_class_t *class;
  int res;
  pr_netacl_t *acl;

  class = pr_class_get(NULL);
  fail_unless(class == NULL, "Failed to handle empty class list");

  acl = pr_netacl_create(p, "all");
  fail_unless(acl != NULL, "Failed to handle ACL string 'all': %s",
    strerror(errno));

  res = pr_class_open(p, "foo");
  fail_unless(res == 0, "Failed to open class: %s", strerror(errno));

  res = pr_class_add_acl(acl);
  fail_unless(res == 0, "Failed to add ACL: %s", strerror(errno));

  class = pr_class_get(NULL);
  fail_unless(class == NULL, "Failed to handle unclosed class in list");

  res = pr_class_close();
  fail_unless(res == 0, "Failed to close class: %s", strerror(errno));

  class = pr_class_get(NULL);
  fail_unless(class != NULL, "Failed to get class in list: %s",
    strerror(errno));
  fail_unless(strcmp(class->cls_name, "foo") == 0,
    "Expected '%s', got '%s'", "foo", class->cls_name);

  class = pr_class_get(class);
  fail_unless(class == NULL, "Failed to return NULL for end-of-list");
}
Beispiel #4
0
END_TEST

START_TEST (class_close_test) {
  pr_netacl_t *acl;
  int res;

  res = pr_class_close();
  fail_unless(res == 0, "Failed to close nonexistent current class: %s",
    strerror(errno));

  res = pr_class_open(p, "foo");
  fail_unless(res == 0, "Failed to open class: %s", strerror(errno));

  res = pr_class_close();
  fail_unless(res == -1, "Failed to close empty class");
  fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
  fail_unless(main_server->config_type == CONF_ROOT,
    "Expected config_type of %d, got %d", CONF_ROOT, main_server->config_type);

  res = pr_class_open(p, "foo");
  fail_unless(res == 0, "Failed to open class: %s", strerror(errno));

  acl = pr_netacl_create(p, "all");
  fail_unless(acl != NULL, "Failed to handle ACL string 'all': %s",
    strerror(errno));

  res = pr_class_add_acl(acl);
  fail_unless(res == 0, "Failed to add ACL: %s", strerror(errno));

  res = pr_class_close();
  fail_unless(res == 0, "Failed to close class: %s", strerror(errno));
  fail_unless(main_server->config_type == CONF_ROOT,
    "Expected config_type of %d, got %d", CONF_ROOT, main_server->config_type);
}
Beispiel #5
0
END_TEST

START_TEST (netacl_get_negated_test) {
  pr_netacl_t *acl;
  int res;

  res = pr_netacl_get_negated(NULL);
  fail_unless(res == -1, "Failed to handle NULL argument");
  fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");

  acl = pr_netacl_create(p, "127.0.0.1");
  fail_unless(acl != NULL, "Failed to create ACL: %s", strerror(errno));

  res = pr_netacl_get_negated(acl);
  fail_unless(res == 0, "Expected %d, got %d", 0, res);

  acl = pr_netacl_create(p, "!127.0.0.1");
  fail_unless(acl != NULL, "Failed to create ACL: %s", strerror(errno));

  res = pr_netacl_get_negated(acl);
  fail_unless(res == 1, "Expected %d, got %d", 1, res);
}
Beispiel #6
0
END_TEST

START_TEST (expr_eval_class_or_test) {
  pr_netacl_t *acl;
  char *names1[3] = { "foo", "test", NULL }, *names2[2] = { "test", NULL },
    *names3[2] = { "!baz", NULL }, *names4[2] = { "foo", NULL };
  int res;

  res = pr_expr_eval_class_or(NULL);
  fail_unless(res == -1, "Failed to handle null argument");
  fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");

  session.conn_class = NULL;

  res = pr_expr_eval_class_or(names1);
  fail_unless(res == FALSE, "Expected FALSE, got TRUE");

  init_netaddr();
  init_class();

  res = pr_class_open(p, "test");
  fail_unless(res == 0, "Failed to open class: %s", strerror(errno));

  acl = pr_netacl_create(p, "all");
  fail_unless(acl != NULL, "Failed to create ACL: %s", strerror(errno));

  res = pr_class_add_acl(acl);
  fail_unless(res == 0, "Failed to add ACL to class: %s", strerror(errno));

  res = pr_class_close();
  fail_unless(res == 0, "Failed to close class: %s", strerror(errno));

  session.conn_class = pr_class_find("test");
  fail_unless(session.conn_class != NULL, "Failed to find 'test' class: %s",
    strerror(errno));

  res = pr_expr_eval_class_or(names1);
  fail_unless(res == TRUE, "Expected TRUE, got FALSE");

  res = pr_expr_eval_class_or(names2);
  fail_unless(res == TRUE, "Expected TRUE, got FALSE");

  res = pr_expr_eval_class_or(names3);
  fail_unless(res == TRUE, "Expected TRUE, got FALSE");

  res = pr_expr_eval_class_or(names4);
  fail_unless(res == FALSE, "Expected FALSE, got TRUE");
}
Beispiel #7
0
END_TEST

START_TEST (class_find_test) {
  const pr_class_t *class;
  pr_netacl_t *acl;
  int res;

  class = pr_class_find(NULL);
  fail_unless(class == NULL, "Failed to handle NULL argument");
  fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");

  class = pr_class_find("foo");
  fail_unless(class == NULL, "Failed to handle empty list");
  fail_unless(errno == ENOENT, "Failed to set errno to ENOENT");

  acl = pr_netacl_create(p, "all");
  fail_unless(acl != NULL, "Failed to handle ACL string 'all': %s",
    strerror(errno));

  res = pr_class_open(p, "foo");
  fail_unless(res == 0, "Failed to open class: %s", strerror(errno));

  res = pr_class_add_acl(acl);
  fail_unless(res == 0, "Failed to add ACL: %s", strerror(errno));

  class = pr_class_find("foo");
  fail_unless(class == NULL, "Failed to handle empty list");
  fail_unless(errno == ENOENT, "Failed to set errno to ENOENT");

  res = pr_class_close();
  fail_unless(res == 0, "Failed to close class: %s", strerror(errno));

  class = pr_class_find("foo");
  fail_unless(class != NULL, "Failed to handle class 'foo': %s",
    strerror(errno));

  class = pr_class_find("bar");
  fail_unless(class == NULL, "Failed to handle nonexistent class");
  fail_unless(errno == ENOENT, "Failed to set errno to ENOENT");
}
Beispiel #8
0
END_TEST

START_TEST (class_add_acl_test) {
  pr_netacl_t *acl;
  int res;

  res = pr_class_add_acl(NULL);
  fail_unless(res == -1, "Failed to handle NULL argument");
  fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");

  acl = pr_netacl_create(p, "all");
  fail_unless(acl != NULL, "Failed to handle ACL string 'all': %s",
    strerror(errno));

  res = pr_class_add_acl(acl);
  fail_unless(res == -1, "Failed to handle unopened class");
  fail_unless(errno == EPERM, "Failed to set errno to EPERM");

  res = pr_class_open(p, "foo");
  fail_unless(res == 0, "Failed to open class: %s", strerror(errno));

  res = pr_class_add_acl(acl);
  fail_unless(res == 0, "Failed to add ACL: %s", strerror(errno));
}
Beispiel #9
0
END_TEST

START_TEST (netacl_match_test) {
  pr_netacl_t *acl;
  pr_netaddr_t *addr;
  char *acl_str;
  int have_localdomain = FALSE, res;

  res = pr_netacl_match(NULL, NULL);
  fail_unless(res == -2, "Failed to handle NULL arguments");
  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 handle ACL string '%s': %s", acl_str,
    strerror(errno));

  res = pr_netacl_match(acl, NULL);
  fail_unless(res == -2, "Failed to handle NULL addr");
  fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");

  addr = pr_netaddr_get_addr(p, "localhost", NULL);
  fail_unless(addr != NULL, "Failed to get addr for '%s': %s", "localhost",
    strerror(errno));

  /* It's possible that the DNS name for 'localhost' that is used will
   * actually be 'localhost.localdomain', depending on the contents of
   * the host's /etc/hosts file.
   */
  if (strcmp(pr_netaddr_get_dnsstr(addr), "localhost.localdomain") == 0) {
    have_localdomain = TRUE;
  }

  res = pr_netacl_match(NULL, addr);
  fail_unless(res == -2, "Failed to handle NULL ACL");
  fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");

  res = pr_netacl_match(acl, addr);
  fail_unless(res == 1, "Failed to positively match ACL to addr: %s",
    strerror(errno));

  acl_str = "none";
  acl = pr_netacl_create(p, acl_str);
  fail_unless(acl != NULL, "Failed to handle ACL string '%s': %s", acl_str,
    strerror(errno));

  res = pr_netacl_match(acl, addr);
  fail_unless(res == -1, "Failed to negatively match ACL to addr: %s",
    strerror(errno));

  acl_str = pstrdup(p, "127.0.0.1");
  acl = pr_netacl_create(p, acl_str);
  fail_unless(acl != NULL, "Failed to handle ACL string '%s': %s", acl_str,
    strerror(errno));

  res = pr_netacl_match(acl, addr);
  fail_unless(res == 1, "Failed to positively match ACL to addr: %s",
    strerror(errno));

  acl_str = pstrdup(p, "!127.0.0.1");
  acl = pr_netacl_create(p, acl_str);
  fail_unless(acl != NULL, "Failed to handle ACL string '%s': %s", acl_str,
    strerror(errno));

  res = pr_netacl_match(acl, addr);
  fail_unless(res == -1, "Failed to negatively match ACL to addr: %s",
    strerror(errno));

  acl_str = pstrdup(p, "192.168.0.1");
  acl = pr_netacl_create(p, acl_str);
  fail_unless(acl != NULL, "Failed to handle ACL string '%s': %s", acl_str,
    strerror(errno));

  res = pr_netacl_match(acl, addr);
  fail_unless(res == 0, "Failed to match ACL to addr: %s", strerror(errno));

  acl_str = pstrdup(p, "!192.168.0.1");
  acl = pr_netacl_create(p, acl_str);
  fail_unless(acl != NULL, "Failed to handle ACL string '%s': %s", acl_str,
    strerror(errno));

  res = pr_netacl_match(acl, addr);
  fail_unless(res == 1, "Failed to positively match ACL to addr: %s",
    strerror(errno));

  acl_str = pstrdup(p, "127.0.0.0/24");
  acl = pr_netacl_create(p, acl_str);
  fail_unless(acl != NULL, "Failed to handle ACL string '%s': %s", acl_str,
    strerror(errno));

  res = pr_netacl_match(acl, addr);
  fail_unless(res == 1, "Failed to positively match ACL to addr: %s",
    strerror(errno));

  acl_str = pstrdup(p, "!127.0.0.0/24");
  acl = pr_netacl_create(p, acl_str);
  fail_unless(acl != NULL, "Failed to handle ACL string '%s': %s", acl_str,
    strerror(errno));

  res = pr_netacl_match(acl, addr);
  fail_unless(res == -1, "Failed to negatively match ACL to addr: %s",
    strerror(errno));

  acl_str = pstrdup(p, "127.0.0.");
  acl = pr_netacl_create(p, acl_str);
  fail_unless(acl != NULL, "Failed to handle ACL string '%s': %s", acl_str,
    strerror(errno));

  res = pr_netacl_match(acl, addr);
  fail_unless(res == 1, "Failed to positively match ACL to addr: %s",
    strerror(errno));

  acl_str = pstrdup(p, "!127.0.0.");
  acl = pr_netacl_create(p, acl_str);
  fail_unless(acl != NULL, "Failed to handle ACL string '%s': %s", acl_str,
    strerror(errno));

  res = pr_netacl_match(acl, addr);
  fail_unless(res == -1, "Failed to negatively match ACL to addr: %s",
    strerror(errno));

  if (!have_localdomain) {
    acl_str = pstrdup(p, "localhost");

  } else {
    acl_str = pstrdup(p, "localhost.localdomain");
  }

  acl = pr_netacl_create(p, acl_str);
  fail_unless(acl != NULL, "Failed to handle ACL string '%s': %s", acl_str,
    strerror(errno));

  res = pr_netacl_match(acl, addr);
  fail_unless(res == 1, "Failed to positively match ACL to addr: %s",
    strerror(errno));

  if (!have_localdomain) {
    acl_str = pstrdup(p, "!localhost");

  } else {
    acl_str = pstrdup(p, "!localhost.localdomain");
  }

  acl = pr_netacl_create(p, acl_str);
  fail_unless(acl != NULL, "Failed to handle ACL string '%s': %s", acl_str,
    strerror(errno));

  res = pr_netacl_match(acl, addr);
  fail_unless(res == -1, "Failed to negatively match ACL to addr: %s",
    strerror(errno));

  if (!have_localdomain) {
    acl_str = pstrdup(p, "loc*st");

  } else {
    acl_str = pstrdup(p, "loc*st.loc*in");
  }

  acl = pr_netacl_create(p, acl_str);
  fail_unless(acl != NULL, "Failed to handle ACL string '%s': %s", acl_str,
    strerror(errno));

  res = pr_netacl_match(acl, addr);
  fail_unless(res == 1, "Failed to positively match ACL to addr: %s",
    strerror(errno));

  if (!have_localdomain) {
    acl_str = pstrdup(p, "!loc*st");

  } else {
    acl_str = pstrdup(p, "!loc*st.loc*in");
  }

  acl = pr_netacl_create(p, acl_str);
  fail_unless(acl != NULL, "Failed to handle ACL string '%s': %s", acl_str,
    strerror(errno));

  res = pr_netacl_match(acl, addr);
  fail_unless(res == -1, "Failed to negatively match ACL to addr: %s",
    strerror(errno));
}
Beispiel #10
0
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
}
Beispiel #11
0
END_TEST

START_TEST (class_match_addr_test) {
  const pr_netaddr_t *addr;
  const pr_class_t *class;
  pr_netacl_t *acl;
  int res;

  class = pr_class_match_addr(NULL);
  fail_unless(class == NULL, "Failed to handle NULL argument");
  fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");

  addr = pr_netaddr_get_addr(p, "localhost", FALSE);
  fail_unless(addr != NULL, "Failed to get addr: %s", strerror(errno));

  class = pr_class_match_addr(addr);
  fail_unless(class == NULL, "Failed to handle empty class list");
  fail_unless(errno == ENOENT, "Failed to set errno to ENOENT");

  res = pr_class_open(p, "localhost");
  fail_unless(res == 0, "Failed to open class: %s", strerror(errno));

  acl = pr_netacl_create(p, "127.0.0.1");
  fail_unless(acl != NULL, "Failed to create ACL: %s", strerror(errno));

  res = pr_class_add_acl(acl);
  fail_unless(res == 0, "Failed to add ACL to class: %s", strerror(errno));

  res = pr_class_close();
  fail_unless(res == 0, "Failed to close class: %s", strerror(errno));

  res = pr_class_open(p, "!localhost");
  fail_unless(res == 0, "Failed to open class: %s", strerror(errno));

  acl = pr_netacl_create(p, "!127.0.0.1");
  fail_unless(acl != NULL, "Failed to create ACL: %s", strerror(errno));

  res = pr_class_add_acl(acl);
  fail_unless(res == 0, "Failed to add ACL to class: %s", strerror(errno));

  res = pr_class_close();
  fail_unless(res == 0, "Failed to close class: %s", strerror(errno));

  class = pr_class_match_addr(addr);
  fail_unless(class != NULL, "Failed to match class for addr: %s",
    strerror(errno));
  fail_unless(strcmp(class->cls_name, "localhost") == 0,
    "Expected '%s', got '%s'", "localhost", class->cls_name);

  /* Reset the class list, add classes in a different order, and try again. */
  init_class();

  res = pr_class_open(p, "!localhost");
  fail_unless(res == 0, "Failed to open class: %s", strerror(errno));

  acl = pr_netacl_create(p, "!127.0.0.1");
  fail_unless(acl != NULL, "Failed to create ACL: %s", strerror(errno));

  res = pr_class_add_acl(acl);
  fail_unless(res == 0, "Failed to add ACL to class: %s", strerror(errno));

  res = pr_class_close();
  fail_unless(res == 0, "Failed to close class: %s", strerror(errno));

  res = pr_class_open(p, "localhost");
  fail_unless(res == 0, "Failed to open class: %s", strerror(errno));

  acl = pr_netacl_create(p, "127.0.0.1");
  fail_unless(acl != NULL, "Failed to create ACL: %s", strerror(errno));

  res = pr_class_add_acl(acl);
  fail_unless(res == 0, "Failed to add ACL to class: %s", strerror(errno));

  res = pr_class_close();
  fail_unless(res == 0, "Failed to close class: %s", strerror(errno));

  class = pr_class_match_addr(addr);
  fail_unless(class != NULL, "Failed to match class for addr: %s",
    strerror(errno));
  fail_unless(strcmp(class->cls_name, "localhost") == 0,
    "Expected '%s', got '%s'", "localhost", class->cls_name);

  /* Reset the class list, and see what happens when we try to match
   * the addr against an impossible set of rules.
   */
  init_class();

  res = pr_class_open(p, "impossible");
  fail_unless(res == 0, "Failed to open class: %s", strerror(errno));

  acl = pr_netacl_create(p, "!127.0.0.1");
  fail_unless(acl != NULL, "Failed to create ACL: %s", strerror(errno));

  res = pr_class_add_acl(acl);
  fail_unless(res == 0, "Failed to add ACL to class: %s", strerror(errno));

  acl = pr_netacl_create(p, "127.0.0.1");
  fail_unless(acl != NULL, "Failed to create ACL: %s", strerror(errno));

  res = pr_class_add_acl(acl);
  fail_unless(res == 0, "Failed to add ACL to class: %s", strerror(errno));

  res = pr_class_set_satisfy(PR_CLASS_SATISFY_ALL);
  fail_unless(res == 0, "Failed to set satisfy value: %s", strerror(errno));

  res = pr_class_close();
  fail_unless(res == 0, "Failed to close class: %s", strerror(errno));

  class = pr_class_match_addr(addr);
  fail_unless(class == NULL, "Unexpectedly matched class for addr");
  fail_unless(errno == ENOENT, "Failed to set errno to ENOENT");

  /* Reset the class list, add two classes with identical rules, and
   * verify that the first matching class wins.
   */
  init_class();

  res = pr_class_open(p, "first");
  fail_unless(res == 0, "Failed to open class: %s", strerror(errno));

  acl = pr_netacl_create(p, "127.0.0.1");
  fail_unless(acl != NULL, "Failed to create ACL: %s", strerror(errno));

  res = pr_class_add_acl(acl);
  fail_unless(res == 0, "Failed to add ACL to class: %s", strerror(errno));

  res = pr_class_close();
  fail_unless(res == 0, "Failed to close class: %s", strerror(errno));

  res = pr_class_open(p, "second");
  fail_unless(res == 0, "Failed to open class: %s", strerror(errno));

  acl = pr_netacl_create(p, "127.0.0.1");
  fail_unless(acl != NULL, "Failed to create ACL: %s", strerror(errno));

  res = pr_class_add_acl(acl);
  fail_unless(res == 0, "Failed to add ACL to class: %s", strerror(errno));

  res = pr_class_close();
  fail_unless(res == 0, "Failed to close class: %s", strerror(errno));

  class = pr_class_match_addr(addr);
  fail_unless(class != NULL, "Failed to match class for addr: %s",
    strerror(errno));
  fail_unless(strcmp(class->cls_name, "first") == 0,
    "Expected '%s', got '%s'", "first", class->cls_name);

  init_class();

  res = pr_class_open(p, "second");
  fail_unless(res == 0, "Failed to open class: %s", strerror(errno));

  acl = pr_netacl_create(p, "127.0.0.1");
  fail_unless(acl != NULL, "Failed to create ACL: %s", strerror(errno));

  res = pr_class_add_acl(acl);
  fail_unless(res == 0, "Failed to add ACL to class: %s", strerror(errno));

  res = pr_class_close();
  fail_unless(res == 0, "Failed to close class: %s", strerror(errno));

  res = pr_class_open(p, "first");
  fail_unless(res == 0, "Failed to open class: %s", strerror(errno));

  acl = pr_netacl_create(p, "127.0.0.1");
  fail_unless(acl != NULL, "Failed to create ACL: %s", strerror(errno));

  res = pr_class_add_acl(acl);
  fail_unless(res == 0, "Failed to add ACL to class: %s", strerror(errno));

  res = pr_class_close();
  fail_unless(res == 0, "Failed to close class: %s", strerror(errno));

  class = pr_class_match_addr(addr);
  fail_unless(class != NULL, "Failed to match class for addr: %s",
    strerror(errno));
  fail_unless(strcmp(class->cls_name, "second") == 0,
    "Expected '%s', got '%s'", "second", class->cls_name);

  init_class();

  res = pr_class_open(p, "match");
  fail_unless(res == 0, "Failed to open class: %s", strerror(errno));

  acl = pr_netacl_create(p, "127.0.0.1");
  fail_unless(acl != NULL, "Failed to create ACL: %s", strerror(errno));

  res = pr_class_add_acl(acl);
  fail_unless(res == 0, "Failed to add ACL to class: %s", strerror(errno));

  res = pr_class_set_satisfy(PR_CLASS_SATISFY_ALL);
  fail_unless(res == 0, "Failed to set satisfy value: %s", strerror(errno));

  res = pr_class_close();
  fail_unless(res == 0, "Failed to close class: %s", strerror(errno));

  class = pr_class_match_addr(addr);
  fail_unless(class != NULL, "Failed to match class for addr: %s",
    strerror(errno));
  fail_unless(strcmp(class->cls_name, "match") == 0,
    "Expected '%s', got '%s'", "match", class->cls_name);

}