/* * FreeS/WAN config file parser (keywords.c) * Copyright (C) 2003 Michael Richardson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * RCSID $Id: keywords.c,v 1.5 2004/01/21 01:35:03 mcr Exp $ */ #define DEBUG #include #include #include #include #include "freeswan.h" #include "pluto/constants.h" #include "parser.h" #include "keywords.h" #include "parser.tab.h" #include "parserlast.h" struct keyword_enum_value kw_klipsdebug_values[]={ { "all", LRANGE(KDF_XMIT, KDF_COMP) }, { "none", 0 }, { "verbose", LELEM(KDF_VERBOSE) }, { "xmit", LELEM(KDF_XMIT) }, { "tunnel-xmit", LELEM(KDF_XMIT) }, { "netlink", LELEM(KDF_NETLINK) }, { "xform", LELEM(KDF_XFORM) }, { "eroute", LELEM(KDF_EROUTE) }, { "spi", LELEM(KDF_SPI) }, { "radij", LELEM(KDF_RADIJ) }, { "esp", LELEM(KDF_ESP) }, { "ah", LELEM(KDF_AH) }, { "rcv", LELEM(KDF_RCV) }, { "tunnel", LELEM(KDF_TUNNEL) }, { "pfkey", LELEM(KDF_PFKEY) }, { "comp", LELEM(KDF_COMP) }, }; struct keyword_enum_values kw_klipsdebug_list= { kw_klipsdebug_values, sizeof(kw_klipsdebug_values)/sizeof(struct keyword_enum_value)}; struct keyword_enum_value kw_plutodebug_values[]={ { "none", DBG_NONE }, { "all", DBG_ALL }, { "raw", DBG_RAW }, { "crypt", DBG_CRYPT }, { "parsing", DBG_PARSING }, { "emitting", DBG_EMITTING }, { "control", DBG_CONTROL }, { "lifecycle", DBG_LIFECYCLE }, { "klips", DBG_KLIPS }, { "dns", DBG_DNS }, { "oppo", DBG_OPPO }, { "controlmore", DBG_CONTROLMORE }, { "private", DBG_PRIVATE }, { "impair-delay-adns-key-answer", IMPAIR_DELAY_ADNS_KEY_ANSWER }, { "impair-delay-adns-txt-answer", IMPAIR_DELAY_ADNS_TXT_ANSWER }, { "impair-bust-mi2", IMPAIR_BUST_MI2 }, { "impair-bust-mr2", IMPAIR_BUST_MR2 }, }; struct keyword_enum_values kw_plutodebug_list= { kw_plutodebug_values, sizeof(kw_plutodebug_values)/sizeof(struct keyword_enum_value)}; /* * Values for right= and left= */ extern struct keyword_enum_values kw_host_list; /* * Values for keyexchange= */ struct keyword_enum_value kw_keyexchange_values[]={ { "ike", KH_IKE }, }; struct keyword_enum_values kw_keyexchange_list= { kw_keyexchange_values, sizeof(kw_keyexchange_values)/sizeof(struct keyword_enum_value)}; /* * Values for auth={add,start,route,ignore} */ struct keyword_enum_value kw_auto_values[]={ { "ignore", STARTUP_NO }, { "add", STARTUP_ADD }, { "route", STARTUP_ROUTE }, { "start", STARTUP_START }, }; struct keyword_enum_values kw_auto_list= { kw_auto_values, sizeof(kw_auto_values)/sizeof(struct keyword_enum_value)}; /* * Values for type={tunnel,transport,udpencap} */ struct keyword_enum_value kw_type_values[]={ { "tunnel", KS_TUNNEL }, { "transport", KS_TRANSPORT }, { "udpencap", KS_UDPENCAP }, { "passthrough", KS_PASSTHROUGH }, { "udp", KS_UDPENCAP }, { "pass", KS_PASSTHROUGH }, { "reject", KS_REJECT }, { "drop", KS_DROP }, }; struct keyword_enum_values kw_type_list= { kw_type_values, sizeof(kw_type_values)/sizeof(struct keyword_enum_value)}; /* * Values for authby={rsasig, secret} */ struct keyword_enum_value kw_authby_values[]={ { "rsasig", POLICY_RSASIG}, { "secret", POLICY_PSK}, }; struct keyword_enum_values kw_authby_list= { kw_authby_values, sizeof(kw_authby_values)/sizeof(struct keyword_enum_value)}; /* * Values for failureshunt={passthrough, drop, reject, none} */ struct keyword_enum_value kw_failureshunt_values[]={ { "none", POLICY_FAIL_NONE }, { "passthrough", POLICY_FAIL_PASS }, { "drop", POLICY_FAIL_DROP }, { "reject", POLICY_FAIL_REJECT }, }; struct keyword_enum_values kw_failureshunt_list= { kw_failureshunt_values, sizeof(kw_failureshunt_values)/sizeof(struct keyword_enum_value)}; /* * Values for rsasigkey={%dnsondemand, %dns, literal } */ struct keyword_enum_value kw_rsasigkey_values[]={ { "", PUBKEY_PREEXCHANGED }, { "%dns", PUBKEY_DNS }, { "%dnsondemand", PUBKEY_DNSONDEMAND }, }; struct keyword_enum_values kw_rsasigkey_list= { kw_rsasigkey_values, sizeof(kw_rsasigkey_values)/sizeof(struct keyword_enum_value)}; struct keyword_def ipsec_conf_keywords_v2[]={ {"interfaces", kv_config, kt_string, KSF_INTERFACES,NOT_ENUM}, {"forwardcontrol", kv_config, kt_bool, KBF_FORWARDCONTROL,NOT_ENUM}, {"myid", kv_config, kt_string, KSF_MYID,NOT_ENUM}, {"syslog", kv_config, kt_string, KSF_SYSLOG,NOT_ENUM}, {"klipsdebug", kv_config, kt_list, KBF_KLIPSDEBUG, &kw_klipsdebug_list}, {"plutodebug", kv_config, kt_list, KBF_PLUTODEBUG, &kw_plutodebug_list}, {"plutoopts", kv_config, kt_string, KSF_PLUTOOPTS,NOT_ENUM}, {"plutostderrlog", kv_config, kt_filename, KSF_PLUTOSTDERRLOG,NOT_ENUM}, {"plutorestartoncrash", kv_config, kt_bool, KBF_PLUTORESTARTONCRASH,NOT_ENUM}, {"dumpdir", kv_config, kt_dirname, KSF_DUMPDIR,NOT_ENUM}, {"manualstart", kv_config, kt_string, KSF_MANUALSTART,NOT_ENUM}, {"pluto", kv_config, kt_filename, KSF_PLUTO, NOT_ENUM}, {"plutowait", kv_config, kt_bool, KBF_PLUTOWAIT,NOT_ENUM}, {"prepluto", kv_config, kt_filename, KSF_PREPLUTO,NOT_ENUM}, {"postpluto", kv_config, kt_filename, KSF_POSTPLUTO,NOT_ENUM}, {"fragicmp", kv_config, kt_bool, KBF_FRAGICMP,NOT_ENUM}, {"hidetos", kv_config, kt_bool, KBF_HIDETOS,NOT_ENUM}, {"rp_filter", kv_config, kt_enum, KBF_RPFILTER,NOT_ENUM}, {"uniqueids", kv_config, kt_bool, KBF_UNIQUEIDS,NOT_ENUM}, {"overridemtu", kv_config, kt_number, KBF_OVERRIDEMTU,NOT_ENUM}, {"nocrsend", kv_config, kt_bool, KBF_NOCRSEND,NOT_ENUM}, {"strictcrlpolicy",kv_config, kt_enum, KBF_STRICTCRLPOLICY,NOT_ENUM}, {"crlcheckinterval",kv_config,kt_time, KBF_CRLCHECKINTERVAL,NOT_ENUM}, /* this is "left=" and "right=" */ {"", kv_conn|kv_leftright, kt_loose_enum, KSCF_IP, &kw_host_list}, {"subnet", kv_conn|kv_leftright, kt_subnet, KSCF_SUBNET,NOT_ENUM}, {"nexthop", kv_conn|kv_leftright, kt_ipaddr, KSCF_NEXTHOP,NOT_ENUM}, {"firewall", kv_conn|kv_leftright, kt_bool, KNCF_FIREWALL,NOT_ENUM}, {"updown", kv_conn|kv_leftright, kt_filename, KSCF_UPDOWN,NOT_ENUM}, {"id", kv_conn|kv_leftright, kt_idtype, KSCF_ID,NOT_ENUM}, {"rsasigkey", kv_conn|kv_leftright, kt_rsakey, KSCF_RSAKEY1, &kw_rsasigkey_list}, {"rsasigkey2", kv_conn|kv_leftright, kt_rsakey, KSCF_RSAKEY2, &kw_rsasigkey_list}, {"spibase", kv_conn|kv_auto|kv_leftright, kt_number, KNCF_SPIBASE,NOT_ENUM}, {"cert", kv_conn|kv_leftright, kt_filename, KSCF_CERT,NOT_ENUM}, {"ca", kv_conn|kv_leftright, kt_string, KSCF_CA,NOT_ENUM}, {"subnetwithin", kv_conn|kv_leftright, kt_string, KSCF_SUBNETWITHIN,NOT_ENUM}, {"protoport", kv_conn|kv_leftright, kt_string, KSCF_PROTOPORT,NOT_ENUM}, {"auto", kv_conn, kt_enum, KBF_AUTO, &kw_auto_list}, {"also", kv_conn, kt_appendstring, KSF_ALSO,NOT_ENUM}, {"alsoflip", kv_conn, kt_string, KSF_ALSOFLIP,NOT_ENUM}, {"type", kv_conn, kt_enum, KBF_TYPE, &kw_type_list}, {"authby", kv_conn|kv_auto, kt_string, KBF_AUTHBY, &kw_authby_list}, {"keyexchange", kv_conn|kv_auto, kt_enum, KBF_KEYEXCHANGE, &kw_keyexchange_list}, {"pfs", kv_conn|kv_auto, kt_bool, KBF_PFS, NOT_ENUM}, {"keylife", kv_conn|kv_auto, kt_time, KBF_SALIFETIME,NOT_ENUM}, {"lifetime", kv_conn|kv_auto, kt_time, KBF_SALIFETIME,NOT_ENUM}, {"salifetime", kv_conn|kv_auto, kt_time, KBF_SALIFETIME,NOT_ENUM}, {"rekey", kv_conn|kv_auto, kt_bool, KBF_REKEY, NOT_ENUM}, {"rekeymargin", kv_conn|kv_auto, kt_time, KBF_REKEYMARGIN,NOT_ENUM}, {"rekeyfuzz", kv_conn|kv_auto, kt_time, KBF_REKEYFUZZ,NOT_ENUM}, {"compress", kv_conn|kv_auto, kt_bool, KBF_COMPRESS,NOT_ENUM}, {"keyingtries", kv_conn|kv_auto, kt_number, KBF_KEYINGTRIES,NOT_ENUM}, {"ikelifetime", kv_conn|kv_auto, kt_time, KBF_IKELIFETIME,NOT_ENUM}, {"disablearrivalcheck", kv_conn|kv_auto, kt_invertbool, KBF_ARRIVALCHECK,NOT_ENUM}, {"failureshunt", kv_conn|kv_auto, kt_enum, KBF_FAILURESHUNT, &kw_failureshunt_list}, /* things for manual keying only */ {"spi", kv_conn|kv_leftright|kv_manual, kt_number, KNCF_SPI,NOT_ENUM}, {"esp", kv_conn|kv_leftright|kv_manual, kt_string, KSCF_ESP,NOT_ENUM}, {"espenckey", kv_conn|kv_leftright|kv_manual, kt_bitstring, KSCF_ESPENCKEY,NOT_ENUM}, {"espauthkey", kv_conn|kv_leftright|kv_manual, kt_bitstring, KSCF_ESPAUTHKEY,NOT_ENUM}, {"espreplay_window",kv_conn|kv_leftright|kv_manual, kt_number, KNCF_ESPREPLAYWINDOW,NOT_ENUM}, {NULL, 0, 0, 0, NOT_ENUM} }; /* * look for one of the above tokens, and set the value up right. * * if we don't find it, then strdup() the string and return a string * */ /* type is really "token" type, which is actually int */ int parser_find_keyword(const char *s, YYSTYPE *lval) { struct keyword_def *k; bool keyleft; int keywordtype; keyleft=FALSE; k = ipsec_conf_keywords_v2; while(k->keyname != NULL) { if(strcasecmp(s, k->keyname) == 0) { break; } if(k->validity & kv_leftright) { if(strncasecmp(s, "left", 4)==0 && strcasecmp(s+4, k->keyname)==0) { keyleft=TRUE; break; } else if(strncasecmp(s, "right", 5)==0 && strcasecmp(s+5, k->keyname)==0) { keyleft=FALSE; break; } } k++; } /* if we found nothing */ if(k->keyname == NULL) { lval->s = strdup(s); return STRING; } switch(k->type) { case kt_percent: keywordtype = PERCENTWORD; break; case kt_time: keywordtype = TIMEWORD; break; case kt_bool: keywordtype = BOOLWORD; break; default: keywordtype = KEYWORD; break; } /* else, set up llval.k to point, and return KEYWORD */ lval->k.keydef = k; lval->k.keyleft = keyleft; return keywordtype; } unsigned int parser_enum_list(struct keyword_def *kd, const char *s, bool list) { char *piece; char *scopy; int numfound, kevcount; struct keyword_enum_value *kev; unsigned int valresult; char complaintbuf[80]; assert(kd->type == kt_list || kd->type == kt_enum); scopy = strdup(s); valresult = 0; /* * split up the string into comma seperated pieces, and look each piece up in the * value list provided in the definition. */ numfound=0; while((piece = strsep(&scopy, ":, \t")) != NULL) { /* discard empty strings */ if(strlen(piece) == 0) { continue; } assert(kd->validenum != NULL); for(kevcount = kd->validenum->valuesize, kev = kd->validenum->values; kevcount > 0 && strcasecmp(piece, kev->name)!=0; kev++, kevcount--); /* if we found something */ if(kevcount != 0) { /* count it */ numfound++; valresult |= kev->value; } else { /* we didn't find anything, complain */ snprintf(complaintbuf, sizeof(complaintbuf) , "%s: %d: keyword %s, invalid value: %s" , parser_cur_filename(), parser_cur_lineno() , kd->keyname, piece); if(warningsarefatal) { fprintf(stderr, "ERROR: %s\n", complaintbuf); exit(1); } else { fprintf(stderr, "WARNING: %s\n", complaintbuf); } } } if(numfound > 1 && !list) { snprintf(complaintbuf, sizeof(complaintbuf) , "%s: %d: keyword %s accepts only one value, not %s" , parser_cur_filename(), parser_cur_lineno() , kd->keyname, scopy); if(warningsarefatal) { fprintf(stderr, "ERROR: %s\n", complaintbuf); free(scopy); exit(1); } else { fprintf(stderr, "WARNING: %s\n", complaintbuf); valresult=0; } } free(scopy); return valresult; } unsigned int parser_loose_enum(struct keyword *k, const char *s) { struct keyword_def *kd = k->keydef; int kevcount; struct keyword_enum_value *kev; unsigned int valresult; assert(kd->type == kt_loose_enum || kd->type == kt_rsakey); assert(kd->validenum != NULL && kd->validenum->values != NULL); for(kevcount = kd->validenum->valuesize, kev = kd->validenum->values; kevcount > 0 && strcasecmp(s, kev->name)!=0; kev++, kevcount--); /* if we found something */ if(kevcount != 0) { assert(kev->value != 0); valresult = kev->value; k->string = NULL; return valresult; } k->string = strdup(s); return 255; } /* * Local Variables: * c-basic-offset:4 * c-style: pluto * End: */