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