vendor.c revision 1.1
1/* $OpenBSD: */ 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-4.0", 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 if (openbsd_vendor_cap[i].hash) 72 free(openbsd_vendor_cap[i].hash); 73 return (-1); 74} 75 76void 77vendor_init(void) 78{ 79 setup_vendor_hashes(); 80} 81 82int 83add_vendor_openbsd(struct message *msg) 84{ 85 u_int8_t *buf; 86 size_t buflen; 87 int i, n = NUMVIDS; 88 89 for (i = 0; i < n; i++) { 90 buflen = openbsd_vendor_cap[i].hashsize + ISAKMP_GEN_SZ; 91 if ((buf = calloc(buflen, sizeof(char))) == NULL) { 92 log_error("add_vendor_payload: calloc(%lu) failed", 93 (unsigned long)buflen); 94 return (-1); 95 } 96 97 SET_ISAKMP_GEN_LENGTH(buf, buflen); 98 memcpy(buf + ISAKMP_VENDOR_ID_OFF, openbsd_vendor_cap[i].hash, 99 openbsd_vendor_cap[i].hashsize); 100 if (message_add_payload(msg, ISAKMP_PAYLOAD_VENDOR, buf, 101 buflen, 1)) { 102 free(buf); 103 return (-1); 104 } 105 } 106 107 return (0); 108} 109 110void 111check_vendor_openbsd(struct message *msg, struct payload *p) 112{ 113 u_int8_t *pbuf = p->p; 114 ssize_t vlen; 115 int i, n = NUMVIDS; 116 117 if (msg->exchange->flags & EXCHANGE_FLAG_OPENBSD) { 118 p->flags |= PL_MARK; 119 return; 120 } 121 122 vlen = GET_ISAKMP_GEN_LENGTH(pbuf) - ISAKMP_GEN_SZ; 123 124 for (i = 0; i < n; i++) { 125 if (vlen != openbsd_vendor_cap[i].hashsize) { 126 LOG_DBG((LOG_EXCHANGE, 90, 127 "check_vendor_openbsd: bad size %lu != %lu", 128 (unsigned long)vlen, 129 (unsigned long)openbsd_vendor_cap[i].hashsize)); 130 continue; 131 } 132 if (memcmp(openbsd_vendor_cap[i].hash, pbuf + ISAKMP_GEN_SZ, 133 vlen) == 0) { 134 msg->exchange->flags |= EXCHANGE_FLAG_OPENBSD; 135 LOG_DBG((LOG_EXCHANGE, 10, "check_vendor_openbsd: " 136 "OpenBSD (%s)", openbsd_vendor_cap[i].text)); 137 } 138 p->flags |= PL_MARK; 139 } 140} 141