File pam-radius-auth-ip-conf.patch of Package pam_radius
diff -up pam_radius-release_2_0_0/src/pam_radius_auth.c.auth-ip-conf pam_radius-release_2_0_0/src/pam_radius_auth.c
--- pam_radius-release_2_0_0/src/pam_radius_auth.c.auth-ip-conf 2023-03-30 16:15:10.538286268 +0200
+++ pam_radius-release_2_0_0/src/pam_radius_auth.c 2023-03-30 16:16:58.163194003 +0200
@@ -60,6 +60,9 @@ static int _pam_parse(int argc, CONST ch
/* set the default prompt */
snprintf(conf->prompt, MAXPROMPT, "%s: ", DEFAULT_PROMPT);
+ conf->use_ipv4 = 1;
+ conf->use_ipv6 = 1;
+
/*
* If either is not there, then we can't parse anything.
*/
@@ -127,6 +130,14 @@ static int _pam_parse(int argc, CONST ch
} else if (!strncmp(*argv, "max_challenge=", 14)) {
conf->max_challenge = atoi(*argv+14);
+ } else if (!strncmp(*argv, "ipv4=", 5)) {
+ if (!strcmp(*argv + 5, "yes")) conf->use_ipv4 = 1;
+ if (!strcmp(*argv + 5, "no")) conf->use_ipv4 = 0;
+
+ } else if (!strncmp(*argv, "ipv6=", 5)) {
+ if (!strcmp(*argv + 5, "yes")) conf->use_ipv6 = 1;
+ if (!strcmp(*argv + 5, "no")) conf->use_ipv6 = 0;
+
} else if (!strcmp(*argv, "privilege_level")) {
conf->privilege_level = TRUE;
@@ -135,6 +146,12 @@ static int _pam_parse(int argc, CONST ch
}
}
+ if (!conf->use_ipv4 && !conf->use_ipv6) {
+ _pam_log(LOG_WARNING, "Cannot disable both IPv4 and IPv6'");
+
+ conf->use_ipv4 = 1;
+ }
+
return ctrl;
}
@@ -527,8 +544,13 @@ static void cleanup(radius_server_t *ser
}
}
-static int initialize_sockets(int *sockfd, int *sockfd6, struct sockaddr_storage *salocal4, struct sockaddr_storage *salocal6, char *vrf)
+static int initialize_sockets(radius_conf_t const *conf, int *sockfd, int *sockfd6, struct sockaddr_storage *salocal4, struct sockaddr_storage *salocal6, char *vrf)
{
+ if (!conf->use_ipv4) {
+ *sockfd = -1;
+ goto use_ipv6;
+ }
+
/* open a socket. Dies if it fails */
*sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (*sockfd < 0) {
@@ -566,10 +588,22 @@ static int initialize_sockets(int *sockf
return -1;
}
- /* open a IPv6 socket. Dies if it fails */
+ if (!conf->use_ipv6) {
+ *sockfd6 = -1;
+ return 0;
+ }
+
+use_ipv6:
+ /* open a IPv6 socket. */
*sockfd6 = socket(AF_INET6, SOCK_DGRAM, 0);
if (*sockfd6 < 0) {
char error_string[BUFFER_SIZE];
+
+ /*
+ * IPv6 can be disabled on localhost.
+ */
+ if (errno == EAFNOSUPPORT) return 0;
+
get_error_string(errno, error_string, sizeof(error_string));
_pam_log(LOG_ERR, "Failed to open RADIUS IPv6 socket: %s\n", error_string);
return -1;
@@ -745,7 +779,8 @@ static int initialize(radius_conf_t *con
}
if (valid_src_ip == 0 || vrf[0]) {
- if (initialize_sockets(&server->sockfd, &server->sockfd6, &salocal4, &salocal6, vrf) != 0) {
+ if (initialize_sockets(conf, &server->sockfd, &server->sockfd6, &salocal4, &salocal6, vrf) != 0) {
+
goto error;
}
}
@@ -766,7 +801,7 @@ static int initialize(radius_conf_t *con
((struct sockaddr *)&salocal4)->sa_family = AF_INET;
((struct sockaddr *)&salocal6)->sa_family = AF_INET6;
- if (initialize_sockets(&conf->sockfd, &conf->sockfd6, &salocal4, &salocal6, NULL) != 0) {
+ if (initialize_sockets(conf, &conf->sockfd, &conf->sockfd6, &salocal4, &salocal6, NULL) != 0) {
goto error;
}
@@ -892,6 +927,14 @@ static int talk_radius(radius_conf_t *co
sockfd = server->sockfd6 != -1 ? server->sockfd6 : conf->sockfd6;
}
+ /*
+ * Is there a valid socket for this server + address family? If not, skip it.
+ */
+ if (sockfd < 0) {
+ ok = FALSE;
+ goto next;
+ }
+
total_length = ntohs(request->length);
server_tries = tries;
send:
diff -up pam_radius-release_2_0_0/src/pam_radius_auth.h.auth-ip-conf pam_radius-release_2_0_0/src/pam_radius_auth.h
--- pam_radius-release_2_0_0/src/pam_radius_auth.h.auth-ip-conf 2023-03-30 16:15:10.539286276 +0200
+++ pam_radius-release_2_0_0/src/pam_radius_auth.h 2023-03-30 16:17:06.352263072 +0200
@@ -150,6 +150,8 @@ typedef struct radius_server_t {
typedef struct radius_conf_t {
radius_server_t *server;
int retries;
+ int use_ipv4;
+ int use_ipv6;
int localifdown;
char *client_id;
int accounting_bug;