X-Git-Url: https://ruderich.org/simon/gitweb/?a=blobdiff_plain;f=nss%2Ftests%2Fgr.c;fp=nss%2Ftests%2Fgr.c;h=e4aee5b97a7f2adc1e339fa8bb33380d4699f43f;hb=839f07d7b3130efc613d7d3fa8ed71a7d8d5fd7f;hp=0000000000000000000000000000000000000000;hpb=61a186321612e50e2c0224ca84c77434d3c42722;p=nsscash%2Fnsscash.git
diff --git a/nss/tests/gr.c b/nss/tests/gr.c
new file mode 100644
index 0000000..e4aee5b
--- /dev/null
+++ b/nss/tests/gr.c
@@ -0,0 +1,328 @@
+/*
+ * Tests for the NSS cash module
+ *
+ * Copyright (C) 2019 Simon Ruderich
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "../cash_nss.h"
+
+
+static void test_getgrent(void) {
+ struct group g;
+ enum nss_status s;
+ char tmp[1024];
+ char tmp_small[10];
+ int errnop = 0;
+
+ // Test one setgrent/getgrent/endgrent round
+
+ s = _nss_cash_setgrent(0);
+ assert(s == NSS_STATUS_SUCCESS);
+
+ // Multiple calls with too small buffer don't advance any internal indices
+ s = _nss_cash_getgrent_r(&g, tmp_small, sizeof(tmp_small), &errnop);
+ assert(s == NSS_STATUS_TRYAGAIN);
+ assert(errnop == ERANGE);
+ s = _nss_cash_getgrent_r(&g, tmp_small, sizeof(tmp_small), &errnop);
+ assert(s == NSS_STATUS_TRYAGAIN);
+ assert(errnop == ERANGE);
+ s = _nss_cash_getgrent_r(&g, tmp_small, sizeof(tmp_small), &errnop);
+ assert(s == NSS_STATUS_TRYAGAIN);
+ assert(errnop == ERANGE);
+
+ s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
+ assert(s == NSS_STATUS_SUCCESS);
+ assert(!strcmp(g.gr_name, "root"));
+ assert(!strcmp(g.gr_passwd, "x"));
+ assert(g.gr_gid == 0);
+ assert(g.gr_mem != NULL);
+ assert(g.gr_mem[0] == NULL);
+
+ s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
+ assert(s == NSS_STATUS_SUCCESS);
+ assert(!strcmp(g.gr_name, "daemon"));
+ assert(g.gr_gid == 1);
+ assert(g.gr_mem != NULL);
+ assert(!strcmp(g.gr_mem[0], "andariel"));
+ assert(!strcmp(g.gr_mem[1], "duriel"));
+ assert(!strcmp(g.gr_mem[2], "mephisto"));
+ assert(!strcmp(g.gr_mem[3], "diablo"));
+ assert(!strcmp(g.gr_mem[4], "baal"));
+ assert(g.gr_mem[5] == NULL);
+ for (int i = 0; i < 21; i++) {
+ s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
+ assert(s == NSS_STATUS_SUCCESS);
+ }
+ s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
+ assert(s == NSS_STATUS_SUCCESS);
+ assert(!strcmp(g.gr_name, "www-data"));
+ assert(!strcmp(g.gr_passwd, "x"));
+ assert(g.gr_gid == 33);
+ assert(g.gr_mem != NULL);
+ assert(!strcmp(g.gr_mem[0], "nobody"));
+ assert(g.gr_mem[1] == NULL);
+ for (int i = 0; i < 29; i++) {
+ s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
+ assert(s == NSS_STATUS_SUCCESS);
+ }
+ s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
+ assert(s == NSS_STATUS_SUCCESS);
+ assert(!strcmp(g.gr_name, "postfix"));
+ s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
+ assert(s == NSS_STATUS_SUCCESS);
+ assert(!strcmp(g.gr_name, "postdrop"));
+ s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
+ assert(s == NSS_STATUS_NOTFOUND);
+ assert(errnop == ENOENT);
+
+ s = _nss_cash_endgrent();
+ assert(s == NSS_STATUS_SUCCESS);
+
+
+ // Test proper reset
+
+ s = _nss_cash_setgrent(0);
+ assert(s == NSS_STATUS_SUCCESS);
+
+ s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
+ assert(s == NSS_STATUS_SUCCESS);
+ assert(!strcmp(g.gr_name, "root"));
+ assert(!strcmp(g.gr_passwd, "x"));
+ assert(g.gr_gid == 0);
+ assert(g.gr_mem != NULL);
+ assert(g.gr_mem[0] == NULL);
+
+ s = _nss_cash_endgrent();
+ assert(s == NSS_STATUS_SUCCESS);
+
+
+ // Test proper reset the 2nd
+
+ s = _nss_cash_setgrent(0);
+ assert(s == NSS_STATUS_SUCCESS);
+
+ s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
+ assert(s == NSS_STATUS_SUCCESS);
+ assert(!strcmp(g.gr_name, "root"));
+ assert(!strcmp(g.gr_passwd, "x"));
+ assert(g.gr_gid == 0);
+ assert(g.gr_mem != NULL);
+ assert(g.gr_mem[0] == NULL);
+
+ s = _nss_cash_endgrent();
+ assert(s == NSS_STATUS_SUCCESS);
+
+
+ // Test many rounds to check for open file leaks
+ for (int i = 0; i < 10000; i++) {
+ s = _nss_cash_setgrent(0);
+ assert(s == NSS_STATUS_SUCCESS);
+
+ s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
+ assert(s == NSS_STATUS_SUCCESS);
+ assert(!strcmp(g.gr_name, "root"));
+
+ s = _nss_cash_endgrent();
+ assert(s == NSS_STATUS_SUCCESS);
+ }
+
+
+ // Test with cash file is not present
+
+ assert(rename("tests/group.nsscash", "tests/group.nsscash.tmp") == 0);
+ s = _nss_cash_setgrent(0);
+ assert(s == NSS_STATUS_SUCCESS);
+ s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
+ assert(s == NSS_STATUS_UNAVAIL);
+ assert(errnop == ENOENT);
+ s = _nss_cash_getgrent_r(&g, tmp, sizeof(tmp), &errnop);
+ assert(s == NSS_STATUS_UNAVAIL);
+ assert(errnop == ENOENT);
+ s = _nss_cash_endgrent();
+ assert(s == NSS_STATUS_SUCCESS);
+ assert(rename("tests/group.nsscash.tmp", "tests/group.nsscash") == 0);
+}
+
+static void test_getgrgid(void) {
+ struct group g;
+ enum nss_status s;
+ char tmp[1024];
+ char tmp_small[10];
+ int errnop = 0;
+
+ s = _nss_cash_getgrgid_r(0, &g, tmp_small, sizeof(tmp_small), &errnop);
+ assert(s == NSS_STATUS_TRYAGAIN);
+ assert(errnop == ERANGE);
+ s = _nss_cash_getgrgid_r(14, &g, tmp_small, sizeof(tmp_small), &errnop);
+ assert(s == NSS_STATUS_NOTFOUND); // 14 does not exist
+ assert(errnop == ENOENT);
+ s = _nss_cash_getgrgid_r(65534, &g, tmp_small, sizeof(tmp_small), &errnop);
+ assert(s == NSS_STATUS_TRYAGAIN);
+ assert(errnop == ERANGE);
+
+ s = _nss_cash_getgrgid_r(0, &g, tmp, sizeof(tmp), &errnop);
+ assert(s == NSS_STATUS_SUCCESS);
+ assert(!strcmp(g.gr_name, "root"));
+ assert(!strcmp(g.gr_passwd, "x"));
+ assert(g.gr_gid == 0);
+ assert(g.gr_mem != NULL);
+ assert(g.gr_mem[0] == NULL);
+
+ s = _nss_cash_getgrgid_r(1, &g, tmp, sizeof(tmp), &errnop);
+ assert(s == NSS_STATUS_SUCCESS);
+ assert(!strcmp(g.gr_name, "daemon"));
+ assert(g.gr_gid == 1);
+ assert(g.gr_mem != NULL);
+ assert(!strcmp(g.gr_mem[0], "andariel"));
+ assert(!strcmp(g.gr_mem[1], "duriel"));
+ assert(!strcmp(g.gr_mem[2], "mephisto"));
+ assert(!strcmp(g.gr_mem[3], "diablo"));
+ assert(!strcmp(g.gr_mem[4], "baal"));
+ assert(g.gr_mem[5] == NULL);
+
+ s = _nss_cash_getgrgid_r(11, &g, tmp, sizeof(tmp), &errnop);
+ assert(s == NSS_STATUS_NOTFOUND);
+ assert(errnop == ENOENT);
+
+ s = _nss_cash_getgrgid_r(103, &g, tmp, sizeof(tmp), &errnop);
+ assert(s == NSS_STATUS_SUCCESS);
+ assert(!strcmp(g.gr_name, "systemd-network"));
+ assert(!strcmp(g.gr_passwd, "x"));
+ assert(g.gr_gid == 103);
+ assert(g.gr_mem != NULL);
+ assert(g.gr_mem[0] == NULL);
+
+ s = _nss_cash_getgrgid_r(107, &g, tmp, sizeof(tmp), &errnop);
+ assert(s == NSS_STATUS_SUCCESS);
+ assert(!strcmp(g.gr_name, "kvm"));
+ assert(!strcmp(g.gr_passwd, "x"));
+ assert(g.gr_gid == 107);
+ assert(g.gr_mem != NULL);
+ assert(g.gr_mem[0] == NULL);
+
+ s = _nss_cash_getgrgid_r(65534, &g, tmp, sizeof(tmp), &errnop);
+ assert(s == NSS_STATUS_SUCCESS);
+ assert(!strcmp(g.gr_name, "nogroup"));
+ assert(!strcmp(g.gr_passwd, "x"));
+ assert(g.gr_gid == 65534);
+ assert(g.gr_mem != NULL);
+ assert(g.gr_mem[0] == NULL);
+
+ s = _nss_cash_getgrgid_r(INT_MAX, &g, tmp, sizeof(tmp), &errnop);
+ assert(s == NSS_STATUS_NOTFOUND);
+ assert(errnop == ENOENT);
+
+
+ // Test with cash file is not present
+
+ assert(rename("tests/group.nsscash", "tests/group.nsscash.tmp") == 0);
+ s = _nss_cash_getgrgid_r(0, &g, tmp, sizeof(tmp), &errnop);
+ assert(s == NSS_STATUS_UNAVAIL);
+ assert(errnop == ENOENT);
+ s = _nss_cash_getgrgid_r(14, &g, tmp, sizeof(tmp), &errnop);
+ assert(s == NSS_STATUS_UNAVAIL);
+ assert(errnop == ENOENT);
+ assert(rename("tests/group.nsscash.tmp", "tests/group.nsscash") == 0);
+}
+
+static void test_getgrnam(void) {
+ struct group g;
+ enum nss_status s;
+ char tmp[1024];
+ char tmp_small[10];
+ int errnop = 0;
+
+ s = _nss_cash_getgrnam_r("root", &g, tmp_small, sizeof(tmp_small), &errnop);
+ assert(s == NSS_STATUS_TRYAGAIN);
+ assert(errnop == ERANGE);
+ s = _nss_cash_getgrnam_r("nope", &g, tmp_small, sizeof(tmp_small), &errnop);
+ assert(s == NSS_STATUS_NOTFOUND); // does not exist
+ assert(errnop == ENOENT);
+ s = _nss_cash_getgrnam_r("nogroup", &g, tmp_small, sizeof(tmp_small), &errnop);
+ assert(s == NSS_STATUS_TRYAGAIN);
+ assert(errnop == ERANGE);
+
+ s = _nss_cash_getgrnam_r("root", &g, tmp, sizeof(tmp), &errnop);
+ assert(s == NSS_STATUS_SUCCESS);
+ assert(!strcmp(g.gr_name, "root"));
+ assert(!strcmp(g.gr_passwd, "x"));
+ assert(g.gr_gid == 0);
+ assert(g.gr_mem != NULL);
+ assert(g.gr_mem[0] == NULL);
+
+ s = _nss_cash_getgrnam_r("daemon", &g, tmp, sizeof(tmp), &errnop);
+ assert(s == NSS_STATUS_SUCCESS);
+ assert(!strcmp(g.gr_name, "daemon"));
+ assert(g.gr_gid == 1);
+ assert(g.gr_mem != NULL);
+ assert(!strcmp(g.gr_mem[0], "andariel"));
+ assert(!strcmp(g.gr_mem[1], "duriel"));
+ assert(!strcmp(g.gr_mem[2], "mephisto"));
+ assert(!strcmp(g.gr_mem[3], "diablo"));
+ assert(!strcmp(g.gr_mem[4], "baal"));
+ assert(g.gr_mem[5] == NULL);
+
+ s = _nss_cash_getgrnam_r("nope2", &g, tmp, sizeof(tmp), &errnop);
+ assert(s == NSS_STATUS_NOTFOUND);
+ assert(errnop == ENOENT);
+
+ s = _nss_cash_getgrnam_r("systemd-network", &g, tmp, sizeof(tmp), &errnop);
+ assert(s == NSS_STATUS_SUCCESS);
+ assert(!strcmp(g.gr_name, "systemd-network"));
+ assert(!strcmp(g.gr_passwd, "x"));
+ assert(g.gr_gid == 103);
+ assert(g.gr_mem != NULL);
+ assert(g.gr_mem[0] == NULL);
+
+ s = _nss_cash_getgrnam_r("postfix", &g, tmp, sizeof(tmp), &errnop);
+ assert(s == NSS_STATUS_SUCCESS);
+ assert(!strcmp(g.gr_name, "postfix"));
+ assert(!strcmp(g.gr_passwd, "x"));
+ assert(g.gr_gid == 114);
+ assert(g.gr_mem != NULL);
+ assert(g.gr_mem[0] == NULL);
+
+ s = _nss_cash_getgrnam_r("", &g, tmp, sizeof(tmp), &errnop);
+ assert(s == NSS_STATUS_NOTFOUND);
+ assert(errnop == ENOENT);
+
+
+ // Test with cash file is not present
+
+ assert(rename("tests/group.nsscash", "tests/group.nsscash.tmp") == 0);
+ s = _nss_cash_getgrnam_r("root", &g, tmp, sizeof(tmp), &errnop);
+ assert(s == NSS_STATUS_UNAVAIL);
+ assert(errnop == ENOENT);
+ s = _nss_cash_getgrnam_r("nope", &g, tmp, sizeof(tmp), &errnop);
+ assert(s == NSS_STATUS_UNAVAIL);
+ assert(errnop == ENOENT);
+ assert(rename("tests/group.nsscash.tmp", "tests/group.nsscash") == 0);
+}
+
+int main(void) {
+ test_getgrent();
+ test_getgrgid();
+ test_getgrnam();
+
+ return EXIT_SUCCESS;
+}