88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.193 2010/01/31 17:27:22 tgl Exp $
11+ * $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.194 2010/02/02 19:09:36 mha Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -2521,8 +2521,16 @@ CheckRADIUSAuth(Port *port)
25212521 uint8 encryptedpassword [RADIUS_VECTOR_LENGTH ];
25222522 int packetlength ;
25232523 pgsocket sock ;
2524+ #ifdef HAVE_IPV6
2525+ struct sockaddr_in6 localaddr ;
2526+ struct sockaddr_in6 remoteaddr ;
2527+ #else
25242528 struct sockaddr_in localaddr ;
25252529 struct sockaddr_in remoteaddr ;
2530+ #endif
2531+ struct addrinfo hint ;
2532+ struct addrinfo * serveraddrs ;
2533+ char portstr [128 ];
25262534 ACCEPT_TYPE_ARG3 addrsize ;
25272535 fd_set fdset ;
25282536 struct timeval timeout ;
@@ -2549,17 +2557,22 @@ CheckRADIUSAuth(Port *port)
25492557 if (port -> hba -> radiusport == 0 )
25502558 port -> hba -> radiusport = 1812 ;
25512559
2552- memset (& remoteaddr , 0 , sizeof (remoteaddr ));
2553- remoteaddr .sin_family = AF_INET ;
2554- remoteaddr .sin_addr .s_addr = inet_addr (port -> hba -> radiusserver );
2555- if (remoteaddr .sin_addr .s_addr == INADDR_NONE )
2560+ MemSet (& hint , 0 , sizeof (hint ));
2561+ hint .ai_socktype = SOCK_DGRAM ;
2562+ hint .ai_family = AF_UNSPEC ;
2563+ snprintf (portstr , sizeof (portstr ), "%d" , port -> hba -> radiusport );
2564+
2565+ r = pg_getaddrinfo_all (port -> hba -> radiusserver , portstr , & hint , & serveraddrs );
2566+ if (r || !serveraddrs )
25562567 {
25572568 ereport (LOG ,
2558- (errmsg ("RADIUS server '%s' is not a valid IP address" ,
2559- port -> hba -> radiusserver )));
2569+ (errmsg ("could not translate RADIUS server name \"%s\" to address: %s" ,
2570+ port -> hba -> radiusserver , gai_strerror (r ))));
2571+ if (serveraddrs )
2572+ pg_freeaddrinfo_all (hint .ai_family , serveraddrs );
25602573 return STATUS_ERROR ;
25612574 }
2562- remoteaddr . sin_port = htons ( port -> hba -> radiusport );
2575+ /* XXX: add support for multiple returned addresses? */
25632576
25642577 if (port -> hba -> radiusidentifier && port -> hba -> radiusidentifier [0 ])
25652578 identifier = port -> hba -> radiusidentifier ;
@@ -2633,34 +2646,51 @@ CheckRADIUSAuth(Port *port)
26332646 packetlength = packet -> length ;
26342647 packet -> length = htons (packet -> length );
26352648
2636- sock = socket (AF_INET , SOCK_DGRAM , 0 );
2649+ sock = socket (serveraddrs [ 0 ]. ai_family , SOCK_DGRAM , 0 );
26372650 if (sock < 0 )
26382651 {
26392652 ereport (LOG ,
26402653 (errmsg ("could not create RADIUS socket: %m" )));
2654+ pg_freeaddrinfo_all (hint .ai_family , serveraddrs );
26412655 return STATUS_ERROR ;
26422656 }
26432657
26442658 memset (& localaddr , 0 , sizeof (localaddr ));
2645- localaddr .sin_family = AF_INET ;
2659+ #ifdef HAVE_IPV6
2660+ localaddr .sin6_family = serveraddrs [0 ].ai_family ;
2661+ localaddr .sin6_addr = in6addr_any ;
2662+ if (localaddr .sin6_family == AF_INET6 )
2663+ addrsize = sizeof (struct sockaddr_in6 );
2664+ else
2665+ addrsize = sizeof (struct sockaddr_in );
2666+ #else
2667+ localaddr .sin_family = serveraddrs [0 ].ai_family ;
26462668 localaddr .sin_addr .s_addr = INADDR_ANY ;
2647- if (bind (sock , (struct sockaddr * ) & localaddr , sizeof (localaddr )))
2669+ addrsize = sizeof (struct sockaddr_in );
2670+ #endif
2671+ if (bind (sock , (struct sockaddr * ) & localaddr , addrsize ))
26482672 {
26492673 ereport (LOG ,
26502674 (errmsg ("could not bind local RADIUS socket: %m" )));
26512675 closesocket (sock );
2676+ pg_freeaddrinfo_all (hint .ai_family , serveraddrs );
26522677 return STATUS_ERROR ;
26532678 }
26542679
26552680 if (sendto (sock , radius_buffer , packetlength , 0 ,
2656- ( struct sockaddr * ) & remoteaddr , sizeof ( remoteaddr ) ) < 0 )
2681+ serveraddrs [ 0 ]. ai_addr , serveraddrs [ 0 ]. ai_addrlen ) < 0 )
26572682 {
26582683 ereport (LOG ,
26592684 (errmsg ("could not send RADIUS packet: %m" )));
26602685 closesocket (sock );
2686+ pg_freeaddrinfo_all (hint .ai_family , serveraddrs );
26612687 return STATUS_ERROR ;
26622688 }
26632689
2690+ /* Don't need the server address anymore */
2691+ pg_freeaddrinfo_all (hint .ai_family , serveraddrs );
2692+
2693+ /* Wait for a response */
26642694 timeout .tv_sec = RADIUS_TIMEOUT ;
26652695 timeout .tv_usec = 0 ;
26662696 FD_ZERO (& fdset );
@@ -2705,11 +2735,21 @@ CheckRADIUSAuth(Port *port)
27052735
27062736 closesocket (sock );
27072737
2738+ #ifdef HAVE_IPV6
2739+ if (remoteaddr .sin6_port != htons (port -> hba -> radiusport ))
2740+ #else
27082741 if (remoteaddr .sin_port != htons (port -> hba -> radiusport ))
2742+ #endif
27092743 {
2744+ #ifdef HAVE_IPV6
2745+ ereport (LOG ,
2746+ (errmsg ("RADIUS response was sent from incorrect port: %i" ,
2747+ ntohs (remoteaddr .sin6_port ))));
2748+ #else
27102749 ereport (LOG ,
27112750 (errmsg ("RADIUS response was sent from incorrect port: %i" ,
27122751 ntohs (remoteaddr .sin_port ))));
2752+ #endif
27132753 return STATUS_ERROR ;
27142754 }
27152755
0 commit comments