Bug Summary

File:src/usr.sbin/ldpd/pfkey.c
Warning:line 296, column 25
The left operand of '!=' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name pfkey.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/ldpd/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/ldpd -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/ldpd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.sbin/ldpd/pfkey.c
1/* $OpenBSD: pfkey.c,v 1.12 2019/01/23 02:02:04 dlg Exp $ */
2
3/*
4 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5 * Copyright (c) 2003, 2004 Markus Friedl <markus@openbsd.org>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include <sys/types.h>
21#include <errno(*__errno()).h>
22#include <stdlib.h>
23#include <string.h>
24#include <unistd.h>
25
26#include "ldpd.h"
27#include "ldpe.h"
28#include "log.h"
29
30static int pfkey_send(int, uint8_t, uint8_t, uint8_t,
31 int, union ldpd_addr *, union ldpd_addr *,
32 uint32_t, uint8_t, int, char *, uint8_t, int, char *,
33 uint16_t, uint16_t);
34static int pfkey_reply(int, uint32_t *);
35static int pfkey_sa_add(int, union ldpd_addr *, union ldpd_addr *,
36 uint8_t, char *, uint32_t *);
37static int pfkey_sa_remove(int, union ldpd_addr *, union ldpd_addr *,
38 uint32_t *);
39static int pfkey_md5sig_establish(struct nbr *, struct ldp_auth *);
40static int pfkey_md5sig_remove(struct nbr *);
41
42#define PFKEY2_CHUNKsizeof(uint64_t) sizeof(uint64_t)
43#define ROUNDUP(x)(((x) + (sizeof(uint64_t) - 1)) & ~(sizeof(uint64_t) - 1)
)
(((x) + (PFKEY2_CHUNKsizeof(uint64_t) - 1)) & ~(PFKEY2_CHUNKsizeof(uint64_t) - 1))
44#define IOV_CNT20 20
45
46static uint32_t sadb_msg_seq;
47static uint32_t pid; /* should pid_t but pfkey needs uint32_t */
48static int fd;
49
50static int
51pfkey_send(int sd, uint8_t satype, uint8_t mtype, uint8_t dir,
52 int af, union ldpd_addr *src, union ldpd_addr *dst, uint32_t spi,
53 uint8_t aalg, int alen, char *akey, uint8_t ealg, int elen, char *ekey,
54 uint16_t sport, uint16_t dport)
55{
56 struct sadb_msg smsg;
57 struct sadb_sa sa;
58 struct sadb_address sa_src, sa_dst;
59 struct sadb_key sa_akey, sa_ekey;
60 struct sadb_spirange sa_spirange;
61 struct iovec iov[IOV_CNT20];
62 ssize_t n;
63 int len = 0;
64 int iov_cnt;
65 struct sockaddr_storage ssrc, sdst, smask, dmask;
66 struct sockaddr *saptr;
67
68 if (!pid)
69 pid = getpid();
70
71 /* we need clean sockaddr... no ports set */
72 memset(&ssrc, 0, sizeof(ssrc));
73 memset(&smask, 0, sizeof(smask));
74 if ((saptr = addr2sa(af, src, 0)))
75 memcpy(&ssrc, saptr, sizeof(ssrc));
76 switch (af) {
77 case AF_INET2:
78 memset(&((struct sockaddr_in *)&smask)->sin_addr, 0xff, 32/8);
79 break;
80 case AF_INET624:
81 memset(&((struct sockaddr_in6 *)&smask)->sin6_addr, 0xff,
82 128/8);
83 break;
84 default:
85 return (-1);
86 }
87 smask.ss_family = ssrc.ss_family;
88 smask.ss_len = ssrc.ss_len;
89
90 memset(&sdst, 0, sizeof(sdst));
91 memset(&dmask, 0, sizeof(dmask));
92 if ((saptr = addr2sa(af, dst, 0)))
93 memcpy(&sdst, saptr, sizeof(sdst));
94 switch (af) {
95 case AF_INET2:
96 memset(&((struct sockaddr_in *)&dmask)->sin_addr, 0xff, 32/8);
97 break;
98 case AF_INET624:
99 memset(&((struct sockaddr_in6 *)&dmask)->sin6_addr, 0xff,
100 128/8);
101 break;
102 default:
103 return (-1);
104 }
105 dmask.ss_family = sdst.ss_family;
106 dmask.ss_len = sdst.ss_len;
107
108 memset(&smsg, 0, sizeof(smsg));
109 smsg.sadb_msg_version = PF_KEY_V22;
110 smsg.sadb_msg_seq = ++sadb_msg_seq;
111 smsg.sadb_msg_pid = pid;
112 smsg.sadb_msg_len = sizeof(smsg) / 8;
113 smsg.sadb_msg_type = mtype;
114 smsg.sadb_msg_satype = satype;
115
116 switch (mtype) {
117 case SADB_GETSPI1:
118 memset(&sa_spirange, 0, sizeof(sa_spirange));
119 sa_spirange.sadb_spirange_exttype = SADB_EXT_SPIRANGE16;
120 sa_spirange.sadb_spirange_len = sizeof(sa_spirange) / 8;
121 sa_spirange.sadb_spirange_min = 0x100;
122 sa_spirange.sadb_spirange_max = 0xffffffff;
123 sa_spirange.sadb_spirange_reserved = 0;
124 break;
125 case SADB_ADD3:
126 case SADB_UPDATE2:
127 case SADB_DELETE4:
128 memset(&sa, 0, sizeof(sa));
129 sa.sadb_sa_exttype = SADB_EXT_SA1;
130 sa.sadb_sa_len = sizeof(sa) / 8;
131 sa.sadb_sa_replay = 0;
132 sa.sadb_sa_spi = spi;
133 sa.sadb_sa_state = SADB_SASTATE_MATURE1;
134 break;
135 }
136
137 memset(&sa_src, 0, sizeof(sa_src));
138 sa_src.sadb_address_exttype = SADB_EXT_ADDRESS_SRC5;
139 sa_src.sadb_address_len = (sizeof(sa_src) + ROUNDUP(ssrc.ss_len)(((ssrc.ss_len) + (sizeof(uint64_t) - 1)) & ~(sizeof(uint64_t
) - 1))
) / 8;
140
141 memset(&sa_dst, 0, sizeof(sa_dst));
142 sa_dst.sadb_address_exttype = SADB_EXT_ADDRESS_DST6;
143 sa_dst.sadb_address_len = (sizeof(sa_dst) + ROUNDUP(sdst.ss_len)(((sdst.ss_len) + (sizeof(uint64_t) - 1)) & ~(sizeof(uint64_t
) - 1))
) / 8;
144
145 sa.sadb_sa_auth = aalg;
146 sa.sadb_sa_encrypt = SADB_X_EALG_AES12; /* XXX */
147
148 switch (mtype) {
149 case SADB_ADD3:
150 case SADB_UPDATE2:
151 memset(&sa_akey, 0, sizeof(sa_akey));
152 sa_akey.sadb_key_exttype = SADB_EXT_KEY_AUTH8;
153 sa_akey.sadb_key_len = (sizeof(sa_akey) +
154 ((alen + 7) / 8) * 8) / 8;
155 sa_akey.sadb_key_bits = 8 * alen;
156
157 memset(&sa_ekey, 0, sizeof(sa_ekey));
158 sa_ekey.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT9;
159 sa_ekey.sadb_key_len = (sizeof(sa_ekey) +
160 ((elen + 7) / 8) * 8) / 8;
161 sa_ekey.sadb_key_bits = 8 * elen;
162
163 break;
164 }
165
166 iov_cnt = 0;
167
168 /* msghdr */
169 iov[iov_cnt].iov_base = &smsg;
170 iov[iov_cnt].iov_len = sizeof(smsg);
171 iov_cnt++;
172
173 switch (mtype) {
174 case SADB_ADD3:
175 case SADB_UPDATE2:
176 case SADB_DELETE4:
177 /* SA hdr */
178 iov[iov_cnt].iov_base = &sa;
179 iov[iov_cnt].iov_len = sizeof(sa);
180 smsg.sadb_msg_len += sa.sadb_sa_len;
181 iov_cnt++;
182 break;
183 case SADB_GETSPI1:
184 /* SPI range */
185 iov[iov_cnt].iov_base = &sa_spirange;
186 iov[iov_cnt].iov_len = sizeof(sa_spirange);
187 smsg.sadb_msg_len += sa_spirange.sadb_spirange_len;
188 iov_cnt++;
189 break;
190 }
191
192 /* dest addr */
193 iov[iov_cnt].iov_base = &sa_dst;
194 iov[iov_cnt].iov_len = sizeof(sa_dst);
195 iov_cnt++;
196 iov[iov_cnt].iov_base = &sdst;
197 iov[iov_cnt].iov_len = ROUNDUP(sdst.ss_len)(((sdst.ss_len) + (sizeof(uint64_t) - 1)) & ~(sizeof(uint64_t
) - 1))
;
198 smsg.sadb_msg_len += sa_dst.sadb_address_len;
199 iov_cnt++;
200
201 /* src addr */
202 iov[iov_cnt].iov_base = &sa_src;
203 iov[iov_cnt].iov_len = sizeof(sa_src);
204 iov_cnt++;
205 iov[iov_cnt].iov_base = &ssrc;
206 iov[iov_cnt].iov_len = ROUNDUP(ssrc.ss_len)(((ssrc.ss_len) + (sizeof(uint64_t) - 1)) & ~(sizeof(uint64_t
) - 1))
;
207 smsg.sadb_msg_len += sa_src.sadb_address_len;
208 iov_cnt++;
209
210 switch (mtype) {
211 case SADB_ADD3:
212 case SADB_UPDATE2:
213 if (alen) {
214 /* auth key */
215 iov[iov_cnt].iov_base = &sa_akey;
216 iov[iov_cnt].iov_len = sizeof(sa_akey);
217 iov_cnt++;
218 iov[iov_cnt].iov_base = akey;
219 iov[iov_cnt].iov_len = ((alen + 7) / 8) * 8;
220 smsg.sadb_msg_len += sa_akey.sadb_key_len;
221 iov_cnt++;
222 }
223 if (elen) {
224 /* encryption key */
225 iov[iov_cnt].iov_base = &sa_ekey;
226 iov[iov_cnt].iov_len = sizeof(sa_ekey);
227 iov_cnt++;
228 iov[iov_cnt].iov_base = ekey;
229 iov[iov_cnt].iov_len = ((elen + 7) / 8) * 8;
230 smsg.sadb_msg_len += sa_ekey.sadb_key_len;
231 iov_cnt++;
232 }
233 break;
234 }
235
236 len = smsg.sadb_msg_len * 8;
237 do {
238 n = writev(sd, iov, iov_cnt);
239 } while (n == -1 && (errno(*__errno()) == EAGAIN35 || errno(*__errno()) == EINTR4));
240
241 if (n == -1) {
242 log_warn("writev (%d/%d)", iov_cnt, len);
243 return (-1);
244 }
245
246 return (0);
247}
248
249int
250pfkey_read(int sd, struct sadb_msg *h)
251{
252 struct sadb_msg hdr;
253
254 if (recv(sd, &hdr, sizeof(hdr), MSG_PEEK0x2) != sizeof(hdr)) {
8
Assuming the condition is true
9
Taking true branch
255 if (errno(*__errno()) == EAGAIN35 || errno(*__errno()) == EINTR4)
10
Assuming the condition is true
256 return (0);
11
Returning without writing to 'h->sadb_msg_errno'
12
Returning zero, which participates in a condition later
257 log_warn("pfkey peek");
258 return (-1);
259 }
260
261 /* XXX: Only one message can be outstanding. */
262 if (hdr.sadb_msg_seq == sadb_msg_seq &&
263 hdr.sadb_msg_pid == pid) {
264 if (h)
265 *h = hdr;
266 return (0);
267 }
268
269 /* not ours, discard */
270 if (read(sd, &hdr, sizeof(hdr)) == -1) {
271 if (errno(*__errno()) == EAGAIN35 || errno(*__errno()) == EINTR4)
272 return (0);
273 log_warn("pfkey read");
274 return (-1);
275 }
276
277 return (1);
278}
279
280static int
281pfkey_reply(int sd, uint32_t *spip)
282{
283 struct sadb_msg hdr, *msg;
284 struct sadb_ext *ext;
285 struct sadb_sa *sa;
286 uint8_t *data;
287 ssize_t len;
288 int rv;
289
290 do {
15
Loop condition is false. Exiting loop
291 rv = pfkey_read(sd, &hdr);
7
Calling 'pfkey_read'
13
Returning from 'pfkey_read'
292 if (rv == -1)
14
Taking false branch
293 return (-1);
294 } while (rv);
295
296 if (hdr.sadb_msg_errno != 0) {
16
The left operand of '!=' is a garbage value
297 errno(*__errno()) = hdr.sadb_msg_errno;
298 if (errno(*__errno()) == ESRCH3)
299 return (0);
300 else {
301 log_warn("pfkey");
302 return (-1);
303 }
304 }
305 if ((data = reallocarray(NULL((void *)0), hdr.sadb_msg_len, PFKEY2_CHUNKsizeof(uint64_t))) == NULL((void *)0)) {
306 log_warn("pfkey malloc");
307 return (-1);
308 }
309 len = hdr.sadb_msg_len * PFKEY2_CHUNKsizeof(uint64_t);
310 if (read(sd, data, len) != len) {
311 log_warn("pfkey read");
312 freezero(data, len);
313 return (-1);
314 }
315
316 if (hdr.sadb_msg_type == SADB_GETSPI1) {
317 if (spip == NULL((void *)0)) {
318 freezero(data, len);
319 return (0);
320 }
321
322 msg = (struct sadb_msg *)data;
323 for (ext = (struct sadb_ext *)(msg + 1);
324 (size_t)((uint8_t *)ext - (uint8_t *)msg) <
325 msg->sadb_msg_len * PFKEY2_CHUNKsizeof(uint64_t);
326 ext = (struct sadb_ext *)((uint8_t *)ext +
327 ext->sadb_ext_len * PFKEY2_CHUNKsizeof(uint64_t))) {
328 if (ext->sadb_ext_type == SADB_EXT_SA1) {
329 sa = (struct sadb_sa *) ext;
330 *spip = sa->sadb_sa_spi;
331 break;
332 }
333 }
334 }
335 freezero(data, len);
336 return (0);
337}
338
339static int
340pfkey_sa_add(int af, union ldpd_addr *src, union ldpd_addr *dst, uint8_t keylen,
341 char *key, uint32_t *spi)
342{
343 if (pfkey_send(fd, SADB_X_SATYPE_TCPSIGNATURE8, SADB_GETSPI1, 0,
344 af, src, dst, 0, 0, 0, NULL((void *)0), 0, 0, NULL((void *)0), 0, 0) < 0)
345 return (-1);
346 if (pfkey_reply(fd, spi) < 0)
347 return (-1);
348 if (pfkey_send(fd, SADB_X_SATYPE_TCPSIGNATURE8, SADB_UPDATE2, 0,
349 af, src, dst, *spi, 0, keylen, key, 0, 0, NULL((void *)0), 0, 0) < 0)
350 return (-1);
351 if (pfkey_reply(fd, NULL((void *)0)) < 0)
352 return (-1);
353 return (0);
354}
355
356static int
357pfkey_sa_remove(int af, union ldpd_addr *src, union ldpd_addr *dst,
358 uint32_t *spi)
359{
360 if (pfkey_send(fd, SADB_X_SATYPE_TCPSIGNATURE8, SADB_DELETE4, 0,
5
Taking false branch
361 af, src, dst, *spi, 0, 0, NULL((void *)0), 0, 0, NULL((void *)0), 0, 0) < 0)
362 return (-1);
363 if (pfkey_reply(fd, NULL((void *)0)) < 0)
6
Calling 'pfkey_reply'
364 return (-1);
365 *spi = 0;
366 return (0);
367}
368
369static int
370pfkey_md5sig_establish(struct nbr *nbr, struct ldp_auth *auth)
371{
372 sleep(1);
373
374 pfkey_md5sig_remove(nbr);
375
376 if (pfkey_sa_add(nbr->af, &nbr->laddr, &nbr->raddr,
377 auth->md5key_len, auth->md5key, &nbr->auth_spi_out) == -1)
378 return (-1);
379
380 if (pfkey_sa_add(nbr->af, &nbr->raddr, &nbr->laddr,
381 auth->md5key_len, auth->md5key, &nbr->auth_spi_in) == -1)
382 return (-1);
383
384 nbr->auth_established = 1;
385
386 return (0);
387}
388
389static int
390pfkey_md5sig_remove(struct nbr *nbr)
391{
392 if (nbr->auth_spi_out) {
2
Assuming field 'auth_spi_out' is not equal to 0
3
Taking true branch
393 if (pfkey_sa_remove(nbr->af, &nbr->laddr, &nbr->raddr,
4
Calling 'pfkey_sa_remove'
394 &nbr->auth_spi_out) == -1)
395 return (-1);
396 }
397 if (nbr->auth_spi_in) {
398 if (pfkey_sa_remove(nbr->af, &nbr->raddr, &nbr->laddr,
399 &nbr->auth_spi_in) == -1)
400 return (-1);
401 }
402
403 nbr->auth_established = 0;
404 nbr->auth_spi_in = 0;
405 nbr->auth_spi_out = 0;
406
407 return (0);
408}
409
410static struct ldp_auth *
411pfkey_find_auth(struct ldpd_conf *conf, struct nbr *nbr)
412{
413 struct ldp_auth *auth, *match = NULL((void *)0);
414
415 LIST_FOREACH(auth, &conf->auth_list, entry)for((auth) = ((&conf->auth_list)->lh_first); (auth)
!= ((void *)0); (auth) = ((auth)->entry.le_next))
{
416 in_addr_t mask = prefixlen2mask(auth->idlen);
417 if ((auth->id.s_addr & mask) != (nbr->id.s_addr & mask))
418 continue;
419
420 if (match == NULL((void *)0) ||
421 match->idlen < auth->idlen)
422 match = auth;
423 }
424
425 return (match);
426}
427
428int
429pfkey_establish(struct ldpd_conf *conf, struct nbr *nbr)
430{
431 struct ldp_auth *auth = NULL((void *)0);
432
433 auth = pfkey_find_auth(conf, nbr);
434 if (auth == NULL((void *)0) || /* no policy */
435 auth->md5key_len == 0) /* "no tcpmd5 sig" */
436 return (0);
437
438 return (pfkey_md5sig_establish(nbr, auth));
439}
440
441int
442pfkey_remove(struct nbr *nbr)
443{
444 return (pfkey_md5sig_remove(nbr));
1
Calling 'pfkey_md5sig_remove'
445}
446
447int
448pfkey_init(void)
449{
450 if ((fd = socket(PF_KEY30, SOCK_RAW3 | SOCK_CLOEXEC0x8000 | SOCK_NONBLOCK0x4000,
451 PF_KEY_V22)) == -1) {
452 if (errno(*__errno()) == EPROTONOSUPPORT43) {
453 log_warnx("PF_KEY not available");
454 sysdep.no_pfkey = 1;
455 return (-1);
456 } else
457 fatal("pfkey setup failed");
458 }
459 return (fd);
460}