xref: /OK3568_Linux_fs/yocto/poky/meta/recipes-extended/pam/libpam/CVE-2022-28321-0002.patch (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593SmuzhiyunFrom 23393bef92c1e768eda329813d7af55481c6ca9f Mon Sep 17 00:00:00 2001
2*4882a593SmuzhiyunFrom: Thorsten Kukuk <kukuk@suse.com>
3*4882a593SmuzhiyunDate: Thu, 24 Feb 2022 10:37:32 +0100
4*4882a593SmuzhiyunSubject: [PATCH 2/2] pam_access: handle hostnames in access.conf
5*4882a593Smuzhiyun
6*4882a593SmuzhiyunAccording to the manual page, the following entry is valid but does not
7*4882a593Smuzhiyunwork:
8*4882a593Smuzhiyun-:root:ALL EXCEPT localhost
9*4882a593Smuzhiyun
10*4882a593SmuzhiyunSee https://bugzilla.suse.com/show_bug.cgi?id=1019866
11*4882a593Smuzhiyun
12*4882a593SmuzhiyunPatched is based on PR#226 from Josef Moellers
13*4882a593Smuzhiyun
14*4882a593SmuzhiyunUpstream-Status: Backport
15*4882a593SmuzhiyunCVE: CVE-2022-28321
16*4882a593Smuzhiyun
17*4882a593SmuzhiyunReference to upstream patch:
18*4882a593Smuzhiyun[https://github.com/linux-pam/linux-pam/commit/23393bef92c1e768eda329813d7af55481c6ca9f]
19*4882a593Smuzhiyun
20*4882a593SmuzhiyunSigned-off-by: Stefan Ghinea <stefan.ghinea@windriver.com>
21*4882a593Smuzhiyun---
22*4882a593Smuzhiyun modules/pam_access/pam_access.c | 95 ++++++++++++++++++++++++++-------
23*4882a593Smuzhiyun 1 file changed, 76 insertions(+), 19 deletions(-)
24*4882a593Smuzhiyun
25*4882a593Smuzhiyundiff --git a/modules/pam_access/pam_access.c b/modules/pam_access/pam_access.c
26*4882a593Smuzhiyunindex 277192b..bca424f 100644
27*4882a593Smuzhiyun--- a/modules/pam_access/pam_access.c
28*4882a593Smuzhiyun+++ b/modules/pam_access/pam_access.c
29*4882a593Smuzhiyun@@ -637,7 +637,7 @@ remote_match (pam_handle_t *pamh, char *tok, struct login_info *item)
30*4882a593Smuzhiyun       if ((str_len = strlen(string)) > tok_len
31*4882a593Smuzhiyun 	  && strcasecmp(tok, string + str_len - tok_len) == 0)
32*4882a593Smuzhiyun 	return YES;
33*4882a593Smuzhiyun-    } else if (tok[tok_len - 1] == '.') {
34*4882a593Smuzhiyun+    } else if (tok[tok_len - 1] == '.') {       /* internet network numbers (end with ".") */
35*4882a593Smuzhiyun       struct addrinfo hint;
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun       memset (&hint, '\0', sizeof (hint));
38*4882a593Smuzhiyun@@ -678,7 +678,7 @@ remote_match (pam_handle_t *pamh, char *tok, struct login_info *item)
39*4882a593Smuzhiyun       return NO;
40*4882a593Smuzhiyun     }
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun-    /* Assume network/netmask with an IP of a host.  */
43*4882a593Smuzhiyun+    /* Assume network/netmask, IP address or hostname.  */
44*4882a593Smuzhiyun     return network_netmask_match(pamh, tok, string, item);
45*4882a593Smuzhiyun }
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun@@ -696,7 +696,7 @@ string_match (pam_handle_t *pamh, const char *tok, const char *string,
48*4882a593Smuzhiyun     /*
49*4882a593Smuzhiyun      * If the token has the magic value "ALL" the match always succeeds.
50*4882a593Smuzhiyun      * Otherwise, return YES if the token fully matches the string.
51*4882a593Smuzhiyun-	 * "NONE" token matches NULL string.
52*4882a593Smuzhiyun+     * "NONE" token matches NULL string.
53*4882a593Smuzhiyun      */
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun     if (strcasecmp(tok, "ALL") == 0) {		/* all: always matches */
56*4882a593Smuzhiyun@@ -714,7 +714,8 @@ string_match (pam_handle_t *pamh, const char *tok, const char *string,
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun /* network_netmask_match - match a string against one token
59*4882a593Smuzhiyun  * where string is a hostname or ip (v4,v6) address and tok
60*4882a593Smuzhiyun- * represents either a single ip (v4,v6) address or a network/netmask
61*4882a593Smuzhiyun+ * represents either a hostname, a single ip (v4,v6) address
62*4882a593Smuzhiyun+ * or a network/netmask
63*4882a593Smuzhiyun  */
64*4882a593Smuzhiyun static int
65*4882a593Smuzhiyun network_netmask_match (pam_handle_t *pamh,
66*4882a593Smuzhiyun@@ -723,10 +724,12 @@ network_netmask_match (pam_handle_t *pamh,
67*4882a593Smuzhiyun     char *netmask_ptr;
68*4882a593Smuzhiyun     char netmask_string[MAXHOSTNAMELEN + 1];
69*4882a593Smuzhiyun     int addr_type;
70*4882a593Smuzhiyun+    struct addrinfo *ai = NULL;
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun     if (item->debug)
73*4882a593Smuzhiyun-    pam_syslog (pamh, LOG_DEBUG,
74*4882a593Smuzhiyun+      pam_syslog (pamh, LOG_DEBUG,
75*4882a593Smuzhiyun 		"network_netmask_match: tok=%s, item=%s", tok, string);
76*4882a593Smuzhiyun+
77*4882a593Smuzhiyun     /* OK, check if tok is of type addr/mask */
78*4882a593Smuzhiyun     if ((netmask_ptr = strchr(tok, '/')) != NULL)
79*4882a593Smuzhiyun       {
80*4882a593Smuzhiyun@@ -760,54 +763,108 @@ network_netmask_match (pam_handle_t *pamh,
81*4882a593Smuzhiyun 	    netmask_ptr = number_to_netmask(netmask, addr_type,
82*4882a593Smuzhiyun 		netmask_string, MAXHOSTNAMELEN);
83*4882a593Smuzhiyun 	  }
84*4882a593Smuzhiyun-	}
85*4882a593Smuzhiyun+
86*4882a593Smuzhiyun+        /*
87*4882a593Smuzhiyun+         * Construct an addrinfo list from the IP address.
88*4882a593Smuzhiyun+         * This should not fail as the input is a correct IP address...
89*4882a593Smuzhiyun+         */
90*4882a593Smuzhiyun+	if (getaddrinfo (tok, NULL, NULL, &ai) != 0)
91*4882a593Smuzhiyun+	  {
92*4882a593Smuzhiyun+	    return NO;
93*4882a593Smuzhiyun+	  }
94*4882a593Smuzhiyun+      }
95*4882a593Smuzhiyun     else
96*4882a593Smuzhiyun-	/* NO, then check if it is only an addr */
97*4882a593Smuzhiyun-	if (isipaddr(tok, NULL, NULL) != YES)
98*4882a593Smuzhiyun+      {
99*4882a593Smuzhiyun+        /*
100*4882a593Smuzhiyun+	 * It is either an IP address or a hostname.
101*4882a593Smuzhiyun+	 * Let getaddrinfo sort everything out
102*4882a593Smuzhiyun+	 */
103*4882a593Smuzhiyun+	if (getaddrinfo (tok, NULL, NULL, &ai) != 0)
104*4882a593Smuzhiyun 	  {
105*4882a593Smuzhiyun+	    pam_syslog(pamh, LOG_ERR, "cannot resolve hostname \"%s\"", tok);
106*4882a593Smuzhiyun+
107*4882a593Smuzhiyun 	    return NO;
108*4882a593Smuzhiyun 	  }
109*4882a593Smuzhiyun+	netmask_ptr = NULL;
110*4882a593Smuzhiyun+      }
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun     if (isipaddr(string, NULL, NULL) != YES)
113*4882a593Smuzhiyun       {
114*4882a593Smuzhiyun-	/* Assume network/netmask with a name of a host.  */
115*4882a593Smuzhiyun 	struct addrinfo hint;
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun+	/* Assume network/netmask with a name of a host.  */
118*4882a593Smuzhiyun 	memset (&hint, '\0', sizeof (hint));
119*4882a593Smuzhiyun 	hint.ai_flags = AI_CANONNAME;
120*4882a593Smuzhiyun 	hint.ai_family = AF_UNSPEC;
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun 	if (item->gai_rv != 0)
123*4882a593Smuzhiyun+	  {
124*4882a593Smuzhiyun+	    freeaddrinfo(ai);
125*4882a593Smuzhiyun 	    return NO;
126*4882a593Smuzhiyun+	  }
127*4882a593Smuzhiyun 	else if (!item->res &&
128*4882a593Smuzhiyun 		(item->gai_rv = getaddrinfo (string, NULL, &hint, &item->res)) != 0)
129*4882a593Smuzhiyun+	  {
130*4882a593Smuzhiyun+	    freeaddrinfo(ai);
131*4882a593Smuzhiyun 	    return NO;
132*4882a593Smuzhiyun+	  }
133*4882a593Smuzhiyun         else
134*4882a593Smuzhiyun 	  {
135*4882a593Smuzhiyun 	    struct addrinfo *runp = item->res;
136*4882a593Smuzhiyun+	    struct addrinfo *runp1;
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun 	    while (runp != NULL)
139*4882a593Smuzhiyun 	      {
140*4882a593Smuzhiyun 		char buf[INET6_ADDRSTRLEN];
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun-		DIAG_PUSH_IGNORE_CAST_ALIGN;
143*4882a593Smuzhiyun-		inet_ntop (runp->ai_family,
144*4882a593Smuzhiyun-			runp->ai_family == AF_INET
145*4882a593Smuzhiyun-			? (void *) &((struct sockaddr_in *) runp->ai_addr)->sin_addr
146*4882a593Smuzhiyun-			: (void *) &((struct sockaddr_in6 *) runp->ai_addr)->sin6_addr,
147*4882a593Smuzhiyun-			buf, sizeof (buf));
148*4882a593Smuzhiyun-		DIAG_POP_IGNORE_CAST_ALIGN;
149*4882a593Smuzhiyun+		if (getnameinfo (runp->ai_addr, runp->ai_addrlen, buf, sizeof (buf), NULL, 0, NI_NUMERICHOST) != 0)
150*4882a593Smuzhiyun+		  {
151*4882a593Smuzhiyun+		    freeaddrinfo(ai);
152*4882a593Smuzhiyun+		    return NO;
153*4882a593Smuzhiyun+		  }
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun-		if (are_addresses_equal(buf, tok, netmask_ptr))
156*4882a593Smuzhiyun+		for (runp1 = ai; runp1 != NULL; runp1 = runp1->ai_next)
157*4882a593Smuzhiyun 		  {
158*4882a593Smuzhiyun-		    return YES;
159*4882a593Smuzhiyun+                    char buf1[INET6_ADDRSTRLEN];
160*4882a593Smuzhiyun+
161*4882a593Smuzhiyun+                    if (runp->ai_family != runp1->ai_family)
162*4882a593Smuzhiyun+                      continue;
163*4882a593Smuzhiyun+
164*4882a593Smuzhiyun+                    if (getnameinfo (runp1->ai_addr, runp1->ai_addrlen, buf1, sizeof (buf1), NULL, 0, NI_NUMERICHOST) != 0)
165*4882a593Smuzhiyun+		      {
166*4882a593Smuzhiyun+			freeaddrinfo(ai);
167*4882a593Smuzhiyun+			return NO;
168*4882a593Smuzhiyun+		      }
169*4882a593Smuzhiyun+
170*4882a593Smuzhiyun+                    if (are_addresses_equal (buf, buf1, netmask_ptr))
171*4882a593Smuzhiyun+                      {
172*4882a593Smuzhiyun+                        freeaddrinfo(ai);
173*4882a593Smuzhiyun+                        return YES;
174*4882a593Smuzhiyun+                      }
175*4882a593Smuzhiyun 		  }
176*4882a593Smuzhiyun 		runp = runp->ai_next;
177*4882a593Smuzhiyun 	      }
178*4882a593Smuzhiyun 	  }
179*4882a593Smuzhiyun       }
180*4882a593Smuzhiyun     else
181*4882a593Smuzhiyun-      return (are_addresses_equal(string, tok, netmask_ptr));
182*4882a593Smuzhiyun+      {
183*4882a593Smuzhiyun+       struct addrinfo *runp1;
184*4882a593Smuzhiyun+
185*4882a593Smuzhiyun+       for (runp1 = ai; runp1 != NULL; runp1 = runp1->ai_next)
186*4882a593Smuzhiyun+         {
187*4882a593Smuzhiyun+           char buf1[INET6_ADDRSTRLEN];
188*4882a593Smuzhiyun+
189*4882a593Smuzhiyun+           (void) getnameinfo (runp1->ai_addr, runp1->ai_addrlen, buf1, sizeof (buf1), NULL, 0, NI_NUMERICHOST);
190*4882a593Smuzhiyun+
191*4882a593Smuzhiyun+           if (are_addresses_equal(string, buf1, netmask_ptr))
192*4882a593Smuzhiyun+             {
193*4882a593Smuzhiyun+               freeaddrinfo(ai);
194*4882a593Smuzhiyun+               return YES;
195*4882a593Smuzhiyun+             }
196*4882a593Smuzhiyun+         }
197*4882a593Smuzhiyun+      }
198*4882a593Smuzhiyun+
199*4882a593Smuzhiyun+  freeaddrinfo(ai);
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun   return NO;
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun--
204*4882a593Smuzhiyun2.37.3
205*4882a593Smuzhiyun
206