[PATCH] Patch to make pg_hba.conf handle virtualhost access control and samehost keyword - Mailing list pgsql-patches
From | Damien Clermonté |
---|---|
Subject | [PATCH] Patch to make pg_hba.conf handle virtualhost access control and samehost keyword |
Date | |
Msg-id | 3B41E1F4.9030006@free.fr Whole thread Raw |
Responses |
Re: [PATCH] Patch to make pg_hba.conf handle virtualhost access control and samehost keyword
Re: [PATCH] Patch to make pg_hba.conf handle virtualhost access control and samehost keyword |
List | pgsql-patches |
Hi This patch againsts postgresql 7.1.2 allows you to control access based on the virtual host address only (virtualhost access type), or both the remote address and the local address (connection access type). For example: connection all 192.168.42.0 255.255.255.0 192.168.1.42 255.255.255.255 trust This patch also allows keyword "samehost", similar to "sameuser" but for hosts. For example: virtualhost sameuser samehost.sql.domain.com 255.255.255.255 trust will prevent you from doing 1 entry per user, all you need is a (local) dns entry for each host (user foo needs foo.sql.domain.com). If the dns entry is not found, the line is dropped, so rejecting with samehost is not a good idea for the moment. Any comments are welcome. Please not that I'm not on the list. --- Damien Clermonte --- postgresql-7.1.2.orig/src/backend/libpq/hba.c Mon Jul 2 16:25:56 2001 +++ postgresql-7.1.2/src/backend/libpq/hba.c Tue Jul 3 14:01:20 2001 @@ -17,6 +17,7 @@ #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> +#include <netdb.h> #include "postgres.h" @@ -31,6 +32,9 @@ #define IDENT_USERNAME_MAX 512 /* Max size of username ident server can return */ +#define MAX_HOSTNAME 1024 + /* Max size of hostname */ + /* Some standard C libraries, including GNU, have an isblank() function. Others, including Solaris, do not. So we have our own. @@ -256,8 +260,38 @@ if (!inet_aton(buf, &file_ip_addr)) { + if (!strncmp(buf, "samehost", 8)) /* samehost.somedomain */ + { + struct hostent* he; + char host[MAX_HOSTNAME]; + + strcpy(host, port->user); + if(strlen(buf) > 8) + { + strncat(host, buf + 8, MAX_HOSTNAME - 1 - strlen(host)); + host[MAX_HOSTNAME - 1] = '\0'; + } + he = gethostbyname(host); + + if(he != NULL) + { + file_ip_addr.s_addr = *(int*)he->h_addr; + } + else /* Error or Host not found */ + { + read_through_eol(file); + snprintf(PQerrormsg, PQERRORMSG_LENGTH, + "process_hba_record: samehost '%s' not found in pg_hba.conf file\n", host); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + return; + } + } + else + { read_through_eol(file); goto syntax; + } } /* Read the mask field. */ @@ -299,6 +333,301 @@ (strcmp(db, "sameuser") != 0 || strcmp(port->database, port->user) != 0)) || port->raddr.sa.sa_family != AF_INET || ((file_ip_addr.s_addr ^ port->raddr.in.sin_addr.s_addr) & mask.s_addr) != 0x0000) + return; + } + else if (strcmp(buf, "virtualhost") == 0 || strcmp(buf, "virtualhostssl") == 0) + { + struct in_addr file_ip_addr, + mask; + bool discard = 0;/* Discard this entry */ + +#ifdef USE_SSL + /* If SSL, then check that we are on SSL */ + if (strcmp(buf, "virtualhostssl") == 0) + { + if (!port->ssl) + discard = 1; + + /* Placeholder to require specific SSL level, perhaps? */ + /* Or a client certificate */ + + /* Since we were on SSL, proceed as with normal 'host' mode */ + } +#else + /* If not SSL, we don't support this */ + if (strcmp(buf, "virtualhostssl") == 0) + goto syntax; +#endif + + /* Get the database. */ + + next_token(file, db, sizeof(db)); + + if (db[0] == '\0') + goto syntax; + + /* Read the IP address field. */ + + next_token(file, buf, sizeof(buf)); + + if (buf[0] == '\0') + goto syntax; + + /* Remember the IP address field and go get mask field. */ + + if (!inet_aton(buf, &file_ip_addr)) + { + if (!strncmp(buf, "samehost", 8)) /* samehost.somedomain */ + { + struct hostent* he; + char host[MAX_HOSTNAME]; + + strcpy(host, port->user); + if(strlen(buf) > 8) + { + strncat(host, buf + 8, MAX_HOSTNAME - 1 - strlen(host)); + host[MAX_HOSTNAME - 1] = '\0'; + } + he = gethostbyname(host); + + if(he != NULL) + { + file_ip_addr.s_addr = *(int*)he->h_addr; + } + else /* Error or Host not found */ + { + read_through_eol(file); + snprintf(PQerrormsg, PQERRORMSG_LENGTH, + "process_hba_record: samehost '%s' not found in pg_hba.conf file\n", host); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + return; + } + } + else + { + read_through_eol(file); + goto syntax; + } + } + + /* Read the mask field. */ + + next_token(file, buf, sizeof(buf)); + + if (buf[0] == '\0') + goto syntax; + + if (!inet_aton(buf, &mask)) + { + read_through_eol(file); + goto syntax; + } + + /* + * This is the record we're looking for. Read the rest of the + * info from it. + */ + + read_hba_entry2(file, &port->auth_method, port->auth_arg, error_p); + + if (*error_p) + goto syntax; + + /* + * If told to discard earlier. Moved down here so we don't get + * "out of sync" with the file. + */ + if (discard) + return; + + /* + * If this record isn't for our database, or this is the wrong + * sort of connection, ignore it. + */ + + if ((strcmp(db, port->database) != 0 && strcmp(db, "all") != 0 && + (strcmp(db, "sameuser") != 0 || strcmp(port->database, port->user) != 0)) || + port->laddr.sa.sa_family != AF_INET || + ((file_ip_addr.s_addr ^ port->laddr.in.sin_addr.s_addr) & mask.s_addr) != 0x0000) + return; + } + else if (strcmp(buf, "connection") == 0 || strcmp(buf, "connectionssl") == 0) + { + struct in_addr file_ip_raddr, + rmask; + struct in_addr file_ip_laddr, + lmask; + bool discard = 0;/* Discard this entry */ + +#ifdef USE_SSL + /* If SSL, then check that we are on SSL */ + if (strcmp(buf, "connectionssl") == 0) + { + if (!port->ssl) + discard = 1; + + /* Placeholder to require specific SSL level, perhaps? */ + /* Or a client certificate */ + + /* Since we were on SSL, proceed as with normal 'host' mode */ + } +#else + /* If not SSL, we don't support this */ + if (strcmp(buf, "connectionssl") == 0) + goto syntax; +#endif + + /* Get the database. */ + + next_token(file, db, sizeof(db)); + + if (db[0] == '\0') + goto syntax; + + /* Read the remote IP address field. */ + + next_token(file, buf, sizeof(buf)); + + if (buf[0] == '\0') + goto syntax; + + /* Remember the IP address field and go get mask field. */ + + if (!inet_aton(buf, &file_ip_raddr)) + { + if (!strncmp(buf, "samehost", 8)) /* samehost.somedomain */ + { + struct hostent* he; + char host[MAX_HOSTNAME]; + + strcpy(host, port->user); + if(strlen(buf) > 8) + { + strncat(host, buf + 8, MAX_HOSTNAME - 1 - strlen(host)); + host[MAX_HOSTNAME - 1] = '\0'; + } + he = gethostbyname(host); + + if(he != NULL) + { + file_ip_raddr.s_addr = *(int*)he->h_addr; + } + else /* Error or Host not found */ + { + read_through_eol(file); + snprintf(PQerrormsg, PQERRORMSG_LENGTH, + "process_hba_record: samehost '%s' not found in pg_hba.conf file\n", host); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + return; + } + } + else + { + read_through_eol(file); + goto syntax; + } + } + + /* Read the remote mask field. */ + + next_token(file, buf, sizeof(buf)); + + if (buf[0] == '\0') + goto syntax; + + if (!inet_aton(buf, &rmask)) + { + read_through_eol(file); + goto syntax; + } + + /* Read the local IP address field. */ + + next_token(file, buf, sizeof(buf)); + + if (buf[0] == '\0') + goto syntax; + + /* Remember the IP address field and go get mask field. */ + + if (!inet_aton(buf, &file_ip_laddr)) + { + if (!strncmp(buf, "samehost", 8)) /* samehost.somedomain */ + { + struct hostent* he; + char host[MAX_HOSTNAME]; + + strcpy(host, port->user); + if(strlen(buf) > 8) + { + strncat(host, buf + 8, MAX_HOSTNAME - 1 - strlen(host)); + host[MAX_HOSTNAME - 1] = '\0'; + } + he = gethostbyname(host); + + if(he != NULL) + { + file_ip_laddr.s_addr = *(int*)he->h_addr; + } + else /* Error or Host not found */ + { + read_through_eol(file); + snprintf(PQerrormsg, PQERRORMSG_LENGTH, + "process_hba_record: samehost '%s' not found in pg_hba.conf file\n", host); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + return; + } + } + else + { + read_through_eol(file); + goto syntax; + } + } + + /* Read the source mask field. */ + + next_token(file, buf, sizeof(buf)); + + if (buf[0] == '\0') + goto syntax; + + if (!inet_aton(buf, &lmask)) + { + read_through_eol(file); + goto syntax; + } + + /* + * This is the record we're looking for. Read the rest of the + * info from it. + */ + + read_hba_entry2(file, &port->auth_method, port->auth_arg, error_p); + + if (*error_p) + goto syntax; + + /* + * If told to discard earlier. Moved down here so we don't get + * "out of sync" with the file. + */ + if (discard) + return; + + /* + * If this record isn't for our database, or this is the wrong + * sort of connection, ignore it. + */ + + if ((strcmp(db, port->database) != 0 && strcmp(db, "all") != 0 && + (strcmp(db, "sameuser") != 0 || strcmp(port->database, port->user) != 0)) || + port->laddr.sa.sa_family != AF_INET || + ((file_ip_raddr.s_addr ^ port->raddr.in.sin_addr.s_addr) & rmask.s_addr) != 0x0000 || + ((file_ip_laddr.s_addr ^ port->laddr.in.sin_addr.s_addr) & lmask.s_addr) != 0x0000) return; } else
pgsql-patches by date: