1/* $NetBSD: prsa_par.y,v 1.6 2011/03/02 14:49:21 vanhu Exp $ */ 2 3/* Id: prsa_par.y,v 1.3 2004/11/08 12:04:23 ludvigm Exp */ 4 5%{ 6/* 7 * Copyright (C) 2004 SuSE Linux AG, Nuernberg, Germany. 8 * Contributed by: Michal Ludvig <mludvig@suse.cz>, SUSE Labs 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the project nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36/* This file contains a parser for FreeS/WAN-style ipsec.secrets RSA keys. */ 37 38#include "config.h" 39 40#include <stdio.h> 41#include <stdarg.h> 42#include <string.h> 43#include <errno.h> 44#include <unistd.h> 45 46#ifdef HAVE_STDARG_H 47#include <stdarg.h> 48#else 49#include <varargs.h> 50#endif 51 52#include <netdb.h> 53#include <netinet/in.h> 54#include <sys/socket.h> 55#include <arpa/inet.h> 56#include <sys/types.h> 57 58#include <sys/stat.h> 59#include <unistd.h> 60 61#include <openssl/bn.h> 62#include <openssl/rsa.h> 63 64#include "misc.h" 65#include "vmbuf.h" 66#include "plog.h" 67#include "oakley.h" 68#include "isakmp_var.h" 69#include "handler.h" 70#include "crypto_openssl.h" 71#include "sockmisc.h" 72#include "rsalist.h" 73 74extern void prsaerror(const char *str, ...); 75extern int prsawrap (void); 76extern int prsalex (void); 77 78extern char *prsatext; 79extern int prsa_cur_lineno; 80extern char *prsa_cur_fname; 81extern FILE *prsain; 82 83int prsa_cur_lineno = 0; 84char *prsa_cur_fname = NULL; 85struct genlist *prsa_cur_list = NULL; 86enum rsa_key_type prsa_cur_type = RSA_TYPE_ANY; 87 88static RSA *rsa_cur; 89 90void 91prsaerror(const char *s, ...) 92{ 93 char fmt[512]; 94 95 va_list ap; 96#ifdef HAVE_STDARG_H 97 va_start(ap, s); 98#else 99 va_start(ap); 100#endif 101 snprintf(fmt, sizeof(fmt), "%s:%d: %s", 102 prsa_cur_fname, prsa_cur_lineno, s); 103 plogv(LLV_ERROR, LOCATION, NULL, fmt, ap); 104 va_end(ap); 105} 106 107void 108prsawarning(const char *s, ...) 109{ 110 char fmt[512]; 111 112 va_list ap; 113#ifdef HAVE_STDARG_H 114 va_start(ap, s); 115#else 116 va_start(ap); 117#endif 118 snprintf(fmt, sizeof(fmt), "%s:%d: %s", 119 prsa_cur_fname, prsa_cur_lineno, s); 120 plogv(LLV_WARNING, LOCATION, NULL, fmt, ap); 121 va_end(ap); 122} 123 124int 125prsawrap() 126{ 127 return 1; 128} 129%} 130%union { 131 BIGNUM *bn; 132 RSA *rsa; 133 char *chr; 134 long num; 135 struct netaddr *naddr; 136} 137 138%token COLON HEX 139%token OBRACE EBRACE COLON HEX 140%token TAG_RSA TAG_PUB TAG_PSK 141%token MODULUS PUBLIC_EXPONENT PRIVATE_EXPONENT 142%token PRIME1 PRIME2 EXPONENT1 EXPONENT2 COEFFICIENT 143%token ADDR4 ADDR6 ADDRANY SLASH NUMBER BASE64 144 145%type <bn> HEX 146%type <num> NUMBER 147%type <chr> ADDR4 ADDR6 BASE64 148 149%type <rsa> rsa_statement 150%type <num> prefix 151%type <naddr> addr4 addr6 addr 152 153%% 154statements: 155 statements statement 156 | statement 157 ; 158 159statement: 160 addr addr COLON rsa_statement 161 { 162 rsa_key_insert(prsa_cur_list, $1, $2, $4); 163 } 164 | addr COLON rsa_statement 165 { 166 rsa_key_insert(prsa_cur_list, NULL, $1, $3); 167 } 168 | COLON rsa_statement 169 { 170 rsa_key_insert(prsa_cur_list, NULL, NULL, $2); 171 } 172 ; 173 174rsa_statement: 175 TAG_RSA OBRACE params EBRACE 176 { 177 if (prsa_cur_type == RSA_TYPE_PUBLIC) { 178 prsawarning("Using private key for public key purpose.\n"); 179 if (!rsa_cur->n || !rsa_cur->e) { 180 prsaerror("Incomplete key. Mandatory parameters are missing!\n"); 181 YYABORT; 182 } 183 } 184 else { 185 if (!rsa_cur->n || !rsa_cur->e || !rsa_cur->d) { 186 prsaerror("Incomplete key. Mandatory parameters are missing!\n"); 187 YYABORT; 188 } 189 if (!rsa_cur->p || !rsa_cur->q || !rsa_cur->dmp1 190 || !rsa_cur->dmq1 || !rsa_cur->iqmp) { 191 if (rsa_cur->p) BN_clear_free(rsa_cur->p); 192 if (rsa_cur->q) BN_clear_free(rsa_cur->q); 193 if (rsa_cur->dmp1) BN_clear_free(rsa_cur->dmp1); 194 if (rsa_cur->dmq1) BN_clear_free(rsa_cur->dmq1); 195 if (rsa_cur->iqmp) BN_clear_free(rsa_cur->iqmp); 196 197 rsa_cur->p = NULL; 198 rsa_cur->q = NULL; 199 rsa_cur->dmp1 = NULL; 200 rsa_cur->dmq1 = NULL; 201 rsa_cur->iqmp = NULL; 202 } 203 } 204 $$ = rsa_cur; 205 rsa_cur = RSA_new(); 206 } 207 | TAG_PUB BASE64 208 { 209 if (prsa_cur_type == RSA_TYPE_PRIVATE) { 210 prsaerror("Public key in private-key file!\n"); 211 YYABORT; 212 } 213 $$ = base64_pubkey2rsa($2); 214 free($2); 215 } 216 | TAG_PUB HEX 217 { 218 if (prsa_cur_type == RSA_TYPE_PRIVATE) { 219 prsaerror("Public key in private-key file!\n"); 220 YYABORT; 221 } 222 $$ = bignum_pubkey2rsa($2); 223 } 224 ; 225 226addr: 227 addr4 228 | addr6 229 | ADDRANY 230 { 231 $$ = NULL; 232 } 233 ; 234 235addr4: 236 ADDR4 prefix 237 { 238 int err; 239 struct sockaddr_in *sap; 240 struct addrinfo hints, *res; 241 242 if ($2 == -1) $2 = 32; 243 if ($2 < 0 || $2 > 32) { 244 prsaerror ("Invalid IPv4 prefix\n"); 245 YYABORT; 246 } 247 $$ = calloc (sizeof(struct netaddr), 1); 248 $$->prefix = $2; 249 sap = (struct sockaddr_in *)(&$$->sa); 250 memset(&hints, 0, sizeof(hints)); 251 hints.ai_family = AF_INET; 252 hints.ai_flags = AI_NUMERICHOST; 253 err = getaddrinfo($1, NULL, &hints, &res); 254 if (err < 0) { 255 prsaerror("getaddrinfo(%s): %s\n", $1, gai_strerror(err)); 256 YYABORT; 257 } 258 memcpy(sap, res->ai_addr, res->ai_addrlen); 259 freeaddrinfo(res); 260 free($1); 261 } 262 ; 263 264addr6: 265 ADDR6 prefix 266 { 267 int err; 268 struct sockaddr_in6 *sap; 269 struct addrinfo hints, *res; 270 271 if ($2 == -1) $2 = 128; 272 if ($2 < 0 || $2 > 128) { 273 prsaerror ("Invalid IPv6 prefix\n"); 274 YYABORT; 275 } 276 $$ = calloc (sizeof(struct netaddr), 1); 277 $$->prefix = $2; 278 sap = (struct sockaddr_in6 *)(&$$->sa); 279 memset(&hints, 0, sizeof(hints)); 280 hints.ai_family = AF_INET6; 281 hints.ai_flags = AI_NUMERICHOST; 282 err = getaddrinfo($1, NULL, &hints, &res); 283 if (err < 0) { 284 prsaerror("getaddrinfo(%s): %s\n", $1, gai_strerror(err)); 285 YYABORT; 286 } 287 memcpy(sap, res->ai_addr, res->ai_addrlen); 288 freeaddrinfo(res); 289 free($1); 290 } 291 ; 292 293prefix: 294 /* nothing */ { $$ = -1; } 295 | SLASH NUMBER { $$ = $2; } 296 ; 297params: 298 params param 299 | param 300 ; 301 302param: 303 MODULUS COLON HEX 304 { if (!rsa_cur->n) rsa_cur->n = $3; else { prsaerror ("Modulus already defined\n"); YYABORT; } } 305 | PUBLIC_EXPONENT COLON HEX 306 { if (!rsa_cur->e) rsa_cur->e = $3; else { prsaerror ("PublicExponent already defined\n"); YYABORT; } } 307 | PRIVATE_EXPONENT COLON HEX 308 { if (!rsa_cur->d) rsa_cur->d = $3; else { prsaerror ("PrivateExponent already defined\n"); YYABORT; } } 309 | PRIME1 COLON HEX 310 { if (!rsa_cur->p) rsa_cur->p = $3; else { prsaerror ("Prime1 already defined\n"); YYABORT; } } 311 | PRIME2 COLON HEX 312 { if (!rsa_cur->q) rsa_cur->q = $3; else { prsaerror ("Prime2 already defined\n"); YYABORT; } } 313 | EXPONENT1 COLON HEX 314 { if (!rsa_cur->dmp1) rsa_cur->dmp1 = $3; else { prsaerror ("Exponent1 already defined\n"); YYABORT; } } 315 | EXPONENT2 COLON HEX 316 { if (!rsa_cur->dmq1) rsa_cur->dmq1 = $3; else { prsaerror ("Exponent2 already defined\n"); YYABORT; } } 317 | COEFFICIENT COLON HEX 318 { if (!rsa_cur->iqmp) rsa_cur->iqmp = $3; else { prsaerror ("Coefficient already defined\n"); YYABORT; } } 319 ; 320%% 321 322int prsaparse(void); 323 324int 325prsa_parse_file(struct genlist *list, char *fname, enum rsa_key_type type) 326{ 327 FILE *fp = NULL; 328 int ret; 329 330 if (!fname) 331 return -1; 332 if (type == RSA_TYPE_PRIVATE) { 333 struct stat st; 334 if (stat(fname, &st) < 0) 335 return -1; 336 if (st.st_mode & (S_IRWXG | S_IRWXO)) { 337 plog(LLV_ERROR, LOCATION, NULL, 338 "Too slack permissions on private key '%s'\n", 339 fname); 340 plog(LLV_ERROR, LOCATION, NULL, 341 "Should be at most 0600, now is 0%o\n", 342 st.st_mode & 0777); 343 return -1; 344 } 345 } 346 fp = fopen(fname, "r"); 347 if (!fp) 348 return -1; 349 prsain = fp; 350 prsa_cur_lineno = 1; 351 prsa_cur_fname = fname; 352 prsa_cur_list = list; 353 prsa_cur_type = type; 354 rsa_cur = RSA_new(); 355 ret = prsaparse(); 356 if (rsa_cur) { 357 RSA_free(rsa_cur); 358 rsa_cur = NULL; 359 } 360 fclose (fp); 361 prsain = NULL; 362 return ret; 363} 364