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