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