diff options
author | Bruce Momjian <bruce@momjian.us> | 2003-06-12 07:36:51 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 2003-06-12 07:36:51 +0000 |
commit | b4cea00a1fc9d2270bfe9aeeee44915378d5f733 (patch) | |
tree | 16a6702b864f8e8795a498c4e2bf5f91fee54862 /src/backend/libpq/hba.c | |
parent | e5549a272d922c5d9ed177a823914fdee6ada08d (diff) |
IPv6 cleanups.
Kurt Roeckx
Andrew Dunstan
Diffstat (limited to 'src/backend/libpq/hba.c')
-rw-r--r-- | src/backend/libpq/hba.c | 205 |
1 files changed, 146 insertions, 59 deletions
diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c index 4310261a16b..c277c90d1b9 100644 --- a/src/backend/libpq/hba.c +++ b/src/backend/libpq/hba.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.102 2003/06/12 07:00:57 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.103 2003/06/12 07:36:51 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -542,9 +542,14 @@ static void parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) { int line_number; - char *token; - char *db; - char *user; + char *token; + char *db; + char *user; + struct addrinfo *file_ip_addr = NULL, *file_ip_mask = NULL; + struct addrinfo hints; + struct sockaddr_storage *mask; + char *cidr_slash; + int ret; Assert(line != NIL); line_number = lfirsti(line); @@ -582,12 +587,11 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) port->auth_method == uaKrb5) goto hba_syntax; - if (port->raddr.sa.sa_family != AF_UNIX) + if (port->raddr.addr.ss_family != AF_UNIX) return; } else if (strcmp(token, "host") == 0 || strcmp(token, "hostssl") == 0) { - SockAddr file_ip_addr, mask; if (strcmp(token, "hostssl") == 0) { @@ -618,26 +622,77 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) goto hba_syntax; user = lfirst(line); - /* Read the IP address field. */ + /* Read the IP address field. (with or without CIDR netmask) */ line = lnext(line); if (!line) goto hba_syntax; token = lfirst(line); - if(SockAddr_pton(&file_ip_addr, token) < 0) - goto hba_syntax; + /* Check if it has a CIDR suffix and if so isolate it */ + cidr_slash = index(token,'/'); + if (cidr_slash) + { + *cidr_slash = '\0'; + } - /* Read the mask field. */ - line = lnext(line); - if (!line) + hints.ai_flags = AI_NUMERICHOST; + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = 0; + hints.ai_protocol = 0; + hints.ai_addrlen = 0; + hints.ai_canonname = NULL; + hints.ai_addr = NULL; + hints.ai_next = NULL; + + /* Get the IP address either way */ + ret = getaddrinfo2(token, NULL, &hints, &file_ip_addr); + if (ret) + { + elog(LOG, "getaddrinfo2() returned %d", ret); + if (cidr_slash) + { + *cidr_slash = '/'; + } goto hba_syntax; - token = lfirst(line); + } - if(SockAddr_pton(&mask, token) < 0) - goto hba_syntax; + if (file_ip_addr->ai_family != port->raddr.addr.ss_family) + { + /* Wrong address family. */ + freeaddrinfo2(hints.ai_family, file_ip_addr); + return; + } - if(file_ip_addr.sa.sa_family != mask.sa.sa_family) - goto hba_syntax; + /* Get the netmask */ + if (cidr_slash) + { + *cidr_slash = '/'; + if (SockAddr_cidr_mask(&mask, cidr_slash + 1, + file_ip_addr->ai_family) < 0) + { + goto hba_syntax; + } + } + else + { + /* Read the mask field. */ + line = lnext(line); + if (!line) + goto hba_syntax; + token = lfirst(line); + + ret = getaddrinfo2(token, NULL, &hints, &file_ip_mask); + if (ret) + { + goto hba_syntax; + } + mask = (struct sockaddr_storage *)file_ip_mask->ai_addr; + + if(file_ip_addr->ai_family != mask->ss_family) + { + goto hba_syntax; + } + } /* Read the rest of the line. */ line = lnext(line); @@ -648,9 +703,16 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) goto hba_syntax; /* Must meet network restrictions */ - if (!isAF_INETx(port->raddr.sa.sa_family) || - !rangeSockAddr(&port->raddr, &file_ip_addr, &mask)) - return; + if (!rangeSockAddr(&port->raddr.addr, + (struct sockaddr_storage *)file_ip_addr->ai_addr, mask)) + { + goto hba_freeaddr; + } + freeaddrinfo2(hints.ai_family, file_ip_addr); + if (file_ip_mask) + { + freeaddrinfo2(hints.ai_family, file_ip_mask); + } } else goto hba_syntax; @@ -670,6 +732,16 @@ hba_syntax: line ? (const char *) lfirst(line) : "(end of line)"); *error_p = true; + +hba_freeaddr: + if (file_ip_addr) + { + freeaddrinfo2(hints.ai_family, file_ip_addr); + } + if (file_ip_mask) + { + freeaddrinfo2(hints.ai_family, file_ip_mask); + } return; } @@ -1106,10 +1178,8 @@ interpret_ident_response(char *ident_response, * But iff we're unable to get the information from ident, return false. */ static bool -ident_inet(const struct in_addr remote_ip_addr, - const struct in_addr local_ip_addr, - const ushort remote_port, - const ushort local_port, +ident_inet(const SockAddr remote_addr, + const SockAddr local_addr, char *ident_user) { int sock_fd, /* File descriptor for socket on which we @@ -1117,8 +1187,39 @@ ident_inet(const struct in_addr remote_ip_addr, rc; /* Return code from a locally called * function */ bool ident_return; + char remote_addr_s[NI_MAXHOST]; + char remote_port[NI_MAXSERV]; + char local_addr_s[NI_MAXHOST]; + char local_port[NI_MAXSERV]; + char ident_port[NI_MAXSERV]; + struct addrinfo *ident_serv = NULL, *la = NULL, hints; + + /* Might look a little weird to first convert it to text and + * then back to sockaddr, but it's protocol indepedant. */ + getnameinfo((struct sockaddr *)&remote_addr.addr, + remote_addr.salen, remote_addr_s, sizeof(remote_addr_s), + remote_port, sizeof(remote_port), + NI_NUMERICHOST|NI_NUMERICSERV); + getnameinfo((struct sockaddr *)&local_addr.addr, + local_addr.salen, local_addr_s, sizeof(local_addr_s), + local_port, sizeof(local_port), + NI_NUMERICHOST|NI_NUMERICSERV); + + snprintf(ident_port, sizeof(ident_port), "%d", IDENT_PORT); + hints.ai_flags = AI_NUMERICHOST; + hints.ai_family = remote_addr.addr.ss_family; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + hints.ai_addrlen = 0; + hints.ai_canonname = NULL; + hints.ai_addr = NULL; + hints.ai_next = NULL; + getaddrinfo2(remote_addr_s, ident_port, &hints, &ident_serv); + getaddrinfo2(local_addr_s, NULL, &hints, &la); + + sock_fd = socket(ident_serv->ai_family, ident_serv->ai_socktype, + ident_serv->ai_protocol); - sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); if (sock_fd == -1) { elog(LOG, "Failed to create socket on which to talk to Ident server: %m"); @@ -1126,42 +1227,27 @@ ident_inet(const struct in_addr remote_ip_addr, } else { - struct sockaddr_in ident_server; - struct sockaddr_in la; - - /* - * Socket address of Ident server on the system from which client - * is attempting to connect to us. - */ - ident_server.sin_family = AF_INET; - ident_server.sin_port = htons(IDENT_PORT); - ident_server.sin_addr = remote_ip_addr; - /* * Bind to the address which the client originally contacted, * otherwise the ident server won't be able to match up the right * connection. This is necessary if the PostgreSQL server is * running on an IP alias. */ - memset(&la, 0, sizeof(la)); - la.sin_family = AF_INET; - la.sin_addr = local_ip_addr; - rc = bind(sock_fd, (struct sockaddr *) & la, sizeof(la)); + + rc = bind(sock_fd, la->ai_addr, la->ai_addrlen); if (rc == 0) { - rc = connect(sock_fd, - (struct sockaddr *) & ident_server, sizeof(ident_server)); + rc = connect(sock_fd, ident_serv->ai_addr, + ident_serv->ai_addrlen); } if (rc != 0) { - /* save_errno is in case inet_ntoa changes errno */ - int save_errno = errno; + int save_errno = errno; elog(LOG, "Unable to connect to Ident server on the host which is " "trying to connect to Postgres " - "(IP address %s, Port %d): %s", - inet_ntoa(remote_ip_addr), IDENT_PORT, - strerror(save_errno)); + "(Address %s, Port %s): %s", remote_addr_s, + ident_port, strerror(save_errno)); ident_return = false; } else @@ -1169,8 +1255,8 @@ ident_inet(const struct in_addr remote_ip_addr, char ident_query[80]; /* The query we send to the Ident server */ - snprintf(ident_query, sizeof(ident_query), "%d,%d\n", - ntohs(remote_port), ntohs(local_port)); + snprintf(ident_query, sizeof(ident_query), "%s,%s\r\n", + remote_port, local_port); /* loop in case send is interrupted */ do { @@ -1181,10 +1267,9 @@ ident_inet(const struct in_addr remote_ip_addr, int save_errno = errno; elog(LOG, "Unable to send query to Ident server on the host which is " - "trying to connect to Postgres (Host %s, Port %d), " + "trying to connect to Postgres (Host %s, Port %s), " "even though we successfully connected to it: %s", - inet_ntoa(remote_ip_addr), IDENT_PORT, - strerror(save_errno)); + remote_addr_s, ident_port, strerror(save_errno)); ident_return = false; } else @@ -1199,9 +1284,9 @@ ident_inet(const struct in_addr remote_ip_addr, elog(LOG, "Unable to receive response from Ident server " "on the host which is " - "trying to connect to Postgres (Host %s, Port %d), " + "trying to connect to Postgres (Host %s, Port %s), " "even though we successfully sent our query to it: %s", - inet_ntoa(remote_ip_addr), IDENT_PORT, + remote_addr_s, ident_port, strerror(save_errno)); ident_return = false; } @@ -1215,6 +1300,8 @@ ident_inet(const struct in_addr remote_ip_addr, closesocket(sock_fd); } } + freeaddrinfo2(hints.ai_family, la); + freeaddrinfo2(hints.ai_family, ident_serv); return ident_return; } @@ -1371,13 +1458,13 @@ authident(hbaPort *port) { char ident_user[IDENT_USERNAME_MAX + 1]; - switch (port->raddr.sa.sa_family) + switch (port->raddr.addr.ss_family) { case AF_INET: - if (!ident_inet(port->raddr.in.sin_addr, - port->laddr.in.sin_addr, - port->raddr.in.sin_port, - port->laddr.in.sin_port, ident_user)) +#ifdef HAVE_IPV6 + case AF_INET6: +#endif + if (!ident_inet(port->raddr, port->laddr, ident_user)) return STATUS_ERROR; break; case AF_UNIX: |