8
8
*
9
9
*
10
10
* 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 $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -2521,8 +2521,16 @@ CheckRADIUSAuth(Port *port)
2521
2521
uint8 encryptedpassword [RADIUS_VECTOR_LENGTH ];
2522
2522
int packetlength ;
2523
2523
pgsocket sock ;
2524
+ #ifdef HAVE_IPV6
2525
+ struct sockaddr_in6 localaddr ;
2526
+ struct sockaddr_in6 remoteaddr ;
2527
+ #else
2524
2528
struct sockaddr_in localaddr ;
2525
2529
struct sockaddr_in remoteaddr ;
2530
+ #endif
2531
+ struct addrinfo hint ;
2532
+ struct addrinfo * serveraddrs ;
2533
+ char portstr [128 ];
2526
2534
ACCEPT_TYPE_ARG3 addrsize ;
2527
2535
fd_set fdset ;
2528
2536
struct timeval timeout ;
@@ -2549,17 +2557,22 @@ CheckRADIUSAuth(Port *port)
2549
2557
if (port -> hba -> radiusport == 0 )
2550
2558
port -> hba -> radiusport = 1812 ;
2551
2559
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 )
2556
2567
{
2557
2568
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 );
2560
2573
return STATUS_ERROR ;
2561
2574
}
2562
- remoteaddr . sin_port = htons ( port -> hba -> radiusport );
2575
+ /* XXX: add support for multiple returned addresses? */
2563
2576
2564
2577
if (port -> hba -> radiusidentifier && port -> hba -> radiusidentifier [0 ])
2565
2578
identifier = port -> hba -> radiusidentifier ;
@@ -2633,34 +2646,51 @@ CheckRADIUSAuth(Port *port)
2633
2646
packetlength = packet -> length ;
2634
2647
packet -> length = htons (packet -> length );
2635
2648
2636
- sock = socket (AF_INET , SOCK_DGRAM , 0 );
2649
+ sock = socket (serveraddrs [ 0 ]. ai_family , SOCK_DGRAM , 0 );
2637
2650
if (sock < 0 )
2638
2651
{
2639
2652
ereport (LOG ,
2640
2653
(errmsg ("could not create RADIUS socket: %m" )));
2654
+ pg_freeaddrinfo_all (hint .ai_family , serveraddrs );
2641
2655
return STATUS_ERROR ;
2642
2656
}
2643
2657
2644
2658
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 ;
2646
2668
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 ))
2648
2672
{
2649
2673
ereport (LOG ,
2650
2674
(errmsg ("could not bind local RADIUS socket: %m" )));
2651
2675
closesocket (sock );
2676
+ pg_freeaddrinfo_all (hint .ai_family , serveraddrs );
2652
2677
return STATUS_ERROR ;
2653
2678
}
2654
2679
2655
2680
if (sendto (sock , radius_buffer , packetlength , 0 ,
2656
- ( struct sockaddr * ) & remoteaddr , sizeof ( remoteaddr ) ) < 0 )
2681
+ serveraddrs [ 0 ]. ai_addr , serveraddrs [ 0 ]. ai_addrlen ) < 0 )
2657
2682
{
2658
2683
ereport (LOG ,
2659
2684
(errmsg ("could not send RADIUS packet: %m" )));
2660
2685
closesocket (sock );
2686
+ pg_freeaddrinfo_all (hint .ai_family , serveraddrs );
2661
2687
return STATUS_ERROR ;
2662
2688
}
2663
2689
2690
+ /* Don't need the server address anymore */
2691
+ pg_freeaddrinfo_all (hint .ai_family , serveraddrs );
2692
+
2693
+ /* Wait for a response */
2664
2694
timeout .tv_sec = RADIUS_TIMEOUT ;
2665
2695
timeout .tv_usec = 0 ;
2666
2696
FD_ZERO (& fdset );
@@ -2705,11 +2735,21 @@ CheckRADIUSAuth(Port *port)
2705
2735
2706
2736
closesocket (sock );
2707
2737
2738
+ #ifdef HAVE_IPV6
2739
+ if (remoteaddr .sin6_port != htons (port -> hba -> radiusport ))
2740
+ #else
2708
2741
if (remoteaddr .sin_port != htons (port -> hba -> radiusport ))
2742
+ #endif
2709
2743
{
2744
+ #ifdef HAVE_IPV6
2745
+ ereport (LOG ,
2746
+ (errmsg ("RADIUS response was sent from incorrect port: %i" ,
2747
+ ntohs (remoteaddr .sin6_port ))));
2748
+ #else
2710
2749
ereport (LOG ,
2711
2750
(errmsg ("RADIUS response was sent from incorrect port: %i" ,
2712
2751
ntohs (remoteaddr .sin_port ))));
2752
+ #endif
2713
2753
return STATUS_ERROR ;
2714
2754
}
2715
2755
0 commit comments