1/* $Id: vendorid.c,v 1.7 2005/01/29 16:34:25 vanhu Exp $ */ 2 3/* 4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the project nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32#include "config.h" 33 34#include <sys/types.h> 35#include <sys/param.h> 36 37#include <stdlib.h> 38#include <stdio.h> 39#include <string.h> 40#include <errno.h> 41#include <ctype.h> 42 43#include "var.h" 44#include "misc.h" 45#include "vmbuf.h" 46#include "plog.h" 47#include "debug.h" 48 49#include "localconf.h" 50#include "isakmp_var.h" 51#include "isakmp.h" 52#include "vendorid.h" 53#include "crypto_openssl.h" 54 55static struct vendor_id all_vendor_ids[] = { 56{ VENDORID_KAME , "KAME/racoon" }, 57{ VENDORID_GSSAPI_LONG, "A GSS-API Authentication Method for IKE" }, 58{ VENDORID_GSSAPI , "GSSAPI" }, 59{ VENDORID_MS_NT5 , "MS NT5 ISAKMPOAKLEY" }, 60{ VENDORID_NATT_00 , "draft-ietf-ipsec-nat-t-ike-00" }, 61{ VENDORID_NATT_01 , "draft-ietf-ipsec-nat-t-ike-01" }, 62{ VENDORID_NATT_02 , "draft-ietf-ipsec-nat-t-ike-02" }, 63{ VENDORID_NATT_02_N , "draft-ietf-ipsec-nat-t-ike-02\n" }, 64{ VENDORID_NATT_03 , "draft-ietf-ipsec-nat-t-ike-03" }, 65{ VENDORID_NATT_04 , "draft-ietf-ipsec-nat-t-ike-04" }, 66{ VENDORID_NATT_05 , "draft-ietf-ipsec-nat-t-ike-05" }, 67{ VENDORID_NATT_06 , "draft-ietf-ipsec-nat-t-ike-06" }, 68{ VENDORID_NATT_07 , "draft-ietf-ipsec-nat-t-ike-07" }, 69{ VENDORID_NATT_08 , "draft-ietf-ipsec-nat-t-ike-08" }, 70{ VENDORID_NATT_APPLE , "draft-ietf-ipsec-nat-t-ike" }, 71{ VENDORID_NATT_RFC , "RFC 3947" }, 72{ VENDORID_XAUTH , "draft-ietf-ipsra-isakmp-xauth-06.txt" }, 73{ VENDORID_UNITY , "CISCO-UNITY" }, 74{ VENDORID_FRAG , "FRAGMENTATION" }, 75/* Just a readable string for DPD ... */ 76{ VENDORID_DPD , "DPD" }, 77}; 78 79#define NUMVENDORIDS (sizeof(all_vendor_ids)/sizeof(all_vendor_ids[0])) 80 81#define DPD_MAJOR_VERSION 0x01 82#define DPD_MINOR_VERSION 0x00 83 84const char vendorid_dpd_hash[] = { 85 0xAF, 0xCA, 0xD7, 0x13, 86 0x68, 0xA1, 0xF1, 0xC9, 87 0x6B, 0x86, 0x96, 0xFC, 88 0x77, 0x57, DPD_MAJOR_VERSION, DPD_MINOR_VERSION 89}; 90 91 92static vchar_t *vendorid_fixup(int, vchar_t *t); 93 94static struct vendor_id * 95lookup_vendor_id_by_id (int id) 96{ 97 int i; 98 99 for (i = 0; i < NUMVENDORIDS; i++) 100 if (all_vendor_ids[i].id == id) 101 return &all_vendor_ids[i]; 102 103 return NULL; 104} 105 106const char * 107vid_string_by_id (int id) 108{ 109 struct vendor_id *current; 110 111 if (id == VENDORID_DPD) 112 return vendorid_dpd_hash; 113 114 current = lookup_vendor_id_by_id(id); 115 116 return current ? current->string : NULL; 117} 118 119static struct vendor_id * 120lookup_vendor_id_by_hash (const char *hash) 121{ 122 int i; 123 124 for (i = 0; i < NUMVENDORIDS; i++) 125 if (strncmp(all_vendor_ids[i].hash->v, hash, 126 all_vendor_ids[i].hash->l) == 0) 127 return &all_vendor_ids[i]; 128 129 return NULL; 130} 131 132void 133compute_vendorids (void) 134{ 135 int i; 136 vchar_t vid; 137 138 for (i = 0; i < NUMVENDORIDS; i++) { 139 /* VENDORID_DPD is not a MD5 sum... */ 140 if(i == VENDORID_DPD){ 141 all_vendor_ids[i].hash = vmalloc(sizeof(vendorid_dpd_hash)); 142 if (all_vendor_ids[i].hash == NULL) { 143 plog(ASL_LEVEL_ERR, 144 "unable to get memory for VID hash\n"); 145 exit(1); /* this really shouldn't happen */ 146 } 147 memcpy(all_vendor_ids[i].hash->v, vendorid_dpd_hash, 148 sizeof(vendorid_dpd_hash)); 149 continue; 150 } 151 152 vid.v = (char *) all_vendor_ids[i].string; 153 vid.l = strlen(vid.v); 154 155 all_vendor_ids[i].hash = eay_md5_one(&vid); 156 if (all_vendor_ids[i].hash == NULL) 157 plog(ASL_LEVEL_ERR, 158 "unable to hash vendor ID string\n"); 159 160 /* Special cases */ 161 all_vendor_ids[i].hash = 162 vendorid_fixup(all_vendor_ids[i].id, 163 all_vendor_ids[i].hash); 164 } 165} 166 167/* 168 * set hashed vendor id. 169 * hash function is always MD5. 170 */ 171vchar_t * 172set_vendorid(int vendorid) 173{ 174 struct vendor_id *current; 175 176 if (vendorid == VENDORID_UNKNOWN) { 177 /* 178 * The default unknown ID gets translated to 179 * KAME/racoon. 180 */ 181 vendorid = VENDORID_KAME; 182 } 183 184 current = lookup_vendor_id_by_id(vendorid); 185 if (current == NULL) { 186 plog(ASL_LEVEL_ERR, 187 "invalid vendor ID index: %d\n", vendorid); 188 return (NULL); 189 } 190 191 /* The rest of racoon expects a private copy 192 * of the VID that could be free'd after use. 193 * That's why we don't return the original pointer. */ 194 return vdup(current->hash); 195} 196 197/* 198 * Check the vendor ID payload -- return the vendor ID index 199 * if we find a recognized one, or UNKNOWN if we don't. 200 * 201 * gen ... points to Vendor ID payload. 202 */ 203int 204check_vendorid(struct isakmp_gen *gen) 205{ 206 int vidlen; 207 struct vendor_id *current; 208 209 if (gen == NULL) 210 return (VENDORID_UNKNOWN); 211 212 vidlen = ntohs(gen->len) - sizeof(*gen); 213 214 current = lookup_vendor_id_by_hash((char *)(gen + 1)); 215 if (!current) 216 goto unknown; 217 218 if (current->hash->l < vidlen) 219 plog(ASL_LEVEL_INFO, 220 "received broken Microsoft ID: %s\n", 221 current->string); 222 else 223 plog(ASL_LEVEL_INFO, 224 "received Vendor ID: %s\n", 225 current->string); 226 227 return current->id; 228 229unknown: 230 plogdump(ASL_LEVEL_DEBUG, (char *)(gen + 1), vidlen, "received unknown Vendor ID:\n"); 231 return (VENDORID_UNKNOWN); 232} 233 234static vchar_t * 235vendorid_fixup(vendorid, vidhash) 236 int vendorid; 237 vchar_t *vidhash; 238{ 239 switch(vendorid) { 240 case VENDORID_XAUTH: { /* The vendor Id is truncated */ 241 vchar_t *tmp; 242 243 if ((tmp = vmalloc(8)) == NULL) { 244 plog(ASL_LEVEL_ERR, 245 "unable to hash vendor ID string\n"); 246 return NULL; 247 } 248 249 memcpy(tmp->v, vidhash->v, 8); 250 vfree(vidhash); 251 vidhash = tmp; 252 253 break; 254 } 255 case VENDORID_UNITY: /* Two bytes tweak */ 256 vidhash->v[14] = 0x01; 257 vidhash->v[15] = 0x00; 258 break; 259 260 default: 261 break; 262 } 263 264 return vidhash; 265} 266