diff options
author | Polampalli, Archana <archana.polampalli@windriver.com> | 2022-10-28 16:30:22 +0000 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2022-11-23 18:27:07 +0000 |
commit | b5596124ee7b2e0685f010de9659ed3c76f5d2b4 (patch) | |
tree | 0d38a3e6fe9560e7a5369130cb5006899157f2ba /meta | |
parent | 61fac62194b3c7e1c31a9119390f4f960077dea4 (diff) | |
download | poky-b5596124ee7b2e0685f010de9659ed3c76f5d2b4.tar.gz |
libpam: fix CVE-2022-28321
The Linux-PAM package before 1.5.2-6.1 for openSUSE Tumbleweed allows
authentication bypass for SSH logins. The pam_access.so module doesn't
correctly restrict login if a user tries to connect from an IP address
that is not resolvable via DNS. In such conditions, a user with denied
access to a machine can still get access. NOTE: the relevance of this
issue is largely limited to openSUSE Tumbleweed and openSUSE Factory;
it does not affect Linux-PAM upstream.
References:
https://nvd.nist.gov/vuln/detail/CVE-2022-28321
Upstream patches:
https://github.com/linux-pam/linux-pam/commit/08992030c56c940c0707ccbc442b1c325aa01e6d
https://github.com/linux-pam/linux-pam/commit/23393bef92c1e768eda329813d7af55481c6ca9f
(From OE-Core rev: b1fd799af0086347de1ec4b72d562b1fb490def1)
Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com>
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta')
-rw-r--r-- | meta/recipes-extended/pam/libpam/CVE-2022-28321-0002.patch | 205 | ||||
-rw-r--r-- | meta/recipes-extended/pam/libpam_1.5.2.bb | 1 |
2 files changed, 206 insertions, 0 deletions
diff --git a/meta/recipes-extended/pam/libpam/CVE-2022-28321-0002.patch b/meta/recipes-extended/pam/libpam/CVE-2022-28321-0002.patch new file mode 100644 index 0000000000..e7bf03f9f7 --- /dev/null +++ b/meta/recipes-extended/pam/libpam/CVE-2022-28321-0002.patch | |||
@@ -0,0 +1,205 @@ | |||
1 | From 23393bef92c1e768eda329813d7af55481c6ca9f Mon Sep 17 00:00:00 2001 | ||
2 | From: Thorsten Kukuk <kukuk@suse.com> | ||
3 | Date: Thu, 24 Feb 2022 10:37:32 +0100 | ||
4 | Subject: [PATCH 2/2] pam_access: handle hostnames in access.conf | ||
5 | |||
6 | According to the manual page, the following entry is valid but does not | ||
7 | work: | ||
8 | -:root:ALL EXCEPT localhost | ||
9 | |||
10 | See https://bugzilla.suse.com/show_bug.cgi?id=1019866 | ||
11 | |||
12 | Patched is based on PR#226 from Josef Moellers | ||
13 | |||
14 | Upstream-Status: Backport | ||
15 | CVE: CVE-2022-28321 | ||
16 | |||
17 | Reference to upstream patch: | ||
18 | [https://github.com/linux-pam/linux-pam/commit/23393bef92c1e768eda329813d7af55481c6ca9f] | ||
19 | |||
20 | Signed-off-by: Stefan Ghinea <stefan.ghinea@windriver.com> | ||
21 | --- | ||
22 | modules/pam_access/pam_access.c | 95 ++++++++++++++++++++++++++------- | ||
23 | 1 file changed, 76 insertions(+), 19 deletions(-) | ||
24 | |||
25 | diff --git a/modules/pam_access/pam_access.c b/modules/pam_access/pam_access.c | ||
26 | index 277192b..bca424f 100644 | ||
27 | --- a/modules/pam_access/pam_access.c | ||
28 | +++ b/modules/pam_access/pam_access.c | ||
29 | @@ -637,7 +637,7 @@ remote_match (pam_handle_t *pamh, char *tok, struct login_info *item) | ||
30 | if ((str_len = strlen(string)) > tok_len | ||
31 | && strcasecmp(tok, string + str_len - tok_len) == 0) | ||
32 | return YES; | ||
33 | - } else if (tok[tok_len - 1] == '.') { | ||
34 | + } else if (tok[tok_len - 1] == '.') { /* internet network numbers (end with ".") */ | ||
35 | struct addrinfo hint; | ||
36 | |||
37 | memset (&hint, '\0', sizeof (hint)); | ||
38 | @@ -678,7 +678,7 @@ remote_match (pam_handle_t *pamh, char *tok, struct login_info *item) | ||
39 | return NO; | ||
40 | } | ||
41 | |||
42 | - /* Assume network/netmask with an IP of a host. */ | ||
43 | + /* Assume network/netmask, IP address or hostname. */ | ||
44 | return network_netmask_match(pamh, tok, string, item); | ||
45 | } | ||
46 | |||
47 | @@ -696,7 +696,7 @@ string_match (pam_handle_t *pamh, const char *tok, const char *string, | ||
48 | /* | ||
49 | * If the token has the magic value "ALL" the match always succeeds. | ||
50 | * Otherwise, return YES if the token fully matches the string. | ||
51 | - * "NONE" token matches NULL string. | ||
52 | + * "NONE" token matches NULL string. | ||
53 | */ | ||
54 | |||
55 | if (strcasecmp(tok, "ALL") == 0) { /* all: always matches */ | ||
56 | @@ -714,7 +714,8 @@ string_match (pam_handle_t *pamh, const char *tok, const char *string, | ||
57 | |||
58 | /* network_netmask_match - match a string against one token | ||
59 | * where string is a hostname or ip (v4,v6) address and tok | ||
60 | - * represents either a single ip (v4,v6) address or a network/netmask | ||
61 | + * represents either a hostname, a single ip (v4,v6) address | ||
62 | + * or a network/netmask | ||
63 | */ | ||
64 | static int | ||
65 | network_netmask_match (pam_handle_t *pamh, | ||
66 | @@ -723,10 +724,12 @@ network_netmask_match (pam_handle_t *pamh, | ||
67 | char *netmask_ptr; | ||
68 | char netmask_string[MAXHOSTNAMELEN + 1]; | ||
69 | int addr_type; | ||
70 | + struct addrinfo *ai = NULL; | ||
71 | |||
72 | if (item->debug) | ||
73 | - pam_syslog (pamh, LOG_DEBUG, | ||
74 | + pam_syslog (pamh, LOG_DEBUG, | ||
75 | "network_netmask_match: tok=%s, item=%s", tok, string); | ||
76 | + | ||
77 | /* OK, check if tok is of type addr/mask */ | ||
78 | if ((netmask_ptr = strchr(tok, '/')) != NULL) | ||
79 | { | ||
80 | @@ -760,54 +763,108 @@ network_netmask_match (pam_handle_t *pamh, | ||
81 | netmask_ptr = number_to_netmask(netmask, addr_type, | ||
82 | netmask_string, MAXHOSTNAMELEN); | ||
83 | } | ||
84 | - } | ||
85 | + | ||
86 | + /* | ||
87 | + * Construct an addrinfo list from the IP address. | ||
88 | + * This should not fail as the input is a correct IP address... | ||
89 | + */ | ||
90 | + if (getaddrinfo (tok, NULL, NULL, &ai) != 0) | ||
91 | + { | ||
92 | + return NO; | ||
93 | + } | ||
94 | + } | ||
95 | else | ||
96 | - /* NO, then check if it is only an addr */ | ||
97 | - if (isipaddr(tok, NULL, NULL) != YES) | ||
98 | + { | ||
99 | + /* | ||
100 | + * It is either an IP address or a hostname. | ||
101 | + * Let getaddrinfo sort everything out | ||
102 | + */ | ||
103 | + if (getaddrinfo (tok, NULL, NULL, &ai) != 0) | ||
104 | { | ||
105 | + pam_syslog(pamh, LOG_ERR, "cannot resolve hostname \"%s\"", tok); | ||
106 | + | ||
107 | return NO; | ||
108 | } | ||
109 | + netmask_ptr = NULL; | ||
110 | + } | ||
111 | |||
112 | if (isipaddr(string, NULL, NULL) != YES) | ||
113 | { | ||
114 | - /* Assume network/netmask with a name of a host. */ | ||
115 | struct addrinfo hint; | ||
116 | |||
117 | + /* Assume network/netmask with a name of a host. */ | ||
118 | memset (&hint, '\0', sizeof (hint)); | ||
119 | hint.ai_flags = AI_CANONNAME; | ||
120 | hint.ai_family = AF_UNSPEC; | ||
121 | |||
122 | if (item->gai_rv != 0) | ||
123 | + { | ||
124 | + freeaddrinfo(ai); | ||
125 | return NO; | ||
126 | + } | ||
127 | else if (!item->res && | ||
128 | (item->gai_rv = getaddrinfo (string, NULL, &hint, &item->res)) != 0) | ||
129 | + { | ||
130 | + freeaddrinfo(ai); | ||
131 | return NO; | ||
132 | + } | ||
133 | else | ||
134 | { | ||
135 | struct addrinfo *runp = item->res; | ||
136 | + struct addrinfo *runp1; | ||
137 | |||
138 | while (runp != NULL) | ||
139 | { | ||
140 | char buf[INET6_ADDRSTRLEN]; | ||
141 | |||
142 | - DIAG_PUSH_IGNORE_CAST_ALIGN; | ||
143 | - inet_ntop (runp->ai_family, | ||
144 | - runp->ai_family == AF_INET | ||
145 | - ? (void *) &((struct sockaddr_in *) runp->ai_addr)->sin_addr | ||
146 | - : (void *) &((struct sockaddr_in6 *) runp->ai_addr)->sin6_addr, | ||
147 | - buf, sizeof (buf)); | ||
148 | - DIAG_POP_IGNORE_CAST_ALIGN; | ||
149 | + if (getnameinfo (runp->ai_addr, runp->ai_addrlen, buf, sizeof (buf), NULL, 0, NI_NUMERICHOST) != 0) | ||
150 | + { | ||
151 | + freeaddrinfo(ai); | ||
152 | + return NO; | ||
153 | + } | ||
154 | |||
155 | - if (are_addresses_equal(buf, tok, netmask_ptr)) | ||
156 | + for (runp1 = ai; runp1 != NULL; runp1 = runp1->ai_next) | ||
157 | { | ||
158 | - return YES; | ||
159 | + char buf1[INET6_ADDRSTRLEN]; | ||
160 | + | ||
161 | + if (runp->ai_family != runp1->ai_family) | ||
162 | + continue; | ||
163 | + | ||
164 | + if (getnameinfo (runp1->ai_addr, runp1->ai_addrlen, buf1, sizeof (buf1), NULL, 0, NI_NUMERICHOST) != 0) | ||
165 | + { | ||
166 | + freeaddrinfo(ai); | ||
167 | + return NO; | ||
168 | + } | ||
169 | + | ||
170 | + if (are_addresses_equal (buf, buf1, netmask_ptr)) | ||
171 | + { | ||
172 | + freeaddrinfo(ai); | ||
173 | + return YES; | ||
174 | + } | ||
175 | } | ||
176 | runp = runp->ai_next; | ||
177 | } | ||
178 | } | ||
179 | } | ||
180 | else | ||
181 | - return (are_addresses_equal(string, tok, netmask_ptr)); | ||
182 | + { | ||
183 | + struct addrinfo *runp1; | ||
184 | + | ||
185 | + for (runp1 = ai; runp1 != NULL; runp1 = runp1->ai_next) | ||
186 | + { | ||
187 | + char buf1[INET6_ADDRSTRLEN]; | ||
188 | + | ||
189 | + (void) getnameinfo (runp1->ai_addr, runp1->ai_addrlen, buf1, sizeof (buf1), NULL, 0, NI_NUMERICHOST); | ||
190 | + | ||
191 | + if (are_addresses_equal(string, buf1, netmask_ptr)) | ||
192 | + { | ||
193 | + freeaddrinfo(ai); | ||
194 | + return YES; | ||
195 | + } | ||
196 | + } | ||
197 | + } | ||
198 | + | ||
199 | + freeaddrinfo(ai); | ||
200 | |||
201 | return NO; | ||
202 | } | ||
203 | -- | ||
204 | 2.37.3 | ||
205 | |||
diff --git a/meta/recipes-extended/pam/libpam_1.5.2.bb b/meta/recipes-extended/pam/libpam_1.5.2.bb index bde7fef8a2..3be879082e 100644 --- a/meta/recipes-extended/pam/libpam_1.5.2.bb +++ b/meta/recipes-extended/pam/libpam_1.5.2.bb | |||
@@ -24,6 +24,7 @@ SRC_URI = "${GITHUB_BASE_URI}/download/v${PV}/Linux-PAM-${PV}.tar.xz \ | |||
24 | file://0001-run-xtests.sh-check-whether-files-exist.patch \ | 24 | file://0001-run-xtests.sh-check-whether-files-exist.patch \ |
25 | file://run-ptest \ | 25 | file://run-ptest \ |
26 | file://pam-volatiles.conf \ | 26 | file://pam-volatiles.conf \ |
27 | file://CVE-2022-28321-0002.patch \ | ||
27 | " | 28 | " |
28 | 29 | ||
29 | SRC_URI[sha256sum] = "e4ec7131a91da44512574268f493c6d8ca105c87091691b8e9b56ca685d4f94d" | 30 | SRC_URI[sha256sum] = "e4ec7131a91da44512574268f493c6d8ca105c87091691b8e9b56ca685d4f94d" |