xref: /openbsd/sbin/isakmpd/vendor.c (revision 09467b48)
1 /*	$OpenBSD: vendor.c,v 1.6 2017/11/08 13:33:49 patrick Exp $	*/
2 /*
3  * Copyright (c) 2006 Hans-Joerg Hoexer <hshoexer@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/types.h>
19 #include <stdlib.h>
20 #include <string.h>
21 
22 #include "exchange.h"
23 #include "hash.h"
24 #include "log.h"
25 #include "message.h"
26 #include "vendor.h"
27 
28 static struct vendor_cap openbsd_vendor_cap[] = {
29 	{ "OpenBSD-6.3", NULL, 0 },
30 };
31 
32 #define NUMVIDS	(sizeof openbsd_vendor_cap / sizeof openbsd_vendor_cap[0])
33 
34 static int
35 setup_vendor_hashes(void)
36 {
37 	struct hash	*hash;
38 	int		 i, n = NUMVIDS;
39 
40 	hash = hash_get(HASH_MD5);
41 	if (!hash) {
42 		log_print("setup_vendor_hashes: could not find MD5 hash");
43 		return -1;
44 	}
45 
46 	for (i = 0; i < n; i++) {
47 		openbsd_vendor_cap[i].hashsize = hash->hashsize;
48 		openbsd_vendor_cap[i].hash = calloc(hash->hashsize,
49 		    sizeof(u_int8_t));
50 		if (openbsd_vendor_cap[i].hash == NULL) {
51 			log_error("setup_vendor_hashes: calloc failed");
52 			goto errout;
53 		}
54 
55 		hash->Init(hash->ctx);
56 		hash->Update(hash->ctx,
57 		    (unsigned char *)openbsd_vendor_cap[i].text,
58 		    strlen(openbsd_vendor_cap[i].text));
59 		hash->Final(openbsd_vendor_cap[i].hash, hash->ctx);
60 
61 		LOG_DBG((LOG_EXCHANGE, 50, "setup_vendor_hashes: "
62 		    "MD5(\"%s\") (%lu bytes)", openbsd_vendor_cap[i].text,
63 		    (unsigned long)hash->hashsize));
64 		LOG_DBG_BUF((LOG_EXCHANGE, 50, "setup_vendor_hashes",
65 		    openbsd_vendor_cap[i].hash, hash->hashsize));
66 	}
67 	return 0;
68 
69 errout:
70 	for (i = 0; i < n; i++)
71 		free(openbsd_vendor_cap[i].hash);
72 	return -1;
73 }
74 
75 void
76 vendor_init(void)
77 {
78 	setup_vendor_hashes();
79 }
80 
81 int
82 add_vendor_openbsd(struct message *msg)
83 {
84 	u_int8_t	*buf;
85 	size_t		 buflen;
86 	int		 i, n = NUMVIDS;
87 
88 	for (i = 0; i < n; i++) {
89 		buflen = openbsd_vendor_cap[i].hashsize + ISAKMP_GEN_SZ;
90 		if ((buf = calloc(buflen, sizeof(char))) == NULL) {
91 			log_error("add_vendor_payload: calloc(%lu) failed",
92 			    (unsigned long)buflen);
93 			return -1;
94 		}
95 
96 		SET_ISAKMP_GEN_LENGTH(buf, buflen);
97 		memcpy(buf + ISAKMP_VENDOR_ID_OFF, openbsd_vendor_cap[i].hash,
98 		    openbsd_vendor_cap[i].hashsize);
99 		if (message_add_payload(msg, ISAKMP_PAYLOAD_VENDOR, buf,
100 		    buflen, 1)) {
101 			free(buf);
102 			return -1;
103 		}
104 	}
105 
106 	return 0;
107 }
108 
109 void
110 check_vendor_openbsd(struct message *msg, struct payload *p)
111 {
112 	u_int8_t	*pbuf = p->p;
113 	ssize_t		 vlen;
114 	int		 i, n = NUMVIDS;
115 
116 	if (msg->exchange->flags & EXCHANGE_FLAG_OPENBSD) {
117 		p->flags |= PL_MARK;
118 		return;
119 	}
120 
121 	vlen = GET_ISAKMP_GEN_LENGTH(pbuf) - ISAKMP_GEN_SZ;
122 
123 	for (i = 0; i < n; i++) {
124 		if (vlen != openbsd_vendor_cap[i].hashsize) {
125 			LOG_DBG((LOG_EXCHANGE, 90,
126 			    "check_vendor_openbsd: bad size %lu != %lu",
127 			    (unsigned long)vlen,
128 			    (unsigned long)openbsd_vendor_cap[i].hashsize));
129 			continue;
130 		}
131 		if (memcmp(openbsd_vendor_cap[i].hash, pbuf + ISAKMP_GEN_SZ,
132 		    vlen) == 0) {
133 			msg->exchange->flags |= EXCHANGE_FLAG_OPENBSD;
134 			LOG_DBG((LOG_EXCHANGE, 10, "check_vendor_openbsd: "
135 			    "OpenBSD (%s)", openbsd_vendor_cap[i].text));
136 		}
137 		p->flags |= PL_MARK;
138 	}
139 }
140