• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
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
prsaerror(const char * s,...)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
prsawarning(const char * s,...)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
prsawrap()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 		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 
226 addr:
227 	addr4
228 	| addr6
229 	| ADDRANY
230 	{
231 		$$ = NULL;
232 	}
233 	;
234 
235 addr4:
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 
264 addr6:
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 
293 prefix:
294 	/* nothing */ { $$ = -1; }
295 	| SLASH NUMBER { $$ = $2; }
296 	;
297 params:
298 	params param
299 	| param
300 	;
301 
302 param:
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 
322 int prsaparse(void);
323 
324 int
prsa_parse_file(struct genlist * list,char * fname,enum rsa_key_type type)325 prsa_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