1/* $NetBSD: prsa_par.y,v 1.4 2006/09/09 16:22:10 manu 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 } 215 | TAG_PUB HEX 216 { 217 if (prsa_cur_type == RSA_TYPE_PRIVATE) { 218 prsaerror("Public key in private-key file!\n"); 219 YYABORT; 220 } 221 $$ = bignum_pubkey2rsa($2); 222 } 223 ; 224 225addr: 226 addr4 227 | addr6 228 | ADDRANY 229 { 230 $$ = NULL; 231 } 232 ; 233 234addr4: 235 ADDR4 prefix 236 { 237 int err; 238 struct sockaddr_in *sap; 239 240 if ($2 == -1) $2 = 32; 241 if ($2 < 0 || $2 > 32) { 242 prsaerror ("Invalid IPv4 prefix\n"); 243 YYABORT; 244 } 245 $$ = calloc (sizeof(struct netaddr), 1); 246 $$->prefix = $2; 247 sap = (struct sockaddr_in *)(&$$->sa); 248 sap->sin_family = AF_INET; 249 err = inet_pton(AF_INET, $1, (struct in_addr*)(&sap->sin_addr)); 250 if (err <= 0) { 251 prsaerror("inet_pton(%s): %s\n", $1, strerror(errno)); 252 YYABORT; 253 } 254 } 255 ; 256 257addr6: 258 ADDR6 prefix 259 { 260 int err; 261 struct sockaddr_in6 *sap; 262 263 if ($2 == -1) $2 = 128; 264 if ($2 < 0 || $2 > 128) { 265 prsaerror ("Invalid IPv6 prefix\n"); 266 YYABORT; 267 } 268 $$ = calloc (sizeof(struct netaddr), 1); 269 $$->prefix = $2; 270 sap = (struct sockaddr_in6 *)(&$$->sa); 271 sap->sin6_family = AF_INET6; 272 err = inet_pton(AF_INET6, $1, (struct in6_addr*)(&sap->sin6_addr)); 273 if (err <= 0) { 274 prsaerror("inet_pton(%s): %s\n", $1, strerror(errno)); 275 YYABORT; 276 } 277 } 278 ; 279 280prefix: 281 /* nothing */ { $$ = -1; } 282 | SLASH NUMBER { $$ = $2; } 283 ; 284params: 285 params param 286 | param 287 ; 288 289param: 290 MODULUS COLON HEX 291 { if (!rsa_cur->n) rsa_cur->n = $3; else { prsaerror ("Modulus already defined\n"); YYABORT; } } 292 | PUBLIC_EXPONENT COLON HEX 293 { if (!rsa_cur->e) rsa_cur->e = $3; else { prsaerror ("PublicExponent already defined\n"); YYABORT; } } 294 | PRIVATE_EXPONENT COLON HEX 295 { if (!rsa_cur->d) rsa_cur->d = $3; else { prsaerror ("PrivateExponent already defined\n"); YYABORT; } } 296 | PRIME1 COLON HEX 297 { if (!rsa_cur->p) rsa_cur->p = $3; else { prsaerror ("Prime1 already defined\n"); YYABORT; } } 298 | PRIME2 COLON HEX 299 { if (!rsa_cur->q) rsa_cur->q = $3; else { prsaerror ("Prime2 already defined\n"); YYABORT; } } 300 | EXPONENT1 COLON HEX 301 { if (!rsa_cur->dmp1) rsa_cur->dmp1 = $3; else { prsaerror ("Exponent1 already defined\n"); YYABORT; } } 302 | EXPONENT2 COLON HEX 303 { if (!rsa_cur->dmq1) rsa_cur->dmq1 = $3; else { prsaerror ("Exponent2 already defined\n"); YYABORT; } } 304 | COEFFICIENT COLON HEX 305 { if (!rsa_cur->iqmp) rsa_cur->iqmp = $3; else { prsaerror ("Coefficient already defined\n"); YYABORT; } } 306 ; 307%% 308 309int prsaparse(void); 310 311int 312prsa_parse_file(struct genlist *list, char *fname, enum rsa_key_type type) 313{ 314 FILE *fp = NULL; 315 int ret; 316 317 if (!fname) 318 return -1; 319 if (type == RSA_TYPE_PRIVATE) { 320 struct stat st; 321 if (stat(fname, &st) < 0) 322 return -1; 323 if (st.st_mode & (S_IRWXG | S_IRWXO)) { 324 plog(LLV_ERROR, LOCATION, NULL, 325 "Too slack permissions on private key '%s'\n", 326 fname); 327 plog(LLV_ERROR, LOCATION, NULL, 328 "Should be at most 0600, now is 0%o\n", 329 st.st_mode & 0777); 330 return -1; 331 } 332 } 333 fp = fopen(fname, "r"); 334 if (!fp) 335 return -1; 336 prsain = fp; 337 prsa_cur_lineno = 1; 338 prsa_cur_fname = fname; 339 prsa_cur_list = list; 340 prsa_cur_type = type; 341 rsa_cur = RSA_new(); 342 ret = prsaparse(); 343 if (rsa_cur) { 344 RSA_free(rsa_cur); 345 rsa_cur = NULL; 346 } 347 fclose (fp); 348 prsain = NULL; 349 return ret; 350} 351