summaryrefslogtreecommitdiffstats
path: root/ipsec-tools/src/racoon/prsa_par.y
diff options
context:
space:
mode:
Diffstat (limited to 'ipsec-tools/src/racoon/prsa_par.y')
-rw-r--r--ipsec-tools/src/racoon/prsa_par.y363
1 files changed, 363 insertions, 0 deletions
diff --git a/ipsec-tools/src/racoon/prsa_par.y b/ipsec-tools/src/racoon/prsa_par.y
new file mode 100644
index 00000000..1987e4d4
--- /dev/null
+++ b/ipsec-tools/src/racoon/prsa_par.y
@@ -0,0 +1,363 @@
+/* $NetBSD: prsa_par.y,v 1.6 2011/03/02 14:49:21 vanhu Exp $ */
+
+/* Id: prsa_par.y,v 1.3 2004/11/08 12:04:23 ludvigm Exp */
+
+%{
+/*
+ * Copyright (C) 2004 SuSE Linux AG, Nuernberg, Germany.
+ * Contributed by: Michal Ludvig <mludvig@suse.cz>, SUSE Labs
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* This file contains a parser for FreeS/WAN-style ipsec.secrets RSA keys. */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+
+#include "misc.h"
+#include "vmbuf.h"
+#include "plog.h"
+#include "oakley.h"
+#include "isakmp_var.h"
+#include "handler.h"
+#include "crypto_openssl.h"
+#include "sockmisc.h"
+#include "rsalist.h"
+
+extern void prsaerror(const char *str, ...);
+extern int prsawrap (void);
+extern int prsalex (void);
+
+extern char *prsatext;
+extern int prsa_cur_lineno;
+extern char *prsa_cur_fname;
+extern FILE *prsain;
+
+int prsa_cur_lineno = 0;
+char *prsa_cur_fname = NULL;
+struct genlist *prsa_cur_list = NULL;
+enum rsa_key_type prsa_cur_type = RSA_TYPE_ANY;
+
+static RSA *rsa_cur;
+
+void
+prsaerror(const char *s, ...)
+{
+ char fmt[512];
+
+ va_list ap;
+#ifdef HAVE_STDARG_H
+ va_start(ap, s);
+#else
+ va_start(ap);
+#endif
+ snprintf(fmt, sizeof(fmt), "%s:%d: %s",
+ prsa_cur_fname, prsa_cur_lineno, s);
+ plogv(LLV_ERROR, LOCATION, NULL, fmt, ap);
+ va_end(ap);
+}
+
+void
+prsawarning(const char *s, ...)
+{
+ char fmt[512];
+
+ va_list ap;
+#ifdef HAVE_STDARG_H
+ va_start(ap, s);
+#else
+ va_start(ap);
+#endif
+ snprintf(fmt, sizeof(fmt), "%s:%d: %s",
+ prsa_cur_fname, prsa_cur_lineno, s);
+ plogv(LLV_WARNING, LOCATION, NULL, fmt, ap);
+ va_end(ap);
+}
+
+int
+prsawrap()
+{
+ return 1;
+}
+%}
+%union {
+ BIGNUM *bn;
+ RSA *rsa;
+ char *chr;
+ long num;
+ struct netaddr *naddr;
+}
+
+%token COLON HEX
+%token OBRACE EBRACE COLON HEX
+%token TAG_RSA TAG_PUB TAG_PSK
+%token MODULUS PUBLIC_EXPONENT PRIVATE_EXPONENT
+%token PRIME1 PRIME2 EXPONENT1 EXPONENT2 COEFFICIENT
+%token ADDR4 ADDR6 ADDRANY SLASH NUMBER BASE64
+
+%type <bn> HEX
+%type <num> NUMBER
+%type <chr> ADDR4 ADDR6 BASE64
+
+%type <rsa> rsa_statement
+%type <num> prefix
+%type <naddr> addr4 addr6 addr
+
+%%
+statements:
+ statements statement
+ | statement
+ ;
+
+statement:
+ addr addr COLON rsa_statement
+ {
+ rsa_key_insert(prsa_cur_list, $1, $2, $4);
+ }
+ | addr COLON rsa_statement
+ {
+ rsa_key_insert(prsa_cur_list, NULL, $1, $3);
+ }
+ | COLON rsa_statement
+ {
+ rsa_key_insert(prsa_cur_list, NULL, NULL, $2);
+ }
+ ;
+
+rsa_statement:
+ TAG_RSA OBRACE params EBRACE
+ {
+ if (prsa_cur_type == RSA_TYPE_PUBLIC) {
+ prsawarning("Using private key for public key purpose.\n");
+ if (!rsa_cur->n || !rsa_cur->e) {
+ prsaerror("Incomplete key. Mandatory parameters are missing!\n");
+ YYABORT;
+ }
+ }
+ else {
+ if (!rsa_cur->n || !rsa_cur->e || !rsa_cur->d) {
+ prsaerror("Incomplete key. Mandatory parameters are missing!\n");
+ YYABORT;
+ }
+ if (!rsa_cur->p || !rsa_cur->q || !rsa_cur->dmp1
+ || !rsa_cur->dmq1 || !rsa_cur->iqmp) {
+ if (rsa_cur->p) BN_clear_free(rsa_cur->p);
+ if (rsa_cur->q) BN_clear_free(rsa_cur->q);
+ if (rsa_cur->dmp1) BN_clear_free(rsa_cur->dmp1);
+ if (rsa_cur->dmq1) BN_clear_free(rsa_cur->dmq1);
+ if (rsa_cur->iqmp) BN_clear_free(rsa_cur->iqmp);
+
+ rsa_cur->p = NULL;
+ rsa_cur->q = NULL;
+ rsa_cur->dmp1 = NULL;
+ rsa_cur->dmq1 = NULL;
+ rsa_cur->iqmp = NULL;
+ }
+ }
+ $$ = rsa_cur;
+ rsa_cur = RSA_new();
+ }
+ | TAG_PUB BASE64
+ {
+ if (prsa_cur_type == RSA_TYPE_PRIVATE) {
+ prsaerror("Public key in private-key file!\n");
+ YYABORT;
+ }
+ $$ = base64_pubkey2rsa($2);
+ free($2);
+ }
+ | TAG_PUB HEX
+ {
+ if (prsa_cur_type == RSA_TYPE_PRIVATE) {
+ prsaerror("Public key in private-key file!\n");
+ YYABORT;
+ }
+ $$ = bignum_pubkey2rsa($2);
+ }
+ ;
+
+addr:
+ addr4
+ | addr6
+ | ADDRANY
+ {
+ $$ = NULL;
+ }
+ ;
+
+addr4:
+ ADDR4 prefix
+ {
+ int err;
+ struct sockaddr_in *sap;
+ struct addrinfo hints, *res;
+
+ if ($2 == -1) $2 = 32;
+ if ($2 < 0 || $2 > 32) {
+ prsaerror ("Invalid IPv4 prefix\n");
+ YYABORT;
+ }
+ $$ = calloc (sizeof(struct netaddr), 1);
+ $$->prefix = $2;
+ sap = (struct sockaddr_in *)(&$$->sa);
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET;
+ hints.ai_flags = AI_NUMERICHOST;
+ err = getaddrinfo($1, NULL, &hints, &res);
+ if (err < 0) {
+ prsaerror("getaddrinfo(%s): %s\n", $1, gai_strerror(err));
+ YYABORT;
+ }
+ memcpy(sap, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo(res);
+ free($1);
+ }
+ ;
+
+addr6:
+ ADDR6 prefix
+ {
+ int err;
+ struct sockaddr_in6 *sap;
+ struct addrinfo hints, *res;
+
+ if ($2 == -1) $2 = 128;
+ if ($2 < 0 || $2 > 128) {
+ prsaerror ("Invalid IPv6 prefix\n");
+ YYABORT;
+ }
+ $$ = calloc (sizeof(struct netaddr), 1);
+ $$->prefix = $2;
+ sap = (struct sockaddr_in6 *)(&$$->sa);
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET6;
+ hints.ai_flags = AI_NUMERICHOST;
+ err = getaddrinfo($1, NULL, &hints, &res);
+ if (err < 0) {
+ prsaerror("getaddrinfo(%s): %s\n", $1, gai_strerror(err));
+ YYABORT;
+ }
+ memcpy(sap, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo(res);
+ free($1);
+ }
+ ;
+
+prefix:
+ /* nothing */ { $$ = -1; }
+ | SLASH NUMBER { $$ = $2; }
+ ;
+params:
+ params param
+ | param
+ ;
+
+param:
+ MODULUS COLON HEX
+ { if (!rsa_cur->n) rsa_cur->n = $3; else { prsaerror ("Modulus already defined\n"); YYABORT; } }
+ | PUBLIC_EXPONENT COLON HEX
+ { if (!rsa_cur->e) rsa_cur->e = $3; else { prsaerror ("PublicExponent already defined\n"); YYABORT; } }
+ | PRIVATE_EXPONENT COLON HEX
+ { if (!rsa_cur->d) rsa_cur->d = $3; else { prsaerror ("PrivateExponent already defined\n"); YYABORT; } }
+ | PRIME1 COLON HEX
+ { if (!rsa_cur->p) rsa_cur->p = $3; else { prsaerror ("Prime1 already defined\n"); YYABORT; } }
+ | PRIME2 COLON HEX
+ { if (!rsa_cur->q) rsa_cur->q = $3; else { prsaerror ("Prime2 already defined\n"); YYABORT; } }
+ | EXPONENT1 COLON HEX
+ { if (!rsa_cur->dmp1) rsa_cur->dmp1 = $3; else { prsaerror ("Exponent1 already defined\n"); YYABORT; } }
+ | EXPONENT2 COLON HEX
+ { if (!rsa_cur->dmq1) rsa_cur->dmq1 = $3; else { prsaerror ("Exponent2 already defined\n"); YYABORT; } }
+ | COEFFICIENT COLON HEX
+ { if (!rsa_cur->iqmp) rsa_cur->iqmp = $3; else { prsaerror ("Coefficient already defined\n"); YYABORT; } }
+ ;
+%%
+
+int prsaparse(void);
+
+int
+prsa_parse_file(struct genlist *list, char *fname, enum rsa_key_type type)
+{
+ FILE *fp = NULL;
+ int ret;
+
+ if (!fname)
+ return -1;
+ if (type == RSA_TYPE_PRIVATE) {
+ struct stat st;
+ if (stat(fname, &st) < 0)
+ return -1;
+ if (st.st_mode & (S_IRWXG | S_IRWXO)) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Too slack permissions on private key '%s'\n",
+ fname);
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Should be at most 0600, now is 0%o\n",
+ st.st_mode & 0777);
+ return -1;
+ }
+ }
+ fp = fopen(fname, "r");
+ if (!fp)
+ return -1;
+ prsain = fp;
+ prsa_cur_lineno = 1;
+ prsa_cur_fname = fname;
+ prsa_cur_list = list;
+ prsa_cur_type = type;
+ rsa_cur = RSA_new();
+ ret = prsaparse();
+ if (rsa_cur) {
+ RSA_free(rsa_cur);
+ rsa_cur = NULL;
+ }
+ fclose (fp);
+ prsain = NULL;
+ return ret;
+}