xref: /openbsd-src/sbin/iked/print.c (revision b8d799641995473596d7b40de33938a46b588b0e)
1 /*	$OpenBSD: print.c,v 1.6 2024/12/26 18:25:51 sthen Exp $	*/
2 
3 /*
4  * Copyright (c) 2019-2021 Tobias Heider <tobias.heider@stusta.de>
5  * Copyright (c) 2010-2013 Reyk Floeter <reyk@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 <sys/socket.h>
22 #include <sys/uio.h>
23 #include <net/if.h>
24 
25 #include <inttypes.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <event.h>
30 
31 #include "iked.h"
32 #include "ikev2.h"
33 #include "eap.h"
34 
35 const char *
36 print_xf(unsigned int id, unsigned int length, const struct ipsec_xf xfs[])
37 {
38 	int		i;
39 
40 	for (i = 0; xfs[i].name != NULL; i++) {
41 		if (xfs[i].id == id) {
42 			if (length == 0 || length == xfs[i].length)
43 				return (xfs[i].name);
44 		}
45 	}
46 	return ("unknown");
47 }
48 
49 void
50 print_user(struct iked_user *usr)
51 {
52 	print_verbose("user \"%s\" \"%s\"\n", usr->usr_name, usr->usr_pass);
53 }
54 
55 void
56 print_policy(struct iked_policy *pol)
57 {
58 	struct iked_proposal	*pp;
59 	struct iked_transform	*xform;
60 	struct iked_flow	*flow;
61 	struct iked_cfg		*cfg;
62 	unsigned int		 i, j;
63 	const struct ipsec_xf	*xfs = NULL;
64 	char			 iface[IF_NAMESIZE];
65 
66 	print_verbose("ikev2");
67 
68 	if (pol->pol_name[0] != '\0')
69 		print_verbose(" \"%s\"", pol->pol_name);
70 
71 	if (pol->pol_flags & IKED_POLICY_DEFAULT)
72 		print_verbose(" default");
73 	else if (pol->pol_flags & IKED_POLICY_QUICK)
74 		print_verbose(" quick");
75 	else if (pol->pol_flags & IKED_POLICY_SKIP)
76 		print_verbose(" skip");
77 
78 	if (pol->pol_flags & IKED_POLICY_ACTIVE)
79 		print_verbose(" active");
80 	else
81 		print_verbose(" passive");
82 
83 	if (pol->pol_flags & IKED_POLICY_IPCOMP)
84 		print_verbose(" ipcomp");
85 
86 	if (pol->pol_flags & IKED_POLICY_TRANSPORT)
87 		print_verbose(" transport");
88 	else
89 		print_verbose(" tunnel");
90 
91 	if (pol->pol_flags & IKED_POLICY_NATT_FORCE)
92 		print_verbose(" natt");
93 
94 	print_verbose(" %s", print_xf(pol->pol_saproto, 0, saxfs));
95 
96 	if (pol->pol_nipproto > 0) {
97 		print_verbose(" proto {");
98 		for (i = 0; i < pol->pol_nipproto; i++) {
99 			if (i == 0)
100 				print_verbose(" %s", print_proto(pol->pol_ipproto[i]));
101 			else
102 				print_verbose(", %s", print_proto(pol->pol_ipproto[i]));
103 		}
104 		print_verbose(" }");
105 	}
106 
107 	if (pol->pol_af) {
108 		if (pol->pol_af == AF_INET)
109 			print_verbose(" inet");
110 		else
111 			print_verbose(" inet6");
112 	}
113 
114 	if (pol->pol_rdomain >= 0)
115 		print_verbose(" rdomain %d", pol->pol_rdomain);
116 
117 	RB_FOREACH(flow, iked_flows, &pol->pol_flows) {
118 		print_verbose(" from %s", print_addr(&flow->flow_src.addr));
119 		if (flow->flow_src.addr_af != AF_UNSPEC &&
120 		    flow->flow_src.addr_net)
121 			print_verbose("/%d", flow->flow_src.addr_mask);
122 		if (flow->flow_src.addr_port)
123 			print_verbose(" port %d",
124 			    ntohs(flow->flow_src.addr_port));
125 
126 		print_verbose(" to %s", print_addr(&flow->flow_dst.addr));
127 		if (flow->flow_dst.addr_af != AF_UNSPEC &&
128 		    flow->flow_dst.addr_net)
129 			print_verbose("/%d", flow->flow_dst.addr_mask);
130 		if (flow->flow_dst.addr_port)
131 			print_verbose(" port %d",
132 			    ntohs(flow->flow_dst.addr_port));
133 	}
134 
135 	if ((pol->pol_flags & IKED_POLICY_DEFAULT) == 0) {
136 		print_verbose(" local %s", print_addr(&pol->pol_local.addr));
137 		if (pol->pol_local.addr.ss_family != AF_UNSPEC &&
138 		    pol->pol_local.addr_net)
139 			print_verbose("/%d", pol->pol_local.addr_mask);
140 
141 		print_verbose(" peer %s", print_addr(&pol->pol_peer.addr));
142 		if (pol->pol_peer.addr.ss_family != AF_UNSPEC &&
143 		    pol->pol_peer.addr_net)
144 			print_verbose("/%d", pol->pol_peer.addr_mask);
145 	}
146 
147 	TAILQ_FOREACH(pp, &pol->pol_proposals, prop_entry) {
148 		if (!pp->prop_nxforms)
149 			continue;
150 		if (pp->prop_protoid == IKEV2_SAPROTO_IKE)
151 			print_verbose(" ikesa");
152 		else
153 			print_verbose(" childsa");
154 
155 		for (j = 0; ikev2_xformtype_map[j].cm_type != 0; j++) {
156 			xfs = NULL;
157 
158 			for (i = 0; i < pp->prop_nxforms; i++) {
159 				xform = pp->prop_xforms + i;
160 
161 				if (xform->xform_type !=
162 				    ikev2_xformtype_map[j].cm_type)
163 					continue;
164 
165 				switch (xform->xform_type) {
166 				case IKEV2_XFORMTYPE_INTEGR:
167 					print_verbose(" auth ");
168 					xfs = authxfs;
169 					break;
170 				case IKEV2_XFORMTYPE_ENCR:
171 					print_verbose(" enc ");
172 					if (pp->prop_protoid ==
173 					    IKEV2_SAPROTO_IKE)
174 						xfs = ikeencxfs;
175 					else
176 						xfs = ipsecencxfs;
177 					break;
178 				case IKEV2_XFORMTYPE_PRF:
179 					print_verbose(" prf ");
180 					xfs = prfxfs;
181 					break;
182 				case IKEV2_XFORMTYPE_DH:
183 					print_verbose(" group ");
184 					xfs = groupxfs;
185 					break;
186 				case IKEV2_XFORMTYPE_ESN:
187 					print_verbose(" ");
188 					xfs = esnxfs;
189 					break;
190 				default:
191 					continue;
192 				}
193 
194 				print_verbose("%s", print_xf(xform->xform_id,
195 				    xform->xform_length / 8, xfs));
196 			}
197 		}
198 	}
199 
200 	if (pol->pol_localid.id_length != 0)
201 		print_verbose(" srcid %s", pol->pol_localid.id_data);
202 	if (pol->pol_peerid.id_length != 0)
203 		print_verbose(" dstid %s", pol->pol_peerid.id_data);
204 
205 	if (pol->pol_rekey)
206 		print_verbose(" ikelifetime %u", pol->pol_rekey);
207 
208 	print_verbose(" lifetime %llu bytes %llu",
209 	    pol->pol_lifetime.lt_seconds, pol->pol_lifetime.lt_bytes);
210 
211 	switch (pol->pol_auth.auth_method) {
212 	case IKEV2_AUTH_NONE:
213 		print_verbose (" none");
214 		break;
215 	case IKEV2_AUTH_SHARED_KEY_MIC:
216 		print_verbose(" psk 0x");
217 		for (i = 0; i < pol->pol_auth.auth_length; i++)
218 			print_verbose("%02x", pol->pol_auth.auth_data[i]);
219 		break;
220 	default:
221 		if (pol->pol_auth.auth_eap)
222 			print_verbose(" eap \"%s\"",
223 			    print_map(pol->pol_auth.auth_eap, eap_type_map));
224 		else
225 			print_verbose(" %s",
226 			    print_xf(pol->pol_auth.auth_method, 0, methodxfs));
227 	}
228 
229 	for (i = 0; i < pol->pol_ncfg; i++) {
230 		cfg = &pol->pol_cfg[i];
231 		print_verbose(" %s %s %s",
232 		    cfg->cfg_action == IKEV2_CP_REPLY ? "config" : "request",
233 		    print_xf(cfg->cfg_type,
234 		    cfg->cfg.address.addr_af, cpxfs),
235 		    print_addr(&cfg->cfg.address.addr));
236 	}
237 
238 	if (pol->pol_iface != 0 && if_indextoname(pol->pol_iface, iface) != NULL)
239 		print_verbose(" iface %s", iface);
240 
241 	if (pol->pol_tag[0] != '\0')
242 		print_verbose(" tag \"%s\"", pol->pol_tag);
243 
244 	if (pol->pol_tap != 0)
245 		print_verbose(" tap \"enc%u\"", pol->pol_tap);
246 
247 	print_verbose("\n");
248 }
249