diff --git a/sources/frontend.c b/sources/frontend.c index 4264bc47..cb5affa6 100644 --- a/sources/frontend.c +++ b/sources/frontend.c @@ -2128,10 +2128,22 @@ void od_frontend(void *arg) /* HBA check */ rc = od_hba_process(client); + char client_ip[64]; + od_getpeername(client->io.io, client_ip, sizeof(client_ip), 1, 0); + /* client authentication */ if (rc == OK_RESPONSE) { rc = od_auth_frontend(client); + od_log(&instance->logger, "auth", client, NULL, + "ip '%s' user '%s.%s': host based authentication allowed", + client_ip, client->startup.database.value, + client->startup.user.value); } else { + od_error( + &instance->logger, "auth", client, NULL, + "ip '%s' user '%s.%s': host based authentication rejected", + client_ip, client->startup.database.value, + client->startup.user.value); od_frontend_error(client, KIWI_INVALID_PASSWORD, "host based authentication rejected"); } diff --git a/sources/hba_reader.c b/sources/hba_reader.c index 26354220..c46c7500 100644 --- a/sources/hba_reader.c +++ b/sources/hba_reader.c @@ -190,34 +190,46 @@ static int od_hba_reader_address(struct sockaddr_storage *dest, return -1; } -static int od_hba_reader_prefix(od_hba_rule_t *hba, char *prefix) +static inline uint32 od_hba_bswap32(uint32 x) +{ + return ((x << 24) & 0xff000000) | ((x << 8) & 0x00ff0000) | + ((x >> 8) & 0x0000ff00) | ((x >> 24) & 0x000000ff); +} + +int od_hba_reader_prefix(od_hba_rule_t *hba, char *prefix) { char *end = NULL; - unsigned long int len = strtoul(prefix, &end, 10); - + long len = strtoul(prefix, &end, 10); + if (*prefix == '\0' || *end != '\0') { + return -1; + } if (hba->addr.ss_family == AF_INET) { if (len > 32) return -1; - uint32_t mask = 0; - unsigned int i; struct sockaddr_in *addr = (struct sockaddr_in *)&hba->mask; - for (i = 0; i < len / 8; ++i) { - mask = 0xff | (mask << 8); - } - if (len % 8 != 0) - mask = mask | ((len % 8) << (i * 8)); - addr->sin_addr.s_addr = mask; + long mask; + if (len > 0) + mask = (0xffffffffUL << (32 - (int)len)) & 0xffffffffUL; + else + mask = 0; + addr->sin_addr.s_addr = od_hba_bswap32(mask); return 0; } else if (hba->addr.ss_family == AF_INET6) { if (len > 128) return -1; - unsigned int i; struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&hba->mask; - for (i = 0; i < len / 8; ++i) { - addr->sin6_addr.s6_addr[i] = 0xff; + int i; + for (i = 0; i < 16; i++) { + if (len <= 0) + addr->sin6_addr.s6_addr[i] = 0; + else if (len >= 8) + addr->sin6_addr.s6_addr[i] = 0xff; + else { + addr->sin6_addr.s6_addr[i] = + (0xff << (8 - (int)len)) & 0xff; + } + len -= 8; } - if (len % 8 != 0) - addr->sin6_addr.s6_addr[i] = len & 7; return 0; } @@ -334,7 +346,8 @@ int od_hba_reader_parse(od_config_reader_t *reader) if (mask) *mask++ = 0; - if (od_hba_reader_address(&hba->addr, address) == -1) { + if (od_hba_reader_address(&hba->addr, address) == + NOT_OK_RESPONSE) { od_hba_reader_error(reader, "invalid IP address"); goto error; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 75149738..af25bb9c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -65,10 +65,14 @@ set(od_test_src ../sources/util.h ../sources/build.h ../sources/debugprintf.h + ../sources/hba.c + ../sources/hba_rule.c + ../sources/hba_reader.c odyssey/test_attribute.c odyssey/test_tdigest.c odyssey/test_util.c odyssey/test_locks.c + odyssey/test_hba_parse.c ) file(COPY machinarium/ca.crt DESTINATION machinarium) diff --git a/test/odyssey/test_hba_parse.c b/test/odyssey/test_hba_parse.c new file mode 100644 index 00000000..41102b1d --- /dev/null +++ b/test/odyssey/test_hba_parse.c @@ -0,0 +1,32 @@ + +#include "odyssey.h" +#include + +void test_od_hba_reader_prefix(sa_family_t net, char *prefix, char *value) +{ + od_hba_rule_t *hba = NULL; + char buffer[INET6_ADDRSTRLEN]; + hba = od_hba_rule_create(); + hba->addr.ss_family = net; + test(od_hba_reader_prefix(hba, prefix) == 0); + if (net == AF_INET) { + struct sockaddr_in *addr = (struct sockaddr_in *)&hba->mask; + inet_ntop(net, &addr->sin_addr, buffer, sizeof(buffer)); + } else { + struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&hba->mask; + inet_ntop(net, &addr->sin6_addr, buffer, sizeof(buffer)); + } + test(memcmp(value, buffer, strlen(buffer)) == 0); + od_hba_rule_free(hba); +} + +void odyssey_test_hba(void) +{ + test_od_hba_reader_prefix(AF_INET, "31", "255.255.255.254"); + test_od_hba_reader_prefix(AF_INET, "24", "255.255.255.0"); + test_od_hba_reader_prefix(AF_INET, "12", "255.240.0.0"); + test_od_hba_reader_prefix(AF_INET, "7", "254.0.0.0"); + test_od_hba_reader_prefix(AF_INET6, "10", "ffc0::"); + test_od_hba_reader_prefix(AF_INET6, "120", + "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00"); +} \ No newline at end of file diff --git a/test/odyssey_test.c b/test/odyssey_test.c index 93a6c110..3b767be5 100644 --- a/test/odyssey_test.c +++ b/test/odyssey_test.c @@ -79,6 +79,7 @@ extern void odyssey_test_tdigest(void); extern void odyssey_test_attribute(void); extern void odyssey_test_util(void); extern void odyssey_test_lock(void); +extern void odyssey_test_hba(void); int main(int argc, char *argv[]) { @@ -147,6 +148,7 @@ int main(int argc, char *argv[]) odyssey_test(odyssey_test_attribute); odyssey_test(odyssey_test_util); odyssey_test(odyssey_test_lock); + odyssey_test(odyssey_test_hba); return 0; } \ No newline at end of file