vendor.c revision 1.6
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
28static 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
34static int
35setup_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
69errout:
70	for (i = 0; i < n; i++)
71		free(openbsd_vendor_cap[i].hash);
72	return -1;
73}
74
75void
76vendor_init(void)
77{
78	setup_vendor_hashes();
79}
80
81int
82add_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
109void
110check_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