IPv6 code for pam_radius-1.3.17
kentaro aoki
kentaro.aoki at gmail.com
Fri Jul 18 10:36:10 CEST 2008
Hi,
I make the patch of ipv6 for pam_radius-1.3.17.
Please use, if very well.
Thank you.
Kentaro Aoki
The config file is following.
/etc/raddb/server
127.0.0.1:1645 secret 1
127.0.0.1 secret 1
[::1]:1645 secret 1
::1 secret 1
The patch is following.
diff -c pam_radius-1.3.17/pam_radius_auth.c
pam_radius-1.3.17-ipv6/pam_radius_auth.c
*** pam_radius-1.3.17/pam_radius_auth.c 2007-03-26 18:36:13.000000000 +0900
--- pam_radius-1.3.17-ipv6/pam_radius_auth.c 2008-07-18 16:14:08.000000000 +0900
***************
*** 27,32 ****
--- 27,33 ----
* 1.3.15 - Implement retry option, miscellanous bug fixes.
* 1.3.16 - Miscellaneous fixes (see CVS for history)
* 1.3.17 - Security fixes
+ * 1.3.17-ipv6 - Added ipv6 code by Kentaro Aoki <kentaro.aoki at gmail.com>
*
*
* This program is free software; you can redistribute it and/or modify
***************
*** 252,257 ****
--- 253,315 ----
return(ntohl(*(UINT4 *)hp->h_addr));
}
+ int dup_addrinfo(struct addrinfo **pptr_dup_addrinfo, struct
addrinfo *ptr_addrinfo)
+ {
+ int result = 0;
+ struct addrinfo *ptr_tmp_addrinfo;
+ struct addrinfo *ptr_tmp_dup_addrinfo = NULL;;
+ struct addrinfo *ptr_tmp_cur_addrinfo = NULL;;
+
+ *pptr_dup_addrinfo = NULL;
+ for (ptr_tmp_addrinfo = ptr_addrinfo; ptr_tmp_addrinfo != NULL;
ptr_tmp_addrinfo = ptr_tmp_addrinfo->ai_next) {
+ ptr_tmp_dup_addrinfo = malloc(sizeof(struct addrinfo));
+ if (ptr_tmp_dup_addrinfo == NULL) {
+ continue;
+ }
+ memset(ptr_tmp_dup_addrinfo, 0, sizeof(struct addrinfo));
+
+ if (ptr_tmp_addrinfo->ai_addr == NULL ||
ptr_tmp_addrinfo->ai_addrlen <= 0) {
+ ptr_tmp_dup_addrinfo->ai_addr = NULL;
+ } else {
+ ptr_tmp_dup_addrinfo->ai_addr = malloc(ptr_tmp_addrinfo->ai_addrlen);
+ memcpy(ptr_tmp_dup_addrinfo->ai_addr, ptr_tmp_addrinfo->ai_addr,
ptr_tmp_addrinfo->ai_addrlen);
+ }
+ ptr_tmp_dup_addrinfo->ai_addrlen = ptr_tmp_addrinfo->ai_addrlen;
+ if (ptr_tmp_addrinfo->ai_canonname != NULL) {
+ ptr_tmp_dup_addrinfo->ai_canonname =
strdup(ptr_tmp_addrinfo->ai_canonname);
+ } else {
+ ptr_tmp_dup_addrinfo->ai_canonname = NULL;
+ }
+ ptr_tmp_dup_addrinfo->ai_family = ptr_tmp_addrinfo->ai_family;
+ ptr_tmp_dup_addrinfo->ai_flags = ptr_tmp_addrinfo->ai_flags;
+ ptr_tmp_dup_addrinfo->ai_protocol = ptr_tmp_addrinfo->ai_protocol;
+ ptr_tmp_dup_addrinfo->ai_socktype = ptr_tmp_addrinfo->ai_socktype;
+ ptr_tmp_dup_addrinfo->ai_next = NULL;
+
+ if (*pptr_dup_addrinfo == NULL) {
+ *pptr_dup_addrinfo = ptr_tmp_dup_addrinfo;
+ } else {
+ ptr_tmp_cur_addrinfo->ai_next = ptr_tmp_dup_addrinfo;
+ }
+ ptr_tmp_cur_addrinfo = ptr_tmp_dup_addrinfo;
+ }
+ return result;
+ }
+
+ void free_addrinfo(struct addrinfo **pptr_addrinfo)
+ {
+ if (*pptr_addrinfo != NULL) {
+ if ((*pptr_addrinfo)->ai_addr != NULL) {
+ free((*pptr_addrinfo)->ai_addr);
+ }
+ if ((*pptr_addrinfo)->ai_canonname != NULL) {
+ free((*pptr_addrinfo)->ai_canonname);
+ }
+ free(*pptr_addrinfo);
+ *pptr_addrinfo = NULL;
+ }
+ }
+
/*
* take server->hostname, and convert it to server->ip and server->port
*/
***************
*** 260,314 ****
{
char *p;
int ctrl = 1; /* for DPRINT */
!
! if ((p = strchr(server->hostname, ':')) != NULL) {
! *(p++) = '\0'; /* split the port off from the host name */
}
!
! if ((server->ip.s_addr = get_ipaddr(server->hostname)) == ((UINT4)0)) {
! DPRINT(LOG_DEBUG, "DEBUG: get_ipaddr(%s) returned 0.\n",
server->hostname);
! return PAM_AUTHINFO_UNAVAIL;
}
!
! /*
! * If the server port hasn't already been defined, go get it.
! */
! if (!server->port) {
! if (p && isdigit(*p)) { /* the port looks like it's a number */
! unsigned int i = atoi(p) & 0xffff;
!
! if (!server->accounting) {
! server->port = htons((u_short) i);
! } else {
! server->port = htons((u_short) (i + 1));
! }
! } else { /* the port looks like it's a name */
! struct servent *svp;
!
! if (p) { /* maybe it's not "radius" */
! svp = getservbyname (p, "udp");
! /* quotes allow distinction from above, lest p be radius or radacct */
! DPRINT(LOG_DEBUG, "DEBUG: getservbyname('%s', udp) returned %d.\n", p, svp);
! *(--p) = ':'; /* be sure to put the delimiter back */
! } else {
! if (!server->accounting) {
! svp = getservbyname ("radius", "udp");
! DPRINT(LOG_DEBUG, "DEBUG: getservbyname(radius, udp) returned %d.\n", svp);
! } else {
! svp = getservbyname ("radacct", "udp");
! DPRINT(LOG_DEBUG, "DEBUG: getservbyname(radacct, udp) returned
%d.\n", svp);
! }
! }
!
! if (svp == (struct servent *) 0) {
! /* debugging above... */
! return PAM_AUTHINFO_UNAVAIL;
! }
!
! server->port = svp->s_port;
! }
}
!
return PAM_SUCCESS;
}
--- 318,372 ----
{
char *p;
int ctrl = 1; /* for DPRINT */
! char *ptr_host = NULL;
! char *ptr_service = NULL;
! char *ptr_hostname;
! int i;
! struct addrinfo hintsaddr;
! struct addrinfo *peeraddrs;
!
! ptr_hostname = strdup(server->hostname);
! ptr_host = ptr_hostname;
! /* If the host name may be catenated ipv6-string with port, go get it. */
! if (*ptr_host == '[') {
! ptr_host ++;
! p = strchr(ptr_host, ']');
! *(p++) = '\0'; /* split the port off from the host name */
! ptr_service = strchr(p, ':');
! ptr_service++;
! } else {
! /* Checks the host name for ipv6. */
! i = 0;
! for (p = ptr_host; *p != '\0'; p ++) {
! if (*p == ':') {
! i ++;
! }
! }
! /* If the host name may be ipv4-string, go get it. */
! if (i < 2) {
! if ((ptr_service = strchr(ptr_host, ':')) != NULL) {
! *(ptr_service++) = '\0'; /* split the port off from the host name */
! }
! }
}
! if (ptr_service == NULL) {
! if (!server->accounting) {
! ptr_service = "radius";
! } else {
! ptr_service = "radacct";
! }
}
!
! /* Resolves host with service. */
! memset(&hintsaddr, 0, sizeof(struct addrinfo));
! hintsaddr.ai_family = AF_UNSPEC;
! hintsaddr.ai_socktype = SOCK_DGRAM;
! if ((i = getaddrinfo(ptr_host, ptr_service, &hintsaddr, &peeraddrs)) != 0) {
! DPRINT(LOG_DEBUG, "DEBUG: getaddrinfo(%s, %s) returned %d.\n",
ptr_host, ptr_service, i);
! return PAM_AUTHINFO_UNAVAIL;
}
! dup_addrinfo(&server->addressinfo, peeraddrs);
! free(ptr_hostname);
return PAM_SUCCESS;
}
***************
*** 641,647 ****
server->hostname = strdup(hostname);
server->secret = strdup(secret);
server->accounting = accounting;
! server->port = 0;
if ((timeout < 1) || (timeout > 60)) {
server->timeout = 3;
--- 699,705 ----
server->hostname = strdup(hostname);
server->secret = strdup(secret);
server->accounting = accounting;
! server->addressinfo = NULL;
if ((timeout < 1) || (timeout > 60)) {
server->timeout = 3;
***************
*** 699,705 ****
build_radius_packet(AUTH_HDR *request, CONST char *user, CONST char
*password, radius_conf_t *conf)
{
char hostname[256];
! UINT4 ipaddr;
hostname[0] = '\0';
gethostname(hostname, sizeof(hostname) - 1);
--- 757,765 ----
build_radius_packet(AUTH_HDR *request, CONST char *user, CONST char
*password, radius_conf_t *conf)
{
char hostname[256];
! struct addrinfo hintsaddr;
! struct addrinfo *peeraddrs;
! struct addrinfo *peeraddr;
hostname[0] = '\0';
gethostname(hostname, sizeof(hostname) - 1);
***************
*** 725,746 ****
add_password(request, PW_PASSWORD, "", conf->server->secret);
}
! /* the packet is from localhost if on localhost, to make configs easier */
! if ((conf->server->ip.s_addr == ntohl(0x7f000001)) || (!hostname[0])) {
! ipaddr = 0x7f000001;
! } else {
! struct hostent *hp;
!
! if ((hp = gethostbyname(hostname)) == (struct hostent *) NULL) {
! ipaddr = 0x00000000; /* no client IP address */
! } else {
! ipaddr = ntohl(*(UINT4 *) hp->h_addr); /* use the first one available */
! }
}
/* If we can't find an IP address, then don't add one */
! if (ipaddr) {
! add_int_attribute(request, PW_NAS_IP_ADDRESS, ipaddr);
}
/* There's always a NAS identifier */
--- 785,814 ----
add_password(request, PW_PASSWORD, "", conf->server->secret);
}
! if (hostname[0] == '\0') {
! strncpy(hostname, "127.0.0.1", sizeof(hostname));
}
/* If we can't find an IP address, then don't add one */
! if (hostname[0] != '\0') {
! hintsaddr.ai_family = AF_UNSPEC;
! hintsaddr.ai_socktype = SOCK_DGRAM;
! if (getaddrinfo(hostname, NULL, &hintsaddr, &peeraddrs) == 0) {
! for (peeraddr = peeraddrs; peeraddr != NULL; peeraddr =
peeraddr->ai_next) {
! switch (peeraddr->ai_family) {
! case AF_INET:
! add_attribute(request, PW_NAS_IP_ADDRESS,
! (unsigned char *)&((struct sockaddr_in
*)peeraddr->ai_addr)->sin_addr, 4);
! break;
! case AF_INET6:
! add_attribute(request, PW_NAS_IPV6_ADDRESS,
! (unsigned char *)&((struct sockaddr_in6
*)peeraddr->ai_addr)->sin6_addr, 16);
! break;
! default:
! break;
! }
! }
! }
}
/* There's always a NAS identifier */
***************
*** 766,780 ****
talk_radius(radius_conf_t *conf, AUTH_HDR *request, AUTH_HDR *response,
char *password, char *old_password, int tries)
{
! int salen, total_length;
fd_set set;
struct timeval tv;
time_t now, end;
int rcode;
! struct sockaddr saremote;
! struct sockaddr_in *s_in = (struct sockaddr_in *) &saremote;
radius_server_t *server = conf->server;
! int ok;
int server_tries;
int retval;
--- 834,849 ----
talk_radius(radius_conf_t *conf, AUTH_HDR *request, AUTH_HDR *response,
char *password, char *old_password, int tries)
{
! int total_length;
fd_set set;
struct timeval tv;
time_t now, end;
int rcode;
! struct addrinfo *cur_addrinfo;
! struct sockaddr_in6 saremote;
! socklen_t salen = sizeof(struct sockaddr_in6);
radius_server_t *server = conf->server;
! int ok = TRUE;
int server_tries;
int retval;
***************
*** 804,957 ****
}
/* set up per-server IP && port configuration */
- memset ((char *) s_in, '\0', sizeof(struct sockaddr));
- s_in->sin_family = AF_INET;
- s_in->sin_addr.s_addr = htonl(server->ip.s_addr);
- s_in->sin_port = server->port;
total_length = ntohs(request->length);
if (!password) { /* make an RFC 2139 p6 request authenticator */
get_accounting_vector(request, server);
}
! server_tries = tries;
! send:
! /* send the packet */
! if (sendto(conf->sockfd, (char *) request, total_length, 0,
! &saremote, sizeof(struct sockaddr_in)) < 0) {
! _pam_log(LOG_ERR, "Error sending RADIUS packet to server %s: %s",
! server->hostname, strerror(errno));
! ok = FALSE;
! goto next; /* skip to the next server */
! }
!
! /* ************************************************************ */
! /* Wait for the response, and verify it. */
! salen = sizeof(struct sockaddr);
! tv.tv_sec = server->timeout; /* wait for the specified time */
! tv.tv_usec = 0;
! FD_ZERO(&set); /* clear out the set */
! FD_SET(conf->sockfd, &set); /* wait only for the RADIUS UDP socket */
!
! time(&now);
! end = now + tv.tv_sec;
!
! /* loop, waiting for the select to return data */
! ok = TRUE;
! while (ok) {
!
! rcode = select(conf->sockfd + 1, &set, NULL, NULL, &tv);
!
! /* select timed out */
! if (rcode == 0) {
! _pam_log(LOG_ERR, "RADIUS server %s failed to respond",
! server->hostname);
! if (--server_tries)
! goto send;
! ok = FALSE;
! break; /* exit from the select loop */
! } else if (rcode < 0) {
!
! /* select had an error */
! if (errno == EINTR) { /* we were interrupted */
! time(&now);
!
! if (now > end) {
! _pam_log(LOG_ERR, "RADIUS server %s failed to respond",
! server->hostname);
! if (--server_tries)
! goto send;
! ok = FALSE;
! break; /* exit from the select loop */
! }
!
! tv.tv_sec = end - now;
! if (tv.tv_sec == 0) { /* keep waiting */
! tv.tv_sec = 1;
! }
!
! } else { /* not an interrupt, it was a real error */
! _pam_log(LOG_ERR, "Error waiting for response from RADIUS server %s: %s",
! server->hostname, strerror(errno));
! ok = FALSE;
! break;
}
!
! /* the select returned OK */
! } else if (FD_ISSET(conf->sockfd, &set)) {
!
! /* try to receive some data */
! if ((total_length = recvfrom(conf->sockfd, (char *) response,
! BUFFER_SIZE,
! 0, &saremote, &salen)) < 0) {
! _pam_log(LOG_ERR, "error reading RADIUS packet from server %s: %s",
! server->hostname, strerror(errno));
! ok = FALSE;
! break;
!
! /* there's data, see if it's valid */
! } else {
! char *p = server->secret;
!
! if ((ntohs(response->length) != total_length) ||
! (ntohs(response->length) > BUFFER_SIZE)) {
! _pam_log(LOG_ERR, "RADIUS packet from server %s is corrupted",
! server->hostname);
! ok = FALSE;
! break;
! }
!
! /* Check if we have the data OK. We should also check request->id */
!
! if (password) {
! if (old_password) {
#ifdef LIVINGSTON_PASSWORD_VERIFY_BUG_FIXED
! p = old_password; /* what it should be */
! #else
! p = ""; /* what it really is */
! #endif
! }
! /*
! * RFC 2139 p.6 says not do do this, but the Livingston 1.16
! * server disagrees. If the user says he wants the bug, give in.
! */
! } else { /* authentication request */
! if (conf->accounting_bug) {
! p = "";
! }
! }
!
! if (!verify_packet(p, response, request)) {
! _pam_log(LOG_ERR, "packet from RADIUS server %s fails
verification: The shared secret is probably incorrect.",
! server->hostname);
! ok = FALSE;
! break;
! }
!
! /*
! * Check that the response ID matches the request ID.
! */
! if (response->id != request->id) {
! _pam_log(LOG_WARNING, "Response packet ID %d does not match the
request packet ID %d: verification of packet fails", response->id,
request->id);
! ok = FALSE;
! break;
! }
! }
!
! /*
! * Whew! The select is done. It hasn't timed out, or errored out.
! * It's our descriptor. We've got some data. It's the right size.
! * The packet is valid.
! * NOW, we can skip out of the select loop, and process the packet
! */
! break;
! }
! /* otherwise, we've got data on another descriptor, keep select'ing */
! }
/* go to the next server if this one didn't respond */
next:
! if (!ok) {
radius_server_t *old; /* forget about this server */
old = server;
--- 873,1058 ----
}
/* set up per-server IP && port configuration */
total_length = ntohs(request->length);
if (!password) { /* make an RFC 2139 p6 request authenticator */
get_accounting_vector(request, server);
}
! for (cur_addrinfo = server->addressinfo
! ; cur_addrinfo != NULL
! ; cur_addrinfo = cur_addrinfo->ai_next) {
!
! struct sockaddr_in peer_sockaddr;
! struct sockaddr_in6 peer_sockaddr6;
! const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
! u_short local_port;
! struct sockaddr *sockaddr_ptr;
! int sockaddr_len;
! int sockfd;
!
! ok = TRUE;
! if (cur_addrinfo->ai_family != AF_INET && cur_addrinfo->ai_family
!= AF_INET6) {
! ok = FALSE;
! continue;
! }
! /* send the packet */
! sockfd = socket(cur_addrinfo->ai_family,
! cur_addrinfo->ai_socktype,
! cur_addrinfo->ai_protocol);
! if (sockfd < 0) {
! ok = FALSE;
! continue;
! }
!
! /*
! * Use our process ID as a local port for RADIUS.
! */
! local_port = (getpid() & 0x7fff) + 1024;
! do {
! local_port++;
! if (cur_addrinfo->ai_family == AF_INET) {
! peer_sockaddr.sin_family = cur_addrinfo->ai_family;
! peer_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
! peer_sockaddr.sin_port = htons(local_port);
! sockaddr_ptr = (struct sockaddr *)&peer_sockaddr;
! sockaddr_len = sizeof(struct sockaddr_in);
! } else if (cur_addrinfo->ai_family == AF_INET6) {
! peer_sockaddr6.sin6_family = cur_addrinfo->ai_family;
! peer_sockaddr6.sin6_addr = in6addr_any;
! peer_sockaddr6.sin6_port = htons(local_port);
! sockaddr_ptr = (struct sockaddr *)&peer_sockaddr6;
! sockaddr_len = sizeof(struct sockaddr_in6);
! } else {
! continue;
! }
! } while ((bind(sockfd, sockaddr_ptr, sockaddr_len) < 0) &&
! (local_port < 64000));
! if (local_port >= 64000) {
! close(sockfd);
! _pam_log(LOG_ERR, "No open port we could bind to.");
! continue;
! }
!
! if (sendto(sockfd, (char *) request, total_length, 0,
! cur_addrinfo->ai_addr, cur_addrinfo->ai_addrlen) < 0) {
! _pam_log(LOG_ERR, "Error sending RADIUS packet to server %s: %s",
! server->hostname, strerror(errno));
! close(sockfd);
! continue;
! }
! server_tries = tries;
! do {
! tv.tv_sec = server->timeout; /* wait for the specified time */
! tv.tv_usec = 0;
! FD_ZERO(&set); /* clear out the set */
! FD_SET(sockfd, &set); /* wait only for the RADIUS UDP socket */
! rcode = select(sockfd + 1, &set, NULL, NULL, &tv);
! /* select timed out */
! if (rcode == 0) {
! _pam_log(LOG_ERR, "RADIUS server %s failed to respond(time
out %d(sec))",
! server->hostname, server->timeout);
! if (--server_tries) {
! continue;
! }
! ok = FALSE;
! break; /* exit from the select loop */
! } else if (rcode < 0) {
! /* select had an error */
! if (errno == EINTR) { /* we were interrupted */
! time(&now);
! if (now > end) {
! _pam_log(LOG_ERR, "RADIUS server %s failed to respond",
! server->hostname);
! if (--server_tries) {
! continue;
! }
! ok = FALSE;
! break; /* exit from the select loop */
! }
! tv.tv_sec = end - now;
! if (tv.tv_sec == 0) { /* keep waiting */
! tv.tv_sec = 1;
! }
! } else { /* not an interrupt, it was a real error */
! _pam_log(LOG_ERR, "Error waiting for response from RADIUS
server %s: %s",
! server->hostname, strerror(errno));
! ok = FALSE;
! break;
! }
! /* the select returned OK */
! } else if (FD_ISSET(sockfd, &set)) {
! /* try to receive some data */
! if ((total_length = recvfrom(sockfd, (char *) response,
BUFFER_SIZE, 0, (struct sockaddr *)&saremote, &salen)) < 0) {
! _pam_log(LOG_ERR, "error reading RADIUS packet from server %s: %s",
! server->hostname, strerror(errno));
! ok = FALSE;
! break;
! /* there's data, see if it's valid */
! }
! }
! } while (0);
! close(sockfd);
! if (ok != FALSE) {
! break;
! }
}
! do {
! if (ok == TRUE) {
! char *p = server->secret;
! if ((ntohs(response->length) != total_length) ||
! (ntohs(response->length) > BUFFER_SIZE)) {
! _pam_log(LOG_ERR, "RADIUS packet from server %s is corrupted",
! server->hostname);
! ok = FALSE;
! break;
! }
! /* Check if we have the data OK. We should also check request->id */
! if (password) {
! if (old_password) {
#ifdef LIVINGSTON_PASSWORD_VERIFY_BUG_FIXED
! p = old_password; /* what it should be */
! #else next:
+ p = ""; /* what it really is */
+ #endif
+ }
+ /*
+ * RFC 2139 p.6 says not do do this, but the Livingston 1.16
+ * server disagrees. If the user says he wants the bug, give in.
+ */
+ } else { /* authentication request */
+ if (conf->accounting_bug) {
+ p = "";
+ }
+ }
+ if (!verify_packet(p, response, request)) {
+ _pam_log(LOG_ERR, "packet from RADIUS server %s fails
verification: The shared secret is probably incorrect.",
+ server->hostname);
+ ok = FALSE;
+ break;
+ }
+ /*
+ * Check that the response ID matches the request ID.
+ */
+ if (response->id != request->id) {
+ _pam_log(LOG_WARNING, "Response packet ID %d does not match the
request packet ID %d: verification of packet fails", response->id,
request->id);
+ ok = FALSE;
+ break;
+ }
+ /*
+ * Whew! The select is done. It hasn't timed out, or errored out.
+ * It's our descriptor. We've got some data. It's the right size.
+ * The packet is valid.
+ * NOW, we can skip out of the select loop, and process the packet
+ */
+ break;
+ }
+ /* otherwise, we've got data on another descriptor, keep select'ing */
+ } while (0);
/* go to the next server if this one didn't respond */
next:
! if (ok == FALSE) {
radius_server_t *old; /* forget about this server */
old = server;
***************
*** 960,965 ****
--- 1061,1067 ----
_pam_forget(old->secret);
free(old->hostname);
+ free_addrinfo(&old->addressinfo);
free(old);
if (server) { /* if there's more servers to check */
***************
*** 1137,1143 ****
if(password) {
password = strdup(password);
- DPRINT(LOG_DEBUG, "Got password %s", password);
}
/* no previous password: maybe get one from the user */
--- 1239,1244 ----
diff -c pam_radius-1.3.17/pam_radius_auth.conf
pam_radius-1.3.17-ipv6/pam_radius_auth.conf
*** pam_radius-1.3.17/pam_radius_auth.conf 2000-07-11 04:18:42.000000000 +0900
--- pam_radius-1.3.17-ipv6/pam_radius_auth.conf 2008-07-18
16:36:15.000000000 +0900
***************
*** 8,14 ****
# lines. Blank lines or lines beginning with '#' are treated as
# comments, and are ignored. The fields are:
#
! # server[:port] secret [timeout]
#
# the port name or number is optional. The default port name is
# "radius", and is looked up from /etc/services The timeout field is
--- 8,17 ----
# lines. Blank lines or lines beginning with '#' are treated as
# comments, and are ignored. The fields are:
#
! # hostname-server[:port] secret [timeout]
! # ipv4-server[:port] secret [timeout]
! # ipv6-server secret [timeout]
! # \[ipv6-server\]:port secret [timeout]
#
# the port name or number is optional. The default port name is
# "radius", and is looked up from /etc/services The timeout field is
***************
*** 23,28 ****
--- 26,35 ----
# deciding that the server has failed to respond.
#
# server[:port] shared_secret timeout (s)
+ # ex.
+ # ::1 secret 1
+ # [::1]:1645 secret 1
+
127.0.0.1 secret 1
other-server other-secret 3
diff -c pam_radius-1.3.17/pam_radius_auth.h
pam_radius-1.3.17-ipv6/pam_radius_auth.h
*** pam_radius-1.3.17/pam_radius_auth.h 2007-03-26 14:35:31.000000000 +0900
--- pam_radius-1.3.17-ipv6/pam_radius_auth.h 2008-07-18 16:14:19.000000000 +0900
***************
*** 36,43 ****
typedef struct radius_server_t {
struct radius_server_t *next;
! struct in_addr ip;
! u_short port;
char *hostname;
char *secret;
int timeout;
--- 36,42 ----
typedef struct radius_server_t {
struct radius_server_t *next;
! struct addrinfo *addressinfo;
char *hostname;
char *secret;
int timeout;
diff -c pam_radius-1.3.17/radius.h pam_radius-1.3.17-ipv6/radius.h
*** pam_radius-1.3.17/radius.h 2000-08-23 00:24:47.000000000 +0900
--- pam_radius-1.3.17-ipv6/radius.h 2008-07-18 16:07:34.000000000 +0900
***************
*** 125,130 ****
--- 125,131 ----
#define PW_LOGIN_LAT_PORT 63 /* string */
#define PW_PROMPT 64 /* integer */
+ #define PW_NAS_IPV6_ADDRESS 95 /* address */
/*
* INTEGER TRANSLATIONS
*/
More information about the Freeradius-Devel
mailing list