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 (at) 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 74 extern void prsaerror(const char *str, ...); 75 extern int prsawrap (void); 76 extern int prsalex (void); 77 78 extern char *prsatext; 79 extern int prsa_cur_lineno; 80 extern char *prsa_cur_fname; 81 extern FILE *prsain; 82 83 int prsa_cur_lineno = 0; 84 char *prsa_cur_fname = NULL; 85 struct genlist *prsa_cur_list = NULL; 86 enum rsa_key_type prsa_cur_type = RSA_TYPE_ANY; 87 88 static RSA *rsa_cur; 89 90 void 91 prsaerror(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 107 void 108 prsawarning(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 124 int 125 prsawrap() 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 %% 154 statements: 155 statements statement 156 | statement 157 ; 158 159 statement: 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 174 rsa_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 225 addr: 226 addr4 227 | addr6 228 | ADDRANY 229 { 230 $$ = NULL; 231 } 232 ; 233 234 addr4: 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 257 addr6: 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 280 prefix: 281 /* nothing */ { $$ = -1; } 282 | SLASH NUMBER { $$ = $2; } 283 ; 284 params: 285 params param 286 | param 287 ; 288 289 param: 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 309 int prsaparse(void); 310 311 int 312 prsa_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