/[pkg-openswan]/trunk/lib/libopenswan/alg_info.c
ViewVC logotype

Contents of /trunk/lib/libopenswan/alg_info.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 613 - (show annotations) (download)
Thu May 27 18:26:17 2010 UTC (2 years, 11 months ago) by harald-jenny-guest
File MIME type: text/plain
File size: 25885 byte(s)
new upstream release
1 /*
2 * Algorithm info parsing and creation functions
3 * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
4 *
5 * alg_info.c,v 1.1.2.1 2003/11/21 18:12:23 jjo Exp
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17 #include <stddef.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <string.h>
21 #include <netinet/in.h>
22 #include <sys/socket.h>
23 #include <sys/stat.h>
24 #include <netinet/in.h>
25 #include <arpa/inet.h>
26 #include <limits.h>
27
28 #include <ctype.h>
29 #include <openswan.h>
30 #include <openswan/ipsec_policy.h>
31 #include <openswan/passert.h>
32 #include <openswan/pfkeyv2.h>
33
34 #include "constants.h"
35 #include "alg_info.h"
36 #include "oswlog.h"
37 #include "oswalloc.h"
38
39 #ifdef HAVE_LIBNSS
40 #include "oswconf.h"
41 #endif
42
43 /* abstract reference */
44 struct oakley_group_desc;
45
46 /* sadb/ESP aa attrib converters */
47 enum ipsec_authentication_algo
48 alg_info_esp_aa2sadb(enum ikev1_auth_attribute auth)
49 {
50 switch(auth) {
51 case AUTH_ALGORITHM_HMAC_MD5:
52 return AH_MD5;
53 case AUTH_ALGORITHM_HMAC_SHA1:
54 return AH_SHA;
55
56 case AUTH_ALGORITHM_HMAC_SHA2_256:
57 return AH_SHA2_256;
58 case AUTH_ALGORITHM_HMAC_SHA2_384:
59 return AH_SHA2_384;
60 case AUTH_ALGORITHM_HMAC_SHA2_512:
61 return AH_SHA2_512;
62 case AUTH_ALGORITHM_HMAC_RIPEMD:
63 return AH_RIPEMD;
64 case AUTH_ALGORITHM_NONE:
65 return AH_NONE;
66
67 default:
68 bad_case(auth);
69 }
70 return 0;
71 }
72
73 /*
74 * should change all algorithms to use IKEv2 numbers, and translate
75 * at edges only
76 */
77 enum ikev1_auth_attribute
78 alg_info_esp_v2tov1aa(enum ikev2_trans_type_integ ti)
79 {
80 switch(ti) {
81 case IKEv2_AUTH_NONE:
82 return AUTH_ALGORITHM_NONE;
83 case IKEv2_AUTH_HMAC_MD5_96:
84 return AUTH_ALGORITHM_HMAC_MD5;
85 case IKEv2_AUTH_HMAC_SHA1_96:
86 return AUTH_ALGORITHM_HMAC_SHA1;
87 case IKEv2_AUTH_HMAC_SHA2_256_128:
88 return AUTH_ALGORITHM_HMAC_SHA2_256;
89 case IKEv2_AUTH_HMAC_SHA2_384_192:
90 return AUTH_ALGORITHM_HMAC_SHA2_256;
91 case IKEv2_AUTH_HMAC_SHA2_512_256:
92 return AUTH_ALGORITHM_HMAC_SHA2_256;
93
94 /* invalid or not yet supported */
95 case IKEv2_AUTH_DES_MAC:
96 case IKEv2_AUTH_KPDK_MD5:
97 case IKEv2_AUTH_AES_XCBC_96:
98 case IKEv2_AUTH_INVALID:
99 case IKEv2_AUTH_HMAC_MD5_128:
100 case IKEv2_AUTH_HMAC_SHA1_160:
101 case IKEv2_AUTH_AES_CMAC_96:
102 case IKEv2_AUTH_AES_128_GMAC:
103 case IKEv2_AUTH_AES_192_GMAC:
104 case IKEv2_AUTH_AES_256_GMAC:
105 bad_case(ti);
106 }
107 return 0;
108 }
109
110 int /* __attribute__ ((unused)) */
111 alg_info_esp_sadb2aa(int sadb_aalg)
112 {
113 int auth=0;
114 switch(sadb_aalg) {
115 case SADB_AALG_MD5HMAC:
116 case SADB_AALG_SHA1HMAC:
117 auth=sadb_aalg-1;
118 break;
119 /* since they are the same ... :) */
120 case AUTH_ALGORITHM_HMAC_SHA2_256:
121 case AUTH_ALGORITHM_HMAC_SHA2_384:
122 case AUTH_ALGORITHM_HMAC_SHA2_512:
123 case AUTH_ALGORITHM_HMAC_RIPEMD:
124 auth=sadb_aalg;
125 break;
126 default:
127 /* loose ... */
128 auth=sadb_aalg;
129 }
130 return auth;
131 }
132
133 /*
134 * Search enum_name array with in prefixed uppercase
135 */
136 int
137 alg_enum_search_prefix (enum_names *ed, const char *prefix, const char *str, int str_len)
138 {
139 char buf[64];
140 char *ptr;
141 int ret;
142 int len=sizeof(buf)-1; /* reserve space for final \0 */
143
144 for (ptr=buf; *prefix; *ptr++=*prefix++, len--);
145
146 while (str_len--&&len--&&*str) *ptr++=toupper(*str++);
147 *ptr=0;
148
149 DBG(DBG_CRYPT, DBG_log("enum_search_prefix () "
150 "calling enum_search(%p, \"%s\")", ed, buf));
151
152 ret=enum_search(ed, buf);
153 return ret;
154 }
155 /*
156 * Search enum_name array with in prefixed and postfixed uppercase
157 */
158 int
159 alg_enum_search_ppfix (enum_names *ed, const char *prefix
160 , const char *postfix, const char *str
161 , int str_len)
162 {
163 char buf[64];
164 char *ptr;
165 int ret;
166 int len=sizeof(buf)-1; /* reserve space for final \0 */
167 for (ptr=buf; *prefix; *ptr++=*prefix++, len--);
168 while (str_len--&&len--&&*str) *ptr++=toupper(*str++);
169 while (len--&&*postfix) *ptr++=*postfix++;
170 *ptr=0;
171 DBG(DBG_CRYPT, DBG_log("enum_search_ppfixi () "
172 "calling enum_search(%p, \"%s\")", ed, buf));
173 ret=enum_search(ed, buf);
174 return ret;
175 }
176
177 /*
178 * Search esp_transformid_names for a match, eg:
179 * "3des" <=> "ESP_3DES"
180 */
181 #define ESP_MAGIC_ID 0x00ffff01
182 static int
183 ealg_getbyname_esp(const char *const str, int len)
184 {
185 int ret=-1;
186 if (!str||!*str)
187 goto out;
188 /* leave special case for eg: "id248" string */
189 if (strcmp("id", str)==0)
190 return ESP_MAGIC_ID;
191 ret=alg_enum_search_prefix(&esp_transformid_names, "ESP_", str, len);
192 out:
193 return ret;
194 }
195
196
197 /*
198 * Search auth_alg_names for a match, eg:
199 * "md5" <=> "AUTH_ALGORITHM_HMAC_MD5"
200 */
201 static int
202 aalg_getbyname_esp(const char *const str, int len)
203 {
204 int ret=-1;
205 unsigned num;
206 if (!str||!*str)
207 goto out;
208 ret=alg_enum_search_prefix(&auth_alg_names,"AUTH_ALGORITHM_HMAC_",str,len);
209 if (ret>=0) goto out;
210 ret=alg_enum_search_prefix(&auth_alg_names,"AUTH_ALGORITHM_",str,len);
211 if (ret>=0) goto out;
212
213 /* Special value for no authentication since zero is already used. */
214 ret = INT_MAX;
215 if (!strncasecmp(str, "null", len))
216 goto out;
217
218 sscanf(str, "id%d%n", &ret, &num);
219 if (ret >=0 && num!=strlen(str))
220 ret=-1;
221 out:
222 return ret;
223 }
224 static int
225 modp_getbyname_esp(const char *const str, int len)
226 {
227 int ret=-1;
228 if (!str||!*str)
229 goto out;
230 ret=alg_enum_search_prefix(&oakley_group_names,"OAKLEY_GROUP_",str,len);
231 if (ret>=0) goto out;
232 ret=alg_enum_search_ppfix(&oakley_group_names, "OAKLEY_GROUP_", " (extension)", str, len);
233 out:
234 return ret;
235 }
236
237 void
238 alg_info_free(struct alg_info *alg_info) {
239 pfreeany(alg_info);
240 }
241
242 /*
243 * Raw add routine: only checks for no duplicates
244 */
245 static void
246 __alg_info_esp_add (struct alg_info_esp *alg_info
247 , int ealg_id, unsigned ek_bits
248 , int aalg_id, unsigned ak_bits)
249 {
250 struct esp_info *esp_info=alg_info->esp;
251 unsigned cnt=alg_info->alg_info_cnt, i;
252 /* check for overflows */
253 passert(cnt < elemsof(alg_info->esp));
254 /* dont add duplicates */
255 for (i=0;i<cnt;i++)
256 if ( esp_info[i].esp_ealg_id==ealg_id &&
257 (!ek_bits || esp_info[i].esp_ealg_keylen==ek_bits) &&
258 esp_info[i].esp_aalg_id==aalg_id &&
259 (!ak_bits || esp_info[i].esp_aalg_keylen==ak_bits))
260 return;
261 esp_info[cnt].esp_ealg_id=ealg_id;
262 esp_info[cnt].esp_ealg_keylen=ek_bits;
263 esp_info[cnt].esp_aalg_id=aalg_id;
264 esp_info[cnt].esp_aalg_keylen=ak_bits;
265 /* sadb values */
266 esp_info[cnt].encryptalg=ealg_id;
267 esp_info[cnt].authalg=alg_info_esp_aa2sadb(aalg_id);
268 alg_info->alg_info_cnt++;
269 DBG(DBG_CRYPT, DBG_log("__alg_info_esp_add() "
270 "ealg=%d aalg=%d cnt=%d",
271 ealg_id, aalg_id, alg_info->alg_info_cnt));
272 }
273
274 /*
275 * Add ESP alg info _with_ logic (policy):
276 */
277 static void
278 alg_info_esp_add (struct alg_info *alg_info,
279 int ealg_id, int ek_bits,
280 int aalg_id, int ak_bits,
281 int modp_id, bool permit_manconn)
282 {
283 /* Policy: default to 3DES */
284 if (ealg_id==0)
285 ealg_id=ESP_3DES;
286
287 if (ealg_id>0) {
288
289 if(aalg_id > 0 ||
290 (permit_manconn && aalg_id == 0))
291 {
292 if (aalg_id == INT_MAX)
293 aalg_id = 0;
294 __alg_info_esp_add((struct alg_info_esp *)alg_info,
295 ealg_id, ek_bits,
296 aalg_id, ak_bits);
297 }
298 else
299 {
300 /* Policy: default to MD5 and SHA1 */
301 __alg_info_esp_add((struct alg_info_esp *)alg_info,
302 ealg_id, ek_bits, \
303 AUTH_ALGORITHM_HMAC_MD5, ak_bits);
304 __alg_info_esp_add((struct alg_info_esp *)alg_info,
305 ealg_id, ek_bits, \
306 AUTH_ALGORITHM_HMAC_SHA1, ak_bits);
307 }
308 }
309 }
310
311 /*
312 * Add AH alg info _with_ logic (policy):
313 */
314 static void
315 alg_info_ah_add (struct alg_info *alg_info,
316 int ealg_id, int ek_bits,
317 int aalg_id, int ak_bits,
318 int modp_id, bool permit_manconn)
319 {
320 if(aalg_id > 0 ||
321 (permit_manconn && aalg_id == 0))
322 {
323 __alg_info_esp_add((struct alg_info_esp *)alg_info,
324 ealg_id, ek_bits,
325 aalg_id, ak_bits);
326 }
327 else
328 {
329 /* Policy: default to MD5 and SHA1 */
330 __alg_info_esp_add((struct alg_info_esp *)alg_info,
331 ealg_id, ek_bits, \
332 AUTH_ALGORITHM_HMAC_MD5, ak_bits);
333 __alg_info_esp_add((struct alg_info_esp *)alg_info,
334 ealg_id, ek_bits, \
335 AUTH_ALGORITHM_HMAC_SHA1, ak_bits);
336 }
337 }
338
339 static const char *parser_state_esp_names[] = {
340 "ST_INI",
341 "ST_INI_AA",
342 "ST_EA",
343 "ST_EA_END",
344 "ST_EK",
345 "ST_EK_END",
346 "ST_AA",
347 "ST_AA_END",
348 "ST_AK",
349 "ST_AK_END",
350 "ST_MOPD",
351 "ST_FLAG_STRICT",
352 "ST_END",
353 "ST_EOF",
354 "ST_ERR"
355 };
356
357 static const char *parser_state_name_esp(enum parser_state_esp state) {
358 return parser_state_esp_names[state];
359 }
360
361 static inline void parser_set_state(struct parser_context *p_ctx, enum parser_state_esp state) {
362 if (state!=p_ctx->state) {
363 p_ctx->old_state=p_ctx->state;
364 p_ctx->state=state;
365 }
366
367 }
368
369 static int
370 parser_machine(struct parser_context *p_ctx)
371 {
372 int ch=p_ctx->ch;
373 /* special 'absolute' cases */
374 p_ctx->err="No error.";
375
376 /* chars that end algo strings */
377 switch(ch){
378 case 0: /* end-of-string */
379 case '!': /* flag as strict algo list */
380 case ',': /* algo string separator */
381 switch(p_ctx->state) {
382 case ST_EA:
383 case ST_EK:
384 case ST_AA:
385 case ST_AK:
386 case ST_MODP:
387 case ST_FLAG_STRICT:
388 {
389 enum parser_state_esp next_state=0;
390 switch(ch) {
391 case 0: next_state=ST_EOF;break;
392 case ',': next_state=ST_END;break;
393 case '!': next_state=ST_FLAG_STRICT;break;
394 }
395 /* ch? parser_set_state(p_ctx, ST_END) : parser_set_state(p_ctx, ST_EOF) ; */
396 parser_set_state(p_ctx, next_state);
397 goto out;
398 }
399 default:
400 p_ctx->err="String ended with invalid char";
401 goto err;
402 }
403 }
404 re_eval:
405 switch(p_ctx->state) {
406 case ST_INI:
407 if (isspace(ch))
408 break;
409 if (isalnum(ch)) {
410 *(p_ctx->ealg_str++)=ch;
411 parser_set_state(p_ctx, ST_EA);
412 break;
413 }
414 p_ctx->err="No alphanum. char initially found";
415 goto err;
416
417 case ST_INI_AA:
418 if (isspace(ch))
419 break;
420 if (isalnum(ch)) {
421 *(p_ctx->aalg_str++)=ch;
422 parser_set_state(p_ctx, ST_AA);
423 break;
424 }
425 p_ctx->err="No alphanum. char initially found";
426 goto err;
427
428 case ST_EA:
429 if (isalpha(ch) || ch == '_') {
430 *(p_ctx->ealg_str++)=ch;
431 break;
432 }
433 if (isdigit(ch)) {
434 /* bravely switch to enc keylen */
435 *(p_ctx->ealg_str)=0;
436 parser_set_state(p_ctx, ST_EK);
437 goto re_eval;
438 }
439 if (ch=='-') {
440 *(p_ctx->ealg_str)=0;
441 parser_set_state(p_ctx, ST_EA_END);
442 break;
443 }
444 p_ctx->err="No valid char found after enc alg string";
445 goto err;
446 case ST_EA_END:
447 if (isdigit(ch)) {
448 /* bravely switch to enc keylen */
449 parser_set_state(p_ctx, ST_EK);
450 goto re_eval;
451 }
452 if (isalpha(ch)) {
453 parser_set_state(p_ctx, ST_AA);
454 goto re_eval;
455 }
456 p_ctx->err="No alphanum char found after enc alg separator";
457 goto err;
458 case ST_EK:
459 if (ch=='-') {
460 parser_set_state(p_ctx, ST_EK_END);
461 break;
462 }
463 if (isdigit(ch)) {
464 p_ctx->eklen=p_ctx->eklen*10+ch-'0';
465 break;
466 }
467 p_ctx->err="Non digit or valid separator found while reading enc keylen";
468 goto err;
469 case ST_EK_END:
470 if (isalpha(ch)) {
471 parser_set_state(p_ctx, ST_AA);
472 goto re_eval;
473 }
474 p_ctx->err="Non alpha char found after enc keylen end separator";
475 goto err;
476 case ST_AA:
477 if (ch=='-') {
478 *(p_ctx->aalg_str++)=0;
479 parser_set_state(p_ctx, ST_AA_END);
480 break;
481 }
482 if (ch==';') {
483 *(p_ctx->aalg_str++)=0;
484 parser_set_state(p_ctx, ST_AK_END);
485 break;
486 }
487 if (isalnum(ch) || ch=='_') {
488 *(p_ctx->aalg_str++)=ch;
489 break;
490 }
491 p_ctx->err="Non alphanum or valid separator found in auth string";
492 goto err;
493 case ST_AA_END:
494 if (isdigit(ch)) {
495 parser_set_state(p_ctx, ST_AK);
496 goto re_eval;
497 }
498 /* Only allow modpXXXX string if we have
499 * a modp_getbyname method
500 */
501 if ((p_ctx->modp_getbyname) && isalpha(ch)) {
502 parser_set_state(p_ctx, ST_MODP);
503 goto re_eval;
504 }
505 p_ctx->err="Non initial digit found for auth keylen";
506 goto err;
507 case ST_AK:
508 if (ch=='-'||ch==';') {
509 parser_set_state(p_ctx, ST_AK_END);
510 break;
511 }
512 if (isdigit(ch)) {
513 p_ctx->aklen=p_ctx->aklen*10+ch-'0';
514 break;
515 }
516 p_ctx->err="Non digit found for auth keylen";
517 goto err;
518 case ST_AK_END:
519 /* Only allow modpXXXX string if we have
520 * a modp_getbyname method
521 */
522 if ((p_ctx->modp_getbyname) && isalpha(ch)) {
523 parser_set_state(p_ctx, ST_MODP);
524 goto re_eval;
525 }
526 p_ctx->err="Non alpha char found after auth keylen";
527 goto err;
528 case ST_MODP:
529 if (isalnum(ch)) {
530 *(p_ctx->modp_str++)=ch;
531 break;
532 }
533 p_ctx->err="Non alphanum char found after in modp string";
534 goto err;
535 case ST_FLAG_STRICT:
536 if (ch == 0) {
537 parser_set_state(p_ctx, ST_END);
538 }
539 p_ctx->err="Flags character(s) must be at end of whole string";
540 goto err;
541
542 /* XXX */
543 case ST_END:
544 case ST_EOF:
545 case ST_ERR:
546 break;
547 /* XXX */
548 }
549 out:
550 return p_ctx->state;
551 err:
552 parser_set_state(p_ctx, ST_ERR);
553 return ST_ERR;
554 }
555
556 /*
557 * Must be called for each "new" char, with new
558 * character in ctx.ch
559 */
560 static void
561 parser_init_esp(struct parser_context *p_ctx)
562 {
563 memset(p_ctx, 0, sizeof (*p_ctx));
564
565 p_ctx->protoid=PROTO_IPSEC_ESP;
566 p_ctx->ealg_str=p_ctx->ealg_buf;
567 p_ctx->aalg_str=p_ctx->aalg_buf;
568 p_ctx->modp_str=p_ctx->modp_buf;
569 p_ctx->ealg_permit = TRUE;
570 p_ctx->aalg_permit = TRUE;
571 p_ctx->state=ST_INI;
572
573 p_ctx->ealg_getbyname=ealg_getbyname_esp;
574 p_ctx->aalg_getbyname=aalg_getbyname_esp;
575
576 }
577
578 /*
579 * Must be called for each "new" char, with new
580 * character in ctx.ch
581 */
582 static void
583 parser_init_ah(struct parser_context *p_ctx)
584 {
585 memset(p_ctx, 0, sizeof (*p_ctx));
586
587 p_ctx->protoid=PROTO_IPSEC_AH;
588 p_ctx->ealg_str=NULL;
589 p_ctx->ealg_permit = FALSE;
590 p_ctx->aalg_str=p_ctx->aalg_buf;
591 p_ctx->aalg_permit = TRUE;
592 p_ctx->modp_str=p_ctx->modp_buf;
593 p_ctx->state=ST_INI_AA;
594
595 p_ctx->ealg_getbyname=NULL;
596 p_ctx->aalg_getbyname=aalg_getbyname_esp;
597
598 }
599
600 static int
601 parser_alg_info_add(struct parser_context *p_ctx
602 , struct alg_info *alg_info
603 , void (*alg_info_add)(struct alg_info *alg_info
604 , int ealg_id, int ek_bits
605 , int aalg_id, int ak_bits
606 , int modp_id
607 , bool permitmann)
608 , const struct oakley_group_desc *(*lookup_group)(u_int16_t group)
609 , bool permitike)
610 {
611 int ealg_id, aalg_id;
612 int modp_id = 0;
613 const struct oakley_group_desc *gd;
614
615 ealg_id=aalg_id=-1;
616 if (p_ctx->ealg_permit && *p_ctx->ealg_buf) {
617 ealg_id=p_ctx->ealg_getbyname(p_ctx->ealg_buf, strlen(p_ctx->ealg_buf));
618 if (ealg_id==ESP_MAGIC_ID) {
619 ealg_id=p_ctx->eklen;
620 p_ctx->eklen=0;
621 }
622 if (ealg_id<0) {
623 p_ctx->err="enc_alg not found";
624 goto out;
625 }
626 DBG(DBG_CRYPT, DBG_log("parser_alg_info_add() "
627 "ealg_getbyname(\"%s\")=%d",
628 p_ctx->ealg_buf,
629 ealg_id));
630 }
631 if (p_ctx->aalg_permit && *p_ctx->aalg_buf) {
632 aalg_id=p_ctx->aalg_getbyname(p_ctx->aalg_buf, strlen(p_ctx->aalg_buf));
633 if (aalg_id<0) {
634 p_ctx->err="hash_alg not found";
635 goto out;
636 }
637
638 #ifdef HAVE_LIBNSS
639 if ( Pluto_IsFIPS() && ((aalg_id == OAKLEY_SHA2_256 ) ||(aalg_id == OAKLEY_SHA2_384 ) || (aalg_id == OAKLEY_SHA2_512 )) ) {
640 p_ctx->err="SHA2 Not supported in FIPS mode with NSS";
641 goto out;
642 }
643 #endif
644 DBG(DBG_CRYPT, DBG_log("parser_alg_info_add() "
645 "aalg_getbyname(\"%s\")=%d",
646 p_ctx->aalg_buf,
647 aalg_id));
648 }
649 if (p_ctx->modp_getbyname && *p_ctx->modp_buf) {
650 modp_id=p_ctx->modp_getbyname(p_ctx->modp_buf, strlen(p_ctx->modp_buf));
651 if (modp_id<0) {
652 p_ctx->err="modp group not found";
653 goto out;
654 }
655
656 DBG(DBG_CRYPT, DBG_log("parser_alg_info_add() "
657 "modp_getbyname(\"%s\")=%d",
658 p_ctx->modp_buf,
659 modp_id));
660
661 if (modp_id && !(gd=lookup_group(modp_id))) {
662 p_ctx->err="found modp group id, but not supported";
663 goto out;
664 }
665 }
666
667 (*alg_info_add)(alg_info
668 ,ealg_id, p_ctx->eklen
669 ,aalg_id, p_ctx->aklen
670 ,modp_id, permitike);
671 return 0;
672 out:
673 return -1;
674 }
675
676 int
677 alg_info_parse_str (struct alg_info *alg_info
678 , const char *alg_str
679 , const char **err_p
680 , void (*parser_init)(struct parser_context *p_ctx)
681 , void (*alg_info_add)(struct alg_info *alg_info
682 , int ealg_id, int ek_bits
683 , int aalg_id, int ak_bits
684 , int modp_id
685 , bool permitmann)
686 , const struct oakley_group_desc *(*lookup_group)(u_int16_t group)
687 , bool permitmann)
688 {
689 struct parser_context ctx;
690 int ret;
691 const char *ptr;
692 static char err_buf[256];
693 *err_buf=0;
694
695 (*parser_init)(&ctx);
696
697 if (err_p) *err_p=NULL;
698
699 /* use default if nul esp string */
700 if (!*alg_str) {
701 (*alg_info_add)(alg_info, 0, 0, 0, 0, 0, 0);
702 }
703
704 for(ret=0,ptr=alg_str;ret<ST_EOF;) {
705 ctx.ch=*ptr++;
706 ret= parser_machine(&ctx);
707 switch(ret) {
708 case ST_FLAG_STRICT:
709 alg_info->alg_info_flags |= ALG_INFO_F_STRICT;
710 break;
711
712 case ST_END:
713 case ST_EOF:
714 DBG(DBG_CRYPT, DBG_log("alg_info_parse_str() "
715 "ealg_buf=%s aalg_buf=%s"
716 "eklen=%d aklen=%d",
717 ctx.ealg_buf, ctx.aalg_buf,
718 ctx.eklen, ctx.aklen));
719
720 if (parser_alg_info_add(&ctx, alg_info
721 , alg_info_add
722 , lookup_group
723 , permitmann)<0) {
724 snprintf(err_buf, sizeof(err_buf),
725 "%s, enc_alg=\"%s\", auth_alg=\"%s\", "
726 "modp=\"%s\"",
727 ctx.err,
728 ctx.ealg_buf,
729 ctx.aalg_buf,
730 ctx.modp_buf);
731 goto err;
732 }
733 /* zero out for next run (ST_END) */
734 parser_init(&ctx);
735 break;
736
737 case ST_ERR:
738 snprintf(err_buf, sizeof(err_buf),
739 "%s, "
740 "just after \"%.*s\""
741 " (old_state=%s)",
742 ctx.err,
743 (int)(ptr-alg_str-1), alg_str ,
744 parser_state_name_esp(ctx.old_state) );
745
746 goto err;
747 default:
748 if (!ctx.ch) break;
749 }
750 }
751 return 0;
752 err:
753 if (err_p) {
754 *err_p=err_buf;
755 }
756 return -1;
757 }
758
759 static bool
760 alg_info_discover_pfsgroup_hack(struct alg_info_esp *aie
761 , char *esp_buf
762 , const char **err_p)
763 {
764 char *pfs_name;
765 static char err_buf[256];
766 int ret;
767
768 pfs_name=index(esp_buf, ';');
769
770 if(pfs_name) {
771 *pfs_name='\0';
772 pfs_name++;
773
774 /* if pfs strings AND first char is not '0' */
775 if (*pfs_name && pfs_name[0]!='0') {
776 ret=modp_getbyname_esp(pfs_name, strlen(pfs_name));
777 if (ret<0) {
778 /* Bomb if pfsgroup not found */
779 DBG(DBG_CRYPT, DBG_log("alg_info_*_create_from_str(): "
780 "pfsgroup \"%s\" not found",
781 pfs_name));
782 if (*err_p) {
783 snprintf(err_buf, sizeof(err_buf),
784 "pfsgroup \"%s\" not found",
785 pfs_name);
786 *err_p=err_buf;
787 }
788 return FALSE;
789 }
790 aie->esp_pfsgroup=ret;
791 }
792 } else
793 aie->esp_pfsgroup = 0;
794
795 return TRUE;
796 }
797
798
799 struct alg_info_esp *
800 alg_info_esp_create_from_str (const char *alg_str
801 , const char **err_p
802 , bool permitmann)
803 {
804 struct alg_info_esp *alg_info_esp;
805 char esp_buf[256];
806 int ret =0;
807
808 /*
809 * alg_info storage should be sized dynamically
810 * but this may require 2passes to know
811 * transform count in advance.
812 */
813 alg_info_esp=alloc_thing (struct alg_info_esp, "alg_info_esp");
814
815 if (!alg_info_esp) goto out;
816
817 strcpy(esp_buf, alg_str);
818 if(!alg_info_discover_pfsgroup_hack(alg_info_esp, esp_buf, err_p)) {
819 return NULL;
820 }
821
822 alg_info_esp->alg_info_protoid=PROTO_IPSEC_ESP;
823 ret=alg_info_parse_str((struct alg_info *)alg_info_esp
824 , esp_buf, err_p
825 , parser_init_esp
826 , alg_info_esp_add
827 , NULL
828 , permitmann);
829
830 out:
831 if (ret<0)
832 {
833 pfreeany(alg_info_esp);
834 alg_info_esp=NULL;
835 }
836 return alg_info_esp;
837
838 }
839
840 struct alg_info_esp *
841 alg_info_ah_create_from_str (const char *alg_str
842 , const char **err_p
843 , bool permitmann)
844 {
845 struct alg_info_esp *alg_info_esp;
846 char esp_buf[256];
847 int ret =0;
848
849 /*
850 * alg_info storage should be sized dynamically
851 * but this may require 2passes to know
852 * transform count in advance.
853 */
854 alg_info_esp=alloc_thing (struct alg_info_esp, "alg_info_esp");
855
856 strcpy(esp_buf, alg_str);
857 if(!alg_info_discover_pfsgroup_hack(alg_info_esp, esp_buf, err_p)) {
858 return NULL;
859 }
860
861 alg_info_esp->alg_info_protoid=PROTO_IPSEC_AH;
862 ret=alg_info_parse_str((struct alg_info *)alg_info_esp
863 , esp_buf, err_p
864 , parser_init_ah
865 , alg_info_ah_add
866 , NULL
867 , permitmann);
868
869 if (ret<0)
870 {
871 pfreeany(alg_info_esp);
872 alg_info_esp=NULL;
873 }
874 return alg_info_esp;
875 }
876
877 /*
878 * alg_info struct can be shared by
879 * several connections instances,
880 * handle free() with ref_cnts
881 */
882 void
883 alg_info_addref(struct alg_info *alg_info)
884 {
885 if (alg_info != NULL) {
886 alg_info->ref_cnt++;
887 DBG(DBG_CONTROL, DBG_log("alg_info_addref() "
888 "alg_info->ref_cnt=%d", alg_info->ref_cnt));
889 }
890 }
891 void
892 alg_info_delref(struct alg_info **alg_info_p)
893 {
894 struct alg_info *alg_info=*alg_info_p;
895
896 #if 0
897 DBG(DBG_CONTROL, DBG_log("alg_info_delref(%p) "
898 , alg_info));
899 #endif
900
901 if (alg_info != NULL) {
902 DBG(DBG_CONTROL, DBG_log("alg_info_delref(%p) "
903 "alg_info->ref_cnt=%d"
904 , alg_info, alg_info->ref_cnt));
905 passert(alg_info->ref_cnt != 0);
906 alg_info->ref_cnt--;
907 if (alg_info->ref_cnt==0) {
908 DBG(DBG_CONTROL, DBG_log("alg_info_delref(%p) "
909 "freeing alg_info", alg_info));
910 alg_info_free(alg_info);
911 }
912 *alg_info_p=NULL;
913 }
914 }
915
916 /* snprint already parsed transform list (alg_info) */
917 int
918 alg_info_snprint(char *buf, int buflen
919 , struct alg_info *alg_info
920 , bool permitike)
921 {
922 char *ptr=buf;
923 int np=0;
924 struct esp_info *esp_info;
925 struct ike_info *ike_info;
926
927 int cnt;
928 ptr=buf;
929 switch(alg_info->alg_info_protoid) {
930 case PROTO_IPSEC_ESP:
931 {
932 struct alg_info_esp *alg_info_esp=(struct alg_info_esp *)alg_info;
933 ALG_INFO_ESP_FOREACH(alg_info_esp, esp_info, cnt) {
934 np=snprintf(ptr, buflen, "%s(%d)_%03d-%s(%d)_%03d"
935 , enum_name(&esp_transformid_names, esp_info->esp_ealg_id)+sizeof("ESP")
936 , esp_info->esp_ealg_id
937 , (int)esp_info->esp_ealg_keylen
938 , enum_name(&auth_alg_names, esp_info->esp_aalg_id) + (esp_info->esp_aalg_id ? sizeof("AUTH_ALGORITHM_HMAC") : sizeof("AUTH_ALGORITHM"))
939 , esp_info->esp_aalg_id
940 , (int)esp_info->esp_aalg_keylen);
941 if(np < buflen) {
942 ptr+=np;
943 buflen-=np;
944 } else {
945 ptr+=buflen;
946 buflen=0;
947 }
948 if ( cnt > 0) {
949 np=snprintf(ptr, buflen, ", ");
950 if(np < buflen) {
951 ptr+=np;
952 buflen-=np;
953 } else {
954 ptr+=buflen;
955 buflen=0;
956 }
957 }
958 if(buflen <= 0) goto out;
959 }
960 if (alg_info_esp->esp_pfsgroup) {
961 np=snprintf(ptr, buflen, "; pfsgroup=%s(%d)"
962 , enum_name(&oakley_group_names, alg_info_esp->esp_pfsgroup)+ sizeof("OAKLEY_GROUP")
963 , alg_info_esp->esp_pfsgroup);
964 if(np < buflen) {
965 ptr+=np;
966 buflen-=np;
967 } else {
968 ptr+=buflen;
969 buflen=0;
970 }
971 if(buflen <= 0) goto out;
972 }
973 break;
974 }
975
976 case PROTO_IPSEC_AH:
977 {
978 struct alg_info_esp *alg_info_esp=(struct alg_info_esp *)alg_info;
979 ALG_INFO_ESP_FOREACH(alg_info_esp, esp_info, cnt) {
980 np=snprintf(ptr, buflen, "%s(%d)_%03d"
981 , enum_name(&auth_alg_names, esp_info->esp_aalg_id)+sizeof("AUTH_ALGORITHM_HMAC")
982 , esp_info->esp_aalg_id
983 , (int)esp_info->esp_aalg_keylen);
984 if(np < buflen) {
985 ptr+=np;
986 buflen-=np;
987 } else {
988 ptr+=buflen;
989 buflen=0;
990 }
991 if ( cnt > 0) {
992 np=snprintf(ptr, buflen, ", ");
993 if(np < buflen) {
994 ptr+=np;
995 buflen-=np;
996 } else {
997 ptr+=buflen;
998 buflen=0;
999 }
1000 }
1001 if(buflen <= 0) goto out;
1002 }
1003 if (alg_info_esp->esp_pfsgroup) {
1004 np=snprintf(ptr, buflen, "; pfsgroup=%s(%d)"
1005 , enum_name(&oakley_group_names, alg_info_esp->esp_pfsgroup)+ sizeof("OAKLEY_GROUP")
1006 , alg_info_esp->esp_pfsgroup);
1007 if(np < buflen) {
1008 ptr+=np;
1009 buflen-=np;
1010 } else {
1011 ptr+=buflen;
1012 buflen=0;
1013 }
1014 if(buflen <= 0) goto out;
1015 }
1016 break;
1017 }
1018
1019 case PROTO_ISAKMP:
1020 if(permitike) {
1021 ALG_INFO_IKE_FOREACH((struct alg_info_ike *)alg_info, ike_info, cnt) {
1022 np=snprintf(ptr, buflen, "%s(%d)_%03d-%s(%d)_%03d-%s(%d)"
1023 , enum_name(&oakley_enc_names, ike_info->ike_ealg)+sizeof("OAKLEY")
1024 , ike_info->ike_ealg
1025 , (int)ike_info->ike_eklen
1026 , enum_name(&oakley_hash_names, ike_info->ike_halg)+ sizeof("OAKLEY")
1027 , ike_info->ike_halg
1028 , (int)ike_info->ike_hklen
1029 , enum_name(&oakley_group_names, ike_info->ike_modp)+ sizeof("OAKLEY_GROUP")
1030 , ike_info->ike_modp);
1031 if(np < buflen) {
1032 ptr+=np;
1033 buflen-=np;
1034 } else {
1035 ptr+=buflen;
1036 buflen=0;
1037 }
1038 if ( cnt > 0) {
1039 np=snprintf(ptr, buflen, ", ");
1040 if(np < buflen) {
1041 ptr+=np;
1042 buflen-=np;
1043 } else {
1044 ptr+=buflen;
1045 buflen=0;
1046 }
1047 }
1048 if(buflen <= 0) goto out;
1049 }
1050 break;
1051 }
1052 /* FALLTHROUGH */
1053
1054 default:
1055 np=snprintf(buf, buflen, "INVALID protoid=%d\n",
1056 alg_info->alg_info_protoid);
1057 if(np < buflen) {
1058 ptr+=np;
1059 buflen-=np;
1060 } else {
1061 ptr+=buflen;
1062 buflen=0;
1063 }
1064 goto out;
1065 }
1066 if(buflen > 0){
1067 np=snprintf(ptr, buflen, "; flags=%s",
1068 alg_info->alg_info_flags&ALG_INFO_F_STRICT?
1069 "strict":"-strict");
1070 if(np < buflen) {
1071 ptr+=np;
1072 buflen-=np;
1073 } else {
1074 ptr+=buflen;
1075 buflen=0;
1076 }
1077 }
1078
1079 out:
1080 passert(buflen >= 0);
1081
1082 return ptr-buf;
1083 }
1084
1085 /*
1086 * Local Variables:
1087 * c-basic-offset:4
1088 * c-style: pluto
1089 * End:
1090 */

  ViewVC Help
Powered by ViewVC 1.1.5