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
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 }
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
prsa_parse_file(struct genlist * list,char * fname,enum rsa_key_type type)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