Re: [PATCH] Patch to make pg_hba.conf handle virtualhost access control and samehost keyword - Mailing list pgsql-patches
From | Bruce Momjian |
---|---|
Subject | Re: [PATCH] Patch to make pg_hba.conf handle virtualhost access control and samehost keyword |
Date | |
Msg-id | 200107121929.f6CJT9e25709@candle.pha.pa.us Whole thread Raw |
In response to | [PATCH] Patch to make pg_hba.conf handle virtualhost access control and samehost keyword (Damien Clermonté <damien.clermonte@free.fr>) |
List | pgsql-patches |
I assume you are aware that 7.1.X postmaster can control which addresses it accepts connections from with -h: -h hostname Specifies the TCP/IP hostname or address on which the postmaster is to listen for connections from client applications. Defaults to listening on all configured addresses (including localhost). My question is why virtualhosts are useful in the pg_hba.conf file? > 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 > > ---------------------------(end of broadcast)--------------------------- > TIP 4: Don't 'kill -9' the postmaster -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 853-3000 + If your life is a hard drive, | 830 Blythe Avenue + Christ can be your backup. | Drexel Hill, Pennsylvania 19026
pgsql-patches by date: