From b13fe082e942680d0c77b0dcf7fd9bd21fc3902b Mon Sep 17 00:00:00 2001 From: Lukas Braun <lukas.braun@fau.de> Date: Sun, 27 Aug 2017 23:50:07 +0200 Subject: [PATCH] Add ability to query multiple servers in pam_goatherd.so The OTP is sent to all servers and authentication only succeeds if a majority answers with OK. No communication between servers or their backing DBs is necessary. Servers are re-synchronized after a (limited) downtime by the usual lookahead range. --- Makefile | 2 +- pam_goatherd.c | 61 +++++++---- pam_goatherd_test.conf | 3 + test.crt | 28 +++++ test.key | 240 +++++++++++++++++++++++++++++++++++++++++ test_pam_goatherd.sh | 105 ++++++++++++++++++ 6 files changed, 419 insertions(+), 20 deletions(-) create mode 100644 pam_goatherd_test.conf create mode 100644 test.crt create mode 100644 test.key create mode 100644 test_pam_goatherd.sh diff --git a/Makefile b/Makefile index 20b6c1c..7e2adea 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -CFLAGS += -std=c11 -D_POSIX_C_SOURCE=201112 -Wall -Wconversion -fPIC +CFLAGS += -std=c11 -D_GNU_SOURCE -Wall -Wconversion -fPIC PAMDIR ?= /lib/security diff --git a/pam_goatherd.c b/pam_goatherd.c index 6cd78a2..06a50a9 100644 --- a/pam_goatherd.c +++ b/pam_goatherd.c @@ -18,14 +18,16 @@ #define PAM_SM_AUTH #include <security/pam_modules.h> +// arbitrary but small because currently all servers are asked sequentially +#define MAX_SERVERS 7 + struct cfg { int debug; - const char *server; - const char *port; + const char *servers[MAX_SERVERS]; + const char *ports[MAX_SERVERS]; const char *certs; }; static const char arg_server[] = "server="; -static const char arg_port[] = "port="; static const char arg_certs[] = "certs="; static const char str_ok[] = "OK\n"; @@ -42,6 +44,7 @@ static const char str_fail[] = "FAIL\n"; static int verify_cb(gnutls_session_t session) { int err; + // used in debug macros struct cfg cfg = *(const struct cfg *)gnutls_session_get_ptr(session); unsigned int status; if ((err = gnutls_certificate_verify_peers2(session, &status)) < 0) @@ -82,8 +85,7 @@ static int send_full(gnutls_session_t session, const void *data, size_t len) return 0; } - -static int check_hotp(struct cfg cfg, const char *user, const char *hotp) +static int check_hotp(struct cfg cfg, size_t n_server, const char *user, const char *hotp) { int err; @@ -135,7 +137,7 @@ static int check_hotp(struct cfg cfg, const char *user, const char *hotp) dbgp("connecting..."); struct addrinfo hint = { .ai_socktype = SOCK_STREAM }; struct addrinfo *addris_start; - if ((err = getaddrinfo(cfg.server, cfg.port, &hint, &addris_start)) != 0) + if ((err = getaddrinfo(cfg.servers[n_server], cfg.ports[n_server], &hint, &addris_start)) != 0) { dbgp(gai_strerror(err)); err = PAM_AUTHINFO_UNAVAIL; @@ -236,6 +238,7 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) { int err; struct cfg cfg = { 0 }; + size_t n_servers = 0; for (int i = 0; i < argc; i++) { @@ -245,11 +248,28 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) } else if (!strncmp(argv[i], arg_server, strlen(arg_server))) { - cfg.server = &argv[i][strlen(arg_server)]; - } - else if (!strncmp(argv[i], arg_port, strlen(arg_port))) - { - cfg.port = &argv[i][strlen(arg_port)]; + if (n_servers >= MAX_SERVERS) + { + fprintf(stderr, "Too many servers specified (max %i)\n", MAX_SERVERS); + return PAM_AUTHINFO_UNAVAIL; + } + + // Duplicate the string so we can use strtok to split address + // and port (pam argv entries are const). Use strdupa to + // allocate on the stack and avoid free() headaches (needs + // _GNU_SOURCE). + char *serverport = strdupa(&argv[i][strlen(arg_server)]); + char *saveptr; + + // TODO: handle IPv6 addrs + cfg.servers[n_servers] = strtok_r(serverport, ":", &saveptr); + cfg.ports[n_servers] = strtok_r(NULL, ":", &saveptr); + if (!cfg.ports[n_servers]) { + dbgp2("Fatal: need port for", serverport); + return PAM_AUTHINFO_UNAVAIL; + } + + n_servers++; } else if (!strncmp(argv[i], arg_certs, strlen(arg_certs))) { @@ -257,16 +277,11 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) } } - if (!cfg.server) + if (n_servers == 0) { dbgp("Fatal: No server specified"); return PAM_AUTHINFO_UNAVAIL; } - if (!cfg.port) - { - dbgp("Fatal: No port specified"); - return PAM_AUTHINFO_UNAVAIL; - } if (!cfg.certs) { dbgp("Fatal: No certs specified"); @@ -307,10 +322,18 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) char *hotp = resp[0].resp; free(resp); - err = check_hotp(cfg, user, hotp); + unsigned int acks = 0; + for (size_t i = 0; i < n_servers; i++) + { + err = check_hotp(cfg, i, user, hotp); + if (err == PAM_SUCCESS) + { + acks++; + } + } free(hotp); - return err; + return acks > n_servers/2 ? PAM_SUCCESS : PAM_AUTH_ERR; } PAM_EXTERN int diff --git a/pam_goatherd_test.conf b/pam_goatherd_test.conf new file mode 100644 index 0000000..3b12406 --- /dev/null +++ b/pam_goatherd_test.conf @@ -0,0 +1,3 @@ +{ + "db_driver": "postgres" +} diff --git a/test.crt b/test.crt new file mode 100644 index 0000000..b551847 --- /dev/null +++ b/test.crt @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEtTCCAp2gAwIBAgIMWaMZjRy8vAhZmO2cMA0GCSqGSIb3DQEBDQUAMAAwHhcN +MTcwODI3MTkxMjEzWhcNMTgwODI3MTkxMjEzWjAAMIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEAy2P8WJLAE379dc2ho8KV+wJHHaGdSOf1pA3GwrSXzvA1 +niQ9RpCi2HdLCEEA42gGwfQ80ndkVZDCJhl/tQ7O6uVGhxcq4u0nHZvbQ77kCTrf +qrdiTAsGaYO+5/d9Y8V8swx5xzEJ8ZHmlCm/AnPzT0fDRTkEcqTvH4uyVKfERpmq +l00BNQ51ELmTColgzshdrd3MiJ+H74L+6Te6IjfzwxqQvuqxEYLHg5Hl7BfkZQZa +w5lpCNyb1b2pyUbjlGIWgh6AEPbB46IBIW2rikDkZCqnii5asrD+Y+BWdu4yDC6j +tRYPg9SEwKlndp4y2pt+Etc7j2ElwK57EphpRHSN7yx8dk+LGAsubo5LfQfaskjW +ft89M/N8Fr8xTqNIXiFx4RXZYuojRHjHbhahf0bq4ekzNXr09G0GbhRf5/Uf4IZ+ +hFS8YhEXJVKDYgSL+3iUH0ul6+5U7vxxyXm64Qnqffu/9Mh6UGJmAAsrs/d7hARv +XeMilSag6bVAriEmUQi8f+jGRf0MCpmWS3uB4IMyIpk9CHegSFha6OaiSJqI4TG2 +wWXjdlnX9uxSqXaUydVKYckTZ2GRIgHMHHht7ddYCC2QyP5sROhwyUZ5dZ3CbL00 +xFITrWnXCHMz6Ndnd2D+smqJSU9/GtbUIPG3ux91X42dClWuDuAWYSZHFWjD7c0C +AwEAAaMvMC0wDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU+6xchmUIp4qZosx58zgP +zlgBg1swDQYJKoZIhvcNAQENBQADggIBAF9C5d+3o/WI6L+h99Hd2cAJeCtFO7w7 +RYi3Thd9A5tIsnGBc0zy34Y5VnfgUr1HSZb8lCtsRenitwe/cDBnSkZgzavz/ti0 +y6cnQsUaNRNFdOCApBaFNXGgBrJoeW05AdktjMkcQozGQ7uDBSWnK0ctmRry+AFw +o6WQx3noz+/XxmbwSXm7tBYJgJrs4+cl70Avh5hMVo1Arp/RFZY5JRdsXYvEYSzb +/ArjX8UKjF8gmRuQwTwFqQyn1MI61uC7Rga7WI4+EuyJkbYpo/GkMLscEJkQ4O6f +YPrOwWtkTqEvC5DDC0R1HP50omac1j+DxxJBxAyMwluTjcHvg6W9bZzkyuP7wxm+ +Q9LeQtQYwDFtcp2jfd2fxwpV/WGF2IoWSUFWr8A/pzdIAVgGxCnFHcCV6B8GRayO +czBytwItCW6GWuYiLi4YlUxco5388Vp6JkCYCjLr90+td+C11Uc3I8Al0cTPW6F7 +jfcaJRvqvDN19pS+nkZk38rmRN6wyJwBSbe1wIFa2aXpK3ZTHRuoGMRseITezjwt +UA9rJI93XI/ZdnYFOSnmhFSm6+hcS5+rDxwN4mwl6Ok93bxMGpkWLme6lkVipWpy +bhL0bn+S7bCsbz9MQKOt2Uc0GmlEFZZJIGZUvLh694QTJtXJa+YTvLCiAfGwbN3R +pZ+uIa0JSizC +-----END CERTIFICATE----- diff --git a/test.key b/test.key new file mode 100644 index 0000000..456872e --- /dev/null +++ b/test.key @@ -0,0 +1,240 @@ +Public Key Info: + Public Key Algorithm: RSA + Key Security Level: High (4096 bits) + +modulus: + 00:cb:63:fc:58:92:c0:13:7e:fd:75:cd:a1:a3:c2:95 + fb:02:47:1d:a1:9d:48:e7:f5:a4:0d:c6:c2:b4:97:ce + f0:35:9e:24:3d:46:90:a2:d8:77:4b:08:41:00:e3:68 + 06:c1:f4:3c:d2:77:64:55:90:c2:26:19:7f:b5:0e:ce + ea:e5:46:87:17:2a:e2:ed:27:1d:9b:db:43:be:e4:09 + 3a:df:aa:b7:62:4c:0b:06:69:83:be:e7:f7:7d:63:c5 + 7c:b3:0c:79:c7:31:09:f1:91:e6:94:29:bf:02:73:f3 + 4f:47:c3:45:39:04:72:a4:ef:1f:8b:b2:54:a7:c4:46 + 99:aa:97:4d:01:35:0e:75:10:b9:93:0a:89:60:ce:c8 + 5d:ad:dd:cc:88:9f:87:ef:82:fe:e9:37:ba:22:37:f3 + c3:1a:90:be:ea:b1:11:82:c7:83:91:e5:ec:17:e4:65 + 06:5a:c3:99:69:08:dc:9b:d5:bd:a9:c9:46:e3:94:62 + 16:82:1e:80:10:f6:c1:e3:a2:01:21:6d:ab:8a:40:e4 + 64:2a:a7:8a:2e:5a:b2:b0:fe:63:e0:56:76:ee:32:0c + 2e:a3:b5:16:0f:83:d4:84:c0:a9:67:76:9e:32:da:9b + 7e:12:d7:3b:8f:61:25:c0:ae:7b:12:98:69:44:74:8d + ef:2c:7c:76:4f:8b:18:0b:2e:6e:8e:4b:7d:07:da:b2 + 48:d6:7e:df:3d:33:f3:7c:16:bf:31:4e:a3:48:5e:21 + 71:e1:15:d9:62:ea:23:44:78:c7:6e:16:a1:7f:46:ea + e1:e9:33:35:7a:f4:f4:6d:06:6e:14:5f:e7:f5:1f:e0 + 86:7e:84:54:bc:62:11:17:25:52:83:62:04:8b:fb:78 + 94:1f:4b:a5:eb:ee:54:ee:fc:71:c9:79:ba:e1:09:ea + 7d:fb:bf:f4:c8:7a:50:62:66:00:0b:2b:b3:f7:7b:84 + 04:6f:5d:e3:22:95:26:a0:e9:b5:40:ae:21:26:51:08 + bc:7f:e8:c6:45:fd:0c:0a:99:96:4b:7b:81:e0:83:32 + 22:99:3d:08:77:a0:48:58:5a:e8:e6:a2:48:9a:88:e1 + 31:b6:c1:65:e3:76:59:d7:f6:ec:52:a9:76:94:c9:d5 + 4a:61:c9:13:67:61:91:22:01:cc:1c:78:6d:ed:d7:58 + 08:2d:90:c8:fe:6c:44:e8:70:c9:46:79:75:9d:c2:6c + bd:34:c4:52:13:ad:69:d7:08:73:33:e8:d7:67:77:60 + fe:b2:6a:89:49:4f:7f:1a:d6:d4:20:f1:b7:bb:1f:75 + 5f:8d:9d:0a:55:ae:0e:e0:16:61:26:47:15:68:c3:ed + cd: + +public exponent: + 01:00:01: + +private exponent: + 00:96:37:53:81:cb:68:e7:3d:4c:4f:7c:3f:1c:a6:b3 + 84:be:ca:ed:5c:96:c0:e8:e8:a8:70:b0:52:cf:74:ab + 97:07:d2:b3:ab:39:f9:ca:fc:1b:27:24:82:75:f8:7e + b5:36:fc:7f:0b:66:b8:88:e5:b0:2e:d9:78:53:ae:0b + 2e:bb:85:5a:72:c6:ee:f0:fe:89:c4:b9:ad:90:47:f5 + 75:31:0a:72:04:bc:6b:0c:22:53:f6:64:76:8a:7a:6c + ba:4b:b7:34:1d:e4:df:16:36:8e:d8:f0:f8:2d:04:9c + 37:fa:a5:82:f3:b8:90:3f:b6:88:52:f1:b3:ca:70:91 + 40:1f:19:3d:fb:5d:47:3f:38:ca:06:8a:aa:aa:00:2f + 45:d9:0a:ce:6c:3d:7e:f5:6b:87:7f:91:f3:fc:1f:dc + fe:45:19:90:97:df:8d:32:4c:ce:a4:ab:ee:b2:3a:b2 + 4e:7e:2c:a6:9a:47:bc:3f:b0:1e:33:4e:ff:f7:47:79 + 26:6c:95:c0:3a:47:35:2e:3d:51:9e:71:d4:56:f8:d4 + 76:12:76:c8:fc:b1:69:f6:84:fc:19:0d:63:2b:4b:75 + 69:e0:e8:f6:d1:20:a9:8e:1e:89:3f:6c:01:2d:47:fd + bd:a0:86:ac:6b:99:f1:7b:1c:a2:b3:3a:33:cd:26:54 + 48:75:f9:86:1d:49:ab:bb:a4:ab:e3:84:03:8d:8c:3b + e7:0e:c3:10:71:14:ec:5a:b9:7b:72:93:a8:30:e0:a6 + 2f:29:2e:8c:ea:da:fd:14:9c:c3:5c:ee:5d:8e:9b:f6 + 9b:20:f9:6d:88:84:f5:ef:51:fb:40:cd:48:c4:a3:95 + 0a:c7:c8:4a:01:42:99:21:9b:66:2c:f4:2d:60:5e:eb + e4:ea:88:06:ed:96:d4:44:bd:d2:0c:c9:f8:2b:1b:d1 + fa:68:6f:81:4d:e8:ca:c6:be:c7:8b:21:91:75:af:5e + c5:be:8a:45:db:dd:b2:6b:41:2c:c7:16:b7:cd:f2:d6 + 47:48:7a:1a:a2:c0:b8:34:df:8c:23:db:52:2c:f6:12 + d8:1d:e8:d9:31:0e:2e:83:a3:9e:2a:fb:93:b4:33:ef + d0:23:bb:c9:86:51:3e:d7:ce:b4:26:5e:be:5d:8b:d0 + c9:a5:c7:a6:a6:66:40:7c:15:9c:bf:0f:61:f6:02:4c + 65:2e:34:78:da:e8:24:f6:1b:56:79:e7:8b:25:e1:7d + db:26:48:5c:b2:ab:1d:6f:b1:77:5b:6d:9d:35:e8:90 + 39:6a:42:f3:8a:dd:f8:06:bf:7e:c3:48:99:8a:3c:d5 + d7:ae:52:a4:45:22:a0:bc:f8:a3:1d:bf:a1:32:16:48 + e1: + +prime1: + 00:f8:ec:b6:f0:76:a9:40:c3:1b:5c:9b:9f:b2:d9:17 + 6d:6a:1d:a4:83:52:c8:3a:7d:26:1e:c5:6d:18:27:e3 + 49:f8:51:11:a7:f7:f7:ee:f7:d0:c9:06:0a:a1:8b:26 + 1f:9d:7e:13:80:aa:eb:f6:10:7a:bb:cc:74:46:b0:53 + 55:24:13:f6:7b:ca:62:77:48:dc:d1:4f:0c:2b:fd:8f + 54:90:5c:32:2c:d8:13:1d:4f:59:ea:8c:cf:72:06:c2 + f0:38:98:5c:27:56:8e:65:9f:38:ea:e1:9a:b6:02:db + 3b:f7:d6:ce:fa:a1:32:12:ab:8a:b5:86:52:1d:1c:19 + d6:26:58:cb:44:4e:07:e0:fc:e5:0f:e9:a4:29:12:38 + 79:1e:0a:6a:55:93:6c:4d:41:be:50:37:02:70:81:6d + c8:99:d0:31:9c:3a:53:f8:de:32:36:eb:c3:c1:1a:84 + 33:b7:48:49:71:a3:64:05:b3:00:ee:fc:d7:5a:63:b3 + 4b:67:b6:f9:b1:a8:11:83:18:b2:e1:59:4e:f2:08:23 + 23:c5:da:b5:68:8c:c1:86:d2:94:cd:67:db:59:6a:90 + 5d:f1:4e:47:e7:4f:98:e0:70:d1:7a:a9:bf:72:9c:9e + be:6d:b4:77:97:e5:47:79:cb:a9:6d:5a:81:94:b5:eb + c5: + +prime2: + 00:d1:2b:f1:eb:2f:46:23:69:f5:26:91:f5:ea:d5:08 + 60:f3:0d:17:90:84:a9:ce:69:cd:0d:3b:0a:e3:ec:db + cc:77:8f:89:39:3a:ef:47:c3:92:85:8e:07:90:11:6e + a6:41:8c:c3:d3:10:5a:da:a8:51:0f:c9:72:e6:27:1b + 00:be:60:cf:2c:5e:a7:a2:fe:a4:ab:84:ed:d3:71:39 + 67:20:ba:f2:4e:a6:a1:36:61:d5:38:c7:6a:85:58:f7 + 87:71:f5:a2:11:68:41:9f:4d:63:de:89:72:41:a9:a1 + e2:bd:9b:19:ba:d8:3e:be:62:82:f3:b0:44:d9:3e:4d + d1:cf:17:48:00:e8:db:2f:a3:31:3d:0d:b4:c7:5d:6d + ab:1b:32:d5:82:33:73:28:d9:0b:5e:80:23:fb:a5:a8 + 90:5d:55:d5:d5:53:f9:c3:cc:2b:83:5f:72:29:b5:52 + bd:d4:86:fe:ee:fe:a6:1b:e0:fd:b9:c6:b4:eb:f9:f8 + 35:c3:b5:ec:8f:be:d2:97:5e:d7:f9:4b:78:ee:bc:2a + 9d:08:c6:7d:02:3f:6e:e5:d1:a0:9e:f9:50:9d:e6:47 + 74:54:7e:b8:6d:4d:fc:52:4b:e0:03:75:a5:5e:9c:8d + 80:7f:12:0a:62:24:c1:08:a8:f4:90:6c:40:a2:8e:f2 + 69: + +coefficient: + 00:d9:00:40:e9:68:0e:73:b0:85:69:d3:41:3e:64:89 + 7f:31:af:47:80:35:58:c9:2e:25:a5:ab:7a:5f:0c:9e + 5d:2e:ad:f4:7f:68:38:7d:14:35:04:75:28:d7:86:08 + 74:8c:b2:1e:4f:22:98:c3:2e:1e:ec:9f:b4:fc:62:f5 + c1:66:79:76:9f:52:28:67:3a:03:9b:7d:47:8c:26:93 + 18:b9:2c:2d:f8:c2:6e:77:ca:d8:68:c0:7a:8a:3c:fa + df:4e:ad:4f:31:ad:c8:77:7f:24:95:e2:66:56:8b:13 + e0:21:d5:ba:19:98:77:87:8c:43:0d:da:5d:a7:35:cb + 1b:ba:fa:ff:07:fa:26:44:1e:8e:9b:da:f6:e8:5c:e2 + 38:63:7b:cc:33:b3:63:71:3e:dc:29:eb:21:2f:04:f4 + 18:99:2b:9d:4e:78:3c:d2:17:43:81:d6:67:2b:b6:48 + 58:e2:f7:a5:e4:62:fd:e3:53:35:9c:17:94:21:57:02 + c3:ea:c8:b1:23:58:78:0a:fd:1f:5f:4a:50:e1:7d:aa + 52:61:5f:e2:00:59:f0:ad:e3:e3:19:a6:9d:8b:90:f5 + fb:80:aa:65:00:e9:82:52:5f:98:4d:37:11:e3:0b:a8 + 6a:c2:1e:78:7b:54:eb:ef:77:03:0c:61:b2:8b:56:8d + 14: + +exp1: + 00:d5:dd:f3:53:68:70:04:9f:5c:fb:d5:0d:81:88:f9 + 92:dd:10:38:cf:47:a9:96:6e:fd:f8:84:21:36:16:d7 + 36:2f:6d:df:a0:93:f0:e5:d4:ef:02:37:f9:9c:4f:c4 + 62:77:5a:e2:00:b3:59:66:21:44:81:e3:a8:a7:2f:49 + 79:a6:34:ac:9a:31:09:26:79:68:97:40:b6:31:79:79 + d2:ea:f0:fb:7f:01:ea:72:4d:41:f0:be:28:61:4c:a3 + e1:e6:8e:28:e6:f7:7c:02:9d:a9:36:4c:bd:32:d2:03 + 70:63:80:a0:76:3f:56:99:29:df:54:14:e2:a9:f6:01 + d0:b7:43:a4:e8:bb:ae:13:44:d4:bd:36:3c:ff:b8:92 + e2:a4:c7:c8:12:5c:46:39:9e:59:97:eb:9b:61:f4:21 + d1:af:2d:6b:e2:51:4e:e2:4c:6d:92:38:40:08:c1:f2 + 81:c8:60:08:11:e5:92:c3:3e:c7:77:8d:ae:ad:0f:69 + f5:48:57:b1:f2:4c:77:37:4e:5a:2a:39:24:15:d8:9d + f0:57:46:90:84:12:23:17:e6:07:48:ef:89:4b:2a:be + 7c:a8:1d:5c:b3:c4:f4:91:28:fd:21:c9:84:1e:41:a8 + 35:ee:65:96:36:e0:1b:e7:ed:ee:54:70:e5:52:52:77 + 0d: + +exp2: + 56:9b:db:8f:86:03:84:a6:5a:db:9d:94:35:a7:ff:d0 + 24:d3:46:ee:8f:ff:bf:78:0f:6f:6b:03:17:5c:fb:a5 + ad:db:c0:f5:f1:71:22:45:d8:65:74:69:ad:3d:8a:93 + 4c:90:fc:84:68:41:36:48:7b:48:0e:21:85:2a:ac:03 + a2:d0:72:f7:ec:39:7d:43:f2:eb:12:1f:67:6d:7a:57 + 39:36:2f:1e:61:e0:5e:a4:23:a5:5e:ec:bc:4a:1a:33 + fa:fb:ba:1f:7b:0b:b0:ea:5a:6f:ca:79:84:b6:b8:51 + 2a:31:0e:76:4f:13:ab:c1:1e:77:c8:84:b9:6f:12:c9 + cc:f5:d6:da:89:90:38:29:5a:39:ed:72:ed:19:c2:4f + 16:f3:f5:73:f3:d9:bb:10:23:a4:fd:69:e8:c8:af:03 + 17:a2:72:e7:e1:dd:89:35:00:cf:64:b5:e0:8f:33:b3 + 66:4c:7f:42:76:2e:51:5c:d7:b2:14:94:d5:20:ab:a5 + 97:63:bc:8f:c8:73:6a:39:db:33:5e:0c:b4:cd:34:d7 + d0:ca:5e:f8:8f:4b:5b:dd:70:a4:62:96:fe:ca:5a:cb + d0:30:a8:2c:9a:1d:df:f5:8a:cb:e3:ea:95:42:3d:54 + f7:48:81:04:22:33:cb:62:29:e1:a2:f1:20:5e:10:01 + + + +Public Key ID: + sha256:43:61:86:78:D1:41:6A:CB:B4:29:B4:5A:BD:F7:7A:89:6B:73:E0:67:13:E9:18:65:74:58:E9:C1:00:24:7D:14 + sha1:FB:AC:5C:86:65:08:A7:8A:99:A2:CC:79:F3:38:0F:CE:58:01:83:5B +Public key's random art: ++--[ RSA 4096]----+ +| | +|. | +|.oE . . | +| oo + . | +|. . . S o | +| +.. = | +|. +o. o o | +|+.*+o . = | +|.=.+=o o.o | ++-----------------+ + +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- diff --git a/test_pam_goatherd.sh b/test_pam_goatherd.sh new file mode 100644 index 0000000..50747ac --- /dev/null +++ b/test_pam_goatherd.sh @@ -0,0 +1,105 @@ +#!/bin/sh + +TODO: pam_goatherd.so path in service file + +PAMWRAPPER=/usr/lib/x86_64-linux-gnu/libpam_wrapper.so + +set -eu + +export PGHOST="$PWD/pg_pam_test" +. ./start_pg.sh + +cleanup() { + start_pg_cleanup + + pkill goatherd +} +trap 'cleanup' EXIT INT + +pw() { + LD_PRELOAD=$PAMWRAPPER PAM_WRAPPER=1 \ + PAM_WRAPPER_SERVICE_DIR=$PWD/test_pam_goatherd_services "$@" +} + +ghdb() { + DB=$1 + shift + ./goatherd -db-url="host=$PGHOST dbname=goatherd_test_$DB" -config="$PWD/pam_goatherd_test.conf" "$@" +} + +die() { + echo $@ >&2 + exit 1 +} + +for i in $(seq 1 3); do + createdb "goatherd_test_$i" + ghdb $i -init-db +done + + +echo +echo ===== Tests ===== +echo == Single server tests == + +echo auth requisite $PWD/pam_goatherd.so certs=test.crt server=localhost:9999 >$PWD/test_pam_goatherd_services/single_server + +echo blub | if pw pamtester single_server someuser authenticate; then + die "FAIL: Auth succeeded but no server is running" +else + echo "(failure expected)" +fi + +ghdb 1 -listen 127.0.0.1:9999 -tls-key test.key -tls-cert test.crt & + +echo blub | if pw pamtester single_server someuser authenticate; then + die "FAIL: Auth succeeded but user is not valid" +else + echo "(failure expected)" +fi + +secret=12345678901234567890 +ghdb 1 -add-user someuser -secret $(echo -n $secret | base64) + +echo blub | if pw pamtester single_server someuser authenticate; then + die "FAIL: Auth succeeded but OTP is not valid" +else + echo "(failure expected)" +fi + +oathtool -d 8 -c 1 $(echo -n $secret | xxd -p) | \ + if ! pw pamtester single_server someuser authenticate; then + die "FAIL: Unable to authenticate with valid OTP" +fi + + +echo +echo "== Multi server tests ==" + +echo auth requisite $PWD/pam_goatherd.so certs=test.crt server=localhost:9999 server=localhost:9998 server=localhost:9997 >$PWD/test_pam_goatherd_services/three_servers + +oathtool -d 8 -c 2 $(echo -n $secret | xxd -p) | \ + if pw pamtester three_servers someuser authenticate; then + die "FAIL: 1/3 servers running but authentication succeeded" +else + echo "(failure expected)" +fi + +ghdb 2 -listen 127.0.0.1:9998 -tls-key test.key -tls-cert test.crt & + +oathtool -d 8 -c 2 $(echo -n $secret | xxd -p) | \ + if pw pamtester three_servers someuser authenticate; then + die "FAIL: 2/3 servers running with one missung user but authentication succeeded" +else + echo "(failure expected)" +fi + +ghdb 2 -add-user someuser -secret $(echo -n $secret | base64) + +oathtool -d 8 -c 3 $(echo -n $secret | xxd -p) | \ + if ! pw pamtester three_servers someuser authenticate; then + die "FAIL: 2/3 servers running correctly but authentication failed" +fi + + +echo "\n\n===== Tests OK =====\n\n" -- GitLab