From 3d7a244b5470e104539580c7bc489d7b581430eb Mon Sep 17 00:00:00 2001 From: Andreas Steffen Date: Sun, 19 Apr 2009 19:16:09 +0000 Subject: [PATCH] conversion from 8 spaces to 4 spaces per tab --- src/pluto/ac.c | 1384 +++--- src/pluto/ac.h | 54 +- src/pluto/adns.c | 718 +-- src/pluto/adns.h | 54 +- src/pluto/alg_info.c | 1664 +++---- src/pluto/alg_info.h | 64 +- src/pluto/asn1.c | 1096 ++--- src/pluto/asn1.h | 124 +- src/pluto/ca.c | 904 ++-- src/pluto/ca.h | 40 +- src/pluto/certs.c | 296 +- src/pluto/certs.h | 38 +- src/pluto/connections.c | 6560 +++++++++++++-------------- src/pluto/connections.h | 266 +- src/pluto/constants.c | 1650 +++---- src/pluto/constants.h | 976 ++-- src/pluto/cookie.c | 50 +- src/pluto/cookie.h | 4 +- src/pluto/crl.c | 1106 ++--- src/pluto/crl.h | 32 +- src/pluto/crypto.c | 646 +-- src/pluto/crypto.h | 68 +- src/pluto/db_ops.c | 520 +-- src/pluto/db_ops.h | 34 +- src/pluto/defs.c | 186 +- src/pluto/defs.h | 34 +- src/pluto/demux.c | 3860 ++++++++-------- src/pluto/demux.h | 62 +- src/pluto/dnskey.c | 2514 +++++------ src/pluto/dnskey.h | 68 +- src/pluto/dsa.c | 530 +-- src/pluto/dsa.h | 6 +- src/pluto/elgamal.c | 714 +-- src/pluto/elgamal.h | 6 +- src/pluto/fetch.c | 1180 ++--- src/pluto/fetch.h | 26 +- src/pluto/foodgroups.c | 588 +-- src/pluto/foodgroups.h | 2 +- src/pluto/gcryptfix.c | 266 +- src/pluto/gcryptfix.h | 26 +- src/pluto/id.c | 660 +-- src/pluto/id.h | 30 +- src/pluto/ike_alg.c | 718 +-- src/pluto/ike_alg.h | 74 +- src/pluto/ipsec_doi.c | 8354 +++++++++++++++++------------------ src/pluto/ipsec_doi.h | 78 +- src/pluto/kameipsec.h | 46 +- src/pluto/kernel.c | 4502 +++++++++---------- src/pluto/kernel.h | 200 +- src/pluto/kernel_alg.c | 1078 ++--- src/pluto/kernel_netlink.c | 1680 +++---- src/pluto/kernel_noklips.c | 58 +- src/pluto/kernel_pfkey.c | 1178 ++--- src/pluto/keys.c | 2046 ++++----- src/pluto/keys.h | 64 +- src/pluto/lex.c | 254 +- src/pluto/lex.h | 18 +- src/pluto/library.c | 80 +- src/pluto/library.h | 30 +- src/pluto/log.c | 986 ++--- src/pluto/log.h | 102 +- src/pluto/md2.c | 58 +- src/pluto/md2.h | 6 +- src/pluto/md5.c | 36 +- src/pluto/md5.h | 6 +- src/pluto/modecfg.c | 1858 ++++---- src/pluto/mp_defs.c | 48 +- src/pluto/mp_defs.h | 10 +- src/pluto/nat_traversal.c | 1216 ++--- src/pluto/nat_traversal.h | 60 +- src/pluto/ocsp.c | 1964 ++++---- src/pluto/ocsp.h | 62 +- src/pluto/packet.c | 1278 +++--- src/pluto/packet.h | 310 +- src/pluto/pem.c | 576 +-- src/pluto/pem.h | 2 +- src/pluto/pgp.c | 844 ++-- src/pluto/pgp.h | 20 +- src/pluto/pkcs1.c | 856 ++-- src/pluto/pkcs1.h | 46 +- src/pluto/pkcs7.c | 1222 ++--- src/pluto/pkcs7.h | 14 +- src/pluto/plutomain.c | 1140 ++--- src/pluto/primegen.c | 882 ++-- src/pluto/rcv_whack.c | 1060 ++--- src/pluto/rnd.c | 126 +- src/pluto/server.c | 1428 +++--- src/pluto/server.h | 26 +- src/pluto/sha1.c | 202 +- src/pluto/sha1.h | 6 +- src/pluto/smallprime.c | 162 +- src/pluto/smartcard.c | 2658 +++++------ src/pluto/smartcard.h | 54 +- src/pluto/spdb.c | 3834 ++++++++-------- src/pluto/spdb.h | 82 +- src/pluto/state.c | 1198 ++--- src/pluto/state.h | 252 +- src/pluto/timer.c | 806 ++-- src/pluto/timer.h | 12 +- src/pluto/vendor.c | 762 ++-- src/pluto/vendor.h | 250 +- src/pluto/virtual.c | 406 +- src/pluto/virtual.h | 4 +- src/pluto/x509.c | 3214 +++++++------- src/pluto/x509.h | 86 +- src/pluto/xauth.c | 72 +- src/pluto/xauth.h | 16 +- src/scepclient/loglite.c | 288 +- src/scepclient/pkcs10.c | 200 +- src/scepclient/pkcs10.h | 18 +- src/scepclient/rsakey.c | 434 +- src/scepclient/rsakey.h | 2 +- src/scepclient/scep.c | 720 +-- src/scepclient/scep.h | 34 +- src/scepclient/scepclient.c | 1734 ++++---- src/starter/args.c | 968 ++-- src/starter/args.h | 6 +- src/starter/cmp.c | 84 +- src/starter/confread.c | 1726 ++++---- src/starter/confread.h | 294 +- src/starter/exec.c | 24 +- src/starter/files.h | 10 +- src/starter/interfaces.c | 196 +- src/starter/interfaces.h | 8 +- src/starter/invokecharon.c | 330 +- src/starter/invokepluto.c | 482 +- src/starter/keywords.h | 306 +- src/starter/klips.c | 80 +- src/starter/loglite.c | 288 +- src/starter/netkey.c | 84 +- src/starter/parser.h | 22 +- src/starter/parser.l | 206 +- src/starter/parser.y | 334 +- src/starter/starter.c | 1208 ++--- src/starter/starterstroke.c | 492 +-- src/starter/starterwhack.c | 542 +-- src/whack/whack.c | 3198 +++++++------- src/whack/whack.h | 412 +- 138 files changed, 47306 insertions(+), 47306 deletions(-) diff --git a/src/pluto/ac.c b/src/pluto/ac.c index d7aca06a3..d661557db 100644 --- a/src/pluto/ac.c +++ b/src/pluto/ac.c @@ -50,161 +50,161 @@ static ietfAttrList_t *ietfAttributes = NULL; static const asn1Object_t ietfAttrSyntaxObjects[] = { - { 0, "ietfAttrSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "policyAuthority", ASN1_CONTEXT_C_0, ASN1_OPT | - ASN1_BODY }, /* 1 */ - { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */ - { 1, "values", ASN1_SEQUENCE, ASN1_LOOP }, /* 3 */ - { 2, "octets", ASN1_OCTET_STRING, ASN1_OPT | - ASN1_BODY }, /* 4 */ - { 2, "end choice", ASN1_EOC, ASN1_END }, /* 5 */ - { 2, "oid", ASN1_OID, ASN1_OPT | - ASN1_BODY }, /* 6 */ - { 2, "end choice", ASN1_EOC, ASN1_END }, /* 7 */ - { 2, "string", ASN1_UTF8STRING, ASN1_OPT | - ASN1_BODY }, /* 8 */ - { 2, "end choice", ASN1_EOC, ASN1_END }, /* 9 */ - { 1, "end loop", ASN1_EOC, ASN1_END } /* 10 */ + { 0, "ietfAttrSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ + { 1, "policyAuthority", ASN1_CONTEXT_C_0, ASN1_OPT | + ASN1_BODY }, /* 1 */ + { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */ + { 1, "values", ASN1_SEQUENCE, ASN1_LOOP }, /* 3 */ + { 2, "octets", ASN1_OCTET_STRING, ASN1_OPT | + ASN1_BODY }, /* 4 */ + { 2, "end choice", ASN1_EOC, ASN1_END }, /* 5 */ + { 2, "oid", ASN1_OID, ASN1_OPT | + ASN1_BODY }, /* 6 */ + { 2, "end choice", ASN1_EOC, ASN1_END }, /* 7 */ + { 2, "string", ASN1_UTF8STRING, ASN1_OPT | + ASN1_BODY }, /* 8 */ + { 2, "end choice", ASN1_EOC, ASN1_END }, /* 9 */ + { 1, "end loop", ASN1_EOC, ASN1_END } /* 10 */ }; -#define IETF_ATTR_OCTETS 4 -#define IETF_ATTR_OID 6 -#define IETF_ATTR_STRING 8 -#define IETF_ATTR_ROOF 11 +#define IETF_ATTR_OCTETS 4 +#define IETF_ATTR_OID 6 +#define IETF_ATTR_STRING 8 +#define IETF_ATTR_ROOF 11 /* ASN.1 definition of roleSyntax */ static const asn1Object_t roleSyntaxObjects[] = { - { 0, "roleSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "roleAuthority", ASN1_CONTEXT_C_0, ASN1_OPT | - ASN1_OBJ }, /* 1 */ - { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */ - { 1, "roleName", ASN1_CONTEXT_C_1, ASN1_OBJ } /* 3 */ + { 0, "roleSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ + { 1, "roleAuthority", ASN1_CONTEXT_C_0, ASN1_OPT | + ASN1_OBJ }, /* 1 */ + { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */ + { 1, "roleName", ASN1_CONTEXT_C_1, ASN1_OBJ } /* 3 */ }; -#define ROLE_ROOF 4 +#define ROLE_ROOF 4 /* ASN.1 definition of an X509 attribute certificate */ static const asn1Object_t acObjects[] = { - { 0, "AttributeCertificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */ + { 0, "AttributeCertificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */ { 1, "AttributeCertificateInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */ - { 2, "version", ASN1_INTEGER, ASN1_DEF | - ASN1_BODY }, /* 2 */ - { 2, "holder", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */ - { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 4 */ - { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */ - { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 6 */ - { 4, "issuerUID", ASN1_BIT_STRING, ASN1_OPT | - ASN1_BODY }, /* 7 */ - { 4, "end opt", ASN1_EOC, ASN1_END }, /* 8 */ - { 3, "end opt", ASN1_EOC, ASN1_END }, /* 9 */ - { 3, "entityName", ASN1_CONTEXT_C_1, ASN1_OPT | - ASN1_OBJ }, /* 10 */ - { 3, "end opt", ASN1_EOC, ASN1_END }, /* 11 */ - { 3, "objectDigestInfo", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 12 */ - { 4, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 13*/ - { 4, "otherObjectTypeID", ASN1_OID, ASN1_OPT | - ASN1_BODY }, /* 14 */ - { 4, "end opt", ASN1_EOC, ASN1_END }, /* 15*/ - { 4, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 16 */ - { 3, "end opt", ASN1_EOC, ASN1_END }, /* 17 */ - { 2, "v2Form", ASN1_CONTEXT_C_0, ASN1_NONE }, /* 18 */ - { 3, "issuerName", ASN1_SEQUENCE, ASN1_OPT | - ASN1_OBJ }, /* 19 */ - { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */ - { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 21 */ - { 4, "issuerSerial", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */ - { 5, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 23 */ - { 5, "serial", ASN1_INTEGER, ASN1_BODY }, /* 24 */ - { 5, "issuerUID", ASN1_BIT_STRING, ASN1_OPT | - ASN1_BODY }, /* 25 */ - { 5, "end opt", ASN1_EOC, ASN1_END }, /* 26 */ - { 3, "end opt", ASN1_EOC, ASN1_END }, /* 27 */ - { 3, "objectDigestInfo", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 28 */ - { 4, "digestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 29 */ - { 5, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 30 */ - { 5, "otherObjectTypeID", ASN1_OID, ASN1_OPT | - ASN1_BODY }, /* 31 */ - { 5, "end opt", ASN1_EOC, ASN1_END }, /* 32 */ - { 5, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 33 */ - { 3, "end opt", ASN1_EOC, ASN1_END }, /* 34 */ - { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 35 */ - { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 36 */ - { 2, "attrCertValidityPeriod", ASN1_SEQUENCE, ASN1_NONE }, /* 37 */ - { 3, "notBeforeTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 38 */ - { 3, "notAfterTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 39 */ - { 2, "attributes", ASN1_SEQUENCE, ASN1_LOOP }, /* 40 */ - { 3, "attribute", ASN1_SEQUENCE, ASN1_NONE }, /* 41 */ - { 4, "type", ASN1_OID, ASN1_BODY }, /* 42 */ - { 4, "values", ASN1_SET, ASN1_LOOP }, /* 43 */ - { 5, "value", ASN1_EOC, ASN1_RAW }, /* 44 */ - { 4, "end loop", ASN1_EOC, ASN1_END }, /* 45 */ - { 2, "end loop", ASN1_EOC, ASN1_END }, /* 46 */ - { 2, "extensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 47 */ - { 3, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 48 */ - { 4, "extnID", ASN1_OID, ASN1_BODY }, /* 49 */ - { 4, "critical", ASN1_BOOLEAN, ASN1_DEF | - ASN1_BODY }, /* 50 */ - { 4, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 51 */ - { 2, "end loop", ASN1_EOC, ASN1_END }, /* 52 */ - { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 53 */ - { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY } /* 54 */ + { 2, "version", ASN1_INTEGER, ASN1_DEF | + ASN1_BODY }, /* 2 */ + { 2, "holder", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */ + { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 4 */ + { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */ + { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 6 */ + { 4, "issuerUID", ASN1_BIT_STRING, ASN1_OPT | + ASN1_BODY }, /* 7 */ + { 4, "end opt", ASN1_EOC, ASN1_END }, /* 8 */ + { 3, "end opt", ASN1_EOC, ASN1_END }, /* 9 */ + { 3, "entityName", ASN1_CONTEXT_C_1, ASN1_OPT | + ASN1_OBJ }, /* 10 */ + { 3, "end opt", ASN1_EOC, ASN1_END }, /* 11 */ + { 3, "objectDigestInfo", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 12 */ + { 4, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 13*/ + { 4, "otherObjectTypeID", ASN1_OID, ASN1_OPT | + ASN1_BODY }, /* 14 */ + { 4, "end opt", ASN1_EOC, ASN1_END }, /* 15*/ + { 4, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 16 */ + { 3, "end opt", ASN1_EOC, ASN1_END }, /* 17 */ + { 2, "v2Form", ASN1_CONTEXT_C_0, ASN1_NONE }, /* 18 */ + { 3, "issuerName", ASN1_SEQUENCE, ASN1_OPT | + ASN1_OBJ }, /* 19 */ + { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */ + { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 21 */ + { 4, "issuerSerial", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */ + { 5, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 23 */ + { 5, "serial", ASN1_INTEGER, ASN1_BODY }, /* 24 */ + { 5, "issuerUID", ASN1_BIT_STRING, ASN1_OPT | + ASN1_BODY }, /* 25 */ + { 5, "end opt", ASN1_EOC, ASN1_END }, /* 26 */ + { 3, "end opt", ASN1_EOC, ASN1_END }, /* 27 */ + { 3, "objectDigestInfo", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 28 */ + { 4, "digestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 29 */ + { 5, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 30 */ + { 5, "otherObjectTypeID", ASN1_OID, ASN1_OPT | + ASN1_BODY }, /* 31 */ + { 5, "end opt", ASN1_EOC, ASN1_END }, /* 32 */ + { 5, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 33 */ + { 3, "end opt", ASN1_EOC, ASN1_END }, /* 34 */ + { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 35 */ + { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 36 */ + { 2, "attrCertValidityPeriod", ASN1_SEQUENCE, ASN1_NONE }, /* 37 */ + { 3, "notBeforeTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 38 */ + { 3, "notAfterTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 39 */ + { 2, "attributes", ASN1_SEQUENCE, ASN1_LOOP }, /* 40 */ + { 3, "attribute", ASN1_SEQUENCE, ASN1_NONE }, /* 41 */ + { 4, "type", ASN1_OID, ASN1_BODY }, /* 42 */ + { 4, "values", ASN1_SET, ASN1_LOOP }, /* 43 */ + { 5, "value", ASN1_EOC, ASN1_RAW }, /* 44 */ + { 4, "end loop", ASN1_EOC, ASN1_END }, /* 45 */ + { 2, "end loop", ASN1_EOC, ASN1_END }, /* 46 */ + { 2, "extensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 47 */ + { 3, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 48 */ + { 4, "extnID", ASN1_OID, ASN1_BODY }, /* 49 */ + { 4, "critical", ASN1_BOOLEAN, ASN1_DEF | + ASN1_BODY }, /* 50 */ + { 4, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 51 */ + { 2, "end loop", ASN1_EOC, ASN1_END }, /* 52 */ + { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 53 */ + { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY } /* 54 */ }; -#define AC_OBJ_CERTIFICATE 0 -#define AC_OBJ_CERTIFICATE_INFO 1 -#define AC_OBJ_VERSION 2 -#define AC_OBJ_HOLDER_ISSUER 5 -#define AC_OBJ_HOLDER_SERIAL 6 -#define AC_OBJ_ENTITY_NAME 10 -#define AC_OBJ_ISSUER_NAME 19 -#define AC_OBJ_ISSUER 23 -#define AC_OBJ_SIG_ALG 35 -#define AC_OBJ_SERIAL_NUMBER 36 -#define AC_OBJ_NOT_BEFORE 38 -#define AC_OBJ_NOT_AFTER 39 -#define AC_OBJ_ATTRIBUTE_TYPE 42 -#define AC_OBJ_ATTRIBUTE_VALUE 44 -#define AC_OBJ_EXTN_ID 49 -#define AC_OBJ_CRITICAL 50 -#define AC_OBJ_EXTN_VALUE 51 -#define AC_OBJ_ALGORITHM 53 -#define AC_OBJ_SIGNATURE 54 -#define AC_OBJ_ROOF 55 +#define AC_OBJ_CERTIFICATE 0 +#define AC_OBJ_CERTIFICATE_INFO 1 +#define AC_OBJ_VERSION 2 +#define AC_OBJ_HOLDER_ISSUER 5 +#define AC_OBJ_HOLDER_SERIAL 6 +#define AC_OBJ_ENTITY_NAME 10 +#define AC_OBJ_ISSUER_NAME 19 +#define AC_OBJ_ISSUER 23 +#define AC_OBJ_SIG_ALG 35 +#define AC_OBJ_SERIAL_NUMBER 36 +#define AC_OBJ_NOT_BEFORE 38 +#define AC_OBJ_NOT_AFTER 39 +#define AC_OBJ_ATTRIBUTE_TYPE 42 +#define AC_OBJ_ATTRIBUTE_VALUE 44 +#define AC_OBJ_EXTN_ID 49 +#define AC_OBJ_CRITICAL 50 +#define AC_OBJ_EXTN_VALUE 51 +#define AC_OBJ_ALGORITHM 53 +#define AC_OBJ_SIGNATURE 54 +#define AC_OBJ_ROOF 55 const x509acert_t empty_ac = { - NULL , /* *next */ - 0 , /* installed */ - { NULL, 0 }, /* certificate */ - { NULL, 0 }, /* certificateInfo */ - 1 , /* version */ - /* holder */ - /* baseCertificateID */ - { NULL, 0 }, /* holderIssuer */ - { NULL, 0 }, /* holderSerial */ - /* entityName */ - { NULL, 0 }, /* generalNames */ - /* v2Form */ - { NULL, 0 }, /* issuerName */ - /* signature */ - OID_UNKNOWN, /* sigAlg */ - { NULL, 0 }, /* serialNumber */ - /* attrCertValidityPeriod */ - 0 , /* notBefore */ - 0 , /* notAfter */ - /* attributes */ - NULL , /* charging */ - NULL , /* groups */ - /* extensions */ - { NULL, 0 }, /* authKeyID */ - { NULL, 0 }, /* authKeySerialNumber */ - FALSE , /* noRevAvail */ - /* signatureAlgorithm */ - OID_UNKNOWN, /* algorithm */ - { NULL, 0 }, /* signature */ + NULL , /* *next */ + 0 , /* installed */ + { NULL, 0 }, /* certificate */ + { NULL, 0 }, /* certificateInfo */ + 1 , /* version */ + /* holder */ + /* baseCertificateID */ + { NULL, 0 }, /* holderIssuer */ + { NULL, 0 }, /* holderSerial */ + /* entityName */ + { NULL, 0 }, /* generalNames */ + /* v2Form */ + { NULL, 0 }, /* issuerName */ + /* signature */ + OID_UNKNOWN, /* sigAlg */ + { NULL, 0 }, /* serialNumber */ + /* attrCertValidityPeriod */ + 0 , /* notBefore */ + 0 , /* notAfter */ + /* attributes */ + NULL , /* charging */ + NULL , /* groups */ + /* extensions */ + { NULL, 0 }, /* authKeyID */ + { NULL, 0 }, /* authKeySerialNumber */ + FALSE , /* noRevAvail */ + /* signatureAlgorithm */ + OID_UNKNOWN, /* algorithm */ + { NULL, 0 }, /* signature */ }; @@ -214,17 +214,17 @@ const x509acert_t empty_ac = { static int cmp_ietfAttr(ietfAttr_t *a,ietfAttr_t *b) { - int cmp_len, len, cmp_value; + int cmp_len, len, cmp_value; - /* cannot compare OID with STRING or OCTETS attributes */ - if (a->kind == IETF_ATTRIBUTE_OID && b->kind != IETF_ATTRIBUTE_OID) - return 1; - - cmp_len = a->value.len - b->value.len; - len = (cmp_len < 0)? a->value.len : b->value.len; - cmp_value = memcmp(a->value.ptr, b->value.ptr, len); + /* cannot compare OID with STRING or OCTETS attributes */ + if (a->kind == IETF_ATTRIBUTE_OID && b->kind != IETF_ATTRIBUTE_OID) + return 1; + + cmp_len = a->value.len - b->value.len; + len = (cmp_len < 0)? a->value.len : b->value.len; + cmp_value = memcmp(a->value.ptr, b->value.ptr, len); - return (cmp_value == 0)? cmp_len : cmp_value; + return (cmp_value == 0)? cmp_len : cmp_value; } /* @@ -233,41 +233,41 @@ cmp_ietfAttr(ietfAttr_t *a,ietfAttr_t *b) static ietfAttr_t* add_ietfAttr(ietfAttr_t *attr) { - ietfAttrList_t **listp = &ietfAttributes; - ietfAttrList_t *list = *listp; - int cmp = -1; + ietfAttrList_t **listp = &ietfAttributes; + ietfAttrList_t *list = *listp; + int cmp = -1; - while (list != NULL) - { - cmp = cmp_ietfAttr(attr, list->attr); - if (cmp <= 0) - break; - listp = &list->next; - list = *listp; - } + while (list != NULL) + { + cmp = cmp_ietfAttr(attr, list->attr); + if (cmp <= 0) + break; + listp = &list->next; + list = *listp; + } - if (cmp == 0) - { - /* attribute already exists, increase count */ - free(attr); - list->attr->count++; - return list->attr; - } - else - { - ietfAttrList_t *el = malloc_thing(ietfAttrList_t); + if (cmp == 0) + { + /* attribute already exists, increase count */ + free(attr); + list->attr->count++; + return list->attr; + } + else + { + ietfAttrList_t *el = malloc_thing(ietfAttrList_t); - /* new attribute, unshare value */ - attr->value = chunk_clone(attr->value); - attr->count = 1; - time(&attr->installed); + /* new attribute, unshare value */ + attr->value = chunk_clone(attr->value); + attr->count = 1; + time(&attr->installed); - el->attr = attr; - el->next = list; - *listp = el; + el->attr = attr; + el->next = list; + *listp = el; - return attr; - } + return attr; + } } /* @@ -276,106 +276,106 @@ add_ietfAttr(ietfAttr_t *attr) void decode_groups(char *groups, ietfAttrList_t **listp) { - if (groups == NULL) - return; + if (groups == NULL) + return; - while (strlen(groups) > 0) - { - char *end; - char *next = strchr(groups, ','); - - if (next == NULL) - end = next = groups + strlen(groups); - else - end = next++; - - /* eat preceeding whitespace */ - while (groups < end && *groups == ' ') - groups++; - - /* eat trailing whitespace */ - while (end > groups && *(end-1) == ' ') - end--; - - if (groups < end) + while (strlen(groups) > 0) { - ietfAttr_t *attr = malloc_thing(ietfAttr_t); - ietfAttrList_t *el = malloc_thing(ietfAttrList_t); + char *end; + char *next = strchr(groups, ','); - attr->kind = IETF_ATTRIBUTE_STRING; - attr->value.ptr = groups; - attr->value.len = end - groups; - attr->count = 0; + if (next == NULL) + end = next = groups + strlen(groups); + else + end = next++; - el->attr = add_ietfAttr(attr); - el->next = *listp; - *listp = el; + /* eat preceeding whitespace */ + while (groups < end && *groups == ' ') + groups++; + + /* eat trailing whitespace */ + while (end > groups && *(end-1) == ' ') + end--; + + if (groups < end) + { + ietfAttr_t *attr = malloc_thing(ietfAttr_t); + ietfAttrList_t *el = malloc_thing(ietfAttrList_t); + + attr->kind = IETF_ATTRIBUTE_STRING; + attr->value.ptr = groups; + attr->value.len = end - groups; + attr->count = 0; + + el->attr = add_ietfAttr(attr); + el->next = *listp; + *listp = el; + } + + groups = next; } - - groups = next; - } } static bool same_attribute(const ietfAttr_t *a, const ietfAttr_t *b) { - return (a->kind == b->kind && a->value.len == b->value.len - && memeq(a->value.ptr, b->value.ptr, b->value.len)); + return (a->kind == b->kind && a->value.len == b->value.len + && memeq(a->value.ptr, b->value.ptr, b->value.len)); } bool group_membership(const ietfAttrList_t *peer_list - , const char *conn - , const ietfAttrList_t *conn_list) + , const char *conn + , const ietfAttrList_t *conn_list) { - if (conn_list == NULL) - return TRUE; - - while (peer_list != NULL) - { - const ietfAttr_t *peer_attr = peer_list->attr; - const ietfAttrList_t *list = conn_list; - - while (list != NULL) - { - ietfAttr_t *conn_attr = list->attr; - - if (same_attribute(conn_attr, peer_attr)) - { - DBG(DBG_CONTROL, - DBG_log("%s: peer matches group '%.*s'" - , conn - , (int)peer_attr->value.len, peer_attr->value.ptr) - ) + if (conn_list == NULL) return TRUE; - } - list = list->next; + + while (peer_list != NULL) + { + const ietfAttr_t *peer_attr = peer_list->attr; + const ietfAttrList_t *list = conn_list; + + while (list != NULL) + { + ietfAttr_t *conn_attr = list->attr; + + if (same_attribute(conn_attr, peer_attr)) + { + DBG(DBG_CONTROL, + DBG_log("%s: peer matches group '%.*s'" + , conn + , (int)peer_attr->value.len, peer_attr->value.ptr) + ) + return TRUE; + } + list = list->next; + } + peer_list = peer_list->next; } - peer_list = peer_list->next; - } - DBG(DBG_CONTROL, - DBG_log("%s: peer doesn't match any group", conn) - ) - return FALSE; + DBG(DBG_CONTROL, + DBG_log("%s: peer doesn't match any group", conn) + ) + return FALSE; } void unshare_ietfAttrList(ietfAttrList_t **listp) { - ietfAttrList_t *list = *listp; + ietfAttrList_t *list = *listp; - while (list != NULL) - { - ietfAttrList_t *el = malloc_thing(ietfAttrList_t); + while (list != NULL) + { + ietfAttrList_t *el = malloc_thing(ietfAttrList_t); - el->attr = list->attr; - el->attr->count++; - el->next = NULL; - *listp = el; - listp = &el->next; - list = list->next; - } + el->attr = list->attr; + el->attr->count++; + el->next = NULL; + *listp = el; + listp = &el->next; + list = list->next; + } } /* @@ -384,44 +384,44 @@ unshare_ietfAttrList(ietfAttrList_t **listp) static ietfAttrList_t* parse_ietfAttrSyntax(chunk_t blob, int level0) { - asn1_ctx_t ctx; - chunk_t object; - u_int level; - int objectID = 0; + asn1_ctx_t ctx; + chunk_t object; + u_int level; + int objectID = 0; - ietfAttrList_t *list = NULL; + ietfAttrList_t *list = NULL; - asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); + asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); - while (objectID < IETF_ATTR_ROOF) - { - if (!extract_object(ietfAttrSyntaxObjects, &objectID, &object, &level, &ctx)) - return NULL; - - switch (objectID) + while (objectID < IETF_ATTR_ROOF) { - case IETF_ATTR_OCTETS: - case IETF_ATTR_OID: - case IETF_ATTR_STRING: - { - ietfAttr_t *attr = malloc_thing(ietfAttr_t); - ietfAttrList_t *el = malloc_thing(ietfAttrList_t); + if (!extract_object(ietfAttrSyntaxObjects, &objectID, &object, &level, &ctx)) + return NULL; - attr->kind = (objectID - IETF_ATTR_OCTETS) / 2; - attr->value = object; - attr->count = 0; + switch (objectID) + { + case IETF_ATTR_OCTETS: + case IETF_ATTR_OID: + case IETF_ATTR_STRING: + { + ietfAttr_t *attr = malloc_thing(ietfAttr_t); + ietfAttrList_t *el = malloc_thing(ietfAttrList_t); - el->attr = add_ietfAttr(attr); - el->next = list; - list = el; - } - break; - default: - break; + attr->kind = (objectID - IETF_ATTR_OCTETS) / 2; + attr->value = object; + attr->count = 0; + + el->attr = add_ietfAttr(attr); + el->next = list; + list = el; + } + break; + default: + break; + } + objectID++; } - objectID++; - } - return list; + return list; } /* * parses roleSyntax @@ -429,24 +429,24 @@ parse_ietfAttrSyntax(chunk_t blob, int level0) static void parse_roleSyntax(chunk_t blob, int level0) { - asn1_ctx_t ctx; - chunk_t object; - u_int level; - int objectID = 0; + asn1_ctx_t ctx; + chunk_t object; + u_int level; + int objectID = 0; - asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); + asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); - while (objectID < ROLE_ROOF) - { - if (!extract_object(roleSyntaxObjects, &objectID, &object, &level, &ctx)) - return; + while (objectID < ROLE_ROOF) + { + if (!extract_object(roleSyntaxObjects, &objectID, &object, &level, &ctx)) + return; - switch (objectID) { - default: - break; + switch (objectID) { + default: + break; + } + objectID++; } - objectID++; - } } /* @@ -455,146 +455,146 @@ parse_roleSyntax(chunk_t blob, int level0) bool parse_ac(chunk_t blob, x509acert_t *ac) { - asn1_ctx_t ctx; - bool critical; - chunk_t object; - u_int level; - int objectID = 0; - int type = OID_UNKNOWN; - int extn_oid = OID_UNKNOWN; + asn1_ctx_t ctx; + bool critical; + chunk_t object; + u_int level; + int objectID = 0; + int type = OID_UNKNOWN; + int extn_oid = OID_UNKNOWN; - asn1_init(&ctx, blob, 0, FALSE, DBG_RAW); + asn1_init(&ctx, blob, 0, FALSE, DBG_RAW); - while (objectID < AC_OBJ_ROOF) { + while (objectID < AC_OBJ_ROOF) { - if (!extract_object(acObjects, &objectID, &object, &level, &ctx)) - return FALSE; + if (!extract_object(acObjects, &objectID, &object, &level, &ctx)) + return FALSE; - /* those objects which will parsed further need the next higher level */ - level++; + /* those objects which will parsed further need the next higher level */ + level++; + + switch (objectID) + { + case AC_OBJ_CERTIFICATE: + ac->certificate = object; + break; + case AC_OBJ_CERTIFICATE_INFO: + ac->certificateInfo = object; + break; + case AC_OBJ_VERSION: + ac->version = (object.len) ? (1 + (u_int)*object.ptr) : 1; + DBG(DBG_PARSING, + DBG_log(" v%d", ac->version); + ) + if (ac->version != 2) + { + plog("v%d attribute certificates are not supported" + , ac->version); + return FALSE; + } + break; + case AC_OBJ_HOLDER_ISSUER: + ac->holderIssuer = get_directoryName(object, level, FALSE); + break; + case AC_OBJ_HOLDER_SERIAL: + ac->holderSerial = object; + break; + case AC_OBJ_ENTITY_NAME: + ac->entityName = get_directoryName(object, level, TRUE); + break; + case AC_OBJ_ISSUER_NAME: + ac->issuerName = get_directoryName(object, level, FALSE); + break; + case AC_OBJ_SIG_ALG: + ac->sigAlg = parse_algorithmIdentifier(object, level, NULL); + break; + case AC_OBJ_SERIAL_NUMBER: + ac->serialNumber = object; + break; + case AC_OBJ_NOT_BEFORE: + ac->notBefore = asn1totime(&object, ASN1_GENERALIZEDTIME); + break; + case AC_OBJ_NOT_AFTER: + ac->notAfter = asn1totime(&object, ASN1_GENERALIZEDTIME); + break; + case AC_OBJ_ATTRIBUTE_TYPE: + type = asn1_known_oid(object); + break; + case AC_OBJ_ATTRIBUTE_VALUE: + { + switch (type) { + case OID_AUTHENTICATION_INFO: + DBG(DBG_PARSING, + DBG_log(" need to parse authenticationInfo") + ) + break; + case OID_ACCESS_IDENTITY: + DBG(DBG_PARSING, + DBG_log(" need to parse accessIdentity") + ) + break; + case OID_CHARGING_IDENTITY: + ac->charging = parse_ietfAttrSyntax(object, level); + break; + case OID_GROUP: + ac->groups = parse_ietfAttrSyntax(object, level); + break; + case OID_ROLE: + parse_roleSyntax(object, level); + break; + default: + break; + } + } + break; + case AC_OBJ_EXTN_ID: + extn_oid = asn1_known_oid(object); + break; + case AC_OBJ_CRITICAL: + critical = object.len && *object.ptr; + DBG(DBG_PARSING, + DBG_log(" %s",(critical)?"TRUE":"FALSE"); + ) + break; + case AC_OBJ_EXTN_VALUE: + { + switch (extn_oid) { + case OID_CRL_DISTRIBUTION_POINTS: + DBG(DBG_PARSING, + DBG_log(" need to parse crlDistributionPoints") + ) + break; + case OID_AUTHORITY_KEY_ID: + parse_authorityKeyIdentifier(object, level + , &ac->authKeyID, &ac->authKeySerialNumber); + break; + case OID_TARGET_INFORMATION: + DBG(DBG_PARSING, + DBG_log(" need to parse targetInformation") + ) + break; + case OID_NO_REV_AVAIL: + ac->noRevAvail = TRUE; + break; + default: + break; + } + } + break; + case AC_OBJ_ALGORITHM: + ac->algorithm = parse_algorithmIdentifier(object, level, NULL); + break; + case AC_OBJ_SIGNATURE: + ac->signature = object; + break; - switch (objectID) - { - case AC_OBJ_CERTIFICATE: - ac->certificate = object; - break; - case AC_OBJ_CERTIFICATE_INFO: - ac->certificateInfo = object; - break; - case AC_OBJ_VERSION: - ac->version = (object.len) ? (1 + (u_int)*object.ptr) : 1; - DBG(DBG_PARSING, - DBG_log(" v%d", ac->version); - ) - if (ac->version != 2) - { - plog("v%d attribute certificates are not supported" - , ac->version); - return FALSE; - } - break; - case AC_OBJ_HOLDER_ISSUER: - ac->holderIssuer = get_directoryName(object, level, FALSE); - break; - case AC_OBJ_HOLDER_SERIAL: - ac->holderSerial = object; - break; - case AC_OBJ_ENTITY_NAME: - ac->entityName = get_directoryName(object, level, TRUE); - break; - case AC_OBJ_ISSUER_NAME: - ac->issuerName = get_directoryName(object, level, FALSE); - break; - case AC_OBJ_SIG_ALG: - ac->sigAlg = parse_algorithmIdentifier(object, level, NULL); - break; - case AC_OBJ_SERIAL_NUMBER: - ac->serialNumber = object; - break; - case AC_OBJ_NOT_BEFORE: - ac->notBefore = asn1totime(&object, ASN1_GENERALIZEDTIME); - break; - case AC_OBJ_NOT_AFTER: - ac->notAfter = asn1totime(&object, ASN1_GENERALIZEDTIME); - break; - case AC_OBJ_ATTRIBUTE_TYPE: - type = asn1_known_oid(object); - break; - case AC_OBJ_ATTRIBUTE_VALUE: - { - switch (type) { - case OID_AUTHENTICATION_INFO: - DBG(DBG_PARSING, - DBG_log(" need to parse authenticationInfo") - ) - break; - case OID_ACCESS_IDENTITY: - DBG(DBG_PARSING, - DBG_log(" need to parse accessIdentity") - ) - break; - case OID_CHARGING_IDENTITY: - ac->charging = parse_ietfAttrSyntax(object, level); - break; - case OID_GROUP: - ac->groups = parse_ietfAttrSyntax(object, level); - break; - case OID_ROLE: - parse_roleSyntax(object, level); - break; default: - break; + break; } - } - break; - case AC_OBJ_EXTN_ID: - extn_oid = asn1_known_oid(object); - break; - case AC_OBJ_CRITICAL: - critical = object.len && *object.ptr; - DBG(DBG_PARSING, - DBG_log(" %s",(critical)?"TRUE":"FALSE"); - ) - break; - case AC_OBJ_EXTN_VALUE: - { - switch (extn_oid) { - case OID_CRL_DISTRIBUTION_POINTS: - DBG(DBG_PARSING, - DBG_log(" need to parse crlDistributionPoints") - ) - break; - case OID_AUTHORITY_KEY_ID: - parse_authorityKeyIdentifier(object, level - , &ac->authKeyID, &ac->authKeySerialNumber); - break; - case OID_TARGET_INFORMATION: - DBG(DBG_PARSING, - DBG_log(" need to parse targetInformation") - ) - break; - case OID_NO_REV_AVAIL: - ac->noRevAvail = TRUE; - break; - default: - break; - } - } - break; - case AC_OBJ_ALGORITHM: - ac->algorithm = parse_algorithmIdentifier(object, level, NULL); - break; - case AC_OBJ_SIGNATURE: - ac->signature = object; - break; - - default: - break; + objectID++; } - objectID++; - } - time(&ac->installed); - return TRUE; + time(&ac->installed); + return TRUE; } /* @@ -603,22 +603,22 @@ parse_ac(chunk_t blob, x509acert_t *ac) static void release_ietfAttr(ietfAttr_t* attr) { - if (--attr->count == 0) - { - ietfAttrList_t **plist = &ietfAttributes; - ietfAttrList_t *list = *plist; - - while (list->attr != attr) + if (--attr->count == 0) { - plist = &list->next; - list = *plist; + ietfAttrList_t **plist = &ietfAttributes; + ietfAttrList_t *list = *plist; + + while (list->attr != attr) + { + plist = &list->next; + list = *plist; + } + *plist = list->next; + + free(attr->value.ptr); + free(attr); + free(list); } - *plist = list->next; - - free(attr->value.ptr); - free(attr); - free(list); - } } /* @@ -627,14 +627,14 @@ release_ietfAttr(ietfAttr_t* attr) void free_ietfAttrList(ietfAttrList_t* list) { - while (list != NULL) - { - ietfAttrList_t *el = list; + while (list != NULL) + { + ietfAttrList_t *el = list; - release_ietfAttr(el->attr); - list = list->next; - free(el); - } + release_ietfAttr(el->attr); + list = list->next; + free(el); + } } /* @@ -643,13 +643,13 @@ free_ietfAttrList(ietfAttrList_t* list) void free_acert(x509acert_t *ac) { - if (ac != NULL) - { - free_ietfAttrList(ac->charging); - free_ietfAttrList(ac->groups); - free(ac->certificate.ptr); - free(ac); - } + if (ac != NULL) + { + free_ietfAttrList(ac->charging); + free_ietfAttrList(ac->groups); + free(ac->certificate.ptr); + free(ac); + } } /* @@ -658,9 +658,9 @@ free_acert(x509acert_t *ac) static void free_first_acert(void) { - x509acert_t *first = x509acerts; - x509acerts = first->next; - free_acert(first); + x509acert_t *first = x509acerts; + x509acerts = first->next; + free_acert(first); } /* @@ -669,8 +669,8 @@ free_first_acert(void) void free_acerts(void) { - while (x509acerts != NULL) - free_first_acert(); + while (x509acerts != NULL) + free_first_acert(); } /* @@ -679,27 +679,27 @@ free_acerts(void) x509acert_t* get_x509acert(chunk_t issuer, chunk_t serial) { - x509acert_t *ac = x509acerts; - x509acert_t *prev_ac = NULL; + x509acert_t *ac = x509acerts; + x509acert_t *prev_ac = NULL; - while (ac != NULL) - { - if (same_dn(issuer, ac->holderIssuer) - && same_serial(serial, ac->holderSerial)) + while (ac != NULL) { - if (ac!= x509acerts) - { - /* bring the certificate up front */ - prev_ac->next = ac->next; - ac->next = x509acerts; - x509acerts = ac; - } - return ac; + if (same_dn(issuer, ac->holderIssuer) + && same_serial(serial, ac->holderSerial)) + { + if (ac!= x509acerts) + { + /* bring the certificate up front */ + prev_ac->next = ac->next; + ac->next = x509acerts; + x509acerts = ac; + } + return ac; + } + prev_ac = ac; + ac = ac->next; } - prev_ac = ac; - ac = ac->next; - } - return NULL; + return NULL; } /* @@ -708,32 +708,32 @@ get_x509acert(chunk_t issuer, chunk_t serial) static void add_acert(x509acert_t *ac) { - x509acert_t *old_ac = get_x509acert(ac->holderIssuer, ac->holderSerial); + x509acert_t *old_ac = get_x509acert(ac->holderIssuer, ac->holderSerial); - if (old_ac != NULL) - { - if (ac->notBefore >old_ac->notBefore) + if (old_ac != NULL) { - /* delete the old attribute cert */ - free_first_acert(); - DBG(DBG_CONTROL, - DBG_log("attribute cert is newer - existing cert deleted") - ) + if (ac->notBefore >old_ac->notBefore) + { + /* delete the old attribute cert */ + free_first_acert(); + DBG(DBG_CONTROL, + DBG_log("attribute cert is newer - existing cert deleted") + ) + } + else + { + DBG(DBG_CONTROL, + DBG_log("attribute cert is not newer - existing cert kept"); + ) + free_acert(ac); + return; + } } - else - { - DBG(DBG_CONTROL, - DBG_log("attribute cert is not newer - existing cert kept"); - ) - free_acert(ac); - return; - } - } - plog("attribute cert added"); + plog("attribute cert added"); - /* insert new attribute cert at the root of the chain */ - ac->next = x509acerts; - x509acerts = ac; + /* insert new attribute cert at the root of the chain */ + ac->next = x509acerts; + x509acerts = ac; } /* verify the validity of an attribute certificate by @@ -742,21 +742,21 @@ add_acert(x509acert_t *ac) static err_t check_ac_validity(const x509acert_t *ac) { - time_t current_time; + time_t current_time; - time(¤t_time); - DBG(DBG_CONTROL | DBG_PARSING, - DBG_log(" not before : %T", &ac->notBefore, TRUE); - DBG_log(" current time: %T", ¤t_time, TRUE); - DBG_log(" not after : %T", &ac->notAfter, TRUE); - ) + time(¤t_time); + DBG(DBG_CONTROL | DBG_PARSING, + DBG_log(" not before : %T", &ac->notBefore, TRUE); + DBG_log(" current time: %T", ¤t_time, TRUE); + DBG_log(" not after : %T", &ac->notAfter, TRUE); + ) - if (current_time < ac->notBefore) - return "attribute certificate is not valid yet"; - if (current_time > ac->notAfter) - return "attribute certificate has expired"; - else - return NULL; + if (current_time < ac->notBefore) + return "attribute certificate is not valid yet"; + if (current_time > ac->notAfter) + return "attribute certificate has expired"; + else + return NULL; } /* @@ -765,54 +765,54 @@ check_ac_validity(const x509acert_t *ac) bool verify_x509acert(x509acert_t *ac, bool strict) { - u_char buf[BUF_LEN]; - x509cert_t *aacert; - err_t ugh = NULL; - time_t valid_until = ac->notAfter; + u_char buf[BUF_LEN]; + x509cert_t *aacert; + err_t ugh = NULL; + time_t valid_until = ac->notAfter; - DBG(DBG_CONTROL, - dntoa(buf, BUF_LEN, ac->entityName); - DBG_log("holder: '%s'",buf); - dntoa(buf, BUF_LEN, ac->issuerName); - DBG_log("issuer: '%s'",buf); - ) - - ugh = check_ac_validity(ac); + DBG(DBG_CONTROL, + dntoa(buf, BUF_LEN, ac->entityName); + DBG_log("holder: '%s'",buf); + dntoa(buf, BUF_LEN, ac->issuerName); + DBG_log("issuer: '%s'",buf); + ) + + ugh = check_ac_validity(ac); - if (ugh != NULL) - { - plog("%s", ugh); - return FALSE; - } - DBG(DBG_CONTROL, - DBG_log("attribute certificate is valid") - ) + if (ugh != NULL) + { + plog("%s", ugh); + return FALSE; + } + DBG(DBG_CONTROL, + DBG_log("attribute certificate is valid") + ) - lock_authcert_list("verify_x509acert"); - aacert = get_authcert(ac->issuerName, ac->authKeySerialNumber - , ac->authKeyID, AUTH_AA); - unlock_authcert_list("verify_x509acert"); + lock_authcert_list("verify_x509acert"); + aacert = get_authcert(ac->issuerName, ac->authKeySerialNumber + , ac->authKeyID, AUTH_AA); + unlock_authcert_list("verify_x509acert"); - if (aacert == NULL) - { - plog("issuer aacert not found"); - return FALSE; - } - DBG(DBG_CONTROL, - DBG_log("issuer aacert found") - ) + if (aacert == NULL) + { + plog("issuer aacert not found"); + return FALSE; + } + DBG(DBG_CONTROL, + DBG_log("issuer aacert found") + ) - if (!check_signature(ac->certificateInfo, ac->signature - , ac->algorithm, ac->algorithm, aacert)) - { - plog("attribute certificate signature is invalid"); - return FALSE; - } - DBG(DBG_CONTROL, - DBG_log("attribute certificate signature is valid"); - ) + if (!check_signature(ac->certificateInfo, ac->signature + , ac->algorithm, ac->algorithm, aacert)) + { + plog("attribute certificate signature is invalid"); + return FALSE; + } + DBG(DBG_CONTROL, + DBG_log("attribute certificate signature is valid"); + ) - return verify_x509cert(aacert, strict, &valid_until); + return verify_x509cert(aacert, strict, &valid_until); } /* @@ -821,45 +821,45 @@ verify_x509acert(x509acert_t *ac, bool strict) void load_acerts(void) { - u_char buf[BUF_LEN]; + u_char buf[BUF_LEN]; - /* change directory to specified path */ - u_char *save_dir = getcwd(buf, BUF_LEN); + /* change directory to specified path */ + u_char *save_dir = getcwd(buf, BUF_LEN); - if (!chdir(A_CERT_PATH)) - { - struct dirent **filelist; - int n; - - plog("Changing to directory '%s'",A_CERT_PATH); - n = scandir(A_CERT_PATH, &filelist, file_select, alphasort); - - if (n > 0) + if (!chdir(A_CERT_PATH)) { - while (n--) - { - chunk_t blob = chunk_empty; - bool pgp = FALSE; + struct dirent **filelist; + int n; - if (load_coded_file(filelist[n]->d_name, NULL, "acert", &blob, &pgp)) + plog("Changing to directory '%s'",A_CERT_PATH); + n = scandir(A_CERT_PATH, &filelist, file_select, alphasort); + + if (n > 0) { - x509acert_t *ac = malloc_thing(x509acert_t); - - *ac = empty_ac; + while (n--) + { + chunk_t blob = chunk_empty; + bool pgp = FALSE; - if (parse_ac(blob, ac) - && verify_x509acert(ac, FALSE)) - add_acert(ac); - else - free_acert(ac); + if (load_coded_file(filelist[n]->d_name, NULL, "acert", &blob, &pgp)) + { + x509acert_t *ac = malloc_thing(x509acert_t); + + *ac = empty_ac; + + if (parse_ac(blob, ac) + && verify_x509acert(ac, FALSE)) + add_acert(ac); + else + free_acert(ac); + } + free(filelist[n]); + } + free(filelist); } - free(filelist[n]); - } - free(filelist); } - } - /* restore directory path */ - ignore_result(chdir(save_dir)); + /* restore directory path */ + ignore_result(chdir(save_dir)); } /* @@ -868,30 +868,30 @@ load_acerts(void) void format_groups(const ietfAttrList_t *list, char *buf, int len) { - bool first_group = TRUE; + bool first_group = TRUE; - while (list != NULL && len > 0) - { - ietfAttr_t *attr = list->attr; - - if (attr->kind == IETF_ATTRIBUTE_OCTETS - || attr->kind == IETF_ATTRIBUTE_STRING) + while (list != NULL && len > 0) { - int written = snprintf(buf, len, "%s%.*s" - , (first_group)? "" : ", " - , (int)attr->value.len, attr->value.ptr); + ietfAttr_t *attr = list->attr; - first_group = FALSE; - - /* return value of snprintf() up to glibc 2.0.6 */ - if (written < 0) - break; + if (attr->kind == IETF_ATTRIBUTE_OCTETS + || attr->kind == IETF_ATTRIBUTE_STRING) + { + int written = snprintf(buf, len, "%s%.*s" + , (first_group)? "" : ", " + , (int)attr->value.len, attr->value.ptr); - buf += written; - len -= written; + first_group = FALSE; + + /* return value of snprintf() up to glibc 2.0.6 */ + if (written < 0) + break; + + buf += written; + len -= written; + } + list = list->next; } - list = list->next; - } } /* @@ -900,71 +900,71 @@ format_groups(const ietfAttrList_t *list, char *buf, int len) void list_acerts(bool utc) { - x509acert_t *ac = x509acerts; - time_t now; + x509acert_t *ac = x509acerts; + time_t now; - /* determine the current time */ - time(&now); + /* determine the current time */ + time(&now); - if (ac != NULL) - { - whack_log(RC_COMMENT, " "); - whack_log(RC_COMMENT, "List of X.509 Attribute Certificates:"); - whack_log(RC_COMMENT, " "); - } - - while (ac != NULL) - { - u_char buf[BUF_LEN]; - - whack_log(RC_COMMENT, "%T", &ac->installed, utc); - if (ac->entityName.ptr != NULL) + if (ac != NULL) { - dntoa(buf, BUF_LEN, ac->entityName); - whack_log(RC_COMMENT, " holder: '%s'", buf); - } - if (ac->holderIssuer.ptr != NULL) - { - dntoa(buf, BUF_LEN, ac->holderIssuer); - whack_log(RC_COMMENT, " hissuer: '%s'", buf); - } - if (ac->holderSerial.ptr != NULL) - { - datatot(ac->holderSerial.ptr, ac->holderSerial.len, ':' - , buf, BUF_LEN); - whack_log(RC_COMMENT, " hserial: %s", buf); - } - if (ac->groups != NULL) - { - format_groups(ac->groups, buf, BUF_LEN); - whack_log(RC_COMMENT, " groups: %s", buf); - } - dntoa(buf, BUF_LEN, ac->issuerName); - whack_log(RC_COMMENT, " issuer: '%s'", buf); - datatot(ac->serialNumber.ptr, ac->serialNumber.len, ':' - , buf, BUF_LEN); - whack_log(RC_COMMENT, " serial: %s", buf); - whack_log(RC_COMMENT, " validity: not before %T %s", - &ac->notBefore, utc, - (ac->notBefore < now)?"ok":"fatal (not valid yet)"); - whack_log(RC_COMMENT, " not after %T %s", - &ac->notAfter, utc, - check_expiry(ac->notAfter, ACERT_WARNING_INTERVAL, TRUE)); - if (ac->authKeyID.ptr != NULL) - { - datatot(ac->authKeyID.ptr, ac->authKeyID.len, ':' - , buf, BUF_LEN); - whack_log(RC_COMMENT, " authkey: %s", buf); - } - if (ac->authKeySerialNumber.ptr != NULL) - { - datatot(ac->authKeySerialNumber.ptr, ac->authKeySerialNumber.len, ':' - , buf, BUF_LEN); - whack_log(RC_COMMENT, " aserial: %s", buf); + whack_log(RC_COMMENT, " "); + whack_log(RC_COMMENT, "List of X.509 Attribute Certificates:"); + whack_log(RC_COMMENT, " "); } - ac = ac->next; - } + while (ac != NULL) + { + u_char buf[BUF_LEN]; + + whack_log(RC_COMMENT, "%T", &ac->installed, utc); + if (ac->entityName.ptr != NULL) + { + dntoa(buf, BUF_LEN, ac->entityName); + whack_log(RC_COMMENT, " holder: '%s'", buf); + } + if (ac->holderIssuer.ptr != NULL) + { + dntoa(buf, BUF_LEN, ac->holderIssuer); + whack_log(RC_COMMENT, " hissuer: '%s'", buf); + } + if (ac->holderSerial.ptr != NULL) + { + datatot(ac->holderSerial.ptr, ac->holderSerial.len, ':' + , buf, BUF_LEN); + whack_log(RC_COMMENT, " hserial: %s", buf); + } + if (ac->groups != NULL) + { + format_groups(ac->groups, buf, BUF_LEN); + whack_log(RC_COMMENT, " groups: %s", buf); + } + dntoa(buf, BUF_LEN, ac->issuerName); + whack_log(RC_COMMENT, " issuer: '%s'", buf); + datatot(ac->serialNumber.ptr, ac->serialNumber.len, ':' + , buf, BUF_LEN); + whack_log(RC_COMMENT, " serial: %s", buf); + whack_log(RC_COMMENT, " validity: not before %T %s", + &ac->notBefore, utc, + (ac->notBefore < now)?"ok":"fatal (not valid yet)"); + whack_log(RC_COMMENT, " not after %T %s", + &ac->notAfter, utc, + check_expiry(ac->notAfter, ACERT_WARNING_INTERVAL, TRUE)); + if (ac->authKeyID.ptr != NULL) + { + datatot(ac->authKeyID.ptr, ac->authKeyID.len, ':' + , buf, BUF_LEN); + whack_log(RC_COMMENT, " authkey: %s", buf); + } + if (ac->authKeySerialNumber.ptr != NULL) + { + datatot(ac->authKeySerialNumber.ptr, ac->authKeySerialNumber.len, ':' + , buf, BUF_LEN); + whack_log(RC_COMMENT, " aserial: %s", buf); + } + + ac = ac->next; + } } /* @@ -973,34 +973,34 @@ list_acerts(bool utc) void list_groups(bool utc) { - ietfAttrList_t *list = ietfAttributes; - - if (list != NULL) - { - whack_log(RC_COMMENT, " "); - whack_log(RC_COMMENT, "List of Group Attributes:"); - whack_log(RC_COMMENT, " "); - } - - while (list != NULL) - { - ietfAttr_t *attr = list->attr; - - whack_log(RC_COMMENT, "%T, count: %d", &attr->installed, utc, attr->count); + ietfAttrList_t *list = ietfAttributes; - switch (attr->kind) + if (list != NULL) { - case IETF_ATTRIBUTE_OCTETS: - case IETF_ATTRIBUTE_STRING: - whack_log(RC_COMMENT, " %.*s", (int)attr->value.len, attr->value.ptr); - break; - case IETF_ATTRIBUTE_OID: - whack_log(RC_COMMENT, " OID"); - break; - default: - break; - } + whack_log(RC_COMMENT, " "); + whack_log(RC_COMMENT, "List of Group Attributes:"); + whack_log(RC_COMMENT, " "); + } - list = list->next; - } + while (list != NULL) + { + ietfAttr_t *attr = list->attr; + + whack_log(RC_COMMENT, "%T, count: %d", &attr->installed, utc, attr->count); + + switch (attr->kind) + { + case IETF_ATTRIBUTE_OCTETS: + case IETF_ATTRIBUTE_STRING: + whack_log(RC_COMMENT, " %.*s", (int)attr->value.len, attr->value.ptr); + break; + case IETF_ATTRIBUTE_OID: + whack_log(RC_COMMENT, " OID"); + break; + default: + break; + } + + list = list->next; + } } diff --git a/src/pluto/ac.h b/src/pluto/ac.h index 158c71b1b..1100052ab 100644 --- a/src/pluto/ac.h +++ b/src/pluto/ac.h @@ -1,7 +1,7 @@ /* Support of X.509 attribute certificates * Copyright (C) 2002 Ueli Galizzi, Ariane Seiler * Copyright (C) 2003 Martin Berner, Lukas Suter - + * * 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 @@ -22,9 +22,9 @@ /* definition of ietfAttribute kinds */ typedef enum { - IETF_ATTRIBUTE_OCTETS = 0, - IETF_ATTRIBUTE_OID = 1, - IETF_ATTRIBUTE_STRING = 2 + IETF_ATTRIBUTE_OCTETS = 0, + IETF_ATTRIBUTE_OID = 1, + IETF_ATTRIBUTE_STRING = 2 } ietfAttribute_t; /* access structure for an ietfAttribute */ @@ -32,17 +32,17 @@ typedef enum { typedef struct ietfAttr ietfAttr_t; struct ietfAttr { - time_t installed; - int count; + time_t installed; + int count; ietfAttribute_t kind; - chunk_t value; + chunk_t value; }; typedef struct ietfAttrList ietfAttrList_t; struct ietfAttrList { ietfAttrList_t *next; - ietfAttr_t *attr; + ietfAttr_t *attr; }; @@ -52,31 +52,31 @@ typedef struct x509acert x509acert_t; struct x509acert { x509acert_t *next; - time_t installed; - chunk_t certificate; - chunk_t certificateInfo; - u_int version; - /* holder */ - /* baseCertificateID */ - chunk_t holderIssuer; - chunk_t holderSerial; - chunk_t entityName; - /* v2Form */ - chunk_t issuerName; - /* signature */ + time_t installed; + chunk_t certificate; + chunk_t certificateInfo; + u_int version; + /* holder */ + /* baseCertificateID */ + chunk_t holderIssuer; + chunk_t holderSerial; + chunk_t entityName; + /* v2Form */ + chunk_t issuerName; + /* signature */ int sigAlg; - chunk_t serialNumber; - /* attrCertValidityPeriod */ + chunk_t serialNumber; + /* attrCertValidityPeriod */ time_t notBefore; time_t notAfter; - /* attributes */ + /* attributes */ ietfAttrList_t *charging; ietfAttrList_t *groups; - /* extensions */ + /* extensions */ chunk_t authKeyID; chunk_t authKeySerialNumber; - bool noRevAvail; - /* signatureAlgorithm */ + bool noRevAvail; + /* signatureAlgorithm */ int algorithm; chunk_t signature; }; @@ -88,7 +88,7 @@ extern void unshare_ietfAttrList(ietfAttrList_t **listp); extern void free_ietfAttrList(ietfAttrList_t *list); extern void decode_groups(char *groups, ietfAttrList_t **listp); extern bool group_membership(const ietfAttrList_t *my_list - , const char *conn, const ietfAttrList_t *conn_list); + , const char *conn, const ietfAttrList_t *conn_list); extern bool parse_ac(chunk_t blob, x509acert_t *ac); extern bool verify_x509acert(x509acert_t *ac, bool strict); extern x509acert_t* get_x509acert(chunk_t issuer, chunk_t serial); diff --git a/src/pluto/adns.c b/src/pluto/adns.c index 637207fab..97971ffff 100644 --- a/src/pluto/adns.c +++ b/src/pluto/adns.c @@ -14,7 +14,7 @@ * RCSID $Id$ */ -#ifndef USE_LWRES /* whole file! */ +#ifndef USE_LWRES /* whole file! */ /* This program executes as multiple processes. The Master process * receives queries (struct adns_query messages) from Pluto and distributes @@ -58,7 +58,7 @@ #include #include #include -#include /* ??? for h_errno */ +#include /* ??? for h_errno */ #include @@ -70,11 +70,11 @@ #endif #include "constants.h" -#include "adns.h" /* needs */ +#include "adns.h" /* needs */ /* shared by all processes */ -static const char *name; /* program name, for messages */ +static const char *name; /* program name, for messages */ static bool debug = FALSE; @@ -88,43 +88,43 @@ static bool debug = FALSE; static enum helper_exit_status read_pipe(int fd, unsigned char *stuff, size_t minlen, size_t maxlen) { - size_t n = 0; - size_t goal = minlen; + size_t n = 0; + size_t goal = minlen; - do { - ssize_t m = read(fd, stuff + n, goal - n); + do { + ssize_t m = read(fd, stuff + n, goal - n); - if (m == -1) - { - if (errno != EINTR) - { - syslog(LOG_ERR, "Input error on pipe: %s", strerror(errno)); - return HES_IO_ERROR_IN; - } - } - else if (m == 0) - { - return HES_OK; /* treat empty message as EOF */ - } - else - { - n += m; - if (n >= sizeof(size_t)) - { - goal = *(size_t *)(void *)stuff; - if (goal < minlen || maxlen < goal) + if (m == -1) { - if (debug) - fprintf(stderr, "%lu : [%lu, %lu]\n" - , (unsigned long)goal - , (unsigned long)minlen, (unsigned long)maxlen); - return HES_BAD_LEN; + if (errno != EINTR) + { + syslog(LOG_ERR, "Input error on pipe: %s", strerror(errno)); + return HES_IO_ERROR_IN; + } } - } - } - } while (n < goal); + else if (m == 0) + { + return HES_OK; /* treat empty message as EOF */ + } + else + { + n += m; + if (n >= sizeof(size_t)) + { + goal = *(size_t *)(void *)stuff; + if (goal < minlen || maxlen < goal) + { + if (debug) + fprintf(stderr, "%lu : [%lu, %lu]\n" + , (unsigned long)goal + , (unsigned long)minlen, (unsigned long)maxlen); + return HES_BAD_LEN; + } + } + } + } while (n < goal); - return HES_CONTINUE; + return HES_CONTINUE; } /* Write a variable-length record to a pipe. @@ -135,27 +135,27 @@ read_pipe(int fd, unsigned char *stuff, size_t minlen, size_t maxlen) static enum helper_exit_status write_pipe(int fd, const unsigned char *stuff) { - size_t len = *(const size_t *)(const void *)stuff; - size_t n = 0; + size_t len = *(const size_t *)(const void *)stuff; + size_t n = 0; - do { - ssize_t m = write(fd, stuff + n, len - n); + do { + ssize_t m = write(fd, stuff + n, len - n); - if (m == -1) - { - /* error, but ignore and retry if EINTR */ - if (errno != EINTR) - { - syslog(LOG_ERR, "Output error from master: %s", strerror(errno)); - return HES_IO_ERROR_OUT; - } - } - else - { - n += m; - } - } while (n != len); - return HES_CONTINUE; + if (m == -1) + { + /* error, but ignore and retry if EINTR */ + if (errno != EINTR) + { + syslog(LOG_ERR, "Output error from master: %s", strerror(errno)); + return HES_IO_ERROR_OUT; + } + } + else + { + n += m; + } + } while (n != len); + return HES_CONTINUE; } /**************** worker process ****************/ @@ -171,14 +171,14 @@ write_pipe(int fd, const unsigned char *stuff) */ #if (__RES) <= 19960801 -# define OLD_RESOLVER 1 +# define OLD_RESOLVER 1 #endif #ifdef OLD_RESOLVER # define res_ninit(statp) res_init() # define res_nquery(statp, dname, class, type, answer, anslen) \ - res_query(dname, class, type, answer, anslen) + res_query(dname, class, type, answer, anslen) # define res_nclose(statp) res_close() static struct __res_state *statp = &_res; @@ -193,75 +193,75 @@ static res_state statp = &my_res_state; static int worker(int qfd, int afd) { - { - int r = res_ninit(statp); - - if (r != 0) { - syslog(LOG_ERR, "cannot initialize resolver"); - return HES_RES_INIT; - } + int r = res_ninit(statp); + + if (r != 0) + { + syslog(LOG_ERR, "cannot initialize resolver"); + return HES_RES_INIT; + } #ifndef OLD_RESOLVER - statp->options |= RES_ROTATE; + statp->options |= RES_ROTATE; #endif - statp->options |= RES_DEBUG; - } - - for (;;) - { - struct adns_query q; - struct adns_answer a; - - enum helper_exit_status r = read_pipe(qfd, (unsigned char *)&q - , sizeof(q), sizeof(q)); - - if (r != HES_CONTINUE) - return r; /* some kind of exit */ - - if (q.qmagic != ADNS_Q_MAGIC) - { - syslog(LOG_ERR, "error in input from master: bad magic"); - return HES_BAD_MAGIC; + statp->options |= RES_DEBUG; } - a.amagic = ADNS_A_MAGIC; - a.serial = q.serial; + for (;;) + { + struct adns_query q; + struct adns_answer a; - a.result = res_nquery(statp, q.name_buf, C_IN, q.type, a.ans, sizeof(a.ans)); - a.h_errno_val = h_errno; + enum helper_exit_status r = read_pipe(qfd, (unsigned char *)&q + , sizeof(q), sizeof(q)); - a.len = offsetof(struct adns_answer, ans) + (a.result < 0? 0 : a.result); + if (r != HES_CONTINUE) + return r; /* some kind of exit */ + + if (q.qmagic != ADNS_Q_MAGIC) + { + syslog(LOG_ERR, "error in input from master: bad magic"); + return HES_BAD_MAGIC; + } + + a.amagic = ADNS_A_MAGIC; + a.serial = q.serial; + + a.result = res_nquery(statp, q.name_buf, C_IN, q.type, a.ans, sizeof(a.ans)); + a.h_errno_val = h_errno; + + a.len = offsetof(struct adns_answer, ans) + (a.result < 0? 0 : a.result); #ifdef DEBUG - if (((q.debugging & IMPAIR_DELAY_ADNS_KEY_ANSWER) && q.type == T_KEY) - || ((q.debugging & IMPAIR_DELAY_ADNS_TXT_ANSWER) && q.type == T_TXT)) - sleep(30); /* delay the answer */ + if (((q.debugging & IMPAIR_DELAY_ADNS_KEY_ANSWER) && q.type == T_KEY) + || ((q.debugging & IMPAIR_DELAY_ADNS_TXT_ANSWER) && q.type == T_TXT)) + sleep(30); /* delay the answer */ #endif - /* write answer, possibly a bit at a time */ - r = write_pipe(afd, (const unsigned char *)&a); + /* write answer, possibly a bit at a time */ + r = write_pipe(afd, (const unsigned char *)&a); - if (r != HES_CONTINUE) - return r; /* some kind of exit */ - } + if (r != HES_CONTINUE) + return r; /* some kind of exit */ + } } /**************** master process ****************/ bool eof_from_pluto = FALSE; -#define PLUTO_QFD 0 /* queries come on stdin */ -#define PLUTO_AFD 1 /* answers go out on stdout */ +#define PLUTO_QFD 0 /* queries come on stdin */ +#define PLUTO_AFD 1 /* answers go out on stdout */ #ifndef MAX_WORKERS -# define MAX_WORKERS 10 /* number of in-flight queries */ +# define MAX_WORKERS 10 /* number of in-flight queries */ #endif struct worker_info { - int qfd; /* query pipe's file descriptor */ - int afd; /* answer pipe's file descriptor */ - pid_t pid; - bool busy; - void *continuation; /* of outstanding request */ + int qfd; /* query pipe's file descriptor */ + int afd; /* answer pipe's file descriptor */ + pid_t pid; + bool busy; + void *continuation; /* of outstanding request */ }; static struct worker_info wi[MAX_WORKERS]; @@ -270,300 +270,300 @@ static struct worker_info *wi_roof = wi; /* request FIFO */ struct query_list { - struct query_list *next; - struct adns_query aq; + struct query_list *next; + struct adns_query aq; }; static struct query_list *oldest_query = NULL; -static struct query_list *newest_query; /* undefined when oldest == NULL */ +static struct query_list *newest_query; /* undefined when oldest == NULL */ static struct query_list *free_queries = NULL; static bool spawn_worker(void) { - int qfds[2]; - int afds[2]; - pid_t p; + int qfds[2]; + int afds[2]; + pid_t p; - if (pipe(qfds) != 0 || pipe(afds) != 0) - { - syslog(LOG_ERR, "pipe(2) failed: %s", strerror(errno)); - exit(HES_PIPE); - } - - wi_roof->qfd = qfds[1]; /* write end of query pipe */ - wi_roof->afd = afds[0]; /* read end of answer pipe */ - - p = fork(); - if (p == -1) - { - /* fork failed: ignore if at least one worker exists */ - if (wi_roof == wi) + if (pipe(qfds) != 0 || pipe(afds) != 0) { - syslog(LOG_ERR, "fork(2) error creating first worker: %s", strerror(errno)); - exit(HES_FORK); + syslog(LOG_ERR, "pipe(2) failed: %s", strerror(errno)); + exit(HES_PIPE); } - close(qfds[0]); - close(qfds[1]); - close(afds[0]); - close(afds[1]); - return FALSE; - } - else if (p == 0) - { - /* child */ - struct worker_info *w; - close(PLUTO_QFD); - close(PLUTO_AFD); - /* close all master pipes, including ours */ - for (w = wi; w <= wi_roof; w++) + wi_roof->qfd = qfds[1]; /* write end of query pipe */ + wi_roof->afd = afds[0]; /* read end of answer pipe */ + + p = fork(); + if (p == -1) { - close(w->qfd); - close(w->afd); + /* fork failed: ignore if at least one worker exists */ + if (wi_roof == wi) + { + syslog(LOG_ERR, "fork(2) error creating first worker: %s", strerror(errno)); + exit(HES_FORK); + } + close(qfds[0]); + close(qfds[1]); + close(afds[0]); + close(afds[1]); + return FALSE; } - exit(worker(qfds[0], afds[1])); - } - else - { - /* parent */ - struct worker_info *w = wi_roof++; + else if (p == 0) + { + /* child */ + struct worker_info *w; - w->pid = p; - w->busy = FALSE; - close(qfds[0]); - close(afds[1]); - return TRUE; - } + close(PLUTO_QFD); + close(PLUTO_AFD); + /* close all master pipes, including ours */ + for (w = wi; w <= wi_roof; w++) + { + close(w->qfd); + close(w->afd); + } + exit(worker(qfds[0], afds[1])); + } + else + { + /* parent */ + struct worker_info *w = wi_roof++; + + w->pid = p; + w->busy = FALSE; + close(qfds[0]); + close(afds[1]); + return TRUE; + } } static void send_eof(struct worker_info *w) { - pid_t p; - int status; + pid_t p; + int status; - close(w->qfd); - w->qfd = NULL_FD; + close(w->qfd); + w->qfd = NULL_FD; - close(w->afd); - w->afd = NULL_FD; + close(w->afd); + w->afd = NULL_FD; - /* reap child */ - p = waitpid(w->pid, &status, 0); - /* ignore result -- what could we do with it? */ + /* reap child */ + p = waitpid(w->pid, &status, 0); + /* ignore result -- what could we do with it? */ } static void forward_query(struct worker_info *w) { - struct query_list *q = oldest_query; + struct query_list *q = oldest_query; - if (q == NULL) - { - if (eof_from_pluto) - send_eof(w); - } - else - { - enum helper_exit_status r - = write_pipe(w->qfd, (const unsigned char *) &q->aq); + if (q == NULL) + { + if (eof_from_pluto) + send_eof(w); + } + else + { + enum helper_exit_status r + = write_pipe(w->qfd, (const unsigned char *) &q->aq); - if (r != HES_CONTINUE) - exit(r); + if (r != HES_CONTINUE) + exit(r); - w->busy = TRUE; + w->busy = TRUE; - oldest_query = q->next; - q->next = free_queries; - free_queries = q; - } + oldest_query = q->next; + q->next = free_queries; + free_queries = q; + } } static void query(void) { - struct query_list *q = free_queries; - enum helper_exit_status r; + struct query_list *q = free_queries; + enum helper_exit_status r; - /* find an unused queue entry */ - if (q == NULL) - { - q = malloc(sizeof(*q)); + /* find an unused queue entry */ if (q == NULL) { - syslog(LOG_ERR, "malloc(3) failed"); - exit(HES_MALLOC); + q = malloc(sizeof(*q)); + if (q == NULL) + { + syslog(LOG_ERR, "malloc(3) failed"); + exit(HES_MALLOC); + } } - } - else - { - free_queries = q->next; - } - - r = read_pipe(PLUTO_QFD, (unsigned char *)&q->aq - , sizeof(q->aq), sizeof(q->aq)); - - if (r == HES_OK) - { - /* EOF: we're done, except for unanswered queries */ - struct worker_info *w; - - eof_from_pluto = TRUE; - q->next = free_queries; - free_queries = q; - - /* Send bye-bye to unbusy processes. - * Note that if there are queued queries, there won't be - * any non-busy workers. - */ - for (w = wi; w != wi_roof; w++) - if (!w->busy) - send_eof(w); - } - else if (r != HES_CONTINUE) - { - exit(r); - } - else if (q->aq.qmagic != ADNS_Q_MAGIC) - { - syslog(LOG_ERR, "error in query from Pluto: bad magic"); - exit(HES_BAD_MAGIC); - } - else - { - struct worker_info *w; - - /* got a query */ - - /* add it to FIFO */ - q->next = NULL; - if (oldest_query == NULL) - oldest_query = q; else - newest_query->next = q; - newest_query = q; - - /* See if any worker available */ - for (w = wi; ; w++) { - if (w == wi_roof) - { - /* no free worker */ - if (w == wi + MAX_WORKERS) - break; /* no more to be created */ - /* make a new one */ - if (!spawn_worker()) - break; /* cannot create one at this time */ - } - if (!w->busy) - { - /* assign first to free worker */ - forward_query(w); - break; - } + free_queries = q->next; } - } - return; + + r = read_pipe(PLUTO_QFD, (unsigned char *)&q->aq + , sizeof(q->aq), sizeof(q->aq)); + + if (r == HES_OK) + { + /* EOF: we're done, except for unanswered queries */ + struct worker_info *w; + + eof_from_pluto = TRUE; + q->next = free_queries; + free_queries = q; + + /* Send bye-bye to unbusy processes. + * Note that if there are queued queries, there won't be + * any non-busy workers. + */ + for (w = wi; w != wi_roof; w++) + if (!w->busy) + send_eof(w); + } + else if (r != HES_CONTINUE) + { + exit(r); + } + else if (q->aq.qmagic != ADNS_Q_MAGIC) + { + syslog(LOG_ERR, "error in query from Pluto: bad magic"); + exit(HES_BAD_MAGIC); + } + else + { + struct worker_info *w; + + /* got a query */ + + /* add it to FIFO */ + q->next = NULL; + if (oldest_query == NULL) + oldest_query = q; + else + newest_query->next = q; + newest_query = q; + + /* See if any worker available */ + for (w = wi; ; w++) + { + if (w == wi_roof) + { + /* no free worker */ + if (w == wi + MAX_WORKERS) + break; /* no more to be created */ + /* make a new one */ + if (!spawn_worker()) + break; /* cannot create one at this time */ + } + if (!w->busy) + { + /* assign first to free worker */ + forward_query(w); + break; + } + } + } + return; } static void answer(struct worker_info *w) { - struct adns_answer a; - enum helper_exit_status r = read_pipe(w->afd, (unsigned char *)&a - , offsetof(struct adns_answer, ans), sizeof(a)); + struct adns_answer a; + enum helper_exit_status r = read_pipe(w->afd, (unsigned char *)&a + , offsetof(struct adns_answer, ans), sizeof(a)); - if (r == HES_OK) - { - /* unexpected EOF */ - syslog(LOG_ERR, "unexpected EOF from worker"); - exit(HES_IO_ERROR_IN); - } - else if (r != HES_CONTINUE) - { - exit(r); - } - else if (a.amagic != ADNS_A_MAGIC) - { - syslog(LOG_ERR, "Input from worker error: bad magic"); - exit(HES_BAD_MAGIC); - } - else if (a.continuation != w->continuation) - { - /* answer doesn't match query */ - syslog(LOG_ERR, "Input from worker error: continuation mismatch"); - exit(HES_SYNC); - } - else - { - /* pass the answer on to Pluto */ - enum helper_exit_status r - = write_pipe(PLUTO_AFD, (const unsigned char *) &a); + if (r == HES_OK) + { + /* unexpected EOF */ + syslog(LOG_ERR, "unexpected EOF from worker"); + exit(HES_IO_ERROR_IN); + } + else if (r != HES_CONTINUE) + { + exit(r); + } + else if (a.amagic != ADNS_A_MAGIC) + { + syslog(LOG_ERR, "Input from worker error: bad magic"); + exit(HES_BAD_MAGIC); + } + else if (a.continuation != w->continuation) + { + /* answer doesn't match query */ + syslog(LOG_ERR, "Input from worker error: continuation mismatch"); + exit(HES_SYNC); + } + else + { + /* pass the answer on to Pluto */ + enum helper_exit_status r + = write_pipe(PLUTO_AFD, (const unsigned char *) &a); - if (r != HES_CONTINUE) - exit(r); - w->busy = FALSE; - forward_query(w); - } + if (r != HES_CONTINUE) + exit(r); + w->busy = FALSE; + forward_query(w); + } } /* assumption: input limited; accept blocking on output */ static int master(void) { - for (;;) - { - fd_set readfds; - int maxfd = PLUTO_QFD; /* approximate lower bound */ - int ndes = 0; - struct worker_info *w; + for (;;) + { + fd_set readfds; + int maxfd = PLUTO_QFD; /* approximate lower bound */ + int ndes = 0; + struct worker_info *w; - FD_ZERO(&readfds); - if (!eof_from_pluto) - { - FD_SET(PLUTO_QFD, &readfds); - ndes++; - } - for (w = wi; w != wi_roof; w++) - { - if (w->busy) - { - FD_SET(w->afd, &readfds); - ndes++; - if (maxfd < w->afd) - maxfd = w->afd; - } - } - - if (ndes == 0) - return HES_OK; /* done! */ - - do { - ndes = select(maxfd + 1, &readfds, NULL, NULL, NULL); - } while (ndes == -1 && errno == EINTR); - if (ndes == -1) - { - syslog(LOG_ERR, "select(2) error: %s", strerror(errno)); - exit(HES_IO_ERROR_SELECT); - } - else if (ndes > 0) - { - if (FD_ISSET(PLUTO_QFD, &readfds)) - { - query(); - ndes--; - } - for (w = wi; ndes > 0 && w != wi_roof; w++) - { - if (w->busy && FD_ISSET(w->afd, &readfds)) + FD_ZERO(&readfds); + if (!eof_from_pluto) { - answer(w); - ndes--; + FD_SET(PLUTO_QFD, &readfds); + ndes++; + } + for (w = wi; w != wi_roof; w++) + { + if (w->busy) + { + FD_SET(w->afd, &readfds); + ndes++; + if (maxfd < w->afd) + maxfd = w->afd; + } + } + + if (ndes == 0) + return HES_OK; /* done! */ + + do { + ndes = select(maxfd + 1, &readfds, NULL, NULL, NULL); + } while (ndes == -1 && errno == EINTR); + if (ndes == -1) + { + syslog(LOG_ERR, "select(2) error: %s", strerror(errno)); + exit(HES_IO_ERROR_SELECT); + } + else if (ndes > 0) + { + if (FD_ISSET(PLUTO_QFD, &readfds)) + { + query(); + ndes--; + } + for (w = wi; ndes > 0 && w != wi_roof; w++) + { + if (w->busy && FD_ISSET(w->afd, &readfds)) + { + answer(w); + ndes--; + } + } } - } } - } } /* Not to be invoked by strangers -- user hostile. @@ -574,42 +574,42 @@ master(void) static void adns_usage(const char *fmt, const char *arg) { - const char **sp = ipsec_copyright_notice(); + const char **sp = ipsec_copyright_notice(); - fprintf(stderr, "INTERNAL TO PLUTO: DO NOT EXECUTE\n"); + fprintf(stderr, "INTERNAL TO PLUTO: DO NOT EXECUTE\n"); - fprintf(stderr, fmt, arg); - fprintf(stderr, "\n%s\n", ipsec_version_string()); + fprintf(stderr, fmt, arg); + fprintf(stderr, "\n%s\n", ipsec_version_string()); - for (; *sp != NULL; sp++) - fprintf(stderr, "%s\n", *sp); + for (; *sp != NULL; sp++) + fprintf(stderr, "%s\n", *sp); - syslog(LOG_ERR, fmt, arg); - exit(HES_INVOCATION); + syslog(LOG_ERR, fmt, arg); + exit(HES_INVOCATION); } int main(int argc UNUSED, char **argv) { - int i = 1; + int i = 1; - name = argv[0]; + name = argv[0]; - while (i < argc) - { - if (streq(argv[i], "-d")) + while (i < argc) { - i++; - debug = TRUE; + if (streq(argv[i], "-d")) + { + i++; + debug = TRUE; + } + else + { + adns_usage("unexpected argument \"%s\"", argv[i]); + /*NOTREACHED*/ + } } - else - { - adns_usage("unexpected argument \"%s\"", argv[i]); - /*NOTREACHED*/ - } - } - return master(); + return master(); } #endif /* !USE_LWRES */ diff --git a/src/pluto/adns.h b/src/pluto/adns.h index e5be969a9..69b0fc9c0 100644 --- a/src/pluto/adns.h +++ b/src/pluto/adns.h @@ -14,7 +14,7 @@ * RCSID $Id$ */ -#ifndef USE_LWRES /* whole file! */ +#ifndef USE_LWRES /* whole file! */ /* The interface in RHL6.x and BIND distribution 8.2.2 are different, * so we build some of our own :-( @@ -38,38 +38,38 @@ */ struct adns_query { - size_t len; - unsigned int qmagic; - unsigned long serial; - lset_t debugging; /* only used #ifdef DEBUG, but don't want layout to change */ - u_char name_buf[NS_MAXDNAME + 2]; - int type; /* T_KEY or T_TXT */ + size_t len; + unsigned int qmagic; + unsigned long serial; + lset_t debugging; /* only used #ifdef DEBUG, but don't want layout to change */ + u_char name_buf[NS_MAXDNAME + 2]; + int type; /* T_KEY or T_TXT */ }; struct adns_answer { - size_t len; - unsigned int amagic; - unsigned long serial; - struct adns_continuation *continuation; - int result; - int h_errno_val; - u_char ans[NS_PACKETSZ * 10]; /* very probably bigger than necessary */ + size_t len; + unsigned int amagic; + unsigned long serial; + struct adns_continuation *continuation; + int result; + int h_errno_val; + u_char ans[NS_PACKETSZ * 10]; /* very probably bigger than necessary */ }; enum helper_exit_status { - HES_CONTINUE = -1, /* not an exit */ - HES_OK = 0, /* all's well that ends well (perhaps EOF) */ - HES_INVOCATION, /* improper invocation */ - HES_IO_ERROR_SELECT, /* IO error in select() */ - HES_MALLOC, /* malloc failed */ - HES_IO_ERROR_IN, /* error reading pipe */ - HES_IO_ERROR_OUT, /* error reading pipe */ - HES_PIPE, /* pipe(2) failed */ - HES_SYNC, /* answer from worker doesn't match query */ - HES_FORK, /* fork(2) failed */ - HES_RES_INIT, /* resolver initialization failed */ - HES_BAD_LEN, /* implausible .len field */ - HES_BAD_MAGIC, /* .magic field wrong */ + HES_CONTINUE = -1, /* not an exit */ + HES_OK = 0, /* all's well that ends well (perhaps EOF) */ + HES_INVOCATION, /* improper invocation */ + HES_IO_ERROR_SELECT, /* IO error in select() */ + HES_MALLOC, /* malloc failed */ + HES_IO_ERROR_IN, /* error reading pipe */ + HES_IO_ERROR_OUT, /* error reading pipe */ + HES_PIPE, /* pipe(2) failed */ + HES_SYNC, /* answer from worker doesn't match query */ + HES_FORK, /* fork(2) failed */ + HES_RES_INIT, /* resolver initialization failed */ + HES_BAD_LEN, /* implausible .len field */ + HES_BAD_MAGIC, /* .magic field wrong */ }; #endif /* !USE_LWRES */ diff --git a/src/pluto/alg_info.c b/src/pluto/alg_info.c index 3f56fb118..cd0916597 100644 --- a/src/pluto/alg_info.c +++ b/src/pluto/alg_info.c @@ -47,48 +47,48 @@ int alg_info_esp_aa2sadb(int auth) { - int sadb_aalg = 0; + int sadb_aalg = 0; - switch(auth) { - case AUTH_ALGORITHM_HMAC_MD5: - case AUTH_ALGORITHM_HMAC_SHA1: - sadb_aalg = auth + 1; - break; - case AUTH_ALGORITHM_HMAC_SHA2_256: - case AUTH_ALGORITHM_HMAC_SHA2_384: - case AUTH_ALGORITHM_HMAC_SHA2_512: - case AUTH_ALGORITHM_HMAC_RIPEMD: - sadb_aalg = auth; - break; - default: - /* loose ... */ - sadb_aalg = auth; - } - return sadb_aalg; + switch(auth) { + case AUTH_ALGORITHM_HMAC_MD5: + case AUTH_ALGORITHM_HMAC_SHA1: + sadb_aalg = auth + 1; + break; + case AUTH_ALGORITHM_HMAC_SHA2_256: + case AUTH_ALGORITHM_HMAC_SHA2_384: + case AUTH_ALGORITHM_HMAC_SHA2_512: + case AUTH_ALGORITHM_HMAC_RIPEMD: + sadb_aalg = auth; + break; + default: + /* loose ... */ + sadb_aalg = auth; + } + return sadb_aalg; } int /* __attribute__ ((unused)) */ alg_info_esp_sadb2aa(int sadb_aalg) { - int auth = 0; + int auth = 0; - switch(sadb_aalg) { - case SADB_AALG_MD5HMAC: - case SADB_AALG_SHA1HMAC: - auth = sadb_aalg - 1; - break; - /* since they are the same ... :) */ - case AUTH_ALGORITHM_HMAC_SHA2_256: - case AUTH_ALGORITHM_HMAC_SHA2_384: - case AUTH_ALGORITHM_HMAC_SHA2_512: - case AUTH_ALGORITHM_HMAC_RIPEMD: - auth = sadb_aalg; - break; - default: - /* loose ... */ - auth = sadb_aalg; - } - return auth; + switch(sadb_aalg) { + case SADB_AALG_MD5HMAC: + case SADB_AALG_SHA1HMAC: + auth = sadb_aalg - 1; + break; + /* since they are the same ... :) */ + case AUTH_ALGORITHM_HMAC_SHA2_256: + case AUTH_ALGORITHM_HMAC_SHA2_384: + case AUTH_ALGORITHM_HMAC_SHA2_512: + case AUTH_ALGORITHM_HMAC_RIPEMD: + auth = sadb_aalg; + break; + default: + /* loose ... */ + auth = sadb_aalg; + } + return auth; } /* @@ -97,21 +97,21 @@ alg_info_esp_sadb2aa(int sadb_aalg) static int enum_search_prefix (enum_names *ed, const char *prefix, const char *str, int strlen) { - char buf[64]; - char *ptr; - int ret; - int len = sizeof(buf) - 1; /* reserve space for final \0 */ + char buf[64]; + char *ptr; + int ret; + int len = sizeof(buf) - 1; /* reserve space for final \0 */ - for (ptr = buf; *prefix; *ptr++ = *prefix++, len--); - while (strlen-- && len-- && *str) *ptr++ = toupper(*str++); - *ptr = 0; + for (ptr = buf; *prefix; *ptr++ = *prefix++, len--); + while (strlen-- && len-- && *str) *ptr++ = toupper(*str++); + *ptr = 0; - DBG(DBG_CRYPT, - DBG_log("enum_search_prefix () calling enum_search(%p, \"%s\")" - , ed, buf) - ) - ret = enum_search(ed, buf); - return ret; + DBG(DBG_CRYPT, + DBG_log("enum_search_prefix () calling enum_search(%p, \"%s\")" + , ed, buf) + ) + ret = enum_search(ed, buf); + return ret; } /* @@ -120,99 +120,99 @@ enum_search_prefix (enum_names *ed, const char *prefix, const char *str, int str static int enum_search_ppfix (enum_names *ed, const char *prefix, const char *postfix, const char *str, int strlen) { - char buf[64]; - char *ptr; - int ret; - int len = sizeof(buf) - 1; /* reserve space for final \0 */ + char buf[64]; + char *ptr; + int ret; + int len = sizeof(buf) - 1; /* reserve space for final \0 */ - for (ptr = buf; *prefix; *ptr++ = *prefix++, len--); - while (strlen-- && len-- && *str) *ptr++ = toupper(*str++); - while (len-- && *postfix) *ptr++ = *postfix++; - *ptr = 0; + for (ptr = buf; *prefix; *ptr++ = *prefix++, len--); + while (strlen-- && len-- && *str) *ptr++ = toupper(*str++); + while (len-- && *postfix) *ptr++ = *postfix++; + *ptr = 0; - DBG(DBG_CRYPT, - DBG_log("enum_search_ppfixi () calling enum_search(%p, \"%s\")" - , ed, buf) - ) - ret = enum_search(ed, buf); - return ret; + DBG(DBG_CRYPT, + DBG_log("enum_search_ppfixi () calling enum_search(%p, \"%s\")" + , ed, buf) + ) + ret = enum_search(ed, buf); + return ret; } /* * Search esp_transformid_names for a match, eg: - * "3des" <=> "ESP_3DES" + * "3des" <=> "ESP_3DES" */ #define ESP_MAGIC_ID 0x00ffff01 static int ealg_getbyname_esp(const char *const str, int len) { - if (!str || !*str) - { - return -1; - } + if (!str || !*str) + { + return -1; + } - /* leave special case for eg: "id248" string */ - if (streq("id", str)) - { - return ESP_MAGIC_ID; - } - return enum_search_prefix(&esp_transformid_names, "ESP_", str, len); + /* leave special case for eg: "id248" string */ + if (streq("id", str)) + { + return ESP_MAGIC_ID; + } + return enum_search_prefix(&esp_transformid_names, "ESP_", str, len); } /* * Search auth_alg_names for a match, eg: - * "md5" <=> "AUTH_ALGORITHM_HMAC_MD5" + * "md5" <=> "AUTH_ALGORITHM_HMAC_MD5" */ static int aalg_getbyname_esp(const char *const str, int len) { - int ret; - unsigned num; + int ret; + unsigned num; - if (!str || !*str) - return -1; + if (!str || !*str) + return -1; - /* interpret 'SHA' as 'SHA1' */ - if (strncasecmp("SHA", str, len) == 0) - return AUTH_ALGORITHM_HMAC_SHA1; + /* interpret 'SHA' as 'SHA1' */ + if (strncasecmp("SHA", str, len) == 0) + return AUTH_ALGORITHM_HMAC_SHA1; - /* interpret 'AESXCBC' as 'AES_XCBC_MAC' */ - if (strncasecmp("AESXCBC", str, len) == 0) - return AUTH_ALGORITHM_AES_XCBC_MAC; + /* interpret 'AESXCBC' as 'AES_XCBC_MAC' */ + if (strncasecmp("AESXCBC", str, len) == 0) + return AUTH_ALGORITHM_AES_XCBC_MAC; - ret = enum_search_prefix(&auth_alg_names,"AUTH_ALGORITHM_HMAC_", str ,len); - if (ret >= 0) - return ret; + ret = enum_search_prefix(&auth_alg_names,"AUTH_ALGORITHM_HMAC_", str ,len); + if (ret >= 0) + return ret; - ret = enum_search_prefix(&auth_alg_names,"AUTH_ALGORITHM_", str, len); - if (ret >= 0) - return ret; + ret = enum_search_prefix(&auth_alg_names,"AUTH_ALGORITHM_", str, len); + if (ret >= 0) + return ret; - sscanf(str, "id%d%n", &ret, &num); - return (ret >= 0 && num != strlen(str))? -1 : ret; + sscanf(str, "id%d%n", &ret, &num); + return (ret >= 0 && num != strlen(str))? -1 : ret; } static int modp_getbyname_esp(const char *const str, int len) { - int ret; + int ret; - if (!str || !*str) - return -1; - - ret = enum_search_prefix(&oakley_group_names,"OAKLEY_GROUP_", str, len); - if (ret >= 0) + if (!str || !*str) + return -1; + + ret = enum_search_prefix(&oakley_group_names,"OAKLEY_GROUP_", str, len); + if (ret >= 0) + return ret; + + ret = enum_search_ppfix(&oakley_group_names, "OAKLEY_GROUP_", " (extension)", str, len); return ret; - - ret = enum_search_ppfix(&oakley_group_names, "OAKLEY_GROUP_", " (extension)", str, len); - return ret; } void alg_info_free(struct alg_info *alg_info) { - free(alg_info); + free(alg_info); } /* @@ -221,36 +221,36 @@ alg_info_free(struct alg_info *alg_info) static void __alg_info_esp_add (struct alg_info_esp *alg_info, int ealg_id, unsigned ek_bits, int aalg_id, unsigned ak_bits) { - struct esp_info *esp_info = alg_info->esp; - unsigned cnt = alg_info->alg_info_cnt, i; + struct esp_info *esp_info = alg_info->esp; + unsigned cnt = alg_info->alg_info_cnt, i; - /* check for overflows */ - passert(cnt < countof(alg_info->esp)); + /* check for overflows */ + passert(cnt < countof(alg_info->esp)); - /* dont add duplicates */ - for (i = 0; i < cnt; i++) - { - if (esp_info[i].esp_ealg_id == ealg_id - && (!ek_bits || esp_info[i].esp_ealg_keylen == ek_bits) - && esp_info[i].esp_aalg_id == aalg_id - && (!ak_bits || esp_info[i].esp_aalg_keylen == ak_bits)) - return; - } + /* dont add duplicates */ + for (i = 0; i < cnt; i++) + { + if (esp_info[i].esp_ealg_id == ealg_id + && (!ek_bits || esp_info[i].esp_ealg_keylen == ek_bits) + && esp_info[i].esp_aalg_id == aalg_id + && (!ak_bits || esp_info[i].esp_aalg_keylen == ak_bits)) + return; + } - esp_info[cnt].esp_ealg_id = ealg_id; - esp_info[cnt].esp_ealg_keylen = ek_bits; - esp_info[cnt].esp_aalg_id = aalg_id; - esp_info[cnt].esp_aalg_keylen = ak_bits; + esp_info[cnt].esp_ealg_id = ealg_id; + esp_info[cnt].esp_ealg_keylen = ek_bits; + esp_info[cnt].esp_aalg_id = aalg_id; + esp_info[cnt].esp_aalg_keylen = ak_bits; - /* sadb values */ - esp_info[cnt].encryptalg = ealg_id; - esp_info[cnt].authalg = alg_info_esp_aa2sadb(aalg_id); - alg_info->alg_info_cnt++; + /* sadb values */ + esp_info[cnt].encryptalg = ealg_id; + esp_info[cnt].authalg = alg_info_esp_aa2sadb(aalg_id); + alg_info->alg_info_cnt++; - DBG(DBG_CRYPT, - DBG_log("__alg_info_esp_add() ealg=%d aalg=%d cnt=%d" - , ealg_id, aalg_id, alg_info->alg_info_cnt) - ) + DBG(DBG_CRYPT, + DBG_log("__alg_info_esp_add() ealg=%d aalg=%d cnt=%d" + , ealg_id, aalg_id, alg_info->alg_info_cnt) + ) } /* @@ -259,138 +259,138 @@ __alg_info_esp_add (struct alg_info_esp *alg_info, int ealg_id, unsigned ek_bits static void alg_info_esp_add (struct alg_info *alg_info, int ealg_id, int ek_bits, int aalg_id, int ak_bits) { - /* Policy: default to 3DES */ - if (ealg_id == 0) - ealg_id = ESP_3DES; + /* Policy: default to 3DES */ + if (ealg_id == 0) + ealg_id = ESP_3DES; - if (ealg_id > 0) - { -#ifndef NO_PLUTO - if (aalg_id > 0) -#else - /* Allow no auth for manual conns (from spi.c) */ - if (aalg_id >= 0) -#endif - __alg_info_esp_add((struct alg_info_esp *)alg_info, - ealg_id, ek_bits, - aalg_id, ak_bits); - else + if (ealg_id > 0) { - /* Policy: default to MD5 and SHA1 */ - __alg_info_esp_add((struct alg_info_esp *)alg_info, - ealg_id, ek_bits, - AUTH_ALGORITHM_HMAC_MD5, ak_bits); - __alg_info_esp_add((struct alg_info_esp *)alg_info, - ealg_id, ek_bits, - AUTH_ALGORITHM_HMAC_SHA1, ak_bits); +#ifndef NO_PLUTO + if (aalg_id > 0) +#else + /* Allow no auth for manual conns (from spi.c) */ + if (aalg_id >= 0) +#endif + __alg_info_esp_add((struct alg_info_esp *)alg_info, + ealg_id, ek_bits, + aalg_id, ak_bits); + else + { + /* Policy: default to MD5 and SHA1 */ + __alg_info_esp_add((struct alg_info_esp *)alg_info, + ealg_id, ek_bits, + AUTH_ALGORITHM_HMAC_MD5, ak_bits); + __alg_info_esp_add((struct alg_info_esp *)alg_info, + ealg_id, ek_bits, + AUTH_ALGORITHM_HMAC_SHA1, ak_bits); + } } - } } #ifndef NO_PLUTO /************************************** * - * IKE alg + * IKE alg * *************************************/ /* * Search oakley_enc_names for a match, eg: - * "3des_cbc" <=> "OAKLEY_3DES_CBC" + * "3des_cbc" <=> "OAKLEY_3DES_CBC" */ static int ealg_getbyname_ike(const char *const str, int len) { - int ret; + int ret; - if (!str || !*str) - return -1; + if (!str || !*str) + return -1; - ret = enum_search_prefix(&oakley_enc_names,"OAKLEY_", str, len); - if (ret >= 0) + ret = enum_search_prefix(&oakley_enc_names,"OAKLEY_", str, len); + if (ret >= 0) + return ret; + + ret = enum_search_ppfix(&oakley_enc_names, "OAKLEY_", "_CBC", str, len); return ret; - - ret = enum_search_ppfix(&oakley_enc_names, "OAKLEY_", "_CBC", str, len); - return ret; } /* * Search oakley_hash_names for a match, eg: - * "md5" <=> "OAKLEY_MD5" + * "md5" <=> "OAKLEY_MD5" */ static int aalg_getbyname_ike(const char *const str, int len) { - int ret; - unsigned num; + int ret; + unsigned num; - if (!str || !*str) - return -1; + if (!str || !*str) + return -1; - /* interpret 'SHA1' as 'SHA' */ - if (strncasecmp("SHA1", str, len) == 0) - return enum_search(&oakley_hash_names, "OAKLEY_SHA"); + /* interpret 'SHA1' as 'SHA' */ + if (strncasecmp("SHA1", str, len) == 0) + return enum_search(&oakley_hash_names, "OAKLEY_SHA"); - ret = enum_search_prefix(&oakley_hash_names,"OAKLEY_", str, len); - if (ret >= 0) - return ret; + ret = enum_search_prefix(&oakley_hash_names,"OAKLEY_", str, len); + if (ret >= 0) + return ret; - sscanf(str, "id%d%n", &ret, &num); - return (ret >=0 && num != strlen(str))? -1 : ret; + sscanf(str, "id%d%n", &ret, &num); + return (ret >=0 && num != strlen(str))? -1 : ret; } /* * Search oakley_group_names for a match, eg: - * "modp1024" <=> "OAKLEY_GROUP_MODP1024" + * "modp1024" <=> "OAKLEY_GROUP_MODP1024" */ static int modp_getbyname_ike(const char *const str, int len) { - int ret; + int ret; - if (!str || !*str) - return -1; + if (!str || !*str) + return -1; - ret = enum_search_prefix(&oakley_group_names,"OAKLEY_GROUP_", str, len); - if (ret >= 0) + ret = enum_search_prefix(&oakley_group_names,"OAKLEY_GROUP_", str, len); + if (ret >= 0) + return ret; + + ret = enum_search_ppfix(&oakley_group_names, "OAKLEY_GROUP_", " (extension)", str, len); return ret; - - ret = enum_search_ppfix(&oakley_group_names, "OAKLEY_GROUP_", " (extension)", str, len); - return ret; } static void __alg_info_ike_add (struct alg_info_ike *alg_info, int ealg_id, unsigned ek_bits, int aalg_id, unsigned ak_bits, int modp_id) { - struct ike_info *ike_info = alg_info->ike; - unsigned cnt = alg_info->alg_info_cnt; - unsigned i; + struct ike_info *ike_info = alg_info->ike; + unsigned cnt = alg_info->alg_info_cnt; + unsigned i; - /* check for overflows */ - passert(cnt < countof(alg_info->ike)); + /* check for overflows */ + passert(cnt < countof(alg_info->ike)); - /* dont add duplicates */ + /* dont add duplicates */ for (i = 0;i < cnt; i++) { - if (ike_info[i].ike_ealg == ealg_id - && (!ek_bits || ike_info[i].ike_eklen == ek_bits) - && ike_info[i].ike_halg == aalg_id - && (!ak_bits || ike_info[i].ike_hklen == ak_bits) - && ike_info[i].ike_modp==modp_id) - return; - } + if (ike_info[i].ike_ealg == ealg_id + && (!ek_bits || ike_info[i].ike_eklen == ek_bits) + && ike_info[i].ike_halg == aalg_id + && (!ak_bits || ike_info[i].ike_hklen == ak_bits) + && ike_info[i].ike_modp==modp_id) + return; + } - ike_info[cnt].ike_ealg = ealg_id; - ike_info[cnt].ike_eklen = ek_bits; - ike_info[cnt].ike_halg = aalg_id; - ike_info[cnt].ike_hklen = ak_bits; - ike_info[cnt].ike_modp = modp_id; - alg_info->alg_info_cnt++; + ike_info[cnt].ike_ealg = ealg_id; + ike_info[cnt].ike_eklen = ek_bits; + ike_info[cnt].ike_halg = aalg_id; + ike_info[cnt].ike_hklen = ak_bits; + ike_info[cnt].ike_modp = modp_id; + alg_info->alg_info_cnt++; - DBG(DBG_CRYPT, - DBG_log("__alg_info_ike_add() ealg=%d aalg=%d modp_id=%d, cnt=%d" - , ealg_id, aalg_id, modp_id - , alg_info->alg_info_cnt) - ) + DBG(DBG_CRYPT, + DBG_log("__alg_info_ike_add() ealg=%d aalg=%d modp_id=%d, cnt=%d" + , ealg_id, aalg_id, modp_id + , alg_info->alg_info_cnt) + ) } /* @@ -399,318 +399,318 @@ __alg_info_ike_add (struct alg_info_ike *alg_info, int ealg_id, unsigned ek_bits */ static int default_ike_groups[] = { - OAKLEY_GROUP_MODP1536, - OAKLEY_GROUP_MODP1024 + OAKLEY_GROUP_MODP1536, + OAKLEY_GROUP_MODP1024 }; -/* - * Add IKE alg info _with_ logic (policy): +/* + * Add IKE alg info _with_ logic (policy): */ static void alg_info_ike_add (struct alg_info *alg_info, int ealg_id, int ek_bits, int aalg_id, int ak_bits, int modp_id) { - int i = 0; - int n_groups = countof(default_ike_groups); + int i = 0; + int n_groups = countof(default_ike_groups); - /* if specified modp_id avoid loop over default_ike_groups */ - if (modp_id) - { - n_groups=0; - goto in_loop; - } - - for (; n_groups--; i++) - { - modp_id = default_ike_groups[i]; -in_loop: - /* Policy: default to 3DES */ - if (ealg_id == 0) - ealg_id = OAKLEY_3DES_CBC; - - if (ealg_id > 0) + /* if specified modp_id avoid loop over default_ike_groups */ + if (modp_id) { - if (aalg_id > 0) - __alg_info_ike_add((struct alg_info_ike *)alg_info, - ealg_id, ek_bits, - aalg_id, ak_bits, - modp_id); - else - { - /* Policy: default to MD5 and SHA */ - __alg_info_ike_add((struct alg_info_ike *)alg_info, - ealg_id, ek_bits, - OAKLEY_MD5, ak_bits, - modp_id); - __alg_info_ike_add((struct alg_info_ike *)alg_info, - ealg_id, ek_bits, - OAKLEY_SHA, ak_bits, - modp_id); - } + n_groups=0; + goto in_loop; + } + + for (; n_groups--; i++) + { + modp_id = default_ike_groups[i]; +in_loop: + /* Policy: default to 3DES */ + if (ealg_id == 0) + ealg_id = OAKLEY_3DES_CBC; + + if (ealg_id > 0) + { + if (aalg_id > 0) + __alg_info_ike_add((struct alg_info_ike *)alg_info, + ealg_id, ek_bits, + aalg_id, ak_bits, + modp_id); + else + { + /* Policy: default to MD5 and SHA */ + __alg_info_ike_add((struct alg_info_ike *)alg_info, + ealg_id, ek_bits, + OAKLEY_MD5, ak_bits, + modp_id); + __alg_info_ike_add((struct alg_info_ike *)alg_info, + ealg_id, ek_bits, + OAKLEY_SHA, ak_bits, + modp_id); + } + } } - } } #endif /* NO_PLUTO */ -/* - * Creates a new alg_info by parsing passed string +/* + * Creates a new alg_info by parsing passed string */ enum parser_state_esp { - ST_INI, - ST_EA, /* encrypt algo */ - ST_EA_END, - ST_EK, /* enc. key length */ - ST_EK_END, - ST_AA, /* auth algo */ - ST_AA_END, - ST_AK, /* auth. key length */ - ST_AK_END, - ST_MODP, /* modp spec */ - ST_FLAG_STRICT, - ST_END, - ST_EOF, - ST_ERR + ST_INI, + ST_EA, /* encrypt algo */ + ST_EA_END, + ST_EK, /* enc. key length */ + ST_EK_END, + ST_AA, /* auth algo */ + ST_AA_END, + ST_AK, /* auth. key length */ + ST_AK_END, + ST_MODP, /* modp spec */ + ST_FLAG_STRICT, + ST_END, + ST_EOF, + ST_ERR }; static const char *parser_state_esp_names[] = { - "ST_INI", - "ST_EA", - "ST_EA_END", - "ST_EK", - "ST_EK_END", - "ST_AA", - "ST_AA_END", - "ST_AK", - "ST_AK_END", - "ST_MOPD", - "ST_FLAG_STRICT", - "ST_END", - "ST_EOF", - "ST_ERR" + "ST_INI", + "ST_EA", + "ST_EA_END", + "ST_EK", + "ST_EK_END", + "ST_AA", + "ST_AA_END", + "ST_AK", + "ST_AK_END", + "ST_MOPD", + "ST_FLAG_STRICT", + "ST_END", + "ST_EOF", + "ST_ERR" }; static const char* parser_state_name_esp(enum parser_state_esp state) { - return parser_state_esp_names[state]; + return parser_state_esp_names[state]; } /* XXX:jjo to implement different parser for ESP and IKE */ struct parser_context { - unsigned state, old_state; - unsigned protoid; - char ealg_buf[16]; - char aalg_buf[16]; - char modp_buf[16]; - int (*ealg_getbyname)(const char *const str, int len); - int (*aalg_getbyname)(const char *const str, int len); - int (*modp_getbyname)(const char *const str, int len); - char *ealg_str; - char *aalg_str; - char *modp_str; - int eklen; - int aklen; - int ch; - const char *err; + unsigned state, old_state; + unsigned protoid; + char ealg_buf[16]; + char aalg_buf[16]; + char modp_buf[16]; + int (*ealg_getbyname)(const char *const str, int len); + int (*aalg_getbyname)(const char *const str, int len); + int (*modp_getbyname)(const char *const str, int len); + char *ealg_str; + char *aalg_str; + char *modp_str; + int eklen; + int aklen; + int ch; + const char *err; }; static inline void parser_set_state(struct parser_context *p_ctx, enum parser_state_esp state) { - if (state != p_ctx->state) - { - p_ctx->old_state = p_ctx->state; - p_ctx->state = state; - } + if (state != p_ctx->state) + { + p_ctx->old_state = p_ctx->state; + p_ctx->state = state; + } } static int parser_machine(struct parser_context *p_ctx) { - int ch = p_ctx->ch; + int ch = p_ctx->ch; - /* special 'absolute' cases */ - p_ctx->err = "No error."; + /* special 'absolute' cases */ + p_ctx->err = "No error."; - /* chars that end algo strings */ - switch (ch){ - case 0: /* end-of-string */ - case '!': /* flag as strict algo list */ - case ',': /* algo string separator */ - switch (p_ctx->state) { - case ST_EA: - case ST_EK: - case ST_AA: - case ST_AK: - case ST_MODP: - case ST_FLAG_STRICT: - { - enum parser_state_esp next_state = 0; + /* chars that end algo strings */ + switch (ch){ + case 0: /* end-of-string */ + case '!': /* flag as strict algo list */ + case ',': /* algo string separator */ + switch (p_ctx->state) { + case ST_EA: + case ST_EK: + case ST_AA: + case ST_AK: + case ST_MODP: + case ST_FLAG_STRICT: + { + enum parser_state_esp next_state = 0; - switch (ch) { - case 0: - next_state = ST_EOF; - break; - case ',': - next_state = ST_END; - break; - case '!': - next_state = ST_FLAG_STRICT; - break; - } - /* ch? parser_set_state(p_ctx, ST_END) : parser_set_state(p_ctx, ST_EOF) ; */ - parser_set_state(p_ctx, next_state); - goto out; - } - default: - p_ctx->err = "String ended with invalid char"; - goto err; + switch (ch) { + case 0: + next_state = ST_EOF; + break; + case ',': + next_state = ST_END; + break; + case '!': + next_state = ST_FLAG_STRICT; + break; + } + /* ch? parser_set_state(p_ctx, ST_END) : parser_set_state(p_ctx, ST_EOF) ; */ + parser_set_state(p_ctx, next_state); + goto out; + } + default: + p_ctx->err = "String ended with invalid char"; + goto err; + } } - } re_eval: - switch (p_ctx->state) { - case ST_INI: - if (isspace(ch)) - break; - if (isalnum(ch)) - { - *(p_ctx->ealg_str++) = ch; - parser_set_state(p_ctx, ST_EA); - break; - } - p_ctx->err = "No alphanum. char initially found"; - goto err; - case ST_EA: - if (isalpha(ch) || ch == '_') - { - *(p_ctx->ealg_str++) = ch; - break; - } - if (isdigit(ch)) - { - /* bravely switch to enc keylen */ - *(p_ctx->ealg_str) = 0; - parser_set_state(p_ctx, ST_EK); - goto re_eval; - } - if (ch == '-') - { - *(p_ctx->ealg_str) = 0; - parser_set_state(p_ctx, ST_EA_END); - break; - } - p_ctx->err = "No valid char found after enc alg string"; - goto err; - case ST_EA_END: - if (isdigit(ch)) - { - /* bravely switch to enc keylen */ - parser_set_state(p_ctx, ST_EK); - goto re_eval; - } - if (isalpha(ch)) - { - parser_set_state(p_ctx, ST_AA); - goto re_eval; - } - p_ctx->err = "No alphanum char found after enc alg separator"; - goto err; - case ST_EK: - if (ch == '-') - { - parser_set_state(p_ctx, ST_EK_END); - break; - } - if (isdigit(ch)) - { - p_ctx->eklen = p_ctx->eklen*10 + ch - '0'; - break; - } - p_ctx->err = "Non digit or valid separator found while reading enc keylen"; - goto err; - case ST_EK_END: - if (isalpha(ch)) - { - parser_set_state(p_ctx, ST_AA); - goto re_eval; - } - p_ctx->err = "Non alpha char found after enc keylen end separator"; - goto err; - case ST_AA: - if (ch == '-') - { - *(p_ctx->aalg_str++) = 0; - parser_set_state(p_ctx, ST_AA_END); - break; - } - if (isalnum(ch) || ch == '_') - { - *(p_ctx->aalg_str++) = ch; - break; - } - p_ctx->err = "Non alphanum or valid separator found in auth string"; - goto err; - case ST_AA_END: - if (isdigit(ch)) - { - parser_set_state(p_ctx, ST_AK); - goto re_eval; - } - /* Only allow modpXXXX string if we have a modp_getbyname method */ - if ((p_ctx->modp_getbyname) && isalpha(ch)) - { - parser_set_state(p_ctx, ST_MODP); - goto re_eval; - } - p_ctx->err = "Non initial digit found for auth keylen"; - goto err; - case ST_AK: - if (ch=='-') - { - parser_set_state(p_ctx, ST_AK_END); - break; - } - if (isdigit(ch)) - { - p_ctx->aklen = p_ctx->aklen*10 + ch - '0'; - break; - } - p_ctx->err = "Non digit found for auth keylen"; - goto err; - case ST_AK_END: - /* Only allow modpXXXX string if we have a modp_getbyname method */ - if ((p_ctx->modp_getbyname) && isalpha(ch)) - { - parser_set_state(p_ctx, ST_MODP); - goto re_eval; - } - p_ctx->err = "Non alpha char found after auth keylen"; - goto err; - case ST_MODP: - if (isalnum(ch)) - { - *(p_ctx->modp_str++) = ch; - break; - } - p_ctx->err = "Non alphanum char found after in modp string"; - goto err; - case ST_FLAG_STRICT: - if (ch == 0) - parser_set_state(p_ctx, ST_END); - p_ctx->err = "Flags character(s) must be at end of whole string"; - goto err; + switch (p_ctx->state) { + case ST_INI: + if (isspace(ch)) + break; + if (isalnum(ch)) + { + *(p_ctx->ealg_str++) = ch; + parser_set_state(p_ctx, ST_EA); + break; + } + p_ctx->err = "No alphanum. char initially found"; + goto err; + case ST_EA: + if (isalpha(ch) || ch == '_') + { + *(p_ctx->ealg_str++) = ch; + break; + } + if (isdigit(ch)) + { + /* bravely switch to enc keylen */ + *(p_ctx->ealg_str) = 0; + parser_set_state(p_ctx, ST_EK); + goto re_eval; + } + if (ch == '-') + { + *(p_ctx->ealg_str) = 0; + parser_set_state(p_ctx, ST_EA_END); + break; + } + p_ctx->err = "No valid char found after enc alg string"; + goto err; + case ST_EA_END: + if (isdigit(ch)) + { + /* bravely switch to enc keylen */ + parser_set_state(p_ctx, ST_EK); + goto re_eval; + } + if (isalpha(ch)) + { + parser_set_state(p_ctx, ST_AA); + goto re_eval; + } + p_ctx->err = "No alphanum char found after enc alg separator"; + goto err; + case ST_EK: + if (ch == '-') + { + parser_set_state(p_ctx, ST_EK_END); + break; + } + if (isdigit(ch)) + { + p_ctx->eklen = p_ctx->eklen*10 + ch - '0'; + break; + } + p_ctx->err = "Non digit or valid separator found while reading enc keylen"; + goto err; + case ST_EK_END: + if (isalpha(ch)) + { + parser_set_state(p_ctx, ST_AA); + goto re_eval; + } + p_ctx->err = "Non alpha char found after enc keylen end separator"; + goto err; + case ST_AA: + if (ch == '-') + { + *(p_ctx->aalg_str++) = 0; + parser_set_state(p_ctx, ST_AA_END); + break; + } + if (isalnum(ch) || ch == '_') + { + *(p_ctx->aalg_str++) = ch; + break; + } + p_ctx->err = "Non alphanum or valid separator found in auth string"; + goto err; + case ST_AA_END: + if (isdigit(ch)) + { + parser_set_state(p_ctx, ST_AK); + goto re_eval; + } + /* Only allow modpXXXX string if we have a modp_getbyname method */ + if ((p_ctx->modp_getbyname) && isalpha(ch)) + { + parser_set_state(p_ctx, ST_MODP); + goto re_eval; + } + p_ctx->err = "Non initial digit found for auth keylen"; + goto err; + case ST_AK: + if (ch=='-') + { + parser_set_state(p_ctx, ST_AK_END); + break; + } + if (isdigit(ch)) + { + p_ctx->aklen = p_ctx->aklen*10 + ch - '0'; + break; + } + p_ctx->err = "Non digit found for auth keylen"; + goto err; + case ST_AK_END: + /* Only allow modpXXXX string if we have a modp_getbyname method */ + if ((p_ctx->modp_getbyname) && isalpha(ch)) + { + parser_set_state(p_ctx, ST_MODP); + goto re_eval; + } + p_ctx->err = "Non alpha char found after auth keylen"; + goto err; + case ST_MODP: + if (isalnum(ch)) + { + *(p_ctx->modp_str++) = ch; + break; + } + p_ctx->err = "Non alphanum char found after in modp string"; + goto err; + case ST_FLAG_STRICT: + if (ch == 0) + parser_set_state(p_ctx, ST_END); + p_ctx->err = "Flags character(s) must be at end of whole string"; + goto err; - /* XXX */ - case ST_END: - case ST_EOF: - case ST_ERR: - break; - /* XXX */ - } + /* XXX */ + case ST_END: + case ST_EOF: + case ST_ERR: + break; + /* XXX */ + } out: - return p_ctx->state; + return p_ctx->state; err: - parser_set_state(p_ctx, ST_ERR); - return ST_ERR; + parser_set_state(p_ctx, ST_ERR); + return ST_ERR; } /* @@ -720,470 +720,470 @@ err: static void parser_init(struct parser_context *p_ctx, unsigned protoid) { - memset(p_ctx, 0, sizeof (*p_ctx)); - p_ctx->protoid = protoid; /* XXX: jjo */ - p_ctx->protoid = PROTO_IPSEC_ESP; - p_ctx->ealg_str = p_ctx->ealg_buf; - p_ctx->aalg_str = p_ctx->aalg_buf; - p_ctx->modp_str = p_ctx->modp_buf; - p_ctx->state = ST_INI; + memset(p_ctx, 0, sizeof (*p_ctx)); + p_ctx->protoid = protoid; /* XXX: jjo */ + p_ctx->protoid = PROTO_IPSEC_ESP; + p_ctx->ealg_str = p_ctx->ealg_buf; + p_ctx->aalg_str = p_ctx->aalg_buf; + p_ctx->modp_str = p_ctx->modp_buf; + p_ctx->state = ST_INI; - switch (protoid) { + switch (protoid) { #ifndef NO_PLUTO - case PROTO_ISAKMP: - p_ctx->ealg_getbyname = ealg_getbyname_ike; - p_ctx->aalg_getbyname = aalg_getbyname_ike; - p_ctx->modp_getbyname = modp_getbyname_ike; - break; + case PROTO_ISAKMP: + p_ctx->ealg_getbyname = ealg_getbyname_ike; + p_ctx->aalg_getbyname = aalg_getbyname_ike; + p_ctx->modp_getbyname = modp_getbyname_ike; + break; #endif - case PROTO_IPSEC_ESP: - p_ctx->ealg_getbyname = ealg_getbyname_esp; - p_ctx->aalg_getbyname = aalg_getbyname_esp; - break; - } + case PROTO_IPSEC_ESP: + p_ctx->ealg_getbyname = ealg_getbyname_esp; + p_ctx->aalg_getbyname = aalg_getbyname_esp; + break; + } } static int parser_alg_info_add(struct parser_context *p_ctx, struct alg_info *alg_info) { - int ealg_id = 0; - int aalg_id = 0; - int modp_id = 0; + int ealg_id = 0; + int aalg_id = 0; + int modp_id = 0; #ifndef NO_PLUTO - const struct oakley_group_desc *gd; + const struct oakley_group_desc *gd; #endif - if (*p_ctx->ealg_buf) - { - ealg_id = p_ctx->ealg_getbyname(p_ctx->ealg_buf, strlen(p_ctx->ealg_buf)); - if (ealg_id == ESP_MAGIC_ID) + if (*p_ctx->ealg_buf) { - ealg_id = p_ctx->eklen; - p_ctx->eklen = 0; + ealg_id = p_ctx->ealg_getbyname(p_ctx->ealg_buf, strlen(p_ctx->ealg_buf)); + if (ealg_id == ESP_MAGIC_ID) + { + ealg_id = p_ctx->eklen; + p_ctx->eklen = 0; + } + if (ealg_id < 0) + { + p_ctx->err = "enc_alg not found"; + return -1; + } + DBG(DBG_CRYPT, + DBG_log("parser_alg_info_add() ealg_getbyname(\"%s\")=%d" + , p_ctx->ealg_buf + , ealg_id) + ) } - if (ealg_id < 0) + if (*p_ctx->aalg_buf) { - p_ctx->err = "enc_alg not found"; - return -1; + aalg_id = p_ctx->aalg_getbyname(p_ctx->aalg_buf, strlen(p_ctx->aalg_buf)); + if (aalg_id < 0) + { + p_ctx->err = "hash_alg not found"; + return -1; + } + DBG(DBG_CRYPT, + DBG_log("parser_alg_info_add() aalg_getbyname(\"%s\")=%d" + , p_ctx->aalg_buf + , aalg_id) + ) } - DBG(DBG_CRYPT, - DBG_log("parser_alg_info_add() ealg_getbyname(\"%s\")=%d" - , p_ctx->ealg_buf - , ealg_id) - ) - } - if (*p_ctx->aalg_buf) - { - aalg_id = p_ctx->aalg_getbyname(p_ctx->aalg_buf, strlen(p_ctx->aalg_buf)); - if (aalg_id < 0) + if (p_ctx->modp_getbyname && *p_ctx->modp_buf) { - p_ctx->err = "hash_alg not found"; - return -1; + modp_id = p_ctx->modp_getbyname(p_ctx->modp_buf, strlen(p_ctx->modp_buf)); + if (modp_id < 0) + { + p_ctx->err = "modp group not found"; + return -1; + } + DBG(DBG_CRYPT, + DBG_log("parser_alg_info_add() modp_getbyname(\"%s\")=%d" + , p_ctx->modp_buf + , modp_id) + ) } - DBG(DBG_CRYPT, - DBG_log("parser_alg_info_add() aalg_getbyname(\"%s\")=%d" - , p_ctx->aalg_buf - , aalg_id) - ) - } - if (p_ctx->modp_getbyname && *p_ctx->modp_buf) - { - modp_id = p_ctx->modp_getbyname(p_ctx->modp_buf, strlen(p_ctx->modp_buf)); - if (modp_id < 0) - { - p_ctx->err = "modp group not found"; - return -1; - } - DBG(DBG_CRYPT, - DBG_log("parser_alg_info_add() modp_getbyname(\"%s\")=%d" - , p_ctx->modp_buf - , modp_id) - ) - } - switch (alg_info->alg_info_protoid) { - case PROTO_IPSEC_ESP: - alg_info_esp_add(alg_info, - ealg_id, p_ctx->eklen, - aalg_id, p_ctx->aklen); - break; + switch (alg_info->alg_info_protoid) { + case PROTO_IPSEC_ESP: + alg_info_esp_add(alg_info, + ealg_id, p_ctx->eklen, + aalg_id, p_ctx->aklen); + break; #ifndef NO_PLUTO - case PROTO_ISAKMP: - if (modp_id && !(gd = lookup_group(modp_id))) - { - p_ctx->err = "found modp group id, but not supported"; - return -1; - } - alg_info_ike_add(alg_info, - ealg_id, p_ctx->eklen, - aalg_id, p_ctx->aklen, - modp_id); - break; + case PROTO_ISAKMP: + if (modp_id && !(gd = lookup_group(modp_id))) + { + p_ctx->err = "found modp group id, but not supported"; + return -1; + } + alg_info_ike_add(alg_info, + ealg_id, p_ctx->eklen, + aalg_id, p_ctx->aklen, + modp_id); + break; #endif - default: - return -1; - } - return 0; + default: + return -1; + } + return 0; } static int alg_info_parse_str (struct alg_info *alg_info, const char *alg_str, const char **err_p) { - struct parser_context ctx; - int ret; - const char *ptr; - static char err_buf[256]; + struct parser_context ctx; + int ret; + const char *ptr; + static char err_buf[256]; - *err_buf = 0; - parser_init(&ctx, alg_info->alg_info_protoid); - if (err_p) - *err_p = NULL; + *err_buf = 0; + parser_init(&ctx, alg_info->alg_info_protoid); + if (err_p) + *err_p = NULL; - /* use default if nul esp string */ - if (!*alg_str) - { - switch (alg_info->alg_info_protoid) { + /* use default if nul esp string */ + if (!*alg_str) + { + switch (alg_info->alg_info_protoid) { #ifndef NO_PLUTO - case PROTO_ISAKMP: - alg_info_ike_add(alg_info, 0, 0, 0, 0, 0); - return 0; + case PROTO_ISAKMP: + alg_info_ike_add(alg_info, 0, 0, 0, 0, 0); + return 0; #endif - case PROTO_IPSEC_ESP: - alg_info_esp_add(alg_info, 0, 0, 0, 0); - return 0; - default: - /* IMPOSSIBLE */ - passert(alg_info->alg_info_protoid); + case PROTO_IPSEC_ESP: + alg_info_esp_add(alg_info, 0, 0, 0, 0); + return 0; + default: + /* IMPOSSIBLE */ + passert(alg_info->alg_info_protoid); + } } - } - for (ret = 0, ptr = alg_str; ret < ST_EOF;) - { - ctx.ch = *ptr++; - ret = parser_machine(&ctx); - - switch (ret) { - case ST_FLAG_STRICT: - alg_info->alg_info_flags |= ALG_INFO_F_STRICT; - break; - case ST_END: - case ST_EOF: - DBG(DBG_CRYPT, - DBG_log("alg_info_parse_str() ealg_buf=%s aalg_buf=%s" - "eklen=%d aklen=%d", - ctx.ealg_buf, ctx.aalg_buf, - ctx.eklen, ctx.aklen) - ) - if (parser_alg_info_add(&ctx, alg_info) < 0) - { - snprintf(err_buf, sizeof(err_buf), - "%s, enc_alg=\"%s\", auth_alg=\"%s\", modp=\"%s\"", - ctx.err, - ctx.ealg_buf, - ctx.aalg_buf, - ctx.modp_buf); - goto err; - } - /* zero out for next run (ST_END) */ - parser_init(&ctx, alg_info->alg_info_protoid); - break; - case ST_ERR: - snprintf(err_buf, sizeof(err_buf), - "%s, just after \"%.*s\" (old_state=%s)", - ctx.err, - (int)(ptr-alg_str-1), alg_str , - parser_state_name_esp(ctx.old_state)); - goto err; - default: - if (!ctx.ch) - break; + for (ret = 0, ptr = alg_str; ret < ST_EOF;) + { + ctx.ch = *ptr++; + ret = parser_machine(&ctx); + + switch (ret) { + case ST_FLAG_STRICT: + alg_info->alg_info_flags |= ALG_INFO_F_STRICT; + break; + case ST_END: + case ST_EOF: + DBG(DBG_CRYPT, + DBG_log("alg_info_parse_str() ealg_buf=%s aalg_buf=%s" + "eklen=%d aklen=%d", + ctx.ealg_buf, ctx.aalg_buf, + ctx.eklen, ctx.aklen) + ) + if (parser_alg_info_add(&ctx, alg_info) < 0) + { + snprintf(err_buf, sizeof(err_buf), + "%s, enc_alg=\"%s\", auth_alg=\"%s\", modp=\"%s\"", + ctx.err, + ctx.ealg_buf, + ctx.aalg_buf, + ctx.modp_buf); + goto err; + } + /* zero out for next run (ST_END) */ + parser_init(&ctx, alg_info->alg_info_protoid); + break; + case ST_ERR: + snprintf(err_buf, sizeof(err_buf), + "%s, just after \"%.*s\" (old_state=%s)", + ctx.err, + (int)(ptr-alg_str-1), alg_str , + parser_state_name_esp(ctx.old_state)); + goto err; + default: + if (!ctx.ch) + break; + } } - } - return 0; + return 0; err: - if (err_p) - *err_p=err_buf; - return -1; + if (err_p) + *err_p=err_buf; + return -1; } struct alg_info_esp * alg_info_esp_create_from_str (const char *alg_str, const char **err_p) { - struct alg_info_esp *alg_info_esp; - char esp_buf[256]; - static char err_buf[256]; - char *pfs_name; - int ret = 0; - /* - * alg_info storage should be sized dynamically - * but this may require 2passes to know - * transform count in advance. - */ - alg_info_esp = malloc_thing (struct alg_info_esp); - zero(alg_info_esp); + struct alg_info_esp *alg_info_esp; + char esp_buf[256]; + static char err_buf[256]; + char *pfs_name; + int ret = 0; + /* + * alg_info storage should be sized dynamically + * but this may require 2passes to know + * transform count in advance. + */ + alg_info_esp = malloc_thing (struct alg_info_esp); + zero(alg_info_esp); - pfs_name=index (alg_str, ';'); - if (pfs_name) - { - memcpy(esp_buf, alg_str, pfs_name-alg_str); - esp_buf[pfs_name-alg_str] = 0; - alg_str = esp_buf; - pfs_name++; - - /* if pfs strings AND first char is not '0' */ - if (*pfs_name && pfs_name[0] != '0') + pfs_name=index (alg_str, ';'); + if (pfs_name) { - ret = modp_getbyname_esp(pfs_name, strlen(pfs_name)); - if (ret < 0) - { - /* Bomb if pfsgroup not found */ - DBG(DBG_CRYPT, - DBG_log("alg_info_esp_create_from_str(): pfsgroup \"%s\" not found" - , pfs_name) - ) - if (*err_p) - { - snprintf(err_buf, sizeof(err_buf), - "pfsgroup \"%s\" not found", - pfs_name); + memcpy(esp_buf, alg_str, pfs_name-alg_str); + esp_buf[pfs_name-alg_str] = 0; + alg_str = esp_buf; + pfs_name++; - *err_p = err_buf; + /* if pfs strings AND first char is not '0' */ + if (*pfs_name && pfs_name[0] != '0') + { + ret = modp_getbyname_esp(pfs_name, strlen(pfs_name)); + if (ret < 0) + { + /* Bomb if pfsgroup not found */ + DBG(DBG_CRYPT, + DBG_log("alg_info_esp_create_from_str(): pfsgroup \"%s\" not found" + , pfs_name) + ) + if (*err_p) + { + snprintf(err_buf, sizeof(err_buf), + "pfsgroup \"%s\" not found", + pfs_name); + + *err_p = err_buf; + } + goto out; + } + alg_info_esp->esp_pfsgroup = ret; } - goto out; - } - alg_info_esp->esp_pfsgroup = ret; } - } - else - alg_info_esp->esp_pfsgroup = 0; - - alg_info_esp->alg_info_protoid = PROTO_IPSEC_ESP; - ret = alg_info_parse_str((struct alg_info *)alg_info_esp, alg_str, err_p) ; + else + alg_info_esp->esp_pfsgroup = 0; + + alg_info_esp->alg_info_protoid = PROTO_IPSEC_ESP; + ret = alg_info_parse_str((struct alg_info *)alg_info_esp, alg_str, err_p) ; out: - if (ret < 0) - { - free(alg_info_esp); - alg_info_esp = NULL; - } - return alg_info_esp; + if (ret < 0) + { + free(alg_info_esp); + alg_info_esp = NULL; + } + return alg_info_esp; } #ifndef NO_PLUTO struct alg_info_ike * alg_info_ike_create_from_str (const char *alg_str, const char **err_p) { - struct alg_info_ike *alg_info_ike; - /* - * alg_info storage should be sized dynamically - * but this may require 2passes to know - * transform count in advance. - */ - alg_info_ike = malloc_thing (struct alg_info_ike); - zero(alg_info_ike); - alg_info_ike->alg_info_protoid = PROTO_ISAKMP; + struct alg_info_ike *alg_info_ike; + /* + * alg_info storage should be sized dynamically + * but this may require 2passes to know + * transform count in advance. + */ + alg_info_ike = malloc_thing (struct alg_info_ike); + zero(alg_info_ike); + alg_info_ike->alg_info_protoid = PROTO_ISAKMP; - if (alg_info_parse_str((struct alg_info *)alg_info_ike, alg_str, err_p) < 0) - { - free(alg_info_ike); - return NULL; - } - return alg_info_ike; + if (alg_info_parse_str((struct alg_info *)alg_info_ike, alg_str, err_p) < 0) + { + free(alg_info_ike); + return NULL; + } + return alg_info_ike; } #endif /* - * alg_info struct can be shared by - * several connections instances, - * handle free() with ref_cnts + * alg_info struct can be shared by + * several connections instances, + * handle free() with ref_cnts */ void alg_info_addref(struct alg_info *alg_info) { - if (alg_info != NULL) - { - alg_info->ref_cnt++; - DBG(DBG_CRYPT, - DBG_log("alg_info_addref() alg_info->ref_cnt=%d" - , alg_info->ref_cnt) - ) - } + if (alg_info != NULL) + { + alg_info->ref_cnt++; + DBG(DBG_CRYPT, + DBG_log("alg_info_addref() alg_info->ref_cnt=%d" + , alg_info->ref_cnt) + ) + } } void alg_info_delref(struct alg_info **alg_info_p) { - struct alg_info *alg_info = *alg_info_p; + struct alg_info *alg_info = *alg_info_p; - if (alg_info != NULL) - { - passert(alg_info->ref_cnt != 0); - alg_info->ref_cnt--; - DBG(DBG_CRYPT, - DBG_log("alg_info_delref() alg_info->ref_cnt=%d" - , alg_info->ref_cnt) - ) - if (alg_info->ref_cnt == 0) + if (alg_info != NULL) { - DBG(DBG_CRYPT, - DBG_log("alg_info_delref() freeing alg_info") - ) - alg_info_free(alg_info); + passert(alg_info->ref_cnt != 0); + alg_info->ref_cnt--; + DBG(DBG_CRYPT, + DBG_log("alg_info_delref() alg_info->ref_cnt=%d" + , alg_info->ref_cnt) + ) + if (alg_info->ref_cnt == 0) + { + DBG(DBG_CRYPT, + DBG_log("alg_info_delref() freeing alg_info") + ) + alg_info_free(alg_info); + } + *alg_info_p = NULL; } - *alg_info_p = NULL; - } } /* snprint already parsed transform list (alg_info) */ int alg_info_snprint(char *buf, int buflen, struct alg_info *alg_info) { - char *ptr = buf; - int np = 0; - struct esp_info *esp_info; + char *ptr = buf; + int np = 0; + struct esp_info *esp_info; #ifndef NO_PLUTO - struct ike_info *ike_info; + struct ike_info *ike_info; #endif - int cnt; - - switch (alg_info->alg_info_protoid) { - case PROTO_IPSEC_ESP: - { - struct alg_info_esp *alg_info_esp = (struct alg_info_esp *)alg_info; + int cnt; + + switch (alg_info->alg_info_protoid) { + case PROTO_IPSEC_ESP: + { + struct alg_info_esp *alg_info_esp = (struct alg_info_esp *)alg_info; - ALG_INFO_ESP_FOREACH(alg_info_esp, esp_info, cnt) - { - np = snprintf(ptr, buflen, "%d_%03d-%d, " - , esp_info->esp_ealg_id - , (int)esp_info->esp_ealg_keylen - , esp_info->esp_aalg_id); - ptr += np; - buflen -= np; - if (buflen < 0) - goto out; - } - if (alg_info_esp->esp_pfsgroup) - { - np = snprintf(ptr, buflen, "; pfsgroup=%d; " - , alg_info_esp->esp_pfsgroup); - ptr += np; - buflen -= np; - if (buflen < 0) - goto out; - } - break; - } + ALG_INFO_ESP_FOREACH(alg_info_esp, esp_info, cnt) + { + np = snprintf(ptr, buflen, "%d_%03d-%d, " + , esp_info->esp_ealg_id + , (int)esp_info->esp_ealg_keylen + , esp_info->esp_aalg_id); + ptr += np; + buflen -= np; + if (buflen < 0) + goto out; + } + if (alg_info_esp->esp_pfsgroup) + { + np = snprintf(ptr, buflen, "; pfsgroup=%d; " + , alg_info_esp->esp_pfsgroup); + ptr += np; + buflen -= np; + if (buflen < 0) + goto out; + } + break; + } #ifndef NO_PLUTO - case PROTO_ISAKMP: - ALG_INFO_IKE_FOREACH((struct alg_info_ike *)alg_info, ike_info, cnt) - { - np = snprintf(ptr, buflen, "%d_%03d-%d-%d, " - , ike_info->ike_ealg - , (int)ike_info->ike_eklen - , ike_info->ike_halg - , ike_info->ike_modp); - ptr += np; - buflen -= np; - if (buflen < 0) - goto out; - } - break; + case PROTO_ISAKMP: + ALG_INFO_IKE_FOREACH((struct alg_info_ike *)alg_info, ike_info, cnt) + { + np = snprintf(ptr, buflen, "%d_%03d-%d-%d, " + , ike_info->ike_ealg + , (int)ike_info->ike_eklen + , ike_info->ike_halg + , ike_info->ike_modp); + ptr += np; + buflen -= np; + if (buflen < 0) + goto out; + } + break; #endif - default: - np = snprintf(buf, buflen, "INVALID protoid=%d\n" - , alg_info->alg_info_protoid); - ptr += np; - buflen -= np; - goto out; + default: + np = snprintf(buf, buflen, "INVALID protoid=%d\n" + , alg_info->alg_info_protoid); + ptr += np; + buflen -= np; + goto out; } np = snprintf(ptr, buflen, "%s" - , alg_info->alg_info_flags & ALG_INFO_F_STRICT? - "strict":""); + , alg_info->alg_info_flags & ALG_INFO_F_STRICT? + "strict":""); ptr += np; buflen -= np; out: - if (buflen < 0) - { - loglog(RC_LOG_SERIOUS - , "buffer space exhausted in alg_info_snprint_ike(), buflen=%d" - , buflen); - } - - return ptr - buf; + if (buflen < 0) + { + loglog(RC_LOG_SERIOUS + , "buffer space exhausted in alg_info_snprint_ike(), buflen=%d" + , buflen); + } + + return ptr - buf; } #ifndef NO_PLUTO int alg_info_snprint_esp(char *buf, int buflen, struct alg_info_esp *alg_info) { - char *ptr = buf; + char *ptr = buf; - int cnt = alg_info->alg_info_cnt; - struct esp_info *esp_info = alg_info->esp; + int cnt = alg_info->alg_info_cnt; + struct esp_info *esp_info = alg_info->esp; - while (cnt--) - { - if (kernel_alg_esp_enc_ok(esp_info->esp_ealg_id, 0, NULL) - && kernel_alg_esp_auth_ok(esp_info->esp_aalg_id, NULL)) + while (cnt--) { - u_int eklen = (esp_info->esp_ealg_keylen) - ? esp_info->esp_ealg_keylen - : kernel_alg_esp_enc_keylen(esp_info->esp_ealg_id) - * BITS_PER_BYTE; + if (kernel_alg_esp_enc_ok(esp_info->esp_ealg_id, 0, NULL) + && kernel_alg_esp_auth_ok(esp_info->esp_aalg_id, NULL)) + { + u_int eklen = (esp_info->esp_ealg_keylen) + ? esp_info->esp_ealg_keylen + : kernel_alg_esp_enc_keylen(esp_info->esp_ealg_id) + * BITS_PER_BYTE; - u_int aklen = esp_info->esp_aalg_keylen - ? esp_info->esp_aalg_keylen - : kernel_alg_esp_auth_keylen(esp_info->esp_aalg_id) - * BITS_PER_BYTE; + u_int aklen = esp_info->esp_aalg_keylen + ? esp_info->esp_aalg_keylen + : kernel_alg_esp_auth_keylen(esp_info->esp_aalg_id) + * BITS_PER_BYTE; - int ret = snprintf(ptr, buflen, "%d_%03d-%d_%03d, ", - esp_info->esp_ealg_id, eklen, - esp_info->esp_aalg_id, aklen); - ptr += ret; - buflen -= ret; - if (buflen < 0) - break; + int ret = snprintf(ptr, buflen, "%d_%03d-%d_%03d, ", + esp_info->esp_ealg_id, eklen, + esp_info->esp_aalg_id, aklen); + ptr += ret; + buflen -= ret; + if (buflen < 0) + break; + } + esp_info++; } - esp_info++; - } - return ptr - buf; + return ptr - buf; } int alg_info_snprint_ike(char *buf, int buflen, struct alg_info_ike *alg_info) { - char *ptr = buf; + char *ptr = buf; - int cnt = alg_info->alg_info_cnt; - struct ike_info *ike_info = alg_info->ike; + int cnt = alg_info->alg_info_cnt; + struct ike_info *ike_info = alg_info->ike; - while (cnt--) - { - struct encrypt_desc *enc_desc = ike_alg_get_encrypter(ike_info->ike_ealg); - struct hash_desc *hash_desc = ike_alg_get_hasher(ike_info->ike_halg); - - if (enc_desc != NULL && hash_desc != NULL - && lookup_group(ike_info->ike_modp)) + while (cnt--) { + struct encrypt_desc *enc_desc = ike_alg_get_encrypter(ike_info->ike_ealg); + struct hash_desc *hash_desc = ike_alg_get_hasher(ike_info->ike_halg); - u_int eklen = (ike_info->ike_eklen) - ? ike_info->ike_eklen - : enc_desc->keydeflen; + if (enc_desc != NULL && hash_desc != NULL + && lookup_group(ike_info->ike_modp)) + { - u_int aklen = (ike_info->ike_hklen) - ? ike_info->ike_hklen - : hash_desc->hash_digest_size * BITS_PER_BYTE; + u_int eklen = (ike_info->ike_eklen) + ? ike_info->ike_eklen + : enc_desc->keydeflen; - int ret = snprintf(ptr, buflen, "%d_%03d-%d_%03d-%d, ", - ike_info->ike_ealg, eklen, - ike_info->ike_halg, aklen, - ike_info->ike_modp); - ptr += ret; - buflen -= ret; - if (buflen < 0) - break; + u_int aklen = (ike_info->ike_hklen) + ? ike_info->ike_hklen + : hash_desc->hash_digest_size * BITS_PER_BYTE; + + int ret = snprintf(ptr, buflen, "%d_%03d-%d_%03d-%d, ", + ike_info->ike_ealg, eklen, + ike_info->ike_halg, aklen, + ike_info->ike_modp); + ptr += ret; + buflen -= ret; + if (buflen < 0) + break; + } + ike_info++; } - ike_info++; - } - return ptr - buf; + return ptr - buf; } #endif /* NO_PLUTO */ diff --git a/src/pluto/alg_info.h b/src/pluto/alg_info.h index 59894a4e2..0a5a54aeb 100644 --- a/src/pluto/alg_info.h +++ b/src/pluto/alg_info.h @@ -18,49 +18,49 @@ #define ALG_INFO_H struct esp_info { - u_int8_t transid; /* ESP transform */ - u_int16_t auth; /* AUTH */ - size_t enckeylen; /* keylength for ESP transform */ - size_t authkeylen; /* keylength for AUTH */ - u_int8_t encryptalg; /* normally encryptalg=transid */ - u_int8_t authalg; /* normally authalg=auth+1 */ + u_int8_t transid; /* ESP transform */ + u_int16_t auth; /* AUTH */ + size_t enckeylen; /* keylength for ESP transform */ + size_t authkeylen; /* keylength for AUTH */ + u_int8_t encryptalg; /* normally encryptalg=transid */ + u_int8_t authalg; /* normally authalg=auth+1 */ }; struct ike_info { - u_int16_t ike_ealg; /* high 16 bit nums for reserved */ - u_int8_t ike_halg; - size_t ike_eklen; - size_t ike_hklen; - u_int16_t ike_modp; + u_int16_t ike_ealg; /* high 16 bit nums for reserved */ + u_int8_t ike_halg; + size_t ike_eklen; + size_t ike_hklen; + u_int16_t ike_modp; }; #define ALG_INFO_COMMON \ - int alg_info_cnt; \ - int ref_cnt; \ - unsigned alg_info_flags; \ - unsigned alg_info_protoid + int alg_info_cnt; \ + int ref_cnt; \ + unsigned alg_info_flags; \ + unsigned alg_info_protoid struct alg_info { - ALG_INFO_COMMON; + ALG_INFO_COMMON; }; struct alg_info_esp { - ALG_INFO_COMMON; - struct esp_info esp[64]; - int esp_pfsgroup; + ALG_INFO_COMMON; + struct esp_info esp[64]; + int esp_pfsgroup; }; struct alg_info_ike { - ALG_INFO_COMMON; - struct ike_info ike[64]; + ALG_INFO_COMMON; + struct ike_info ike[64]; }; #define esp_ealg_id transid #define esp_aalg_id auth -#define esp_ealg_keylen enckeylen /* bits */ -#define esp_aalg_keylen authkeylen /* bits */ +#define esp_ealg_keylen enckeylen /* bits */ +#define esp_aalg_keylen authkeylen /* bits */ -/* alg_info_flags bits */ -#define ALG_INFO_F_STRICT 0x01 +/* alg_info_flags bits */ +#define ALG_INFO_F_STRICT 0x01 extern int alg_info_esp_aa2sadb(int auth); extern int alg_info_esp_sadb2aa(int sadb_aalg); @@ -68,18 +68,18 @@ extern void alg_info_free(struct alg_info *alg_info); extern void alg_info_addref(struct alg_info *alg_info); extern void alg_info_delref(struct alg_info **alg_info); extern struct alg_info_esp* alg_info_esp_create_from_str(const char *alg_str - , const char **err_p); + , const char **err_p); extern struct alg_info_ike* alg_info_ike_create_from_str(const char *alg_str - , const char **err_p); + , const char **err_p); extern int alg_info_parse(const char *str); extern int alg_info_snprint(char *buf, int buflen - , struct alg_info *alg_info); + , struct alg_info *alg_info); extern int alg_info_snprint_esp(char *buf, int buflen - , struct alg_info_esp *alg_info); + , struct alg_info_esp *alg_info); extern int alg_info_snprint_ike(char *buf, int buflen - , struct alg_info_ike *alg_info); + , struct alg_info_ike *alg_info); #define ALG_INFO_ESP_FOREACH(ai, ai_esp, i) \ - for (i=(ai)->alg_info_cnt,ai_esp=(ai)->esp; i--; ai_esp++) + for (i=(ai)->alg_info_cnt,ai_esp=(ai)->esp; i--; ai_esp++) #define ALG_INFO_IKE_FOREACH(ai, ai_ike, i) \ - for (i=(ai)->alg_info_cnt,ai_ike=(ai)->ike; i--; ai_ike++) + for (i=(ai)->alg_info_cnt,ai_ike=(ai)->ike; i--; ai_ike++) #endif /* ALG_INFO_H */ diff --git a/src/pluto/asn1.c b/src/pluto/asn1.c index 3d4852c8d..fa0b4e74f 100644 --- a/src/pluto/asn1.c +++ b/src/pluto/asn1.c @@ -40,33 +40,33 @@ const chunk_t ASN1_INTEGER_2 = chunk_from_buf(ASN1_INTEGER_2_str); /* some popular algorithmIdentifiers */ static u_char ASN1_md5_id_str[] = { - 0x30, 0x0C, - 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, - 0x05, 0x00 + 0x30, 0x0C, + 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, + 0x05, 0x00 }; static u_char ASN1_sha1_id_str[] = { - 0x30, 0x09, - 0x06, 0x05, 0x2B, 0x0E,0x03, 0x02, 0x1A, - 0x05, 0x00 + 0x30, 0x09, + 0x06, 0x05, 0x2B, 0x0E,0x03, 0x02, 0x1A, + 0x05, 0x00 }; static u_char ASN1_md5WithRSA_id_str[] = { - 0x30, 0x0D, - 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x04, - 0x05, 0x00 + 0x30, 0x0D, + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x04, + 0x05, 0x00 }; static u_char ASN1_sha1WithRSA_id_str[] = { - 0x30, 0x0D, - 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, - 0x05, 0x00 + 0x30, 0x0D, + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, + 0x05, 0x00 }; static u_char ASN1_rsaEncryption_id_str[] = { - 0x30, 0x0D, - 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, - 0x05, 0x00 + 0x30, 0x0D, + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, + 0x05, 0x00 }; const chunk_t ASN1_md5_id = chunk_from_buf(ASN1_md5_id_str); @@ -78,16 +78,16 @@ const chunk_t ASN1_sha1WithRSA_id = chunk_from_buf(ASN1_sha1WithRSA_id_str); /* ASN.1 definition of an algorithmIdentifier */ static const asn1Object_t algorithmIdentifierObjects[] = { - { 0, "algorithmIdentifier", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "algorithm", ASN1_OID, ASN1_BODY }, /* 1 */ - { 1, "parameters", ASN1_EOC, ASN1_OPT | - ASN1_RAW }, /* 2 */ - { 1, "end opt", ASN1_EOC, ASN1_END } /* 3 */ + { 0, "algorithmIdentifier", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ + { 1, "algorithm", ASN1_OID, ASN1_BODY }, /* 1 */ + { 1, "parameters", ASN1_EOC, ASN1_OPT | + ASN1_RAW }, /* 2 */ + { 1, "end opt", ASN1_EOC, ASN1_END } /* 3 */ }; -#define ALGORITHM_ID_ALG 1 -#define ALGORITHM_ID_PARAMETERS 2 -#define ALGORITHM_ID_ROOF 4 +#define ALGORITHM_ID_ALG 1 +#define ALGORITHM_ID_PARAMETERS 2 +#define ALGORITHM_ID_ROOF 4 /* * return the ASN.1 encoded algorithm identifier @@ -95,21 +95,21 @@ static const asn1Object_t algorithmIdentifierObjects[] = { chunk_t asn1_algorithmIdentifier(int oid) { - switch (oid) - { - case OID_RSA_ENCRYPTION: - return ASN1_rsaEncryption_id; - case OID_MD5_WITH_RSA: - return ASN1_md5WithRSA_id; - case OID_SHA1_WITH_RSA: - return ASN1_sha1WithRSA_id; - case OID_MD5: - return ASN1_md5_id; + switch (oid) + { + case OID_RSA_ENCRYPTION: + return ASN1_rsaEncryption_id; + case OID_MD5_WITH_RSA: + return ASN1_md5WithRSA_id; + case OID_SHA1_WITH_RSA: + return ASN1_sha1WithRSA_id; + case OID_MD5: + return ASN1_md5_id; case OID_SHA1: - return ASN1_sha1_id; + return ASN1_sha1_id; default: - return chunk_empty; - } + return chunk_empty; + } } /* If the oid is listed in the oid_names table then the corresponding @@ -118,34 +118,34 @@ asn1_algorithmIdentifier(int oid) int asn1_known_oid(chunk_t object) { - int oid = 0; + int oid = 0; - while (object.len) - { - if (oid_names[oid].octet == *object.ptr) + while (object.len) { - if (--object.len == 0 || oid_names[oid].down == 0) - { - return oid; /* found terminal symbol */ - } - else - { - object.ptr++; oid++; /* advance to next hex octet */ - } + if (oid_names[oid].octet == *object.ptr) + { + if (--object.len == 0 || oid_names[oid].down == 0) + { + return oid; /* found terminal symbol */ + } + else + { + object.ptr++; oid++; /* advance to next hex octet */ + } + } + else + { + if (oid_names[oid].next) + { + oid = oid_names[oid].next; + } + else + { + return OID_UNKNOWN; + } + } } - else - { - if (oid_names[oid].next) - { - oid = oid_names[oid].next; - } - else - { - return OID_UNKNOWN; - } - } - } - return -1; + return -1; } /* @@ -154,32 +154,32 @@ asn1_known_oid(chunk_t object) chunk_t asn1_build_known_oid(int n) { - chunk_t oid; - int i; - - if (n < 0 || n >= OID_MAX) - { - return chunk_empty; - } - - i = oid_names[n].level + 1; - oid.ptr = malloc(2 + i); - oid.len = i; - oid.ptr[0] = ASN1_OID; - oid.ptr[1] = i; - - do - { - if (oid_names[n].level >= i) + chunk_t oid; + int i; + + if (n < 0 || n >= OID_MAX) { - n--; - continue; + return chunk_empty; } - oid.ptr[--i + 2] = oid_names[n--].octet; - } - while (i > 0); - - return oid; + + i = oid_names[n].level + 1; + oid.ptr = malloc(2 + i); + oid.len = i; + oid.ptr[0] = ASN1_OID; + oid.ptr[1] = i; + + do + { + if (oid_names[n].level >= i) + { + n--; + continue; + } + oid.ptr[--i + 2] = oid_names[n--].octet; + } + while (i > 0); + + return oid; } /* @@ -188,48 +188,48 @@ asn1_build_known_oid(int n) u_int asn1_length(chunk_t *blob) { - u_char n; - size_t len; + u_char n; + size_t len; - /* advance from tag field on to length field */ - blob->ptr++; - blob->len--; - - /* read first octet of length field */ - n = *blob->ptr++; - blob->len--; - - if ((n & 0x80) == 0) /* single length octet */ - return n; - - /* composite length, determine number of length octets */ - n &= 0x7f; - - if (n > blob->len) - { - DBG(DBG_PARSING, - DBG_log("number of length octets is larger than ASN.1 object") - ) - return ASN1_INVALID_LENGTH; - } - - if (n > sizeof(len)) - { - DBG(DBG_PARSING, - DBG_log("number of length octets is larger than limit of %d octets" - , (int)sizeof(len)) - ) - return ASN1_INVALID_LENGTH; - } - - len = 0; - - while (n-- > 0) - { - len = 256*len + *blob->ptr++; + /* advance from tag field on to length field */ + blob->ptr++; blob->len--; - } - return len; + + /* read first octet of length field */ + n = *blob->ptr++; + blob->len--; + + if ((n & 0x80) == 0) /* single length octet */ + return n; + + /* composite length, determine number of length octets */ + n &= 0x7f; + + if (n > blob->len) + { + DBG(DBG_PARSING, + DBG_log("number of length octets is larger than ASN.1 object") + ) + return ASN1_INVALID_LENGTH; + } + + if (n > sizeof(len)) + { + DBG(DBG_PARSING, + DBG_log("number of length octets is larger than limit of %d octets" + , (int)sizeof(len)) + ) + return ASN1_INVALID_LENGTH; + } + + len = 0; + + while (n-- > 0) + { + len = 256*len + *blob->ptr++; + blob->len--; + } + return len; } /* @@ -238,32 +238,32 @@ asn1_length(chunk_t *blob) void code_asn1_length(size_t length, chunk_t *code) { - if (length < 128) - { - code->ptr[0] = length; - code->len = 1; - } - else if (length < 256) - { - code->ptr[0] = 0x81; - code->ptr[1] = (u_char) length; - code->len = 2; - } - else if (length < 65536) - { - code->ptr[0] = 0x82; - code->ptr[1] = length >> 8; - code->ptr[2] = length & 0x00ff; - code->len = 3; - } - else - { - code->ptr[0] = 0x83; - code->ptr[1] = length >> 16; - code->ptr[2] = (length >> 8) & 0x00ff; - code->ptr[3] = length & 0x0000ff; - code->len = 4; - } + if (length < 128) + { + code->ptr[0] = length; + code->len = 1; + } + else if (length < 256) + { + code->ptr[0] = 0x81; + code->ptr[1] = (u_char) length; + code->len = 2; + } + else if (length < 65536) + { + code->ptr[0] = 0x82; + code->ptr[1] = length >> 8; + code->ptr[2] = length & 0x00ff; + code->len = 3; + } + else + { + code->ptr[0] = 0x83; + code->ptr[1] = length >> 16; + code->ptr[2] = (length >> 8) & 0x00ff; + code->ptr[3] = length & 0x0000ff; + code->len = 4; + } } /* @@ -272,23 +272,23 @@ code_asn1_length(size_t length, chunk_t *code) u_char* build_asn1_object(chunk_t *object, asn1_t type, size_t datalen) { - u_char length_buf[4]; - chunk_t length = { length_buf, 0 }; - u_char *pos; + u_char length_buf[4]; + chunk_t length = { length_buf, 0 }; + u_char *pos; - /* code the asn.1 length field */ - code_asn1_length(datalen, &length); + /* code the asn.1 length field */ + code_asn1_length(datalen, &length); - /* allocate memory for the asn.1 TLV object */ - object->len = 1 + length.len + datalen; - object->ptr = malloc(object->len); + /* allocate memory for the asn.1 TLV object */ + object->len = 1 + length.len + datalen; + object->ptr = malloc(object->len); - /* set position pointer at the start of the object */ - pos = object->ptr; + /* set position pointer at the start of the object */ + pos = object->ptr; - /* copy the asn.1 tag field and advance the pointer */ + /* copy the asn.1 tag field and advance the pointer */ *pos++ = type; - + /* copy the asn.1 length field and advance the pointer */ chunkcpy(pos, length); @@ -301,12 +301,12 @@ build_asn1_object(chunk_t *object, asn1_t type, size_t datalen) chunk_t asn1_simple_object(asn1_t tag, chunk_t content) { - chunk_t object; + chunk_t object; - u_char *pos = build_asn1_object(&object, tag, content.len); - chunkcpy(pos, content); + u_char *pos = build_asn1_object(&object, tag, content.len); + chunkcpy(pos, content); - return object; + return object; } /* Build an ASN.1 object from a variable number of individual chunks. @@ -315,44 +315,44 @@ asn1_simple_object(asn1_t tag, chunk_t content) chunk_t asn1_wrap(asn1_t type, const char *mode, ...) { - chunk_t construct; - va_list chunks; - u_char *pos; - int i; - int count = strlen(mode); - - /* sum up lengths of individual chunks */ - va_start(chunks, mode); - construct.len = 0; - for (i = 0; i < count; i++) - { - chunk_t ch = va_arg(chunks, chunk_t); - construct.len += ch.len; - } - va_end(chunks); - - /* allocate needed memory for construct */ - pos = build_asn1_object(&construct, type, construct.len); - - /* copy or move the chunks */ - va_start(chunks, mode); - for (i = 0; i < count; i++) - { - chunk_t ch = va_arg(chunks, chunk_t); - - switch (*mode++) + chunk_t construct; + va_list chunks; + u_char *pos; + int i; + int count = strlen(mode); + + /* sum up lengths of individual chunks */ + va_start(chunks, mode); + construct.len = 0; + for (i = 0; i < count; i++) { - case 'm': - mv_chunk(&pos, ch); - break; - case 'c': - default: - chunkcpy(pos, ch); + chunk_t ch = va_arg(chunks, chunk_t); + construct.len += ch.len; } - } - va_end(chunks); + va_end(chunks); - return construct; + /* allocate needed memory for construct */ + pos = build_asn1_object(&construct, type, construct.len); + + /* copy or move the chunks */ + va_start(chunks, mode); + for (i = 0; i < count; i++) + { + chunk_t ch = va_arg(chunks, chunk_t); + + switch (*mode++) + { + case 'm': + mv_chunk(&pos, ch); + break; + case 'c': + default: + chunkcpy(pos, ch); + } + } + va_end(chunks); + + return construct; } /* @@ -361,11 +361,11 @@ asn1_wrap(asn1_t type, const char *mode, ...) chunk_t asn1_integer_from_mpz(const mpz_t value) { - size_t bits = mpz_sizeinbase(value, 2); /* size in bits */ - size_t size = 1 + bits / BITS_PER_BYTE; /* size in bytes */ - chunk_t n = mpz_to_n(value, size); + size_t bits = mpz_sizeinbase(value, 2); /* size in bits */ + size_t size = 1 + bits / BITS_PER_BYTE; /* size in bytes */ + chunk_t n = mpz_to_n(value, size); - return asn1_wrap(ASN1_INTEGER, "m", n); + return asn1_wrap(ASN1_INTEGER, "m", n); } /* @@ -374,19 +374,19 @@ asn1_integer_from_mpz(const mpz_t value) bool is_printablestring(chunk_t str) { - const char printablestring_charset[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 '()+,-./:=?"; - u_int i; + const char printablestring_charset[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 '()+,-./:=?"; + u_int i; - for (i = 0; i < str.len; i++) - { - if (strchr(printablestring_charset, str.ptr[i]) == NULL) - return FALSE; - } - return TRUE; + for (i = 0; i < str.len; i++) + { + if (strchr(printablestring_charset, str.ptr[i]) == NULL) + return FALSE; + } + return TRUE; } -#define TIME_MAX 0x7fffffff +#define TIME_MAX 0x7fffffff /* * Converts ASN.1 UTCTIME or GENERALIZEDTIME into calender time @@ -394,77 +394,77 @@ is_printablestring(chunk_t str) time_t asn1totime(const chunk_t *utctime, asn1_t type) { - struct tm t; - time_t tc, tz_offset; - u_char *eot = NULL; + struct tm t; + time_t tc, tz_offset; + u_char *eot = NULL; - if ((eot = memchr(utctime->ptr, 'Z', utctime->len)) != NULL) - { - tz_offset = 0; /* Zulu time with a zero time zone offset */ - } - else if ((eot = memchr(utctime->ptr, '+', utctime->len)) != NULL) - { - int tz_hour, tz_min; + if ((eot = memchr(utctime->ptr, 'Z', utctime->len)) != NULL) + { + tz_offset = 0; /* Zulu time with a zero time zone offset */ + } + else if ((eot = memchr(utctime->ptr, '+', utctime->len)) != NULL) + { + int tz_hour, tz_min; - sscanf(eot+1, "%2d%2d", &tz_hour, &tz_min); - tz_offset = 3600*tz_hour + 60*tz_min; /* positive time zone offset */ - } - else if ((eot = memchr(utctime->ptr, '-', utctime->len)) != NULL) - { - int tz_hour, tz_min; + sscanf(eot+1, "%2d%2d", &tz_hour, &tz_min); + tz_offset = 3600*tz_hour + 60*tz_min; /* positive time zone offset */ + } + else if ((eot = memchr(utctime->ptr, '-', utctime->len)) != NULL) + { + int tz_hour, tz_min; - sscanf(eot+1, "%2d%2d", &tz_hour, &tz_min); - tz_offset = -3600*tz_hour - 60*tz_min; /* negative time zone offset */ - } - else - { - return 0; /* error in time format */ - } + sscanf(eot+1, "%2d%2d", &tz_hour, &tz_min); + tz_offset = -3600*tz_hour - 60*tz_min; /* negative time zone offset */ + } + else + { + return 0; /* error in time format */ + } - /* parse ASN.1 time string */ - { - const char* format = (type == ASN1_UTCTIME)? "%2d%2d%2d%2d%2d": - "%4d%2d%2d%2d%2d"; + /* parse ASN.1 time string */ + { + const char* format = (type == ASN1_UTCTIME)? "%2d%2d%2d%2d%2d": + "%4d%2d%2d%2d%2d"; - sscanf(utctime->ptr, format, &t.tm_year, &t.tm_mon, &t.tm_mday, - &t.tm_hour, &t.tm_min); - } + sscanf(utctime->ptr, format, &t.tm_year, &t.tm_mon, &t.tm_mday, + &t.tm_hour, &t.tm_min); + } - /* is there a seconds field? */ - if ((eot - utctime->ptr) == ((type == ASN1_UTCTIME)?12:14)) - { - sscanf(eot-2, "%2d", &t.tm_sec); - } - else - { - t.tm_sec = 0; - } + /* is there a seconds field? */ + if ((eot - utctime->ptr) == ((type == ASN1_UTCTIME)?12:14)) + { + sscanf(eot-2, "%2d", &t.tm_sec); + } + else + { + t.tm_sec = 0; + } - /* representation of year */ - if (t.tm_year >= 1900) - { - t.tm_year -= 1900; - } - else if (t.tm_year >= 100) - { - return 0; - } - else if (t.tm_year < 50) - { - t.tm_year += 100; - } + /* representation of year */ + if (t.tm_year >= 1900) + { + t.tm_year -= 1900; + } + else if (t.tm_year >= 100) + { + return 0; + } + else if (t.tm_year < 50) + { + t.tm_year += 100; + } - /* representation of month 0..11*/ - t.tm_mon--; + /* representation of month 0..11*/ + t.tm_mon--; - /* set daylight saving time to off */ - t.tm_isdst = 0; + /* set daylight saving time to off */ + t.tm_isdst = 0; - /* convert to time_t */ - tc = mktime(&t); + /* convert to time_t */ + tc = mktime(&t); - /* if no conversion overflow occurred, compensate timezone */ - return (tc == -1) ? TIME_MAX : (tc - timezone - tz_offset); + /* if no conversion overflow occurred, compensate timezone */ + return (tc == -1) ? TIME_MAX : (tc - timezone - tz_offset); } /* @@ -473,27 +473,27 @@ asn1totime(const chunk_t *utctime, asn1_t type) chunk_t timetoasn1(const time_t *time, asn1_t type) { - int offset; - const char *format; - char buf[TIMETOA_BUF]; - chunk_t formatted_time; - struct tm *t = gmtime(time); + int offset; + const char *format; + char buf[TIMETOA_BUF]; + chunk_t formatted_time; + struct tm *t = gmtime(time); - if (type == ASN1_GENERALIZEDTIME) - { - format = "%04d%02d%02d%02d%02d%02dZ"; - offset = 1900; - } - else /* ASN1_UTCTIME */ - { - format = "%02d%02d%02d%02d%02d%02dZ"; - offset = (t->tm_year < 100)? 0 : -100; - } - sprintf(buf, format, t->tm_year + offset, t->tm_mon + 1, t->tm_mday - , t->tm_hour, t->tm_min, t->tm_sec); - formatted_time.ptr = buf; - formatted_time.len = strlen(buf); - return asn1_simple_object(type, formatted_time); + if (type == ASN1_GENERALIZEDTIME) + { + format = "%04d%02d%02d%02d%02d%02dZ"; + offset = 1900; + } + else /* ASN1_UTCTIME */ + { + format = "%02d%02d%02d%02d%02d%02dZ"; + offset = (t->tm_year < 100)? 0 : -100; + } + sprintf(buf, format, t->tm_year + offset, t->tm_mon + 1, t->tm_mday + , t->tm_hour, t->tm_min, t->tm_sec); + formatted_time.ptr = buf; + formatted_time.len = strlen(buf); + return asn1_simple_object(type, formatted_time); } @@ -502,13 +502,13 @@ timetoasn1(const time_t *time, asn1_t type) */ void asn1_init(asn1_ctx_t *ctx, chunk_t blob, u_int level0, - bool implicit, u_int cond) + bool implicit, u_int cond) { - ctx->blobs[0] = blob; - ctx->level0 = level0; - ctx->implicit = implicit; - ctx->cond = cond; - memset(ctx->loopAddr, '\0', sizeof(ctx->loopAddr)); + ctx->blobs[0] = blob; + ctx->level0 = level0; + ctx->implicit = implicit; + ctx->cond = cond; + memset(ctx->loopAddr, '\0', sizeof(ctx->loopAddr)); } /* @@ -517,42 +517,42 @@ asn1_init(asn1_ctx_t *ctx, chunk_t blob, u_int level0, static void debug_asn1_simple_object(chunk_t object, asn1_t type, u_int cond) { - int oid; + int oid; - switch (type) - { - case ASN1_OID: - oid = asn1_known_oid(object); - if (oid != OID_UNKNOWN) + switch (type) { - DBG(DBG_PARSING, - DBG_log(" '%s'",oid_names[oid].name); - ) - return; + case ASN1_OID: + oid = asn1_known_oid(object); + if (oid != OID_UNKNOWN) + { + DBG(DBG_PARSING, + DBG_log(" '%s'",oid_names[oid].name); + ) + return; + } + break; + case ASN1_UTF8STRING: + case ASN1_IA5STRING: + case ASN1_PRINTABLESTRING: + case ASN1_T61STRING: + case ASN1_VISIBLESTRING: + DBG(DBG_PARSING, + DBG_log(" '%.*s'", (int)object.len, object.ptr); + ) + return; + case ASN1_UTCTIME: + case ASN1_GENERALIZEDTIME: + DBG(DBG_PARSING, + time_t time = asn1totime(&object, type); + DBG_log(" '%T'", &time, TRUE); + ) + return; + default: + break; } - break; - case ASN1_UTF8STRING: - case ASN1_IA5STRING: - case ASN1_PRINTABLESTRING: - case ASN1_T61STRING: - case ASN1_VISIBLESTRING: - DBG(DBG_PARSING, - DBG_log(" '%.*s'", (int)object.len, object.ptr); + DBG(cond, + DBG_dump_chunk("", object); ) - return; - case ASN1_UTCTIME: - case ASN1_GENERALIZEDTIME: - DBG(DBG_PARSING, - time_t time = asn1totime(&object, type); - DBG_log(" '%T'", &time, TRUE); - ) - return; - default: - break; - } - DBG(cond, - DBG_dump_chunk("", object); - ) } /* @@ -560,149 +560,149 @@ debug_asn1_simple_object(chunk_t object, asn1_t type, u_int cond) */ bool extract_object(asn1Object_t const *objects, - u_int *objectID, chunk_t *object, u_int *level, asn1_ctx_t *ctx) + u_int *objectID, chunk_t *object, u_int *level, asn1_ctx_t *ctx) { - asn1Object_t obj = objects[*objectID]; - chunk_t *blob; - chunk_t *blob1; - u_char *start_ptr; + asn1Object_t obj = objects[*objectID]; + chunk_t *blob; + chunk_t *blob1; + u_char *start_ptr; - *object = chunk_empty; + *object = chunk_empty; - if (obj.flags & ASN1_END) /* end of loop or option found */ - { - if (ctx->loopAddr[obj.level] && ctx->blobs[obj.level+1].len > 0) + if (obj.flags & ASN1_END) /* end of loop or option found */ { - *objectID = ctx->loopAddr[obj.level]; /* another iteration */ - obj = objects[*objectID]; + if (ctx->loopAddr[obj.level] && ctx->blobs[obj.level+1].len > 0) + { + *objectID = ctx->loopAddr[obj.level]; /* another iteration */ + obj = objects[*objectID]; + } + else + { + ctx->loopAddr[obj.level] = 0; /* exit loop or option*/ + return TRUE; + } } - else - { - ctx->loopAddr[obj.level] = 0; /* exit loop or option*/ - return TRUE; - } - } - *level = ctx->level0 + obj.level; - blob = ctx->blobs + obj.level; - blob1 = blob + 1; - start_ptr = blob->ptr; + *level = ctx->level0 + obj.level; + blob = ctx->blobs + obj.level; + blob1 = blob + 1; + start_ptr = blob->ptr; /* handle ASN.1 defaults values */ - if ((obj.flags & ASN1_DEF) - && (blob->len == 0 || *start_ptr != obj.type) ) - { - /* field is missing */ - DBG(DBG_PARSING, - DBG_log("L%d - %s:", *level, obj.name); - ) - if (obj.type & ASN1_CONSTRUCTED) + if ((obj.flags & ASN1_DEF) + && (blob->len == 0 || *start_ptr != obj.type) ) { - (*objectID)++ ; /* skip context-specific tag */ + /* field is missing */ + DBG(DBG_PARSING, + DBG_log("L%d - %s:", *level, obj.name); + ) + if (obj.type & ASN1_CONSTRUCTED) + { + (*objectID)++ ; /* skip context-specific tag */ + } + return TRUE; + } + + /* handle ASN.1 options */ + + if ((obj.flags & ASN1_OPT) + && (blob->len == 0 || *start_ptr != obj.type)) + { + /* advance to end of missing option field */ + do + (*objectID)++; + while (!((objects[*objectID].flags & ASN1_END) + && (objects[*objectID].level == obj.level))); + return TRUE; + } + + /* an ASN.1 object must possess at least a tag and length field */ + + if (blob->len < 2) + { + DBG(DBG_PARSING, + DBG_log("L%d - %s: ASN.1 object smaller than 2 octets", + *level, obj.name); + ) + return FALSE; + } + + blob1->len = asn1_length(blob); + + if (blob1->len == ASN1_INVALID_LENGTH || blob->len < blob1->len) + { + DBG(DBG_PARSING, + DBG_log("L%d - %s: length of ASN.1 object invalid or too large", + *level, obj.name); + ) + return FALSE; + } + + blob1->ptr = blob->ptr; + blob->ptr += blob1->len; + blob->len -= blob1->len; + + /* return raw ASN.1 object without prior type checking */ + + if (obj.flags & ASN1_RAW) + { + DBG(DBG_PARSING, + DBG_log("L%d - %s:", *level, obj.name); + ) + object->ptr = start_ptr; + object->len = (size_t)(blob->ptr - start_ptr); + return TRUE; + } + + if (*start_ptr != obj.type && !(ctx->implicit && *objectID == 0)) + { + DBG(DBG_PARSING, + DBG_log("L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x", + *level, obj.name, obj.type, *start_ptr); + DBG_dump("", start_ptr, (u_int)(blob->ptr - start_ptr)); + ) + return FALSE; + } + + DBG(DBG_PARSING, + DBG_log("L%d - %s:", ctx->level0+obj.level, obj.name); + ) + + /* In case of "SEQUENCE OF" or "SET OF" start a loop */ + + if (obj.flags & ASN1_LOOP) + { + if (blob1->len > 0) + { + /* at least one item, start the loop */ + ctx->loopAddr[obj.level] = *objectID + 1; + } + else + { + /* no items, advance directly to end of loop */ + do + (*objectID)++; + while (!((objects[*objectID].flags & ASN1_END) + && (objects[*objectID].level == obj.level))); + return TRUE; + } + } + + if (obj.flags & ASN1_OBJ) + { + object->ptr = start_ptr; + object->len = (size_t)(blob->ptr - start_ptr); + DBG(ctx->cond, + DBG_dump_chunk("", *object); + ) + } + else if (obj.flags & ASN1_BODY) + { + *object = *blob1; + debug_asn1_simple_object(*object, obj.type, ctx->cond); } return TRUE; - } - - /* handle ASN.1 options */ - - if ((obj.flags & ASN1_OPT) - && (blob->len == 0 || *start_ptr != obj.type)) - { - /* advance to end of missing option field */ - do - (*objectID)++; - while (!((objects[*objectID].flags & ASN1_END) - && (objects[*objectID].level == obj.level))); - return TRUE; - } - - /* an ASN.1 object must possess at least a tag and length field */ - - if (blob->len < 2) - { - DBG(DBG_PARSING, - DBG_log("L%d - %s: ASN.1 object smaller than 2 octets", - *level, obj.name); - ) - return FALSE; - } - - blob1->len = asn1_length(blob); - - if (blob1->len == ASN1_INVALID_LENGTH || blob->len < blob1->len) - { - DBG(DBG_PARSING, - DBG_log("L%d - %s: length of ASN.1 object invalid or too large", - *level, obj.name); - ) - return FALSE; - } - - blob1->ptr = blob->ptr; - blob->ptr += blob1->len; - blob->len -= blob1->len; - - /* return raw ASN.1 object without prior type checking */ - - if (obj.flags & ASN1_RAW) - { - DBG(DBG_PARSING, - DBG_log("L%d - %s:", *level, obj.name); - ) - object->ptr = start_ptr; - object->len = (size_t)(blob->ptr - start_ptr); - return TRUE; - } - - if (*start_ptr != obj.type && !(ctx->implicit && *objectID == 0)) - { - DBG(DBG_PARSING, - DBG_log("L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x", - *level, obj.name, obj.type, *start_ptr); - DBG_dump("", start_ptr, (u_int)(blob->ptr - start_ptr)); - ) - return FALSE; - } - - DBG(DBG_PARSING, - DBG_log("L%d - %s:", ctx->level0+obj.level, obj.name); - ) - - /* In case of "SEQUENCE OF" or "SET OF" start a loop */ - - if (obj.flags & ASN1_LOOP) - { - if (blob1->len > 0) - { - /* at least one item, start the loop */ - ctx->loopAddr[obj.level] = *objectID + 1; - } - else - { - /* no items, advance directly to end of loop */ - do - (*objectID)++; - while (!((objects[*objectID].flags & ASN1_END) - && (objects[*objectID].level == obj.level))); - return TRUE; - } - } - - if (obj.flags & ASN1_OBJ) - { - object->ptr = start_ptr; - object->len = (size_t)(blob->ptr - start_ptr); - DBG(ctx->cond, - DBG_dump_chunk("", *object); - ) - } - else if (obj.flags & ASN1_BODY) - { - *object = *blob1; - debug_asn1_simple_object(*object, obj.type, ctx->cond); - } - return TRUE; } /* @@ -712,43 +712,43 @@ bool parse_asn1_simple_object(chunk_t *object, asn1_t type, u_int level , const char* name) { - size_t len; + size_t len; + + /* an ASN.1 object must possess at least a tag and length field */ + if (object->len < 2) + { + DBG(DBG_PARSING, + DBG_log("L%d - %s: ASN.1 object smaller than 2 octets", + level, name); + ) + return FALSE; + } + + if (*object->ptr != type) + { + DBG(DBG_PARSING, + DBG_log("L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x", + level, name, type, *object->ptr); + ) + return FALSE; + } + + len = asn1_length(object); + + if (len == ASN1_INVALID_LENGTH || object->len < len) + { + DBG(DBG_PARSING, + DBG_log("L%d - %s: length of ASN.1 object invalid or too large", + level, name); + ) + return FALSE; + } - /* an ASN.1 object must possess at least a tag and length field */ - if (object->len < 2) - { DBG(DBG_PARSING, - DBG_log("L%d - %s: ASN.1 object smaller than 2 octets", - level, name); + DBG_log("L%d - %s:", level, name); ) - return FALSE; - } - - if (*object->ptr != type) - { - DBG(DBG_PARSING, - DBG_log("L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x", - level, name, type, *object->ptr); - ) - return FALSE; - } - - len = asn1_length(object); - - if (len == ASN1_INVALID_LENGTH || object->len < len) - { - DBG(DBG_PARSING, - DBG_log("L%d - %s: length of ASN.1 object invalid or too large", - level, name); - ) - return FALSE; - } - - DBG(DBG_PARSING, - DBG_log("L%d - %s:", level, name); - ) - debug_asn1_simple_object(*object, type, DBG_RAW); - return TRUE; + debug_asn1_simple_object(*object, type, DBG_RAW); + return TRUE; } /* @@ -757,34 +757,34 @@ parse_asn1_simple_object(chunk_t *object, asn1_t type, u_int level int parse_algorithmIdentifier(chunk_t blob, int level0, chunk_t *parameters) { - asn1_ctx_t ctx; - chunk_t object; - u_int level; - int alg = OID_UNKNOWN; - int objectID = 0; + asn1_ctx_t ctx; + chunk_t object; + u_int level; + int alg = OID_UNKNOWN; + int objectID = 0; - asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); + asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); - while (objectID < ALGORITHM_ID_ROOF) - { - if (!extract_object(algorithmIdentifierObjects, &objectID, &object, &level, &ctx)) - return alg; - - switch (objectID) + while (objectID < ALGORITHM_ID_ROOF) { - case ALGORITHM_ID_ALG: - alg = asn1_known_oid(object); - break; - case ALGORITHM_ID_PARAMETERS: - if (parameters != NULL) - *parameters = object; - break; - default: - break; + if (!extract_object(algorithmIdentifierObjects, &objectID, &object, &level, &ctx)) + return alg; + + switch (objectID) + { + case ALGORITHM_ID_ALG: + alg = asn1_known_oid(object); + break; + case ALGORITHM_ID_PARAMETERS: + if (parameters != NULL) + *parameters = object; + break; + default: + break; + } + objectID++; } - objectID++; - } - return alg; + return alg; } /* @@ -793,33 +793,33 @@ parse_algorithmIdentifier(chunk_t blob, int level0, chunk_t *parameters) bool is_asn1(chunk_t blob) { - u_int len; - u_char tag = *blob.ptr; + u_int len; + u_char tag = *blob.ptr; + + if (tag != ASN1_SEQUENCE && tag != ASN1_SET) + { + DBG(DBG_PARSING, + DBG_log(" file content is not binary ASN.1"); + ) + return FALSE; + } + + len = asn1_length(&blob); + + /* exact match */ + if (len == blob.len) + { + return TRUE; + } + + /* some websites append a surplus newline character to the blob */ + if (len + 1 == blob.len && *(blob.ptr + len) == '\n') + { + return TRUE; + } - if (tag != ASN1_SEQUENCE && tag != ASN1_SET) - { DBG(DBG_PARSING, - DBG_log(" file content is not binary ASN.1"); + DBG_log(" file size does not match ASN.1 coded length"); ) return FALSE; - } - - len = asn1_length(&blob); - - /* exact match */ - if (len == blob.len) - { - return TRUE; - } - - /* some websites append a surplus newline character to the blob */ - if (len + 1 == blob.len && *(blob.ptr + len) == '\n') - { - return TRUE; - } - - DBG(DBG_PARSING, - DBG_log(" file size does not match ASN.1 coded length"); - ) - return FALSE; } diff --git a/src/pluto/asn1.h b/src/pluto/asn1.h index abbdf0f19..cbc923bac 100644 --- a/src/pluto/asn1.h +++ b/src/pluto/asn1.h @@ -25,82 +25,82 @@ /* Defines some primitive ASN1 types */ typedef enum { - ASN1_EOC = 0x00, - ASN1_BOOLEAN = 0x01, - ASN1_INTEGER = 0x02, - ASN1_BIT_STRING = 0x03, - ASN1_OCTET_STRING = 0x04, - ASN1_NULL = 0x05, - ASN1_OID = 0x06, - ASN1_ENUMERATED = 0x0A, - ASN1_UTF8STRING = 0x0C, - ASN1_NUMERICSTRING = 0x12, - ASN1_PRINTABLESTRING = 0x13, - ASN1_T61STRING = 0x14, - ASN1_VIDEOTEXSTRING = 0x15, - ASN1_IA5STRING = 0x16, - ASN1_UTCTIME = 0x17, - ASN1_GENERALIZEDTIME = 0x18, - ASN1_GRAPHICSTRING = 0x19, - ASN1_VISIBLESTRING = 0x1A, - ASN1_GENERALSTRING = 0x1B, - ASN1_UNIVERSALSTRING = 0x1C, - ASN1_BMPSTRING = 0x1E, + ASN1_EOC = 0x00, + ASN1_BOOLEAN = 0x01, + ASN1_INTEGER = 0x02, + ASN1_BIT_STRING = 0x03, + ASN1_OCTET_STRING = 0x04, + ASN1_NULL = 0x05, + ASN1_OID = 0x06, + ASN1_ENUMERATED = 0x0A, + ASN1_UTF8STRING = 0x0C, + ASN1_NUMERICSTRING = 0x12, + ASN1_PRINTABLESTRING = 0x13, + ASN1_T61STRING = 0x14, + ASN1_VIDEOTEXSTRING = 0x15, + ASN1_IA5STRING = 0x16, + ASN1_UTCTIME = 0x17, + ASN1_GENERALIZEDTIME = 0x18, + ASN1_GRAPHICSTRING = 0x19, + ASN1_VISIBLESTRING = 0x1A, + ASN1_GENERALSTRING = 0x1B, + ASN1_UNIVERSALSTRING = 0x1C, + ASN1_BMPSTRING = 0x1E, - ASN1_CONSTRUCTED = 0x20, + ASN1_CONSTRUCTED = 0x20, - ASN1_SEQUENCE = 0x30, + ASN1_SEQUENCE = 0x30, - ASN1_SET = 0x31, + ASN1_SET = 0x31, - ASN1_CONTEXT_S_0 = 0x80, - ASN1_CONTEXT_S_1 = 0x81, - ASN1_CONTEXT_S_2 = 0x82, - ASN1_CONTEXT_S_3 = 0x83, - ASN1_CONTEXT_S_4 = 0x84, - ASN1_CONTEXT_S_5 = 0x85, - ASN1_CONTEXT_S_6 = 0x86, - ASN1_CONTEXT_S_7 = 0x87, - ASN1_CONTEXT_S_8 = 0x88, + ASN1_CONTEXT_S_0 = 0x80, + ASN1_CONTEXT_S_1 = 0x81, + ASN1_CONTEXT_S_2 = 0x82, + ASN1_CONTEXT_S_3 = 0x83, + ASN1_CONTEXT_S_4 = 0x84, + ASN1_CONTEXT_S_5 = 0x85, + ASN1_CONTEXT_S_6 = 0x86, + ASN1_CONTEXT_S_7 = 0x87, + ASN1_CONTEXT_S_8 = 0x88, - ASN1_CONTEXT_C_0 = 0xA0, - ASN1_CONTEXT_C_1 = 0xA1, - ASN1_CONTEXT_C_2 = 0xA2, - ASN1_CONTEXT_C_3 = 0xA3, - ASN1_CONTEXT_C_4 = 0xA4, - ASN1_CONTEXT_C_5 = 0xA5 + ASN1_CONTEXT_C_0 = 0xA0, + ASN1_CONTEXT_C_1 = 0xA1, + ASN1_CONTEXT_C_2 = 0xA2, + ASN1_CONTEXT_C_3 = 0xA3, + ASN1_CONTEXT_C_4 = 0xA4, + ASN1_CONTEXT_C_5 = 0xA5 } asn1_t; /* Definition of ASN1 flags */ -#define ASN1_NONE 0x00 -#define ASN1_DEF 0x01 -#define ASN1_OPT 0x02 -#define ASN1_LOOP 0x04 -#define ASN1_END 0x08 -#define ASN1_OBJ 0x10 -#define ASN1_BODY 0x20 -#define ASN1_RAW 0x40 +#define ASN1_NONE 0x00 +#define ASN1_DEF 0x01 +#define ASN1_OPT 0x02 +#define ASN1_LOOP 0x04 +#define ASN1_END 0x08 +#define ASN1_OBJ 0x10 +#define ASN1_BODY 0x20 +#define ASN1_RAW 0x40 -#define ASN1_INVALID_LENGTH 0xffffffff +#define ASN1_INVALID_LENGTH 0xffffffff /* definition of an ASN.1 object */ typedef struct { - u_int level; - const u_char *name; - asn1_t type; - u_char flags; + u_int level; + const u_char *name; + asn1_t type; + u_char flags; } asn1Object_t; -#define ASN1_MAX_LEVEL 10 +#define ASN1_MAX_LEVEL 10 typedef struct { - bool implicit; - u_int cond; - u_int level0; - u_int loopAddr[ASN1_MAX_LEVEL+1]; - chunk_t blobs[ASN1_MAX_LEVEL+2]; + bool implicit; + u_int cond; + u_int level0; + u_int loopAddr[ASN1_MAX_LEVEL+1]; + chunk_t blobs[ASN1_MAX_LEVEL+2]; } asn1_ctx_t; /* some common prefabricated ASN.1 constants */ @@ -129,13 +129,13 @@ extern bool is_printablestring(chunk_t str); extern time_t asn1totime(const chunk_t *utctime, asn1_t type); extern chunk_t timetoasn1(const time_t *time, asn1_t type); extern void asn1_init(asn1_ctx_t *ctx, chunk_t blob - , u_int level0, bool implicit, u_int cond); + , u_int level0, bool implicit, u_int cond); extern bool extract_object(asn1Object_t const *objects - , u_int *objectID, chunk_t *object, u_int *level, asn1_ctx_t *ctx); + , u_int *objectID, chunk_t *object, u_int *level, asn1_ctx_t *ctx); extern bool parse_asn1_simple_object(chunk_t *object, asn1_t type, u_int level - , const char* name); + , const char* name); extern int parse_algorithmIdentifier(chunk_t blob, int level0 - , chunk_t *parameters); + , chunk_t *parameters); extern bool is_asn1(chunk_t blob); #endif /* _ASN1_H */ diff --git a/src/pluto/ca.c b/src/pluto/ca.c index 72398a433..679d5fe1f 100644 --- a/src/pluto/ca.c +++ b/src/pluto/ca.c @@ -40,17 +40,17 @@ static x509cert_t *x509authcerts = NULL; const ca_info_t empty_ca_info = { - NULL , /* next */ - NULL , /* name */ - UNDEFINED_TIME, - { NULL, 0 } , /* authName */ - { NULL, 0 } , /* authKeyID */ - { NULL, 0 } , /* authKey SerialNumber */ - NULL , /* ldaphost */ - NULL , /* ldapbase */ - NULL , /* ocspori */ - NULL , /* crluri */ - FALSE /* strictcrlpolicy */ + NULL , /* next */ + NULL , /* name */ + UNDEFINED_TIME, + { NULL, 0 } , /* authName */ + { NULL, 0 } , /* authKeyID */ + { NULL, 0 } , /* authKey SerialNumber */ + NULL , /* ldaphost */ + NULL , /* ldapbase */ + NULL , /* ocspori */ + NULL , /* crluri */ + FALSE /* strictcrlpolicy */ }; /* chained list of X.509 certification authority information records */ @@ -63,52 +63,52 @@ static ca_info_t *ca_infos = NULL; bool trusted_ca(chunk_t a, chunk_t b, int *pathlen) { - bool match = FALSE; + bool match = FALSE; - /* no CA b specified -> any CA a is accepted */ - if (b.ptr == NULL) - { - *pathlen = (a.ptr == NULL)? 0 : MAX_CA_PATH_LEN; - return TRUE; - } + /* no CA b specified -> any CA a is accepted */ + if (b.ptr == NULL) + { + *pathlen = (a.ptr == NULL)? 0 : MAX_CA_PATH_LEN; + return TRUE; + } - /* no CA a specified -> trust cannot be established */ - if (a.ptr == NULL) - { - *pathlen = MAX_CA_PATH_LEN; - return FALSE; - } + /* no CA a specified -> trust cannot be established */ + if (a.ptr == NULL) + { + *pathlen = MAX_CA_PATH_LEN; + return FALSE; + } - *pathlen = 0; + *pathlen = 0; - /* CA a equals CA b -> we have a match */ - if (same_dn(a, b)) - return TRUE; + /* CA a equals CA b -> we have a match */ + if (same_dn(a, b)) + return TRUE; - /* CA a might be a subordinate CA of b */ - lock_authcert_list("trusted_ca"); + /* CA a might be a subordinate CA of b */ + lock_authcert_list("trusted_ca"); - while ((*pathlen)++ < MAX_CA_PATH_LEN) - { - x509cert_t *cacert = get_authcert(a, chunk_empty, chunk_empty, AUTH_CA); + while ((*pathlen)++ < MAX_CA_PATH_LEN) + { + x509cert_t *cacert = get_authcert(a, chunk_empty, chunk_empty, AUTH_CA); - /* cacert not found or self-signed root cacert-> exit */ - if (cacert == NULL || same_dn(cacert->issuer, a)) - break; + /* cacert not found or self-signed root cacert-> exit */ + if (cacert == NULL || same_dn(cacert->issuer, a)) + break; - /* does the issuer of CA a match CA b? */ - match = same_dn(cacert->issuer, b); + /* does the issuer of CA a match CA b? */ + match = same_dn(cacert->issuer, b); - /* we have a match and exit the loop */ - if (match) - break; + /* we have a match and exit the loop */ + if (match) + break; - /* go one level up in the CA chain */ - a = cacert->issuer; - } - - unlock_authcert_list("trusted_ca"); - return match; + /* go one level up in the CA chain */ + a = cacert->issuer; + } + + unlock_authcert_list("trusted_ca"); + return match; } /* @@ -117,36 +117,36 @@ trusted_ca(chunk_t a, chunk_t b, int *pathlen) bool match_requested_ca(generalName_t *requested_ca, chunk_t our_ca, int *our_pathlen) { - /* if no ca is requested than any ca will match */ - if (requested_ca == NULL) - { - *our_pathlen = 0; - return TRUE; - } - - *our_pathlen = MAX_CA_PATH_LEN + 1; - - while (requested_ca != NULL) - { - int pathlen; - - if (trusted_ca(our_ca, requested_ca->name, &pathlen) - && pathlen < *our_pathlen) + /* if no ca is requested than any ca will match */ + if (requested_ca == NULL) { - *our_pathlen = pathlen; + *our_pathlen = 0; + return TRUE; } - requested_ca = requested_ca->next; - } - if (*our_pathlen > MAX_CA_PATH_LEN) - { - *our_pathlen = MAX_CA_PATH_LEN; - return FALSE; - } - else - { - return TRUE; - } + *our_pathlen = MAX_CA_PATH_LEN + 1; + + while (requested_ca != NULL) + { + int pathlen; + + if (trusted_ca(our_ca, requested_ca->name, &pathlen) + && pathlen < *our_pathlen) + { + *our_pathlen = pathlen; + } + requested_ca = requested_ca->next; + } + + if (*our_pathlen > MAX_CA_PATH_LEN) + { + *our_pathlen = MAX_CA_PATH_LEN; + return FALSE; + } + else + { + return TRUE; + } } /* @@ -155,9 +155,9 @@ match_requested_ca(generalName_t *requested_ca, chunk_t our_ca, int *our_pathlen static void free_first_authcert(void) { - x509cert_t *first = x509authcerts; - x509authcerts = first->next; - free_x509cert(first); + x509cert_t *first = x509authcerts; + x509authcerts = first->next; + free_x509cert(first); } /* @@ -166,12 +166,12 @@ free_first_authcert(void) void free_authcerts(void) { - lock_authcert_list("free_authcerts"); + lock_authcert_list("free_authcerts"); - while (x509authcerts != NULL) - free_first_authcert(); + while (x509authcerts != NULL) + free_first_authcert(); - unlock_authcert_list("free_authcerts"); + unlock_authcert_list("free_authcerts"); } /* @@ -180,29 +180,29 @@ free_authcerts(void) x509cert_t* get_authcert(chunk_t subject, chunk_t serial, chunk_t keyid, u_char auth_flags) { - x509cert_t *cert = x509authcerts; - x509cert_t *prev_cert = NULL; + x509cert_t *cert = x509authcerts; + x509cert_t *prev_cert = NULL; - while (cert != NULL) - { - if (cert->authority_flags & auth_flags - && ((keyid.ptr != NULL) ? same_keyid(keyid, cert->subjectKeyID) - : (same_dn(subject, cert->subject) - && same_serial(serial, cert->serialNumber)))) + while (cert != NULL) { - if (cert != x509authcerts) - { - /* bring the certificate up front */ - prev_cert->next = cert->next; - cert->next = x509authcerts; - x509authcerts = cert; - } - return cert; + if (cert->authority_flags & auth_flags + && ((keyid.ptr != NULL) ? same_keyid(keyid, cert->subjectKeyID) + : (same_dn(subject, cert->subject) + && same_serial(serial, cert->serialNumber)))) + { + if (cert != x509authcerts) + { + /* bring the certificate up front */ + prev_cert->next = cert->next; + cert->next = x509authcerts; + x509authcerts = cert; + } + return cert; + } + prev_cert = cert; + cert = cert->next; } - prev_cert = cert; - cert = cert->next; - } - return NULL; + return NULL; } /* @@ -211,49 +211,49 @@ get_authcert(chunk_t subject, chunk_t serial, chunk_t keyid, u_char auth_flags) x509cert_t* add_authcert(x509cert_t *cert, u_char auth_flags) { - x509cert_t *old_cert; + x509cert_t *old_cert; - /* set authority flags */ - cert->authority_flags |= auth_flags; + /* set authority flags */ + cert->authority_flags |= auth_flags; - lock_authcert_list("add_authcert"); + lock_authcert_list("add_authcert"); - old_cert = get_authcert(cert->subject, cert->serialNumber - , cert->subjectKeyID, auth_flags); + old_cert = get_authcert(cert->subject, cert->serialNumber + , cert->subjectKeyID, auth_flags); - if (old_cert != NULL) - { - if (same_x509cert(cert, old_cert)) + if (old_cert != NULL) { - /* cert is already present, just add additional authority flags */ - old_cert->authority_flags |= cert->authority_flags; - DBG(DBG_CONTROL | DBG_PARSING , - DBG_log(" authcert is already present and identical") - ) - unlock_authcert_list("add_authcert"); + if (same_x509cert(cert, old_cert)) + { + /* cert is already present, just add additional authority flags */ + old_cert->authority_flags |= cert->authority_flags; + DBG(DBG_CONTROL | DBG_PARSING , + DBG_log(" authcert is already present and identical") + ) + unlock_authcert_list("add_authcert"); - free_x509cert(cert); - return old_cert; + free_x509cert(cert); + return old_cert; + } + else + { + /* cert is already present but will be replaced by new cert */ + free_first_authcert(); + DBG(DBG_CONTROL | DBG_PARSING , + DBG_log(" existing authcert deleted") + ) + } } - else - { - /* cert is already present but will be replaced by new cert */ - free_first_authcert(); - DBG(DBG_CONTROL | DBG_PARSING , - DBG_log(" existing authcert deleted") - ) - } - } - /* add new authcert to chained list */ - cert->next = x509authcerts; - x509authcerts = cert; - share_x509cert(cert); /* set count to one */ - DBG(DBG_CONTROL | DBG_PARSING, - DBG_log(" authcert inserted") - ) - unlock_authcert_list("add_authcert"); - return cert; + /* add new authcert to chained list */ + cert->next = x509authcerts; + x509authcerts = cert; + share_x509cert(cert); /* set count to one */ + DBG(DBG_CONTROL | DBG_PARSING, + DBG_log(" authcert inserted") + ) + unlock_authcert_list("add_authcert"); + return cert; } /* @@ -262,41 +262,41 @@ add_authcert(x509cert_t *cert, u_char auth_flags) void load_authcerts(const char *type, const char *path, u_char auth_flags) { - struct dirent **filelist; - u_char buf[BUF_LEN]; - u_char *save_dir; - int n; + struct dirent **filelist; + u_char buf[BUF_LEN]; + u_char *save_dir; + int n; - /* change directory to specified path */ - save_dir = getcwd(buf, BUF_LEN); + /* change directory to specified path */ + save_dir = getcwd(buf, BUF_LEN); - if (chdir(path)) - { - plog("Could not change to directory '%s'", path); - } - else - { - plog("Changing to directory '%s'", path); - n = scandir(path, &filelist, file_select, alphasort); - - if (n < 0) - plog(" scandir() error"); + if (chdir(path)) + { + plog("Could not change to directory '%s'", path); + } else { - while (n--) - { - cert_t cert; + plog("Changing to directory '%s'", path); + n = scandir(path, &filelist, file_select, alphasort); - if (load_cert(filelist[n]->d_name, type, &cert)) - add_authcert(cert.u.x509, auth_flags); + if (n < 0) + plog(" scandir() error"); + else + { + while (n--) + { + cert_t cert; - free(filelist[n]); - } - free(filelist); + if (load_cert(filelist[n]->d_name, type, &cert)) + add_authcert(cert.u.x509, auth_flags); + + free(filelist[n]); + } + free(filelist); + } } - } - /* restore directory path */ - ignore_result(chdir(save_dir)); + /* restore directory path */ + ignore_result(chdir(save_dir)); } /* @@ -305,9 +305,9 @@ load_authcerts(const char *type, const char *path, u_char auth_flags) void list_authcerts(const char *caption, u_char auth_flags, bool utc) { - lock_authcert_list("list_authcerts"); - list_x509cert_chain(caption, x509authcerts, auth_flags, utc); - unlock_authcert_list("list_authcerts"); + lock_authcert_list("list_authcerts"); + list_x509cert_chain(caption, x509authcerts, auth_flags, utc); + unlock_authcert_list("list_authcerts"); } /* @@ -315,19 +315,19 @@ list_authcerts(const char *caption, u_char auth_flags, bool utc) */ static const x509cert_t* get_alt_cacert(chunk_t subject, chunk_t serial, chunk_t keyid - , const x509cert_t *cert) + , const x509cert_t *cert) { - while (cert != NULL) - { - if ((keyid.ptr != NULL) ? same_keyid(keyid, cert->subjectKeyID) - : (same_dn(subject, cert->subject) - && same_serial(serial, cert->serialNumber))) + while (cert != NULL) { - return cert; + if ((keyid.ptr != NULL) ? same_keyid(keyid, cert->subjectKeyID) + : (same_dn(subject, cert->subject) + && same_serial(serial, cert->serialNumber))) + { + return cert; + } + cert = cert->next; } - cert = cert->next; - } - return NULL; + return NULL; } /* establish trust into a candidate authcert by going up the trust chain. @@ -336,85 +336,85 @@ get_alt_cacert(chunk_t subject, chunk_t serial, chunk_t keyid bool trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chain) { - int pathlen; + int pathlen; - lock_authcert_list("trust_authcert_candidate"); + lock_authcert_list("trust_authcert_candidate"); - for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++) - { - const x509cert_t *authcert = NULL; - u_char buf[BUF_LEN]; - - DBG(DBG_CONTROL, - dntoa(buf, BUF_LEN, cert->subject); - DBG_log("subject: '%s'",buf); - dntoa(buf, BUF_LEN, cert->issuer); - DBG_log("issuer: '%s'",buf); - if (cert->authKeyID.ptr != NULL) - { - datatot(cert->authKeyID.ptr, cert->authKeyID.len, ':' - , buf, BUF_LEN); - DBG_log("authkey: %s", buf); - } - ) - - /* search in alternative chain first */ - authcert = get_alt_cacert(cert->issuer, cert->authKeySerialNumber - , cert->authKeyID, alt_chain); - - if (authcert != NULL) + for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++) { - DBG(DBG_CONTROL, - DBG_log("issuer cacert found in alternative chain") - ) - } - else - { - /* search in trusted chain */ - authcert = get_authcert(cert->issuer, cert->authKeySerialNumber - , cert->authKeyID, AUTH_CA); + const x509cert_t *authcert = NULL; + u_char buf[BUF_LEN]; - if (authcert != NULL) - { DBG(DBG_CONTROL, - DBG_log("issuer cacert found") + dntoa(buf, BUF_LEN, cert->subject); + DBG_log("subject: '%s'",buf); + dntoa(buf, BUF_LEN, cert->issuer); + DBG_log("issuer: '%s'",buf); + if (cert->authKeyID.ptr != NULL) + { + datatot(cert->authKeyID.ptr, cert->authKeyID.len, ':' + , buf, BUF_LEN); + DBG_log("authkey: %s", buf); + } ) - } - else - { - plog("issuer cacert not found"); - unlock_authcert_list("trust_authcert_candidate"); - return FALSE; - } - } - if (!check_signature(cert->tbsCertificate, cert->signature - , cert->algorithm, cert->algorithm, authcert)) - { - plog("certificate signature is invalid"); - unlock_authcert_list("trust_authcert_candidate"); - return FALSE; - } - DBG(DBG_CONTROL, - DBG_log("certificate signature is valid") - ) + /* search in alternative chain first */ + authcert = get_alt_cacert(cert->issuer, cert->authKeySerialNumber + , cert->authKeyID, alt_chain); - /* check if cert is a self-signed root ca */ - if (pathlen > 0 && same_dn(cert->issuer, cert->subject)) - { - DBG(DBG_CONTROL, - DBG_log("reached self-signed root ca") - ) - unlock_authcert_list("trust_authcert_candidate"); - return TRUE; - } + if (authcert != NULL) + { + DBG(DBG_CONTROL, + DBG_log("issuer cacert found in alternative chain") + ) + } + else + { + /* search in trusted chain */ + authcert = get_authcert(cert->issuer, cert->authKeySerialNumber + , cert->authKeyID, AUTH_CA); - /* go up one step in the trust chain */ - cert = authcert; - } - plog("maximum ca path length of %d levels exceeded", MAX_CA_PATH_LEN); - unlock_authcert_list("trust_authcert_candidate"); - return FALSE; + if (authcert != NULL) + { + DBG(DBG_CONTROL, + DBG_log("issuer cacert found") + ) + } + else + { + plog("issuer cacert not found"); + unlock_authcert_list("trust_authcert_candidate"); + return FALSE; + } + } + + if (!check_signature(cert->tbsCertificate, cert->signature + , cert->algorithm, cert->algorithm, authcert)) + { + plog("certificate signature is invalid"); + unlock_authcert_list("trust_authcert_candidate"); + return FALSE; + } + DBG(DBG_CONTROL, + DBG_log("certificate signature is valid") + ) + + /* check if cert is a self-signed root ca */ + if (pathlen > 0 && same_dn(cert->issuer, cert->subject)) + { + DBG(DBG_CONTROL, + DBG_log("reached self-signed root ca") + ) + unlock_authcert_list("trust_authcert_candidate"); + return TRUE; + } + + /* go up one step in the trust chain */ + cert = authcert; + } + plog("maximum ca path length of %d levels exceeded", MAX_CA_PATH_LEN); + unlock_authcert_list("trust_authcert_candidate"); + return FALSE; } /* @@ -423,19 +423,19 @@ trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chain) ca_info_t* get_ca_info(chunk_t authname, chunk_t serial, chunk_t keyid) { - ca_info_t *ca= ca_infos; + ca_info_t *ca= ca_infos; - while (ca!= NULL) - { - if ((keyid.ptr != NULL) ? same_keyid(keyid, ca->authKeyID) - : (same_dn(authname, ca->authName) - && same_serial(serial, ca->authKeySerialNumber))) + while (ca!= NULL) { - return ca; + if ((keyid.ptr != NULL) ? same_keyid(keyid, ca->authKeyID) + : (same_dn(authname, ca->authName) + && same_serial(serial, ca->authKeySerialNumber))) + { + return ca; + } + ca = ca->next; } - ca = ca->next; - } - return NULL; + return NULL; } @@ -445,18 +445,18 @@ get_ca_info(chunk_t authname, chunk_t serial, chunk_t keyid) static void free_ca_info(ca_info_t* ca_info) { - if (ca_info == NULL) - return; + if (ca_info == NULL) + return; - free(ca_info->name); - free(ca_info->ldaphost); - free(ca_info->ldapbase); - free(ca_info->ocspuri); - free(ca_info->authName.ptr); - free(ca_info->authKeyID.ptr); - free(ca_info->authKeySerialNumber.ptr); - free_generalNames(ca_info->crluri, TRUE); - free(ca_info); + free(ca_info->name); + free(ca_info->ldaphost); + free(ca_info->ldapbase); + free(ca_info->ocspuri); + free(ca_info->authName.ptr); + free(ca_info->authKeyID.ptr); + free(ca_info->authKeySerialNumber.ptr); + free_generalNames(ca_info->crluri, TRUE); + free(ca_info); } /* @@ -465,13 +465,13 @@ free_ca_info(ca_info_t* ca_info) void free_ca_infos(void) { - while (ca_infos != NULL) - { - ca_info_t *ca = ca_infos; + while (ca_infos != NULL) + { + ca_info_t *ca = ca_infos; - ca_infos = ca_infos->next; - free_ca_info(ca); - } + ca_infos = ca_infos->next; + free_ca_info(ca); + } } /* @@ -480,28 +480,28 @@ free_ca_infos(void) bool find_ca_info_by_name(const char *name, bool delete) { - ca_info_t **ca_p = &ca_infos; - ca_info_t *ca = *ca_p; + ca_info_t **ca_p = &ca_infos; + ca_info_t *ca = *ca_p; - while (ca != NULL) - { - /* is there already an entry? */ - if (streq(name, ca->name)) + while (ca != NULL) { - if (delete) - { - lock_ca_info_list("find_ca_info_by_name"); - *ca_p = ca->next; - free_ca_info(ca); - plog("deleting ca description \"%s\"", name); - unlock_ca_info_list("find_ca_info_by_name"); - } - return TRUE; + /* is there already an entry? */ + if (streq(name, ca->name)) + { + if (delete) + { + lock_ca_info_list("find_ca_info_by_name"); + *ca_p = ca->next; + free_ca_info(ca); + plog("deleting ca description \"%s\"", name); + unlock_ca_info_list("find_ca_info_by_name"); + } + return TRUE; + } + ca_p = &ca->next; + ca = *ca_p; } - ca_p = &ca->next; - ca = *ca_p; - } - return FALSE; + return FALSE; } @@ -511,133 +511,133 @@ find_ca_info_by_name(const char *name, bool delete) void add_ca_info(const whack_message_t *msg) { - smartcard_t *sc = NULL; - cert_t cert; - bool valid_cert = FALSE; - bool cached_cert = FALSE; + smartcard_t *sc = NULL; + cert_t cert; + bool valid_cert = FALSE; + bool cached_cert = FALSE; - if (find_ca_info_by_name(msg->name, FALSE)) - { - loglog(RC_DUPNAME, "attempt to redefine ca record \"%s\"", msg->name); - return; - } - - if (scx_on_smartcard(msg->cacert)) - { - /* load CA cert from smartcard */ - valid_cert = scx_load_cert(msg->cacert, &sc, &cert, &cached_cert); - } - else - { - /* load CA cert from file */ - valid_cert = load_ca_cert(msg->cacert, &cert); - } - - if (valid_cert) - { - char buf[BUF_LEN]; - x509cert_t *cacert = cert.u.x509; - ca_info_t *ca = NULL; - - /* does the authname already exist? */ - ca = get_ca_info(cacert->subject, cacert->serialNumber - , cacert->subjectKeyID); - - if (ca != NULL) + if (find_ca_info_by_name(msg->name, FALSE)) { - /* ca_info is already present */ - loglog(RC_DUPNAME, " duplicate ca information in record \"%s\" found," - "ignoring \"%s\"", ca->name, msg->name); - free_x509cert(cacert); - return; + loglog(RC_DUPNAME, "attempt to redefine ca record \"%s\"", msg->name); + return; } - plog("added ca description \"%s\"", msg->name); - - /* create and initialize new ca_info record */ - ca = malloc_thing(ca_info_t); - *ca = empty_ca_info; - - /* name */ - ca->name = clone_str(msg->name); - - /* authName */ - ca->authName = chunk_clone(cacert->subject); - dntoa(buf, BUF_LEN, ca->authName); - DBG(DBG_CONTROL, - DBG_log("authname: '%s'", buf) - ) - - /* authSerialNumber */ - ca->authKeySerialNumber = chunk_clone(cacert->serialNumber); - - /* authKeyID */ - if (cacert->subjectKeyID.ptr != NULL) + if (scx_on_smartcard(msg->cacert)) { - ca->authKeyID = chunk_clone(cacert->subjectKeyID); - datatot(cacert->subjectKeyID.ptr, cacert->subjectKeyID.len, ':' - , buf, BUF_LEN); - DBG(DBG_CONTROL | DBG_PARSING , - DBG_log("authkey: %s", buf) - ) + /* load CA cert from smartcard */ + valid_cert = scx_load_cert(msg->cacert, &sc, &cert, &cached_cert); + } + else + { + /* load CA cert from file */ + valid_cert = load_ca_cert(msg->cacert, &cert); } - /* ldaphost */ - ca->ldaphost = clone_str(msg->ldaphost); - - /* ldapbase */ - ca->ldapbase = clone_str(msg->ldapbase); - - /* ocspuri */ - if (msg->ocspuri != NULL) + if (valid_cert) { - if (strncasecmp(msg->ocspuri, "http", 4) == 0) - ca->ocspuri = clone_str(msg->ocspuri); - else - plog(" ignoring ocspuri with unkown protocol"); + char buf[BUF_LEN]; + x509cert_t *cacert = cert.u.x509; + ca_info_t *ca = NULL; + + /* does the authname already exist? */ + ca = get_ca_info(cacert->subject, cacert->serialNumber + , cacert->subjectKeyID); + + if (ca != NULL) + { + /* ca_info is already present */ + loglog(RC_DUPNAME, " duplicate ca information in record \"%s\" found," + "ignoring \"%s\"", ca->name, msg->name); + free_x509cert(cacert); + return; + } + + plog("added ca description \"%s\"", msg->name); + + /* create and initialize new ca_info record */ + ca = malloc_thing(ca_info_t); + *ca = empty_ca_info; + + /* name */ + ca->name = clone_str(msg->name); + + /* authName */ + ca->authName = chunk_clone(cacert->subject); + dntoa(buf, BUF_LEN, ca->authName); + DBG(DBG_CONTROL, + DBG_log("authname: '%s'", buf) + ) + + /* authSerialNumber */ + ca->authKeySerialNumber = chunk_clone(cacert->serialNumber); + + /* authKeyID */ + if (cacert->subjectKeyID.ptr != NULL) + { + ca->authKeyID = chunk_clone(cacert->subjectKeyID); + datatot(cacert->subjectKeyID.ptr, cacert->subjectKeyID.len, ':' + , buf, BUF_LEN); + DBG(DBG_CONTROL | DBG_PARSING , + DBG_log("authkey: %s", buf) + ) + } + + /* ldaphost */ + ca->ldaphost = clone_str(msg->ldaphost); + + /* ldapbase */ + ca->ldapbase = clone_str(msg->ldapbase); + + /* ocspuri */ + if (msg->ocspuri != NULL) + { + if (strncasecmp(msg->ocspuri, "http", 4) == 0) + ca->ocspuri = clone_str(msg->ocspuri); + else + plog(" ignoring ocspuri with unkown protocol"); + } + + /* crluri2*/ + if (msg->crluri2 != NULL) + { + generalName_t gn = + { NULL, GN_URI, {msg->crluri2, strlen(msg->crluri2)} }; + + add_distribution_points(&gn, &ca->crluri); + } + + /* crluri */ + if (msg->crluri != NULL) + { + generalName_t gn = + { NULL, GN_URI, {msg->crluri, strlen(msg->crluri)} }; + + add_distribution_points(&gn, &ca->crluri); + } + + /* strictrlpolicy */ + ca->strictcrlpolicy = msg->whack_strict; + + /* insert ca_info record into the chained list */ + lock_ca_info_list("add_ca_info"); + + ca->next = ca_infos; + ca_infos = ca; + ca->installed = time(NULL); + + unlock_ca_info_list("add_ca_info"); + + /* add cacert to list of authcerts */ + if (!cached_cert && sc != NULL) + { + if (sc->last_cert.type == CERT_X509_SIGNATURE) + sc->last_cert.u.x509->count--; + sc->last_cert.u.x509 = add_authcert(cacert, AUTH_CA); + share_cert(sc->last_cert); + } + if (sc != NULL) + time(&sc->last_load); } - - /* crluri2*/ - if (msg->crluri2 != NULL) - { - generalName_t gn = - { NULL, GN_URI, {msg->crluri2, strlen(msg->crluri2)} }; - - add_distribution_points(&gn, &ca->crluri); - } - - /* crluri */ - if (msg->crluri != NULL) - { - generalName_t gn = - { NULL, GN_URI, {msg->crluri, strlen(msg->crluri)} }; - - add_distribution_points(&gn, &ca->crluri); - } - - /* strictrlpolicy */ - ca->strictcrlpolicy = msg->whack_strict; - - /* insert ca_info record into the chained list */ - lock_ca_info_list("add_ca_info"); - - ca->next = ca_infos; - ca_infos = ca; - ca->installed = time(NULL); - - unlock_ca_info_list("add_ca_info"); - - /* add cacert to list of authcerts */ - if (!cached_cert && sc != NULL) - { - if (sc->last_cert.type == CERT_X509_SIGNATURE) - sc->last_cert.u.x509->count--; - sc->last_cert.u.x509 = add_authcert(cacert, AUTH_CA); - share_cert(sc->last_cert); - } - if (sc != NULL) - time(&sc->last_load); - } } /* @@ -646,51 +646,51 @@ add_ca_info(const whack_message_t *msg) void list_ca_infos(bool utc) { - ca_info_t *ca = ca_infos; - - if (ca != NULL) - { - whack_log(RC_COMMENT, " "); - whack_log(RC_COMMENT, "List of X.509 CA Information Records:"); - whack_log(RC_COMMENT, " "); - } - - while (ca != NULL) - { - u_char buf[BUF_LEN]; - - /* strictpolicy per CA not supported yet - * - whack_log(RC_COMMENT, "%T, \"%s\", strictcrlpolicy: %s" - , &ca->installed, utc, ca->name - , ca->strictcrlpolicy? "yes":"no"); - */ - whack_log(RC_COMMENT, "%T, \"%s\"", &ca->installed, utc, ca->name); - dntoa(buf, BUF_LEN, ca->authName); - whack_log(RC_COMMENT, " authname: '%s'", buf); - if (ca->ldaphost != NULL) - whack_log(RC_COMMENT, " ldaphost: '%s'", ca->ldaphost); - if (ca->ldapbase != NULL) - whack_log(RC_COMMENT, " ldapbase: '%s'", ca->ldapbase); - if (ca->ocspuri != NULL) - whack_log(RC_COMMENT, " ocspuri: '%s'", ca->ocspuri); - - list_distribution_points(ca->crluri); - - if (ca->authKeyID.ptr != NULL) + ca_info_t *ca = ca_infos; + + if (ca != NULL) { - datatot(ca->authKeyID.ptr, ca->authKeyID.len, ':' - , buf, BUF_LEN); - whack_log(RC_COMMENT, " authkey: %s", buf); + whack_log(RC_COMMENT, " "); + whack_log(RC_COMMENT, "List of X.509 CA Information Records:"); + whack_log(RC_COMMENT, " "); } - if (ca->authKeySerialNumber.ptr != NULL) + + while (ca != NULL) { - datatot(ca->authKeySerialNumber.ptr, ca->authKeySerialNumber.len, ':' - , buf, BUF_LEN); - whack_log(RC_COMMENT, " aserial: %s", buf); + u_char buf[BUF_LEN]; + + /* strictpolicy per CA not supported yet + * + whack_log(RC_COMMENT, "%T, \"%s\", strictcrlpolicy: %s" + , &ca->installed, utc, ca->name + , ca->strictcrlpolicy? "yes":"no"); + */ + whack_log(RC_COMMENT, "%T, \"%s\"", &ca->installed, utc, ca->name); + dntoa(buf, BUF_LEN, ca->authName); + whack_log(RC_COMMENT, " authname: '%s'", buf); + if (ca->ldaphost != NULL) + whack_log(RC_COMMENT, " ldaphost: '%s'", ca->ldaphost); + if (ca->ldapbase != NULL) + whack_log(RC_COMMENT, " ldapbase: '%s'", ca->ldapbase); + if (ca->ocspuri != NULL) + whack_log(RC_COMMENT, " ocspuri: '%s'", ca->ocspuri); + + list_distribution_points(ca->crluri); + + if (ca->authKeyID.ptr != NULL) + { + datatot(ca->authKeyID.ptr, ca->authKeyID.len, ':' + , buf, BUF_LEN); + whack_log(RC_COMMENT, " authkey: %s", buf); + } + if (ca->authKeySerialNumber.ptr != NULL) + { + datatot(ca->authKeySerialNumber.ptr, ca->authKeySerialNumber.len, ':' + , buf, BUF_LEN); + whack_log(RC_COMMENT, " aserial: %s", buf); + } + ca = ca->next; } - ca = ca->next; - } } diff --git a/src/pluto/ca.h b/src/pluto/ca.h index 9cfa35b87..11bfbf16d 100644 --- a/src/pluto/ca.h +++ b/src/pluto/ca.h @@ -20,45 +20,45 @@ #include "x509.h" #include "whack.h" -#define MAX_CA_PATH_LEN 7 +#define MAX_CA_PATH_LEN 7 /* authority flags */ -#define AUTH_NONE 0x00 /* no authorities */ -#define AUTH_CA 0x01 /* certification authority */ -#define AUTH_AA 0x02 /* authorization authority */ -#define AUTH_OCSP 0x04 /* ocsp signing authority */ +#define AUTH_NONE 0x00 /* no authorities */ +#define AUTH_CA 0x01 /* certification authority */ +#define AUTH_AA 0x02 /* authorization authority */ +#define AUTH_OCSP 0x04 /* ocsp signing authority */ /* CA info structures */ typedef struct ca_info ca_info_t; struct ca_info { - ca_info_t *next; - char *name; - time_t installed; - chunk_t authName; - chunk_t authKeyID; - chunk_t authKeySerialNumber; - char *ldaphost; - char *ldapbase; - char *ocspuri; - generalName_t *crluri; - bool strictcrlpolicy; + ca_info_t *next; + char *name; + time_t installed; + chunk_t authName; + chunk_t authKeyID; + chunk_t authKeySerialNumber; + char *ldaphost; + char *ldapbase; + char *ocspuri; + generalName_t *crluri; + bool strictcrlpolicy; }; extern bool trusted_ca(chunk_t a, chunk_t b, int *pathlen); extern bool match_requested_ca(generalName_t *requested_ca - , chunk_t our_ca, int *our_pathlen); + , chunk_t our_ca, int *our_pathlen); extern x509cert_t* get_authcert(chunk_t subject, chunk_t serial, chunk_t keyid - , u_char auth_flags); + , u_char auth_flags); extern void load_authcerts(const char *type, const char *path - , u_char auth_flags); + , u_char auth_flags); extern x509cert_t* add_authcert(x509cert_t *cert, u_char auth_flags); extern void free_authcerts(void); extern void list_authcerts(const char *caption, u_char auth_flags, bool utc); extern bool trust_authcert_candidate(const x509cert_t *cert - , const x509cert_t *alt_chain); + , const x509cert_t *alt_chain); extern ca_info_t* get_ca_info(chunk_t name, chunk_t serial, chunk_t keyid); extern bool find_ca_info_by_name(const char *name, bool delete); extern void add_ca_info(const whack_message_t *msg); diff --git a/src/pluto/certs.c b/src/pluto/certs.c index d17fd80ad..c9c270c8a 100644 --- a/src/pluto/certs.c +++ b/src/pluto/certs.c @@ -43,15 +43,15 @@ const cert_t empty_cert = {CERT_NONE, {NULL}}; chunk_t get_mycert(cert_t cert) { - switch (cert.type) - { - case CERT_PGP: - return cert.u.pgp->certificate; - case CERT_X509_SIGNATURE: - return cert.u.x509->certificate; - default: - return chunk_empty; - } + switch (cert.type) + { + case CERT_PGP: + return cert.u.pgp->certificate; + case CERT_X509_SIGNATURE: + return cert.u.x509->certificate; + default: + return chunk_empty; + } } /* load a coded key or certificate file with autodetection @@ -61,64 +61,64 @@ bool load_coded_file(const char *filename, prompt_pass_t *pass, const char *type , chunk_t *blob, bool *pgp) { - err_t ugh = NULL; + err_t ugh = NULL; - FILE *fd = fopen(filename, "r"); + FILE *fd = fopen(filename, "r"); - if (fd) - { - int bytes; - fseek(fd, 0, SEEK_END ); - blob->len = ftell(fd); - rewind(fd); - blob->ptr = malloc(blob->len); - bytes = fread(blob->ptr, 1, blob->len, fd); - fclose(fd); - plog(" loaded %s file '%s' (%d bytes)", type, filename, bytes); - - *pgp = FALSE; - - /* try DER format */ - if (is_asn1(*blob)) + if (fd) { - DBG(DBG_PARSING, - DBG_log(" file coded in DER format"); - ) - return TRUE; + int bytes; + fseek(fd, 0, SEEK_END ); + blob->len = ftell(fd); + rewind(fd); + blob->ptr = malloc(blob->len); + bytes = fread(blob->ptr, 1, blob->len, fd); + fclose(fd); + plog(" loaded %s file '%s' (%d bytes)", type, filename, bytes); + + *pgp = FALSE; + + /* try DER format */ + if (is_asn1(*blob)) + { + DBG(DBG_PARSING, + DBG_log(" file coded in DER format"); + ) + return TRUE; + } + + /* try PEM format */ + ugh = pemtobin(blob, pass, filename, pgp); + + if (ugh == NULL) + { + if (*pgp) + { + DBG(DBG_PARSING, + DBG_log(" file coded in armored PGP format"); + ) + return TRUE; + } + if (is_asn1(*blob)) + { + DBG(DBG_PARSING, + DBG_log(" file coded in PEM format"); + ) + return TRUE; + } + ugh = "file coded in unknown format, discarded"; + } + + /* a conversion error has occured */ + plog(" %s", ugh); + free(blob->ptr); + *blob = chunk_empty; } - - /* try PEM format */ - ugh = pemtobin(blob, pass, filename, pgp); - - if (ugh == NULL) + else { - if (*pgp) - { - DBG(DBG_PARSING, - DBG_log(" file coded in armored PGP format"); - ) - return TRUE; - } - if (is_asn1(*blob)) - { - DBG(DBG_PARSING, - DBG_log(" file coded in PEM format"); - ) - return TRUE; - } - ugh = "file coded in unknown format, discarded"; + plog(" could not open %s file '%s'", type, filename); } - - /* a conversion error has occured */ - plog(" %s", ugh); - free(blob->ptr); - *blob = chunk_empty; - } - else - { - plog(" could not open %s file '%s'", type, filename); - } - return FALSE; + return FALSE; } /* @@ -128,30 +128,30 @@ err_t load_rsa_private_key(const char* filename, prompt_pass_t *pass , RSA_private_key_t *key) { - err_t ugh = NULL; - bool pgp = FALSE; - chunk_t blob = chunk_empty; + err_t ugh = NULL; + bool pgp = FALSE; + chunk_t blob = chunk_empty; - const char *path = concatenate_paths(PRIVATE_KEY_PATH, filename); + const char *path = concatenate_paths(PRIVATE_KEY_PATH, filename); - if (load_coded_file(path, pass, "private key", &blob, &pgp)) - { - if (pgp) + if (load_coded_file(path, pass, "private key", &blob, &pgp)) { - if (!parse_pgp(blob, NULL, key)) - ugh = "syntax error in PGP private key file"; + if (pgp) + { + if (!parse_pgp(blob, NULL, key)) + ugh = "syntax error in PGP private key file"; + } + else + { + if (!pkcs1_parse_private_key(blob, key)) + ugh = "syntax error in PKCS#1 private key file"; + } + free(blob.ptr); } else - { - if (!pkcs1_parse_private_key(blob, key)) - ugh = "syntax error in PKCS#1 private key file"; - } - free(blob.ptr); - } - else - ugh = "error loading RSA private key file"; + ugh = "error loading RSA private key file"; - return ugh; + return ugh; } /* * Loads a X.509 or OpenPGP certificate @@ -159,51 +159,51 @@ load_rsa_private_key(const char* filename, prompt_pass_t *pass bool load_cert(const char *filename, const char *label, cert_t *cert) { - bool pgp = FALSE; - chunk_t blob = chunk_empty; + bool pgp = FALSE; + chunk_t blob = chunk_empty; - /* initialize cert struct */ - cert->type = CERT_NONE; - cert->u.x509 = NULL; + /* initialize cert struct */ + cert->type = CERT_NONE; + cert->u.x509 = NULL; - if (load_coded_file(filename, NULL, label, &blob, &pgp)) - { - if (pgp) + if (load_coded_file(filename, NULL, label, &blob, &pgp)) { - pgpcert_t *pgpcert = malloc_thing(pgpcert_t); - *pgpcert = empty_pgpcert; - if (parse_pgp(blob, pgpcert, NULL)) - { - cert->type = CERT_PGP; - cert->u.pgp = pgpcert; - return TRUE; - } - else - { - plog(" error in OpenPGP certificate"); - free_pgpcert(pgpcert); - return FALSE; - } + if (pgp) + { + pgpcert_t *pgpcert = malloc_thing(pgpcert_t); + *pgpcert = empty_pgpcert; + if (parse_pgp(blob, pgpcert, NULL)) + { + cert->type = CERT_PGP; + cert->u.pgp = pgpcert; + return TRUE; + } + else + { + plog(" error in OpenPGP certificate"); + free_pgpcert(pgpcert); + return FALSE; + } + } + else + { + x509cert_t *x509cert = malloc_thing(x509cert_t); + *x509cert = empty_x509cert; + if (parse_x509cert(blob, 0, x509cert)) + { + cert->type = CERT_X509_SIGNATURE; + cert->u.x509 = x509cert; + return TRUE; + } + else + { + plog(" error in X.509 certificate"); + free_x509cert(x509cert); + return FALSE; + } + } } - else - { - x509cert_t *x509cert = malloc_thing(x509cert_t); - *x509cert = empty_x509cert; - if (parse_x509cert(blob, 0, x509cert)) - { - cert->type = CERT_X509_SIGNATURE; - cert->u.x509 = x509cert; - return TRUE; - } - else - { - plog(" error in X.509 certificate"); - free_x509cert(x509cert); - return FALSE; - } - } - } - return FALSE; + return FALSE; } /* @@ -212,9 +212,9 @@ load_cert(const char *filename, const char *label, cert_t *cert) bool load_host_cert(const char *filename, cert_t *cert) { - const char *path = concatenate_paths(HOST_CERT_PATH, filename); + const char *path = concatenate_paths(HOST_CERT_PATH, filename); - return load_cert(path, "host cert", cert); + return load_cert(path, "host cert", cert); } /* @@ -223,9 +223,9 @@ load_host_cert(const char *filename, cert_t *cert) bool load_ca_cert(const char *filename, cert_t *cert) { - const char *path = concatenate_paths(CA_CERT_PATH, filename); + const char *path = concatenate_paths(CA_CERT_PATH, filename); - return load_cert(path, "CA cert", cert); + return load_cert(path, "CA cert", cert); } /* @@ -234,7 +234,7 @@ load_ca_cert(const char *filename, cert_t *cert) bool same_cert(const cert_t *a, const cert_t *b) { - return a->type == b->type && a->u.x509 == b->u.x509; + return a->type == b->type && a->u.x509 == b->u.x509; } /* for each link pointing to the certif icate @@ -243,17 +243,17 @@ same_cert(const cert_t *a, const cert_t *b) void share_cert(cert_t cert) { - switch (cert.type) - { - case CERT_PGP: - share_pgpcert(cert.u.pgp); - break; - case CERT_X509_SIGNATURE: - share_x509cert(cert.u.x509); - break; - default: - break; - } + switch (cert.type) + { + case CERT_PGP: + share_pgpcert(cert.u.pgp); + break; + case CERT_X509_SIGNATURE: + share_x509cert(cert.u.x509); + break; + default: + break; + } } /* release of a certificate decreases the count by one @@ -263,16 +263,16 @@ void release_cert(cert_t cert) { switch (cert.type) - { - case CERT_PGP: - release_pgpcert(cert.u.pgp); - break; - case CERT_X509_SIGNATURE: - release_x509cert(cert.u.x509); - break; - default: - break; - } + { + case CERT_PGP: + release_pgpcert(cert.u.pgp); + break; + case CERT_X509_SIGNATURE: + release_x509cert(cert.u.x509); + break; + default: + break; + } } /* @@ -281,7 +281,7 @@ release_cert(cert_t cert) void list_certs(bool utc) { - list_x509_end_certs(utc); - list_pgp_end_certs(utc); + list_x509_end_certs(utc); + list_pgp_end_certs(utc); } diff --git a/src/pluto/certs.h b/src/pluto/certs.h index 7aee9c927..a3701460a 100644 --- a/src/pluto/certs.h +++ b/src/pluto/certs.h @@ -26,31 +26,31 @@ */ #define PRIVATE_KEY_PATH IPSEC_CONFDIR "/ipsec.d/private" #define HOST_CERT_PATH IPSEC_CONFDIR "/ipsec.d/certs" -#define CA_CERT_PATH IPSEC_CONFDIR "/ipsec.d/cacerts" -#define A_CERT_PATH IPSEC_CONFDIR "/ipsec.d/acerts" -#define AA_CERT_PATH IPSEC_CONFDIR "/ipsec.d/aacerts" -#define OCSP_CERT_PATH IPSEC_CONFDIR "/ipsec.d/ocspcerts" -#define CRL_PATH IPSEC_CONFDIR "/ipsec.d/crls" -#define REQ_PATH IPSEC_CONFDIR "/ipsec.d/reqs" +#define CA_CERT_PATH IPSEC_CONFDIR "/ipsec.d/cacerts" +#define A_CERT_PATH IPSEC_CONFDIR "/ipsec.d/acerts" +#define AA_CERT_PATH IPSEC_CONFDIR "/ipsec.d/aacerts" +#define OCSP_CERT_PATH IPSEC_CONFDIR "/ipsec.d/ocspcerts" +#define CRL_PATH IPSEC_CONFDIR "/ipsec.d/crls" +#define REQ_PATH IPSEC_CONFDIR "/ipsec.d/reqs" /* advance warning of imminent expiry of * cacerts, public keys, and crls */ -#define CA_CERT_WARNING_INTERVAL 30 /* days */ -#define OCSP_CERT_WARNING_INTERVAL 30 /* days */ -#define PUBKEY_WARNING_INTERVAL 7 /* days */ -#define CRL_WARNING_INTERVAL 7 /* days */ -#define ACERT_WARNING_INTERVAL 1 /* day */ +#define CA_CERT_WARNING_INTERVAL 30 /* days */ +#define OCSP_CERT_WARNING_INTERVAL 30 /* days */ +#define PUBKEY_WARNING_INTERVAL 7 /* days */ +#define CRL_WARNING_INTERVAL 7 /* days */ +#define ACERT_WARNING_INTERVAL 1 /* day */ /* certificate access structure * currently X.509 and OpenPGP certificates are supported */ typedef struct { - u_char type; - union { - x509cert_t *x509; - pgpcert_t *pgp; - } u; + u_char type; + union { + x509cert_t *x509; + pgpcert_t *pgp; + } u; } cert_t; /* used for initialization */ @@ -62,12 +62,12 @@ extern const cert_t empty_cert; extern bool no_cr_send; extern err_t load_rsa_private_key(const char* filename, prompt_pass_t *pass - , RSA_private_key_t *key); + , RSA_private_key_t *key); extern chunk_t get_mycert(cert_t cert); extern bool load_coded_file(const char *filename, prompt_pass_t *pass - , const char *type, chunk_t *blob, bool *pgp); + , const char *type, chunk_t *blob, bool *pgp); extern bool load_cert(const char *filename, const char *label - , cert_t *cert); + , cert_t *cert); extern bool load_host_cert(const char *filename, cert_t *cert); extern bool load_ca_cert(const char *filename, cert_t *cert); extern bool same_cert(const cert_t *a, const cert_t *b); diff --git a/src/pluto/connections.c b/src/pluto/connections.c index b51515d17..6c1d2b149 100644 --- a/src/pluto/connections.c +++ b/src/pluto/connections.c @@ -25,7 +25,7 @@ #include #include #include -#include /* missing from on old systems */ +#include /* missing from on old systems */ #include #include @@ -48,13 +48,13 @@ #include "demux.h" #include "state.h" #include "timer.h" -#include "ipsec_doi.h" /* needs demux.h and state.h */ +#include "ipsec_doi.h" /* needs demux.h and state.h */ #include "server.h" #include "kernel.h" #include "log.h" #include "keys.h" -#include "adns.h" /* needs */ -#include "dnskey.h" /* needs keys.h and adns.h */ +#include "adns.h" /* needs */ +#include "dnskey.h" /* needs keys.h and adns.h */ #include "whack.h" #include "alg_info.h" #include "ike_alg.h" @@ -62,7 +62,7 @@ #include "nat_traversal.h" #include "virtual.h" -static void flush_pending_by_connection(struct connection *c); /* forward */ +static void flush_pending_by_connection(struct connection *c); /* forward */ static struct connection *connections = NULL; @@ -77,14 +77,14 @@ static struct connection *connections = NULL; */ struct host_pair { - struct { - ip_address addr; - u_int16_t port; /* host order */ - } me, him; - bool initial_connection_sent; - struct connection *connections; /* connections with this pair */ - struct pending *pending; /* awaiting Keying Channel */ - struct host_pair *next; + struct { + ip_address addr; + u_int16_t port; /* host order */ + } me, him; + bool initial_connection_sent; + struct connection *connections; /* connections with this pair */ + struct pending *pending; /* awaiting Keying Channel */ + struct host_pair *next; }; static struct host_pair *host_pairs = NULL; @@ -96,45 +96,45 @@ bool same_peer_ids(const struct connection *c, const struct connection *d , const struct id *his_id) { - return same_id(&c->spd.this.id, &d->spd.this.id) - && same_id(his_id == NULL? &c->spd.that.id : his_id, &d->spd.that.id); + return same_id(&c->spd.this.id, &d->spd.this.id) + && same_id(his_id == NULL? &c->spd.that.id : his_id, &d->spd.that.id); } static struct host_pair * find_host_pair(const ip_address *myaddr, u_int16_t myport , const ip_address *hisaddr, u_int16_t hisport) { - struct host_pair *p, *prev; + struct host_pair *p, *prev; - /* default hisaddr to an appropriate any */ - if (hisaddr == NULL) - hisaddr = aftoinfo(addrtypeof(myaddr))->any; - - if (nat_traversal_enabled) - { - /** - * port is not relevant in host_pair. with nat_traversal we - * always use pluto_port (500) - */ - myport = pluto_port; - hisport = pluto_port; - } - - for (prev = NULL, p = host_pairs; p != NULL; prev = p, p = p->next) - { - if (sameaddr(&p->me.addr, myaddr) && p->me.port == myport - && sameaddr(&p->him.addr, hisaddr) && p->him.port == hisport) + /* default hisaddr to an appropriate any */ + if (hisaddr == NULL) + hisaddr = aftoinfo(addrtypeof(myaddr))->any; + + if (nat_traversal_enabled) { - if (prev != NULL) - { - prev->next = p->next; /* remove p from list */ - p->next = host_pairs; /* and stick it on front */ - host_pairs = p; - } - break; + /** + * port is not relevant in host_pair. with nat_traversal we + * always use pluto_port (500) + */ + myport = pluto_port; + hisport = pluto_port; } - } - return p; + + for (prev = NULL, p = host_pairs; p != NULL; prev = p, p = p->next) + { + if (sameaddr(&p->me.addr, myaddr) && p->me.port == myport + && sameaddr(&p->him.addr, hisaddr) && p->him.port == hisport) + { + if (prev != NULL) + { + prev->next = p->next; /* remove p from list */ + p->next = host_pairs; /* and stick it on front */ + host_pairs = p; + } + break; + } + } + return p; } /* find head of list of connections with this pair of hosts */ @@ -142,63 +142,63 @@ static struct connection * find_host_pair_connections(const ip_address *myaddr, u_int16_t myport , const ip_address *hisaddr, u_int16_t hisport) { - struct host_pair *hp = find_host_pair(myaddr, myport, hisaddr, hisport); + struct host_pair *hp = find_host_pair(myaddr, myport, hisaddr, hisport); - if (nat_traversal_enabled && hp && hisaddr) - { - struct connection *c; - - for (c = hp->connections; c != NULL; c = c->hp_next) + if (nat_traversal_enabled && hp && hisaddr) { - if (c->spd.this.host_port == myport && c->spd.that.host_port == hisport) - return c; + struct connection *c; + + for (c = hp->connections; c != NULL; c = c->hp_next) + { + if (c->spd.this.host_port == myport && c->spd.that.host_port == hisport) + return c; + } + return NULL; } - return NULL; - } - return hp == NULL? NULL : hp->connections; + return hp == NULL? NULL : hp->connections; } static void connect_to_host_pair(struct connection *c) { - if (oriented(*c)) - { - struct host_pair *hp; - - ip_address his_addr = (c->spd.that.allow_any) - ? *aftoinfo(addrtypeof(&c->spd.that.host_addr))->any - : c->spd.that.host_addr; - - hp = find_host_pair(&c->spd.this.host_addr, c->spd.this.host_port - , &his_addr, c->spd.that.host_port); - - if (hp == NULL) + if (oriented(*c)) { - /* no suitable host_pair -- build one */ - hp = malloc_thing(struct host_pair); - hp->me.addr = c->spd.this.host_addr; - hp->him.addr = his_addr; - hp->me.port = nat_traversal_enabled ? pluto_port : c->spd.this.host_port; - hp->him.port = nat_traversal_enabled ? pluto_port : c->spd.that.host_port; - hp->initial_connection_sent = FALSE; - hp->connections = NULL; - hp->pending = NULL; - hp->next = host_pairs; - host_pairs = hp; + struct host_pair *hp; + + ip_address his_addr = (c->spd.that.allow_any) + ? *aftoinfo(addrtypeof(&c->spd.that.host_addr))->any + : c->spd.that.host_addr; + + hp = find_host_pair(&c->spd.this.host_addr, c->spd.this.host_port + , &his_addr, c->spd.that.host_port); + + if (hp == NULL) + { + /* no suitable host_pair -- build one */ + hp = malloc_thing(struct host_pair); + hp->me.addr = c->spd.this.host_addr; + hp->him.addr = his_addr; + hp->me.port = nat_traversal_enabled ? pluto_port : c->spd.this.host_port; + hp->him.port = nat_traversal_enabled ? pluto_port : c->spd.that.host_port; + hp->initial_connection_sent = FALSE; + hp->connections = NULL; + hp->pending = NULL; + hp->next = host_pairs; + host_pairs = hp; + } + c->host_pair = hp; + c->hp_next = hp->connections; + hp->connections = c; + } + else + { + /* since this connection isn't oriented, we place it + * in the unoriented_connections list instead. + */ + c->host_pair = NULL; + c->hp_next = unoriented_connections; + unoriented_connections = c; } - c->host_pair = hp; - c->hp_next = hp->connections; - hp->connections = c; - } - else - { - /* since this connection isn't oriented, we place it - * in the unoriented_connections list instead. - */ - c->host_pair = NULL; - c->hp_next = unoriented_connections; - unoriented_connections = c; - } } /* find a connection by name. @@ -209,317 +209,317 @@ connect_to_host_pair(struct connection *c) struct connection * con_by_name(const char *nm, bool strict) { - struct connection *p, *prev; + struct connection *p, *prev; - for (prev = NULL, p = connections; ; prev = p, p = p->ac_next) - { - if (p == NULL) + for (prev = NULL, p = connections; ; prev = p, p = p->ac_next) { - if (strict) - whack_log(RC_UNKNOWN_NAME - , "no connection named \"%s\"", nm); - break; + if (p == NULL) + { + if (strict) + whack_log(RC_UNKNOWN_NAME + , "no connection named \"%s\"", nm); + break; + } + if (streq(p->name, nm) + && (!strict || p->kind != CK_INSTANCE)) + { + if (prev != NULL) + { + prev->ac_next = p->ac_next; /* remove p from list */ + p->ac_next = connections; /* and stick it on front */ + connections = p; + } + break; + } } - if (streq(p->name, nm) - && (!strict || p->kind != CK_INSTANCE)) - { - if (prev != NULL) - { - prev->ac_next = p->ac_next; /* remove p from list */ - p->ac_next = connections; /* and stick it on front */ - connections = p; - } - break; - } - } - return p; + return p; } void release_connection(struct connection *c, bool relations) { - if (c->kind == CK_INSTANCE) - { - /* This does everything we need. - * Note that we will be called recursively by delete_connection, - * but kind will be CK_GOING_AWAY. - */ - delete_connection(c, relations); - } - else - { - flush_pending_by_connection(c); - delete_states_by_connection(c, relations); - unroute_connection(c); - } + if (c->kind == CK_INSTANCE) + { + /* This does everything we need. + * Note that we will be called recursively by delete_connection, + * but kind will be CK_GOING_AWAY. + */ + delete_connection(c, relations); + } + else + { + flush_pending_by_connection(c); + delete_states_by_connection(c, relations); + unroute_connection(c); + } } /* Delete a connection */ #define list_rm(etype, enext, e, ehead) { \ - etype **ep; \ - for (ep = &(ehead); *ep != (e); ep = &(*ep)->enext) \ - passert(*ep != NULL); /* we must not come up empty-handed */ \ - *ep = (e)->enext; \ - } + etype **ep; \ + for (ep = &(ehead); *ep != (e); ep = &(*ep)->enext) \ + passert(*ep != NULL); /* we must not come up empty-handed */ \ + *ep = (e)->enext; \ + } void delete_connection(struct connection *c, bool relations) { - struct connection *old_cur_connection - = cur_connection == c? NULL : cur_connection; + struct connection *old_cur_connection + = cur_connection == c? NULL : cur_connection; #ifdef DEBUG - lset_t old_cur_debugging = cur_debugging; + lset_t old_cur_debugging = cur_debugging; #endif - set_cur_connection(c); + set_cur_connection(c); - /* Must be careful to avoid circularity: - * we mark c as going away so it won't get deleted recursively. - */ - passert(c->kind != CK_GOING_AWAY); - if (c->kind == CK_INSTANCE) - { - plog("deleting connection \"%s\" instance with peer %s {isakmp=#%lu/ipsec=#%lu}" - , c->name - , ip_str(&c->spd.that.host_addr) - , c->newest_isakmp_sa, c->newest_ipsec_sa); - c->kind = CK_GOING_AWAY; - } - else - { - plog("deleting connection"); - } - release_connection(c, relations); /* won't delete c */ - - if (c->kind == CK_GROUP) - delete_group(c); - - /* free up any logging resources */ - perpeer_logfree(c); - - /* find and delete c from connections list */ - list_rm(struct connection, ac_next, c, connections); - cur_connection = old_cur_connection; - - /* find and delete c from the host pair list */ - if (c->host_pair == NULL) - { - if (c->ikev1) - list_rm(struct connection, hp_next, c, unoriented_connections); - } - else - { - struct host_pair *hp = c->host_pair; - - list_rm(struct connection, hp_next, c, hp->connections); - c->host_pair = NULL; /* redundant, but safe */ - - /* if there are no more connections with this host_pair - * and we haven't even made an initial contact, let's delete - * this guy in case we were created by an attempted DOS attack. + /* Must be careful to avoid circularity: + * we mark c as going away so it won't get deleted recursively. */ - if (hp->connections == NULL - && !hp->initial_connection_sent) + passert(c->kind != CK_GOING_AWAY); + if (c->kind == CK_INSTANCE) { - passert(hp->pending == NULL); /* ??? must deal with this! */ - list_rm(struct host_pair, next, hp, host_pairs); - free(hp); + plog("deleting connection \"%s\" instance with peer %s {isakmp=#%lu/ipsec=#%lu}" + , c->name + , ip_str(&c->spd.that.host_addr) + , c->newest_isakmp_sa, c->newest_ipsec_sa); + c->kind = CK_GOING_AWAY; + } + else + { + plog("deleting connection"); + } + release_connection(c, relations); /* won't delete c */ + + if (c->kind == CK_GROUP) + delete_group(c); + + /* free up any logging resources */ + perpeer_logfree(c); + + /* find and delete c from connections list */ + list_rm(struct connection, ac_next, c, connections); + cur_connection = old_cur_connection; + + /* find and delete c from the host pair list */ + if (c->host_pair == NULL) + { + if (c->ikev1) + list_rm(struct connection, hp_next, c, unoriented_connections); + } + else + { + struct host_pair *hp = c->host_pair; + + list_rm(struct connection, hp_next, c, hp->connections); + c->host_pair = NULL; /* redundant, but safe */ + + /* if there are no more connections with this host_pair + * and we haven't even made an initial contact, let's delete + * this guy in case we were created by an attempted DOS attack. + */ + if (hp->connections == NULL + && !hp->initial_connection_sent) + { + passert(hp->pending == NULL); /* ??? must deal with this! */ + list_rm(struct host_pair, next, hp, host_pairs); + free(hp); + } + } + if (c->kind != CK_GOING_AWAY) + { + free(c->spd.that.virt); } - } - if (c->kind != CK_GOING_AWAY) - { - free(c->spd.that.virt); - } #ifdef DEBUG - cur_debugging = old_cur_debugging; + cur_debugging = old_cur_debugging; #endif - free(c->name); - free_id_content(&c->spd.this.id); - free(c->spd.this.updown); - free(c->spd.this.ca.ptr); - free_ietfAttrList(c->spd.this.groups); - free_id_content(&c->spd.that.id); - free(c->spd.that.updown); - free(c->spd.that.ca.ptr); - free_ietfAttrList(c->spd.that.groups); - free_generalNames(c->requested_ca, TRUE); - gw_delref(&c->gw_info); + free(c->name); + free_id_content(&c->spd.this.id); + free(c->spd.this.updown); + free(c->spd.this.ca.ptr); + free_ietfAttrList(c->spd.this.groups); + free_id_content(&c->spd.that.id); + free(c->spd.that.updown); + free(c->spd.that.ca.ptr); + free_ietfAttrList(c->spd.that.groups); + free_generalNames(c->requested_ca, TRUE); + gw_delref(&c->gw_info); - lock_certs_and_keys("delete_connection"); - release_cert(c->spd.this.cert); - scx_release(c->spd.this.sc); - release_cert(c->spd.that.cert); - scx_release(c->spd.that.sc); - unlock_certs_and_keys("delete_connection"); + lock_certs_and_keys("delete_connection"); + release_cert(c->spd.this.cert); + scx_release(c->spd.this.sc); + release_cert(c->spd.that.cert); + scx_release(c->spd.that.sc); + unlock_certs_and_keys("delete_connection"); - alg_info_delref((struct alg_info **)&c->alg_info_esp); - alg_info_delref((struct alg_info **)&c->alg_info_ike); + alg_info_delref((struct alg_info **)&c->alg_info_esp); + alg_info_delref((struct alg_info **)&c->alg_info_ike); - free(c); + free(c); } /* Delete connections with the specified name */ void delete_connections_by_name(const char *name, bool strict) { - struct connection *c = con_by_name(name, strict); + struct connection *c = con_by_name(name, strict); - for (; c != NULL; c = con_by_name(name, FALSE)) - delete_connection(c, FALSE); + for (; c != NULL; c = con_by_name(name, FALSE)) + delete_connection(c, FALSE); } void delete_every_connection(void) { - while (connections != NULL) - delete_connection(connections, TRUE); + while (connections != NULL) + delete_connection(connections, TRUE); } void release_dead_interfaces(void) { - struct host_pair *hp; + struct host_pair *hp; - for (hp = host_pairs; hp != NULL; hp = hp->next) - { - struct connection **pp - , *p; - - for (pp = &hp->connections; (p = *pp) != NULL; ) + for (hp = host_pairs; hp != NULL; hp = hp->next) { - if (p->interface->change == IFN_DELETE) - { - /* this connection's interface is going away */ - enum connection_kind k = p->kind; + struct connection **pp + , *p; - release_connection(p, TRUE); - - if (k <= CK_PERMANENT) + for (pp = &hp->connections; (p = *pp) != NULL; ) { - /* The connection should have survived release: - * move it to the unoriented_connections list. - */ - passert(p == *pp); + if (p->interface->change == IFN_DELETE) + { + /* this connection's interface is going away */ + enum connection_kind k = p->kind; - p->interface = NULL; + release_connection(p, TRUE); - *pp = p->hp_next; /* advance *pp */ - p->host_pair = NULL; - p->hp_next = unoriented_connections; - unoriented_connections = p; + if (k <= CK_PERMANENT) + { + /* The connection should have survived release: + * move it to the unoriented_connections list. + */ + passert(p == *pp); + + p->interface = NULL; + + *pp = p->hp_next; /* advance *pp */ + p->host_pair = NULL; + p->hp_next = unoriented_connections; + unoriented_connections = p; + } + else + { + /* The connection should have vanished, + * but the previous connection remains. + */ + passert(p != *pp); + } + } + else + { + pp = &p->hp_next; /* advance pp */ + } } - else - { - /* The connection should have vanished, - * but the previous connection remains. - */ - passert(p != *pp); - } - } - else - { - pp = &p->hp_next; /* advance pp */ - } } - } } /* adjust orientations of connections to reflect newly added interfaces */ void check_orientations(void) { - /* try to orient all the unoriented connections */ - { - struct connection *c = unoriented_connections; - - unoriented_connections = NULL; - - while (c != NULL) + /* try to orient all the unoriented connections */ { - struct connection *nxt = c->hp_next; + struct connection *c = unoriented_connections; - (void)orient(c); - connect_to_host_pair(c); - c = nxt; - } - } + unoriented_connections = NULL; - /* Check that no oriented connection has become double-oriented. - * In other words, the far side must not match one of our new interfaces. - */ - { - struct iface *i; - - for (i = interfaces; i != NULL; i = i->next) - { - if (i->change == IFN_ADD) - { - struct host_pair *hp; - - for (hp = host_pairs; hp != NULL; hp = hp->next) + while (c != NULL) { - if (sameaddr(&hp->him.addr, &i->addr) - && (!no_klips || hp->him.port == pluto_port)) - { - /* bad news: the whole chain of connections - * hanging off this host pair has both sides - * matching an interface. - * We'll get rid of them, using orient and - * connect_to_host_pair. But we'll be lazy - * and not ditch the host_pair itself (the - * cost of leaving it is slight and cannot - * be induced by a foe). - */ - struct connection *c = hp->connections; + struct connection *nxt = c->hp_next; - hp->connections = NULL; - while (c != NULL) + (void)orient(c); + connect_to_host_pair(c); + c = nxt; + } + } + + /* Check that no oriented connection has become double-oriented. + * In other words, the far side must not match one of our new interfaces. + */ + { + struct iface *i; + + for (i = interfaces; i != NULL; i = i->next) + { + if (i->change == IFN_ADD) { - struct connection *nxt = c->hp_next; + struct host_pair *hp; + + for (hp = host_pairs; hp != NULL; hp = hp->next) + { + if (sameaddr(&hp->him.addr, &i->addr) + && (!no_klips || hp->him.port == pluto_port)) + { + /* bad news: the whole chain of connections + * hanging off this host pair has both sides + * matching an interface. + * We'll get rid of them, using orient and + * connect_to_host_pair. But we'll be lazy + * and not ditch the host_pair itself (the + * cost of leaving it is slight and cannot + * be induced by a foe). + */ + struct connection *c = hp->connections; + + hp->connections = NULL; + while (c != NULL) + { + struct connection *nxt = c->hp_next; - c->interface = NULL; - (void)orient(c); - connect_to_host_pair(c); - c = nxt; + c->interface = NULL; + (void)orient(c); + connect_to_host_pair(c); + c = nxt; + } + } + } } - } } - } } - } } static err_t default_end(struct end *e, ip_address *dflt_nexthop) { - err_t ugh = NULL; - const struct af_info *afi = aftoinfo(addrtypeof(&e->host_addr)); + err_t ugh = NULL; + const struct af_info *afi = aftoinfo(addrtypeof(&e->host_addr)); - if (afi == NULL) - return "unknown address family in default_end"; + if (afi == NULL) + return "unknown address family in default_end"; - /* default ID to IP (but only if not NO_IP -- WildCard) */ - if (e->id.kind == ID_NONE && !isanyaddr(&e->host_addr)) - { - e->id.kind = afi->id_addr; - e->id.ip_addr = e->host_addr; - e->has_id_wildcards = FALSE; - } + /* default ID to IP (but only if not NO_IP -- WildCard) */ + if (e->id.kind == ID_NONE && !isanyaddr(&e->host_addr)) + { + e->id.kind = afi->id_addr; + e->id.ip_addr = e->host_addr; + e->has_id_wildcards = FALSE; + } - /* default nexthop to other side */ - if (isanyaddr(&e->host_nexthop)) - e->host_nexthop = *dflt_nexthop; + /* default nexthop to other side */ + if (isanyaddr(&e->host_nexthop)) + e->host_nexthop = *dflt_nexthop; - /* default client to subnet containing only self - * XXX This may mean that the client's address family doesn't match - * tunnel_addr_family. - */ - if (!e->has_client) - ugh = addrtosubnet(&e->host_addr, &e->client); + /* default client to subnet containing only self + * XXX This may mean that the client's address family doesn't match + * tunnel_addr_family. + */ + if (!e->has_client) + ugh = addrtosubnet(&e->host_addr, &e->client); - return ugh; + return ugh; } /* Format the topology of a connection end, leaving out defaults. @@ -535,643 +535,643 @@ format_end(char *buf , bool is_left , lset_t policy) { - char client[SUBNETTOT_BUF]; - const char *client_sep = ""; - char protoport[sizeof(":255/65535")]; - const char *host = NULL; - char host_space[ADDRTOT_BUF]; - char host_port[sizeof(":65535")]; - char host_id[BUF_LEN + 2]; - char hop[ADDRTOT_BUF]; - const char *hop_sep = ""; - const char *open_brackets = ""; - const char *close_brackets = ""; + char client[SUBNETTOT_BUF]; + const char *client_sep = ""; + char protoport[sizeof(":255/65535")]; + const char *host = NULL; + char host_space[ADDRTOT_BUF]; + char host_port[sizeof(":65535")]; + char host_id[BUF_LEN + 2]; + char hop[ADDRTOT_BUF]; + const char *hop_sep = ""; + const char *open_brackets = ""; + const char *close_brackets = ""; - if (isanyaddr(&this->host_addr)) - { - switch (policy & (POLICY_GROUP | POLICY_OPPO)) + if (isanyaddr(&this->host_addr)) { - case POLICY_GROUP: - host = "%group"; - break; - case POLICY_OPPO: - host = "%opportunistic"; - break; - case POLICY_GROUP | POLICY_OPPO: - host = "%opportunisticgroup"; - break; - default: - host = "%any"; - break; + switch (policy & (POLICY_GROUP | POLICY_OPPO)) + { + case POLICY_GROUP: + host = "%group"; + break; + case POLICY_OPPO: + host = "%opportunistic"; + break; + case POLICY_GROUP | POLICY_OPPO: + host = "%opportunisticgroup"; + break; + default: + host = "%any"; + break; + } } - } - client[0] = '\0'; + client[0] = '\0'; - if (is_virtual_end(this) && isanyaddr(&this->host_addr)) - { - host = "%virtual"; - } + if (is_virtual_end(this) && isanyaddr(&this->host_addr)) + { + host = "%virtual"; + } - /* [client===] */ - if (this->has_client) - { - ip_address client_net, client_mask; + /* [client===] */ + if (this->has_client) + { + ip_address client_net, client_mask; - networkof(&this->client, &client_net); - maskof(&this->client, &client_mask); - client_sep = "==="; + networkof(&this->client, &client_net); + maskof(&this->client, &client_mask); + client_sep = "==="; - /* {client_subnet_wildcard} */ - if (this->has_client_wildcard) - { - open_brackets = "{"; - close_brackets = "}"; - } + /* {client_subnet_wildcard} */ + if (this->has_client_wildcard) + { + open_brackets = "{"; + close_brackets = "}"; + } - if (isanyaddr(&client_net) && isanyaddr(&client_mask) - && (policy & (POLICY_GROUP | POLICY_OPPO))) - client_sep = ""; /* boring case */ - else if (subnetisnone(&this->client)) - strcpy(client, "?"); + if (isanyaddr(&client_net) && isanyaddr(&client_mask) + && (policy & (POLICY_GROUP | POLICY_OPPO))) + client_sep = ""; /* boring case */ + else if (subnetisnone(&this->client)) + strcpy(client, "?"); + else + subnettot(&this->client, 0, client, sizeof(client)); + } + else if (this->modecfg && isanyaddr(&this->host_srcip)) + { + /* we are mode config client */ + client_sep = "==="; + strcpy(client, "%modecfg"); + } + + /* host */ + if (host == NULL) + { + addrtot(&this->host_addr, 0, host_space, sizeof(host_space)); + host = host_space; + } + + host_port[0] = '\0'; + if (this->host_port != IKE_UDP_PORT) + snprintf(host_port, sizeof(host_port), ":%u" + , this->host_port); + + /* payload portocol and port */ + protoport[0] = '\0'; + if (this->has_port_wildcard) + snprintf(protoport, sizeof(protoport), ":%u/%%any", this->protocol); + else if (this->port || this->protocol) + snprintf(protoport, sizeof(protoport), ":%u/%u", this->protocol + , this->port); + + /* id, if different from host */ + host_id[0] = '\0'; + if (this->id.kind == ID_MYID) + { + strcpy(host_id, "[%myid]"); + } + else if (!(this->id.kind == ID_NONE + || (id_is_ipaddr(&this->id) && sameaddr(&this->id.ip_addr, &this->host_addr)))) + { + int len = idtoa(&this->id, host_id+1, sizeof(host_id)-2); + + host_id[0] = '['; + strcpy(&host_id[len < 0? (ptrdiff_t)sizeof(host_id)-2 : 1 + len], "]"); + } + + /* [---hop] */ + hop[0] = '\0'; + hop_sep = ""; + if (that != NULL && !sameaddr(&this->host_nexthop, &that->host_addr)) + { + addrtot(&this->host_nexthop, 0, hop, sizeof(hop)); + hop_sep = "---"; + } + + if (is_left) + snprintf(buf, buf_len, "%s%s%s%s%s%s%s%s%s%s%s" + , open_brackets, client, close_brackets, client_sep + , this->allow_any? "%":"" + , host, host_port, host_id, protoport + , hop_sep, hop); else - subnettot(&this->client, 0, client, sizeof(client)); - } - else if (this->modecfg && isanyaddr(&this->host_srcip)) - { - /* we are mode config client */ - client_sep = "==="; - strcpy(client, "%modecfg"); - } - - /* host */ - if (host == NULL) - { - addrtot(&this->host_addr, 0, host_space, sizeof(host_space)); - host = host_space; - } - - host_port[0] = '\0'; - if (this->host_port != IKE_UDP_PORT) - snprintf(host_port, sizeof(host_port), ":%u" - , this->host_port); - - /* payload portocol and port */ - protoport[0] = '\0'; - if (this->has_port_wildcard) - snprintf(protoport, sizeof(protoport), ":%u/%%any", this->protocol); - else if (this->port || this->protocol) - snprintf(protoport, sizeof(protoport), ":%u/%u", this->protocol - , this->port); - - /* id, if different from host */ - host_id[0] = '\0'; - if (this->id.kind == ID_MYID) - { - strcpy(host_id, "[%myid]"); - } - else if (!(this->id.kind == ID_NONE - || (id_is_ipaddr(&this->id) && sameaddr(&this->id.ip_addr, &this->host_addr)))) - { - int len = idtoa(&this->id, host_id+1, sizeof(host_id)-2); - - host_id[0] = '['; - strcpy(&host_id[len < 0? (ptrdiff_t)sizeof(host_id)-2 : 1 + len], "]"); - } - - /* [---hop] */ - hop[0] = '\0'; - hop_sep = ""; - if (that != NULL && !sameaddr(&this->host_nexthop, &that->host_addr)) - { - addrtot(&this->host_nexthop, 0, hop, sizeof(hop)); - hop_sep = "---"; - } - - if (is_left) - snprintf(buf, buf_len, "%s%s%s%s%s%s%s%s%s%s%s" - , open_brackets, client, close_brackets, client_sep - , this->allow_any? "%":"" - , host, host_port, host_id, protoport - , hop_sep, hop); - else - snprintf(buf, buf_len, "%s%s%s%s%s%s%s%s%s%s%s" - , hop, hop_sep - , this->allow_any? "%":"" - , host, host_port, host_id, protoport, client_sep - , open_brackets, client, close_brackets); - return strlen(buf); + snprintf(buf, buf_len, "%s%s%s%s%s%s%s%s%s%s%s" + , hop, hop_sep + , this->allow_any? "%":"" + , host, host_port, host_id, protoport, client_sep + , open_brackets, client, close_brackets); + return strlen(buf); } /* format topology of a connection. * Two symmetric ends separated by ... */ -#define CONNECTION_BUF (2 * (END_BUF - 1) + 4) +#define CONNECTION_BUF (2 * (END_BUF - 1) + 4) static size_t format_connection(char *buf, size_t buf_len - , const struct connection *c - , struct spd_route *sr) + , const struct connection *c + , struct spd_route *sr) { - size_t w = format_end(buf, buf_len, &sr->this, &sr->that, TRUE, LEMPTY); + size_t w = format_end(buf, buf_len, &sr->this, &sr->that, TRUE, LEMPTY); - w += snprintf(buf + w, buf_len - w, "..."); - return w + format_end(buf + w, buf_len - w, &sr->that, &sr->this, FALSE, c->policy); + w += snprintf(buf + w, buf_len - w, "..."); + return w + format_end(buf + w, buf_len - w, &sr->that, &sr->this, FALSE, c->policy); } static void unshare_connection_strings(struct connection *c) { - c->name = clone_str(c->name); + c->name = clone_str(c->name); - unshare_id_content(&c->spd.this.id); - c->spd.this.updown = clone_str(c->spd.this.updown); - scx_share(c->spd.this.sc); - share_cert(c->spd.this.cert); - c->spd.this.ca = chunk_clone(c->spd.this.ca); + unshare_id_content(&c->spd.this.id); + c->spd.this.updown = clone_str(c->spd.this.updown); + scx_share(c->spd.this.sc); + share_cert(c->spd.this.cert); + c->spd.this.ca = chunk_clone(c->spd.this.ca); - unshare_id_content(&c->spd.that.id); - c->spd.that.updown = clone_str(c->spd.that.updown); - scx_share(c->spd.that.sc); - share_cert(c->spd.that.cert); - c->spd.that.ca = chunk_clone(c->spd.that.ca); + unshare_id_content(&c->spd.that.id); + c->spd.that.updown = clone_str(c->spd.that.updown); + scx_share(c->spd.that.sc); + share_cert(c->spd.that.cert); + c->spd.that.ca = chunk_clone(c->spd.that.ca); - /* increment references to algo's */ - alg_info_addref((struct alg_info *)c->alg_info_esp); - alg_info_addref((struct alg_info *)c->alg_info_ike); + /* increment references to algo's */ + alg_info_addref((struct alg_info *)c->alg_info_esp); + alg_info_addref((struct alg_info *)c->alg_info_ike); } static void load_end_certificate(const char *filename, struct end *dst) { - time_t valid_until; - cert_t cert; - bool valid_cert = FALSE; - bool cached_cert = FALSE; + time_t valid_until; + cert_t cert; + bool valid_cert = FALSE; + bool cached_cert = FALSE; - /* initialize end certificate */ - dst->cert.type = CERT_NONE; - dst->cert.u.x509 = NULL; + /* initialize end certificate */ + dst->cert.type = CERT_NONE; + dst->cert.u.x509 = NULL; - /* initialize smartcard info record */ - dst->sc = NULL; + /* initialize smartcard info record */ + dst->sc = NULL; - if (filename != NULL) - { - if (scx_on_smartcard(filename)) + if (filename != NULL) { - /* load cert from smartcard */ - valid_cert = scx_load_cert(filename, &dst->sc, &cert, &cached_cert); - } - else - { - /* load cert from file */ - valid_cert = load_host_cert(filename, &cert); - } - } - - if (valid_cert) - { - err_t ugh = NULL; - - switch (cert.type) - { - case CERT_PGP: - select_pgpcert_id(cert.u.pgp, &dst->id); - - if (cached_cert) - dst->cert = cert; - else - { - valid_until = cert.u.pgp->until; - add_pgp_public_key(cert.u.pgp, cert.u.pgp->until, DAL_LOCAL); - dst->cert.type = cert.type; - dst->cert.u.pgp = add_pgpcert(cert.u.pgp); - } - break; - case CERT_X509_SIGNATURE: - select_x509cert_id(cert.u.x509, &dst->id); - - if (cached_cert) - dst->cert = cert; - else - { - /* check validity of cert */ - valid_until = cert.u.x509->notAfter; - ugh = check_validity(cert.u.x509, &valid_until); - if (ugh != NULL) + if (scx_on_smartcard(filename)) { - plog(" %s", ugh); - free_x509cert(cert.u.x509); - break; + /* load cert from smartcard */ + valid_cert = scx_load_cert(filename, &dst->sc, &cert, &cached_cert); + } + else + { + /* load cert from file */ + valid_cert = load_host_cert(filename, &cert); + } + } + + if (valid_cert) + { + err_t ugh = NULL; + + switch (cert.type) + { + case CERT_PGP: + select_pgpcert_id(cert.u.pgp, &dst->id); + + if (cached_cert) + dst->cert = cert; + else + { + valid_until = cert.u.pgp->until; + add_pgp_public_key(cert.u.pgp, cert.u.pgp->until, DAL_LOCAL); + dst->cert.type = cert.type; + dst->cert.u.pgp = add_pgpcert(cert.u.pgp); + } + break; + case CERT_X509_SIGNATURE: + select_x509cert_id(cert.u.x509, &dst->id); + + if (cached_cert) + dst->cert = cert; + else + { + /* check validity of cert */ + valid_until = cert.u.x509->notAfter; + ugh = check_validity(cert.u.x509, &valid_until); + if (ugh != NULL) + { + plog(" %s", ugh); + free_x509cert(cert.u.x509); + break; + } + + DBG(DBG_CONTROL, + DBG_log("certificate is valid") + ) + add_x509_public_key(cert.u.x509, valid_until, DAL_LOCAL); + dst->cert.type = cert.type; + dst->cert.u.x509 = add_x509cert(cert.u.x509); + } + /* if no CA is defined, use issuer as default */ + if (dst->ca.ptr == NULL) + dst->ca = dst->cert.u.x509->issuer; + break; + default: + break; } - DBG(DBG_CONTROL, - DBG_log("certificate is valid") - ) - add_x509_public_key(cert.u.x509, valid_until, DAL_LOCAL); - dst->cert.type = cert.type; - dst->cert.u.x509 = add_x509cert(cert.u.x509); - } - /* if no CA is defined, use issuer as default */ - if (dst->ca.ptr == NULL) - dst->ca = dst->cert.u.x509->issuer; - break; - default: - break; + /* cache the certificate that was last retrieved from the smartcard */ + if (dst->sc != NULL) + { + if (!same_cert(&dst->sc->last_cert, &dst->cert)) + { + lock_certs_and_keys("load_end_certificates"); + release_cert(dst->sc->last_cert); + dst->sc->last_cert = dst->cert; + share_cert(dst->cert); + unlock_certs_and_keys("load_end_certificates"); + } + time(&dst->sc->last_load); + } } - - /* cache the certificate that was last retrieved from the smartcard */ - if (dst->sc != NULL) - { - if (!same_cert(&dst->sc->last_cert, &dst->cert)) - { - lock_certs_and_keys("load_end_certificates"); - release_cert(dst->sc->last_cert); - dst->sc->last_cert = dst->cert; - share_cert(dst->cert); - unlock_certs_and_keys("load_end_certificates"); - } - time(&dst->sc->last_load); - } - } } static bool extract_end(struct end *dst, const whack_end_t *src, const char *which) { - bool same_ca = FALSE; + bool same_ca = FALSE; - /* decode id, if any */ - if (src->id == NULL) - { - dst->id.kind = ID_NONE; - } - else - { - err_t ugh = atoid(src->id, &dst->id, TRUE); - - if (ugh != NULL) + /* decode id, if any */ + if (src->id == NULL) { - loglog(RC_BADID, "bad %s --id: %s (ignored)", which, ugh); - dst->id = empty_id; /* ignore bad one */ + dst->id.kind = ID_NONE; } - } - - dst->ca = chunk_empty; - - /* decode CA distinguished name, if any */ - if (src->ca != NULL) - { - if streq(src->ca, "%same") - same_ca = TRUE; - else if (!streq(src->ca, "%any")) - { - err_t ugh; - - dst->ca.ptr = temporary_cyclic_buffer(); - ugh = atodn(src->ca, &dst->ca); - if (ugh != NULL) - { - plog("bad CA string '%s': %s (ignored)", src->ca, ugh); - dst->ca = chunk_empty; - } - } - } - - /* load local end certificate and extract ID, if any */ - load_end_certificate(src->cert, dst); - - /* does id has wildcards? */ - dst->has_id_wildcards = id_count_wildcards(&dst->id) > 0; - - /* decode group attributes, if any */ - decode_groups(src->groups, &dst->groups); - - /* the rest is simple copying of corresponding fields */ - dst->host_addr = src->host_addr; - dst->host_nexthop = src->host_nexthop; - dst->host_srcip = src->host_srcip; - dst->has_natip = src->has_natip; - dst->client = src->client; - dst->protocol = src->protocol; - dst->port = src->port; - dst->has_port_wildcard = src->has_port_wildcard; - dst->key_from_DNS_on_demand = src->key_from_DNS_on_demand; - dst->has_client = src->has_client; - dst->has_client_wildcard = src->has_client_wildcard; - dst->modecfg = src->modecfg; - dst->hostaccess = src->hostaccess; - dst->allow_any = src->allow_any; - dst->sendcert = src->sendcert; - dst->updown = src->updown; - dst->host_port = src->host_port; - - /* if host sourceip is defined but no client is present - * behind the host then set client to sourceip/32 - */ - if (addrbytesptr(&dst->host_srcip, NULL) - && !isanyaddr(&dst->host_srcip) - && !dst->has_natip - && !dst->has_client) - { - err_t ugh = addrtosubnet(&dst->host_srcip, &dst->client); - - if (ugh != NULL) - plog("could not assign host sourceip to client subnet"); else - dst->has_client = TRUE; - } - return same_ca; + { + err_t ugh = atoid(src->id, &dst->id, TRUE); + + if (ugh != NULL) + { + loglog(RC_BADID, "bad %s --id: %s (ignored)", which, ugh); + dst->id = empty_id; /* ignore bad one */ + } + } + + dst->ca = chunk_empty; + + /* decode CA distinguished name, if any */ + if (src->ca != NULL) + { + if streq(src->ca, "%same") + same_ca = TRUE; + else if (!streq(src->ca, "%any")) + { + err_t ugh; + + dst->ca.ptr = temporary_cyclic_buffer(); + ugh = atodn(src->ca, &dst->ca); + if (ugh != NULL) + { + plog("bad CA string '%s': %s (ignored)", src->ca, ugh); + dst->ca = chunk_empty; + } + } + } + + /* load local end certificate and extract ID, if any */ + load_end_certificate(src->cert, dst); + + /* does id has wildcards? */ + dst->has_id_wildcards = id_count_wildcards(&dst->id) > 0; + + /* decode group attributes, if any */ + decode_groups(src->groups, &dst->groups); + + /* the rest is simple copying of corresponding fields */ + dst->host_addr = src->host_addr; + dst->host_nexthop = src->host_nexthop; + dst->host_srcip = src->host_srcip; + dst->has_natip = src->has_natip; + dst->client = src->client; + dst->protocol = src->protocol; + dst->port = src->port; + dst->has_port_wildcard = src->has_port_wildcard; + dst->key_from_DNS_on_demand = src->key_from_DNS_on_demand; + dst->has_client = src->has_client; + dst->has_client_wildcard = src->has_client_wildcard; + dst->modecfg = src->modecfg; + dst->hostaccess = src->hostaccess; + dst->allow_any = src->allow_any; + dst->sendcert = src->sendcert; + dst->updown = src->updown; + dst->host_port = src->host_port; + + /* if host sourceip is defined but no client is present + * behind the host then set client to sourceip/32 + */ + if (addrbytesptr(&dst->host_srcip, NULL) + && !isanyaddr(&dst->host_srcip) + && !dst->has_natip + && !dst->has_client) + { + err_t ugh = addrtosubnet(&dst->host_srcip, &dst->client); + + if (ugh != NULL) + plog("could not assign host sourceip to client subnet"); + else + dst->has_client = TRUE; + } + return same_ca; } static bool check_connection_end(const whack_end_t *this, const whack_end_t *that , const whack_message_t *wm) { - if (wm->addr_family != addrtypeof(&this->host_addr) - || wm->addr_family != addrtypeof(&this->host_nexthop) - || (this->has_client? wm->tunnel_addr_family : wm->addr_family) - != subnettypeof(&this->client) - || subnettypeof(&this->client) != subnettypeof(&that->client)) - { - /* this should have been diagnosed by whack, so we need not be clear - * !!! overloaded use of RC_CLASH - */ - loglog(RC_CLASH, "address family inconsistency in connection"); - return FALSE; - } - - if (isanyaddr(&that->host_addr)) - { - /* other side is wildcard: we must check if other conditions met */ - if (isanyaddr(&this->host_addr)) + if (wm->addr_family != addrtypeof(&this->host_addr) + || wm->addr_family != addrtypeof(&this->host_nexthop) + || (this->has_client? wm->tunnel_addr_family : wm->addr_family) + != subnettypeof(&this->client) + || subnettypeof(&this->client) != subnettypeof(&that->client)) { - loglog(RC_ORIENT, "connection must specify host IP address for our side"); - return FALSE; + /* this should have been diagnosed by whack, so we need not be clear + * !!! overloaded use of RC_CLASH + */ + loglog(RC_CLASH, "address family inconsistency in connection"); + return FALSE; } - } - if (this->virt && (!isanyaddr(&this->host_addr) || this->has_client)) - { - loglog(RC_CLASH, - "virtual IP must only be used with %%any and without client"); - return FALSE; - } + if (isanyaddr(&that->host_addr)) + { + /* other side is wildcard: we must check if other conditions met */ + if (isanyaddr(&this->host_addr)) + { + loglog(RC_ORIENT, "connection must specify host IP address for our side"); + return FALSE; + } + } - return TRUE; /* happy */ + if (this->virt && (!isanyaddr(&this->host_addr) || this->has_client)) + { + loglog(RC_CLASH, + "virtual IP must only be used with %%any and without client"); + return FALSE; + } + + return TRUE; /* happy */ } struct connection * find_connection_by_reqid(uint32_t reqid) { - struct connection *c; + struct connection *c; - reqid &= ~3; - for (c = connections; c != NULL; c = c->ac_next) - { - if (c->spd.reqid == reqid) - return c; - } + reqid &= ~3; + for (c = connections; c != NULL; c = c->ac_next) + { + if (c->spd.reqid == reqid) + return c; + } - return NULL; + return NULL; } static uint32_t gen_reqid(void) { - uint32_t start; - static uint32_t reqid = IPSEC_MANUAL_REQID_MAX & ~3; + uint32_t start; + static uint32_t reqid = IPSEC_MANUAL_REQID_MAX & ~3; - start = reqid; - do { - reqid += 4; - if (reqid == 0) - reqid = (IPSEC_MANUAL_REQID_MAX & ~3) + 4; - if (!find_connection_by_reqid(reqid)) - return reqid; - } while (reqid != start); + start = reqid; + do { + reqid += 4; + if (reqid == 0) + reqid = (IPSEC_MANUAL_REQID_MAX & ~3) + 4; + if (!find_connection_by_reqid(reqid)) + return reqid; + } while (reqid != start); - exit_log("unable to allocate reqid"); - return 0; /* never reached ... */ + exit_log("unable to allocate reqid"); + return 0; /* never reached ... */ } void add_connection(const whack_message_t *wm) { - if (con_by_name(wm->name, FALSE) != NULL) - { - loglog(RC_DUPNAME, "attempt to redefine connection \"%s\"", wm->name); - } - else if (wm->right.protocol != wm->left.protocol) - { - /* this should haven been diagnosed by whack - * !!! overloaded use of RC_CLASH - */ - loglog(RC_CLASH, "the protocol must be the same for leftport and rightport"); - } - else if (check_connection_end(&wm->right, &wm->left, wm) - && check_connection_end(&wm->left, &wm->right, wm)) - { - bool same_rightca, same_leftca; - struct connection *c = malloc_thing(struct connection); - - zero(c); - c->name = wm->name; - c->ikev1 = wm->ikev1; - c->policy = wm->policy; - - if ((c->policy & POLICY_COMPRESS) && !can_do_IPcomp) - loglog(RC_COMMENT - , "ignoring --compress in \"%s\" because KLIPS is not configured to do IPCOMP" - , c->name); - - if (wm->esp) + if (con_by_name(wm->name, FALSE) != NULL) { - const char *ugh; - - DBG(DBG_CONTROL, - DBG_log("from whack: got --esp=%s", wm->esp ? wm->esp: "NULL") - ) - c->alg_info_esp= alg_info_esp_create_from_str(wm->esp? wm->esp : "", &ugh); - - DBG(DBG_CRYPT|DBG_CONTROL, - static char buf[256]=""; - - if (c->alg_info_esp) - alg_info_snprint(buf, sizeof(buf) - ,(struct alg_info *)c->alg_info_esp); - DBG_log("esp string values: %s", buf); - ) - if (c->alg_info_esp) - { - if (c->alg_info_esp->alg_info_cnt==0) - loglog(RC_LOG_SERIOUS - , "got 0 transforms for esp=\"%s\"", wm->esp); - } - else - { - loglog(RC_LOG_SERIOUS - , "esp string error: %s", ugh? ugh : "Unknown"); - } + loglog(RC_DUPNAME, "attempt to redefine connection \"%s\"", wm->name); } - - if (wm->ike) + else if (wm->right.protocol != wm->left.protocol) { - const char *ugh; - - DBG(DBG_CONTROL, - DBG_log("from whack: got --ike=%s", wm->ike ? wm->ike: "NULL") - ) - c->alg_info_ike= alg_info_ike_create_from_str(wm->ike? wm->ike : "", &ugh); - - DBG(DBG_CRYPT|DBG_CONTROL, - static char buf[256]=""; - - if (c->alg_info_ike) - alg_info_snprint(buf, sizeof(buf) - , (struct alg_info *)c->alg_info_ike); - DBG_log("ike string values: %s", buf); - ) - if (c->alg_info_ike) - { - if (c->alg_info_ike->alg_info_cnt==0) - loglog(RC_LOG_SERIOUS - , "got 0 transforms for ike=\"%s\"", wm->ike); - } - else - { - loglog(RC_LOG_SERIOUS - , "ike string error: %s", ugh? ugh : "Unknown"); - } + /* this should haven been diagnosed by whack + * !!! overloaded use of RC_CLASH + */ + loglog(RC_CLASH, "the protocol must be the same for leftport and rightport"); } - - c->sa_ike_life_seconds = wm->sa_ike_life_seconds; - c->sa_ipsec_life_seconds = wm->sa_ipsec_life_seconds; - c->sa_rekey_margin = wm->sa_rekey_margin; - c->sa_rekey_fuzz = wm->sa_rekey_fuzz; - c->sa_keying_tries = wm->sa_keying_tries; - - /* RFC 3706 DPD */ - c->dpd_delay = wm->dpd_delay; - c->dpd_timeout = wm->dpd_timeout; - c->dpd_action = wm->dpd_action; - - c->addr_family = wm->addr_family; - c->tunnel_addr_family = wm->tunnel_addr_family; - - c->requested_ca = NULL; - - same_leftca = extract_end(&c->spd.this, &wm->left, "left"); - same_rightca = extract_end(&c->spd.that, &wm->right, "right"); - - if (same_rightca) - c->spd.that.ca = c->spd.this.ca; - else if (same_leftca) - c->spd.this.ca = c->spd.that.ca; - - default_end(&c->spd.this, &c->spd.that.host_addr); - default_end(&c->spd.that, &c->spd.this.host_addr); - - /* force any wildcard host IP address, any wildcard subnet - * or any wildcard ID to that end - */ - if (isanyaddr(&c->spd.this.host_addr) || c->spd.this.has_client_wildcard - || c->spd.this.has_port_wildcard || c->spd.this.has_id_wildcards - || c->spd.this.allow_any) + else if (check_connection_end(&wm->right, &wm->left, wm) + && check_connection_end(&wm->left, &wm->right, wm)) { - struct end t = c->spd.this; + bool same_rightca, same_leftca; + struct connection *c = malloc_thing(struct connection); - c->spd.this = c->spd.that; - c->spd.that = t; - } + zero(c); + c->name = wm->name; + c->ikev1 = wm->ikev1; + c->policy = wm->policy; - c->spd.next = NULL; - c->spd.reqid = gen_reqid(); + if ((c->policy & POLICY_COMPRESS) && !can_do_IPcomp) + loglog(RC_COMMENT + , "ignoring --compress in \"%s\" because KLIPS is not configured to do IPCOMP" + , c->name); - /* set internal fields */ - c->instance_serial = 0; - c->ac_next = connections; - connections = c; - c->interface = NULL; - c->spd.routing = RT_UNROUTED; - c->newest_isakmp_sa = SOS_NOBODY; - c->newest_ipsec_sa = SOS_NOBODY; - c->spd.eroute_owner = SOS_NOBODY; + if (wm->esp) + { + const char *ugh; - if (c->policy & POLICY_GROUP) - { - c->kind = CK_GROUP; - add_group(c); - } - else if ((isanyaddr(&c->spd.that.host_addr) && !NEVER_NEGOTIATE(c->policy)) - || c->spd.that.has_client_wildcard || c->spd.that.has_port_wildcard - || c->spd.that.has_id_wildcards || c->spd.that.allow_any) - { - /* Opportunistic or Road Warrior or wildcard client subnet - * or wildcard ID */ - c->kind = CK_TEMPLATE; - } - else - { - c->kind = CK_PERMANENT; - } - set_policy_prio(c); /* must be after kind is set */ + DBG(DBG_CONTROL, + DBG_log("from whack: got --esp=%s", wm->esp ? wm->esp: "NULL") + ) + c->alg_info_esp= alg_info_esp_create_from_str(wm->esp? wm->esp : "", &ugh); + + DBG(DBG_CRYPT|DBG_CONTROL, + static char buf[256]=""; + + if (c->alg_info_esp) + alg_info_snprint(buf, sizeof(buf) + ,(struct alg_info *)c->alg_info_esp); + DBG_log("esp string values: %s", buf); + ) + if (c->alg_info_esp) + { + if (c->alg_info_esp->alg_info_cnt==0) + loglog(RC_LOG_SERIOUS + , "got 0 transforms for esp=\"%s\"", wm->esp); + } + else + { + loglog(RC_LOG_SERIOUS + , "esp string error: %s", ugh? ugh : "Unknown"); + } + } + + if (wm->ike) + { + const char *ugh; + + DBG(DBG_CONTROL, + DBG_log("from whack: got --ike=%s", wm->ike ? wm->ike: "NULL") + ) + c->alg_info_ike= alg_info_ike_create_from_str(wm->ike? wm->ike : "", &ugh); + + DBG(DBG_CRYPT|DBG_CONTROL, + static char buf[256]=""; + + if (c->alg_info_ike) + alg_info_snprint(buf, sizeof(buf) + , (struct alg_info *)c->alg_info_ike); + DBG_log("ike string values: %s", buf); + ) + if (c->alg_info_ike) + { + if (c->alg_info_ike->alg_info_cnt==0) + loglog(RC_LOG_SERIOUS + , "got 0 transforms for ike=\"%s\"", wm->ike); + } + else + { + loglog(RC_LOG_SERIOUS + , "ike string error: %s", ugh? ugh : "Unknown"); + } + } + + c->sa_ike_life_seconds = wm->sa_ike_life_seconds; + c->sa_ipsec_life_seconds = wm->sa_ipsec_life_seconds; + c->sa_rekey_margin = wm->sa_rekey_margin; + c->sa_rekey_fuzz = wm->sa_rekey_fuzz; + c->sa_keying_tries = wm->sa_keying_tries; + + /* RFC 3706 DPD */ + c->dpd_delay = wm->dpd_delay; + c->dpd_timeout = wm->dpd_timeout; + c->dpd_action = wm->dpd_action; + + c->addr_family = wm->addr_family; + c->tunnel_addr_family = wm->tunnel_addr_family; + + c->requested_ca = NULL; + + same_leftca = extract_end(&c->spd.this, &wm->left, "left"); + same_rightca = extract_end(&c->spd.that, &wm->right, "right"); + + if (same_rightca) + c->spd.that.ca = c->spd.this.ca; + else if (same_leftca) + c->spd.this.ca = c->spd.that.ca; + + default_end(&c->spd.this, &c->spd.that.host_addr); + default_end(&c->spd.that, &c->spd.this.host_addr); + + /* force any wildcard host IP address, any wildcard subnet + * or any wildcard ID to that end + */ + if (isanyaddr(&c->spd.this.host_addr) || c->spd.this.has_client_wildcard + || c->spd.this.has_port_wildcard || c->spd.this.has_id_wildcards + || c->spd.this.allow_any) + { + struct end t = c->spd.this; + + c->spd.this = c->spd.that; + c->spd.that = t; + } + + c->spd.next = NULL; + c->spd.reqid = gen_reqid(); + + /* set internal fields */ + c->instance_serial = 0; + c->ac_next = connections; + connections = c; + c->interface = NULL; + c->spd.routing = RT_UNROUTED; + c->newest_isakmp_sa = SOS_NOBODY; + c->newest_ipsec_sa = SOS_NOBODY; + c->spd.eroute_owner = SOS_NOBODY; + + if (c->policy & POLICY_GROUP) + { + c->kind = CK_GROUP; + add_group(c); + } + else if ((isanyaddr(&c->spd.that.host_addr) && !NEVER_NEGOTIATE(c->policy)) + || c->spd.that.has_client_wildcard || c->spd.that.has_port_wildcard + || c->spd.that.has_id_wildcards || c->spd.that.allow_any) + { + /* Opportunistic or Road Warrior or wildcard client subnet + * or wildcard ID */ + c->kind = CK_TEMPLATE; + } + else + { + c->kind = CK_PERMANENT; + } + set_policy_prio(c); /* must be after kind is set */ #ifdef DEBUG - c->extra_debugging = wm->debugging; + c->extra_debugging = wm->debugging; #endif - c->gw_info = NULL; + c->gw_info = NULL; - passert(!(wm->left.virt && wm->right.virt)); - if (wm->left.virt || wm->right.virt) - { - passert(isanyaddr(&c->spd.that.host_addr)); - c->spd.that.virt = create_virtual(c, - wm->left.virt ? wm->left.virt : wm->right.virt); - if (c->spd.that.virt) - c->spd.that.has_client = TRUE; + passert(!(wm->left.virt && wm->right.virt)); + if (wm->left.virt || wm->right.virt) + { + passert(isanyaddr(&c->spd.that.host_addr)); + c->spd.that.virt = create_virtual(c, + wm->left.virt ? wm->left.virt : wm->right.virt); + if (c->spd.that.virt) + c->spd.that.has_client = TRUE; + } + + unshare_connection_strings(c); + (void)orient(c); + + if (c->ikev1) + connect_to_host_pair(c); + + /* log all about this connection */ + plog("added connection description \"%s\"", c->name); + DBG(DBG_CONTROL, + char topo[CONNECTION_BUF]; + + (void) format_connection(topo, sizeof(topo), c, &c->spd); + + DBG_log("%s", topo); + + /* Make sure that address families can be correctly inferred + * from printed ends. + */ + passert(c->addr_family == addrtypeof(&c->spd.this.host_addr) + && c->addr_family == addrtypeof(&c->spd.this.host_nexthop) + && (c->spd.this.has_client? c->tunnel_addr_family : c->addr_family) + == subnettypeof(&c->spd.this.client) + + && c->addr_family == addrtypeof(&c->spd.that.host_addr) + && c->addr_family == addrtypeof(&c->spd.that.host_nexthop) + && (c->spd.that.has_client? c->tunnel_addr_family : c->addr_family) + == subnettypeof(&c->spd.that.client)); + + DBG_log("ike_life: %lus; ipsec_life: %lus; rekey_margin: %lus;" + " rekey_fuzz: %lu%%; keyingtries: %lu; policy: %s" + , (unsigned long) c->sa_ike_life_seconds + , (unsigned long) c->sa_ipsec_life_seconds + , (unsigned long) c->sa_rekey_margin + , (unsigned long) c->sa_rekey_fuzz + , (unsigned long) c->sa_keying_tries + , prettypolicy(c->policy)); + ); } - - unshare_connection_strings(c); - (void)orient(c); - - if (c->ikev1) - connect_to_host_pair(c); - - /* log all about this connection */ - plog("added connection description \"%s\"", c->name); - DBG(DBG_CONTROL, - char topo[CONNECTION_BUF]; - - (void) format_connection(topo, sizeof(topo), c, &c->spd); - - DBG_log("%s", topo); - - /* Make sure that address families can be correctly inferred - * from printed ends. - */ - passert(c->addr_family == addrtypeof(&c->spd.this.host_addr) - && c->addr_family == addrtypeof(&c->spd.this.host_nexthop) - && (c->spd.this.has_client? c->tunnel_addr_family : c->addr_family) - == subnettypeof(&c->spd.this.client) - - && c->addr_family == addrtypeof(&c->spd.that.host_addr) - && c->addr_family == addrtypeof(&c->spd.that.host_nexthop) - && (c->spd.that.has_client? c->tunnel_addr_family : c->addr_family) - == subnettypeof(&c->spd.that.client)); - - DBG_log("ike_life: %lus; ipsec_life: %lus; rekey_margin: %lus;" - " rekey_fuzz: %lu%%; keyingtries: %lu; policy: %s" - , (unsigned long) c->sa_ike_life_seconds - , (unsigned long) c->sa_ipsec_life_seconds - , (unsigned long) c->sa_rekey_margin - , (unsigned long) c->sa_rekey_fuzz - , (unsigned long) c->sa_keying_tries - , prettypolicy(c->policy)); - ); - } } /* Derive a template connection from a group connection and target. @@ -1182,62 +1182,62 @@ add_connection(const whack_message_t *wm) char * add_group_instance(struct connection *group, const ip_subnet *target) { - char namebuf[100] - , targetbuf[SUBNETTOT_BUF]; - struct connection *t; - char *name = NULL; + char namebuf[100] + , targetbuf[SUBNETTOT_BUF]; + struct connection *t; + char *name = NULL; - passert(group->kind == CK_GROUP); - passert(oriented(*group)); + passert(group->kind == CK_GROUP); + passert(oriented(*group)); - /* manufacture a unique name for this template */ - subnettot(target, 0, targetbuf, sizeof(targetbuf)); - snprintf(namebuf, sizeof(namebuf), "%s#%s", group->name, targetbuf); + /* manufacture a unique name for this template */ + subnettot(target, 0, targetbuf, sizeof(targetbuf)); + snprintf(namebuf, sizeof(namebuf), "%s#%s", group->name, targetbuf); - if (con_by_name(namebuf, FALSE) != NULL) - { - loglog(RC_DUPNAME, "group name + target yields duplicate name \"%s\"" - , namebuf); - } - else - { - t = clone_thing(*group); - t->name = namebuf; - unshare_connection_strings(t); - name = clone_str(t->name); - t->spd.that.client = *target; - t->policy &= ~(POLICY_GROUP | POLICY_GROUTED); - t->kind = isanyaddr(&t->spd.that.host_addr) && !NEVER_NEGOTIATE(t->policy) - ? CK_TEMPLATE : CK_INSTANCE; - - /* reset log file info */ - t->log_file_name = NULL; - t->log_file = NULL; - t->log_file_err = FALSE; - - t->spd.reqid = gen_reqid(); - - if (t->spd.that.virt) + if (con_by_name(namebuf, FALSE) != NULL) { - DBG_log("virtual_ip not supported in group instance"); - t->spd.that.virt = NULL; + loglog(RC_DUPNAME, "group name + target yields duplicate name \"%s\"" + , namebuf); } - - /* add to connections list */ - t->ac_next = connections; - connections = t; - - /* same host_pair as parent: stick after parent on list */ - group->hp_next = t; - - /* route if group is routed */ - if (group->policy & POLICY_GROUTED) + else { - if (!trap_connection(t)) - whack_log(RC_ROUTE, "could not route"); + t = clone_thing(*group); + t->name = namebuf; + unshare_connection_strings(t); + name = clone_str(t->name); + t->spd.that.client = *target; + t->policy &= ~(POLICY_GROUP | POLICY_GROUTED); + t->kind = isanyaddr(&t->spd.that.host_addr) && !NEVER_NEGOTIATE(t->policy) + ? CK_TEMPLATE : CK_INSTANCE; + + /* reset log file info */ + t->log_file_name = NULL; + t->log_file = NULL; + t->log_file_err = FALSE; + + t->spd.reqid = gen_reqid(); + + if (t->spd.that.virt) + { + DBG_log("virtual_ip not supported in group instance"); + t->spd.that.virt = NULL; + } + + /* add to connections list */ + t->ac_next = connections; + connections = t; + + /* same host_pair as parent: stick after parent on list */ + group->hp_next = t; + + /* route if group is routed */ + if (group->policy & POLICY_GROUTED) + { + if (!trap_connection(t)) + whack_log(RC_ROUTE, "could not route"); + } } - } - return name; + return name; } /* an old target has disappeared for a group: delete instance */ @@ -1245,10 +1245,10 @@ void remove_group_instance(const struct connection *group USED_BY_DEBUG , const char *name) { - passert(group->kind == CK_GROUP); - passert(oriented(*group)); + passert(group->kind == CK_GROUP); + passert(oriented(*group)); - delete_connections_by_name(name, FALSE); + delete_connections_by_name(name, FALSE); } /* Common part of instantiating a Road Warrior or Opportunistic connection. @@ -1266,90 +1266,90 @@ instantiate(struct connection *c, const ip_address *him , u_int16_t his_port , const struct id *his_id) { - struct connection *d; - int wildcards; + struct connection *d; + int wildcards; - passert(c->kind == CK_TEMPLATE); - passert(c->spd.next == NULL); + passert(c->kind == CK_TEMPLATE); + passert(c->spd.next == NULL); - c->instance_serial++; - d = clone_thing(*c); - d->spd.that.allow_any = FALSE; + c->instance_serial++; + d = clone_thing(*c); + d->spd.that.allow_any = FALSE; - if (his_id != NULL) - { - passert(match_id(his_id, &d->spd.that.id, &wildcards)); - d->spd.that.id = *his_id; - d->spd.that.has_id_wildcards = FALSE; - } - unshare_connection_strings(d); - unshare_ietfAttrList(&d->spd.this.groups); - unshare_ietfAttrList(&d->spd.that.groups); - d->kind = CK_INSTANCE; + if (his_id != NULL) + { + passert(match_id(his_id, &d->spd.that.id, &wildcards)); + d->spd.that.id = *his_id; + d->spd.that.has_id_wildcards = FALSE; + } + unshare_connection_strings(d); + unshare_ietfAttrList(&d->spd.this.groups); + unshare_ietfAttrList(&d->spd.that.groups); + d->kind = CK_INSTANCE; - passert(oriented(*d)); - d->spd.that.host_addr = *him; - setportof(htons(c->spd.that.port), &d->spd.that.host_addr); + passert(oriented(*d)); + d->spd.that.host_addr = *him; + setportof(htons(c->spd.that.port), &d->spd.that.host_addr); - if (his_port) d->spd.that.host_port = his_port; + if (his_port) d->spd.that.host_port = his_port; - default_end(&d->spd.that, &d->spd.this.host_addr); + default_end(&d->spd.that, &d->spd.this.host_addr); - /* We cannot guess what our next_hop should be, but if it was - * explicitly specified as 0.0.0.0, we set it to be him. - * (whack will not allow nexthop to be elided in RW case.) - */ - default_end(&d->spd.this, &d->spd.that.host_addr); - d->spd.next = NULL; - d->spd.reqid = gen_reqid(); + /* We cannot guess what our next_hop should be, but if it was + * explicitly specified as 0.0.0.0, we set it to be him. + * (whack will not allow nexthop to be elided in RW case.) + */ + default_end(&d->spd.this, &d->spd.that.host_addr); + d->spd.next = NULL; + d->spd.reqid = gen_reqid(); - /* set internal fields */ - d->ac_next = connections; - connections = d; - d->spd.routing = RT_UNROUTED; - d->newest_isakmp_sa = SOS_NOBODY; - d->newest_ipsec_sa = SOS_NOBODY; - d->spd.eroute_owner = SOS_NOBODY; + /* set internal fields */ + d->ac_next = connections; + connections = d; + d->spd.routing = RT_UNROUTED; + d->newest_isakmp_sa = SOS_NOBODY; + d->newest_ipsec_sa = SOS_NOBODY; + d->spd.eroute_owner = SOS_NOBODY; - /* reset log file info */ - d->log_file_name = NULL; - d->log_file = NULL; - d->log_file_err = FALSE; + /* reset log file info */ + d->log_file_name = NULL; + d->log_file = NULL; + d->log_file_err = FALSE; - connect_to_host_pair(d); + connect_to_host_pair(d); - return d; - if (sameaddr(&d->spd.that.host_addr, &d->spd.this.host_nexthop)) - { - d->spd.this.host_nexthop = *him; - } + return d; + if (sameaddr(&d->spd.that.host_addr, &d->spd.this.host_nexthop)) + { + d->spd.this.host_nexthop = *him; + } } struct connection * rw_instantiate(struct connection *c, const ip_address *him, u_int16_t his_port , const ip_subnet *his_net, const struct id *his_id) { - struct connection *d = instantiate(c, him, his_port, his_id); + struct connection *d = instantiate(c, him, his_port, his_id); - if (d && his_net && is_virtual_connection(c)) - { - d->spd.that.client = *his_net; - d->spd.that.virt = NULL; - if (subnetishost(his_net) && addrinsubnet(him, his_net)) - d->spd.that.has_client = FALSE; - } + if (d && his_net && is_virtual_connection(c)) + { + d->spd.that.client = *his_net; + d->spd.that.virt = NULL; + if (subnetishost(his_net) && addrinsubnet(him, his_net)) + d->spd.that.has_client = FALSE; + } - if (d->policy & POLICY_OPPO) - { - /* This must be before we know the client addresses. - * Fill in one that is impossible. This prevents anyone else from - * trying to use this connection to get to a particular client - */ - d->spd.that.client = *aftoinfo(subnettypeof(&d->spd.that.client))->none; - } - DBG(DBG_CONTROL - , DBG_log("instantiated \"%s\" for %s" , d->name, ip_str(him))); - return d; + if (d->policy & POLICY_OPPO) + { + /* This must be before we know the client addresses. + * Fill in one that is impossible. This prevents anyone else from + * trying to use this connection to get to a particular client + */ + d->spd.that.client = *aftoinfo(subnettypeof(&d->spd.that.client))->none; + } + DBG(DBG_CONTROL + , DBG_log("instantiated \"%s\" for %s" , d->name, ip_str(him))); + return d; } struct connection * @@ -1360,77 +1360,77 @@ oppo_instantiate(struct connection *c , const ip_address *our_client USED_BY_DEBUG , const ip_address *peer_client) { - struct connection *d = instantiate(c, him, 0, his_id); + struct connection *d = instantiate(c, him, 0, his_id); - passert(d->spd.next == NULL); + passert(d->spd.next == NULL); - /* fill in our client side */ - if (d->spd.this.has_client) - { - /* there was a client in the abstract connection - * so we demand that the required client is within that subnet. + /* fill in our client side */ + if (d->spd.this.has_client) + { + /* there was a client in the abstract connection + * so we demand that the required client is within that subnet. + */ + passert(addrinsubnet(our_client, &d->spd.this.client)); + happy(addrtosubnet(our_client, &d->spd.this.client)); + /* opportunistic connections do not use port selectors */ + setportof(0, &d->spd.this.client.addr); + } + else + { + /* there was no client in the abstract connection + * so we demand that the required client be the host + */ + passert(sameaddr(our_client, &d->spd.this.host_addr)); + } + + /* fill in peer's client side. + * If the client is the peer, excise the client from the connection. */ - passert(addrinsubnet(our_client, &d->spd.this.client)); - happy(addrtosubnet(our_client, &d->spd.this.client)); + passert((d->policy & POLICY_OPPO) + && addrinsubnet(peer_client, &d->spd.that.client)); + happy(addrtosubnet(peer_client, &d->spd.that.client)); /* opportunistic connections do not use port selectors */ - setportof(0, &d->spd.this.client.addr); - } - else - { - /* there was no client in the abstract connection - * so we demand that the required client be the host + setportof(0, &d->spd.that.client.addr); + + if (sameaddr(peer_client, &d->spd.that.host_addr)) + d->spd.that.has_client = FALSE; + + passert(d->gw_info == NULL); + gw_addref(gw); + d->gw_info = gw; + + /* Adjust routing if something is eclipsing c. + * It must be a %hold for us (hard to passert this). + * If there was another instance eclipsing, we'd be using it. */ - passert(sameaddr(our_client, &d->spd.this.host_addr)); - } + if (c->spd.routing == RT_ROUTED_ECLIPSED) + d->spd.routing = RT_ROUTED_PROSPECTIVE; - /* fill in peer's client side. - * If the client is the peer, excise the client from the connection. - */ - passert((d->policy & POLICY_OPPO) - && addrinsubnet(peer_client, &d->spd.that.client)); - happy(addrtosubnet(peer_client, &d->spd.that.client)); - /* opportunistic connections do not use port selectors */ - setportof(0, &d->spd.that.client.addr); + /* Remember if the template is routed: + * if so, this instance applies for initiation + * even if it is created for responding. + */ + if (routed(c->spd.routing)) + d->instance_initiation_ok = TRUE; - if (sameaddr(peer_client, &d->spd.that.host_addr)) - d->spd.that.has_client = FALSE; + DBG(DBG_CONTROL, + char topo[CONNECTION_BUF]; - passert(d->gw_info == NULL); - gw_addref(gw); - d->gw_info = gw; - - /* Adjust routing if something is eclipsing c. - * It must be a %hold for us (hard to passert this). - * If there was another instance eclipsing, we'd be using it. - */ - if (c->spd.routing == RT_ROUTED_ECLIPSED) - d->spd.routing = RT_ROUTED_PROSPECTIVE; - - /* Remember if the template is routed: - * if so, this instance applies for initiation - * even if it is created for responding. - */ - if (routed(c->spd.routing)) - d->instance_initiation_ok = TRUE; - - DBG(DBG_CONTROL, - char topo[CONNECTION_BUF]; - - (void) format_connection(topo, sizeof(topo), d, &d->spd); - DBG_log("instantiated \"%s\": %s", d->name, topo); - ); - return d; + (void) format_connection(topo, sizeof(topo), d, &d->spd); + DBG_log("instantiated \"%s\": %s", d->name, topo); + ); + return d; } /* priority formatting */ void fmt_policy_prio(policy_prio_t pp, char buf[POLICY_PRIO_BUF]) { - if (pp == BOTTOM_PRIO) - snprintf(buf, POLICY_PRIO_BUF, "0"); - else - snprintf(buf, POLICY_PRIO_BUF, "%lu,%lu" - , pp>>16, (pp & ~(~(policy_prio_t)0 << 16)) >> 8); + if (pp == BOTTOM_PRIO) + snprintf(buf, POLICY_PRIO_BUF, "0"); + else + snprintf(buf, POLICY_PRIO_BUF, "%lu,%lu" + , pp>>16, (pp & ~(~(policy_prio_t)0 << 16)) >> 8); } /* Format any information needed to identify an instance of a connection. @@ -1441,65 +1441,65 @@ fmt_policy_prio(policy_prio_t pp, char buf[POLICY_PRIO_BUF]) static size_t fmt_client(const ip_subnet *client, const ip_address *gw, const char *prefix, char buf[ADDRTOT_BUF]) { - if (subnetisaddr(client, gw)) - { - buf[0] = '\0'; /* compact denotation for "self" */ - } - else - { - char *ap; - - strcpy(buf, prefix); - ap = buf + strlen(prefix); - if (subnetisnone(client)) - strcpy(ap, "?"); /* unknown */ + if (subnetisaddr(client, gw)) + { + buf[0] = '\0'; /* compact denotation for "self" */ + } else - subnettot(client, 0, ap, SUBNETTOT_BUF); - } - return strlen(buf); + { + char *ap; + + strcpy(buf, prefix); + ap = buf + strlen(prefix); + if (subnetisnone(client)) + strcpy(ap, "?"); /* unknown */ + else + subnettot(client, 0, ap, SUBNETTOT_BUF); + } + return strlen(buf); } void fmt_conn_instance(const struct connection *c, char buf[CONN_INST_BUF]) { - char *p = buf; + char *p = buf; - *p = '\0'; + *p = '\0'; - if (c->kind == CK_INSTANCE) - { - if (c->instance_serial != 0) + if (c->kind == CK_INSTANCE) { - snprintf(p, CONN_INST_BUF, "[%lu]", c->instance_serial); - p += strlen(p); - } + if (c->instance_serial != 0) + { + snprintf(p, CONN_INST_BUF, "[%lu]", c->instance_serial); + p += strlen(p); + } - if (c->policy & POLICY_OPPO) - { - size_t w = fmt_client(&c->spd.this.client, &c->spd.this.host_addr, " ", p); + if (c->policy & POLICY_OPPO) + { + size_t w = fmt_client(&c->spd.this.client, &c->spd.this.host_addr, " ", p); - p += w; + p += w; - strcpy(p, w == 0? " ..." : "=== ..."); - p += strlen(p); + strcpy(p, w == 0? " ..." : "=== ..."); + p += strlen(p); - addrtot(&c->spd.that.host_addr, 0, p, ADDRTOT_BUF); - p += strlen(p); + addrtot(&c->spd.that.host_addr, 0, p, ADDRTOT_BUF); + p += strlen(p); - (void) fmt_client(&c->spd.that.client, &c->spd.that.host_addr, "===", p); - } - else - { - *p++ = ' '; - addrtot(&c->spd.that.host_addr, 0, p, ADDRTOT_BUF); + (void) fmt_client(&c->spd.that.client, &c->spd.that.host_addr, "===", p); + } + else + { + *p++ = ' '; + addrtot(&c->spd.that.host_addr, 0, p, ADDRTOT_BUF); # - if (c->spd.that.host_port != pluto_port) - { - p += strlen(p); - sprintf(p, ":%d", c->spd.that.host_port); - } + if (c->spd.that.host_port != pluto_port) + { + p += strlen(p); + sprintf(p, ":%d", c->spd.that.host_port); + } + } } - } } /* Find an existing connection for a trapped outbound packet. @@ -1519,124 +1519,124 @@ fmt_conn_instance(const struct connection *c, char buf[CONN_INST_BUF]) */ struct connection * find_connection_for_clients(struct spd_route **srp, - const ip_address *our_client, - const ip_address *peer_client, - int transport_proto) + const ip_address *our_client, + const ip_address *peer_client, + int transport_proto) { - struct connection *c = connections, *best = NULL; - policy_prio_t best_prio = BOTTOM_PRIO; - struct spd_route *sr; - struct spd_route *best_sr = NULL; - int our_port = ntohs(portof(our_client)); - int peer_port = ntohs(portof(peer_client)); + struct connection *c = connections, *best = NULL; + policy_prio_t best_prio = BOTTOM_PRIO; + struct spd_route *sr; + struct spd_route *best_sr = NULL; + int our_port = ntohs(portof(our_client)); + int peer_port = ntohs(portof(peer_client)); - passert(!isanyaddr(our_client) && !isanyaddr(peer_client)); + passert(!isanyaddr(our_client) && !isanyaddr(peer_client)); #ifdef DEBUG - if (DBGP(DBG_CONTROL)) - { - char ocb[ADDRTOT_BUF], pcb[ADDRTOT_BUF]; - - addrtot(our_client, 0, ocb, sizeof(ocb)); - addrtot(peer_client, 0, pcb, sizeof(pcb)); - DBG_log("find_connection: " - "looking for policy for connection: %s:%d/%d -> %s:%d/%d" - , ocb, transport_proto, our_port, pcb, transport_proto, peer_port); - } -#endif /* DEBUG */ - - for (c = connections; c != NULL; c = c->ac_next) - { - if (c->kind == CK_GROUP) - continue; - - for (sr = &c->spd; best!=c && sr; sr = sr->next) + if (DBGP(DBG_CONTROL)) { - if ((routed(sr->routing) || c->instance_initiation_ok) - && addrinsubnet(our_client, &sr->this.client) - && addrinsubnet(peer_client, &sr->that.client) - && addrinsubnet(peer_client, &sr->that.client) - && (!sr->this.protocol || transport_proto == sr->this.protocol) - && (!sr->this.port || our_port == sr->this.port) - && (!sr->that.port || peer_port == sr->that.port)) - { - char cib[CONN_INST_BUF]; - char cib2[CONN_INST_BUF]; + char ocb[ADDRTOT_BUF], pcb[ADDRTOT_BUF]; - policy_prio_t prio = 8 * (c->prio + (c->kind == CK_INSTANCE)) - + 2 * (sr->this.port == our_port) - + 2 * (sr->that.port == peer_port) - + (sr->this.protocol == transport_proto); - -#ifdef DEBUG - if (DBGP(DBG_CONTROL|DBG_CONTROLMORE)) - { - char c_ocb[SUBNETTOT_BUF], c_pcb[SUBNETTOT_BUF]; - - subnettot(&c->spd.this.client, 0, c_ocb, sizeof(c_ocb)); - subnettot(&c->spd.that.client, 0, c_pcb, sizeof(c_pcb)); - DBG_log("find_connection: conn \"%s\"%s has compatible peers: %s->%s [pri: %ld]" - , c->name - , (fmt_conn_instance(c, cib), cib) - , c_ocb, c_pcb, prio); - } + addrtot(our_client, 0, ocb, sizeof(ocb)); + addrtot(peer_client, 0, pcb, sizeof(pcb)); + DBG_log("find_connection: " + "looking for policy for connection: %s:%d/%d -> %s:%d/%d" + , ocb, transport_proto, our_port, pcb, transport_proto, peer_port); + } #endif /* DEBUG */ - if (best == NULL) - { - best = c; - best_sr = sr; - best_prio = prio; - } - - DBG(DBG_CONTROLMORE, - DBG_log("find_connection: " - "comparing best \"%s\"%s [pri:%ld]{%p} (child %s) to \"%s\"%s [pri:%ld]{%p} (child %s)" - , best->name - , (fmt_conn_instance(best, cib), cib) - , best_prio - , best - , (best->policy_next ? best->policy_next->name : "none") - , c->name - , (fmt_conn_instance(c, cib2), cib2) - , prio - , c - , (c->policy_next ? c->policy_next->name : "none"))); - - if (prio > best_prio) - { - best = c; - best_sr = sr; - best_prio = prio; - } - } - } - } - - if (best!= NULL && NEVER_NEGOTIATE(best->policy)) - best = NULL; - - if (srp != NULL && best != NULL) - *srp = best_sr; - -#ifdef DEBUG - if (DBGP(DBG_CONTROL)) - { - if (best) + for (c = connections; c != NULL; c = c->ac_next) { - char cib[CONN_INST_BUF]; - DBG_log("find_connection: concluding with \"%s\"%s [pri:%ld]{%p} kind=%s" - , best->name - , (fmt_conn_instance(best, cib), cib) - , best_prio - , best - , enum_name(&connection_kind_names, best->kind)); - } else { - DBG_log("find_connection: concluding with empty"); - } - } + if (c->kind == CK_GROUP) + continue; + + for (sr = &c->spd; best!=c && sr; sr = sr->next) + { + if ((routed(sr->routing) || c->instance_initiation_ok) + && addrinsubnet(our_client, &sr->this.client) + && addrinsubnet(peer_client, &sr->that.client) + && addrinsubnet(peer_client, &sr->that.client) + && (!sr->this.protocol || transport_proto == sr->this.protocol) + && (!sr->this.port || our_port == sr->this.port) + && (!sr->that.port || peer_port == sr->that.port)) + { + char cib[CONN_INST_BUF]; + char cib2[CONN_INST_BUF]; + + policy_prio_t prio = 8 * (c->prio + (c->kind == CK_INSTANCE)) + + 2 * (sr->this.port == our_port) + + 2 * (sr->that.port == peer_port) + + (sr->this.protocol == transport_proto); + +#ifdef DEBUG + if (DBGP(DBG_CONTROL|DBG_CONTROLMORE)) + { + char c_ocb[SUBNETTOT_BUF], c_pcb[SUBNETTOT_BUF]; + + subnettot(&c->spd.this.client, 0, c_ocb, sizeof(c_ocb)); + subnettot(&c->spd.that.client, 0, c_pcb, sizeof(c_pcb)); + DBG_log("find_connection: conn \"%s\"%s has compatible peers: %s->%s [pri: %ld]" + , c->name + , (fmt_conn_instance(c, cib), cib) + , c_ocb, c_pcb, prio); + } #endif /* DEBUG */ - return best; + if (best == NULL) + { + best = c; + best_sr = sr; + best_prio = prio; + } + + DBG(DBG_CONTROLMORE, + DBG_log("find_connection: " + "comparing best \"%s\"%s [pri:%ld]{%p} (child %s) to \"%s\"%s [pri:%ld]{%p} (child %s)" + , best->name + , (fmt_conn_instance(best, cib), cib) + , best_prio + , best + , (best->policy_next ? best->policy_next->name : "none") + , c->name + , (fmt_conn_instance(c, cib2), cib2) + , prio + , c + , (c->policy_next ? c->policy_next->name : "none"))); + + if (prio > best_prio) + { + best = c; + best_sr = sr; + best_prio = prio; + } + } + } + } + + if (best!= NULL && NEVER_NEGOTIATE(best->policy)) + best = NULL; + + if (srp != NULL && best != NULL) + *srp = best_sr; + +#ifdef DEBUG + if (DBGP(DBG_CONTROL)) + { + if (best) + { + char cib[CONN_INST_BUF]; + DBG_log("find_connection: concluding with \"%s\"%s [pri:%ld]{%p} kind=%s" + , best->name + , (fmt_conn_instance(best, cib), cib) + , best_prio + , best + , enum_name(&connection_kind_names, best->kind)); + } else { + DBG_log("find_connection: concluding with empty"); + } + } +#endif /* DEBUG */ + + return best; } /* Find and instantiate a connection for an outgoing Opportunistic connection. @@ -1663,203 +1663,203 @@ find_connection_for_clients(struct spd_route **srp, */ struct connection * build_outgoing_opportunistic_connection(struct gw_info *gw - ,const ip_address *our_client - ,const ip_address *peer_client) + ,const ip_address *our_client + ,const ip_address *peer_client) { - struct iface *p; - struct connection *best = NULL; - struct spd_route *sr, *bestsr; - char ocb[ADDRTOT_BUF], pcb[ADDRTOT_BUF]; + struct iface *p; + struct connection *best = NULL; + struct spd_route *sr, *bestsr; + char ocb[ADDRTOT_BUF], pcb[ADDRTOT_BUF]; - addrtot(our_client, 0, ocb, sizeof(ocb)); - addrtot(peer_client, 0, pcb, sizeof(pcb)); + addrtot(our_client, 0, ocb, sizeof(ocb)); + addrtot(peer_client, 0, pcb, sizeof(pcb)); - passert(!isanyaddr(our_client) && !isanyaddr(peer_client)); + passert(!isanyaddr(our_client) && !isanyaddr(peer_client)); - /* We don't know his ID yet, so gw id must be an ipaddr */ - passert(gw->key != NULL); - passert(id_is_ipaddr(&gw->gw_id)); + /* We don't know his ID yet, so gw id must be an ipaddr */ + passert(gw->key != NULL); + passert(id_is_ipaddr(&gw->gw_id)); - /* for each of our addresses... */ - for (p = interfaces; p != NULL; p = p->next) - { - /* go through those connections with our address and NO_IP as hosts - * We cannot know what port the peer would use, so we assume - * that it is pluto_port (makes debugging easier). - */ - struct connection *c = find_host_pair_connections(&p->addr - , pluto_port, (ip_address *)NULL, pluto_port); - - for (; c != NULL; c = c->hp_next) + /* for each of our addresses... */ + for (p = interfaces; p != NULL; p = p->next) { - DBG(DBG_OPPO, - DBG_log("checking %s", c->name)); - if (c->kind == CK_GROUP) - { - continue; - } + /* go through those connections with our address and NO_IP as hosts + * We cannot know what port the peer would use, so we assume + * that it is pluto_port (makes debugging easier). + */ + struct connection *c = find_host_pair_connections(&p->addr + , pluto_port, (ip_address *)NULL, pluto_port); - for (sr = &c->spd; best!=c && sr; sr = sr->next) - { - if (routed(sr->routing) - && addrinsubnet(our_client, &sr->this.client) - && addrinsubnet(peer_client, &sr->that.client)) + for (; c != NULL; c = c->hp_next) { - if (best == NULL) - { - best = c; - break; - } - - DBG(DBG_OPPO, - DBG_log("comparing best %s to %s" - , best->name, c->name)); - - for (bestsr = &best->spd; best!=c && bestsr; bestsr=bestsr->next) - { - if (!subnetinsubnet(&bestsr->this.client, &sr->this.client) - || (samesubnet(&bestsr->this.client, &sr->this.client) - && !subnetinsubnet(&bestsr->that.client - , &sr->that.client))) + DBG(DBG_OPPO, + DBG_log("checking %s", c->name)); + if (c->kind == CK_GROUP) { - best = c; + continue; } - } - } - } - } - } - if (best == NULL - || NEVER_NEGOTIATE(best->policy) - || (best->policy & POLICY_OPPO) == LEMPTY - || best->kind != CK_TEMPLATE) - return NULL; - else - return oppo_instantiate(best, &gw->gw_id.ip_addr, NULL, gw - , our_client, peer_client); + for (sr = &c->spd; best!=c && sr; sr = sr->next) + { + if (routed(sr->routing) + && addrinsubnet(our_client, &sr->this.client) + && addrinsubnet(peer_client, &sr->that.client)) + { + if (best == NULL) + { + best = c; + break; + } + + DBG(DBG_OPPO, + DBG_log("comparing best %s to %s" + , best->name, c->name)); + + for (bestsr = &best->spd; best!=c && bestsr; bestsr=bestsr->next) + { + if (!subnetinsubnet(&bestsr->this.client, &sr->this.client) + || (samesubnet(&bestsr->this.client, &sr->this.client) + && !subnetinsubnet(&bestsr->that.client + , &sr->that.client))) + { + best = c; + } + } + } + } + } + } + + if (best == NULL + || NEVER_NEGOTIATE(best->policy) + || (best->policy & POLICY_OPPO) == LEMPTY + || best->kind != CK_TEMPLATE) + return NULL; + else + return oppo_instantiate(best, &gw->gw_id.ip_addr, NULL, gw + , our_client, peer_client); } bool orient(struct connection *c) { - struct spd_route *sr; + struct spd_route *sr; - if (!oriented(*c)) - { - struct iface *p; - - for (sr = &c->spd; sr; sr = sr->next) + if (!oriented(*c)) { - /* Note: this loop does not stop when it finds a match: - * it continues checking to catch any ambiguity. - */ - for (p = interfaces; p != NULL; p = p->next) - { - if (p->ike_float) - continue; + struct iface *p; - for (;;) + for (sr = &c->spd; sr; sr = sr->next) { - /* check if this interface matches this end */ - if (sameaddr(&sr->this.host_addr, &p->addr) - && (!no_klips || sr->this.host_port == pluto_port)) - { - if (oriented(*c)) + /* Note: this loop does not stop when it finds a match: + * it continues checking to catch any ambiguity. + */ + for (p = interfaces; p != NULL; p = p->next) { - if (c->interface == p) - loglog(RC_LOG_SERIOUS - , "both sides of \"%s\" are our interface %s!" - , c->name, p->rname); - else - loglog(RC_LOG_SERIOUS, "two interfaces match \"%s\" (%s, %s)" - , c->name, c->interface->rname, p->rname); - c->interface = NULL; /* withdraw orientation */ - return FALSE; + if (p->ike_float) + continue; + + for (;;) + { + /* check if this interface matches this end */ + if (sameaddr(&sr->this.host_addr, &p->addr) + && (!no_klips || sr->this.host_port == pluto_port)) + { + if (oriented(*c)) + { + if (c->interface == p) + loglog(RC_LOG_SERIOUS + , "both sides of \"%s\" are our interface %s!" + , c->name, p->rname); + else + loglog(RC_LOG_SERIOUS, "two interfaces match \"%s\" (%s, %s)" + , c->name, c->interface->rname, p->rname); + c->interface = NULL; /* withdraw orientation */ + return FALSE; + } + c->interface = p; + } + + /* done with this interface if it doesn't match that end */ + if (!(sameaddr(&sr->that.host_addr, &p->addr) + && (!no_klips || sr->that.host_port == pluto_port))) + break; + + /* swap ends and try again. + * It is a little tricky to see that this loop will stop. + * Only continue if the far side matches. + * If both sides match, there is an error-out. + */ + { + struct end t = sr->this; + + sr->this = sr->that; + sr->that = t; + } + } } - c->interface = p; - } - - /* done with this interface if it doesn't match that end */ - if (!(sameaddr(&sr->that.host_addr, &p->addr) - && (!no_klips || sr->that.host_port == pluto_port))) - break; - - /* swap ends and try again. - * It is a little tricky to see that this loop will stop. - * Only continue if the far side matches. - * If both sides match, there is an error-out. - */ - { - struct end t = sr->this; - - sr->this = sr->that; - sr->that = t; - } } - } } - } - return oriented(*c); + return oriented(*c); } void initiate_connection(const char *name, int whackfd) { - struct connection *c = con_by_name(name, TRUE); + struct connection *c = con_by_name(name, TRUE); - if (c != NULL && c->ikev1) - { - set_cur_connection(c); - if (!oriented(*c)) + if (c != NULL && c->ikev1) { - loglog(RC_ORIENT, "we have no ipsecN interface for either end of this connection"); - } - else if (NEVER_NEGOTIATE(c->policy)) - { - loglog(RC_INITSHUNT - , "cannot initiate an authby=never connection"); - } - else if (c->kind != CK_PERMANENT && !c->spd.that.allow_any) - { - if (isanyaddr(&c->spd.that.host_addr)) - loglog(RC_NOPEERIP, "cannot initiate connection without knowing peer IP address"); - else - loglog(RC_WILDCARD, "cannot initiate connection with ID wildcards"); - } - else - { - /* do we have to prompt for a PIN code? */ - if (c->spd.this.sc != NULL && !c->spd.this.sc->valid && whackfd != NULL_FD) - { - scx_get_pin(c->spd.this.sc, whackfd); - } - if (c->spd.this.sc != NULL && !c->spd.this.sc->valid) - { - loglog(RC_NOVALIDPIN, "cannot initiate connection without valid PIN"); - } - else - { - - if (c->spd.that.allow_any) + set_cur_connection(c); + if (!oriented(*c)) { - c = instantiate(c, &c->spd.that.host_addr, c->spd.that.host_port - , &c->spd.that.id); + loglog(RC_ORIENT, "we have no ipsecN interface for either end of this connection"); } + else if (NEVER_NEGOTIATE(c->policy)) + { + loglog(RC_INITSHUNT + , "cannot initiate an authby=never connection"); + } + else if (c->kind != CK_PERMANENT && !c->spd.that.allow_any) + { + if (isanyaddr(&c->spd.that.host_addr)) + loglog(RC_NOPEERIP, "cannot initiate connection without knowing peer IP address"); + else + loglog(RC_WILDCARD, "cannot initiate connection with ID wildcards"); + } + else + { + /* do we have to prompt for a PIN code? */ + if (c->spd.this.sc != NULL && !c->spd.this.sc->valid && whackfd != NULL_FD) + { + scx_get_pin(c->spd.this.sc, whackfd); + } + if (c->spd.this.sc != NULL && !c->spd.this.sc->valid) + { + loglog(RC_NOVALIDPIN, "cannot initiate connection without valid PIN"); + } + else + { - /* We will only request an IPsec SA if policy isn't empty - * (ignoring Main Mode items). - * This is a fudge, but not yet important. - * If we are to proceed asynchronously, whackfd will be NULL_FD. - */ - c->policy |= POLICY_UP; - ipsecdoi_initiate(whackfd, c, c->policy, 1, SOS_NOBODY); - whackfd = NULL_FD; /* protect from close */ - } + if (c->spd.that.allow_any) + { + c = instantiate(c, &c->spd.that.host_addr, c->spd.that.host_port + , &c->spd.that.id); + } + + /* We will only request an IPsec SA if policy isn't empty + * (ignoring Main Mode items). + * This is a fudge, but not yet important. + * If we are to proceed asynchronously, whackfd will be NULL_FD. + */ + c->policy |= POLICY_UP; + ipsecdoi_initiate(whackfd, c, c->policy, 1, SOS_NOBODY); + whackfd = NULL_FD; /* protect from close */ + } + } + reset_cur_connection(); } - reset_cur_connection(); - } - close_any(whackfd); + close_any(whackfd); } /* (Possibly) Opportunistic Initiation: @@ -1873,10 +1873,10 @@ initiate_connection(const char *name, int whackfd) * Most of the code will be restarted if an ADNS request is made * to discover the gateway. The only difference between the first * and second entry is whether gateways_from_dns is NULL or not. - * initiate_opportunistic: initial entrypoint - * continue_oppo: where we pickup when ADNS result arrives - * initiate_opportunistic_body: main body shared by above routines - * cannot_oppo: a helper function to log a diagnostic + * initiate_opportunistic: initial entrypoint + * continue_oppo: where we pickup when ADNS result arrives + * initiate_opportunistic_body: main body shared by above routines + * cannot_oppo: a helper function to log a diagnostic * This structure repeats a lot of code when the ADNS result arrives. * This seems like a waste, but anything learned the first time through * may no longer be true! @@ -1886,174 +1886,174 @@ initiate_connection(const char *name, int whackfd) */ enum find_oppo_step { - fos_start, - fos_myid_ip_txt, - fos_myid_hostname_txt, - fos_myid_ip_key, - fos_myid_hostname_key, - fos_our_client, - fos_our_txt, + fos_start, + fos_myid_ip_txt, + fos_myid_hostname_txt, + fos_myid_ip_key, + fos_myid_hostname_key, + fos_our_client, + fos_our_txt, #ifdef USE_KEYRR - fos_our_key, + fos_our_key, #endif /* USE_KEYRR */ - fos_his_client, - fos_done + fos_his_client, + fos_done }; #ifdef DEBUG static const char *const oppo_step_name[] = { - "fos_start", - "fos_myid_ip_txt", - "fos_myid_hostname_txt", - "fos_myid_ip_key", - "fos_myid_hostname_key", - "fos_our_client", - "fos_our_txt", + "fos_start", + "fos_myid_ip_txt", + "fos_myid_hostname_txt", + "fos_myid_ip_key", + "fos_myid_hostname_key", + "fos_our_client", + "fos_our_txt", #ifdef USE_KEYRR - "fos_our_key", + "fos_our_key", #endif /* USE_KEYRR */ - "fos_his_client", - "fos_done" + "fos_his_client", + "fos_done" }; #endif /* DEBUG */ struct find_oppo_bundle { - enum find_oppo_step step; - err_t want; - bool failure_ok; /* if true, continue_oppo should not die on DNS failure */ - ip_address our_client; /* not pointer! */ - ip_address peer_client; - int transport_proto; - bool held; - policy_prio_t policy_prio; - ipsec_spi_t failure_shunt; /* in host order! 0 for delete. */ - int whackfd; + enum find_oppo_step step; + err_t want; + bool failure_ok; /* if true, continue_oppo should not die on DNS failure */ + ip_address our_client; /* not pointer! */ + ip_address peer_client; + int transport_proto; + bool held; + policy_prio_t policy_prio; + ipsec_spi_t failure_shunt; /* in host order! 0 for delete. */ + int whackfd; }; struct find_oppo_continuation { - struct adns_continuation ac; /* common prefix */ - struct find_oppo_bundle b; + struct adns_continuation ac; /* common prefix */ + struct find_oppo_bundle b; }; static void cannot_oppo(struct connection *c - , struct find_oppo_bundle *b - , err_t ugh) + , struct find_oppo_bundle *b + , err_t ugh) { - char pcb[ADDRTOT_BUF]; - char ocb[ADDRTOT_BUF]; + char pcb[ADDRTOT_BUF]; + char ocb[ADDRTOT_BUF]; - addrtot(&b->peer_client, 0, pcb, sizeof(pcb)); - addrtot(&b->our_client, 0, ocb, sizeof(ocb)); + addrtot(&b->peer_client, 0, pcb, sizeof(pcb)); + addrtot(&b->our_client, 0, ocb, sizeof(ocb)); - DBG(DBG_DNS | DBG_OPPO, DBG_log("Can't Opportunistically initiate for %s to %s: %s" - , ocb, pcb, ugh)); + DBG(DBG_DNS | DBG_OPPO, DBG_log("Can't Opportunistically initiate for %s to %s: %s" + , ocb, pcb, ugh)); - whack_log(RC_OPPOFAILURE - , "Can't Opportunistically initiate for %s to %s: %s" - , ocb, pcb, ugh); + whack_log(RC_OPPOFAILURE + , "Can't Opportunistically initiate for %s to %s: %s" + , ocb, pcb, ugh); - if (c != NULL && c->policy_next != NULL) - { - /* there is some policy that comes afterwards */ - struct spd_route *shunt_spd; - struct connection *nc = c->policy_next; - struct state *st; + if (c != NULL && c->policy_next != NULL) + { + /* there is some policy that comes afterwards */ + struct spd_route *shunt_spd; + struct connection *nc = c->policy_next; + struct state *st; - passert(c->kind == CK_TEMPLATE); - passert(c->policy_next->kind == CK_PERMANENT); + passert(c->kind == CK_TEMPLATE); + passert(c->policy_next->kind == CK_PERMANENT); - DBG(DBG_OPPO, DBG_log("OE failed for %s to %s, but %s overrides shunt" - , ocb, pcb, c->policy_next->name)); + DBG(DBG_OPPO, DBG_log("OE failed for %s to %s, but %s overrides shunt" + , ocb, pcb, c->policy_next->name)); - /* - * okay, here we need add to the "next" policy, which is ought - * to be an instance. - * We will add another entry to the spd_route list for the specific - * situation that we have. - */ + /* + * okay, here we need add to the "next" policy, which is ought + * to be an instance. + * We will add another entry to the spd_route list for the specific + * situation that we have. + */ - shunt_spd = clone_thing(nc->spd); + shunt_spd = clone_thing(nc->spd); - shunt_spd->next = nc->spd.next; - nc->spd.next = shunt_spd; + shunt_spd->next = nc->spd.next; + nc->spd.next = shunt_spd; - happy(addrtosubnet(&b->peer_client, &shunt_spd->that.client)); + happy(addrtosubnet(&b->peer_client, &shunt_spd->that.client)); - if (sameaddr(&b->peer_client, &shunt_spd->that.host_addr)) - shunt_spd->that.has_client = FALSE; + if (sameaddr(&b->peer_client, &shunt_spd->that.host_addr)) + shunt_spd->that.has_client = FALSE; - /* - * override the tunnel destination with the one from the secondaried - * policy - */ - shunt_spd->that.host_addr = nc->spd.that.host_addr; + /* + * override the tunnel destination with the one from the secondaried + * policy + */ + shunt_spd->that.host_addr = nc->spd.that.host_addr; - /* now, lookup the state, and poke it up. - */ + /* now, lookup the state, and poke it up. + */ - st = state_with_serialno(nc->newest_ipsec_sa); + st = state_with_serialno(nc->newest_ipsec_sa); - /* XXX what to do if the IPSEC SA has died? */ - passert(st != NULL); + /* XXX what to do if the IPSEC SA has died? */ + passert(st != NULL); - /* link the new connection instance to the state's list of - * connections - */ + /* link the new connection instance to the state's list of + * connections + */ - DBG(DBG_OPPO, DBG_log("installing state: %ld for %s to %s" - , nc->newest_ipsec_sa - , ocb, pcb)); + DBG(DBG_OPPO, DBG_log("installing state: %ld for %s to %s" + , nc->newest_ipsec_sa + , ocb, pcb)); #ifdef DEBUG - if (DBGP(DBG_OPPO | DBG_CONTROLMORE)) - { - char state_buf[LOG_WIDTH]; - char state_buf2[LOG_WIDTH]; - time_t n = now(); + if (DBGP(DBG_OPPO | DBG_CONTROLMORE)) + { + char state_buf[LOG_WIDTH]; + char state_buf2[LOG_WIDTH]; + time_t n = now(); - fmt_state(FALSE, st, n - , state_buf, sizeof(state_buf) - , state_buf2, sizeof(state_buf2)); - DBG_log("cannot_oppo, failure SA1: %s", state_buf); - DBG_log("cannot_oppo, failure SA2: %s", state_buf2); - } + fmt_state(FALSE, st, n + , state_buf, sizeof(state_buf) + , state_buf2, sizeof(state_buf2)); + DBG_log("cannot_oppo, failure SA1: %s", state_buf); + DBG_log("cannot_oppo, failure SA2: %s", state_buf2); + } #endif /* DEBUG */ - if (!route_and_eroute(c, shunt_spd, st)) - { - whack_log(RC_OPPOFAILURE - , "failed to instantiate shunt policy %s for %s to %s" - , c->name - , ocb, pcb); + if (!route_and_eroute(c, shunt_spd, st)) + { + whack_log(RC_OPPOFAILURE + , "failed to instantiate shunt policy %s for %s to %s" + , c->name + , ocb, pcb); + } + return; } - return; - } #ifdef KLIPS - if (b->held) - { - /* Replace HOLD with b->failure_shunt. - * If no b->failure_shunt specified, use SPI_PASS -- THIS MAY CHANGE. - */ - if (b->failure_shunt == 0) + if (b->held) { - DBG(DBG_OPPO, DBG_log("no explicit failure shunt for %s to %s; installing %%pass" - , ocb, pcb)); - } + /* Replace HOLD with b->failure_shunt. + * If no b->failure_shunt specified, use SPI_PASS -- THIS MAY CHANGE. + */ + if (b->failure_shunt == 0) + { + DBG(DBG_OPPO, DBG_log("no explicit failure shunt for %s to %s; installing %%pass" + , ocb, pcb)); + } - (void) replace_bare_shunt(&b->our_client, &b->peer_client - , b->policy_prio - , b->failure_shunt - , b->failure_shunt != 0 - , b->transport_proto - , ugh); - } + (void) replace_bare_shunt(&b->our_client, &b->peer_client + , b->policy_prio + , b->failure_shunt + , b->failure_shunt != 0 + , b->transport_proto + , ugh); + } #endif } static void initiate_opportunistic_body(struct find_oppo_bundle *b - , struct adns_continuation *ac, err_t ac_ugh); /* forward */ + , struct adns_continuation *ac, err_t ac_ugh); /* forward */ void initiate_opportunistic(const ip_address *our_client @@ -2062,93 +2062,93 @@ initiate_opportunistic(const ip_address *our_client , bool held , int whackfd) { - struct find_oppo_bundle b; + struct find_oppo_bundle b; - b.want = (whackfd == NULL_FD ? "whack" : "acquire"); - b.failure_ok = FALSE; - b.our_client = *our_client; - b.peer_client = *peer_client; - b.transport_proto = transport_proto; - b.held = held; - b.policy_prio = BOTTOM_PRIO; - b.failure_shunt = 0; - b.whackfd = whackfd; - b.step = fos_start; - initiate_opportunistic_body(&b, NULL, NULL); + b.want = (whackfd == NULL_FD ? "whack" : "acquire"); + b.failure_ok = FALSE; + b.our_client = *our_client; + b.peer_client = *peer_client; + b.transport_proto = transport_proto; + b.held = held; + b.policy_prio = BOTTOM_PRIO; + b.failure_shunt = 0; + b.whackfd = whackfd; + b.step = fos_start; + initiate_opportunistic_body(&b, NULL, NULL); } static void continue_oppo(struct adns_continuation *acr, err_t ugh) { - struct find_oppo_continuation *cr = (void *)acr; /* inherit, damn you! */ - struct connection *c; - bool was_held = cr->b.held; - int whackfd = cr->b.whackfd; + struct find_oppo_continuation *cr = (void *)acr; /* inherit, damn you! */ + struct connection *c; + bool was_held = cr->b.held; + int whackfd = cr->b.whackfd; - /* note: cr->id has no resources; cr->sgw_id is id_none: - * neither need freeing. - */ - whack_log_fd = whackfd; + /* note: cr->id has no resources; cr->sgw_id is id_none: + * neither need freeing. + */ + whack_log_fd = whackfd; #ifdef KLIPS - /* Discover and record whether %hold has gone away. - * This could have happened while we were awaiting DNS. - * We must check BEFORE any call to cannot_oppo. - */ - if (was_held) - cr->b.held = has_bare_hold(&cr->b.our_client, &cr->b.peer_client - , cr->b.transport_proto); + /* Discover and record whether %hold has gone away. + * This could have happened while we were awaiting DNS. + * We must check BEFORE any call to cannot_oppo. + */ + if (was_held) + cr->b.held = has_bare_hold(&cr->b.our_client, &cr->b.peer_client + , cr->b.transport_proto); #endif #ifdef DEBUG - /* if we're going to ignore the error, at least note it in debugging log */ - if (cr->b.failure_ok && ugh != NULL) - { - DBG(DBG_CONTROL | DBG_DNS, - { + /* if we're going to ignore the error, at least note it in debugging log */ + if (cr->b.failure_ok && ugh != NULL) + { + DBG(DBG_CONTROL | DBG_DNS, + { + char ocb[ADDRTOT_BUF]; + char pcb[ADDRTOT_BUF]; + + addrtot(&cr->b.our_client, 0, ocb, sizeof(ocb)); + addrtot(&cr->b.peer_client, 0, pcb, sizeof(pcb)); + DBG_log("continuing from failed DNS lookup for %s, %s to %s: %s" + , cr->b.want, ocb, pcb, ugh); + }); + } +#endif + + if (!cr->b.failure_ok && ugh != NULL) + { + c = find_connection_for_clients(NULL, &cr->b.our_client, &cr->b.peer_client + , cr->b.transport_proto); + cannot_oppo(c, &cr->b + , builddiag("%s: %s", cr->b.want, ugh)); + } + else if (was_held && !cr->b.held) + { + /* was_held indicates we were started due to a %trap firing + * (as opposed to a "whack --oppohere --oppothere"). + * Since the %hold has gone, we can assume that somebody else + * has beaten us to the punch. We can go home. But lets log it. + */ char ocb[ADDRTOT_BUF]; char pcb[ADDRTOT_BUF]; addrtot(&cr->b.our_client, 0, ocb, sizeof(ocb)); addrtot(&cr->b.peer_client, 0, pcb, sizeof(pcb)); - DBG_log("continuing from failed DNS lookup for %s, %s to %s: %s" - , cr->b.want, ocb, pcb, ugh); - }); - } -#endif - if (!cr->b.failure_ok && ugh != NULL) - { - c = find_connection_for_clients(NULL, &cr->b.our_client, &cr->b.peer_client - , cr->b.transport_proto); - cannot_oppo(c, &cr->b - , builddiag("%s: %s", cr->b.want, ugh)); - } - else if (was_held && !cr->b.held) - { - /* was_held indicates we were started due to a %trap firing - * (as opposed to a "whack --oppohere --oppothere"). - * Since the %hold has gone, we can assume that somebody else - * has beaten us to the punch. We can go home. But lets log it. - */ - char ocb[ADDRTOT_BUF]; - char pcb[ADDRTOT_BUF]; + loglog(RC_COMMENT + , "%%hold otherwise handled during DNS lookup for Opportunistic Initiation for %s to %s" + , ocb, pcb); + } + else + { + initiate_opportunistic_body(&cr->b, &cr->ac, ugh); + whackfd = NULL_FD; /* was handed off */ + } - addrtot(&cr->b.our_client, 0, ocb, sizeof(ocb)); - addrtot(&cr->b.peer_client, 0, pcb, sizeof(pcb)); - - loglog(RC_COMMENT - , "%%hold otherwise handled during DNS lookup for Opportunistic Initiation for %s to %s" - , ocb, pcb); - } - else - { - initiate_opportunistic_body(&cr->b, &cr->ac, ugh); - whackfd = NULL_FD; /* was handed off */ - } - - whack_log_fd = NULL_FD; - close_any(whackfd); + whack_log_fd = NULL_FD; + close_any(whackfd); } #ifdef USE_KEYRR @@ -2157,54 +2157,54 @@ check_key_recs(enum myid_state try_state , const struct connection *c , struct adns_continuation *ac) { - /* Check if KEY lookup yielded good results. - * Looking up based on our ID. Used if - * client is ourself, or if TXT had no public key. - * Note: if c is different this time, there is - * a chance that we did the wrong query. - * If so, treat as a kind of failure. - */ - enum myid_state old_myid_state = myid_state; - const struct RSA_private_key *our_RSA_pri; - err_t ugh = NULL; - - myid_state = try_state; - - if (old_myid_state != myid_state - && old_myid_state == MYID_SPECIFIED) - { - ugh = "%myid was specified while we were guessing"; - } - else if ((our_RSA_pri = get_RSA_private_key(c)) == NULL) - { - ugh = "we don't know our own RSA key"; - } - else if (!same_id(&ac->id, &c->spd.this.id)) - { - ugh = "our ID changed underfoot"; - } - else - { - /* Similar to code in RSA_check_signature - * for checking the other side. + /* Check if KEY lookup yielded good results. + * Looking up based on our ID. Used if + * client is ourself, or if TXT had no public key. + * Note: if c is different this time, there is + * a chance that we did the wrong query. + * If so, treat as a kind of failure. */ - pubkey_list_t *kr; + enum myid_state old_myid_state = myid_state; + const struct RSA_private_key *our_RSA_pri; + err_t ugh = NULL; - ugh = "no KEY RR found for us"; - for (kr = ac->keys_from_dns; kr != NULL; kr = kr->next) + myid_state = try_state; + + if (old_myid_state != myid_state + && old_myid_state == MYID_SPECIFIED) { - ugh = "all our KEY RRs have the wrong public key"; - if (kr->key->alg == PUBKEY_ALG_RSA - && same_RSA_public_key(&our_RSA_pri->pub, &kr->key->u.rsa)) - { - ugh = NULL; /* good! */ - break; - } + ugh = "%myid was specified while we were guessing"; } - } - if (ugh != NULL) - myid_state = old_myid_state; - return ugh; + else if ((our_RSA_pri = get_RSA_private_key(c)) == NULL) + { + ugh = "we don't know our own RSA key"; + } + else if (!same_id(&ac->id, &c->spd.this.id)) + { + ugh = "our ID changed underfoot"; + } + else + { + /* Similar to code in RSA_check_signature + * for checking the other side. + */ + pubkey_list_t *kr; + + ugh = "no KEY RR found for us"; + for (kr = ac->keys_from_dns; kr != NULL; kr = kr->next) + { + ugh = "all our KEY RRs have the wrong public key"; + if (kr->key->alg == PUBKEY_ALG_RSA + && same_RSA_public_key(&our_RSA_pri->pub, &kr->key->u.rsa)) + { + ugh = NULL; /* good! */ + break; + } + } + } + if (ugh != NULL) + myid_state = old_myid_state; + return ugh; } #endif /* USE_KEYRR */ @@ -2213,54 +2213,54 @@ check_txt_recs(enum myid_state try_state , const struct connection *c , struct adns_continuation *ac) { - /* Check if TXT lookup yielded good results. - * Looking up based on our ID. Used if - * client is ourself, or if TXT had no public key. - * Note: if c is different this time, there is - * a chance that we did the wrong query. - * If so, treat as a kind of failure. - */ - enum myid_state old_myid_state = myid_state; - const struct RSA_private_key *our_RSA_pri; - err_t ugh = NULL; - - myid_state = try_state; - - if (old_myid_state != myid_state - && old_myid_state == MYID_SPECIFIED) - { - ugh = "%myid was specified while we were guessing"; - } - else if ((our_RSA_pri = get_RSA_private_key(c)) == NULL) - { - ugh = "we don't know our own RSA key"; - } - else if (!same_id(&ac->id, &c->spd.this.id)) - { - ugh = "our ID changed underfoot"; - } - else - { - /* Similar to code in RSA_check_signature - * for checking the other side. + /* Check if TXT lookup yielded good results. + * Looking up based on our ID. Used if + * client is ourself, or if TXT had no public key. + * Note: if c is different this time, there is + * a chance that we did the wrong query. + * If so, treat as a kind of failure. */ - struct gw_info *gwp; + enum myid_state old_myid_state = myid_state; + const struct RSA_private_key *our_RSA_pri; + err_t ugh = NULL; - ugh = "no TXT RR found for us"; - for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next) + myid_state = try_state; + + if (old_myid_state != myid_state + && old_myid_state == MYID_SPECIFIED) { - ugh = "all our TXT RRs have the wrong public key"; - if (gwp->key->alg == PUBKEY_ALG_RSA - && same_RSA_public_key(&our_RSA_pri->pub, &gwp->key->u.rsa)) - { - ugh = NULL; /* good! */ - break; - } + ugh = "%myid was specified while we were guessing"; } - } - if (ugh != NULL) - myid_state = old_myid_state; - return ugh; + else if ((our_RSA_pri = get_RSA_private_key(c)) == NULL) + { + ugh = "we don't know our own RSA key"; + } + else if (!same_id(&ac->id, &c->spd.this.id)) + { + ugh = "our ID changed underfoot"; + } + else + { + /* Similar to code in RSA_check_signature + * for checking the other side. + */ + struct gw_info *gwp; + + ugh = "no TXT RR found for us"; + for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next) + { + ugh = "all our TXT RRs have the wrong public key"; + if (gwp->key->alg == PUBKEY_ALG_RSA + && same_RSA_public_key(&our_RSA_pri->pub, &gwp->key->u.rsa)) + { + ugh = NULL; /* good! */ + break; + } + } + } + if (ugh != NULL) + myid_state = old_myid_state; + return ugh; } @@ -2270,775 +2270,775 @@ initiate_opportunistic_body(struct find_oppo_bundle *b , struct adns_continuation *ac , err_t ac_ugh) { - struct connection *c; - struct spd_route *sr; + struct connection *c; + struct spd_route *sr; - /* What connection shall we use? - * First try for one that explicitly handles the clients. - */ - DBG(DBG_CONTROL, - { - char ours[ADDRTOT_BUF]; - char his[ADDRTOT_BUF]; - int ourport; - int hisport; - - addrtot(&b->our_client, 0, ours, sizeof(ours)); - addrtot(&b->peer_client, 0, his, sizeof(his)); - ourport = ntohs(portof(&b->our_client)); - hisport = ntohs(portof(&b->peer_client)); - DBG_log("initiate on demand from %s:%d to %s:%d proto=%d state: %s because: %s" - , ours, ourport, his, hisport, b->transport_proto - , oppo_step_name[b->step], b->want); - }); - if (isanyaddr(&b->our_client) || isanyaddr(&b->peer_client)) - { - cannot_oppo(NULL, b, "impossible IP address"); - } - else if ((c = find_connection_for_clients(&sr - , &b->our_client - , &b->peer_client - , b->transport_proto)) == NULL) - { - /* No connection explicitly handles the clients and there - * are no Opportunistic connections -- whine and give up. - * The failure policy cannot be gotten from a connection; we pick %pass. + /* What connection shall we use? + * First try for one that explicitly handles the clients. */ - cannot_oppo(NULL, b, "no routed Opportunistic template covers this pair"); - } - else if (c->kind != CK_TEMPLATE) - { - /* We've found a connection that can serve. - * Do we have to initiate it? - * Not if there is currently an IPSEC SA. - * But if there is an IPSEC SA, then KLIPS would not - * have generated the acquire. So we assume that there isn't one. - * This may be redundant if a non-opportunistic - * negotiation is already being attempted. - */ - - /* If we are to proceed asynchronously, b->whackfd will be NULL_FD. */ - - if(c->kind == CK_INSTANCE) - { - char cib[CONN_INST_BUF]; - /* there is already an instance being negotiated, no nothing */ - DBG(DBG_CONTROL, DBG_log("found existing instance \"%s\"%s, rekeying it" - , c->name - , (fmt_conn_instance(c, cib), cib))); - /* XXX-mcr - return; */ - } - - /* otherwise, there is some kind of static conn that can handle - * this connection, so we initiate it */ - -#ifdef KLIPS - if (b->held) - { - /* what should we do on failure? */ - (void) assign_hold(c, sr, b->transport_proto, &b->our_client, &b->peer_client); - } -#endif - ipsecdoi_initiate(b->whackfd, c, c->policy, 1, SOS_NOBODY); - b->whackfd = NULL_FD; /* protect from close */ - } - else - { - /* We are handling an opportunistic situation. - * This involves several DNS lookup steps that require suspension. - * Note: many facts might change while we're suspended. - * Here be dragons. - * - * The first chunk of code handles the result of the previous - * DNS query (if any). It also selects the kind of the next step. - * The second chunk initiates the next DNS query (if any). - */ - enum find_oppo_step next_step = fos_myid_ip_txt; - err_t ugh = ac_ugh; - char mycredentialstr[BUF_LEN]; - char cib[CONN_INST_BUF]; - - DBG(DBG_CONTROL, DBG_log("creating new instance from \"%s\"%s" - , c->name - , (fmt_conn_instance(c, cib), cib))); - - - idtoa(&sr->this.id, mycredentialstr, sizeof(mycredentialstr)); - - passert(c->policy & POLICY_OPPO); /* can't initiate Road Warrior connections */ - - /* handle any DNS answer; select next step */ - - switch (b->step) - { - case fos_start: - /* just starting out: select first query step */ - next_step = fos_myid_ip_txt; - break; - - case fos_myid_ip_txt: /* TXT for our default IP address as %myid */ - ugh = check_txt_recs(MYID_IP, c, ac); - if (ugh != NULL) - { - /* cannot use our IP as OE identitiy for initiation */ - DBG(DBG_OPPO, DBG_log("can not use our IP (%s:TXT) as identity: %s" - , myid_str[MYID_IP] - , ugh)); - if (!logged_myid_ip_txt_warning) - { - loglog(RC_LOG_SERIOUS - , "can not use our IP (%s:TXT) as identity: %s" - , myid_str[MYID_IP] - , ugh); - logged_myid_ip_txt_warning = TRUE; - } - - next_step = fos_myid_hostname_txt; - ugh = NULL; /* failure can be recovered from */ - } - else - { - /* we can use our IP as OE identity for initiation */ - if (!logged_myid_ip_txt_warning) - { - loglog(RC_LOG_SERIOUS - , "using our IP (%s:TXT) as identity!" - , myid_str[MYID_IP]); - logged_myid_ip_txt_warning = TRUE; - } - - next_step = fos_our_client; - } - break; - - case fos_myid_hostname_txt: /* TXT for our hostname as %myid */ - ugh = check_txt_recs(MYID_HOSTNAME, c, ac); - if (ugh != NULL) - { - /* cannot use our hostname as OE identitiy for initiation */ - DBG(DBG_OPPO, DBG_log("can not use our hostname (%s:TXT) as identity: %s" - , myid_str[MYID_HOSTNAME] - , ugh)); - if (!logged_myid_fqdn_txt_warning) - { - loglog(RC_LOG_SERIOUS - , "can not use our hostname (%s:TXT) as identity: %s" - , myid_str[MYID_HOSTNAME] - , ugh); - logged_myid_fqdn_txt_warning = TRUE; - } -#ifdef USE_KEYRR - next_step = fos_myid_ip_key; - ugh = NULL; /* failure can be recovered from */ -#endif - } - else - { - /* we can use our hostname as OE identity for initiation */ - if (!logged_myid_fqdn_txt_warning) - { - loglog(RC_LOG_SERIOUS - , "using our hostname (%s:TXT) as identity!" - , myid_str[MYID_HOSTNAME]); - logged_myid_fqdn_txt_warning = TRUE; - } - next_step = fos_our_client; - } - break; - -#ifdef USE_KEYRR - case fos_myid_ip_key: /* KEY for our default IP address as %myid */ - ugh = check_key_recs(MYID_IP, c, ac); - if (ugh != NULL) - { - /* cannot use our IP as OE identitiy for initiation */ - DBG(DBG_OPPO, DBG_log("can not use our IP (%s:KEY) as identity: %s" - , myid_str[MYID_IP] - , ugh)); - if (!logged_myid_ip_key_warning) - { - loglog(RC_LOG_SERIOUS - , "can not use our IP (%s:KEY) as identity: %s" - , myid_str[MYID_IP] - , ugh); - logged_myid_ip_key_warning = TRUE; - } - - next_step = fos_myid_hostname_key; - ugh = NULL; /* failure can be recovered from */ - } - else - { - /* we can use our IP as OE identity for initiation */ - if (!logged_myid_ip_key_warning) - { - loglog(RC_LOG_SERIOUS - , "using our IP (%s:KEY) as identity!" - , myid_str[MYID_IP]); - logged_myid_ip_key_warning = TRUE; - } - next_step = fos_our_client; - } - break; - - case fos_myid_hostname_key: /* KEY for our hostname as %myid */ - ugh = check_key_recs(MYID_HOSTNAME, c, ac); - if (ugh != NULL) - { - /* cannot use our IP as OE identitiy for initiation */ - DBG(DBG_OPPO, DBG_log("can not use our hostname (%s:KEY) as identity: %s" - , myid_str[MYID_HOSTNAME] - , ugh)); - if (!logged_myid_fqdn_key_warning) - { - loglog(RC_LOG_SERIOUS - , "can not use our hostname (%s:KEY) as identity: %s" - , myid_str[MYID_HOSTNAME] - , ugh); - logged_myid_fqdn_key_warning = TRUE; - } - - next_step = fos_myid_hostname_key; - ugh = NULL; /* failure can be recovered from */ - } - else - { - /* we can use our IP as OE identity for initiation */ - if (!logged_myid_fqdn_key_warning) - { - loglog(RC_LOG_SERIOUS - , "using our hostname (%s:KEY) as identity!" - , myid_str[MYID_HOSTNAME]); - logged_myid_fqdn_key_warning = TRUE; - } - next_step = fos_our_client; - } - break; -#endif - - case fos_our_client: /* TXT for our client */ - { - /* Our client is not us: we must check the TXT records. - * Note: if c is different this time, there is - * a chance that we did the wrong query. - * If so, treat as a kind of failure. - */ - const struct RSA_private_key *our_RSA_pri = get_RSA_private_key(c); - - next_step = fos_his_client; /* normal situation */ - - passert(sr != NULL); - - if (our_RSA_pri == NULL) - { - ugh = "we don't know our own RSA key"; - } - else if (sameaddr(&sr->this.host_addr, &b->our_client)) - { - /* this wasn't true when we started -- bail */ - ugh = "our IP address changed underfoot"; - } - else if (!same_id(&ac->sgw_id, &sr->this.id)) - { - /* this wasn't true when we started -- bail */ - ugh = "our ID changed underfoot"; - } - else - { - /* Similar to code in quick_inI1_outR1_tail - * for checking the other side. - */ - struct gw_info *gwp; - - ugh = "no TXT RR for our client delegates us"; - for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next) - { - passert(same_id(&gwp->gw_id, &sr->this.id)); - - ugh = "TXT RR for our client has wrong key"; - /* If there is a key from the TXT record, - * we count it as a win if we match the key. - * If there was no key, we have a tentative win: - * we need to check our KEY record to be sure. - */ - if (!gwp->gw_key_present) - { - /* Success, but the TXT had no key - * so we must check our our own KEY records. - */ - next_step = fos_our_txt; - ugh = NULL; /* good! */ - break; - } - if (same_RSA_public_key(&our_RSA_pri->pub, &gwp->key->u.rsa)) - { - ugh = NULL; /* good! */ - break; - } - } - } - } - break; - - case fos_our_txt: /* TXT for us */ - { - /* Check if TXT lookup yielded good results. - * Looking up based on our ID. Used if - * client is ourself, or if TXT had no public key. - * Note: if c is different this time, there is - * a chance that we did the wrong query. - * If so, treat as a kind of failure. - */ - const struct RSA_private_key *our_RSA_pri = get_RSA_private_key(c); - - next_step = fos_his_client; /* unless we decide to look for KEY RR */ - - if (our_RSA_pri == NULL) - { - ugh = "we don't know our own RSA key"; - } - else if (!same_id(&ac->id, &c->spd.this.id)) - { - ugh = "our ID changed underfoot"; - } - else - { - /* Similar to code in RSA_check_signature - * for checking the other side. - */ - struct gw_info *gwp; - - ugh = "no TXT RR for us"; - for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next) - { - passert(same_id(&gwp->gw_id, &sr->this.id)); - - ugh = "TXT RR for us has wrong key"; - if (gwp->gw_key_present - && same_RSA_public_key(&our_RSA_pri->pub, &gwp->key->u.rsa)) - { - DBG(DBG_CONTROL, - DBG_log("initiate on demand found TXT with right public key at: %s" - , mycredentialstr)); - ugh = NULL; - break; - } - } -#ifdef USE_KEYRR - if (ugh != NULL) - { - /* if no TXT with right key, try KEY */ - DBG(DBG_CONTROL, - DBG_log("will try for KEY RR since initiate on demand found %s: %s" - , ugh, mycredentialstr)); - next_step = fos_our_key; - ugh = NULL; - } -#endif - } - } - break; - -#ifdef USE_KEYRR - case fos_our_key: /* KEY for us */ - { - /* Check if KEY lookup yielded good results. - * Looking up based on our ID. Used if - * client is ourself, or if TXT had no public key. - * Note: if c is different this time, there is - * a chance that we did the wrong query. - * If so, treat as a kind of failure. - */ - const struct RSA_private_key *our_RSA_pri = get_RSA_private_key(c); - - next_step = fos_his_client; /* always */ - - if (our_RSA_pri == NULL) - { - ugh = "we don't know our own RSA key"; - } - else if (!same_id(&ac->id, &c->spd.this.id)) - { - ugh = "our ID changed underfoot"; - } - else - { - /* Similar to code in RSA_check_signature - * for checking the other side. - */ - pubkey_list_t *kr; - - ugh = "no KEY RR found for us (and no good TXT RR)"; - for (kr = ac->keys_from_dns; kr != NULL; kr = kr->next) - { - ugh = "all our KEY RRs have the wrong public key (and no good TXT RR)"; - if (kr->key->alg == PUBKEY_ALG_RSA - && same_RSA_public_key(&our_RSA_pri->pub, &kr->key->u.rsa)) - { - /* do this only once a day */ - if (!logged_txt_warning) - { - loglog(RC_LOG_SERIOUS - , "found KEY RR but not TXT RR for %s. See http://www.freeswan.org/err/txt-change.html." - , mycredentialstr); - logged_txt_warning = TRUE; - } - ugh = NULL; /* good! */ - break; - } - } - } - } - break; -#endif /* USE_KEYRR */ - - case fos_his_client: /* TXT for his client */ - { - /* We've finished last DNS queries: TXT for his client. - * Using the information, try to instantiate a connection - * and start negotiating. - * We now know the peer. The chosing of "c" ignored this, - * so we will disregard its current value. - * !!! We need to randomize the entry in gw that we choose. - */ - next_step = fos_done; /* no more queries */ - - c = build_outgoing_opportunistic_connection(ac->gateways_from_dns - , &b->our_client - , &b->peer_client); - - if (c == NULL) - { - /* We cannot seem to instantiate a suitable connection: - * complain clearly. - */ - char ocb[ADDRTOT_BUF] - , pcb[ADDRTOT_BUF] - , pb[ADDRTOT_BUF]; - - addrtot(&b->our_client, 0, ocb, sizeof(ocb)); - addrtot(&b->peer_client, 0, pcb, sizeof(pcb)); - passert(id_is_ipaddr(&ac->gateways_from_dns->gw_id)); - addrtot(&ac->gateways_from_dns->gw_id.ip_addr, 0, pb, sizeof(pb)); - loglog(RC_OPPOFAILURE - , "no suitable connection for opportunism" - " between %s and %s with %s as peer" - , ocb, pcb, pb); - -#ifdef KLIPS - if (b->held) - { - /* Replace HOLD with PASS. - * The type of replacement *ought* to be - * specified by policy. - */ - (void) replace_bare_shunt(&b->our_client, &b->peer_client - , BOTTOM_PRIO - , SPI_PASS /* fail into PASS */ - , TRUE, b->transport_proto - , "no suitable connection"); - } -#endif - } - else - { - /* If we are to proceed asynchronously, b->whackfd will be NULL_FD. */ - passert(c->kind == CK_INSTANCE); - passert(c->gw_info != NULL); - passert(HAS_IPSEC_POLICY(c->policy)); - passert(LHAS(LELEM(RT_UNROUTED) | LELEM(RT_ROUTED_PROSPECTIVE), c->spd.routing)); -#ifdef KLIPS - if (b->held) - { - /* what should we do on failure? */ - (void) assign_hold(c, &c->spd - , b->transport_proto - , &b->our_client, &b->peer_client); - } -#endif - c->gw_info->key->last_tried_time = now(); - ipsecdoi_initiate(b->whackfd, c, c->policy, 1, SOS_NOBODY); - b->whackfd = NULL_FD; /* protect from close */ - } - } - break; - - default: - bad_case(b->step); - } - - /* the second chunk: initiate the next DNS query (if any) */ DBG(DBG_CONTROL, - { - char ours[ADDRTOT_BUF]; - char his[ADDRTOT_BUF]; + { + char ours[ADDRTOT_BUF]; + char his[ADDRTOT_BUF]; + int ourport; + int hisport; - addrtot(&b->our_client, 0, ours, sizeof(ours)); - addrtot(&b->peer_client, 0, his, sizeof(his)); - DBG_log("initiate on demand from %s to %s new state: %s with ugh: %s" - , ours, his, oppo_step_name[b->step], ugh ? ugh : "ok"); - }); - - if (ugh != NULL) + addrtot(&b->our_client, 0, ours, sizeof(ours)); + addrtot(&b->peer_client, 0, his, sizeof(his)); + ourport = ntohs(portof(&b->our_client)); + hisport = ntohs(portof(&b->peer_client)); + DBG_log("initiate on demand from %s:%d to %s:%d proto=%d state: %s because: %s" + , ours, ourport, his, hisport, b->transport_proto + , oppo_step_name[b->step], b->want); + }); + if (isanyaddr(&b->our_client) || isanyaddr(&b->peer_client)) { - b->policy_prio = c->prio; - b->failure_shunt = shunt_policy_spi(c, FALSE); - cannot_oppo(c, b, ugh); + cannot_oppo(NULL, b, "impossible IP address"); } - else if (next_step == fos_done) + else if ((c = find_connection_for_clients(&sr + , &b->our_client + , &b->peer_client + , b->transport_proto)) == NULL) { - /* nothing to do */ + /* No connection explicitly handles the clients and there + * are no Opportunistic connections -- whine and give up. + * The failure policy cannot be gotten from a connection; we pick %pass. + */ + cannot_oppo(NULL, b, "no routed Opportunistic template covers this pair"); + } + else if (c->kind != CK_TEMPLATE) + { + /* We've found a connection that can serve. + * Do we have to initiate it? + * Not if there is currently an IPSEC SA. + * But if there is an IPSEC SA, then KLIPS would not + * have generated the acquire. So we assume that there isn't one. + * This may be redundant if a non-opportunistic + * negotiation is already being attempted. + */ + + /* If we are to proceed asynchronously, b->whackfd will be NULL_FD. */ + + if(c->kind == CK_INSTANCE) + { + char cib[CONN_INST_BUF]; + /* there is already an instance being negotiated, no nothing */ + DBG(DBG_CONTROL, DBG_log("found existing instance \"%s\"%s, rekeying it" + , c->name + , (fmt_conn_instance(c, cib), cib))); + /* XXX-mcr - return; */ + } + + /* otherwise, there is some kind of static conn that can handle + * this connection, so we initiate it */ + +#ifdef KLIPS + if (b->held) + { + /* what should we do on failure? */ + (void) assign_hold(c, sr, b->transport_proto, &b->our_client, &b->peer_client); + } +#endif + ipsecdoi_initiate(b->whackfd, c, c->policy, 1, SOS_NOBODY); + b->whackfd = NULL_FD; /* protect from close */ } else { - /* set up the next query */ - struct find_oppo_continuation *cr = malloc_thing(struct find_oppo_continuation); - struct id id; + /* We are handling an opportunistic situation. + * This involves several DNS lookup steps that require suspension. + * Note: many facts might change while we're suspended. + * Here be dragons. + * + * The first chunk of code handles the result of the previous + * DNS query (if any). It also selects the kind of the next step. + * The second chunk initiates the next DNS query (if any). + */ + enum find_oppo_step next_step = fos_myid_ip_txt; + err_t ugh = ac_ugh; + char mycredentialstr[BUF_LEN]; + char cib[CONN_INST_BUF]; - b->policy_prio = c->prio; - b->failure_shunt = shunt_policy_spi(c, FALSE); - cr->b = *b; /* copy; start hand off of whackfd */ - cr->b.failure_ok = FALSE; - cr->b.step = next_step; + DBG(DBG_CONTROL, DBG_log("creating new instance from \"%s\"%s" + , c->name + , (fmt_conn_instance(c, cib), cib))); + - for (sr = &c->spd - ; sr!=NULL && !sameaddr(&sr->this.host_addr, &b->our_client) - ; sr = sr->next) - ; + idtoa(&sr->this.id, mycredentialstr, sizeof(mycredentialstr)); - if (sr == NULL) - sr = &c->spd; + passert(c->policy & POLICY_OPPO); /* can't initiate Road Warrior connections */ - /* If a %hold shunt has replaced the eroute for this template, - * record this fact. - */ - if (b->held - && sr->routing == RT_ROUTED_PROSPECTIVE && eclipsable(sr)) - { - sr->routing = RT_ROUTED_ECLIPSED; - eclipse_count++; - } + /* handle any DNS answer; select next step */ - /* Switch to issue next query. - * A case may turn out to be unnecessary. If so, it falls - * through to the next case. - * Figuring out what %myid can stand for must be done before - * our client credentials are looked up: we must know what - * the client credentials may use to identify us. - * On the other hand, our own credentials should be looked - * up after our clients in case our credentials are not - * needed at all. - * XXX this is a wasted effort if we don't have credentials - * BUT they are not needed. - */ - switch (next_step) - { - case fos_myid_ip_txt: - if (c->spd.this.id.kind == ID_MYID - && myid_state != MYID_SPECIFIED) + switch (b->step) { - cr->b.failure_ok = TRUE; - cr->b.want = b->want = "TXT record for IP address as %myid"; - ugh = start_adns_query(&myids[MYID_IP] - , &myids[MYID_IP] - , T_TXT - , continue_oppo - , &cr->ac); - break; - } - cr->b.step = fos_myid_hostname_txt; - /* fall through */ + case fos_start: + /* just starting out: select first query step */ + next_step = fos_myid_ip_txt; + break; - case fos_myid_hostname_txt: - if (c->spd.this.id.kind == ID_MYID - && myid_state != MYID_SPECIFIED) - { + case fos_myid_ip_txt: /* TXT for our default IP address as %myid */ + ugh = check_txt_recs(MYID_IP, c, ac); + if (ugh != NULL) + { + /* cannot use our IP as OE identitiy for initiation */ + DBG(DBG_OPPO, DBG_log("can not use our IP (%s:TXT) as identity: %s" + , myid_str[MYID_IP] + , ugh)); + if (!logged_myid_ip_txt_warning) + { + loglog(RC_LOG_SERIOUS + , "can not use our IP (%s:TXT) as identity: %s" + , myid_str[MYID_IP] + , ugh); + logged_myid_ip_txt_warning = TRUE; + } + + next_step = fos_myid_hostname_txt; + ugh = NULL; /* failure can be recovered from */ + } + else + { + /* we can use our IP as OE identity for initiation */ + if (!logged_myid_ip_txt_warning) + { + loglog(RC_LOG_SERIOUS + , "using our IP (%s:TXT) as identity!" + , myid_str[MYID_IP]); + logged_myid_ip_txt_warning = TRUE; + } + + next_step = fos_our_client; + } + break; + + case fos_myid_hostname_txt: /* TXT for our hostname as %myid */ + ugh = check_txt_recs(MYID_HOSTNAME, c, ac); + if (ugh != NULL) + { + /* cannot use our hostname as OE identitiy for initiation */ + DBG(DBG_OPPO, DBG_log("can not use our hostname (%s:TXT) as identity: %s" + , myid_str[MYID_HOSTNAME] + , ugh)); + if (!logged_myid_fqdn_txt_warning) + { + loglog(RC_LOG_SERIOUS + , "can not use our hostname (%s:TXT) as identity: %s" + , myid_str[MYID_HOSTNAME] + , ugh); + logged_myid_fqdn_txt_warning = TRUE; + } #ifdef USE_KEYRR - cr->b.failure_ok = TRUE; -#else - cr->b.failure_ok = FALSE; + next_step = fos_myid_ip_key; + ugh = NULL; /* failure can be recovered from */ #endif - cr->b.want = b->want = "TXT record for hostname as %myid"; - ugh = start_adns_query(&myids[MYID_HOSTNAME] - , &myids[MYID_HOSTNAME] - , T_TXT - , continue_oppo - , &cr->ac); - break; - } + } + else + { + /* we can use our hostname as OE identity for initiation */ + if (!logged_myid_fqdn_txt_warning) + { + loglog(RC_LOG_SERIOUS + , "using our hostname (%s:TXT) as identity!" + , myid_str[MYID_HOSTNAME]); + logged_myid_fqdn_txt_warning = TRUE; + } + next_step = fos_our_client; + } + break; #ifdef USE_KEYRR - cr->b.step = fos_myid_ip_key; - /* fall through */ + case fos_myid_ip_key: /* KEY for our default IP address as %myid */ + ugh = check_key_recs(MYID_IP, c, ac); + if (ugh != NULL) + { + /* cannot use our IP as OE identitiy for initiation */ + DBG(DBG_OPPO, DBG_log("can not use our IP (%s:KEY) as identity: %s" + , myid_str[MYID_IP] + , ugh)); + if (!logged_myid_ip_key_warning) + { + loglog(RC_LOG_SERIOUS + , "can not use our IP (%s:KEY) as identity: %s" + , myid_str[MYID_IP] + , ugh); + logged_myid_ip_key_warning = TRUE; + } - case fos_myid_ip_key: - if (c->spd.this.id.kind == ID_MYID - && myid_state != MYID_SPECIFIED) - { - cr->b.failure_ok = TRUE; - cr->b.want = b->want = "KEY record for IP address as %myid (no good TXT)"; - ugh = start_adns_query(&myids[MYID_IP] - , (const struct id *) NULL /* security gateway meaningless */ - , T_KEY - , continue_oppo - , &cr->ac); - break; - } - cr->b.step = fos_myid_hostname_key; - /* fall through */ + next_step = fos_myid_hostname_key; + ugh = NULL; /* failure can be recovered from */ + } + else + { + /* we can use our IP as OE identity for initiation */ + if (!logged_myid_ip_key_warning) + { + loglog(RC_LOG_SERIOUS + , "using our IP (%s:KEY) as identity!" + , myid_str[MYID_IP]); + logged_myid_ip_key_warning = TRUE; + } + next_step = fos_our_client; + } + break; - case fos_myid_hostname_key: - if (c->spd.this.id.kind == ID_MYID - && myid_state != MYID_SPECIFIED) - { - cr->b.failure_ok = FALSE; /* last attempt! */ - cr->b.want = b->want = "KEY record for hostname as %myid (no good TXT)"; - ugh = start_adns_query(&myids[MYID_HOSTNAME] - , (const struct id *) NULL /* security gateway meaningless */ - , T_KEY - , continue_oppo - , &cr->ac); - break; - } + case fos_myid_hostname_key: /* KEY for our hostname as %myid */ + ugh = check_key_recs(MYID_HOSTNAME, c, ac); + if (ugh != NULL) + { + /* cannot use our IP as OE identitiy for initiation */ + DBG(DBG_OPPO, DBG_log("can not use our hostname (%s:KEY) as identity: %s" + , myid_str[MYID_HOSTNAME] + , ugh)); + if (!logged_myid_fqdn_key_warning) + { + loglog(RC_LOG_SERIOUS + , "can not use our hostname (%s:KEY) as identity: %s" + , myid_str[MYID_HOSTNAME] + , ugh); + logged_myid_fqdn_key_warning = TRUE; + } + + next_step = fos_myid_hostname_key; + ugh = NULL; /* failure can be recovered from */ + } + else + { + /* we can use our IP as OE identity for initiation */ + if (!logged_myid_fqdn_key_warning) + { + loglog(RC_LOG_SERIOUS + , "using our hostname (%s:KEY) as identity!" + , myid_str[MYID_HOSTNAME]); + logged_myid_fqdn_key_warning = TRUE; + } + next_step = fos_our_client; + } + break; #endif - cr->b.step = fos_our_client; - /* fall through */ - case fos_our_client: /* TXT for our client */ - if (!sameaddr(&c->spd.this.host_addr, &b->our_client)) - { - /* Check that at least one TXT(reverse(b->our_client)) is workable. - * Note: {unshare|free}_id_content not needed for id: ephemeral. - */ - cr->b.want = b->want = "our client's TXT record"; - iptoid(&b->our_client, &id); - ugh = start_adns_query(&id - , &c->spd.this.id /* we are the security gateway */ - , T_TXT - , continue_oppo - , &cr->ac); - break; - } - cr->b.step = fos_our_txt; - /* fall through */ + case fos_our_client: /* TXT for our client */ + { + /* Our client is not us: we must check the TXT records. + * Note: if c is different this time, there is + * a chance that we did the wrong query. + * If so, treat as a kind of failure. + */ + const struct RSA_private_key *our_RSA_pri = get_RSA_private_key(c); - case fos_our_txt: /* TXT for us */ - cr->b.failure_ok = b->failure_ok = TRUE; - cr->b.want = b->want = "our TXT record"; - ugh = start_adns_query(&sr->this.id - , &sr->this.id /* we are the security gateway XXX - maybe ignore? mcr */ - , T_TXT - , continue_oppo - , &cr->ac); - break; + next_step = fos_his_client; /* normal situation */ + + passert(sr != NULL); + + if (our_RSA_pri == NULL) + { + ugh = "we don't know our own RSA key"; + } + else if (sameaddr(&sr->this.host_addr, &b->our_client)) + { + /* this wasn't true when we started -- bail */ + ugh = "our IP address changed underfoot"; + } + else if (!same_id(&ac->sgw_id, &sr->this.id)) + { + /* this wasn't true when we started -- bail */ + ugh = "our ID changed underfoot"; + } + else + { + /* Similar to code in quick_inI1_outR1_tail + * for checking the other side. + */ + struct gw_info *gwp; + + ugh = "no TXT RR for our client delegates us"; + for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next) + { + passert(same_id(&gwp->gw_id, &sr->this.id)); + + ugh = "TXT RR for our client has wrong key"; + /* If there is a key from the TXT record, + * we count it as a win if we match the key. + * If there was no key, we have a tentative win: + * we need to check our KEY record to be sure. + */ + if (!gwp->gw_key_present) + { + /* Success, but the TXT had no key + * so we must check our our own KEY records. + */ + next_step = fos_our_txt; + ugh = NULL; /* good! */ + break; + } + if (same_RSA_public_key(&our_RSA_pri->pub, &gwp->key->u.rsa)) + { + ugh = NULL; /* good! */ + break; + } + } + } + } + break; + + case fos_our_txt: /* TXT for us */ + { + /* Check if TXT lookup yielded good results. + * Looking up based on our ID. Used if + * client is ourself, or if TXT had no public key. + * Note: if c is different this time, there is + * a chance that we did the wrong query. + * If so, treat as a kind of failure. + */ + const struct RSA_private_key *our_RSA_pri = get_RSA_private_key(c); + + next_step = fos_his_client; /* unless we decide to look for KEY RR */ + + if (our_RSA_pri == NULL) + { + ugh = "we don't know our own RSA key"; + } + else if (!same_id(&ac->id, &c->spd.this.id)) + { + ugh = "our ID changed underfoot"; + } + else + { + /* Similar to code in RSA_check_signature + * for checking the other side. + */ + struct gw_info *gwp; + + ugh = "no TXT RR for us"; + for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next) + { + passert(same_id(&gwp->gw_id, &sr->this.id)); + + ugh = "TXT RR for us has wrong key"; + if (gwp->gw_key_present + && same_RSA_public_key(&our_RSA_pri->pub, &gwp->key->u.rsa)) + { + DBG(DBG_CONTROL, + DBG_log("initiate on demand found TXT with right public key at: %s" + , mycredentialstr)); + ugh = NULL; + break; + } + } +#ifdef USE_KEYRR + if (ugh != NULL) + { + /* if no TXT with right key, try KEY */ + DBG(DBG_CONTROL, + DBG_log("will try for KEY RR since initiate on demand found %s: %s" + , ugh, mycredentialstr)); + next_step = fos_our_key; + ugh = NULL; + } +#endif + } + } + break; #ifdef USE_KEYRR - case fos_our_key: /* KEY for us */ - cr->b.want = b->want = "our KEY record"; - cr->b.failure_ok = b->failure_ok = FALSE; - ugh = start_adns_query(&sr->this.id - , (const struct id *) NULL /* security gateway meaningless */ - , T_KEY - , continue_oppo - , &cr->ac); - break; + case fos_our_key: /* KEY for us */ + { + /* Check if KEY lookup yielded good results. + * Looking up based on our ID. Used if + * client is ourself, or if TXT had no public key. + * Note: if c is different this time, there is + * a chance that we did the wrong query. + * If so, treat as a kind of failure. + */ + const struct RSA_private_key *our_RSA_pri = get_RSA_private_key(c); + + next_step = fos_his_client; /* always */ + + if (our_RSA_pri == NULL) + { + ugh = "we don't know our own RSA key"; + } + else if (!same_id(&ac->id, &c->spd.this.id)) + { + ugh = "our ID changed underfoot"; + } + else + { + /* Similar to code in RSA_check_signature + * for checking the other side. + */ + pubkey_list_t *kr; + + ugh = "no KEY RR found for us (and no good TXT RR)"; + for (kr = ac->keys_from_dns; kr != NULL; kr = kr->next) + { + ugh = "all our KEY RRs have the wrong public key (and no good TXT RR)"; + if (kr->key->alg == PUBKEY_ALG_RSA + && same_RSA_public_key(&our_RSA_pri->pub, &kr->key->u.rsa)) + { + /* do this only once a day */ + if (!logged_txt_warning) + { + loglog(RC_LOG_SERIOUS + , "found KEY RR but not TXT RR for %s. See http://www.freeswan.org/err/txt-change.html." + , mycredentialstr); + logged_txt_warning = TRUE; + } + ugh = NULL; /* good! */ + break; + } + } + } + } + break; #endif /* USE_KEYRR */ - case fos_his_client: /* TXT for his client */ - /* note: {unshare|free}_id_content not needed for id: ephemeral */ - cr->b.want = b->want = "target's TXT record"; - cr->b.failure_ok = b->failure_ok = FALSE; - iptoid(&b->peer_client, &id); - ugh = start_adns_query(&id - , (const struct id *) NULL /* security gateway unconstrained */ - , T_TXT - , continue_oppo - , &cr->ac); - break; + case fos_his_client: /* TXT for his client */ + { + /* We've finished last DNS queries: TXT for his client. + * Using the information, try to instantiate a connection + * and start negotiating. + * We now know the peer. The chosing of "c" ignored this, + * so we will disregard its current value. + * !!! We need to randomize the entry in gw that we choose. + */ + next_step = fos_done; /* no more queries */ - default: - bad_case(next_step); - } + c = build_outgoing_opportunistic_connection(ac->gateways_from_dns + , &b->our_client + , &b->peer_client); - if (ugh == NULL) - b->whackfd = NULL_FD; /* complete hand-off */ - else - cannot_oppo(c, b, ugh); + if (c == NULL) + { + /* We cannot seem to instantiate a suitable connection: + * complain clearly. + */ + char ocb[ADDRTOT_BUF] + , pcb[ADDRTOT_BUF] + , pb[ADDRTOT_BUF]; + + addrtot(&b->our_client, 0, ocb, sizeof(ocb)); + addrtot(&b->peer_client, 0, pcb, sizeof(pcb)); + passert(id_is_ipaddr(&ac->gateways_from_dns->gw_id)); + addrtot(&ac->gateways_from_dns->gw_id.ip_addr, 0, pb, sizeof(pb)); + loglog(RC_OPPOFAILURE + , "no suitable connection for opportunism" + " between %s and %s with %s as peer" + , ocb, pcb, pb); + +#ifdef KLIPS + if (b->held) + { + /* Replace HOLD with PASS. + * The type of replacement *ought* to be + * specified by policy. + */ + (void) replace_bare_shunt(&b->our_client, &b->peer_client + , BOTTOM_PRIO + , SPI_PASS /* fail into PASS */ + , TRUE, b->transport_proto + , "no suitable connection"); + } +#endif + } + else + { + /* If we are to proceed asynchronously, b->whackfd will be NULL_FD. */ + passert(c->kind == CK_INSTANCE); + passert(c->gw_info != NULL); + passert(HAS_IPSEC_POLICY(c->policy)); + passert(LHAS(LELEM(RT_UNROUTED) | LELEM(RT_ROUTED_PROSPECTIVE), c->spd.routing)); +#ifdef KLIPS + if (b->held) + { + /* what should we do on failure? */ + (void) assign_hold(c, &c->spd + , b->transport_proto + , &b->our_client, &b->peer_client); + } +#endif + c->gw_info->key->last_tried_time = now(); + ipsecdoi_initiate(b->whackfd, c, c->policy, 1, SOS_NOBODY); + b->whackfd = NULL_FD; /* protect from close */ + } + } + break; + + default: + bad_case(b->step); + } + + /* the second chunk: initiate the next DNS query (if any) */ + DBG(DBG_CONTROL, + { + char ours[ADDRTOT_BUF]; + char his[ADDRTOT_BUF]; + + addrtot(&b->our_client, 0, ours, sizeof(ours)); + addrtot(&b->peer_client, 0, his, sizeof(his)); + DBG_log("initiate on demand from %s to %s new state: %s with ugh: %s" + , ours, his, oppo_step_name[b->step], ugh ? ugh : "ok"); + }); + + if (ugh != NULL) + { + b->policy_prio = c->prio; + b->failure_shunt = shunt_policy_spi(c, FALSE); + cannot_oppo(c, b, ugh); + } + else if (next_step == fos_done) + { + /* nothing to do */ + } + else + { + /* set up the next query */ + struct find_oppo_continuation *cr = malloc_thing(struct find_oppo_continuation); + struct id id; + + b->policy_prio = c->prio; + b->failure_shunt = shunt_policy_spi(c, FALSE); + cr->b = *b; /* copy; start hand off of whackfd */ + cr->b.failure_ok = FALSE; + cr->b.step = next_step; + + for (sr = &c->spd + ; sr!=NULL && !sameaddr(&sr->this.host_addr, &b->our_client) + ; sr = sr->next) + ; + + if (sr == NULL) + sr = &c->spd; + + /* If a %hold shunt has replaced the eroute for this template, + * record this fact. + */ + if (b->held + && sr->routing == RT_ROUTED_PROSPECTIVE && eclipsable(sr)) + { + sr->routing = RT_ROUTED_ECLIPSED; + eclipse_count++; + } + + /* Switch to issue next query. + * A case may turn out to be unnecessary. If so, it falls + * through to the next case. + * Figuring out what %myid can stand for must be done before + * our client credentials are looked up: we must know what + * the client credentials may use to identify us. + * On the other hand, our own credentials should be looked + * up after our clients in case our credentials are not + * needed at all. + * XXX this is a wasted effort if we don't have credentials + * BUT they are not needed. + */ + switch (next_step) + { + case fos_myid_ip_txt: + if (c->spd.this.id.kind == ID_MYID + && myid_state != MYID_SPECIFIED) + { + cr->b.failure_ok = TRUE; + cr->b.want = b->want = "TXT record for IP address as %myid"; + ugh = start_adns_query(&myids[MYID_IP] + , &myids[MYID_IP] + , T_TXT + , continue_oppo + , &cr->ac); + break; + } + cr->b.step = fos_myid_hostname_txt; + /* fall through */ + + case fos_myid_hostname_txt: + if (c->spd.this.id.kind == ID_MYID + && myid_state != MYID_SPECIFIED) + { +#ifdef USE_KEYRR + cr->b.failure_ok = TRUE; +#else + cr->b.failure_ok = FALSE; +#endif + cr->b.want = b->want = "TXT record for hostname as %myid"; + ugh = start_adns_query(&myids[MYID_HOSTNAME] + , &myids[MYID_HOSTNAME] + , T_TXT + , continue_oppo + , &cr->ac); + break; + } + +#ifdef USE_KEYRR + cr->b.step = fos_myid_ip_key; + /* fall through */ + + case fos_myid_ip_key: + if (c->spd.this.id.kind == ID_MYID + && myid_state != MYID_SPECIFIED) + { + cr->b.failure_ok = TRUE; + cr->b.want = b->want = "KEY record for IP address as %myid (no good TXT)"; + ugh = start_adns_query(&myids[MYID_IP] + , (const struct id *) NULL /* security gateway meaningless */ + , T_KEY + , continue_oppo + , &cr->ac); + break; + } + cr->b.step = fos_myid_hostname_key; + /* fall through */ + + case fos_myid_hostname_key: + if (c->spd.this.id.kind == ID_MYID + && myid_state != MYID_SPECIFIED) + { + cr->b.failure_ok = FALSE; /* last attempt! */ + cr->b.want = b->want = "KEY record for hostname as %myid (no good TXT)"; + ugh = start_adns_query(&myids[MYID_HOSTNAME] + , (const struct id *) NULL /* security gateway meaningless */ + , T_KEY + , continue_oppo + , &cr->ac); + break; + } +#endif + cr->b.step = fos_our_client; + /* fall through */ + + case fos_our_client: /* TXT for our client */ + if (!sameaddr(&c->spd.this.host_addr, &b->our_client)) + { + /* Check that at least one TXT(reverse(b->our_client)) is workable. + * Note: {unshare|free}_id_content not needed for id: ephemeral. + */ + cr->b.want = b->want = "our client's TXT record"; + iptoid(&b->our_client, &id); + ugh = start_adns_query(&id + , &c->spd.this.id /* we are the security gateway */ + , T_TXT + , continue_oppo + , &cr->ac); + break; + } + cr->b.step = fos_our_txt; + /* fall through */ + + case fos_our_txt: /* TXT for us */ + cr->b.failure_ok = b->failure_ok = TRUE; + cr->b.want = b->want = "our TXT record"; + ugh = start_adns_query(&sr->this.id + , &sr->this.id /* we are the security gateway XXX - maybe ignore? mcr */ + , T_TXT + , continue_oppo + , &cr->ac); + break; + +#ifdef USE_KEYRR + case fos_our_key: /* KEY for us */ + cr->b.want = b->want = "our KEY record"; + cr->b.failure_ok = b->failure_ok = FALSE; + ugh = start_adns_query(&sr->this.id + , (const struct id *) NULL /* security gateway meaningless */ + , T_KEY + , continue_oppo + , &cr->ac); + break; +#endif /* USE_KEYRR */ + + case fos_his_client: /* TXT for his client */ + /* note: {unshare|free}_id_content not needed for id: ephemeral */ + cr->b.want = b->want = "target's TXT record"; + cr->b.failure_ok = b->failure_ok = FALSE; + iptoid(&b->peer_client, &id); + ugh = start_adns_query(&id + , (const struct id *) NULL /* security gateway unconstrained */ + , T_TXT + , continue_oppo + , &cr->ac); + break; + + default: + bad_case(next_step); + } + + if (ugh == NULL) + b->whackfd = NULL_FD; /* complete hand-off */ + else + cannot_oppo(c, b, ugh); + } } - } - close_any(b->whackfd); + close_any(b->whackfd); } void terminate_connection(const char *nm) { - /* Loop because more than one may match (master and instances) - * But at least one is required (enforced by con_by_name). - */ - struct connection *c = con_by_name(nm, TRUE); + /* Loop because more than one may match (master and instances) + * But at least one is required (enforced by con_by_name). + */ + struct connection *c = con_by_name(nm, TRUE); - if (c == NULL || !c->ikev1) - return; + if (c == NULL || !c->ikev1) + return; - do - { - struct connection *n = c->ac_next; /* grab this before c might disappear */ - - if (streq(c->name, nm) - && c->kind >= CK_PERMANENT - && !NEVER_NEGOTIATE(c->policy)) + do { - set_cur_connection(c); - plog("terminating SAs using this connection"); - c->policy &= ~POLICY_UP; - flush_pending_by_connection(c); - delete_states_by_connection(c, FALSE); - if (c->kind == CK_INSTANCE) - delete_connection(c, FALSE); - reset_cur_connection(); - } - c = n; - } while (c != NULL); + struct connection *n = c->ac_next; /* grab this before c might disappear */ + + if (streq(c->name, nm) + && c->kind >= CK_PERMANENT + && !NEVER_NEGOTIATE(c->policy)) + { + set_cur_connection(c); + plog("terminating SAs using this connection"); + c->policy &= ~POLICY_UP; + flush_pending_by_connection(c); + delete_states_by_connection(c, FALSE); + if (c->kind == CK_INSTANCE) + delete_connection(c, FALSE); + reset_cur_connection(); + } + c = n; + } while (c != NULL); } /* an ISAKMP SA has been established. * Note the serial number, and release any connections with * the same peer ID but different peer IP address. */ -bool uniqueIDs = FALSE; /* --uniqueids? */ +bool uniqueIDs = FALSE; /* --uniqueids? */ void ISAKMP_SA_established(struct connection *c, so_serial_t serial) { - c->newest_isakmp_sa = serial; + c->newest_isakmp_sa = serial; - /* the connection is now oriented so that we are able to determine - * whether we are a mode config server with a virtual IP to send. - */ - if (!isanyaddr(&c->spd.that.host_srcip) && !c->spd.that.has_natip) - c->spd.that.modecfg = TRUE; - - if (uniqueIDs) - { - /* for all connections: if the same Phase 1 IDs are used - * for a different IP address, unorient that connection. + /* the connection is now oriented so that we are able to determine + * whether we are a mode config server with a virtual IP to send. */ - struct connection *d; - - for (d = connections; d != NULL; ) + if (!isanyaddr(&c->spd.that.host_srcip) && !c->spd.that.has_natip) + c->spd.that.modecfg = TRUE; + + if (uniqueIDs) { - struct connection *next = d->ac_next; /* might move underneath us */ + /* for all connections: if the same Phase 1 IDs are used + * for a different IP address, unorient that connection. + */ + struct connection *d; - if (d->kind >= CK_PERMANENT - && same_id(&c->spd.this.id, &d->spd.this.id) - && same_id(&c->spd.that.id, &d->spd.that.id) - && !sameaddr(&c->spd.that.host_addr, &d->spd.that.host_addr)) - { - release_connection(d, FALSE); - } - d = next; + for (d = connections; d != NULL; ) + { + struct connection *next = d->ac_next; /* might move underneath us */ + + if (d->kind >= CK_PERMANENT + && same_id(&c->spd.this.id, &d->spd.this.id) + && same_id(&c->spd.that.id, &d->spd.that.id) + && !sameaddr(&c->spd.that.host_addr, &d->spd.that.host_addr)) + { + release_connection(d, FALSE); + } + d = next; + } } - } } /* Find the connection to connection c's peer's client with the @@ -3054,108 +3054,108 @@ ISAKMP_SA_established(struct connection *c, so_serial_t serial) */ struct connection * route_owner(struct connection *c - , struct spd_route **srp - , struct connection **erop - , struct spd_route **esrp) + , struct spd_route **srp + , struct connection **erop + , struct spd_route **esrp) { - struct connection *d - , *best_ro = c - , *best_ero = c; - struct spd_route *srd, *src; - struct spd_route *best_sr, *best_esr; - enum routing_t best_routing, best_erouting; + struct connection *d + , *best_ro = c + , *best_ero = c; + struct spd_route *srd, *src; + struct spd_route *best_sr, *best_esr; + enum routing_t best_routing, best_erouting; - passert(oriented(*c)); - best_sr = NULL; - best_esr = NULL; - best_routing = c->spd.routing; - best_erouting = best_routing; + passert(oriented(*c)); + best_sr = NULL; + best_esr = NULL; + best_routing = c->spd.routing; + best_erouting = best_routing; - for (d = connections; d != NULL; d = d->ac_next) - { - for (srd = &d->spd; srd; srd = srd->next) + for (d = connections; d != NULL; d = d->ac_next) { - if (srd->routing == RT_UNROUTED) - continue; - - for (src = &c->spd; src; src=src->next) - { - if (!samesubnet(&src->that.client, &srd->that.client)) - continue; - if (src->that.protocol != srd->that.protocol) - continue; - if (src->that.port != srd->that.port) - continue; - passert(oriented(*d)); - if (srd->routing > best_routing) + for (srd = &d->spd; srd; srd = srd->next) { - best_ro = d; - best_sr = srd; - best_routing = srd->routing; - } + if (srd->routing == RT_UNROUTED) + continue; - if (!samesubnet(&src->this.client, &srd->this.client)) - continue; - if (src->this.protocol != srd->this.protocol) - continue; - if (src->this.port != srd->this.port) - continue; - if (srd->routing > best_erouting) - { - best_ero = d; - best_esr = srd; - best_erouting = srd->routing; + for (src = &c->spd; src; src=src->next) + { + if (!samesubnet(&src->that.client, &srd->that.client)) + continue; + if (src->that.protocol != srd->that.protocol) + continue; + if (src->that.port != srd->that.port) + continue; + passert(oriented(*d)); + if (srd->routing > best_routing) + { + best_ro = d; + best_sr = srd; + best_routing = srd->routing; + } + + if (!samesubnet(&src->this.client, &srd->this.client)) + continue; + if (src->this.protocol != srd->this.protocol) + continue; + if (src->this.port != srd->this.port) + continue; + if (srd->routing > best_erouting) + { + best_ero = d; + best_esr = srd; + best_erouting = srd->routing; + } + } } - } } - } - DBG(DBG_CONTROL, + DBG(DBG_CONTROL, + { + char cib[CONN_INST_BUF]; + err_t m = builddiag("route owner of \"%s\"%s %s:" + , c->name + , (fmt_conn_instance(c, cib), cib) + , enum_name(&routing_story, c->spd.routing)); + + if (!routed(best_ro->spd.routing)) + m = builddiag("%s NULL", m); + else if (best_ro == c) + m = builddiag("%s self", m); + else + m = builddiag("%s \"%s\"%s %s", m + , best_ro->name + , (fmt_conn_instance(best_ro, cib), cib) + , enum_name(&routing_story, best_ro->spd.routing)); + + if (erop != NULL) + { + m = builddiag("%s; eroute owner:", m); + if (!erouted(best_ero->spd.routing)) + m = builddiag("%s NULL", m); + else if (best_ero == c) + m = builddiag("%s self", m); + else + m = builddiag("%s \"%s\"%s %s", m + , best_ero->name + , (fmt_conn_instance(best_ero, cib), cib) + , enum_name(&routing_story, best_ero->spd.routing)); + } + + DBG_log("%s", m); + }); + + if (erop != NULL) + *erop = erouted(best_erouting)? best_ero : NULL; + + if (srp != NULL ) { - char cib[CONN_INST_BUF]; - err_t m = builddiag("route owner of \"%s\"%s %s:" - , c->name - , (fmt_conn_instance(c, cib), cib) - , enum_name(&routing_story, c->spd.routing)); + *srp = best_sr; + if (esrp != NULL ) + *esrp = best_esr; + } - if (!routed(best_ro->spd.routing)) - m = builddiag("%s NULL", m); - else if (best_ro == c) - m = builddiag("%s self", m); - else - m = builddiag("%s \"%s\"%s %s", m - , best_ro->name - , (fmt_conn_instance(best_ro, cib), cib) - , enum_name(&routing_story, best_ro->spd.routing)); - - if (erop != NULL) - { - m = builddiag("%s; eroute owner:", m); - if (!erouted(best_ero->spd.routing)) - m = builddiag("%s NULL", m); - else if (best_ero == c) - m = builddiag("%s self", m); - else - m = builddiag("%s \"%s\"%s %s", m - , best_ero->name - , (fmt_conn_instance(best_ero, cib), cib) - , enum_name(&routing_story, best_ero->spd.routing)); - } - - DBG_log("%s", m); - }); - - if (erop != NULL) - *erop = erouted(best_erouting)? best_ero : NULL; - - if (srp != NULL ) - { - *srp = best_sr; - if (esrp != NULL ) - *esrp = best_esr; - } - - return routed(best_routing)? best_ro : NULL; + return routed(best_routing)? best_ro : NULL; } /* Find a connection that owns the shunt eroute between subnets. @@ -3165,20 +3165,20 @@ route_owner(struct connection *c struct connection * shunt_owner(const ip_subnet *ours, const ip_subnet *his) { - struct connection *c; - struct spd_route *sr; + struct connection *c; + struct spd_route *sr; - for (c = connections; c != NULL; c = c->ac_next) - { - for (sr = &c->spd; sr; sr = sr->next) + for (c = connections; c != NULL; c = c->ac_next) { - if (shunt_erouted(sr->routing) - && samesubnet(ours, &sr->this.client) - && samesubnet(his, &sr->that.client)) - return c; + for (sr = &c->spd; sr; sr = sr->next) + { + if (shunt_erouted(sr->routing) + && samesubnet(ours, &sr->this.client) + && samesubnet(his, &sr->that.client)) + return c; + } } - } - return NULL; + return NULL; } /* Find some connection with this pair of hosts. @@ -3189,25 +3189,25 @@ struct connection * find_host_connection(const ip_address *me, u_int16_t my_port , const ip_address *him, u_int16_t his_port, lset_t policy) { - struct connection *c = find_host_pair_connections(me, my_port, him, his_port); + struct connection *c = find_host_pair_connections(me, my_port, him, his_port); - if (policy != LEMPTY) - { - lset_t auth_requested = policy & POLICY_ID_AUTH_MASK; - - /* if we have requirements for the policy, - * choose the first matching connection. - */ - while (c != NULL) + if (policy != LEMPTY) { - if (c->policy & auth_requested) - { - break; - } - c = c->hp_next; + lset_t auth_requested = policy & POLICY_ID_AUTH_MASK; + + /* if we have requirements for the policy, + * choose the first matching connection. + */ + while (c != NULL) + { + if (c->policy & auth_requested) + { + break; + } + c = c->hp_next; + } } - } - return c; + return c; } /* given an up-until-now satisfactory connection, find the best connection @@ -3264,187 +3264,187 @@ find_host_connection(const ip_address *me, u_int16_t my_port * * In the Initiator case, the particular connection might have been * specified by whatever provoked Pluto to initiate. For example: - * whack --initiate connection-name + * whack --initiate connection-name * The advantages of switching connections when we're the Initiator seem * less important than the disadvantages, so after FreeS/WAN 1.9, we * don't do this. */ -#define PRIO_NO_MATCH_FOUND 2048 +#define PRIO_NO_MATCH_FOUND 2048 struct connection * refine_host_connection(const struct state *st, const struct id *peer_id , chunk_t peer_ca) { - struct connection *c = st->st_connection; - struct connection *d; - struct connection *best_found = NULL; - u_int16_t auth = st->st_oakley.auth; - lset_t auth_policy = POLICY_PSK; - const chunk_t *psk = NULL; - bool wcpip; /* wildcard Peer IP? */ - int best_prio = PRIO_NO_MATCH_FOUND; - int wildcards, our_pathlen, peer_pathlen; + struct connection *c = st->st_connection; + struct connection *d; + struct connection *best_found = NULL; + u_int16_t auth = st->st_oakley.auth; + lset_t auth_policy = POLICY_PSK; + const chunk_t *psk = NULL; + bool wcpip; /* wildcard Peer IP? */ + int best_prio = PRIO_NO_MATCH_FOUND; + int wildcards, our_pathlen, peer_pathlen; - if (same_id(&c->spd.that.id, peer_id) - && trusted_ca(peer_ca, c->spd.that.ca, &peer_pathlen) - && peer_pathlen == 0 - && match_requested_ca(c->requested_ca, c->spd.this.ca, &our_pathlen) - && our_pathlen == 0) - { - DBG(DBG_CONTROL, - DBG_log("current connection is a full match" - " -- no need to look further"); - ) - return c; - } - - switch (auth) - { - case OAKLEY_PRESHARED_KEY: - auth_policy = POLICY_PSK; - psk = get_preshared_secret(c); - /* It should be virtually impossible to fail to find PSK: - * we just used it to decode the current message! - */ - if (psk == NULL) - return NULL; /* cannot determine PSK! */ - break; - case XAUTHInitPreShared: - case XAUTHRespPreShared: - auth_policy = POLICY_XAUTH_PSK; - psk = get_preshared_secret(c); - if (psk == NULL) - return NULL; /* cannot determine PSK! */ - break; - case OAKLEY_RSA_SIG: - auth_policy = POLICY_RSASIG; - break; - case XAUTHInitRSA: - case XAUTHRespRSA: - auth_policy = POLICY_XAUTH_RSASIG; - break; - default: - bad_case(auth); - } - - /* The current connection won't do: search for one that will. - * First search for one with the same pair of hosts. - * If that fails, search for a suitable Road Warrior or Opportunistic - * connection (i.e. wildcard peer IP). - * We need to match: - * - peer_id (slightly complicated by instantiation) - * - if PSK auth, the key must not change (we used it to decode message) - * - policy-as-used must be acceptable to new connection - */ - d = c->host_pair->connections; - for (wcpip = FALSE; ; wcpip = TRUE) - { - for (; d != NULL; d = d->hp_next) + if (same_id(&c->spd.that.id, peer_id) + && trusted_ca(peer_ca, c->spd.that.ca, &peer_pathlen) + && peer_pathlen == 0 + && match_requested_ca(c->requested_ca, c->spd.this.ca, &our_pathlen) + && our_pathlen == 0) { - const char *match_name[] = {"no", "ok"}; - - bool matching_id = match_id(peer_id - , &d->spd.that.id, &wildcards); - bool matching_auth = (d->policy & auth_policy) != LEMPTY; - - bool matching_trust = trusted_ca(peer_ca - , d->spd.that.ca, &peer_pathlen); - bool matching_request = match_requested_ca(c->requested_ca - , d->spd.this.ca, &our_pathlen); - bool match = matching_id && matching_auth && matching_trust; - - int prio = (MAX_WILDCARDS + 1) * !matching_request + wildcards; - - prio = (MAX_CA_PATH_LEN + 1) * prio + peer_pathlen; - prio = (MAX_CA_PATH_LEN + 1) * prio + our_pathlen; - - DBG(DBG_CONTROLMORE, - DBG_log("%s: %s match (id: %s, auth: %s, trust: %s, request: %s, prio: %4d)" - , d->name - , match ? "full":" no" - , match_name[matching_id] - , match_name[matching_auth] - , match_name[matching_trust] - , match_name[matching_request] - , match ? prio:PRIO_NO_MATCH_FOUND) - ) - - /* do we have a match? */ - if (!match) - continue; - - /* ignore group connections */ - if (d->policy & POLICY_GROUP) - continue; - - if (c->spd.that.host_port != d->spd.that.host_port - && d->kind == CK_INSTANCE) - { - continue; - } - - switch (auth) - { - case OAKLEY_PRESHARED_KEY: - case XAUTHInitPreShared: - case XAUTHRespPreShared: - /* secret must match the one we already used */ - { - const chunk_t *dpsk = get_preshared_secret(d); - - if (dpsk == NULL) - continue; /* no secret */ - - if (psk != dpsk) - if (psk->len != dpsk->len - || memcmp(psk->ptr, dpsk->ptr, psk->len) != 0) - continue; /* different secret */ - } - break; - - case OAKLEY_RSA_SIG: - case XAUTHInitRSA: - case XAUTHRespRSA: - /* - * We must at least be able to find our private key - .*/ - if (d->spd.this.sc == NULL /* no smartcard */ - && get_RSA_private_key(d) == NULL) /* no private key */ - continue; - break; - - default: - bad_case(auth); - } - - /* d has passed all the tests. - * We'll go with it if the Peer ID was an exact match. - */ - if (prio == 0) - { - return d; - } - - /* We'll remember it as best_found in case an exact - * match doesn't come along. - */ - if (prio < best_prio) - { - best_found = d; - best_prio = prio; - } + DBG(DBG_CONTROL, + DBG_log("current connection is a full match" + " -- no need to look further"); + ) + return c; } - if (wcpip) - return best_found; /* been around twice already */ - /* Starting second time around. - * We're willing to settle for a connection that needs Peer IP - * instantiated: Road Warrior or Opportunistic. - * Look on list of connections for host pair with wildcard Peer IP + switch (auth) + { + case OAKLEY_PRESHARED_KEY: + auth_policy = POLICY_PSK; + psk = get_preshared_secret(c); + /* It should be virtually impossible to fail to find PSK: + * we just used it to decode the current message! + */ + if (psk == NULL) + return NULL; /* cannot determine PSK! */ + break; + case XAUTHInitPreShared: + case XAUTHRespPreShared: + auth_policy = POLICY_XAUTH_PSK; + psk = get_preshared_secret(c); + if (psk == NULL) + return NULL; /* cannot determine PSK! */ + break; + case OAKLEY_RSA_SIG: + auth_policy = POLICY_RSASIG; + break; + case XAUTHInitRSA: + case XAUTHRespRSA: + auth_policy = POLICY_XAUTH_RSASIG; + break; + default: + bad_case(auth); + } + + /* The current connection won't do: search for one that will. + * First search for one with the same pair of hosts. + * If that fails, search for a suitable Road Warrior or Opportunistic + * connection (i.e. wildcard peer IP). + * We need to match: + * - peer_id (slightly complicated by instantiation) + * - if PSK auth, the key must not change (we used it to decode message) + * - policy-as-used must be acceptable to new connection */ - d = find_host_pair_connections(&c->spd.this.host_addr, c->spd.this.host_port - , (ip_address *)NULL, c->spd.that.host_port); - } + d = c->host_pair->connections; + for (wcpip = FALSE; ; wcpip = TRUE) + { + for (; d != NULL; d = d->hp_next) + { + const char *match_name[] = {"no", "ok"}; + + bool matching_id = match_id(peer_id + , &d->spd.that.id, &wildcards); + bool matching_auth = (d->policy & auth_policy) != LEMPTY; + + bool matching_trust = trusted_ca(peer_ca + , d->spd.that.ca, &peer_pathlen); + bool matching_request = match_requested_ca(c->requested_ca + , d->spd.this.ca, &our_pathlen); + bool match = matching_id && matching_auth && matching_trust; + + int prio = (MAX_WILDCARDS + 1) * !matching_request + wildcards; + + prio = (MAX_CA_PATH_LEN + 1) * prio + peer_pathlen; + prio = (MAX_CA_PATH_LEN + 1) * prio + our_pathlen; + + DBG(DBG_CONTROLMORE, + DBG_log("%s: %s match (id: %s, auth: %s, trust: %s, request: %s, prio: %4d)" + , d->name + , match ? "full":" no" + , match_name[matching_id] + , match_name[matching_auth] + , match_name[matching_trust] + , match_name[matching_request] + , match ? prio:PRIO_NO_MATCH_FOUND) + ) + + /* do we have a match? */ + if (!match) + continue; + + /* ignore group connections */ + if (d->policy & POLICY_GROUP) + continue; + + if (c->spd.that.host_port != d->spd.that.host_port + && d->kind == CK_INSTANCE) + { + continue; + } + + switch (auth) + { + case OAKLEY_PRESHARED_KEY: + case XAUTHInitPreShared: + case XAUTHRespPreShared: + /* secret must match the one we already used */ + { + const chunk_t *dpsk = get_preshared_secret(d); + + if (dpsk == NULL) + continue; /* no secret */ + + if (psk != dpsk) + if (psk->len != dpsk->len + || memcmp(psk->ptr, dpsk->ptr, psk->len) != 0) + continue; /* different secret */ + } + break; + + case OAKLEY_RSA_SIG: + case XAUTHInitRSA: + case XAUTHRespRSA: + /* + * We must at least be able to find our private key + .*/ + if (d->spd.this.sc == NULL /* no smartcard */ + && get_RSA_private_key(d) == NULL) /* no private key */ + continue; + break; + + default: + bad_case(auth); + } + + /* d has passed all the tests. + * We'll go with it if the Peer ID was an exact match. + */ + if (prio == 0) + { + return d; + } + + /* We'll remember it as best_found in case an exact + * match doesn't come along. + */ + if (prio < best_prio) + { + best_found = d; + best_prio = prio; + } + } + if (wcpip) + return best_found; /* been around twice already */ + + /* Starting second time around. + * We're willing to settle for a connection that needs Peer IP + * instantiated: Road Warrior or Opportunistic. + * Look on list of connections for host pair with wildcard Peer IP + */ + d = find_host_pair_connections(&c->spd.this.host_addr, c->spd.this.host_port + , (ip_address *)NULL, c->spd.that.host_port); + } } /** @@ -3454,35 +3454,35 @@ refine_host_connection(const struct state *st, const struct id *peer_id static bool is_virtual_net_used(const ip_subnet *peer_net, const struct id *peer_id) { - struct connection *d; + struct connection *d; - for (d = connections; d != NULL; d = d->ac_next) - { - switch (d->kind) + for (d = connections; d != NULL; d = d->ac_next) { - case CK_PERMANENT: - case CK_INSTANCE: - if ((subnetinsubnet(peer_net,&d->spd.that.client) || - subnetinsubnet(&d->spd.that.client,peer_net)) - && !same_id(&d->spd.that.id, peer_id)) - { - char buf[BUF_LEN]; - char client[SUBNETTOT_BUF]; + switch (d->kind) + { + case CK_PERMANENT: + case CK_INSTANCE: + if ((subnetinsubnet(peer_net,&d->spd.that.client) || + subnetinsubnet(&d->spd.that.client,peer_net)) + && !same_id(&d->spd.that.id, peer_id)) + { + char buf[BUF_LEN]; + char client[SUBNETTOT_BUF]; - subnettot(peer_net, 0, client, sizeof(client)); - idtoa(&d->spd.that.id, buf, sizeof(buf)); - plog("Virtual IP %s is already used by '%s'", client, buf); - idtoa(peer_id, buf, sizeof(buf)); - plog("Your ID is '%s'", buf); - return TRUE; /* already used by another one */ - } - break; - case CK_GOING_AWAY: - default: - break; + subnettot(peer_net, 0, client, sizeof(client)); + idtoa(&d->spd.that.id, buf, sizeof(buf)); + plog("Virtual IP %s is already used by '%s'", client, buf); + idtoa(peer_id, buf, sizeof(buf)); + plog("Your ID is '%s'", buf); + return TRUE; /* already used by another one */ + } + break; + case CK_GOING_AWAY: + default: + break; + } } - } - return FALSE; /* you can safely use it */ + return FALSE; /* you can safely use it */ } /* find_client_connection: given a connection suitable for ISAKMP @@ -3510,9 +3510,9 @@ is_virtual_net_used(const ip_subnet *peer_net, const struct id *peer_id) * instantiation. They are the IDs that have been authenticated. */ -#define PATH_WEIGHT 1 -#define WILD_WEIGHT (MAX_CA_PATH_LEN+1) -#define PRIO_WEIGHT (MAX_WILDCARDS+1)*WILD_WEIGHT +#define PATH_WEIGHT 1 +#define WILD_WEIGHT (MAX_CA_PATH_LEN+1) +#define PRIO_WEIGHT (MAX_WILDCARDS+1)*WILD_WEIGHT /* fc_try: a helper function for find_client_connection */ static struct connection * @@ -3528,121 +3528,121 @@ fc_try(const struct connection *c , chunk_t peer_ca , const ietfAttrList_t *peer_list) { - struct connection *d; - struct connection *best = NULL; - policy_prio_t best_prio = BOTTOM_PRIO; - int wildcards, pathlen; + struct connection *d; + struct connection *best = NULL; + policy_prio_t best_prio = BOTTOM_PRIO; + int wildcards, pathlen; - const bool peer_net_is_host = subnetisaddr(peer_net, &c->spd.that.host_addr); + const bool peer_net_is_host = subnetisaddr(peer_net, &c->spd.that.host_addr); - for (d = hp->connections; d != NULL; d = d->hp_next) - { - struct spd_route *sr; - - if (d->policy & POLICY_GROUP) - continue; - - if (!(same_id(&c->spd.this.id, &d->spd.this.id) - && match_id(&c->spd.that.id, &d->spd.that.id, &wildcards) - && trusted_ca(peer_ca, d->spd.that.ca, &pathlen) - && group_membership(peer_list, d->name, d->spd.that.groups))) - continue; - - /* compare protocol and ports */ - if (d->spd.this.protocol != our_protocol - || d->spd.this.port != our_port - || d->spd.that.protocol != peer_protocol - || (d->spd.that.port != peer_port && !d->spd.that.has_port_wildcard)) - continue; - - /* non-Opportunistic case: - * our_client must match. - * - * So must peer_client, but the testing is complicated - * by the fact that the peer might be a wildcard - * and if so, the default value of that.client - * won't match the default peer_net. The appropriate test: - * - * If d has a peer client, it must match peer_net. - * If d has no peer client, peer_net must just have peer itself. - */ - - for (sr = &d->spd; best != d && sr != NULL; sr = sr->next) + for (d = hp->connections; d != NULL; d = d->hp_next) { - policy_prio_t prio; -#ifdef DEBUG - if (DBGP(DBG_CONTROLMORE)) - { - char s1[SUBNETTOT_BUF],d1[SUBNETTOT_BUF]; - char s3[SUBNETTOT_BUF],d3[SUBNETTOT_BUF]; + struct spd_route *sr; - subnettot(our_net, 0, s1, sizeof(s1)); - subnettot(peer_net, 0, d1, sizeof(d1)); - subnettot(&sr->this.client, 0, s3, sizeof(s3)); - subnettot(&sr->that.client, 0, d3, sizeof(d3)); - DBG_log(" fc_try trying " - "%s:%s:%d/%d -> %s:%d/%d vs %s:%s:%d/%d -> %s:%d/%d" - , c->name, s1, c->spd.this.protocol, c->spd.this.port - , d1, c->spd.that.protocol, c->spd.that.port - , d->name, s3, sr->this.protocol, sr->this.port - , d3, sr->that.protocol, sr->that.port); - } + if (d->policy & POLICY_GROUP) + continue; + + if (!(same_id(&c->spd.this.id, &d->spd.this.id) + && match_id(&c->spd.that.id, &d->spd.that.id, &wildcards) + && trusted_ca(peer_ca, d->spd.that.ca, &pathlen) + && group_membership(peer_list, d->name, d->spd.that.groups))) + continue; + + /* compare protocol and ports */ + if (d->spd.this.protocol != our_protocol + || d->spd.this.port != our_port + || d->spd.that.protocol != peer_protocol + || (d->spd.that.port != peer_port && !d->spd.that.has_port_wildcard)) + continue; + + /* non-Opportunistic case: + * our_client must match. + * + * So must peer_client, but the testing is complicated + * by the fact that the peer might be a wildcard + * and if so, the default value of that.client + * won't match the default peer_net. The appropriate test: + * + * If d has a peer client, it must match peer_net. + * If d has no peer client, peer_net must just have peer itself. + */ + + for (sr = &d->spd; best != d && sr != NULL; sr = sr->next) + { + policy_prio_t prio; +#ifdef DEBUG + if (DBGP(DBG_CONTROLMORE)) + { + char s1[SUBNETTOT_BUF],d1[SUBNETTOT_BUF]; + char s3[SUBNETTOT_BUF],d3[SUBNETTOT_BUF]; + + subnettot(our_net, 0, s1, sizeof(s1)); + subnettot(peer_net, 0, d1, sizeof(d1)); + subnettot(&sr->this.client, 0, s3, sizeof(s3)); + subnettot(&sr->that.client, 0, d3, sizeof(d3)); + DBG_log(" fc_try trying " + "%s:%s:%d/%d -> %s:%d/%d vs %s:%s:%d/%d -> %s:%d/%d" + , c->name, s1, c->spd.this.protocol, c->spd.this.port + , d1, c->spd.that.protocol, c->spd.that.port + , d->name, s3, sr->this.protocol, sr->this.port + , d3, sr->that.protocol, sr->that.port); + } #endif /* DEBUG */ - if (!samesubnet(&sr->this.client, our_net)) - continue; + if (!samesubnet(&sr->this.client, our_net)) + continue; - if (sr->that.has_client) - { - if (sr->that.has_client_wildcard) - { - if (!subnetinsubnet(peer_net, &sr->that.client)) - continue; - } - else - { - if (!samesubnet(&sr->that.client, peer_net) && !is_virtual_connection(d)) - continue; - if (is_virtual_connection(d) - && (!is_virtual_net_allowed(d, peer_net, &c->spd.that.host_addr) - || is_virtual_net_used(peer_net, peer_id?peer_id:&c->spd.that.id))) - continue; - } - } - else - { - if (!peer_net_is_host) - continue; - } + if (sr->that.has_client) + { + if (sr->that.has_client_wildcard) + { + if (!subnetinsubnet(peer_net, &sr->that.client)) + continue; + } + else + { + if (!samesubnet(&sr->that.client, peer_net) && !is_virtual_connection(d)) + continue; + if (is_virtual_connection(d) + && (!is_virtual_net_allowed(d, peer_net, &c->spd.that.host_addr) + || is_virtual_net_used(peer_net, peer_id?peer_id:&c->spd.that.id))) + continue; + } + } + else + { + if (!peer_net_is_host) + continue; + } - /* We've run the gauntlet -- success: - * We've got an exact match of subnets. - * The connection is feasible, but we continue looking for the best. - * The highest priority wins, implementing eroute-like rule. - * - a routed connection is preferrred - * - given that, the smallest number of ID wildcards are preferred - * - given that, the shortest CA pathlength is preferred - */ - prio = PRIO_WEIGHT * routed(sr->routing) - + WILD_WEIGHT * (MAX_WILDCARDS - wildcards) - + PATH_WEIGHT * (MAX_CA_PATH_LEN - pathlen) - + 1; - if (prio > best_prio) - { - best = d; - best_prio = prio; - } + /* We've run the gauntlet -- success: + * We've got an exact match of subnets. + * The connection is feasible, but we continue looking for the best. + * The highest priority wins, implementing eroute-like rule. + * - a routed connection is preferrred + * - given that, the smallest number of ID wildcards are preferred + * - given that, the shortest CA pathlength is preferred + */ + prio = PRIO_WEIGHT * routed(sr->routing) + + WILD_WEIGHT * (MAX_WILDCARDS - wildcards) + + PATH_WEIGHT * (MAX_CA_PATH_LEN - pathlen) + + 1; + if (prio > best_prio) + { + best = d; + best_prio = prio; + } + } } - } - if (best != NULL && NEVER_NEGOTIATE(best->policy)) - best = NULL; + if (best != NULL && NEVER_NEGOTIATE(best->policy)) + best = NULL; - DBG(DBG_CONTROLMORE, - DBG_log(" fc_try concluding with %s [%ld]" - , (best ? best->name : "none"), best_prio) - ) - return best; + DBG(DBG_CONTROLMORE, + DBG_log(" fc_try concluding with %s [%ld]" + , (best ? best->name : "none"), best_prio) + ) + return best; } static struct connection * @@ -3657,92 +3657,92 @@ fc_try_oppo(const struct connection *c , chunk_t peer_ca , const ietfAttrList_t *peer_list) { - struct connection *d; - struct connection *best = NULL; - policy_prio_t best_prio = BOTTOM_PRIO; - int wildcards, pathlen; + struct connection *d; + struct connection *best = NULL; + policy_prio_t best_prio = BOTTOM_PRIO; + int wildcards, pathlen; - for (d = hp->connections; d != NULL; d = d->hp_next) - { - struct spd_route *sr; - policy_prio_t prio; - - if (d->policy & POLICY_GROUP) - continue; - - if (!(same_id(&c->spd.this.id, &d->spd.this.id) - && match_id(&c->spd.that.id, &d->spd.that.id, &wildcards) - && trusted_ca(peer_ca, d->spd.that.ca, &pathlen) - && group_membership(peer_list, d->name, d->spd.that.groups))) - continue; - - /* compare protocol and ports */ - if (d->spd.this.protocol != our_protocol - || d->spd.this.port != our_port - || d->spd.that.protocol != peer_protocol - || (d->spd.that.port != peer_port && !d->spd.that.has_port_wildcard)) - continue; - - /* Opportunistic case: - * our_net must be inside d->spd.this.client - * and peer_net must be inside d->spd.that.client - * Note: this host_pair chain also has shunt - * eroute conns (clear, drop), but they won't - * be marked as opportunistic. - */ - for (sr = &d->spd; sr != NULL; sr = sr->next) + for (d = hp->connections; d != NULL; d = d->hp_next) { -#ifdef DEBUG - if (DBGP(DBG_CONTROLMORE)) - { - char s1[SUBNETTOT_BUF],d1[SUBNETTOT_BUF]; - char s3[SUBNETTOT_BUF],d3[SUBNETTOT_BUF]; + struct spd_route *sr; + policy_prio_t prio; - subnettot(our_net, 0, s1, sizeof(s1)); - subnettot(peer_net, 0, d1, sizeof(d1)); - subnettot(&sr->this.client, 0, s3, sizeof(s3)); - subnettot(&sr->that.client, 0, d3, sizeof(d3)); - DBG_log(" fc_try_oppo trying %s:%s -> %s vs %s:%s -> %s" - , c->name, s1, d1, d->name, s3, d3); - } + if (d->policy & POLICY_GROUP) + continue; + + if (!(same_id(&c->spd.this.id, &d->spd.this.id) + && match_id(&c->spd.that.id, &d->spd.that.id, &wildcards) + && trusted_ca(peer_ca, d->spd.that.ca, &pathlen) + && group_membership(peer_list, d->name, d->spd.that.groups))) + continue; + + /* compare protocol and ports */ + if (d->spd.this.protocol != our_protocol + || d->spd.this.port != our_port + || d->spd.that.protocol != peer_protocol + || (d->spd.that.port != peer_port && !d->spd.that.has_port_wildcard)) + continue; + + /* Opportunistic case: + * our_net must be inside d->spd.this.client + * and peer_net must be inside d->spd.that.client + * Note: this host_pair chain also has shunt + * eroute conns (clear, drop), but they won't + * be marked as opportunistic. + */ + for (sr = &d->spd; sr != NULL; sr = sr->next) + { +#ifdef DEBUG + if (DBGP(DBG_CONTROLMORE)) + { + char s1[SUBNETTOT_BUF],d1[SUBNETTOT_BUF]; + char s3[SUBNETTOT_BUF],d3[SUBNETTOT_BUF]; + + subnettot(our_net, 0, s1, sizeof(s1)); + subnettot(peer_net, 0, d1, sizeof(d1)); + subnettot(&sr->this.client, 0, s3, sizeof(s3)); + subnettot(&sr->that.client, 0, d3, sizeof(d3)); + DBG_log(" fc_try_oppo trying %s:%s -> %s vs %s:%s -> %s" + , c->name, s1, d1, d->name, s3, d3); + } #endif /* DEBUG */ - if (!subnetinsubnet(our_net, &sr->this.client) - || !subnetinsubnet(peer_net, &sr->that.client)) - continue; + if (!subnetinsubnet(our_net, &sr->this.client) + || !subnetinsubnet(peer_net, &sr->that.client)) + continue; - /* The connection is feasible, but we continue looking for the best. - * The highest priority wins, implementing eroute-like rule. - * - our smallest client subnet is preferred (longest mask) - * - given that, his smallest client subnet is preferred - * - given that, a routed connection is preferrred - * - given that, the smallest number of ID wildcards are preferred - * - given that, the shortest CA pathlength is preferred - */ - prio = PRIO_WEIGHT * (d->prio + routed(sr->routing)) - + WILD_WEIGHT * (MAX_WILDCARDS - wildcards) - + PATH_WEIGHT * (MAX_CA_PATH_LEN - pathlen); - if (prio > best_prio) - { - best = d; - best_prio = prio; - } + /* The connection is feasible, but we continue looking for the best. + * The highest priority wins, implementing eroute-like rule. + * - our smallest client subnet is preferred (longest mask) + * - given that, his smallest client subnet is preferred + * - given that, a routed connection is preferrred + * - given that, the smallest number of ID wildcards are preferred + * - given that, the shortest CA pathlength is preferred + */ + prio = PRIO_WEIGHT * (d->prio + routed(sr->routing)) + + WILD_WEIGHT * (MAX_WILDCARDS - wildcards) + + PATH_WEIGHT * (MAX_CA_PATH_LEN - pathlen); + if (prio > best_prio) + { + best = d; + best_prio = prio; + } + } } - } - /* if the best wasn't opportunistic, we fail: it must be a shunt */ - if (best != NULL - && (NEVER_NEGOTIATE(best->policy) - || (best->policy & POLICY_OPPO) == LEMPTY)) - { - best = NULL; - } + /* if the best wasn't opportunistic, we fail: it must be a shunt */ + if (best != NULL + && (NEVER_NEGOTIATE(best->policy) + || (best->policy & POLICY_OPPO) == LEMPTY)) + { + best = NULL; + } - DBG(DBG_CONTROLMORE, - DBG_log(" fc_try_oppo concluding with %s [%ld]" - , (best ? best->name : "none"), best_prio) - ) - return best; + DBG(DBG_CONTROLMORE, + DBG_log(" fc_try_oppo concluding with %s [%ld]" + , (best ? best->name : "none"), best_prio) + ) + return best; } @@ -3752,28 +3752,28 @@ fc_try_oppo(const struct connection *c chunk_t get_peer_ca_and_groups(struct connection *c, const ietfAttrList_t **peer_list) { - struct state *p1st = find_phase1_state(c, ISAKMP_SA_ESTABLISHED_STATES); + struct state *p1st = find_phase1_state(c, ISAKMP_SA_ESTABLISHED_STATES); - *peer_list = NULL; + *peer_list = NULL; - if (p1st != NULL - && p1st->st_peer_pubkey != NULL - && p1st->st_peer_pubkey->issuer.ptr != NULL) - { - x509acert_t *ac = get_x509acert(p1st->st_peer_pubkey->issuer - , p1st->st_peer_pubkey->serial);; - - if (ac != NULL && verify_x509acert(ac, strict_crl_policy)) - *peer_list = ac->groups; - else + if (p1st != NULL + && p1st->st_peer_pubkey != NULL + && p1st->st_peer_pubkey->issuer.ptr != NULL) { - DBG(DBG_CONTROL, - DBG_log("no valid attribute cert found") - ) + x509acert_t *ac = get_x509acert(p1st->st_peer_pubkey->issuer + , p1st->st_peer_pubkey->serial);; + + if (ac != NULL && verify_x509acert(ac, strict_crl_policy)) + *peer_list = ac->groups; + else + { + DBG(DBG_CONTROL, + DBG_log("no valid attribute cert found") + ) + } + return p1st->st_peer_pubkey->issuer; } - return p1st->st_peer_pubkey->issuer; - } - return chunk_empty; + return chunk_empty; } struct connection * @@ -3782,325 +3782,325 @@ find_client_connection(struct connection *c , const u_int8_t our_protocol, const u_int16_t our_port , const u_int8_t peer_protocol, const u_int16_t peer_port) { - struct connection *d; - struct spd_route *sr; + struct connection *d; + struct spd_route *sr; - const ietfAttrList_t *peer_list = NULL; - chunk_t peer_ca = get_peer_ca_and_groups(c, &peer_list); + const ietfAttrList_t *peer_list = NULL; + chunk_t peer_ca = get_peer_ca_and_groups(c, &peer_list); #ifdef DEBUG - if (DBGP(DBG_CONTROLMORE)) - { - char s1[SUBNETTOT_BUF],d1[SUBNETTOT_BUF]; - - subnettot(our_net, 0, s1, sizeof(s1)); - subnettot(peer_net, 0, d1, sizeof(d1)); - - DBG_log("find_client_connection starting with %s" - , (c ? c->name : "(none)")); - DBG_log(" looking for %s:%d/%d -> %s:%d/%d" - , s1, our_protocol, our_port - , d1, peer_protocol, peer_port); - } -#endif /* DEBUG */ - - /* give priority to current connection - * but even greater priority to a routed concrete connection - */ - { - struct connection *unrouted = NULL; - int srnum = -1; - - for (sr = &c->spd; unrouted == NULL && sr != NULL; sr = sr->next) + if (DBGP(DBG_CONTROLMORE)) { - srnum++; + char s1[SUBNETTOT_BUF],d1[SUBNETTOT_BUF]; -#ifdef DEBUG - if (DBGP(DBG_CONTROLMORE)) - { - char s2[SUBNETTOT_BUF],d2[SUBNETTOT_BUF]; + subnettot(our_net, 0, s1, sizeof(s1)); + subnettot(peer_net, 0, d1, sizeof(d1)); - subnettot(&sr->this.client, 0, s2, sizeof(s2)); - subnettot(&sr->that.client, 0, d2, sizeof(d2)); - DBG_log(" concrete checking against sr#%d %s -> %s" - , srnum, s2, d2); - } + DBG_log("find_client_connection starting with %s" + , (c ? c->name : "(none)")); + DBG_log(" looking for %s:%d/%d -> %s:%d/%d" + , s1, our_protocol, our_port + , d1, peer_protocol, peer_port); + } #endif /* DEBUG */ - if (samesubnet(&sr->this.client, our_net) - && samesubnet(&sr->that.client, peer_net) - && sr->this.protocol == our_protocol - && sr->this.port == our_port - && sr->that.protocol == peer_protocol - && sr->that.port == peer_port - && group_membership(peer_list, c->name, sr->that.groups)) - { - passert(oriented(*c)); - if (routed(sr->routing)) - return c; + /* give priority to current connection + * but even greater priority to a routed concrete connection + */ + { + struct connection *unrouted = NULL; + int srnum = -1; - unrouted = c; - } + for (sr = &c->spd; unrouted == NULL && sr != NULL; sr = sr->next) + { + srnum++; + +#ifdef DEBUG + if (DBGP(DBG_CONTROLMORE)) + { + char s2[SUBNETTOT_BUF],d2[SUBNETTOT_BUF]; + + subnettot(&sr->this.client, 0, s2, sizeof(s2)); + subnettot(&sr->that.client, 0, d2, sizeof(d2)); + DBG_log(" concrete checking against sr#%d %s -> %s" + , srnum, s2, d2); + } +#endif /* DEBUG */ + + if (samesubnet(&sr->this.client, our_net) + && samesubnet(&sr->that.client, peer_net) + && sr->this.protocol == our_protocol + && sr->this.port == our_port + && sr->that.protocol == peer_protocol + && sr->that.port == peer_port + && group_membership(peer_list, c->name, sr->that.groups)) + { + passert(oriented(*c)); + if (routed(sr->routing)) + return c; + + unrouted = c; + } + } + + /* exact match? */ + d = fc_try(c, c->host_pair, NULL, our_net, peer_net + , our_protocol, our_port, peer_protocol, peer_port + , peer_ca, peer_list); + + DBG(DBG_CONTROLMORE, + DBG_log(" fc_try %s gives %s" + , c->name + , (d ? d->name : "none")) + ) + + if (d == NULL) + d = unrouted; } - /* exact match? */ - d = fc_try(c, c->host_pair, NULL, our_net, peer_net - , our_protocol, our_port, peer_protocol, peer_port - , peer_ca, peer_list); - - DBG(DBG_CONTROLMORE, - DBG_log(" fc_try %s gives %s" - , c->name - , (d ? d->name : "none")) - ) - if (d == NULL) - d = unrouted; - } - - if (d == NULL) - { - /* look for an abstract connection to match */ - struct spd_route *sr; - struct host_pair *hp = NULL; - - for (sr = &c->spd; hp==NULL && sr != NULL; sr = sr->next) { - hp = find_host_pair(&sr->this.host_addr - , sr->this.host_port - , NULL - , sr->that.host_port); + /* look for an abstract connection to match */ + struct spd_route *sr; + struct host_pair *hp = NULL; + + for (sr = &c->spd; hp==NULL && sr != NULL; sr = sr->next) + { + hp = find_host_pair(&sr->this.host_addr + , sr->this.host_port + , NULL + , sr->that.host_port); #ifdef DEBUG - if (DBGP(DBG_CONTROLMORE)) - { - char s2[SUBNETTOT_BUF],d2[SUBNETTOT_BUF]; + if (DBGP(DBG_CONTROLMORE)) + { + char s2[SUBNETTOT_BUF],d2[SUBNETTOT_BUF]; - subnettot(&sr->this.client, 0, s2, sizeof(s2)); - subnettot(&sr->that.client, 0, d2, sizeof(d2)); + subnettot(&sr->this.client, 0, s2, sizeof(s2)); + subnettot(&sr->that.client, 0, d2, sizeof(d2)); - DBG_log(" checking hostpair %s -> %s is %s" - , s2, d2 - , (hp ? "found" : "not found")); - } + DBG_log(" checking hostpair %s -> %s is %s" + , s2, d2 + , (hp ? "found" : "not found")); + } #endif /* DEBUG */ + } + + if (hp != NULL) + { + /* RW match with actual peer_id or abstract peer_id? */ + d = fc_try(c, hp, NULL, our_net, peer_net + , our_protocol, our_port, peer_protocol, peer_port + , peer_ca, peer_list); + + if (d == NULL + && subnetishost(our_net) + && subnetishost(peer_net)) + { + /* Opportunistic match? + * Always use abstract peer_id. + * Note that later instantiation will result in the same peer_id. + */ + d = fc_try_oppo(c, hp, our_net, peer_net + , our_protocol, our_port, peer_protocol, peer_port + , peer_ca, peer_list); + } + } } - if (hp != NULL) - { - /* RW match with actual peer_id or abstract peer_id? */ - d = fc_try(c, hp, NULL, our_net, peer_net - , our_protocol, our_port, peer_protocol, peer_port - , peer_ca, peer_list); - - if (d == NULL - && subnetishost(our_net) - && subnetishost(peer_net)) - { - /* Opportunistic match? - * Always use abstract peer_id. - * Note that later instantiation will result in the same peer_id. - */ - d = fc_try_oppo(c, hp, our_net, peer_net - , our_protocol, our_port, peer_protocol, peer_port - , peer_ca, peer_list); - } - } - } - - DBG(DBG_CONTROLMORE, - DBG_log(" concluding with d = %s" - , (d ? d->name : "none")) - ) - return d; + DBG(DBG_CONTROLMORE, + DBG_log(" concluding with d = %s" + , (d ? d->name : "none")) + ) + return d; } int connection_compare(const struct connection *ca , const struct connection *cb) { - int ret; + int ret; - /* DBG_log("comparing %s to %s", ca->name, cb->name); */ + /* DBG_log("comparing %s to %s", ca->name, cb->name); */ - ret = strcasecmp(ca->name, cb->name); - if (ret != 0) - return ret; + ret = strcasecmp(ca->name, cb->name); + if (ret != 0) + return ret; - ret = ca->kind - cb->kind; /* note: enum connection_kind behaves like int */ - if (ret != 0) - return ret; + ret = ca->kind - cb->kind; /* note: enum connection_kind behaves like int */ + if (ret != 0) + return ret; - /* same name, and same type */ - switch (ca->kind) - { - case CK_INSTANCE: - return ca->instance_serial < cb->instance_serial ? -1 - : ca->instance_serial > cb->instance_serial ? 1 - : 0; + /* same name, and same type */ + switch (ca->kind) + { + case CK_INSTANCE: + return ca->instance_serial < cb->instance_serial ? -1 + : ca->instance_serial > cb->instance_serial ? 1 + : 0; - default: - return ca->prio < cb->prio ? -1 - : ca->prio > cb->prio ? 1 - : 0; - } + default: + return ca->prio < cb->prio ? -1 + : ca->prio > cb->prio ? 1 + : 0; + } } static int connection_compare_qsort(const void *a, const void *b) { - return connection_compare(*(const struct connection *const *)a - , *(const struct connection *const *)b); + return connection_compare(*(const struct connection *const *)a + , *(const struct connection *const *)b); } void show_connections_status(bool all, const char *name) { - struct connection *c; - int count, i; - struct connection **array; + struct connection *c; + int count, i; + struct connection **array; - /* make an array of connections, and sort it */ - count = 0; - for (c = connections; c != NULL; c = c->ac_next) - { - if (c->ikev1 && (name == NULL || streq(c->name, name))) - count++; - } - array = malloc(sizeof(struct connection *)*count); - - count=0; - for (c = connections; c != NULL; c = c->ac_next) - { - if (c->ikev1 && (name == NULL || streq(c->name, name))) - array[count++]=c; - } - - /* sort it! */ - qsort(array, count, sizeof(struct connection *), connection_compare_qsort); - - for (i = 0; i < count; i++) - { - const char *ifn; - char instance[1 + 10 + 1]; - char prio[POLICY_PRIO_BUF]; - - c = array[i]; - - ifn = oriented(*c)? c->interface->rname : ""; - - instance[0] = '\0'; - if (c->kind == CK_INSTANCE && c->instance_serial != 0) - snprintf(instance, sizeof(instance), "[%lu]", c->instance_serial); - - /* show topology */ + /* make an array of connections, and sort it */ + count = 0; + for (c = connections; c != NULL; c = c->ac_next) { - char topo[CONNECTION_BUF]; - struct spd_route *sr = &c->spd; - int num=0; + if (c->ikev1 && (name == NULL || streq(c->name, name))) + count++; + } + array = malloc(sizeof(struct connection *)*count); - while (sr != NULL) - { - (void) format_connection(topo, sizeof(topo), c, sr); - whack_log(RC_COMMENT, "\"%s\"%s: %s; %s; eroute owner: #%lu" - , c->name, instance, topo - , enum_name(&routing_story, sr->routing) - , sr->eroute_owner); - sr = sr->next; - num++; - } + count=0; + for (c = connections; c != NULL; c = c->ac_next) + { + if (c->ikev1 && (name == NULL || streq(c->name, name))) + array[count++]=c; } - if (all) + /* sort it! */ + qsort(array, count, sizeof(struct connection *), connection_compare_qsort); + + for (i = 0; i < count; i++) { - /* show CAs if defined */ - if (c->spd.this.ca.ptr != NULL || c->spd.that.ca.ptr != NULL) - { - char this_ca[BUF_LEN], that_ca[BUF_LEN]; + const char *ifn; + char instance[1 + 10 + 1]; + char prio[POLICY_PRIO_BUF]; - dntoa_or_null(this_ca, BUF_LEN, c->spd.this.ca, "%any"); - dntoa_or_null(that_ca, BUF_LEN, c->spd.that.ca, "%any"); + c = array[i]; + + ifn = oriented(*c)? c->interface->rname : ""; + + instance[0] = '\0'; + if (c->kind == CK_INSTANCE && c->instance_serial != 0) + snprintf(instance, sizeof(instance), "[%lu]", c->instance_serial); + + /* show topology */ + { + char topo[CONNECTION_BUF]; + struct spd_route *sr = &c->spd; + int num=0; + + while (sr != NULL) + { + (void) format_connection(topo, sizeof(topo), c, sr); + whack_log(RC_COMMENT, "\"%s\"%s: %s; %s; eroute owner: #%lu" + , c->name, instance, topo + , enum_name(&routing_story, sr->routing) + , sr->eroute_owner); + sr = sr->next; + num++; + } + } + + if (all) + { + /* show CAs if defined */ + if (c->spd.this.ca.ptr != NULL || c->spd.that.ca.ptr != NULL) + { + char this_ca[BUF_LEN], that_ca[BUF_LEN]; + + dntoa_or_null(this_ca, BUF_LEN, c->spd.this.ca, "%any"); + dntoa_or_null(that_ca, BUF_LEN, c->spd.that.ca, "%any"); + + whack_log(RC_COMMENT + , "\"%s\"%s: CAs: '%s'...'%s'" + , c->name + , instance + , this_ca + , that_ca); + } + + /* show group attributes if defined */ + if (c->spd.that.groups != NULL) + { + char buf[BUF_LEN]; + + format_groups(c->spd.that.groups, buf, BUF_LEN); + whack_log(RC_COMMENT + , "\"%s\"%s: groups: %s" + , c->name + , instance + , buf); + } + + whack_log(RC_COMMENT + , "\"%s\"%s: ike_life: %lus; ipsec_life: %lus;" + " rekey_margin: %lus; rekey_fuzz: %lu%%; keyingtries: %lu" + , c->name + , instance + , (unsigned long) c->sa_ike_life_seconds + , (unsigned long) c->sa_ipsec_life_seconds + , (unsigned long) c->sa_rekey_margin + , (unsigned long) c->sa_rekey_fuzz + , (unsigned long) c->sa_keying_tries); + + /* show DPD parameters if defined */ + + if (c->dpd_action != DPD_ACTION_NONE) + whack_log(RC_COMMENT + , "\"%s\"%s: dpd_action: %s;" + " dpd_delay: %lus; dpd_timeout: %lus;" + , c->name + , instance + , enum_show(&dpd_action_names, c->dpd_action) + , (unsigned long) c->dpd_delay + , (unsigned long) c->dpd_timeout); + + if (c->policy_next) + { + whack_log(RC_COMMENT + , "\"%s\"%s: policy_next: %s" + , c->name, instance, c->policy_next->name); + } + + /* Note: we display key_from_DNS_on_demand as if policy [lr]KOD */ + fmt_policy_prio(c->prio, prio); + whack_log(RC_COMMENT + , "\"%s\"%s: policy: %s%s%s; prio: %s; interface: %s; " + , c->name + , instance + , prettypolicy(c->policy) + , c->spd.this.key_from_DNS_on_demand? "+lKOD" : "" + , c->spd.that.key_from_DNS_on_demand? "+rKOD" : "" + , prio + , ifn); + } whack_log(RC_COMMENT - , "\"%s\"%s: CAs: '%s'...'%s'" - , c->name - , instance - , this_ca - , that_ca); - } - - /* show group attributes if defined */ - if (c->spd.that.groups != NULL) - { - char buf[BUF_LEN]; - - format_groups(c->spd.that.groups, buf, BUF_LEN); - whack_log(RC_COMMENT - , "\"%s\"%s: groups: %s" - , c->name - , instance - , buf); - } - - whack_log(RC_COMMENT - , "\"%s\"%s: ike_life: %lus; ipsec_life: %lus;" - " rekey_margin: %lus; rekey_fuzz: %lu%%; keyingtries: %lu" - , c->name - , instance - , (unsigned long) c->sa_ike_life_seconds - , (unsigned long) c->sa_ipsec_life_seconds - , (unsigned long) c->sa_rekey_margin - , (unsigned long) c->sa_rekey_fuzz - , (unsigned long) c->sa_keying_tries); - - /* show DPD parameters if defined */ - - if (c->dpd_action != DPD_ACTION_NONE) - whack_log(RC_COMMENT - , "\"%s\"%s: dpd_action: %s;" - " dpd_delay: %lus; dpd_timeout: %lus;" - , c->name - , instance - , enum_show(&dpd_action_names, c->dpd_action) - , (unsigned long) c->dpd_delay - , (unsigned long) c->dpd_timeout); - - if (c->policy_next) - { - whack_log(RC_COMMENT - , "\"%s\"%s: policy_next: %s" - , c->name, instance, c->policy_next->name); - } - - /* Note: we display key_from_DNS_on_demand as if policy [lr]KOD */ - fmt_policy_prio(c->prio, prio); - whack_log(RC_COMMENT - , "\"%s\"%s: policy: %s%s%s; prio: %s; interface: %s; " - , c->name - , instance - , prettypolicy(c->policy) - , c->spd.this.key_from_DNS_on_demand? "+lKOD" : "" - , c->spd.that.key_from_DNS_on_demand? "+rKOD" : "" - , prio - , ifn); + , "\"%s\"%s: newest ISAKMP SA: #%ld; newest IPsec SA: #%ld; " + , c->name + , instance + , c->newest_isakmp_sa + , c->newest_ipsec_sa); + + if (all) + { + ike_alg_show_connection(c, instance); + kernel_alg_show_connection(c, instance); + } } + if (count > 0) + whack_log(RC_COMMENT, BLANK_FORMAT); /* spacer */ - whack_log(RC_COMMENT - , "\"%s\"%s: newest ISAKMP SA: #%ld; newest IPsec SA: #%ld; " - , c->name - , instance - , c->newest_isakmp_sa - , c->newest_ipsec_sa); - - if (all) - { - ike_alg_show_connection(c, instance); - kernel_alg_show_connection(c, instance); - } - } - if (count > 0) - whack_log(RC_COMMENT, BLANK_FORMAT); /* spacer */ - - free(array); + free(array); } /* struct pending, the structure representing Quick Mode @@ -4109,14 +4109,14 @@ show_connections_status(bool all, const char *name) */ struct pending { - int whack_sock; - struct state *isakmp_sa; - struct connection *connection; - lset_t policy; - unsigned long try; - so_serial_t replacing; + int whack_sock; + struct state *isakmp_sa; + struct connection *connection; + lset_t policy; + unsigned long try; + so_serial_t replacing; - struct pending *next; + struct pending *next; }; /* queue a Quick Mode negotiation pending completion of a suitable Main Mode */ @@ -4128,36 +4128,36 @@ add_pending(int whack_sock , unsigned long try , so_serial_t replacing) { - bool already_queued = FALSE; - struct pending *p = c->host_pair->pending; + bool already_queued = FALSE; + struct pending *p = c->host_pair->pending; - while (p != NULL) - { - if (streq(c->name, p->connection->name)) + while (p != NULL) { - already_queued = TRUE; - break; + if (streq(c->name, p->connection->name)) + { + already_queued = TRUE; + break; + } + p = p->next; } - p = p->next; - } - DBG(DBG_CONTROL, - DBG_log("Queuing pending Quick Mode with %s \"%s\"%s" - , ip_str(&c->spd.that.host_addr) - , c->name - , already_queued? " already done" : "") - ) - if (already_queued) - return; + DBG(DBG_CONTROL, + DBG_log("Queuing pending Quick Mode with %s \"%s\"%s" + , ip_str(&c->spd.that.host_addr) + , c->name + , already_queued? " already done" : "") + ) + if (already_queued) + return; - p = malloc_thing(struct pending); - p->whack_sock = whack_sock; - p->isakmp_sa = isakmp_sa; - p->connection = c; - p->policy = policy; - p->try = try; - p->replacing = replacing; - p->next = c->host_pair->pending; - c->host_pair->pending = p; + p = malloc_thing(struct pending); + p->whack_sock = whack_sock; + p->isakmp_sa = isakmp_sa; + p->connection = c; + p->policy = policy; + p->try = try; + p->replacing = replacing; + p->next = c->host_pair->pending; + c->host_pair->pending = p; } /* Release all the whacks awaiting the completion of this state. @@ -4167,157 +4167,157 @@ add_pending(int whack_sock void release_pending_whacks(struct state *st, err_t story) { - struct pending *p; - struct stat stst; + struct pending *p; + struct stat stst; - if (st->st_whack_sock == NULL_FD || fstat(st->st_whack_sock, &stst) != 0) - zero(&stst); /* resulting st_dev/st_ino ought to be distinct */ + if (st->st_whack_sock == NULL_FD || fstat(st->st_whack_sock, &stst) != 0) + zero(&stst); /* resulting st_dev/st_ino ought to be distinct */ - release_whack(st); + release_whack(st); - for (p = st->st_connection->host_pair->pending; p != NULL; p = p->next) - { - if (p->isakmp_sa == st && p->whack_sock != NULL_FD) + for (p = st->st_connection->host_pair->pending; p != NULL; p = p->next) { - struct stat pst; + if (p->isakmp_sa == st && p->whack_sock != NULL_FD) + { + struct stat pst; - if (fstat(p->whack_sock, &pst) == 0 - && (stst.st_dev != pst.st_dev || stst.st_ino != pst.st_ino)) - { - passert(whack_log_fd == NULL_FD); - whack_log_fd = p->whack_sock; - whack_log(RC_COMMENT - , "%s for ISAKMP SA, but releasing whack for pending IPSEC SA" - , story); - whack_log_fd = NULL_FD; - } - close(p->whack_sock); - p->whack_sock = NULL_FD; + if (fstat(p->whack_sock, &pst) == 0 + && (stst.st_dev != pst.st_dev || stst.st_ino != pst.st_ino)) + { + passert(whack_log_fd == NULL_FD); + whack_log_fd = p->whack_sock; + whack_log(RC_COMMENT + , "%s for ISAKMP SA, but releasing whack for pending IPSEC SA" + , story); + whack_log_fd = NULL_FD; + } + close(p->whack_sock); + p->whack_sock = NULL_FD; + } } - } } static void delete_pending(struct pending **pp) { - struct pending *p = *pp; + struct pending *p = *pp; - *pp = p->next; - if (p->connection != NULL) - connection_discard(p->connection); - close_any(p->whack_sock); - free(p); + *pp = p->next; + if (p->connection != NULL) + connection_discard(p->connection); + close_any(p->whack_sock); + free(p); } void unpend(struct state *st) { - struct pending **pp - , *p; + struct pending **pp + , *p; - for (pp = &st->st_connection->host_pair->pending; (p = *pp) != NULL; ) - { - if (p->isakmp_sa == st) + for (pp = &st->st_connection->host_pair->pending; (p = *pp) != NULL; ) { - DBG(DBG_CONTROL, DBG_log("unqueuing pending Quick Mode with %s \"%s\"" - , ip_str(&p->connection->spd.that.host_addr) - , p->connection->name)); - (void) quick_outI1(p->whack_sock, st, p->connection, p->policy - , p->try, p->replacing); - p->whack_sock = NULL_FD; /* ownership transferred */ - p->connection = NULL; /* ownership transferred */ - delete_pending(pp); + if (p->isakmp_sa == st) + { + DBG(DBG_CONTROL, DBG_log("unqueuing pending Quick Mode with %s \"%s\"" + , ip_str(&p->connection->spd.that.host_addr) + , p->connection->name)); + (void) quick_outI1(p->whack_sock, st, p->connection, p->policy + , p->try, p->replacing); + p->whack_sock = NULL_FD; /* ownership transferred */ + p->connection = NULL; /* ownership transferred */ + delete_pending(pp); + } + else + { + pp = &p->next; + } } - else - { - pp = &p->next; - } - } } /* a Main Mode negotiation has been replaced; update any pending */ void update_pending(struct state *os, struct state *ns) { - struct pending *p; + struct pending *p; - for (p = os->st_connection->host_pair->pending; p != NULL; p = p->next) - { - if (p->isakmp_sa == os) - p->isakmp_sa = ns; - if (p->connection->spd.this.host_port != ns->st_connection->spd.this.host_port) + for (p = os->st_connection->host_pair->pending; p != NULL; p = p->next) { - p->connection->spd.this.host_port = ns->st_connection->spd.this.host_port; - p->connection->spd.that.host_port = ns->st_connection->spd.that.host_port; + if (p->isakmp_sa == os) + p->isakmp_sa = ns; + if (p->connection->spd.this.host_port != ns->st_connection->spd.this.host_port) + { + p->connection->spd.this.host_port = ns->st_connection->spd.this.host_port; + p->connection->spd.that.host_port = ns->st_connection->spd.that.host_port; + } } - } } /* a Main Mode negotiation has failed; discard any pending */ void flush_pending_by_state(struct state *st) { - struct host_pair *hp = st->st_connection->host_pair; + struct host_pair *hp = st->st_connection->host_pair; - if (hp != NULL) - { - struct pending **pp - , *p; - - for (pp = &hp->pending; (p = *pp) != NULL; ) + if (hp != NULL) { - if (p->isakmp_sa == st) - delete_pending(pp); - else - pp = &p->next; + struct pending **pp + , *p; + + for (pp = &hp->pending; (p = *pp) != NULL; ) + { + if (p->isakmp_sa == st) + delete_pending(pp); + else + pp = &p->next; + } } - } } /* a connection has been deleted; discard any related pending */ static void flush_pending_by_connection(struct connection *c) { - if (c->host_pair != NULL) - { - struct pending **pp - , *p; - - for (pp = &c->host_pair->pending; (p = *pp) != NULL; ) + if (c->host_pair != NULL) { - if (p->connection == c) - { - p->connection = NULL; /* prevent delete_pending from releasing */ - delete_pending(pp); - } - else - { - pp = &p->next; - } + struct pending **pp + , *p; + + for (pp = &c->host_pair->pending; (p = *pp) != NULL; ) + { + if (p->connection == c) + { + p->connection = NULL; /* prevent delete_pending from releasing */ + delete_pending(pp); + } + else + { + pp = &p->next; + } + } } - } } void show_pending_phase2(const struct host_pair *hp, const struct state *st) { - const struct pending *p; + const struct pending *p; - for (p = hp->pending; p != NULL; p = p->next) - { - if (p->isakmp_sa == st) + for (p = hp->pending; p != NULL; p = p->next) { - /* connection-name state-number [replacing state-number] */ - char cip[CONN_INST_BUF]; + if (p->isakmp_sa == st) + { + /* connection-name state-number [replacing state-number] */ + char cip[CONN_INST_BUF]; - fmt_conn_instance(p->connection, cip); - whack_log(RC_COMMENT, "#%lu: pending Phase 2 for \"%s\"%s replacing #%lu" - , p->isakmp_sa->st_serialno - , p->connection->name - , cip - , p->replacing); + fmt_conn_instance(p->connection, cip); + whack_log(RC_COMMENT, "#%lu: pending Phase 2 for \"%s\"%s replacing #%lu" + , p->isakmp_sa->st_serialno + , p->connection->name + , cip + , p->replacing); + } } - } } /* Delete a connection if it is an instance and it is no longer in use. @@ -4327,18 +4327,18 @@ show_pending_phase2(const struct host_pair *hp, const struct state *st) void connection_discard(struct connection *c) { - if (c->kind == CK_INSTANCE) - { - /* see if it is being used by a pending */ - struct pending *p; + if (c->kind == CK_INSTANCE) + { + /* see if it is being used by a pending */ + struct pending *p; - for (p = c->host_pair->pending; p != NULL; p = p->next) - if (p->connection == c) - return; /* in use, so we're done */ + for (p = c->host_pair->pending; p != NULL; p = p->next) + if (p->connection == c) + return; /* in use, so we're done */ - if (!states_use_connection(c)) - delete_connection(c, FALSE); - } + if (!states_use_connection(c)) + delete_connection(c, FALSE); + } } @@ -4352,32 +4352,32 @@ long eclipse_count = 0; struct connection * eclipsed(struct connection *c, struct spd_route **esrp) { - struct connection *ue; - struct spd_route *sr1 = &c->spd; + struct connection *ue; + struct spd_route *sr1 = &c->spd; - ue = NULL; + ue = NULL; - while (sr1 != NULL && ue != NULL) - { - for (ue = connections; ue != NULL; ue = ue->ac_next) + while (sr1 != NULL && ue != NULL) { - struct spd_route *srue = &ue->spd; + for (ue = connections; ue != NULL; ue = ue->ac_next) + { + struct spd_route *srue = &ue->spd; - while (srue != NULL - && srue->routing == RT_ROUTED_ECLIPSED - && !(samesubnet(&sr1->this.client, &srue->this.client) - && samesubnet(&sr1->that.client, &srue->that.client))) - { - srue = srue->next; - } - if (srue != NULL && srue->routing==RT_ROUTED_ECLIPSED) - { - *esrp = srue; - break; - } + while (srue != NULL + && srue->routing == RT_ROUTED_ECLIPSED + && !(samesubnet(&sr1->this.client, &srue->this.client) + && samesubnet(&sr1->that.client, &srue->that.client))) + { + srue = srue->next; + } + if (srue != NULL && srue->routing==RT_ROUTED_ECLIPSED) + { + *esrp = srue; + break; + } + } } - } - return ue; + return ue; } /* diff --git a/src/pluto/connections.h b/src/pluto/connections.h index 4b6e95749..a81e2c273 100644 --- a/src/pluto/connections.h +++ b/src/pluto/connections.h @@ -118,135 +118,135 @@ * - display format: n,m */ typedef unsigned long policy_prio_t; -#define BOTTOM_PRIO ((policy_prio_t)0) /* smaller than any real prio */ +#define BOTTOM_PRIO ((policy_prio_t)0) /* smaller than any real prio */ #define set_policy_prio(c) { (c)->prio = \ - ((policy_prio_t)(c)->spd.this.client.maskbits << 16) \ - | ((policy_prio_t)(c)->spd.that.client.maskbits << 8) \ - | (policy_prio_t)1; } -#define POLICY_PRIO_BUF (3+1+3+1) + ((policy_prio_t)(c)->spd.this.client.maskbits << 16) \ + | ((policy_prio_t)(c)->spd.that.client.maskbits << 8) \ + | (policy_prio_t)1; } +#define POLICY_PRIO_BUF (3+1+3+1) extern void fmt_policy_prio(policy_prio_t pp, char buf[POLICY_PRIO_BUF]); struct virtual_t; struct end { - struct id id; - ip_address - host_addr, - host_nexthop, - host_srcip; - ip_subnet client; + struct id id; + ip_address + host_addr, + host_nexthop, + host_srcip; + ip_subnet client; - bool key_from_DNS_on_demand; - bool has_client; - bool has_client_wildcard; - bool has_port_wildcard; - bool has_id_wildcards; - bool has_natip; - char *updown; - u_int16_t host_port; /* host order */ - u_int16_t port; /* host order */ - u_int8_t protocol; - cert_t cert; /* end certificate */ - chunk_t ca; /* CA distinguished name */ - struct ietfAttrList *groups;/* access control groups */ - smartcard_t *sc; /* smartcard reader and key info */ - struct virtual_t *virt; - bool modecfg; /* this end: request local address from server */ - /* that end: give local addresses to clients */ - bool hostaccess; /* allow access to host via iptables INPUT/OUTPUT */ - /* rules if client behind host is a subnet */ - bool allow_any; /* IP address is subject to change */ - certpolicy_t sendcert; /* whether or not to send the certificate */ + bool key_from_DNS_on_demand; + bool has_client; + bool has_client_wildcard; + bool has_port_wildcard; + bool has_id_wildcards; + bool has_natip; + char *updown; + u_int16_t host_port; /* host order */ + u_int16_t port; /* host order */ + u_int8_t protocol; + cert_t cert; /* end certificate */ + chunk_t ca; /* CA distinguished name */ + struct ietfAttrList *groups;/* access control groups */ + smartcard_t *sc; /* smartcard reader and key info */ + struct virtual_t *virt; + bool modecfg; /* this end: request local address from server */ + /* that end: give local addresses to clients */ + bool hostaccess; /* allow access to host via iptables INPUT/OUTPUT */ + /* rules if client behind host is a subnet */ + bool allow_any; /* IP address is subject to change */ + certpolicy_t sendcert; /* whether or not to send the certificate */ }; struct spd_route { - struct spd_route *next; - struct end this; - struct end that; - so_serial_t eroute_owner; - enum routing_t routing; /* level of routing in place */ - uint32_t reqid; + struct spd_route *next; + struct end this; + struct end that; + so_serial_t eroute_owner; + enum routing_t routing; /* level of routing in place */ + uint32_t reqid; }; struct connection { - char *name; - bool ikev1; + char *name; + bool ikev1; - lset_t policy; - time_t sa_ike_life_seconds; - time_t sa_ipsec_life_seconds; - time_t sa_rekey_margin; - unsigned long sa_rekey_fuzz; - unsigned long sa_keying_tries; + lset_t policy; + time_t sa_ike_life_seconds; + time_t sa_ipsec_life_seconds; + time_t sa_rekey_margin; + unsigned long sa_rekey_fuzz; + unsigned long sa_keying_tries; - /* RFC 3706 DPD */ - time_t dpd_delay; - time_t dpd_timeout; - dpd_action_t dpd_action; + /* RFC 3706 DPD */ + time_t dpd_delay; + time_t dpd_timeout; + dpd_action_t dpd_action; - char *log_file_name; /* name of log file */ - FILE *log_file; /* possibly open FILE */ - TAILQ_ENTRY(connection) log_link; /* linked list of open conns */ - bool log_file_err; /* only bitch once */ + char *log_file_name; /* name of log file */ + FILE *log_file; /* possibly open FILE */ + TAILQ_ENTRY(connection) log_link; /* linked list of open conns */ + bool log_file_err; /* only bitch once */ - struct spd_route spd; + struct spd_route spd; - /* internal fields: */ + /* internal fields: */ - unsigned long instance_serial; - policy_prio_t prio; - bool instance_initiation_ok; /* this is an instance of a policy that mandates initiate */ - enum connection_kind kind; - const struct iface *interface; /* filled in iff oriented */ + unsigned long instance_serial; + policy_prio_t prio; + bool instance_initiation_ok; /* this is an instance of a policy that mandates initiate */ + enum connection_kind kind; + const struct iface *interface; /* filled in iff oriented */ - so_serial_t /* state object serial number */ - newest_isakmp_sa, - newest_ipsec_sa; + so_serial_t /* state object serial number */ + newest_isakmp_sa, + newest_ipsec_sa; #ifdef DEBUG - lset_t extra_debugging; + lset_t extra_debugging; #endif - /* note: if the client is the gateway, the following must be equal */ - sa_family_t addr_family; /* between gateways */ - sa_family_t tunnel_addr_family; /* between clients */ + /* note: if the client is the gateway, the following must be equal */ + sa_family_t addr_family; /* between gateways */ + sa_family_t tunnel_addr_family; /* between clients */ - struct connection *policy_next; /* if multiple policies, - next one to apply */ + struct connection *policy_next; /* if multiple policies, + next one to apply */ - struct gw_info *gw_info; - struct alg_info_esp *alg_info_esp; - struct alg_info_ike *alg_info_ike; + struct gw_info *gw_info; + struct alg_info_esp *alg_info_esp; + struct alg_info_ike *alg_info_ike; - struct host_pair *host_pair; - struct connection *hp_next; /* host pair list link */ + struct host_pair *host_pair; + struct connection *hp_next; /* host pair list link */ - struct connection *ac_next; /* all connections list link */ + struct connection *ac_next; /* all connections list link */ - generalName_t *requested_ca; /* collected certificate requests */ - bool got_certrequest; + generalName_t *requested_ca; /* collected certificate requests */ + bool got_certrequest; }; #define oriented(c) ((c).interface != NULL) extern bool orient(struct connection *c); extern bool same_peer_ids(const struct connection *c - , const struct connection *d, const struct id *his_id); + , const struct connection *d, const struct id *his_id); /* Format the topology of a connection end, leaving out defaults. * Largest left end looks like: client === host : port [ host_id ] --- hop * Note: if that==NULL, skip nexthop */ -#define END_BUF (SUBNETTOT_BUF + ADDRTOT_BUF + IDTOA_BUF + ADDRTOT_BUF + 10) +#define END_BUF (SUBNETTOT_BUF + ADDRTOT_BUF + IDTOA_BUF + ADDRTOT_BUF + 10) extern size_t format_end(char *buf, size_t buf_len - , const struct end *this, const struct end *that - , bool is_left, lset_t policy); + , const struct end *this, const struct end *that + , bool is_left, lset_t policy); extern void add_connection(const whack_message_t *wm); extern void initiate_connection(const char *name, int whackfd); extern void initiate_opportunistic(const ip_address *our_client - , const ip_address *peer_client, int transport_proto, bool held, int whackfd); + , const ip_address *peer_client, int transport_proto, bool held, int whackfd); extern void terminate_connection(const char *nm); extern void release_connection(struct connection *c, bool relations); extern void delete_connection(struct connection *c, bool relations); @@ -257,87 +257,87 @@ extern void remove_group_instance(const struct connection *group, const char *na extern void release_dead_interfaces(void); extern void check_orientations(void); extern struct connection *route_owner(struct connection *c - , struct spd_route **srp - , struct connection **erop - , struct spd_route **esrp); + , struct spd_route **srp + , struct connection **erop + , struct spd_route **esrp); extern struct connection *shunt_owner(const ip_subnet *ours - , const ip_subnet *his); + , const ip_subnet *his); -extern bool uniqueIDs; /* --uniqueids? */ +extern bool uniqueIDs; /* --uniqueids? */ extern void ISAKMP_SA_established(struct connection *c, so_serial_t serial); #define his_id_was_instantiated(c) ((c)->kind == CK_INSTANCE \ - && (id_is_ipaddr(&(c)->spd.that.id)? \ - sameaddr(&(c)->spd.that.id.ip_addr, &(c)->spd.that.host_addr) : TRUE)) + && (id_is_ipaddr(&(c)->spd.that.id)? \ + sameaddr(&(c)->spd.that.id.ip_addr, &(c)->spd.that.host_addr) : TRUE)) -struct state; /* forward declaration of tag (defined in state.h) */ +struct state; /* forward declaration of tag (defined in state.h) */ extern struct connection - *con_by_name(const char *nm, bool strict), - *find_host_connection(const ip_address *me, u_int16_t my_port - , const ip_address *him, u_int16_t his_port, lset_t policy), - *refine_host_connection(const struct state *st, const struct id *id - , chunk_t peer_ca), - *find_client_connection(struct connection *c - , const ip_subnet *our_net - , const ip_subnet *peer_net - , const u_int8_t our_protocol - , const u_int16_t out_port - , const u_int8_t peer_protocol - , const u_int16_t peer_port), - *find_connection_by_reqid(uint32_t reqid); + *con_by_name(const char *nm, bool strict), + *find_host_connection(const ip_address *me, u_int16_t my_port + , const ip_address *him, u_int16_t his_port, lset_t policy), + *refine_host_connection(const struct state *st, const struct id *id + , chunk_t peer_ca), + *find_client_connection(struct connection *c + , const ip_subnet *our_net + , const ip_subnet *peer_net + , const u_int8_t our_protocol + , const u_int16_t out_port + , const u_int8_t peer_protocol + , const u_int16_t peer_port), + *find_connection_by_reqid(uint32_t reqid); extern struct connection * find_connection_for_clients(struct spd_route **srp - , const ip_address *our_client - , const ip_address *peer_client - , int transport_proto); + , const ip_address *our_client + , const ip_address *peer_client + , int transport_proto); extern chunk_t get_peer_ca_and_groups(struct connection *c - , const ietfAttrList_t **peer_list); - + , const ietfAttrList_t **peer_list); + /* instantiating routines * Note: connection_discard() is in state.h because all its work * is looking through state objects. */ -struct gw_info; /* forward declaration of tag (defined in dnskey.h) */ -struct alg_info; /* forward declaration of tag (defined in alg_info.h) */ +struct gw_info; /* forward declaration of tag (defined in dnskey.h) */ +struct alg_info; /* forward declaration of tag (defined in alg_info.h) */ extern struct connection *rw_instantiate(struct connection *c - , const ip_address *him - , u_int16_t his_port - , const ip_subnet *his_net - , const struct id *his_id); + , const ip_address *him + , u_int16_t his_port + , const ip_subnet *his_net + , const struct id *his_id); extern struct connection *oppo_instantiate(struct connection *c - , const ip_address *him - , const struct id *his_id - , struct gw_info *gw - , const ip_address *our_client - , const ip_address *peer_client); + , const ip_address *him + , const struct id *his_id + , struct gw_info *gw + , const ip_address *our_client + , const ip_address *peer_client); extern struct connection *build_outgoing_opportunistic_connection(struct gw_info *gw - , const ip_address *our_client - , const ip_address *peer_client); + , const ip_address *our_client + , const ip_address *peer_client); /* worst case: "[" serial "] " myclient "=== ..." peer "===" hisclient '\0' */ #define CONN_INST_BUF \ - (2 + 10 + 1 + SUBNETTOT_BUF + 7 + ADDRTOT_BUF + 3 + SUBNETTOT_BUF + 1) + (2 + 10 + 1 + SUBNETTOT_BUF + 7 + ADDRTOT_BUF + 3 + SUBNETTOT_BUF + 1) extern void fmt_conn_instance(const struct connection *c - , char buf[CONN_INST_BUF]); + , char buf[CONN_INST_BUF]); /* operations on "pending", the structure representing Quick Mode * negotiations delayed until a Keying Channel has been negotiated. */ -struct pending; /* forward declaration (opaque outside connections.c) */ +struct pending; /* forward declaration (opaque outside connections.c) */ extern void add_pending(int whack_sock - , struct state *isakmp_sa - , struct connection *c - , lset_t policy - , unsigned long try - , so_serial_t replacing); + , struct state *isakmp_sa + , struct connection *c + , lset_t policy + , unsigned long try + , so_serial_t replacing); extern void release_pending_whacks(struct state *st, err_t story); extern void unpend(struct state *st); @@ -360,9 +360,9 @@ extern struct connection *eclipsed(struct connection *c, struct spd_route **); extern void show_connections_status(bool all, const char *name); extern int connection_compare(const struct connection *ca - , const struct connection *cb); + , const struct connection *cb); extern void update_host_pair(const char *why, struct connection *c - , const ip_address *myaddr, u_int16_t myport - , const ip_address *hisaddr, u_int16_t hisport); + , const ip_address *myaddr, u_int16_t myport + , const ip_address *hisaddr, u_int16_t hisport); #endif /* _CONNECTIONS_H */ diff --git a/src/pluto/constants.c b/src/pluto/constants.c index e2af4afb0..199f8f019 100644 --- a/src/pluto/constants.c +++ b/src/pluto/constants.c @@ -36,93 +36,93 @@ const char compile_time_interop_options[] = "" #ifdef THREADS - " THREADS" + " THREADS" #endif #ifdef LIBCURL - " LIBCURL" + " LIBCURL" #endif #ifdef LIBLDAP - " LIBLDAP" + " LIBLDAP" #endif #ifdef SMARTCARD - " SMARTCARD" + " SMARTCARD" #endif #ifdef VENDORID - " VENDORID" + " VENDORID" #endif #ifdef CISCO_QUIRKS - " CISCO_QUIRKS" + " CISCO_QUIRKS" #endif #ifdef USE_KEYRR - " KEYRR" + " KEYRR" #endif - ; + ; /* version */ static const char *const version_name[] = { - "ISAKMP Version 1.0", + "ISAKMP Version 1.0", }; enum_names version_names = - { ISAKMP_MAJOR_VERSION< if not officially defined */ static const char *const esp_transform_name_high[] = { - "ESP_SERPENT", - "ESP_TWOFISH" - }; + "ESP_SERPENT", + "ESP_TWOFISH" + }; enum_names esp_transformid_names_high = - { ESP_SERPENT, ESP_TWOFISH, esp_transform_name_high, NULL }; + { ESP_SERPENT, ESP_TWOFISH, esp_transform_name_high, NULL }; enum_names esp_transformid_names = - { ESP_DES_IV64, ESP_CAMELLIA, esp_transform_name, &esp_transformid_names_high }; + { ESP_DES_IV64, ESP_CAMELLIA, esp_transform_name, &esp_transformid_names_high }; /* IPCOMP transform values */ static const char *const ipcomp_transform_name[] = { - "IPCOMP_OUI", - "IPCOMP_DEFLAT", - "IPCOMP_LZS", - "IPCOMP_LZJH", - }; + "IPCOMP_OUI", + "IPCOMP_DEFLAT", + "IPCOMP_LZS", + "IPCOMP_LZJH", + }; enum_names ipcomp_transformid_names = - { IPCOMP_OUI, IPCOMP_LZJH, ipcomp_transform_name, NULL }; + { IPCOMP_OUI, IPCOMP_LZJH, ipcomp_transform_name, NULL }; /* Identification type values */ static const char *const ident_name[] = { - "ID_IPV4_ADDR", - "ID_FQDN", - "ID_USER_FQDN", - "ID_IPV4_ADDR_SUBNET", - "ID_IPV6_ADDR", - "ID_IPV6_ADDR_SUBNET", - "ID_IPV4_ADDR_RANGE", - "ID_IPV6_ADDR_RANGE", - "ID_DER_ASN1_DN", - "ID_DER_ASN1_GN", - "ID_KEY_ID", - }; + "ID_IPV4_ADDR", + "ID_FQDN", + "ID_USER_FQDN", + "ID_IPV4_ADDR_SUBNET", + "ID_IPV6_ADDR", + "ID_IPV6_ADDR_SUBNET", + "ID_IPV4_ADDR_RANGE", + "ID_IPV6_ADDR_RANGE", + "ID_DER_ASN1_DN", + "ID_DER_ASN1_GN", + "ID_KEY_ID", + }; enum_names ident_names = - { ID_IPV4_ADDR, ID_KEY_ID, ident_name, NULL }; + { ID_IPV4_ADDR, ID_KEY_ID, ident_name, NULL }; /* Certificate type values */ static const char *const cert_type_name[] = { - "CERT_NONE", - "CERT_PKCS7_WRAPPED_X509", - "CERT_PGP", - "CERT_DNS_SIGNED_KEY", - "CERT_X509_SIGNATURE", - "CERT_X509_KEY_EXCHANGE", - "CERT_KERBEROS_TOKENS", - "CERT_CRL", - "CERT_ARL", - "CERT_SPKI", - "CERT_X509_ATTRIBUTE", - }; + "CERT_NONE", + "CERT_PKCS7_WRAPPED_X509", + "CERT_PGP", + "CERT_DNS_SIGNED_KEY", + "CERT_X509_SIGNATURE", + "CERT_X509_KEY_EXCHANGE", + "CERT_KERBEROS_TOKENS", + "CERT_CRL", + "CERT_ARL", + "CERT_SPKI", + "CERT_X509_ATTRIBUTE", + }; enum_names cert_type_names = - { CERT_NONE, CERT_X509_ATTRIBUTE, cert_type_name, NULL }; + { CERT_NONE, CERT_X509_ATTRIBUTE, cert_type_name, NULL }; /* Certificate policy names */ static const char *const cert_policy_name[] = { - "ALWAYS_SEND", - "SEND_IF_ASKED", - "NEVER_SEND", - }; + "ALWAYS_SEND", + "SEND_IF_ASKED", + "NEVER_SEND", + }; enum_names cert_policy_names = - { CERT_ALWAYS_SEND, CERT_NEVER_SEND, cert_policy_name, NULL }; + { CERT_ALWAYS_SEND, CERT_NEVER_SEND, cert_policy_name, NULL }; /* Goal BITs for establishing an SA * Note: we drop the POLICY_ prefix so that logs are more concise. */ const char *const sa_policy_bit_names[] = { - "PSK", - "RSASIG", - "ENCRYPT", - "AUTHENTICATE", - "COMPRESS", - "TUNNEL", - "PFS", - "DISABLEARRIVALCHECK", - "SHUNT0", - "SHUNT1", - "FAILSHUNT0", - "FAILSHUNT1", - "DONTREKEY", - "OPPORTUNISTIC", - "GROUP", - "GROUTED", - "UP", - "MODECFGPUSH", - "XAUTHPSK", - "XAUTHRSASIG", - "XAUTHSERVER", - "DONTREAUTH", - "BEET", - "MOBIKE", - "ECDSA", - "PROXY", - NULL - }; + "PSK", + "RSASIG", + "ENCRYPT", + "AUTHENTICATE", + "COMPRESS", + "TUNNEL", + "PFS", + "DISABLEARRIVALCHECK", + "SHUNT0", + "SHUNT1", + "FAILSHUNT0", + "FAILSHUNT1", + "DONTREKEY", + "OPPORTUNISTIC", + "GROUP", + "GROUTED", + "UP", + "MODECFGPUSH", + "XAUTHPSK", + "XAUTHRSASIG", + "XAUTHSERVER", + "DONTREAUTH", + "BEET", + "MOBIKE", + "ECDSA", + "PROXY", + NULL + }; const char *const policy_shunt_names[4] = { - "TRAP", - "PASS", - "DROP", - "REJECT", - }; + "TRAP", + "PASS", + "DROP", + "REJECT", + }; const char *const policy_fail_names[4] = { - "NONE", - "PASS", - "DROP", - "REJECT", - }; + "NONE", + "PASS", + "DROP", + "REJECT", + }; /* Oakley transform attributes * oakley_attr_bit_names does double duty: it is used for enum names @@ -542,172 +542,172 @@ const char *const policy_fail_names[4] = { */ const char *const oakley_attr_bit_names[] = { - "OAKLEY_ENCRYPTION_ALGORITHM", - "OAKLEY_HASH_ALGORITHM", - "OAKLEY_AUTHENTICATION_METHOD", - "OAKLEY_GROUP_DESCRIPTION", - "OAKLEY_GROUP_TYPE", - "OAKLEY_GROUP_PRIME", - "OAKLEY_GROUP_GENERATOR_ONE", - "OAKLEY_GROUP_GENERATOR_TWO", - "OAKLEY_GROUP_CURVE_A", - "OAKLEY_GROUP_CURVE_B", - "OAKLEY_LIFE_TYPE", - "OAKLEY_LIFE_DURATION", - "OAKLEY_PRF", - "OAKLEY_KEY_LENGTH", - "OAKLEY_FIELD_SIZE", - "OAKLEY_GROUP_ORDER", - "OAKLEY_BLOCK_SIZE", - NULL - }; + "OAKLEY_ENCRYPTION_ALGORITHM", + "OAKLEY_HASH_ALGORITHM", + "OAKLEY_AUTHENTICATION_METHOD", + "OAKLEY_GROUP_DESCRIPTION", + "OAKLEY_GROUP_TYPE", + "OAKLEY_GROUP_PRIME", + "OAKLEY_GROUP_GENERATOR_ONE", + "OAKLEY_GROUP_GENERATOR_TWO", + "OAKLEY_GROUP_CURVE_A", + "OAKLEY_GROUP_CURVE_B", + "OAKLEY_LIFE_TYPE", + "OAKLEY_LIFE_DURATION", + "OAKLEY_PRF", + "OAKLEY_KEY_LENGTH", + "OAKLEY_FIELD_SIZE", + "OAKLEY_GROUP_ORDER", + "OAKLEY_BLOCK_SIZE", + NULL + }; static const char *const oakley_var_attr_name[] = { - "OAKLEY_GROUP_PRIME (variable length)", - "OAKLEY_GROUP_GENERATOR_ONE (variable length)", - "OAKLEY_GROUP_GENERATOR_TWO (variable length)", - "OAKLEY_GROUP_CURVE_A (variable length)", - "OAKLEY_GROUP_CURVE_B (variable length)", - NULL, - "OAKLEY_LIFE_DURATION (variable length)", - NULL, - NULL, - NULL, - "OAKLEY_GROUP_ORDER (variable length)", - }; + "OAKLEY_GROUP_PRIME (variable length)", + "OAKLEY_GROUP_GENERATOR_ONE (variable length)", + "OAKLEY_GROUP_GENERATOR_TWO (variable length)", + "OAKLEY_GROUP_CURVE_A (variable length)", + "OAKLEY_GROUP_CURVE_B (variable length)", + NULL, + "OAKLEY_LIFE_DURATION (variable length)", + NULL, + NULL, + NULL, + "OAKLEY_GROUP_ORDER (variable length)", + }; static enum_names oakley_attr_desc_tv = { - OAKLEY_ENCRYPTION_ALGORITHM + ISAKMP_ATTR_AF_TV, - OAKLEY_GROUP_ORDER + ISAKMP_ATTR_AF_TV, oakley_attr_bit_names, NULL }; + OAKLEY_ENCRYPTION_ALGORITHM + ISAKMP_ATTR_AF_TV, + OAKLEY_GROUP_ORDER + ISAKMP_ATTR_AF_TV, oakley_attr_bit_names, NULL }; enum_names oakley_attr_names = { - OAKLEY_GROUP_PRIME, OAKLEY_GROUP_ORDER, - oakley_var_attr_name, &oakley_attr_desc_tv }; + OAKLEY_GROUP_PRIME, OAKLEY_GROUP_ORDER, + oakley_var_attr_name, &oakley_attr_desc_tv }; /* for each Oakley attribute, which enum_names describes its values? */ enum_names *oakley_attr_val_descs[] = { - NULL, /* (none) */ - &oakley_enc_names, /* OAKLEY_ENCRYPTION_ALGORITHM */ - &oakley_hash_names, /* OAKLEY_HASH_ALGORITHM */ - &oakley_auth_names, /* OAKLEY_AUTHENTICATION_METHOD */ - &oakley_group_names, /* OAKLEY_GROUP_DESCRIPTION */ - &oakley_group_type_names,/* OAKLEY_GROUP_TYPE */ - NULL, /* OAKLEY_GROUP_PRIME */ - NULL, /* OAKLEY_GROUP_GENERATOR_ONE */ - NULL, /* OAKLEY_GROUP_GENERATOR_TWO */ - NULL, /* OAKLEY_GROUP_CURVE_A */ - NULL, /* OAKLEY_GROUP_CURVE_B */ - &oakley_lifetime_names, /* OAKLEY_LIFE_TYPE */ - NULL, /* OAKLEY_LIFE_DURATION */ - &oakley_prf_names, /* OAKLEY_PRF */ - NULL, /* OAKLEY_KEY_LENGTH */ - NULL, /* OAKLEY_FIELD_SIZE */ - NULL, /* OAKLEY_GROUP_ORDER */ - }; + NULL, /* (none) */ + &oakley_enc_names, /* OAKLEY_ENCRYPTION_ALGORITHM */ + &oakley_hash_names, /* OAKLEY_HASH_ALGORITHM */ + &oakley_auth_names, /* OAKLEY_AUTHENTICATION_METHOD */ + &oakley_group_names, /* OAKLEY_GROUP_DESCRIPTION */ + &oakley_group_type_names,/* OAKLEY_GROUP_TYPE */ + NULL, /* OAKLEY_GROUP_PRIME */ + NULL, /* OAKLEY_GROUP_GENERATOR_ONE */ + NULL, /* OAKLEY_GROUP_GENERATOR_TWO */ + NULL, /* OAKLEY_GROUP_CURVE_A */ + NULL, /* OAKLEY_GROUP_CURVE_B */ + &oakley_lifetime_names, /* OAKLEY_LIFE_TYPE */ + NULL, /* OAKLEY_LIFE_DURATION */ + &oakley_prf_names, /* OAKLEY_PRF */ + NULL, /* OAKLEY_KEY_LENGTH */ + NULL, /* OAKLEY_FIELD_SIZE */ + NULL, /* OAKLEY_GROUP_ORDER */ + }; /* IPsec DOI attributes (RFC 2407 "IPsec DOI" section 4.5) */ static const char *const ipsec_attr_name[] = { - "SA_LIFE_TYPE", - "SA_LIFE_DURATION", - "GROUP_DESCRIPTION", - "ENCAPSULATION_MODE", - "AUTH_ALGORITHM", - "KEY_LENGTH", - "KEY_ROUNDS", - "COMPRESS_DICT_SIZE", - "COMPRESS_PRIVATE_ALG", - }; + "SA_LIFE_TYPE", + "SA_LIFE_DURATION", + "GROUP_DESCRIPTION", + "ENCAPSULATION_MODE", + "AUTH_ALGORITHM", + "KEY_LENGTH", + "KEY_ROUNDS", + "COMPRESS_DICT_SIZE", + "COMPRESS_PRIVATE_ALG", + }; static const char *const ipsec_var_attr_name[] = { - "SA_LIFE_DURATION (variable length)", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "COMPRESS_PRIVATE_ALG (variable length)", - }; + "SA_LIFE_DURATION (variable length)", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "COMPRESS_PRIVATE_ALG (variable length)", + }; static enum_names ipsec_attr_desc_tv = { - SA_LIFE_TYPE + ISAKMP_ATTR_AF_TV, - COMPRESS_PRIVATE_ALG + ISAKMP_ATTR_AF_TV, - ipsec_attr_name, NULL }; + SA_LIFE_TYPE + ISAKMP_ATTR_AF_TV, + COMPRESS_PRIVATE_ALG + ISAKMP_ATTR_AF_TV, + ipsec_attr_name, NULL }; enum_names ipsec_attr_names = { - SA_LIFE_DURATION, COMPRESS_PRIVATE_ALG, - ipsec_var_attr_name, &ipsec_attr_desc_tv }; + SA_LIFE_DURATION, COMPRESS_PRIVATE_ALG, + ipsec_var_attr_name, &ipsec_attr_desc_tv }; /* for each IPsec attribute, which enum_names describes its values? */ enum_names *ipsec_attr_val_descs[] = { - NULL, /* (none) */ - &sa_lifetime_names, /* SA_LIFE_TYPE */ - NULL, /* SA_LIFE_DURATION */ - &oakley_group_names, /* GROUP_DESCRIPTION */ - &enc_mode_names, /* ENCAPSULATION_MODE */ - &auth_alg_names, /* AUTH_ALGORITHM */ - NULL, /* KEY_LENGTH */ - NULL, /* KEY_ROUNDS */ - NULL, /* COMPRESS_DICT_SIZE */ - NULL, /* COMPRESS_PRIVATE_ALG */ - }; + NULL, /* (none) */ + &sa_lifetime_names, /* SA_LIFE_TYPE */ + NULL, /* SA_LIFE_DURATION */ + &oakley_group_names, /* GROUP_DESCRIPTION */ + &enc_mode_names, /* ENCAPSULATION_MODE */ + &auth_alg_names, /* AUTH_ALGORITHM */ + NULL, /* KEY_LENGTH */ + NULL, /* KEY_ROUNDS */ + NULL, /* COMPRESS_DICT_SIZE */ + NULL, /* COMPRESS_PRIVATE_ALG */ + }; /* SA Lifetime Type attribute */ static const char *const sa_lifetime_name[] = { - "SA_LIFE_TYPE_SECONDS", - "SA_LIFE_TYPE_KBYTES", - }; + "SA_LIFE_TYPE_SECONDS", + "SA_LIFE_TYPE_KBYTES", + }; enum_names sa_lifetime_names = - { SA_LIFE_TYPE_SECONDS, SA_LIFE_TYPE_KBYTES, sa_lifetime_name, NULL }; + { SA_LIFE_TYPE_SECONDS, SA_LIFE_TYPE_KBYTES, sa_lifetime_name, NULL }; /* Encapsulation Mode attribute */ static const char *const enc_mode_name[] = { - "ENCAPSULATION_MODE_TUNNEL", - "ENCAPSULATION_MODE_TRANSPORT", - "ENCAPSULATION_MODE_UDP_TUNNEL", - "ENCAPSULATION_MODE_UDP_TRANSPORT", - }; + "ENCAPSULATION_MODE_TUNNEL", + "ENCAPSULATION_MODE_TRANSPORT", + "ENCAPSULATION_MODE_UDP_TUNNEL", + "ENCAPSULATION_MODE_UDP_TRANSPORT", + }; static const char *const enc_udp_mode_name[] = { - "ENCAPSULATION_MODE_UDP_TUNNEL", - "ENCAPSULATION_MODE_UDP_TRANSPORT", - }; + "ENCAPSULATION_MODE_UDP_TUNNEL", + "ENCAPSULATION_MODE_UDP_TRANSPORT", + }; static enum_names enc_udp_mode_names = - { ENCAPSULATION_MODE_UDP_TUNNEL_DRAFTS, ENCAPSULATION_MODE_UDP_TRANSPORT_DRAFTS, enc_udp_mode_name, NULL }; + { ENCAPSULATION_MODE_UDP_TUNNEL_DRAFTS, ENCAPSULATION_MODE_UDP_TRANSPORT_DRAFTS, enc_udp_mode_name, NULL }; enum_names enc_mode_names = - { ENCAPSULATION_MODE_TUNNEL, ENCAPSULATION_MODE_UDP_TRANSPORT_RFC, enc_mode_name, &enc_udp_mode_names }; + { ENCAPSULATION_MODE_TUNNEL, ENCAPSULATION_MODE_UDP_TRANSPORT_RFC, enc_mode_name, &enc_udp_mode_names }; /* Auth Algorithm attribute */ static const char *const auth_alg_name[] = { - "AUTH_ALGORITHM_HMAC_MD5", - "AUTH_ALGORITHM_HMAC_SHA1", - "AUTH_ALGORITHM_DES_MAC", - "AUTH_ALGORITHM_KPDK", - "AUTH_ALGORITHM_HMAC_SHA2_256", - "AUTH_ALGORITHM_HMAC_SHA2_384", - "AUTH_ALGORITHM_HMAC_SHA2_512", - "AUTH_ALGORITHM_HMAC_RIPEMD", - "AUTH_ALGORITHM_AES_XCBC_MAC", - "AUTH_ALGORITHM_SIG_RSA" - }; + "AUTH_ALGORITHM_HMAC_MD5", + "AUTH_ALGORITHM_HMAC_SHA1", + "AUTH_ALGORITHM_DES_MAC", + "AUTH_ALGORITHM_KPDK", + "AUTH_ALGORITHM_HMAC_SHA2_256", + "AUTH_ALGORITHM_HMAC_SHA2_384", + "AUTH_ALGORITHM_HMAC_SHA2_512", + "AUTH_ALGORITHM_HMAC_RIPEMD", + "AUTH_ALGORITHM_AES_XCBC_MAC", + "AUTH_ALGORITHM_SIG_RSA" + }; static const char *const extended_auth_alg_name[] = { - "AUTH_ALGORITHM_NULL" - }; + "AUTH_ALGORITHM_NULL" + }; enum_names extended_auth_alg_names = - { AUTH_ALGORITHM_NULL, AUTH_ALGORITHM_NULL, extended_auth_alg_name, NULL }; + { AUTH_ALGORITHM_NULL, AUTH_ALGORITHM_NULL, extended_auth_alg_name, NULL }; enum_names auth_alg_names = - { AUTH_ALGORITHM_HMAC_MD5, AUTH_ALGORITHM_SIG_RSA, auth_alg_name - , &extended_auth_alg_names }; + { AUTH_ALGORITHM_HMAC_MD5, AUTH_ALGORITHM_SIG_RSA, auth_alg_name + , &extended_auth_alg_names }; /* From draft-beaulieu-ike-xauth */ static const char *const xauth_type_name[] = { @@ -718,323 +718,323 @@ static const char *const xauth_type_name[] = { }; enum_names xauth_type_names = - { XAUTH_TYPE_GENERIC, XAUTH_TYPE_SKEY, xauth_type_name, NULL}; + { XAUTH_TYPE_GENERIC, XAUTH_TYPE_SKEY, xauth_type_name, NULL}; /* From draft-beaulieu-ike-xauth */ static const char *const xauth_attr_tv_name[] = { - "XAUTH_TYPE", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "XAUTH_STATUS", - }; + "XAUTH_TYPE", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "XAUTH_STATUS", + }; enum_names xauth_attr_tv_names = { - XAUTH_TYPE + ISAKMP_ATTR_AF_TV, - XAUTH_STATUS + ISAKMP_ATTR_AF_TV, xauth_attr_tv_name, NULL }; + XAUTH_TYPE + ISAKMP_ATTR_AF_TV, + XAUTH_STATUS + ISAKMP_ATTR_AF_TV, xauth_attr_tv_name, NULL }; static const char *const unity_attr_name[] = { - "UNITY_BANNER", - "UNITY_SAVE_PASSWD", - "UNITY_DEF_DOMAIN", - "UNITY_SPLITDNS_NAME", - "UNITY_SPLIT_INCLUDE", - "UNITY_NATT_PORT", - "UNITY_LOCAL_LAN", - "UNITY_PFS", - "UNITY_FW_TYPE", - "UNITY_BACKUP_SERVERS", - "UNITY_DDNS_HOSTNAME", + "UNITY_BANNER", + "UNITY_SAVE_PASSWD", + "UNITY_DEF_DOMAIN", + "UNITY_SPLITDNS_NAME", + "UNITY_SPLIT_INCLUDE", + "UNITY_NATT_PORT", + "UNITY_LOCAL_LAN", + "UNITY_PFS", + "UNITY_FW_TYPE", + "UNITY_BACKUP_SERVERS", + "UNITY_DDNS_HOSTNAME", }; enum_names unity_attr_names = - { UNITY_BANNER , UNITY_DDNS_HOSTNAME, unity_attr_name , &xauth_attr_tv_names }; + { UNITY_BANNER , UNITY_DDNS_HOSTNAME, unity_attr_name , &xauth_attr_tv_names }; static const char *const microsoft_attr_name[] = { - "INTERNAL_IP4_SERVER", - "INTERNAL_IP6_SERVER", + "INTERNAL_IP4_SERVER", + "INTERNAL_IP6_SERVER", }; enum_names microsoft_attr_names = - { INTERNAL_IP4_SERVER, INTERNAL_IP6_SERVER, microsoft_attr_name , &unity_attr_names }; + { INTERNAL_IP4_SERVER, INTERNAL_IP6_SERVER, microsoft_attr_name , &unity_attr_names }; static const char *const xauth_attr_name[] = { - "XAUTH_USER_NAME", - "XAUTH_USER_PASSWORD", - "XAUTH_PASSCODE", - "XAUTH_MESSAGE", - "XAUTH_CHALLENGE", - "XAUTH_DOMAIN", - "XAUTH_STATUS (wrong TLV syntax, should be TV)", - "XAUTH_NEXT_PIN", - "XAUTH_ANSWER", - }; + "XAUTH_USER_NAME", + "XAUTH_USER_PASSWORD", + "XAUTH_PASSCODE", + "XAUTH_MESSAGE", + "XAUTH_CHALLENGE", + "XAUTH_DOMAIN", + "XAUTH_STATUS (wrong TLV syntax, should be TV)", + "XAUTH_NEXT_PIN", + "XAUTH_ANSWER", + }; enum_names xauth_attr_names = - { XAUTH_USER_NAME , XAUTH_ANSWER, xauth_attr_name , µsoft_attr_names }; + { XAUTH_USER_NAME , XAUTH_ANSWER, xauth_attr_name , µsoft_attr_names }; static const char *const modecfg_attr_name[] = { - "INTERNAL_IP4_ADDRESS", - "INTERNAL_IP4_NETMASK", - "INTERNAL_IP4_DNS", - "INTERNAL_IP4_NBNS", - "INTERNAL_ADDRESS_EXPIRY", - "INTERNAL_IP4_DHCP", - "APPLICATION_VERSION", - "INTERNAL_IP6_ADDRESS", - "INTERNAL_IP6_NETMASK", - "INTERNAL_IP6_DNS", - "INTERNAL_IP6_NBNS", - "INTERNAL_IP6_DHCP", - "INTERNAL_IP4_SUBNET", - "SUPPORTED_ATTRIBUTES", - "INTERNAL_IP6_SUBNET", - }; + "INTERNAL_IP4_ADDRESS", + "INTERNAL_IP4_NETMASK", + "INTERNAL_IP4_DNS", + "INTERNAL_IP4_NBNS", + "INTERNAL_ADDRESS_EXPIRY", + "INTERNAL_IP4_DHCP", + "APPLICATION_VERSION", + "INTERNAL_IP6_ADDRESS", + "INTERNAL_IP6_NETMASK", + "INTERNAL_IP6_DNS", + "INTERNAL_IP6_NBNS", + "INTERNAL_IP6_DHCP", + "INTERNAL_IP4_SUBNET", + "SUPPORTED_ATTRIBUTES", + "INTERNAL_IP6_SUBNET", + }; enum_names modecfg_attr_names = - { INTERNAL_IP4_ADDRESS, INTERNAL_IP6_SUBNET, modecfg_attr_name , &xauth_attr_names }; + { INTERNAL_IP4_ADDRESS, INTERNAL_IP6_SUBNET, modecfg_attr_name , &xauth_attr_names }; /* Oakley Lifetime Type attribute */ static const char *const oakley_lifetime_name[] = { - "OAKLEY_LIFE_SECONDS", - "OAKLEY_LIFE_KILOBYTES", - }; + "OAKLEY_LIFE_SECONDS", + "OAKLEY_LIFE_KILOBYTES", + }; enum_names oakley_lifetime_names = - { OAKLEY_LIFE_SECONDS, OAKLEY_LIFE_KILOBYTES, oakley_lifetime_name, NULL }; + { OAKLEY_LIFE_SECONDS, OAKLEY_LIFE_KILOBYTES, oakley_lifetime_name, NULL }; /* Oakley PRF attribute (none defined) */ enum_names oakley_prf_names = - { 1, 0, NULL, NULL }; + { 1, 0, NULL, NULL }; /* Oakley Encryption Algorithm attribute */ static const char *const oakley_enc_name[] = { - "OAKLEY_DES_CBC", - "OAKLEY_IDEA_CBC", - "OAKLEY_BLOWFISH_CBC", - "OAKLEY_RC5_R16_B64_CBC", - "OAKLEY_3DES_CBC", - "OAKLEY_CAST_CBC", - "OAKLEY_AES_CBC", - }; + "OAKLEY_DES_CBC", + "OAKLEY_IDEA_CBC", + "OAKLEY_BLOWFISH_CBC", + "OAKLEY_RC5_R16_B64_CBC", + "OAKLEY_3DES_CBC", + "OAKLEY_CAST_CBC", + "OAKLEY_AES_CBC", + }; #ifdef NO_EXTRA_IKE enum_names oakley_enc_names = - { OAKLEY_DES_CBC, OAKLEY_AES_CBC, oakley_enc_name, NULL }; + { OAKLEY_DES_CBC, OAKLEY_AES_CBC, oakley_enc_name, NULL }; #else static const char *const oakley_enc_name_draft_aes_cbc_02[] = { - "OAKLEY_MARS_CBC" /* 65001 */, - "OAKLEY_RC6_CBC" /* 65002 */, - "OAKLEY_ID_65003" /* 65003 */, - "OAKLEY_SERPENT_CBC" /* 65004 */, - "OAKLEY_TWOFISH_CBC" /* 65005 */, + "OAKLEY_MARS_CBC" /* 65001 */, + "OAKLEY_RC6_CBC" /* 65002 */, + "OAKLEY_ID_65003" /* 65003 */, + "OAKLEY_SERPENT_CBC" /* 65004 */, + "OAKLEY_TWOFISH_CBC" /* 65005 */, }; static const char *const oakley_enc_name_ssh[] = { - "OAKLEY_TWOFISH_CBC_SSH", + "OAKLEY_TWOFISH_CBC_SSH", }; enum_names oakley_enc_names_ssh = - { OAKLEY_TWOFISH_CBC_SSH, OAKLEY_TWOFISH_CBC_SSH, oakley_enc_name_ssh - , NULL }; + { OAKLEY_TWOFISH_CBC_SSH, OAKLEY_TWOFISH_CBC_SSH, oakley_enc_name_ssh + , NULL }; enum_names oakley_enc_names_draft_aes_cbc_02 = - { OAKLEY_MARS_CBC, OAKLEY_TWOFISH_CBC, oakley_enc_name_draft_aes_cbc_02 - , &oakley_enc_names_ssh }; + { OAKLEY_MARS_CBC, OAKLEY_TWOFISH_CBC, oakley_enc_name_draft_aes_cbc_02 + , &oakley_enc_names_ssh }; enum_names oakley_enc_names = - { OAKLEY_DES_CBC, OAKLEY_AES_CBC, oakley_enc_name - , &oakley_enc_names_draft_aes_cbc_02 }; + { OAKLEY_DES_CBC, OAKLEY_AES_CBC, oakley_enc_name + , &oakley_enc_names_draft_aes_cbc_02 }; #endif /* Oakley Hash Algorithm attribute */ static const char *const oakley_hash_name[] = { - "OAKLEY_MD5", - "OAKLEY_SHA", - "OAKLEY_TIGER", - "OAKLEY_SHA2_256", - "OAKLEY_SHA2_384", - "OAKLEY_SHA2_512", - }; + "OAKLEY_MD5", + "OAKLEY_SHA", + "OAKLEY_TIGER", + "OAKLEY_SHA2_256", + "OAKLEY_SHA2_384", + "OAKLEY_SHA2_512", + }; enum_names oakley_hash_names = - { OAKLEY_MD5, OAKLEY_SHA2_512, oakley_hash_name, NULL }; + { OAKLEY_MD5, OAKLEY_SHA2_512, oakley_hash_name, NULL }; /* Oakley Authentication Method attribute */ static const char *const oakley_auth_name1[] = { - "OAKLEY_PRESHARED_KEY", - "OAKLEY_DSS_SIG", - "OAKLEY_RSA_SIG", - "OAKLEY_RSA_ENC", - "OAKLEY_RSA_ENC_REV", - "OAKLEY_ELGAMAL_ENC", - "OAKLEY_ELGAMAL_ENC_REV", - }; + "OAKLEY_PRESHARED_KEY", + "OAKLEY_DSS_SIG", + "OAKLEY_RSA_SIG", + "OAKLEY_RSA_ENC", + "OAKLEY_RSA_ENC_REV", + "OAKLEY_ELGAMAL_ENC", + "OAKLEY_ELGAMAL_ENC_REV", + }; static const char *const oakley_auth_name2[] = { - "HybridInitRSA", - "HybridRespRSA", - "HybridInitDSS", - "HybridRespDSS", - }; + "HybridInitRSA", + "HybridRespRSA", + "HybridInitDSS", + "HybridRespDSS", + }; static const char *const oakley_auth_name3[] = { - "XAUTHInitPreShared", - "XAUTHRespPreShared", - "XAUTHInitDSS", - "XAUTHRespDSS", - "XAUTHInitRSA", - "XAUTHRespRSA", - "XAUTHInitRSAEncryption", - "XAUTHRespRSAEncryption", - "XAUTHInitRSARevisedEncryption", - "XAUTHRespRSARevisedEncryption", - }; + "XAUTHInitPreShared", + "XAUTHRespPreShared", + "XAUTHInitDSS", + "XAUTHRespDSS", + "XAUTHInitRSA", + "XAUTHRespRSA", + "XAUTHInitRSAEncryption", + "XAUTHRespRSAEncryption", + "XAUTHInitRSARevisedEncryption", + "XAUTHRespRSARevisedEncryption", + }; static enum_names oakley_auth_names1 = - { OAKLEY_PRESHARED_KEY, OAKLEY_ELGAMAL_ENC_REV - , oakley_auth_name1, NULL }; + { OAKLEY_PRESHARED_KEY, OAKLEY_ELGAMAL_ENC_REV + , oakley_auth_name1, NULL }; static enum_names oakley_auth_names2 = - { HybridInitRSA, HybridRespDSS - , oakley_auth_name2, &oakley_auth_names1 }; + { HybridInitRSA, HybridRespDSS + , oakley_auth_name2, &oakley_auth_names1 }; enum_names oakley_auth_names = - { XAUTHInitPreShared, XAUTHRespRSARevisedEncryption - , oakley_auth_name3, &oakley_auth_names2 }; + { XAUTHInitPreShared, XAUTHRespRSARevisedEncryption + , oakley_auth_name3, &oakley_auth_names2 }; /* Oakley Group Description attribute */ static const char *const oakley_group_name[] = { - "OAKLEY_GROUP_MODP768", - "OAKLEY_GROUP_MODP1024", - "OAKLEY_GROUP_GP155", - "OAKLEY_GROUP_GP185", - "OAKLEY_GROUP_MODP1536", - }; + "OAKLEY_GROUP_MODP768", + "OAKLEY_GROUP_MODP1024", + "OAKLEY_GROUP_GP155", + "OAKLEY_GROUP_GP185", + "OAKLEY_GROUP_MODP1536", + }; static const char *const oakley_group_name_rfc3526[] = { - "OAKLEY_GROUP_MODP2048", - "OAKLEY_GROUP_MODP3072", - "OAKLEY_GROUP_MODP4096", - "OAKLEY_GROUP_MODP6144", - "OAKLEY_GROUP_MODP8192" + "OAKLEY_GROUP_MODP2048", + "OAKLEY_GROUP_MODP3072", + "OAKLEY_GROUP_MODP4096", + "OAKLEY_GROUP_MODP6144", + "OAKLEY_GROUP_MODP8192" }; enum_names oakley_group_names_rfc3526 = - { OAKLEY_GROUP_MODP2048, OAKLEY_GROUP_MODP8192, - oakley_group_name_rfc3526, NULL }; + { OAKLEY_GROUP_MODP2048, OAKLEY_GROUP_MODP8192, + oakley_group_name_rfc3526, NULL }; enum_names oakley_group_names = - { OAKLEY_GROUP_MODP768, OAKLEY_GROUP_MODP1536, - oakley_group_name, &oakley_group_names_rfc3526 }; + { OAKLEY_GROUP_MODP768, OAKLEY_GROUP_MODP1536, + oakley_group_name, &oakley_group_names_rfc3526 }; /* Oakley Group Type attribute */ static const char *const oakley_group_type_name[] = { - "OAKLEY_GROUP_TYPE_MODP", - "OAKLEY_GROUP_TYPE_ECP", - "OAKLEY_GROUP_TYPE_EC2N", - }; + "OAKLEY_GROUP_TYPE_MODP", + "OAKLEY_GROUP_TYPE_ECP", + "OAKLEY_GROUP_TYPE_EC2N", + }; enum_names oakley_group_type_names = - { OAKLEY_GROUP_TYPE_MODP, OAKLEY_GROUP_TYPE_EC2N, oakley_group_type_name, NULL }; + { OAKLEY_GROUP_TYPE_MODP, OAKLEY_GROUP_TYPE_EC2N, oakley_group_type_name, NULL }; /* Notify messages -- error types */ static const char *const notification_name[] = { - "INVALID_PAYLOAD_TYPE", - "DOI_NOT_SUPPORTED", - "SITUATION_NOT_SUPPORTED", - "INVALID_COOKIE", - "INVALID_MAJOR_VERSION", - "INVALID_MINOR_VERSION", - "INVALID_EXCHANGE_TYPE", - "INVALID_FLAGS", - "INVALID_MESSAGE_ID", - "INVALID_PROTOCOL_ID", - "INVALID_SPI", - "INVALID_TRANSFORM_ID", - "ATTRIBUTES_NOT_SUPPORTED", - "NO_PROPOSAL_CHOSEN", - "BAD_PROPOSAL_SYNTAX", - "PAYLOAD_MALFORMED", - "INVALID_KEY_INFORMATION", - "INVALID_ID_INFORMATION", - "INVALID_CERT_ENCODING", - "INVALID_CERTIFICATE", - "CERT_TYPE_UNSUPPORTED", - "INVALID_CERT_AUTHORITY", - "INVALID_HASH_INFORMATION", - "AUTHENTICATION_FAILED", - "INVALID_SIGNATURE", - "ADDRESS_NOTIFICATION", - "NOTIFY_SA_LIFETIME", - "CERTIFICATE_UNAVAILABLE", - "UNSUPPORTED_EXCHANGE_TYPE", - "UNEQUAL_PAYLOAD_LENGTHS", - }; + "INVALID_PAYLOAD_TYPE", + "DOI_NOT_SUPPORTED", + "SITUATION_NOT_SUPPORTED", + "INVALID_COOKIE", + "INVALID_MAJOR_VERSION", + "INVALID_MINOR_VERSION", + "INVALID_EXCHANGE_TYPE", + "INVALID_FLAGS", + "INVALID_MESSAGE_ID", + "INVALID_PROTOCOL_ID", + "INVALID_SPI", + "INVALID_TRANSFORM_ID", + "ATTRIBUTES_NOT_SUPPORTED", + "NO_PROPOSAL_CHOSEN", + "BAD_PROPOSAL_SYNTAX", + "PAYLOAD_MALFORMED", + "INVALID_KEY_INFORMATION", + "INVALID_ID_INFORMATION", + "INVALID_CERT_ENCODING", + "INVALID_CERTIFICATE", + "CERT_TYPE_UNSUPPORTED", + "INVALID_CERT_AUTHORITY", + "INVALID_HASH_INFORMATION", + "AUTHENTICATION_FAILED", + "INVALID_SIGNATURE", + "ADDRESS_NOTIFICATION", + "NOTIFY_SA_LIFETIME", + "CERTIFICATE_UNAVAILABLE", + "UNSUPPORTED_EXCHANGE_TYPE", + "UNEQUAL_PAYLOAD_LENGTHS", + }; static const char *const notification_status_name[] = { - "CONNECTED", - }; + "CONNECTED", + }; static const char *const ipsec_notification_name[] = { - "IPSEC_RESPONDER_LIFETIME", - "IPSEC_REPLAY_STATUS", - "IPSEC_INITIAL_CONTACT", - }; + "IPSEC_RESPONDER_LIFETIME", + "IPSEC_REPLAY_STATUS", + "IPSEC_INITIAL_CONTACT", + }; static const char *const notification_dpd_name[] = { - "R_U_THERE", - "R_U_THERE_ACK", + "R_U_THERE", + "R_U_THERE_ACK", }; enum_names notification_dpd_names = - { R_U_THERE, R_U_THERE_ACK, - notification_dpd_name, NULL }; + { R_U_THERE, R_U_THERE_ACK, + notification_dpd_name, NULL }; enum_names ipsec_notification_names = - { IPSEC_RESPONDER_LIFETIME, IPSEC_INITIAL_CONTACT, - ipsec_notification_name, ¬ification_dpd_names }; + { IPSEC_RESPONDER_LIFETIME, IPSEC_INITIAL_CONTACT, + ipsec_notification_name, ¬ification_dpd_names }; enum_names notification_status_names = - { CONNECTED, CONNECTED, - notification_status_name, &ipsec_notification_names }; + { CONNECTED, CONNECTED, + notification_status_name, &ipsec_notification_names }; enum_names notification_names = - { INVALID_PAYLOAD_TYPE, UNEQUAL_PAYLOAD_LENGTHS, - notification_name, ¬ification_status_names }; + { INVALID_PAYLOAD_TYPE, UNEQUAL_PAYLOAD_LENGTHS, + notification_name, ¬ification_status_names }; /* MODECFG * From draft-dukes-ike-mode-cfg */ const char *const attr_msg_type_name[] = { - "ISAKMP_CFG_RESERVED", - "ISAKMP_CFG_REQUEST", - "ISAKMP_CFG_REPLY", - "ISAKMP_CFG_SET", - "ISAKMP_CFG_ACK", - NULL - }; + "ISAKMP_CFG_RESERVED", + "ISAKMP_CFG_REQUEST", + "ISAKMP_CFG_REPLY", + "ISAKMP_CFG_SET", + "ISAKMP_CFG_ACK", + NULL + }; enum_names attr_msg_type_names = - { 0 , ISAKMP_CFG_ACK, attr_msg_type_name , NULL }; + { 0 , ISAKMP_CFG_ACK, attr_msg_type_name , NULL }; /* socket address family info */ static const char *const af_inet_name[] = { - "AF_INET", - }; + "AF_INET", + }; static const char *const af_inet6_name[] = { - "AF_INET6", - }; + "AF_INET6", + }; static enum_names af_names6 = { AF_INET6, AF_INET6, af_inet6_name, NULL }; @@ -1045,46 +1045,46 @@ static ip_subnet ipv4_wildcard, ipv6_wildcard; static ip_subnet ipv4_all, ipv6_all; const struct af_info af_inet4_info = { - AF_INET, - "AF_INET", - sizeof(struct in_addr), - sizeof(struct sockaddr_in), - 32, - ID_IPV4_ADDR, ID_IPV4_ADDR_SUBNET, ID_IPV4_ADDR_RANGE, - &ipv4_any, &ipv4_wildcard, &ipv4_all, - }; + AF_INET, + "AF_INET", + sizeof(struct in_addr), + sizeof(struct sockaddr_in), + 32, + ID_IPV4_ADDR, ID_IPV4_ADDR_SUBNET, ID_IPV4_ADDR_RANGE, + &ipv4_any, &ipv4_wildcard, &ipv4_all, + }; const struct af_info af_inet6_info = { - AF_INET6, - "AF_INET6", - sizeof(struct in6_addr), - sizeof(struct sockaddr_in6), - 128, - ID_IPV6_ADDR, ID_IPV6_ADDR_SUBNET, ID_IPV6_ADDR_RANGE, - &ipv6_any, &ipv6_wildcard, &ipv6_all, - }; + AF_INET6, + "AF_INET6", + sizeof(struct in6_addr), + sizeof(struct sockaddr_in6), + 128, + ID_IPV6_ADDR, ID_IPV6_ADDR_SUBNET, ID_IPV6_ADDR_RANGE, + &ipv6_any, &ipv6_wildcard, &ipv6_all, + }; const struct af_info * aftoinfo(int af) { - switch (af) - { - case AF_INET: - return &af_inet4_info; - case AF_INET6: - return &af_inet6_info; - default: - return NULL; - } + switch (af) + { + case AF_INET: + return &af_inet4_info; + case AF_INET6: + return &af_inet6_info; + default: + return NULL; + } } bool subnetisnone(const ip_subnet *sn) { - ip_address base; + ip_address base; - networkof(sn, &base); - return isanyaddr(&base) && subnetishost(sn); + networkof(sn, &base); + return isanyaddr(&base) && subnetishost(sn); } /* BIND enumerated types */ @@ -1092,62 +1092,62 @@ subnetisnone(const ip_subnet *sn) #include static const char *const rr_type_name[] = { - "T_A", /* 1 host address */ - "T_NS", /* 2 authoritative server */ - "T_MD", /* 3 mail destination */ - "T_MF", /* 4 mail forwarder */ - "T_CNAME", /* 5 canonical name */ - "T_SOA", /* 6 start of authority zone */ - "T_MB", /* 7 mailbox domain name */ - "T_MG", /* 8 mail group member */ - "T_MR", /* 9 mail rename name */ - "T_NULL", /* 10 null resource record */ - "T_WKS", /* 11 well known service */ - "T_PTR", /* 12 domain name pointer */ - "T_HINFO", /* 13 host information */ - "T_MINFO", /* 14 mailbox information */ - "T_MX", /* 15 mail routing information */ - "T_TXT", /* 16 text strings */ - "T_RP", /* 17 responsible person */ - "T_AFSDB", /* 18 AFS cell database */ - "T_X25", /* 19 X_25 calling address */ - "T_ISDN", /* 20 ISDN calling address */ - "T_RT", /* 21 router */ - "T_NSAP", /* 22 NSAP address */ - "T_NSAP_PTR", /* 23 reverse NSAP lookup (deprecated) */ - "T_SIG", /* 24 security signature */ - "T_KEY", /* 25 security key */ - "T_PX", /* 26 X.400 mail mapping */ - "T_GPOS", /* 27 geographical position (withdrawn) */ - "T_AAAA", /* 28 IP6 Address */ - "T_LOC", /* 29 Location Information */ - "T_NXT", /* 30 Next Valid Name in Zone */ - "T_EID", /* 31 Endpoint identifier */ - "T_NIMLOC", /* 32 Nimrod locator */ - "T_SRV", /* 33 Server selection */ - "T_ATMA", /* 34 ATM Address */ - "T_NAPTR", /* 35 Naming Authority PoinTeR */ - NULL - }; + "T_A", /* 1 host address */ + "T_NS", /* 2 authoritative server */ + "T_MD", /* 3 mail destination */ + "T_MF", /* 4 mail forwarder */ + "T_CNAME", /* 5 canonical name */ + "T_SOA", /* 6 start of authority zone */ + "T_MB", /* 7 mailbox domain name */ + "T_MG", /* 8 mail group member */ + "T_MR", /* 9 mail rename name */ + "T_NULL", /* 10 null resource record */ + "T_WKS", /* 11 well known service */ + "T_PTR", /* 12 domain name pointer */ + "T_HINFO", /* 13 host information */ + "T_MINFO", /* 14 mailbox information */ + "T_MX", /* 15 mail routing information */ + "T_TXT", /* 16 text strings */ + "T_RP", /* 17 responsible person */ + "T_AFSDB", /* 18 AFS cell database */ + "T_X25", /* 19 X_25 calling address */ + "T_ISDN", /* 20 ISDN calling address */ + "T_RT", /* 21 router */ + "T_NSAP", /* 22 NSAP address */ + "T_NSAP_PTR", /* 23 reverse NSAP lookup (deprecated) */ + "T_SIG", /* 24 security signature */ + "T_KEY", /* 25 security key */ + "T_PX", /* 26 X.400 mail mapping */ + "T_GPOS", /* 27 geographical position (withdrawn) */ + "T_AAAA", /* 28 IP6 Address */ + "T_LOC", /* 29 Location Information */ + "T_NXT", /* 30 Next Valid Name in Zone */ + "T_EID", /* 31 Endpoint identifier */ + "T_NIMLOC", /* 32 Nimrod locator */ + "T_SRV", /* 33 Server selection */ + "T_ATMA", /* 34 ATM Address */ + "T_NAPTR", /* 35 Naming Authority PoinTeR */ + NULL + }; enum_names rr_type_names = { T_A, T_NAPTR, rr_type_name, NULL }; /* Query type values which do not appear in resource records */ static const char *const rr_qtype_name[] = { - "T_IXFR", /* 251 incremental zone transfer */ - "T_AXFR", /* 252 transfer zone of authority */ - "T_MAILB", /* 253 transfer mailbox records */ - "T_MAILA", /* 254 transfer mail agent records */ - "T_ANY", /* 255 wildcard match */ - NULL - }; + "T_IXFR", /* 251 incremental zone transfer */ + "T_AXFR", /* 252 transfer zone of authority */ + "T_MAILB", /* 253 transfer mailbox records */ + "T_MAILA", /* 254 transfer mail agent records */ + "T_ANY", /* 255 wildcard match */ + NULL + }; enum_names rr_qtype_names = { T_IXFR, T_ANY, rr_qtype_name, &rr_type_names }; static const char *const rr_class_name[] = { - "C_IN", /* 1 the arpa internet */ - NULL - }; + "C_IN", /* 1 the arpa internet */ + NULL + }; enum_names rr_class_names = { C_IN, C_IN, rr_class_name, NULL }; @@ -1176,14 +1176,14 @@ const char *const natt_type_bitnames[] = { const char * enum_name(enum_names *ed, unsigned long val) { - enum_names *p; + enum_names *p; - for (p = ed; p != NULL; p = p->en_next_range) - { - if (p->en_first <= val && val <= p->en_last) - return p->en_names[val - p->en_first]; - } - return NULL; + for (p = ed; p != NULL; p = p->en_next_range) + { + if (p->en_first <= val && val <= p->en_last) + return p->en_names[val - p->en_first]; + } + return NULL; } /* find or construct a string to describe an enum value @@ -1192,16 +1192,16 @@ enum_name(enum_names *ed, unsigned long val) const char * enum_show(enum_names *ed, unsigned long val) { - const char *p = enum_name(ed, val); + const char *p = enum_name(ed, val); - if (p == NULL) - { - static char buf[12]; /* only one! I hope that it is big enough */ + if (p == NULL) + { + static char buf[12]; /* only one! I hope that it is big enough */ - snprintf(buf, sizeof(buf), "%lu??", val); - p = buf; - } - return p; + snprintf(buf, sizeof(buf), "%lu??", val); + p = buf; + } + return p; } @@ -1210,26 +1210,26 @@ static char bitnamesbuf[200]; /* only one! I hope that it is big enough! */ int enum_search(enum_names *ed, const char *str) { - enum_names *p; - const char *ptr; - unsigned en; + enum_names *p; + const char *ptr; + unsigned en; - for (p = ed; p != NULL; p = p->en_next_range) - { - for (en = p->en_first; en <= p->en_last ;en++) + for (p = ed; p != NULL; p = p->en_next_range) { - ptr = p->en_names[en - p->en_first]; - if (ptr == 0) - { - continue; - } - if (streq(ptr, str)) - { - return en; - } + for (en = p->en_first; en <= p->en_last ;en++) + { + ptr = p->en_names[en - p->en_first]; + if (ptr == 0) + { + continue; + } + if (streq(ptr, str)) + { + return en; + } + } } - } - return -1; + return -1; } /* construct a string to name the bits on in a set @@ -1239,46 +1239,46 @@ enum_search(enum_names *ed, const char *str) const char * bitnamesof(const char *const table[], lset_t val) { - char *p = bitnamesbuf; - lset_t bit; - const char *const *tp; + char *p = bitnamesbuf; + lset_t bit; + const char *const *tp; - if (val == 0) - return "none"; + if (val == 0) + return "none"; - for (tp = table, bit = 01; val != 0; bit <<= 1) - { - if (val & bit) + for (tp = table, bit = 01; val != 0; bit <<= 1) { - const char *n = *tp; - size_t nl; + if (val & bit) + { + const char *n = *tp; + size_t nl; - if (n == NULL || *n == '\0') - { - /* no name for this bit, so use hex */ - static char flagbuf[sizeof("0x80000000")]; + if (n == NULL || *n == '\0') + { + /* no name for this bit, so use hex */ + static char flagbuf[sizeof("0x80000000")]; - snprintf(flagbuf, sizeof(flagbuf), "0x%llx", bit); - n = flagbuf; - } + snprintf(flagbuf, sizeof(flagbuf), "0x%llx", bit); + n = flagbuf; + } - nl = strlen(n); + nl = strlen(n); - if (p != bitnamesbuf && p < bitnamesbuf+sizeof(bitnamesbuf) - 1) - *p++ = '+'; + if (p != bitnamesbuf && p < bitnamesbuf+sizeof(bitnamesbuf) - 1) + *p++ = '+'; - if (bitnamesbuf+sizeof(bitnamesbuf) - p > (ptrdiff_t)nl) - { - strcpy(p, n); - p += nl; - } - val -= bit; + if (bitnamesbuf+sizeof(bitnamesbuf) - p > (ptrdiff_t)nl) + { + strcpy(p, n); + p += nl; + } + val -= bit; + } + if (*tp != NULL) + tp++; /* move on, but not past end */ } - if (*tp != NULL) - tp++; /* move on, but not past end */ - } - *p = '\0'; - return bitnamesbuf; + *p = '\0'; + return bitnamesbuf; } /* print a policy: like bitnamesof, but it also does the non-bitfields. @@ -1287,33 +1287,33 @@ bitnamesof(const char *const table[], lset_t val) const char * prettypolicy(lset_t policy) { - const char *bn = bitnamesof(sa_policy_bit_names - , policy & ~(POLICY_SHUNT_MASK | POLICY_FAIL_MASK)); - size_t len; - lset_t shunt = (policy & POLICY_SHUNT_MASK) >> POLICY_SHUNT_SHIFT; - lset_t fail = (policy & POLICY_FAIL_MASK) >> POLICY_FAIL_SHIFT; + const char *bn = bitnamesof(sa_policy_bit_names + , policy & ~(POLICY_SHUNT_MASK | POLICY_FAIL_MASK)); + size_t len; + lset_t shunt = (policy & POLICY_SHUNT_MASK) >> POLICY_SHUNT_SHIFT; + lset_t fail = (policy & POLICY_FAIL_MASK) >> POLICY_FAIL_SHIFT; - if (bn != bitnamesbuf) - bitnamesbuf[0] = '\0'; - len = strlen(bitnamesbuf); - if (shunt != 0) - { - snprintf(bitnamesbuf + len, sizeof(bitnamesbuf) - len, "+%s" - , policy_shunt_names[shunt]); - len += strlen(bitnamesbuf + len); - } - if (fail != 0) - { - snprintf(bitnamesbuf + len, sizeof(bitnamesbuf) - len, "+failure%s" - , policy_fail_names[fail]); - len += strlen(bitnamesbuf + len); - } - if (NEVER_NEGOTIATE(policy)) - { - snprintf(bitnamesbuf + len, sizeof(bitnamesbuf) - len, "+NEVER_NEGOTIATE"); - len += strlen(bitnamesbuf + len); - } - return bitnamesbuf; + if (bn != bitnamesbuf) + bitnamesbuf[0] = '\0'; + len = strlen(bitnamesbuf); + if (shunt != 0) + { + snprintf(bitnamesbuf + len, sizeof(bitnamesbuf) - len, "+%s" + , policy_shunt_names[shunt]); + len += strlen(bitnamesbuf + len); + } + if (fail != 0) + { + snprintf(bitnamesbuf + len, sizeof(bitnamesbuf) - len, "+failure%s" + , policy_fail_names[fail]); + len += strlen(bitnamesbuf + len); + } + if (NEVER_NEGOTIATE(policy)) + { + snprintf(bitnamesbuf + len, sizeof(bitnamesbuf) - len, "+NEVER_NEGOTIATE"); + len += strlen(bitnamesbuf + len); + } + return bitnamesbuf; } /* test a set by seeing if all bits have names */ @@ -1321,18 +1321,18 @@ prettypolicy(lset_t policy) bool testset(const char *const table[], lset_t val) { - lset_t bit; - const char *const *tp; + lset_t bit; + const char *const *tp; - for (tp = table, bit = 01; val != 0; bit <<= 1, tp++) - { - const char *n = *tp; + for (tp = table, bit = 01; val != 0; bit <<= 1, tp++) + { + const char *n = *tp; - if (n == NULL || ((val & bit) && *n == '\0')) - return FALSE; - val &= ~bit; - } - return TRUE; + if (n == NULL || ((val & bit) && *n == '\0')) + return FALSE; + val &= ~bit; + } + return TRUE; } @@ -1341,12 +1341,12 @@ const char sparse_end[] = "end of sparse names"; /* look up enum names in a sparse_names */ const char *sparse_name(sparse_names sd, unsigned long val) { - const struct sparse_name *p; + const struct sparse_name *p; - for (p = sd; p->name != sparse_end; p++) - if (p->val == val) - return p->name; - return NULL; + for (p = sd; p->name != sparse_end; p++) + if (p->val == val) + return p->name; + return NULL; } /* find or construct a string to describe an sparse value @@ -1355,26 +1355,26 @@ const char *sparse_name(sparse_names sd, unsigned long val) const char * sparse_val_show(sparse_names sd, unsigned long val) { - const char *p = sparse_name(sd, val); + const char *p = sparse_name(sd, val); - if (p == NULL) - { - static char buf[12]; /* only one! I hope that it is big enough */ + if (p == NULL) + { + static char buf[12]; /* only one! I hope that it is big enough */ - snprintf(buf, sizeof(buf), "%lu??", val); - p = buf; - } - return p; + snprintf(buf, sizeof(buf), "%lu??", val); + p = buf; + } + return p; } void init_constants(void) { - happy(anyaddr(AF_INET, &ipv4_any)); - happy(anyaddr(AF_INET6, &ipv6_any)); + happy(anyaddr(AF_INET, &ipv4_any)); + happy(anyaddr(AF_INET6, &ipv6_any)); - happy(addrtosubnet(&ipv4_any, &ipv4_wildcard)); - happy(addrtosubnet(&ipv6_any, &ipv6_wildcard)); + happy(addrtosubnet(&ipv4_any, &ipv4_wildcard)); + happy(addrtosubnet(&ipv6_any, &ipv6_wildcard)); - happy(initsubnet(&ipv4_any, 0, '0', &ipv4_all)); - happy(initsubnet(&ipv6_any, 0, '0', &ipv6_all)); + happy(initsubnet(&ipv4_any, 0, '0', &ipv4_all)); + happy(initsubnet(&ipv6_any, 0, '0', &ipv6_all)); } diff --git a/src/pluto/constants.h b/src/pluto/constants.h index a21627421..f069402be 100644 --- a/src/pluto/constants.h +++ b/src/pluto/constants.h @@ -39,7 +39,7 @@ extern void init_constants(void); * defines err_t for this return type. */ -#define NULL_FD (-1) /* NULL file descriptor */ +#define NULL_FD (-1) /* NULL file descriptor */ #define dup_any(fd) ((fd) == NULL_FD? NULL_FD : dup(fd)) #define close_any(fd) { if ((fd) != NULL_FD) { close(fd); (fd) = NULL_FD; } } @@ -62,8 +62,8 @@ typedef unsigned long long lset_t; # define DEFAULT_CTLBASE IPSEC_PIDDIR "/pluto" #endif -#define CTL_SUFFIX ".ctl" /* for UNIX domain socket pathname */ -#define LOCK_SUFFIX ".pid" /* for pluto's lock */ +#define CTL_SUFFIX ".ctl" /* for UNIX domain socket pathname */ +#define LOCK_SUFFIX ".pid" /* for pluto's lock */ #define INFO_SUFFIX ".info" /* for UNIX domain socket for apps */ /* Routines to check and display values. @@ -77,10 +77,10 @@ typedef unsigned long long lset_t; */ struct enum_names { - unsigned long en_first; /* first value in range */ - unsigned long en_last; /* last value in range (inclusive) */ - const char *const *en_names; - const struct enum_names *en_next_range; /* descriptor of next range */ + unsigned long en_first; /* first value in range */ + unsigned long en_last; /* last value in range (inclusive) */ + const char *const *en_names; + const struct enum_names *en_next_range; /* descriptor of next range */ }; typedef const struct enum_names enum_names; @@ -99,8 +99,8 @@ extern const char *bitnamesof(const char *const table[], lset_t val); * Often appropriate for enums defined by others. */ struct sparse_name { - unsigned long val; - const char *const name; + unsigned long val; + const char *const name; }; typedef const struct sparse_name sparse_names[]; @@ -115,191 +115,191 @@ extern const char sparse_end[]; #define MODP_GENERATOR "2" #define MODP768_MODULUS \ - "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 " \ - "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD " \ - "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 " \ - "E485B576 625E7EC6 F44C42E9 A63A3620 FFFFFFFF FFFFFFFF" + "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 " \ + "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD " \ + "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 " \ + "E485B576 625E7EC6 F44C42E9 A63A3620 FFFFFFFF FFFFFFFF" #define MODP1024_MODULUS \ - "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 " \ - "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD " \ - "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 " \ - "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED " \ - "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381 " \ - "FFFFFFFF FFFFFFFF" + "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 " \ + "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD " \ + "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 " \ + "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED " \ + "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381 " \ + "FFFFFFFF FFFFFFFF" #define MODP1536_MODULUS \ - "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 " \ - "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD " \ - "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 " \ - "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED " \ - "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D " \ - "C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F " \ - "83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D " \ - "670C354E 4ABC9804 F1746C08 CA237327 FFFFFFFF FFFFFFFF " + "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 " \ + "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD " \ + "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 " \ + "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED " \ + "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D " \ + "C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F " \ + "83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D " \ + "670C354E 4ABC9804 F1746C08 CA237327 FFFFFFFF FFFFFFFF " /* draft-ietf-ipsec-ike-modp-groups-03.txt */ #define MODP2048_MODULUS \ - "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" \ - "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" \ - "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" \ - "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" \ - "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" \ - "C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" \ - "83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" \ - "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" \ - "E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" \ - "DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" \ - "15728E5A 8AACAA68 FFFFFFFF FFFFFFFF" + "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" \ + "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" \ + "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" \ + "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" \ + "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" \ + "C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" \ + "83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" \ + "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" \ + "E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" \ + "DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" \ + "15728E5A 8AACAA68 FFFFFFFF FFFFFFFF" #define MODP3072_MODULUS \ - "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" \ - "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" \ - "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" \ - "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" \ - "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" \ - "C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" \ - "83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" \ - "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" \ - "E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" \ - "DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" \ - "15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64" \ - "ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7" \ - "ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B" \ - "F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" \ - "BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31" \ - "43DB5BFC E0FD108E 4B82D120 A93AD2CA FFFFFFFF FFFFFFFF" + "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" \ + "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" \ + "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" \ + "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" \ + "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" \ + "C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" \ + "83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" \ + "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" \ + "E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" \ + "DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" \ + "15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64" \ + "ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7" \ + "ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B" \ + "F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" \ + "BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31" \ + "43DB5BFC E0FD108E 4B82D120 A93AD2CA FFFFFFFF FFFFFFFF" #define MODP4096_MODULUS \ - "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" \ - "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" \ - "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" \ - "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" \ - "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" \ - "C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" \ - "83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" \ - "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" \ - "E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" \ - "DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" \ - "15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64" \ - "ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7" \ - "ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B" \ - "F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" \ - "BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31" \ - "43DB5BFC E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7" \ - "88719A10 BDBA5B26 99C32718 6AF4E23C 1A946834 B6150BDA" \ - "2583E9CA 2AD44CE8 DBBBC2DB 04DE8EF9 2E8EFC14 1FBECAA6" \ - "287C5947 4E6BC05D 99B2964F A090C3A2 233BA186 515BE7ED" \ - "1F612970 CEE2D7AF B81BDD76 2170481C D0069127 D5B05AA9" \ - "93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34063199" \ - "FFFFFFFF FFFFFFFF" + "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" \ + "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" \ + "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" \ + "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" \ + "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" \ + "C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" \ + "83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" \ + "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" \ + "E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" \ + "DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" \ + "15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64" \ + "ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7" \ + "ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B" \ + "F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" \ + "BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31" \ + "43DB5BFC E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7" \ + "88719A10 BDBA5B26 99C32718 6AF4E23C 1A946834 B6150BDA" \ + "2583E9CA 2AD44CE8 DBBBC2DB 04DE8EF9 2E8EFC14 1FBECAA6" \ + "287C5947 4E6BC05D 99B2964F A090C3A2 233BA186 515BE7ED" \ + "1F612970 CEE2D7AF B81BDD76 2170481C D0069127 D5B05AA9" \ + "93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34063199" \ + "FFFFFFFF FFFFFFFF" /* copy&pasted from rfc3526: */ #define MODP6144_MODULUS \ - "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08" \ - "8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B" \ - "302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9" \ - "A637ED6B 0BFF5CB6 F406B7ED EE386BFB 5A899FA5 AE9F2411 7C4B1FE6" \ - "49286651 ECE45B3D C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8" \ - "FD24CF5F 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" \ - "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B E39E772C" \ - "180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 DE2BCBF6 95581718" \ - "3995497C EA956AE5 15D22618 98FA0510 15728E5A 8AAAC42D AD33170D" \ - "04507A33 A85521AB DF1CBA64 ECFB8504 58DBEF0A 8AEA7157 5D060C7D" \ - "B3970F85 A6E1E4C7 ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226" \ - "1AD2EE6B F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" \ - "BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 43DB5BFC" \ - "E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7 88719A10 BDBA5B26" \ - "99C32718 6AF4E23C 1A946834 B6150BDA 2583E9CA 2AD44CE8 DBBBC2DB" \ - "04DE8EF9 2E8EFC14 1FBECAA6 287C5947 4E6BC05D 99B2964F A090C3A2" \ - "233BA186 515BE7ED 1F612970 CEE2D7AF B81BDD76 2170481C D0069127" \ - "D5B05AA9 93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34028492" \ - "36C3FAB4 D27C7026 C1D4DCB2 602646DE C9751E76 3DBA37BD F8FF9406" \ - "AD9E530E E5DB382F 413001AE B06A53ED 9027D831 179727B0 865A8918" \ - "DA3EDBEB CF9B14ED 44CE6CBA CED4BB1B DB7F1447 E6CC254B 33205151" \ - "2BD7AF42 6FB8F401 378CD2BF 5983CA01 C64B92EC F032EA15 D1721D03" \ - "F482D7CE 6E74FEF6 D55E702F 46980C82 B5A84031 900B1C9E 59E7C97F" \ - "BEC7E8F3 23A97A7E 36CC88BE 0F1D45B7 FF585AC5 4BD407B2 2B4154AA" \ - "CC8F6D7E BF48E1D8 14CC5ED2 0F8037E0 A79715EE F29BE328 06A1D58B" \ - "B7C5DA76 F550AA3D 8A1FBFF0 EB19CCB1 A313D55C DA56C9EC 2EF29632" \ - "387FE8D7 6E3C0468 043E8F66 3F4860EE 12BF2D5B 0B7474D6 E694F91E" \ - "6DCC4024 FFFFFFFF FFFFFFFF" + "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08" \ + "8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B" \ + "302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9" \ + "A637ED6B 0BFF5CB6 F406B7ED EE386BFB 5A899FA5 AE9F2411 7C4B1FE6" \ + "49286651 ECE45B3D C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8" \ + "FD24CF5F 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" \ + "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B E39E772C" \ + "180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 DE2BCBF6 95581718" \ + "3995497C EA956AE5 15D22618 98FA0510 15728E5A 8AAAC42D AD33170D" \ + "04507A33 A85521AB DF1CBA64 ECFB8504 58DBEF0A 8AEA7157 5D060C7D" \ + "B3970F85 A6E1E4C7 ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226" \ + "1AD2EE6B F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" \ + "BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 43DB5BFC" \ + "E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7 88719A10 BDBA5B26" \ + "99C32718 6AF4E23C 1A946834 B6150BDA 2583E9CA 2AD44CE8 DBBBC2DB" \ + "04DE8EF9 2E8EFC14 1FBECAA6 287C5947 4E6BC05D 99B2964F A090C3A2" \ + "233BA186 515BE7ED 1F612970 CEE2D7AF B81BDD76 2170481C D0069127" \ + "D5B05AA9 93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34028492" \ + "36C3FAB4 D27C7026 C1D4DCB2 602646DE C9751E76 3DBA37BD F8FF9406" \ + "AD9E530E E5DB382F 413001AE B06A53ED 9027D831 179727B0 865A8918" \ + "DA3EDBEB CF9B14ED 44CE6CBA CED4BB1B DB7F1447 E6CC254B 33205151" \ + "2BD7AF42 6FB8F401 378CD2BF 5983CA01 C64B92EC F032EA15 D1721D03" \ + "F482D7CE 6E74FEF6 D55E702F 46980C82 B5A84031 900B1C9E 59E7C97F" \ + "BEC7E8F3 23A97A7E 36CC88BE 0F1D45B7 FF585AC5 4BD407B2 2B4154AA" \ + "CC8F6D7E BF48E1D8 14CC5ED2 0F8037E0 A79715EE F29BE328 06A1D58B" \ + "B7C5DA76 F550AA3D 8A1FBFF0 EB19CCB1 A313D55C DA56C9EC 2EF29632" \ + "387FE8D7 6E3C0468 043E8F66 3F4860EE 12BF2D5B 0B7474D6 E694F91E" \ + "6DCC4024 FFFFFFFF FFFFFFFF" /* copy&pasted from rfc3526: */ #define MODP8192_MODULUS \ - "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" \ - "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" \ - "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" \ - "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" \ - "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" \ - "C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" \ - "83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" \ - "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" \ - "E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" \ - "DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" \ - "15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64" \ - "ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7" \ - "ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B" \ - "F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" \ - "BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31" \ - "43DB5BFC E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7" \ - "88719A10 BDBA5B26 99C32718 6AF4E23C 1A946834 B6150BDA" \ - "2583E9CA 2AD44CE8 DBBBC2DB 04DE8EF9 2E8EFC14 1FBECAA6" \ - "287C5947 4E6BC05D 99B2964F A090C3A2 233BA186 515BE7ED" \ - "1F612970 CEE2D7AF B81BDD76 2170481C D0069127 D5B05AA9" \ - "93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34028492" \ - "36C3FAB4 D27C7026 C1D4DCB2 602646DE C9751E76 3DBA37BD" \ - "F8FF9406 AD9E530E E5DB382F 413001AE B06A53ED 9027D831" \ - "179727B0 865A8918 DA3EDBEB CF9B14ED 44CE6CBA CED4BB1B" \ - "DB7F1447 E6CC254B 33205151 2BD7AF42 6FB8F401 378CD2BF" \ - "5983CA01 C64B92EC F032EA15 D1721D03 F482D7CE 6E74FEF6" \ - "D55E702F 46980C82 B5A84031 900B1C9E 59E7C97F BEC7E8F3" \ - "23A97A7E 36CC88BE 0F1D45B7 FF585AC5 4BD407B2 2B4154AA" \ - "CC8F6D7E BF48E1D8 14CC5ED2 0F8037E0 A79715EE F29BE328" \ - "06A1D58B B7C5DA76 F550AA3D 8A1FBFF0 EB19CCB1 A313D55C" \ - "DA56C9EC 2EF29632 387FE8D7 6E3C0468 043E8F66 3F4860EE" \ - "12BF2D5B 0B7474D6 E694F91E 6DBE1159 74A3926F 12FEE5E4" \ - "38777CB6 A932DF8C D8BEC4D0 73B931BA 3BC832B6 8D9DD300" \ - "741FA7BF 8AFC47ED 2576F693 6BA42466 3AAB639C 5AE4F568" \ - "3423B474 2BF1C978 238F16CB E39D652D E3FDB8BE FC848AD9" \ - "22222E04 A4037C07 13EB57A8 1A23F0C7 3473FC64 6CEA306B" \ - "4BCBC886 2F8385DD FA9D4B7F A2C087E8 79683303 ED5BDD3A" \ - "062B3CF5 B3A278A6 6D2A13F8 3F44F82D DF310EE0 74AB6A36" \ - "4597E899 A0255DC1 64F31CC5 0846851D F9AB4819 5DED7EA1" \ - "B1D510BD 7EE74D73 FAF36BC3 1ECFA268 359046F4 EB879F92" \ - "4009438B 481C6CD7 889A002E D5EE382B C9190DA6 FC026E47" \ - "9558E447 5677E9AA 9E3050E2 765694DF C81F56E8 80B96E71" \ - "60C980DD 98EDD3DF FFFFFFFF FFFFFFFF" -#define LOCALSECRETSIZE (512 / BITS_PER_BYTE) + "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" \ + "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" \ + "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" \ + "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" \ + "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" \ + "C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" \ + "83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" \ + "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" \ + "E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" \ + "DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" \ + "15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64" \ + "ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7" \ + "ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B" \ + "F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" \ + "BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31" \ + "43DB5BFC E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7" \ + "88719A10 BDBA5B26 99C32718 6AF4E23C 1A946834 B6150BDA" \ + "2583E9CA 2AD44CE8 DBBBC2DB 04DE8EF9 2E8EFC14 1FBECAA6" \ + "287C5947 4E6BC05D 99B2964F A090C3A2 233BA186 515BE7ED" \ + "1F612970 CEE2D7AF B81BDD76 2170481C D0069127 D5B05AA9" \ + "93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34028492" \ + "36C3FAB4 D27C7026 C1D4DCB2 602646DE C9751E76 3DBA37BD" \ + "F8FF9406 AD9E530E E5DB382F 413001AE B06A53ED 9027D831" \ + "179727B0 865A8918 DA3EDBEB CF9B14ED 44CE6CBA CED4BB1B" \ + "DB7F1447 E6CC254B 33205151 2BD7AF42 6FB8F401 378CD2BF" \ + "5983CA01 C64B92EC F032EA15 D1721D03 F482D7CE 6E74FEF6" \ + "D55E702F 46980C82 B5A84031 900B1C9E 59E7C97F BEC7E8F3" \ + "23A97A7E 36CC88BE 0F1D45B7 FF585AC5 4BD407B2 2B4154AA" \ + "CC8F6D7E BF48E1D8 14CC5ED2 0F8037E0 A79715EE F29BE328" \ + "06A1D58B B7C5DA76 F550AA3D 8A1FBFF0 EB19CCB1 A313D55C" \ + "DA56C9EC 2EF29632 387FE8D7 6E3C0468 043E8F66 3F4860EE" \ + "12BF2D5B 0B7474D6 E694F91E 6DBE1159 74A3926F 12FEE5E4" \ + "38777CB6 A932DF8C D8BEC4D0 73B931BA 3BC832B6 8D9DD300" \ + "741FA7BF 8AFC47ED 2576F693 6BA42466 3AAB639C 5AE4F568" \ + "3423B474 2BF1C978 238F16CB E39D652D E3FDB8BE FC848AD9" \ + "22222E04 A4037C07 13EB57A8 1A23F0C7 3473FC64 6CEA306B" \ + "4BCBC886 2F8385DD FA9D4B7F A2C087E8 79683303 ED5BDD3A" \ + "062B3CF5 B3A278A6 6D2A13F8 3F44F82D DF310EE0 74AB6A36" \ + "4597E899 A0255DC1 64F31CC5 0846851D F9AB4819 5DED7EA1" \ + "B1D510BD 7EE74D73 FAF36BC3 1ECFA268 359046F4 EB879F92" \ + "4009438B 481C6CD7 889A002E D5EE382B C9190DA6 FC026E47" \ + "9558E447 5677E9AA 9E3050E2 765694DF C81F56E8 80B96E71" \ + "60C980DD 98EDD3DF FFFFFFFF FFFFFFFF" +#define LOCALSECRETSIZE (512 / BITS_PER_BYTE) /* limits on nonce sizes. See RFC2409 "The internet key exchange (IKE)" 5 */ -#define MINIMUM_NONCE_SIZE 8 /* bytes */ -#define DEFAULT_NONCE_SIZE 16 /* bytes */ -#define MAXIMUM_NONCE_SIZE 256 /* bytes */ +#define MINIMUM_NONCE_SIZE 8 /* bytes */ +#define DEFAULT_NONCE_SIZE 16 /* bytes */ +#define MAXIMUM_NONCE_SIZE 256 /* bytes */ #define COOKIE_SIZE 8 #define MAX_ISAKMP_SPI_SIZE 16 -#define MD2_DIGEST_SIZE (128 / BITS_PER_BYTE) -#define MD5_DIGEST_SIZE (128 / BITS_PER_BYTE) -#define SHA1_DIGEST_SIZE (160 / BITS_PER_BYTE) -#define SHA2_256_DIGEST_SIZE (256 / BITS_PER_BYTE) -#define SHA2_384_DIGEST_SIZE (384 / BITS_PER_BYTE) -#define SHA2_512_DIGEST_SIZE (512 / BITS_PER_BYTE) +#define MD2_DIGEST_SIZE (128 / BITS_PER_BYTE) +#define MD5_DIGEST_SIZE (128 / BITS_PER_BYTE) +#define SHA1_DIGEST_SIZE (160 / BITS_PER_BYTE) +#define SHA2_256_DIGEST_SIZE (256 / BITS_PER_BYTE) +#define SHA2_384_DIGEST_SIZE (384 / BITS_PER_BYTE) +#define SHA2_512_DIGEST_SIZE (512 / BITS_PER_BYTE) -#define MD5_BLOCK_SIZE (512 / BITS_PER_BYTE) -#define SHA1_BLOCK_SIZE (512 / BITS_PER_BYTE) -#define SHA2_256_BLOCK_SIZE (512 / BITS_PER_BYTE) -#define SHA2_384_BLOCK_SIZE (1024 / BITS_PER_BYTE) -#define SHA2_512_BLOCK_SIZE (1024 / BITS_PER_BYTE) +#define MD5_BLOCK_SIZE (512 / BITS_PER_BYTE) +#define SHA1_BLOCK_SIZE (512 / BITS_PER_BYTE) +#define SHA2_256_BLOCK_SIZE (512 / BITS_PER_BYTE) +#define SHA2_384_BLOCK_SIZE (1024 / BITS_PER_BYTE) +#define SHA2_512_BLOCK_SIZE (1024 / BITS_PER_BYTE) -#define DES_CBC_BLOCK_SIZE (64 / BITS_PER_BYTE) +#define DES_CBC_BLOCK_SIZE (64 / BITS_PER_BYTE) -#define DSS_QBITS 160 /* bits in DSS's "q" (FIPS 186-1) */ +#define DSS_QBITS 160 /* bits in DSS's "q" (FIPS 186-1) */ /* Maximum is required for SHA2_512 */ -#define MAX_DIGEST_LEN SHA2_512_DIGEST_SIZE -#define MAX_HASH_BLOCK_SIZE SHA2_512_BLOCK_SIZE +#define MAX_DIGEST_LEN SHA2_512_DIGEST_SIZE +#define MAX_HASH_BLOCK_SIZE SHA2_512_BLOCK_SIZE /* RFC 2404 "HMAC-SHA-1-96" section 3 */ #define HMAC_SHA1_KEY_LEN SHA1_DIGEST_SIZE @@ -307,15 +307,15 @@ extern const char sparse_end[]; /* RFC 2403 "HMAC-MD5-96" section 3 */ #define HMAC_MD5_KEY_LEN MD5_DIGEST_SIZE -#define IKE_UDP_PORT 500 +#define IKE_UDP_PORT 500 /* RFC 2560 OCSP - certificate status */ typedef enum { - CERT_GOOD = 0, - CERT_REVOKED = 1, - CERT_UNKNOWN = 2, - CERT_UNDEFINED = 3 + CERT_GOOD = 0, + CERT_REVOKED = 1, + CERT_UNKNOWN = 2, + CERT_UNDEFINED = 3 } cert_status_t; /* RFC 2459 CRL reason codes */ @@ -323,14 +323,14 @@ typedef enum { extern enum_names crl_reason_names; typedef enum { - REASON_UNSPECIFIED = 0, - REASON_KEY_COMPROMISE = 1, - REASON_CA_COMPROMISE = 2, - REASON_AFFILIATION_CHANGED = 3, - REASON_SUPERSEDED = 4, - REASON_CESSATION_OF_OPERATON = 5, - REASON_CERTIFICATE_HOLD = 6, - REASON_REMOVE_FROM_CRL = 8 + REASON_UNSPECIFIED = 0, + REASON_KEY_COMPROMISE = 1, + REASON_CA_COMPROMISE = 2, + REASON_AFFILIATION_CHANGED = 3, + REASON_SUPERSEDED = 4, + REASON_CESSATION_OF_OPERATON = 5, + REASON_CERTIFICATE_HOLD = 6, + REASON_REMOVE_FROM_CRL = 8 } crl_reason_t; /* RFC 3706 Dead Peer Detection */ @@ -338,11 +338,11 @@ typedef enum { extern enum_names dpd_action_names; typedef enum { - DPD_ACTION_NONE = 0, - DPD_ACTION_CLEAR = 1, - DPD_ACTION_HOLD = 2, - DPD_ACTION_RESTART = 3, - DPD_ACTION_UNKNOWN = 4 + DPD_ACTION_NONE = 0, + DPD_ACTION_CLEAR = 1, + DPD_ACTION_HOLD = 2, + DPD_ACTION_RESTART = 3, + DPD_ACTION_UNKNOWN = 4 } dpd_action_t; /* Timer events */ @@ -350,24 +350,24 @@ typedef enum { extern enum_names timer_event_names; enum event_type { - EVENT_NULL, /* non-event */ - EVENT_REINIT_SECRET, /* Refresh cookie secret */ + EVENT_NULL, /* non-event */ + EVENT_REINIT_SECRET, /* Refresh cookie secret */ #ifdef KLIPS - EVENT_SHUNT_SCAN, /* scan shunt eroutes known to kernel */ + EVENT_SHUNT_SCAN, /* scan shunt eroutes known to kernel */ #endif - EVENT_SO_DISCARD, /* discard unfinished state object */ - EVENT_RETRANSMIT, /* Retransmit packet */ - EVENT_SA_REPLACE, /* SA replacement event */ - EVENT_SA_REPLACE_IF_USED, /* SA replacement event */ - EVENT_SA_EXPIRE, /* SA expiration event */ - EVENT_NAT_T_KEEPALIVE, /* NAT Traversal Keepalive */ - EVENT_DPD, /* dead peer detection */ - EVENT_DPD_TIMEOUT, /* dead peer detection timeout */ - EVENT_LOG_DAILY /* reset certain log events/stats */ + EVENT_SO_DISCARD, /* discard unfinished state object */ + EVENT_RETRANSMIT, /* Retransmit packet */ + EVENT_SA_REPLACE, /* SA replacement event */ + EVENT_SA_REPLACE_IF_USED, /* SA replacement event */ + EVENT_SA_EXPIRE, /* SA expiration event */ + EVENT_NAT_T_KEEPALIVE, /* NAT Traversal Keepalive */ + EVENT_DPD, /* dead peer detection */ + EVENT_DPD_TIMEOUT, /* dead peer detection timeout */ + EVENT_LOG_DAILY /* reset certain log events/stats */ }; -#define EVENT_REINIT_SECRET_DELAY 3600 /* 1 hour */ -#define EVENT_RETRANSMIT_DELAY_0 10 /* 10 seconds */ +#define EVENT_REINIT_SECRET_DELAY 3600 /* 1 hour */ +#define EVENT_RETRANSMIT_DELAY_0 10 /* 10 seconds */ /* Misc. stuff */ @@ -420,29 +420,29 @@ extern enum_names doi_names; extern const char *const debug_bit_names[]; #endif -#define DBG_RAW LELEM(0) /* raw packet I/O */ -#define DBG_CRYPT LELEM(1) /* encryption/decryption of messages */ -#define DBG_PARSING LELEM(2) /* show decoding of messages */ -#define DBG_EMITTING LELEM(3) /* show encoding of messages */ -#define DBG_CONTROL LELEM(4) /* control flow within Pluto */ -#define DBG_LIFECYCLE LELEM(5) /* SA lifecycle */ -#define DBG_KLIPS LELEM(6) /* messages to KLIPS */ -#define DBG_DNS LELEM(7) /* DNS activity */ -#define DBG_NATT LELEM(8) /* NAT-T */ -#define DBG_OPPO LELEM(9) /* opportunism */ -#define DBG_CONTROLMORE LELEM(10) /* more detailed debugging */ +#define DBG_RAW LELEM(0) /* raw packet I/O */ +#define DBG_CRYPT LELEM(1) /* encryption/decryption of messages */ +#define DBG_PARSING LELEM(2) /* show decoding of messages */ +#define DBG_EMITTING LELEM(3) /* show encoding of messages */ +#define DBG_CONTROL LELEM(4) /* control flow within Pluto */ +#define DBG_LIFECYCLE LELEM(5) /* SA lifecycle */ +#define DBG_KLIPS LELEM(6) /* messages to KLIPS */ +#define DBG_DNS LELEM(7) /* DNS activity */ +#define DBG_NATT LELEM(8) /* NAT-T */ +#define DBG_OPPO LELEM(9) /* opportunism */ +#define DBG_CONTROLMORE LELEM(10) /* more detailed debugging */ -#define DBG_PRIVATE LELEM(11) /* private information: DANGER! */ +#define DBG_PRIVATE LELEM(11) /* private information: DANGER! */ -#define IMPAIR0 12 /* first bit for IMPAIR_* */ +#define IMPAIR0 12 /* first bit for IMPAIR_* */ -#define IMPAIR_DELAY_ADNS_KEY_ANSWER LELEM(IMPAIR0+0) /* sleep before answering */ -#define IMPAIR_DELAY_ADNS_TXT_ANSWER LELEM(IMPAIR0+1) /* sleep before answering */ -#define IMPAIR_BUST_MI2 LELEM(IMPAIR0+2) /* make MI2 really large */ -#define IMPAIR_BUST_MR2 LELEM(IMPAIR0+3) /* make MI2 really large */ +#define IMPAIR_DELAY_ADNS_KEY_ANSWER LELEM(IMPAIR0+0) /* sleep before answering */ +#define IMPAIR_DELAY_ADNS_TXT_ANSWER LELEM(IMPAIR0+1) /* sleep before answering */ +#define IMPAIR_BUST_MI2 LELEM(IMPAIR0+2) /* make MI2 really large */ +#define IMPAIR_BUST_MR2 LELEM(IMPAIR0+3) /* make MI2 really large */ -#define DBG_NONE 0 /* no options on, including impairments */ -#define DBG_ALL LRANGES(DBG_RAW, DBG_CONTROLMORE) /* all logging options on EXCEPT DBG_PRIVATE */ +#define DBG_NONE 0 /* no options on, including impairments */ +#define DBG_ALL LRANGES(DBG_RAW, DBG_CONTROLMORE) /* all logging options on EXCEPT DBG_PRIVATE */ /* State of exchanges * @@ -475,86 +475,86 @@ extern enum_names state_names; extern const char *const state_story[]; enum state_kind { - STATE_UNDEFINED, /* 0 -- most likely accident */ + STATE_UNDEFINED, /* 0 -- most likely accident */ - /* Opportunism states: see "Opportunistic Encryption" 2.2 */ + /* Opportunism states: see "Opportunistic Encryption" 2.2 */ - OPPO_ACQUIRE, /* got an ACQUIRE message for this pair */ - OPPO_GW_DISCOVERED, /* got TXT specifying gateway */ + OPPO_ACQUIRE, /* got an ACQUIRE message for this pair */ + OPPO_GW_DISCOVERED, /* got TXT specifying gateway */ - /* IKE states */ + /* IKE states */ - STATE_MAIN_R0, - STATE_MAIN_I1, - STATE_MAIN_R1, - STATE_MAIN_I2, - STATE_MAIN_R2, - STATE_MAIN_I3, - STATE_MAIN_R3, - STATE_MAIN_I4, + STATE_MAIN_R0, + STATE_MAIN_I1, + STATE_MAIN_R1, + STATE_MAIN_I2, + STATE_MAIN_R2, + STATE_MAIN_I3, + STATE_MAIN_R3, + STATE_MAIN_I4, - STATE_QUICK_R0, - STATE_QUICK_I1, - STATE_QUICK_R1, - STATE_QUICK_I2, - STATE_QUICK_R2, + STATE_QUICK_R0, + STATE_QUICK_I1, + STATE_QUICK_R1, + STATE_QUICK_I2, + STATE_QUICK_R2, - STATE_INFO, - STATE_INFO_PROTECTED, + STATE_INFO, + STATE_INFO_PROTECTED, - /* XAUTH states */ + /* XAUTH states */ - STATE_XAUTH_I0, /* initiator state (client) */ - STATE_XAUTH_R1, /* responder state (server) */ - STATE_XAUTH_I1, - STATE_XAUTH_R2, - STATE_XAUTH_I2, - STATE_XAUTH_R3, + STATE_XAUTH_I0, /* initiator state (client) */ + STATE_XAUTH_R1, /* responder state (server) */ + STATE_XAUTH_I1, + STATE_XAUTH_R2, + STATE_XAUTH_I2, + STATE_XAUTH_R3, - /* Mode Config pull states */ + /* Mode Config pull states */ - STATE_MODE_CFG_R0, /* responder state (server) */ - STATE_MODE_CFG_I1, /* initiator state (client) */ - STATE_MODE_CFG_R1, - STATE_MODE_CFG_I2, + STATE_MODE_CFG_R0, /* responder state (server) */ + STATE_MODE_CFG_I1, /* initiator state (client) */ + STATE_MODE_CFG_R1, + STATE_MODE_CFG_I2, - /* Mode Config push states */ + /* Mode Config push states */ - STATE_MODE_CFG_I0, /* initiator state (client) */ - STATE_MODE_CFG_R3, /* responder state (server) */ - STATE_MODE_CFG_I3, - STATE_MODE_CFG_R4, + STATE_MODE_CFG_I0, /* initiator state (client) */ + STATE_MODE_CFG_R3, /* responder state (server) */ + STATE_MODE_CFG_I3, + STATE_MODE_CFG_R4, - STATE_IKE_ROOF + STATE_IKE_ROOF }; -#define STATE_IKE_FLOOR STATE_MAIN_R0 +#define STATE_IKE_FLOOR STATE_MAIN_R0 -#define PHASE1_INITIATOR_STATES (LELEM(STATE_MAIN_I1) | LELEM(STATE_MAIN_I2) \ - | LELEM(STATE_MAIN_I3) | LELEM(STATE_MAIN_I4)) +#define PHASE1_INITIATOR_STATES (LELEM(STATE_MAIN_I1) | LELEM(STATE_MAIN_I2) \ + | LELEM(STATE_MAIN_I3) | LELEM(STATE_MAIN_I4)) #define ISAKMP_SA_ESTABLISHED_STATES ( \ - LELEM(STATE_MAIN_R3) | LELEM(STATE_MAIN_I4) \ - | LELEM(STATE_XAUTH_R1) | LELEM(STATE_XAUTH_R2) | LELEM(STATE_XAUTH_R3) \ - | LELEM(STATE_XAUTH_I1) | LELEM(STATE_XAUTH_I2) \ - | LELEM(STATE_MODE_CFG_I1) | LELEM(STATE_MODE_CFG_R1) | LELEM(STATE_MODE_CFG_I2) \ - | LELEM(STATE_MODE_CFG_R3) | LELEM(STATE_MODE_CFG_I3) | LELEM(STATE_MODE_CFG_R4)) + LELEM(STATE_MAIN_R3) | LELEM(STATE_MAIN_I4) \ + | LELEM(STATE_XAUTH_R1) | LELEM(STATE_XAUTH_R2) | LELEM(STATE_XAUTH_R3) \ + | LELEM(STATE_XAUTH_I1) | LELEM(STATE_XAUTH_I2) \ + | LELEM(STATE_MODE_CFG_I1) | LELEM(STATE_MODE_CFG_R1) | LELEM(STATE_MODE_CFG_I2) \ + | LELEM(STATE_MODE_CFG_R3) | LELEM(STATE_MODE_CFG_I3) | LELEM(STATE_MODE_CFG_R4)) #define IS_PHASE1(s) ((STATE_MAIN_R0 <= (s) && (s) <= STATE_MAIN_I4) \ - || (STATE_XAUTH_I0 <= (s) && (s) <= STATE_XAUTH_R3) \ - || (STATE_MODE_CFG_R0 <= (s) && (s) <= STATE_MODE_CFG_R4)) + || (STATE_XAUTH_I0 <= (s) && (s) <= STATE_XAUTH_R3) \ + || (STATE_MODE_CFG_R0 <= (s) && (s) <= STATE_MODE_CFG_R4)) #define IS_QUICK(s) (STATE_QUICK_R0 <= (s) && (s) <= STATE_QUICK_R2) #define IS_ISAKMP_ENCRYPTED(s) (STATE_MAIN_I2 <= (s)) #define IS_ISAKMP_SA_ESTABLISHED(s) ( \ - (s) == STATE_MAIN_R3 \ - || (s) == STATE_MAIN_I4 \ - || (s) == STATE_XAUTH_I2 \ - || (s) == STATE_XAUTH_R3 \ - || (s) == STATE_MODE_CFG_R1 \ - || (s) == STATE_MODE_CFG_I2 \ - || (s) == STATE_MODE_CFG_I3 \ - || (s) == STATE_MODE_CFG_R4) + (s) == STATE_MAIN_R3 \ + || (s) == STATE_MAIN_I4 \ + || (s) == STATE_XAUTH_I2 \ + || (s) == STATE_XAUTH_R3 \ + || (s) == STATE_MODE_CFG_R1 \ + || (s) == STATE_MODE_CFG_I2 \ + || (s) == STATE_MODE_CFG_I3 \ + || (s) == STATE_MODE_CFG_R4) #define IS_IPSEC_SA_ESTABLISHED(s) ((s) == STATE_QUICK_I2 || (s) == STATE_QUICK_R2) #define IS_ONLY_INBOUND_IPSEC_SA_ESTABLISHED(s) ((s) == STATE_QUICK_R1) @@ -566,11 +566,11 @@ enum state_kind { extern enum_names connection_kind_names; enum connection_kind { - CK_GROUP, /* policy group: instantiates to template */ - CK_TEMPLATE, /* abstract connection, with wildcard */ - CK_PERMANENT, /* normal connection */ - CK_INSTANCE, /* instance of template, created for a particular attempt */ - CK_GOING_AWAY /* instance being deleted -- don't delete again */ + CK_GROUP, /* policy group: instantiates to template */ + CK_TEMPLATE, /* abstract connection, with wildcard */ + CK_PERMANENT, /* normal connection */ + CK_INSTANCE, /* instance of template, created for a particular attempt */ + CK_GOING_AWAY /* instance being deleted -- don't delete again */ }; @@ -584,14 +584,14 @@ extern enum_names routing_story; /* note that this is assumed to be ordered! */ enum routing_t { - RT_UNROUTED, /* unrouted */ - RT_UNROUTED_HOLD, /* unrouted, but HOLD shunt installed */ - RT_ROUTED_ECLIPSED, /* RT_ROUTED_PROSPECTIVE except bare HOLD or instance has eroute */ - RT_ROUTED_PROSPECTIVE, /* routed, and prospective shunt installed */ - RT_ROUTED_HOLD, /* routed, and HOLD shunt installed */ - RT_ROUTED_FAILURE, /* routed, and failure-context shunt installed */ - RT_ROUTED_TUNNEL, /* routed, and erouted to an IPSEC SA group */ - RT_UNROUTED_KEYED /* keyed, but not routed, on purpose */ + RT_UNROUTED, /* unrouted */ + RT_UNROUTED_HOLD, /* unrouted, but HOLD shunt installed */ + RT_ROUTED_ECLIPSED, /* RT_ROUTED_PROSPECTIVE except bare HOLD or instance has eroute */ + RT_ROUTED_PROSPECTIVE, /* routed, and prospective shunt installed */ + RT_ROUTED_HOLD, /* routed, and HOLD shunt installed */ + RT_ROUTED_FAILURE, /* routed, and failure-context shunt installed */ + RT_ROUTED_TUNNEL, /* routed, and erouted to an IPSEC SA group */ + RT_UNROUTED_KEYED /* keyed, but not routed, on purpose */ }; #define routed(rs) ((rs) > RT_UNROUTED_HOLD) @@ -609,25 +609,25 @@ enum routing_t { extern enum_names payload_names; extern const char *const payload_name[]; -#define ISAKMP_NEXT_NONE 0 /* No other payload following */ -#define ISAKMP_NEXT_SA 1 /* Security Association */ -#define ISAKMP_NEXT_P 2 /* Proposal */ -#define ISAKMP_NEXT_T 3 /* Transform */ -#define ISAKMP_NEXT_KE 4 /* Key Exchange */ -#define ISAKMP_NEXT_ID 5 /* Identification */ -#define ISAKMP_NEXT_CERT 6 /* Certificate */ -#define ISAKMP_NEXT_CR 7 /* Certificate Request */ -#define ISAKMP_NEXT_HASH 8 /* Hash */ -#define ISAKMP_NEXT_SIG 9 /* Signature */ -#define ISAKMP_NEXT_NONCE 10 /* Nonce */ -#define ISAKMP_NEXT_N 11 /* Notification */ -#define ISAKMP_NEXT_D 12 /* Delete */ -#define ISAKMP_NEXT_VID 13 /* Vendor ID */ +#define ISAKMP_NEXT_NONE 0 /* No other payload following */ +#define ISAKMP_NEXT_SA 1 /* Security Association */ +#define ISAKMP_NEXT_P 2 /* Proposal */ +#define ISAKMP_NEXT_T 3 /* Transform */ +#define ISAKMP_NEXT_KE 4 /* Key Exchange */ +#define ISAKMP_NEXT_ID 5 /* Identification */ +#define ISAKMP_NEXT_CERT 6 /* Certificate */ +#define ISAKMP_NEXT_CR 7 /* Certificate Request */ +#define ISAKMP_NEXT_HASH 8 /* Hash */ +#define ISAKMP_NEXT_SIG 9 /* Signature */ +#define ISAKMP_NEXT_NONCE 10 /* Nonce */ +#define ISAKMP_NEXT_N 11 /* Notification */ +#define ISAKMP_NEXT_D 12 /* Delete */ +#define ISAKMP_NEXT_VID 13 /* Vendor ID */ #define ISAKMP_NEXT_ATTR 14 /* Mode config Attribute */ -#define ISAKMP_NEXT_NATD_RFC 20 /* NAT-Traversal: NAT-D (rfc) */ -#define ISAKMP_NEXT_NATOA_RFC 21 /* NAT-Traversal: NAT-OA (rfc) */ -#define ISAKMP_NEXT_ROOF 22 /* roof on payload types */ +#define ISAKMP_NEXT_NATD_RFC 20 /* NAT-Traversal: NAT-D (rfc) */ +#define ISAKMP_NEXT_NATOA_RFC 21 /* NAT-Traversal: NAT-OA (rfc) */ +#define ISAKMP_NEXT_ROOF 22 /* roof on payload types */ #define ISAKMP_NEXT_NATD_DRAFTS 130 /* NAT-Traversal: NAT-D (drafts) */ #define ISAKMP_NEXT_NATOA_DRAFTS 131 /* NAT-Traversal: NAT-OA (drafts) */ @@ -679,23 +679,23 @@ extern enum_names modecfg_attr_names; extern enum_names xauth_attr_names; /* ISAKMP mode config attributes specific to Microsoft */ -#define INTERNAL_IP4_SERVER 23456 -#define INTERNAL_IP6_SERVER 23457 +#define INTERNAL_IP4_SERVER 23456 +#define INTERNAL_IP6_SERVER 23457 extern enum_names microsoft_attr_names; /* ISAKMP mode config attributes specific to the Unity vendor ID */ -#define UNITY_BANNER 28672 -#define UNITY_SAVE_PASSWD 28673 -#define UNITY_DEF_DOMAIN 28674 -#define UNITY_SPLITDNS_NAME 28675 -#define UNITY_SPLIT_INCLUDE 28676 -#define UNITY_NATT_PORT 28677 -#define UNITY_LOCAL_LAN 28678 -#define UNITY_PFS 28679 -#define UNITY_FW_TYPE 28680 -#define UNITY_BACKUP_SERVERS 28681 -#define UNITY_DDNS_HOSTNAME 28682 +#define UNITY_BANNER 28672 +#define UNITY_SAVE_PASSWD 28673 +#define UNITY_DEF_DOMAIN 28674 +#define UNITY_SPLITDNS_NAME 28675 +#define UNITY_SPLIT_INCLUDE 28676 +#define UNITY_NATT_PORT 28677 +#define UNITY_LOCAL_LAN 28678 +#define UNITY_PFS 28679 +#define UNITY_FW_TYPE 28680 +#define UNITY_BACKUP_SERVERS 28681 +#define UNITY_DDNS_HOSTNAME 28682 #define UNITY_BASE UNITY_BANNER @@ -708,8 +708,8 @@ extern enum_names unity_attr_names; #define XAUTH_TYPE_SKEY 3 /* Values for XAUTH_STATUS */ -#define XAUTH_STATUS_FAIL 0 -#define XAUTH_STATUS_OK 1 +#define XAUTH_STATUS_FAIL 0 +#define XAUTH_STATUS_OK 1 extern enum_names xauth_type_names; @@ -729,19 +729,19 @@ extern enum_names exchange_names; #define ISAKMP_XCHG_NONE 0 #define ISAKMP_XCHG_BASE 1 -#define ISAKMP_XCHG_IDPROT 2 /* ID Protection */ -#define ISAKMP_XCHG_AO 3 /* Authentication Only */ -#define ISAKMP_XCHG_AGGR 4 /* Aggressive */ -#define ISAKMP_XCHG_INFO 5 /* Informational */ -#define ISAKMP_XCHG_MODE_CFG 6 /* Mode Config */ +#define ISAKMP_XCHG_IDPROT 2 /* ID Protection */ +#define ISAKMP_XCHG_AO 3 /* Authentication Only */ +#define ISAKMP_XCHG_AGGR 4 /* Aggressive */ +#define ISAKMP_XCHG_INFO 5 /* Informational */ +#define ISAKMP_XCHG_MODE_CFG 6 /* Mode Config */ /* Extra exchange types, defined by Oakley * RFC2409 "The Internet Key Exchange (IKE)", near end of Appendix A */ -#define ISAKMP_XCHG_QUICK 32 /* Oakley Quick Mode */ -#define ISAKMP_XCHG_NGRP 33 /* Oakley New Group Mode */ +#define ISAKMP_XCHG_QUICK 32 /* Oakley Quick Mode */ +#define ISAKMP_XCHG_NGRP 33 /* Oakley New Group Mode */ /* added in draft-ietf-ipsec-ike-01.txt, near end of Appendix A */ -#define ISAKMP_XCHG_ACK_INFO 34 /* Oakley Acknowledged Informational */ +#define ISAKMP_XCHG_ACK_INFO 34 /* Oakley Acknowledged Informational */ /* Flag bits */ @@ -771,10 +771,10 @@ extern enum_names protocol_names; /* warning: trans_show uses enum_show, so same static buffer is used */ #define trans_show(p, t) \ - ((p)==PROTO_IPSEC_AH ? enum_show(&ah_transformid_names, (t)) \ - : (p)==PROTO_IPSEC_ESP ? enum_show(&esp_transformid_names, (t)) \ - : (p)==PROTO_IPCOMP ? enum_show(&ipcomp_transformid_names, (t)) \ - : "??") + ((p)==PROTO_IPSEC_AH ? enum_show(&ah_transformid_names, (t)) \ + : (p)==PROTO_IPSEC_ESP ? enum_show(&esp_transformid_names, (t)) \ + : (p)==PROTO_IPCOMP ? enum_show(&ipcomp_transformid_names, (t)) \ + : "??") /* many transform values are moved to freeswan/ipsec_policy.h */ @@ -801,12 +801,12 @@ extern enum_names cert_type_names; extern enum_names cert_policy_names; typedef enum certpolicy { - CERT_ALWAYS_SEND = 0, /* the default */ + CERT_ALWAYS_SEND = 0, /* the default */ CERT_SEND_IF_ASKED = 1, CERT_NEVER_SEND = 2, - CERT_YES_SEND = 3, /* synonym for CERT_ALWAYS_SEND */ - CERT_NO_SEND = 4 /* synonym for CERT_NEVER_SEND */ + CERT_YES_SEND = 3, /* synonym for CERT_ALWAYS_SEND */ + CERT_NO_SEND = 4 /* synonym for CERT_NEVER_SEND */ } certpolicy_t; /* Policies for establishing an SA @@ -824,34 +824,34 @@ extern const char *prettypolicy(lset_t policy); #define POLICY_PSK LELEM(0) #define POLICY_RSASIG LELEM(1) -#define POLICY_ISAKMP_SHIFT 0 /* log2(POLICY_PSK) */ -#define POLICY_ID_AUTH_MASK (POLICY_PSK | POLICY_RSASIG | POLICY_XAUTH_PSK | POLICY_XAUTH_RSASIG) -#define POLICY_ISAKMP_MASK POLICY_ID_AUTH_MASK /* all so far */ +#define POLICY_ISAKMP_SHIFT 0 /* log2(POLICY_PSK) */ +#define POLICY_ID_AUTH_MASK (POLICY_PSK | POLICY_RSASIG | POLICY_XAUTH_PSK | POLICY_XAUTH_RSASIG) +#define POLICY_ISAKMP_MASK POLICY_ID_AUTH_MASK /* all so far */ /* Quick Mode (IPSEC) attributes */ -#define POLICY_ENCRYPT LELEM(2) /* must be first of IPSEC policies */ -#define POLICY_AUTHENTICATE LELEM(3) /* must be second */ -#define POLICY_COMPRESS LELEM(4) /* must be third */ +#define POLICY_ENCRYPT LELEM(2) /* must be first of IPSEC policies */ +#define POLICY_AUTHENTICATE LELEM(3) /* must be second */ +#define POLICY_COMPRESS LELEM(4) /* must be third */ #define POLICY_TUNNEL LELEM(5) #define POLICY_PFS LELEM(6) -#define POLICY_DISABLEARRIVALCHECK LELEM(7) /* supress tunnel egress address checking */ +#define POLICY_DISABLEARRIVALCHECK LELEM(7) /* supress tunnel egress address checking */ -#define POLICY_IPSEC_SHIFT 2 /* log2(POLICY_ENCRYPT) */ -#define POLICY_IPSEC_MASK LRANGES(POLICY_ENCRYPT, POLICY_DISABLEARRIVALCHECK) +#define POLICY_IPSEC_SHIFT 2 /* log2(POLICY_ENCRYPT) */ +#define POLICY_IPSEC_MASK LRANGES(POLICY_ENCRYPT, POLICY_DISABLEARRIVALCHECK) /* shunt attributes: what to do when routed without tunnel (2 bits) */ -#define POLICY_SHUNT_SHIFT 8 /* log2(POLICY_SHUNT_PASS) */ -#define POLICY_SHUNT_MASK (03ul << POLICY_SHUNT_SHIFT) +#define POLICY_SHUNT_SHIFT 8 /* log2(POLICY_SHUNT_PASS) */ +#define POLICY_SHUNT_MASK (03ul << POLICY_SHUNT_SHIFT) -#define POLICY_SHUNT_TRAP (0ul << POLICY_SHUNT_SHIFT) /* default: negotiate */ -#define POLICY_SHUNT_PASS (1ul << POLICY_SHUNT_SHIFT) -#define POLICY_SHUNT_DROP (2ul << POLICY_SHUNT_SHIFT) -#define POLICY_SHUNT_REJECT (3ul << POLICY_SHUNT_SHIFT) +#define POLICY_SHUNT_TRAP (0ul << POLICY_SHUNT_SHIFT) /* default: negotiate */ +#define POLICY_SHUNT_PASS (1ul << POLICY_SHUNT_SHIFT) +#define POLICY_SHUNT_DROP (2ul << POLICY_SHUNT_SHIFT) +#define POLICY_SHUNT_REJECT (3ul << POLICY_SHUNT_SHIFT) /* fail attributes: what to do with failed negotiation (2 bits) */ -#define POLICY_FAIL_SHIFT 10 /* log2(POLICY_FAIL_PASS) */ -#define POLICY_FAIL_MASK (03ul << POLICY_FAIL_SHIFT) +#define POLICY_FAIL_SHIFT 10 /* log2(POLICY_FAIL_PASS) */ +#define POLICY_FAIL_MASK (03ul << POLICY_FAIL_SHIFT) #define POLICY_FAIL_NONE (0ul << POLICY_FAIL_SHIFT) /* default */ #define POLICY_FAIL_PASS (1ul << POLICY_FAIL_SHIFT) @@ -861,21 +861,21 @@ extern const char *prettypolicy(lset_t policy); /* connection policy * Other policies could vary per state object. These live in connection. */ -#define POLICY_DONT_REKEY LELEM(12) /* don't rekey state either Phase */ -#define POLICY_OPPO LELEM(13) /* is this opportunistic? */ -#define POLICY_GROUP LELEM(14) /* is this a group template? */ -#define POLICY_GROUTED LELEM(15) /* do we want this group routed? */ -#define POLICY_UP LELEM(16) /* do we want this up? */ -#define POLICY_MODECFG_PUSH LELEM(17) /* is modecfg pushed by server? */ -#define POLICY_XAUTH_PSK LELEM(18) /* do we support XAUTH????PreShared? */ -#define POLICY_XAUTH_RSASIG LELEM(19) /* do we support XAUTH????RSA? */ -#define POLICY_XAUTH_SERVER LELEM(20) /* are we an XAUTH server? */ -#define POLICY_DONT_REAUTH LELEM(21) /* don't reauthenticate on rekeying, IKEv2 only */ -#define POLICY_BEET LELEM(22) /* bound end2end tunnel, IKEv2 */ -#define POLICY_MOBIKE LELEM(23) /* enable MOBIKE for IKEv2 */ -#define POLICY_FORCE_ENCAP LELEM(24) /* force UDP encapsulation (IKEv2) */ -#define POLICY_ECDSASIG LELEM(25) /* ECDSA signature (IKEv2) */ -#define POLICY_PROXY LELEM(26) /* proxy transport mode (MIPv6) */ +#define POLICY_DONT_REKEY LELEM(12) /* don't rekey state either Phase */ +#define POLICY_OPPO LELEM(13) /* is this opportunistic? */ +#define POLICY_GROUP LELEM(14) /* is this a group template? */ +#define POLICY_GROUTED LELEM(15) /* do we want this group routed? */ +#define POLICY_UP LELEM(16) /* do we want this up? */ +#define POLICY_MODECFG_PUSH LELEM(17) /* is modecfg pushed by server? */ +#define POLICY_XAUTH_PSK LELEM(18) /* do we support XAUTH????PreShared? */ +#define POLICY_XAUTH_RSASIG LELEM(19) /* do we support XAUTH????RSA? */ +#define POLICY_XAUTH_SERVER LELEM(20) /* are we an XAUTH server? */ +#define POLICY_DONT_REAUTH LELEM(21) /* don't reauthenticate on rekeying, IKEv2 only */ +#define POLICY_BEET LELEM(22) /* bound end2end tunnel, IKEv2 */ +#define POLICY_MOBIKE LELEM(23) /* enable MOBIKE for IKEv2 */ +#define POLICY_FORCE_ENCAP LELEM(24) /* force UDP encapsulation (IKEv2) */ +#define POLICY_ECDSASIG LELEM(25) /* ECDSA signature (IKEv2) */ +#define POLICY_PROXY LELEM(26) /* proxy transport mode (MIPv6) */ /* Any IPsec policy? If not, a connection description * is only for ISAKMP SA, not IPSEC SA. (A pun, I admit.) @@ -900,17 +900,17 @@ extern const char *const oakley_attr_bit_names[]; #define OAKLEY_AUTHENTICATION_METHOD 3 #define OAKLEY_GROUP_DESCRIPTION 4 #define OAKLEY_GROUP_TYPE 5 -#define OAKLEY_GROUP_PRIME 6 /* B/V */ -#define OAKLEY_GROUP_GENERATOR_ONE 7 /* B/V */ -#define OAKLEY_GROUP_GENERATOR_TWO 8 /* B/V */ -#define OAKLEY_GROUP_CURVE_A 9 /* B/V */ -#define OAKLEY_GROUP_CURVE_B 10 /* B/V */ +#define OAKLEY_GROUP_PRIME 6 /* B/V */ +#define OAKLEY_GROUP_GENERATOR_ONE 7 /* B/V */ +#define OAKLEY_GROUP_GENERATOR_TWO 8 /* B/V */ +#define OAKLEY_GROUP_CURVE_A 9 /* B/V */ +#define OAKLEY_GROUP_CURVE_B 10 /* B/V */ #define OAKLEY_LIFE_TYPE 11 -#define OAKLEY_LIFE_DURATION 12 /* B/V */ +#define OAKLEY_LIFE_DURATION 12 /* B/V */ #define OAKLEY_PRF 13 #define OAKLEY_KEY_LENGTH 14 #define OAKLEY_FIELD_SIZE 15 -#define OAKLEY_GROUP_ORDER 16 /* B/V */ +#define OAKLEY_GROUP_ORDER 16 /* B/V */ #define OAKLEY_BLOCK_SIZE 17 /* for each Oakley attribute, which enum_names describes its values? */ @@ -923,14 +923,14 @@ extern enum_names *oakley_attr_val_descs[]; extern enum_names ipsec_attr_names; #define SA_LIFE_TYPE 1 -#define SA_LIFE_DURATION 2 /* B/V */ +#define SA_LIFE_DURATION 2 /* B/V */ #define GROUP_DESCRIPTION 3 #define ENCAPSULATION_MODE 4 #define AUTH_ALGORITHM 5 #define KEY_LENGTH 6 #define KEY_ROUNDS 7 #define COMPRESS_DICT_SIZE 8 -#define COMPRESS_PRIVATE_ALG 9 /* B/V */ +#define COMPRESS_PRIVATE_ALG 9 /* B/V */ /* for each IPsec attribute, which enum_names describes its values? */ extern enum_names *ipsec_attr_val_descs[]; @@ -958,9 +958,9 @@ extern enum_names sa_lifetime_names; #define PLUTO_SA_LIFE_DURATION_DEFAULT 3600 /* one hour (pluto(8)) */ #define SA_LIFE_DURATION_MAXIMUM 86400 /* one day */ -#define SA_REPLACEMENT_MARGIN_DEFAULT 540 /* (IPSEC & IKE) nine minutes */ -#define SA_REPLACEMENT_FUZZ_DEFAULT 100 /* (IPSEC & IKE) 100% of MARGIN */ -#define SA_REPLACEMENT_RETRIES_DEFAULT 3 /* (IPSEC & IKE) */ +#define SA_REPLACEMENT_MARGIN_DEFAULT 540 /* (IPSEC & IKE) nine minutes */ +#define SA_REPLACEMENT_FUZZ_DEFAULT 100 /* (IPSEC & IKE) 100% of MARGIN */ +#define SA_REPLACEMENT_RETRIES_DEFAULT 3 /* (IPSEC & IKE) */ #define SA_LIFE_DURATION_K_DEFAULT 0xFFFFFFFFlu @@ -968,7 +968,7 @@ extern enum_names sa_lifetime_names; extern enum_names enc_mode_names; -#define ENCAPSULATION_MODE_UNSPECIFIED 0 /* not legal -- used internally */ +#define ENCAPSULATION_MODE_UNSPECIFIED 0 /* not legal -- used internally */ #define ENCAPSULATION_MODE_TUNNEL 1 #define ENCAPSULATION_MODE_TRANSPORT 2 @@ -982,18 +982,18 @@ extern enum_names enc_mode_names; extern enum_names auth_alg_names, extended_auth_alg_names; -#define AUTH_ALGORITHM_NONE 0 /* our private designation */ -#define AUTH_ALGORITHM_HMAC_MD5 1 -#define AUTH_ALGORITHM_HMAC_SHA1 2 -#define AUTH_ALGORITHM_DES_MAC 3 -#define AUTH_ALGORITHM_KPDK 4 -#define AUTH_ALGORITHM_HMAC_SHA2_256 5 -#define AUTH_ALGORITHM_HMAC_SHA2_384 6 -#define AUTH_ALGORITHM_HMAC_SHA2_512 7 -#define AUTH_ALGORITHM_HMAC_RIPEMD 8 -#define AUTH_ALGORITHM_AES_XCBC_MAC 9 -#define AUTH_ALGORITHM_SIG_RSA 10 -#define AUTH_ALGORITHM_NULL 251 +#define AUTH_ALGORITHM_NONE 0 /* our private designation */ +#define AUTH_ALGORITHM_HMAC_MD5 1 +#define AUTH_ALGORITHM_HMAC_SHA1 2 +#define AUTH_ALGORITHM_DES_MAC 3 +#define AUTH_ALGORITHM_KPDK 4 +#define AUTH_ALGORITHM_HMAC_SHA2_256 5 +#define AUTH_ALGORITHM_HMAC_SHA2_384 6 +#define AUTH_ALGORITHM_HMAC_SHA2_512 7 +#define AUTH_ALGORITHM_HMAC_RIPEMD 8 +#define AUTH_ALGORITHM_AES_XCBC_MAC 9 +#define AUTH_ALGORITHM_SIG_RSA 10 +#define AUTH_ALGORITHM_NULL 251 /* Oakley Lifetime Type attribute * draft-ietf-ipsec-ike-01.txt appendix A @@ -1027,23 +1027,23 @@ extern enum_names oakley_prf_names; extern enum_names oakley_enc_names; -#define OAKLEY_DES_CBC 1 -#define OAKLEY_IDEA_CBC 2 -#define OAKLEY_BLOWFISH_CBC 3 -#define OAKLEY_RC5_R16_B64_CBC 4 -#define OAKLEY_3DES_CBC 5 -#define OAKLEY_CAST_CBC 6 -#define OAKLEY_AES_CBC 7 +#define OAKLEY_DES_CBC 1 +#define OAKLEY_IDEA_CBC 2 +#define OAKLEY_BLOWFISH_CBC 3 +#define OAKLEY_RC5_R16_B64_CBC 4 +#define OAKLEY_3DES_CBC 5 +#define OAKLEY_CAST_CBC 6 +#define OAKLEY_AES_CBC 7 -#define OAKLEY_MARS_CBC 65001 -#define OAKLEY_RC6_CBC 65002 -#define OAKLEY_ID_65003 65003 -#define OAKLEY_SERPENT_CBC 65004 -#define OAKLEY_TWOFISH_CBC 65005 +#define OAKLEY_MARS_CBC 65001 +#define OAKLEY_RC6_CBC 65002 +#define OAKLEY_ID_65003 65003 +#define OAKLEY_SERPENT_CBC 65004 +#define OAKLEY_TWOFISH_CBC 65005 -#define OAKLEY_TWOFISH_CBC_SSH 65289 +#define OAKLEY_TWOFISH_CBC_SSH 65289 -#define OAKLEY_ENCRYPT_MAX 65535 /* pretty useless :) */ +#define OAKLEY_ENCRYPT_MAX 65535 /* pretty useless :) */ /* Oakley Hash Algorithm attribute * draft-ietf-ipsec-ike-01.txt appendix A @@ -1077,23 +1077,23 @@ extern enum_names oakley_auth_names; #define OAKLEY_ELGAMAL_ENC 6 #define OAKLEY_ELGAMAL_ENC_REV 7 -#define OAKLEY_AUTH_ROOF 8 /* roof on auth values THAT WE SUPPORT */ +#define OAKLEY_AUTH_ROOF 8 /* roof on auth values THAT WE SUPPORT */ -#define HybridInitRSA 64221 -#define HybridRespRSA 64222 -#define HybridInitDSS 64223 -#define HybridRespDSS 64224 +#define HybridInitRSA 64221 +#define HybridRespRSA 64222 +#define HybridInitDSS 64223 +#define HybridRespDSS 64224 -#define XAUTHInitPreShared 65001 -#define XAUTHRespPreShared 65002 -#define XAUTHInitDSS 65003 +#define XAUTHInitPreShared 65001 +#define XAUTHRespPreShared 65002 +#define XAUTHInitDSS 65003 #define XAUTHRespDSS 65004 -#define XAUTHInitRSA 65005 -#define XAUTHRespRSA 65006 -#define XAUTHInitRSAEncryption 65007 -#define XAUTHRespRSAEncryption 65008 -#define XAUTHInitRSARevisedEncryption 65009 -#define XAUTHRespRSARevisedEncryption 65010 +#define XAUTHInitRSA 65005 +#define XAUTHRespRSA 65006 +#define XAUTHInitRSAEncryption 65007 +#define XAUTHRespRSAEncryption 65008 +#define XAUTHInitRSARevisedEncryption 65009 +#define XAUTHRespRSARevisedEncryption 65010 /* Oakley Group Description attribute * draft-ietf-ipsec-ike-01.txt appendix A @@ -1111,7 +1111,7 @@ extern enum_names oakley_group_names; #define OAKLEY_GROUP_MODP4096 16 #define OAKLEY_GROUP_MODP6144 17 #define OAKLEY_GROUP_MODP8192 18 -/* you must also touch: constants.c, crypto.c */ +/* you must also touch: constants.c, crypto.c */ /* Oakley Group Type attribute * draft-ietf-ipsec-ike-01.txt appendix A @@ -1131,54 +1131,54 @@ extern enum_names notification_names; extern enum_names ipsec_notification_names; typedef enum { - NOTHING_WRONG = 0, /* unofficial! */ + NOTHING_WRONG = 0, /* unofficial! */ - INVALID_PAYLOAD_TYPE = 1, - DOI_NOT_SUPPORTED = 2, - SITUATION_NOT_SUPPORTED = 3, - INVALID_COOKIE = 4, - INVALID_MAJOR_VERSION = 5, - INVALID_MINOR_VERSION = 6, - INVALID_EXCHANGE_TYPE = 7, - INVALID_FLAGS = 8, - INVALID_MESSAGE_ID = 9, - INVALID_PROTOCOL_ID = 10, - INVALID_SPI = 11, - INVALID_TRANSFORM_ID = 12, - ATTRIBUTES_NOT_SUPPORTED = 13, - NO_PROPOSAL_CHOSEN = 14, - BAD_PROPOSAL_SYNTAX = 15, - PAYLOAD_MALFORMED = 16, - INVALID_KEY_INFORMATION = 17, - INVALID_ID_INFORMATION = 18, - INVALID_CERT_ENCODING = 19, - INVALID_CERTIFICATE = 20, - CERT_TYPE_UNSUPPORTED = 21, - INVALID_CERT_AUTHORITY = 22, - INVALID_HASH_INFORMATION = 23, - AUTHENTICATION_FAILED = 24, - INVALID_SIGNATURE = 25, - ADDRESS_NOTIFICATION = 26, - NOTIFY_SA_LIFETIME = 27, - CERTIFICATE_UNAVAILABLE = 28, - UNSUPPORTED_EXCHANGE_TYPE = 29, - UNEQUAL_PAYLOAD_LENGTHS = 30, + INVALID_PAYLOAD_TYPE = 1, + DOI_NOT_SUPPORTED = 2, + SITUATION_NOT_SUPPORTED = 3, + INVALID_COOKIE = 4, + INVALID_MAJOR_VERSION = 5, + INVALID_MINOR_VERSION = 6, + INVALID_EXCHANGE_TYPE = 7, + INVALID_FLAGS = 8, + INVALID_MESSAGE_ID = 9, + INVALID_PROTOCOL_ID = 10, + INVALID_SPI = 11, + INVALID_TRANSFORM_ID = 12, + ATTRIBUTES_NOT_SUPPORTED = 13, + NO_PROPOSAL_CHOSEN = 14, + BAD_PROPOSAL_SYNTAX = 15, + PAYLOAD_MALFORMED = 16, + INVALID_KEY_INFORMATION = 17, + INVALID_ID_INFORMATION = 18, + INVALID_CERT_ENCODING = 19, + INVALID_CERTIFICATE = 20, + CERT_TYPE_UNSUPPORTED = 21, + INVALID_CERT_AUTHORITY = 22, + INVALID_HASH_INFORMATION = 23, + AUTHENTICATION_FAILED = 24, + INVALID_SIGNATURE = 25, + ADDRESS_NOTIFICATION = 26, + NOTIFY_SA_LIFETIME = 27, + CERTIFICATE_UNAVAILABLE = 28, + UNSUPPORTED_EXCHANGE_TYPE = 29, + UNEQUAL_PAYLOAD_LENGTHS = 30, - /* ISAKMP status type */ - CONNECTED = 16384, + /* ISAKMP status type */ + CONNECTED = 16384, - /* IPSEC DOI additions; status types (RFC2407 IPSEC DOI 4.6.3) - * These must be sent under the protection of an ISAKMP SA. - */ - IPSEC_RESPONDER_LIFETIME = 24576, - IPSEC_REPLAY_STATUS = 24577, - IPSEC_INITIAL_CONTACT = 24578, + /* IPSEC DOI additions; status types (RFC2407 IPSEC DOI 4.6.3) + * These must be sent under the protection of an ISAKMP SA. + */ + IPSEC_RESPONDER_LIFETIME = 24576, + IPSEC_REPLAY_STATUS = 24577, + IPSEC_INITIAL_CONTACT = 24578, - /* RFC 3706 DPD */ - R_U_THERE = 36136, - R_U_THERE_ACK = 36137 + /* RFC 3706 DPD */ + R_U_THERE = 36136, + R_U_THERE_ACK = 36137 - } notification_t; + } notification_t; /* Public key algorithm number @@ -1189,8 +1189,8 @@ typedef enum { enum pubkey_alg { - PUBKEY_ALG_RSA = 1, - PUBKEY_ALG_DSA = 3, + PUBKEY_ALG_RSA = 1, + PUBKEY_ALG_DSA = 3, }; /* Limits on size of RSA moduli. @@ -1200,37 +1200,37 @@ enum pubkey_alg * real security. For now, we require 512 bits. */ -#define RSA_MIN_OCTETS_RFC 12 +#define RSA_MIN_OCTETS_RFC 12 -#define RSA_MIN_OCTETS (512 / BITS_PER_BYTE) -#define RSA_MIN_OCTETS_UGH "RSA modulus too small for security: less than 512 bits" +#define RSA_MIN_OCTETS (512 / BITS_PER_BYTE) +#define RSA_MIN_OCTETS_UGH "RSA modulus too small for security: less than 512 bits" -#define RSA_MAX_OCTETS (8192 / BITS_PER_BYTE) -#define RSA_MAX_OCTETS_UGH "RSA modulus too large: more than 8192 bits" +#define RSA_MAX_OCTETS (8192 / BITS_PER_BYTE) +#define RSA_MAX_OCTETS_UGH "RSA modulus too large: more than 8192 bits" /* Note: RFC 2537 encoding adds a few bytes. If you use a small * modulus like 3, the overhead is only 2 bytes */ -#define RSA_MAX_ENCODING_BYTES (RSA_MAX_OCTETS + 2) +#define RSA_MAX_ENCODING_BYTES (RSA_MAX_OCTETS + 2) /* socket address family info */ struct af_info { - int af; - const char *name; - size_t ia_sz; - size_t sa_sz; - int mask_cnt; - u_int8_t id_addr, id_subnet, id_range; - const ip_address *any; - const ip_subnet *none; /* 0.0.0.0/32 or IPv6 equivalent */ - const ip_subnet *all; /* 0.0.0.0/0 or IPv6 equivalent */ + int af; + const char *name; + size_t ia_sz; + size_t sa_sz; + int mask_cnt; + u_int8_t id_addr, id_subnet, id_range; + const ip_address *any; + const ip_subnet *none; /* 0.0.0.0/32 or IPv6 equivalent */ + const ip_subnet *all; /* 0.0.0.0/0 or IPv6 equivalent */ }; extern const struct af_info - af_inet4_info, - af_inet6_info; + af_inet4_info, + af_inet6_info; extern const struct af_info *aftoinfo(int af); @@ -1242,18 +1242,18 @@ extern bool subnetisnone(const ip_subnet *sn); /* BIND enumerated types */ extern enum_names - rr_qtype_names, - rr_type_names, - rr_class_names; + rr_qtype_names, + rr_type_names, + rr_class_names; /* How authenticated is info that might have come from DNS? * In order of increasing confidence. */ enum dns_auth_level { - DAL_UNSIGNED, /* AD in response, but no signature: no authentication */ - DAL_NOTSEC, /* no AD in response: authentication impossible */ - DAL_SIGNED, /* AD and signature in response: authentic */ - DAL_LOCAL /* locally provided (pretty good) */ + DAL_UNSIGNED, /* AD in response, but no signature: no authentication */ + DAL_NOTSEC, /* no AD in response: authentication impossible */ + DAL_SIGNED, /* AD and signature in response: authentic */ + DAL_LOCAL /* locally provided (pretty good) */ }; /* diff --git a/src/pluto/cookie.c b/src/pluto/cookie.c index 31d1f69cd..f13152f0d 100644 --- a/src/pluto/cookie.c +++ b/src/pluto/cookie.c @@ -29,7 +29,7 @@ #include "rnd.h" #include "cookie.h" -const u_char zero_cookie[COOKIE_SIZE]; /* guaranteed 0 */ +const u_char zero_cookie[COOKIE_SIZE]; /* guaranteed 0 */ /* Generate a cookie. * First argument is true if we're to create an Initiator cookie. @@ -38,30 +38,30 @@ const u_char zero_cookie[COOKIE_SIZE]; /* guaranteed 0 */ void get_cookie(bool initiator, u_int8_t *cookie, int length, const ip_address *addr) { - u_char buffer[SHA1_DIGEST_SIZE]; - SHA1_CTX ctx; + u_char buffer[SHA1_DIGEST_SIZE]; + SHA1_CTX ctx; - do { - if (initiator) - { - get_rnd_bytes(cookie, length); - } - else /* Responder cookie */ - { - /* This looks as good as any way */ - size_t addr_length; - static u_int32_t counter = 0; - unsigned char addr_buff[ - sizeof(union {struct in_addr A; struct in6_addr B;})]; + do { + if (initiator) + { + get_rnd_bytes(cookie, length); + } + else /* Responder cookie */ + { + /* This looks as good as any way */ + size_t addr_length; + static u_int32_t counter = 0; + unsigned char addr_buff[ + sizeof(union {struct in_addr A; struct in6_addr B;})]; - addr_length = addrbytesof(addr, addr_buff, sizeof(addr_buff)); - SHA1Init(&ctx); - SHA1Update(&ctx, addr_buff, addr_length); - SHA1Update(&ctx, secret_of_the_day, sizeof(secret_of_the_day)); - counter++; - SHA1Update(&ctx, (const void *) &counter, sizeof(counter)); - SHA1Final(buffer, &ctx); - memcpy(cookie, buffer, length); - } - } while (is_zero_cookie(cookie)); /* probably never loops */ + addr_length = addrbytesof(addr, addr_buff, sizeof(addr_buff)); + SHA1Init(&ctx); + SHA1Update(&ctx, addr_buff, addr_length); + SHA1Update(&ctx, secret_of_the_day, sizeof(secret_of_the_day)); + counter++; + SHA1Update(&ctx, (const void *) &counter, sizeof(counter)); + SHA1Final(buffer, &ctx); + memcpy(cookie, buffer, length); + } + } while (is_zero_cookie(cookie)); /* probably never loops */ } diff --git a/src/pluto/cookie.h b/src/pluto/cookie.h index 9b8fb7ce3..ceacc69ef 100644 --- a/src/pluto/cookie.h +++ b/src/pluto/cookie.h @@ -16,9 +16,9 @@ #include -extern const u_char zero_cookie[COOKIE_SIZE]; /* guaranteed 0 */ +extern const u_char zero_cookie[COOKIE_SIZE]; /* guaranteed 0 */ extern void get_cookie(bool initiator, u_int8_t *cookie, int length - , const ip_address *addr); + , const ip_address *addr); #define is_zero_cookie(cookie) all_zero((cookie), COOKIE_SIZE) diff --git a/src/pluto/crl.c b/src/pluto/crl.c index 1119d4ad0..eb9765b0b 100644 --- a/src/pluto/crl.c +++ b/src/pluto/crl.c @@ -46,84 +46,84 @@ static x509crl_t *x509crls = NULL; /* ASN.1 definition of an X.509 certificate list */ static const asn1Object_t crlObjects[] = { - { 0, "certificateList", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */ - { 1, "tbsCertList", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */ - { 2, "version", ASN1_INTEGER, ASN1_OPT | - ASN1_BODY }, /* 2 */ - { 2, "end opt", ASN1_EOC, ASN1_END }, /* 3 */ - { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 4 */ - { 2, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */ - { 2, "thisUpdate", ASN1_EOC, ASN1_RAW }, /* 6 */ - { 2, "nextUpdate", ASN1_EOC, ASN1_RAW }, /* 7 */ - { 2, "revokedCertificates", ASN1_SEQUENCE, ASN1_OPT | - ASN1_LOOP }, /* 8 */ - { 3, "certList", ASN1_SEQUENCE, ASN1_NONE }, /* 9 */ - { 4, "userCertificate", ASN1_INTEGER, ASN1_BODY }, /* 10 */ - { 4, "revocationDate", ASN1_EOC, ASN1_RAW }, /* 11 */ - { 4, "crlEntryExtensions", ASN1_SEQUENCE, ASN1_OPT | - ASN1_LOOP }, /* 12 */ - { 5, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 13 */ - { 6, "extnID", ASN1_OID, ASN1_BODY }, /* 14 */ - { 6, "critical", ASN1_BOOLEAN, ASN1_DEF | - ASN1_BODY }, /* 15 */ - { 6, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 16 */ - { 4, "end opt or loop", ASN1_EOC, ASN1_END }, /* 17 */ - { 2, "end opt or loop", ASN1_EOC, ASN1_END }, /* 18 */ - { 2, "optional extensions", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 19 */ - { 3, "crlExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 20 */ - { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 21 */ - { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 22 */ - { 5, "critical", ASN1_BOOLEAN, ASN1_DEF | - ASN1_BODY }, /* 23 */ - { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 24 */ - { 3, "end loop", ASN1_EOC, ASN1_END }, /* 25 */ - { 2, "end opt", ASN1_EOC, ASN1_END }, /* 26 */ - { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 27 */ - { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY } /* 28 */ + { 0, "certificateList", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */ + { 1, "tbsCertList", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */ + { 2, "version", ASN1_INTEGER, ASN1_OPT | + ASN1_BODY }, /* 2 */ + { 2, "end opt", ASN1_EOC, ASN1_END }, /* 3 */ + { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 4 */ + { 2, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */ + { 2, "thisUpdate", ASN1_EOC, ASN1_RAW }, /* 6 */ + { 2, "nextUpdate", ASN1_EOC, ASN1_RAW }, /* 7 */ + { 2, "revokedCertificates", ASN1_SEQUENCE, ASN1_OPT | + ASN1_LOOP }, /* 8 */ + { 3, "certList", ASN1_SEQUENCE, ASN1_NONE }, /* 9 */ + { 4, "userCertificate", ASN1_INTEGER, ASN1_BODY }, /* 10 */ + { 4, "revocationDate", ASN1_EOC, ASN1_RAW }, /* 11 */ + { 4, "crlEntryExtensions", ASN1_SEQUENCE, ASN1_OPT | + ASN1_LOOP }, /* 12 */ + { 5, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 13 */ + { 6, "extnID", ASN1_OID, ASN1_BODY }, /* 14 */ + { 6, "critical", ASN1_BOOLEAN, ASN1_DEF | + ASN1_BODY }, /* 15 */ + { 6, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 16 */ + { 4, "end opt or loop", ASN1_EOC, ASN1_END }, /* 17 */ + { 2, "end opt or loop", ASN1_EOC, ASN1_END }, /* 18 */ + { 2, "optional extensions", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 19 */ + { 3, "crlExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 20 */ + { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 21 */ + { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 22 */ + { 5, "critical", ASN1_BOOLEAN, ASN1_DEF | + ASN1_BODY }, /* 23 */ + { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 24 */ + { 3, "end loop", ASN1_EOC, ASN1_END }, /* 25 */ + { 2, "end opt", ASN1_EOC, ASN1_END }, /* 26 */ + { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 27 */ + { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY } /* 28 */ }; -#define CRL_OBJ_CERTIFICATE_LIST 0 -#define CRL_OBJ_TBS_CERT_LIST 1 -#define CRL_OBJ_VERSION 2 -#define CRL_OBJ_SIG_ALG 4 -#define CRL_OBJ_ISSUER 5 -#define CRL_OBJ_THIS_UPDATE 6 -#define CRL_OBJ_NEXT_UPDATE 7 -#define CRL_OBJ_USER_CERTIFICATE 10 -#define CRL_OBJ_REVOCATION_DATE 11 -#define CRL_OBJ_CRL_ENTRY_EXTN_ID 14 -#define CRL_OBJ_CRL_ENTRY_CRITICAL 15 -#define CRL_OBJ_CRL_ENTRY_EXTN_VALUE 16 -#define CRL_OBJ_EXTN_ID 22 -#define CRL_OBJ_CRITICAL 23 -#define CRL_OBJ_EXTN_VALUE 24 -#define CRL_OBJ_ALGORITHM 27 -#define CRL_OBJ_SIGNATURE 28 -#define CRL_OBJ_ROOF 29 +#define CRL_OBJ_CERTIFICATE_LIST 0 +#define CRL_OBJ_TBS_CERT_LIST 1 +#define CRL_OBJ_VERSION 2 +#define CRL_OBJ_SIG_ALG 4 +#define CRL_OBJ_ISSUER 5 +#define CRL_OBJ_THIS_UPDATE 6 +#define CRL_OBJ_NEXT_UPDATE 7 +#define CRL_OBJ_USER_CERTIFICATE 10 +#define CRL_OBJ_REVOCATION_DATE 11 +#define CRL_OBJ_CRL_ENTRY_EXTN_ID 14 +#define CRL_OBJ_CRL_ENTRY_CRITICAL 15 +#define CRL_OBJ_CRL_ENTRY_EXTN_VALUE 16 +#define CRL_OBJ_EXTN_ID 22 +#define CRL_OBJ_CRITICAL 23 +#define CRL_OBJ_EXTN_VALUE 24 +#define CRL_OBJ_ALGORITHM 27 +#define CRL_OBJ_SIGNATURE 28 +#define CRL_OBJ_ROOF 29 const x509crl_t empty_x509crl = { - NULL , /* *next */ - UNDEFINED_TIME, /* installed */ - NULL , /* distributionPoints */ - { NULL, 0 } , /* certificateList */ - { NULL, 0 } , /* tbsCertList */ - 1 , /* version */ - OID_UNKNOWN , /* sigAlg */ - { NULL, 0 } , /* issuer */ - UNDEFINED_TIME, /* thisUpdate */ - UNDEFINED_TIME, /* nextUpdate */ - NULL , /* revokedCertificates */ - /* crlExtensions */ - /* extension */ - /* extnID */ - /* critical */ - /* extnValue */ - { NULL, 0 } , /* authKeyID */ - { NULL, 0 } , /* authKeySerialNumber */ - { NULL, 0 } , /* crlNumber */ - OID_UNKNOWN , /* algorithm */ - { NULL, 0 } /* signature */ + NULL , /* *next */ + UNDEFINED_TIME, /* installed */ + NULL , /* distributionPoints */ + { NULL, 0 } , /* certificateList */ + { NULL, 0 } , /* tbsCertList */ + 1 , /* version */ + OID_UNKNOWN , /* sigAlg */ + { NULL, 0 } , /* issuer */ + UNDEFINED_TIME, /* thisUpdate */ + UNDEFINED_TIME, /* nextUpdate */ + NULL , /* revokedCertificates */ + /* crlExtensions */ + /* extension */ + /* extnID */ + /* critical */ + /* extnValue */ + { NULL, 0 } , /* authKeyID */ + { NULL, 0 } , /* authKeySerialNumber */ + { NULL, 0 } , /* crlNumber */ + OID_UNKNOWN , /* algorithm */ + { NULL, 0 } /* signature */ }; /* @@ -132,28 +132,28 @@ const x509crl_t empty_x509crl = { static x509crl_t* get_x509crl(chunk_t issuer, chunk_t serial, chunk_t keyid) { - x509crl_t *crl = x509crls; - x509crl_t *prev_crl = NULL; + x509crl_t *crl = x509crls; + x509crl_t *prev_crl = NULL; - while (crl != NULL) - { - if ((keyid.ptr != NULL && crl->authKeyID.ptr != NULL) - ? same_keyid(keyid, crl->authKeyID) - : (same_dn(crl->issuer, issuer) && same_serial(serial, crl->authKeySerialNumber))) + while (crl != NULL) { - if (crl != x509crls) - { - /* bring the CRL up front */ - prev_crl->next = crl->next; - crl->next = x509crls; - x509crls = crl; - } - return crl; + if ((keyid.ptr != NULL && crl->authKeyID.ptr != NULL) + ? same_keyid(keyid, crl->authKeyID) + : (same_dn(crl->issuer, issuer) && same_serial(serial, crl->authKeySerialNumber))) + { + if (crl != x509crls) + { + /* bring the CRL up front */ + prev_crl->next = crl->next; + crl->next = x509crls; + x509crls = crl; + } + return crl; + } + prev_crl = crl; + crl = crl->next; } - prev_crl = crl; - crl = crl->next; - } - return NULL; + return NULL; } /* @@ -162,12 +162,12 @@ get_x509crl(chunk_t issuer, chunk_t serial, chunk_t keyid) static void free_revoked_certs(revokedCert_t* revokedCerts) { - while (revokedCerts != NULL) - { - revokedCert_t * revokedCert = revokedCerts; - revokedCerts = revokedCert->next; - free(revokedCert); - } + while (revokedCerts != NULL) + { + revokedCert_t * revokedCert = revokedCerts; + revokedCerts = revokedCert->next; + free(revokedCert); + } } /* @@ -176,30 +176,30 @@ free_revoked_certs(revokedCert_t* revokedCerts) void free_crl(x509crl_t *crl) { - free_revoked_certs(crl->revokedCertificates); - free_generalNames(crl->distributionPoints, TRUE); - free(crl->certificateList.ptr); - free(crl); + free_revoked_certs(crl->revokedCertificates); + free_generalNames(crl->distributionPoints, TRUE); + free(crl->certificateList.ptr); + free(crl); } static void free_first_crl(void) { - x509crl_t *crl = x509crls; + x509crl_t *crl = x509crls; - x509crls = crl->next; - free_crl(crl); + x509crls = crl->next; + free_crl(crl); } void free_crls(void) { - lock_crl_list("free_crls"); + lock_crl_list("free_crls"); - while (x509crls != NULL) - free_first_crl(); + while (x509crls != NULL) + free_first_crl(); - unlock_crl_list("free_crls"); + unlock_crl_list("free_crls"); } /* @@ -208,118 +208,118 @@ free_crls(void) bool insert_crl(chunk_t blob, chunk_t crl_uri, bool cache_crl) { - x509crl_t *crl = malloc_thing(x509crl_t); + x509crl_t *crl = malloc_thing(x509crl_t); - *crl = empty_x509crl; + *crl = empty_x509crl; - if (parse_x509crl(blob, 0, crl)) - { - x509cert_t *issuer_cert; - x509crl_t *oldcrl; - bool valid_sig; - generalName_t *gn; - - /* add distribution point */ - gn = malloc_thing(generalName_t); - gn->kind = GN_URI; - gn->name = crl_uri; - gn->next = crl->distributionPoints; - crl->distributionPoints = gn; - - lock_authcert_list("insert_crl"); - /* get the issuer cacert */ - issuer_cert = get_authcert(crl->issuer, crl->authKeySerialNumber, - crl->authKeyID, AUTH_CA); - if (issuer_cert == NULL) + if (parse_x509crl(blob, 0, crl)) { - plog("crl issuer cacert not found"); - free_crl(crl); - unlock_authcert_list("insert_crl"); - return FALSE; - } - DBG(DBG_CONTROL, - DBG_log("crl issuer cacert found") - ) + x509cert_t *issuer_cert; + x509crl_t *oldcrl; + bool valid_sig; + generalName_t *gn; - /* check the issuer's signature of the crl */ - valid_sig = check_signature(crl->tbsCertList, crl->signature - , crl->algorithm, crl->algorithm, issuer_cert); - unlock_authcert_list("insert_crl"); + /* add distribution point */ + gn = malloc_thing(generalName_t); + gn->kind = GN_URI; + gn->name = crl_uri; + gn->next = crl->distributionPoints; + crl->distributionPoints = gn; - if (!valid_sig) - { - free_crl(crl); - return FALSE; - } - DBG(DBG_CONTROL, - DBG_log("crl signature is valid") - ) - - lock_crl_list("insert_crl"); - oldcrl = get_x509crl(crl->issuer, crl->authKeySerialNumber - , crl->authKeyID); - - if (oldcrl != NULL) - { - if (crl->thisUpdate > oldcrl->thisUpdate) - { - /* keep any known CRL distribution points */ - add_distribution_points(oldcrl->distributionPoints - , &crl->distributionPoints); - - /* now delete the old CRL */ - free_first_crl(); + lock_authcert_list("insert_crl"); + /* get the issuer cacert */ + issuer_cert = get_authcert(crl->issuer, crl->authKeySerialNumber, + crl->authKeyID, AUTH_CA); + if (issuer_cert == NULL) + { + plog("crl issuer cacert not found"); + free_crl(crl); + unlock_authcert_list("insert_crl"); + return FALSE; + } DBG(DBG_CONTROL, - DBG_log("thisUpdate is newer - existing crl deleted") + DBG_log("crl issuer cacert found") ) - } - else - { - unlock_crl_list("insert_crls"); + + /* check the issuer's signature of the crl */ + valid_sig = check_signature(crl->tbsCertList, crl->signature + , crl->algorithm, crl->algorithm, issuer_cert); + unlock_authcert_list("insert_crl"); + + if (!valid_sig) + { + free_crl(crl); + return FALSE; + } DBG(DBG_CONTROL, - DBG_log("thisUpdate is not newer - existing crl not replaced"); + DBG_log("crl signature is valid") ) + + lock_crl_list("insert_crl"); + oldcrl = get_x509crl(crl->issuer, crl->authKeySerialNumber + , crl->authKeyID); + + if (oldcrl != NULL) + { + if (crl->thisUpdate > oldcrl->thisUpdate) + { + /* keep any known CRL distribution points */ + add_distribution_points(oldcrl->distributionPoints + , &crl->distributionPoints); + + /* now delete the old CRL */ + free_first_crl(); + DBG(DBG_CONTROL, + DBG_log("thisUpdate is newer - existing crl deleted") + ) + } + else + { + unlock_crl_list("insert_crls"); + DBG(DBG_CONTROL, + DBG_log("thisUpdate is not newer - existing crl not replaced"); + ) + free_crl(crl); + return oldcrl->nextUpdate - time(NULL) > 2*crl_check_interval; + } + } + + /* insert new CRL */ + crl->next = x509crls; + x509crls = crl; + + unlock_crl_list("insert_crl"); + + /* If crl caching is enabled then the crl is saved locally. + * Only http or ldap URIs are cached but not local file URIs. + * The issuer's subjectKeyID is used as a unique filename + */ + if (cache_crl && strncasecmp(crl_uri.ptr, "file", 4) != 0) + { + char path[BUF_LEN]; + char buf[BUF_LEN]; + char digest_buf[SHA1_DIGEST_SIZE]; + chunk_t subjectKeyID = { digest_buf, SHA1_DIGEST_SIZE }; + + if (issuer_cert->subjectKeyID.ptr == NULL) + compute_subjectKeyID(issuer_cert, subjectKeyID); + else + subjectKeyID = issuer_cert->subjectKeyID; + + datatot(subjectKeyID.ptr, subjectKeyID.len, 16, buf, BUF_LEN); + snprintf(path, BUF_LEN, "%s/%s.crl", CRL_PATH, buf); + write_chunk(path, "crl", crl->certificateList, 0022, TRUE); + } + + /* is the fetched crl valid? */ + return crl->nextUpdate - time(NULL) > 2*crl_check_interval; + } + else + { + plog(" error in X.509 crl"); free_crl(crl); - return oldcrl->nextUpdate - time(NULL) > 2*crl_check_interval; - } + return FALSE; } - - /* insert new CRL */ - crl->next = x509crls; - x509crls = crl; - - unlock_crl_list("insert_crl"); - - /* If crl caching is enabled then the crl is saved locally. - * Only http or ldap URIs are cached but not local file URIs. - * The issuer's subjectKeyID is used as a unique filename - */ - if (cache_crl && strncasecmp(crl_uri.ptr, "file", 4) != 0) - { - char path[BUF_LEN]; - char buf[BUF_LEN]; - char digest_buf[SHA1_DIGEST_SIZE]; - chunk_t subjectKeyID = { digest_buf, SHA1_DIGEST_SIZE }; - - if (issuer_cert->subjectKeyID.ptr == NULL) - compute_subjectKeyID(issuer_cert, subjectKeyID); - else - subjectKeyID = issuer_cert->subjectKeyID; - - datatot(subjectKeyID.ptr, subjectKeyID.len, 16, buf, BUF_LEN); - snprintf(path, BUF_LEN, "%s/%s.crl", CRL_PATH, buf); - write_chunk(path, "crl", crl->certificateList, 0022, TRUE); - } - - /* is the fetched crl valid? */ - return crl->nextUpdate - time(NULL) > 2*crl_check_interval; - } - else - { - plog(" error in X.509 crl"); - free_crl(crl); - return FALSE; - } } /* @@ -328,52 +328,52 @@ insert_crl(chunk_t blob, chunk_t crl_uri, bool cache_crl) void load_crls(void) { - struct dirent **filelist; - u_char buf[BUF_LEN]; - u_char *save_dir; - int n; + struct dirent **filelist; + u_char buf[BUF_LEN]; + u_char *save_dir; + int n; - /* change directory to specified path */ - save_dir = getcwd(buf, BUF_LEN); - if (chdir(CRL_PATH)) - { - plog("Could not change to directory '%s'", CRL_PATH); - } - else - { - plog("Changing to directory '%s'", CRL_PATH); - n = scandir(CRL_PATH, &filelist, file_select, alphasort); - - if (n < 0) - plog(" scandir() error"); + /* change directory to specified path */ + save_dir = getcwd(buf, BUF_LEN); + if (chdir(CRL_PATH)) + { + plog("Could not change to directory '%s'", CRL_PATH); + } else { - while (n--) - { - bool pgp = FALSE; - chunk_t blob = chunk_empty; - char *filename = filelist[n]->d_name; + plog("Changing to directory '%s'", CRL_PATH); + n = scandir(CRL_PATH, &filelist, file_select, alphasort); - if (load_coded_file(filename, NULL, "crl", &blob, &pgp)) + if (n < 0) + plog(" scandir() error"); + else { - chunk_t crl_uri; + while (n--) + { + bool pgp = FALSE; + chunk_t blob = chunk_empty; + char *filename = filelist[n]->d_name; - crl_uri.len = 7 + sizeof(CRL_PATH) + strlen(filename); - crl_uri.ptr = malloc(crl_uri.len + 1); + if (load_coded_file(filename, NULL, "crl", &blob, &pgp)) + { + chunk_t crl_uri; - /* build CRL file URI */ - snprintf(crl_uri.ptr, crl_uri.len + 1, "file://%s/%s" - , CRL_PATH, filename); + crl_uri.len = 7 + sizeof(CRL_PATH) + strlen(filename); + crl_uri.ptr = malloc(crl_uri.len + 1); - insert_crl(blob, crl_uri, FALSE); + /* build CRL file URI */ + snprintf(crl_uri.ptr, crl_uri.len + 1, "file://%s/%s" + , CRL_PATH, filename); + + insert_crl(blob, crl_uri, FALSE); + } + free(filelist[n]); + } + free(filelist); } - free(filelist[n]); - } - free(filelist); } - } - /* restore directory path */ - ignore_result(chdir(save_dir)); + /* restore directory path */ + ignore_result(chdir(save_dir)); } /* @@ -382,18 +382,18 @@ load_crls(void) static crl_reason_t parse_crl_reasonCode(chunk_t object) { - crl_reason_t reason = REASON_UNSPECIFIED; + crl_reason_t reason = REASON_UNSPECIFIED; - if (*object.ptr == ASN1_ENUMERATED - && asn1_length(&object) == 1) - { - reason = *object.ptr; - } + if (*object.ptr == ASN1_ENUMERATED + && asn1_length(&object) == 1) + { + reason = *object.ptr; + } - DBG(DBG_PARSING, - DBG_log(" '%s'", enum_name(&crl_reason_names, reason)) - ) - return reason; + DBG(DBG_PARSING, + DBG_log(" '%s'", enum_name(&crl_reason_names, reason)) + ) + return reason; } /* @@ -402,117 +402,117 @@ parse_crl_reasonCode(chunk_t object) bool parse_x509crl(chunk_t blob, u_int level0, x509crl_t *crl) { - u_char buf[BUF_LEN]; - asn1_ctx_t ctx; - bool critical; - chunk_t extnID; - chunk_t userCertificate = chunk_empty; - chunk_t object; - u_int level; - int objectID = 0; + u_char buf[BUF_LEN]; + asn1_ctx_t ctx; + bool critical; + chunk_t extnID; + chunk_t userCertificate = chunk_empty; + chunk_t object; + u_int level; + int objectID = 0; - asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); + asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); - while (objectID < CRL_OBJ_ROOF) - { - if (!extract_object(crlObjects, &objectID, &object, &level, &ctx)) - return FALSE; + while (objectID < CRL_OBJ_ROOF) + { + if (!extract_object(crlObjects, &objectID, &object, &level, &ctx)) + return FALSE; - /* those objects which will parsed further need the next higher level */ - level++; + /* those objects which will parsed further need the next higher level */ + level++; - switch (objectID) { - case CRL_OBJ_CERTIFICATE_LIST: - crl->certificateList = object; - break; - case CRL_OBJ_TBS_CERT_LIST: - crl->tbsCertList = object; - break; - case CRL_OBJ_VERSION: - crl->version = (object.len) ? (1+(u_int)*object.ptr) : 1; - DBG(DBG_PARSING, - DBG_log(" v%d", crl->version); - ) - break; - case CRL_OBJ_SIG_ALG: - crl->sigAlg = parse_algorithmIdentifier(object, level, NULL); - break; - case CRL_OBJ_ISSUER: - crl->issuer = object; - DBG(DBG_PARSING, - dntoa(buf, BUF_LEN, object); - DBG_log(" '%s'",buf) - ) - break; - case CRL_OBJ_THIS_UPDATE: - crl->thisUpdate = parse_time(object, level); - break; - case CRL_OBJ_NEXT_UPDATE: - crl->nextUpdate = parse_time(object, level); - break; - case CRL_OBJ_USER_CERTIFICATE: - userCertificate = object; - break; - case CRL_OBJ_REVOCATION_DATE: - { - /* put all the serial numbers and the revocation date in a chained list - with revocedCertificates pointing to the first revoked certificate */ + switch (objectID) { + case CRL_OBJ_CERTIFICATE_LIST: + crl->certificateList = object; + break; + case CRL_OBJ_TBS_CERT_LIST: + crl->tbsCertList = object; + break; + case CRL_OBJ_VERSION: + crl->version = (object.len) ? (1+(u_int)*object.ptr) : 1; + DBG(DBG_PARSING, + DBG_log(" v%d", crl->version); + ) + break; + case CRL_OBJ_SIG_ALG: + crl->sigAlg = parse_algorithmIdentifier(object, level, NULL); + break; + case CRL_OBJ_ISSUER: + crl->issuer = object; + DBG(DBG_PARSING, + dntoa(buf, BUF_LEN, object); + DBG_log(" '%s'",buf) + ) + break; + case CRL_OBJ_THIS_UPDATE: + crl->thisUpdate = parse_time(object, level); + break; + case CRL_OBJ_NEXT_UPDATE: + crl->nextUpdate = parse_time(object, level); + break; + case CRL_OBJ_USER_CERTIFICATE: + userCertificate = object; + break; + case CRL_OBJ_REVOCATION_DATE: + { + /* put all the serial numbers and the revocation date in a chained list + with revocedCertificates pointing to the first revoked certificate */ - revokedCert_t *revokedCert = malloc_thing(revokedCert_t); - revokedCert->userCertificate = userCertificate; - revokedCert->revocationDate = parse_time(object, level); - revokedCert->revocationReason = REASON_UNSPECIFIED; - revokedCert->next = crl->revokedCertificates; - crl->revokedCertificates = revokedCert; - } - break; - case CRL_OBJ_CRL_ENTRY_EXTN_ID: - case CRL_OBJ_EXTN_ID: - extnID = object; - break; - case CRL_OBJ_CRL_ENTRY_CRITICAL: - case CRL_OBJ_CRITICAL: - critical = object.len && *object.ptr; - DBG(DBG_PARSING, - DBG_log(" %s",(critical)?"TRUE":"FALSE"); - ) - break; - case CRL_OBJ_CRL_ENTRY_EXTN_VALUE: - case CRL_OBJ_EXTN_VALUE: - { - u_int extn_oid = asn1_known_oid(extnID); + revokedCert_t *revokedCert = malloc_thing(revokedCert_t); + revokedCert->userCertificate = userCertificate; + revokedCert->revocationDate = parse_time(object, level); + revokedCert->revocationReason = REASON_UNSPECIFIED; + revokedCert->next = crl->revokedCertificates; + crl->revokedCertificates = revokedCert; + } + break; + case CRL_OBJ_CRL_ENTRY_EXTN_ID: + case CRL_OBJ_EXTN_ID: + extnID = object; + break; + case CRL_OBJ_CRL_ENTRY_CRITICAL: + case CRL_OBJ_CRITICAL: + critical = object.len && *object.ptr; + DBG(DBG_PARSING, + DBG_log(" %s",(critical)?"TRUE":"FALSE"); + ) + break; + case CRL_OBJ_CRL_ENTRY_EXTN_VALUE: + case CRL_OBJ_EXTN_VALUE: + { + u_int extn_oid = asn1_known_oid(extnID); - if (extn_oid == OID_CRL_REASON_CODE) - { - crl->revokedCertificates->revocationReason = - parse_crl_reasonCode(object); + if (extn_oid == OID_CRL_REASON_CODE) + { + crl->revokedCertificates->revocationReason = + parse_crl_reasonCode(object); + } + else if (extn_oid == OID_AUTHORITY_KEY_ID) + { + parse_authorityKeyIdentifier(object, level + , &crl->authKeyID, &crl->authKeySerialNumber); + } + else if (extn_oid == OID_CRL_NUMBER) + { + if (!parse_asn1_simple_object(&object, ASN1_INTEGER, level, "crlNumber")) + return FALSE; + crl->crlNumber = object; + } + } + break; + case CRL_OBJ_ALGORITHM: + crl->algorithm = parse_algorithmIdentifier(object, level, NULL); + break; + case CRL_OBJ_SIGNATURE: + crl->signature = object; + break; + default: + break; } - else if (extn_oid == OID_AUTHORITY_KEY_ID) - { - parse_authorityKeyIdentifier(object, level - , &crl->authKeyID, &crl->authKeySerialNumber); - } - else if (extn_oid == OID_CRL_NUMBER) - { - if (!parse_asn1_simple_object(&object, ASN1_INTEGER, level, "crlNumber")) - return FALSE; - crl->crlNumber = object; - } - } - break; - case CRL_OBJ_ALGORITHM: - crl->algorithm = parse_algorithmIdentifier(object, level, NULL); - break; - case CRL_OBJ_SIGNATURE: - crl->signature = object; - break; - default: - break; + objectID++; } - objectID++; - } - time(&crl->installed); - return TRUE; + time(&crl->installed); + return TRUE; } /* Checks if the current certificate is revoked. It goes through the @@ -523,28 +523,28 @@ static cert_status_t check_revocation(const x509crl_t *crl, chunk_t serial , time_t *revocationDate, crl_reason_t * revocationReason) { - revokedCert_t *revokedCert = crl->revokedCertificates; + revokedCert_t *revokedCert = crl->revokedCertificates; - *revocationDate = UNDEFINED_TIME; - *revocationReason = REASON_UNSPECIFIED; - - DBG(DBG_CONTROL, - DBG_dump_chunk("serial number:", serial) - ) + *revocationDate = UNDEFINED_TIME; + *revocationReason = REASON_UNSPECIFIED; + + DBG(DBG_CONTROL, + DBG_dump_chunk("serial number:", serial) + ) - while(revokedCert != NULL) - { - /* compare serial numbers */ - if (revokedCert->userCertificate.len == serial.len && - memeq(revokedCert->userCertificate.ptr, serial.ptr, serial.len)) + while(revokedCert != NULL) { - *revocationDate = revokedCert->revocationDate; - *revocationReason = revokedCert->revocationReason; - return CERT_REVOKED; + /* compare serial numbers */ + if (revokedCert->userCertificate.len == serial.len && + memeq(revokedCert->userCertificate.ptr, serial.ptr, serial.len)) + { + *revocationDate = revokedCert->revocationDate; + *revocationReason = revokedCert->revocationReason; + return CERT_REVOKED; + } + revokedCert = revokedCert->next; } - revokedCert = revokedCert->next; - } - return CERT_GOOD; + return CERT_GOOD; } /* @@ -553,37 +553,37 @@ check_revocation(const x509crl_t *crl, chunk_t serial void check_crls(void) { - x509crl_t *crl; + x509crl_t *crl; - lock_crl_list("check_crls"); - crl = x509crls; + lock_crl_list("check_crls"); + crl = x509crls; - while (crl != NULL) - { - time_t time_left = crl->nextUpdate - time(NULL); - u_char buf[BUF_LEN]; - - DBG(DBG_CONTROL, - dntoa(buf, BUF_LEN, crl->issuer); - DBG_log("issuer: '%s'",buf); - if (crl->authKeyID.ptr != NULL) - { - datatot(crl->authKeyID.ptr, crl->authKeyID.len, ':' - , buf, BUF_LEN); - DBG_log("authkey: %s", buf); - } - DBG_log("%ld seconds left", time_left) - ) - if (time_left < 2*crl_check_interval) + while (crl != NULL) { - fetch_req_t *req = build_crl_fetch_request(crl->issuer - , crl->authKeySerialNumber - , crl->authKeyID, crl->distributionPoints); - add_crl_fetch_request(req); + time_t time_left = crl->nextUpdate - time(NULL); + u_char buf[BUF_LEN]; + + DBG(DBG_CONTROL, + dntoa(buf, BUF_LEN, crl->issuer); + DBG_log("issuer: '%s'",buf); + if (crl->authKeyID.ptr != NULL) + { + datatot(crl->authKeyID.ptr, crl->authKeyID.len, ':' + , buf, BUF_LEN); + DBG_log("authkey: %s", buf); + } + DBG_log("%ld seconds left", time_left) + ) + if (time_left < 2*crl_check_interval) + { + fetch_req_t *req = build_crl_fetch_request(crl->issuer + , crl->authKeySerialNumber + , crl->authKeyID, crl->distributionPoints); + add_crl_fetch_request(req); + } + crl = crl->next; } - crl = crl->next; - } - unlock_crl_list("check_crls"); + unlock_crl_list("check_crls"); } /* @@ -593,117 +593,117 @@ cert_status_t verify_by_crl(const x509cert_t *cert, time_t *until, time_t *revocationDate , crl_reason_t *revocationReason) { - x509crl_t *crl; + x509crl_t *crl; - ca_info_t *ca = get_ca_info(cert->issuer, cert->authKeySerialNumber - , cert->authKeyID); + ca_info_t *ca = get_ca_info(cert->issuer, cert->authKeySerialNumber + , cert->authKeyID); - generalName_t *crluri = (ca == NULL)? NULL : ca->crluri; + generalName_t *crluri = (ca == NULL)? NULL : ca->crluri; - *revocationDate = UNDEFINED_TIME; - *revocationReason = REASON_UNSPECIFIED; + *revocationDate = UNDEFINED_TIME; + *revocationReason = REASON_UNSPECIFIED; - lock_crl_list("verify_by_crl"); - crl = get_x509crl(cert->issuer, cert->authKeySerialNumber, cert->authKeyID); + lock_crl_list("verify_by_crl"); + crl = get_x509crl(cert->issuer, cert->authKeySerialNumber, cert->authKeyID); - if (crl == NULL) - { - unlock_crl_list("verify_by_crl"); - plog("crl not found"); - - if (cert->crlDistributionPoints != NULL) + if (crl == NULL) { - fetch_req_t *req = build_crl_fetch_request(cert->issuer - , cert->authKeySerialNumber - , cert->authKeyID, cert->crlDistributionPoints); - add_crl_fetch_request(req); - } + unlock_crl_list("verify_by_crl"); + plog("crl not found"); - if (crluri != NULL) - { - fetch_req_t *req = build_crl_fetch_request(cert->issuer - , cert->authKeySerialNumber - , cert->authKeyID, crluri); - add_crl_fetch_request(req); - } + if (cert->crlDistributionPoints != NULL) + { + fetch_req_t *req = build_crl_fetch_request(cert->issuer + , cert->authKeySerialNumber + , cert->authKeyID, cert->crlDistributionPoints); + add_crl_fetch_request(req); + } - if (cert->crlDistributionPoints != 0 || crluri != NULL) - { - wake_fetch_thread("verify_by_crl"); - return CERT_UNKNOWN; + if (crluri != NULL) + { + fetch_req_t *req = build_crl_fetch_request(cert->issuer + , cert->authKeySerialNumber + , cert->authKeyID, crluri); + add_crl_fetch_request(req); + } + + if (cert->crlDistributionPoints != 0 || crluri != NULL) + { + wake_fetch_thread("verify_by_crl"); + return CERT_UNKNOWN; + } + else + return CERT_UNDEFINED; } else - return CERT_UNDEFINED; - } - else - { - x509cert_t *issuer_cert; - bool valid; - - DBG(DBG_CONTROL, - DBG_log("crl found") - ) - - add_distribution_points(cert->crlDistributionPoints - , &crl->distributionPoints); - - add_distribution_points(crluri - , &crl->distributionPoints); - - lock_authcert_list("verify_by_crl"); - - issuer_cert = get_authcert(crl->issuer, crl->authKeySerialNumber - , crl->authKeyID, AUTH_CA); - valid = check_signature(crl->tbsCertList, crl->signature - , crl->algorithm, crl->algorithm, issuer_cert); - - unlock_authcert_list("verify_by_crl"); - - if (valid) { - cert_status_t status; + x509cert_t *issuer_cert; + bool valid; - DBG(DBG_CONTROL, - DBG_log("crl signature is valid") - ) - /* return the expiration date */ - *until = crl->nextUpdate; - - /* has the certificate been revoked? */ - status = check_revocation(crl, cert->serialNumber, revocationDate - , revocationReason); - - if (*until < time(NULL)) - { - fetch_req_t *req; - - plog("crl update is overdue since %T", until, TRUE); - - /* try to fetch a crl update */ - req = build_crl_fetch_request(crl->issuer - , crl->authKeySerialNumber - , crl->authKeyID, crl->distributionPoints); - unlock_crl_list("verify_by_crl"); - - add_crl_fetch_request(req); - wake_fetch_thread("verify_by_crl"); - } - else - { - unlock_crl_list("verify_by_crl"); DBG(DBG_CONTROL, - DBG_log("crl is valid") + DBG_log("crl found") ) - } - return status; + + add_distribution_points(cert->crlDistributionPoints + , &crl->distributionPoints); + + add_distribution_points(crluri + , &crl->distributionPoints); + + lock_authcert_list("verify_by_crl"); + + issuer_cert = get_authcert(crl->issuer, crl->authKeySerialNumber + , crl->authKeyID, AUTH_CA); + valid = check_signature(crl->tbsCertList, crl->signature + , crl->algorithm, crl->algorithm, issuer_cert); + + unlock_authcert_list("verify_by_crl"); + + if (valid) + { + cert_status_t status; + + DBG(DBG_CONTROL, + DBG_log("crl signature is valid") + ) + /* return the expiration date */ + *until = crl->nextUpdate; + + /* has the certificate been revoked? */ + status = check_revocation(crl, cert->serialNumber, revocationDate + , revocationReason); + + if (*until < time(NULL)) + { + fetch_req_t *req; + + plog("crl update is overdue since %T", until, TRUE); + + /* try to fetch a crl update */ + req = build_crl_fetch_request(crl->issuer + , crl->authKeySerialNumber + , crl->authKeyID, crl->distributionPoints); + unlock_crl_list("verify_by_crl"); + + add_crl_fetch_request(req); + wake_fetch_thread("verify_by_crl"); + } + else + { + unlock_crl_list("verify_by_crl"); + DBG(DBG_CONTROL, + DBG_log("crl is valid") + ) + } + return status; + } + else + { + unlock_crl_list("verify_by_crl"); + plog("crl signature is invalid"); + return CERT_UNKNOWN; + } } - else - { - unlock_crl_list("verify_by_crl"); - plog("crl signature is invalid"); - return CERT_UNKNOWN; - } - } } /* @@ -712,63 +712,63 @@ verify_by_crl(const x509cert_t *cert, time_t *until, time_t *revocationDate void list_crls(bool utc, bool strict) { - x509crl_t *crl; + x509crl_t *crl; - lock_crl_list("list_crls"); - crl = x509crls; + lock_crl_list("list_crls"); + crl = x509crls; - if (crl != NULL) - { - whack_log(RC_COMMENT, " "); - whack_log(RC_COMMENT, "List of X.509 CRLs:"); - whack_log(RC_COMMENT, " "); - } - - while (crl != NULL) - { - u_char buf[BUF_LEN]; - u_int revoked = 0; - revokedCert_t *revokedCert = crl->revokedCertificates; - - /* count number of revoked certificates in CRL */ - while (revokedCert != NULL) + if (crl != NULL) { - revoked++; - revokedCert = revokedCert->next; - } - - whack_log(RC_COMMENT, "%T, revoked certs: %d", - &crl->installed, utc, revoked); - dntoa(buf, BUF_LEN, crl->issuer); - whack_log(RC_COMMENT, " issuer: '%s'", buf); - if (crl->crlNumber.ptr != NULL) - { - datatot(crl->crlNumber.ptr, crl->crlNumber.len, ':' - , buf, BUF_LEN); - whack_log(RC_COMMENT, " crlnumber: %s", buf); - } - list_distribution_points(crl->distributionPoints); - - whack_log(RC_COMMENT, " updates: this %T", - &crl->thisUpdate, utc); - whack_log(RC_COMMENT, " next %T %s", - &crl->nextUpdate, utc, - check_expiry(crl->nextUpdate, CRL_WARNING_INTERVAL, strict)); - if (crl->authKeyID.ptr != NULL) - { - datatot(crl->authKeyID.ptr, crl->authKeyID.len, ':' - , buf, BUF_LEN); - whack_log(RC_COMMENT, " authkey: %s", buf); - } - if (crl->authKeySerialNumber.ptr != NULL) - { - datatot(crl->authKeySerialNumber.ptr, crl->authKeySerialNumber.len, ':' - , buf, BUF_LEN); - whack_log(RC_COMMENT, " aserial: %s", buf); + whack_log(RC_COMMENT, " "); + whack_log(RC_COMMENT, "List of X.509 CRLs:"); + whack_log(RC_COMMENT, " "); } - crl = crl->next; - } - unlock_crl_list("list_crls"); + while (crl != NULL) + { + u_char buf[BUF_LEN]; + u_int revoked = 0; + revokedCert_t *revokedCert = crl->revokedCertificates; + + /* count number of revoked certificates in CRL */ + while (revokedCert != NULL) + { + revoked++; + revokedCert = revokedCert->next; + } + + whack_log(RC_COMMENT, "%T, revoked certs: %d", + &crl->installed, utc, revoked); + dntoa(buf, BUF_LEN, crl->issuer); + whack_log(RC_COMMENT, " issuer: '%s'", buf); + if (crl->crlNumber.ptr != NULL) + { + datatot(crl->crlNumber.ptr, crl->crlNumber.len, ':' + , buf, BUF_LEN); + whack_log(RC_COMMENT, " crlnumber: %s", buf); + } + list_distribution_points(crl->distributionPoints); + + whack_log(RC_COMMENT, " updates: this %T", + &crl->thisUpdate, utc); + whack_log(RC_COMMENT, " next %T %s", + &crl->nextUpdate, utc, + check_expiry(crl->nextUpdate, CRL_WARNING_INTERVAL, strict)); + if (crl->authKeyID.ptr != NULL) + { + datatot(crl->authKeyID.ptr, crl->authKeyID.len, ':' + , buf, BUF_LEN); + whack_log(RC_COMMENT, " authkey: %s", buf); + } + if (crl->authKeySerialNumber.ptr != NULL) + { + datatot(crl->authKeySerialNumber.ptr, crl->authKeySerialNumber.len, ':' + , buf, BUF_LEN); + whack_log(RC_COMMENT, " aserial: %s", buf); + } + + crl = crl->next; + } + unlock_crl_list("list_crls"); } diff --git a/src/pluto/crl.h b/src/pluto/crl.h index adca2ffae..04be64cd6 100644 --- a/src/pluto/crl.h +++ b/src/pluto/crl.h @@ -22,9 +22,9 @@ typedef struct revokedCert revokedCert_t; struct revokedCert{ revokedCert_t *next; - chunk_t userCertificate; - time_t revocationDate; - crl_reason_t revocationReason; + chunk_t userCertificate; + time_t revocationDate; + crl_reason_t revocationReason; }; /* storage structure for an X.509 CRL */ @@ -33,28 +33,28 @@ typedef struct x509crl x509crl_t; struct x509crl { x509crl_t *next; - time_t installed; + time_t installed; generalName_t *distributionPoints; chunk_t certificateList; chunk_t tbsCertList; u_int version; - /* signature */ + /* signature */ int sigAlg; chunk_t issuer; time_t thisUpdate; time_t nextUpdate; revokedCert_t *revokedCertificates; - /* v2 extensions */ - /* crlExtensions */ - /* extension */ - /* extnID */ - /* critical */ - /* extnValue */ - chunk_t authKeyID; - chunk_t authKeySerialNumber; - chunk_t crlNumber; + /* v2 extensions */ + /* crlExtensions */ + /* extension */ + /* extnID */ + /* critical */ + /* extnValue */ + chunk_t authKeyID; + chunk_t authKeySerialNumber; + chunk_t crlNumber; - /* signatureAlgorithm */ + /* signatureAlgorithm */ int algorithm; chunk_t signature; }; @@ -82,7 +82,7 @@ extern void load_crls(void); extern void check_crls(void); extern bool insert_crl(chunk_t blob, chunk_t crl_uri, bool cache_crl); extern cert_status_t verify_by_crl(const x509cert_t *cert, time_t *until - , time_t *revocationDate, crl_reason_t *revocationReason); + , time_t *revocationDate, crl_reason_t *revocationReason); extern void list_crls(bool utc, bool strict); extern void free_crls(void); extern void free_crl(x509crl_t *crl); diff --git a/src/pluto/crypto.c b/src/pluto/crypto.c index 20e4d9ec8..a6b106f04 100644 --- a/src/pluto/crypto.c +++ b/src/pluto/crypto.c @@ -40,29 +40,29 @@ /* moduli and generator. */ static MP_INT - modp1024_modulus, - modp1536_modulus, - modp2048_modulus, - modp3072_modulus, - modp4096_modulus, - modp6144_modulus, - modp8192_modulus; + modp1024_modulus, + modp1536_modulus, + modp2048_modulus, + modp3072_modulus, + modp4096_modulus, + modp6144_modulus, + modp8192_modulus; -MP_INT groupgenerator; /* MODP group generator (2) */ +MP_INT groupgenerator; /* MODP group generator (2) */ static void do_3des(u_int8_t *buf, size_t buf_len, u_int8_t *key, size_t key_size, u_int8_t *iv, bool enc); static struct encrypt_desc crypto_encryptor_3des = -{ - algo_type: IKE_ALG_ENCRYPT, - algo_id: OAKLEY_3DES_CBC, - algo_next: NULL, - enc_ctxsize: sizeof(des_key_schedule) * 3, - enc_blocksize: DES_CBC_BLOCK_SIZE, - keydeflen: DES_CBC_BLOCK_SIZE * 3 * BITS_PER_BYTE, - keyminlen: DES_CBC_BLOCK_SIZE * 3 * BITS_PER_BYTE, - keymaxlen: DES_CBC_BLOCK_SIZE * 3 * BITS_PER_BYTE, - do_crypt: do_3des, +{ + algo_type: IKE_ALG_ENCRYPT, + algo_id: OAKLEY_3DES_CBC, + algo_next: NULL, + enc_ctxsize: sizeof(des_key_schedule) * 3, + enc_blocksize: DES_CBC_BLOCK_SIZE, + keydeflen: DES_CBC_BLOCK_SIZE * 3 * BITS_PER_BYTE, + keyminlen: DES_CBC_BLOCK_SIZE * 3 * BITS_PER_BYTE, + keymaxlen: DES_CBC_BLOCK_SIZE * 3 * BITS_PER_BYTE, + do_crypt: do_3des, }; /* MD5 hash test vectors @@ -75,93 +75,93 @@ static const u_char md5_test0_msg[] = { }; static const u_char md5_test0_msg_digest[] = { - 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, - 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e + 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, + 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e }; static const u_char md5_test1_msg[] = { - 0x61 + 0x61 }; static const u_char md5_test1_msg_digest[] = { - 0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, - 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 + 0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, + 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 }; static const u_char md5_test2_msg[] = { - 0x61, 0x62, 0x63 + 0x61, 0x62, 0x63 }; static const u_char md5_test2_msg_digest[] = { - 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, - 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 + 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, + 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 }; static const u_char md5_test3_msg[] = { - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, - 0x64, 0x69, 0x67, 0x65, 0x73, 0x74 + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, + 0x64, 0x69, 0x67, 0x65, 0x73, 0x74 }; static const u_char md5_test3_msg_digest[] = { - 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, - 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 + 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, + 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 }; static const u_char md5_test4_msg[] = { - 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, - 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, - 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, - 0x79, 0x7a + 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, + 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a }; static const u_char md5_test4_msg_digest[] = { - 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, - 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b + 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, + 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b }; static const u_char md5_test5_msg[] = { - 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, - 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, - 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, - 0x59, 0x5a, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, - 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, - 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, - 0x77, 0x78, 0x79, 0x7a, 0x30, 0x31, 0x32, 0x33, - 0x34, 0x35, 0x36, 0x37, 0x38, 0x39 + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, + 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, + 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, + 0x77, 0x78, 0x79, 0x7a, 0x30, 0x31, 0x32, 0x33, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39 }; static const u_char md5_test5_msg_digest[] = { - 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, - 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f + 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, + 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f }; static const u_char md5_test6_msg[] = { - 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, - 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, - 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, - 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, - 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, - 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, - 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, - 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, - 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, - 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30 + 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, + 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, + 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, + 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, + 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, + 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30 }; static const u_char md5_test6_msg_digest[] = { - 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, - 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a + 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, + 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a }; static const hash_testvector_t md5_hash_testvectors[] = { - { sizeof(md5_test0_msg), md5_test0_msg, md5_test0_msg_digest }, - { sizeof(md5_test1_msg), md5_test1_msg, md5_test1_msg_digest }, - { sizeof(md5_test2_msg), md5_test2_msg, md5_test2_msg_digest }, - { sizeof(md5_test3_msg), md5_test3_msg, md5_test3_msg_digest }, - { sizeof(md5_test4_msg), md5_test4_msg, md5_test4_msg_digest }, - { sizeof(md5_test5_msg), md5_test5_msg, md5_test5_msg_digest }, - { sizeof(md5_test6_msg), md5_test6_msg, md5_test6_msg_digest }, - { 0, NULL, NULL } + { sizeof(md5_test0_msg), md5_test0_msg, md5_test0_msg_digest }, + { sizeof(md5_test1_msg), md5_test1_msg, md5_test1_msg_digest }, + { sizeof(md5_test2_msg), md5_test2_msg, md5_test2_msg_digest }, + { sizeof(md5_test3_msg), md5_test3_msg, md5_test3_msg_digest }, + { sizeof(md5_test4_msg), md5_test4_msg, md5_test4_msg_digest }, + { sizeof(md5_test5_msg), md5_test5_msg, md5_test5_msg_digest }, + { sizeof(md5_test6_msg), md5_test6_msg, md5_test6_msg_digest }, + { 0, NULL, NULL } }; /* MD5 hmac test vectors @@ -170,146 +170,146 @@ static const hash_testvector_t md5_hash_testvectors[] = { */ static const u_char md5_hmac1_key[] = { - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b }; static const u_char md5_hmac1_msg[] = { - 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65 + 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65 }; static const u_char md5_hmac1[] = { - 0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c, - 0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d + 0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c, + 0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d }; static const u_char md5_hmac2_key[] = { - 0x4a, 0x65, 0x66, 0x65 + 0x4a, 0x65, 0x66, 0x65 }; static const u_char md5_hmac2_msg[] = { - 0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20, - 0x79, 0x61, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20, - 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68, - 0x69, 0x6e, 0x67, 0x3f + 0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20, + 0x79, 0x61, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20, + 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68, + 0x69, 0x6e, 0x67, 0x3f }; static const u_char md5_hmac2[] = { - 0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03, - 0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38 + 0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03, + 0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38 }; static const u_char md5_hmac3_key[] = { - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa }; static const u_char md5_hmac3_msg[] = { - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd }; static const u_char md5_hmac3[] = { - 0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88, - 0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6 + 0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88, + 0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6 }; static const u_char md5_hmac4_key[] = { - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, - 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, - 0x19 + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19 }; static const u_char md5_hmac4_msg[] = { - 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, - 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, - 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, - 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, - 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, - 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, - 0xcd, 0xcd + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd }; static const u_char md5_hmac4[] = { - 0x69, 0x7e, 0xaf, 0x0a, 0xca, 0x3a, 0x3a, 0xea, - 0x3a, 0x75, 0x16, 0x47, 0x46, 0xff, 0xaa, 0x79 + 0x69, 0x7e, 0xaf, 0x0a, 0xca, 0x3a, 0x3a, 0xea, + 0x3a, 0x75, 0x16, 0x47, 0x46, 0xff, 0xaa, 0x79 }; static const u_char md5_hmac6_key[] = { - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, }; static const u_char md5_hmac6_msg[] = { - 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69, - 0x6e, 0x67, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65, - 0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a, - 0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x2d, 0x20, - 0x48, 0x61, 0x73, 0x68, 0x20, 0x4b, 0x65, 0x79, - 0x20, 0x46, 0x69, 0x72, 0x73, 0x74 + 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69, + 0x6e, 0x67, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65, + 0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a, + 0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x2d, 0x20, + 0x48, 0x61, 0x73, 0x68, 0x20, 0x4b, 0x65, 0x79, + 0x20, 0x46, 0x69, 0x72, 0x73, 0x74 }; static const u_char md5_hmac6[] = { - 0x6b, 0x1a, 0xb7, 0xfe, 0x4b, 0xd7, 0xbf, 0x8f, - 0x0b, 0x62, 0xe6, 0xce, 0x61, 0xb9, 0xd0, 0xcd + 0x6b, 0x1a, 0xb7, 0xfe, 0x4b, 0xd7, 0xbf, 0x8f, + 0x0b, 0x62, 0xe6, 0xce, 0x61, 0xb9, 0xd0, 0xcd }; static const u_char md5_hmac7_msg[] = { - 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69, - 0x6e, 0x67, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65, - 0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a, - 0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x61, 0x6e, - 0x64, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65, 0x72, - 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x4f, 0x6e, - 0x65, 0x20, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, - 0x53, 0x69, 0x7a, 0x65, 0x20, 0x44, 0x61, 0x74, - 0x61 + 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69, + 0x6e, 0x67, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65, + 0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a, + 0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x61, 0x6e, + 0x64, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65, 0x72, + 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x4f, 0x6e, + 0x65, 0x20, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, + 0x53, 0x69, 0x7a, 0x65, 0x20, 0x44, 0x61, 0x74, + 0x61 }; static const u_char md5_hmac7[] = { - 0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd, 0xa0, 0xee, - 0x1f, 0xb1, 0xf5, 0x62, 0xdb, 0x3a, 0xa5, 0x3e + 0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd, 0xa0, 0xee, + 0x1f, 0xb1, 0xf5, 0x62, 0xdb, 0x3a, 0xa5, 0x3e }; static const hmac_testvector_t md5_hmac_testvectors[] = { - { sizeof(md5_hmac1_key), md5_hmac1_key, sizeof(md5_hmac1_msg), md5_hmac1_msg, md5_hmac1 }, - { sizeof(md5_hmac2_key), md5_hmac2_key, sizeof(md5_hmac2_msg), md5_hmac2_msg, md5_hmac2 }, - { sizeof(md5_hmac3_key), md5_hmac3_key, sizeof(md5_hmac3_msg), md5_hmac3_msg, md5_hmac3 }, - { sizeof(md5_hmac4_key), md5_hmac4_key, sizeof(md5_hmac4_msg), md5_hmac4_msg, md5_hmac4 }, - { sizeof(md5_hmac6_key), md5_hmac6_key, sizeof(md5_hmac6_msg), md5_hmac6_msg, md5_hmac6 }, - { sizeof(md5_hmac6_key), md5_hmac6_key, sizeof(md5_hmac7_msg), md5_hmac7_msg, md5_hmac7 }, - { 0, NULL, 0, NULL, NULL } + { sizeof(md5_hmac1_key), md5_hmac1_key, sizeof(md5_hmac1_msg), md5_hmac1_msg, md5_hmac1 }, + { sizeof(md5_hmac2_key), md5_hmac2_key, sizeof(md5_hmac2_msg), md5_hmac2_msg, md5_hmac2 }, + { sizeof(md5_hmac3_key), md5_hmac3_key, sizeof(md5_hmac3_msg), md5_hmac3_msg, md5_hmac3 }, + { sizeof(md5_hmac4_key), md5_hmac4_key, sizeof(md5_hmac4_msg), md5_hmac4_msg, md5_hmac4 }, + { sizeof(md5_hmac6_key), md5_hmac6_key, sizeof(md5_hmac6_msg), md5_hmac6_msg, md5_hmac6 }, + { sizeof(md5_hmac6_key), md5_hmac6_key, sizeof(md5_hmac7_msg), md5_hmac7_msg, md5_hmac7 }, + { 0, NULL, 0, NULL, NULL } }; static struct hash_desc crypto_hasher_md5 = -{ - algo_type: IKE_ALG_HASH, - algo_id: OAKLEY_MD5, - algo_next: NULL, - hash_ctx_size: sizeof(MD5_CTX), - hash_block_size: MD5_BLOCK_SIZE, - hash_digest_size: MD5_DIGEST_SIZE, - hash_testvectors: md5_hash_testvectors, - hmac_testvectors: md5_hmac_testvectors, - hash_init: (void (*)(void *)) MD5Init, - hash_update: (void (*)(void *, const u_int8_t *, size_t)) MD5Update, - hash_final: (void (*)(u_char *, void *)) MD5Final +{ + algo_type: IKE_ALG_HASH, + algo_id: OAKLEY_MD5, + algo_next: NULL, + hash_ctx_size: sizeof(MD5_CTX), + hash_block_size: MD5_BLOCK_SIZE, + hash_digest_size: MD5_DIGEST_SIZE, + hash_testvectors: md5_hash_testvectors, + hmac_testvectors: md5_hmac_testvectors, + hash_init: (void (*)(void *)) MD5Init, + hash_update: (void (*)(void *, const u_int8_t *, size_t)) MD5Update, + hash_final: (void (*)(u_char *, void *)) MD5Final }; /* SHA-1 test vectors @@ -318,61 +318,61 @@ static struct hash_desc crypto_hasher_md5 = */ static const u_char sha1_short2_msg[] = { - 0x5e + 0x5e }; static const u_char sha1_short2_msg_digest[] = { - 0x5e, 0x6f, 0x80, 0xa3, 0x4a, 0x97, 0x98, 0xca, - 0xfc, 0x6a, 0x5d, 0xb9, 0x6c, 0xc5, 0x7b, 0xa4, - 0xc4, 0xdb, 0x59, 0xc2 + 0x5e, 0x6f, 0x80, 0xa3, 0x4a, 0x97, 0x98, 0xca, + 0xfc, 0x6a, 0x5d, 0xb9, 0x6c, 0xc5, 0x7b, 0xa4, + 0xc4, 0xdb, 0x59, 0xc2 }; static const u_char sha1_short4_msg[] = { - 0x9a, 0x7d, 0xfd, 0xf1, 0xec, 0xea, 0xd0, 0x6e, - 0xd6, 0x46, 0xaa, 0x55, 0xfe, 0x75, 0x71, 0x46 + 0x9a, 0x7d, 0xfd, 0xf1, 0xec, 0xea, 0xd0, 0x6e, + 0xd6, 0x46, 0xaa, 0x55, 0xfe, 0x75, 0x71, 0x46 }; static const u_char sha1_short4_msg_digest[] = { - 0x82, 0xab, 0xff, 0x66, 0x05, 0xdb, 0xe1, 0xc1, - 0x7d, 0xef, 0x12, 0xa3, 0x94, 0xfa, 0x22, 0xa8, - 0x2b, 0x54, 0x4a, 0x35 + 0x82, 0xab, 0xff, 0x66, 0x05, 0xdb, 0xe1, 0xc1, + 0x7d, 0xef, 0x12, 0xa3, 0x94, 0xfa, 0x22, 0xa8, + 0x2b, 0x54, 0x4a, 0x35 }; static const u_char sha1_long2_msg[] = { - 0xf7, 0x8f, 0x92, 0x14, 0x1b, 0xcd, 0x17, 0x0a, - 0xe8, 0x9b, 0x4f, 0xba, 0x15, 0xa1, 0xd5, 0x9f, - 0x3f, 0xd8, 0x4d, 0x22, 0x3c, 0x92, 0x51, 0xbd, - 0xac, 0xbb, 0xae, 0x61, 0xd0, 0x5e, 0xd1, 0x15, - 0xa0, 0x6a, 0x7c, 0xe1, 0x17, 0xb7, 0xbe, 0xea, - 0xd2, 0x44, 0x21, 0xde, 0xd9, 0xc3, 0x25, 0x92, - 0xbd, 0x57, 0xed, 0xea, 0xe3, 0x9c, 0x39, 0xfa, - 0x1f, 0xe8, 0x94, 0x6a, 0x84, 0xd0, 0xcf, 0x1f, - 0x7b, 0xee, 0xad, 0x17, 0x13, 0xe2, 0xe0, 0x95, - 0x98, 0x97, 0x34, 0x7f, 0x67, 0xc8, 0x0b, 0x04, - 0x00, 0xc2, 0x09, 0x81, 0x5d, 0x6b, 0x10, 0xa6, - 0x83, 0x83, 0x6f, 0xd5, 0x56, 0x2a, 0x56, 0xca, - 0xb1, 0xa2, 0x8e, 0x81, 0xb6, 0x57, 0x66, 0x54, - 0x63, 0x1c, 0xf1, 0x65, 0x66, 0xb8, 0x6e, 0x3b, - 0x33, 0xa1, 0x08, 0xb0, 0x53, 0x07, 0xc0, 0x0a, - 0xff, 0x14, 0xa7, 0x68, 0xed, 0x73, 0x50, 0x60, - 0x6a, 0x0f, 0x85, 0xe6, 0xa9, 0x1d, 0x39, 0x6f, - 0x5b, 0x5c, 0xbe, 0x57, 0x7f, 0x9b, 0x38, 0x80, - 0x7c, 0x7d, 0x52, 0x3d, 0x6d, 0x79, 0x2f, 0x6e, - 0xbc, 0x24, 0xa4, 0xec, 0xf2, 0xb3, 0xa4, 0x27, - 0xcd, 0xbb, 0xfb + 0xf7, 0x8f, 0x92, 0x14, 0x1b, 0xcd, 0x17, 0x0a, + 0xe8, 0x9b, 0x4f, 0xba, 0x15, 0xa1, 0xd5, 0x9f, + 0x3f, 0xd8, 0x4d, 0x22, 0x3c, 0x92, 0x51, 0xbd, + 0xac, 0xbb, 0xae, 0x61, 0xd0, 0x5e, 0xd1, 0x15, + 0xa0, 0x6a, 0x7c, 0xe1, 0x17, 0xb7, 0xbe, 0xea, + 0xd2, 0x44, 0x21, 0xde, 0xd9, 0xc3, 0x25, 0x92, + 0xbd, 0x57, 0xed, 0xea, 0xe3, 0x9c, 0x39, 0xfa, + 0x1f, 0xe8, 0x94, 0x6a, 0x84, 0xd0, 0xcf, 0x1f, + 0x7b, 0xee, 0xad, 0x17, 0x13, 0xe2, 0xe0, 0x95, + 0x98, 0x97, 0x34, 0x7f, 0x67, 0xc8, 0x0b, 0x04, + 0x00, 0xc2, 0x09, 0x81, 0x5d, 0x6b, 0x10, 0xa6, + 0x83, 0x83, 0x6f, 0xd5, 0x56, 0x2a, 0x56, 0xca, + 0xb1, 0xa2, 0x8e, 0x81, 0xb6, 0x57, 0x66, 0x54, + 0x63, 0x1c, 0xf1, 0x65, 0x66, 0xb8, 0x6e, 0x3b, + 0x33, 0xa1, 0x08, 0xb0, 0x53, 0x07, 0xc0, 0x0a, + 0xff, 0x14, 0xa7, 0x68, 0xed, 0x73, 0x50, 0x60, + 0x6a, 0x0f, 0x85, 0xe6, 0xa9, 0x1d, 0x39, 0x6f, + 0x5b, 0x5c, 0xbe, 0x57, 0x7f, 0x9b, 0x38, 0x80, + 0x7c, 0x7d, 0x52, 0x3d, 0x6d, 0x79, 0x2f, 0x6e, + 0xbc, 0x24, 0xa4, 0xec, 0xf2, 0xb3, 0xa4, 0x27, + 0xcd, 0xbb, 0xfb }; static const u_char sha1_long2_msg_digest[] = { - 0xcb, 0x00, 0x82, 0xc8, 0xf1, 0x97, 0xd2, 0x60, - 0x99, 0x1b, 0xa6, 0xa4, 0x60, 0xe7, 0x6e, 0x20, - 0x2b, 0xad, 0x27, 0xb3 + 0xcb, 0x00, 0x82, 0xc8, 0xf1, 0x97, 0xd2, 0x60, + 0x99, 0x1b, 0xa6, 0xa4, 0x60, 0xe7, 0x6e, 0x20, + 0x2b, 0xad, 0x27, 0xb3 }; static const hash_testvector_t sha1_hash_testvectors[] = { - { sizeof(sha1_short2_msg), sha1_short2_msg, sha1_short2_msg_digest }, - { sizeof(sha1_short4_msg), sha1_short4_msg, sha1_short4_msg_digest }, - { sizeof(sha1_long2_msg), sha1_long2_msg, sha1_long2_msg_digest }, - { 0, NULL, NULL } + { sizeof(sha1_short2_msg), sha1_short2_msg, sha1_short2_msg_digest }, + { sizeof(sha1_short4_msg), sha1_short4_msg, sha1_short4_msg_digest }, + { sizeof(sha1_long2_msg), sha1_long2_msg, sha1_long2_msg_digest }, + { 0, NULL, NULL } }; /* SHA-1 hmac test vectors @@ -381,109 +381,109 @@ static const hash_testvector_t sha1_hash_testvectors[] = { */ static const u_char sha1_hmac1_key[] = { - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b }; static const u_char sha1_hmac1[] = { - 0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, - 0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e, - 0xf1, 0x46, 0xbe, 0x00 + 0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, + 0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e, + 0xf1, 0x46, 0xbe, 0x00 }; static const u_char sha1_hmac2[] = { - 0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2, - 0xd2, 0x74, 0x16, 0xd5, 0xf1, 0x84, 0xdf, 0x9c, - 0x25, 0x9a, 0x7c, 0x79 + 0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2, + 0xd2, 0x74, 0x16, 0xd5, 0xf1, 0x84, 0xdf, 0x9c, + 0x25, 0x9a, 0x7c, 0x79 }; static const u_char sha1_hmac3_key[] = { - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa }; static const u_char sha1_hmac3[] = { - 0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac, 0x11, 0xcd, - 0x91, 0xa3, 0x9a, 0xf4, 0x8a, 0xa1, 0x7b, 0x4f, - 0x63, 0xf1, 0x75, 0xd3 + 0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac, 0x11, 0xcd, + 0x91, 0xa3, 0x9a, 0xf4, 0x8a, 0xa1, 0x7b, 0x4f, + 0x63, 0xf1, 0x75, 0xd3 }; static const u_char sha1_hmac4[] = { - 0x4c, 0x90, 0x07, 0xf4, 0x02, 0x62, 0x50, 0xc6, - 0xbc, 0x84, 0x14, 0xf9, 0xbf, 0x50, 0xc8, 0x6c, - 0x2d, 0x72, 0x35, 0xda + 0x4c, 0x90, 0x07, 0xf4, 0x02, 0x62, 0x50, 0xc6, + 0xbc, 0x84, 0x14, 0xf9, 0xbf, 0x50, 0xc8, 0x6c, + 0x2d, 0x72, 0x35, 0xda }; static const u_char sha1_hmac6[] = { - 0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e, - 0x95, 0x70, 0x56, 0x37, 0xce, 0x8a, 0x3b, 0x55, - 0xed, 0x40, 0x21, 0x12 + 0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e, + 0x95, 0x70, 0x56, 0x37, 0xce, 0x8a, 0x3b, 0x55, + 0xed, 0x40, 0x21, 0x12 }; static const u_char sha1_hmac7[] = { - 0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, - 0x6d, 0x6b, 0xba, 0xa7, 0x96, 0x5c, 0x78, 0x08, - 0xbb, 0xff, 0x1a, 0x91 + 0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, + 0x6d, 0x6b, 0xba, 0xa7, 0x96, 0x5c, 0x78, 0x08, + 0xbb, 0xff, 0x1a, 0x91 }; static const hmac_testvector_t sha1_hmac_testvectors[] = { - { sizeof(sha1_hmac1_key), sha1_hmac1_key, sizeof(md5_hmac1_msg), md5_hmac1_msg, sha1_hmac1 }, - { sizeof(md5_hmac2_key), md5_hmac2_key, sizeof(md5_hmac2_msg), md5_hmac2_msg, sha1_hmac2 }, - { sizeof(sha1_hmac3_key), sha1_hmac3_key, sizeof(md5_hmac3_msg), md5_hmac3_msg, sha1_hmac3 }, - { sizeof(md5_hmac4_key), md5_hmac4_key, sizeof(md5_hmac4_msg), md5_hmac4_msg, sha1_hmac4 }, - { sizeof(md5_hmac6_key), md5_hmac6_key, sizeof(md5_hmac6_msg), md5_hmac6_msg, sha1_hmac6 }, - { sizeof(md5_hmac6_key), md5_hmac6_key, sizeof(md5_hmac7_msg), md5_hmac7_msg, sha1_hmac7 }, - { 0, NULL, 0, NULL, NULL } + { sizeof(sha1_hmac1_key), sha1_hmac1_key, sizeof(md5_hmac1_msg), md5_hmac1_msg, sha1_hmac1 }, + { sizeof(md5_hmac2_key), md5_hmac2_key, sizeof(md5_hmac2_msg), md5_hmac2_msg, sha1_hmac2 }, + { sizeof(sha1_hmac3_key), sha1_hmac3_key, sizeof(md5_hmac3_msg), md5_hmac3_msg, sha1_hmac3 }, + { sizeof(md5_hmac4_key), md5_hmac4_key, sizeof(md5_hmac4_msg), md5_hmac4_msg, sha1_hmac4 }, + { sizeof(md5_hmac6_key), md5_hmac6_key, sizeof(md5_hmac6_msg), md5_hmac6_msg, sha1_hmac6 }, + { sizeof(md5_hmac6_key), md5_hmac6_key, sizeof(md5_hmac7_msg), md5_hmac7_msg, sha1_hmac7 }, + { 0, NULL, 0, NULL, NULL } }; static struct hash_desc crypto_hasher_sha1 = -{ - algo_type: IKE_ALG_HASH, - algo_id: OAKLEY_SHA, - algo_next: NULL, - hash_ctx_size: sizeof(SHA1_CTX), - hash_block_size: SHA1_BLOCK_SIZE, - hash_digest_size: SHA1_DIGEST_SIZE, - hash_testvectors: sha1_hash_testvectors, - hmac_testvectors: sha1_hmac_testvectors, - hash_init: (void (*)(void *)) SHA1Init, - hash_update: (void (*)(void *, const u_int8_t *, size_t)) SHA1Update, - hash_final: (void (*)(u_char *, void *)) SHA1Final +{ + algo_type: IKE_ALG_HASH, + algo_id: OAKLEY_SHA, + algo_next: NULL, + hash_ctx_size: sizeof(SHA1_CTX), + hash_block_size: SHA1_BLOCK_SIZE, + hash_digest_size: SHA1_DIGEST_SIZE, + hash_testvectors: sha1_hash_testvectors, + hmac_testvectors: sha1_hmac_testvectors, + hash_init: (void (*)(void *)) SHA1Init, + hash_update: (void (*)(void *, const u_int8_t *, size_t)) SHA1Update, + hash_final: (void (*)(u_char *, void *)) SHA1Final }; void init_crypto(void) { - if (mpz_init_set_str(&groupgenerator, MODP_GENERATOR, 10) != 0 - || mpz_init_set_str(&modp1024_modulus, MODP1024_MODULUS, 16) != 0 - || mpz_init_set_str(&modp1536_modulus, MODP1536_MODULUS, 16) != 0 - || mpz_init_set_str(&modp2048_modulus, MODP2048_MODULUS, 16) != 0 - || mpz_init_set_str(&modp3072_modulus, MODP3072_MODULUS, 16) != 0 - || mpz_init_set_str(&modp4096_modulus, MODP4096_MODULUS, 16) != 0 - || mpz_init_set_str(&modp6144_modulus, MODP6144_MODULUS, 16) != 0 - || mpz_init_set_str(&modp8192_modulus, MODP8192_MODULUS, 16) != 0) - exit_log("mpz_init_set_str() failed in init_crypto()"); + if (mpz_init_set_str(&groupgenerator, MODP_GENERATOR, 10) != 0 + || mpz_init_set_str(&modp1024_modulus, MODP1024_MODULUS, 16) != 0 + || mpz_init_set_str(&modp1536_modulus, MODP1536_MODULUS, 16) != 0 + || mpz_init_set_str(&modp2048_modulus, MODP2048_MODULUS, 16) != 0 + || mpz_init_set_str(&modp3072_modulus, MODP3072_MODULUS, 16) != 0 + || mpz_init_set_str(&modp4096_modulus, MODP4096_MODULUS, 16) != 0 + || mpz_init_set_str(&modp6144_modulus, MODP6144_MODULUS, 16) != 0 + || mpz_init_set_str(&modp8192_modulus, MODP8192_MODULUS, 16) != 0) + exit_log("mpz_init_set_str() failed in init_crypto()"); - ike_alg_add((struct ike_alg *) &crypto_encryptor_3des); - ike_alg_add((struct ike_alg *) &crypto_hasher_sha1); - ike_alg_add((struct ike_alg *) &crypto_hasher_md5); - ike_alg_init(); - ike_alg_test(); + ike_alg_add((struct ike_alg *) &crypto_encryptor_3des); + ike_alg_add((struct ike_alg *) &crypto_hasher_sha1); + ike_alg_add((struct ike_alg *) &crypto_hasher_md5); + ike_alg_init(); + ike_alg_test(); } void free_crypto(void) { - mpz_clear(&groupgenerator); - mpz_clear(&modp1024_modulus); - mpz_clear(&modp1536_modulus); - mpz_clear(&modp2048_modulus); - mpz_clear(&modp3072_modulus); - mpz_clear(&modp4096_modulus); - mpz_clear(&modp6144_modulus); - mpz_clear(&modp8192_modulus); + mpz_clear(&groupgenerator); + mpz_clear(&modp1024_modulus); + mpz_clear(&modp1536_modulus); + mpz_clear(&modp2048_modulus); + mpz_clear(&modp3072_modulus); + mpz_clear(&modp4096_modulus); + mpz_clear(&modp6144_modulus); + mpz_clear(&modp8192_modulus); } /* Oakley group description @@ -491,29 +491,29 @@ free_crypto(void) * See RFC2409 "The Internet key exchange (IKE)" 6. */ -const struct oakley_group_desc unset_group = {0, NULL, 0}; /* magic signifier */ +const struct oakley_group_desc unset_group = {0, NULL, 0}; /* magic signifier */ const struct oakley_group_desc oakley_group[OAKLEY_GROUP_SIZE] = { # define BYTES(bits) (((bits) + BITS_PER_BYTE - 1) / BITS_PER_BYTE) - { OAKLEY_GROUP_MODP1024, &modp1024_modulus, BYTES(1024) }, - { OAKLEY_GROUP_MODP1536, &modp1536_modulus, BYTES(1536) }, - { OAKLEY_GROUP_MODP2048, &modp2048_modulus, BYTES(2048) }, - { OAKLEY_GROUP_MODP3072, &modp3072_modulus, BYTES(3072) }, - { OAKLEY_GROUP_MODP4096, &modp4096_modulus, BYTES(4096) }, - { OAKLEY_GROUP_MODP6144, &modp6144_modulus, BYTES(6144) }, - { OAKLEY_GROUP_MODP8192, &modp8192_modulus, BYTES(8192) }, + { OAKLEY_GROUP_MODP1024, &modp1024_modulus, BYTES(1024) }, + { OAKLEY_GROUP_MODP1536, &modp1536_modulus, BYTES(1536) }, + { OAKLEY_GROUP_MODP2048, &modp2048_modulus, BYTES(2048) }, + { OAKLEY_GROUP_MODP3072, &modp3072_modulus, BYTES(3072) }, + { OAKLEY_GROUP_MODP4096, &modp4096_modulus, BYTES(4096) }, + { OAKLEY_GROUP_MODP6144, &modp6144_modulus, BYTES(6144) }, + { OAKLEY_GROUP_MODP8192, &modp8192_modulus, BYTES(8192) }, # undef BYTES }; const struct oakley_group_desc * lookup_group(u_int16_t group) { - int i; + int i; - for (i = 0; i != countof(oakley_group); i++) - if (group == oakley_group[i].group) - return &oakley_group[i]; - return NULL; + for (i = 0; i != countof(oakley_group); i++) + if (group == oakley_group[i].group) + return &oakley_group[i]; + return NULL; } /* Encryption Routines @@ -528,16 +528,16 @@ lookup_group(u_int16_t group) static void __attribute__ ((unused)) do_des(bool enc, void *buf, size_t buf_len, struct state *st) { - des_key_schedule ks; + des_key_schedule ks; - (void) des_set_key((des_cblock *)st->st_enc_key.ptr, ks); + (void) des_set_key((des_cblock *)st->st_enc_key.ptr, ks); - passert(st->st_new_iv_len >= DES_CBC_BLOCK_SIZE); - st->st_new_iv_len = DES_CBC_BLOCK_SIZE; /* truncate */ + passert(st->st_new_iv_len >= DES_CBC_BLOCK_SIZE); + st->st_new_iv_len = DES_CBC_BLOCK_SIZE; /* truncate */ - des_ncbc_encrypt((des_cblock *)buf, (des_cblock *)buf, buf_len, - ks, - (des_cblock *)st->st_new_iv, enc); + des_ncbc_encrypt((des_cblock *)buf, (des_cblock *)buf, buf_len, + ks, + (des_cblock *)st->st_new_iv, enc); } /* encrypt or decrypt part of an IKE message using 3DES @@ -546,30 +546,30 @@ do_des(bool enc, void *buf, size_t buf_len, struct state *st) static void do_3des(u_int8_t *buf, size_t buf_len, u_int8_t *key, size_t key_size, u_int8_t *iv, bool enc) { - des_key_schedule ks[3]; + des_key_schedule ks[3]; - passert (!key_size || (key_size==(DES_CBC_BLOCK_SIZE * 3))) - (void) des_set_key((des_cblock *)key + 0, ks[0]); - (void) des_set_key((des_cblock *)key + 1, ks[1]); - (void) des_set_key((des_cblock *)key + 2, ks[2]); + passert (!key_size || (key_size==(DES_CBC_BLOCK_SIZE * 3))) + (void) des_set_key((des_cblock *)key + 0, ks[0]); + (void) des_set_key((des_cblock *)key + 1, ks[1]); + (void) des_set_key((des_cblock *)key + 2, ks[2]); - des_ede3_cbc_encrypt((des_cblock *)buf, (des_cblock *)buf, buf_len, - ks[0], ks[1], ks[2], - (des_cblock *)iv, enc); + des_ede3_cbc_encrypt((des_cblock *)buf, (des_cblock *)buf, buf_len, + ks[0], ks[1], ks[2], + (des_cblock *)iv, enc); } /* hash and prf routines */ void crypto_cbc_encrypt(const struct encrypt_desc *e, bool enc, u_int8_t *buf, size_t size, struct state *st) { - passert(st->st_new_iv_len >= e->enc_blocksize); - st->st_new_iv_len = e->enc_blocksize; /* truncate */ + passert(st->st_new_iv_len >= e->enc_blocksize); + st->st_new_iv_len = e->enc_blocksize; /* truncate */ - e->do_crypt(buf, size, st->st_enc_key.ptr, st->st_enc_key.len, st->st_new_iv, enc); - /* - e->set_key(&ctx, st->st_enc_key.ptr, st->st_enc_key.len); - e->cbc_crypt(&ctx, buf, size, st->st_new_iv, enc); - */ + e->do_crypt(buf, size, st->st_enc_key.ptr, st->st_enc_key.len, st->st_new_iv, enc); + /* + e->set_key(&ctx, st->st_enc_key.ptr, st->st_enc_key.len); + e->cbc_crypt(&ctx, buf, size, st->st_new_iv, enc); + */ } /* HMAC package @@ -578,63 +578,63 @@ crypto_cbc_encrypt(const struct encrypt_desc *e, bool enc, u_int8_t *buf, size_t void hmac_init(struct hmac_ctx *ctx, - const struct hash_desc *h, - const u_char *key, size_t key_len) + const struct hash_desc *h, + const u_char *key, size_t key_len) { - int k; + int k; - ctx->h = h; - ctx->hmac_digest_size = h->hash_digest_size; + ctx->h = h; + ctx->hmac_digest_size = h->hash_digest_size; - /* Prepare the two pads for the HMAC */ + /* Prepare the two pads for the HMAC */ - memset(ctx->buf1, '\0', h->hash_block_size); + memset(ctx->buf1, '\0', h->hash_block_size); - if (key_len <= h->hash_block_size) - { - memcpy(ctx->buf1, key, key_len); - } - else - { - h->hash_init(&ctx->hash_ctx); - h->hash_update(&ctx->hash_ctx, key, key_len); - h->hash_final(ctx->buf1, &ctx->hash_ctx); - } + if (key_len <= h->hash_block_size) + { + memcpy(ctx->buf1, key, key_len); + } + else + { + h->hash_init(&ctx->hash_ctx); + h->hash_update(&ctx->hash_ctx, key, key_len); + h->hash_final(ctx->buf1, &ctx->hash_ctx); + } - memcpy(ctx->buf2, ctx->buf1, h->hash_block_size); + memcpy(ctx->buf2, ctx->buf1, h->hash_block_size); - for (k = 0; k < h->hash_block_size; k++) - { - ctx->buf1[k] ^= HMAC_IPAD; - ctx->buf2[k] ^= HMAC_OPAD; - } + for (k = 0; k < h->hash_block_size; k++) + { + ctx->buf1[k] ^= HMAC_IPAD; + ctx->buf2[k] ^= HMAC_OPAD; + } - hmac_reinit(ctx); + hmac_reinit(ctx); } void hmac_reinit(struct hmac_ctx *ctx) { - ctx->h->hash_init(&ctx->hash_ctx); - ctx->h->hash_update(&ctx->hash_ctx, ctx->buf1, ctx->h->hash_block_size); + ctx->h->hash_init(&ctx->hash_ctx); + ctx->h->hash_update(&ctx->hash_ctx, ctx->buf1, ctx->h->hash_block_size); } void hmac_update(struct hmac_ctx *ctx, - const u_char *data, size_t data_len) + const u_char *data, size_t data_len) { - ctx->h->hash_update(&ctx->hash_ctx, data, data_len); + ctx->h->hash_update(&ctx->hash_ctx, data, data_len); } void hmac_final(u_char *output, struct hmac_ctx *ctx) { - const struct hash_desc *h = ctx->h; + const struct hash_desc *h = ctx->h; - h->hash_final(output, &ctx->hash_ctx); + h->hash_final(output, &ctx->hash_ctx); - h->hash_init(&ctx->hash_ctx); - h->hash_update(&ctx->hash_ctx, ctx->buf2, h->hash_block_size); - h->hash_update(&ctx->hash_ctx, output, h->hash_digest_size); - h->hash_final(output, &ctx->hash_ctx); + h->hash_init(&ctx->hash_ctx); + h->hash_update(&ctx->hash_ctx, ctx->buf2, h->hash_block_size); + h->hash_update(&ctx->hash_ctx, output, h->hash_digest_size); + h->hash_final(output, &ctx->hash_ctx); } diff --git a/src/pluto/crypto.h b/src/pluto/crypto.h index f19c12add..ce03748de 100644 --- a/src/pluto/crypto.h +++ b/src/pluto/crypto.h @@ -24,15 +24,15 @@ extern void free_crypto(void); /* Oakley group descriptions */ -extern MP_INT groupgenerator; /* MODP group generator (2) */ +extern MP_INT groupgenerator; /* MODP group generator (2) */ struct oakley_group_desc { - u_int16_t group; - MP_INT *modulus; - size_t bytes; + u_int16_t group; + MP_INT *modulus; + size_t bytes; }; -extern const struct oakley_group_desc unset_group; /* magic signifier */ +extern const struct oakley_group_desc unset_group; /* magic signifier */ extern const struct oakley_group_desc *lookup_group(u_int16_t group); #define OAKLEY_GROUP_SIZE 7 extern const struct oakley_group_desc oakley_group[OAKLEY_GROUP_SIZE]; @@ -47,26 +47,26 @@ extern const struct oakley_group_desc oakley_group[OAKLEY_GROUP_SIZE]; #define MAX_OAKLEY_KEY_LEN0 (3 * DES_CBC_BLOCK_SIZE) #define MAX_OAKLEY_KEY_LEN (256/BITS_PER_BYTE) -struct state; /* forward declaration, dammit */ +struct state; /* forward declaration, dammit */ void crypto_cbc_encrypt(const struct encrypt_desc *e, bool enc, u_int8_t *buf, size_t size, struct state *st); -#define update_iv(st) memcpy((st)->st_iv, (st)->st_new_iv \ - , (st)->st_iv_len = (st)->st_new_iv_len) +#define update_iv(st) memcpy((st)->st_iv, (st)->st_new_iv \ + , (st)->st_iv_len = (st)->st_new_iv_len) #define set_ph1_iv(st, iv) \ - passert((st)->st_ph1_iv_len <= sizeof((st)->st_ph1_iv)); \ - memcpy((st)->st_ph1_iv, (iv), (st)->st_ph1_iv_len); + passert((st)->st_ph1_iv_len <= sizeof((st)->st_ph1_iv)); \ + memcpy((st)->st_ph1_iv, (iv), (st)->st_ph1_iv_len); /* unification of cryptographic hashing mechanisms */ #ifndef NO_HASH_CTX union hash_ctx { - MD5_CTX ctx_md5; - SHA1_CTX ctx_sha1; - sha256_context ctx_sha256; - sha512_context ctx_sha512; - }; + MD5_CTX ctx_md5; + SHA1_CTX ctx_sha1; + sha256_context ctx_sha256; + sha512_context ctx_sha512; + }; /* HMAC package * Note that hmac_ctx can be (and is) copied since there are @@ -74,36 +74,36 @@ union hash_ctx { */ struct hmac_ctx { - const struct hash_desc *h; /* underlying hash function */ - size_t hmac_digest_size; /* copy of h->hash_digest_size */ - union hash_ctx hash_ctx; /* ctx for hash function */ - u_char buf1[MAX_HASH_BLOCK_SIZE]; - u_char buf2[MAX_HASH_BLOCK_SIZE]; - }; + const struct hash_desc *h; /* underlying hash function */ + size_t hmac_digest_size; /* copy of h->hash_digest_size */ + union hash_ctx hash_ctx; /* ctx for hash function */ + u_char buf1[MAX_HASH_BLOCK_SIZE]; + u_char buf2[MAX_HASH_BLOCK_SIZE]; + }; extern void hmac_init( - struct hmac_ctx *ctx, - const struct hash_desc *h, - const u_char *key, - size_t key_len); + struct hmac_ctx *ctx, + const struct hash_desc *h, + const u_char *key, + size_t key_len); #define hmac_init_chunk(ctx, h, ch) hmac_init((ctx), (h), (ch).ptr, (ch).len) -extern void hmac_reinit(struct hmac_ctx *ctx); /* saves recreating pads */ +extern void hmac_reinit(struct hmac_ctx *ctx); /* saves recreating pads */ extern void hmac_update( - struct hmac_ctx *ctx, - const u_char *data, - size_t data_len); + struct hmac_ctx *ctx, + const u_char *data, + size_t data_len); #define hmac_update_chunk(ctx, ch) hmac_update((ctx), (ch).ptr, (ch).len) extern void hmac_final(u_char *output, struct hmac_ctx *ctx); #define hmac_final_chunk(ch, name, ctx) { \ - free((ch).ptr); \ - (ch).len = (ctx)->hmac_digest_size; \ - (ch).ptr = malloc((ch).len); \ - hmac_final((ch).ptr, (ctx)); \ - } + free((ch).ptr); \ + (ch).len = (ctx)->hmac_digest_size; \ + (ch).ptr = malloc((ch).len); \ + hmac_final((ch).ptr, (ctx)); \ + } #endif diff --git a/src/pluto/db_ops.c b/src/pluto/db_ops.c index 65f9380bc..ed903e92f 100644 --- a/src/pluto/db_ops.c +++ b/src/pluto/db_ops.c @@ -31,22 +31,22 @@ * also update attrs_cur (by offset) * * db_context structure: - * +---------------------+ - * | prop | - * | .protoid | - * | .trans | --+ - * | .trans_cnt | | - * +---------------------+ <-+ - * | trans0 | ----> { trans#1 | ... | trans#i | ... } - * +---------------------+ ^ - * | trans_cur | ----------------------' current transf. - * +---------------------+ - * | attrs0 | ----> { attr#1 | ... | attr#j | ... } - * +---------------------+ ^ - * | attrs_cur | ---------------------' current attr. - * +---------------------+ - * | max_trans,max_attrs | max_trans/attrs: number of elem. of each vector - * +---------------------+ + * +---------------------+ + * | prop | + * | .protoid | + * | .trans | --+ + * | .trans_cnt | | + * +---------------------+ <-+ + * | trans0 | ----> { trans#1 | ... | trans#i | ... } + * +---------------------+ ^ + * | trans_cur | ----------------------' current transf. + * +---------------------+ + * | attrs0 | ----> { attr#1 | ... | attr#j | ... } + * +---------------------+ ^ + * | attrs_cur | ---------------------' current attr. + * +---------------------+ + * | max_trans,max_attrs | max_trans/attrs: number of elem. of each vector + * +---------------------+ * * See testing examples at end for interface usage. */ @@ -71,29 +71,29 @@ #ifdef NOT_YET /* - * Allocator cache: - * Because of the single-threaded nature of pluto/spdb.c, - * alloc()/free() is exercised many times with very small - * lifetime objects. - * Just caching last object (currently it will select the - * largest) will avoid this allocation mas^Wperturbations + * Allocator cache: + * Because of the single-threaded nature of pluto/spdb.c, + * alloc()/free() is exercised many times with very small + * lifetime objects. + * Just caching last object (currently it will select the + * largest) will avoid this allocation mas^Wperturbations * */ struct db_ops_alloc_cache { - void *ptr; - int size; + void *ptr; + int size; }; #endif #ifndef NO_DB_OPS_STATS -/* - * stats: do account for allocations - * displayed in db_ops_show_status() +/* + * stats: do account for allocations + * displayed in db_ops_show_status() */ struct db_ops_stats { - int st_curr_cnt; /* current number of allocations */ - int st_total_cnt; /* total allocations so far */ - size_t st_maxsz; /* max. size requested */ + int st_curr_cnt; /* current number of allocations */ + int st_total_cnt; /* total allocations so far */ + size_t st_maxsz; /* max. size requested */ }; #define DB_OPS_ZERO { 0, 0, 0}; #define DB_OPS_STATS_DESC "{curr_cnt, total_cnt, maxsz}" @@ -104,14 +104,14 @@ static struct db_ops_stats db_trans_st = DB_OPS_ZERO; static struct db_ops_stats db_attrs_st = DB_OPS_ZERO; static __inline__ void *malloc_bytes_st(size_t size, struct db_ops_stats *st) { - void *ptr = malloc(size); - if (ptr) - { - st->st_curr_cnt++; - st->st_total_cnt++; - if (size > st->st_maxsz) st->st_maxsz=size; - } - return ptr; + void *ptr = malloc(size); + if (ptr) + { + st->st_curr_cnt++; + st->st_total_cnt++; + if (size > st->st_maxsz) st->st_maxsz=size; + } + return ptr; } #define ALLOC_BYTES_ST(z,st) malloc_bytes_st(z, &st); #define PFREE_ST(p,st) do { st.st_curr_cnt--; free(p); } while (0); @@ -122,220 +122,220 @@ static __inline__ void *malloc_bytes_st(size_t size, struct db_ops_stats *st) #define PFREE_ST(p,n) free(p); #endif /* NO_DB_OPS_STATS */ -/* Initialize db object - * max_trans and max_attrs can be 0, will be dynamically expanded - * as a result of "add" operations +/* Initialize db object + * max_trans and max_attrs can be 0, will be dynamically expanded + * as a result of "add" operations */ int db_prop_init(struct db_context *ctx, u_int8_t protoid, int max_trans, int max_attrs) { - int ret=-1; + int ret=-1; - ctx->trans0 = NULL; - ctx->attrs0 = NULL; - - if (max_trans > 0) { /* quite silly if not */ - ctx->trans0 = ALLOC_BYTES_ST ( sizeof(struct db_trans) * max_trans, - db_trans_st); - memset(ctx->trans0, '\0', sizeof(struct db_trans) * max_trans); - } - - if (max_attrs > 0) { /* quite silly if not */ - ctx->attrs0 = ALLOC_BYTES_ST (sizeof(struct db_attr) * max_attrs, - db_attrs_st); - memset(ctx->attrs0, '\0', sizeof(struct db_attr) * max_attrs); - } - ret = 0; -out: - if (ret < 0 && ctx->trans0) { - PFREE_ST(ctx->trans0, db_trans_st); ctx->trans0 = NULL; - } - ctx->max_trans = max_trans; - ctx->max_attrs = max_attrs; - ctx->trans_cur = ctx->trans0; - ctx->attrs_cur = ctx->attrs0; - ctx->prop.protoid = protoid; - ctx->prop.trans = ctx->trans0; - ctx->prop.trans_cnt = 0; - return ret; + ctx->attrs0 = NULL; + + if (max_trans > 0) { /* quite silly if not */ + ctx->trans0 = ALLOC_BYTES_ST ( sizeof(struct db_trans) * max_trans, + db_trans_st); + memset(ctx->trans0, '\0', sizeof(struct db_trans) * max_trans); + } + + if (max_attrs > 0) { /* quite silly if not */ + ctx->attrs0 = ALLOC_BYTES_ST (sizeof(struct db_attr) * max_attrs, + db_attrs_st); + memset(ctx->attrs0, '\0', sizeof(struct db_attr) * max_attrs); + } + ret = 0; +out: + if (ret < 0 && ctx->trans0) { + PFREE_ST(ctx->trans0, db_trans_st); + ctx->trans0 = NULL; + } + ctx->max_trans = max_trans; + ctx->max_attrs = max_attrs; + ctx->trans_cur = ctx->trans0; + ctx->attrs_cur = ctx->attrs0; + ctx->prop.protoid = protoid; + ctx->prop.trans = ctx->trans0; + ctx->prop.trans_cnt = 0; + return ret; } -/* Expand storage for transforms by number delta_trans */ +/* Expand storage for transforms by number delta_trans */ static int db_trans_expand(struct db_context *ctx, int delta_trans) { - int ret = -1; - struct db_trans *new_trans, *old_trans; - int max_trans = ctx->max_trans + delta_trans; - int offset; + int ret = -1; + struct db_trans *new_trans, *old_trans; + int max_trans = ctx->max_trans + delta_trans; + int offset; - old_trans = ctx->trans0; - new_trans = ALLOC_BYTES_ST ( sizeof (struct db_trans) * max_trans, - db_trans_st); - if (!new_trans) - goto out; - memcpy(new_trans, old_trans, ctx->max_trans * sizeof(struct db_trans)); - - /* update trans0 (obviously) */ - ctx->trans0 = ctx->prop.trans = new_trans; - /* update trans_cur (by offset) */ - offset = (char *)(new_trans) - (char *)(old_trans); + old_trans = ctx->trans0; + new_trans = ALLOC_BYTES_ST ( sizeof (struct db_trans) * max_trans, + db_trans_st); + if (!new_trans) + goto out; + memcpy(new_trans, old_trans, ctx->max_trans * sizeof(struct db_trans)); + + /* update trans0 (obviously) */ + ctx->trans0 = ctx->prop.trans = new_trans; + /* update trans_cur (by offset) */ + offset = (char *)(new_trans) - (char *)(old_trans); - { - char *cctx = (char *)(ctx->trans_cur); - - cctx += offset; - ctx->trans_cur = (struct db_trans *)cctx; - } - /* update elem count */ - ctx->max_trans = max_trans; - PFREE_ST(old_trans, db_trans_st); - ret = 0; + { + char *cctx = (char *)(ctx->trans_cur); + + cctx += offset; + ctx->trans_cur = (struct db_trans *)cctx; + } + /* update elem count */ + ctx->max_trans = max_trans; + PFREE_ST(old_trans, db_trans_st); + ret = 0; out: - return ret; + return ret; } -/* - * Expand storage for attributes by delta_attrs number AND - * rewrite trans->attr pointers +/* + * Expand storage for attributes by delta_attrs number AND + * rewrite trans->attr pointers */ static int db_attrs_expand(struct db_context *ctx, int delta_attrs) { - int ret = -1; - struct db_attr *new_attrs, *old_attrs; - struct db_trans *t; - int ti; - int max_attrs = ctx->max_attrs + delta_attrs; - int offset; + int ret = -1; + struct db_attr *new_attrs, *old_attrs; + struct db_trans *t; + int ti; + int max_attrs = ctx->max_attrs + delta_attrs; + int offset; - old_attrs = ctx->attrs0; - new_attrs = ALLOC_BYTES_ST ( sizeof (struct db_attr) * max_attrs, - db_attrs_st); - if (!new_attrs) - goto out; + old_attrs = ctx->attrs0; + new_attrs = ALLOC_BYTES_ST ( sizeof (struct db_attr) * max_attrs, + db_attrs_st); + if (!new_attrs) + goto out; - memcpy(new_attrs, old_attrs, ctx->max_attrs * sizeof(struct db_attr)); - - /* update attrs0 and attrs_cur (obviously) */ - offset = (char *)(new_attrs) - (char *)(old_attrs); - - { - char *actx = (char *)(ctx->attrs0); - - actx += offset; - ctx->attrs0 = (struct db_attr *)actx; - - actx = (char *)ctx->attrs_cur; - actx += offset; - ctx->attrs_cur = (struct db_attr *)actx; - } + memcpy(new_attrs, old_attrs, ctx->max_attrs * sizeof(struct db_attr)); + + /* update attrs0 and attrs_cur (obviously) */ + offset = (char *)(new_attrs) - (char *)(old_attrs); + + { + char *actx = (char *)(ctx->attrs0); + + actx += offset; + ctx->attrs0 = (struct db_attr *)actx; + + actx = (char *)ctx->attrs_cur; + actx += offset; + ctx->attrs_cur = (struct db_attr *)actx; + } - /* for each transform, rewrite attrs pointer by offsetting it */ - for (t=ctx->prop.trans, ti=0; ti < ctx->prop.trans_cnt; t++, ti++) { - char *actx = (char *)(t->attrs); - - actx += offset; - t->attrs = (struct db_attr *)actx; - } - /* update elem count */ - ctx->max_attrs = max_attrs; - PFREE_ST(old_attrs, db_attrs_st); - ret = 0; + /* for each transform, rewrite attrs pointer by offsetting it */ + for (t=ctx->prop.trans, ti=0; ti < ctx->prop.trans_cnt; t++, ti++) { + char *actx = (char *)(t->attrs); + + actx += offset; + t->attrs = (struct db_attr *)actx; + } + /* update elem count */ + ctx->max_attrs = max_attrs; + PFREE_ST(old_attrs, db_attrs_st); + ret = 0; out: - return ret; + return ret; } -/* Allocate a new db object */ +/* Allocate a new db object */ struct db_context * db_prop_new(u_int8_t protoid, int max_trans, int max_attrs) { - struct db_context *ctx; - ctx = ALLOC_BYTES_ST ( sizeof (struct db_context), db_context_st); - if (!ctx) goto out; - - if (db_prop_init(ctx, protoid, max_trans, max_attrs) < 0) { - PFREE_ST(ctx, db_context_st); - ctx=NULL; - } + struct db_context *ctx; + ctx = ALLOC_BYTES_ST ( sizeof (struct db_context), db_context_st); + if (!ctx) goto out; + + if (db_prop_init(ctx, protoid, max_trans, max_attrs) < 0) { + PFREE_ST(ctx, db_context_st); + ctx=NULL; + } out: - return ctx; + return ctx; } -/* Free a db object */ +/* Free a db object */ void db_destroy(struct db_context *ctx) { - if (ctx->trans0) PFREE_ST(ctx->trans0, db_trans_st); - if (ctx->attrs0) PFREE_ST(ctx->attrs0, db_attrs_st); - PFREE_ST(ctx, db_context_st); + if (ctx->trans0) PFREE_ST(ctx->trans0, db_trans_st); + if (ctx->attrs0) PFREE_ST(ctx->attrs0, db_attrs_st); + PFREE_ST(ctx, db_context_st); } -/* Start a new transform, expand trans0 is needed */ +/* Start a new transform, expand trans0 is needed */ int db_trans_add(struct db_context *ctx, u_int8_t transid) { - /* skip incrementing current trans pointer the 1st time*/ - if (ctx->trans_cur && ctx->trans_cur->attr_cnt) - ctx->trans_cur++; - /* - * Strategy: if more space is needed, expand by - * /2 + 1 - * - * This happens to produce a "reasonable" sequence - * after few allocations, eg.: - * 0,1,2,4,8,13,20,31,47 - */ - if ((ctx->trans_cur - ctx->trans0) >= ctx->max_trans) { - /* XXX:jjo if fails should shout and flag it */ - if (db_trans_expand(ctx, ctx->max_trans/2 + 1)<0) - return -1; - } - ctx->trans_cur->transid = transid; - ctx->trans_cur->attrs=ctx->attrs_cur; - ctx->trans_cur->attr_cnt = 0; - ctx->prop.trans_cnt++; - return 0; + /* skip incrementing current trans pointer the 1st time*/ + if (ctx->trans_cur && ctx->trans_cur->attr_cnt) + ctx->trans_cur++; + /* + * Strategy: if more space is needed, expand by + * /2 + 1 + * + * This happens to produce a "reasonable" sequence + * after few allocations, eg.: + * 0,1,2,4,8,13,20,31,47 + */ + if ((ctx->trans_cur - ctx->trans0) >= ctx->max_trans) { + /* XXX:jjo if fails should shout and flag it */ + if (db_trans_expand(ctx, ctx->max_trans/2 + 1)<0) + return -1; + } + ctx->trans_cur->transid = transid; + ctx->trans_cur->attrs=ctx->attrs_cur; + ctx->trans_cur->attr_cnt = 0; + ctx->prop.trans_cnt++; + return 0; } -/* Add attr copy to current transform, expanding attrs0 if needed */ +/* Add attr copy to current transform, expanding attrs0 if needed */ int db_attr_add(struct db_context *ctx, const struct db_attr *a) { - /* - * Strategy: if more space is needed, expand by - * /2 + 1 - */ - if ((ctx->attrs_cur - ctx->attrs0) >= ctx->max_attrs) { - /* XXX:jjo if fails should shout and flag it */ - if (db_attrs_expand(ctx, ctx->max_attrs/2 + 1) < 0) - return -1; - } - *ctx->attrs_cur++=*a; - ctx->trans_cur->attr_cnt++; - return 0; + /* + * Strategy: if more space is needed, expand by + * /2 + 1 + */ + if ((ctx->attrs_cur - ctx->attrs0) >= ctx->max_attrs) { + /* XXX:jjo if fails should shout and flag it */ + if (db_attrs_expand(ctx, ctx->max_attrs/2 + 1) < 0) + return -1; + } + *ctx->attrs_cur++=*a; + ctx->trans_cur->attr_cnt++; + return 0; } -/* Add attr copy (by value) to current transform, - * expanding attrs0 if needed, just calls db_attr_add(). +/* Add attr copy (by value) to current transform, + * expanding attrs0 if needed, just calls db_attr_add(). */ int db_attr_add_values(struct db_context *ctx, u_int16_t type, u_int16_t val) { - struct db_attr attr; - attr.type = type; - attr.val = val; - return db_attr_add (ctx, &attr); + struct db_attr attr; + attr.type = type; + attr.val = val; + return db_attr_add (ctx, &attr); } #ifndef NO_DB_OPS_STATS int db_ops_show_status(void) { - whack_log(RC_COMMENT, "stats " __FILE__ ": " - DB_OPS_STATS_DESC " :" - DB_OPS_STATS_STR("context") - DB_OPS_STATS_STR("trans") - DB_OPS_STATS_STR("attrs"), - DB_OPS_STATS_F(db_context_st), - DB_OPS_STATS_F(db_trans_st), - DB_OPS_STATS_F(db_attrs_st) - ); - return 0; + whack_log(RC_COMMENT, "stats " __FILE__ ": " + DB_OPS_STATS_DESC " :" + DB_OPS_STATS_STR("context") + DB_OPS_STATS_STR("trans") + DB_OPS_STATS_STR("attrs"), + DB_OPS_STATS_F(db_context_st), + DB_OPS_STATS_F(db_trans_st), + DB_OPS_STATS_F(db_attrs_st) + ); + return 0; } #endif /* NO_DB_OPS_STATS */ /* @@ -344,51 +344,51 @@ db_ops_show_status(void) #ifdef TEST static void db_prop_print(struct db_prop *p) { - struct db_trans *t; - struct db_attr *a; - int ti, ai; - enum_names *n, *n_at, *n_av; - printf("protoid=\"%s\"\n", enum_name(&protocol_names, p->protoid)); - for (ti=0, t=p->trans; ti< p->trans_cnt; ti++, t++) { - switch( t->transid) { - case PROTO_ISAKMP: - n=&isakmp_transformid_names;break; - case PROTO_IPSEC_ESP: - n=&esp_transformid_names;break; - default: - continue; + struct db_trans *t; + struct db_attr *a; + int ti, ai; + enum_names *n, *n_at, *n_av; + printf("protoid=\"%s\"\n", enum_name(&protocol_names, p->protoid)); + for (ti=0, t=p->trans; ti< p->trans_cnt; ti++, t++) { + switch( t->transid) { + case PROTO_ISAKMP: + n=&isakmp_transformid_names;break; + case PROTO_IPSEC_ESP: + n=&esp_transformid_names;break; + default: + continue; + } + printf(" transid=\"%s\"\n", + enum_name(n, t->transid)); + for (ai=0, a=t->attrs; ai < t->attr_cnt; ai++, a++) { + int i; + switch( t->transid) { + case PROTO_ISAKMP: + n_at=&oakley_attr_names; + i=a->type|ISAKMP_ATTR_AF_TV; + n_av=oakley_attr_val_descs[(i)&ISAKMP_ATTR_RTYPE_MASK]; + break; + case PROTO_IPSEC_ESP: + n_at=&ipsec_attr_names; + i=a->type|ISAKMP_ATTR_AF_TV; + n_av=ipsec_attr_val_descs[(i)&ISAKMP_ATTR_RTYPE_MASK]; + break; + default: + continue; + } + printf(" type=\"%s\" value=\"%s\"\n", + enum_name(n_at, i), + enum_name(n_av, a->val)); + } } - printf(" transid=\"%s\"\n", - enum_name(n, t->transid)); - for (ai=0, a=t->attrs; ai < t->attr_cnt; ai++, a++) { - int i; - switch( t->transid) { - case PROTO_ISAKMP: - n_at=&oakley_attr_names; - i=a->type|ISAKMP_ATTR_AF_TV; - n_av=oakley_attr_val_descs[(i)&ISAKMP_ATTR_RTYPE_MASK]; - break; - case PROTO_IPSEC_ESP: - n_at=&ipsec_attr_names; - i=a->type|ISAKMP_ATTR_AF_TV; - n_av=ipsec_attr_val_descs[(i)&ISAKMP_ATTR_RTYPE_MASK]; - break; - default: - continue; - } - printf(" type=\"%s\" value=\"%s\"\n", - enum_name(n_at, i), - enum_name(n_av, a->val)); - } - } } static void db_print(struct db_context *ctx) { - printf("trans_cur diff=%d, attrs_cur diff=%d\n", - ctx->trans_cur - ctx->trans0, - ctx->attrs_cur - ctx->attrs0); - db_prop_print(&ctx->prop); + printf("trans_cur diff=%d, attrs_cur diff=%d\n", + ctx->trans_cur - ctx->trans0, + ctx->attrs_cur - ctx->attrs0); + db_prop_print(&ctx->prop); } void @@ -397,25 +397,25 @@ void abort(void); void passert_fail(const char *pred_str, const char *file_str, unsigned long line_no) { - fprintf(stderr, "ASSERTION FAILED at %s:%lu: %s", file_str, line_no, pred_str); - abort(); /* exiting correctly doesn't always work */ + fprintf(stderr, "ASSERTION FAILED at %s:%lu: %s", file_str, line_no, pred_str); + abort(); /* exiting correctly doesn't always work */ } int main(void) { - struct db_context *ctx=db_prop_new(PROTO_ISAKMP, 0, 0); - db_trans_add(ctx, KEY_IKE); - db_attr_add_values(ctx, OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC); - db_attr_add_values(ctx, OAKLEY_HASH_ALGORITHM, OAKLEY_MD5); - db_attr_add_values(ctx, OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG); - db_attr_add_values(ctx, OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024); - db_trans_add(ctx, KEY_IKE); - db_attr_add_values(ctx, OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_AES_CBC); - db_attr_add_values(ctx, OAKLEY_HASH_ALGORITHM, OAKLEY_MD5); - db_attr_add_values(ctx, OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY); - db_attr_add_values(ctx, OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536); - db_trans_add(ctx, ESP_3DES); - db_attr_add_values(ctx, AUTH_ALGORITHM, AUTH_ALGORITHM_HMAC_SHA1); - db_print(ctx); - db_destroy(ctx); - return 0; + struct db_context *ctx=db_prop_new(PROTO_ISAKMP, 0, 0); + db_trans_add(ctx, KEY_IKE); + db_attr_add_values(ctx, OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC); + db_attr_add_values(ctx, OAKLEY_HASH_ALGORITHM, OAKLEY_MD5); + db_attr_add_values(ctx, OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG); + db_attr_add_values(ctx, OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024); + db_trans_add(ctx, KEY_IKE); + db_attr_add_values(ctx, OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_AES_CBC); + db_attr_add_values(ctx, OAKLEY_HASH_ALGORITHM, OAKLEY_MD5); + db_attr_add_values(ctx, OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY); + db_attr_add_values(ctx, OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536); + db_trans_add(ctx, ESP_3DES); + db_attr_add_values(ctx, AUTH_ALGORITHM, AUTH_ALGORITHM_HMAC_SHA1); + db_print(ctx); + db_destroy(ctx); + return 0; } #endif diff --git a/src/pluto/db_ops.h b/src/pluto/db_ops.h index 5df5ac313..f3718a4b2 100644 --- a/src/pluto/db_ops.h +++ b/src/pluto/db_ops.h @@ -18,39 +18,39 @@ #define _DB_OPS_H /* - * Main db object, (quite proposal "oriented") + * Main db object, (quite proposal "oriented") */ #ifndef NO_DB_CONTEXT struct db_context { - struct db_prop prop; /* proposal buffer (not pointer) */ - struct db_trans *trans0; /* transf. list, dynamically sized */ - struct db_trans *trans_cur; /* current transform ptr */ - struct db_attr *attrs0; /* attr. list, dynamically sized */ - struct db_attr *attrs_cur; /* current attribute ptr */ - int max_trans; /* size of trans list */ - int max_attrs; /* size of attrs list */ + struct db_prop prop; /* proposal buffer (not pointer) */ + struct db_trans *trans0; /* transf. list, dynamically sized */ + struct db_trans *trans_cur; /* current transform ptr */ + struct db_attr *attrs0; /* attr. list, dynamically sized */ + struct db_attr *attrs_cur; /* current attribute ptr */ + int max_trans; /* size of trans list */ + int max_attrs; /* size of attrs list */ }; /* - * Allocate a new db object + * Allocate a new db object */ struct db_context * db_prop_new(u_int8_t protoid, int max_trans, int max_attrs); -/* Initialize object for proposal building */ +/* Initialize object for proposal building */ int db_prop_init(struct db_context *ctx, u_int8_t protoid, int max_trans, int max_attrs); -/* Free all resourses for this db */ +/* Free all resourses for this db */ void db_destroy(struct db_context *ctx); -/* Start a new transform */ +/* Start a new transform */ int db_trans_add(struct db_context *ctx, u_int8_t transid); -/* Add a new attribute by copying db_attr content */ +/* Add a new attribute by copying db_attr content */ int db_attr_add(struct db_context *db_ctx, const struct db_attr *attr); -/* Add a new attribute by value */ +/* Add a new attribute by value */ int db_attr_add_values(struct db_context *ctx, u_int16_t type, u_int16_t val); -/* Get proposal from db object */ +/* Get proposal from db object */ static __inline__ struct db_prop *db_prop_get(struct db_context *ctx) { - return &ctx->prop; + return &ctx->prop; } -/* Show stats (allocation, etc) */ +/* Show stats (allocation, etc) */ #endif /* NO_DB_CONTEXT */ int db_ops_show_status(void); #endif /* _DB_OPS_H */ diff --git a/src/pluto/defs.c b/src/pluto/defs.c index 2b88d73d9..09fd8415b 100644 --- a/src/pluto/defs.c +++ b/src/pluto/defs.c @@ -27,25 +27,25 @@ #include "constants.h" #include "defs.h" #include "log.h" -#include "whack.h" /* for RC_LOG_SERIOUS */ +#include "whack.h" /* for RC_LOG_SERIOUS */ bool all_zero(const unsigned char *m, size_t len) { - size_t i; + size_t i; - for (i = 0; i != len; i++) - if (m[i] != '\0') - return FALSE; - return TRUE; + for (i = 0; i != len; i++) + if (m[i] != '\0') + return FALSE; + return TRUE; } void *clone_bytes(const void *orig, size_t size) { - void *p = malloc(size); + void *p = malloc(size); - memcpy(p, orig, size); - return p; + memcpy(p, orig, size); + return p; } /* Note that there may be as many as six IDs that are temporary at @@ -53,16 +53,16 @@ void *clone_bytes(const void *orig, size_t size) * at least six temporary buffers for DER_ASN1_DN IDs. * We rotate them. Be careful! */ -#define MAX_BUF 10 +#define MAX_BUF 10 char* temporary_cyclic_buffer(void) { - static char buf[MAX_BUF][BUF_LEN]; /* MAX_BUF internal buffers */ - static int counter = 0; /* cyclic counter */ + static char buf[MAX_BUF][BUF_LEN]; /* MAX_BUF internal buffers */ + static int counter = 0; /* cyclic counter */ - if (++counter == MAX_BUF) counter = 0; /* next internal buffer */ - return buf[counter]; /* assign temporary buffer */ + if (++counter == MAX_BUF) counter = 0; /* next internal buffer */ + return buf[counter]; /* assign temporary buffer */ } /* concatenates two sub paths into a string with a maximum size of BUF_LEN @@ -71,14 +71,14 @@ temporary_cyclic_buffer(void) const char* concatenate_paths(const char *a, const char *b) { - char *c; + char *c; - if (*b == '/' || *b == '.') - return b; + if (*b == '/' || *b == '.') + return b; - c = temporary_cyclic_buffer(); - snprintf(c, BUF_LEN, "%s/%s", a, b); - return c; + c = temporary_cyclic_buffer(); + snprintf(c, BUF_LEN, "%s/%s", a, b); + return c; } /* moves a chunk to a memory position, chunk is freed afterwards @@ -87,11 +87,11 @@ concatenate_paths(const char *a, const char *b) void mv_chunk(u_char **pos, chunk_t content) { - if (content.len > 0) - { - chunkcpy(*pos, content); - free(content.ptr); - } + if (content.len > 0) + { + chunkcpy(*pos, content); + free(content.ptr); + } } /* @@ -101,46 +101,46 @@ bool write_chunk(const char *filename, const char *label, chunk_t ch , mode_t mask, bool force) { - mode_t oldmask; - FILE *fd; - size_t written; + mode_t oldmask; + FILE *fd; + size_t written; + + if (!force) + { + fd = fopen(filename, "r"); + if (fd) + { + fclose(fd); + plog(" %s file '%s' already exists", label, filename); + return FALSE; + } + } + + /* set umask */ + oldmask = umask(mask); + + fd = fopen(filename, "w"); - if (!force) - { - fd = fopen(filename, "r"); if (fd) { - fclose(fd); - plog(" %s file '%s' already exists", label, filename); - return FALSE; + written = fwrite(ch.ptr, sizeof(u_char), ch.len, fd); + fclose(fd); + if (written != ch.len) + { + plog(" writing to %s file '%s' failed", label, filename); + umask(oldmask); + return FALSE; + } + plog(" written %s file '%s' (%d bytes)", label, filename, (int)ch.len); + umask(oldmask); + return TRUE; } - } - - /* set umask */ - oldmask = umask(mask); - - fd = fopen(filename, "w"); - - if (fd) - { - written = fwrite(ch.ptr, sizeof(u_char), ch.len, fd); - fclose(fd); - if (written != ch.len) + else { - plog(" writing to %s file '%s' failed", label, filename); - umask(oldmask); - return FALSE; + plog(" could not open %s file '%s' for writing", label, filename); + umask(oldmask); + return FALSE; } - plog(" written %s file '%s' (%d bytes)", label, filename, (int)ch.len); - umask(oldmask); - return TRUE; - } - else - { - plog(" could not open %s file '%s' for writing", label, filename); - umask(oldmask); - return FALSE; - } } /* checks if the expiration date has been reached and @@ -151,44 +151,44 @@ write_chunk(const char *filename, const char *label, chunk_t ch const char* check_expiry(time_t expiration_date, int warning_interval, bool strict) { - time_t now; - int time_left; + time_t now; + int time_left; - if (expiration_date == UNDEFINED_TIME) - return "ok (expires never)"; + if (expiration_date == UNDEFINED_TIME) + return "ok (expires never)"; - /* determine the current time */ - time(&now); + /* determine the current time */ + time(&now); - time_left = (expiration_date - now); - if (time_left < 0) - return strict? "fatal (expired)" : "warning (expired)"; + time_left = (expiration_date - now); + if (time_left < 0) + return strict? "fatal (expired)" : "warning (expired)"; - if (time_left > 86400*warning_interval) - return "ok"; - { - static char buf[35]; /* temporary storage */ - const char* unit = "second"; - - if (time_left > 172800) + if (time_left > 86400*warning_interval) + return "ok"; { - time_left /= 86400; - unit = "day"; + static char buf[35]; /* temporary storage */ + const char* unit = "second"; + + if (time_left > 172800) + { + time_left /= 86400; + unit = "day"; + } + else if (time_left > 7200) + { + time_left /= 3600; + unit = "hour"; + } + else if (time_left > 120) + { + time_left /= 60; + unit = "minute"; + } + snprintf(buf, 35, "warning (expires in %d %s%s)", time_left, + unit, (time_left == 1)?"":"s"); + return buf; } - else if (time_left > 7200) - { - time_left /= 3600; - unit = "hour"; - } - else if (time_left > 120) - { - time_left /= 60; - unit = "minute"; - } - snprintf(buf, 35, "warning (expires in %d %s%s)", time_left, - unit, (time_left == 1)?"":"s"); - return buf; - } } @@ -198,8 +198,8 @@ check_expiry(time_t expiration_date, int warning_interval, bool strict) int file_select(const struct dirent *entry) { - return strcmp(entry->d_name, "." ) && - strcmp(entry->d_name, ".."); + return strcmp(entry->d_name, "." ) && + strcmp(entry->d_name, ".."); } diff --git a/src/pluto/defs.h b/src/pluto/defs.h index 888748161..1ad1de0fa 100644 --- a/src/pluto/defs.h +++ b/src/pluto/defs.h @@ -24,23 +24,23 @@ #include #ifdef KLIPS -# define USED_BY_KLIPS /* ignore */ +# define USED_BY_KLIPS /* ignore */ #else -# define USED_BY_KLIPS UNUSED +# define USED_BY_KLIPS UNUSED #endif #ifdef DEBUG -# define USED_BY_DEBUG /* ignore */ +# define USED_BY_DEBUG /* ignore */ #else -# define USED_BY_DEBUG UNUSED +# define USED_BY_DEBUG UNUSED #endif /* type of serial number of a state object * Needed in connections.h and state.h; here to simplify dependencies. */ typedef unsigned long so_serial_t; -#define SOS_NOBODY 0 /* null serial number */ -#define SOS_FIRST 1 /* first normal serial number */ +#define SOS_NOBODY 0 /* null serial number */ +#define SOS_FIRST 1 /* first normal serial number */ /* memory allocation */ @@ -49,13 +49,13 @@ extern void *clone_bytes(const void *orig, size_t size); #define clone_thing(orig) clone_bytes((const void *)&(orig), sizeof(orig)) #define clone_str(str) \ - ((str) == NULL? NULL : strdup(str)) + ((str) == NULL? NULL : strdup(str)) #define replace(p, q) \ - { free(p); (p) = (q); } + { free(p); (p) = (q); } #define chunkcpy(dst, chunk) \ - { memcpy(dst, chunk.ptr, chunk.len); dst += chunk.len;} + { memcpy(dst, chunk.ptr, chunk.len); dst += chunk.len;} extern char* temporary_cyclic_buffer(void); extern const char* concatenate_paths(const char *a, const char *b); @@ -65,26 +65,26 @@ extern void mv_chunk(u_char **pos, chunk_t content); /* write the binary contents of a chunk_t to a file */ extern bool write_chunk(const char *filename, const char *label, chunk_t ch - ,mode_t mask, bool force); + ,mode_t mask, bool force); /* warns a predefined interval before expiry */ extern const char* check_expiry(time_t expiration_date, - int warning_interval, bool strict); + int warning_interval, bool strict); -#define MAX_PROMPT_PASS_TRIALS 5 -#define PROMPT_PASS_LEN 64 +#define MAX_PROMPT_PASS_TRIALS 5 +#define PROMPT_PASS_LEN 64 /* struct used to prompt for a secret passphrase * from a console with file descriptor fd */ typedef struct { - char secret[PROMPT_PASS_LEN+1]; - bool prompt; - int fd; + char secret[PROMPT_PASS_LEN+1]; + bool prompt; + int fd; } prompt_pass_t; /* size of timetoa string buffer */ -#define TIMETOA_BUF 30 +#define TIMETOA_BUF 30 /* filter eliminating the directory entries '.' and '..' */ typedef struct dirent dirent_t; diff --git a/src/pluto/demux.c b/src/pluto/demux.c index 5509bd2a2..555cde558 100644 --- a/src/pluto/demux.c +++ b/src/pluto/demux.c @@ -110,8 +110,8 @@ #include #include #include -#include /* only used for belt-and-suspenders select call */ -#include /* only used for forensic poll call */ +#include /* only used for belt-and-suspenders select call */ +#include /* only used for forensic poll call */ #include #include #include @@ -119,9 +119,9 @@ #include #if defined(IP_RECVERR) && defined(MSG_ERRQUEUE) -# include /* for __u8, __u32 */ +# include /* for __u8, __u32 */ # include -# include /* struct iovec */ +# include /* struct iovec */ #endif #include @@ -137,10 +137,10 @@ #include "crypto.h" /* requires sha1.h and md5.h */ #include "ike_alg.h" #include "log.h" -#include "demux.h" /* needs packet.h */ -#include "ipsec_doi.h" /* needs demux.h and state.h */ +#include "demux.h" /* needs packet.h */ +#include "ipsec_doi.h" /* needs demux.h and state.h */ #include "timer.h" -#include "whack.h" /* requires connections.h */ +#include "whack.h" /* requires connections.h */ #include "server.h" #include "nat_traversal.h" #include "vendor.h" @@ -173,14 +173,14 @@ u_int8_t reply_buffer[MAX_OUTPUT_UDP_SIZE]; */ struct state_microcode { - enum state_kind state, next_state; - lset_t flags; - lset_t req_payloads; /* required payloads (allows just one) */ - lset_t opt_payloads; /* optional payloads (any mumber) */ - /* if not ISAKMP_NEXT_NONE, process_packet will emit HDR with this as np */ - u_int8_t first_out_payload; - enum event_type timeout_event; - state_transition_fn *processor; + enum state_kind state, next_state; + lset_t flags; + lset_t req_payloads; /* required payloads (allows just one) */ + lset_t opt_payloads; /* optional payloads (any mumber) */ + /* if not ISAKMP_NEXT_NONE, process_packet will emit HDR with this as np */ + u_int8_t first_out_payload; + enum event_type timeout_event; + state_transition_fn *processor; }; /* State Microcode Flags, in several groups */ @@ -190,19 +190,19 @@ struct state_microcode { * Note: SMF_ALL_AUTH matches 0 for those circumstances when no auth * has been set. */ -#define SMF_ALL_AUTH LRANGE(0, OAKLEY_AUTH_ROOF-1) -#define SMF_PSK_AUTH LELEM(OAKLEY_PRESHARED_KEY) -#define SMF_DS_AUTH (LELEM(OAKLEY_DSS_SIG) | LELEM(OAKLEY_RSA_SIG)) -#define SMF_PKE_AUTH (LELEM(OAKLEY_RSA_ENC) | LELEM(OAKLEY_ELGAMAL_ENC)) -#define SMF_RPKE_AUTH (LELEM(OAKLEY_RSA_ENC_REV) | LELEM(OAKLEY_ELGAMAL_ENC_REV)) +#define SMF_ALL_AUTH LRANGE(0, OAKLEY_AUTH_ROOF-1) +#define SMF_PSK_AUTH LELEM(OAKLEY_PRESHARED_KEY) +#define SMF_DS_AUTH (LELEM(OAKLEY_DSS_SIG) | LELEM(OAKLEY_RSA_SIG)) +#define SMF_PKE_AUTH (LELEM(OAKLEY_RSA_ENC) | LELEM(OAKLEY_ELGAMAL_ENC)) +#define SMF_RPKE_AUTH (LELEM(OAKLEY_RSA_ENC_REV) | LELEM(OAKLEY_ELGAMAL_ENC_REV)) /* misc flags */ -#define SMF_INITIATOR LELEM(OAKLEY_AUTH_ROOF + 0) -#define SMF_FIRST_ENCRYPTED_INPUT LELEM(OAKLEY_AUTH_ROOF + 1) -#define SMF_INPUT_ENCRYPTED LELEM(OAKLEY_AUTH_ROOF + 2) -#define SMF_OUTPUT_ENCRYPTED LELEM(OAKLEY_AUTH_ROOF + 3) -#define SMF_RETRANSMIT_ON_DUPLICATE LELEM(OAKLEY_AUTH_ROOF + 4) +#define SMF_INITIATOR LELEM(OAKLEY_AUTH_ROOF + 0) +#define SMF_FIRST_ENCRYPTED_INPUT LELEM(OAKLEY_AUTH_ROOF + 1) +#define SMF_INPUT_ENCRYPTED LELEM(OAKLEY_AUTH_ROOF + 2) +#define SMF_OUTPUT_ENCRYPTED LELEM(OAKLEY_AUTH_ROOF + 3) +#define SMF_RETRANSMIT_ON_DUPLICATE LELEM(OAKLEY_AUTH_ROOF + 4) #define SMF_ENCRYPTED (SMF_INPUT_ENCRYPTED | SMF_OUTPUT_ENCRYPTED) @@ -210,14 +210,14 @@ struct state_microcode { #define SMF_REPLY LELEM(OAKLEY_AUTH_ROOF + 5) /* this state completes P1, so any pending P2 negotiations should start */ -#define SMF_RELEASE_PENDING_P2 LELEM(OAKLEY_AUTH_ROOF + 6) +#define SMF_RELEASE_PENDING_P2 LELEM(OAKLEY_AUTH_ROOF + 6) /* end of flags */ -static state_transition_fn /* forward declaration */ - unexpected, - informational; +static state_transition_fn /* forward declaration */ + unexpected, + informational; /* state_microcode_table is a table of all state_microcode tuples. * It must be in order of state (the first element). @@ -228,288 +228,288 @@ static state_transition_fn /* forward declaration */ */ static const struct state_microcode - *ike_microcode_index[STATE_IKE_ROOF - STATE_IKE_FLOOR]; + *ike_microcode_index[STATE_IKE_ROOF - STATE_IKE_FLOOR]; static const struct state_microcode state_microcode_table[] = { #define PT(n) ISAKMP_NEXT_##n #define P(n) LELEM(PT(n)) - /***** Phase 1 Main Mode *****/ + /***** Phase 1 Main Mode *****/ - /* No state for main_outI1: --> HDR, SA */ + /* No state for main_outI1: --> HDR, SA */ - /* STATE_MAIN_R0: I1 --> R1 - * HDR, SA --> HDR, SA - */ - { STATE_MAIN_R0, STATE_MAIN_R1 - , SMF_ALL_AUTH | SMF_REPLY - , P(SA), P(VID) | P(CR), PT(NONE) - , EVENT_RETRANSMIT, main_inI1_outR1}, + /* STATE_MAIN_R0: I1 --> R1 + * HDR, SA --> HDR, SA + */ + { STATE_MAIN_R0, STATE_MAIN_R1 + , SMF_ALL_AUTH | SMF_REPLY + , P(SA), P(VID) | P(CR), PT(NONE) + , EVENT_RETRANSMIT, main_inI1_outR1}, - /* STATE_MAIN_I1: R1 --> I2 - * HDR, SA --> auth dependent - * SMF_PSK_AUTH, SMF_DS_AUTH: --> HDR, KE, Ni - * SMF_PKE_AUTH: - * --> HDR, KE, [ HASH(1), ] PubKey_r, PubKey_r - * SMF_RPKE_AUTH: - * --> HDR, [ HASH(1), ] Pubkey_r, Ke_i, Ke_i [,<Ke_i] - * Note: since we don't know auth at start, we cannot differentiate - * microcode entries based on it. - */ - { STATE_MAIN_I1, STATE_MAIN_I2 - , SMF_ALL_AUTH | SMF_INITIATOR | SMF_REPLY - , P(SA), P(VID) | P(CR), PT(NONE) /* don't know yet */ - , EVENT_RETRANSMIT, main_inR1_outI2 }, + /* STATE_MAIN_I1: R1 --> I2 + * HDR, SA --> auth dependent + * SMF_PSK_AUTH, SMF_DS_AUTH: --> HDR, KE, Ni + * SMF_PKE_AUTH: + * --> HDR, KE, [ HASH(1), ] PubKey_r, PubKey_r + * SMF_RPKE_AUTH: + * --> HDR, [ HASH(1), ] Pubkey_r, Ke_i, Ke_i [,<Ke_i] + * Note: since we don't know auth at start, we cannot differentiate + * microcode entries based on it. + */ + { STATE_MAIN_I1, STATE_MAIN_I2 + , SMF_ALL_AUTH | SMF_INITIATOR | SMF_REPLY + , P(SA), P(VID) | P(CR), PT(NONE) /* don't know yet */ + , EVENT_RETRANSMIT, main_inR1_outI2 }, - /* STATE_MAIN_R1: I2 --> R2 - * SMF_PSK_AUTH, SMF_DS_AUTH: HDR, KE, Ni --> HDR, KE, Nr - * SMF_PKE_AUTH: HDR, KE, [ HASH(1), ] PubKey_r, PubKey_r - * --> HDR, KE, PubKey_i, PubKey_i - * SMF_RPKE_AUTH: - * HDR, [ HASH(1), ] Pubkey_r, Ke_i, Ke_i [,<Ke_i] - * --> HDR, PubKey_i, Ke_r, Ke_r - */ - { STATE_MAIN_R1, STATE_MAIN_R2 - , SMF_PSK_AUTH | SMF_DS_AUTH | SMF_REPLY - , P(KE) | P(NONCE), P(VID) | P(CR) | P(NATD_RFC), PT(KE) - , EVENT_RETRANSMIT, main_inI2_outR2 }, + /* STATE_MAIN_R1: I2 --> R2 + * SMF_PSK_AUTH, SMF_DS_AUTH: HDR, KE, Ni --> HDR, KE, Nr + * SMF_PKE_AUTH: HDR, KE, [ HASH(1), ] PubKey_r, PubKey_r + * --> HDR, KE, PubKey_i, PubKey_i + * SMF_RPKE_AUTH: + * HDR, [ HASH(1), ] Pubkey_r, Ke_i, Ke_i [,<Ke_i] + * --> HDR, PubKey_i, Ke_r, Ke_r + */ + { STATE_MAIN_R1, STATE_MAIN_R2 + , SMF_PSK_AUTH | SMF_DS_AUTH | SMF_REPLY + , P(KE) | P(NONCE), P(VID) | P(CR) | P(NATD_RFC), PT(KE) + , EVENT_RETRANSMIT, main_inI2_outR2 }, - { STATE_MAIN_R1, STATE_UNDEFINED - , SMF_PKE_AUTH | SMF_REPLY - , P(KE) | P(ID) | P(NONCE), P(VID) | P(CR) | P(HASH), PT(KE) - , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ }, + { STATE_MAIN_R1, STATE_UNDEFINED + , SMF_PKE_AUTH | SMF_REPLY + , P(KE) | P(ID) | P(NONCE), P(VID) | P(CR) | P(HASH), PT(KE) + , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ }, - { STATE_MAIN_R1, STATE_UNDEFINED - , SMF_RPKE_AUTH | SMF_REPLY - , P(NONCE) | P(KE) | P(ID), P(VID) | P(CR) | P(HASH) | P(CERT), PT(NONCE) - , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ }, + { STATE_MAIN_R1, STATE_UNDEFINED + , SMF_RPKE_AUTH | SMF_REPLY + , P(NONCE) | P(KE) | P(ID), P(VID) | P(CR) | P(HASH) | P(CERT), PT(NONCE) + , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ }, - /* for states from here on, output message must be encrypted */ + /* for states from here on, output message must be encrypted */ - /* STATE_MAIN_I2: R2 --> I3 - * SMF_PSK_AUTH: HDR, KE, Nr --> HDR*, IDi1, HASH_I - * SMF_DS_AUTH: HDR, KE, Nr --> HDR*, IDi1, [ CERT, ] SIG_I - * SMF_PKE_AUTH: HDR, KE, PubKey_i, PubKey_i - * --> HDR*, HASH_I - * SMF_RPKE_AUTH: HDR, PubKey_i, Ke_r, Ke_r - * --> HDR*, HASH_I - */ - { STATE_MAIN_I2, STATE_MAIN_I3 - , SMF_PSK_AUTH | SMF_DS_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED | SMF_REPLY - , P(KE) | P(NONCE), P(VID) | P(CR) | P(NATD_RFC), PT(ID) - , EVENT_RETRANSMIT, main_inR2_outI3 }, + /* STATE_MAIN_I2: R2 --> I3 + * SMF_PSK_AUTH: HDR, KE, Nr --> HDR*, IDi1, HASH_I + * SMF_DS_AUTH: HDR, KE, Nr --> HDR*, IDi1, [ CERT, ] SIG_I + * SMF_PKE_AUTH: HDR, KE, PubKey_i, PubKey_i + * --> HDR*, HASH_I + * SMF_RPKE_AUTH: HDR, PubKey_i, Ke_r, Ke_r + * --> HDR*, HASH_I + */ + { STATE_MAIN_I2, STATE_MAIN_I3 + , SMF_PSK_AUTH | SMF_DS_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED | SMF_REPLY + , P(KE) | P(NONCE), P(VID) | P(CR) | P(NATD_RFC), PT(ID) + , EVENT_RETRANSMIT, main_inR2_outI3 }, - { STATE_MAIN_I2, STATE_UNDEFINED - , SMF_PKE_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED | SMF_REPLY - , P(KE) | P(ID) | P(NONCE), P(VID) | P(CR), PT(HASH) - , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ }, + { STATE_MAIN_I2, STATE_UNDEFINED + , SMF_PKE_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED | SMF_REPLY + , P(KE) | P(ID) | P(NONCE), P(VID) | P(CR), PT(HASH) + , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ }, - { STATE_MAIN_I2, STATE_UNDEFINED - , SMF_ALL_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED | SMF_REPLY - , P(NONCE) | P(KE) | P(ID), P(VID) | P(CR), PT(HASH) - , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ }, + { STATE_MAIN_I2, STATE_UNDEFINED + , SMF_ALL_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED | SMF_REPLY + , P(NONCE) | P(KE) | P(ID), P(VID) | P(CR), PT(HASH) + , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ }, - /* for states from here on, input message must be encrypted */ + /* for states from here on, input message must be encrypted */ - /* STATE_MAIN_R2: I3 --> R3 - * SMF_PSK_AUTH: HDR*, IDi1, HASH_I --> HDR*, IDr1, HASH_R - * SMF_DS_AUTH: HDR*, IDi1, [ CERT, ] SIG_I --> HDR*, IDr1, [ CERT, ] SIG_R - * SMF_PKE_AUTH, SMF_RPKE_AUTH: HDR*, HASH_I --> HDR*, HASH_R - */ - { STATE_MAIN_R2, STATE_MAIN_R3 - , SMF_PSK_AUTH | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED - | SMF_REPLY | SMF_RELEASE_PENDING_P2 - , P(ID) | P(HASH), P(VID) | P(CR), PT(NONE) - , EVENT_SA_REPLACE, main_inI3_outR3 }, + /* STATE_MAIN_R2: I3 --> R3 + * SMF_PSK_AUTH: HDR*, IDi1, HASH_I --> HDR*, IDr1, HASH_R + * SMF_DS_AUTH: HDR*, IDi1, [ CERT, ] SIG_I --> HDR*, IDr1, [ CERT, ] SIG_R + * SMF_PKE_AUTH, SMF_RPKE_AUTH: HDR*, HASH_I --> HDR*, HASH_R + */ + { STATE_MAIN_R2, STATE_MAIN_R3 + , SMF_PSK_AUTH | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED + | SMF_REPLY | SMF_RELEASE_PENDING_P2 + , P(ID) | P(HASH), P(VID) | P(CR), PT(NONE) + , EVENT_SA_REPLACE, main_inI3_outR3 }, - { STATE_MAIN_R2, STATE_MAIN_R3 - , SMF_DS_AUTH | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED - | SMF_REPLY | SMF_RELEASE_PENDING_P2 - , P(ID) | P(SIG), P(VID) | P(CR) | P(CERT), PT(NONE) - , EVENT_SA_REPLACE, main_inI3_outR3 }, + { STATE_MAIN_R2, STATE_MAIN_R3 + , SMF_DS_AUTH | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED + | SMF_REPLY | SMF_RELEASE_PENDING_P2 + , P(ID) | P(SIG), P(VID) | P(CR) | P(CERT), PT(NONE) + , EVENT_SA_REPLACE, main_inI3_outR3 }, - { STATE_MAIN_R2, STATE_UNDEFINED - , SMF_PKE_AUTH | SMF_RPKE_AUTH | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED - | SMF_REPLY | SMF_RELEASE_PENDING_P2 - , P(HASH), P(VID) | P(CR), PT(NONE) - , EVENT_SA_REPLACE, unexpected /* ??? not yet implemented */ }, + { STATE_MAIN_R2, STATE_UNDEFINED + , SMF_PKE_AUTH | SMF_RPKE_AUTH | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED + | SMF_REPLY | SMF_RELEASE_PENDING_P2 + , P(HASH), P(VID) | P(CR), PT(NONE) + , EVENT_SA_REPLACE, unexpected /* ??? not yet implemented */ }, - /* STATE_MAIN_I3: R3 --> done - * SMF_PSK_AUTH: HDR*, IDr1, HASH_R --> done - * SMF_DS_AUTH: HDR*, IDr1, [ CERT, ] SIG_R --> done - * SMF_PKE_AUTH, SMF_RPKE_AUTH: HDR*, HASH_R --> done - * May initiate quick mode by calling quick_outI1 - */ - { STATE_MAIN_I3, STATE_MAIN_I4 - , SMF_PSK_AUTH | SMF_INITIATOR - | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2 - , P(ID) | P(HASH), P(VID) | P(CR), PT(NONE) - , EVENT_SA_REPLACE, main_inR3 }, + /* STATE_MAIN_I3: R3 --> done + * SMF_PSK_AUTH: HDR*, IDr1, HASH_R --> done + * SMF_DS_AUTH: HDR*, IDr1, [ CERT, ] SIG_R --> done + * SMF_PKE_AUTH, SMF_RPKE_AUTH: HDR*, HASH_R --> done + * May initiate quick mode by calling quick_outI1 + */ + { STATE_MAIN_I3, STATE_MAIN_I4 + , SMF_PSK_AUTH | SMF_INITIATOR + | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2 + , P(ID) | P(HASH), P(VID) | P(CR), PT(NONE) + , EVENT_SA_REPLACE, main_inR3 }, - { STATE_MAIN_I3, STATE_MAIN_I4 - , SMF_DS_AUTH | SMF_INITIATOR - | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2 - , P(ID) | P(SIG), P(VID) | P(CR) | P(CERT), PT(NONE) - , EVENT_SA_REPLACE, main_inR3 }, + { STATE_MAIN_I3, STATE_MAIN_I4 + , SMF_DS_AUTH | SMF_INITIATOR + | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2 + , P(ID) | P(SIG), P(VID) | P(CR) | P(CERT), PT(NONE) + , EVENT_SA_REPLACE, main_inR3 }, - { STATE_MAIN_I3, STATE_UNDEFINED - , SMF_PKE_AUTH | SMF_RPKE_AUTH | SMF_INITIATOR - | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2 - , P(HASH), P(VID) | P(CR), PT(NONE) - , EVENT_SA_REPLACE, unexpected /* ??? not yet implemented */ }, + { STATE_MAIN_I3, STATE_UNDEFINED + , SMF_PKE_AUTH | SMF_RPKE_AUTH | SMF_INITIATOR + | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2 + , P(HASH), P(VID) | P(CR), PT(NONE) + , EVENT_SA_REPLACE, unexpected /* ??? not yet implemented */ }, - /* STATE_MAIN_R3: can only get here due to packet loss */ - { STATE_MAIN_R3, STATE_UNDEFINED - , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RETRANSMIT_ON_DUPLICATE - , LEMPTY, LEMPTY - , PT(NONE), EVENT_NULL, unexpected }, + /* STATE_MAIN_R3: can only get here due to packet loss */ + { STATE_MAIN_R3, STATE_UNDEFINED + , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RETRANSMIT_ON_DUPLICATE + , LEMPTY, LEMPTY + , PT(NONE), EVENT_NULL, unexpected }, - /* STATE_MAIN_I4: can only get here due to packet loss */ - { STATE_MAIN_I4, STATE_UNDEFINED - , SMF_ALL_AUTH | SMF_INITIATOR | SMF_ENCRYPTED - , LEMPTY, LEMPTY - , PT(NONE), EVENT_NULL, unexpected }, + /* STATE_MAIN_I4: can only get here due to packet loss */ + { STATE_MAIN_I4, STATE_UNDEFINED + , SMF_ALL_AUTH | SMF_INITIATOR | SMF_ENCRYPTED + , LEMPTY, LEMPTY + , PT(NONE), EVENT_NULL, unexpected }, - /***** Phase 2 Quick Mode *****/ + /***** Phase 2 Quick Mode *****/ - /* No state for quick_outI1: - * --> HDR*, HASH(1), SA, Nr [, KE ] [, IDci, IDcr ] - */ + /* No state for quick_outI1: + * --> HDR*, HASH(1), SA, Nr [, KE ] [, IDci, IDcr ] + */ - /* STATE_QUICK_R0: - * HDR*, HASH(1), SA, Ni [, KE ] [, IDci, IDcr ] --> - * HDR*, HASH(2), SA, Nr [, KE ] [, IDci, IDcr ] - * Installs inbound IPsec SAs. - * Because it may suspend for asynchronous DNS, first_out_payload - * is set to NONE to suppress early emission of HDR*. - * ??? it is legal to have multiple SAs, but we don't support it yet. - */ - { STATE_QUICK_R0, STATE_QUICK_R1 - , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY - , P(HASH) | P(SA) | P(NONCE), /* P(SA) | */ P(KE) | P(ID) | P(NATOA_RFC), PT(NONE) - , EVENT_RETRANSMIT, quick_inI1_outR1 }, + /* STATE_QUICK_R0: + * HDR*, HASH(1), SA, Ni [, KE ] [, IDci, IDcr ] --> + * HDR*, HASH(2), SA, Nr [, KE ] [, IDci, IDcr ] + * Installs inbound IPsec SAs. + * Because it may suspend for asynchronous DNS, first_out_payload + * is set to NONE to suppress early emission of HDR*. + * ??? it is legal to have multiple SAs, but we don't support it yet. + */ + { STATE_QUICK_R0, STATE_QUICK_R1 + , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY + , P(HASH) | P(SA) | P(NONCE), /* P(SA) | */ P(KE) | P(ID) | P(NATOA_RFC), PT(NONE) + , EVENT_RETRANSMIT, quick_inI1_outR1 }, - /* STATE_QUICK_I1: - * HDR*, HASH(2), SA, Nr [, KE ] [, IDci, IDcr ] --> - * HDR*, HASH(3) - * Installs inbound and outbound IPsec SAs, routing, etc. - * ??? it is legal to have multiple SAs, but we don't support it yet. - */ - { STATE_QUICK_I1, STATE_QUICK_I2 - , SMF_ALL_AUTH | SMF_INITIATOR | SMF_ENCRYPTED | SMF_REPLY - , P(HASH) | P(SA) | P(NONCE), /* P(SA) | */ P(KE) | P(ID) | P(NATOA_RFC), PT(HASH) - , EVENT_SA_REPLACE, quick_inR1_outI2 }, + /* STATE_QUICK_I1: + * HDR*, HASH(2), SA, Nr [, KE ] [, IDci, IDcr ] --> + * HDR*, HASH(3) + * Installs inbound and outbound IPsec SAs, routing, etc. + * ??? it is legal to have multiple SAs, but we don't support it yet. + */ + { STATE_QUICK_I1, STATE_QUICK_I2 + , SMF_ALL_AUTH | SMF_INITIATOR | SMF_ENCRYPTED | SMF_REPLY + , P(HASH) | P(SA) | P(NONCE), /* P(SA) | */ P(KE) | P(ID) | P(NATOA_RFC), PT(HASH) + , EVENT_SA_REPLACE, quick_inR1_outI2 }, - /* STATE_QUICK_R1: HDR*, HASH(3) --> done - * Installs outbound IPsec SAs, routing, etc. - */ - { STATE_QUICK_R1, STATE_QUICK_R2 - , SMF_ALL_AUTH | SMF_ENCRYPTED - , P(HASH), LEMPTY, PT(NONE) - , EVENT_SA_REPLACE, quick_inI2 }, + /* STATE_QUICK_R1: HDR*, HASH(3) --> done + * Installs outbound IPsec SAs, routing, etc. + */ + { STATE_QUICK_R1, STATE_QUICK_R2 + , SMF_ALL_AUTH | SMF_ENCRYPTED + , P(HASH), LEMPTY, PT(NONE) + , EVENT_SA_REPLACE, quick_inI2 }, - /* STATE_QUICK_I2: can only happen due to lost packet */ - { STATE_QUICK_I2, STATE_UNDEFINED - , SMF_ALL_AUTH | SMF_INITIATOR | SMF_ENCRYPTED | SMF_RETRANSMIT_ON_DUPLICATE - , LEMPTY, LEMPTY, PT(NONE) - , EVENT_NULL, unexpected }, + /* STATE_QUICK_I2: can only happen due to lost packet */ + { STATE_QUICK_I2, STATE_UNDEFINED + , SMF_ALL_AUTH | SMF_INITIATOR | SMF_ENCRYPTED | SMF_RETRANSMIT_ON_DUPLICATE + , LEMPTY, LEMPTY, PT(NONE) + , EVENT_NULL, unexpected }, - /* STATE_QUICK_R2: can only happen due to lost packet */ - { STATE_QUICK_R2, STATE_UNDEFINED - , SMF_ALL_AUTH | SMF_ENCRYPTED - , LEMPTY, LEMPTY, PT(NONE) - , EVENT_NULL, unexpected }, + /* STATE_QUICK_R2: can only happen due to lost packet */ + { STATE_QUICK_R2, STATE_UNDEFINED + , SMF_ALL_AUTH | SMF_ENCRYPTED + , LEMPTY, LEMPTY, PT(NONE) + , EVENT_NULL, unexpected }, - /***** informational messages *****/ + /***** informational messages *****/ - /* STATE_INFO: */ - { STATE_INFO, STATE_UNDEFINED - , SMF_ALL_AUTH - , LEMPTY, LEMPTY, PT(NONE) - , EVENT_NULL, informational }, + /* STATE_INFO: */ + { STATE_INFO, STATE_UNDEFINED + , SMF_ALL_AUTH + , LEMPTY, LEMPTY, PT(NONE) + , EVENT_NULL, informational }, - /* STATE_INFO_PROTECTED: */ - { STATE_INFO_PROTECTED, STATE_UNDEFINED - , SMF_ALL_AUTH | SMF_ENCRYPTED - , P(HASH), LEMPTY, PT(NONE) - , EVENT_NULL, informational }, + /* STATE_INFO_PROTECTED: */ + { STATE_INFO_PROTECTED, STATE_UNDEFINED + , SMF_ALL_AUTH | SMF_ENCRYPTED + , P(HASH), LEMPTY, PT(NONE) + , EVENT_NULL, informational }, - /* XAUTH state transitions */ - { STATE_XAUTH_I0, STATE_XAUTH_I1 - , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY - , P(ATTR) | P(HASH), P(VID), PT(HASH) - , EVENT_RETRANSMIT, xauth_inI0 }, + /* XAUTH state transitions */ + { STATE_XAUTH_I0, STATE_XAUTH_I1 + , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY + , P(ATTR) | P(HASH), P(VID), PT(HASH) + , EVENT_RETRANSMIT, xauth_inI0 }, - { STATE_XAUTH_R1, STATE_XAUTH_R2 - , SMF_ALL_AUTH | SMF_ENCRYPTED - , P(ATTR) | P(HASH), P(VID), PT(HASH) - , EVENT_RETRANSMIT, xauth_inR1 }, + { STATE_XAUTH_R1, STATE_XAUTH_R2 + , SMF_ALL_AUTH | SMF_ENCRYPTED + , P(ATTR) | P(HASH), P(VID), PT(HASH) + , EVENT_RETRANSMIT, xauth_inR1 }, - { STATE_XAUTH_I1, STATE_XAUTH_I2 - , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2 - , P(ATTR) | P(HASH), P(VID), PT(HASH) - , EVENT_SA_REPLACE, xauth_inI1 }, + { STATE_XAUTH_I1, STATE_XAUTH_I2 + , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2 + , P(ATTR) | P(HASH), P(VID), PT(HASH) + , EVENT_SA_REPLACE, xauth_inI1 }, - { STATE_XAUTH_R2, STATE_XAUTH_R3 - , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2 - , P(ATTR) | P(HASH), P(VID), PT(NONE) - , EVENT_SA_REPLACE, xauth_inR2 }, + { STATE_XAUTH_R2, STATE_XAUTH_R3 + , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2 + , P(ATTR) | P(HASH), P(VID), PT(NONE) + , EVENT_SA_REPLACE, xauth_inR2 }, - { STATE_XAUTH_I2, STATE_UNDEFINED - , SMF_ALL_AUTH | SMF_ENCRYPTED - , LEMPTY, LEMPTY, PT(NONE) - , EVENT_NULL, unexpected }, + { STATE_XAUTH_I2, STATE_UNDEFINED + , SMF_ALL_AUTH | SMF_ENCRYPTED + , LEMPTY, LEMPTY, PT(NONE) + , EVENT_NULL, unexpected }, - { STATE_XAUTH_R3, STATE_UNDEFINED - , SMF_ALL_AUTH | SMF_ENCRYPTED - , LEMPTY, LEMPTY, PT(NONE) - , EVENT_NULL, unexpected }, + { STATE_XAUTH_R3, STATE_UNDEFINED + , SMF_ALL_AUTH | SMF_ENCRYPTED + , LEMPTY, LEMPTY, PT(NONE) + , EVENT_NULL, unexpected }, - /* ModeCfg pull mode state transitions */ + /* ModeCfg pull mode state transitions */ - { STATE_MODE_CFG_R0, STATE_MODE_CFG_R1 - , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2 - , P(ATTR) | P(HASH), P(VID), PT(HASH) - , EVENT_SA_REPLACE, modecfg_inR0 }, + { STATE_MODE_CFG_R0, STATE_MODE_CFG_R1 + , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2 + , P(ATTR) | P(HASH), P(VID), PT(HASH) + , EVENT_SA_REPLACE, modecfg_inR0 }, - { STATE_MODE_CFG_I1, STATE_MODE_CFG_I2 - , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2 - , P(ATTR) | P(HASH), P(VID), PT(HASH) - , EVENT_SA_REPLACE, modecfg_inI1 }, + { STATE_MODE_CFG_I1, STATE_MODE_CFG_I2 + , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2 + , P(ATTR) | P(HASH), P(VID), PT(HASH) + , EVENT_SA_REPLACE, modecfg_inI1 }, - { STATE_MODE_CFG_R1, STATE_UNDEFINED - , SMF_ALL_AUTH | SMF_ENCRYPTED - , LEMPTY, LEMPTY, PT(NONE) - , EVENT_NULL, unexpected }, + { STATE_MODE_CFG_R1, STATE_UNDEFINED + , SMF_ALL_AUTH | SMF_ENCRYPTED + , LEMPTY, LEMPTY, PT(NONE) + , EVENT_NULL, unexpected }, - { STATE_MODE_CFG_I2, STATE_UNDEFINED - , SMF_ALL_AUTH | SMF_ENCRYPTED - , LEMPTY, LEMPTY, PT(NONE) - , EVENT_NULL, unexpected }, + { STATE_MODE_CFG_I2, STATE_UNDEFINED + , SMF_ALL_AUTH | SMF_ENCRYPTED + , LEMPTY, LEMPTY, PT(NONE) + , EVENT_NULL, unexpected }, /* ModeCfg push mode state transitions */ - { STATE_MODE_CFG_I0, STATE_MODE_CFG_I3 - , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2 - , P(ATTR) | P(HASH), P(VID), PT(HASH) - , EVENT_SA_REPLACE, modecfg_inI0 }, + { STATE_MODE_CFG_I0, STATE_MODE_CFG_I3 + , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2 + , P(ATTR) | P(HASH), P(VID), PT(HASH) + , EVENT_SA_REPLACE, modecfg_inI0 }, - { STATE_MODE_CFG_R3, STATE_MODE_CFG_R4 - , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2 - , P(ATTR) | P(HASH), P(VID), PT(HASH) - , EVENT_SA_REPLACE, modecfg_inR3 }, + { STATE_MODE_CFG_R3, STATE_MODE_CFG_R4 + , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2 + , P(ATTR) | P(HASH), P(VID), PT(HASH) + , EVENT_SA_REPLACE, modecfg_inR3 }, - { STATE_MODE_CFG_I3, STATE_UNDEFINED - , SMF_ALL_AUTH | SMF_ENCRYPTED - , LEMPTY, LEMPTY, PT(NONE) - , EVENT_NULL, unexpected }, + { STATE_MODE_CFG_I3, STATE_UNDEFINED + , SMF_ALL_AUTH | SMF_ENCRYPTED + , LEMPTY, LEMPTY, PT(NONE) + , EVENT_NULL, unexpected }, - { STATE_MODE_CFG_R4, STATE_UNDEFINED - , SMF_ALL_AUTH | SMF_ENCRYPTED - , LEMPTY, LEMPTY, PT(NONE) - , EVENT_NULL, unexpected }, + { STATE_MODE_CFG_R4, STATE_UNDEFINED + , SMF_ALL_AUTH | SMF_ENCRYPTED + , LEMPTY, LEMPTY, PT(NONE) + , EVENT_NULL, unexpected }, #undef P #undef PT @@ -518,23 +518,23 @@ static const struct state_microcode state_microcode_table[] = { void init_demux(void) { - /* fill ike_microcode_index: - * make ike_microcode_index[s] point to first entry in - * state_microcode_table for state s (backward scan makes this easier). - * Check that table is in order -- catch coding errors. - * For what it's worth, this routine is idempotent. - */ - const struct state_microcode *t; + /* fill ike_microcode_index: + * make ike_microcode_index[s] point to first entry in + * state_microcode_table for state s (backward scan makes this easier). + * Check that table is in order -- catch coding errors. + * For what it's worth, this routine is idempotent. + */ + const struct state_microcode *t; - for (t = &state_microcode_table[countof(state_microcode_table) - 1];;) - { - passert(STATE_IKE_FLOOR <= t->state && t->state < STATE_IKE_ROOF); - ike_microcode_index[t->state - STATE_IKE_FLOOR] = t; - if (t == state_microcode_table) - break; - t--; - passert(t[0].state <= t[1].state); - } + for (t = &state_microcode_table[countof(state_microcode_table) - 1];;) + { + passert(STATE_IKE_FLOOR <= t->state && t->state < STATE_IKE_ROOF); + ike_microcode_index[t->state - STATE_IKE_FLOOR] = t; + if (t == state_microcode_table) + break; + t--; + passert(t[0].state <= t[1].state); + } } /* Process any message on the MSG_ERRQUEUE @@ -586,357 +586,357 @@ init_demux(void) static bool check_msg_errqueue(const struct iface *ifp, short interest) { - struct pollfd pfd; + struct pollfd pfd; - pfd.fd = ifp->fd; - pfd.events = interest | POLLPRI | POLLOUT; + pfd.fd = ifp->fd; + pfd.events = interest | POLLPRI | POLLOUT; - while (pfd.revents = 0 - , poll(&pfd, 1, -1) > 0 && (pfd.revents & POLLERR)) - { - u_int8_t buffer[3000]; /* hope that this is big enough */ - union + while (pfd.revents = 0 + , poll(&pfd, 1, -1) > 0 && (pfd.revents & POLLERR)) { - struct sockaddr sa; - struct sockaddr_in sa_in4; - struct sockaddr_in6 sa_in6; - } from; - - int from_len = sizeof(from); - - int packet_len; - - struct msghdr emh; - struct iovec eiov; - union { - /* force alignment (not documented as necessary) */ - struct cmsghdr ecms; - - /* how much space is enough? */ - unsigned char space[256]; - } ecms_buf; - - struct cmsghdr *cm; - char fromstr[sizeof(" for message to port 65536") + INET6_ADDRSTRLEN]; - struct state *sender = NULL; - - zero(&from.sa); - from_len = sizeof(from); - - emh.msg_name = &from.sa; /* ??? filled in? */ - emh.msg_namelen = sizeof(from); - emh.msg_iov = &eiov; - emh.msg_iovlen = 1; - emh.msg_control = &ecms_buf; - emh.msg_controllen = sizeof(ecms_buf); - emh.msg_flags = 0; - - eiov.iov_base = buffer; /* see readv(2) */ - eiov.iov_len = sizeof(buffer); - - packet_len = recvmsg(ifp->fd, &emh, MSG_ERRQUEUE); - - if (packet_len == -1) - { - log_errno((e, "recvmsg(,, MSG_ERRQUEUE) on %s failed in comm_handle" - , ifp->rname)); - break; - } - else if (packet_len == sizeof(buffer)) - { - plog("MSG_ERRQUEUE message longer than %lu bytes; truncated" - , (unsigned long) sizeof(buffer)); - } - else - { - sender = find_sender((size_t) packet_len, buffer); - } - - DBG_cond_dump(DBG_ALL, "rejected packet:\n", buffer, packet_len); - DBG_cond_dump(DBG_ALL, "control:\n", emh.msg_control, emh.msg_controllen); - /* ??? Andi Kleen and misc documentation - * suggests that name will have the original destination - * of the packet. We seem to see msg_namelen == 0. - * Andi says that this is a kernel bug and has fixed it. - * Perhaps in 2.2.18/2.4.0. - */ - passert(emh.msg_name == &from.sa); - DBG_cond_dump(DBG_ALL, "name:\n", emh.msg_name - , emh.msg_namelen); - - fromstr[0] = '\0'; /* usual case :-( */ - switch (from.sa.sa_family) - { - char as[INET6_ADDRSTRLEN]; - - case AF_INET: - if (emh.msg_namelen == sizeof(struct sockaddr_in)) - snprintf(fromstr, sizeof(fromstr) - , " for message to %s port %u" - , inet_ntop(from.sa.sa_family - , &from.sa_in4.sin_addr, as, sizeof(as)) - , ntohs(from.sa_in4.sin_port)); - break; - case AF_INET6: - if (emh.msg_namelen == sizeof(struct sockaddr_in6)) - snprintf(fromstr, sizeof(fromstr) - , " for message to %s port %u" - , inet_ntop(from.sa.sa_family - , &from.sa_in6.sin6_addr, as, sizeof(as)) - , ntohs(from.sa_in6.sin6_port)); - break; - } - - for (cm = CMSG_FIRSTHDR(&emh) - ; cm != NULL - ; cm = CMSG_NXTHDR(&emh,cm)) - { - if (cm->cmsg_level == SOL_IP - && cm->cmsg_type == IP_RECVERR) - { - /* ip(7) and recvmsg(2) specify: - * ee_origin is SO_EE_ORIGIN_ICMP for ICMP - * or SO_EE_ORIGIN_LOCAL for locally generated errors. - * ee_type and ee_code are from the ICMP header. - * ee_info is the discovered MTU for EMSGSIZE errors - * ee_data is not used. - * - * ??? recvmsg(2) says "SOCK_EE_OFFENDER" but - * means "SO_EE_OFFENDER". The OFFENDER is really - * the router that complained. As such, the port - * is meaningless. - */ - - /* ??? cmsg(3) claims that CMSG_DATA returns - * void *, but RFC 2292 and /usr/include/bits/socket.h - * say unsigned char *. The manual is being fixed. - */ - struct sock_extended_err *ee = (void *)CMSG_DATA(cm); - const char *offstr = "unspecified"; - char offstrspace[INET6_ADDRSTRLEN]; - char orname[50]; - - if (cm->cmsg_len > CMSG_LEN(sizeof(struct sock_extended_err))) + u_int8_t buffer[3000]; /* hope that this is big enough */ + union { - const struct sockaddr *offender = SO_EE_OFFENDER(ee); + struct sockaddr sa; + struct sockaddr_in sa_in4; + struct sockaddr_in6 sa_in6; + } from; - switch (offender->sa_family) - { - case AF_INET: - offstr = inet_ntop(offender->sa_family - , &((const struct sockaddr_in *)offender)->sin_addr - , offstrspace, sizeof(offstrspace)); + int from_len = sizeof(from); + + int packet_len; + + struct msghdr emh; + struct iovec eiov; + union { + /* force alignment (not documented as necessary) */ + struct cmsghdr ecms; + + /* how much space is enough? */ + unsigned char space[256]; + } ecms_buf; + + struct cmsghdr *cm; + char fromstr[sizeof(" for message to port 65536") + INET6_ADDRSTRLEN]; + struct state *sender = NULL; + + zero(&from.sa); + from_len = sizeof(from); + + emh.msg_name = &from.sa; /* ??? filled in? */ + emh.msg_namelen = sizeof(from); + emh.msg_iov = &eiov; + emh.msg_iovlen = 1; + emh.msg_control = &ecms_buf; + emh.msg_controllen = sizeof(ecms_buf); + emh.msg_flags = 0; + + eiov.iov_base = buffer; /* see readv(2) */ + eiov.iov_len = sizeof(buffer); + + packet_len = recvmsg(ifp->fd, &emh, MSG_ERRQUEUE); + + if (packet_len == -1) + { + log_errno((e, "recvmsg(,, MSG_ERRQUEUE) on %s failed in comm_handle" + , ifp->rname)); break; - case AF_INET6: - offstr = inet_ntop(offender->sa_family - , &((const struct sockaddr_in6 *)offender)->sin6_addr - , offstrspace, sizeof(offstrspace)); - break; - default: - offstr = "unknown"; - break; - } + } + else if (packet_len == sizeof(buffer)) + { + plog("MSG_ERRQUEUE message longer than %lu bytes; truncated" + , (unsigned long) sizeof(buffer)); + } + else + { + sender = find_sender((size_t) packet_len, buffer); } - switch (ee->ee_origin) + DBG_cond_dump(DBG_ALL, "rejected packet:\n", buffer, packet_len); + DBG_cond_dump(DBG_ALL, "control:\n", emh.msg_control, emh.msg_controllen); + /* ??? Andi Kleen and misc documentation + * suggests that name will have the original destination + * of the packet. We seem to see msg_namelen == 0. + * Andi says that this is a kernel bug and has fixed it. + * Perhaps in 2.2.18/2.4.0. + */ + passert(emh.msg_name == &from.sa); + DBG_cond_dump(DBG_ALL, "name:\n", emh.msg_name + , emh.msg_namelen); + + fromstr[0] = '\0'; /* usual case :-( */ + switch (from.sa.sa_family) { - case SO_EE_ORIGIN_NONE: - snprintf(orname, sizeof(orname), "none"); - break; - case SO_EE_ORIGIN_LOCAL: - snprintf(orname, sizeof(orname), "local"); - break; - case SO_EE_ORIGIN_ICMP: - snprintf(orname, sizeof(orname) - , "ICMP type %d code %d (not authenticated)" - , ee->ee_type, ee->ee_code - ); - break; - case SO_EE_ORIGIN_ICMP6: - snprintf(orname, sizeof(orname) - , "ICMP6 type %d code %d (not authenticated)" - , ee->ee_type, ee->ee_code - ); - break; - default: - snprintf(orname, sizeof(orname), "invalid origin %lu" - , (unsigned long) ee->ee_origin); - break; + char as[INET6_ADDRSTRLEN]; + + case AF_INET: + if (emh.msg_namelen == sizeof(struct sockaddr_in)) + snprintf(fromstr, sizeof(fromstr) + , " for message to %s port %u" + , inet_ntop(from.sa.sa_family + , &from.sa_in4.sin_addr, as, sizeof(as)) + , ntohs(from.sa_in4.sin_port)); + break; + case AF_INET6: + if (emh.msg_namelen == sizeof(struct sockaddr_in6)) + snprintf(fromstr, sizeof(fromstr) + , " for message to %s port %u" + , inet_ntop(from.sa.sa_family + , &from.sa_in6.sin6_addr, as, sizeof(as)) + , ntohs(from.sa_in6.sin6_port)); + break; } + for (cm = CMSG_FIRSTHDR(&emh) + ; cm != NULL + ; cm = CMSG_NXTHDR(&emh,cm)) { - struct state *old_state = cur_state; + if (cm->cmsg_level == SOL_IP + && cm->cmsg_type == IP_RECVERR) + { + /* ip(7) and recvmsg(2) specify: + * ee_origin is SO_EE_ORIGIN_ICMP for ICMP + * or SO_EE_ORIGIN_LOCAL for locally generated errors. + * ee_type and ee_code are from the ICMP header. + * ee_info is the discovered MTU for EMSGSIZE errors + * ee_data is not used. + * + * ??? recvmsg(2) says "SOCK_EE_OFFENDER" but + * means "SO_EE_OFFENDER". The OFFENDER is really + * the router that complained. As such, the port + * is meaningless. + */ - cur_state = sender; + /* ??? cmsg(3) claims that CMSG_DATA returns + * void *, but RFC 2292 and /usr/include/bits/socket.h + * say unsigned char *. The manual is being fixed. + */ + struct sock_extended_err *ee = (void *)CMSG_DATA(cm); + const char *offstr = "unspecified"; + char offstrspace[INET6_ADDRSTRLEN]; + char orname[50]; - /* note dirty trick to suppress ~ at start of format - * if we know what state to blame. - */ - if ((packet_len == 1) && (buffer[0] = 0xff) + if (cm->cmsg_len > CMSG_LEN(sizeof(struct sock_extended_err))) + { + const struct sockaddr *offender = SO_EE_OFFENDER(ee); + + switch (offender->sa_family) + { + case AF_INET: + offstr = inet_ntop(offender->sa_family + , &((const struct sockaddr_in *)offender)->sin_addr + , offstrspace, sizeof(offstrspace)); + break; + case AF_INET6: + offstr = inet_ntop(offender->sa_family + , &((const struct sockaddr_in6 *)offender)->sin6_addr + , offstrspace, sizeof(offstrspace)); + break; + default: + offstr = "unknown"; + break; + } + } + + switch (ee->ee_origin) + { + case SO_EE_ORIGIN_NONE: + snprintf(orname, sizeof(orname), "none"); + break; + case SO_EE_ORIGIN_LOCAL: + snprintf(orname, sizeof(orname), "local"); + break; + case SO_EE_ORIGIN_ICMP: + snprintf(orname, sizeof(orname) + , "ICMP type %d code %d (not authenticated)" + , ee->ee_type, ee->ee_code + ); + break; + case SO_EE_ORIGIN_ICMP6: + snprintf(orname, sizeof(orname) + , "ICMP6 type %d code %d (not authenticated)" + , ee->ee_type, ee->ee_code + ); + break; + default: + snprintf(orname, sizeof(orname), "invalid origin %lu" + , (unsigned long) ee->ee_origin); + break; + } + + { + struct state *old_state = cur_state; + + cur_state = sender; + + /* note dirty trick to suppress ~ at start of format + * if we know what state to blame. + */ + if ((packet_len == 1) && (buffer[0] = 0xff) #ifdef DEBUG - && ((cur_debugging & DBG_NATT) == 0) + && ((cur_debugging & DBG_NATT) == 0) #endif - ) { - /* don't log NAT-T keepalive related errors unless NATT debug is - * enabled - */ - } - else - plog((sender != NULL) + "~" - "ERROR: asynchronous network error report on %s" - "%s" - ", complainant %s" - ": %s" - " [errno %lu, origin %s" - /* ", pad %d, info %ld" */ - /* ", data %ld" */ - "]" - , ifp->rname - , fromstr - , offstr - , strerror(ee->ee_errno) - , (unsigned long) ee->ee_errno - , orname - /* , ee->ee_pad, (unsigned long)ee->ee_info */ - /* , (unsigned long)ee->ee_data */ - ); - cur_state = old_state; + ) { + /* don't log NAT-T keepalive related errors unless NATT debug is + * enabled + */ + } + else + plog((sender != NULL) + "~" + "ERROR: asynchronous network error report on %s" + "%s" + ", complainant %s" + ": %s" + " [errno %lu, origin %s" + /* ", pad %d, info %ld" */ + /* ", data %ld" */ + "]" + , ifp->rname + , fromstr + , offstr + , strerror(ee->ee_errno) + , (unsigned long) ee->ee_errno + , orname + /* , ee->ee_pad, (unsigned long)ee->ee_info */ + /* , (unsigned long)ee->ee_data */ + ); + cur_state = old_state; + } + } + else + { + /* .cmsg_len is a kernel_size_t(!), but the value + * certainly ought to fit in an unsigned long. + */ + plog("unknown cmsg: level %d, type %d, len %lu" + , cm->cmsg_level, cm->cmsg_type + , (unsigned long) cm->cmsg_len); + } } - } - else - { - /* .cmsg_len is a kernel_size_t(!), but the value - * certainly ought to fit in an unsigned long. - */ - plog("unknown cmsg: level %d, type %d, len %lu" - , cm->cmsg_level, cm->cmsg_type - , (unsigned long) cm->cmsg_len); - } } - } - return (pfd.revents & interest) != 0; + return (pfd.revents & interest) != 0; } #endif /* defined(IP_RECVERR) && defined(MSG_ERRQUEUE) */ bool send_packet(struct state *st, const char *where) { - struct connection *c = st->st_connection; - int port_buf; - bool err; - u_int8_t ike_pkt[MAX_OUTPUT_UDP_SIZE]; - u_int8_t *ptr; - unsigned long len; + struct connection *c = st->st_connection; + int port_buf; + bool err; + u_int8_t ike_pkt[MAX_OUTPUT_UDP_SIZE]; + u_int8_t *ptr; + unsigned long len; - if (c->interface->ike_float && st->st_tpacket.len != 1) - { - if ((unsigned long) st->st_tpacket.len > (MAX_OUTPUT_UDP_SIZE-sizeof(u_int32_t))) + if (c->interface->ike_float && st->st_tpacket.len != 1) { - DBG_log("send_packet(): really too big"); - return FALSE; + if ((unsigned long) st->st_tpacket.len > (MAX_OUTPUT_UDP_SIZE-sizeof(u_int32_t))) + { + DBG_log("send_packet(): really too big"); + return FALSE; + } + ptr = ike_pkt; + /** Add Non-ESP marker **/ + memset(ike_pkt, 0, sizeof(u_int32_t)); + memcpy(ike_pkt + sizeof(u_int32_t), st->st_tpacket.ptr, + (unsigned long)st->st_tpacket.len); + len = (unsigned long) st->st_tpacket.len + sizeof(u_int32_t); } - ptr = ike_pkt; - /** Add Non-ESP marker **/ - memset(ike_pkt, 0, sizeof(u_int32_t)); - memcpy(ike_pkt + sizeof(u_int32_t), st->st_tpacket.ptr, - (unsigned long)st->st_tpacket.len); - len = (unsigned long) st->st_tpacket.len + sizeof(u_int32_t); - } - else - { - ptr = st->st_tpacket.ptr; - len = (unsigned long) st->st_tpacket.len; - } - - DBG(DBG_RAW, + else { - DBG_log("sending %lu bytes for %s through %s to %s:%u:" - , (unsigned long) st->st_tpacket.len - , where - , c->interface->rname - , ip_str(&c->spd.that.host_addr) - , (unsigned)c->spd.that.host_port); - DBG_dump_chunk(NULL, st->st_tpacket); - }); + ptr = st->st_tpacket.ptr; + len = (unsigned long) st->st_tpacket.len; + } - /* XXX: Not very clean. We manipulate the port of the ip_address to - * have a port in the sockaddr*, but we retain the original port - * and restore it afterwards. - */ + DBG(DBG_RAW, + { + DBG_log("sending %lu bytes for %s through %s to %s:%u:" + , (unsigned long) st->st_tpacket.len + , where + , c->interface->rname + , ip_str(&c->spd.that.host_addr) + , (unsigned)c->spd.that.host_port); + DBG_dump_chunk(NULL, st->st_tpacket); + }); - port_buf = portof(&c->spd.that.host_addr); - setportof(htons(c->spd.that.host_port), &c->spd.that.host_addr); + /* XXX: Not very clean. We manipulate the port of the ip_address to + * have a port in the sockaddr*, but we retain the original port + * and restore it afterwards. + */ + + port_buf = portof(&c->spd.that.host_addr); + setportof(htons(c->spd.that.host_port), &c->spd.that.host_addr); #if defined(IP_RECVERR) && defined(MSG_ERRQUEUE) - (void) check_msg_errqueue(c->interface, POLLOUT); + (void) check_msg_errqueue(c->interface, POLLOUT); #endif /* defined(IP_RECVERR) && defined(MSG_ERRQUEUE) */ - err = sendto(c->interface->fd - , ptr, len, 0 - , sockaddrof(&c->spd.that.host_addr) - , sockaddrlenof(&c->spd.that.host_addr)) != (ssize_t)len; + err = sendto(c->interface->fd + , ptr, len, 0 + , sockaddrof(&c->spd.that.host_addr) + , sockaddrlenof(&c->spd.that.host_addr)) != (ssize_t)len; - /* restore port */ - setportof(port_buf, &c->spd.that.host_addr); + /* restore port */ + setportof(port_buf, &c->spd.that.host_addr); - if (err) - { - /* do not log NAT-T Keep Alive packets */ - if (streq(where, "NAT-T Keep Alive")) - return FALSE; - log_errno((e, "sendto on %s to %s:%u failed in %s" - , c->interface->rname - , ip_str(&c->spd.that.host_addr) - , (unsigned)c->spd.that.host_port - , where)); - return FALSE; - } - else - { - return TRUE; - } + if (err) + { + /* do not log NAT-T Keep Alive packets */ + if (streq(where, "NAT-T Keep Alive")) + return FALSE; + log_errno((e, "sendto on %s to %s:%u failed in %s" + , c->interface->rname + , ip_str(&c->spd.that.host_addr) + , (unsigned)c->spd.that.host_port + , where)); + return FALSE; + } + else + { + return TRUE; + } } static stf_status unexpected(struct msg_digest *md) { - loglog(RC_LOG_SERIOUS, "unexpected message received in state %s" - , enum_name(&state_names, md->st->st_state)); - return STF_IGNORE; + loglog(RC_LOG_SERIOUS, "unexpected message received in state %s" + , enum_name(&state_names, md->st->st_state)); + return STF_IGNORE; } static stf_status informational(struct msg_digest *md UNUSED) { - struct payload_digest *const n_pld = md->chain[ISAKMP_NEXT_N]; + struct payload_digest *const n_pld = md->chain[ISAKMP_NEXT_N]; - /* If the Notification Payload is not null... */ - if (n_pld != NULL) - { - pb_stream *const n_pbs = &n_pld->pbs; - struct isakmp_notification *const n = &n_pld->payload.notification; - int disp_len; - char disp_buf[200]; + /* If the Notification Payload is not null... */ + if (n_pld != NULL) + { + pb_stream *const n_pbs = &n_pld->pbs; + struct isakmp_notification *const n = &n_pld->payload.notification; + int disp_len; + char disp_buf[200]; - /* Switch on Notification Type (enum) */ - switch (n->isan_type) - { - case R_U_THERE: - return dpd_inI_outR(md->st, n, n_pbs); + /* Switch on Notification Type (enum) */ + switch (n->isan_type) + { + case R_U_THERE: + return dpd_inI_outR(md->st, n, n_pbs); - case R_U_THERE_ACK: - return dpd_inR(md->st, n, n_pbs); - default: - if (pbs_left(n_pbs) >= sizeof(disp_buf)-1) - disp_len = sizeof(disp_buf)-1; - else - disp_len = pbs_left(n_pbs); - memcpy(disp_buf, n_pbs->cur, disp_len); - disp_buf[disp_len] = '\0'; - break; - } - } - return STF_IGNORE; + case R_U_THERE_ACK: + return dpd_inR(md->st, n, n_pbs); + default: + if (pbs_left(n_pbs) >= sizeof(disp_buf)-1) + disp_len = sizeof(disp_buf)-1; + else + disp_len = pbs_left(n_pbs); + memcpy(disp_buf, n_pbs->cur, disp_len); + disp_buf[disp_len] = '\0'; + break; + } + } + return STF_IGNORE; } /* message digest allocation and deallocation */ @@ -947,57 +947,57 @@ static struct msg_digest *md_pool = NULL; void free_md_pool(void) { - for (;;) - { - struct msg_digest *md = md_pool; + for (;;) + { + struct msg_digest *md = md_pool; - if (md == NULL) - break; - md_pool = md->next; - free(md); - } + if (md == NULL) + break; + md_pool = md->next; + free(md); + } } static struct msg_digest * malloc_md(void) { - struct msg_digest *md = md_pool; + struct msg_digest *md = md_pool; - /* convenient initializer: - * - all pointers NULL - * - .note = NOTHING_WRONG - * - .encrypted = FALSE - */ - static const struct msg_digest blank_md; + /* convenient initializer: + * - all pointers NULL + * - .note = NOTHING_WRONG + * - .encrypted = FALSE + */ + static const struct msg_digest blank_md; - if (md == NULL) - { - md = malloc_thing(struct msg_digest); - zero(md); - } - else - md_pool = md->next; + if (md == NULL) + { + md = malloc_thing(struct msg_digest); + zero(md); + } + else + md_pool = md->next; - *md = blank_md; - md->digest_roof = md->digest; + *md = blank_md; + md->digest_roof = md->digest; - /* note: although there may be multiple msg_digests at once - * (due to suspended state transitions), there is a single - * global reply_buffer. It will need to be saved and restored. - */ - init_pbs(&md->reply, reply_buffer, sizeof(reply_buffer), "reply packet"); + /* note: although there may be multiple msg_digests at once + * (due to suspended state transitions), there is a single + * global reply_buffer. It will need to be saved and restored. + */ + init_pbs(&md->reply, reply_buffer, sizeof(reply_buffer), "reply packet"); - return md; + return md; } void release_md(struct msg_digest *md) { - chunk_free(&md->raw_packet); - free(md->packet_pbs.start); - md->packet_pbs.start = NULL; - md->next = md_pool; - md_pool = md; + chunk_free(&md->raw_packet); + free(md->packet_pbs.start); + md->packet_pbs.start = NULL; + md->next = md_pool; + md_pool = md; } /* wrapper for read_packet and process_packet @@ -1016,35 +1016,35 @@ release_md(struct msg_digest *md) void comm_handle(const struct iface *ifp) { - static struct msg_digest *md; + static struct msg_digest *md; #if defined(IP_RECVERR) && defined(MSG_ERRQUEUE) - /* Even though select(2) says that there is a message, - * it might only be a MSG_ERRQUEUE message. At least - * sometimes that leads to a hanging recvfrom. To avoid - * what appears to be a kernel bug, check_msg_errqueue - * uses poll(2) and tells us if there is anything for us - * to read. - * - * This is early enough that teardown isn't required: - * just return on failure. - */ - if (!check_msg_errqueue(ifp, POLLIN)) - return; /* no normal message to read */ + /* Even though select(2) says that there is a message, + * it might only be a MSG_ERRQUEUE message. At least + * sometimes that leads to a hanging recvfrom. To avoid + * what appears to be a kernel bug, check_msg_errqueue + * uses poll(2) and tells us if there is anything for us + * to read. + * + * This is early enough that teardown isn't required: + * just return on failure. + */ + if (!check_msg_errqueue(ifp, POLLIN)) + return; /* no normal message to read */ #endif /* defined(IP_RECVERR) && defined(MSG_ERRQUEUE) */ - md = malloc_md(); - md->iface = ifp; + md = malloc_md(); + md->iface = ifp; - if (read_packet(md)) - process_packet(&md); + if (read_packet(md)) + process_packet(&md); - if (md != NULL) - release_md(md); + if (md != NULL) + release_md(md); - cur_state = NULL; - reset_cur_connection(); - cur_from = NULL; + cur_state = NULL; + reset_cur_connection(); + cur_from = NULL; } /* read the message. @@ -1055,177 +1055,177 @@ comm_handle(const struct iface *ifp) static bool read_packet(struct msg_digest *md) { - const struct iface *ifp = md->iface; - int packet_len; - u_int8_t *buffer; - u_int8_t *buffer_nat; - union - { - struct sockaddr sa; - struct sockaddr_in sa_in4; - struct sockaddr_in6 sa_in6; - } from; - int from_len = sizeof(from); - err_t from_ugh = NULL; - static const char undisclosed[] = "unknown source"; - - happy(anyaddr(addrtypeof(&ifp->addr), &md->sender)); - zero(&from.sa); - ioctl(ifp->fd, FIONREAD, &packet_len); - buffer = malloc(packet_len); - packet_len = recvfrom(ifp->fd, buffer, packet_len, 0 - , &from.sa, &from_len); - - /* First: digest the from address. - * We presume that nothing here disturbs errno. - */ - if (packet_len == -1 - && from_len == sizeof(from) - && all_zero((const void *)&from.sa, sizeof(from))) - { - /* "from" is untouched -- not set by recvfrom */ - from_ugh = undisclosed; - } - else if (from_len - < (int) (offsetof(struct sockaddr, sa_family) + sizeof(from.sa.sa_family))) - { - from_ugh = "truncated"; - } - else - { - const struct af_info *afi = aftoinfo(from.sa.sa_family); - - if (afi == NULL) + const struct iface *ifp = md->iface; + int packet_len; + u_int8_t *buffer; + u_int8_t *buffer_nat; + union { - from_ugh = "unexpected Address Family"; + struct sockaddr sa; + struct sockaddr_in sa_in4; + struct sockaddr_in6 sa_in6; + } from; + int from_len = sizeof(from); + err_t from_ugh = NULL; + static const char undisclosed[] = "unknown source"; + + happy(anyaddr(addrtypeof(&ifp->addr), &md->sender)); + zero(&from.sa); + ioctl(ifp->fd, FIONREAD, &packet_len); + buffer = malloc(packet_len); + packet_len = recvfrom(ifp->fd, buffer, packet_len, 0 + , &from.sa, &from_len); + + /* First: digest the from address. + * We presume that nothing here disturbs errno. + */ + if (packet_len == -1 + && from_len == sizeof(from) + && all_zero((const void *)&from.sa, sizeof(from))) + { + /* "from" is untouched -- not set by recvfrom */ + from_ugh = undisclosed; } - else if (from_len != (int)afi->sa_sz) + else if (from_len + < (int) (offsetof(struct sockaddr, sa_family) + sizeof(from.sa.sa_family))) { - from_ugh = "wrong length"; + from_ugh = "truncated"; } else { - switch (from.sa.sa_family) - { - case AF_INET: - from_ugh = initaddr((void *) &from.sa_in4.sin_addr - , sizeof(from.sa_in4.sin_addr), AF_INET, &md->sender); - md->sender_port = ntohs(from.sa_in4.sin_port); - break; - case AF_INET6: - from_ugh = initaddr((void *) &from.sa_in6.sin6_addr - , sizeof(from.sa_in6.sin6_addr), AF_INET6, &md->sender); - md->sender_port = ntohs(from.sa_in6.sin6_port); - break; - } - } - } + const struct af_info *afi = aftoinfo(from.sa.sa_family); - /* now we report any actual I/O error */ - if (packet_len == -1) - { - if (from_ugh == undisclosed - && errno == ECONNREFUSED) + if (afi == NULL) + { + from_ugh = "unexpected Address Family"; + } + else if (from_len != (int)afi->sa_sz) + { + from_ugh = "wrong length"; + } + else + { + switch (from.sa.sa_family) + { + case AF_INET: + from_ugh = initaddr((void *) &from.sa_in4.sin_addr + , sizeof(from.sa_in4.sin_addr), AF_INET, &md->sender); + md->sender_port = ntohs(from.sa_in4.sin_port); + break; + case AF_INET6: + from_ugh = initaddr((void *) &from.sa_in6.sin6_addr + , sizeof(from.sa_in6.sin6_addr), AF_INET6, &md->sender); + md->sender_port = ntohs(from.sa_in6.sin6_port); + break; + } + } + } + + /* now we report any actual I/O error */ + if (packet_len == -1) { - /* Tone down scary message for vague event: - * We get "connection refused" in response to some - * datagram we sent, but we cannot tell which one. - */ - plog("some IKE message we sent has been rejected with ECONNREFUSED (kernel supplied no details)"); + if (from_ugh == undisclosed + && errno == ECONNREFUSED) + { + /* Tone down scary message for vague event: + * We get "connection refused" in response to some + * datagram we sent, but we cannot tell which one. + */ + plog("some IKE message we sent has been rejected with ECONNREFUSED (kernel supplied no details)"); + } + else if (from_ugh != NULL) + { + log_errno((e, "recvfrom on %s failed; Pluto cannot decode source sockaddr in rejection: %s" + , ifp->rname, from_ugh)); + } + else + { + log_errno((e, "recvfrom on %s from %s:%u failed" + , ifp->rname + , ip_str(&md->sender), (unsigned)md->sender_port)); + } + + return FALSE; } else if (from_ugh != NULL) { - log_errno((e, "recvfrom on %s failed; Pluto cannot decode source sockaddr in rejection: %s" - , ifp->rname, from_ugh)); + plog("recvfrom on %s returned misformed source sockaddr: %s" + , ifp->rname, from_ugh); + return FALSE; } - else + cur_from = &md->sender; + cur_from_port = md->sender_port; + + if (ifp->ike_float == TRUE) { - log_errno((e, "recvfrom on %s from %s:%u failed" - , ifp->rname - , ip_str(&md->sender), (unsigned)md->sender_port)); + u_int32_t non_esp; + + if (packet_len < (int)sizeof(u_int32_t)) + { + plog("recvfrom %s:%u too small packet (%d)" + , ip_str(cur_from), (unsigned) cur_from_port, packet_len); + return FALSE; + } + memcpy(&non_esp, buffer, sizeof(u_int32_t)); + if (non_esp != 0) + { + plog("recvfrom %s:%u has no Non-ESP marker" + , ip_str(cur_from), (unsigned) cur_from_port); + return FALSE; + } + packet_len -= sizeof(u_int32_t); + buffer_nat = malloc(packet_len); + memcpy(buffer_nat, buffer + sizeof(u_int32_t), packet_len); + free(buffer); + buffer = buffer_nat; } - return FALSE; - } - else if (from_ugh != NULL) - { - plog("recvfrom on %s returned misformed source sockaddr: %s" - , ifp->rname, from_ugh); - return FALSE; - } - cur_from = &md->sender; - cur_from_port = md->sender_port; + /* Clone actual message contents + * and set up md->packet_pbs to describe it. + */ + init_pbs(&md->packet_pbs, buffer, packet_len, "packet"); - if (ifp->ike_float == TRUE) - { - u_int32_t non_esp; + DBG(DBG_RAW | DBG_CRYPT | DBG_PARSING | DBG_CONTROL, + { + DBG_log(BLANK_FORMAT); + DBG_log("*received %d bytes from %s:%u on %s" + , (int) pbs_room(&md->packet_pbs) + , ip_str(cur_from), (unsigned) cur_from_port + , ifp->rname); + }); - if (packet_len < (int)sizeof(u_int32_t)) + DBG(DBG_RAW, + DBG_dump("", md->packet_pbs.start, pbs_room(&md->packet_pbs))); + + if ((pbs_room(&md->packet_pbs)==1) && (md->packet_pbs.start[0]==0xff)) + { + /** + * NAT-T Keep-alive packets should be discarded by kernel ESPinUDP + * layer. But bogus keep-alive packets (sent with a non-esp marker) + * can reach this point. Complain and discard them. + */ + DBG(DBG_NATT, + DBG_log("NAT-T keep-alive (bogus ?) should not reach this point. " + "Ignored. Sender: %s:%u", ip_str(cur_from), + (unsigned) cur_from_port); + ) + return FALSE; + } + +#define IKEV2_VERSION_OFFSET 17 +#define IKEV2_VERSION 0x20 + + /* ignore IKEv2 packets - they will be handled by charon */ + if (pbs_room(&md->packet_pbs) > IKEV2_VERSION_OFFSET + && md->packet_pbs.start[IKEV2_VERSION_OFFSET] == IKEV2_VERSION) { - plog("recvfrom %s:%u too small packet (%d)" - , ip_str(cur_from), (unsigned) cur_from_port, packet_len); - return FALSE; - } - memcpy(&non_esp, buffer, sizeof(u_int32_t)); - if (non_esp != 0) - { - plog("recvfrom %s:%u has no Non-ESP marker" - , ip_str(cur_from), (unsigned) cur_from_port); - return FALSE; - } - packet_len -= sizeof(u_int32_t); - buffer_nat = malloc(packet_len); - memcpy(buffer_nat, buffer + sizeof(u_int32_t), packet_len); - free(buffer); - buffer = buffer_nat; - } - - /* Clone actual message contents - * and set up md->packet_pbs to describe it. - */ - init_pbs(&md->packet_pbs, buffer, packet_len, "packet"); - - DBG(DBG_RAW | DBG_CRYPT | DBG_PARSING | DBG_CONTROL, - { - DBG_log(BLANK_FORMAT); - DBG_log("*received %d bytes from %s:%u on %s" - , (int) pbs_room(&md->packet_pbs) - , ip_str(cur_from), (unsigned) cur_from_port - , ifp->rname); - }); - - DBG(DBG_RAW, - DBG_dump("", md->packet_pbs.start, pbs_room(&md->packet_pbs))); - - if ((pbs_room(&md->packet_pbs)==1) && (md->packet_pbs.start[0]==0xff)) - { - /** - * NAT-T Keep-alive packets should be discarded by kernel ESPinUDP - * layer. But bogus keep-alive packets (sent with a non-esp marker) - * can reach this point. Complain and discard them. - */ - DBG(DBG_NATT, - DBG_log("NAT-T keep-alive (bogus ?) should not reach this point. " - "Ignored. Sender: %s:%u", ip_str(cur_from), - (unsigned) cur_from_port); - ) - return FALSE; + DBG(DBG_CONTROLMORE, + DBG_log(" ignoring IKEv2 packet") + ) + return FALSE; } -#define IKEV2_VERSION_OFFSET 17 -#define IKEV2_VERSION 0x20 - - /* ignore IKEv2 packets - they will be handled by charon */ - if (pbs_room(&md->packet_pbs) > IKEV2_VERSION_OFFSET - && md->packet_pbs.start[IKEV2_VERSION_OFFSET] == IKEV2_VERSION) - { - DBG(DBG_CONTROLMORE, - DBG_log(" ignoring IKEv2 packet") - ) - return FALSE; - } - - return TRUE; + return TRUE; } /* process an input packet, possibly generating a reply. @@ -1236,860 +1236,860 @@ read_packet(struct msg_digest *md) static void process_packet(struct msg_digest **mdp) { - struct msg_digest *md = *mdp; - const struct state_microcode *smc; - bool new_iv_set = FALSE; - bool restore_iv = FALSE; - u_char new_iv[MAX_DIGEST_LEN]; - u_int new_iv_len = 0; + struct msg_digest *md = *mdp; + const struct state_microcode *smc; + bool new_iv_set = FALSE; + bool restore_iv = FALSE; + u_char new_iv[MAX_DIGEST_LEN]; + u_int new_iv_len = 0; - struct state *st = NULL; - enum state_kind from_state = STATE_UNDEFINED; /* state we started in */ + struct state *st = NULL; + enum state_kind from_state = STATE_UNDEFINED; /* state we started in */ #define SEND_NOTIFICATION(t) { \ - if (st) send_notification_from_state(st, from_state, t); \ - else send_notification_from_md(md, t); } + if (st) send_notification_from_state(st, from_state, t); \ + else send_notification_from_md(md, t); } - if (!in_struct(&md->hdr, &isakmp_hdr_desc, &md->packet_pbs, &md->message_pbs)) - { - /* Identify specific failures: - * - bad ISAKMP major/minor version numbers - */ - if (md->packet_pbs.roof - md->packet_pbs.cur >= (ptrdiff_t)isakmp_hdr_desc.size) + if (!in_struct(&md->hdr, &isakmp_hdr_desc, &md->packet_pbs, &md->message_pbs)) { - struct isakmp_hdr *hdr = (struct isakmp_hdr *)md->packet_pbs.cur; - if ((hdr->isa_version >> ISA_MAJ_SHIFT) != ISAKMP_MAJOR_VERSION) - { - SEND_NOTIFICATION(INVALID_MAJOR_VERSION); - return; - } - else if ((hdr->isa_version & ISA_MIN_MASK) != ISAKMP_MINOR_VERSION) - { - SEND_NOTIFICATION(INVALID_MINOR_VERSION); - return; - } - } - SEND_NOTIFICATION(PAYLOAD_MALFORMED); - return; - } - - if (md->packet_pbs.roof != md->message_pbs.roof) - { - plog("size (%u) differs from size specified in ISAKMP HDR (%u)" - , (unsigned) pbs_room(&md->packet_pbs), md->hdr.isa_length); -#ifdef CISCO_QUIRKS - if (pbs_room(&md->packet_pbs) - md->hdr.isa_length == 16) - plog("Cisco VPN client appends 16 surplus NULL bytes"); - else -#endif - return; - } - - switch (md->hdr.isa_xchg) - { -#ifdef NOTYET - case ISAKMP_XCHG_NONE: - case ISAKMP_XCHG_BASE: -#endif - - case ISAKMP_XCHG_IDPROT: /* part of a Main Mode exchange */ - if (md->hdr.isa_msgid != MAINMODE_MSGID) - { - plog("Message ID was 0x%08lx but should be zero in Main Mode", - (unsigned long) md->hdr.isa_msgid); - SEND_NOTIFICATION(INVALID_MESSAGE_ID); - return; - } - - if (is_zero_cookie(md->hdr.isa_icookie)) - { - plog("Initiator Cookie must not be zero in Main Mode message"); - SEND_NOTIFICATION(INVALID_COOKIE); - return; - } - - if (is_zero_cookie(md->hdr.isa_rcookie)) - { - /* initial message from initiator - * ??? what if this is a duplicate of another message? - */ - if (md->hdr.isa_flags & ISAKMP_FLAG_ENCRYPTION) - { - plog("initial Main Mode message is invalid:" - " its Encrypted Flag is on"); - SEND_NOTIFICATION(INVALID_FLAGS); - return; - } - - /* don't build a state until the message looks tasty */ - from_state = STATE_MAIN_R0; - } - else - { - /* not an initial message */ - - st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie - , &md->sender, md->hdr.isa_msgid); - - if (st == NULL) - { - /* perhaps this is a first message from the responder - * and contains a responder cookie that we've not yet seen. + /* Identify specific failures: + * - bad ISAKMP major/minor version numbers */ - st = find_state(md->hdr.isa_icookie, zero_cookie - , &md->sender, md->hdr.isa_msgid); + if (md->packet_pbs.roof - md->packet_pbs.cur >= (ptrdiff_t)isakmp_hdr_desc.size) + { + struct isakmp_hdr *hdr = (struct isakmp_hdr *)md->packet_pbs.cur; + if ((hdr->isa_version >> ISA_MAJ_SHIFT) != ISAKMP_MAJOR_VERSION) + { + SEND_NOTIFICATION(INVALID_MAJOR_VERSION); + return; + } + else if ((hdr->isa_version & ISA_MIN_MASK) != ISAKMP_MINOR_VERSION) + { + SEND_NOTIFICATION(INVALID_MINOR_VERSION); + return; + } + } + SEND_NOTIFICATION(PAYLOAD_MALFORMED); + return; + } + + if (md->packet_pbs.roof != md->message_pbs.roof) + { + plog("size (%u) differs from size specified in ISAKMP HDR (%u)" + , (unsigned) pbs_room(&md->packet_pbs), md->hdr.isa_length); +#ifdef CISCO_QUIRKS + if (pbs_room(&md->packet_pbs) - md->hdr.isa_length == 16) + plog("Cisco VPN client appends 16 surplus NULL bytes"); + else +#endif + return; + } + + switch (md->hdr.isa_xchg) + { +#ifdef NOTYET + case ISAKMP_XCHG_NONE: + case ISAKMP_XCHG_BASE: +#endif + + case ISAKMP_XCHG_IDPROT: /* part of a Main Mode exchange */ + if (md->hdr.isa_msgid != MAINMODE_MSGID) + { + plog("Message ID was 0x%08lx but should be zero in Main Mode", + (unsigned long) md->hdr.isa_msgid); + SEND_NOTIFICATION(INVALID_MESSAGE_ID); + return; + } + + if (is_zero_cookie(md->hdr.isa_icookie)) + { + plog("Initiator Cookie must not be zero in Main Mode message"); + SEND_NOTIFICATION(INVALID_COOKIE); + return; + } + + if (is_zero_cookie(md->hdr.isa_rcookie)) + { + /* initial message from initiator + * ??? what if this is a duplicate of another message? + */ + if (md->hdr.isa_flags & ISAKMP_FLAG_ENCRYPTION) + { + plog("initial Main Mode message is invalid:" + " its Encrypted Flag is on"); + SEND_NOTIFICATION(INVALID_FLAGS); + return; + } + + /* don't build a state until the message looks tasty */ + from_state = STATE_MAIN_R0; + } + else + { + /* not an initial message */ + + st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie + , &md->sender, md->hdr.isa_msgid); + + if (st == NULL) + { + /* perhaps this is a first message from the responder + * and contains a responder cookie that we've not yet seen. + */ + st = find_state(md->hdr.isa_icookie, zero_cookie + , &md->sender, md->hdr.isa_msgid); + + if (st == NULL) + { + plog("Main Mode message is part of an unknown exchange"); + /* XXX Could send notification back */ + return; + } + } + set_cur_state(st); + from_state = st->st_state; + } + break; + +#ifdef NOTYET + case ISAKMP_XCHG_AO: + case ISAKMP_XCHG_AGGR: +#endif + + case ISAKMP_XCHG_INFO: /* an informational exchange */ + st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie + , &md->sender, MAINMODE_MSGID); + + if (st != NULL) + set_cur_state(st); + + if (md->hdr.isa_flags & ISAKMP_FLAG_ENCRYPTION) + { + if (st == NULL) + { + plog("Informational Exchange is for an unknown (expired?) SA"); + /* XXX Could send notification back */ + return; + } + + if (!IS_ISAKMP_ENCRYPTED(st->st_state)) + { + loglog(RC_LOG_SERIOUS, "encrypted Informational Exchange message is invalid" + " because no key is known"); + /* XXX Could send notification back */ + return; + } + + if (md->hdr.isa_msgid == MAINMODE_MSGID) + { + loglog(RC_LOG_SERIOUS, "Informational Exchange message is invalid because" + " it has a Message ID of 0"); + /* XXX Could send notification back */ + return; + } + + if (!reserve_msgid(st, md->hdr.isa_msgid)) + { + loglog(RC_LOG_SERIOUS, "Informational Exchange message is invalid because" + " it has a previously used Message ID (0x%08lx)" + , (unsigned long)md->hdr.isa_msgid); + /* XXX Could send notification back */ + return; + } + + if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state)) + { + memcpy(st->st_ph1_iv, st->st_new_iv, st->st_new_iv_len); + st->st_ph1_iv_len = st->st_new_iv_len; + + /* backup new_iv */ + new_iv_len = st->st_new_iv_len; + passert(new_iv_len <= MAX_DIGEST_LEN) + memcpy(new_iv, st->st_new_iv, new_iv_len); + restore_iv = TRUE; + } + init_phase2_iv(st, &md->hdr.isa_msgid); + new_iv_set = TRUE; + + from_state = STATE_INFO_PROTECTED; + } + else + { + if (st != NULL && IS_ISAKMP_ENCRYPTED(st->st_state)) + { + loglog(RC_LOG_SERIOUS, "Informational Exchange message" + " must be encrypted"); + /* XXX Could send notification back */ + return; + } + from_state = STATE_INFO; + } + break; + + case ISAKMP_XCHG_QUICK: /* part of a Quick Mode exchange */ + if (is_zero_cookie(md->hdr.isa_icookie)) + { + plog("Quick Mode message is invalid because" + " it has an Initiator Cookie of 0"); + SEND_NOTIFICATION(INVALID_COOKIE); + return; + } + + if (is_zero_cookie(md->hdr.isa_rcookie)) + { + plog("Quick Mode message is invalid because" + " it has a Responder Cookie of 0"); + SEND_NOTIFICATION(INVALID_COOKIE); + return; + } + + if (md->hdr.isa_msgid == MAINMODE_MSGID) + { + plog("Quick Mode message is invalid because" + " it has a Message ID of 0"); + SEND_NOTIFICATION(INVALID_MESSAGE_ID); + return; + } + + st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie + , &md->sender, md->hdr.isa_msgid); if (st == NULL) { - plog("Main Mode message is part of an unknown exchange"); - /* XXX Could send notification back */ - return; + /* No appropriate Quick Mode state. + * See if we have a Main Mode state. + * ??? what if this is a duplicate of another message? + */ + st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie + , &md->sender, MAINMODE_MSGID); + + if (st == NULL) + { + plog("Quick Mode message is for a non-existent (expired?)" + " ISAKMP SA"); + /* XXX Could send notification back */ + return; + } + + set_cur_state(st); + + if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state)) + { + loglog(RC_LOG_SERIOUS, "Quick Mode message is unacceptable because" + " it is for an incomplete ISAKMP SA"); + SEND_NOTIFICATION(PAYLOAD_MALFORMED /* XXX ? */); + return; + } + + /* only accept this new Quick Mode exchange if it has a unique message ID */ + if (!reserve_msgid(st, md->hdr.isa_msgid)) + { + loglog(RC_LOG_SERIOUS, "Quick Mode I1 message is unacceptable because" + " it uses a previously used Message ID 0x%08lx" + " (perhaps this is a duplicated packet)" + , (unsigned long) md->hdr.isa_msgid); + SEND_NOTIFICATION(INVALID_MESSAGE_ID); + return; + } + + /* Quick Mode Initial IV */ + init_phase2_iv(st, &md->hdr.isa_msgid); + new_iv_set = TRUE; + + from_state = STATE_QUICK_R0; } - } - set_cur_state(st); - from_state = st->st_state; - } - break; + else + { + set_cur_state(st); + from_state = st->st_state; + } + + break; + + case ISAKMP_XCHG_MODE_CFG: + if (is_zero_cookie(md->hdr.isa_icookie)) + { + plog("ModeCfg message is invalid because" + " it has an Initiator Cookie of 0"); + /* XXX Could send notification back */ + return; + } + + if (is_zero_cookie(md->hdr.isa_rcookie)) + { + plog("ModeCfg message is invalid because" + " it has a Responder Cookie of 0"); + /* XXX Could send notification back */ + return; + } + + if (md->hdr.isa_msgid == 0) + { + plog("ModeCfg message is invalid because" + " it has a Message ID of 0"); + /* XXX Could send notification back */ + return; + } + + st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie + , &md->sender, md->hdr.isa_msgid); + + if (st == NULL) + { + bool has_xauth_policy; + + /* No appropriate ModeCfg state. + * See if we have a Main Mode state. + * ??? what if this is a duplicate of another message? + */ + st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie + , &md->sender, 0); + + if (st == NULL) + { + plog("ModeCfg message is for a non-existent (expired?)" + " ISAKMP SA"); + /* XXX Could send notification back */ + return; + } + + set_cur_state(st); + + /* the XAUTH_STATUS message might have a new msgid */ + if (st->st_state == STATE_XAUTH_I1) + { + init_phase2_iv(st, &md->hdr.isa_msgid); + new_iv_set = TRUE; + from_state = st->st_state; + break; + } + + if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state)) + { + loglog(RC_LOG_SERIOUS, "ModeCfg message is unacceptable because" + " it is for an incomplete ISAKMP SA (state=%s)" + , enum_name(&state_names, st->st_state)); + /* XXX Could send notification back */ + return; + } + init_phase2_iv(st, &md->hdr.isa_msgid); + new_iv_set = TRUE; + + /* + * okay, now we have to figure out if we are receiving a bogus + * new message in an oustanding XAUTH server conversation + * (i.e. a reply to our challenge) + * (this occurs with some broken other implementations). + * + * or if receiving for the first time, an XAUTH challenge. + * + * or if we are getting a MODECFG request. + * + * we distinguish these states because we can not both be an + * XAUTH server and client, and our policy tells us which + * one we are. + * + * to complicate further, it is normal to start a new msgid + * when going from one state to another, or when restarting + * the challenge. + * + */ + + has_xauth_policy = (st->st_connection->policy + & (POLICY_XAUTH_RSASIG | POLICY_XAUTH_PSK)) + != LEMPTY; + + if (has_xauth_policy && !st->st_xauth.started + && IS_PHASE1(st->st_state)) + { + from_state = STATE_XAUTH_I0; + } + else if (st->st_connection->spd.that.modecfg + && IS_PHASE1(st->st_state)) + { + from_state = STATE_MODE_CFG_R0; + } + else if (st->st_connection->spd.this.modecfg + && IS_PHASE1(st->st_state)) + { + from_state = STATE_MODE_CFG_I0; + } + else + { + /* XXX check if we are being a mode config server here */ + plog("received ModeCfg message when in state %s, and we aren't mode config client" + , enum_name(&state_names, st->st_state)); + return; + } + } + else + { + set_cur_state(st); + from_state = st->st_state; + } + break; #ifdef NOTYET - case ISAKMP_XCHG_AO: - case ISAKMP_XCHG_AGGR: + case ISAKMP_XCHG_NGRP: + case ISAKMP_XCHG_ACK_INFO: #endif - case ISAKMP_XCHG_INFO: /* an informational exchange */ - st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie - , &md->sender, MAINMODE_MSGID); + default: + plog("unsupported exchange type %s in message" + , enum_show(&exchange_names, md->hdr.isa_xchg)); + SEND_NOTIFICATION(UNSUPPORTED_EXCHANGE_TYPE); + return; + } + + /* We have found a from_state, and perhaps a state object. + * If we need to build a new state object, + * we wait until the packet has been sanity checked. + */ + + /* We don't support the Commit Flag. It is such a bad feature. + * It isn't protected -- neither encrypted nor authenticated. + * A man in the middle turns it on, leading to DoS. + * We just ignore it, with a warning. + * By placing the check here, we could easily add a policy bit + * to a connection to suppress the warning. This might be useful + * because the Commit Flag is expected from some peers. + */ + if (md->hdr.isa_flags & ISAKMP_FLAG_COMMIT) + { + plog("IKE message has the Commit Flag set but Pluto doesn't implement this feature; ignoring flag"); + } + + /* Set smc to describe this state's properties. + * Look up the appropriate microcode based on state and + * possibly Oakley Auth type. + */ + passert(STATE_IKE_FLOOR <= from_state && from_state <= STATE_IKE_ROOF); + smc = ike_microcode_index[from_state - STATE_IKE_FLOOR]; if (st != NULL) - set_cur_state(st); + { + u_int16_t auth; + + switch (st->st_oakley.auth) + { + case XAUTHInitPreShared: + case XAUTHRespPreShared: + auth = OAKLEY_PRESHARED_KEY; + break; + case XAUTHInitRSA: + case XAUTHRespRSA: + auth = OAKLEY_RSA_SIG; + break; + default: + auth = st->st_oakley.auth; + } + + while (!LHAS(smc->flags, auth)) + { + smc++; + passert(smc->state == from_state); + } + } + + /* Ignore a packet if the state has a suspended state transition + * Probably a duplicated packet but the original packet is not yet + * recorded in st->st_rpacket, so duplicate checking won't catch. + * ??? Should the packet be recorded earlier to improve diagnosis? + */ + if (st != NULL && st->st_suspended_md != NULL) + { + loglog(RC_LOG, "discarding packet received during DNS lookup in %s" + , enum_name(&state_names, st->st_state)); + return; + } + + /* Detect and handle duplicated packets. + * This won't work for the initial packet of an exchange + * because we won't have a state object to remember it. + * If we are in a non-receiving state (terminal), and the preceding + * state did transmit, then the duplicate may indicate that that + * transmission wasn't received -- retransmit it. + * Otherwise, just discard it. + * ??? Notification packets are like exchanges -- I hope that + * they are idempotent! + */ + if (st != NULL + && st->st_rpacket.ptr != NULL + && st->st_rpacket.len == pbs_room(&md->packet_pbs) + && memeq(st->st_rpacket.ptr, md->packet_pbs.start, st->st_rpacket.len)) + { + if (smc->flags & SMF_RETRANSMIT_ON_DUPLICATE) + { + if (st->st_retransmit < MAXIMUM_RETRANSMISSIONS) + { + st->st_retransmit++; + loglog(RC_RETRANSMISSION + , "retransmitting in response to duplicate packet; already %s" + , enum_name(&state_names, st->st_state)); + send_packet(st, "retransmit in response to duplicate"); + } + else + { + loglog(RC_LOG_SERIOUS, "discarding duplicate packet -- exhausted retransmission; already %s" + , enum_name(&state_names, st->st_state)); + } + } + else + { + loglog(RC_LOG_SERIOUS, "discarding duplicate packet; already %s" + , enum_name(&state_names, st->st_state)); + } + return; + } if (md->hdr.isa_flags & ISAKMP_FLAG_ENCRYPTION) { - if (st == NULL) - { - plog("Informational Exchange is for an unknown (expired?) SA"); - /* XXX Could send notification back */ - return; - } + DBG(DBG_CRYPT, DBG_log("received encrypted packet from %s:%u" + , ip_str(&md->sender), (unsigned)md->sender_port)); - if (!IS_ISAKMP_ENCRYPTED(st->st_state)) - { - loglog(RC_LOG_SERIOUS, "encrypted Informational Exchange message is invalid" - " because no key is known"); - /* XXX Could send notification back */ - return; - } + if (st == NULL) + { + plog("discarding encrypted message for an unknown ISAKMP SA"); + SEND_NOTIFICATION(PAYLOAD_MALFORMED /* XXX ? */); + return; + } + if (st->st_skeyid_e.ptr == (u_char *) NULL) + { + loglog(RC_LOG_SERIOUS, "discarding encrypted message" + " because we haven't yet negotiated keying materiel"); + SEND_NOTIFICATION(INVALID_FLAGS); + return; + } - if (md->hdr.isa_msgid == MAINMODE_MSGID) - { - loglog(RC_LOG_SERIOUS, "Informational Exchange message is invalid because" - " it has a Message ID of 0"); - /* XXX Could send notification back */ - return; - } + /* Mark as encrypted */ + md->encrypted = TRUE; - if (!reserve_msgid(st, md->hdr.isa_msgid)) - { - loglog(RC_LOG_SERIOUS, "Informational Exchange message is invalid because" - " it has a previously used Message ID (0x%08lx)" - , (unsigned long)md->hdr.isa_msgid); - /* XXX Could send notification back */ - return; - } + DBG(DBG_CRYPT, DBG_log("decrypting %u bytes using algorithm %s" + , (unsigned) pbs_left(&md->message_pbs) + , enum_show(&oakley_enc_names, st->st_oakley.encrypt))); - if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state)) - { - memcpy(st->st_ph1_iv, st->st_new_iv, st->st_new_iv_len); - st->st_ph1_iv_len = st->st_new_iv_len; - - /* backup new_iv */ - new_iv_len = st->st_new_iv_len; - passert(new_iv_len <= MAX_DIGEST_LEN) - memcpy(new_iv, st->st_new_iv, new_iv_len); - restore_iv = TRUE; - } - init_phase2_iv(st, &md->hdr.isa_msgid); - new_iv_set = TRUE; + /* do the specified decryption + * + * IV is from st->st_iv or (if new_iv_set) st->st_new_iv. + * The new IV is placed in st->st_new_iv + * + * See RFC 2409 "IKE" Appendix B + * + * XXX The IV should only be updated really if the packet + * is successfully processed. + * We should keep this value, check for a success return + * value from the parsing routines and then replace. + * + * Each post phase 1 exchange generates IVs from + * the last phase 1 block, not the last block sent. + */ + { + const struct encrypt_desc *e = st->st_oakley.encrypter; - from_state = STATE_INFO_PROTECTED; + if (pbs_left(&md->message_pbs) % e->enc_blocksize != 0) + { + loglog(RC_LOG_SERIOUS, "malformed message: not a multiple of encryption blocksize"); + SEND_NOTIFICATION(PAYLOAD_MALFORMED); + return; + } + + /* XXX Detect weak keys */ + + /* grab a copy of raw packet (for duplicate packet detection) */ + md->raw_packet = chunk_create(md->packet_pbs.start, pbs_room(&md->packet_pbs)); + md->raw_packet = chunk_clone(md->raw_packet); + + /* Decrypt everything after header */ + if (!new_iv_set) + { + /* use old IV */ + passert(st->st_iv_len <= sizeof(st->st_new_iv)); + st->st_new_iv_len = st->st_iv_len; + memcpy(st->st_new_iv, st->st_iv, st->st_new_iv_len); + } + crypto_cbc_encrypt(e, FALSE, md->message_pbs.cur, + pbs_left(&md->message_pbs) , st); + if (restore_iv) + { + memcpy(st->st_new_iv, new_iv, new_iv_len); + st->st_new_iv_len = new_iv_len; + } + } + + DBG_cond_dump(DBG_CRYPT, "decrypted:\n", md->message_pbs.cur + , md->message_pbs.roof - md->message_pbs.cur); + + DBG_cond_dump(DBG_CRYPT, "next IV:" + , st->st_new_iv, st->st_new_iv_len); } else { - if (st != NULL && IS_ISAKMP_ENCRYPTED(st->st_state)) - { - loglog(RC_LOG_SERIOUS, "Informational Exchange message" - " must be encrypted"); - /* XXX Could send notification back */ - return; - } - from_state = STATE_INFO; - } - break; + /* packet was not encryped -- should it have been? */ - case ISAKMP_XCHG_QUICK: /* part of a Quick Mode exchange */ - if (is_zero_cookie(md->hdr.isa_icookie)) - { - plog("Quick Mode message is invalid because" - " it has an Initiator Cookie of 0"); - SEND_NOTIFICATION(INVALID_COOKIE); - return; + if (smc->flags & SMF_INPUT_ENCRYPTED) + { + loglog(RC_LOG_SERIOUS, "packet rejected: should have been encrypted"); + SEND_NOTIFICATION(INVALID_FLAGS); + return; + } } - if (is_zero_cookie(md->hdr.isa_rcookie)) - { - plog("Quick Mode message is invalid because" - " it has a Responder Cookie of 0"); - SEND_NOTIFICATION(INVALID_COOKIE); - return; - } - - if (md->hdr.isa_msgid == MAINMODE_MSGID) - { - plog("Quick Mode message is invalid because" - " it has a Message ID of 0"); - SEND_NOTIFICATION(INVALID_MESSAGE_ID); - return; - } - - st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie - , &md->sender, md->hdr.isa_msgid); - - if (st == NULL) - { - /* No appropriate Quick Mode state. - * See if we have a Main Mode state. - * ??? what if this is a duplicate of another message? - */ - st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie - , &md->sender, MAINMODE_MSGID); - - if (st == NULL) - { - plog("Quick Mode message is for a non-existent (expired?)" - " ISAKMP SA"); - /* XXX Could send notification back */ - return; - } - - set_cur_state(st); - - if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state)) - { - loglog(RC_LOG_SERIOUS, "Quick Mode message is unacceptable because" - " it is for an incomplete ISAKMP SA"); - SEND_NOTIFICATION(PAYLOAD_MALFORMED /* XXX ? */); - return; - } - - /* only accept this new Quick Mode exchange if it has a unique message ID */ - if (!reserve_msgid(st, md->hdr.isa_msgid)) - { - loglog(RC_LOG_SERIOUS, "Quick Mode I1 message is unacceptable because" - " it uses a previously used Message ID 0x%08lx" - " (perhaps this is a duplicated packet)" - , (unsigned long) md->hdr.isa_msgid); - SEND_NOTIFICATION(INVALID_MESSAGE_ID); - return; - } - - /* Quick Mode Initial IV */ - init_phase2_iv(st, &md->hdr.isa_msgid); - new_iv_set = TRUE; - - from_state = STATE_QUICK_R0; - } - else - { - set_cur_state(st); - from_state = st->st_state; - } - - break; - - case ISAKMP_XCHG_MODE_CFG: - if (is_zero_cookie(md->hdr.isa_icookie)) - { - plog("ModeCfg message is invalid because" - " it has an Initiator Cookie of 0"); - /* XXX Could send notification back */ - return; - } - - if (is_zero_cookie(md->hdr.isa_rcookie)) - { - plog("ModeCfg message is invalid because" - " it has a Responder Cookie of 0"); - /* XXX Could send notification back */ - return; - } - - if (md->hdr.isa_msgid == 0) - { - plog("ModeCfg message is invalid because" - " it has a Message ID of 0"); - /* XXX Could send notification back */ - return; - } - - st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie - , &md->sender, md->hdr.isa_msgid); - - if (st == NULL) - { - bool has_xauth_policy; - - /* No appropriate ModeCfg state. - * See if we have a Main Mode state. - * ??? what if this is a duplicate of another message? - */ - st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie - , &md->sender, 0); - - if (st == NULL) - { - plog("ModeCfg message is for a non-existent (expired?)" - " ISAKMP SA"); - /* XXX Could send notification back */ - return; - } - - set_cur_state(st); - - /* the XAUTH_STATUS message might have a new msgid */ - if (st->st_state == STATE_XAUTH_I1) - { - init_phase2_iv(st, &md->hdr.isa_msgid); - new_iv_set = TRUE; - from_state = st->st_state; - break; - } - - if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state)) - { - loglog(RC_LOG_SERIOUS, "ModeCfg message is unacceptable because" - " it is for an incomplete ISAKMP SA (state=%s)" - , enum_name(&state_names, st->st_state)); - /* XXX Could send notification back */ - return; - } - init_phase2_iv(st, &md->hdr.isa_msgid); - new_iv_set = TRUE; - - /* - * okay, now we have to figure out if we are receiving a bogus - * new message in an oustanding XAUTH server conversation - * (i.e. a reply to our challenge) - * (this occurs with some broken other implementations). - * - * or if receiving for the first time, an XAUTH challenge. - * - * or if we are getting a MODECFG request. - * - * we distinguish these states because we can not both be an - * XAUTH server and client, and our policy tells us which - * one we are. - * - * to complicate further, it is normal to start a new msgid - * when going from one state to another, or when restarting - * the challenge. - * - */ - - has_xauth_policy = (st->st_connection->policy - & (POLICY_XAUTH_RSASIG | POLICY_XAUTH_PSK)) - != LEMPTY; - - if (has_xauth_policy && !st->st_xauth.started - && IS_PHASE1(st->st_state)) - { - from_state = STATE_XAUTH_I0; - } - else if (st->st_connection->spd.that.modecfg - && IS_PHASE1(st->st_state)) - { - from_state = STATE_MODE_CFG_R0; - } - else if (st->st_connection->spd.this.modecfg - && IS_PHASE1(st->st_state)) - { - from_state = STATE_MODE_CFG_I0; - } - else - { - /* XXX check if we are being a mode config server here */ - plog("received ModeCfg message when in state %s, and we aren't mode config client" - , enum_name(&state_names, st->st_state)); - return; - } - } - else - { - set_cur_state(st); - from_state = st->st_state; - } - break; - -#ifdef NOTYET - case ISAKMP_XCHG_NGRP: - case ISAKMP_XCHG_ACK_INFO: -#endif - - default: - plog("unsupported exchange type %s in message" - , enum_show(&exchange_names, md->hdr.isa_xchg)); - SEND_NOTIFICATION(UNSUPPORTED_EXCHANGE_TYPE); - return; - } - - /* We have found a from_state, and perhaps a state object. - * If we need to build a new state object, - * we wait until the packet has been sanity checked. - */ - - /* We don't support the Commit Flag. It is such a bad feature. - * It isn't protected -- neither encrypted nor authenticated. - * A man in the middle turns it on, leading to DoS. - * We just ignore it, with a warning. - * By placing the check here, we could easily add a policy bit - * to a connection to suppress the warning. This might be useful - * because the Commit Flag is expected from some peers. - */ - if (md->hdr.isa_flags & ISAKMP_FLAG_COMMIT) - { - plog("IKE message has the Commit Flag set but Pluto doesn't implement this feature; ignoring flag"); - } - - /* Set smc to describe this state's properties. - * Look up the appropriate microcode based on state and - * possibly Oakley Auth type. - */ - passert(STATE_IKE_FLOOR <= from_state && from_state <= STATE_IKE_ROOF); - smc = ike_microcode_index[from_state - STATE_IKE_FLOOR]; - - if (st != NULL) - { - u_int16_t auth; - - switch (st->st_oakley.auth) - { - case XAUTHInitPreShared: - case XAUTHRespPreShared: - auth = OAKLEY_PRESHARED_KEY; - break; - case XAUTHInitRSA: - case XAUTHRespRSA: - auth = OAKLEY_RSA_SIG; - break; - default: - auth = st->st_oakley.auth; - } - - while (!LHAS(smc->flags, auth)) - { - smc++; - passert(smc->state == from_state); - } - } - - /* Ignore a packet if the state has a suspended state transition - * Probably a duplicated packet but the original packet is not yet - * recorded in st->st_rpacket, so duplicate checking won't catch. - * ??? Should the packet be recorded earlier to improve diagnosis? - */ - if (st != NULL && st->st_suspended_md != NULL) - { - loglog(RC_LOG, "discarding packet received during DNS lookup in %s" - , enum_name(&state_names, st->st_state)); - return; - } - - /* Detect and handle duplicated packets. - * This won't work for the initial packet of an exchange - * because we won't have a state object to remember it. - * If we are in a non-receiving state (terminal), and the preceding - * state did transmit, then the duplicate may indicate that that - * transmission wasn't received -- retransmit it. - * Otherwise, just discard it. - * ??? Notification packets are like exchanges -- I hope that - * they are idempotent! - */ - if (st != NULL - && st->st_rpacket.ptr != NULL - && st->st_rpacket.len == pbs_room(&md->packet_pbs) - && memeq(st->st_rpacket.ptr, md->packet_pbs.start, st->st_rpacket.len)) - { - if (smc->flags & SMF_RETRANSMIT_ON_DUPLICATE) - { - if (st->st_retransmit < MAXIMUM_RETRANSMISSIONS) - { - st->st_retransmit++; - loglog(RC_RETRANSMISSION - , "retransmitting in response to duplicate packet; already %s" - , enum_name(&state_names, st->st_state)); - send_packet(st, "retransmit in response to duplicate"); - } - else - { - loglog(RC_LOG_SERIOUS, "discarding duplicate packet -- exhausted retransmission; already %s" - , enum_name(&state_names, st->st_state)); - } - } - else - { - loglog(RC_LOG_SERIOUS, "discarding duplicate packet; already %s" - , enum_name(&state_names, st->st_state)); - } - return; - } - - if (md->hdr.isa_flags & ISAKMP_FLAG_ENCRYPTION) - { - DBG(DBG_CRYPT, DBG_log("received encrypted packet from %s:%u" - , ip_str(&md->sender), (unsigned)md->sender_port)); - - if (st == NULL) - { - plog("discarding encrypted message for an unknown ISAKMP SA"); - SEND_NOTIFICATION(PAYLOAD_MALFORMED /* XXX ? */); - return; - } - if (st->st_skeyid_e.ptr == (u_char *) NULL) - { - loglog(RC_LOG_SERIOUS, "discarding encrypted message" - " because we haven't yet negotiated keying materiel"); - SEND_NOTIFICATION(INVALID_FLAGS); - return; - } - - /* Mark as encrypted */ - md->encrypted = TRUE; - - DBG(DBG_CRYPT, DBG_log("decrypting %u bytes using algorithm %s" - , (unsigned) pbs_left(&md->message_pbs) - , enum_show(&oakley_enc_names, st->st_oakley.encrypt))); - - /* do the specified decryption - * - * IV is from st->st_iv or (if new_iv_set) st->st_new_iv. - * The new IV is placed in st->st_new_iv - * - * See RFC 2409 "IKE" Appendix B - * - * XXX The IV should only be updated really if the packet - * is successfully processed. - * We should keep this value, check for a success return - * value from the parsing routines and then replace. - * - * Each post phase 1 exchange generates IVs from - * the last phase 1 block, not the last block sent. + /* Digest the message. + * Padding must be removed to make hashing work. + * Padding comes from encryption (so this code must be after decryption). + * Padding rules are described before the definition of + * struct isakmp_hdr in packet.h. */ { - const struct encrypt_desc *e = st->st_oakley.encrypter; + struct payload_digest *pd = md->digest; + int np = md->hdr.isa_np; + lset_t needed = smc->req_payloads; + const char *excuse + = LIN(SMF_PSK_AUTH | SMF_FIRST_ENCRYPTED_INPUT, smc->flags) + ? "probable authentication failure (mismatch of preshared secrets?): " + : ""; - if (pbs_left(&md->message_pbs) % e->enc_blocksize != 0) - { - loglog(RC_LOG_SERIOUS, "malformed message: not a multiple of encryption blocksize"); - SEND_NOTIFICATION(PAYLOAD_MALFORMED); - return; - } + while (np != ISAKMP_NEXT_NONE) + { + struct_desc *sd = np < ISAKMP_NEXT_ROOF? payload_descs[np] : NULL; - /* XXX Detect weak keys */ + if (pd == &md->digest[PAYLIMIT]) + { + loglog(RC_LOG_SERIOUS, "more than %d payloads in message; ignored", PAYLIMIT); + SEND_NOTIFICATION(PAYLOAD_MALFORMED); + return; + } - /* grab a copy of raw packet (for duplicate packet detection) */ - md->raw_packet = chunk_create(md->packet_pbs.start, pbs_room(&md->packet_pbs)); - md->raw_packet = chunk_clone(md->raw_packet); + switch (np) + { + case ISAKMP_NEXT_NATD_RFC: + case ISAKMP_NEXT_NATOA_RFC: + if (!st || !(st->nat_traversal & NAT_T_WITH_RFC_VALUES)) + { + /* + * don't accept NAT-D/NAT-OA reloc directly in message, unless + * we're using NAT-T RFC + */ + sd = NULL; + } + break; + } - /* Decrypt everything after header */ - if (!new_iv_set) - { - /* use old IV */ - passert(st->st_iv_len <= sizeof(st->st_new_iv)); - st->st_new_iv_len = st->st_iv_len; - memcpy(st->st_new_iv, st->st_iv, st->st_new_iv_len); - } - crypto_cbc_encrypt(e, FALSE, md->message_pbs.cur, - pbs_left(&md->message_pbs) , st); - if (restore_iv) - { - memcpy(st->st_new_iv, new_iv, new_iv_len); - st->st_new_iv_len = new_iv_len; - } - } + if (sd == NULL) + { + /* payload type is out of range or requires special handling */ + switch (np) + { + case ISAKMP_NEXT_ID: + sd = IS_PHASE1(from_state) + ? &isakmp_identification_desc : &isakmp_ipsec_identification_desc; + break; + case ISAKMP_NEXT_NATD_DRAFTS: + np = ISAKMP_NEXT_NATD_RFC; /* NAT-D relocated */ + sd = payload_descs[np]; + break; + case ISAKMP_NEXT_NATOA_DRAFTS: + np = ISAKMP_NEXT_NATOA_RFC; /* NAT-OA relocated */ + sd = payload_descs[np]; + break; + default: + loglog(RC_LOG_SERIOUS, "%smessage ignored because it contains an unknown or" + " unexpected payload type (%s) at the outermost level" + , excuse, enum_show(&payload_names, np)); + SEND_NOTIFICATION(INVALID_PAYLOAD_TYPE); + return; + } + } - DBG_cond_dump(DBG_CRYPT, "decrypted:\n", md->message_pbs.cur - , md->message_pbs.roof - md->message_pbs.cur); + { + lset_t s = LELEM(np); - DBG_cond_dump(DBG_CRYPT, "next IV:" - , st->st_new_iv, st->st_new_iv_len); - } - else - { - /* packet was not encryped -- should it have been? */ + if (LDISJOINT(s + , needed | smc->opt_payloads| LELEM(ISAKMP_NEXT_N) | LELEM(ISAKMP_NEXT_D))) + { + loglog(RC_LOG_SERIOUS, "%smessage ignored because it " + "contains an unexpected payload type (%s)" + , excuse, enum_show(&payload_names, np)); + SEND_NOTIFICATION(INVALID_PAYLOAD_TYPE); + return; + } + needed &= ~s; + } - if (smc->flags & SMF_INPUT_ENCRYPTED) - { - loglog(RC_LOG_SERIOUS, "packet rejected: should have been encrypted"); - SEND_NOTIFICATION(INVALID_FLAGS); - return; - } - } + if (!in_struct(&pd->payload, sd, &md->message_pbs, &pd->pbs)) + { + loglog(RC_LOG_SERIOUS, "%smalformed payload in packet", excuse); + if (md->hdr.isa_xchg != ISAKMP_XCHG_INFO) + SEND_NOTIFICATION(PAYLOAD_MALFORMED); + return; + } - /* Digest the message. - * Padding must be removed to make hashing work. - * Padding comes from encryption (so this code must be after decryption). - * Padding rules are described before the definition of - * struct isakmp_hdr in packet.h. - */ - { - struct payload_digest *pd = md->digest; - int np = md->hdr.isa_np; - lset_t needed = smc->req_payloads; - const char *excuse - = LIN(SMF_PSK_AUTH | SMF_FIRST_ENCRYPTED_INPUT, smc->flags) - ? "probable authentication failure (mismatch of preshared secrets?): " - : ""; + /* place this payload at the end of the chain for this type */ + { + struct payload_digest **p; - while (np != ISAKMP_NEXT_NONE) - { - struct_desc *sd = np < ISAKMP_NEXT_ROOF? payload_descs[np] : NULL; + for (p = &md->chain[np]; *p != NULL; p = &(*p)->next) + ; + *p = pd; + pd->next = NULL; + } - if (pd == &md->digest[PAYLIMIT]) - { - loglog(RC_LOG_SERIOUS, "more than %d payloads in message; ignored", PAYLIMIT); - SEND_NOTIFICATION(PAYLOAD_MALFORMED); - return; - } + np = pd->payload.generic.isag_np; + pd++; - switch (np) - { - case ISAKMP_NEXT_NATD_RFC: - case ISAKMP_NEXT_NATOA_RFC: - if (!st || !(st->nat_traversal & NAT_T_WITH_RFC_VALUES)) - { - /* - * don't accept NAT-D/NAT-OA reloc directly in message, unless - * we're using NAT-T RFC + /* since we've digested one payload happily, it is probably + * the case that any decryption worked. So we will not suggest + * encryption failure as an excuse for subsequent payload + * problems. */ - sd = NULL; - } - break; - } - - if (sd == NULL) - { - /* payload type is out of range or requires special handling */ - switch (np) - { - case ISAKMP_NEXT_ID: - sd = IS_PHASE1(from_state) - ? &isakmp_identification_desc : &isakmp_ipsec_identification_desc; - break; - case ISAKMP_NEXT_NATD_DRAFTS: - np = ISAKMP_NEXT_NATD_RFC; /* NAT-D relocated */ - sd = payload_descs[np]; - break; - case ISAKMP_NEXT_NATOA_DRAFTS: - np = ISAKMP_NEXT_NATOA_RFC; /* NAT-OA relocated */ - sd = payload_descs[np]; - break; - default: - loglog(RC_LOG_SERIOUS, "%smessage ignored because it contains an unknown or" - " unexpected payload type (%s) at the outermost level" - , excuse, enum_show(&payload_names, np)); - SEND_NOTIFICATION(INVALID_PAYLOAD_TYPE); - return; + excuse = ""; } - } - { - lset_t s = LELEM(np); + md->digest_roof = pd; - if (LDISJOINT(s - , needed | smc->opt_payloads| LELEM(ISAKMP_NEXT_N) | LELEM(ISAKMP_NEXT_D))) + DBG(DBG_PARSING, + if (pbs_left(&md->message_pbs) != 0) + DBG_log("removing %d bytes of padding", (int) pbs_left(&md->message_pbs))); + + md->message_pbs.roof = md->message_pbs.cur; + + /* check that all mandatory payloads appeared */ + + if (needed != 0) { - loglog(RC_LOG_SERIOUS, "%smessage ignored because it " - "contains an unexpected payload type (%s)" - , excuse, enum_show(&payload_names, np)); - SEND_NOTIFICATION(INVALID_PAYLOAD_TYPE); - return; + loglog(RC_LOG_SERIOUS, "message for %s is missing payloads %s" + , enum_show(&state_names, from_state) + , bitnamesof(payload_name, needed)); + SEND_NOTIFICATION(PAYLOAD_MALFORMED); + return; } - needed &= ~s; - } - - if (!in_struct(&pd->payload, sd, &md->message_pbs, &pd->pbs)) - { - loglog(RC_LOG_SERIOUS, "%smalformed payload in packet", excuse); - if (md->hdr.isa_xchg != ISAKMP_XCHG_INFO) - SEND_NOTIFICATION(PAYLOAD_MALFORMED); - return; - } - - /* place this payload at the end of the chain for this type */ - { - struct payload_digest **p; - - for (p = &md->chain[np]; *p != NULL; p = &(*p)->next) - ; - *p = pd; - pd->next = NULL; - } - - np = pd->payload.generic.isag_np; - pd++; - - /* since we've digested one payload happily, it is probably - * the case that any decryption worked. So we will not suggest - * encryption failure as an excuse for subsequent payload - * problems. - */ - excuse = ""; } - md->digest_roof = pd; + /* more sanity checking: enforce most ordering constraints */ - DBG(DBG_PARSING, - if (pbs_left(&md->message_pbs) != 0) - DBG_log("removing %d bytes of padding", (int) pbs_left(&md->message_pbs))); - - md->message_pbs.roof = md->message_pbs.cur; - - /* check that all mandatory payloads appeared */ - - if (needed != 0) + if (IS_PHASE1(from_state)) { - loglog(RC_LOG_SERIOUS, "message for %s is missing payloads %s" - , enum_show(&state_names, from_state) - , bitnamesof(payload_name, needed)); - SEND_NOTIFICATION(PAYLOAD_MALFORMED); - return; + /* rfc2409: The Internet Key Exchange (IKE), 5 Exchanges: + * "The SA payload MUST precede all other payloads in a phase 1 exchange." + */ + if (md->chain[ISAKMP_NEXT_SA] != NULL + && md->hdr.isa_np != ISAKMP_NEXT_SA) + { + loglog(RC_LOG_SERIOUS, "malformed Phase 1 message: does not start with an SA payload"); + SEND_NOTIFICATION(PAYLOAD_MALFORMED); + return; + } } - } + else if (IS_QUICK(from_state)) + { + /* rfc2409: The Internet Key Exchange (IKE), 5.5 Phase 2 - Quick Mode + * + * "In Quick Mode, a HASH payload MUST immediately follow the ISAKMP + * header and a SA payload MUST immediately follow the HASH." + * [NOTE: there may be more than one SA payload, so this is not + * totally reasonable. Probably all SAs should be so constrained.] + * + * "If ISAKMP is acting as a client negotiator on behalf of another + * party, the identities of the parties MUST be passed as IDci and + * then IDcr." + * + * "With the exception of the HASH, SA, and the optional ID payloads, + * there are no payload ordering restrictions on Quick Mode." + */ - /* more sanity checking: enforce most ordering constraints */ + if (md->hdr.isa_np != ISAKMP_NEXT_HASH) + { + loglog(RC_LOG_SERIOUS, "malformed Quick Mode message: does not start with a HASH payload"); + SEND_NOTIFICATION(PAYLOAD_MALFORMED); + return; + } - if (IS_PHASE1(from_state)) - { - /* rfc2409: The Internet Key Exchange (IKE), 5 Exchanges: - * "The SA payload MUST precede all other payloads in a phase 1 exchange." + { + struct payload_digest *p; + int i; + + for (p = md->chain[ISAKMP_NEXT_SA], i = 1; p != NULL + ; p = p->next, i++) + { + if (p != &md->digest[i]) + { + loglog(RC_LOG_SERIOUS, "malformed Quick Mode message: SA payload is in wrong position"); + SEND_NOTIFICATION(PAYLOAD_MALFORMED); + return; + } + } + } + + /* rfc2409: The Internet Key Exchange (IKE), 5.5 Phase 2 - Quick Mode: + * "If ISAKMP is acting as a client negotiator on behalf of another + * party, the identities of the parties MUST be passed as IDci and + * then IDcr." + */ + { + struct payload_digest *id = md->chain[ISAKMP_NEXT_ID]; + + if (id != NULL) + { + if (id->next == NULL || id->next->next != NULL) + { + loglog(RC_LOG_SERIOUS, "malformed Quick Mode message:" + " if any ID payload is present," + " there must be exactly two"); + SEND_NOTIFICATION(PAYLOAD_MALFORMED); + return; + } + if (id+1 != id->next) + { + loglog(RC_LOG_SERIOUS, "malformed Quick Mode message:" + " the ID payloads are not adjacent"); + SEND_NOTIFICATION(PAYLOAD_MALFORMED); + return; + } + } + } + } + + /* Ignore payloads that we don't handle: + * Delete, Notification, VendorID */ - if (md->chain[ISAKMP_NEXT_SA] != NULL - && md->hdr.isa_np != ISAKMP_NEXT_SA) + /* XXX Handle deletions */ + /* XXX Handle Notifications */ + /* XXX Handle VID payloads */ { - loglog(RC_LOG_SERIOUS, "malformed Phase 1 message: does not start with an SA payload"); - SEND_NOTIFICATION(PAYLOAD_MALFORMED); - return; - } - } - else if (IS_QUICK(from_state)) - { - /* rfc2409: The Internet Key Exchange (IKE), 5.5 Phase 2 - Quick Mode - * - * "In Quick Mode, a HASH payload MUST immediately follow the ISAKMP - * header and a SA payload MUST immediately follow the HASH." - * [NOTE: there may be more than one SA payload, so this is not - * totally reasonable. Probably all SAs should be so constrained.] - * - * "If ISAKMP is acting as a client negotiator on behalf of another - * party, the identities of the parties MUST be passed as IDci and - * then IDcr." - * - * "With the exception of the HASH, SA, and the optional ID payloads, - * there are no payload ordering restrictions on Quick Mode." - */ + struct payload_digest *p; - if (md->hdr.isa_np != ISAKMP_NEXT_HASH) - { - loglog(RC_LOG_SERIOUS, "malformed Quick Mode message: does not start with a HASH payload"); - SEND_NOTIFICATION(PAYLOAD_MALFORMED); - return; - } - - { - struct payload_digest *p; - int i; - - for (p = md->chain[ISAKMP_NEXT_SA], i = 1; p != NULL - ; p = p->next, i++) - { - if (p != &md->digest[i]) + for (p = md->chain[ISAKMP_NEXT_N]; p != NULL; p = p->next) { - loglog(RC_LOG_SERIOUS, "malformed Quick Mode message: SA payload is in wrong position"); - SEND_NOTIFICATION(PAYLOAD_MALFORMED); - return; + if (p->payload.notification.isan_type != R_U_THERE + && p->payload.notification.isan_type != R_U_THERE_ACK) + { + loglog(RC_LOG_SERIOUS, "ignoring informational payload, type %s" + , enum_show(¬ification_names, p->payload.notification.isan_type)); + } + DBG_cond_dump(DBG_PARSING, "info:", p->pbs.cur, pbs_left(&p->pbs)); } - } - } - /* rfc2409: The Internet Key Exchange (IKE), 5.5 Phase 2 - Quick Mode: - * "If ISAKMP is acting as a client negotiator on behalf of another - * party, the identities of the parties MUST be passed as IDci and - * then IDcr." - */ - { - struct payload_digest *id = md->chain[ISAKMP_NEXT_ID]; - - if (id != NULL) - { - if (id->next == NULL || id->next->next != NULL) + for (p = md->chain[ISAKMP_NEXT_D]; p != NULL; p = p->next) { - loglog(RC_LOG_SERIOUS, "malformed Quick Mode message:" - " if any ID payload is present," - " there must be exactly two"); - SEND_NOTIFICATION(PAYLOAD_MALFORMED); - return; + accept_delete(st, md, p); + DBG_cond_dump(DBG_PARSING, "del:", p->pbs.cur, pbs_left(&p->pbs)); } - if (id+1 != id->next) + + for (p = md->chain[ISAKMP_NEXT_VID]; p != NULL; p = p->next) { - loglog(RC_LOG_SERIOUS, "malformed Quick Mode message:" - " the ID payloads are not adjacent"); - SEND_NOTIFICATION(PAYLOAD_MALFORMED); - return; + handle_vendorid(md, p->pbs.cur, pbs_left(&p->pbs)); } - } } - } + md->from_state = from_state; + md->smc = smc; + md->st = st; - /* Ignore payloads that we don't handle: - * Delete, Notification, VendorID - */ - /* XXX Handle deletions */ - /* XXX Handle Notifications */ - /* XXX Handle VID payloads */ - { - struct payload_digest *p; + /* possibly fill in hdr */ + if (smc->first_out_payload != ISAKMP_NEXT_NONE) + echo_hdr(md, (smc->flags & SMF_OUTPUT_ENCRYPTED) != 0 + , smc->first_out_payload); - for (p = md->chain[ISAKMP_NEXT_N]; p != NULL; p = p->next) - { - if (p->payload.notification.isan_type != R_U_THERE - && p->payload.notification.isan_type != R_U_THERE_ACK) - { - loglog(RC_LOG_SERIOUS, "ignoring informational payload, type %s" - , enum_show(¬ification_names, p->payload.notification.isan_type)); - } - DBG_cond_dump(DBG_PARSING, "info:", p->pbs.cur, pbs_left(&p->pbs)); - } - - for (p = md->chain[ISAKMP_NEXT_D]; p != NULL; p = p->next) - { - accept_delete(st, md, p); - DBG_cond_dump(DBG_PARSING, "del:", p->pbs.cur, pbs_left(&p->pbs)); - } - - for (p = md->chain[ISAKMP_NEXT_VID]; p != NULL; p = p->next) - { - handle_vendorid(md, p->pbs.cur, pbs_left(&p->pbs)); - } - } - md->from_state = from_state; - md->smc = smc; - md->st = st; - - /* possibly fill in hdr */ - if (smc->first_out_payload != ISAKMP_NEXT_NONE) - echo_hdr(md, (smc->flags & SMF_OUTPUT_ENCRYPTED) != 0 - , smc->first_out_payload); - - complete_state_transition(mdp, smc->processor(md)); + complete_state_transition(mdp, smc->processor(md)); } /* complete job started by the state-specific state transition function */ @@ -2097,406 +2097,406 @@ process_packet(struct msg_digest **mdp) void complete_state_transition(struct msg_digest **mdp, stf_status result) { - bool has_xauth_policy; - bool is_xauth_server; - struct msg_digest *md = *mdp; - const struct state_microcode *smc = md->smc; - enum state_kind from_state = md->from_state; - struct state *st; + bool has_xauth_policy; + bool is_xauth_server; + struct msg_digest *md = *mdp; + const struct state_microcode *smc = md->smc; + enum state_kind from_state = md->from_state; + struct state *st; - cur_state = st = md->st; /* might have changed */ + cur_state = st = md->st; /* might have changed */ - /* If state has DPD support, import it */ - if (st && md->dpd) - st->st_dpd = TRUE; + /* If state has DPD support, import it */ + if (st && md->dpd) + st->st_dpd = TRUE; - switch (result) - { - case STF_IGNORE: - break; + switch (result) + { + case STF_IGNORE: + break; - case STF_SUSPEND: - /* the stf didn't complete its job: don't relase md */ - *mdp = NULL; - break; + case STF_SUSPEND: + /* the stf didn't complete its job: don't relase md */ + *mdp = NULL; + break; - case STF_OK: - /* advance the state */ - st->st_state = smc->next_state; + case STF_OK: + /* advance the state */ + st->st_state = smc->next_state; - /* Delete previous retransmission event. - * New event will be scheduled below. - */ - delete_event(st); - - /* replace previous receive packet with latest */ - - free(st->st_rpacket.ptr); - - if (md->encrypted) - { - /* if encrypted, duplication already done */ - st->st_rpacket = md->raw_packet; - md->raw_packet.ptr = NULL; - } - else - { - st->st_rpacket = chunk_create(md->packet_pbs.start, - pbs_room(&md->packet_pbs)); - st->st_rpacket = chunk_clone(st->st_rpacket); - } - - /* free previous transmit packet */ - chunk_free(&st->st_tpacket); - - /* if requested, send the new reply packet */ - if (smc->flags & SMF_REPLY) - { - close_output_pbs(&md->reply); /* good form, but actually a no-op */ - - st->st_tpacket = chunk_create(md->reply.start, pbs_offset(&md->reply)); - st->st_tpacket = chunk_clone(st->st_tpacket); - - if (nat_traversal_enabled) - nat_traversal_change_port_lookup(md, md->st); - - /* actually send the packet - * Note: this is a great place to implement "impairments" - * for testing purposes. Suppress or duplicate the - * send_packet call depending on st->st_state. - */ - send_packet(st, enum_name(&state_names, from_state)); - } - - /* Schedule for whatever timeout is specified */ - { - time_t delay = UNDEFINED_TIME; - enum event_type kind = smc->timeout_event; - bool agreed_time = FALSE; - struct connection *c = st->st_connection; - - switch (kind) - { - case EVENT_RETRANSMIT: /* Retransmit packet */ - delay = EVENT_RETRANSMIT_DELAY_0; - break; - - case EVENT_SA_REPLACE: /* SA replacement event */ - if (IS_PHASE1(st->st_state)) - { - /* Note: we will defer to the "negotiated" (dictated) - * lifetime if we are POLICY_DONT_REKEY. - * This allows the other side to dictate - * a time we would not otherwise accept - * but it prevents us from having to initiate - * rekeying. The negative consequences seem - * minor. + /* Delete previous retransmission event. + * New event will be scheduled below. */ - delay = c->sa_ike_life_seconds; - if ((c->policy & POLICY_DONT_REKEY) - || delay >= st->st_oakley.life_seconds) - { - agreed_time = TRUE; - delay = st->st_oakley.life_seconds; - } - } - else - { - /* Delay is min of up to four things: - * each can limit the lifetime. - */ - delay = c->sa_ipsec_life_seconds; - if (st->st_ah.present - && delay >= st->st_ah.attrs.life_seconds) - { - agreed_time = TRUE; - delay = st->st_ah.attrs.life_seconds; - } - if (st->st_esp.present - && delay >= st->st_esp.attrs.life_seconds) - { - agreed_time = TRUE; - delay = st->st_esp.attrs.life_seconds; - } - if (st->st_ipcomp.present - && delay >= st->st_ipcomp.attrs.life_seconds) - { - agreed_time = TRUE; - delay = st->st_ipcomp.attrs.life_seconds; - } - } + delete_event(st); - /* By default, we plan to rekey. - * - * If there isn't enough time to rekey, plan to - * expire. - * - * If we are --dontrekey, a lot more rules apply. - * If we are the Initiator, use REPLACE_IF_USED. - * If we are the Responder, and the dictated time - * was unacceptable (too large), plan to REPLACE - * (the only way to ratchet down the time). - * If we are the Responder, and the dictated time - * is acceptable, plan to EXPIRE. - * - * Important policy lies buried here. - * For example, we favour the initiator over the - * responder by making the initiator start rekeying - * sooner. Also, fuzz is only added to the - * initiator's margin. - * - * Note: for ISAKMP SA, we let the negotiated - * time stand (implemented by earlier logic). - */ - if (agreed_time - && (c->policy & POLICY_DONT_REKEY)) - { - kind = (smc->flags & SMF_INITIATOR) - ? EVENT_SA_REPLACE_IF_USED - : EVENT_SA_EXPIRE; - } - if (kind != EVENT_SA_EXPIRE) - { - unsigned long marg = c->sa_rekey_margin; + /* replace previous receive packet with latest */ - if (smc->flags & SMF_INITIATOR) - marg += marg - * c->sa_rekey_fuzz / 100.E0 - * (rand() / (RAND_MAX + 1.E0)); - else - marg /= 2; + free(st->st_rpacket.ptr); - if ((unsigned long)delay > marg) + if (md->encrypted) { - delay -= marg; - st->st_margin = marg; + /* if encrypted, duplication already done */ + st->st_rpacket = md->raw_packet; + md->raw_packet.ptr = NULL; } else { - kind = EVENT_SA_EXPIRE; + st->st_rpacket = chunk_create(md->packet_pbs.start, + pbs_room(&md->packet_pbs)); + st->st_rpacket = chunk_clone(st->st_rpacket); } - } - break; - case EVENT_NULL: /* non-event */ - case EVENT_REINIT_SECRET: /* Refresh cookie secret */ - default: - bad_case(kind); - } - event_schedule(kind, delay, st); - } + /* free previous transmit packet */ + chunk_free(&st->st_tpacket); - /* tell whack and log of progress */ - { - const char *story = state_story[st->st_state - STATE_MAIN_R0]; - enum rc_type w = RC_NEW_STATE + st->st_state; - char sadetails[128]; - - sadetails[0]='\0'; + /* if requested, send the new reply packet */ + if (smc->flags & SMF_REPLY) + { + close_output_pbs(&md->reply); /* good form, but actually a no-op */ - if (IS_IPSEC_SA_ESTABLISHED(st->st_state)) - { - char *b = sadetails; - const char *ini = " {"; - const char *fin = ""; + st->st_tpacket = chunk_create(md->reply.start, pbs_offset(&md->reply)); + st->st_tpacket = chunk_clone(st->st_tpacket); - /* -1 is to leave space for "fin" */ + if (nat_traversal_enabled) + nat_traversal_change_port_lookup(md, md->st); - if (st->st_esp.present) - { - snprintf(b, sizeof(sadetails)-(b-sadetails)-1 - , "%sESP=>0x%08x <0x%08x" - , ini - , ntohl(st->st_esp.attrs.spi) - , ntohl(st->st_esp.our_spi)); - ini = " "; - fin = "}"; - } - /* advance b to end of string */ - b = b + strlen(b); + /* actually send the packet + * Note: this is a great place to implement "impairments" + * for testing purposes. Suppress or duplicate the + * send_packet call depending on st->st_state. + */ + send_packet(st, enum_name(&state_names, from_state)); + } - if (st->st_ah.present) - { - snprintf(b, sizeof(sadetails)-(b-sadetails)-1 - , "%sAH=>0x%08x <0x%08x" - , ini - , ntohl(st->st_ah.attrs.spi) - , ntohl(st->st_ah.our_spi)); - ini = " "; - fin = "}"; - } - /* advance b to end of string */ - b = b + strlen(b); + /* Schedule for whatever timeout is specified */ + { + time_t delay = UNDEFINED_TIME; + enum event_type kind = smc->timeout_event; + bool agreed_time = FALSE; + struct connection *c = st->st_connection; - if (st->st_ipcomp.present) - { - snprintf(b, sizeof(sadetails)-(b-sadetails)-1 - , "%sIPCOMP=>0x%08x <0x%08x" - , ini - , ntohl(st->st_ipcomp.attrs.spi) - , ntohl(st->st_ipcomp.our_spi)); - ini = " "; - fin = "}"; - } - /* advance b to end of string */ - b = b + strlen(b); + switch (kind) + { + case EVENT_RETRANSMIT: /* Retransmit packet */ + delay = EVENT_RETRANSMIT_DELAY_0; + break; - if (st->nat_traversal) - { - char oa[ADDRTOT_BUF]; - addrtot(&st->nat_oa, 0, oa, sizeof(oa)); - snprintf(b, sizeof(sadetails)-(b-sadetails)-1 - , "%sNATOA=%s" - , ini, oa); - ini = " "; - fin = "}"; - } + case EVENT_SA_REPLACE: /* SA replacement event */ + if (IS_PHASE1(st->st_state)) + { + /* Note: we will defer to the "negotiated" (dictated) + * lifetime if we are POLICY_DONT_REKEY. + * This allows the other side to dictate + * a time we would not otherwise accept + * but it prevents us from having to initiate + * rekeying. The negative consequences seem + * minor. + */ + delay = c->sa_ike_life_seconds; + if ((c->policy & POLICY_DONT_REKEY) + || delay >= st->st_oakley.life_seconds) + { + agreed_time = TRUE; + delay = st->st_oakley.life_seconds; + } + } + else + { + /* Delay is min of up to four things: + * each can limit the lifetime. + */ + delay = c->sa_ipsec_life_seconds; + if (st->st_ah.present + && delay >= st->st_ah.attrs.life_seconds) + { + agreed_time = TRUE; + delay = st->st_ah.attrs.life_seconds; + } + if (st->st_esp.present + && delay >= st->st_esp.attrs.life_seconds) + { + agreed_time = TRUE; + delay = st->st_esp.attrs.life_seconds; + } + if (st->st_ipcomp.present + && delay >= st->st_ipcomp.attrs.life_seconds) + { + agreed_time = TRUE; + delay = st->st_ipcomp.attrs.life_seconds; + } + } - /* advance b to end of string */ - b = b + strlen(b); + /* By default, we plan to rekey. + * + * If there isn't enough time to rekey, plan to + * expire. + * + * If we are --dontrekey, a lot more rules apply. + * If we are the Initiator, use REPLACE_IF_USED. + * If we are the Responder, and the dictated time + * was unacceptable (too large), plan to REPLACE + * (the only way to ratchet down the time). + * If we are the Responder, and the dictated time + * is acceptable, plan to EXPIRE. + * + * Important policy lies buried here. + * For example, we favour the initiator over the + * responder by making the initiator start rekeying + * sooner. Also, fuzz is only added to the + * initiator's margin. + * + * Note: for ISAKMP SA, we let the negotiated + * time stand (implemented by earlier logic). + */ + if (agreed_time + && (c->policy & POLICY_DONT_REKEY)) + { + kind = (smc->flags & SMF_INITIATOR) + ? EVENT_SA_REPLACE_IF_USED + : EVENT_SA_EXPIRE; + } + if (kind != EVENT_SA_EXPIRE) + { + unsigned long marg = c->sa_rekey_margin; - if (st->st_dpd) - { - snprintf(b, sizeof(sadetails)-(b-sadetails)-1 - , "%sDPD" - , ini); - ini = " "; - fin = "}"; - } + if (smc->flags & SMF_INITIATOR) + marg += marg + * c->sa_rekey_fuzz / 100.E0 + * (rand() / (RAND_MAX + 1.E0)); + else + marg /= 2; - strcat(b, fin); - } + if ((unsigned long)delay > marg) + { + delay -= marg; + st->st_margin = marg; + } + else + { + kind = EVENT_SA_EXPIRE; + } + } + break; - if (IS_ISAKMP_SA_ESTABLISHED(st->st_state) - || IS_IPSEC_SA_ESTABLISHED(st->st_state)) - { - /* log our success */ - plog("%s%s", story, sadetails); - w = RC_SUCCESS; - } + case EVENT_NULL: /* non-event */ + case EVENT_REINIT_SECRET: /* Refresh cookie secret */ + default: + bad_case(kind); + } + event_schedule(kind, delay, st); + } - /* tell whack our progress */ - whack_log(w - , "%s: %s%s" - , enum_name(&state_names, st->st_state) - , story, sadetails); - } + /* tell whack and log of progress */ + { + const char *story = state_story[st->st_state - STATE_MAIN_R0]; + enum rc_type w = RC_NEW_STATE + st->st_state; + char sadetails[128]; + + sadetails[0]='\0'; - has_xauth_policy = (st->st_connection->policy - & (POLICY_XAUTH_RSASIG | POLICY_XAUTH_PSK)) - != LEMPTY; - is_xauth_server = (st->st_connection->policy - & POLICY_XAUTH_SERVER) - != LEMPTY; + if (IS_IPSEC_SA_ESTABLISHED(st->st_state)) + { + char *b = sadetails; + const char *ini = " {"; + const char *fin = ""; - /* Should we start XAUTH as a server */ - if (has_xauth_policy && is_xauth_server - && IS_ISAKMP_SA_ESTABLISHED(st->st_state) - && !st->st_xauth.started) - { - DBG(DBG_CONTROL, - DBG_log("starting XAUTH server") - ) - xauth_send_request(st); - break; - } + /* -1 is to leave space for "fin" */ - /* Wait for XAUTH request from server */ - if (has_xauth_policy && !is_xauth_server - && IS_ISAKMP_SA_ESTABLISHED(st->st_state) - && !st->st_xauth.started) - { - DBG(DBG_CONTROL, - DBG_log("waiting for XAUTH request from server") - ) - break; - } + if (st->st_esp.present) + { + snprintf(b, sizeof(sadetails)-(b-sadetails)-1 + , "%sESP=>0x%08x <0x%08x" + , ini + , ntohl(st->st_esp.attrs.spi) + , ntohl(st->st_esp.our_spi)); + ini = " "; + fin = "}"; + } + /* advance b to end of string */ + b = b + strlen(b); - /* Should we start ModeConfig as a client? */ - if (st->st_connection->spd.this.modecfg - && IS_ISAKMP_SA_ESTABLISHED(st->st_state) - && !(st->st_connection->policy & POLICY_MODECFG_PUSH) - && !st->st_modecfg.started) - { - DBG(DBG_CONTROL, - DBG_log("starting ModeCfg client in pull mode") - ) - modecfg_send_request(st); - break; - } + if (st->st_ah.present) + { + snprintf(b, sizeof(sadetails)-(b-sadetails)-1 + , "%sAH=>0x%08x <0x%08x" + , ini + , ntohl(st->st_ah.attrs.spi) + , ntohl(st->st_ah.our_spi)); + ini = " "; + fin = "}"; + } + /* advance b to end of string */ + b = b + strlen(b); - /* Should we start ModeConfig as a server? */ - if (st->st_connection->spd.that.modecfg - && IS_ISAKMP_SA_ESTABLISHED(st->st_state) - && !st->st_modecfg.started - && (st->st_connection->policy & POLICY_MODECFG_PUSH)) - { - DBG(DBG_CONTROL, - DBG_log("starting ModeCfg server in push mode") - ) - modecfg_send_set(st); - break; - } + if (st->st_ipcomp.present) + { + snprintf(b, sizeof(sadetails)-(b-sadetails)-1 + , "%sIPCOMP=>0x%08x <0x%08x" + , ini + , ntohl(st->st_ipcomp.attrs.spi) + , ntohl(st->st_ipcomp.our_spi)); + ini = " "; + fin = "}"; + } + /* advance b to end of string */ + b = b + strlen(b); - /* Wait for ModeConfig set from server */ - if (st->st_connection->spd.this.modecfg - && IS_ISAKMP_SA_ESTABLISHED(st->st_state) - && !st->st_modecfg.vars_set) - { - DBG(DBG_CONTROL, - DBG_log("waiting for ModeCfg set from server") - ) - break; - } + if (st->nat_traversal) + { + char oa[ADDRTOT_BUF]; + addrtot(&st->nat_oa, 0, oa, sizeof(oa)); + snprintf(b, sizeof(sadetails)-(b-sadetails)-1 + , "%sNATOA=%s" + , ini, oa); + ini = " "; + fin = "}"; + } - if (smc->flags & SMF_RELEASE_PENDING_P2) - { - /* Initiate any Quick Mode negotiations that - * were waiting to piggyback on this Keying Channel. - * - * ??? there is a potential race condition - * if we are the responder: the initial Phase 2 - * message might outrun the final Phase 1 message. - * I think that retransmission will recover. - */ - unpend(st); - } + /* advance b to end of string */ + b = b + strlen(b); - if (IS_ISAKMP_SA_ESTABLISHED(st->st_state) - || IS_IPSEC_SA_ESTABLISHED(st->st_state)) - release_whack(st); - break; + if (st->st_dpd) + { + snprintf(b, sizeof(sadetails)-(b-sadetails)-1 + , "%sDPD" + , ini); + ini = " "; + fin = "}"; + } - case STF_INTERNAL_ERROR: - whack_log(RC_INTERNALERR + md->note - , "%s: internal error" - , enum_name(&state_names, st->st_state)); + strcat(b, fin); + } - DBG(DBG_CONTROL, - DBG_log("state transition function for %s had internal error" - , enum_name(&state_names, from_state))); - break; + if (IS_ISAKMP_SA_ESTABLISHED(st->st_state) + || IS_IPSEC_SA_ESTABLISHED(st->st_state)) + { + /* log our success */ + plog("%s%s", story, sadetails); + w = RC_SUCCESS; + } - default: /* a shortcut to STF_FAIL, setting md->note */ - passert(result > STF_FAIL); - md->note = result - STF_FAIL; - result = STF_FAIL; - /* FALL THROUGH ... */ - case STF_FAIL: - /* As it is, we act as if this message never happened: - * whatever retrying was in place, remains in place. - */ - whack_log(RC_NOTIFICATION + md->note - , "%s: %s" - , enum_name(&state_names, (st == NULL)? STATE_MAIN_R0:st->st_state) - , enum_name(¬ification_names, md->note)); + /* tell whack our progress */ + whack_log(w + , "%s: %s%s" + , enum_name(&state_names, st->st_state) + , story, sadetails); + } - SEND_NOTIFICATION(md->note); + has_xauth_policy = (st->st_connection->policy + & (POLICY_XAUTH_RSASIG | POLICY_XAUTH_PSK)) + != LEMPTY; + is_xauth_server = (st->st_connection->policy + & POLICY_XAUTH_SERVER) + != LEMPTY; - DBG(DBG_CONTROL, - DBG_log("state transition function for %s failed: %s" - , enum_name(&state_names, from_state) - , enum_name(¬ification_names, md->note))); - break; - } + /* Should we start XAUTH as a server */ + if (has_xauth_policy && is_xauth_server + && IS_ISAKMP_SA_ESTABLISHED(st->st_state) + && !st->st_xauth.started) + { + DBG(DBG_CONTROL, + DBG_log("starting XAUTH server") + ) + xauth_send_request(st); + break; + } + + /* Wait for XAUTH request from server */ + if (has_xauth_policy && !is_xauth_server + && IS_ISAKMP_SA_ESTABLISHED(st->st_state) + && !st->st_xauth.started) + { + DBG(DBG_CONTROL, + DBG_log("waiting for XAUTH request from server") + ) + break; + } + + /* Should we start ModeConfig as a client? */ + if (st->st_connection->spd.this.modecfg + && IS_ISAKMP_SA_ESTABLISHED(st->st_state) + && !(st->st_connection->policy & POLICY_MODECFG_PUSH) + && !st->st_modecfg.started) + { + DBG(DBG_CONTROL, + DBG_log("starting ModeCfg client in pull mode") + ) + modecfg_send_request(st); + break; + } + + /* Should we start ModeConfig as a server? */ + if (st->st_connection->spd.that.modecfg + && IS_ISAKMP_SA_ESTABLISHED(st->st_state) + && !st->st_modecfg.started + && (st->st_connection->policy & POLICY_MODECFG_PUSH)) + { + DBG(DBG_CONTROL, + DBG_log("starting ModeCfg server in push mode") + ) + modecfg_send_set(st); + break; + } + + /* Wait for ModeConfig set from server */ + if (st->st_connection->spd.this.modecfg + && IS_ISAKMP_SA_ESTABLISHED(st->st_state) + && !st->st_modecfg.vars_set) + { + DBG(DBG_CONTROL, + DBG_log("waiting for ModeCfg set from server") + ) + break; + } + + if (smc->flags & SMF_RELEASE_PENDING_P2) + { + /* Initiate any Quick Mode negotiations that + * were waiting to piggyback on this Keying Channel. + * + * ??? there is a potential race condition + * if we are the responder: the initial Phase 2 + * message might outrun the final Phase 1 message. + * I think that retransmission will recover. + */ + unpend(st); + } + + if (IS_ISAKMP_SA_ESTABLISHED(st->st_state) + || IS_IPSEC_SA_ESTABLISHED(st->st_state)) + release_whack(st); + break; + + case STF_INTERNAL_ERROR: + whack_log(RC_INTERNALERR + md->note + , "%s: internal error" + , enum_name(&state_names, st->st_state)); + + DBG(DBG_CONTROL, + DBG_log("state transition function for %s had internal error" + , enum_name(&state_names, from_state))); + break; + + default: /* a shortcut to STF_FAIL, setting md->note */ + passert(result > STF_FAIL); + md->note = result - STF_FAIL; + result = STF_FAIL; + /* FALL THROUGH ... */ + case STF_FAIL: + /* As it is, we act as if this message never happened: + * whatever retrying was in place, remains in place. + */ + whack_log(RC_NOTIFICATION + md->note + , "%s: %s" + , enum_name(&state_names, (st == NULL)? STATE_MAIN_R0:st->st_state) + , enum_name(¬ification_names, md->note)); + + SEND_NOTIFICATION(md->note); + + DBG(DBG_CONTROL, + DBG_log("state transition function for %s failed: %s" + , enum_name(&state_names, from_state) + , enum_name(¬ification_names, md->note))); + break; + } } diff --git a/src/pluto/demux.h b/src/pluto/demux.h index a012b2d80..020ce7012 100644 --- a/src/pluto/demux.h +++ b/src/pluto/demux.h @@ -16,7 +16,7 @@ #include "packet.h" -struct state; /* forward declaration of tag */ +struct state; /* forward declaration of tag */ extern void init_demux(void); extern bool send_packet(struct state *st, const char *where); extern void comm_handle(const struct iface *ifp); @@ -36,9 +36,9 @@ extern u_int8_t reply_buffer[MAX_OUTPUT_UDP_SIZE]; */ struct payload_digest { - pb_stream pbs; - union payload payload; - struct payload_digest *next; /* of same kind */ + pb_stream pbs; + union payload payload; + struct payload_digest *next; /* of same kind */ }; /* message digest @@ -46,30 +46,30 @@ struct payload_digest { */ struct msg_digest { - struct msg_digest *next; /* for free list */ - chunk_t raw_packet; /* if encrypted, received packet before decryption */ - const struct iface *iface; /* interface on which message arrived */ - ip_address sender; /* where message came from */ - u_int16_t sender_port; /* host order */ - pb_stream packet_pbs; /* whole packet */ - pb_stream message_pbs; /* message to be processed */ - struct isakmp_hdr hdr; /* message's header */ - bool encrypted; /* was it encrypted? */ - enum state_kind from_state; /* state we started in */ - const struct state_microcode *smc; /* microcode for initial state */ - struct state *st; /* current state object */ - pb_stream reply; /* room for reply */ - pb_stream rbody; /* room for reply body (after header) */ - notification_t note; /* reason for failure */ - bool dpd; /* peer supports RFC 3706 DPD */ - bool openpgp; /* peer supports OpenPGP certificates */ + struct msg_digest *next; /* for free list */ + chunk_t raw_packet; /* if encrypted, received packet before decryption */ + const struct iface *iface; /* interface on which message arrived */ + ip_address sender; /* where message came from */ + u_int16_t sender_port; /* host order */ + pb_stream packet_pbs; /* whole packet */ + pb_stream message_pbs; /* message to be processed */ + struct isakmp_hdr hdr; /* message's header */ + bool encrypted; /* was it encrypted? */ + enum state_kind from_state; /* state we started in */ + const struct state_microcode *smc; /* microcode for initial state */ + struct state *st; /* current state object */ + pb_stream reply; /* room for reply */ + pb_stream rbody; /* room for reply body (after header) */ + notification_t note; /* reason for failure */ + bool dpd; /* peer supports RFC 3706 DPD */ + bool openpgp; /* peer supports OpenPGP certificates */ # define PAYLIMIT 40 - struct payload_digest - digest[PAYLIMIT], - *digest_roof, - *chain[ISAKMP_NEXT_ROOF]; - unsigned short nat_traversal_vid; + struct payload_digest + digest[PAYLIMIT], + *digest_roof, + *chain[ISAKMP_NEXT_ROOF]; + unsigned short nat_traversal_vid; }; extern void release_md(struct msg_digest *md); @@ -79,11 +79,11 @@ extern void release_md(struct msg_digest *md); */ typedef enum { - STF_IGNORE, /* don't respond */ - STF_SUSPEND, /* unfinished -- don't release resources */ - STF_OK, /* success */ - STF_INTERNAL_ERROR, /* discard everything, we failed */ - STF_FAIL /* discard everything, something failed. notification_t added. */ + STF_IGNORE, /* don't respond */ + STF_SUSPEND, /* unfinished -- don't release resources */ + STF_OK, /* success */ + STF_INTERNAL_ERROR, /* discard everything, we failed */ + STF_FAIL /* discard everything, something failed. notification_t added. */ } stf_status; typedef stf_status state_transition_fn(struct msg_digest *md); diff --git a/src/pluto/dnskey.c b/src/pluto/dnskey.c index 18e36ab94..45e451673 100644 --- a/src/pluto/dnskey.c +++ b/src/pluto/dnskey.c @@ -26,32 +26,32 @@ #include #include #include -#include /* ??? for h_errno */ +#include /* ??? for h_errno */ #include #include #include #include "constants.h" -#include "adns.h" /* needs */ +#include "adns.h" /* needs */ #include "defs.h" #include "log.h" #include "id.h" #include "connections.h" -#include "keys.h" /* needs connections.h */ +#include "keys.h" /* needs connections.h */ #include "dnskey.h" #include "packet.h" #include "timer.h" /* somebody has to decide */ -#define MAX_TXT_RDATA ((MAX_KEY_BYTES * 8 / 6) + 40) /* somewhat arbitrary overkill */ +#define MAX_TXT_RDATA ((MAX_KEY_BYTES * 8 / 6) + 40) /* somewhat arbitrary overkill */ /* ADNS stuff */ -int adns_qfd = NULL_FD, /* file descriptor for sending queries to adns (O_NONBLOCK) */ - adns_afd = NULL_FD; /* file descriptor for receiving answers from adns */ +int adns_qfd = NULL_FD, /* file descriptor for sending queries to adns (O_NONBLOCK) */ + adns_afd = NULL_FD; /* file descriptor for receiving answers from adns */ static pid_t adns_pid = 0; -const char *pluto_adns_option = NULL; /* path from --pluto_adns */ +const char *pluto_adns_option = NULL; /* path from --pluto_adns */ int adns_restart_count; #define ADNS_RESTART_MAX 20 @@ -59,152 +59,152 @@ int adns_restart_count; void init_adns(void) { - const char *adns_path = pluto_adns_option; + const char *adns_path = pluto_adns_option; #ifndef USE_LWRES - static const char adns_name[] = "_pluto_adns"; - const char *helper_bin_dir = getenv("IPSEC_LIBDIR"); + static const char adns_name[] = "_pluto_adns"; + const char *helper_bin_dir = getenv("IPSEC_LIBDIR"); #else /* USE_LWRES */ - static const char adns_name[] = "lwdnsq"; - const char *helper_bin_dir = getenv("IPSEC_EXECDIR"); + static const char adns_name[] = "lwdnsq"; + const char *helper_bin_dir = getenv("IPSEC_EXECDIR"); #endif /* USE_LWRES */ - char adns_path_space[4096]; /* plenty long? */ - int qfds[2]; - int afds[2]; + char adns_path_space[4096]; /* plenty long? */ + int qfds[2]; + int afds[2]; - /* find a pathname to the ADNS program */ - if (adns_path == NULL) - { - /* pathname was not specified as an option: build it. - * First, figure out the directory to be used. - */ - ssize_t n; - - if (helper_bin_dir != NULL) + /* find a pathname to the ADNS program */ + if (adns_path == NULL) { - n = strlen(helper_bin_dir); - if ((size_t)n <= sizeof(adns_path_space) - sizeof(adns_name)) - { - strcpy(adns_path_space, helper_bin_dir); - if (n > 0 && adns_path_space[n -1] != '/') - adns_path_space[n++] = '/'; - } + /* pathname was not specified as an option: build it. + * First, figure out the directory to be used. + */ + ssize_t n; + + if (helper_bin_dir != NULL) + { + n = strlen(helper_bin_dir); + if ((size_t)n <= sizeof(adns_path_space) - sizeof(adns_name)) + { + strcpy(adns_path_space, helper_bin_dir); + if (n > 0 && adns_path_space[n -1] != '/') + adns_path_space[n++] = '/'; + } + } + else + { + /* The program will be in the same directory as Pluto, + * so we use the sympolic link /proc/self/exe to + * tell us of the path prefix. + */ + n = readlink("/proc/self/exe", adns_path_space, sizeof(adns_path_space)); + + if (n < 0) + exit_log_errno((e + , "readlink(\"/proc/self/exe\") failed in init_adns()")); + + } + + if ((size_t)n > sizeof(adns_path_space) - sizeof(adns_name)) + exit_log("path to %s is too long", adns_name); + + while (n > 0 && adns_path_space[n - 1] != '/') + n--; + + strcpy(adns_path_space + n, adns_name); + adns_path = adns_path_space; } - else + if (access(adns_path, X_OK) < 0) + exit_log_errno((e, "%s missing or not executable", adns_path)); + + if (pipe(qfds) != 0 || pipe(afds) != 0) + exit_log_errno((e, "pipe(2) failed in init_adns()")); + + adns_pid = fork(); + switch (adns_pid) { - /* The program will be in the same directory as Pluto, - * so we use the sympolic link /proc/self/exe to - * tell us of the path prefix. - */ - n = readlink("/proc/self/exe", adns_path_space, sizeof(adns_path_space)); + case -1: + exit_log_errno((e, "fork() failed in init_adns()")); - if (n < 0) - exit_log_errno((e - , "readlink(\"/proc/self/exe\") failed in init_adns()")); + case 0: + /* child */ + { + /* Make stdin and stdout our pipes. + * Take care to handle case where pipes already use these fds. + */ + if (afds[1] == 0) + afds[1] = dup(afds[1]); /* avoid being overwritten */ + if (qfds[0] != 0) + { + dup2(qfds[0], 0); + close(qfds[0]); + } + if (afds[1] != 1) + { + dup2(afds[1], 1); + close(qfds[1]); + } + if (afds[0] > 1) + close(afds[0]); + if (afds[1] > 1) + close(afds[1]); - } + DBG(DBG_DNS, execlp(adns_path, adns_name, "-d", NULL)); - if ((size_t)n > sizeof(adns_path_space) - sizeof(adns_name)) - exit_log("path to %s is too long", adns_name); + execlp(adns_path, adns_name, NULL); + exit_log_errno((e, "execlp of %s failed", adns_path)); + } - while (n > 0 && adns_path_space[n - 1] != '/') - n--; - - strcpy(adns_path_space + n, adns_name); - adns_path = adns_path_space; - } - if (access(adns_path, X_OK) < 0) - exit_log_errno((e, "%s missing or not executable", adns_path)); - - if (pipe(qfds) != 0 || pipe(afds) != 0) - exit_log_errno((e, "pipe(2) failed in init_adns()")); - - adns_pid = fork(); - switch (adns_pid) - { - case -1: - exit_log_errno((e, "fork() failed in init_adns()")); - - case 0: - /* child */ - { - /* Make stdin and stdout our pipes. - * Take care to handle case where pipes already use these fds. - */ - if (afds[1] == 0) - afds[1] = dup(afds[1]); /* avoid being overwritten */ - if (qfds[0] != 0) - { - dup2(qfds[0], 0); + default: + /* parent */ close(qfds[0]); - } - if (afds[1] != 1) - { - dup2(afds[1], 1); - close(qfds[1]); - } - if (afds[0] > 1) - close(afds[0]); - if (afds[1] > 1) + adns_qfd = qfds[1]; + adns_afd = afds[0]; close(afds[1]); - - DBG(DBG_DNS, execlp(adns_path, adns_name, "-d", NULL)); - - execlp(adns_path, adns_name, NULL); - exit_log_errno((e, "execlp of %s failed", adns_path)); + fcntl(adns_qfd, F_SETFD, FD_CLOEXEC); + fcntl(adns_afd, F_SETFD, FD_CLOEXEC); + fcntl(adns_qfd, F_SETFL, O_NONBLOCK); + break; } - - default: - /* parent */ - close(qfds[0]); - adns_qfd = qfds[1]; - adns_afd = afds[0]; - close(afds[1]); - fcntl(adns_qfd, F_SETFD, FD_CLOEXEC); - fcntl(adns_afd, F_SETFD, FD_CLOEXEC); - fcntl(adns_qfd, F_SETFL, O_NONBLOCK); - break; - } } void stop_adns(void) { - close_any(adns_qfd); - adns_qfd = NULL_FD; - close_any(adns_afd); - adns_afd = NULL_FD; + close_any(adns_qfd); + adns_qfd = NULL_FD; + close_any(adns_afd); + adns_afd = NULL_FD; - if (adns_pid != 0) - { - int status; - pid_t p = waitpid(adns_pid, &status, 0); + if (adns_pid != 0) + { + int status; + pid_t p = waitpid(adns_pid, &status, 0); - if (p == -1) - { - log_errno((e, "waitpid for ADNS process failed")); + if (p == -1) + { + log_errno((e, "waitpid for ADNS process failed")); + } + else if (WIFEXITED(status)) + { + if (WEXITSTATUS(status) != 0) + plog("ADNS process exited with status %d" + , (int) WEXITSTATUS(status)); + } + else if (WIFSIGNALED(status)) + { + plog("ADNS process terminated by signal %d", (int)WTERMSIG(status)); + } + else + { + plog("wait for end of ADNS process returned odd status 0x%x\n" + , status); + } } - else if (WIFEXITED(status)) - { - if (WEXITSTATUS(status) != 0) - plog("ADNS process exited with status %d" - , (int) WEXITSTATUS(status)); - } - else if (WIFSIGNALED(status)) - { - plog("ADNS process terminated by signal %d", (int)WTERMSIG(status)); - } - else - { - plog("wait for end of ADNS process returned odd status 0x%x\n" - , status); - } - } } /* tricky macro to pass any hot potato */ -#define TRY(x) { err_t ugh = x; if (ugh != NULL) return ugh; } +#define TRY(x) { err_t ugh = x; if (ugh != NULL) return ugh; } /* Process TXT X-IPsec-Server record, accumulating relevant ones @@ -225,246 +225,246 @@ static const char our_TXT_attr[] = our_TXT_attr_string; static err_t decode_iii(u_char **pp, struct id *gw_id) { - u_char *p = *pp + strspn(*pp, " \t"); - u_char *e = p + strcspn(p, " \t"); - u_char under = *e; + u_char *p = *pp + strspn(*pp, " \t"); + u_char *e = p + strcspn(p, " \t"); + u_char under = *e; - if (p == e) - return "TXT " our_TXT_attr_string " badly formed (no gateway specified)"; + if (p == e) + return "TXT " our_TXT_attr_string " badly formed (no gateway specified)"; - *e = '\0'; - if (*p == '@') - { - /* gateway specification in this record is @FQDN */ - err_t ugh = atoid(p, gw_id, FALSE); + *e = '\0'; + if (*p == '@') + { + /* gateway specification in this record is @FQDN */ + err_t ugh = atoid(p, gw_id, FALSE); - if (ugh != NULL) - return builddiag("malformed FQDN in TXT " our_TXT_attr_string ": %s" - , ugh); - } - else - { - /* gateway specification is numeric */ - ip_address ip; - err_t ugh = tnatoaddr(p, e-p - , strchr(p, ':') == NULL? AF_INET : AF_INET6 - , &ip); + if (ugh != NULL) + return builddiag("malformed FQDN in TXT " our_TXT_attr_string ": %s" + , ugh); + } + else + { + /* gateway specification is numeric */ + ip_address ip; + err_t ugh = tnatoaddr(p, e-p + , strchr(p, ':') == NULL? AF_INET : AF_INET6 + , &ip); - if (ugh != NULL) - return builddiag("malformed IP address in TXT " our_TXT_attr_string ": %s" - , ugh); + if (ugh != NULL) + return builddiag("malformed IP address in TXT " our_TXT_attr_string ": %s" + , ugh); - if (isanyaddr(&ip)) - return "gateway address must not be 0.0.0.0 or 0::0"; + if (isanyaddr(&ip)) + return "gateway address must not be 0.0.0.0 or 0::0"; - iptoid(&ip, gw_id); - } + iptoid(&ip, gw_id); + } - *e = under; - *pp = e + strspn(e, " \t"); + *e = under; + *pp = e + strspn(e, " \t"); - return NULL; + return NULL; } static err_t process_txt_rr_body(u_char *str -, bool doit /* should we capture information? */ +, bool doit /* should we capture information? */ , enum dns_auth_level dns_auth_level , struct adns_continuation *const cr) { - const struct id *client_id = &cr->id; /* subject of query */ - u_char *p = str; - unsigned long pref = 0; - struct gw_info gi; + const struct id *client_id = &cr->id; /* subject of query */ + u_char *p = str; + unsigned long pref = 0; + struct gw_info gi; - p += strspn(p, " \t"); /* ignore leading whitespace */ + p += strspn(p, " \t"); /* ignore leading whitespace */ - /* is this for us? */ - if (strncasecmp(p, our_TXT_attr, sizeof(our_TXT_attr)-1) != 0) - return NULL; /* neither interesting nor bad */ + /* is this for us? */ + if (strncasecmp(p, our_TXT_attr, sizeof(our_TXT_attr)-1) != 0) + return NULL; /* neither interesting nor bad */ - p += sizeof(our_TXT_attr) - 1; /* ignore our attribute name */ - p += strspn(p, " \t"); /* ignore leading whitespace */ + p += sizeof(our_TXT_attr) - 1; /* ignore our attribute name */ + p += strspn(p, " \t"); /* ignore leading whitespace */ - /* decode '(' nnn ')' */ - if (*p != '(') - return "X-IPsec-Server missing '('"; + /* decode '(' nnn ')' */ + if (*p != '(') + return "X-IPsec-Server missing '('"; - { - char *e; + { + char *e; - p++; - pref = strtoul(p, &e, 0); - if ((u_char *)e == p) - return "malformed X-IPsec-Server priority"; + p++; + pref = strtoul(p, &e, 0); + if ((u_char *)e == p) + return "malformed X-IPsec-Server priority"; - p = e + strspn(e, " \t"); + p = e + strspn(e, " \t"); - if (*p != ')') - return "X-IPsec-Server priority missing ')'"; + if (*p != ')') + return "X-IPsec-Server priority missing ')'"; + + p++; + p += strspn(p, " \t"); + + if (pref > 0xFFFF) + return "X-IPsec-Server priority larger than 0xFFFF"; + } + + /* time for '=' */ + + if (*p != '=') + return "X-IPsec-Server priority missing '='"; p++; p += strspn(p, " \t"); - if (pref > 0xFFFF) - return "X-IPsec-Server priority larger than 0xFFFF"; - } + /* Decode iii (Security Gateway ID). */ - /* time for '=' */ + zero(&gi); /* before first use */ - if (*p != '=') - return "X-IPsec-Server priority missing '='"; + TRY(decode_iii(&p, &gi.gw_id)); /* will need to unshare_id_content */ - p++; - p += strspn(p, " \t"); - - /* Decode iii (Security Gateway ID). */ - - zero(&gi); /* before first use */ - - TRY(decode_iii(&p, &gi.gw_id)); /* will need to unshare_id_content */ - - if (!cr->sgw_specified) - { - /* we don't know the peer's ID (because we are initiating - * and we don't know who to initiate with. - * So we're looking for gateway specs with an IP address - */ - if (!id_is_ipaddr(&gi.gw_id)) + if (!cr->sgw_specified) { - DBG(DBG_DNS, + /* we don't know the peer's ID (because we are initiating + * and we don't know who to initiate with. + * So we're looking for gateway specs with an IP address + */ + if (!id_is_ipaddr(&gi.gw_id)) { - char cidb[BUF_LEN]; - char gwidb[BUF_LEN]; + DBG(DBG_DNS, + { + char cidb[BUF_LEN]; + char gwidb[BUF_LEN]; - idtoa(client_id, cidb, sizeof(cidb)); - idtoa(&gi.gw_id, gwidb, sizeof(gwidb)); - DBG_log("TXT %s record for %s: security gateway %s;" - " ignored because gateway's IP is unspecified" - , our_TXT_attr, cidb, gwidb); - }); - return NULL; /* we cannot use this record, but it isn't wrong */ + idtoa(client_id, cidb, sizeof(cidb)); + idtoa(&gi.gw_id, gwidb, sizeof(gwidb)); + DBG_log("TXT %s record for %s: security gateway %s;" + " ignored because gateway's IP is unspecified" + , our_TXT_attr, cidb, gwidb); + }); + return NULL; /* we cannot use this record, but it isn't wrong */ + } } - } - else - { - /* We do know the peer's ID (because we are responding) - * So we're looking for gateway specs specifying this known ID. - */ - const struct id *peer_id = &cr->sgw_id; - - if (!same_id(peer_id, &gi.gw_id)) + else { - DBG(DBG_DNS, + /* We do know the peer's ID (because we are responding) + * So we're looking for gateway specs specifying this known ID. + */ + const struct id *peer_id = &cr->sgw_id; + + if (!same_id(peer_id, &gi.gw_id)) { - char cidb[BUF_LEN]; - char gwidb[BUF_LEN]; - char pidb[BUF_LEN]; + DBG(DBG_DNS, + { + char cidb[BUF_LEN]; + char gwidb[BUF_LEN]; + char pidb[BUF_LEN]; - idtoa(client_id, cidb, sizeof(cidb)); - idtoa(&gi.gw_id, gwidb, sizeof(gwidb)); - idtoa(peer_id, pidb, sizeof(pidb)); - DBG_log("TXT %s record for %s: security gateway %s;" - " ignored -- looking to confirm %s as gateway" - , our_TXT_attr, cidb, gwidb, pidb); - }); - return NULL; /* we cannot use this record, but it isn't wrong */ + idtoa(client_id, cidb, sizeof(cidb)); + idtoa(&gi.gw_id, gwidb, sizeof(gwidb)); + idtoa(peer_id, pidb, sizeof(pidb)); + DBG_log("TXT %s record for %s: security gateway %s;" + " ignored -- looking to confirm %s as gateway" + , our_TXT_attr, cidb, gwidb, pidb); + }); + return NULL; /* we cannot use this record, but it isn't wrong */ + } } - } - if (doit) - { - /* really accept gateway */ - struct gw_info **gwip; /* gateway insertion point */ - - gi.client_id = *client_id; /* will need to unshare_id_content */ - - /* decode optional kkk: base 64 encoding of key */ - - gi.gw_key_present = *p != '\0'; - if (gi.gw_key_present) + if (doit) { - /* Decode base 64 encoding of key. - * Similar code is in process_lwdnsq_key. - */ - u_char kb[RSA_MAX_ENCODING_BYTES]; /* plenty of space for binary form of public key */ - chunk_t kbc; - struct RSA_public_key r; + /* really accept gateway */ + struct gw_info **gwip; /* gateway insertion point */ - err_t ugh = ttodatav(p, 0, 64, kb, sizeof(kb), &kbc.len - , diag_space, sizeof(diag_space), TTODATAV_SPACECOUNTS); + gi.client_id = *client_id; /* will need to unshare_id_content */ - if (ugh != NULL) - return builddiag("malformed key data: %s", ugh); + /* decode optional kkk: base 64 encoding of key */ - if (kbc.len > sizeof(kb)) - return builddiag("key data larger than %lu bytes" - , (unsigned long) sizeof(kb)); - - kbc.ptr = kb; - ugh = unpack_RSA_public_key(&r, &kbc); - if (ugh != NULL) - return builddiag("invalid key data: %s", ugh); - - /* now find a key entry to put it in */ - gi.key = public_key_from_rsa(&r); - - free_RSA_public_content(&r); - - unreference_key(&cr->last_info); - cr->last_info = reference_key(gi.key); - } - - /* we're home free! Allocate everything and add to gateways list. */ - gi.refcnt = 1; - gi.pref = pref; - gi.key->dns_auth_level = dns_auth_level; - gi.key->last_tried_time = gi.key->last_worked_time = NO_TIME; - - /* find insertion point */ - for (gwip = &cr->gateways_from_dns; *gwip != NULL && (*gwip)->pref < pref; gwip = &(*gwip)->next) - ; - - DBG(DBG_DNS, - { - char cidb[BUF_LEN]; - char gwidb[BUF_LEN]; - - idtoa(client_id, cidb, sizeof(cidb)); - idtoa(&gi.gw_id, gwidb, sizeof(gwidb)); + gi.gw_key_present = *p != '\0'; if (gi.gw_key_present) { - DBG_log("gateway for %s is %s with key %s" - , cidb, gwidb, gi.key->u.rsa.keyid); - } - else - { - DBG_log("gateway for %s is %s; no key specified" - , cidb, gwidb); - } - }); + /* Decode base 64 encoding of key. + * Similar code is in process_lwdnsq_key. + */ + u_char kb[RSA_MAX_ENCODING_BYTES]; /* plenty of space for binary form of public key */ + chunk_t kbc; + struct RSA_public_key r; - gi.next = *gwip; - *gwip = clone_thing(gi); - unshare_id_content(&(*gwip)->gw_id); - unshare_id_content(&(*gwip)->client_id); - } + err_t ugh = ttodatav(p, 0, 64, kb, sizeof(kb), &kbc.len + , diag_space, sizeof(diag_space), TTODATAV_SPACECOUNTS); - return NULL; + if (ugh != NULL) + return builddiag("malformed key data: %s", ugh); + + if (kbc.len > sizeof(kb)) + return builddiag("key data larger than %lu bytes" + , (unsigned long) sizeof(kb)); + + kbc.ptr = kb; + ugh = unpack_RSA_public_key(&r, &kbc); + if (ugh != NULL) + return builddiag("invalid key data: %s", ugh); + + /* now find a key entry to put it in */ + gi.key = public_key_from_rsa(&r); + + free_RSA_public_content(&r); + + unreference_key(&cr->last_info); + cr->last_info = reference_key(gi.key); + } + + /* we're home free! Allocate everything and add to gateways list. */ + gi.refcnt = 1; + gi.pref = pref; + gi.key->dns_auth_level = dns_auth_level; + gi.key->last_tried_time = gi.key->last_worked_time = NO_TIME; + + /* find insertion point */ + for (gwip = &cr->gateways_from_dns; *gwip != NULL && (*gwip)->pref < pref; gwip = &(*gwip)->next) + ; + + DBG(DBG_DNS, + { + char cidb[BUF_LEN]; + char gwidb[BUF_LEN]; + + idtoa(client_id, cidb, sizeof(cidb)); + idtoa(&gi.gw_id, gwidb, sizeof(gwidb)); + if (gi.gw_key_present) + { + DBG_log("gateway for %s is %s with key %s" + , cidb, gwidb, gi.key->u.rsa.keyid); + } + else + { + DBG_log("gateway for %s is %s; no key specified" + , cidb, gwidb); + } + }); + + gi.next = *gwip; + *gwip = clone_thing(gi); + unshare_id_content(&(*gwip)->gw_id); + unshare_id_content(&(*gwip)->client_id); + } + + return NULL; } static const char * rr_typename(int type) { - switch (type) - { - case T_TXT: - return "TXT"; - case T_KEY: - return "KEY"; - default: - return "???"; - } + switch (type) + { + case T_TXT: + return "TXT"; + case T_KEY: + return "KEY"; + default: + return "???"; + } } @@ -476,72 +476,72 @@ process_lwdnsq_key(u_char *str , enum dns_auth_level dns_auth_level , struct adns_continuation *const cr) { - /* fields of KEY record. See RFC 2535 3.1 KEY RDATA format. */ - unsigned long flags /* 16 bits */ - , protocol /* 8 bits */ - , algorithm; /* 8 bits */ + /* fields of KEY record. See RFC 2535 3.1 KEY RDATA format. */ + unsigned long flags /* 16 bits */ + , protocol /* 8 bits */ + , algorithm; /* 8 bits */ - char *rest = str - , *p - , *endofnumber; + char *rest = str + , *p + , *endofnumber; - /* flags */ - p = strsep(&rest, " \t"); - if (p == NULL) - return "lwdnsq KEY: missing flags"; + /* flags */ + p = strsep(&rest, " \t"); + if (p == NULL) + return "lwdnsq KEY: missing flags"; - flags = strtoul(p, &endofnumber, 10); - if (*endofnumber != '\0') - return "lwdnsq KEY: malformed flags"; + flags = strtoul(p, &endofnumber, 10); + if (*endofnumber != '\0') + return "lwdnsq KEY: malformed flags"; - /* protocol */ - p = strsep(&rest, " \t"); - if (p == NULL) - return "lwdnsq KEY: missing protocol"; + /* protocol */ + p = strsep(&rest, " \t"); + if (p == NULL) + return "lwdnsq KEY: missing protocol"; - protocol = strtoul(p, &endofnumber, 10); - if (*endofnumber != '\0') - return "lwdnsq KEY: malformed protocol"; + protocol = strtoul(p, &endofnumber, 10); + if (*endofnumber != '\0') + return "lwdnsq KEY: malformed protocol"; - /* algorithm */ - p = strsep(&rest, " \t"); - if (p == NULL) - return "lwdnsq KEY: missing algorithm"; + /* algorithm */ + p = strsep(&rest, " \t"); + if (p == NULL) + return "lwdnsq KEY: missing algorithm"; - algorithm = strtoul(p, &endofnumber, 10); - if (*endofnumber != '\0') - return "lwdnsq KEY: malformed algorithm"; + algorithm = strtoul(p, &endofnumber, 10); + if (*endofnumber != '\0') + return "lwdnsq KEY: malformed algorithm"; - /* is this key interesting? */ - if (protocol == 4 /* IPSEC (RFC 2535 3.1.3) */ - && algorithm == 1 /* RSA/MD5 (RFC 2535 3.2) */ - && (flags & 0x8000ul) == 0 /* use for authentication (3.1.2) */ - && (flags & 0x2CF0ul) == 0) /* must be zero */ - { - /* Decode base 64 encoding of key. - * Similar code is in process_txt_rr_body. - */ - u_char kb[RSA_MAX_ENCODING_BYTES]; /* plenty of space for binary form of public key */ - chunk_t kbc; - err_t ugh = ttodatav(rest, 0, 64, kb, sizeof(kb), &kbc.len - , diag_space, sizeof(diag_space), TTODATAV_IGNORESPACE); + /* is this key interesting? */ + if (protocol == 4 /* IPSEC (RFC 2535 3.1.3) */ + && algorithm == 1 /* RSA/MD5 (RFC 2535 3.2) */ + && (flags & 0x8000ul) == 0 /* use for authentication (3.1.2) */ + && (flags & 0x2CF0ul) == 0) /* must be zero */ + { + /* Decode base 64 encoding of key. + * Similar code is in process_txt_rr_body. + */ + u_char kb[RSA_MAX_ENCODING_BYTES]; /* plenty of space for binary form of public key */ + chunk_t kbc; + err_t ugh = ttodatav(rest, 0, 64, kb, sizeof(kb), &kbc.len + , diag_space, sizeof(diag_space), TTODATAV_IGNORESPACE); - if (ugh != NULL) - return builddiag("malformed key data: %s", ugh); + if (ugh != NULL) + return builddiag("malformed key data: %s", ugh); - if (kbc.len > sizeof(kb)) - return builddiag("key data larger than %lu bytes" - , (unsigned long) sizeof(kb)); + if (kbc.len > sizeof(kb)) + return builddiag("key data larger than %lu bytes" + , (unsigned long) sizeof(kb)); - kbc.ptr = kb; - TRY(add_public_key(&cr->id, dns_auth_level, PUBKEY_ALG_RSA, &kbc - , &cr->keys_from_dns)); + kbc.ptr = kb; + TRY(add_public_key(&cr->id, dns_auth_level, PUBKEY_ALG_RSA, &kbc + , &cr->keys_from_dns)); - /* keep a reference to last one */ - unreference_key(&cr->last_info); - cr->last_info = reference_key(cr->keys_from_dns->key); - } - return NULL; + /* keep a reference to last one */ + unreference_key(&cr->last_info); + cr->last_info = reference_key(cr->keys_from_dns->key); + } + return NULL; } # endif /* USE_KEYRR */ @@ -580,158 +580,158 @@ process_lwdnsq_key(u_char *str * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ struct qr_header { - u_int16_t id; /* 16-bit identifier to match query */ + u_int16_t id; /* 16-bit identifier to match query */ - u_int16_t stuff; /* packed crud: */ + u_int16_t stuff; /* packed crud: */ -#define QRS_QR 0x8000 /* QR: on if this is a response */ +#define QRS_QR 0x8000 /* QR: on if this is a response */ -#define QRS_OPCODE_SHIFT 11 /* OPCODE field */ -#define QRS_OPCODE_MASK 0xF -#define QRSO_QUERY 0 /* standard query */ -#define QRSO_IQUERY 1 /* inverse query */ -#define QRSO_STATUS 2 /* server status request query */ +#define QRS_OPCODE_SHIFT 11 /* OPCODE field */ +#define QRS_OPCODE_MASK 0xF +#define QRSO_QUERY 0 /* standard query */ +#define QRSO_IQUERY 1 /* inverse query */ +#define QRSO_STATUS 2 /* server status request query */ -#define QRS_AA 0x0400 /* AA: on if Authoritative Answer */ -#define QRS_TC 0x0200 /* TC: on if truncation happened */ -#define QRS_RD 0x0100 /* RD: on if recursion desired */ -#define QRS_RA 0x0080 /* RA: on if recursion available */ -#define QRS_Z 0x0040 /* Z: reserved; must be zero */ -#define QRS_AD 0x0020 /* AD: on if authentic data (RFC 2535) */ -#define QRS_CD 0x0010 /* AD: on if checking disabled (RFC 2535) */ +#define QRS_AA 0x0400 /* AA: on if Authoritative Answer */ +#define QRS_TC 0x0200 /* TC: on if truncation happened */ +#define QRS_RD 0x0100 /* RD: on if recursion desired */ +#define QRS_RA 0x0080 /* RA: on if recursion available */ +#define QRS_Z 0x0040 /* Z: reserved; must be zero */ +#define QRS_AD 0x0020 /* AD: on if authentic data (RFC 2535) */ +#define QRS_CD 0x0010 /* AD: on if checking disabled (RFC 2535) */ -#define QRS_RCODE_SHIFT 0 /* RCODE field: response code */ -#define QRS_RCODE_MASK 0xF -#define QRSR_OK 0 +#define QRS_RCODE_SHIFT 0 /* RCODE field: response code */ +#define QRS_RCODE_MASK 0xF +#define QRSR_OK 0 - u_int16_t qdcount; /* number of entries in question section */ - u_int16_t ancount; /* number of resource records in answer section */ - u_int16_t nscount; /* number of name server resource records in authority section */ - u_int16_t arcount; /* number of resource records in additional records section */ + u_int16_t qdcount; /* number of entries in question section */ + u_int16_t ancount; /* number of resource records in answer section */ + u_int16_t nscount; /* number of name server resource records in authority section */ + u_int16_t arcount; /* number of resource records in additional records section */ }; static field_desc qr_header_fields[] = { - { ft_nat, 16/BITS_PER_BYTE, "ID", NULL }, - { ft_nat, 16/BITS_PER_BYTE, "stuff", NULL }, - { ft_nat, 16/BITS_PER_BYTE, "QD Count", NULL }, - { ft_nat, 16/BITS_PER_BYTE, "Answer Count", NULL }, - { ft_nat, 16/BITS_PER_BYTE, "Authority Count", NULL }, - { ft_nat, 16/BITS_PER_BYTE, "Additional Count", NULL }, - { ft_end, 0, NULL, NULL } + { ft_nat, 16/BITS_PER_BYTE, "ID", NULL }, + { ft_nat, 16/BITS_PER_BYTE, "stuff", NULL }, + { ft_nat, 16/BITS_PER_BYTE, "QD Count", NULL }, + { ft_nat, 16/BITS_PER_BYTE, "Answer Count", NULL }, + { ft_nat, 16/BITS_PER_BYTE, "Authority Count", NULL }, + { ft_nat, 16/BITS_PER_BYTE, "Additional Count", NULL }, + { ft_end, 0, NULL, NULL } }; static struct_desc qr_header_desc = { - "Query Response Header", - qr_header_fields, - sizeof(struct qr_header) + "Query Response Header", + qr_header_fields, + sizeof(struct qr_header) }; /* Messages for codes in RCODE (see RFC 1035 4.1.1) */ static const err_t rcode_text[QRS_RCODE_MASK + 1] = { - NULL, /* not an error */ - "Format error - The name server was unable to interpret the query", - "Server failure - The name server was unable to process this query" - " due to a problem with the name server", - "Name Error - Meaningful only for responses from an authoritative name" - " server, this code signifies that the domain name referenced in" - " the query does not exist", - "Not Implemented - The name server does not support the requested" - " kind of query", - "Refused - The name server refuses to perform the specified operation" - " for policy reasons", - /* the rest are reserved for future use */ - }; + NULL, /* not an error */ + "Format error - The name server was unable to interpret the query", + "Server failure - The name server was unable to process this query" + " due to a problem with the name server", + "Name Error - Meaningful only for responses from an authoritative name" + " server, this code signifies that the domain name referenced in" + " the query does not exist", + "Not Implemented - The name server does not support the requested" + " kind of query", + "Refused - The name server refuses to perform the specified operation" + " for policy reasons", + /* the rest are reserved for future use */ + }; /* throw away a possibly compressed domain name */ static err_t eat_name(pb_stream *pbs) { - u_char name_buf[NS_MAXDNAME + 2]; - u_char *ip = pbs->cur; - unsigned oi = 0; - unsigned jump_count = 0; + u_char name_buf[NS_MAXDNAME + 2]; + u_char *ip = pbs->cur; + unsigned oi = 0; + unsigned jump_count = 0; - for (;;) - { - u_int8_t b; - - if (ip >= pbs->roof) - return "ran out of message while skipping domain name"; - - b = *ip++; - if (jump_count == 0) - pbs->cur = ip; - - if (b == 0) - break; - - switch (b & 0xC0) + for (;;) { - case 0x00: - /* we grab the next b characters */ - if (oi + b > NS_MAXDNAME) - return "domain name too long"; + u_int8_t b; - if (pbs->roof - ip <= b) - return "domain name falls off end of message"; + if (ip >= pbs->roof) + return "ran out of message while skipping domain name"; - if (oi != 0) - name_buf[oi++] = '.'; - - memcpy(name_buf + oi, ip, b); - oi += b; - ip += b; + b = *ip++; if (jump_count == 0) - pbs->cur = ip; - break; - - case 0xC0: - { - unsigned ix; - - if (ip >= pbs->roof) - return "ran out of message in middle of compressed domain name"; - - ix = ((b & ~0xC0u) << 8) | *ip++; - if (jump_count == 0) pbs->cur = ip; - if (ix >= pbs_room(pbs)) - return "impossible compressed domain name"; + if (b == 0) + break; - /* Avoid infinite loop. - * There can be no more jumps than there are bytes - * in the packet. Not a tight limit, but good enough. - */ - jump_count++; - if (jump_count > pbs_room(pbs)) - return "loop in compressed domain name"; + switch (b & 0xC0) + { + case 0x00: + /* we grab the next b characters */ + if (oi + b > NS_MAXDNAME) + return "domain name too long"; - ip = pbs->start + ix; + if (pbs->roof - ip <= b) + return "domain name falls off end of message"; + + if (oi != 0) + name_buf[oi++] = '.'; + + memcpy(name_buf + oi, ip, b); + oi += b; + ip += b; + if (jump_count == 0) + pbs->cur = ip; + break; + + case 0xC0: + { + unsigned ix; + + if (ip >= pbs->roof) + return "ran out of message in middle of compressed domain name"; + + ix = ((b & ~0xC0u) << 8) | *ip++; + if (jump_count == 0) + pbs->cur = ip; + + if (ix >= pbs_room(pbs)) + return "impossible compressed domain name"; + + /* Avoid infinite loop. + * There can be no more jumps than there are bytes + * in the packet. Not a tight limit, but good enough. + */ + jump_count++; + if (jump_count > pbs_room(pbs)) + return "loop in compressed domain name"; + + ip = pbs->start + ix; + } + break; + + default: + return "invalid code in label"; } - break; - - default: - return "invalid code in label"; } - } - name_buf[oi++] = '\0'; + name_buf[oi++] = '\0'; - DBG(DBG_DNS, DBG_log("skipping name %s", name_buf)); + DBG(DBG_DNS, DBG_log("skipping name %s", name_buf)); - return NULL; + return NULL; } static err_t eat_name_helpfully(pb_stream *pbs, const char *context) { - err_t ugh = eat_name(pbs); + err_t ugh = eat_name(pbs); - return ugh == NULL? ugh - : builddiag("malformed name within DNS record of %s: %s", context, ugh); + return ugh == NULL? ugh + : builddiag("malformed name within DNS record of %s: %s", context, ugh); } /* non-variable part of 4.1.2 Question Section entry: @@ -749,20 +749,20 @@ eat_name_helpfully(pb_stream *pbs, const char *context) */ struct qs_fixed { - u_int16_t qtype; - u_int16_t qclass; + u_int16_t qtype; + u_int16_t qclass; }; static field_desc qs_fixed_fields[] = { - { ft_loose_enum, 16/BITS_PER_BYTE, "QTYPE", &rr_qtype_names }, - { ft_loose_enum, 16/BITS_PER_BYTE, "QCLASS", &rr_class_names }, - { ft_end, 0, NULL, NULL } + { ft_loose_enum, 16/BITS_PER_BYTE, "QTYPE", &rr_qtype_names }, + { ft_loose_enum, 16/BITS_PER_BYTE, "QCLASS", &rr_class_names }, + { ft_end, 0, NULL, NULL } }; static struct_desc qs_fixed_desc = { - "Question Section entry fixed part", - qs_fixed_fields, - sizeof(struct qs_fixed) + "Question Section entry fixed part", + qs_fixed_fields, + sizeof(struct qs_fixed) }; /* 4.1.3. Resource record format: @@ -789,26 +789,26 @@ static struct_desc qs_fixed_desc = { */ struct rr_fixed { - u_int16_t type; - u_int16_t class; - u_int32_t ttl; /* actually signed */ - u_int16_t rdlength; + u_int16_t type; + u_int16_t class; + u_int32_t ttl; /* actually signed */ + u_int16_t rdlength; }; static field_desc rr_fixed_fields[] = { - { ft_loose_enum, 16/BITS_PER_BYTE, "type", &rr_type_names }, - { ft_loose_enum, 16/BITS_PER_BYTE, "class", &rr_class_names }, - { ft_nat, 32/BITS_PER_BYTE, "TTL", NULL }, - { ft_nat, 16/BITS_PER_BYTE, "RD length", NULL }, - { ft_end, 0, NULL, NULL } + { ft_loose_enum, 16/BITS_PER_BYTE, "type", &rr_type_names }, + { ft_loose_enum, 16/BITS_PER_BYTE, "class", &rr_class_names }, + { ft_nat, 32/BITS_PER_BYTE, "TTL", NULL }, + { ft_nat, 16/BITS_PER_BYTE, "RD length", NULL }, + { ft_end, 0, NULL, NULL } }; static struct_desc rr_fixed_desc = { - "Resource Record fixed part", - rr_fixed_fields, - /* note: following is tricky: avoids padding problems */ - offsetof(struct rr_fixed, rdlength) + sizeof(u_int16_t) + "Resource Record fixed part", + rr_fixed_fields, + /* note: following is tricky: avoids padding problems */ + offsetof(struct rr_fixed, rdlength) + sizeof(u_int16_t) }; /* RFC 1035 3.3.14: TXT RRs have text in the RDATA field. @@ -830,22 +830,22 @@ static struct_desc rr_fixed_desc = { */ struct key_rdata { - u_int16_t flags; - u_int8_t protocol; - u_int8_t algorithm; + u_int16_t flags; + u_int8_t protocol; + u_int8_t algorithm; }; static field_desc key_rdata_fields[] = { - { ft_nat, 16/BITS_PER_BYTE, "flags", NULL }, - { ft_nat, 8/BITS_PER_BYTE, "protocol", NULL }, - { ft_nat, 8/BITS_PER_BYTE, "algorithm", NULL }, - { ft_end, 0, NULL, NULL } + { ft_nat, 16/BITS_PER_BYTE, "flags", NULL }, + { ft_nat, 8/BITS_PER_BYTE, "protocol", NULL }, + { ft_nat, 8/BITS_PER_BYTE, "algorithm", NULL }, + { ft_end, 0, NULL, NULL } }; static struct_desc key_rdata_desc = { - "KEY RR RData fixed part", - key_rdata_fields, - sizeof(struct key_rdata) + "KEY RR RData fixed part", + key_rdata_fields, + sizeof(struct key_rdata) }; /* RFC 2535 4.1 SIG RDATA format: @@ -872,30 +872,30 @@ static struct_desc key_rdata_desc = { */ struct sig_rdata { - u_int16_t type_covered; - u_int8_t algorithm; - u_int8_t labels; - u_int32_t original_ttl; - u_int32_t sig_expiration; - u_int32_t sig_inception; - u_int16_t key_tag; + u_int16_t type_covered; + u_int8_t algorithm; + u_int8_t labels; + u_int32_t original_ttl; + u_int32_t sig_expiration; + u_int32_t sig_inception; + u_int16_t key_tag; }; static field_desc sig_rdata_fields[] = { - { ft_nat, 16/BITS_PER_BYTE, "type_covered", NULL}, - { ft_nat, 8/BITS_PER_BYTE, "algorithm", NULL}, - { ft_nat, 8/BITS_PER_BYTE, "labels", NULL}, - { ft_nat, 32/BITS_PER_BYTE, "original ttl", NULL}, - { ft_nat, 32/BITS_PER_BYTE, "sig expiration", NULL}, - { ft_nat, 32/BITS_PER_BYTE, "sig inception", NULL}, - { ft_nat, 16/BITS_PER_BYTE, "key tag", NULL}, - { ft_end, 0, NULL, NULL } + { ft_nat, 16/BITS_PER_BYTE, "type_covered", NULL}, + { ft_nat, 8/BITS_PER_BYTE, "algorithm", NULL}, + { ft_nat, 8/BITS_PER_BYTE, "labels", NULL}, + { ft_nat, 32/BITS_PER_BYTE, "original ttl", NULL}, + { ft_nat, 32/BITS_PER_BYTE, "sig expiration", NULL}, + { ft_nat, 32/BITS_PER_BYTE, "sig inception", NULL}, + { ft_nat, 16/BITS_PER_BYTE, "key tag", NULL}, + { ft_end, 0, NULL, NULL } }; static struct_desc sig_rdata_desc = { - "SIG RR RData fixed part", - sig_rdata_fields, - sizeof(struct sig_rdata) + "SIG RR RData fixed part", + sig_rdata_fields, + sizeof(struct sig_rdata) }; /* handle a KEY Resource Record. */ @@ -903,37 +903,37 @@ static struct_desc sig_rdata_desc = { #ifdef USE_KEYRR static err_t process_key_rr(u_char *ptr, size_t len -, bool doit /* should we capture information? */ +, bool doit /* should we capture information? */ , enum dns_auth_level dns_auth_level , struct adns_continuation *const cr) { - pb_stream pbs; - struct key_rdata kr; + pb_stream pbs; + struct key_rdata kr; - if (len < sizeof(struct key_rdata)) - return "KEY Resource Record's RD Length is too small"; + if (len < sizeof(struct key_rdata)) + return "KEY Resource Record's RD Length is too small"; - init_pbs(&pbs, ptr, len, "KEY RR"); + init_pbs(&pbs, ptr, len, "KEY RR"); - if (!in_struct(&kr, &key_rdata_desc, &pbs, NULL)) - return "failed to get fixed part of KEY Resource Record RDATA"; + if (!in_struct(&kr, &key_rdata_desc, &pbs, NULL)) + return "failed to get fixed part of KEY Resource Record RDATA"; - if (kr.protocol == 4 /* IPSEC (RFC 2535 3.1.3) */ - && kr.algorithm == 1 /* RSA/MD5 (RFC 2535 3.2) */ - && (kr.flags & 0x8000) == 0 /* use for authentication (3.1.2) */ - && (kr.flags & 0x2CF0) == 0) /* must be zero */ - { - /* we have what seems to be a tasty key */ - - if (doit) + if (kr.protocol == 4 /* IPSEC (RFC 2535 3.1.3) */ + && kr.algorithm == 1 /* RSA/MD5 (RFC 2535 3.2) */ + && (kr.flags & 0x8000) == 0 /* use for authentication (3.1.2) */ + && (kr.flags & 0x2CF0) == 0) /* must be zero */ { - chunk_t k = { pbs.cur, pbs_left(&pbs) }; + /* we have what seems to be a tasty key */ - TRY(add_public_key(&cr->id, dns_auth_level, PUBKEY_ALG_RSA, &k - , &cr->keys_from_dns)); + if (doit) + { + chunk_t k = { pbs.cur, pbs_left(&pbs) }; + + TRY(add_public_key(&cr->id, dns_auth_level, PUBKEY_ALG_RSA, &k + , &cr->keys_from_dns)); + } } - } - return NULL; + return NULL; } #endif /* USE_KEYRR */ @@ -945,130 +945,130 @@ process_key_rr(u_char *ptr, size_t len static err_t unpack_txt_rdata(u_char *d, size_t dlen, const u_char *s, size_t slen) { - size_t i = 0 - , o = 0; + size_t i = 0 + , o = 0; - while (i < slen) - { - size_t cl = s[i++]; + while (i < slen) + { + size_t cl = s[i++]; - if (i + cl > slen) - return "TXT rr RDATA representation malformed"; + if (i + cl > slen) + return "TXT rr RDATA representation malformed"; - if (o + cl >= dlen) - return "TXT rr RDATA too large"; + if (o + cl >= dlen) + return "TXT rr RDATA too large"; - memcpy(d + o, s + i, cl); - i += cl; - o += cl; - } - d[o] = '\0'; - if (strlen(d) != o) - return "TXT rr RDATA contains a NUL"; + memcpy(d + o, s + i, cl); + i += cl; + o += cl; + } + d[o] = '\0'; + if (strlen(d) != o) + return "TXT rr RDATA contains a NUL"; - return NULL; + return NULL; } static err_t process_txt_rr(u_char *rdata, size_t rdlen -, bool doit /* should we capture information? */ +, bool doit /* should we capture information? */ , enum dns_auth_level dns_auth_level , struct adns_continuation *const cr) { - u_char str[RSA_MAX_ENCODING_BYTES * 8 / 6 + 20]; /* space for unpacked RDATA */ + u_char str[RSA_MAX_ENCODING_BYTES * 8 / 6 + 20]; /* space for unpacked RDATA */ - TRY(unpack_txt_rdata(str, sizeof(str), rdata, rdlen)); - return process_txt_rr_body(str, doit, dns_auth_level, cr); + TRY(unpack_txt_rdata(str, sizeof(str), rdata, rdlen)); + return process_txt_rr_body(str, doit, dns_auth_level, cr); } static err_t process_answer_section(pb_stream *pbs -, bool doit /* should we capture information? */ +, bool doit /* should we capture information? */ , enum dns_auth_level *dns_auth_level -, u_int16_t ancount /* number of RRs in the answer section */ +, u_int16_t ancount /* number of RRs in the answer section */ , struct adns_continuation *const cr) { - const int type = cr->query.type; /* type of RR of interest */ - unsigned c; + const int type = cr->query.type; /* type of RR of interest */ + unsigned c; - DBG(DBG_DNS, DBG_log("*Answer Section:")); + DBG(DBG_DNS, DBG_log("*Answer Section:")); - for (c = 0; c != ancount; c++) - { - struct rr_fixed rrf; - size_t tail; - - /* ??? do we need to match the name? */ - - TRY(eat_name_helpfully(pbs, "Answer Section")); - - if (!in_struct(&rrf, &rr_fixed_desc, pbs, NULL)) - return "failed to get fixed part of Answer Section Resource Record"; - - if (rrf.rdlength > pbs_left(pbs)) - return "RD Length extends beyond end of message"; - - /* ??? should we care about ttl? */ - - tail = rrf.rdlength; - - if (rrf.type == type && rrf.class == C_IN) + for (c = 0; c != ancount; c++) { - err_t ugh = NULL; + struct rr_fixed rrf; + size_t tail; - switch (type) - { -#ifdef USE_KEYRR - case T_KEY: - ugh = process_key_rr(pbs->cur, tail, doit, *dns_auth_level, cr); - break; -#endif /* USE_KEYRR */ - case T_TXT: - ugh = process_txt_rr(pbs->cur, tail, doit, *dns_auth_level, cr); - break; - case T_SIG: - /* Check if SIG RR authenticates what we are learning. - * The RRset covered by a SIG must have the same owner, - * class, and type. - * For us, the class is always C_IN, so that matches. - * We decode the SIG RR's fixed part to check - * that the type_covered field matches our query type - * (this may be redundant). - * We don't check the owner (apparently this is the - * name on the record) -- we assume that it matches - * or we would not have been given this SIG in the - * Answer Section. - * - * We only look on first pass, and only if we've something - * to learn. This cuts down on useless decoding. - */ - if (!doit && *dns_auth_level == DAL_UNSIGNED) + /* ??? do we need to match the name? */ + + TRY(eat_name_helpfully(pbs, "Answer Section")); + + if (!in_struct(&rrf, &rr_fixed_desc, pbs, NULL)) + return "failed to get fixed part of Answer Section Resource Record"; + + if (rrf.rdlength > pbs_left(pbs)) + return "RD Length extends beyond end of message"; + + /* ??? should we care about ttl? */ + + tail = rrf.rdlength; + + if (rrf.type == type && rrf.class == C_IN) { - struct sig_rdata sr; + err_t ugh = NULL; - if (!in_struct(&sr, &sig_rdata_desc, pbs, NULL)) - ugh = "failed to get fixed part of SIG Resource Record RDATA"; - else if (sr.type_covered == type) - *dns_auth_level = DAL_SIGNED; - } - break; - default: - ugh = builddiag("unexpected RR type %d", type); - break; - } - if (ugh != NULL) - return ugh; - } - in_raw(NULL, tail, pbs, "RR RDATA"); - } - - return doit - && cr->gateways_from_dns == NULL + switch (type) + { #ifdef USE_KEYRR - && cr->keys_from_dns == NULL + case T_KEY: + ugh = process_key_rr(pbs->cur, tail, doit, *dns_auth_level, cr); + break; #endif /* USE_KEYRR */ - ? builddiag("no suitable %s record found in DNS", rr_typename(type)) - : NULL; + case T_TXT: + ugh = process_txt_rr(pbs->cur, tail, doit, *dns_auth_level, cr); + break; + case T_SIG: + /* Check if SIG RR authenticates what we are learning. + * The RRset covered by a SIG must have the same owner, + * class, and type. + * For us, the class is always C_IN, so that matches. + * We decode the SIG RR's fixed part to check + * that the type_covered field matches our query type + * (this may be redundant). + * We don't check the owner (apparently this is the + * name on the record) -- we assume that it matches + * or we would not have been given this SIG in the + * Answer Section. + * + * We only look on first pass, and only if we've something + * to learn. This cuts down on useless decoding. + */ + if (!doit && *dns_auth_level == DAL_UNSIGNED) + { + struct sig_rdata sr; + + if (!in_struct(&sr, &sig_rdata_desc, pbs, NULL)) + ugh = "failed to get fixed part of SIG Resource Record RDATA"; + else if (sr.type_covered == type) + *dns_auth_level = DAL_SIGNED; + } + break; + default: + ugh = builddiag("unexpected RR type %d", type); + break; + } + if (ugh != NULL) + return ugh; + } + in_raw(NULL, tail, pbs, "RR RDATA"); + } + + return doit + && cr->gateways_from_dns == NULL +#ifdef USE_KEYRR + && cr->keys_from_dns == NULL +#endif /* USE_KEYRR */ + ? builddiag("no suitable %s record found in DNS", rr_typename(type)) + : NULL; } /* process DNS answer -- TXT or KEY query */ @@ -1077,153 +1077,153 @@ static err_t process_dns_answer(struct adns_continuation *const cr , u_char ans[], int anslen) { - const int type = cr->query.type; /* type of record being sought */ - int r; /* all-purpose return value holder */ - u_int16_t c; /* number of current RR in current answer section */ - pb_stream pbs; - u_int8_t *ans_start; /* saved position of answer section */ - struct qr_header qr_header; - enum dns_auth_level dns_auth_level; + const int type = cr->query.type; /* type of record being sought */ + int r; /* all-purpose return value holder */ + u_int16_t c; /* number of current RR in current answer section */ + pb_stream pbs; + u_int8_t *ans_start; /* saved position of answer section */ + struct qr_header qr_header; + enum dns_auth_level dns_auth_level; - init_pbs(&pbs, ans, anslen, "Query Response Message"); + init_pbs(&pbs, ans, anslen, "Query Response Message"); - /* decode and check header */ + /* decode and check header */ - if (!in_struct(&qr_header, &qr_header_desc, &pbs, NULL)) - return "malformed header"; + if (!in_struct(&qr_header, &qr_header_desc, &pbs, NULL)) + return "malformed header"; - /* ID: nothing to do with us */ + /* ID: nothing to do with us */ - /* stuff -- lots of things */ - if ((qr_header.stuff & QRS_QR) == 0) - return "not a response?!?"; + /* stuff -- lots of things */ + if ((qr_header.stuff & QRS_QR) == 0) + return "not a response?!?"; - if (((qr_header.stuff >> QRS_OPCODE_SHIFT) & QRS_OPCODE_MASK) != QRSO_QUERY) - return "unexpected opcode"; + if (((qr_header.stuff >> QRS_OPCODE_SHIFT) & QRS_OPCODE_MASK) != QRSO_QUERY) + return "unexpected opcode"; - /* I don't think we care about AA */ + /* I don't think we care about AA */ - if (qr_header.stuff & QRS_TC) - return "response truncated"; + if (qr_header.stuff & QRS_TC) + return "response truncated"; - /* I don't think we care about RD, RA, or CD */ + /* I don't think we care about RD, RA, or CD */ - /* AD means "authentic data" */ - dns_auth_level = qr_header.stuff & QRS_AD? DAL_UNSIGNED : DAL_NOTSEC; + /* AD means "authentic data" */ + dns_auth_level = qr_header.stuff & QRS_AD? DAL_UNSIGNED : DAL_NOTSEC; - if (qr_header.stuff & QRS_Z) - return "Z bit is not zero"; + if (qr_header.stuff & QRS_Z) + return "Z bit is not zero"; - r = (qr_header.stuff >> QRS_RCODE_SHIFT) & QRS_RCODE_MASK; - if (r != 0) - return r < (int)countof(rcode_text)? rcode_text[r] : "unknown rcode"; + r = (qr_header.stuff >> QRS_RCODE_SHIFT) & QRS_RCODE_MASK; + if (r != 0) + return r < (int)countof(rcode_text)? rcode_text[r] : "unknown rcode"; - if (qr_header.ancount == 0) - return builddiag("no %s RR found by DNS", rr_typename(type)); + if (qr_header.ancount == 0) + return builddiag("no %s RR found by DNS", rr_typename(type)); - /* end of header checking */ + /* end of header checking */ - /* Question Section processing */ + /* Question Section processing */ - /* 4.1.2. Question section format: - * 1 1 1 1 1 1 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | | - * / QNAME / - * / / - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | QTYPE | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | QCLASS | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - */ + /* 4.1.2. Question section format: + * 1 1 1 1 1 1 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | | + * / QNAME / + * / / + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | QTYPE | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | QCLASS | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + */ - DBG(DBG_DNS, DBG_log("*Question Section:")); + DBG(DBG_DNS, DBG_log("*Question Section:")); - for (c = 0; c != qr_header.qdcount; c++) - { - struct qs_fixed qsf; + for (c = 0; c != qr_header.qdcount; c++) + { + struct qs_fixed qsf; - TRY(eat_name_helpfully(&pbs, "Question Section")); + TRY(eat_name_helpfully(&pbs, "Question Section")); - if (!in_struct(&qsf, &qs_fixed_desc, &pbs, NULL)) - return "failed to get fixed part of Question Section"; + if (!in_struct(&qsf, &qs_fixed_desc, &pbs, NULL)) + return "failed to get fixed part of Question Section"; - if (qsf.qtype != type) - return "unexpected QTYPE in Question Section"; + if (qsf.qtype != type) + return "unexpected QTYPE in Question Section"; - if (qsf.qclass != C_IN) - return "unexpected QCLASS in Question Section"; - } + if (qsf.qclass != C_IN) + return "unexpected QCLASS in Question Section"; + } - /* rest of sections are made up of Resource Records */ + /* rest of sections are made up of Resource Records */ - /* Answer Section processing -- error checking, noting T_SIG */ + /* Answer Section processing -- error checking, noting T_SIG */ - ans_start = pbs.cur; /* remember start of answer section */ + ans_start = pbs.cur; /* remember start of answer section */ - TRY(process_answer_section(&pbs, FALSE, &dns_auth_level - , qr_header.ancount, cr)); + TRY(process_answer_section(&pbs, FALSE, &dns_auth_level + , qr_header.ancount, cr)); - /* Authority Section processing (just sanity checking) */ + /* Authority Section processing (just sanity checking) */ - DBG(DBG_DNS, DBG_log("*Authority Section:")); + DBG(DBG_DNS, DBG_log("*Authority Section:")); - for (c = 0; c != qr_header.nscount; c++) - { - struct rr_fixed rrf; - size_t tail; + for (c = 0; c != qr_header.nscount; c++) + { + struct rr_fixed rrf; + size_t tail; - TRY(eat_name_helpfully(&pbs, "Authority Section")); + TRY(eat_name_helpfully(&pbs, "Authority Section")); - if (!in_struct(&rrf, &rr_fixed_desc, &pbs, NULL)) - return "failed to get fixed part of Authority Section Resource Record"; + if (!in_struct(&rrf, &rr_fixed_desc, &pbs, NULL)) + return "failed to get fixed part of Authority Section Resource Record"; - if (rrf.rdlength > pbs_left(&pbs)) - return "RD Length extends beyond end of message"; + if (rrf.rdlength > pbs_left(&pbs)) + return "RD Length extends beyond end of message"; - /* ??? should we care about ttl? */ + /* ??? should we care about ttl? */ - tail = rrf.rdlength; + tail = rrf.rdlength; - in_raw(NULL, tail, &pbs, "RR RDATA"); - } + in_raw(NULL, tail, &pbs, "RR RDATA"); + } - /* Additional Section processing (just sanity checking) */ + /* Additional Section processing (just sanity checking) */ - DBG(DBG_DNS, DBG_log("*Additional Section:")); + DBG(DBG_DNS, DBG_log("*Additional Section:")); - for (c = 0; c != qr_header.arcount; c++) - { - struct rr_fixed rrf; - size_t tail; + for (c = 0; c != qr_header.arcount; c++) + { + struct rr_fixed rrf; + size_t tail; - TRY(eat_name_helpfully(&pbs, "Additional Section")); + TRY(eat_name_helpfully(&pbs, "Additional Section")); - if (!in_struct(&rrf, &rr_fixed_desc, &pbs, NULL)) - return "failed to get fixed part of Additional Section Resource Record"; + if (!in_struct(&rrf, &rr_fixed_desc, &pbs, NULL)) + return "failed to get fixed part of Additional Section Resource Record"; - if (rrf.rdlength > pbs_left(&pbs)) - return "RD Length extends beyond end of message"; + if (rrf.rdlength > pbs_left(&pbs)) + return "RD Length extends beyond end of message"; - /* ??? should we care about ttl? */ + /* ??? should we care about ttl? */ - tail = rrf.rdlength; + tail = rrf.rdlength; - in_raw(NULL, tail, &pbs, "RR RDATA"); - } + in_raw(NULL, tail, &pbs, "RR RDATA"); + } - /* done all sections */ + /* done all sections */ - /* ??? is padding legal, or can we complain if more left in record? */ + /* ??? is padding legal, or can we complain if more left in record? */ - /* process Answer Section again -- accept contents */ + /* process Answer Section again -- accept contents */ - pbs.cur = ans_start; /* go back to start of answer section */ + pbs.cur = ans_start; /* go back to start of answer section */ - return process_answer_section(&pbs, TRUE, &dns_auth_level - , qr_header.ancount, cr); + return process_answer_section(&pbs, TRUE, &dns_auth_level + , qr_header.ancount, cr); } #endif /* ! USE_LWRES */ @@ -1238,101 +1238,101 @@ build_dns_name(u_char name_buf[NS_MAXDNAME + 2] , const char *typename USED_BY_DEBUG , const char *gwname USED_BY_DEBUG) { - /* note: all end in "." to suppress relative searches */ - id = resolve_myid(id); - switch (id->kind) - { - case ID_IPV4_ADDR: - { - /* XXX: this is really ugly and only temporary until addrtot can - * generate the correct format - */ - const unsigned char *b; - size_t bl USED_BY_DEBUG = addrbytesptr(&id->ip_addr, &b); - - passert(bl == 4); - snprintf(name_buf, NS_MAXDNAME + 2, "%d.%d.%d.%d.in-addr.arpa." - , b[3], b[2], b[1], b[0]); - break; - } - - case ID_IPV6_ADDR: - { - /* ??? is this correct? */ - const unsigned char *b; - size_t bl; - u_char *op = name_buf; - static const char suffix[] = "IP6.INT."; - - for (bl = addrbytesptr(&id->ip_addr, &b); bl-- != 0; ) + /* note: all end in "." to suppress relative searches */ + id = resolve_myid(id); + switch (id->kind) { - if (op + 4 + sizeof(suffix) >= name_buf + NS_MAXDNAME + 1) - return "IPv6 reverse name too long"; - op += sprintf(op, "%x.%x.", b[bl] & 0xF, b[bl] >> 4); - } - strcpy(op, suffix); - break; - } - - case ID_FQDN: - /* strip trailing "." characters, then add one */ + case ID_IPV4_ADDR: { - size_t il = id->name.len; + /* XXX: this is really ugly and only temporary until addrtot can + * generate the correct format + */ + const unsigned char *b; + size_t bl USED_BY_DEBUG = addrbytesptr(&id->ip_addr, &b); - while (il > 0 && id->name.ptr[il - 1] == '.') - il--; - if (il > NS_MAXDNAME) - return "FQDN too long for domain name"; - - memcpy(name_buf, id->name.ptr, il); - strcpy(name_buf + il, "."); + passert(bl == 4); + snprintf(name_buf, NS_MAXDNAME + 2, "%d.%d.%d.%d.in-addr.arpa." + , b[3], b[2], b[1], b[0]); + break; } - break; - default: - return "can only query DNS for key for ID that is a FQDN, IPV4_ADDR, or IPV6_ADDR"; - } + case ID_IPV6_ADDR: + { + /* ??? is this correct? */ + const unsigned char *b; + size_t bl; + u_char *op = name_buf; + static const char suffix[] = "IP6.INT."; - DBG(DBG_CONTROL | DBG_DNS, DBG_log("DNS query %lu for %s for %s (gw: %s)" - , serial, typename, name_buf, gwname)); - return NULL; + for (bl = addrbytesptr(&id->ip_addr, &b); bl-- != 0; ) + { + if (op + 4 + sizeof(suffix) >= name_buf + NS_MAXDNAME + 1) + return "IPv6 reverse name too long"; + op += sprintf(op, "%x.%x.", b[bl] & 0xF, b[bl] >> 4); + } + strcpy(op, suffix); + break; + } + + case ID_FQDN: + /* strip trailing "." characters, then add one */ + { + size_t il = id->name.len; + + while (il > 0 && id->name.ptr[il - 1] == '.') + il--; + if (il > NS_MAXDNAME) + return "FQDN too long for domain name"; + + memcpy(name_buf, id->name.ptr, il); + strcpy(name_buf + il, "."); + } + break; + + default: + return "can only query DNS for key for ID that is a FQDN, IPV4_ADDR, or IPV6_ADDR"; + } + + DBG(DBG_CONTROL | DBG_DNS, DBG_log("DNS query %lu for %s for %s (gw: %s)" + , serial, typename, name_buf, gwname)); + return NULL; } void gw_addref(struct gw_info *gw) { - if (gw != NULL) - { - DBG(DBG_DNS, DBG_log("gw_addref: %p refcnt: %d++", gw, gw->refcnt)) - gw->refcnt++; - } + if (gw != NULL) + { + DBG(DBG_DNS, DBG_log("gw_addref: %p refcnt: %d++", gw, gw->refcnt)) + gw->refcnt++; + } } void gw_delref(struct gw_info **gwp) { - struct gw_info *gw = *gwp; + struct gw_info *gw = *gwp; - if (gw != NULL) - { - DBG(DBG_DNS, DBG_log("gw_delref: %p refcnt: %d--", gw, gw->refcnt)); - - passert(gw->refcnt != 0); - gw->refcnt--; - if (gw->refcnt == 0) + if (gw != NULL) { - free_id_content(&gw->client_id); - free_id_content(&gw->gw_id); - if (gw->gw_key_present) - unreference_key(&gw->key); - gw_delref(&gw->next); - free(gw); /* trickery could make this a tail-call */ + DBG(DBG_DNS, DBG_log("gw_delref: %p refcnt: %d--", gw, gw->refcnt)); + + passert(gw->refcnt != 0); + gw->refcnt--; + if (gw->refcnt == 0) + { + free_id_content(&gw->client_id); + free_id_content(&gw->gw_id); + if (gw->gw_key_present) + unreference_key(&gw->key); + gw_delref(&gw->next); + free(gw); /* trickery could make this a tail-call */ + } + *gwp = NULL; } - *gwp = NULL; - } } -static int adns_in_flight = 0; /* queries outstanding */ +static int adns_in_flight = 0; /* queries outstanding */ /* Start an asynchronous DNS query. * @@ -1371,123 +1371,123 @@ static int adns_in_flight = 0; /* queries outstanding */ * disestablishing any logging context (whack_log_fd, cur_*). */ -static struct adns_continuation *continuations = NULL; /* newest of queue */ -static struct adns_continuation *next_query = NULL; /* oldest not sent */ +static struct adns_continuation *continuations = NULL; /* newest of queue */ +static struct adns_continuation *next_query = NULL; /* oldest not sent */ static struct adns_continuation * continuation_for_qtid(unsigned long qtid) { - struct adns_continuation *cr = NULL; + struct adns_continuation *cr = NULL; - if (qtid != 0) - for (cr = continuations; cr != NULL && cr->qtid != qtid; cr = cr->previous) - ; - return cr; + if (qtid != 0) + for (cr = continuations; cr != NULL && cr->qtid != qtid; cr = cr->previous) + ; + return cr; } static void release_adns_continuation(struct adns_continuation *cr) { - passert(cr != next_query); - gw_delref(&cr->gateways_from_dns); + passert(cr != next_query); + gw_delref(&cr->gateways_from_dns); #ifdef USE_KEYRR - free_public_keys(&cr->keys_from_dns); + free_public_keys(&cr->keys_from_dns); #endif /* USE_KEYRR */ - unshare_id_content(&cr->id); - unshare_id_content(&cr->sgw_id); + unshare_id_content(&cr->id); + unshare_id_content(&cr->sgw_id); - /* unlink from doubly-linked list */ - if (cr->next == NULL) - { - passert(continuations == cr); - continuations = cr->previous; - } - else - { - passert(cr->next->previous == cr); - cr->next->previous = cr->previous; - } + /* unlink from doubly-linked list */ + if (cr->next == NULL) + { + passert(continuations == cr); + continuations = cr->previous; + } + else + { + passert(cr->next->previous == cr); + cr->next->previous = cr->previous; + } - if (cr->previous != NULL) - { - passert(cr->previous->next == cr); - cr->previous->next = cr->next; - } + if (cr->previous != NULL) + { + passert(cr->previous->next == cr); + cr->previous->next = cr->next; + } - free(cr); + free(cr); } err_t -start_adns_query(const struct id *id /* domain to query */ -, const struct id *sgw_id /* if non-null, any accepted gw_info must match */ -, int type /* T_TXT or T_KEY, selecting rr type of interest */ +start_adns_query(const struct id *id /* domain to query */ +, const struct id *sgw_id /* if non-null, any accepted gw_info must match */ +, int type /* T_TXT or T_KEY, selecting rr type of interest */ , cont_fn_t cont_fn , struct adns_continuation *cr) { - static unsigned long qtid = 1; /* query transaction id; NOTE: static */ - const char *typename = rr_typename(type); - char gwidb[BUF_LEN]; + static unsigned long qtid = 1; /* query transaction id; NOTE: static */ + const char *typename = rr_typename(type); + char gwidb[BUF_LEN]; - if(adns_pid == 0 - && adns_restart_count < ADNS_RESTART_MAX) - { - plog("ADNS helper was not running. Restarting attempt %d",adns_restart_count); - init_adns(); - } + if(adns_pid == 0 + && adns_restart_count < ADNS_RESTART_MAX) + { + plog("ADNS helper was not running. Restarting attempt %d",adns_restart_count); + init_adns(); + } - /* Splice this in at head of doubly-linked list of continuations. - * Note: this must be done before any release_adns_continuation(). - */ - cr->next = NULL; - cr->previous = continuations; - if (continuations != NULL) - { - passert(continuations->next == NULL); - continuations->next = cr; - } - continuations = cr; + /* Splice this in at head of doubly-linked list of continuations. + * Note: this must be done before any release_adns_continuation(). + */ + cr->next = NULL; + cr->previous = continuations; + if (continuations != NULL) + { + passert(continuations->next == NULL); + continuations->next = cr; + } + continuations = cr; - cr->qtid = qtid++; - cr->type = type; - cr->cont_fn = cont_fn; - cr->id = *id; - unshare_id_content(&cr->id); - cr->sgw_specified = sgw_id != NULL; - cr->sgw_id = cr->sgw_specified? *sgw_id : empty_id; - unshare_id_content(&cr->sgw_id); - cr->gateways_from_dns = NULL; + cr->qtid = qtid++; + cr->type = type; + cr->cont_fn = cont_fn; + cr->id = *id; + unshare_id_content(&cr->id); + cr->sgw_specified = sgw_id != NULL; + cr->sgw_id = cr->sgw_specified? *sgw_id : empty_id; + unshare_id_content(&cr->sgw_id); + cr->gateways_from_dns = NULL; #ifdef USE_KEYRR - cr->keys_from_dns = NULL; + cr->keys_from_dns = NULL; #endif /* USE_KEYRR */ #ifdef DEBUG - cr->debugging = cur_debugging; + cr->debugging = cur_debugging; #else - cr->debugging = LEMPTY; + cr->debugging = LEMPTY; #endif - idtoa(&cr->sgw_id, gwidb, sizeof(gwidb)); + idtoa(&cr->sgw_id, gwidb, sizeof(gwidb)); - zero(&cr->query); + zero(&cr->query); - { - err_t ugh = build_dns_name(cr->query.name_buf, cr->qtid - , id, typename, gwidb); - - if (ugh != NULL) { - release_adns_continuation(cr); - return ugh; + err_t ugh = build_dns_name(cr->query.name_buf, cr->qtid + , id, typename, gwidb); + + if (ugh != NULL) + { + release_adns_continuation(cr); + return ugh; + } } - } - if (next_query == NULL) - next_query = cr; + if (next_query == NULL) + next_query = cr; - unsent_ADNS_queries = TRUE; + unsent_ADNS_queries = TRUE; - return NULL; + return NULL; } /* send remaining ADNS queries (until pipe full or none left) @@ -1500,79 +1500,79 @@ bool unsent_ADNS_queries = FALSE; void send_unsent_ADNS_queries(void) { - static const unsigned char *buf_end = NULL; /* NOTE STATIC */ - static const unsigned char *buf_cur = NULL; /* NOTE STATIC */ + static const unsigned char *buf_end = NULL; /* NOTE STATIC */ + static const unsigned char *buf_cur = NULL; /* NOTE STATIC */ - if (adns_qfd == NULL_FD) - return; /* nothing useful to do */ + if (adns_qfd == NULL_FD) + return; /* nothing useful to do */ - for (;;) - { - if (buf_cur != buf_end) + for (;;) { - static int try = 0; /* NOTE STATIC */ - size_t n = buf_end - buf_cur; - ssize_t r = write(adns_qfd, buf_cur, n); - - if (r == -1) - { - switch (errno) + if (buf_cur != buf_end) { - case EINTR: - continue; /* try again now */ - case EAGAIN: - DBG(DBG_DNS, DBG_log("EAGAIN writing to ADNS")); - break; /* try again later */ - default: - try++; - log_errno((e, "error %d writing DNS query", try)); - break; /* try again later */ + static int try = 0; /* NOTE STATIC */ + size_t n = buf_end - buf_cur; + ssize_t r = write(adns_qfd, buf_cur, n); + + if (r == -1) + { + switch (errno) + { + case EINTR: + continue; /* try again now */ + case EAGAIN: + DBG(DBG_DNS, DBG_log("EAGAIN writing to ADNS")); + break; /* try again later */ + default: + try++; + log_errno((e, "error %d writing DNS query", try)); + break; /* try again later */ + } + unsent_ADNS_queries = TRUE; + break; /* done! */ + } + else + { + passert(r >= 0); + try = 0; + buf_cur += r; + } } - unsent_ADNS_queries = TRUE; - break; /* done! */ - } - else - { - passert(r >= 0); - try = 0; - buf_cur += r; - } - } - else - { - if (next_query == NULL) - { - unsent_ADNS_queries = FALSE; - break; /* done! */ - } + else + { + if (next_query == NULL) + { + unsent_ADNS_queries = FALSE; + break; /* done! */ + } #ifdef USE_LWRES - next_query->used = FALSE; - { - /* NOTE STATIC: */ - static unsigned char qbuf[LWDNSQ_CMDBUF_LEN + 1]; /* room for NUL */ + next_query->used = FALSE; + { + /* NOTE STATIC: */ + static unsigned char qbuf[LWDNSQ_CMDBUF_LEN + 1]; /* room for NUL */ - snprintf(qbuf, sizeof(qbuf), "%s %lu %s\n" - , rr_typename(next_query->type) - , next_query->qtid - , next_query->query.name_buf); - DBG(DBG_DNS, DBG_log("lwdnsq query: %.*s", (int)(strlen(qbuf) - 1), qbuf)); - buf_cur = qbuf; - buf_end = qbuf + strlen(qbuf); - } + snprintf(qbuf, sizeof(qbuf), "%s %lu %s\n" + , rr_typename(next_query->type) + , next_query->qtid + , next_query->query.name_buf); + DBG(DBG_DNS, DBG_log("lwdnsq query: %.*s", (int)(strlen(qbuf) - 1), qbuf)); + buf_cur = qbuf; + buf_end = qbuf + strlen(qbuf); + } #else /* !USE_LWRES */ - next_query->query.debugging = next_query->debugging; - next_query->query.serial = next_query->qtid; - next_query->query.len = sizeof(next_query->query); - next_query->query.qmagic = ADNS_Q_MAGIC; - next_query->query.type = next_query->type; - buf_cur = (const void *)&next_query->query; - buf_end = buf_cur + sizeof(next_query->query); + next_query->query.debugging = next_query->debugging; + next_query->query.serial = next_query->qtid; + next_query->query.len = sizeof(next_query->query); + next_query->query.qmagic = ADNS_Q_MAGIC; + next_query->query.type = next_query->type; + buf_cur = (const void *)&next_query->query; + buf_end = buf_cur + sizeof(next_query->query); #endif /* !USE_LWRES */ - next_query = next_query->next; - adns_in_flight++; + next_query = next_query->next; + adns_in_flight++; + } } - } } #ifdef USE_LWRES @@ -1583,379 +1583,379 @@ send_unsent_ADNS_queries(void) static err_t process_lwdnsq_answer(char *ts) { - err_t ugh = NULL; - char *rest; - char *p; - char *endofnumber; - struct adns_continuation *cr = NULL; - unsigned long qtid; - time_t anstime; /* time of answer */ - char *atype; /* type of answer */ - long ttl; /* ttl of answer; int, but long for conversion */ - bool AuthenticatedData = FALSE; - static char scratch_null_str[] = ""; /* cannot be const, but isn't written */ + err_t ugh = NULL; + char *rest; + char *p; + char *endofnumber; + struct adns_continuation *cr = NULL; + unsigned long qtid; + time_t anstime; /* time of answer */ + char *atype; /* type of answer */ + long ttl; /* ttl of answer; int, but long for conversion */ + bool AuthenticatedData = FALSE; + static char scratch_null_str[] = ""; /* cannot be const, but isn't written */ - /* query transaction id */ - rest = ts; - p = strsep(&rest, " \t"); - if (p == NULL) - return "lwdnsq: answer missing query transaction ID"; + /* query transaction id */ + rest = ts; + p = strsep(&rest, " \t"); + if (p == NULL) + return "lwdnsq: answer missing query transaction ID"; - qtid = strtoul(p, &endofnumber, 10); - if (*endofnumber != '\0') - return "lwdnsq: malformed query transaction ID"; + qtid = strtoul(p, &endofnumber, 10); + if (*endofnumber != '\0') + return "lwdnsq: malformed query transaction ID"; - cr = continuation_for_qtid(qtid); - if (qtid != 0 && cr == NULL) - return "lwdnsq: unrecognized qtid"; /* can't happen! */ + cr = continuation_for_qtid(qtid); + if (qtid != 0 && cr == NULL) + return "lwdnsq: unrecognized qtid"; /* can't happen! */ - /* time */ - p = strsep(&rest, " \t"); - if (p == NULL) - return "lwdnsq: missing time"; + /* time */ + p = strsep(&rest, " \t"); + if (p == NULL) + return "lwdnsq: missing time"; - anstime = strtoul(p, &endofnumber, 10); - if (*endofnumber != '\0') - return "lwdnsq: malformed time"; + anstime = strtoul(p, &endofnumber, 10); + if (*endofnumber != '\0') + return "lwdnsq: malformed time"; - /* TTL */ - p = strsep(&rest, " \t"); - if (p == NULL) - return "lwdnsq: missing TTL"; + /* TTL */ + p = strsep(&rest, " \t"); + if (p == NULL) + return "lwdnsq: missing TTL"; - ttl = strtol(p, &endofnumber, 10); - if (*endofnumber != '\0') - return "lwdnsq: malformed TTL"; + ttl = strtol(p, &endofnumber, 10); + if (*endofnumber != '\0') + return "lwdnsq: malformed TTL"; - /* type */ - atype = strsep(&rest, " \t"); - if (atype == NULL) - return "lwdnsq: missing type"; + /* type */ + atype = strsep(&rest, " \t"); + if (atype == NULL) + return "lwdnsq: missing type"; - /* if rest is NULL, make it "", otherwise eat whitespace after type */ - rest = rest == NULL? scratch_null_str : rest + strspn(rest, " \t"); + /* if rest is NULL, make it "", otherwise eat whitespace after type */ + rest = rest == NULL? scratch_null_str : rest + strspn(rest, " \t"); - if (strncasecmp(atype, "AD-", 3) == 0) - { - AuthenticatedData = TRUE; - atype += 3; - } - - /* deal with each type */ - - if (cr == NULL) - { - /* we don't actually know which this applies to */ - return builddiag("lwdnsq: 0 qtid invalid with %s", atype); - } - else if (strcaseeq(atype, "START")) - { - /* ignore */ - } - else if (strcaseeq(atype, "DONE")) - { - if (!cr->used) + if (strncasecmp(atype, "AD-", 3) == 0) { - /* "no results returned by lwdnsq" should not happen */ - cr->cont_fn(cr - , cr->gateways_from_dns == NULL + AuthenticatedData = TRUE; + atype += 3; + } + + /* deal with each type */ + + if (cr == NULL) + { + /* we don't actually know which this applies to */ + return builddiag("lwdnsq: 0 qtid invalid with %s", atype); + } + else if (strcaseeq(atype, "START")) + { + /* ignore */ + } + else if (strcaseeq(atype, "DONE")) + { + if (!cr->used) + { + /* "no results returned by lwdnsq" should not happen */ + cr->cont_fn(cr + , cr->gateways_from_dns == NULL #ifdef USE_KEYRR - && cr->keys_from_dns == NULL + && cr->keys_from_dns == NULL #endif /* USE_KEYRR */ - ? "no results returned by lwdnsq" : NULL); - cr->used = TRUE; + ? "no results returned by lwdnsq" : NULL); + cr->used = TRUE; + } + reset_globals(); + release_adns_continuation(cr); + adns_in_flight--; } - reset_globals(); - release_adns_continuation(cr); - adns_in_flight--; - } - else if (strcaseeq(atype, "RETRY")) - { - if (!cr->used) + else if (strcaseeq(atype, "RETRY")) { - cr->cont_fn(cr, rest); - cr->used = TRUE; + if (!cr->used) + { + cr->cont_fn(cr, rest); + cr->used = TRUE; + } } - } - else if (strcaseeq(atype, "FATAL")) - { - if (!cr->used) + else if (strcaseeq(atype, "FATAL")) { - cr->cont_fn(cr, rest); - cr->used = TRUE; + if (!cr->used) + { + cr->cont_fn(cr, rest); + cr->used = TRUE; + } } - } - else if (strcaseeq(atype, "DNSSEC")) - { - /* ignore */ - } - else if (strcaseeq(atype, "NAME")) - { - /* ignore */ - } - else if (strcaseeq(atype, "TXT")) - { - char *end = rest + strlen(rest); - err_t txt_ugh; + else if (strcaseeq(atype, "DNSSEC")) + { + /* ignore */ + } + else if (strcaseeq(atype, "NAME")) + { + /* ignore */ + } + else if (strcaseeq(atype, "TXT")) + { + char *end = rest + strlen(rest); + err_t txt_ugh; - if (*rest == '"' && end[-1] == '"') - { - /* strip those pesky quotes */ - rest++; - *--end = '\0'; - } + if (*rest == '"' && end[-1] == '"') + { + /* strip those pesky quotes */ + rest++; + *--end = '\0'; + } - txt_ugh = process_txt_rr_body(rest - , TRUE - , AuthenticatedData? DAL_SIGNED : DAL_NOTSEC - , cr); + txt_ugh = process_txt_rr_body(rest + , TRUE + , AuthenticatedData? DAL_SIGNED : DAL_NOTSEC + , cr); - if (txt_ugh != NULL) - { - DBG(DBG_DNS, - DBG_log("error processing TXT resource record (%s) while processing: %s" - , txt_ugh, rest)); - cr->cont_fn(cr, txt_ugh); - cr->used = TRUE; + if (txt_ugh != NULL) + { + DBG(DBG_DNS, + DBG_log("error processing TXT resource record (%s) while processing: %s" + , txt_ugh, rest)); + cr->cont_fn(cr, txt_ugh); + cr->used = TRUE; + } } - } - else if (strcaseeq(atype, "SIG")) - { - /* record the SIG records for posterity */ - if (cr->last_info != NULL) + else if (strcaseeq(atype, "SIG")) { - free(cr->last_info->dns_sig); - cr->last_info->dns_sig = clone_str(rest); + /* record the SIG records for posterity */ + if (cr->last_info != NULL) + { + free(cr->last_info->dns_sig); + cr->last_info->dns_sig = clone_str(rest); + } + } + else if (strcaseeq(atype, "A")) + { + /* ignore */ + } + else if (strcaseeq(atype, "AAAA")) + { + /* ignore */ + } + else if (strcaseeq(atype, "CNAME")) + { + /* ignore */ + } + else if (strcaseeq(atype, "CNAMEFROM")) + { + /* ignore */ + } + else if (strcaseeq(atype, "PTR")) + { + /* ignore */ } - } - else if (strcaseeq(atype, "A")) - { - /* ignore */ - } - else if (strcaseeq(atype, "AAAA")) - { - /* ignore */ - } - else if (strcaseeq(atype, "CNAME")) - { - /* ignore */ - } - else if (strcaseeq(atype, "CNAMEFROM")) - { - /* ignore */ - } - else if (strcaseeq(atype, "PTR")) - { - /* ignore */ - } #ifdef USE_KEYRR - else if (strcaseeq(atype, "KEY")) - { - err_t key_ugh = process_lwdnsq_key(rest - , AuthenticatedData? DAL_SIGNED : DAL_NOTSEC - , cr); - - if (key_ugh != NULL) + else if (strcaseeq(atype, "KEY")) { - DBG(DBG_DNS, - DBG_log("error processing KEY resource record (%s) while processing: %s" - , key_ugh, rest)); - cr->cont_fn(cr, key_ugh); - cr->used = TRUE; + err_t key_ugh = process_lwdnsq_key(rest + , AuthenticatedData? DAL_SIGNED : DAL_NOTSEC + , cr); + + if (key_ugh != NULL) + { + DBG(DBG_DNS, + DBG_log("error processing KEY resource record (%s) while processing: %s" + , key_ugh, rest)); + cr->cont_fn(cr, key_ugh); + cr->used = TRUE; + } } - } #endif /* USE_KEYRR */ - else - { - ugh = "lwdnsq: unrecognized type"; - } - return ugh; + else + { + ugh = "lwdnsq: unrecognized type"; + } + return ugh; } #endif /* USE_LWRES */ static void recover_adns_die(void) { - struct adns_continuation *cr = NULL; - - adns_pid = 0; - if(adns_restart_count < ADNS_RESTART_MAX) { - adns_restart_count++; + struct adns_continuation *cr = NULL; + + adns_pid = 0; + if(adns_restart_count < ADNS_RESTART_MAX) { + adns_restart_count++; - /* next DNS query will restart it */ + /* next DNS query will restart it */ - /* we have to walk the list of the outstanding requests, - * and redo them! - */ + /* we have to walk the list of the outstanding requests, + * and redo them! + */ - cr = continuations; + cr = continuations; - /* find the head of the list */ - if(continuations != NULL) { - for (; cr->previous != NULL; cr = cr->previous); + /* find the head of the list */ + if(continuations != NULL) { + for (; cr->previous != NULL; cr = cr->previous); + } + + next_query = cr; + + if(next_query != NULL) { + unsent_ADNS_queries = TRUE; + } } - - next_query = cr; - - if(next_query != NULL) { - unsent_ADNS_queries = TRUE; - } - } } void reset_adns_restart_count(void) { - adns_restart_count=0; + adns_restart_count=0; } void handle_adns_answer(void) { /* These are retained across calls to handle_adns_answer. */ - static size_t buflen = 0; /* bytes in answer buffer */ + static size_t buflen = 0; /* bytes in answer buffer */ #ifndef USE_LWRES - static struct adns_answer buf; + static struct adns_answer buf; #else /* USE_LWRES */ - static char buf[LWDNSQ_RESULT_LEN_MAX]; - static char buf_copy[LWDNSQ_RESULT_LEN_MAX]; + static char buf[LWDNSQ_RESULT_LEN_MAX]; + static char buf_copy[LWDNSQ_RESULT_LEN_MAX]; #endif /* USE_LWRES */ - ssize_t n; + ssize_t n; - passert(buflen < sizeof(buf)); - n = read(adns_afd, (unsigned char *)&buf + buflen, sizeof(buf) - buflen); + passert(buflen < sizeof(buf)); + n = read(adns_afd, (unsigned char *)&buf + buflen, sizeof(buf) - buflen); - if (n < 0) - { - if (errno != EINTR) + if (n < 0) { - log_errno((e, "error reading answer from adns")); - /* ??? how can we recover? */ + if (errno != EINTR) + { + log_errno((e, "error reading answer from adns")); + /* ??? how can we recover? */ + } + n = 0; /* now n reflects amount read */ } - n = 0; /* now n reflects amount read */ - } - else if (n == 0) - { - /* EOF */ - if (adns_in_flight != 0) + else if (n == 0) { - plog("EOF from ADNS with %d queries outstanding (restarts %d)" - , adns_in_flight, adns_restart_count); - recover_adns_die(); - } - if (buflen != 0) - { - plog("EOF from ADNS with %lu bytes of a partial answer outstanding" - "(restarts %d)" - , (unsigned long)buflen - , adns_restart_count); - recover_adns_die(); - } - stop_adns(); - return; - } - else - { - passert(adns_in_flight > 0); - } - - buflen += n; -#ifndef USE_LWRES - while (buflen >= offsetof(struct adns_answer, ans) && buflen >= buf.len) - { - /* we've got a tasty answer -- process it */ - err_t ugh; - struct adns_continuation *cr = continuation_for_qtid(buf.serial); /* assume it works */ - const char *typename = rr_typename(cr->query.type); - const char *name_buf = cr->query.name_buf; - -#ifdef USE_KEYRR - passert(cr->keys_from_dns == NULL); -#endif /* USE_KEYRR */ - passert(cr->gateways_from_dns == NULL); - adns_in_flight--; - if (buf.result == -1) - { - /* newer resolvers support statp->res_h_errno as well as h_errno. - * That might be better, but older resolvers don't. - * See resolver(3), if you have it. - * The undocumented(!) h_errno values are defined in - * /usr/include/netdb.h. - */ - switch (buf.h_errno_val) - { - case NO_DATA: - ugh = builddiag("no %s record for %s", typename, name_buf); - break; - case HOST_NOT_FOUND: - ugh = builddiag("no host %s for %s record", name_buf, typename); - break; - default: - ugh = builddiag("failure querying DNS for %s of %s: %s" - , typename, name_buf, hstrerror(buf.h_errno_val)); - break; - } - } - else if (buf.result > (int) sizeof(buf.ans)) - { - ugh = builddiag("(INTERNAL ERROR) answer too long (%ld) for buffer" - , (long)buf.result); + /* EOF */ + if (adns_in_flight != 0) + { + plog("EOF from ADNS with %d queries outstanding (restarts %d)" + , adns_in_flight, adns_restart_count); + recover_adns_die(); + } + if (buflen != 0) + { + plog("EOF from ADNS with %lu bytes of a partial answer outstanding" + "(restarts %d)" + , (unsigned long)buflen + , adns_restart_count); + recover_adns_die(); + } + stop_adns(); + return; } else { - ugh = process_dns_answer(cr, buf.ans, buf.result); - if (ugh != NULL) - ugh = builddiag("failure processing %s record of DNS answer for %s: %s" - , typename, name_buf, ugh); + passert(adns_in_flight > 0); } - DBG(DBG_RAW | DBG_CRYPT | DBG_PARSING | DBG_CONTROL | DBG_DNS, - DBG_log(BLANK_FORMAT); - if (ugh == NULL) - DBG_log("asynch DNS answer %lu for %s of %s" - , cr->query.serial, typename, name_buf); - else - DBG_log("asynch DNS answer %lu %s", cr->query.serial, ugh); - ); - passert(GLOBALS_ARE_RESET()); - cr->cont_fn(cr, ugh); - reset_globals(); - release_adns_continuation(cr); + buflen += n; +#ifndef USE_LWRES + while (buflen >= offsetof(struct adns_answer, ans) && buflen >= buf.len) + { + /* we've got a tasty answer -- process it */ + err_t ugh; + struct adns_continuation *cr = continuation_for_qtid(buf.serial); /* assume it works */ + const char *typename = rr_typename(cr->query.type); + const char *name_buf = cr->query.name_buf; - /* shift out answer that we've consumed */ - buflen -= buf.len; - memmove((unsigned char *)&buf, (unsigned char *)&buf + buf.len, buflen); - } +#ifdef USE_KEYRR + passert(cr->keys_from_dns == NULL); +#endif /* USE_KEYRR */ + passert(cr->gateways_from_dns == NULL); + adns_in_flight--; + if (buf.result == -1) + { + /* newer resolvers support statp->res_h_errno as well as h_errno. + * That might be better, but older resolvers don't. + * See resolver(3), if you have it. + * The undocumented(!) h_errno values are defined in + * /usr/include/netdb.h. + */ + switch (buf.h_errno_val) + { + case NO_DATA: + ugh = builddiag("no %s record for %s", typename, name_buf); + break; + case HOST_NOT_FOUND: + ugh = builddiag("no host %s for %s record", name_buf, typename); + break; + default: + ugh = builddiag("failure querying DNS for %s of %s: %s" + , typename, name_buf, hstrerror(buf.h_errno_val)); + break; + } + } + else if (buf.result > (int) sizeof(buf.ans)) + { + ugh = builddiag("(INTERNAL ERROR) answer too long (%ld) for buffer" + , (long)buf.result); + } + else + { + ugh = process_dns_answer(cr, buf.ans, buf.result); + if (ugh != NULL) + ugh = builddiag("failure processing %s record of DNS answer for %s: %s" + , typename, name_buf, ugh); + } + DBG(DBG_RAW | DBG_CRYPT | DBG_PARSING | DBG_CONTROL | DBG_DNS, + DBG_log(BLANK_FORMAT); + if (ugh == NULL) + DBG_log("asynch DNS answer %lu for %s of %s" + , cr->query.serial, typename, name_buf); + else + DBG_log("asynch DNS answer %lu %s", cr->query.serial, ugh); + ); + + passert(GLOBALS_ARE_RESET()); + cr->cont_fn(cr, ugh); + reset_globals(); + release_adns_continuation(cr); + + /* shift out answer that we've consumed */ + buflen -= buf.len; + memmove((unsigned char *)&buf, (unsigned char *)&buf + buf.len, buflen); + } #else /* USE_LWRES */ - for (;;) - { - err_t ugh; - char *nlp = memchr(buf, '\n', buflen); + for (;;) + { + err_t ugh; + char *nlp = memchr(buf, '\n', buflen); - if (nlp == NULL) - break; + if (nlp == NULL) + break; - /* we've got a line */ - *nlp++ = '\0'; + /* we've got a line */ + *nlp++ = '\0'; - DBG(DBG_RAW | DBG_CRYPT | DBG_PARSING | DBG_CONTROL | DBG_DNS - , DBG_log("lwdns: %s", buf)); + DBG(DBG_RAW | DBG_CRYPT | DBG_PARSING | DBG_CONTROL | DBG_DNS + , DBG_log("lwdns: %s", buf)); - /* process lwdnsq_answer may modify buf, so make a copy. */ - buf_copy[0]='\0'; - strncat(buf_copy, buf, sizeof(buf_copy)); + /* process lwdnsq_answer may modify buf, so make a copy. */ + buf_copy[0]='\0'; + strncat(buf_copy, buf, sizeof(buf_copy)); - ugh = process_lwdnsq_answer(buf_copy); - if (ugh != NULL) - plog("failure processing lwdnsq output: %s; record: %s" - , ugh, buf); + ugh = process_lwdnsq_answer(buf_copy); + if (ugh != NULL) + plog("failure processing lwdnsq output: %s; record: %s" + , ugh, buf); - passert(GLOBALS_ARE_RESET()); - reset_globals(); + passert(GLOBALS_ARE_RESET()); + reset_globals(); - /* shift out answer that we've consumed */ - buflen -= nlp - buf; - memmove(buf, nlp, buflen); - } + /* shift out answer that we've consumed */ + buflen -= nlp - buf; + memmove(buf, nlp, buflen); + } #endif /* USE_LWRES */ } diff --git a/src/pluto/dnskey.h b/src/pluto/dnskey.h index bb6448ee1..53b1a5e35 100644 --- a/src/pluto/dnskey.h +++ b/src/pluto/dnskey.h @@ -15,9 +15,9 @@ */ extern int - adns_qfd, /* file descriptor for sending queries to adns */ - adns_afd; /* file descriptor for receiving answers from adns */ -extern const char *pluto_adns_option; /* path from --pluto_adns */ + adns_qfd, /* file descriptor for sending queries to adns */ + adns_afd; /* file descriptor for receiving answers from adns */ +extern const char *pluto_adns_option; /* path from --pluto_adns */ extern void init_adns(void); extern void stop_adns(void); extern void handle_adns_answer(void); @@ -30,55 +30,55 @@ extern void send_unsent_ADNS_queries(void); * Freed by call to release_adns_continuation. */ -struct adns_continuation; /* forward declaration (not far!) */ +struct adns_continuation; /* forward declaration (not far!) */ typedef void (*cont_fn_t)(struct adns_continuation *cr, err_t ugh); struct adns_continuation { - unsigned long qtid; /* query transaction id number */ - int type; /* T_TXT or T_KEY, selecting rr type of interest */ - cont_fn_t cont_fn; /* function to carry on suspended work */ - struct id id; /* subject of query */ - bool sgw_specified; - struct id sgw_id; /* peer, if constrained */ - lset_t debugging; /* only used #ifdef DEBUG, but don't want layout to change */ - struct gw_info *gateways_from_dns; /* answer, if looking for our TXT rrs */ + unsigned long qtid; /* query transaction id number */ + int type; /* T_TXT or T_KEY, selecting rr type of interest */ + cont_fn_t cont_fn; /* function to carry on suspended work */ + struct id id; /* subject of query */ + bool sgw_specified; + struct id sgw_id; /* peer, if constrained */ + lset_t debugging; /* only used #ifdef DEBUG, but don't want layout to change */ + struct gw_info *gateways_from_dns; /* answer, if looking for our TXT rrs */ #ifdef USE_KEYRR - struct pubkey_list *keys_from_dns; /* answer, if looking for KEY rrs */ + struct pubkey_list *keys_from_dns; /* answer, if looking for KEY rrs */ #endif - struct adns_continuation *previous, *next; - struct pubkey *last_info; /* the last structure we accumulated */ + struct adns_continuation *previous, *next; + struct pubkey *last_info; /* the last structure we accumulated */ #ifdef USE_LWRES - bool used; /* have we called the cont_fn yet? */ - struct { - u_char name_buf[NS_MAXDNAME + 2]; - } query; + bool used; /* have we called the cont_fn yet? */ + struct { + u_char name_buf[NS_MAXDNAME + 2]; + } query; #else /* ! USE_LWRES */ - struct adns_query query; + struct adns_query query; #endif /* ! USE_LWRES */ }; -extern err_t start_adns_query(const struct id *id /* domain to query */ - , const struct id *sgw_id /* if non-null, any accepted gw_info must match */ - , int type /* T_TXT or T_KEY, selecting rr type of interest */ - , cont_fn_t cont_fn /* continuation function */ - , struct adns_continuation *cr); +extern err_t start_adns_query(const struct id *id /* domain to query */ + , const struct id *sgw_id /* if non-null, any accepted gw_info must match */ + , int type /* T_TXT or T_KEY, selecting rr type of interest */ + , cont_fn_t cont_fn /* continuation function */ + , struct adns_continuation *cr); /* Gateway info gleaned from reverse DNS of client */ struct gw_info { - unsigned refcnt; /* reference counted! */ - unsigned pref; /* preference: lower is better */ -#define NO_TIME ((time_t) -2) /* time_t value meaning "not_yet" */ - struct id client_id; /* id of client of peer */ - struct id gw_id; /* id of peer (if id_is_ipaddr, .ip_addr is address) */ - bool gw_key_present; - struct pubkey *key; - struct gw_info *next; + unsigned refcnt; /* reference counted! */ + unsigned pref; /* preference: lower is better */ +#define NO_TIME ((time_t) -2) /* time_t value meaning "not_yet" */ + struct id client_id; /* id of client of peer */ + struct id gw_id; /* id of peer (if id_is_ipaddr, .ip_addr is address) */ + bool gw_key_present; + struct pubkey *key; + struct gw_info *next; }; extern void gw_addref(struct gw_info *gw) - , gw_delref(struct gw_info **gwp); + , gw_delref(struct gw_info **gwp); extern void reset_adns_restart_count(void); diff --git a/src/pluto/dsa.c b/src/pluto/dsa.c index c5982fbf4..b877c2551 100644 --- a/src/pluto/dsa.c +++ b/src/pluto/dsa.c @@ -1,5 +1,5 @@ /* dsa.c - DSA signature scheme - * Copyright (C) 1998 Free Software Foundation, Inc. + * Copyright (C) 1998 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -44,19 +44,19 @@ #include "dsa.h" typedef struct { - MPI p; /* prime */ - MPI q; /* group order */ - MPI g; /* group generator */ - MPI y; /* g^x mod p */ + MPI p; /* prime */ + MPI q; /* group order */ + MPI g; /* group generator */ + MPI y; /* g^x mod p */ } DSA_public_key; typedef struct { - MPI p; /* prime */ - MPI q; /* group order */ - MPI g; /* group generator */ - MPI y; /* g^x mod p */ - MPI x; /* secret exponent */ + MPI p; /* prime */ + MPI q; /* group order */ + MPI g; /* group generator */ + MPI y; /* g^x mod p */ + MPI x; /* secret exponent */ } DSA_secret_key; @@ -70,7 +70,7 @@ static int verify(MPI r, MPI s, MPI input, DSA_public_key *pkey); static void progress( int c ) { - fputc( c, stderr ); + fputc( c, stderr ); } @@ -80,82 +80,82 @@ progress( int c ) static MPI gen_k( MPI q ) { - MPI k = mpi_alloc_secure( mpi_get_nlimbs(q) ); - unsigned int nbits = mpi_get_nbits(q); - unsigned int nbytes = (nbits+7)/8; - char *rndbuf = NULL; + MPI k = mpi_alloc_secure( mpi_get_nlimbs(q) ); + unsigned int nbits = mpi_get_nbits(q); + unsigned int nbytes = (nbits+7)/8; + char *rndbuf = NULL; - if( DBG_CIPHER ) - log_debug("choosing a random k "); - for(;;) { if( DBG_CIPHER ) - progress('.'); + log_debug("choosing a random k "); + for(;;) { + if( DBG_CIPHER ) + progress('.'); - if( !rndbuf || nbits < 32 ) { - m_free(rndbuf); - rndbuf = get_random_bits( nbits, 1, 1 ); - } - else { /* change only some of the higher bits */ - /* we could imporove this by directly requesting more memory - * at the first call to get_random_bits() and use this the here - * maybe it is easier to do this directly in random.c */ - char *pp = get_random_bits( 32, 1, 1 ); - memcpy( rndbuf,pp, 4 ); - m_free(pp); - } - mpi_set_buffer( k, rndbuf, nbytes, 0 ); - if( mpi_test_bit( k, nbits-1 ) ) - mpi_set_highbit( k, nbits-1 ); - else { - mpi_set_highbit( k, nbits-1 ); - mpi_clear_bit( k, nbits-1 ); - } + if( !rndbuf || nbits < 32 ) { + m_free(rndbuf); + rndbuf = get_random_bits( nbits, 1, 1 ); + } + else { /* change only some of the higher bits */ + /* we could imporove this by directly requesting more memory + * at the first call to get_random_bits() and use this the here + * maybe it is easier to do this directly in random.c */ + char *pp = get_random_bits( 32, 1, 1 ); + memcpy( rndbuf,pp, 4 ); + m_free(pp); + } + mpi_set_buffer( k, rndbuf, nbytes, 0 ); + if( mpi_test_bit( k, nbits-1 ) ) + mpi_set_highbit( k, nbits-1 ); + else { + mpi_set_highbit( k, nbits-1 ); + mpi_clear_bit( k, nbits-1 ); + } - if( !(mpi_cmp( k, q ) < 0) ) { /* check: k < q */ - if( DBG_CIPHER ) - progress('+'); - continue; /* no */ + if( !(mpi_cmp( k, q ) < 0) ) { /* check: k < q */ + if( DBG_CIPHER ) + progress('+'); + continue; /* no */ + } + if( !(mpi_cmp_ui( k, 0 ) > 0) ) { /* check: k > 0 */ + if( DBG_CIPHER ) + progress('-'); + continue; /* no */ + } + break; /* okay */ } - if( !(mpi_cmp_ui( k, 0 ) > 0) ) { /* check: k > 0 */ - if( DBG_CIPHER ) - progress('-'); - continue; /* no */ - } - break; /* okay */ - } - m_free(rndbuf); - if( DBG_CIPHER ) - progress('\n'); + m_free(rndbuf); + if( DBG_CIPHER ) + progress('\n'); - return k; + return k; } static void test_keys( DSA_secret_key *sk, unsigned qbits ) { - DSA_public_key pk; - MPI test = mpi_alloc( qbits / BITS_PER_MPI_LIMB ); - MPI out1_a = mpi_alloc( qbits / BITS_PER_MPI_LIMB ); - MPI out1_b = mpi_alloc( qbits / BITS_PER_MPI_LIMB ); + DSA_public_key pk; + MPI test = mpi_alloc( qbits / BITS_PER_MPI_LIMB ); + MPI out1_a = mpi_alloc( qbits / BITS_PER_MPI_LIMB ); + MPI out1_b = mpi_alloc( qbits / BITS_PER_MPI_LIMB ); - pk.p = sk->p; - pk.q = sk->q; - pk.g = sk->g; - pk.y = sk->y; - /*mpi_set_bytes( test, qbits, get_random_byte, 0 );*/ - { char *p = get_random_bits( qbits, 0, 0 ); - mpi_set_buffer( test, p, (qbits+7)/8, 0 ); - m_free(p); - } + pk.p = sk->p; + pk.q = sk->q; + pk.g = sk->g; + pk.y = sk->y; + /*mpi_set_bytes( test, qbits, get_random_byte, 0 );*/ + { char *p = get_random_bits( qbits, 0, 0 ); + mpi_set_buffer( test, p, (qbits+7)/8, 0 ); + m_free(p); + } - sign( out1_a, out1_b, test, sk ); - if( !verify( out1_a, out1_b, test, &pk ) ) - log_fatal("DSA:: sign, verify failed\n"); + sign( out1_a, out1_b, test, sk ); + if( !verify( out1_a, out1_b, test, &pk ) ) + log_fatal("DSA:: sign, verify failed\n"); - mpi_free( test ); - mpi_free( out1_a ); - mpi_free( out1_b ); + mpi_free( test ); + mpi_free( out1_a ); + mpi_free( out1_b ); } @@ -163,91 +163,91 @@ test_keys( DSA_secret_key *sk, unsigned qbits ) /**************** * Generate a DSA key pair with a key of size NBITS * Returns: 2 structures filled with all needed values - * and an array with the n-1 factors of (p-1) + * and an array with the n-1 factors of (p-1) */ static void generate( DSA_secret_key *sk, unsigned nbits, MPI **ret_factors ) { - MPI p; /* the prime */ - MPI q; /* the 160 bit prime factor */ - MPI g; /* the generator */ - MPI y; /* g^x mod p */ - MPI x; /* the secret exponent */ - MPI h, e; /* helper */ - unsigned qbits; - byte *rndbuf; + MPI p; /* the prime */ + MPI q; /* the 160 bit prime factor */ + MPI g; /* the generator */ + MPI y; /* g^x mod p */ + MPI x; /* the secret exponent */ + MPI h, e; /* helper */ + unsigned qbits; + byte *rndbuf; - assert( nbits >= 512 && nbits <= 1024 ); + assert( nbits >= 512 && nbits <= 1024 ); - qbits = 160; - p = generate_elg_prime( 1, nbits, qbits, NULL, ret_factors ); - /* get q out of factors */ - q = mpi_copy((*ret_factors)[0]); - if( mpi_get_nbits(q) != qbits ) - BUG(); + qbits = 160; + p = generate_elg_prime( 1, nbits, qbits, NULL, ret_factors ); + /* get q out of factors */ + q = mpi_copy((*ret_factors)[0]); + if( mpi_get_nbits(q) != qbits ) + BUG(); - /* find a generator g (h and e are helpers)*/ - /* e = (p-1)/q */ - e = mpi_alloc( mpi_get_nlimbs(p) ); - mpi_sub_ui( e, p, 1 ); - mpi_fdiv_q( e, e, q ); - g = mpi_alloc( mpi_get_nlimbs(p) ); - h = mpi_alloc_set_ui( 1 ); /* we start with 2 */ - do { - mpi_add_ui( h, h, 1 ); - /* g = h^e mod p */ - mpi_powm( g, h, e, p ); - } while( !mpi_cmp_ui( g, 1 ) ); /* continue until g != 1 */ + /* find a generator g (h and e are helpers)*/ + /* e = (p-1)/q */ + e = mpi_alloc( mpi_get_nlimbs(p) ); + mpi_sub_ui( e, p, 1 ); + mpi_fdiv_q( e, e, q ); + g = mpi_alloc( mpi_get_nlimbs(p) ); + h = mpi_alloc_set_ui( 1 ); /* we start with 2 */ + do { + mpi_add_ui( h, h, 1 ); + /* g = h^e mod p */ + mpi_powm( g, h, e, p ); + } while( !mpi_cmp_ui( g, 1 ) ); /* continue until g != 1 */ - /* select a random number which has these properties: - * 0 < x < q-1 - * This must be a very good random number because this - * is the secret part. */ - if( DBG_CIPHER ) - log_debug("choosing a random x "); - assert( qbits >= 160 ); - x = mpi_alloc_secure( mpi_get_nlimbs(q) ); - mpi_sub_ui( h, q, 1 ); /* put q-1 into h */ - rndbuf = NULL; - do { + /* select a random number which has these properties: + * 0 < x < q-1 + * This must be a very good random number because this + * is the secret part. */ if( DBG_CIPHER ) - progress('.'); - if( !rndbuf ) - rndbuf = get_random_bits( qbits, 2, 1 ); - else { /* change only some of the higher bits (= 2 bytes)*/ - char *r = get_random_bits( 16, 2, 1 ); - memcpy(rndbuf, r, 16/8 ); - m_free(r); + log_debug("choosing a random x "); + assert( qbits >= 160 ); + x = mpi_alloc_secure( mpi_get_nlimbs(q) ); + mpi_sub_ui( h, q, 1 ); /* put q-1 into h */ + rndbuf = NULL; + do { + if( DBG_CIPHER ) + progress('.'); + if( !rndbuf ) + rndbuf = get_random_bits( qbits, 2, 1 ); + else { /* change only some of the higher bits (= 2 bytes)*/ + char *r = get_random_bits( 16, 2, 1 ); + memcpy(rndbuf, r, 16/8 ); + m_free(r); + } + mpi_set_buffer( x, rndbuf, (qbits+7)/8, 0 ); + mpi_clear_highbit( x, qbits+1 ); + } while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, h )<0 ) ); + m_free(rndbuf); + mpi_free( e ); + mpi_free( h ); + + /* y = g^x mod p */ + y = mpi_alloc( mpi_get_nlimbs(p) ); + mpi_powm( y, g, x, p ); + + if( DBG_CIPHER ) { + progress('\n'); + log_mpidump("dsa p= ", p ); + log_mpidump("dsa q= ", q ); + log_mpidump("dsa g= ", g ); + log_mpidump("dsa y= ", y ); + log_mpidump("dsa x= ", x ); } - mpi_set_buffer( x, rndbuf, (qbits+7)/8, 0 ); - mpi_clear_highbit( x, qbits+1 ); - } while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, h )<0 ) ); - m_free(rndbuf); - mpi_free( e ); - mpi_free( h ); - /* y = g^x mod p */ - y = mpi_alloc( mpi_get_nlimbs(p) ); - mpi_powm( y, g, x, p ); + /* copy the stuff to the key structures */ + sk->p = p; + sk->q = q; + sk->g = g; + sk->y = y; + sk->x = x; - if( DBG_CIPHER ) { - progress('\n'); - log_mpidump("dsa p= ", p ); - log_mpidump("dsa q= ", q ); - log_mpidump("dsa g= ", g ); - log_mpidump("dsa y= ", y ); - log_mpidump("dsa x= ", x ); - } - - /* copy the stuff to the key structures */ - sk->p = p; - sk->q = q; - sk->g = g; - sk->y = y; - sk->x = x; - - /* now we can test our keys (this should never fail!) */ - test_keys( sk, qbits ); + /* now we can test our keys (this should never fail!) */ + test_keys( sk, qbits ); } @@ -259,13 +259,13 @@ generate( DSA_secret_key *sk, unsigned nbits, MPI **ret_factors ) static int check_secret_key( DSA_secret_key *sk ) { - int rc; - MPI y = mpi_alloc( mpi_get_nlimbs(sk->y) ); + int rc; + MPI y = mpi_alloc( mpi_get_nlimbs(sk->y) ); - mpi_powm( y, sk->g, sk->x, sk->p ); - rc = !mpi_cmp( y, sk->y ); - mpi_free( y ); - return rc; + mpi_powm( y, sk->g, sk->x, sk->p ); + rc = !mpi_cmp( y, sk->y ); + mpi_free( y ); + return rc; } @@ -277,30 +277,30 @@ check_secret_key( DSA_secret_key *sk ) static void sign(MPI r, MPI s, MPI hash, DSA_secret_key *skey ) { - MPI k; - MPI kinv; - MPI tmp; + MPI k; + MPI kinv; + MPI tmp; - /* select a random k with 0 < k < q */ - k = gen_k( skey->q ); + /* select a random k with 0 < k < q */ + k = gen_k( skey->q ); - /* r = (a^k mod p) mod q */ - mpi_powm( r, skey->g, k, skey->p ); - mpi_fdiv_r( r, r, skey->q ); + /* r = (a^k mod p) mod q */ + mpi_powm( r, skey->g, k, skey->p ); + mpi_fdiv_r( r, r, skey->q ); - /* kinv = k^(-1) mod q */ - kinv = mpi_alloc( mpi_get_nlimbs(k) ); - mpi_invm(kinv, k, skey->q ); + /* kinv = k^(-1) mod q */ + kinv = mpi_alloc( mpi_get_nlimbs(k) ); + mpi_invm(kinv, k, skey->q ); - /* s = (kinv * ( hash + x * r)) mod q */ - tmp = mpi_alloc( mpi_get_nlimbs(skey->p) ); - mpi_mul( tmp, skey->x, r ); - mpi_add( tmp, tmp, hash ); - mpi_mulm( s , kinv, tmp, skey->q ); + /* s = (kinv * ( hash + x * r)) mod q */ + tmp = mpi_alloc( mpi_get_nlimbs(skey->p) ); + mpi_mul( tmp, skey->x, r ); + mpi_add( tmp, tmp, hash ); + mpi_mulm( s , kinv, tmp, skey->q ); - mpi_free(k); - mpi_free(kinv); - mpi_free(tmp); + mpi_free(k); + mpi_free(kinv); + mpi_free(tmp); } @@ -310,45 +310,45 @@ sign(MPI r, MPI s, MPI hash, DSA_secret_key *skey ) static int verify(MPI r, MPI s, MPI hash, DSA_public_key *pkey ) { - int rc; - MPI w, u1, u2, v; - MPI base[3]; - MPI exp[3]; + int rc; + MPI w, u1, u2, v; + MPI base[3]; + MPI exp[3]; - if( !(mpi_cmp_ui( r, 0 ) > 0 && mpi_cmp( r, pkey->q ) < 0) ) - return 0; /* assertion 0 < r < q failed */ - if( !(mpi_cmp_ui( s, 0 ) > 0 && mpi_cmp( s, pkey->q ) < 0) ) - return 0; /* assertion 0 < s < q failed */ + if( !(mpi_cmp_ui( r, 0 ) > 0 && mpi_cmp( r, pkey->q ) < 0) ) + return 0; /* assertion 0 < r < q failed */ + if( !(mpi_cmp_ui( s, 0 ) > 0 && mpi_cmp( s, pkey->q ) < 0) ) + return 0; /* assertion 0 < s < q failed */ - w = mpi_alloc( mpi_get_nlimbs(pkey->q) ); - u1 = mpi_alloc( mpi_get_nlimbs(pkey->q) ); - u2 = mpi_alloc( mpi_get_nlimbs(pkey->q) ); - v = mpi_alloc( mpi_get_nlimbs(pkey->p) ); + w = mpi_alloc( mpi_get_nlimbs(pkey->q) ); + u1 = mpi_alloc( mpi_get_nlimbs(pkey->q) ); + u2 = mpi_alloc( mpi_get_nlimbs(pkey->q) ); + v = mpi_alloc( mpi_get_nlimbs(pkey->p) ); - /* w = s^(-1) mod q */ - mpi_invm( w, s, pkey->q ); + /* w = s^(-1) mod q */ + mpi_invm( w, s, pkey->q ); - /* u1 = (hash * w) mod q */ - mpi_mulm( u1, hash, w, pkey->q ); + /* u1 = (hash * w) mod q */ + mpi_mulm( u1, hash, w, pkey->q ); - /* u2 = r * w mod q */ - mpi_mulm( u2, r, w, pkey->q ); + /* u2 = r * w mod q */ + mpi_mulm( u2, r, w, pkey->q ); - /* v = g^u1 * y^u2 mod p mod q */ - base[0] = pkey->g; exp[0] = u1; - base[1] = pkey->y; exp[1] = u2; - base[2] = NULL; exp[2] = NULL; - mpi_mulpowm( v, base, exp, pkey->p ); - mpi_fdiv_r( v, v, pkey->q ); + /* v = g^u1 * y^u2 mod p mod q */ + base[0] = pkey->g; exp[0] = u1; + base[1] = pkey->y; exp[1] = u2; + base[2] = NULL; exp[2] = NULL; + mpi_mulpowm( v, base, exp, pkey->p ); + mpi_fdiv_r( v, v, pkey->q ); - rc = !mpi_cmp( v, r ); + rc = !mpi_cmp( v, r ); - mpi_free(w); - mpi_free(u1); - mpi_free(u2); - mpi_free(v); - return rc; + mpi_free(w); + mpi_free(u1); + mpi_free(u2); + mpi_free(v); + return rc; } @@ -359,40 +359,40 @@ verify(MPI r, MPI s, MPI hash, DSA_public_key *pkey ) int dsa_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors ) { - DSA_secret_key sk; + DSA_secret_key sk; - if( algo != PUBKEY_ALGO_DSA ) - return G10ERR_PUBKEY_ALGO; + if( algo != PUBKEY_ALGO_DSA ) + return G10ERR_PUBKEY_ALGO; - generate( &sk, nbits, retfactors ); - skey[0] = sk.p; - skey[1] = sk.q; - skey[2] = sk.g; - skey[3] = sk.y; - skey[4] = sk.x; - return 0; + generate( &sk, nbits, retfactors ); + skey[0] = sk.p; + skey[1] = sk.q; + skey[2] = sk.g; + skey[3] = sk.y; + skey[4] = sk.x; + return 0; } int dsa_check_secret_key( int algo, MPI *skey ) { - DSA_secret_key sk; + DSA_secret_key sk; - if( algo != PUBKEY_ALGO_DSA ) - return G10ERR_PUBKEY_ALGO; - if( !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] ) - return G10ERR_BAD_MPI; + if( algo != PUBKEY_ALGO_DSA ) + return G10ERR_PUBKEY_ALGO; + if( !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] ) + return G10ERR_BAD_MPI; - sk.p = skey[0]; - sk.q = skey[1]; - sk.g = skey[2]; - sk.y = skey[3]; - sk.x = skey[4]; - if( !check_secret_key( &sk ) ) - return G10ERR_BAD_SECKEY; + sk.p = skey[0]; + sk.q = skey[1]; + sk.g = skey[2]; + sk.y = skey[3]; + sk.x = skey[4]; + if( !check_secret_key( &sk ) ) + return G10ERR_BAD_SECKEY; - return 0; + return 0; } @@ -400,43 +400,43 @@ dsa_check_secret_key( int algo, MPI *skey ) int dsa_sign( int algo, MPI *resarr, MPI data, MPI *skey ) { - DSA_secret_key sk; + DSA_secret_key sk; - if( algo != PUBKEY_ALGO_DSA ) - return G10ERR_PUBKEY_ALGO; - if( !data || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] ) - return G10ERR_BAD_MPI; + if( algo != PUBKEY_ALGO_DSA ) + return G10ERR_PUBKEY_ALGO; + if( !data || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] ) + return G10ERR_BAD_MPI; - sk.p = skey[0]; - sk.q = skey[1]; - sk.g = skey[2]; - sk.y = skey[3]; - sk.x = skey[4]; - resarr[0] = mpi_alloc( mpi_get_nlimbs( sk.p ) ); - resarr[1] = mpi_alloc( mpi_get_nlimbs( sk.p ) ); - sign( resarr[0], resarr[1], data, &sk ); - return 0; + sk.p = skey[0]; + sk.q = skey[1]; + sk.g = skey[2]; + sk.y = skey[3]; + sk.x = skey[4]; + resarr[0] = mpi_alloc( mpi_get_nlimbs( sk.p ) ); + resarr[1] = mpi_alloc( mpi_get_nlimbs( sk.p ) ); + sign( resarr[0], resarr[1], data, &sk ); + return 0; } int dsa_verify( int algo, MPI hash, MPI *data, MPI *pkey, - int (*cmp)(void *, MPI) UNUSED, void *opaquev UNUSED) + int (*cmp)(void *, MPI) UNUSED, void *opaquev UNUSED) { - DSA_public_key pk; + DSA_public_key pk; - if( algo != PUBKEY_ALGO_DSA ) - return G10ERR_PUBKEY_ALGO; - if( !data[0] || !data[1] || !hash - || !pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] ) - return G10ERR_BAD_MPI; + if( algo != PUBKEY_ALGO_DSA ) + return G10ERR_PUBKEY_ALGO; + if( !data[0] || !data[1] || !hash + || !pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] ) + return G10ERR_BAD_MPI; - pk.p = pkey[0]; - pk.q = pkey[1]; - pk.g = pkey[2]; - pk.y = pkey[3]; - if( !verify( data[0], data[1], hash, &pk ) ) - return G10ERR_BAD_SIGN; - return 0; + pk.p = pkey[0]; + pk.q = pkey[1]; + pk.g = pkey[2]; + pk.y = pkey[3]; + if( !verify( data[0], data[1], hash, &pk ) ) + return G10ERR_BAD_SIGN; + return 0; } @@ -444,9 +444,9 @@ dsa_verify( int algo, MPI hash, MPI *data, MPI *pkey, unsigned dsa_get_nbits( int algo, MPI *pkey ) { - if( algo != PUBKEY_ALGO_DSA ) - return 0; - return mpi_get_nbits( pkey[0] ); + if( algo != PUBKEY_ALGO_DSA ) + return 0; + return mpi_get_nbits( pkey[0] ); } @@ -454,23 +454,23 @@ dsa_get_nbits( int algo, MPI *pkey ) * Return some information about the algorithm. We need algo here to * distinguish different flavors of the algorithm. * Returns: A pointer to string describing the algorithm or NULL if - * the ALGO is invalid. + * the ALGO is invalid. * Usage: Bit 0 set : allows signing - * 1 set : allows encryption + * 1 set : allows encryption */ const char * dsa_get_info( int algo, int *npkey, int *nskey, int *nenc, int *nsig, - int *use ) + int *use ) { - *npkey = 4; - *nskey = 5; - *nenc = 0; - *nsig = 2; + *npkey = 4; + *nskey = 5; + *nenc = 0; + *nsig = 2; - switch( algo ) { - case PUBKEY_ALGO_DSA: *use = PUBKEY_USAGE_SIG; return "DSA"; - default: *use = 0; return NULL; - } + switch( algo ) { + case PUBKEY_ALGO_DSA: *use = PUBKEY_USAGE_SIG; return "DSA"; + default: *use = 0; return NULL; + } } diff --git a/src/pluto/dsa.h b/src/pluto/dsa.h index 1456d65b6..2b22eb8f8 100644 --- a/src/pluto/dsa.h +++ b/src/pluto/dsa.h @@ -1,5 +1,5 @@ /* dsa.h - DSA signature scheme - * Copyright (C) 1998 Free Software Foundation, Inc. + * Copyright (C) 1998 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -24,9 +24,9 @@ int dsa_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors ); int dsa_check_secret_key( int algo, MPI *skey ); int dsa_sign( int algo, MPI *resarr, MPI data, MPI *skey ); int dsa_verify( int algo, MPI hash, MPI *data, MPI *pkey, - int (*cmp)(void *, MPI), void *opaquev ); + int (*cmp)(void *, MPI), void *opaquev ); unsigned dsa_get_nbits( int algo, MPI *pkey ); const char *dsa_get_info( int algo, int *npkey, int *nskey, - int *nenc, int *nsig, int *use ); + int *nenc, int *nsig, int *use ); #endif /*G10_DSA_H*/ diff --git a/src/pluto/elgamal.c b/src/pluto/elgamal.c index 0c099bb90..4e888d10e 100644 --- a/src/pluto/elgamal.c +++ b/src/pluto/elgamal.c @@ -1,5 +1,5 @@ /* elgamal.c - ElGamal Public Key encryption - * Copyright (C) 1998 Free Software Foundation, Inc. + * Copyright (C) 1998 Free Software Foundation, Inc. * * For a description of the algorithm, see: * Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996. @@ -47,17 +47,17 @@ #include "elgamal.h" typedef struct { - MPI p; /* prime */ - MPI g; /* group generator */ - MPI y; /* g^x mod p */ + MPI p; /* prime */ + MPI g; /* group generator */ + MPI y; /* g^x mod p */ } ELG_public_key; typedef struct { - MPI p; /* prime */ - MPI g; /* group generator */ - MPI y; /* g^x mod p */ - MPI x; /* secret exponent */ + MPI p; /* prime */ + MPI g; /* group generator */ + MPI y; /* g^x mod p */ + MPI x; /* secret exponent */ } ELG_secret_key; @@ -74,42 +74,42 @@ static int verify(MPI a, MPI b, MPI input, ELG_public_key *pkey); static void progress( int c ) { - fputc( c, stderr ); + fputc( c, stderr ); } static void test_keys( ELG_secret_key *sk, unsigned nbits ) { - ELG_public_key pk; - MPI test = mpi_alloc( 0 ); - MPI out1_a = mpi_alloc( nbits / BITS_PER_MPI_LIMB ); - MPI out1_b = mpi_alloc( nbits / BITS_PER_MPI_LIMB ); - MPI out2 = mpi_alloc( nbits / BITS_PER_MPI_LIMB ); + ELG_public_key pk; + MPI test = mpi_alloc( 0 ); + MPI out1_a = mpi_alloc( nbits / BITS_PER_MPI_LIMB ); + MPI out1_b = mpi_alloc( nbits / BITS_PER_MPI_LIMB ); + MPI out2 = mpi_alloc( nbits / BITS_PER_MPI_LIMB ); - pk.p = sk->p; - pk.g = sk->g; - pk.y = sk->y; + pk.p = sk->p; + pk.g = sk->g; + pk.y = sk->y; - /*mpi_set_bytes( test, nbits, get_random_byte, 0 );*/ - { char *p = get_random_bits( nbits, 0, 0 ); - mpi_set_buffer( test, p, (nbits+7)/8, 0 ); - m_free(p); - } + /*mpi_set_bytes( test, nbits, get_random_byte, 0 );*/ + { char *p = get_random_bits( nbits, 0, 0 ); + mpi_set_buffer( test, p, (nbits+7)/8, 0 ); + m_free(p); + } - encrypt( out1_a, out1_b, test, &pk ); - decrypt( out2, out1_a, out1_b, sk ); - if( mpi_cmp( test, out2 ) ) - log_fatal("ElGamal operation: encrypt, decrypt failed\n"); + encrypt( out1_a, out1_b, test, &pk ); + decrypt( out2, out1_a, out1_b, sk ); + if( mpi_cmp( test, out2 ) ) + log_fatal("ElGamal operation: encrypt, decrypt failed\n"); - sign( out1_a, out1_b, test, sk ); - if( !verify( out1_a, out1_b, test, &pk ) ) - log_fatal("ElGamal operation: sign, verify failed\n"); + sign( out1_a, out1_b, test, sk ); + if( !verify( out1_a, out1_b, test, &pk ) ) + log_fatal("ElGamal operation: sign, verify failed\n"); - mpi_free( test ); - mpi_free( out1_a ); - mpi_free( out1_b ); - mpi_free( out2 ); + mpi_free( test ); + mpi_free( out1_a ); + mpi_free( out1_b ); + mpi_free( out2 ); } @@ -120,151 +120,151 @@ test_keys( ELG_secret_key *sk, unsigned nbits ) static MPI gen_k( MPI p ) { - MPI k = mpi_alloc_secure( 0 ); - MPI temp = mpi_alloc( mpi_get_nlimbs(p) ); - MPI p_1 = mpi_copy(p); - unsigned int nbits = mpi_get_nbits(p); - unsigned int nbytes = (nbits+7)/8; - char *rndbuf = NULL; + MPI k = mpi_alloc_secure( 0 ); + MPI temp = mpi_alloc( mpi_get_nlimbs(p) ); + MPI p_1 = mpi_copy(p); + unsigned int nbits = mpi_get_nbits(p); + unsigned int nbytes = (nbits+7)/8; + char *rndbuf = NULL; - if( DBG_CIPHER ) - log_debug("choosing a random k "); - mpi_sub_ui( p_1, p, 1); - for(;;) { if( DBG_CIPHER ) - progress('.'); - if( !rndbuf || nbits < 32 ) { - m_free(rndbuf); - rndbuf = get_random_bits( nbits, 1, 1 ); - } - else { /* change only some of the higher bits */ - /* we could imporove this by directly requesting more memory - * at the first call to get_random_bits() and use this the here - * maybe it is easier to do this directly in random.c */ - char *pp = get_random_bits( 32, 1, 1 ); - memcpy( rndbuf,pp, 4 ); - m_free(pp); - } - mpi_set_buffer( k, rndbuf, nbytes, 0 ); - + log_debug("choosing a random k "); + mpi_sub_ui( p_1, p, 1); for(;;) { - /* make sure that the number is of the exact lenght */ - if( mpi_test_bit( k, nbits-1 ) ) - mpi_set_highbit( k, nbits-1 ); - else { - mpi_set_highbit( k, nbits-1 ); - mpi_clear_bit( k, nbits-1 ); - } - if( !(mpi_cmp( k, p_1 ) < 0) ) { /* check: k < (p-1) */ if( DBG_CIPHER ) - progress('+'); - break; /* no */ - } - if( !(mpi_cmp_ui( k, 0 ) > 0) ) { /* check: k > 0 */ - if( DBG_CIPHER ) - progress('-'); - break; /* no */ - } - if( mpi_gcd( temp, k, p_1 ) ) - goto found; /* okay, k is relatively prime to (p-1) */ - mpi_add_ui( k, k, 1 ); - } - } - found: - m_free(rndbuf); - if( DBG_CIPHER ) - progress('\n'); - mpi_free(p_1); - mpi_free(temp); + progress('.'); + if( !rndbuf || nbits < 32 ) { + m_free(rndbuf); + rndbuf = get_random_bits( nbits, 1, 1 ); + } + else { /* change only some of the higher bits */ + /* we could imporove this by directly requesting more memory + * at the first call to get_random_bits() and use this the here + * maybe it is easier to do this directly in random.c */ + char *pp = get_random_bits( 32, 1, 1 ); + memcpy( rndbuf,pp, 4 ); + m_free(pp); + } + mpi_set_buffer( k, rndbuf, nbytes, 0 ); - return k; + for(;;) { + /* make sure that the number is of the exact lenght */ + if( mpi_test_bit( k, nbits-1 ) ) + mpi_set_highbit( k, nbits-1 ); + else { + mpi_set_highbit( k, nbits-1 ); + mpi_clear_bit( k, nbits-1 ); + } + if( !(mpi_cmp( k, p_1 ) < 0) ) { /* check: k < (p-1) */ + if( DBG_CIPHER ) + progress('+'); + break; /* no */ + } + if( !(mpi_cmp_ui( k, 0 ) > 0) ) { /* check: k > 0 */ + if( DBG_CIPHER ) + progress('-'); + break; /* no */ + } + if( mpi_gcd( temp, k, p_1 ) ) + goto found; /* okay, k is relatively prime to (p-1) */ + mpi_add_ui( k, k, 1 ); + } + } + found: + m_free(rndbuf); + if( DBG_CIPHER ) + progress('\n'); + mpi_free(p_1); + mpi_free(temp); + + return k; } /**************** * Generate a key pair with a key of size NBITS * Returns: 2 structures filles with all needed values - * and an array with n-1 factors of (p-1) + * and an array with n-1 factors of (p-1) */ static void generate( ELG_secret_key *sk, unsigned nbits, MPI **ret_factors ) { - MPI p; /* the prime */ - MPI p_min1; - MPI g; - MPI x; /* the secret exponent */ - MPI y; - MPI temp; - unsigned qbits; - byte *rndbuf; + MPI p; /* the prime */ + MPI p_min1; + MPI g; + MPI x; /* the secret exponent */ + MPI y; + MPI temp; + unsigned qbits; + byte *rndbuf; - p_min1 = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB ); - temp = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB ); - if( nbits < 512 ) - qbits = 120; - else if( nbits <= 1024 ) - qbits = 160; - else if( nbits <= 2048 ) - qbits = 200; - else - qbits = 240; - g = mpi_alloc(1); - p = generate_elg_prime( 0, nbits, qbits, g, ret_factors ); - mpi_sub_ui(p_min1, p, 1); - - - /* select a random number which has these properties: - * 0 < x < p-1 - * This must be a very good random number because this is the - * secret part. The prime is public and may be shared anyway, - * so a random generator level of 1 is used for the prime. - */ - x = mpi_alloc_secure( nbits/BITS_PER_MPI_LIMB ); - if( DBG_CIPHER ) - log_debug("choosing a random x "); - rndbuf = NULL; - do { - if( DBG_CIPHER ) - progress('.'); - if( rndbuf ) { /* change only some of the higher bits */ - if( nbits < 16 ) {/* should never happen ... */ - m_free(rndbuf); - rndbuf = get_random_bits( nbits, 2, 1 ); - } - else { - char *r = get_random_bits( 16, 2, 1 ); - memcpy(rndbuf, r, 16/8 ); - m_free(r); - } - } + p_min1 = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB ); + temp = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB ); + if( nbits < 512 ) + qbits = 120; + else if( nbits <= 1024 ) + qbits = 160; + else if( nbits <= 2048 ) + qbits = 200; else - rndbuf = get_random_bits( nbits, 2, 1 ); - mpi_set_buffer( x, rndbuf, (nbits+7)/8, 0 ); - mpi_clear_highbit( x, nbits+1 ); - } while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, p_min1 )<0 ) ); - m_free(rndbuf); + qbits = 240; + g = mpi_alloc(1); + p = generate_elg_prime( 0, nbits, qbits, g, ret_factors ); + mpi_sub_ui(p_min1, p, 1); - y = mpi_alloc(nbits/BITS_PER_MPI_LIMB); - mpi_powm( y, g, x, p ); - if( DBG_CIPHER ) { - progress('\n'); - log_mpidump("elg p= ", p ); - log_mpidump("elg g= ", g ); - log_mpidump("elg y= ", y ); - log_mpidump("elg x= ", x ); - } + /* select a random number which has these properties: + * 0 < x < p-1 + * This must be a very good random number because this is the + * secret part. The prime is public and may be shared anyway, + * so a random generator level of 1 is used for the prime. + */ + x = mpi_alloc_secure( nbits/BITS_PER_MPI_LIMB ); + if( DBG_CIPHER ) + log_debug("choosing a random x "); + rndbuf = NULL; + do { + if( DBG_CIPHER ) + progress('.'); + if( rndbuf ) { /* change only some of the higher bits */ + if( nbits < 16 ) {/* should never happen ... */ + m_free(rndbuf); + rndbuf = get_random_bits( nbits, 2, 1 ); + } + else { + char *r = get_random_bits( 16, 2, 1 ); + memcpy(rndbuf, r, 16/8 ); + m_free(r); + } + } + else + rndbuf = get_random_bits( nbits, 2, 1 ); + mpi_set_buffer( x, rndbuf, (nbits+7)/8, 0 ); + mpi_clear_highbit( x, nbits+1 ); + } while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, p_min1 )<0 ) ); + m_free(rndbuf); - /* copy the stuff to the key structures */ - sk->p = p; - sk->g = g; - sk->y = y; - sk->x = x; + y = mpi_alloc(nbits/BITS_PER_MPI_LIMB); + mpi_powm( y, g, x, p ); - /* now we can test our keys (this should never fail!) */ - test_keys( sk, nbits - 64 ); + if( DBG_CIPHER ) { + progress('\n'); + log_mpidump("elg p= ", p ); + log_mpidump("elg g= ", g ); + log_mpidump("elg y= ", y ); + log_mpidump("elg x= ", x ); + } - mpi_free( p_min1 ); - mpi_free( temp ); + /* copy the stuff to the key structures */ + sk->p = p; + sk->g = g; + sk->y = y; + sk->x = x; + + /* now we can test our keys (this should never fail!) */ + test_keys( sk, nbits - 64 ); + + mpi_free( p_min1 ); + mpi_free( temp ); } @@ -275,46 +275,46 @@ generate( ELG_secret_key *sk, unsigned nbits, MPI **ret_factors ) static int check_secret_key( ELG_secret_key *sk ) { - int rc; - MPI y = mpi_alloc( mpi_get_nlimbs(sk->y) ); + int rc; + MPI y = mpi_alloc( mpi_get_nlimbs(sk->y) ); - mpi_powm( y, sk->g, sk->x, sk->p ); - rc = !mpi_cmp( y, sk->y ); - mpi_free( y ); - return rc; + mpi_powm( y, sk->g, sk->x, sk->p ); + rc = !mpi_cmp( y, sk->y ); + mpi_free( y ); + return rc; } static void encrypt(MPI a, MPI b, MPI input, ELG_public_key *pkey ) { - MPI k; + MPI k; - /* Note: maybe we should change the interface, so that it - * is possible to check that input is < p and return an - * error code. - */ + /* Note: maybe we should change the interface, so that it + * is possible to check that input is < p and return an + * error code. + */ - k = gen_k( pkey->p ); - mpi_powm( a, pkey->g, k, pkey->p ); - /* b = (y^k * input) mod p - * = ((y^k mod p) * (input mod p)) mod p - * and because input is < p - * = ((y^k mod p) * input) mod p - */ - mpi_powm( b, pkey->y, k, pkey->p ); - mpi_mulm( b, b, input, pkey->p ); + k = gen_k( pkey->p ); + mpi_powm( a, pkey->g, k, pkey->p ); + /* b = (y^k * input) mod p + * = ((y^k mod p) * (input mod p)) mod p + * and because input is < p + * = ((y^k mod p) * input) mod p + */ + mpi_powm( b, pkey->y, k, pkey->p ); + mpi_mulm( b, b, input, pkey->p ); #if 0 - if( DBG_CIPHER ) { - log_mpidump("elg encrypted y= ", pkey->y); - log_mpidump("elg encrypted p= ", pkey->p); - log_mpidump("elg encrypted k= ", k); - log_mpidump("elg encrypted M= ", input); - log_mpidump("elg encrypted a= ", a); - log_mpidump("elg encrypted b= ", b); - } + if( DBG_CIPHER ) { + log_mpidump("elg encrypted y= ", pkey->y); + log_mpidump("elg encrypted p= ", pkey->p); + log_mpidump("elg encrypted k= ", k); + log_mpidump("elg encrypted M= ", input); + log_mpidump("elg encrypted a= ", a); + log_mpidump("elg encrypted b= ", b); + } #endif - mpi_free(k); + mpi_free(k); } @@ -323,23 +323,23 @@ encrypt(MPI a, MPI b, MPI input, ELG_public_key *pkey ) static void decrypt(MPI output, MPI a, MPI b, ELG_secret_key *skey ) { - MPI t1 = mpi_alloc_secure( mpi_get_nlimbs( skey->p ) ); + MPI t1 = mpi_alloc_secure( mpi_get_nlimbs( skey->p ) ); - /* output = b/(a^x) mod p */ + /* output = b/(a^x) mod p */ - mpi_powm( t1, a, skey->x, skey->p ); - mpi_invm( t1, t1, skey->p ); - mpi_mulm( output, b, t1, skey->p ); + mpi_powm( t1, a, skey->x, skey->p ); + mpi_invm( t1, t1, skey->p ); + mpi_mulm( output, b, t1, skey->p ); #if 0 - if( DBG_CIPHER ) { - log_mpidump("elg decrypted x= ", skey->x); - log_mpidump("elg decrypted p= ", skey->p); - log_mpidump("elg decrypted a= ", a); - log_mpidump("elg decrypted b= ", b); - log_mpidump("elg decrypted M= ", output); - } + if( DBG_CIPHER ) { + log_mpidump("elg decrypted x= ", skey->x); + log_mpidump("elg decrypted p= ", skey->p); + log_mpidump("elg decrypted a= ", a); + log_mpidump("elg decrypted b= ", b); + log_mpidump("elg decrypted M= ", output); + } #endif - mpi_free(t1); + mpi_free(t1); } @@ -350,43 +350,43 @@ decrypt(MPI output, MPI a, MPI b, ELG_secret_key *skey ) static void sign(MPI a, MPI b, MPI input, ELG_secret_key *skey ) { - MPI k; - MPI t = mpi_alloc( mpi_get_nlimbs(a) ); - MPI inv = mpi_alloc( mpi_get_nlimbs(a) ); - MPI p_1 = mpi_copy(skey->p); + MPI k; + MPI t = mpi_alloc( mpi_get_nlimbs(a) ); + MPI inv = mpi_alloc( mpi_get_nlimbs(a) ); + MPI p_1 = mpi_copy(skey->p); /* - * b = (t * inv) mod (p-1) - * b = (t * inv(k,(p-1),(p-1)) mod (p-1) - * b = (((M-x*a) mod (p-1)) * inv(k,(p-1),(p-1))) mod (p-1) - * - */ - mpi_sub_ui(p_1, p_1, 1); - k = gen_k( skey->p ); - mpi_powm( a, skey->g, k, skey->p ); - mpi_mul(t, skey->x, a ); - mpi_subm(t, input, t, p_1 ); - while( mpi_is_neg(t) ) - mpi_add(t, t, p_1); - mpi_invm(inv, k, p_1 ); - mpi_mulm(b, t, inv, p_1 ); + * b = (t * inv) mod (p-1) + * b = (t * inv(k,(p-1),(p-1)) mod (p-1) + * b = (((M-x*a) mod (p-1)) * inv(k,(p-1),(p-1))) mod (p-1) + * + */ + mpi_sub_ui(p_1, p_1, 1); + k = gen_k( skey->p ); + mpi_powm( a, skey->g, k, skey->p ); + mpi_mul(t, skey->x, a ); + mpi_subm(t, input, t, p_1 ); + while( mpi_is_neg(t) ) + mpi_add(t, t, p_1); + mpi_invm(inv, k, p_1 ); + mpi_mulm(b, t, inv, p_1 ); #if 0 - if( DBG_CIPHER ) { - log_mpidump("elg sign p= ", skey->p); - log_mpidump("elg sign g= ", skey->g); - log_mpidump("elg sign y= ", skey->y); - log_mpidump("elg sign x= ", skey->x); - log_mpidump("elg sign k= ", k); - log_mpidump("elg sign M= ", input); - log_mpidump("elg sign a= ", a); - log_mpidump("elg sign b= ", b); - } + if( DBG_CIPHER ) { + log_mpidump("elg sign p= ", skey->p); + log_mpidump("elg sign g= ", skey->g); + log_mpidump("elg sign y= ", skey->y); + log_mpidump("elg sign x= ", skey->x); + log_mpidump("elg sign k= ", k); + log_mpidump("elg sign M= ", input); + log_mpidump("elg sign a= ", a); + log_mpidump("elg sign b= ", b); + } #endif - mpi_free(k); - mpi_free(t); - mpi_free(inv); - mpi_free(p_1); + mpi_free(k); + mpi_free(t); + mpi_free(inv); + mpi_free(p_1); } @@ -396,54 +396,54 @@ sign(MPI a, MPI b, MPI input, ELG_secret_key *skey ) static int verify(MPI a, MPI b, MPI input, ELG_public_key *pkey ) { - int rc; - MPI t1; - MPI t2; - MPI base[4]; - MPI exp[4]; + int rc; + MPI t1; + MPI t2; + MPI base[4]; + MPI exp[4]; - if( !(mpi_cmp_ui( a, 0 ) > 0 && mpi_cmp( a, pkey->p ) < 0) ) - return 0; /* assertion 0 < a < p failed */ + if( !(mpi_cmp_ui( a, 0 ) > 0 && mpi_cmp( a, pkey->p ) < 0) ) + return 0; /* assertion 0 < a < p failed */ - t1 = mpi_alloc( mpi_get_nlimbs(a) ); - t2 = mpi_alloc( mpi_get_nlimbs(a) ); + t1 = mpi_alloc( mpi_get_nlimbs(a) ); + t2 = mpi_alloc( mpi_get_nlimbs(a) ); #if 0 - /* t1 = (y^a mod p) * (a^b mod p) mod p */ - mpi_powm( t1, pkey->y, a, pkey->p ); - mpi_powm( t2, a, b, pkey->p ); - mpi_mulm( t1, t1, t2, pkey->p ); + /* t1 = (y^a mod p) * (a^b mod p) mod p */ + mpi_powm( t1, pkey->y, a, pkey->p ); + mpi_powm( t2, a, b, pkey->p ); + mpi_mulm( t1, t1, t2, pkey->p ); - /* t2 = g ^ input mod p */ - mpi_powm( t2, pkey->g, input, pkey->p ); + /* t2 = g ^ input mod p */ + mpi_powm( t2, pkey->g, input, pkey->p ); - rc = !mpi_cmp( t1, t2 ); + rc = !mpi_cmp( t1, t2 ); #elif 0 - /* t1 = (y^a mod p) * (a^b mod p) mod p */ - base[0] = pkey->y; exp[0] = a; - base[1] = a; exp[1] = b; - base[2] = NULL; exp[2] = NULL; - mpi_mulpowm( t1, base, exp, pkey->p ); + /* t1 = (y^a mod p) * (a^b mod p) mod p */ + base[0] = pkey->y; exp[0] = a; + base[1] = a; exp[1] = b; + base[2] = NULL; exp[2] = NULL; + mpi_mulpowm( t1, base, exp, pkey->p ); - /* t2 = g ^ input mod p */ - mpi_powm( t2, pkey->g, input, pkey->p ); + /* t2 = g ^ input mod p */ + mpi_powm( t2, pkey->g, input, pkey->p ); - rc = !mpi_cmp( t1, t2 ); + rc = !mpi_cmp( t1, t2 ); #else - /* t1 = g ^ - input * y ^ a * a ^ b mod p */ - mpi_invm(t2, pkey->g, pkey->p ); - base[0] = t2 ; exp[0] = input; - base[1] = pkey->y; exp[1] = a; - base[2] = a; exp[2] = b; - base[3] = NULL; exp[3] = NULL; - mpi_mulpowm( t1, base, exp, pkey->p ); - rc = !mpi_cmp_ui( t1, 1 ); + /* t1 = g ^ - input * y ^ a * a ^ b mod p */ + mpi_invm(t2, pkey->g, pkey->p ); + base[0] = t2 ; exp[0] = input; + base[1] = pkey->y; exp[1] = a; + base[2] = a; exp[2] = b; + base[3] = NULL; exp[3] = NULL; + mpi_mulpowm( t1, base, exp, pkey->p ); + rc = !mpi_cmp_ui( t1, 1 ); #endif - mpi_free(t1); - mpi_free(t2); - return rc; + mpi_free(t1); + mpi_free(t2); + return rc; } /********************************************* @@ -453,38 +453,38 @@ verify(MPI a, MPI b, MPI input, ELG_public_key *pkey ) int elg_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors ) { - ELG_secret_key sk; + ELG_secret_key sk; - if( !is_ELGAMAL(algo) ) - return G10ERR_PUBKEY_ALGO; + if( !is_ELGAMAL(algo) ) + return G10ERR_PUBKEY_ALGO; - generate( &sk, nbits, retfactors ); - skey[0] = sk.p; - skey[1] = sk.g; - skey[2] = sk.y; - skey[3] = sk.x; - return 0; + generate( &sk, nbits, retfactors ); + skey[0] = sk.p; + skey[1] = sk.g; + skey[2] = sk.y; + skey[3] = sk.x; + return 0; } int elg_check_secret_key( int algo, MPI *skey ) { - ELG_secret_key sk; + ELG_secret_key sk; - if( !is_ELGAMAL(algo) ) - return G10ERR_PUBKEY_ALGO; - if( !skey[0] || !skey[1] || !skey[2] || !skey[3] ) - return G10ERR_BAD_MPI; + if( !is_ELGAMAL(algo) ) + return G10ERR_PUBKEY_ALGO; + if( !skey[0] || !skey[1] || !skey[2] || !skey[3] ) + return G10ERR_BAD_MPI; - sk.p = skey[0]; - sk.g = skey[1]; - sk.y = skey[2]; - sk.x = skey[3]; - if( !check_secret_key( &sk ) ) - return G10ERR_BAD_SECKEY; + sk.p = skey[0]; + sk.g = skey[1]; + sk.y = skey[2]; + sk.x = skey[3]; + if( !check_secret_key( &sk ) ) + return G10ERR_BAD_SECKEY; - return 0; + return 0; } @@ -492,80 +492,80 @@ elg_check_secret_key( int algo, MPI *skey ) int elg_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ) { - ELG_public_key pk; + ELG_public_key pk; - if( !is_ELGAMAL(algo) ) - return G10ERR_PUBKEY_ALGO; - if( !data || !pkey[0] || !pkey[1] || !pkey[2] ) - return G10ERR_BAD_MPI; + if( !is_ELGAMAL(algo) ) + return G10ERR_PUBKEY_ALGO; + if( !data || !pkey[0] || !pkey[1] || !pkey[2] ) + return G10ERR_BAD_MPI; - pk.p = pkey[0]; - pk.g = pkey[1]; - pk.y = pkey[2]; - resarr[0] = mpi_alloc( mpi_get_nlimbs( pk.p ) ); - resarr[1] = mpi_alloc( mpi_get_nlimbs( pk.p ) ); - encrypt( resarr[0], resarr[1], data, &pk ); - return 0; + pk.p = pkey[0]; + pk.g = pkey[1]; + pk.y = pkey[2]; + resarr[0] = mpi_alloc( mpi_get_nlimbs( pk.p ) ); + resarr[1] = mpi_alloc( mpi_get_nlimbs( pk.p ) ); + encrypt( resarr[0], resarr[1], data, &pk ); + return 0; } int elg_decrypt( int algo, MPI *result, MPI *data, MPI *skey ) { - ELG_secret_key sk; + ELG_secret_key sk; - if( !is_ELGAMAL(algo) ) - return G10ERR_PUBKEY_ALGO; - if( !data[0] || !data[1] - || !skey[0] || !skey[1] || !skey[2] || !skey[3] ) - return G10ERR_BAD_MPI; + if( !is_ELGAMAL(algo) ) + return G10ERR_PUBKEY_ALGO; + if( !data[0] || !data[1] + || !skey[0] || !skey[1] || !skey[2] || !skey[3] ) + return G10ERR_BAD_MPI; - sk.p = skey[0]; - sk.g = skey[1]; - sk.y = skey[2]; - sk.x = skey[3]; - *result = mpi_alloc_secure( mpi_get_nlimbs( sk.p ) ); - decrypt( *result, data[0], data[1], &sk ); - return 0; + sk.p = skey[0]; + sk.g = skey[1]; + sk.y = skey[2]; + sk.x = skey[3]; + *result = mpi_alloc_secure( mpi_get_nlimbs( sk.p ) ); + decrypt( *result, data[0], data[1], &sk ); + return 0; } int elg_sign( int algo, MPI *resarr, MPI data, MPI *skey ) { - ELG_secret_key sk; + ELG_secret_key sk; - if( !is_ELGAMAL(algo) ) - return G10ERR_PUBKEY_ALGO; - if( !data || !skey[0] || !skey[1] || !skey[2] || !skey[3] ) - return G10ERR_BAD_MPI; + if( !is_ELGAMAL(algo) ) + return G10ERR_PUBKEY_ALGO; + if( !data || !skey[0] || !skey[1] || !skey[2] || !skey[3] ) + return G10ERR_BAD_MPI; - sk.p = skey[0]; - sk.g = skey[1]; - sk.y = skey[2]; - sk.x = skey[3]; - resarr[0] = mpi_alloc( mpi_get_nlimbs( sk.p ) ); - resarr[1] = mpi_alloc( mpi_get_nlimbs( sk.p ) ); - sign( resarr[0], resarr[1], data, &sk ); - return 0; + sk.p = skey[0]; + sk.g = skey[1]; + sk.y = skey[2]; + sk.x = skey[3]; + resarr[0] = mpi_alloc( mpi_get_nlimbs( sk.p ) ); + resarr[1] = mpi_alloc( mpi_get_nlimbs( sk.p ) ); + sign( resarr[0], resarr[1], data, &sk ); + return 0; } int elg_verify( int algo, MPI hash, MPI *data, MPI *pkey, - int (*cmp)(void *, MPI) UNUSED, void *opaquev UNUSED) + int (*cmp)(void *, MPI) UNUSED, void *opaquev UNUSED) { - ELG_public_key pk; + ELG_public_key pk; - if( !is_ELGAMAL(algo) ) - return G10ERR_PUBKEY_ALGO; - if( !data[0] || !data[1] || !hash - || !pkey[0] || !pkey[1] || !pkey[2] ) - return G10ERR_BAD_MPI; + if( !is_ELGAMAL(algo) ) + return G10ERR_PUBKEY_ALGO; + if( !data[0] || !data[1] || !hash + || !pkey[0] || !pkey[1] || !pkey[2] ) + return G10ERR_BAD_MPI; - pk.p = pkey[0]; - pk.g = pkey[1]; - pk.y = pkey[2]; - if( !verify( data[0], data[1], hash, &pk ) ) - return G10ERR_BAD_SIGN; - return 0; + pk.p = pkey[0]; + pk.g = pkey[1]; + pk.y = pkey[2]; + if( !verify( data[0], data[1], hash, &pk ) ) + return G10ERR_BAD_SIGN; + return 0; } @@ -573,9 +573,9 @@ elg_verify( int algo, MPI hash, MPI *data, MPI *pkey, unsigned elg_get_nbits( int algo, MPI *pkey ) { - if( !is_ELGAMAL(algo) ) - return 0; - return mpi_get_nbits( pkey[0] ); + if( !is_ELGAMAL(algo) ) + return 0; + return mpi_get_nbits( pkey[0] ); } @@ -583,31 +583,31 @@ elg_get_nbits( int algo, MPI *pkey ) * Return some information about the algorithm. We need algo here to * distinguish different flavors of the algorithm. * Returns: A pointer to string describing the algorithm or NULL if - * the ALGO is invalid. + * the ALGO is invalid. * Usage: Bit 0 set : allows signing - * 1 set : allows encryption + * 1 set : allows encryption * NOTE: This function allows signing also for ELG-E, which is not * okay but a bad hack to allow to work with old gpg keys. The real check * is done in the gnupg ocde depending on the packet version. */ const char * elg_get_info( int algo, int *npkey, int *nskey, int *nenc, int *nsig, - int *use ) + int *use ) { - *npkey = 3; - *nskey = 4; - *nenc = 2; - *nsig = 2; + *npkey = 3; + *nskey = 4; + *nenc = 2; + *nsig = 2; - switch( algo ) { - case PUBKEY_ALGO_ELGAMAL: - *use = PUBKEY_USAGE_SIG|PUBKEY_USAGE_ENC; - return "ELG"; - case PUBKEY_ALGO_ELGAMAL_E: - *use = PUBKEY_USAGE_SIG|PUBKEY_USAGE_ENC; - return "ELG-E"; - default: *use = 0; return NULL; - } + switch( algo ) { + case PUBKEY_ALGO_ELGAMAL: + *use = PUBKEY_USAGE_SIG|PUBKEY_USAGE_ENC; + return "ELG"; + case PUBKEY_ALGO_ELGAMAL_E: + *use = PUBKEY_USAGE_SIG|PUBKEY_USAGE_ENC; + return "ELG-E"; + default: *use = 0; return NULL; + } } diff --git a/src/pluto/elgamal.h b/src/pluto/elgamal.h index f104c2a52..7ce8a914a 100644 --- a/src/pluto/elgamal.h +++ b/src/pluto/elgamal.h @@ -1,5 +1,5 @@ /* elgamal.h - * Copyright (C) 1998 Free Software Foundation, Inc. + * Copyright (C) 1998 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -26,10 +26,10 @@ int elg_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ); int elg_decrypt( int algo, MPI *result, MPI *data, MPI *skey ); int elg_sign( int algo, MPI *resarr, MPI data, MPI *skey ); int elg_verify( int algo, MPI hash, MPI *data, MPI *pkey, - int (*cmp)(void *, MPI), void *opaquev ); + int (*cmp)(void *, MPI), void *opaquev ); unsigned elg_get_nbits( int algo, MPI *pkey ); const char *elg_get_info( int algo, int *npkey, int *nskey, - int *nenc, int *nsig, int *use ); + int *nenc, int *nsig, int *use ); #endif /*G10_ELGAMAL_H*/ diff --git a/src/pluto/fetch.c b/src/pluto/fetch.c index ecffe76b0..e191f38c5 100644 --- a/src/pluto/fetch.c +++ b/src/pluto/fetch.c @@ -33,7 +33,7 @@ #ifdef LIBLDAP #ifndef LDAP_DEPRECATED -#define LDAP_DEPRECATED 1 +#define LDAP_DEPRECATED 1 #endif #include #endif @@ -52,13 +52,13 @@ #include "fetch.h" fetch_req_t empty_fetch_req = { - NULL , /* next */ - 0 , /* installed */ - 0 , /* trials */ + NULL , /* next */ + 0 , /* installed */ + 0 , /* trials */ { NULL, 0}, /* issuer */ { NULL, 0}, /* authKeyID */ { NULL, 0}, /* authKeySerialNumber */ - NULL /* distributionPoints */ + NULL /* distributionPoints */ }; /* chained list of crl fetch requests */ @@ -85,10 +85,10 @@ static pthread_cond_t fetch_wake_cond = PTHREAD_COND_INITIALIZER; void lock_certs_and_keys(const char *who) { - pthread_mutex_lock(&certs_and_keys_mutex); - DBG(DBG_CONTROLMORE, - DBG_log("certs and keys locked by '%s'", who) - ) + pthread_mutex_lock(&certs_and_keys_mutex); + DBG(DBG_CONTROLMORE, + DBG_log("certs and keys locked by '%s'", who) + ) } /* @@ -97,10 +97,10 @@ lock_certs_and_keys(const char *who) void unlock_certs_and_keys(const char *who) { - DBG(DBG_CONTROLMORE, - DBG_log("certs and keys unlocked by '%s'", who) - ) - pthread_mutex_unlock(&certs_and_keys_mutex); + DBG(DBG_CONTROLMORE, + DBG_log("certs and keys unlocked by '%s'", who) + ) + pthread_mutex_unlock(&certs_and_keys_mutex); } /* @@ -109,10 +109,10 @@ unlock_certs_and_keys(const char *who) void lock_authcert_list(const char *who) { - pthread_mutex_lock(&authcert_list_mutex); - DBG(DBG_CONTROLMORE, - DBG_log("authcert list locked by '%s'", who) - ) + pthread_mutex_lock(&authcert_list_mutex); + DBG(DBG_CONTROLMORE, + DBG_log("authcert list locked by '%s'", who) + ) } /* @@ -121,10 +121,10 @@ lock_authcert_list(const char *who) void unlock_authcert_list(const char *who) { - DBG(DBG_CONTROLMORE, - DBG_log("authcert list unlocked by '%s'", who) - ) - pthread_mutex_unlock(&authcert_list_mutex); + DBG(DBG_CONTROLMORE, + DBG_log("authcert list unlocked by '%s'", who) + ) + pthread_mutex_unlock(&authcert_list_mutex); } /* @@ -133,10 +133,10 @@ unlock_authcert_list(const char *who) void lock_crl_list(const char *who) { - pthread_mutex_lock(&crl_list_mutex); - DBG(DBG_CONTROLMORE, - DBG_log("crl list locked by '%s'", who) - ) + pthread_mutex_lock(&crl_list_mutex); + DBG(DBG_CONTROLMORE, + DBG_log("crl list locked by '%s'", who) + ) } /* @@ -145,10 +145,10 @@ lock_crl_list(const char *who) void unlock_crl_list(const char *who) { - DBG(DBG_CONTROLMORE, - DBG_log("crl list unlocked by '%s'", who) - ) - pthread_mutex_unlock(&crl_list_mutex); + DBG(DBG_CONTROLMORE, + DBG_log("crl list unlocked by '%s'", who) + ) + pthread_mutex_unlock(&crl_list_mutex); } /* @@ -157,10 +157,10 @@ unlock_crl_list(const char *who) extern void lock_ocsp_cache(const char *who) { - pthread_mutex_lock(&ocsp_cache_mutex); - DBG(DBG_CONTROLMORE, - DBG_log("ocsp cache locked by '%s'", who) - ) + pthread_mutex_lock(&ocsp_cache_mutex); + DBG(DBG_CONTROLMORE, + DBG_log("ocsp cache locked by '%s'", who) + ) } /* @@ -169,10 +169,10 @@ lock_ocsp_cache(const char *who) extern void unlock_ocsp_cache(const char *who) { - DBG(DBG_CONTROLMORE, - DBG_log("ocsp cache unlocked by '%s'", who) - ) - pthread_mutex_unlock(&ocsp_cache_mutex); + DBG(DBG_CONTROLMORE, + DBG_log("ocsp cache unlocked by '%s'", who) + ) + pthread_mutex_unlock(&ocsp_cache_mutex); } /* @@ -181,10 +181,10 @@ unlock_ocsp_cache(const char *who) extern void lock_ca_info_list(const char *who) { - pthread_mutex_lock(&ca_info_list_mutex); - DBG(DBG_CONTROLMORE, - DBG_log("ca info list locked by '%s'", who) - ) + pthread_mutex_lock(&ca_info_list_mutex); + DBG(DBG_CONTROLMORE, + DBG_log("ca info list locked by '%s'", who) + ) } /* @@ -193,10 +193,10 @@ lock_ca_info_list(const char *who) extern void unlock_ca_info_list(const char *who) { - DBG(DBG_CONTROLMORE, - DBG_log("ca info list unlocked by '%s'", who) - ) - pthread_mutex_unlock(&ca_info_list_mutex); + DBG(DBG_CONTROLMORE, + DBG_log("ca info list unlocked by '%s'", who) + ) + pthread_mutex_unlock(&ca_info_list_mutex); } /* @@ -205,10 +205,10 @@ unlock_ca_info_list(const char *who) static void lock_crl_fetch_list(const char *who) { - pthread_mutex_lock(&crl_fetch_list_mutex); - DBG(DBG_CONTROLMORE, - DBG_log("crl fetch request list locked by '%s'", who) - ) + pthread_mutex_lock(&crl_fetch_list_mutex); + DBG(DBG_CONTROLMORE, + DBG_log("crl fetch request list locked by '%s'", who) + ) } /* @@ -217,10 +217,10 @@ lock_crl_fetch_list(const char *who) static void unlock_crl_fetch_list(const char *who) { - DBG(DBG_CONTROLMORE, - DBG_log("crl fetch request list unlocked by '%s'", who) - ) - pthread_mutex_unlock(&crl_fetch_list_mutex); + DBG(DBG_CONTROLMORE, + DBG_log("crl fetch request list unlocked by '%s'", who) + ) + pthread_mutex_unlock(&crl_fetch_list_mutex); } /* @@ -229,10 +229,10 @@ unlock_crl_fetch_list(const char *who) static void lock_ocsp_fetch_list(const char *who) { - pthread_mutex_lock(&ocsp_fetch_list_mutex); - DBG(DBG_CONTROLMORE, - DBG_log("ocsp fetch request list locked by '%s'", who) - ) + pthread_mutex_lock(&ocsp_fetch_list_mutex); + DBG(DBG_CONTROLMORE, + DBG_log("ocsp fetch request list locked by '%s'", who) + ) } /* @@ -241,10 +241,10 @@ lock_ocsp_fetch_list(const char *who) static void unlock_ocsp_fetch_list(const char *who) { - DBG(DBG_CONTROLMORE, - DBG_log("ocsp fetch request list unlocked by '%s'", who) - ) - pthread_mutex_unlock(&ocsp_fetch_list_mutex); + DBG(DBG_CONTROLMORE, + DBG_log("ocsp fetch request list unlocked by '%s'", who) + ) + pthread_mutex_unlock(&ocsp_fetch_list_mutex); } /* @@ -253,15 +253,15 @@ unlock_ocsp_fetch_list(const char *who) void wake_fetch_thread(const char *who) { - if (crl_check_interval > 0) - { - DBG(DBG_CONTROLMORE, - DBG_log("fetch thread wake call by '%s'", who) - ) - pthread_mutex_lock(&fetch_wake_mutex); - pthread_cond_signal(&fetch_wake_cond); - pthread_mutex_unlock(&fetch_wake_mutex); - } + if (crl_check_interval > 0) + { + DBG(DBG_CONTROLMORE, + DBG_log("fetch thread wake call by '%s'", who) + ) + pthread_mutex_lock(&fetch_wake_mutex); + pthread_cond_signal(&fetch_wake_cond); + pthread_mutex_unlock(&fetch_wake_mutex); + } } #else /* !THREADS */ #define lock_crl_fetch_list(who) /* do nothing */ @@ -276,11 +276,11 @@ wake_fetch_thread(const char *who) static void free_fetch_request(fetch_req_t *req) { - free(req->issuer.ptr); - free(req->authKeySerialNumber.ptr); - free(req->authKeyID.ptr); - free_generalNames(req->distributionPoints, TRUE); - free(req); + free(req->issuer.ptr); + free(req->authKeySerialNumber.ptr); + free(req->authKeyID.ptr); + free_generalNames(req->distributionPoints, TRUE); + free(req); } /* writes data into a dynamically resizeable chunk_t @@ -289,15 +289,15 @@ free_fetch_request(fetch_req_t *req) size_t write_buffer(void *ptr, size_t size, size_t nmemb, void *data) { - size_t realsize = size * nmemb; - chunk_t *mem = (chunk_t*)data; + size_t realsize = size * nmemb; + chunk_t *mem = (chunk_t*)data; - mem->ptr = (u_char *)realloc(mem->ptr, mem->len + realsize); - if (mem->ptr) { - memcpy(&(mem->ptr[mem->len]), ptr, realsize); - mem->len += realsize; - } - return realsize; + mem->ptr = (u_char *)realloc(mem->ptr, mem->len + realsize); + if (mem->ptr) { + memcpy(&(mem->ptr[mem->len]), ptr, realsize); + mem->len += realsize; + } + return realsize; } #ifdef THREADS @@ -308,44 +308,44 @@ static err_t fetch_curl(char *url, chunk_t *blob) { #ifdef LIBCURL - char errorbuffer[CURL_ERROR_SIZE] = ""; - chunk_t response = chunk_empty; - CURLcode res; + char errorbuffer[CURL_ERROR_SIZE] = ""; + chunk_t response = chunk_empty; + CURLcode res; - /* get it with libcurl */ - CURL *curl = curl_easy_init(); + /* get it with libcurl */ + CURL *curl = curl_easy_init(); - if (curl != NULL) - { - DBG(DBG_CONTROL, - DBG_log("Trying cURL '%s'", url) - ) - - curl_easy_setopt(curl, CURLOPT_URL, url); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_buffer); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response); - curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer); - curl_easy_setopt(curl, CURLOPT_FAILONERROR, TRUE); - curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, FETCH_CMD_TIMEOUT); - - res = curl_easy_perform(curl); - - if (res == CURLE_OK) + if (curl != NULL) { - blob->len = response.len; - blob->ptr = malloc(response.len); - memcpy(blob->ptr, response.ptr, response.len); + DBG(DBG_CONTROL, + DBG_log("Trying cURL '%s'", url) + ) + + curl_easy_setopt(curl, CURLOPT_URL, url); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_buffer); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response); + curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer); + curl_easy_setopt(curl, CURLOPT_FAILONERROR, TRUE); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, FETCH_CMD_TIMEOUT); + + res = curl_easy_perform(curl); + + if (res == CURLE_OK) + { + blob->len = response.len; + blob->ptr = malloc(response.len); + memcpy(blob->ptr, response.ptr, response.len); + } + else + { + plog("fetching uri (%s) with libcurl failed: %s", url, errorbuffer); + } + curl_easy_cleanup(curl); + curl_free(response.ptr); } - else - { - plog("fetching uri (%s) with libcurl failed: %s", url, errorbuffer); - } - curl_easy_cleanup(curl); - curl_free(response.ptr); - } - return strlen(errorbuffer) > 0 ? "libcurl error" : NULL; + return strlen(errorbuffer) > 0 ? "libcurl error" : NULL; #else /* !LIBCURL */ - return "warning: not compiled with libcurl support"; + return "warning: not compiled with libcurl support"; #endif /* !LIBCURL */ } @@ -356,56 +356,56 @@ fetch_curl(char *url, chunk_t *blob) static err_t parse_ldap_result(LDAP * ldap, LDAPMessage *result, chunk_t *blob) { - err_t ugh = NULL; + err_t ugh = NULL; - LDAPMessage * entry = ldap_first_entry(ldap, result); + LDAPMessage * entry = ldap_first_entry(ldap, result); - if (entry != NULL) - { - BerElement *ber = NULL; - char *attr; - - attr = ldap_first_attribute(ldap, entry, &ber); - - if (attr != NULL) + if (entry != NULL) { - struct berval **values = ldap_get_values_len(ldap, entry, attr); + BerElement *ber = NULL; + char *attr; + + attr = ldap_first_attribute(ldap, entry, &ber); - if (values != NULL) - { - if (values[0] != NULL) + if (attr != NULL) { - blob->len = values[0]->bv_len; - blob->ptr = malloc(blob->len); - memcpy(blob->ptr, values[0]->bv_val, blob->len); - if (values[1] != NULL) - { - plog("warning: more than one value was fetched from LDAP URL"); - } + struct berval **values = ldap_get_values_len(ldap, entry, attr); + + if (values != NULL) + { + if (values[0] != NULL) + { + blob->len = values[0]->bv_len; + blob->ptr = malloc(blob->len); + memcpy(blob->ptr, values[0]->bv_val, blob->len); + if (values[1] != NULL) + { + plog("warning: more than one value was fetched from LDAP URL"); + } + } + else + { + ugh = "no values in attribute"; + } + ldap_value_free_len(values); + } + else + { + ugh = ldap_err2string(ldap_result2error(ldap, entry, 0)); + } + ldap_memfree(attr); } else { - ugh = "no values in attribute"; + ugh = ldap_err2string(ldap_result2error(ldap, entry, 0)); } - ldap_value_free_len(values); - } - else - { - ugh = ldap_err2string(ldap_result2error(ldap, entry, 0)); - } - ldap_memfree(attr); + ber_free(ber, 0); } else { - ugh = ldap_err2string(ldap_result2error(ldap, entry, 0)); + ugh = ldap_err2string(ldap_result2error(ldap, result, 0)); } - ber_free(ber, 0); - } - else - { - ugh = ldap_err2string(ldap_result2error(ldap, result, 0)); - } - return ugh; + return ugh; } /* @@ -414,78 +414,78 @@ parse_ldap_result(LDAP * ldap, LDAPMessage *result, chunk_t *blob) static err_t fetch_ldap_url(char *url, chunk_t *blob) { - LDAPURLDesc *lurl; - err_t ugh = NULL; - int rc; + LDAPURLDesc *lurl; + err_t ugh = NULL; + int rc; - DBG(DBG_CONTROL, - DBG_log("Trying LDAP URL '%s'", url) - ) + DBG(DBG_CONTROL, + DBG_log("Trying LDAP URL '%s'", url) + ) - rc = ldap_url_parse(url, &lurl); - - if (rc == LDAP_SUCCESS) - { - LDAP *ldap = ldap_init(lurl->lud_host, lurl->lud_port); - - if (ldap != NULL) + rc = ldap_url_parse(url, &lurl); + + if (rc == LDAP_SUCCESS) { - int ldap_version = LDAP_VERSION3; - struct timeval timeout; + LDAP *ldap = ldap_init(lurl->lud_host, lurl->lud_port); - timeout.tv_sec = FETCH_CMD_TIMEOUT; - timeout.tv_usec = 0; - ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ldap_version); - ldap_set_option(ldap, LDAP_OPT_NETWORK_TIMEOUT, &timeout); - - rc = ldap_simple_bind_s(ldap, NULL, NULL); - - if (rc == LDAP_SUCCESS) - { - LDAPMessage *result; - - timeout.tv_sec = FETCH_CMD_TIMEOUT; - timeout.tv_usec = 0; - - rc = ldap_search_st(ldap, lurl->lud_dn - , lurl->lud_scope - , lurl->lud_filter - , lurl->lud_attrs - , 0, &timeout, &result); - - if (rc == LDAP_SUCCESS) + if (ldap != NULL) { - ugh = parse_ldap_result(ldap, result, blob); - ldap_msgfree(result); + int ldap_version = LDAP_VERSION3; + struct timeval timeout; + + timeout.tv_sec = FETCH_CMD_TIMEOUT; + timeout.tv_usec = 0; + ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ldap_version); + ldap_set_option(ldap, LDAP_OPT_NETWORK_TIMEOUT, &timeout); + + rc = ldap_simple_bind_s(ldap, NULL, NULL); + + if (rc == LDAP_SUCCESS) + { + LDAPMessage *result; + + timeout.tv_sec = FETCH_CMD_TIMEOUT; + timeout.tv_usec = 0; + + rc = ldap_search_st(ldap, lurl->lud_dn + , lurl->lud_scope + , lurl->lud_filter + , lurl->lud_attrs + , 0, &timeout, &result); + + if (rc == LDAP_SUCCESS) + { + ugh = parse_ldap_result(ldap, result, blob); + ldap_msgfree(result); + } + else + { + ugh = ldap_err2string(rc); + } + } + else + { + ugh = ldap_err2string(rc); + } + ldap_unbind_s(ldap); } else { - ugh = ldap_err2string(rc); + ugh = "ldap init"; } - } - else - { - ugh = ldap_err2string(rc); - } - ldap_unbind_s(ldap); + ldap_free_urldesc(lurl); } else { - ugh = "ldap init"; + ugh = ldap_err2string(rc); } - ldap_free_urldesc(lurl); - } - else - { - ugh = ldap_err2string(rc); - } - return ugh; + return ugh; } #else /* !LIBLDAP */ static err_t fetch_ldap_url(char *url, chunk_t *blob) { - return "LDAP URL fetching not activated in pluto source code"; + return "LDAP URL fetching not activated in pluto source code"; } #endif /* !LIBLDAP */ @@ -495,50 +495,50 @@ fetch_ldap_url(char *url, chunk_t *blob) static err_t fetch_asn1_blob(char *url, chunk_t *blob) { - err_t ugh = NULL; + err_t ugh = NULL; - if (strlen(url) >= 4 && strncasecmp(url, "ldap", 4) == 0) - { - ugh = fetch_ldap_url(url, blob); - } - else - { - ugh = fetch_curl(url, blob); - } - if (ugh != NULL) - return ugh; - - if (is_asn1(*blob)) - { - DBG(DBG_PARSING, - DBG_log(" fetched blob coded in DER format") - ) - } - else - { - bool pgp = FALSE; - - ugh = pemtobin(blob, NULL, "", &pgp); - if (ugh == NULL) + if (strlen(url) >= 4 && strncasecmp(url, "ldap", 4) == 0) { - if (is_asn1(*blob)) - { - DBG(DBG_PARSING, - DBG_log(" fetched blob coded in PEM format") - ) - } - else - { - ugh = "blob coded in unknown format"; - free(blob->ptr); - } + ugh = fetch_ldap_url(url, blob); } else { - free(blob->ptr); + ugh = fetch_curl(url, blob); } - } - return ugh; + if (ugh != NULL) + return ugh; + + if (is_asn1(*blob)) + { + DBG(DBG_PARSING, + DBG_log(" fetched blob coded in DER format") + ) + } + else + { + bool pgp = FALSE; + + ugh = pemtobin(blob, NULL, "", &pgp); + if (ugh == NULL) + { + if (is_asn1(*blob)) + { + DBG(DBG_PARSING, + DBG_log(" fetched blob coded in PEM format") + ) + } + else + { + ugh = "blob coded in unknown format"; + free(blob->ptr); + } + } + else + { + free(blob->ptr); + } + } + return ugh; } /* @@ -547,45 +547,45 @@ fetch_asn1_blob(char *url, chunk_t *blob) static char* complete_uri(chunk_t distPoint, const char *ldaphost) { - char *uri; - char *ptr = distPoint.ptr; - size_t len = distPoint.len; + char *uri; + char *ptr = distPoint.ptr; + size_t len = distPoint.len; - char *symbol = memchr(ptr, ':', len); + char *symbol = memchr(ptr, ':', len); - if (symbol != NULL) - { - size_t type_len = symbol - ptr; - - if (type_len >= 4 && strncasecmp(ptr, "ldap", 4) == 0) + if (symbol != NULL) { - ptr = symbol + 1; - len -= (type_len + 1); - - if (len > 2 && *ptr++ == '/' && *ptr++ == '/') - { - len -= 2; - symbol = memchr(ptr, '/', len); + size_t type_len = symbol - ptr; - if (symbol != NULL && symbol - ptr == 0 && ldaphost != NULL) + if (type_len >= 4 && strncasecmp(ptr, "ldap", 4) == 0) { - uri = malloc(distPoint.len + strlen(ldaphost) + 1); + ptr = symbol + 1; + len -= (type_len + 1); - /* insert the ldaphost into the uri */ - sprintf(uri, "%.*s%s%.*s" - , (int)(distPoint.len - len), distPoint.ptr - , ldaphost - , (int)len, symbol); - return uri; + if (len > 2 && *ptr++ == '/' && *ptr++ == '/') + { + len -= 2; + symbol = memchr(ptr, '/', len); + + if (symbol != NULL && symbol - ptr == 0 && ldaphost != NULL) + { + uri = malloc(distPoint.len + strlen(ldaphost) + 1); + + /* insert the ldaphost into the uri */ + sprintf(uri, "%.*s%s%.*s" + , (int)(distPoint.len - len), distPoint.ptr + , ldaphost + , (int)len, symbol); + return uri; + } + } } - } } - } - - /* default action: copy distributionPoint without change */ - uri = malloc(distPoint.len + 1); - sprintf(uri, "%.*s", (int)distPoint.len, distPoint.ptr); - return uri; + + /* default action: copy distributionPoint without change */ + uri = malloc(distPoint.len + 1); + sprintf(uri, "%.*s", (int)distPoint.len, distPoint.ptr); + return uri; } /* @@ -594,158 +594,158 @@ complete_uri(chunk_t distPoint, const char *ldaphost) static void fetch_crls(bool cache_crls) { - fetch_req_t *req; - fetch_req_t **reqp; + fetch_req_t *req; + fetch_req_t **reqp; - lock_crl_fetch_list("fetch_crls"); - req = crl_fetch_reqs; - reqp = &crl_fetch_reqs; + lock_crl_fetch_list("fetch_crls"); + req = crl_fetch_reqs; + reqp = &crl_fetch_reqs; - while (req != NULL) - { - bool valid_crl = FALSE; - chunk_t blob = chunk_empty; - generalName_t *gn = req->distributionPoints; - const char *ldaphost; - ca_info_t *ca; - - lock_ca_info_list("fetch_crls"); - - ca = get_ca_info(req->issuer, req->authKeySerialNumber, req->authKeyID); - ldaphost = (ca == NULL)? NULL : ca->ldaphost; - - while (gn != NULL) + while (req != NULL) { - char *uri = complete_uri(gn->name, ldaphost); + bool valid_crl = FALSE; + chunk_t blob = chunk_empty; + generalName_t *gn = req->distributionPoints; + const char *ldaphost; + ca_info_t *ca; - err_t ugh = fetch_asn1_blob(uri, &blob); - free(uri); + lock_ca_info_list("fetch_crls"); - if (ugh != NULL) - { - plog("fetch failed: %s", ugh); - } - else - { - chunk_t crl_uri = chunk_clone(gn->name); + ca = get_ca_info(req->issuer, req->authKeySerialNumber, req->authKeyID); + ldaphost = (ca == NULL)? NULL : ca->ldaphost; - if (insert_crl(blob, crl_uri, cache_crls)) + while (gn != NULL) { - DBG(DBG_CONTROL, - DBG_log("we have a valid crl") - ) - valid_crl = TRUE; - break; + char *uri = complete_uri(gn->name, ldaphost); + + err_t ugh = fetch_asn1_blob(uri, &blob); + free(uri); + + if (ugh != NULL) + { + plog("fetch failed: %s", ugh); + } + else + { + chunk_t crl_uri = chunk_clone(gn->name); + + if (insert_crl(blob, crl_uri, cache_crls)) + { + DBG(DBG_CONTROL, + DBG_log("we have a valid crl") + ) + valid_crl = TRUE; + break; + } + } + gn = gn->next; } - } - gn = gn->next; - } - unlock_ca_info_list("fetch_crls"); + unlock_ca_info_list("fetch_crls"); - if (valid_crl) - { - /* delete fetch request */ - fetch_req_t *req_free = req; + if (valid_crl) + { + /* delete fetch request */ + fetch_req_t *req_free = req; - req = req->next; - *reqp = req; - free_fetch_request(req_free); + req = req->next; + *reqp = req; + free_fetch_request(req_free); + } + else + { + /* try again next time */ + req->trials++; + reqp = &req->next; + req = req->next; + } } - else - { - /* try again next time */ - req->trials++; - reqp = &req->next; - req = req->next; - } - } - unlock_crl_fetch_list("fetch_crls"); + unlock_crl_fetch_list("fetch_crls"); } static void fetch_ocsp_status(ocsp_location_t* location) { #ifdef LIBCURL - chunk_t request; - chunk_t response = chunk_empty; + chunk_t request; + chunk_t response = chunk_empty; - CURL* curl; - CURLcode res; + CURL* curl; + CURLcode res; - request = build_ocsp_request(location); + request = build_ocsp_request(location); - DBG(DBG_CONTROL, - DBG_log("sending ocsp request to location '%.*s'" - , (int)location->uri.len, location->uri.ptr) - ) - DBG(DBG_RAW, - DBG_dump_chunk("OCSP request", request) - ) + DBG(DBG_CONTROL, + DBG_log("sending ocsp request to location '%.*s'" + , (int)location->uri.len, location->uri.ptr) + ) + DBG(DBG_RAW, + DBG_dump_chunk("OCSP request", request) + ) - /* send via http post using libcurl */ - curl = curl_easy_init(); + /* send via http post using libcurl */ + curl = curl_easy_init(); - if (curl != NULL) - { - char errorbuffer[CURL_ERROR_SIZE]; - struct curl_slist *headers = NULL; - char* uri = malloc(location->uri.len + 1); - - /* we need a null terminated string for curl */ - memcpy(uri, location->uri.ptr, location->uri.len); - *(uri + location->uri.len) = '\0'; - - /* set content type header */ - headers = curl_slist_append(headers, "Content-Type: application/ocsp-request"); - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); - - curl_easy_setopt(curl, CURLOPT_URL, uri); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_buffer); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response); - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (void*)request.ptr); - curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, request.len); - curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer); - curl_easy_setopt(curl, CURLOPT_FAILONERROR, TRUE); - curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, FETCH_CMD_TIMEOUT); - - res = curl_easy_perform(curl); - - if (res == CURLE_OK) + if (curl != NULL) { - DBG(DBG_CONTROL, - DBG_log("received ocsp response") - ) - DBG(DBG_RAW, - DBG_dump_chunk("OCSP response:\n", response) - ) - parse_ocsp(location, response); - } - else - { - plog("failed to fetch ocsp status from '%s': %s", uri, errorbuffer); - } - curl_slist_free_all(headers); - curl_easy_cleanup(curl); - free(uri); - curl_free(response.ptr); - } - free(request.ptr); - chunk_free(&location->nonce); + char errorbuffer[CURL_ERROR_SIZE]; + struct curl_slist *headers = NULL; + char* uri = malloc(location->uri.len + 1); - /* increment the trial counter of the unresolved fetch requests */ - { - ocsp_certinfo_t *certinfo = location->certinfo; - - while (certinfo != NULL) - { - certinfo->trials++; - certinfo = certinfo->next; + /* we need a null terminated string for curl */ + memcpy(uri, location->uri.ptr, location->uri.len); + *(uri + location->uri.len) = '\0'; + + /* set content type header */ + headers = curl_slist_append(headers, "Content-Type: application/ocsp-request"); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + + curl_easy_setopt(curl, CURLOPT_URL, uri); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_buffer); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (void*)request.ptr); + curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, request.len); + curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer); + curl_easy_setopt(curl, CURLOPT_FAILONERROR, TRUE); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, FETCH_CMD_TIMEOUT); + + res = curl_easy_perform(curl); + + if (res == CURLE_OK) + { + DBG(DBG_CONTROL, + DBG_log("received ocsp response") + ) + DBG(DBG_RAW, + DBG_dump_chunk("OCSP response:\n", response) + ) + parse_ocsp(location, response); + } + else + { + plog("failed to fetch ocsp status from '%s': %s", uri, errorbuffer); + } + curl_slist_free_all(headers); + curl_easy_cleanup(curl); + free(uri); + curl_free(response.ptr); } - } - return; + free(request.ptr); + chunk_free(&location->nonce); + + /* increment the trial counter of the unresolved fetch requests */ + { + ocsp_certinfo_t *certinfo = location->certinfo; + + while (certinfo != NULL) + { + certinfo->trials++; + certinfo = certinfo->next; + } + } + return; #else /* !LIBCURL */ - plog("ocsp error: pluto wasn't compiled with libcurl support"); + plog("ocsp error: pluto wasn't compiled with libcurl support"); #endif /* !LIBCURL */ } @@ -755,64 +755,64 @@ fetch_ocsp_status(ocsp_location_t* location) static void fetch_ocsp(void) { - ocsp_location_t *location; + ocsp_location_t *location; - lock_ocsp_fetch_list("fetch_ocsp"); - location = ocsp_fetch_reqs; + lock_ocsp_fetch_list("fetch_ocsp"); + location = ocsp_fetch_reqs; - /* fetch the ocps status for all locations */ - while (location != NULL) - { - if (location->certinfo != NULL) - fetch_ocsp_status(location); - location = location->next; - } + /* fetch the ocps status for all locations */ + while (location != NULL) + { + if (location->certinfo != NULL) + fetch_ocsp_status(location); + location = location->next; + } - unlock_ocsp_fetch_list("fetch_ocsp"); + unlock_ocsp_fetch_list("fetch_ocsp"); } static void* fetch_thread(void *arg) { - struct timespec wait_interval; - - DBG(DBG_CONTROL, - DBG_log("fetch thread started") - ) - - pthread_mutex_lock(&fetch_wake_mutex); - - while(1) - { - int status; - - wait_interval.tv_nsec = 0; - wait_interval.tv_sec = time(NULL) + crl_check_interval; + struct timespec wait_interval; DBG(DBG_CONTROL, - DBG_log("next regular crl check in %ld seconds", crl_check_interval) + DBG_log("fetch thread started") ) - status = pthread_cond_timedwait(&fetch_wake_cond, &fetch_wake_mutex - , &wait_interval); - if (status == ETIMEDOUT) + pthread_mutex_lock(&fetch_wake_mutex); + + while(1) { - DBG(DBG_CONTROL, - DBG_log(" "); - DBG_log("*time to check crls and the ocsp cache") - ) - check_ocsp(); - check_crls(); + int status; + + wait_interval.tv_nsec = 0; + wait_interval.tv_sec = time(NULL) + crl_check_interval; + + DBG(DBG_CONTROL, + DBG_log("next regular crl check in %ld seconds", crl_check_interval) + ) + status = pthread_cond_timedwait(&fetch_wake_cond, &fetch_wake_mutex + , &wait_interval); + + if (status == ETIMEDOUT) + { + DBG(DBG_CONTROL, + DBG_log(" "); + DBG_log("*time to check crls and the ocsp cache") + ) + check_ocsp(); + check_crls(); + } + else + { + DBG(DBG_CONTROL, + DBG_log("fetch thread was woken up") + ) + } + fetch_ocsp(); + fetch_crls(cache_crls); } - else - { - DBG(DBG_CONTROL, - DBG_log("fetch thread was woken up") - ) - } - fetch_ocsp(); - fetch_crls(cache_crls); - } } #endif /* THREADS*/ @@ -823,30 +823,30 @@ void init_fetch(void) { #if defined(LIBCURL) || defined (THREADS) - int status; + int status; #endif #ifdef LIBCURL - /* init curl */ - status = curl_global_init(CURL_GLOBAL_NOTHING); - if (status != CURLE_OK) - { - plog("libcurl could not be initialized, status = %d", status); - } + /* init curl */ + status = curl_global_init(CURL_GLOBAL_NOTHING); + if (status != CURLE_OK) + { + plog("libcurl could not be initialized, status = %d", status); + } #endif /* LIBCURL */ - if (crl_check_interval > 0) - { -#ifdef THREADS - status = pthread_create( &thread, NULL, fetch_thread, NULL); - if (status != 0) + if (crl_check_interval > 0) { - plog("fetching thread could not be started, status = %d", status); - } +#ifdef THREADS + status = pthread_create( &thread, NULL, fetch_thread, NULL); + if (status != 0) + { + plog("fetching thread could not be started, status = %d", status); + } #else /* !THREADS */ - plog("warning: not compiled with pthread support"); + plog("warning: not compiled with pthread support"); #endif /* !THREADS */ - } + } } void @@ -854,21 +854,21 @@ free_crl_fetch(void) { lock_crl_fetch_list("free_crl_fetch"); - while (crl_fetch_reqs != NULL) - { - fetch_req_t *req = crl_fetch_reqs; - crl_fetch_reqs = req->next; - free_fetch_request(req); - } + while (crl_fetch_reqs != NULL) + { + fetch_req_t *req = crl_fetch_reqs; + crl_fetch_reqs = req->next; + free_fetch_request(req); + } - unlock_crl_fetch_list("free_crl_fetch"); + unlock_crl_fetch_list("free_crl_fetch"); #ifdef LIBCURL - if (crl_check_interval > 0) - { - /* cleanup curl */ - curl_global_cleanup(); - } + if (crl_check_interval > 0) + { + /* cleanup curl */ + curl_global_cleanup(); + } #endif /* LIBCURL */ } @@ -878,9 +878,9 @@ free_crl_fetch(void) void free_ocsp_fetch(void) { - lock_ocsp_fetch_list("free_ocsp_fetch"); - free_ocsp_locations(&ocsp_fetch_reqs); - unlock_ocsp_fetch_list("free_ocsp_fetch"); + lock_ocsp_fetch_list("free_ocsp_fetch"); + free_ocsp_locations(&ocsp_fetch_reqs); + unlock_ocsp_fetch_list("free_ocsp_fetch"); } @@ -890,61 +890,61 @@ free_ocsp_fetch(void) void add_distribution_points(const generalName_t *newPoints ,generalName_t **distributionPoints) { - while (newPoints != NULL) - { - /* skip empty distribution point */ - if (newPoints->name.len > 0) - { - bool add = TRUE; - generalName_t *gn = *distributionPoints; + while (newPoints != NULL) + { + /* skip empty distribution point */ + if (newPoints->name.len > 0) + { + bool add = TRUE; + generalName_t *gn = *distributionPoints; - while (gn != NULL) - { - if (gn->kind == newPoints->kind - && gn->name.len == newPoints->name.len - && memeq(gn->name.ptr, newPoints->name.ptr, gn->name.len)) - { - /* skip if the distribution point is already present */ - add = FALSE; - break; - } - gn = gn->next; - } + while (gn != NULL) + { + if (gn->kind == newPoints->kind + && gn->name.len == newPoints->name.len + && memeq(gn->name.ptr, newPoints->name.ptr, gn->name.len)) + { + /* skip if the distribution point is already present */ + add = FALSE; + break; + } + gn = gn->next; + } - if (add) - { - /* clone additional distribution point */ - gn = clone_thing(*newPoints); - gn->name = chunk_clone(newPoints->name); + if (add) + { + /* clone additional distribution point */ + gn = clone_thing(*newPoints); + gn->name = chunk_clone(newPoints->name); - /* insert additional CRL distribution point */ - gn->next = *distributionPoints; - *distributionPoints = gn; - } + /* insert additional CRL distribution point */ + gn->next = *distributionPoints; + *distributionPoints = gn; + } + } + newPoints = newPoints->next; } - newPoints = newPoints->next; - } } fetch_req_t* build_crl_fetch_request(chunk_t issuer, chunk_t authKeySerialNumber , chunk_t authKeyID, const generalName_t *gn) { - fetch_req_t *req = malloc_thing(fetch_req_t); - *req = empty_fetch_req; + fetch_req_t *req = malloc_thing(fetch_req_t); + *req = empty_fetch_req; - /* note current time */ - req->installed = time(NULL); + /* note current time */ + req->installed = time(NULL); - /* clone fields */ - req->issuer = chunk_clone(issuer); - req->authKeySerialNumber = chunk_clone(authKeySerialNumber); - req->authKeyID = chunk_clone(authKeyID); - - /* copy distribution points */ - add_distribution_points(gn, &req->distributionPoints); + /* clone fields */ + req->issuer = chunk_clone(issuer); + req->authKeySerialNumber = chunk_clone(authKeySerialNumber); + req->authKeyID = chunk_clone(authKeyID); - return req; + /* copy distribution points */ + add_distribution_points(gn, &req->distributionPoints); + + return req; } /* @@ -953,40 +953,40 @@ build_crl_fetch_request(chunk_t issuer, chunk_t authKeySerialNumber void add_crl_fetch_request(fetch_req_t *req) { - fetch_req_t *r; + fetch_req_t *r; - lock_crl_fetch_list("add_crl_fetch_request"); - r = crl_fetch_reqs; + lock_crl_fetch_list("add_crl_fetch_request"); + r = crl_fetch_reqs; - while (r != NULL) - { - if ((req->authKeyID.ptr != NULL)? same_keyid(req->authKeyID, r->authKeyID) - : (same_dn(req->issuer, r->issuer) - && same_serial(req->authKeySerialNumber, r->authKeySerialNumber))) + while (r != NULL) { - /* there is already a fetch request */ - DBG(DBG_CONTROL, - DBG_log("crl fetch request already exists") - ) + if ((req->authKeyID.ptr != NULL)? same_keyid(req->authKeyID, r->authKeyID) + : (same_dn(req->issuer, r->issuer) + && same_serial(req->authKeySerialNumber, r->authKeySerialNumber))) + { + /* there is already a fetch request */ + DBG(DBG_CONTROL, + DBG_log("crl fetch request already exists") + ) - /* there might be new distribution points */ - add_distribution_points(req->distributionPoints, &r->distributionPoints); + /* there might be new distribution points */ + add_distribution_points(req->distributionPoints, &r->distributionPoints); - unlock_crl_fetch_list("add_crl_fetch_request"); - free_fetch_request(req); - return; + unlock_crl_fetch_list("add_crl_fetch_request"); + free_fetch_request(req); + return; + } + r = r->next; } - r = r->next; - } - /* insert new fetch request at the head of the queue */ - req->next = crl_fetch_reqs; - crl_fetch_reqs = req; + /* insert new fetch request at the head of the queue */ + req->next = crl_fetch_reqs; + crl_fetch_reqs = req; - DBG(DBG_CONTROL, - DBG_log("crl fetch request added") - ) - unlock_crl_fetch_list("add_crl_fetch_request"); + DBG(DBG_CONTROL, + DBG_log("crl fetch request added") + ) + unlock_crl_fetch_list("add_crl_fetch_request"); } /* @@ -995,13 +995,13 @@ add_crl_fetch_request(fetch_req_t *req) void add_ocsp_fetch_request(ocsp_location_t *location, chunk_t serialNumber) { - ocsp_certinfo_t certinfo; + ocsp_certinfo_t certinfo; - certinfo.serialNumber = serialNumber; + certinfo.serialNumber = serialNumber; - lock_ocsp_fetch_list("add_ocsp_fetch_request"); - add_certinfo(location, &certinfo, &ocsp_fetch_reqs, TRUE); - unlock_ocsp_fetch_list("add_ocsp_fetch_request"); + lock_ocsp_fetch_list("add_ocsp_fetch_request"); + add_certinfo(location, &certinfo, &ocsp_fetch_reqs, TRUE); + unlock_ocsp_fetch_list("add_ocsp_fetch_request"); } /* @@ -1010,15 +1010,15 @@ add_ocsp_fetch_request(ocsp_location_t *location, chunk_t serialNumber) void list_distribution_points(const generalName_t *gn) { - bool first_gn = TRUE; + bool first_gn = TRUE; - while (gn != NULL) - { - whack_log(RC_COMMENT, " %s '%.*s'", (first_gn)? "distPts: " - :" ", (int)gn->name.len, gn->name.ptr); - first_gn = FALSE; - gn = gn->next; - } + while (gn != NULL) + { + whack_log(RC_COMMENT, " %s '%.*s'", (first_gn)? "distPts: " + :" ", (int)gn->name.len, gn->name.ptr); + first_gn = FALSE; + gn = gn->next; + } } /* @@ -1027,49 +1027,49 @@ list_distribution_points(const generalName_t *gn) void list_crl_fetch_requests(bool utc) { - fetch_req_t *req; + fetch_req_t *req; - lock_crl_fetch_list("list_crl_fetch_requests"); - req = crl_fetch_reqs; + lock_crl_fetch_list("list_crl_fetch_requests"); + req = crl_fetch_reqs; - if (req != NULL) - { - whack_log(RC_COMMENT, " "); - whack_log(RC_COMMENT, "List of CRL fetch requests:"); - whack_log(RC_COMMENT, " "); - } - - while (req != NULL) - { - u_char buf[BUF_LEN]; - - whack_log(RC_COMMENT, "%T, trials: %d" - , &req->installed, utc, req->trials); - dntoa(buf, BUF_LEN, req->issuer); - whack_log(RC_COMMENT, " issuer: '%s'", buf); - if (req->authKeyID.ptr != NULL) + if (req != NULL) { - datatot(req->authKeyID.ptr, req->authKeyID.len, ':' - , buf, BUF_LEN); - whack_log(RC_COMMENT, " authkey: %s", buf); + whack_log(RC_COMMENT, " "); + whack_log(RC_COMMENT, "List of CRL fetch requests:"); + whack_log(RC_COMMENT, " "); } - if (req->authKeySerialNumber.ptr != NULL) + + while (req != NULL) { - datatot(req->authKeySerialNumber.ptr, req->authKeySerialNumber.len, ':' - , buf, BUF_LEN); - whack_log(RC_COMMENT, " aserial: %s", buf); + u_char buf[BUF_LEN]; + + whack_log(RC_COMMENT, "%T, trials: %d" + , &req->installed, utc, req->trials); + dntoa(buf, BUF_LEN, req->issuer); + whack_log(RC_COMMENT, " issuer: '%s'", buf); + if (req->authKeyID.ptr != NULL) + { + datatot(req->authKeyID.ptr, req->authKeyID.len, ':' + , buf, BUF_LEN); + whack_log(RC_COMMENT, " authkey: %s", buf); + } + if (req->authKeySerialNumber.ptr != NULL) + { + datatot(req->authKeySerialNumber.ptr, req->authKeySerialNumber.len, ':' + , buf, BUF_LEN); + whack_log(RC_COMMENT, " aserial: %s", buf); + } + list_distribution_points(req->distributionPoints); + req = req->next; } - list_distribution_points(req->distributionPoints); - req = req->next; - } - unlock_crl_fetch_list("list_crl_fetch_requests"); + unlock_crl_fetch_list("list_crl_fetch_requests"); } void list_ocsp_fetch_requests(bool utc) { - lock_ocsp_fetch_list("list_ocsp_fetch_requests"); - list_ocsp_locations(ocsp_fetch_reqs, TRUE, utc, FALSE); - unlock_ocsp_fetch_list("list_ocsp_fetch_requests"); + lock_ocsp_fetch_list("list_ocsp_fetch_requests"); + list_ocsp_locations(ocsp_fetch_reqs, TRUE, utc, FALSE); + unlock_ocsp_fetch_list("list_ocsp_fetch_requests"); } diff --git a/src/pluto/fetch.h b/src/pluto/fetch.h index 64908deda..356288a1e 100644 --- a/src/pluto/fetch.h +++ b/src/pluto/fetch.h @@ -17,25 +17,25 @@ #include "x509.h" -#define FETCH_CMD_TIMEOUT 10 /* seconds */ +#define FETCH_CMD_TIMEOUT 10 /* seconds */ -struct ocsp_location; /* forward declaration of ocsp_location defined in ocsp.h */ +struct ocsp_location; /* forward declaration of ocsp_location defined in ocsp.h */ typedef enum { - FETCH_GET = 1, - FETCH_POST = 2 + FETCH_GET = 1, + FETCH_POST = 2 } fetch_request_t; typedef struct fetch_req fetch_req_t; struct fetch_req { - fetch_req_t *next; - time_t installed; - int trials; - chunk_t issuer; - chunk_t authKeyID; - chunk_t authKeySerialNumber; - generalName_t *distributionPoints; + fetch_req_t *next; + time_t installed; + int trials; + chunk_t issuer; + chunk_t authKeyID; + chunk_t authKeySerialNumber; + generalName_t *distributionPoints; }; #ifdef THREADS @@ -67,9 +67,9 @@ extern void init_fetch(void); extern void free_crl_fetch(void); extern void free_ocsp_fetch(void); extern void add_distribution_points(const generalName_t *newPoints - , generalName_t **distributionPoints); + , generalName_t **distributionPoints); extern fetch_req_t* build_crl_fetch_request(chunk_t issuer, chunk_t authKeySerialNumber - , chunk_t authKeyID, const generalName_t *gn); + , chunk_t authKeyID, const generalName_t *gn); extern void add_crl_fetch_request(fetch_req_t *req); extern void add_ocsp_fetch_request(struct ocsp_location *location, chunk_t serialNumber); extern void list_distribution_points(const generalName_t *gn); diff --git a/src/pluto/foodgroups.c b/src/pluto/foodgroups.c index c779ec31b..ec824629c 100644 --- a/src/pluto/foodgroups.c +++ b/src/pluto/foodgroups.c @@ -49,8 +49,8 @@ static size_t fg_path_space = 0; */ struct fg_groups { - struct fg_groups *next; - struct connection *connection; + struct fg_groups *next; + struct connection *connection; }; static struct fg_groups *groups = NULL; @@ -66,10 +66,10 @@ static struct fg_groups *groups = NULL; */ struct fg_targets { - struct fg_targets *next; - struct fg_groups *group; - ip_subnet subnet; - char *name; /* name of instance of group conn */ + struct fg_targets *next; + struct fg_groups *group; + ip_subnet subnet; + char *name; /* name of instance of group conn */ }; static struct fg_targets *targets = NULL; @@ -83,24 +83,24 @@ struct fg_targets *new_targets; static int ipcmp(ip_address *a, ip_address *b) { - if (addrtypeof(a) != addrtypeof(b)) - { - return addrtypeof(a) < addrtypeof(b)? -1 : 1; - } - else if (sameaddr(a, b)) - { - return 0; - } - else - { - const struct sockaddr *sa = sockaddrof(a) - , *sb = sockaddrof(b); + if (addrtypeof(a) != addrtypeof(b)) + { + return addrtypeof(a) < addrtypeof(b)? -1 : 1; + } + else if (sameaddr(a, b)) + { + return 0; + } + else + { + const struct sockaddr *sa = sockaddrof(a) + , *sb = sockaddrof(b); - passert(addrtypeof(a) == AF_INET); /* not yet implemented IPv6 version :-( */ - return (ntohl(((const struct sockaddr_in *)sa)->sin_addr.s_addr) - < ntohl(((const struct sockaddr_in *)sb)->sin_addr.s_addr)) - ? -1 : 1; - } + passert(addrtypeof(a) == AF_INET); /* not yet implemented IPv6 version :-( */ + return (ntohl(((const struct sockaddr_in *)sa)->sin_addr.s_addr) + < ntohl(((const struct sockaddr_in *)sb)->sin_addr.s_addr)) + ? -1 : 1; + } } /* subnetcmp compares the two ip_subnet values a and b. @@ -110,353 +110,353 @@ ipcmp(ip_address *a, ip_address *b) static int subnetcmp(const ip_subnet *a, const ip_subnet *b) { - ip_address neta, maska, netb, maskb; - int r; + ip_address neta, maska, netb, maskb; + int r; - networkof(a, &neta); - maskof(a, &maska); - networkof(b, &netb); - maskof(b, &maskb); - r = ipcmp(&neta, &netb); - if (r == 0) - r = ipcmp(&maska, &maskb); - return r; + networkof(a, &neta); + maskof(a, &maska); + networkof(b, &netb); + maskof(b, &maskb); + r = ipcmp(&neta, &netb); + if (r == 0) + r = ipcmp(&maska, &maskb); + return r; } static void read_foodgroup(struct fg_groups *g) { - const char *fgn = g->connection->name; - const ip_subnet *lsn = &g->connection->spd.this.client; - size_t plen = strlen(policygroups_dir) + 1 + strlen(fgn) + 1; - struct file_lex_position flp_space; + const char *fgn = g->connection->name; + const ip_subnet *lsn = &g->connection->spd.this.client; + size_t plen = strlen(policygroups_dir) + 1 + strlen(fgn) + 1; + struct file_lex_position flp_space; - if (plen > fg_path_space) - { - free(fg_path); - fg_path_space = plen + 10; - fg_path = malloc(fg_path_space); - } - snprintf(fg_path, fg_path_space, "%s/%s", policygroups_dir, fgn); - if (!lexopen(&flp_space, fg_path, TRUE)) - { - DBG(DBG_CONTROL, DBG_log("no group file \"%s\"", fg_path)); - } - else - { - plog("loading group \"%s\"", fg_path); - for (;;) + if (plen > fg_path_space) { - switch (flp->bdry) - { - case B_none: + free(fg_path); + fg_path_space = plen + 10; + fg_path = malloc(fg_path_space); + } + snprintf(fg_path, fg_path_space, "%s/%s", policygroups_dir, fgn); + if (!lexopen(&flp_space, fg_path, TRUE)) + { + DBG(DBG_CONTROL, DBG_log("no group file \"%s\"", fg_path)); + } + else + { + plog("loading group \"%s\"", fg_path); + for (;;) { - /* !!! this test is not sufficient for distinguishing address families. - * We need a notation to specify that a FQDN is to be resolved to IPv6. - */ - const struct af_info *afi = strchr(tok, ':') == NULL - ? &af_inet4_info: &af_inet6_info; - ip_subnet sn; - err_t ugh; + switch (flp->bdry) + { + case B_none: + { + /* !!! this test is not sufficient for distinguishing address families. + * We need a notation to specify that a FQDN is to be resolved to IPv6. + */ + const struct af_info *afi = strchr(tok, ':') == NULL + ? &af_inet4_info: &af_inet6_info; + ip_subnet sn; + err_t ugh; + + if (strchr(tok, '/') == NULL) + { + /* no /, so treat as /32 or V6 equivalent */ + ip_address t; + + ugh = ttoaddr(tok, 0, afi->af, &t); + if (ugh == NULL) + ugh = addrtosubnet(&t, &sn); + } + else + { + ugh = ttosubnet(tok, 0, afi->af, &sn); + } - if (strchr(tok, '/') == NULL) - { - /* no /, so treat as /32 or V6 equivalent */ - ip_address t; + if (ugh != NULL) + { + loglog(RC_LOG_SERIOUS, "\"%s\" line %d: %s \"%s\"" + , flp->filename, flp->lino, ugh, tok); + } + else if (afi->af != AF_INET) + { + loglog(RC_LOG_SERIOUS + , "\"%s\" line %d: unsupported Address Family \"%s\"" + , flp->filename, flp->lino, tok); + } + else + { + /* Find where new entry ought to go in new_targets. */ + struct fg_targets **pp; + int r; - ugh = ttoaddr(tok, 0, afi->af, &t); - if (ugh == NULL) - ugh = addrtosubnet(&t, &sn); - } - else - { - ugh = ttosubnet(tok, 0, afi->af, &sn); - } + for (pp = &new_targets; ; pp = &(*pp)->next) + { + if (*pp == NULL) + { + r = -1; /* end of list is infinite */ + break; + } + r = subnetcmp(lsn, &(*pp)->group->connection->spd.this.client); + if (r == 0) + r = subnetcmp(&sn, &(*pp)->subnet); + if (r <= 0) + break; + } - if (ugh != NULL) - { - loglog(RC_LOG_SERIOUS, "\"%s\" line %d: %s \"%s\"" - , flp->filename, flp->lino, ugh, tok); - } - else if (afi->af != AF_INET) - { - loglog(RC_LOG_SERIOUS - , "\"%s\" line %d: unsupported Address Family \"%s\"" - , flp->filename, flp->lino, tok); - } - else - { - /* Find where new entry ought to go in new_targets. */ - struct fg_targets **pp; - int r; + if (r == 0) + { + char source[SUBNETTOT_BUF]; - for (pp = &new_targets; ; pp = &(*pp)->next) - { - if (*pp == NULL) - { - r = -1; /* end of list is infinite */ - break; - } - r = subnetcmp(lsn, &(*pp)->group->connection->spd.this.client); - if (r == 0) - r = subnetcmp(&sn, &(*pp)->subnet); - if (r <= 0) - break; - } + subnettot(lsn, 0, source, sizeof(source)); + loglog(RC_LOG_SERIOUS + , "\"%s\" line %d: subnet \"%s\", source %s, already \"%s\"" + , flp->filename + , flp->lino + , tok + , source + , (*pp)->group->connection->name); + } + else + { + struct fg_targets *f = malloc_thing(struct fg_targets); - if (r == 0) - { - char source[SUBNETTOT_BUF]; + f->next = *pp; + f->group = g; + f->subnet = sn; + f->name = NULL; + *pp = f; + } + } + } + (void)shift(); /* next */ + continue; - subnettot(lsn, 0, source, sizeof(source)); - loglog(RC_LOG_SERIOUS - , "\"%s\" line %d: subnet \"%s\", source %s, already \"%s\"" - , flp->filename - , flp->lino - , tok - , source - , (*pp)->group->connection->name); - } - else - { - struct fg_targets *f = malloc_thing(struct fg_targets); + case B_record: + flp->bdry = B_none; /* eat the Record Boundary */ + (void)shift(); /* get real first token */ + continue; - f->next = *pp; - f->group = g; - f->subnet = sn; - f->name = NULL; - *pp = f; + case B_file: + break; /* done */ } - } + break; /* if we reach here, out of loop */ } - (void)shift(); /* next */ - continue; - - case B_record: - flp->bdry = B_none; /* eat the Record Boundary */ - (void)shift(); /* get real first token */ - continue; - - case B_file: - break; /* done */ - } - break; /* if we reach here, out of loop */ + lexclose(); } - lexclose(); - } } static void free_targets(void) { - while (targets != NULL) - { - struct fg_targets *t = targets; + while (targets != NULL) + { + struct fg_targets *t = targets; - targets = t->next; - free(t->name); - free(t); - } + targets = t->next; + free(t->name); + free(t); + } } void load_groups(void) { - passert(new_targets == NULL); + passert(new_targets == NULL); - /* for each group, add config file targets into new_targets */ - { - struct fg_groups *g; - - for (g = groups; g != NULL; g = g->next) - if (oriented(*g->connection)) - read_foodgroup(g); - } - - /* dump new_targets */ - DBG(DBG_CONTROL, + /* for each group, add config file targets into new_targets */ { - struct fg_targets *t; + struct fg_groups *g; - for (t = new_targets; t != NULL; t = t->next) - { - char asource[SUBNETTOT_BUF]; - char atarget[SUBNETTOT_BUF]; - - subnettot(&t->group->connection->spd.this.client - , 0, asource, sizeof(asource)); - subnettot(&t->subnet, 0, atarget, sizeof(atarget)); - DBG_log("%s->%s %s" - , asource, atarget - , t->group->connection->name); - } - }); - - /* determine and deal with differences between targets and new_targets. - * structured like a merge. - */ - { - struct fg_targets *op = targets - , *np = new_targets; - - while (op != NULL && np != NULL) - { - int r = subnetcmp(&op->group->connection->spd.this.client - , &np->group->connection->spd.this.client); - - if (r == 0) - r = subnetcmp(&op->subnet, &np->subnet); - - if (r == 0 && op->group == np->group) - { - /* unchanged -- steal name & skip over */ - np->name = op->name; - op->name = NULL; - op = op->next; - np = np->next; - } - else - { - /* note: following cases overlap! */ - if (r <= 0) - { - remove_group_instance(op->group->connection, op->name); - op = op->next; - } - if (r >= 0) - { - np->name = add_group_instance(np->group->connection, &np->subnet); - np = np->next; - } - } + for (g = groups; g != NULL; g = g->next) + if (oriented(*g->connection)) + read_foodgroup(g); } - for (; op != NULL; op = op->next) - remove_group_instance(op->group->connection, op->name); - for (; np != NULL; np = np->next) - np->name = add_group_instance(np->group->connection, &np->subnet); - /* update: new_targets replaces targets */ - free_targets(); - targets = new_targets; - new_targets = NULL; - } + /* dump new_targets */ + DBG(DBG_CONTROL, + { + struct fg_targets *t; + + for (t = new_targets; t != NULL; t = t->next) + { + char asource[SUBNETTOT_BUF]; + char atarget[SUBNETTOT_BUF]; + + subnettot(&t->group->connection->spd.this.client + , 0, asource, sizeof(asource)); + subnettot(&t->subnet, 0, atarget, sizeof(atarget)); + DBG_log("%s->%s %s" + , asource, atarget + , t->group->connection->name); + } + }); + + /* determine and deal with differences between targets and new_targets. + * structured like a merge. + */ + { + struct fg_targets *op = targets + , *np = new_targets; + + while (op != NULL && np != NULL) + { + int r = subnetcmp(&op->group->connection->spd.this.client + , &np->group->connection->spd.this.client); + + if (r == 0) + r = subnetcmp(&op->subnet, &np->subnet); + + if (r == 0 && op->group == np->group) + { + /* unchanged -- steal name & skip over */ + np->name = op->name; + op->name = NULL; + op = op->next; + np = np->next; + } + else + { + /* note: following cases overlap! */ + if (r <= 0) + { + remove_group_instance(op->group->connection, op->name); + op = op->next; + } + if (r >= 0) + { + np->name = add_group_instance(np->group->connection, &np->subnet); + np = np->next; + } + } + } + for (; op != NULL; op = op->next) + remove_group_instance(op->group->connection, op->name); + for (; np != NULL; np = np->next) + np->name = add_group_instance(np->group->connection, &np->subnet); + + /* update: new_targets replaces targets */ + free_targets(); + targets = new_targets; + new_targets = NULL; + } } void add_group(struct connection *c) { - struct fg_groups *g = malloc_thing(struct fg_groups); + struct fg_groups *g = malloc_thing(struct fg_groups); - g->next = groups; - groups = g; + g->next = groups; + groups = g; - g->connection = c; + g->connection = c; } static struct fg_groups * find_group(const struct connection *c) { - struct fg_groups *g; + struct fg_groups *g; - for (g = groups; g != NULL && g->connection != c; g = g->next) - ; - return g; + for (g = groups; g != NULL && g->connection != c; g = g->next) + ; + return g; } void route_group(struct connection *c) { - /* it makes no sense to route a connection that is ISAKMP-only */ - if (!NEVER_NEGOTIATE(c->policy) && !HAS_IPSEC_POLICY(c->policy)) - { - loglog(RC_ROUTE, "cannot route an ISAKMP-only group connection"); - } - else - { - struct fg_groups *g = find_group(c); - struct fg_targets *t; - - passert(g != NULL); - g->connection->policy |= POLICY_GROUTED; - for (t = targets; t != NULL; t = t->next) + /* it makes no sense to route a connection that is ISAKMP-only */ + if (!NEVER_NEGOTIATE(c->policy) && !HAS_IPSEC_POLICY(c->policy)) { - if (t->group == g) - { - struct connection *ci = con_by_name(t->name, FALSE); + loglog(RC_ROUTE, "cannot route an ISAKMP-only group connection"); + } + else + { + struct fg_groups *g = find_group(c); + struct fg_targets *t; - if (ci != NULL) + passert(g != NULL); + g->connection->policy |= POLICY_GROUTED; + for (t = targets; t != NULL; t = t->next) { - set_cur_connection(ci); - if (!trap_connection(ci)) - whack_log(RC_ROUTE, "could not route"); - set_cur_connection(c); + if (t->group == g) + { + struct connection *ci = con_by_name(t->name, FALSE); + + if (ci != NULL) + { + set_cur_connection(ci); + if (!trap_connection(ci)) + whack_log(RC_ROUTE, "could not route"); + set_cur_connection(c); + } + } } - } } - } } void unroute_group(struct connection *c) { - struct fg_groups *g = find_group(c); - struct fg_targets *t; + struct fg_groups *g = find_group(c); + struct fg_targets *t; - passert(g != NULL); - g->connection->policy &= ~POLICY_GROUTED; - for (t = targets; t != NULL; t = t->next) - { - if (t->group == g) + passert(g != NULL); + g->connection->policy &= ~POLICY_GROUTED; + for (t = targets; t != NULL; t = t->next) { - struct connection *ci = con_by_name(t->name, FALSE); + if (t->group == g) + { + struct connection *ci = con_by_name(t->name, FALSE); - if (ci != NULL) - { - set_cur_connection(ci); - unroute_connection(ci); - set_cur_connection(c); - } + if (ci != NULL) + { + set_cur_connection(ci); + unroute_connection(ci); + set_cur_connection(c); + } + } } - } } void delete_group(const struct connection *c) { - struct fg_groups *g; + struct fg_groups *g; - /* find and remove from groups */ - { - struct fg_groups **pp; - - for (pp = &groups; (g = *pp)->connection != c; pp = &(*pp)->next) - ; - - *pp = g->next; - } - - /* find and remove from targets */ - { - struct fg_targets **pp; - - for (pp = &targets; *pp != NULL; ) + /* find and remove from groups */ { - struct fg_targets *t = *pp; + struct fg_groups **pp; - if (t->group == g) - { - *pp = t->next; - remove_group_instance(t->group->connection, t->name); - free(t); - /* pp is ready for next iteration */ - } - else - { - pp = &t->next; - } + for (pp = &groups; (g = *pp)->connection != c; pp = &(*pp)->next) + ; + + *pp = g->next; } - } - free(g); + /* find and remove from targets */ + { + struct fg_targets **pp; + + for (pp = &targets; *pp != NULL; ) + { + struct fg_targets *t = *pp; + + if (t->group == g) + { + *pp = t->next; + remove_group_instance(t->group->connection, t->name); + free(t); + /* pp is ready for next iteration */ + } + else + { + pp = &t->next; + } + } + } + + free(g); } diff --git a/src/pluto/foodgroups.h b/src/pluto/foodgroups.h index 9093c0662..cc83a8cb9 100644 --- a/src/pluto/foodgroups.h +++ b/src/pluto/foodgroups.h @@ -14,7 +14,7 @@ * RCSID $Id$ */ -struct connection; /* forward declaration */ +struct connection; /* forward declaration */ extern void add_group(struct connection *c); extern void route_group(struct connection *c); extern void unroute_group(struct connection *c); diff --git a/src/pluto/gcryptfix.c b/src/pluto/gcryptfix.c index db360cbe5..9adc44bed 100644 --- a/src/pluto/gcryptfix.c +++ b/src/pluto/gcryptfix.c @@ -22,134 +22,134 @@ #include "defs.h" #include "log.h" #include "rnd.h" -#include "gcryptfix.h" /* includes "defs.h" "rnd.h" */ +#include "gcryptfix.h" /* includes "defs.h" "rnd.h" */ MPI mpi_alloc( unsigned nlimbs UNUSED ) { - MPI n = malloc(sizeof *n); + MPI n = malloc(sizeof *n); - mpz_init(n); - return n; + mpz_init(n); + return n; } MPI mpi_alloc_secure( unsigned nlimbs ) { - return mpi_alloc(nlimbs); + return mpi_alloc(nlimbs); } MPI mpi_alloc_set_ui( unsigned long u) { - MPI n = malloc(sizeof *n); + MPI n = malloc(sizeof *n); - mpz_init_set_ui(n, u); - return n; + mpz_init_set_ui(n, u); + return n; } MPI mpi_copy( MPI a ) { - MPI n = malloc(sizeof *n); + MPI n = malloc(sizeof *n); - mpz_init_set(n, a); - return n; + mpz_init_set(n, a); + return n; } void mpi_free( MPI a ) { - mpz_clear(a); - free(a); + mpz_clear(a); + free(a); } int mpi_divisible_ui(MPI dividend, ulong divisor ) { - ulong rem; - mpz_t remtoo; + ulong rem; + mpz_t remtoo; - mpz_init(remtoo); - rem = mpz_mod_ui(remtoo, dividend, divisor); - mpz_clear(remtoo); - return rem == 0; + mpz_init(remtoo); + rem = mpz_mod_ui(remtoo, dividend, divisor); + mpz_clear(remtoo); + return rem == 0; } unsigned mpi_trailing_zeros( MPI a ) { - return mpz_scan1(a, 0); + return mpz_scan1(a, 0); } unsigned mpi_get_nbits( MPI a ) { - return mpz_sizeinbase(a, 2); + return mpz_sizeinbase(a, 2); } int mpi_test_bit( MPI a, unsigned n ) { - /* inspired by gmp/mpz/clrbit.c */ - mp_size_t li = n / mp_bits_per_limb; + /* inspired by gmp/mpz/clrbit.c */ + mp_size_t li = n / mp_bits_per_limb; - if (li >= a->_mp_size) - return 0; - return (a->_mp_d[li] & ((mp_limb_t) 1 << (n % mp_bits_per_limb))) != 0; + if (li >= a->_mp_size) + return 0; + return (a->_mp_d[li] & ((mp_limb_t) 1 << (n % mp_bits_per_limb))) != 0; } void mpi_set_bit( MPI a, unsigned n ) { - mpz_setbit(a, n); + mpz_setbit(a, n); } void mpi_clear_bit( MPI a, unsigned n ) { - mpz_clrbit(a, n); + mpz_clrbit(a, n); } void mpi_clear_highbit( MPI a, unsigned n ) { - /* This seems whacky, but what do I know. */ - mpz_fdiv_r_2exp(a, a, n); + /* This seems whacky, but what do I know. */ + mpz_fdiv_r_2exp(a, a, n); } void mpi_set_highbit( MPI a, unsigned n ) { - /* This seems whacky, but what do I know. */ - mpz_fdiv_r_2exp(a, a, n+1); - mpz_setbit(a, n); + /* This seems whacky, but what do I know. */ + mpz_fdiv_r_2exp(a, a, n+1); + mpz_setbit(a, n); } void mpi_set_buffer( MPI a, const u_char *buffer, unsigned nbytes, int sign ) { - /* this is a lot like n_to_mpz */ - size_t i; + /* this is a lot like n_to_mpz */ + size_t i; - passert(sign == 0); /* we won't hit any negative numbers */ - mpz_init_set_ui(a, 0); + passert(sign == 0); /* we won't hit any negative numbers */ + mpz_init_set_ui(a, 0); - for (i = 0; i != nbytes; i++) - { - mpz_mul_ui(a, a, 1 << BITS_PER_BYTE); - mpz_add_ui(a, a, buffer[i]); - } + for (i = 0; i != nbytes; i++) + { + mpz_mul_ui(a, a, 1 << BITS_PER_BYTE); + mpz_add_ui(a, a, buffer[i]); + } } u_char * get_random_bits(size_t nbits, int level UNUSED, int secure UNUSED) { - size_t nbytes = (nbits+7)/8; - u_char *b = malloc(nbytes); + size_t nbytes = (nbits+7)/8; + u_char *b = malloc(nbytes); - get_rnd_bytes(b, nbytes); - return b; + get_rnd_bytes(b, nbytes); + return b; } /**************** from gnupg-1.0.0/mpi/mpi-mpow.c * RES = (BASE[0] ^ EXP[0]) * (BASE[1] ^ EXP[1]) * ... * mod M @@ -159,125 +159,125 @@ get_random_bits(size_t nbits, int level UNUSED, int secure UNUSED) static int build_index( MPI *exparray, int k, int i, int t ) { - int j, bitno; - int index = 0; + int j, bitno; + int index = 0; - bitno = t-i; - for(j=k-1; j >= 0; j-- ) { - index <<= 1; - if( mpi_test_bit( exparray[j], bitno ) ) - index |= 1; - } - /*log_debug("t=%d i=%d index=%d\n", t, i, index );*/ - return index; + bitno = t-i; + for(j=k-1; j >= 0; j-- ) { + index <<= 1; + if( mpi_test_bit( exparray[j], bitno ) ) + index |= 1; + } + /*log_debug("t=%d i=%d index=%d\n", t, i, index );*/ + return index; } void mpi_mulpowm( MPI res, MPI *basearray, MPI *exparray, MPI m) { - int k; /* number of elements */ - int t; /* bit size of largest exponent */ - int i, j, idx; - MPI *G; /* table with precomputed values of size 2^k */ - MPI tmp; + int k; /* number of elements */ + int t; /* bit size of largest exponent */ + int i, j, idx; + MPI *G; /* table with precomputed values of size 2^k */ + MPI tmp; #ifdef USE_BARRETT - MPI barrett_y, barrett_r1, barrett_r2; - int barrett_k; + MPI barrett_y, barrett_r1, barrett_r2; + int barrett_k; #endif - for(k=0; basearray[k]; k++ ) - ; - passert(k); - for(t=0, i=0; (tmp=exparray[i]); i++ ) { - /*log_mpidump("exp: ", tmp );*/ - j = mpi_get_nbits(tmp); - if( j > t ) - t = j; - } - /*log_mpidump("mod: ", m );*/ - passert(i==k); - passert(t); - passert( k < 10 ); + for(k=0; basearray[k]; k++ ) + ; + passert(k); + for(t=0, i=0; (tmp=exparray[i]); i++ ) { + /*log_mpidump("exp: ", tmp );*/ + j = mpi_get_nbits(tmp); + if( j > t ) + t = j; + } + /*log_mpidump("mod: ", m );*/ + passert(i==k); + passert(t); + passert( k < 10 ); #ifdef PLUTO - m_alloc_ptrs_clear(G, 1<= 0 && idx < (1<= 0 && idx < (1<= 0; i--) - { - buf[i] = mpz_mdivmod_ui(&temp2, NULL, &temp1, 1 << BITS_PER_BYTE); - mpz_set(&temp1, &temp2); - } + for (i = len-1; i >= 0; i--) + { + buf[i] = mpz_mdivmod_ui(&temp2, NULL, &temp1, 1 << BITS_PER_BYTE); + mpz_set(&temp1, &temp2); + } - passert(mpz_sgn(&temp1) == 0); /* we must have done all the bits */ - mpz_clear(&temp1); - mpz_clear(&temp2); + passert(mpz_sgn(&temp1) == 0); /* we must have done all the bits */ + mpz_clear(&temp1); + mpz_clear(&temp2); #ifdef DEBUG - DBG_dump(text, buf, len); + DBG_dump(text, buf, len); #endif /* DEBUG */ } diff --git a/src/pluto/gcryptfix.h b/src/pluto/gcryptfix.h index 2173e35dd..a527e1e89 100644 --- a/src/pluto/gcryptfix.h +++ b/src/pluto/gcryptfix.h @@ -14,7 +14,7 @@ * RCSID $Id$ */ -#define DBG_CIPHER 1 /* some day we'll do this right */ +#define DBG_CIPHER 1 /* some day we'll do this right */ /* Simulate MPI routines with gmp routines. * gmp's MP_INT is a stuct; MPI's MPI is a pointer to an analogous struct. @@ -35,7 +35,7 @@ extern MPI mpi_alloc_set_ui( unsigned long u); extern void mpi_free( MPI a ); extern MPI mpi_copy( MPI a ); extern unsigned mpi_get_nbits( MPI a ); -#define mpi_get_nlimbs(a) ((a)->_mp_alloc) /* dirty, but useless */ +#define mpi_get_nlimbs(a) ((a)->_mp_alloc) /* dirty, but useless */ extern void mpi_set_buffer( MPI a, const u_char *buffer, unsigned nbytes, int sign ); extern unsigned mpi_trailing_zeros( MPI a ); extern int mpi_test_bit( MPI a, unsigned n ); @@ -66,22 +66,22 @@ extern void mpi_mulpowm( MPI res, MPI *basearray, MPI *exparray, MPI mod); #ifdef DEBUG # define log_debug(f...) DBG_log(f) #else -# define log_debug(f...) do ; while (0) /* do nothing, carefully */ +# define log_debug(f...) do ; while (0) /* do nothing, carefully */ #endif -#define log_fatal(f...) exit_log(f) /* overreaction? */ +#define log_fatal(f...) exit_log(f) /* overreaction? */ extern void log_mpidump( const char *text, MPI a ); #define assert(p) passert(p) #define BUG() passert(FALSE) #define m_alloc_ptrs_clear(pp, n) { \ - int c = (n); \ - (pp) = malloc((n) * sizeof(*(pp))); \ - while (c > 0) (pp)[--c] = NULL; \ - } + int c = (n); \ + (pp) = malloc((n) * sizeof(*(pp))); \ + while (c > 0) (pp)[--c] = NULL; \ + } extern u_char *get_random_bits(size_t nbits, int level, int secure); -#define m_alloc(sz) malloc((sz)) /* not initialized */ +#define m_alloc(sz) malloc((sz)) /* not initialized */ #define m_free(n) free(n) /* always freeing something from get_random_bits */ /* declarations from gnupg-1.0.0/include/cipher.h */ @@ -89,7 +89,7 @@ extern u_char *get_random_bits(size_t nbits, int level, int secure); MPI generate_secret_prime( unsigned nbits ); MPI generate_public_prime( unsigned nbits ); MPI generate_elg_prime( int mode, unsigned pbits, unsigned qbits, - MPI g, MPI **factors ); + MPI g, MPI **factors ); #define PUBKEY_ALGO_ELGAMAL_E 16 /* encrypt only ElGamal (but not for v3)*/ #define PUBKEY_ALGO_DSA 17 @@ -97,15 +97,15 @@ MPI generate_elg_prime( int mode, unsigned pbits, unsigned qbits, #define is_ELGAMAL(a) ((a)==PUBKEY_ALGO_ELGAMAL || (a)==PUBKEY_ALGO_ELGAMAL_E) -#define PUBKEY_USAGE_SIG 1 /* key is good for signatures */ -#define PUBKEY_USAGE_ENC 2 /* key is good for encryption */ +#define PUBKEY_USAGE_SIG 1 /* key is good for signatures */ +#define PUBKEY_USAGE_ENC 2 /* key is good for encryption */ /* from gnupg-1.0.0/include/errors.h */ #define G10ERR_PUBKEY_ALGO 4 /* Unknown pubkey algorithm */ #define G10ERR_BAD_SECKEY 7 /* Bad secret key */ #define G10ERR_BAD_SIGN 8 /* Bad signature */ -#define G10ERR_BAD_MPI 30 +#define G10ERR_BAD_MPI 30 /*-- smallprime.c --*/ extern ushort small_prime_numbers[]; diff --git a/src/pluto/id.c b/src/pluto/id.c index dfffefcca..285607571 100644 --- a/src/pluto/id.c +++ b/src/pluto/id.c @@ -22,8 +22,8 @@ #include #include #include -#ifndef HOST_NAME_MAX /* POSIX 1003.1-2001 says defines this */ -# define HOST_NAME_MAX 255 /* upper bound, according to SUSv2 */ +#ifndef HOST_NAME_MAX /* POSIX 1003.1-2001 says defines this */ +# define HOST_NAME_MAX 255 /* upper bound, according to SUSv2 */ #endif #include @@ -38,10 +38,10 @@ #include "packet.h" #include "whack.h" -const struct id empty_id; /* ID_NONE */ +const struct id empty_id; /* ID_NONE */ enum myid_state myid_state = MYID_UNKNOWN; -struct id myids[MYID_SPECIFIED+1]; /* %myid */ +struct id myids[MYID_SPECIFIED+1]; /* %myid */ char *myid_str[MYID_SPECIFIED+1]; /* string form of IDs */ /* initialize id module @@ -50,20 +50,20 @@ char *myid_str[MYID_SPECIFIED+1]; /* string form of IDs */ void init_id(void) { - passert(empty_id.kind == ID_NONE); - myid_state = MYID_UNKNOWN; - { - enum myid_state s; - - for (s = MYID_UNKNOWN; s <= MYID_SPECIFIED; s++) + passert(empty_id.kind == ID_NONE); + myid_state = MYID_UNKNOWN; { - myids[s] = empty_id; - myid_str[s] = NULL; + enum myid_state s; + + for (s = MYID_UNKNOWN; s <= MYID_SPECIFIED; s++) + { + myids[s] = empty_id; + myid_str[s] = NULL; + } } - } - set_myid(MYID_SPECIFIED, getenv("IPSECmyid")); - set_myid(MYID_IP, getenv("defaultrouteaddr")); - set_myFQDN(); + set_myid(MYID_SPECIFIED, getenv("IPSECmyid")); + set_myid(MYID_IP, getenv("defaultrouteaddr")); + set_myFQDN(); } /* @@ -72,95 +72,95 @@ init_id(void) void free_id(void) { - enum myid_state s; + enum myid_state s; - for (s = MYID_UNKNOWN; s <= MYID_SPECIFIED; s++) - { - free_id_content(&myids[s]); - free(myid_str[s]); - } + for (s = MYID_UNKNOWN; s <= MYID_SPECIFIED; s++) + { + free_id_content(&myids[s]); + free(myid_str[s]); + } } static void calc_myid_str(enum myid_state s) { - /* preformat the ID name */ - char buf[BUF_LEN]; + /* preformat the ID name */ + char buf[BUF_LEN]; - idtoa(&myids[s], buf, BUF_LEN); - replace(myid_str[s], clone_str(buf)); + idtoa(&myids[s], buf, BUF_LEN); + replace(myid_str[s], clone_str(buf)); } void set_myid(enum myid_state s, char *idstr) { - if (idstr != NULL) - { - struct id id; - err_t ugh = atoid(idstr, &id, FALSE); - - if (ugh != NULL) + if (idstr != NULL) { - loglog(RC_BADID, "myid malformed: %s \"%s\"", ugh, idstr); - } - else - { - free_id_content(&myids[s]); - unshare_id_content(&id); - myids[s] = id; - if (s == MYID_SPECIFIED) - myid_state = MYID_SPECIFIED; + struct id id; + err_t ugh = atoid(idstr, &id, FALSE); - calc_myid_str(s); + if (ugh != NULL) + { + loglog(RC_BADID, "myid malformed: %s \"%s\"", ugh, idstr); + } + else + { + free_id_content(&myids[s]); + unshare_id_content(&id); + myids[s] = id; + if (s == MYID_SPECIFIED) + myid_state = MYID_SPECIFIED; + + calc_myid_str(s); + } } - } } void set_myFQDN(void) { - char FQDN[HOST_NAME_MAX + 1]; - int r = gethostname(FQDN, sizeof(FQDN)); - - free_id_content(&myids[MYID_HOSTNAME]); - myids[MYID_HOSTNAME] = empty_id; - if (r != 0) - { - log_errno((e, "gethostname() failed in set_myFQDN")); - } - else - { - FQDN[sizeof(FQDN) - 1] = '\0'; /* insurance */ + char FQDN[HOST_NAME_MAX + 1]; + int r = gethostname(FQDN, sizeof(FQDN)); + free_id_content(&myids[MYID_HOSTNAME]); + myids[MYID_HOSTNAME] = empty_id; + if (r != 0) { - size_t len = strlen(FQDN); - - if (len > 0 && FQDN[len-1] == '.') - { - /* nuke trailing . */ - FQDN[len-1]='\0'; - } + log_errno((e, "gethostname() failed in set_myFQDN")); } - - if (!strcaseeq(FQDN, "localhost.localdomain")) + else { - chunk_t myid_name = { FQDN, strlen(FQDN) }; + FQDN[sizeof(FQDN) - 1] = '\0'; /* insurance */ - myids[MYID_HOSTNAME].name = chunk_clone(myid_name); - myids[MYID_HOSTNAME].kind = ID_FQDN; - calc_myid_str(MYID_HOSTNAME); + { + size_t len = strlen(FQDN); + + if (len > 0 && FQDN[len-1] == '.') + { + /* nuke trailing . */ + FQDN[len-1]='\0'; + } + } + + if (!strcaseeq(FQDN, "localhost.localdomain")) + { + chunk_t myid_name = { FQDN, strlen(FQDN) }; + + myids[MYID_HOSTNAME].name = chunk_clone(myid_name); + myids[MYID_HOSTNAME].kind = ID_FQDN; + calc_myid_str(MYID_HOSTNAME); + } } - } } void show_myid_status(void) { - char idstr[BUF_LEN]; + char idstr[BUF_LEN]; - (void)idtoa(&myids[myid_state], idstr, sizeof(idstr)); - whack_log(RC_COMMENT, "%%myid = %s", idstr); + (void)idtoa(&myids[myid_state], idstr, sizeof(idstr)); + whack_log(RC_COMMENT, "%%myid = %s", idstr); } /* Convert textual form of id into a (temporary) struct id. @@ -169,86 +169,86 @@ show_myid_status(void) err_t atoid(char *src, struct id *id, bool myid_ok) { - err_t ugh = NULL; + err_t ugh = NULL; - *id = empty_id; + *id = empty_id; - if (myid_ok && streq("%myid", src)) - { - id->kind = ID_MYID; - } - else if (strchr(src, '=') != NULL) - { - /* we interpret this as an ASCII X.501 ID_DER_ASN1_DN */ - id->kind = ID_DER_ASN1_DN; - id->name.ptr = temporary_cyclic_buffer(); /* assign temporary buffer */ - id->name.len = 0; - /* convert from LDAP style or openssl x509 -subject style to ASN.1 DN - * discard optional @ character in front of DN - */ - ugh = atodn((*src == '@')?src+1:src, &id->name); - } - else if (strchr(src, '@') == NULL) - { - if (streq(src, "%any") || streq(src, "0.0.0.0")) + if (myid_ok && streq("%myid", src)) { - /* any ID will be accepted */ - id->kind = ID_NONE; + id->kind = ID_MYID; } - else + else if (strchr(src, '=') != NULL) { - /* !!! this test is not sufficient for distinguishing address families. - * We need a notation to specify that a FQDN is to be resolved to IPv6. - */ - const struct af_info *afi = strchr(src, ':') == NULL - ? &af_inet4_info: &af_inet6_info; - - id->kind = afi->id_addr; - ugh = ttoaddr(src, 0, afi->af, &id->ip_addr); - } - } - else - { - if (*src == '@') - { - if (*(src+1) == '#') - { - /* if there is a second specifier (#) on the line - * we interprete this as ID_KEY_ID - */ - id->kind = ID_KEY_ID; - id->name.ptr = src; - /* discard @~, convert from hex to bin */ - ugh = ttodata(src+2, 0, 16, id->name.ptr, strlen(src), &id->name.len); - } - else if (*(src+1) == '~') - { - /* if there is a second specifier (~) on the line - * we interprete this as a binary ID_DER_ASN1_DN - */ + /* we interpret this as an ASCII X.501 ID_DER_ASN1_DN */ id->kind = ID_DER_ASN1_DN; - id->name.ptr = src; - /* discard @~, convert from hex to bin */ - ugh = ttodata(src+2, 0, 16, id->name.ptr, strlen(src), &id->name.len); - } - else - { - id->kind = ID_FQDN; - id->name.ptr = src+1; /* discard @ */ - id->name.len = strlen(src)-1; - } + id->name.ptr = temporary_cyclic_buffer(); /* assign temporary buffer */ + id->name.len = 0; + /* convert from LDAP style or openssl x509 -subject style to ASN.1 DN + * discard optional @ character in front of DN + */ + ugh = atodn((*src == '@')?src+1:src, &id->name); + } + else if (strchr(src, '@') == NULL) + { + if (streq(src, "%any") || streq(src, "0.0.0.0")) + { + /* any ID will be accepted */ + id->kind = ID_NONE; + } + else + { + /* !!! this test is not sufficient for distinguishing address families. + * We need a notation to specify that a FQDN is to be resolved to IPv6. + */ + const struct af_info *afi = strchr(src, ':') == NULL + ? &af_inet4_info: &af_inet6_info; + + id->kind = afi->id_addr; + ugh = ttoaddr(src, 0, afi->af, &id->ip_addr); + } } else { - /* We leave in @, as per DOI 4.6.2.4 - * (but DNS wants . instead). - */ - id->kind = ID_USER_FQDN; - id->name.ptr = src; - id->name.len = strlen(src); + if (*src == '@') + { + if (*(src+1) == '#') + { + /* if there is a second specifier (#) on the line + * we interprete this as ID_KEY_ID + */ + id->kind = ID_KEY_ID; + id->name.ptr = src; + /* discard @~, convert from hex to bin */ + ugh = ttodata(src+2, 0, 16, id->name.ptr, strlen(src), &id->name.len); + } + else if (*(src+1) == '~') + { + /* if there is a second specifier (~) on the line + * we interprete this as a binary ID_DER_ASN1_DN + */ + id->kind = ID_DER_ASN1_DN; + id->name.ptr = src; + /* discard @~, convert from hex to bin */ + ugh = ttodata(src+2, 0, 16, id->name.ptr, strlen(src), &id->name.len); + } + else + { + id->kind = ID_FQDN; + id->name.ptr = src+1; /* discard @ */ + id->name.len = strlen(src)-1; + } + } + else + { + /* We leave in @, as per DOI 4.6.2.4 + * (but DNS wants . instead). + */ + id->kind = ID_USER_FQDN; + id->name.ptr = src; + id->name.len = strlen(src); + } } - } - return ugh; + return ugh; } @@ -258,72 +258,72 @@ atoid(char *src, struct id *id, bool myid_ok) int keyidtoa(char *dst, size_t dstlen, chunk_t keyid) { - int n = datatot(keyid.ptr, keyid.len, 'x', dst, dstlen); - return (((size_t)n < dstlen)? n : dstlen) - 1; + int n = datatot(keyid.ptr, keyid.len, 'x', dst, dstlen); + return (((size_t)n < dstlen)? n : dstlen) - 1; } void iptoid(const ip_address *ip, struct id *id) { - *id = empty_id; + *id = empty_id; - switch (addrtypeof(ip)) - { - case AF_INET: - id->kind = ID_IPV4_ADDR; - break; - case AF_INET6: - id->kind = ID_IPV6_ADDR; - break; - default: - bad_case(addrtypeof(ip)); - } - id->ip_addr = *ip; + switch (addrtypeof(ip)) + { + case AF_INET: + id->kind = ID_IPV4_ADDR; + break; + case AF_INET6: + id->kind = ID_IPV6_ADDR; + break; + default: + bad_case(addrtypeof(ip)); + } + id->ip_addr = *ip; } int idtoa(const struct id *id, char *dst, size_t dstlen) { - int n; + int n; - id = resolve_myid(id); - switch (id->kind) - { - case ID_NONE: - n = snprintf(dst, dstlen, "(none)"); - break; - case ID_IPV4_ADDR: - case ID_IPV6_ADDR: - n = (int)addrtot(&id->ip_addr, 0, dst, dstlen) - 1; - break; - case ID_FQDN: - n = snprintf(dst, dstlen, "@%.*s", (int)id->name.len, id->name.ptr); - break; - case ID_USER_FQDN: - n = snprintf(dst, dstlen, "%.*s", (int)id->name.len, id->name.ptr); - break; - case ID_DER_ASN1_DN: - n = dntoa(dst, dstlen, id->name); - break; - case ID_KEY_ID: - n = keyidtoa(dst, dstlen, id->name); - break; - default: - n = snprintf(dst, dstlen, "unknown id kind %d", id->kind); - break; - } + id = resolve_myid(id); + switch (id->kind) + { + case ID_NONE: + n = snprintf(dst, dstlen, "(none)"); + break; + case ID_IPV4_ADDR: + case ID_IPV6_ADDR: + n = (int)addrtot(&id->ip_addr, 0, dst, dstlen) - 1; + break; + case ID_FQDN: + n = snprintf(dst, dstlen, "@%.*s", (int)id->name.len, id->name.ptr); + break; + case ID_USER_FQDN: + n = snprintf(dst, dstlen, "%.*s", (int)id->name.len, id->name.ptr); + break; + case ID_DER_ASN1_DN: + n = dntoa(dst, dstlen, id->name); + break; + case ID_KEY_ID: + n = keyidtoa(dst, dstlen, id->name); + break; + default: + n = snprintf(dst, dstlen, "unknown id kind %d", id->kind); + break; + } - /* "Sanitize" string so that log isn't endangered: - * replace unprintable characters with '?'. - */ - if (n > 0) - { - for ( ; *dst != '\0'; dst++) - if (!isprint(*dst)) - *dst = '?'; - } + /* "Sanitize" string so that log isn't endangered: + * replace unprintable characters with '?'. + */ + if (n > 0) + { + for ( ; *dst != '\0'; dst++) + if (!isprint(*dst)) + *dst = '?'; + } - return n; + return n; } /* Replace the shell metacharacters ', \, ", `, and $ in a character string @@ -332,26 +332,26 @@ idtoa(const struct id *id, char *dst, size_t dstlen) void escape_metachar(const char *src, char *dst, size_t dstlen) { - while (*src != '\0' && dstlen > 4) - { - switch (*src) + while (*src != '\0' && dstlen > 4) { - case '\'': - case '\\': - case '"': - case '`': - case '$': - sprintf(dst,"\\%s%o", (*src < 64)?"0":"", *src); - dst += 4; - dstlen -= 4; - break; - default: - *dst++ = *src; - dstlen--; + switch (*src) + { + case '\'': + case '\\': + case '"': + case '`': + case '$': + sprintf(dst,"\\%s%o", (*src < 64)?"0":"", *src); + dst += 4; + dstlen -= 4; + break; + default: + *dst++ = *src; + dstlen--; + } + src++; } - src++; - } - *dst = '\0'; + *dst = '\0'; } @@ -361,126 +361,126 @@ escape_metachar(const char *src, char *dst, size_t dstlen) void unshare_id_content(struct id *id) { - switch (id->kind) - { - case ID_FQDN: - case ID_USER_FQDN: - case ID_DER_ASN1_DN: - case ID_KEY_ID: - id->name = chunk_clone(id->name); - break; - case ID_MYID: - case ID_NONE: - case ID_IPV4_ADDR: - case ID_IPV6_ADDR: - break; - default: - bad_case(id->kind); - } + switch (id->kind) + { + case ID_FQDN: + case ID_USER_FQDN: + case ID_DER_ASN1_DN: + case ID_KEY_ID: + id->name = chunk_clone(id->name); + break; + case ID_MYID: + case ID_NONE: + case ID_IPV4_ADDR: + case ID_IPV6_ADDR: + break; + default: + bad_case(id->kind); + } } void free_id_content(struct id *id) { - switch (id->kind) - { - case ID_FQDN: - case ID_USER_FQDN: - case ID_DER_ASN1_DN: - case ID_KEY_ID: - free(id->name.ptr); - break; - case ID_MYID: - case ID_NONE: - case ID_IPV4_ADDR: - case ID_IPV6_ADDR: - break; - default: - bad_case(id->kind); - } + switch (id->kind) + { + case ID_FQDN: + case ID_USER_FQDN: + case ID_DER_ASN1_DN: + case ID_KEY_ID: + free(id->name.ptr); + break; + case ID_MYID: + case ID_NONE: + case ID_IPV4_ADDR: + case ID_IPV6_ADDR: + break; + default: + bad_case(id->kind); + } } /* compare two struct id values */ bool same_id(const struct id *a, const struct id *b) { - a = resolve_myid(a); - b = resolve_myid(b); - if (a->kind != b->kind) - return FALSE; - switch (a->kind) - { - case ID_NONE: - return TRUE; /* kind of vacuous */ - - case ID_IPV4_ADDR: - case ID_IPV6_ADDR: - return sameaddr(&a->ip_addr, &b->ip_addr); - - case ID_FQDN: - case ID_USER_FQDN: - /* assumptions: - * - case should be ignored - * - trailing "." should be ignored (even if the only character?) - */ + a = resolve_myid(a); + b = resolve_myid(b); + if (a->kind != b->kind) + return FALSE; + switch (a->kind) { - size_t al = a->name.len - , bl = b->name.len; + case ID_NONE: + return TRUE; /* kind of vacuous */ - while (al > 0 && a->name.ptr[al - 1] == '.') - al--; - while (bl > 0 && b->name.ptr[bl - 1] == '.') - bl--; - return al == bl - && strncasecmp(a->name.ptr, b->name.ptr, al) == 0; + case ID_IPV4_ADDR: + case ID_IPV6_ADDR: + return sameaddr(&a->ip_addr, &b->ip_addr); + + case ID_FQDN: + case ID_USER_FQDN: + /* assumptions: + * - case should be ignored + * - trailing "." should be ignored (even if the only character?) + */ + { + size_t al = a->name.len + , bl = b->name.len; + + while (al > 0 && a->name.ptr[al - 1] == '.') + al--; + while (bl > 0 && b->name.ptr[bl - 1] == '.') + bl--; + return al == bl + && strncasecmp(a->name.ptr, b->name.ptr, al) == 0; + } + + case ID_DER_ASN1_DN: + return same_dn(a->name, b->name); + + case ID_KEY_ID: + return a->name.len == b->name.len + && memeq(a->name.ptr, b->name.ptr, a->name.len); + + default: + bad_case(a->kind); } - - case ID_DER_ASN1_DN: - return same_dn(a->name, b->name); - - case ID_KEY_ID: - return a->name.len == b->name.len - && memeq(a->name.ptr, b->name.ptr, a->name.len); - - default: - bad_case(a->kind); - } - return FALSE; + return FALSE; } /* compare two struct id values, DNs can contain wildcards */ bool match_id(const struct id *a, const struct id *b, int *wildcards) { - if (b->kind == ID_NONE) - { - *wildcards = MAX_WILDCARDS; - return TRUE; - } - if (a->kind != b->kind) - return FALSE; - if (a->kind == ID_DER_ASN1_DN) - return match_dn(a->name, b->name, wildcards); - else - { - *wildcards = 0; - return same_id(a, b); - } + if (b->kind == ID_NONE) + { + *wildcards = MAX_WILDCARDS; + return TRUE; + } + if (a->kind != b->kind) + return FALSE; + if (a->kind == ID_DER_ASN1_DN) + return match_dn(a->name, b->name, wildcards); + else + { + *wildcards = 0; + return same_id(a, b); + } } /* count the numer of wildcards in an id */ int id_count_wildcards(const struct id *id) { - switch (id->kind) - { - case ID_NONE: - return MAX_WILDCARDS; - case ID_DER_ASN1_DN: - return dn_count_wildcards(id->name); - default: - return 0; - } + switch (id->kind) + { + case ID_NONE: + return MAX_WILDCARDS; + case ID_DER_ASN1_DN: + return dn_count_wildcards(id->name); + default: + return 0; + } } /* build an ID payload @@ -491,31 +491,31 @@ id_count_wildcards(const struct id *id) void build_id_payload(struct isakmp_ipsec_id *hd, chunk_t *tl, struct end *end) { - const struct id *id = resolve_myid(&end->id); + const struct id *id = resolve_myid(&end->id); - zero(hd); - hd->isaiid_idtype = id->kind; - switch (id->kind) - { - case ID_NONE: - hd->isaiid_idtype = aftoinfo(addrtypeof(&end->host_addr))->id_addr; - tl->len = addrbytesptr(&end->host_addr - , (const unsigned char **)&tl->ptr); /* sets tl->ptr too */ - break; - case ID_FQDN: - case ID_USER_FQDN: - case ID_DER_ASN1_DN: - case ID_KEY_ID: - *tl = id->name; - break; - case ID_IPV4_ADDR: - case ID_IPV6_ADDR: - tl->len = addrbytesptr(&id->ip_addr - , (const unsigned char **)&tl->ptr); /* sets tl->ptr too */ - break; - default: - bad_case(id->kind); - } + zero(hd); + hd->isaiid_idtype = id->kind; + switch (id->kind) + { + case ID_NONE: + hd->isaiid_idtype = aftoinfo(addrtypeof(&end->host_addr))->id_addr; + tl->len = addrbytesptr(&end->host_addr + , (const unsigned char **)&tl->ptr); /* sets tl->ptr too */ + break; + case ID_FQDN: + case ID_USER_FQDN: + case ID_DER_ASN1_DN: + case ID_KEY_ID: + *tl = id->name; + break; + case ID_IPV4_ADDR: + case ID_IPV6_ADDR: + tl->len = addrbytesptr(&id->ip_addr + , (const unsigned char **)&tl->ptr); /* sets tl->ptr too */ + break; + default: + bad_case(id->kind); + } } /* diff --git a/src/pluto/id.h b/src/pluto/id.h index 634c97ee6..c8b8138e3 100644 --- a/src/pluto/id.h +++ b/src/pluto/id.h @@ -20,25 +20,25 @@ #include "defs.h" struct id { - int kind; /* ID_* value */ - ip_address ip_addr; /* ID_IPV4_ADDR, ID_IPV6_ADDR */ - chunk_t name; /* ID_FQDN, ID_USER_FQDN (with @) */ - /* ID_KEY_ID, ID_DER_ASN_DN */ + int kind; /* ID_* value */ + ip_address ip_addr; /* ID_IPV4_ADDR, ID_IPV6_ADDR */ + chunk_t name; /* ID_FQDN, ID_USER_FQDN (with @) */ + /* ID_KEY_ID, ID_DER_ASN_DN */ }; extern void init_id(void); extern void free_id(void); -extern const struct id empty_id; /* ID_NONE */ +extern const struct id empty_id; /* ID_NONE */ enum myid_state { - MYID_UNKNOWN, /* not yet figured out */ - MYID_HOSTNAME, /* our current hostname */ - MYID_IP, /* our default IP address */ - MYID_SPECIFIED /* as specified by ipsec.conf */ + MYID_UNKNOWN, /* not yet figured out */ + MYID_HOSTNAME, /* our current hostname */ + MYID_IP, /* our default IP address */ + MYID_SPECIFIED /* as specified by ipsec.conf */ }; extern enum myid_state myid_state; -extern struct id myids[MYID_SPECIFIED+1]; /* %myid */ +extern struct id myids[MYID_SPECIFIED+1]; /* %myid */ extern char *myid_str[MYID_SPECIFIED+1]; /* strings */ extern void set_myid(enum myid_state s, char *); extern void show_myid_status(void); @@ -49,19 +49,19 @@ extern err_t atoid(char *src, struct id *id, bool myid_ok); extern int keyidtoa(char *dst, size_t dstlen, chunk_t keyid); extern void iptoid(const ip_address *ip, struct id *id); extern int idtoa(const struct id *id, char *dst, size_t dstlen); -#define IDTOA_BUF 512 +#define IDTOA_BUF 512 extern void escape_metachar(const char *src, char *dst, size_t dstlen); -struct end; /* forward declaration of tag (defined in connections.h) */ +struct end; /* forward declaration of tag (defined in connections.h) */ extern void unshare_id_content(struct id *id); extern void free_id_content(struct id *id); extern bool same_id(const struct id *a, const struct id *b); -#define MAX_WILDCARDS 15 +#define MAX_WILDCARDS 15 extern bool match_id(const struct id *a, const struct id *b, int *wildcards); extern int id_count_wildcards(const struct id *id); #define id_is_ipaddr(id) ((id)->kind == ID_IPV4_ADDR || (id)->kind == ID_IPV6_ADDR) -struct isakmp_ipsec_id; /* forward declaration of tag (defined in packet.h) */ +struct isakmp_ipsec_id; /* forward declaration of tag (defined in packet.h) */ extern void - build_id_payload(struct isakmp_ipsec_id *hd, chunk_t *tl, struct end *end); + build_id_payload(struct isakmp_ipsec_id *hd, chunk_t *tl, struct end *end); #endif /* _ID_H */ diff --git a/src/pluto/ike_alg.c b/src/pluto/ike_alg.c index 5d48dd45c..c40465828 100644 --- a/src/pluto/ike_alg.c +++ b/src/pluto/ike_alg.c @@ -56,13 +56,13 @@ static struct ike_alg *ike_alg_base[IKE_ALG_MAX+1] = {NULL, NULL}; static struct ike_alg * ike_alg_find(u_int algo_type, u_int algo_id, u_int keysize __attribute__((unused))) { - struct ike_alg *e = ike_alg_base[algo_type]; + struct ike_alg *e = ike_alg_base[algo_type]; - while (e != NULL && algo_id > e->algo_id) - { - e = e->algo_next; - } - return (e != NULL && e->algo_id == algo_id) ? e : NULL; + while (e != NULL && algo_id > e->algo_id) + { + e = e->algo_next; + } + return (e != NULL && e->algo_id == algo_id) ? e : NULL; } /* @@ -71,31 +71,31 @@ ike_alg_find(u_int algo_type, u_int algo_id, u_int keysize __attribute__((unused int ike_alg_add(struct ike_alg* a) { - if (a->algo_type > IKE_ALG_MAX) - { - plog("ike_alg: Not added, invalid algorithm type"); - return -EINVAL; - } - - if (ike_alg_find(a->algo_type, a->algo_id, 0) != NULL) - { - plog("ike_alg: Not added, algorithm already exists"); - return -EEXIST; - } - - { - struct ike_alg **ep = &ike_alg_base[a->algo_type]; - struct ike_alg *e = *ep; - - while (e != NULL && a->algo_id > e->algo_id) + if (a->algo_type > IKE_ALG_MAX) { - ep = &e->algo_next; - e = *ep; + plog("ike_alg: Not added, invalid algorithm type"); + return -EINVAL; + } + + if (ike_alg_find(a->algo_type, a->algo_id, 0) != NULL) + { + plog("ike_alg: Not added, algorithm already exists"); + return -EEXIST; + } + + { + struct ike_alg **ep = &ike_alg_base[a->algo_type]; + struct ike_alg *e = *ep; + + while (e != NULL && a->algo_id > e->algo_id) + { + ep = &e->algo_next; + e = *ep; + } + *ep = a; + a->algo_next = e; + return 0; } - *ep = a; - a->algo_next = e; - return 0; - } } /* @@ -103,7 +103,7 @@ ike_alg_add(struct ike_alg* a) */ struct hash_desc *ike_alg_get_hasher(u_int alg) { - return (struct hash_desc *) ike_alg_find(IKE_ALG_HASH, alg, 0); + return (struct hash_desc *) ike_alg_find(IKE_ALG_HASH, alg, 0); } /* @@ -111,7 +111,7 @@ struct hash_desc *ike_alg_get_hasher(u_int alg) */ struct encrypt_desc *ike_alg_get_encrypter(u_int alg) { - return (struct encrypt_desc *) ike_alg_find(IKE_ALG_ENCRYPT, alg, 0); + return (struct encrypt_desc *) ike_alg_find(IKE_ALG_ENCRYPT, alg, 0); } /* @@ -120,7 +120,7 @@ struct encrypt_desc *ike_alg_get_encrypter(u_int alg) bool ike_alg_hash_present(u_int halg) { - return ike_alg_get_hasher(halg) != NULL; + return ike_alg_get_hasher(halg) != NULL; } /* @@ -129,7 +129,7 @@ ike_alg_hash_present(u_int halg) bool ike_alg_enc_present(u_int ealg) { - return ike_alg_get_encrypter(ealg) != NULL; + return ike_alg_get_encrypter(ealg) != NULL; } /* @@ -138,48 +138,48 @@ ike_alg_enc_present(u_int ealg) int ike_alg_register_hash(struct hash_desc *hash_desc) { - const char *alg_name = NULL; - int ret = 0; + const char *alg_name = NULL; + int ret = 0; - if (hash_desc->algo_id > OAKLEY_HASH_MAX) - { - plog ("ike_alg: hash alg=%d > max=%d" - , hash_desc->algo_id, OAKLEY_HASH_MAX); - return_on(ret,-EINVAL); - } + if (hash_desc->algo_id > OAKLEY_HASH_MAX) + { + plog ("ike_alg: hash alg=%d > max=%d" + , hash_desc->algo_id, OAKLEY_HASH_MAX); + return_on(ret,-EINVAL); + } - if (hash_desc->hash_ctx_size > sizeof (union hash_ctx)) - { - plog ("ike_alg: hash alg=%d has ctx_size=%d > hash_ctx=%d" - , hash_desc->algo_id - , (int)hash_desc->hash_ctx_size - , (int)sizeof (union hash_ctx)); - return_on(ret,-EOVERFLOW); - } + if (hash_desc->hash_ctx_size > sizeof (union hash_ctx)) + { + plog ("ike_alg: hash alg=%d has ctx_size=%d > hash_ctx=%d" + , hash_desc->algo_id + , (int)hash_desc->hash_ctx_size + , (int)sizeof (union hash_ctx)); + return_on(ret,-EOVERFLOW); + } - if (!(hash_desc->hash_init && hash_desc->hash_update && hash_desc->hash_final)) - { - plog ("ike_alg: hash alg=%d needs hash_init(), hash_update() and hash_final()" - , hash_desc->algo_id); - return_on(ret,-EINVAL); - } - - alg_name = enum_name(&oakley_hash_names, hash_desc->algo_id); - if (!alg_name) - { - plog ("ike_alg: hash alg=%d not found in constants.c:oakley_hash_names" - , hash_desc->algo_id); - alg_name = ""; - } + if (!(hash_desc->hash_init && hash_desc->hash_update && hash_desc->hash_final)) + { + plog ("ike_alg: hash alg=%d needs hash_init(), hash_update() and hash_final()" + , hash_desc->algo_id); + return_on(ret,-EINVAL); + } + + alg_name = enum_name(&oakley_hash_names, hash_desc->algo_id); + if (!alg_name) + { + plog ("ike_alg: hash alg=%d not found in constants.c:oakley_hash_names" + , hash_desc->algo_id); + alg_name = ""; + } return_out: - if (ret == 0) - ret = ike_alg_add((struct ike_alg *)hash_desc); + if (ret == 0) + ret = ike_alg_add((struct ike_alg *)hash_desc); - plog("ike_alg: Activating %s hash: %s" - ,alg_name, ret == 0 ? "Ok" : "FAILED"); + plog("ike_alg: Activating %s hash: %s" + ,alg_name, ret == 0 ? "Ok" : "FAILED"); - return ret; + return ret; } /* @@ -188,24 +188,24 @@ return_out: int ike_alg_register_enc(struct encrypt_desc *enc_desc) { - int ret = ike_alg_add((struct ike_alg *)enc_desc); + int ret = ike_alg_add((struct ike_alg *)enc_desc); - const char *alg_name = enum_name(&oakley_enc_names, enc_desc->algo_id); + const char *alg_name = enum_name(&oakley_enc_names, enc_desc->algo_id); - char alg_number[20]; - - /* algorithm is not listed in oakley_enc_names */ - if (alg_name == NULL) - { - snprintf(alg_number, sizeof(alg_number), "OAKLEY_ID_%d" - , enc_desc->algo_id); - alg_name = alg_number; - } + char alg_number[20]; + + /* algorithm is not listed in oakley_enc_names */ + if (alg_name == NULL) + { + snprintf(alg_number, sizeof(alg_number), "OAKLEY_ID_%d" + , enc_desc->algo_id); + alg_name = alg_number; + } - plog("ike_alg: Activating %s encryption: %s" - , alg_name, ret == 0 ? "Ok" : "FAILED"); + plog("ike_alg: Activating %s encryption: %s" + , alg_name, ret == 0 ? "Ok" : "FAILED"); - return ret; + return ret; } /* @@ -214,13 +214,13 @@ ike_alg_register_enc(struct encrypt_desc *enc_desc) const struct oakley_group_desc * ike_alg_pfsgroup(struct connection *c, lset_t policy) { - const struct oakley_group_desc * ret = NULL; + const struct oakley_group_desc * ret = NULL; - if ((policy & POLICY_PFS) - && c->alg_info_esp - && c->alg_info_esp->esp_pfsgroup) - ret = lookup_group(c->alg_info_esp->esp_pfsgroup); - return ret; + if ((policy & POLICY_PFS) + && c->alg_info_esp + && c->alg_info_esp->esp_pfsgroup) + ret = lookup_group(c->alg_info_esp->esp_pfsgroup); + return ret; } /* @@ -229,109 +229,109 @@ ike_alg_pfsgroup(struct connection *c, lset_t policy) struct db_context * ike_alg_db_new(struct alg_info_ike *ai , lset_t policy) { - struct db_context *db_ctx = NULL; - struct ike_info *ike_info; - struct encrypt_desc *enc_desc; - u_int ealg, halg, modp, eklen = 0; - int i; + struct db_context *db_ctx = NULL; + struct ike_info *ike_info; + struct encrypt_desc *enc_desc; + u_int ealg, halg, modp, eklen = 0; + int i; - bool is_xauth_server = (policy & POLICY_XAUTH_SERVER) != LEMPTY; + bool is_xauth_server = (policy & POLICY_XAUTH_SERVER) != LEMPTY; - if (!ai) - { - whack_log(RC_LOG_SERIOUS, "no IKE algorithms " - "for this connection " - "(check ike algorithm string)"); - goto fail; - } - policy &= POLICY_ID_AUTH_MASK; - db_ctx = db_prop_new(PROTO_ISAKMP, 8, 8 * 5); - - /* for each group */ - ALG_INFO_IKE_FOREACH(ai, ike_info, i) - { - ealg = ike_info->ike_ealg; - halg = ike_info->ike_halg; - modp = ike_info->ike_modp; - eklen= ike_info->ike_eklen; - - if (!ike_alg_enc_present(ealg)) + if (!ai) { - DBG_log("ike_alg: ike enc ealg=%d not present" - , ealg); - continue; + whack_log(RC_LOG_SERIOUS, "no IKE algorithms " + "for this connection " + "(check ike algorithm string)"); + goto fail; } + policy &= POLICY_ID_AUTH_MASK; + db_ctx = db_prop_new(PROTO_ISAKMP, 8, 8 * 5); - if (!ike_alg_hash_present(halg)) + /* for each group */ + ALG_INFO_IKE_FOREACH(ai, ike_info, i) { - DBG_log("ike_alg: ike hash halg=%d not present" - , halg); - continue; - } + ealg = ike_info->ike_ealg; + halg = ike_info->ike_halg; + modp = ike_info->ike_modp; + eklen= ike_info->ike_eklen; - enc_desc = ike_alg_get_encrypter(ealg); - passert(enc_desc != NULL); + if (!ike_alg_enc_present(ealg)) + { + DBG_log("ike_alg: ike enc ealg=%d not present" + , ealg); + continue; + } - if (eklen - && (eklen < enc_desc->keyminlen || eklen > enc_desc->keymaxlen)) - { - DBG_log("ike_alg: ealg=%d (specified) keylen:%d, not valid min=%d, max=%d" - , ealg - , eklen - , enc_desc->keyminlen - , enc_desc->keymaxlen - ); - continue; - } + if (!ike_alg_hash_present(halg)) + { + DBG_log("ike_alg: ike hash halg=%d not present" + , halg); + continue; + } - if (policy & POLICY_RSASIG) - { - db_trans_add(db_ctx, KEY_IKE); - db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg); - db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg); - if (eklen) - db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen); - db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG); - db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp); - } + enc_desc = ike_alg_get_encrypter(ealg); + passert(enc_desc != NULL); - if (policy & POLICY_PSK) - { - db_trans_add(db_ctx, KEY_IKE); - db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg); - db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg); - if (eklen) - db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen); - db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY); - db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp); - } + if (eklen + && (eklen < enc_desc->keyminlen || eklen > enc_desc->keymaxlen)) + { + DBG_log("ike_alg: ealg=%d (specified) keylen:%d, not valid min=%d, max=%d" + , ealg + , eklen + , enc_desc->keyminlen + , enc_desc->keymaxlen + ); + continue; + } - if (policy & POLICY_XAUTH_RSASIG) - { - db_trans_add(db_ctx, KEY_IKE); - db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg); - db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg); - if (eklen) - db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen); - db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD - , is_xauth_server ? XAUTHRespRSA : XAUTHInitRSA); - db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp); - } + if (policy & POLICY_RSASIG) + { + db_trans_add(db_ctx, KEY_IKE); + db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg); + db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg); + if (eklen) + db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen); + db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG); + db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp); + } - if (policy & POLICY_XAUTH_PSK) - { - db_trans_add(db_ctx, KEY_IKE); - db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg); - db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg); - if (eklen) - db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen); - db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD - , is_xauth_server ? XAUTHRespPreShared : XAUTHInitPreShared); - db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp); + if (policy & POLICY_PSK) + { + db_trans_add(db_ctx, KEY_IKE); + db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg); + db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg); + if (eklen) + db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen); + db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY); + db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp); + } + + if (policy & POLICY_XAUTH_RSASIG) + { + db_trans_add(db_ctx, KEY_IKE); + db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg); + db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg); + if (eklen) + db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen); + db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD + , is_xauth_server ? XAUTHRespRSA : XAUTHInitRSA); + db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp); + } + + if (policy & POLICY_XAUTH_PSK) + { + db_trans_add(db_ctx, KEY_IKE); + db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg); + db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg); + if (eklen) + db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen); + db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD + , is_xauth_server ? XAUTHRespPreShared : XAUTHInitPreShared); + db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp); + } } - } fail: - return db_ctx; + return db_ctx; } /* @@ -340,54 +340,54 @@ fail: void ike_alg_list(void) { - u_int i; - struct ike_alg *a; + u_int i; + struct ike_alg *a; - whack_log(RC_COMMENT, " "); - whack_log(RC_COMMENT, "List of registered IKE Encryption Algorithms:"); - whack_log(RC_COMMENT, " "); + whack_log(RC_COMMENT, " "); + whack_log(RC_COMMENT, "List of registered IKE Encryption Algorithms:"); + whack_log(RC_COMMENT, " "); - for (a = ike_alg_base[IKE_ALG_ENCRYPT]; a != NULL; a = a->algo_next) - { - struct encrypt_desc *desc = (struct encrypt_desc*)a; + for (a = ike_alg_base[IKE_ALG_ENCRYPT]; a != NULL; a = a->algo_next) + { + struct encrypt_desc *desc = (struct encrypt_desc*)a; - whack_log(RC_COMMENT, "#%-5d %s, blocksize: %d, keylen: %d-%d-%d" - , a->algo_id - , enum_name(&oakley_enc_names, a->algo_id) - , (int)desc->enc_blocksize*BITS_PER_BYTE - , desc->keyminlen - , desc->keydeflen - , desc->keymaxlen - ); - } + whack_log(RC_COMMENT, "#%-5d %s, blocksize: %d, keylen: %d-%d-%d" + , a->algo_id + , enum_name(&oakley_enc_names, a->algo_id) + , (int)desc->enc_blocksize*BITS_PER_BYTE + , desc->keyminlen + , desc->keydeflen + , desc->keymaxlen + ); + } - whack_log(RC_COMMENT, " "); - whack_log(RC_COMMENT, "List of registered IKE Hash Algorithms:"); - whack_log(RC_COMMENT, " "); + whack_log(RC_COMMENT, " "); + whack_log(RC_COMMENT, "List of registered IKE Hash Algorithms:"); + whack_log(RC_COMMENT, " "); - for (a = ike_alg_base[IKE_ALG_HASH]; a != NULL; a = a->algo_next) - { - whack_log(RC_COMMENT, "#%-5d %s, hashsize: %d" - , a->algo_id - , enum_name(&oakley_hash_names, a->algo_id) - , (int)((struct hash_desc *)a)->hash_digest_size*BITS_PER_BYTE - ); - } + for (a = ike_alg_base[IKE_ALG_HASH]; a != NULL; a = a->algo_next) + { + whack_log(RC_COMMENT, "#%-5d %s, hashsize: %d" + , a->algo_id + , enum_name(&oakley_hash_names, a->algo_id) + , (int)((struct hash_desc *)a)->hash_digest_size*BITS_PER_BYTE + ); + } - whack_log(RC_COMMENT, " "); - whack_log(RC_COMMENT, "List of registered IKE DH Groups:"); - whack_log(RC_COMMENT, " "); + whack_log(RC_COMMENT, " "); + whack_log(RC_COMMENT, "List of registered IKE DH Groups:"); + whack_log(RC_COMMENT, " "); - for (i = 0; i < countof(oakley_group); i++) - { - const struct oakley_group_desc *gdesc=oakley_group + i; + for (i = 0; i < countof(oakley_group); i++) + { + const struct oakley_group_desc *gdesc=oakley_group + i; - whack_log(RC_COMMENT, "#%-5d %s, groupsize: %d" - , gdesc->group - , enum_name(&oakley_group_names, gdesc->group) - , (int)gdesc->bytes*BITS_PER_BYTE - ); - } + whack_log(RC_COMMENT, "#%-5d %s, groupsize: %d" + , gdesc->group + , enum_name(&oakley_group_names, gdesc->group) + , (int)gdesc->bytes*BITS_PER_BYTE + ); + } } /* Show IKE algorithms for @@ -397,43 +397,43 @@ ike_alg_list(void) void ike_alg_show_connection(struct connection *c, const char *instance) { - char buf[256]; - struct state *st; + char buf[256]; + struct state *st; - if (c->alg_info_ike) - { - alg_info_snprint(buf, sizeof(buf)-1, (struct alg_info *)c->alg_info_ike); - whack_log(RC_COMMENT - , "\"%s\"%s: IKE algorithms wanted: %s" - , c->name - , instance - , buf - ); + if (c->alg_info_ike) + { + alg_info_snprint(buf, sizeof(buf)-1, (struct alg_info *)c->alg_info_ike); + whack_log(RC_COMMENT + , "\"%s\"%s: IKE algorithms wanted: %s" + , c->name + , instance + , buf + ); - alg_info_snprint_ike(buf, sizeof(buf)-1, c->alg_info_ike); - whack_log(RC_COMMENT - , "\"%s\"%s: IKE algorithms found: %s" - , c->name - , instance - , buf - ); - } + alg_info_snprint_ike(buf, sizeof(buf)-1, c->alg_info_ike); + whack_log(RC_COMMENT + , "\"%s\"%s: IKE algorithms found: %s" + , c->name + , instance + , buf + ); + } - st = state_with_serialno(c->newest_isakmp_sa); - if (st) - whack_log(RC_COMMENT - , "\"%s\"%s: IKE algorithm newest: %s_%d-%s-%s" - , c->name - , instance - , enum_show(&oakley_enc_names, st->st_oakley.encrypt) - +7 /* strlen("OAKLEY_") */ - /* , st->st_oakley.encrypter->keydeflen */ - , st->st_oakley.enckeylen - , enum_show(&oakley_hash_names, st->st_oakley.hash) - +7 /* strlen("OAKLEY_") */ - , enum_show(&oakley_group_names, st->st_oakley.group->group) - +13 /* strlen("OAKLEY_GROUP_") */ - ); + st = state_with_serialno(c->newest_isakmp_sa); + if (st) + whack_log(RC_COMMENT + , "\"%s\"%s: IKE algorithm newest: %s_%d-%s-%s" + , c->name + , instance + , enum_show(&oakley_enc_names, st->st_oakley.encrypt) + +7 /* strlen("OAKLEY_") */ + /* , st->st_oakley.encrypter->keydeflen */ + , st->st_oakley.enckeylen + , enum_show(&oakley_hash_names, st->st_oakley.hash) + +7 /* strlen("OAKLEY_") */ + , enum_show(&oakley_group_names, st->st_oakley.group->group) + +13 /* strlen("OAKLEY_GROUP_") */ + ); } /* @@ -442,70 +442,70 @@ ike_alg_show_connection(struct connection *c, const char *instance) static bool ike_hash_test(const struct hash_desc *desc) { - bool hash_results = TRUE; - bool hmac_results = TRUE; + bool hash_results = TRUE; + bool hmac_results = TRUE; - if (desc->hash_testvectors == NULL) - { - plog(" %s hash self-test not available", enum_name(&oakley_hash_names, desc->algo_id)); - } - else - { - int i; - - for (i = 0; desc->hash_testvectors[i].msg_digest != NULL; i++) + if (desc->hash_testvectors == NULL) { - u_char digest[MAX_DIGEST_LEN]; - bool result; - - union hash_ctx ctx; - - desc->hash_init(&ctx); - desc->hash_update(&ctx, desc->hash_testvectors[i].msg - ,desc->hash_testvectors[i].msg_size); - desc->hash_final(digest, &ctx); - result = memeq(digest, desc->hash_testvectors[i].msg_digest - , desc->hash_digest_size); - DBG(DBG_CRYPT, - DBG_log(" hash testvector %d: %s", i, result ? "ok":"failed") - ) - hash_results &= result; + plog(" %s hash self-test not available", enum_name(&oakley_hash_names, desc->algo_id)); } - plog(" %s hash self-test %s", enum_name(&oakley_hash_names, desc->algo_id) - , hash_results ? "passed":"failed"); - } - - if (desc->hmac_testvectors == NULL) - { - plog(" %s hmac self-test not available", enum_name(&oakley_hash_names, desc->algo_id)); - } - else - { - int i; - - for (i = 0; desc->hmac_testvectors[i].hmac != NULL; i++) + else { - u_char digest[MAX_DIGEST_LEN]; - bool result; + int i; - struct hmac_ctx ctx; + for (i = 0; desc->hash_testvectors[i].msg_digest != NULL; i++) + { + u_char digest[MAX_DIGEST_LEN]; + bool result; - hmac_init(&ctx, desc, desc->hmac_testvectors[i].key - , desc->hmac_testvectors[i].key_size); - hmac_update(&ctx, desc->hmac_testvectors[i].msg - ,desc->hmac_testvectors[i].msg_size); - hmac_final(digest, &ctx); - result = memeq(digest, desc->hmac_testvectors[i].hmac - , desc->hash_digest_size); - DBG(DBG_CRYPT, - DBG_log(" hmac testvector %d: %s", i, result ? "ok":"failed") - ) - hmac_results &= result; + union hash_ctx ctx; + + desc->hash_init(&ctx); + desc->hash_update(&ctx, desc->hash_testvectors[i].msg + ,desc->hash_testvectors[i].msg_size); + desc->hash_final(digest, &ctx); + result = memeq(digest, desc->hash_testvectors[i].msg_digest + , desc->hash_digest_size); + DBG(DBG_CRYPT, + DBG_log(" hash testvector %d: %s", i, result ? "ok":"failed") + ) + hash_results &= result; + } + plog(" %s hash self-test %s", enum_name(&oakley_hash_names, desc->algo_id) + , hash_results ? "passed":"failed"); } - plog(" %s hmac self-test %s", enum_name(&oakley_hash_names, desc->algo_id) - , hmac_results ? "passed":"failed"); - } - return hash_results && hmac_results; + + if (desc->hmac_testvectors == NULL) + { + plog(" %s hmac self-test not available", enum_name(&oakley_hash_names, desc->algo_id)); + } + else + { + int i; + + for (i = 0; desc->hmac_testvectors[i].hmac != NULL; i++) + { + u_char digest[MAX_DIGEST_LEN]; + bool result; + + struct hmac_ctx ctx; + + hmac_init(&ctx, desc, desc->hmac_testvectors[i].key + , desc->hmac_testvectors[i].key_size); + hmac_update(&ctx, desc->hmac_testvectors[i].msg + ,desc->hmac_testvectors[i].msg_size); + hmac_final(digest, &ctx); + result = memeq(digest, desc->hmac_testvectors[i].hmac + , desc->hash_digest_size); + DBG(DBG_CRYPT, + DBG_log(" hmac testvector %d: %s", i, result ? "ok":"failed") + ) + hmac_results &= result; + } + plog(" %s hmac self-test %s", enum_name(&oakley_hash_names, desc->algo_id) + , hmac_results ? "passed":"failed"); + } + return hash_results && hmac_results; } /* @@ -514,30 +514,30 @@ ike_hash_test(const struct hash_desc *desc) bool ike_alg_test(void) { - bool all_results = TRUE; - struct ike_alg *a; + bool all_results = TRUE; + struct ike_alg *a; - plog("Testing registered IKE encryption algorithms:"); + plog("Testing registered IKE encryption algorithms:"); - for (a = ike_alg_base[IKE_ALG_ENCRYPT]; a != NULL; a = a->algo_next) - { - plog(" %s self-test not available", enum_name(&oakley_enc_names, a->algo_id)); - } + for (a = ike_alg_base[IKE_ALG_ENCRYPT]; a != NULL; a = a->algo_next) + { + plog(" %s self-test not available", enum_name(&oakley_enc_names, a->algo_id)); + } - plog("Testing registered IKE hash algorithms:"); + plog("Testing registered IKE hash algorithms:"); - for (a = ike_alg_base[IKE_ALG_HASH]; a != NULL; a = a->algo_next) - { - struct hash_desc *desc = (struct hash_desc*)a; + for (a = ike_alg_base[IKE_ALG_HASH]; a != NULL; a = a->algo_next) + { + struct hash_desc *desc = (struct hash_desc*)a; - all_results &= ike_hash_test(desc); - } + all_results &= ike_hash_test(desc); + } - if (all_results) - plog("All crypto self-tests passed"); - else - plog("Some crypto self-tests failed"); - return all_results; + if (all_results) + plog("All crypto self-tests passed"); + else + plog("Some crypto self-tests failed"); + return all_results; } /* @@ -547,43 +547,43 @@ bool ike_alg_ok_final(u_int ealg, u_int key_len, u_int aalg, u_int group , struct alg_info_ike *alg_info_ike) { - /* - * simple test to discard low key_len, will accept it only - * if specified in "esp" string - */ - bool ealg_insecure = (key_len < 128); + /* + * simple test to discard low key_len, will accept it only + * if specified in "esp" string + */ + bool ealg_insecure = (key_len < 128); - if (ealg_insecure - || (alg_info_ike && alg_info_ike->alg_info_flags & ALG_INFO_F_STRICT)) - { - int i; - struct ike_info *ike_info; - - if (alg_info_ike) + if (ealg_insecure + || (alg_info_ike && alg_info_ike->alg_info_flags & ALG_INFO_F_STRICT)) { - ALG_INFO_IKE_FOREACH(alg_info_ike, ike_info, i) - { - if (ike_info->ike_ealg == ealg - && (ike_info->ike_eklen == 0 || key_len == 0 || ike_info->ike_eklen == key_len) - && ike_info->ike_halg == aalg - && ike_info->ike_modp == group) + int i; + struct ike_info *ike_info; + + if (alg_info_ike) { - if (ealg_insecure) - loglog(RC_LOG_SERIOUS, "You should NOT use insecure IKE algorithms (%s)!" - , enum_name(&oakley_enc_names, ealg)); - return TRUE; + ALG_INFO_IKE_FOREACH(alg_info_ike, ike_info, i) + { + if (ike_info->ike_ealg == ealg + && (ike_info->ike_eklen == 0 || key_len == 0 || ike_info->ike_eklen == key_len) + && ike_info->ike_halg == aalg + && ike_info->ike_modp == group) + { + if (ealg_insecure) + loglog(RC_LOG_SERIOUS, "You should NOT use insecure IKE algorithms (%s)!" + , enum_name(&oakley_enc_names, ealg)); + return TRUE; + } + } } - } + plog("Oakley Transform [%s (%d), %s, %s] refused due to %s" + , enum_name(&oakley_enc_names, ealg), key_len + , enum_name(&oakley_hash_names, aalg) + , enum_name(&oakley_group_names, group) + , ealg_insecure ? + "insecure key_len and enc. alg. not listed in \"ike\" string" : "strict flag" + ); + return FALSE; } - plog("Oakley Transform [%s (%d), %s, %s] refused due to %s" - , enum_name(&oakley_enc_names, ealg), key_len - , enum_name(&oakley_hash_names, aalg) - , enum_name(&oakley_group_names, group) - , ealg_insecure ? - "insecure key_len and enc. alg. not listed in \"ike\" string" : "strict flag" - ); - return FALSE; - } - return TRUE; + return TRUE; } diff --git a/src/pluto/ike_alg.h b/src/pluto/ike_alg.h index 41695e8de..a8ddd1fde 100644 --- a/src/pluto/ike_alg.h +++ b/src/pluto/ike_alg.h @@ -13,66 +13,66 @@ * * RCSID $Id$ */ - + #ifndef _IKE_ALG_H #define _IKE_ALG_H #include "connections.h" struct ike_alg { - u_int16_t algo_type; - u_int16_t algo_id; - struct ike_alg *algo_next; + u_int16_t algo_type; + u_int16_t algo_id; + struct ike_alg *algo_next; }; struct encrypt_desc { - u_int16_t algo_type; - u_int16_t algo_id; - struct ike_alg *algo_next; + u_int16_t algo_type; + u_int16_t algo_id; + struct ike_alg *algo_next; - size_t enc_ctxsize; - size_t enc_blocksize; - u_int keydeflen; - u_int keymaxlen; - u_int keyminlen; - void (*do_crypt)(u_int8_t *dat, size_t datasize, u_int8_t *key, size_t key_size, u_int8_t *iv, bool enc); + size_t enc_ctxsize; + size_t enc_blocksize; + u_int keydeflen; + u_int keymaxlen; + u_int keyminlen; + void (*do_crypt)(u_int8_t *dat, size_t datasize, u_int8_t *key, size_t key_size, u_int8_t *iv, bool enc); }; typedef struct hash_testvector hash_testvector_t; struct hash_testvector { - const size_t msg_size; - const u_char *msg; - const u_char *msg_digest; + const size_t msg_size; + const u_char *msg; + const u_char *msg_digest; }; typedef struct hmac_testvector hmac_testvector_t; struct hmac_testvector { - const size_t key_size; - const u_char *key; - const size_t msg_size; - const u_char *msg; - const u_char *hmac; + const size_t key_size; + const u_char *key; + const size_t msg_size; + const u_char *msg; + const u_char *hmac; }; struct hash_desc { - u_int16_t algo_type; - u_int16_t algo_id; - struct ike_alg *algo_next; + u_int16_t algo_type; + u_int16_t algo_id; + struct ike_alg *algo_next; - size_t hash_ctx_size; - size_t hash_block_size; - size_t hash_digest_size; - const hash_testvector_t *hash_testvectors; - const hmac_testvector_t *hmac_testvectors; - void (*hash_init)(void *ctx); - void (*hash_update)(void *ctx, const u_int8_t *in, size_t datasize); - void (*hash_final)(u_int8_t *out, void *ctx); + size_t hash_ctx_size; + size_t hash_block_size; + size_t hash_digest_size; + const hash_testvector_t *hash_testvectors; + const hmac_testvector_t *hmac_testvectors; + void (*hash_init)(void *ctx); + void (*hash_update)(void *ctx, const u_int8_t *in, size_t datasize); + void (*hash_final)(u_int8_t *out, void *ctx); }; -#define IKE_ALG_ENCRYPT 0 -#define IKE_ALG_HASH 1 -#define IKE_ALG_MAX IKE_ALG_HASH +#define IKE_ALG_ENCRYPT 0 +#define IKE_ALG_HASH 1 +#define IKE_ALG_MAX IKE_ALG_HASH extern int ike_alg_add(struct ike_alg *a); extern struct hash_desc *ike_alg_get_hasher(u_int alg); @@ -82,13 +82,13 @@ extern bool ike_alg_hash_present(u_int halg); extern int ike_alg_register_hash(struct hash_desc *a); extern int ike_alg_register_enc(struct encrypt_desc *e); extern const struct oakley_group_desc* ike_alg_pfsgroup(struct connection *c - , lset_t policy); + , lset_t policy); extern struct db_context * ike_alg_db_new(struct alg_info_ike *ai, lset_t policy); extern void ike_alg_list(void); extern void ike_alg_show_connection(struct connection *c, const char *instance); extern bool ike_alg_test(void); extern bool ike_alg_ok_final(u_int ealg, u_int key_len, u_int aalg, u_int group - , struct alg_info_ike *alg_info_ike); + , struct alg_info_ike *alg_info_ike); extern int ike_alg_init(void); #endif /* _IKE_ALG_H */ diff --git a/src/pluto/ipsec_doi.c b/src/pluto/ipsec_doi.c index c392f19e2..c345fb742 100644 --- a/src/pluto/ipsec_doi.c +++ b/src/pluto/ipsec_doi.c @@ -24,9 +24,9 @@ #include #include #include -#include /* missing from on old systems */ +#include /* missing from on old systems */ #include -#include /* for gettimeofday */ +#include /* for gettimeofday */ #include #include @@ -44,9 +44,9 @@ #include "connections.h" #include "keys.h" #include "packet.h" -#include "demux.h" /* needs packet.h */ -#include "adns.h" /* needs */ -#include "dnskey.h" /* needs keys.h and adns.h */ +#include "demux.h" /* needs packet.h */ +#include "adns.h" /* needs */ +#include "dnskey.h" /* needs keys.h and adns.h */ #include "kernel.h" #include "log.h" #include "cookie.h" @@ -54,7 +54,7 @@ #include "spdb.h" #include "timer.h" #include "rnd.h" -#include "ipsec_doi.h" /* needs demux.h and state.h */ +#include "ipsec_doi.h" /* needs demux.h and state.h */ #include "whack.h" #include "fetch.h" #include "pkcs7.h" @@ -74,48 +74,48 @@ * are we sending Pluto's Vendor ID? */ #ifdef VENDORID -#define SEND_PLUTO_VID 1 +#define SEND_PLUTO_VID 1 #else /* !VENDORID */ -#define SEND_PLUTO_VID 0 +#define SEND_PLUTO_VID 0 #endif /* !VENDORID */ /* * are we sending an XAUTH VID? */ #ifdef XAUTH_VID -#define SEND_XAUTH_VID 1 +#define SEND_XAUTH_VID 1 #else /* !XAUTH_VID */ -#define SEND_XAUTH_VID 0 +#define SEND_XAUTH_VID 0 #endif /* !XAUTH_VID */ /* * are we sending a Cisco Unity VID? */ #ifdef CISCO_QUIRKS -#define SEND_CISCO_UNITY_VID 1 +#define SEND_CISCO_UNITY_VID 1 #else /* !CISCO_QUIRKS */ -#define SEND_CISCO_UNITY_VID 0 +#define SEND_CISCO_UNITY_VID 0 #endif /* !CISCO_QUIRKS */ /* MAGIC: perform f, a function that returns notification_t * and return from the ENCLOSING stf_status returning function if it fails. */ #define RETURN_STF_FAILURE(f) \ - { int r = (f); if (r != NOTHING_WRONG) return STF_FAIL + r; } + { int r = (f); if (r != NOTHING_WRONG) return STF_FAIL + r; } /* create output HDR as replica of input HDR */ void echo_hdr(struct msg_digest *md, bool enc, u_int8_t np) { - struct isakmp_hdr r_hdr = md->hdr; /* mostly same as incoming header */ + struct isakmp_hdr r_hdr = md->hdr; /* mostly same as incoming header */ - r_hdr.isa_flags &= ~ISAKMP_FLAG_COMMIT; /* we won't ever turn on this bit */ - if (enc) - r_hdr.isa_flags |= ISAKMP_FLAG_ENCRYPTION; - /* some day, we may have to set r_hdr.isa_version */ - r_hdr.isa_np = np; - if (!out_struct(&r_hdr, &isakmp_hdr_desc, &md->reply, &md->rbody)) - impossible(); /* surely must have room and be well-formed */ + r_hdr.isa_flags &= ~ISAKMP_FLAG_COMMIT; /* we won't ever turn on this bit */ + if (enc) + r_hdr.isa_flags |= ISAKMP_FLAG_ENCRYPTION; + /* some day, we may have to set r_hdr.isa_version */ + r_hdr.isa_np = np; + if (!out_struct(&r_hdr, &isakmp_hdr_desc, &md->reply, &md->rbody)) + impossible(); /* surely must have room and be well-formed */ } /* Compute DH shared secret from our local secret and the peer's public value. @@ -126,35 +126,35 @@ static void compute_dh_shared(struct state *st, const chunk_t g , const struct oakley_group_desc *group) { - MP_INT mp_g, mp_shared; - struct timeval tv0, tv1; - unsigned long tv_diff; + MP_INT mp_g, mp_shared; + struct timeval tv0, tv1; + unsigned long tv_diff; - gettimeofday(&tv0, NULL); - passert(st->st_sec_in_use); - n_to_mpz(&mp_g, g.ptr, g.len); - mpz_init(&mp_shared); - mpz_powm(&mp_shared, &mp_g, &st->st_sec, group->modulus); - mpz_clear(&mp_g); - free(st->st_shared.ptr); /* happens in odd error cases */ - st->st_shared = mpz_to_n(&mp_shared, group->bytes); - mpz_clear(&mp_shared); - gettimeofday(&tv1, NULL); - tv_diff=(tv1.tv_sec - tv0.tv_sec) * 1000000 + (tv1.tv_usec - tv0.tv_usec); - DBG(DBG_CRYPT, - DBG_log("compute_dh_shared(): time elapsed (%s): %ld usec" - , enum_show(&oakley_group_names, st->st_oakley.group->group) - , tv_diff); - ); - /* if took more than 200 msec ... */ - if (tv_diff > 200000) { - loglog(RC_LOG_SERIOUS, "WARNING: compute_dh_shared(): for %s took " - "%ld usec" - , enum_show(&oakley_group_names, st->st_oakley.group->group) - , tv_diff); - } + gettimeofday(&tv0, NULL); + passert(st->st_sec_in_use); + n_to_mpz(&mp_g, g.ptr, g.len); + mpz_init(&mp_shared); + mpz_powm(&mp_shared, &mp_g, &st->st_sec, group->modulus); + mpz_clear(&mp_g); + free(st->st_shared.ptr); /* happens in odd error cases */ + st->st_shared = mpz_to_n(&mp_shared, group->bytes); + mpz_clear(&mp_shared); + gettimeofday(&tv1, NULL); + tv_diff=(tv1.tv_sec - tv0.tv_sec) * 1000000 + (tv1.tv_usec - tv0.tv_usec); + DBG(DBG_CRYPT, + DBG_log("compute_dh_shared(): time elapsed (%s): %ld usec" + , enum_show(&oakley_group_names, st->st_oakley.group->group) + , tv_diff); + ); + /* if took more than 200 msec ... */ + if (tv_diff > 200000) { + loglog(RC_LOG_SERIOUS, "WARNING: compute_dh_shared(): for %s took " + "%ld usec" + , enum_show(&oakley_group_names, st->st_oakley.group->group) + , tv_diff); + } - DBG_cond_dump_chunk(DBG_CRYPT, "DH shared secret:\n", st->st_shared); + DBG_cond_dump_chunk(DBG_CRYPT, "DH shared secret:\n", st->st_shared); } /* if we haven't already done so, compute a local DH secret (st->st_sec) and @@ -164,25 +164,25 @@ static bool build_and_ship_KE(struct state *st, chunk_t *g , const struct oakley_group_desc *group, pb_stream *outs, u_int8_t np) { - if (!st->st_sec_in_use) - { - u_char tmp[LOCALSECRETSIZE]; - MP_INT mp_g; + if (!st->st_sec_in_use) + { + u_char tmp[LOCALSECRETSIZE]; + MP_INT mp_g; - get_rnd_bytes(tmp, LOCALSECRETSIZE); - st->st_sec_in_use = TRUE; - n_to_mpz(&st->st_sec, tmp, LOCALSECRETSIZE); + get_rnd_bytes(tmp, LOCALSECRETSIZE); + st->st_sec_in_use = TRUE; + n_to_mpz(&st->st_sec, tmp, LOCALSECRETSIZE); - mpz_init(&mp_g); - mpz_powm(&mp_g, &groupgenerator, &st->st_sec, group->modulus); - free(g->ptr); /* happens in odd error cases */ - *g = mpz_to_n(&mp_g, group->bytes); - mpz_clear(&mp_g); - DBG(DBG_CRYPT, - DBG_dump("Local DH secret:\n", tmp, LOCALSECRETSIZE); - DBG_dump_chunk("Public DH value sent:\n", *g)); - } - return out_generic_chunk(np, &isakmp_keyex_desc, outs, *g, "keyex value"); + mpz_init(&mp_g); + mpz_powm(&mp_g, &groupgenerator, &st->st_sec, group->modulus); + free(g->ptr); /* happens in odd error cases */ + *g = mpz_to_n(&mp_g, group->bytes); + mpz_clear(&mp_g); + DBG(DBG_CRYPT, + DBG_dump("Local DH secret:\n", tmp, LOCALSECRETSIZE); + DBG_dump_chunk("Public DH value sent:\n", *g)); + } + return out_generic_chunk(np, &isakmp_keyex_desc, outs, *g, "keyex value"); } /* accept_ke @@ -199,18 +199,18 @@ accept_KE(chunk_t *dest, const char *val_name , const struct oakley_group_desc *gr , pb_stream *pbs) { - if (pbs_left(pbs) != gr->bytes) - { - loglog(RC_LOG_SERIOUS, "KE has %u byte DH public value; %u required" - , (unsigned) pbs_left(pbs), (unsigned) gr->bytes); - /* XXX Could send notification back */ - return INVALID_KEY_INFORMATION; - } - free(dest->ptr); - *dest = chunk_create(pbs->cur, pbs_left(pbs)); - *dest = chunk_clone(*dest); - DBG_cond_dump_chunk(DBG_CRYPT, "DH public value received:\n", *dest); - return NOTHING_WRONG; + if (pbs_left(pbs) != gr->bytes) + { + loglog(RC_LOG_SERIOUS, "KE has %u byte DH public value; %u required" + , (unsigned) pbs_left(pbs), (unsigned) gr->bytes); + /* XXX Could send notification back */ + return INVALID_KEY_INFORMATION; + } + free(dest->ptr); + *dest = chunk_create(pbs->cur, pbs_left(pbs)); + *dest = chunk_clone(*dest); + DBG_cond_dump_chunk(DBG_CRYPT, "DH public value received:\n", *dest); + return NOTHING_WRONG; } /* accept_PFS_KE @@ -222,101 +222,101 @@ static notification_t accept_PFS_KE(struct msg_digest *md, chunk_t *dest , const char *val_name, const char *msg_name) { - struct state *st = md->st; - struct payload_digest *const ke_pd = md->chain[ISAKMP_NEXT_KE]; + struct state *st = md->st; + struct payload_digest *const ke_pd = md->chain[ISAKMP_NEXT_KE]; - if (ke_pd == NULL) - { - if (st->st_pfs_group != NULL) + if (ke_pd == NULL) { - loglog(RC_LOG_SERIOUS, "missing KE payload in %s message", msg_name); - return INVALID_KEY_INFORMATION; + if (st->st_pfs_group != NULL) + { + loglog(RC_LOG_SERIOUS, "missing KE payload in %s message", msg_name); + return INVALID_KEY_INFORMATION; + } } - } - else - { - if (st->st_pfs_group == NULL) + else { - loglog(RC_LOG_SERIOUS, "%s message KE payload requires a GROUP_DESCRIPTION attribute in SA" - , msg_name); - return INVALID_KEY_INFORMATION; + if (st->st_pfs_group == NULL) + { + loglog(RC_LOG_SERIOUS, "%s message KE payload requires a GROUP_DESCRIPTION attribute in SA" + , msg_name); + return INVALID_KEY_INFORMATION; + } + if (ke_pd->next != NULL) + { + loglog(RC_LOG_SERIOUS, "%s message contains several KE payloads; we accept at most one", msg_name); + return INVALID_KEY_INFORMATION; /* ??? */ + } + return accept_KE(dest, val_name, st->st_pfs_group, &ke_pd->pbs); } - if (ke_pd->next != NULL) - { - loglog(RC_LOG_SERIOUS, "%s message contains several KE payloads; we accept at most one", msg_name); - return INVALID_KEY_INFORMATION; /* ??? */ - } - return accept_KE(dest, val_name, st->st_pfs_group, &ke_pd->pbs); - } - return NOTHING_WRONG; + return NOTHING_WRONG; } static bool build_and_ship_nonce(chunk_t *n, pb_stream *outs, u_int8_t np , const char *name) { - free(n->ptr); - *n = chunk_create(malloc(DEFAULT_NONCE_SIZE), DEFAULT_NONCE_SIZE); - get_rnd_bytes(n->ptr, DEFAULT_NONCE_SIZE); - return out_generic_chunk(np, &isakmp_nonce_desc, outs, *n, name); + free(n->ptr); + *n = chunk_create(malloc(DEFAULT_NONCE_SIZE), DEFAULT_NONCE_SIZE); + get_rnd_bytes(n->ptr, DEFAULT_NONCE_SIZE); + return out_generic_chunk(np, &isakmp_nonce_desc, outs, *n, name); } static bool collect_rw_ca_candidates(struct msg_digest *md, generalName_t **top) { - struct connection *d = find_host_connection(&md->iface->addr - , pluto_port, (ip_address*)NULL, md->sender_port, LEMPTY); + struct connection *d = find_host_connection(&md->iface->addr + , pluto_port, (ip_address*)NULL, md->sender_port, LEMPTY); - for (; d != NULL; d = d->hp_next) - { - /* must be a road warrior connection */ - if (d->kind == CK_TEMPLATE && !(d->policy & POLICY_OPPO) - && d->spd.that.ca.ptr != NULL) + for (; d != NULL; d = d->hp_next) { - generalName_t *gn; - bool new_entry = TRUE; - - for (gn = *top; gn != NULL; gn = gn->next) - { - if (same_dn(gn->name, d->spd.that.ca)) + /* must be a road warrior connection */ + if (d->kind == CK_TEMPLATE && !(d->policy & POLICY_OPPO) + && d->spd.that.ca.ptr != NULL) { - new_entry = FALSE; - break; + generalName_t *gn; + bool new_entry = TRUE; + + for (gn = *top; gn != NULL; gn = gn->next) + { + if (same_dn(gn->name, d->spd.that.ca)) + { + new_entry = FALSE; + break; + } + } + if (new_entry) + { + gn = malloc_thing(generalName_t); + gn->kind = GN_DIRECTORY_NAME; + gn->name = d->spd.that.ca; + gn->next = *top; + *top = gn; + } } - } - if (new_entry) - { - gn = malloc_thing(generalName_t); - gn->kind = GN_DIRECTORY_NAME; - gn->name = d->spd.that.ca; - gn->next = *top; - *top = gn; - } } - } - return *top != NULL; + return *top != NULL; } static bool build_and_ship_CR(u_int8_t type, chunk_t ca, pb_stream *outs, u_int8_t np) { - pb_stream cr_pbs; - struct isakmp_cr cr_hd; - cr_hd.isacr_np = np; - cr_hd.isacr_type = type; + pb_stream cr_pbs; + struct isakmp_cr cr_hd; + cr_hd.isacr_np = np; + cr_hd.isacr_type = type; - /* build CR header */ - if (!out_struct(&cr_hd, &isakmp_ipsec_cert_req_desc, outs, &cr_pbs)) - return FALSE; + /* build CR header */ + if (!out_struct(&cr_hd, &isakmp_ipsec_cert_req_desc, outs, &cr_pbs)) + return FALSE; - if (ca.ptr != NULL) - { - /* build CR body containing the distinguished name of the CA */ - if (!out_chunk(ca, &cr_pbs, "CA")) - return FALSE; - } - close_output_pbs(&cr_pbs); - return TRUE; + if (ca.ptr != NULL) + { + /* build CR body containing the distinguished name of the CA */ + if (!out_chunk(ca, &cr_pbs, "CA")) + return FALSE; + } + close_output_pbs(&cr_pbs); + return TRUE; } /* Send a notification to the peer. We could decide @@ -325,196 +325,196 @@ build_and_ship_CR(u_int8_t type, chunk_t ca, pb_stream *outs, u_int8_t np) */ static void send_notification(struct state *sndst, u_int16_t type, struct state *encst, - msgid_t msgid, u_char *icookie, u_char *rcookie, - u_char *spi, size_t spisize, u_char protoid) + msgid_t msgid, u_char *icookie, u_char *rcookie, + u_char *spi, size_t spisize, u_char protoid) { - u_char buffer[1024]; - pb_stream pbs, r_hdr_pbs; - u_char *r_hashval = NULL; /* where in reply to jam hash value */ - u_char *r_hash_start = NULL; /* start of what is to be hashed */ + u_char buffer[1024]; + pb_stream pbs, r_hdr_pbs; + u_char *r_hashval = NULL; /* where in reply to jam hash value */ + u_char *r_hash_start = NULL; /* start of what is to be hashed */ - passert((sndst) && (sndst->st_connection)); + passert((sndst) && (sndst->st_connection)); - plog("sending %snotification %s to %s:%u" - , encst ? "encrypted " : "" - , enum_name(¬ification_names, type) - , ip_str(&sndst->st_connection->spd.that.host_addr) - , (unsigned)sndst->st_connection->spd.that.host_port); + plog("sending %snotification %s to %s:%u" + , encst ? "encrypted " : "" + , enum_name(¬ification_names, type) + , ip_str(&sndst->st_connection->spd.that.host_addr) + , (unsigned)sndst->st_connection->spd.that.host_port); - memset(buffer, 0, sizeof(buffer)); - init_pbs(&pbs, buffer, sizeof(buffer), "ISAKMP notify"); + memset(buffer, 0, sizeof(buffer)); + init_pbs(&pbs, buffer, sizeof(buffer), "ISAKMP notify"); - /* HDR* */ - { - struct isakmp_hdr hdr; - - hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION; - hdr.isa_np = encst ? ISAKMP_NEXT_HASH : ISAKMP_NEXT_N; - hdr.isa_xchg = ISAKMP_XCHG_INFO; - hdr.isa_msgid = msgid; - hdr.isa_flags = encst ? ISAKMP_FLAG_ENCRYPTION : 0; - if (icookie) - memcpy(hdr.isa_icookie, icookie, COOKIE_SIZE); - if (rcookie) - memcpy(hdr.isa_rcookie, rcookie, COOKIE_SIZE); - if (!out_struct(&hdr, &isakmp_hdr_desc, &pbs, &r_hdr_pbs)) - impossible(); - } - - /* HASH -- value to be filled later */ - if (encst) - { - pb_stream hash_pbs; - if (!out_generic(ISAKMP_NEXT_N, &isakmp_hash_desc, &r_hdr_pbs, - &hash_pbs)) - impossible(); - r_hashval = hash_pbs.cur; /* remember where to plant value */ - if (!out_zero( - encst->st_oakley.hasher->hash_digest_size, &hash_pbs, "HASH")) - impossible(); - close_output_pbs(&hash_pbs); - r_hash_start = r_hdr_pbs.cur; /* hash from after HASH */ - } - - /* Notification Payload */ - { - pb_stream not_pbs; - struct isakmp_notification isan; - - isan.isan_doi = ISAKMP_DOI_IPSEC; - isan.isan_np = ISAKMP_NEXT_NONE; - isan.isan_type = type; - isan.isan_spisize = spisize; - isan.isan_protoid = protoid; - - if (!out_struct(&isan, &isakmp_notification_desc, &r_hdr_pbs, ¬_pbs) - || !out_raw(spi, spisize, ¬_pbs, "spi")) - impossible(); - close_output_pbs(¬_pbs); - } - - /* calculate hash value and patch into Hash Payload */ - if (encst) - { - struct hmac_ctx ctx; - hmac_init_chunk(&ctx, encst->st_oakley.hasher, encst->st_skeyid_a); - hmac_update(&ctx, (u_char *) &msgid, sizeof(msgid_t)); - hmac_update(&ctx, r_hash_start, r_hdr_pbs.cur-r_hash_start); - hmac_final(r_hashval, &ctx); - - DBG(DBG_CRYPT, - DBG_log("HASH computed:"); - DBG_dump("", r_hashval, ctx.hmac_digest_size); - ) - } - - /* Encrypt message (preserve st_iv and st_new_iv) */ - if (encst) - { - u_char old_iv[MAX_DIGEST_LEN]; - u_char new_iv[MAX_DIGEST_LEN]; - - u_int old_iv_len = encst->st_iv_len; - u_int new_iv_len = encst->st_new_iv_len; - - if (old_iv_len > MAX_DIGEST_LEN || new_iv_len > MAX_DIGEST_LEN) - impossible(); - - memcpy(old_iv, encst->st_iv, old_iv_len); - memcpy(new_iv, encst->st_new_iv, new_iv_len); - - if (!IS_ISAKMP_SA_ESTABLISHED(encst->st_state)) + /* HDR* */ { - memcpy(encst->st_ph1_iv, encst->st_new_iv, encst->st_new_iv_len); - encst->st_ph1_iv_len = encst->st_new_iv_len; + struct isakmp_hdr hdr; + + hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION; + hdr.isa_np = encst ? ISAKMP_NEXT_HASH : ISAKMP_NEXT_N; + hdr.isa_xchg = ISAKMP_XCHG_INFO; + hdr.isa_msgid = msgid; + hdr.isa_flags = encst ? ISAKMP_FLAG_ENCRYPTION : 0; + if (icookie) + memcpy(hdr.isa_icookie, icookie, COOKIE_SIZE); + if (rcookie) + memcpy(hdr.isa_rcookie, rcookie, COOKIE_SIZE); + if (!out_struct(&hdr, &isakmp_hdr_desc, &pbs, &r_hdr_pbs)) + impossible(); } - init_phase2_iv(encst, &msgid); - if (!encrypt_message(&r_hdr_pbs, encst)) - impossible(); - - /* restore preserved st_iv and st_new_iv */ - memcpy(encst->st_iv, old_iv, old_iv_len); - memcpy(encst->st_new_iv, new_iv, new_iv_len); - encst->st_iv_len = old_iv_len; - encst->st_new_iv_len = new_iv_len; - } - else - { - close_output_pbs(&r_hdr_pbs); - } - /* Send packet (preserve st_tpacket) */ - { - chunk_t saved_tpacket = sndst->st_tpacket; + /* HASH -- value to be filled later */ + if (encst) + { + pb_stream hash_pbs; + if (!out_generic(ISAKMP_NEXT_N, &isakmp_hash_desc, &r_hdr_pbs, + &hash_pbs)) + impossible(); + r_hashval = hash_pbs.cur; /* remember where to plant value */ + if (!out_zero( + encst->st_oakley.hasher->hash_digest_size, &hash_pbs, "HASH")) + impossible(); + close_output_pbs(&hash_pbs); + r_hash_start = r_hdr_pbs.cur; /* hash from after HASH */ + } - sndst->st_tpacket = chunk_create(pbs.start, pbs_offset(&pbs)); - send_packet(sndst, "ISAKMP notify"); - sndst->st_tpacket = saved_tpacket; - } + /* Notification Payload */ + { + pb_stream not_pbs; + struct isakmp_notification isan; + + isan.isan_doi = ISAKMP_DOI_IPSEC; + isan.isan_np = ISAKMP_NEXT_NONE; + isan.isan_type = type; + isan.isan_spisize = spisize; + isan.isan_protoid = protoid; + + if (!out_struct(&isan, &isakmp_notification_desc, &r_hdr_pbs, ¬_pbs) + || !out_raw(spi, spisize, ¬_pbs, "spi")) + impossible(); + close_output_pbs(¬_pbs); + } + + /* calculate hash value and patch into Hash Payload */ + if (encst) + { + struct hmac_ctx ctx; + hmac_init_chunk(&ctx, encst->st_oakley.hasher, encst->st_skeyid_a); + hmac_update(&ctx, (u_char *) &msgid, sizeof(msgid_t)); + hmac_update(&ctx, r_hash_start, r_hdr_pbs.cur-r_hash_start); + hmac_final(r_hashval, &ctx); + + DBG(DBG_CRYPT, + DBG_log("HASH computed:"); + DBG_dump("", r_hashval, ctx.hmac_digest_size); + ) + } + + /* Encrypt message (preserve st_iv and st_new_iv) */ + if (encst) + { + u_char old_iv[MAX_DIGEST_LEN]; + u_char new_iv[MAX_DIGEST_LEN]; + + u_int old_iv_len = encst->st_iv_len; + u_int new_iv_len = encst->st_new_iv_len; + + if (old_iv_len > MAX_DIGEST_LEN || new_iv_len > MAX_DIGEST_LEN) + impossible(); + + memcpy(old_iv, encst->st_iv, old_iv_len); + memcpy(new_iv, encst->st_new_iv, new_iv_len); + + if (!IS_ISAKMP_SA_ESTABLISHED(encst->st_state)) + { + memcpy(encst->st_ph1_iv, encst->st_new_iv, encst->st_new_iv_len); + encst->st_ph1_iv_len = encst->st_new_iv_len; + } + init_phase2_iv(encst, &msgid); + if (!encrypt_message(&r_hdr_pbs, encst)) + impossible(); + + /* restore preserved st_iv and st_new_iv */ + memcpy(encst->st_iv, old_iv, old_iv_len); + memcpy(encst->st_new_iv, new_iv, new_iv_len); + encst->st_iv_len = old_iv_len; + encst->st_new_iv_len = new_iv_len; + } + else + { + close_output_pbs(&r_hdr_pbs); + } + + /* Send packet (preserve st_tpacket) */ + { + chunk_t saved_tpacket = sndst->st_tpacket; + + sndst->st_tpacket = chunk_create(pbs.start, pbs_offset(&pbs)); + send_packet(sndst, "ISAKMP notify"); + sndst->st_tpacket = saved_tpacket; + } } void send_notification_from_state(struct state *st, enum state_kind state, - u_int16_t type) + u_int16_t type) { - struct state *p1st; + struct state *p1st; - passert(st); + passert(st); - if (state == STATE_UNDEFINED) - state = st->st_state; + if (state == STATE_UNDEFINED) + state = st->st_state; - if (IS_QUICK(state)) - { - p1st = find_phase1_state(st->st_connection, ISAKMP_SA_ESTABLISHED_STATES); - if ((p1st == NULL) || (!IS_ISAKMP_SA_ESTABLISHED(p1st->st_state))) + if (IS_QUICK(state)) { - loglog(RC_LOG_SERIOUS, - "no Phase1 state for Quick mode notification"); - return; + p1st = find_phase1_state(st->st_connection, ISAKMP_SA_ESTABLISHED_STATES); + if ((p1st == NULL) || (!IS_ISAKMP_SA_ESTABLISHED(p1st->st_state))) + { + loglog(RC_LOG_SERIOUS, + "no Phase1 state for Quick mode notification"); + return; + } + send_notification(st, type, p1st, generate_msgid(p1st), + st->st_icookie, st->st_rcookie, NULL, 0, PROTO_ISAKMP); + } + else if (IS_ISAKMP_ENCRYPTED(state) && st->st_enc_key.ptr != NULL) + { + send_notification(st, type, st, generate_msgid(st), + st->st_icookie, st->st_rcookie, NULL, 0, PROTO_ISAKMP); + } + else + { + /* no ISAKMP SA established - don't encrypt notification */ + send_notification(st, type, NULL, 0, + st->st_icookie, st->st_rcookie, NULL, 0, PROTO_ISAKMP); } - send_notification(st, type, p1st, generate_msgid(p1st), - st->st_icookie, st->st_rcookie, NULL, 0, PROTO_ISAKMP); - } - else if (IS_ISAKMP_ENCRYPTED(state) && st->st_enc_key.ptr != NULL) - { - send_notification(st, type, st, generate_msgid(st), - st->st_icookie, st->st_rcookie, NULL, 0, PROTO_ISAKMP); - } - else - { - /* no ISAKMP SA established - don't encrypt notification */ - send_notification(st, type, NULL, 0, - st->st_icookie, st->st_rcookie, NULL, 0, PROTO_ISAKMP); - } } void send_notification_from_md(struct msg_digest *md, u_int16_t type) { - /** - * Create a dummy state to be able to use send_packet in - * send_notification - * - * we need to set: - * st_connection->that.host_addr - * st_connection->that.host_port - * st_connection->interface - */ - struct state st; - struct connection cnx; + /** + * Create a dummy state to be able to use send_packet in + * send_notification + * + * we need to set: + * st_connection->that.host_addr + * st_connection->that.host_port + * st_connection->interface + */ + struct state st; + struct connection cnx; - passert(md); + passert(md); - memset(&st, 0, sizeof(st)); - memset(&cnx, 0, sizeof(cnx)); - st.st_connection = &cnx; - cnx.spd.that.host_addr = md->sender; - cnx.spd.that.host_port = md->sender_port; - cnx.interface = md->iface; + memset(&st, 0, sizeof(st)); + memset(&cnx, 0, sizeof(cnx)); + st.st_connection = &cnx; + cnx.spd.that.host_addr = md->sender; + cnx.spd.that.host_port = md->sender_port; + cnx.interface = md->iface; - send_notification(&st, type, NULL, 0, - md->hdr.isa_icookie, md->hdr.isa_rcookie, NULL, 0, PROTO_ISAKMP); + send_notification(&st, type, NULL, 0, + md->hdr.isa_icookie, md->hdr.isa_rcookie, NULL, 0, PROTO_ISAKMP); } /* Send a Delete Notification to announce deletion of ISAKMP SA or @@ -524,346 +524,346 @@ send_notification_from_md(struct msg_digest *md, u_int16_t type) void send_delete(struct state *st) { - pb_stream reply_pbs; - pb_stream r_hdr_pbs; - msgid_t msgid; - u_char buffer[8192]; - struct state *p1st; - ip_said said[EM_MAXRELSPIS]; - ip_said *ns = said; - u_char - *r_hashval, /* where in reply to jam hash value */ - *r_hash_start; /* start of what is to be hashed */ - bool isakmp_sa = FALSE; + pb_stream reply_pbs; + pb_stream r_hdr_pbs; + msgid_t msgid; + u_char buffer[8192]; + struct state *p1st; + ip_said said[EM_MAXRELSPIS]; + ip_said *ns = said; + u_char + *r_hashval, /* where in reply to jam hash value */ + *r_hash_start; /* start of what is to be hashed */ + bool isakmp_sa = FALSE; - if (IS_IPSEC_SA_ESTABLISHED(st->st_state)) - { - p1st = find_phase1_state(st->st_connection, ISAKMP_SA_ESTABLISHED_STATES); - if (p1st == NULL) + if (IS_IPSEC_SA_ESTABLISHED(st->st_state)) { - DBG(DBG_CONTROL, DBG_log("no Phase 1 state for Delete")); - return; + p1st = find_phase1_state(st->st_connection, ISAKMP_SA_ESTABLISHED_STATES); + if (p1st == NULL) + { + DBG(DBG_CONTROL, DBG_log("no Phase 1 state for Delete")); + return; + } + + if (st->st_ah.present) + { + ns->spi = st->st_ah.our_spi; + ns->dst = st->st_connection->spd.this.host_addr; + ns->proto = PROTO_IPSEC_AH; + ns++; + } + if (st->st_esp.present) + { + ns->spi = st->st_esp.our_spi; + ns->dst = st->st_connection->spd.this.host_addr; + ns->proto = PROTO_IPSEC_ESP; + ns++; + } + + passert(ns != said); /* there must be some SAs to delete */ + } + else if (IS_ISAKMP_SA_ESTABLISHED(st->st_state)) + { + p1st = st; + isakmp_sa = TRUE; + } + else + { + return; /* nothing to do */ } - if (st->st_ah.present) + msgid = generate_msgid(p1st); + + zero(buffer); + init_pbs(&reply_pbs, buffer, sizeof(buffer), "delete msg"); + + /* HDR* */ { - ns->spi = st->st_ah.our_spi; - ns->dst = st->st_connection->spd.this.host_addr; - ns->proto = PROTO_IPSEC_AH; - ns++; - } - if (st->st_esp.present) - { - ns->spi = st->st_esp.our_spi; - ns->dst = st->st_connection->spd.this.host_addr; - ns->proto = PROTO_IPSEC_ESP; - ns++; + struct isakmp_hdr hdr; + + hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION; + hdr.isa_np = ISAKMP_NEXT_HASH; + hdr.isa_xchg = ISAKMP_XCHG_INFO; + hdr.isa_msgid = msgid; + hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION; + memcpy(hdr.isa_icookie, p1st->st_icookie, COOKIE_SIZE); + memcpy(hdr.isa_rcookie, p1st->st_rcookie, COOKIE_SIZE); + if (!out_struct(&hdr, &isakmp_hdr_desc, &reply_pbs, &r_hdr_pbs)) + impossible(); } - passert(ns != said); /* there must be some SAs to delete */ - } - else if (IS_ISAKMP_SA_ESTABLISHED(st->st_state)) - { - p1st = st; - isakmp_sa = TRUE; - } - else - { - return; /* nothing to do */ - } - - msgid = generate_msgid(p1st); - - zero(buffer); - init_pbs(&reply_pbs, buffer, sizeof(buffer), "delete msg"); - - /* HDR* */ - { - struct isakmp_hdr hdr; - - hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION; - hdr.isa_np = ISAKMP_NEXT_HASH; - hdr.isa_xchg = ISAKMP_XCHG_INFO; - hdr.isa_msgid = msgid; - hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION; - memcpy(hdr.isa_icookie, p1st->st_icookie, COOKIE_SIZE); - memcpy(hdr.isa_rcookie, p1st->st_rcookie, COOKIE_SIZE); - if (!out_struct(&hdr, &isakmp_hdr_desc, &reply_pbs, &r_hdr_pbs)) - impossible(); - } - - /* HASH -- value to be filled later */ - { - pb_stream hash_pbs; - - if (!out_generic(ISAKMP_NEXT_D, &isakmp_hash_desc, &r_hdr_pbs, &hash_pbs)) - impossible(); - r_hashval = hash_pbs.cur; /* remember where to plant value */ - if (!out_zero(p1st->st_oakley.hasher->hash_digest_size, &hash_pbs, "HASH(1)")) - impossible(); - close_output_pbs(&hash_pbs); - r_hash_start = r_hdr_pbs.cur; /* hash from after HASH(1) */ - } - - /* Delete Payloads */ - if (isakmp_sa) - { - pb_stream del_pbs; - struct isakmp_delete isad; - u_char isakmp_spi[2*COOKIE_SIZE]; - - isad.isad_doi = ISAKMP_DOI_IPSEC; - isad.isad_np = ISAKMP_NEXT_NONE; - isad.isad_spisize = (2 * COOKIE_SIZE); - isad.isad_protoid = PROTO_ISAKMP; - isad.isad_nospi = 1; - - memcpy(isakmp_spi, st->st_icookie, COOKIE_SIZE); - memcpy(isakmp_spi+COOKIE_SIZE, st->st_rcookie, COOKIE_SIZE); - - if (!out_struct(&isad, &isakmp_delete_desc, &r_hdr_pbs, &del_pbs) - || !out_raw(&isakmp_spi, (2*COOKIE_SIZE), &del_pbs, "delete payload")) - impossible(); - close_output_pbs(&del_pbs); - } - else - { - while (ns != said) + /* HASH -- value to be filled later */ { + pb_stream hash_pbs; - pb_stream del_pbs; - struct isakmp_delete isad; - - ns--; - isad.isad_doi = ISAKMP_DOI_IPSEC; - isad.isad_np = ns == said? ISAKMP_NEXT_NONE : ISAKMP_NEXT_D; - isad.isad_spisize = sizeof(ipsec_spi_t); - isad.isad_protoid = ns->proto; - - isad.isad_nospi = 1; - if (!out_struct(&isad, &isakmp_delete_desc, &r_hdr_pbs, &del_pbs) - || !out_raw(&ns->spi, sizeof(ipsec_spi_t), &del_pbs, "delete payload")) - impossible(); - close_output_pbs(&del_pbs); + if (!out_generic(ISAKMP_NEXT_D, &isakmp_hash_desc, &r_hdr_pbs, &hash_pbs)) + impossible(); + r_hashval = hash_pbs.cur; /* remember where to plant value */ + if (!out_zero(p1st->st_oakley.hasher->hash_digest_size, &hash_pbs, "HASH(1)")) + impossible(); + close_output_pbs(&hash_pbs); + r_hash_start = r_hdr_pbs.cur; /* hash from after HASH(1) */ } - } - /* calculate hash value and patch into Hash Payload */ - { - struct hmac_ctx ctx; - hmac_init_chunk(&ctx, p1st->st_oakley.hasher, p1st->st_skeyid_a); - hmac_update(&ctx, (u_char *) &msgid, sizeof(msgid_t)); - hmac_update(&ctx, r_hash_start, r_hdr_pbs.cur-r_hash_start); - hmac_final(r_hashval, &ctx); + /* Delete Payloads */ + if (isakmp_sa) + { + pb_stream del_pbs; + struct isakmp_delete isad; + u_char isakmp_spi[2*COOKIE_SIZE]; - DBG(DBG_CRYPT, - DBG_log("HASH(1) computed:"); - DBG_dump("", r_hashval, ctx.hmac_digest_size); - ) - } + isad.isad_doi = ISAKMP_DOI_IPSEC; + isad.isad_np = ISAKMP_NEXT_NONE; + isad.isad_spisize = (2 * COOKIE_SIZE); + isad.isad_protoid = PROTO_ISAKMP; + isad.isad_nospi = 1; - /* Do a dance to avoid needing a new state object. - * We use the Phase 1 State. This is the one with right - * IV, for one thing. - * The tricky bits are: - * - we need to preserve (save/restore) st_iv (but not st_iv_new) - * - we need to preserve (save/restore) st_tpacket. - */ - { - u_char old_iv[MAX_DIGEST_LEN]; - chunk_t saved_tpacket = p1st->st_tpacket; + memcpy(isakmp_spi, st->st_icookie, COOKIE_SIZE); + memcpy(isakmp_spi+COOKIE_SIZE, st->st_rcookie, COOKIE_SIZE); - memcpy(old_iv, p1st->st_iv, p1st->st_iv_len); - init_phase2_iv(p1st, &msgid); + if (!out_struct(&isad, &isakmp_delete_desc, &r_hdr_pbs, &del_pbs) + || !out_raw(&isakmp_spi, (2*COOKIE_SIZE), &del_pbs, "delete payload")) + impossible(); + close_output_pbs(&del_pbs); + } + else + { + while (ns != said) + { - if (!encrypt_message(&r_hdr_pbs, p1st)) - impossible(); + pb_stream del_pbs; + struct isakmp_delete isad; - p1st->st_tpacket = chunk_create(reply_pbs.start, pbs_offset(&reply_pbs)); - send_packet(p1st, "delete notify"); - p1st->st_tpacket = saved_tpacket; + ns--; + isad.isad_doi = ISAKMP_DOI_IPSEC; + isad.isad_np = ns == said? ISAKMP_NEXT_NONE : ISAKMP_NEXT_D; + isad.isad_spisize = sizeof(ipsec_spi_t); + isad.isad_protoid = ns->proto; - /* get back old IV for this state */ - memcpy(p1st->st_iv, old_iv, p1st->st_iv_len); - } + isad.isad_nospi = 1; + if (!out_struct(&isad, &isakmp_delete_desc, &r_hdr_pbs, &del_pbs) + || !out_raw(&ns->spi, sizeof(ipsec_spi_t), &del_pbs, "delete payload")) + impossible(); + close_output_pbs(&del_pbs); + } + } + + /* calculate hash value and patch into Hash Payload */ + { + struct hmac_ctx ctx; + hmac_init_chunk(&ctx, p1st->st_oakley.hasher, p1st->st_skeyid_a); + hmac_update(&ctx, (u_char *) &msgid, sizeof(msgid_t)); + hmac_update(&ctx, r_hash_start, r_hdr_pbs.cur-r_hash_start); + hmac_final(r_hashval, &ctx); + + DBG(DBG_CRYPT, + DBG_log("HASH(1) computed:"); + DBG_dump("", r_hashval, ctx.hmac_digest_size); + ) + } + + /* Do a dance to avoid needing a new state object. + * We use the Phase 1 State. This is the one with right + * IV, for one thing. + * The tricky bits are: + * - we need to preserve (save/restore) st_iv (but not st_iv_new) + * - we need to preserve (save/restore) st_tpacket. + */ + { + u_char old_iv[MAX_DIGEST_LEN]; + chunk_t saved_tpacket = p1st->st_tpacket; + + memcpy(old_iv, p1st->st_iv, p1st->st_iv_len); + init_phase2_iv(p1st, &msgid); + + if (!encrypt_message(&r_hdr_pbs, p1st)) + impossible(); + + p1st->st_tpacket = chunk_create(reply_pbs.start, pbs_offset(&reply_pbs)); + send_packet(p1st, "delete notify"); + p1st->st_tpacket = saved_tpacket; + + /* get back old IV for this state */ + memcpy(p1st->st_iv, old_iv, p1st->st_iv_len); + } } void accept_delete(struct state *st, struct msg_digest *md, struct payload_digest *p) { - struct isakmp_delete *d = &(p->payload.delete); - size_t sizespi; - int i; + struct isakmp_delete *d = &(p->payload.delete); + size_t sizespi; + int i; - if (!md->encrypted) - { - loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: not encrypted"); - return; - } - - if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state)) - { - /* can't happen (if msg is encrypt), but just to be sure */ - loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: " - "ISAKMP SA not established"); - return; - } - - if (d->isad_nospi == 0) - { - loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: no SPI"); - return; - } - - switch (d->isad_protoid) - { - case PROTO_ISAKMP: - sizespi = 2 * COOKIE_SIZE; - break; - case PROTO_IPSEC_AH: - case PROTO_IPSEC_ESP: - sizespi = sizeof(ipsec_spi_t); - break; - case PROTO_IPCOMP: - /* nothing interesting to delete */ - return; - default: - loglog(RC_LOG_SERIOUS - , "ignoring Delete SA payload: unknown Protocol ID (%s)" - , enum_show(&protocol_names, d->isad_protoid)); - return; - } - - if (d->isad_spisize != sizespi) - { - loglog(RC_LOG_SERIOUS - , "ignoring Delete SA payload: bad SPI size (%d) for %s" - , d->isad_spisize, enum_show(&protocol_names, d->isad_protoid)); - return; - } - - if (pbs_left(&p->pbs) != d->isad_nospi * sizespi) - { - loglog(RC_LOG_SERIOUS - , "ignoring Delete SA payload: invalid payload size"); - return; - } - - for (i = 0; i < d->isad_nospi; i++) - { - u_char *spi = p->pbs.cur + (i * sizespi); - - if (d->isad_protoid == PROTO_ISAKMP) + if (!md->encrypted) { - /** - * ISAKMP - */ - struct state *dst = find_state(spi /*iCookie*/ - , spi+COOKIE_SIZE /*rCookie*/ - , &st->st_connection->spd.that.host_addr - , MAINMODE_MSGID); - - if (dst == NULL) - { - loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: " - "ISAKMP SA not found (maybe expired)"); - } - else if (!same_peer_ids(st->st_connection, dst->st_connection, NULL)) - { - /* we've not authenticated the relevant identities */ - loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: " - "ISAKMP SA used to convey Delete has different IDs from ISAKMP SA it deletes"); - } - else - { - struct connection *oldc; - - oldc = cur_connection; - set_cur_connection(dst->st_connection); - - if (nat_traversal_enabled) - nat_traversal_change_port_lookup(md, dst); - - loglog(RC_LOG_SERIOUS, "received Delete SA payload: " - "deleting ISAKMP State #%lu", dst->st_serialno); - delete_state(dst); - set_cur_connection(oldc); - } + loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: not encrypted"); + return; } - else + + if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state)) { - /** - * IPSEC (ESP/AH) - */ - bool bogus; - struct state *dst = find_phase2_state_to_delete(st - , d->isad_protoid - , *(ipsec_spi_t *)spi /* network order */ - , &bogus); + /* can't happen (if msg is encrypt), but just to be sure */ + loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: " + "ISAKMP SA not established"); + return; + } - if (dst == NULL) - { + if (d->isad_nospi == 0) + { + loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: no SPI"); + return; + } + + switch (d->isad_protoid) + { + case PROTO_ISAKMP: + sizespi = 2 * COOKIE_SIZE; + break; + case PROTO_IPSEC_AH: + case PROTO_IPSEC_ESP: + sizespi = sizeof(ipsec_spi_t); + break; + case PROTO_IPCOMP: + /* nothing interesting to delete */ + return; + default: loglog(RC_LOG_SERIOUS - , "ignoring Delete SA payload: %s SA(0x%08lx) not found (%s)" - , enum_show(&protocol_names, d->isad_protoid) - , (unsigned long)ntohl((unsigned long)*(ipsec_spi_t *)spi) - , bogus ? "our SPI - bogus implementation" : "maybe expired"); - } - else - { - struct connection *rc = dst->st_connection; - struct connection *oldc; - - oldc = cur_connection; - set_cur_connection(rc); + , "ignoring Delete SA payload: unknown Protocol ID (%s)" + , enum_show(&protocol_names, d->isad_protoid)); + return; + } - if (nat_traversal_enabled) - nat_traversal_change_port_lookup(md, dst); + if (d->isad_spisize != sizespi) + { + loglog(RC_LOG_SERIOUS + , "ignoring Delete SA payload: bad SPI size (%d) for %s" + , d->isad_spisize, enum_show(&protocol_names, d->isad_protoid)); + return; + } - if (rc->newest_ipsec_sa == dst->st_serialno - && (rc->policy & POLICY_UP)) - { - /* Last IPSec SA for a permanent connection that we - * have initiated. Replace it in a few seconds. - * - * Useful if the other peer is rebooting. - */ -#define DELETE_SA_DELAY EVENT_RETRANSMIT_DELAY_0 - if (dst->st_event != NULL - && dst->st_event->ev_type == EVENT_SA_REPLACE - && dst->st_event->ev_time <= DELETE_SA_DELAY + now()) - { - /* Patch from Angus Lees to ignore retransmited - * Delete SA. + if (pbs_left(&p->pbs) != d->isad_nospi * sizespi) + { + loglog(RC_LOG_SERIOUS + , "ignoring Delete SA payload: invalid payload size"); + return; + } + + for (i = 0; i < d->isad_nospi; i++) + { + u_char *spi = p->pbs.cur + (i * sizespi); + + if (d->isad_protoid == PROTO_ISAKMP) + { + /** + * ISAKMP */ - loglog(RC_LOG_SERIOUS, "received Delete SA payload: " - "already replacing IPSEC State #%lu in %d seconds" - , dst->st_serialno, (int)(dst->st_event->ev_time - now())); - } - else - { - loglog(RC_LOG_SERIOUS, "received Delete SA payload: " - "replace IPSEC State #%lu in %d seconds" - , dst->st_serialno, DELETE_SA_DELAY); - dst->st_margin = DELETE_SA_DELAY; - delete_event(dst); - event_schedule(EVENT_SA_REPLACE, DELETE_SA_DELAY, dst); - } + struct state *dst = find_state(spi /*iCookie*/ + , spi+COOKIE_SIZE /*rCookie*/ + , &st->st_connection->spd.that.host_addr + , MAINMODE_MSGID); + + if (dst == NULL) + { + loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: " + "ISAKMP SA not found (maybe expired)"); + } + else if (!same_peer_ids(st->st_connection, dst->st_connection, NULL)) + { + /* we've not authenticated the relevant identities */ + loglog(RC_LOG_SERIOUS, "ignoring Delete SA payload: " + "ISAKMP SA used to convey Delete has different IDs from ISAKMP SA it deletes"); + } + else + { + struct connection *oldc; + + oldc = cur_connection; + set_cur_connection(dst->st_connection); + + if (nat_traversal_enabled) + nat_traversal_change_port_lookup(md, dst); + + loglog(RC_LOG_SERIOUS, "received Delete SA payload: " + "deleting ISAKMP State #%lu", dst->st_serialno); + delete_state(dst); + set_cur_connection(oldc); + } } else { - loglog(RC_LOG_SERIOUS, "received Delete SA(0x%08lx) payload: " - "deleting IPSEC State #%lu" - , (unsigned long)ntohl((unsigned long)*(ipsec_spi_t *)spi) - , dst->st_serialno); - delete_state(dst); - } + /** + * IPSEC (ESP/AH) + */ + bool bogus; + struct state *dst = find_phase2_state_to_delete(st + , d->isad_protoid + , *(ipsec_spi_t *)spi /* network order */ + , &bogus); - /* reset connection */ - set_cur_connection(oldc); - } + if (dst == NULL) + { + loglog(RC_LOG_SERIOUS + , "ignoring Delete SA payload: %s SA(0x%08lx) not found (%s)" + , enum_show(&protocol_names, d->isad_protoid) + , (unsigned long)ntohl((unsigned long)*(ipsec_spi_t *)spi) + , bogus ? "our SPI - bogus implementation" : "maybe expired"); + } + else + { + struct connection *rc = dst->st_connection; + struct connection *oldc; + + oldc = cur_connection; + set_cur_connection(rc); + + if (nat_traversal_enabled) + nat_traversal_change_port_lookup(md, dst); + + if (rc->newest_ipsec_sa == dst->st_serialno + && (rc->policy & POLICY_UP)) + { + /* Last IPSec SA for a permanent connection that we + * have initiated. Replace it in a few seconds. + * + * Useful if the other peer is rebooting. + */ +#define DELETE_SA_DELAY EVENT_RETRANSMIT_DELAY_0 + if (dst->st_event != NULL + && dst->st_event->ev_type == EVENT_SA_REPLACE + && dst->st_event->ev_time <= DELETE_SA_DELAY + now()) + { + /* Patch from Angus Lees to ignore retransmited + * Delete SA. + */ + loglog(RC_LOG_SERIOUS, "received Delete SA payload: " + "already replacing IPSEC State #%lu in %d seconds" + , dst->st_serialno, (int)(dst->st_event->ev_time - now())); + } + else + { + loglog(RC_LOG_SERIOUS, "received Delete SA payload: " + "replace IPSEC State #%lu in %d seconds" + , dst->st_serialno, DELETE_SA_DELAY); + dst->st_margin = DELETE_SA_DELAY; + delete_event(dst); + event_schedule(EVENT_SA_REPLACE, DELETE_SA_DELAY, dst); + } + } + else + { + loglog(RC_LOG_SERIOUS, "received Delete SA(0x%08lx) payload: " + "deleting IPSEC State #%lu" + , (unsigned long)ntohl((unsigned long)*(ipsec_spi_t *)spi) + , dst->st_serialno); + delete_state(dst); + } + + /* reset connection */ + set_cur_connection(oldc); + } + } } - } } /* The whole message must be a multiple of 4 octets. @@ -874,11 +874,11 @@ accept_delete(struct state *st, struct msg_digest *md, struct payload_digest *p) void close_message(pb_stream *pbs) { - size_t padding = pad_up(pbs_offset(pbs), 4); + size_t padding = pad_up(pbs_offset(pbs), 4); - if (padding != 0) - (void) out_zero(padding, pbs, "message padding"); - close_output_pbs(pbs); + if (padding != 0) + (void) out_zero(padding, pbs, "message padding"); + close_output_pbs(pbs); } /* Initiate an Oakley Main Mode exchange. @@ -887,181 +887,181 @@ close_message(pb_stream *pbs) */ static stf_status main_outI1(int whack_sock, struct connection *c, struct state *predecessor - , lset_t policy, unsigned long try) + , lset_t policy, unsigned long try) { - struct state *st = new_state(); - pb_stream reply; /* not actually a reply, but you know what I mean */ - pb_stream rbody; + struct state *st = new_state(); + pb_stream reply; /* not actually a reply, but you know what I mean */ + pb_stream rbody; - int vids_to_send = 0; - - /* set up new state */ - st->st_connection = c; - set_cur_state(st); /* we must reset before exit */ - st->st_policy = policy & ~POLICY_IPSEC_MASK; - st->st_whack_sock = whack_sock; - st->st_try = try; - st->st_state = STATE_MAIN_I1; + int vids_to_send = 0; + + /* set up new state */ + st->st_connection = c; + set_cur_state(st); /* we must reset before exit */ + st->st_policy = policy & ~POLICY_IPSEC_MASK; + st->st_whack_sock = whack_sock; + st->st_try = try; + st->st_state = STATE_MAIN_I1; - /* determine how many Vendor ID payloads we will be sending */ - if (SEND_PLUTO_VID) - vids_to_send++; - if (SEND_CISCO_UNITY_VID) - vids_to_send++; - if (c->spd.this.cert.type == CERT_PGP) - vids_to_send++; - if (SEND_XAUTH_VID) - vids_to_send++; - /* always send DPD Vendor ID */ - vids_to_send++; - if (nat_traversal_enabled) - vids_to_send++; + /* determine how many Vendor ID payloads we will be sending */ + if (SEND_PLUTO_VID) + vids_to_send++; + if (SEND_CISCO_UNITY_VID) + vids_to_send++; + if (c->spd.this.cert.type == CERT_PGP) + vids_to_send++; + if (SEND_XAUTH_VID) + vids_to_send++; + /* always send DPD Vendor ID */ + vids_to_send++; + if (nat_traversal_enabled) + vids_to_send++; get_cookie(TRUE, st->st_icookie, COOKIE_SIZE, &c->spd.that.host_addr); - insert_state(st); /* needs cookies, connection, and msgid (0) */ + insert_state(st); /* needs cookies, connection, and msgid (0) */ - if (HAS_IPSEC_POLICY(policy)) - add_pending(dup_any(whack_sock), st, c, policy, 1 - , predecessor == NULL? SOS_NOBODY : predecessor->st_serialno); + if (HAS_IPSEC_POLICY(policy)) + add_pending(dup_any(whack_sock), st, c, policy, 1 + , predecessor == NULL? SOS_NOBODY : predecessor->st_serialno); - if (predecessor == NULL) - plog("initiating Main Mode"); - else - plog("initiating Main Mode to replace #%lu", predecessor->st_serialno); + if (predecessor == NULL) + plog("initiating Main Mode"); + else + plog("initiating Main Mode to replace #%lu", predecessor->st_serialno); - /* set up reply */ - init_pbs(&reply, reply_buffer, sizeof(reply_buffer), "reply packet"); + /* set up reply */ + init_pbs(&reply, reply_buffer, sizeof(reply_buffer), "reply packet"); - /* HDR out */ - { - struct isakmp_hdr hdr; - - zero(&hdr); /* default to 0 */ - hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION; - hdr.isa_np = ISAKMP_NEXT_SA; - hdr.isa_xchg = ISAKMP_XCHG_IDPROT; - memcpy(hdr.isa_icookie, st->st_icookie, COOKIE_SIZE); - /* R-cookie, flags and MessageID are left zero */ - - if (!out_struct(&hdr, &isakmp_hdr_desc, &reply, &rbody)) + /* HDR out */ { - reset_cur_state(); - return STF_INTERNAL_ERROR; - } - } + struct isakmp_hdr hdr; - /* SA out */ - { - u_char *sa_start = rbody.cur; + zero(&hdr); /* default to 0 */ + hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION; + hdr.isa_np = ISAKMP_NEXT_SA; + hdr.isa_xchg = ISAKMP_XCHG_IDPROT; + memcpy(hdr.isa_icookie, st->st_icookie, COOKIE_SIZE); + /* R-cookie, flags and MessageID are left zero */ - if (!out_sa(&rbody, &oakley_sadb, st, TRUE - , vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE)) - { - reset_cur_state(); - return STF_INTERNAL_ERROR; + if (!out_struct(&hdr, &isakmp_hdr_desc, &reply, &rbody)) + { + reset_cur_state(); + return STF_INTERNAL_ERROR; + } } - /* save initiator SA for later HASH */ - passert(st->st_p1isa.ptr == NULL); /* no leak! (MUST be first time) */ - st->st_p1isa = chunk_create(sa_start, rbody.cur - sa_start); - st->st_p1isa = chunk_clone(st->st_p1isa); - } - - /* if enabled send Pluto Vendor ID */ - if (SEND_PLUTO_VID) - { - if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE - , &rbody, VID_STRONGSWAN)) + /* SA out */ { - reset_cur_state(); - return STF_INTERNAL_ERROR; - } - } + u_char *sa_start = rbody.cur; - /* if enabled send Cisco Unity Vendor ID */ - if (SEND_CISCO_UNITY_VID) - { - if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE - , &rbody, VID_CISCO_UNITY)) + if (!out_sa(&rbody, &oakley_sadb, st, TRUE + , vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE)) + { + reset_cur_state(); + return STF_INTERNAL_ERROR; + } + + /* save initiator SA for later HASH */ + passert(st->st_p1isa.ptr == NULL); /* no leak! (MUST be first time) */ + st->st_p1isa = chunk_create(sa_start, rbody.cur - sa_start); + st->st_p1isa = chunk_clone(st->st_p1isa); + } + + /* if enabled send Pluto Vendor ID */ + if (SEND_PLUTO_VID) { - reset_cur_state(); - return STF_INTERNAL_ERROR; + if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE + , &rbody, VID_STRONGSWAN)) + { + reset_cur_state(); + return STF_INTERNAL_ERROR; + } } - } - /* if we have an OpenPGP certificate we assume an - * OpenPGP peer and have to send the Vendor ID - */ - if (c->spd.this.cert.type == CERT_PGP) - { - if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE - , &rbody, VID_OPENPGP)) + + /* if enabled send Cisco Unity Vendor ID */ + if (SEND_CISCO_UNITY_VID) { - reset_cur_state(); - return STF_INTERNAL_ERROR; + if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE + , &rbody, VID_CISCO_UNITY)) + { + reset_cur_state(); + return STF_INTERNAL_ERROR; + } } - } - - /* Announce our ability to do eXtended AUTHentication to the peer */ - if (SEND_XAUTH_VID) - { - if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE - , &rbody, VID_MISC_XAUTH)) + /* if we have an OpenPGP certificate we assume an + * OpenPGP peer and have to send the Vendor ID + */ + if (c->spd.this.cert.type == CERT_PGP) { - reset_cur_state(); - return STF_INTERNAL_ERROR; + if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE + , &rbody, VID_OPENPGP)) + { + reset_cur_state(); + return STF_INTERNAL_ERROR; + } } - } - /* Announce our ability to do Dead Peer Detection to the peer */ - { - if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE - , &rbody, VID_MISC_DPD)) + /* Announce our ability to do eXtended AUTHentication to the peer */ + if (SEND_XAUTH_VID) { - reset_cur_state(); - return STF_INTERNAL_ERROR; + if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE + , &rbody, VID_MISC_XAUTH)) + { + reset_cur_state(); + return STF_INTERNAL_ERROR; + } } - } - if (nat_traversal_enabled) - { - /* Add supported NAT-Traversal VID */ - if (!nat_traversal_add_vid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE - , &rbody)) + /* Announce our ability to do Dead Peer Detection to the peer */ { - reset_cur_state(); - return STF_INTERNAL_ERROR; + if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE + , &rbody, VID_MISC_DPD)) + { + reset_cur_state(); + return STF_INTERNAL_ERROR; + } } - } - close_message(&rbody); - close_output_pbs(&reply); - st->st_tpacket = chunk_create(reply.start, pbs_offset(&reply)); - st->st_tpacket = chunk_clone(st->st_tpacket); + if (nat_traversal_enabled) + { + /* Add supported NAT-Traversal VID */ + if (!nat_traversal_add_vid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE + , &rbody)) + { + reset_cur_state(); + return STF_INTERNAL_ERROR; + } + } - /* Transmit */ + close_message(&rbody); + close_output_pbs(&reply); + st->st_tpacket = chunk_create(reply.start, pbs_offset(&reply)); + st->st_tpacket = chunk_clone(st->st_tpacket); - send_packet(st, "main_outI1"); + /* Transmit */ - /* Set up a retransmission event, half a minute henceforth */ - delete_event(st); - event_schedule(EVENT_RETRANSMIT, EVENT_RETRANSMIT_DELAY_0, st); + send_packet(st, "main_outI1"); - if (predecessor != NULL) - { - update_pending(predecessor, st); - whack_log(RC_NEW_STATE + STATE_MAIN_I1 - , "%s: initiate, replacing #%lu" - , enum_name(&state_names, st->st_state) - , predecessor->st_serialno); - } - else - { - whack_log(RC_NEW_STATE + STATE_MAIN_I1 - , "%s: initiate", enum_name(&state_names, st->st_state)); - } - reset_cur_state(); - return STF_OK; + /* Set up a retransmission event, half a minute henceforth */ + delete_event(st); + event_schedule(EVENT_RETRANSMIT, EVENT_RETRANSMIT_DELAY_0, st); + + if (predecessor != NULL) + { + update_pending(predecessor, st); + whack_log(RC_NEW_STATE + STATE_MAIN_I1 + , "%s: initiate, replacing #%lu" + , enum_name(&state_names, st->st_state) + , predecessor->st_serialno); + } + else + { + whack_log(RC_NEW_STATE + STATE_MAIN_I1 + , "%s: initiate", enum_name(&state_names, st->st_state)); + } + reset_cur_state(); + return STF_OK; } void @@ -1071,40 +1071,40 @@ ipsecdoi_initiate(int whack_sock , unsigned long try , so_serial_t replacing) { - /* If there's already an ISAKMP SA established, use that and - * go directly to Quick Mode. We are even willing to use one - * that is still being negotiated, but only if we are the Initiator - * (thus we can be sure that the IDs are not going to change; - * other issues around intent might matter). - * Note: there is no way to initiate with a Road Warrior. - */ - struct state *st = find_phase1_state(c - , ISAKMP_SA_ESTABLISHED_STATES | PHASE1_INITIATOR_STATES); + /* If there's already an ISAKMP SA established, use that and + * go directly to Quick Mode. We are even willing to use one + * that is still being negotiated, but only if we are the Initiator + * (thus we can be sure that the IDs are not going to change; + * other issues around intent might matter). + * Note: there is no way to initiate with a Road Warrior. + */ + struct state *st = find_phase1_state(c + , ISAKMP_SA_ESTABLISHED_STATES | PHASE1_INITIATOR_STATES); - if (st == NULL) - { - (void) main_outI1(whack_sock, c, NULL, policy, try); - } - else if (HAS_IPSEC_POLICY(policy)) - { - if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state)) + if (st == NULL) { - /* leave our Phase 2 negotiation pending */ - add_pending(whack_sock, st, c, policy, try, replacing); + (void) main_outI1(whack_sock, c, NULL, policy, try); + } + else if (HAS_IPSEC_POLICY(policy)) + { + if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state)) + { + /* leave our Phase 2 negotiation pending */ + add_pending(whack_sock, st, c, policy, try, replacing); + } + else + { + /* ??? we assume that peer_nexthop_sin isn't important: + * we already have it from when we negotiated the ISAKMP SA! + * It isn't clear what to do with the error return. + */ + (void) quick_outI1(whack_sock, st, c, policy, try, replacing); + } } else { - /* ??? we assume that peer_nexthop_sin isn't important: - * we already have it from when we negotiated the ISAKMP SA! - * It isn't clear what to do with the error return. - */ - (void) quick_outI1(whack_sock, st, c, policy, try, replacing); + close_any(whack_sock); } - } - else - { - close_any(whack_sock); - } } /* Replace SA with a fresh one that is similar @@ -1119,44 +1119,44 @@ ipsecdoi_initiate(int whack_sock void ipsecdoi_replace(struct state *st, unsigned long try) { - int whack_sock = dup_any(st->st_whack_sock); - lset_t policy = st->st_policy; + int whack_sock = dup_any(st->st_whack_sock); + lset_t policy = st->st_policy; - if (IS_PHASE1(st->st_state)) - { - passert(!HAS_IPSEC_POLICY(policy)); - (void) main_outI1(whack_sock, st->st_connection, st, policy, try); - } - else - { - /* Add features of actual old state to policy. This ensures - * that rekeying doesn't downgrade security. I admit that - * this doesn't capture everything. - */ - if (st->st_pfs_group != NULL) - policy |= POLICY_PFS; - if (st->st_ah.present) + if (IS_PHASE1(st->st_state)) { - policy |= POLICY_AUTHENTICATE; - if (st->st_ah.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL) - policy |= POLICY_TUNNEL; + passert(!HAS_IPSEC_POLICY(policy)); + (void) main_outI1(whack_sock, st->st_connection, st, policy, try); } - if (st->st_esp.present && st->st_esp.attrs.transid != ESP_NULL) + else { - policy |= POLICY_ENCRYPT; - if (st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL) - policy |= POLICY_TUNNEL; + /* Add features of actual old state to policy. This ensures + * that rekeying doesn't downgrade security. I admit that + * this doesn't capture everything. + */ + if (st->st_pfs_group != NULL) + policy |= POLICY_PFS; + if (st->st_ah.present) + { + policy |= POLICY_AUTHENTICATE; + if (st->st_ah.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL) + policy |= POLICY_TUNNEL; + } + if (st->st_esp.present && st->st_esp.attrs.transid != ESP_NULL) + { + policy |= POLICY_ENCRYPT; + if (st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL) + policy |= POLICY_TUNNEL; + } + if (st->st_ipcomp.present) + { + policy |= POLICY_COMPRESS; + if (st->st_ipcomp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL) + policy |= POLICY_TUNNEL; + } + passert(HAS_IPSEC_POLICY(policy)); + ipsecdoi_initiate(whack_sock, st->st_connection, policy, try + , st->st_serialno); } - if (st->st_ipcomp.present) - { - policy |= POLICY_COMPRESS; - if (st->st_ipcomp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL) - policy |= POLICY_TUNNEL; - } - passert(HAS_IPSEC_POLICY(policy)); - ipsecdoi_initiate(whack_sock, st->st_connection, policy, try - , st->st_serialno); - } } /* SKEYID for preshared keys. @@ -1165,44 +1165,44 @@ ipsecdoi_replace(struct state *st, unsigned long try) static bool skeyid_preshared(struct state *st) { - const chunk_t *pss = get_preshared_secret(st->st_connection); + const chunk_t *pss = get_preshared_secret(st->st_connection); - if (pss == NULL) - { - loglog(RC_LOG_SERIOUS, "preshared secret disappeared!"); - return FALSE; - } - else - { - struct hmac_ctx ctx; + if (pss == NULL) + { + loglog(RC_LOG_SERIOUS, "preshared secret disappeared!"); + return FALSE; + } + else + { + struct hmac_ctx ctx; - hmac_init_chunk(&ctx, st->st_oakley.hasher, *pss); - hmac_update_chunk(&ctx, st->st_ni); - hmac_update_chunk(&ctx, st->st_nr); - hmac_final_chunk(st->st_skeyid, "st_skeyid in skeyid_preshared()", &ctx); - return TRUE; - } + hmac_init_chunk(&ctx, st->st_oakley.hasher, *pss); + hmac_update_chunk(&ctx, st->st_ni); + hmac_update_chunk(&ctx, st->st_nr); + hmac_final_chunk(st->st_skeyid, "st_skeyid in skeyid_preshared()", &ctx); + return TRUE; + } } static bool skeyid_digisig(struct state *st) { - struct hmac_ctx ctx; - chunk_t nir; + struct hmac_ctx ctx; + chunk_t nir; - /* We need to hmac_init with the concatenation of Ni_b and Nr_b, - * so we have to build a temporary concatentation. - */ - nir.len = st->st_ni.len + st->st_nr.len; - nir.ptr = malloc(nir.len); - memcpy(nir.ptr, st->st_ni.ptr, st->st_ni.len); - memcpy(nir.ptr+st->st_ni.len, st->st_nr.ptr, st->st_nr.len); - hmac_init_chunk(&ctx, st->st_oakley.hasher, nir); - free(nir.ptr); + /* We need to hmac_init with the concatenation of Ni_b and Nr_b, + * so we have to build a temporary concatentation. + */ + nir.len = st->st_ni.len + st->st_nr.len; + nir.ptr = malloc(nir.len); + memcpy(nir.ptr, st->st_ni.ptr, st->st_ni.len); + memcpy(nir.ptr+st->st_ni.len, st->st_nr.ptr, st->st_nr.len); + hmac_init_chunk(&ctx, st->st_oakley.hasher, nir); + free(nir.ptr); - hmac_update_chunk(&ctx, st->st_shared); - hmac_final_chunk(st->st_skeyid, "st_skeyid in skeyid_digisig()", &ctx); - return TRUE; + hmac_update_chunk(&ctx, st->st_shared); + hmac_final_chunk(st->st_skeyid, "st_skeyid in skeyid_digisig()", &ctx); + return TRUE; } /* Generate the SKEYID_* and new IV @@ -1211,128 +1211,128 @@ skeyid_digisig(struct state *st) static bool generate_skeyids_iv(struct state *st) { - /* Generate the SKEYID */ - switch (st->st_oakley.auth) - { - case OAKLEY_PRESHARED_KEY: - case XAUTHInitPreShared: - case XAUTHRespPreShared: - if (!skeyid_preshared(st)) - return FALSE; - break; - - case OAKLEY_RSA_SIG: - case XAUTHInitRSA: - case XAUTHRespRSA: - if (!skeyid_digisig(st)) - return FALSE; - break; - - case OAKLEY_DSS_SIG: - /* XXX */ - - case OAKLEY_RSA_ENC: - case OAKLEY_RSA_ENC_REV: - case OAKLEY_ELGAMAL_ENC: - case OAKLEY_ELGAMAL_ENC_REV: - /* XXX */ - - default: - bad_case(st->st_oakley.auth); - } - - /* generate SKEYID_* from SKEYID */ - { - struct hmac_ctx ctx; - - hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid); - - /* SKEYID_D */ - hmac_update_chunk(&ctx, st->st_shared); - hmac_update(&ctx, st->st_icookie, COOKIE_SIZE); - hmac_update(&ctx, st->st_rcookie, COOKIE_SIZE); - hmac_update(&ctx, "\0", 1); - hmac_final_chunk(st->st_skeyid_d, "st_skeyid_d in generate_skeyids_iv()", &ctx); - - /* SKEYID_A */ - hmac_reinit(&ctx); - hmac_update_chunk(&ctx, st->st_skeyid_d); - hmac_update_chunk(&ctx, st->st_shared); - hmac_update(&ctx, st->st_icookie, COOKIE_SIZE); - hmac_update(&ctx, st->st_rcookie, COOKIE_SIZE); - hmac_update(&ctx, "\1", 1); - hmac_final_chunk(st->st_skeyid_a, "st_skeyid_a in generate_skeyids_iv()", &ctx); - - /* SKEYID_E */ - hmac_reinit(&ctx); - hmac_update_chunk(&ctx, st->st_skeyid_a); - hmac_update_chunk(&ctx, st->st_shared); - hmac_update(&ctx, st->st_icookie, COOKIE_SIZE); - hmac_update(&ctx, st->st_rcookie, COOKIE_SIZE); - hmac_update(&ctx, "\2", 1); - hmac_final_chunk(st->st_skeyid_e, "st_skeyid_e in generate_skeyids_iv()", &ctx); - } - - /* generate IV */ - { - union hash_ctx hash_ctx; - const struct hash_desc *h = st->st_oakley.hasher; - - st->st_new_iv_len = h->hash_digest_size; - passert(st->st_new_iv_len <= sizeof(st->st_new_iv)); - - DBG(DBG_CRYPT, - DBG_dump_chunk("DH_i:", st->st_gi); - DBG_dump_chunk("DH_r:", st->st_gr); - ); - h->hash_init(&hash_ctx); - h->hash_update(&hash_ctx, st->st_gi.ptr, st->st_gi.len); - h->hash_update(&hash_ctx, st->st_gr.ptr, st->st_gr.len); - h->hash_final(st->st_new_iv, &hash_ctx); - } - - /* Oakley Keying Material - * Derived from Skeyid_e: if it is not big enough, generate more - * using the PRF. - * See RFC 2409 "IKE" Appendix B - */ - { - /* const size_t keysize = st->st_oakley.encrypter->keydeflen/BITS_PER_BYTE; */ - const size_t keysize = st->st_oakley.enckeylen/BITS_PER_BYTE; - u_char keytemp[MAX_OAKLEY_KEY_LEN + MAX_DIGEST_LEN]; - u_char *k = st->st_skeyid_e.ptr; - - if (keysize > st->st_skeyid_e.len) + /* Generate the SKEYID */ + switch (st->st_oakley.auth) { - struct hmac_ctx ctx; - size_t i = 0; + case OAKLEY_PRESHARED_KEY: + case XAUTHInitPreShared: + case XAUTHRespPreShared: + if (!skeyid_preshared(st)) + return FALSE; + break; - hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid_e); - hmac_update(&ctx, "\0", 1); - for (;;) - { - hmac_final(&keytemp[i], &ctx); - i += ctx.hmac_digest_size; - if (i >= keysize) - break; - hmac_reinit(&ctx); - hmac_update(&ctx, &keytemp[i - ctx.hmac_digest_size], ctx.hmac_digest_size); - } - k = keytemp; + case OAKLEY_RSA_SIG: + case XAUTHInitRSA: + case XAUTHRespRSA: + if (!skeyid_digisig(st)) + return FALSE; + break; + + case OAKLEY_DSS_SIG: + /* XXX */ + + case OAKLEY_RSA_ENC: + case OAKLEY_RSA_ENC_REV: + case OAKLEY_ELGAMAL_ENC: + case OAKLEY_ELGAMAL_ENC_REV: + /* XXX */ + + default: + bad_case(st->st_oakley.auth); } - free(st->st_enc_key.ptr); - st->st_enc_key = chunk_create(k, keysize); - st->st_enc_key = chunk_clone(st->st_enc_key); - } - DBG(DBG_CRYPT, - DBG_dump_chunk("Skeyid: ", st->st_skeyid); - DBG_dump_chunk("Skeyid_d:", st->st_skeyid_d); - DBG_dump_chunk("Skeyid_a:", st->st_skeyid_a); - DBG_dump_chunk("Skeyid_e:", st->st_skeyid_e); - DBG_dump_chunk("enc key:", st->st_enc_key); - DBG_dump("IV:", st->st_new_iv, st->st_new_iv_len)); - return TRUE; + /* generate SKEYID_* from SKEYID */ + { + struct hmac_ctx ctx; + + hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid); + + /* SKEYID_D */ + hmac_update_chunk(&ctx, st->st_shared); + hmac_update(&ctx, st->st_icookie, COOKIE_SIZE); + hmac_update(&ctx, st->st_rcookie, COOKIE_SIZE); + hmac_update(&ctx, "\0", 1); + hmac_final_chunk(st->st_skeyid_d, "st_skeyid_d in generate_skeyids_iv()", &ctx); + + /* SKEYID_A */ + hmac_reinit(&ctx); + hmac_update_chunk(&ctx, st->st_skeyid_d); + hmac_update_chunk(&ctx, st->st_shared); + hmac_update(&ctx, st->st_icookie, COOKIE_SIZE); + hmac_update(&ctx, st->st_rcookie, COOKIE_SIZE); + hmac_update(&ctx, "\1", 1); + hmac_final_chunk(st->st_skeyid_a, "st_skeyid_a in generate_skeyids_iv()", &ctx); + + /* SKEYID_E */ + hmac_reinit(&ctx); + hmac_update_chunk(&ctx, st->st_skeyid_a); + hmac_update_chunk(&ctx, st->st_shared); + hmac_update(&ctx, st->st_icookie, COOKIE_SIZE); + hmac_update(&ctx, st->st_rcookie, COOKIE_SIZE); + hmac_update(&ctx, "\2", 1); + hmac_final_chunk(st->st_skeyid_e, "st_skeyid_e in generate_skeyids_iv()", &ctx); + } + + /* generate IV */ + { + union hash_ctx hash_ctx; + const struct hash_desc *h = st->st_oakley.hasher; + + st->st_new_iv_len = h->hash_digest_size; + passert(st->st_new_iv_len <= sizeof(st->st_new_iv)); + + DBG(DBG_CRYPT, + DBG_dump_chunk("DH_i:", st->st_gi); + DBG_dump_chunk("DH_r:", st->st_gr); + ); + h->hash_init(&hash_ctx); + h->hash_update(&hash_ctx, st->st_gi.ptr, st->st_gi.len); + h->hash_update(&hash_ctx, st->st_gr.ptr, st->st_gr.len); + h->hash_final(st->st_new_iv, &hash_ctx); + } + + /* Oakley Keying Material + * Derived from Skeyid_e: if it is not big enough, generate more + * using the PRF. + * See RFC 2409 "IKE" Appendix B + */ + { + /* const size_t keysize = st->st_oakley.encrypter->keydeflen/BITS_PER_BYTE; */ + const size_t keysize = st->st_oakley.enckeylen/BITS_PER_BYTE; + u_char keytemp[MAX_OAKLEY_KEY_LEN + MAX_DIGEST_LEN]; + u_char *k = st->st_skeyid_e.ptr; + + if (keysize > st->st_skeyid_e.len) + { + struct hmac_ctx ctx; + size_t i = 0; + + hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid_e); + hmac_update(&ctx, "\0", 1); + for (;;) + { + hmac_final(&keytemp[i], &ctx); + i += ctx.hmac_digest_size; + if (i >= keysize) + break; + hmac_reinit(&ctx); + hmac_update(&ctx, &keytemp[i - ctx.hmac_digest_size], ctx.hmac_digest_size); + } + k = keytemp; + } + free(st->st_enc_key.ptr); + st->st_enc_key = chunk_create(k, keysize); + st->st_enc_key = chunk_clone(st->st_enc_key); + } + + DBG(DBG_CRYPT, + DBG_dump_chunk("Skeyid: ", st->st_skeyid); + DBG_dump_chunk("Skeyid_d:", st->st_skeyid_d); + DBG_dump_chunk("Skeyid_a:", st->st_skeyid_a); + DBG_dump_chunk("Skeyid_e:", st->st_skeyid_e); + DBG_dump_chunk("enc key:", st->st_enc_key); + DBG_dump("IV:", st->st_new_iv, st->st_new_iv_len)); + return TRUE; } /* Generate HASH_I or HASH_R for ISAKMP Phase I. @@ -1351,87 +1351,87 @@ generate_skeyids_iv(struct state *st) typedef void (*hash_update_t)(union hash_ctx *, const u_char *, size_t) ; static void main_mode_hash_body(struct state *st -, bool hashi /* Initiator? */ -, const pb_stream *idpl /* ID payload, as PBS */ +, bool hashi /* Initiator? */ +, const pb_stream *idpl /* ID payload, as PBS */ , union hash_ctx *ctx , void (*hash_update_void)(void *, const u_char *input, size_t)) { #define HASH_UPDATE_T (union hash_ctx *, const u_char *input, unsigned int len) - hash_update_t hash_update=(hash_update_t) hash_update_void; -#if 0 /* if desperate to debug hashing */ + hash_update_t hash_update=(hash_update_t) hash_update_void; +#if 0 /* if desperate to debug hashing */ # define hash_update(ctx, input, len) { \ - DBG_dump("hash input", input, len); \ - (hash_update)(ctx, input, len); \ - } + DBG_dump("hash input", input, len); \ + (hash_update)(ctx, input, len); \ + } #endif # define hash_update_chunk(ctx, ch) hash_update((ctx), (ch).ptr, (ch).len) - if (hashi) - { - hash_update_chunk(ctx, st->st_gi); - hash_update_chunk(ctx, st->st_gr); - hash_update(ctx, st->st_icookie, COOKIE_SIZE); - hash_update(ctx, st->st_rcookie, COOKIE_SIZE); - } - else - { - hash_update_chunk(ctx, st->st_gr); - hash_update_chunk(ctx, st->st_gi); - hash_update(ctx, st->st_rcookie, COOKIE_SIZE); - hash_update(ctx, st->st_icookie, COOKIE_SIZE); - } + if (hashi) + { + hash_update_chunk(ctx, st->st_gi); + hash_update_chunk(ctx, st->st_gr); + hash_update(ctx, st->st_icookie, COOKIE_SIZE); + hash_update(ctx, st->st_rcookie, COOKIE_SIZE); + } + else + { + hash_update_chunk(ctx, st->st_gr); + hash_update_chunk(ctx, st->st_gi); + hash_update(ctx, st->st_rcookie, COOKIE_SIZE); + hash_update(ctx, st->st_icookie, COOKIE_SIZE); + } - DBG(DBG_CRYPT, DBG_log("hashing %lu bytes of SA" - , (unsigned long) (st->st_p1isa.len - sizeof(struct isakmp_generic)))); + DBG(DBG_CRYPT, DBG_log("hashing %lu bytes of SA" + , (unsigned long) (st->st_p1isa.len - sizeof(struct isakmp_generic)))); - /* SA_b */ - hash_update(ctx, st->st_p1isa.ptr + sizeof(struct isakmp_generic) - , st->st_p1isa.len - sizeof(struct isakmp_generic)); + /* SA_b */ + hash_update(ctx, st->st_p1isa.ptr + sizeof(struct isakmp_generic) + , st->st_p1isa.len - sizeof(struct isakmp_generic)); - /* Hash identification payload, without generic payload header. - * We used to reconstruct ID Payload for this purpose, but now - * we use the bytes as they appear on the wire to avoid - * "spelling problems". - */ - hash_update(ctx - , idpl->start + sizeof(struct isakmp_generic) - , pbs_offset(idpl) - sizeof(struct isakmp_generic)); + /* Hash identification payload, without generic payload header. + * We used to reconstruct ID Payload for this purpose, but now + * we use the bytes as they appear on the wire to avoid + * "spelling problems". + */ + hash_update(ctx + , idpl->start + sizeof(struct isakmp_generic) + , pbs_offset(idpl) - sizeof(struct isakmp_generic)); # undef hash_update_chunk # undef hash_update } -static size_t /* length of hash */ +static size_t /* length of hash */ main_mode_hash(struct state *st -, u_char *hash_val /* resulting bytes */ -, bool hashi /* Initiator? */ -, const pb_stream *idpl) /* ID payload, as PBS; cur must be at end */ +, u_char *hash_val /* resulting bytes */ +, bool hashi /* Initiator? */ +, const pb_stream *idpl) /* ID payload, as PBS; cur must be at end */ { - struct hmac_ctx ctx; + struct hmac_ctx ctx; - hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid); - main_mode_hash_body(st, hashi, idpl, &ctx.hash_ctx, ctx.h->hash_update); - hmac_final(hash_val, &ctx); - return ctx.hmac_digest_size; + hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid); + main_mode_hash_body(st, hashi, idpl, &ctx.hash_ctx, ctx.h->hash_update); + hmac_final(hash_val, &ctx); + return ctx.hmac_digest_size; } -#if 0 /* only needed for DSS */ +#if 0 /* only needed for DSS */ static void main_mode_sha1(struct state *st -, u_char *hash_val /* resulting bytes */ -, size_t *hash_len /* length of hash */ -, bool hashi /* Initiator? */ -, const pb_stream *idpl) /* ID payload, as PBS */ +, u_char *hash_val /* resulting bytes */ +, size_t *hash_len /* length of hash */ +, bool hashi /* Initiator? */ +, const pb_stream *idpl) /* ID payload, as PBS */ { - union hash_ctx ctx; + union hash_ctx ctx; - SHA1Init(&ctx.ctx_sha1); - SHA1Update(&ctx.ctx_sha1, st->st_skeyid.ptr, st->st_skeyid.len); - *hash_len = SHA1_DIGEST_SIZE; - main_mode_hash_body(st, hashi, idpl, &ctx - , (void (*)(union hash_ctx *, const u_char *, unsigned int))&SHA1Update); - SHA1Final(hash_val, &ctx.ctx_sha1); + SHA1Init(&ctx.ctx_sha1); + SHA1Update(&ctx.ctx_sha1, st->st_skeyid.ptr, st->st_skeyid.len); + *hash_len = SHA1_DIGEST_SIZE; + main_mode_hash_body(st, hashi, idpl, &ctx + , (void (*)(union hash_ctx *, const u_char *, unsigned int))&SHA1Update); + SHA1Final(hash_val, &ctx.ctx_sha1); } #endif @@ -1445,49 +1445,49 @@ RSA_sign_hash(struct connection *c , u_char sig_val[RSA_MAX_OCTETS] , const u_char *hash_val, size_t hash_len) { - size_t sz = 0; - smartcard_t *sc = c->spd.this.sc; + size_t sz = 0; + smartcard_t *sc = c->spd.this.sc; - if (sc == NULL) /* no smartcard */ - { - const struct RSA_private_key *k = get_RSA_private_key(c); - - if (k == NULL) - return 0; /* failure: no key to use */ - - sz = k->pub.k; - passert(RSA_MIN_OCTETS <= sz && 4 + hash_len < sz && sz <= RSA_MAX_OCTETS); - sign_hash(k, hash_val, hash_len, sig_val, sz); - } - else if (sc->valid) /* if valid pin then sign hash on the smartcard */ - { - lock_certs_and_keys("RSA_sign_hash"); - if (!scx_establish_context(sc) || !scx_login(sc)) + if (sc == NULL) /* no smartcard */ { - scx_release_context(sc); - unlock_certs_and_keys("RSA_sign_hash"); - return 0; - } + const struct RSA_private_key *k = get_RSA_private_key(c); - sz = scx_get_keylength(sc); - if (sz == 0) + if (k == NULL) + return 0; /* failure: no key to use */ + + sz = k->pub.k; + passert(RSA_MIN_OCTETS <= sz && 4 + hash_len < sz && sz <= RSA_MAX_OCTETS); + sign_hash(k, hash_val, hash_len, sig_val, sz); + } + else if (sc->valid) /* if valid pin then sign hash on the smartcard */ { - plog("failed to get keylength from smartcard"); - scx_release_context(sc); - unlock_certs_and_keys("RSA_sign_hash"); - return 0; - } + lock_certs_and_keys("RSA_sign_hash"); + if (!scx_establish_context(sc) || !scx_login(sc)) + { + scx_release_context(sc); + unlock_certs_and_keys("RSA_sign_hash"); + return 0; + } - DBG(DBG_CONTROL | DBG_CRYPT, - DBG_log("signing hash with RSA key from smartcard (slot: %d, id: %s)" - , (int)sc->slot, sc->id) - ) - sz = scx_sign_hash(sc, hash_val, hash_len, sig_val, sz) ? sz : 0; - if (!pkcs11_keep_state) - scx_release_context(sc); - unlock_certs_and_keys("RSA_sign_hash"); - } - return sz; + sz = scx_get_keylength(sc); + if (sz == 0) + { + plog("failed to get keylength from smartcard"); + scx_release_context(sc); + unlock_certs_and_keys("RSA_sign_hash"); + return 0; + } + + DBG(DBG_CONTROL | DBG_CRYPT, + DBG_log("signing hash with RSA key from smartcard (slot: %d, id: %s)" + , (int)sc->slot, sc->id) + ) + sz = scx_sign_hash(sc, hash_val, hash_len, sig_val, sz) ? sz : 0; + if (!pkcs11_keep_state) + scx_release_context(sc); + unlock_certs_and_keys("RSA_sign_hash"); + } + return sz; } /* Check a Main Mode RSA Signature against computed hash using RSA public key k. @@ -1504,10 +1504,10 @@ RSA_sign_hash(struct connection *c * greater progress. * * Classes: - * 0 reserved for caller - * 1 SIG length doesn't match key length -- wrong key - * 2-8 malformed ECB after decryption -- probably wrong key - * 9 decrypted hash != computed hash -- probably correct key + * 0 reserved for caller + * 1 SIG length doesn't match key length -- wrong key + * 2-8 malformed ECB after decryption -- probably wrong key + * 9 decrypted hash != computed hash -- probably correct key * * Although the math should be the same for generating and checking signatures, * it is not: the knowledge of the private key allows more efficient (i.e. @@ -1518,108 +1518,108 @@ try_RSA_signature(const u_char hash_val[MAX_DIGEST_LEN], size_t hash_len , const pb_stream *sig_pbs, pubkey_t *kr , struct state *st) { - const u_char *sig_val = sig_pbs->cur; - size_t sig_len = pbs_left(sig_pbs); - u_char s[RSA_MAX_OCTETS]; /* for decrypted sig_val */ - u_char *hash_in_s = &s[sig_len - hash_len]; - const struct RSA_public_key *k = &kr->u.rsa; + const u_char *sig_val = sig_pbs->cur; + size_t sig_len = pbs_left(sig_pbs); + u_char s[RSA_MAX_OCTETS]; /* for decrypted sig_val */ + u_char *hash_in_s = &s[sig_len - hash_len]; + const struct RSA_public_key *k = &kr->u.rsa; - /* decrypt the signature -- reversing RSA_sign_hash */ - if (sig_len != k->k) - { - /* XXX notification: INVALID_KEY_INFORMATION */ - return "1" "SIG length does not match public key length"; - } - - /* actual exponentiation; see PKCS#1 v2.0 5.1 */ - { - chunk_t temp_s; - mpz_t c; - - n_to_mpz(c, sig_val, sig_len); - mpz_powm(c, c, &k->e, &k->n); - - temp_s = mpz_to_n(c, sig_len); /* back to octets */ - memcpy(s, temp_s.ptr, sig_len); - free(temp_s.ptr); - mpz_clear(c); - } - - /* sanity check on signature: see if it matches - * PKCS#1 v1.5 8.1 encryption-block formatting - */ - { - err_t ugh = NULL; - - if (s[0] != 0x00) - ugh = "2" "no leading 00"; - else if (hash_in_s[-1] != 0x00) - ugh = "3" "00 separator not present"; - else if (s[1] == 0x01) + /* decrypt the signature -- reversing RSA_sign_hash */ + if (sig_len != k->k) { - const u_char *p; - - for (p = &s[2]; p != hash_in_s - 1; p++) - { - if (*p != 0xFF) - { - ugh = "4" "invalid Padding String"; - break; - } - } + /* XXX notification: INVALID_KEY_INFORMATION */ + return "1" "SIG length does not match public key length"; } - else if (s[1] == 0x02) + + /* actual exponentiation; see PKCS#1 v2.0 5.1 */ { - const u_char *p; + chunk_t temp_s; + mpz_t c; - for (p = &s[2]; p != hash_in_s - 1; p++) - { - if (*p == 0x00) - { - ugh = "5" "invalid Padding String"; - break; - } - } + n_to_mpz(c, sig_val, sig_len); + mpz_powm(c, c, &k->e, &k->n); + + temp_s = mpz_to_n(c, sig_len); /* back to octets */ + memcpy(s, temp_s.ptr, sig_len); + free(temp_s.ptr); + mpz_clear(c); } - else - ugh = "6" "Block Type not 01 or 02"; - if (ugh != NULL) - { - /* note: it might be a good idea to make sure that - * an observer cannot tell what kind of failure happened. - * I don't know what this means in practice. - */ - /* We probably selected the wrong public key for peer: - * SIG Payload decrypted into malformed ECB - */ - /* XXX notification: INVALID_KEY_INFORMATION */ - return ugh; - } - } - - /* We have the decoded hash: see if it matches. */ - if (memcmp(hash_val, hash_in_s, hash_len) != 0) - { - /* good: header, hash, signature, and other payloads well-formed - * good: we could find an RSA Sig key for the peer. - * bad: hash doesn't match - * Guess: sides disagree about key to be used. + /* sanity check on signature: see if it matches + * PKCS#1 v1.5 8.1 encryption-block formatting */ - DBG_cond_dump(DBG_CRYPT, "decrypted SIG", s, sig_len); - DBG_cond_dump(DBG_CRYPT, "computed HASH", hash_val, hash_len); - /* XXX notification: INVALID_HASH_INFORMATION */ - return "9" "authentication failure: received SIG does not match computed HASH, but message is well-formed"; - } + { + err_t ugh = NULL; - /* Success: copy successful key into state. - * There might be an old one if we previously aborted this - * state transition. - */ - unreference_key(&st->st_peer_pubkey); - st->st_peer_pubkey = reference_key(kr); + if (s[0] != 0x00) + ugh = "2" "no leading 00"; + else if (hash_in_s[-1] != 0x00) + ugh = "3" "00 separator not present"; + else if (s[1] == 0x01) + { + const u_char *p; - return NULL; /* happy happy */ + for (p = &s[2]; p != hash_in_s - 1; p++) + { + if (*p != 0xFF) + { + ugh = "4" "invalid Padding String"; + break; + } + } + } + else if (s[1] == 0x02) + { + const u_char *p; + + for (p = &s[2]; p != hash_in_s - 1; p++) + { + if (*p == 0x00) + { + ugh = "5" "invalid Padding String"; + break; + } + } + } + else + ugh = "6" "Block Type not 01 or 02"; + + if (ugh != NULL) + { + /* note: it might be a good idea to make sure that + * an observer cannot tell what kind of failure happened. + * I don't know what this means in practice. + */ + /* We probably selected the wrong public key for peer: + * SIG Payload decrypted into malformed ECB + */ + /* XXX notification: INVALID_KEY_INFORMATION */ + return ugh; + } + } + + /* We have the decoded hash: see if it matches. */ + if (memcmp(hash_val, hash_in_s, hash_len) != 0) + { + /* good: header, hash, signature, and other payloads well-formed + * good: we could find an RSA Sig key for the peer. + * bad: hash doesn't match + * Guess: sides disagree about key to be used. + */ + DBG_cond_dump(DBG_CRYPT, "decrypted SIG", s, sig_len); + DBG_cond_dump(DBG_CRYPT, "computed HASH", hash_val, hash_len); + /* XXX notification: INVALID_HASH_INFORMATION */ + return "9" "authentication failure: received SIG does not match computed HASH, but message is well-formed"; + } + + /* Success: copy successful key into state. + * There might be an old one if we previously aborted this + * state transition. + */ + unreference_key(&st->st_peer_pubkey); + st->st_peer_pubkey = reference_key(kr); + + return NULL; /* happy happy */ } /* Check signature against all RSA public keys we can find. @@ -1633,17 +1633,17 @@ try_RSA_signature(const u_char hash_val[MAX_DIGEST_LEN], size_t hash_len * If only we had coroutines. */ struct tac_state { - /* RSA_check_signature's args that take_a_crack needs */ - struct state *st; - const u_char *hash_val; - size_t hash_len; - const pb_stream *sig_pbs; + /* RSA_check_signature's args that take_a_crack needs */ + struct state *st; + const u_char *hash_val; + size_t hash_len; + const pb_stream *sig_pbs; - /* state carried between calls */ - err_t best_ugh; /* most successful failure */ - int tried_cnt; /* number of keys tried */ - char tried[50]; /* keyids of tried public keys */ - char *tn; /* roof of tried[] */ + /* state carried between calls */ + err_t best_ugh; /* most successful failure */ + int tried_cnt; /* number of keys tried */ + char tried[50]; /* keyids of tried public keys */ + char *tn; /* roof of tried[] */ }; static bool @@ -1651,34 +1651,34 @@ take_a_crack(struct tac_state *s , pubkey_t *kr , const char *story USED_BY_DEBUG) { - err_t ugh = try_RSA_signature(s->hash_val, s->hash_len, s->sig_pbs - , kr, s->st); - const struct RSA_public_key *k = &kr->u.rsa; + err_t ugh = try_RSA_signature(s->hash_val, s->hash_len, s->sig_pbs + , kr, s->st); + const struct RSA_public_key *k = &kr->u.rsa; - s->tried_cnt++; - if (ugh == NULL) - { - DBG(DBG_CRYPT | DBG_CONTROL - , DBG_log("an RSA Sig check passed with *%s [%s]" - , k->keyid, story)); - return TRUE; - } - else - { - DBG(DBG_CRYPT - , DBG_log("an RSA Sig check failure %s with *%s [%s]" - , ugh + 1, k->keyid, story)); - if (s->best_ugh == NULL || s->best_ugh[0] < ugh[0]) - s->best_ugh = ugh; - if (ugh[0] > '0' - && s->tn - s->tried + KEYID_BUF + 2 < (ptrdiff_t)sizeof(s->tried)) + s->tried_cnt++; + if (ugh == NULL) { - strcpy(s->tn, " *"); - strcpy(s->tn + 2, k->keyid); - s->tn += strlen(s->tn); + DBG(DBG_CRYPT | DBG_CONTROL + , DBG_log("an RSA Sig check passed with *%s [%s]" + , k->keyid, story)); + return TRUE; + } + else + { + DBG(DBG_CRYPT + , DBG_log("an RSA Sig check failure %s with *%s [%s]" + , ugh + 1, k->keyid, story)); + if (s->best_ugh == NULL || s->best_ugh[0] < ugh[0]) + s->best_ugh = ugh; + if (ugh[0] > '0' + && s->tn - s->tried + KEYID_BUF + 2 < (ptrdiff_t)sizeof(s->tried)) + { + strcpy(s->tn, " *"); + strcpy(s->tn + 2, k->keyid); + s->tn += strlen(s->tn); + } + return FALSE; } - return FALSE; - } } static stf_status @@ -1693,169 +1693,169 @@ RSA_check_signature(const struct id* peer , const struct gw_info *gateways_from_dns ) { - const struct connection *c = st->st_connection; - struct tac_state s; - err_t dns_ugh = NULL; + const struct connection *c = st->st_connection; + struct tac_state s; + err_t dns_ugh = NULL; - s.st = st; - s.hash_val = hash_val; - s.hash_len = hash_len; - s.sig_pbs = sig_pbs; + s.st = st; + s.hash_val = hash_val; + s.hash_len = hash_len; + s.sig_pbs = sig_pbs; - s.best_ugh = NULL; - s.tried_cnt = 0; - s.tn = s.tried; + s.best_ugh = NULL; + s.tried_cnt = 0; + s.tn = s.tried; - /* try all gateway records hung off c */ - if (c->policy & POLICY_OPPO) - { - struct gw_info *gw; - - for (gw = c->gw_info; gw != NULL; gw = gw->next) + /* try all gateway records hung off c */ + if (c->policy & POLICY_OPPO) { - /* only consider entries that have a key and are for our peer */ - if (gw->gw_key_present - && same_id(&gw->gw_id, &c->spd.that.id) - && take_a_crack(&s, gw->key, "key saved from DNS TXT")) - return STF_OK; - } - } + struct gw_info *gw; - /* try all appropriate Public keys */ - { - pubkey_list_t *p, **pp; - - pp = &pubkeys; - - for (p = pubkeys; p != NULL; p = *pp) - { - pubkey_t *key = p->key; - - if (key->alg == PUBKEY_ALG_RSA && same_id(peer, &key->id)) - { - time_t now = time(NULL); - - /* check if found public key has expired */ - if (key->until_time != UNDEFINED_TIME && key->until_time < now) + for (gw = c->gw_info; gw != NULL; gw = gw->next) { - loglog(RC_LOG_SERIOUS, - "cached RSA public key has expired and has been deleted"); - *pp = free_public_keyentry(p); - continue; /* continue with next public key */ + /* only consider entries that have a key and are for our peer */ + if (gw->gw_key_present + && same_id(&gw->gw_id, &c->spd.that.id) + && take_a_crack(&s, gw->key, "key saved from DNS TXT")) + return STF_OK; } - - if (take_a_crack(&s, key, "preloaded key")) - return STF_OK; - } - pp = &p->next; } + + /* try all appropriate Public keys */ + { + pubkey_list_t *p, **pp; + + pp = &pubkeys; + + for (p = pubkeys; p != NULL; p = *pp) + { + pubkey_t *key = p->key; + + if (key->alg == PUBKEY_ALG_RSA && same_id(peer, &key->id)) + { + time_t now = time(NULL); + + /* check if found public key has expired */ + if (key->until_time != UNDEFINED_TIME && key->until_time < now) + { + loglog(RC_LOG_SERIOUS, + "cached RSA public key has expired and has been deleted"); + *pp = free_public_keyentry(p); + continue; /* continue with next public key */ + } + + if (take_a_crack(&s, key, "preloaded key")) + return STF_OK; + } + pp = &p->next; + } } - /* if no key was found (evidenced by best_ugh == NULL) - * and that side of connection is key_from_DNS_on_demand - * then go search DNS for keys for peer. - */ - if (s.best_ugh == NULL && c->spd.that.key_from_DNS_on_demand) - { - if (gateways_from_dns != NULL) + /* if no key was found (evidenced by best_ugh == NULL) + * and that side of connection is key_from_DNS_on_demand + * then go search DNS for keys for peer. + */ + if (s.best_ugh == NULL && c->spd.that.key_from_DNS_on_demand) { - /* TXT keys */ - const struct gw_info *gwp; + if (gateways_from_dns != NULL) + { + /* TXT keys */ + const struct gw_info *gwp; - for (gwp = gateways_from_dns; gwp != NULL; gwp = gwp->next) - if (gwp->gw_key_present - && take_a_crack(&s, gwp->key, "key from DNS TXT")) - return STF_OK; - } + for (gwp = gateways_from_dns; gwp != NULL; gwp = gwp->next) + if (gwp->gw_key_present + && take_a_crack(&s, gwp->key, "key from DNS TXT")) + return STF_OK; + } #ifdef USE_KEYRR - else if (keys_from_dns != NULL) - { - /* KEY keys */ - const pubkey_list_t *kr; + else if (keys_from_dns != NULL) + { + /* KEY keys */ + const pubkey_list_t *kr; - for (kr = keys_from_dns; kr != NULL; kr = kr->next) - if (kr->key->alg == PUBKEY_ALG_RSA - && take_a_crack(&s, kr->key, "key from DNS KEY")) - return STF_OK; - } + for (kr = keys_from_dns; kr != NULL; kr = kr->next) + if (kr->key->alg == PUBKEY_ALG_RSA + && take_a_crack(&s, kr->key, "key from DNS KEY")) + return STF_OK; + } #endif /* USE_KEYRR */ - else - { - /* nothing yet: ask for asynch DNS lookup */ - return STF_SUSPEND; - } - } - - /* no acceptable key was found: diagnose */ - { - char id_buf[BUF_LEN]; /* arbitrary limit on length of ID reported */ - - (void) idtoa(peer, id_buf, sizeof(id_buf)); - - if (s.best_ugh == NULL) - { - if (dns_ugh == NULL) - loglog(RC_LOG_SERIOUS, "no RSA public key known for '%s'" - , id_buf); - else - loglog(RC_LOG_SERIOUS, "no RSA public key known for '%s'" - "; DNS search for KEY failed (%s)" - , id_buf, dns_ugh); - - /* ??? is this the best code there is? */ - return STF_FAIL + INVALID_KEY_INFORMATION; + else + { + /* nothing yet: ask for asynch DNS lookup */ + return STF_SUSPEND; + } } - if (s.best_ugh[0] == '9') + /* no acceptable key was found: diagnose */ { - loglog(RC_LOG_SERIOUS, "%s", s.best_ugh + 1); - /* XXX Could send notification back */ - return STF_FAIL + INVALID_HASH_INFORMATION; + char id_buf[BUF_LEN]; /* arbitrary limit on length of ID reported */ + + (void) idtoa(peer, id_buf, sizeof(id_buf)); + + if (s.best_ugh == NULL) + { + if (dns_ugh == NULL) + loglog(RC_LOG_SERIOUS, "no RSA public key known for '%s'" + , id_buf); + else + loglog(RC_LOG_SERIOUS, "no RSA public key known for '%s'" + "; DNS search for KEY failed (%s)" + , id_buf, dns_ugh); + + /* ??? is this the best code there is? */ + return STF_FAIL + INVALID_KEY_INFORMATION; + } + + if (s.best_ugh[0] == '9') + { + loglog(RC_LOG_SERIOUS, "%s", s.best_ugh + 1); + /* XXX Could send notification back */ + return STF_FAIL + INVALID_HASH_INFORMATION; + } + else + { + if (s.tried_cnt == 1) + { + loglog(RC_LOG_SERIOUS + , "Signature check (on %s) failed (wrong key?); tried%s" + , id_buf, s.tried); + DBG(DBG_CONTROL, + DBG_log("public key for %s failed:" + " decrypted SIG payload into a malformed ECB (%s)" + , id_buf, s.best_ugh + 1)); + } + else + { + loglog(RC_LOG_SERIOUS + , "Signature check (on %s) failed:" + " tried%s keys but none worked." + , id_buf, s.tried); + DBG(DBG_CONTROL, + DBG_log("all %d public keys for %s failed:" + " best decrypted SIG payload into a malformed ECB (%s)" + , s.tried_cnt, id_buf, s.best_ugh + 1)); + } + return STF_FAIL + INVALID_KEY_INFORMATION; + } } - else - { - if (s.tried_cnt == 1) - { - loglog(RC_LOG_SERIOUS - , "Signature check (on %s) failed (wrong key?); tried%s" - , id_buf, s.tried); - DBG(DBG_CONTROL, - DBG_log("public key for %s failed:" - " decrypted SIG payload into a malformed ECB (%s)" - , id_buf, s.best_ugh + 1)); - } - else - { - loglog(RC_LOG_SERIOUS - , "Signature check (on %s) failed:" - " tried%s keys but none worked." - , id_buf, s.tried); - DBG(DBG_CONTROL, - DBG_log("all %d public keys for %s failed:" - " best decrypted SIG payload into a malformed ECB (%s)" - , s.tried_cnt, id_buf, s.best_ugh + 1)); - } - return STF_FAIL + INVALID_KEY_INFORMATION; - } - } } static notification_t accept_nonce(struct msg_digest *md, chunk_t *dest, const char *name) { - pb_stream *nonce_pbs = &md->chain[ISAKMP_NEXT_NONCE]->pbs; - size_t len = pbs_left(nonce_pbs); + pb_stream *nonce_pbs = &md->chain[ISAKMP_NEXT_NONCE]->pbs; + size_t len = pbs_left(nonce_pbs); - if (len < MINIMUM_NONCE_SIZE || MAXIMUM_NONCE_SIZE < len) - { - loglog(RC_LOG_SERIOUS, "%s length not between %d and %d" - , name , MINIMUM_NONCE_SIZE, MAXIMUM_NONCE_SIZE); - return PAYLOAD_MALFORMED; /* ??? */ - } - free(dest->ptr); - *dest = chunk_create(nonce_pbs->cur, len); - *dest = chunk_clone(*dest); - return NOTHING_WRONG; + if (len < MINIMUM_NONCE_SIZE || MAXIMUM_NONCE_SIZE < len) + { + loglog(RC_LOG_SERIOUS, "%s length not between %d and %d" + , name , MINIMUM_NONCE_SIZE, MAXIMUM_NONCE_SIZE); + return PAYLOAD_MALFORMED; /* ??? */ + } + free(dest->ptr); + *dest = chunk_create(nonce_pbs->cur, len); + *dest = chunk_clone(*dest); + return NOTHING_WRONG; } /* encrypt message, sans fixed part of header @@ -1866,36 +1866,36 @@ accept_nonce(struct msg_digest *md, chunk_t *dest, const char *name) bool encrypt_message(pb_stream *pbs, struct state *st) { - const struct encrypt_desc *e = st->st_oakley.encrypter; - u_int8_t *enc_start = pbs->start + sizeof(struct isakmp_hdr); - size_t enc_len = pbs_offset(pbs) - sizeof(struct isakmp_hdr); + const struct encrypt_desc *e = st->st_oakley.encrypter; + u_int8_t *enc_start = pbs->start + sizeof(struct isakmp_hdr); + size_t enc_len = pbs_offset(pbs) - sizeof(struct isakmp_hdr); - DBG_cond_dump(DBG_CRYPT | DBG_RAW, "encrypting:\n", enc_start, enc_len); + DBG_cond_dump(DBG_CRYPT | DBG_RAW, "encrypting:\n", enc_start, enc_len); - /* Pad up to multiple of encryption blocksize. - * See the description associated with the definition of - * struct isakmp_hdr in packet.h. - */ - { - size_t padding = pad_up(enc_len, e->enc_blocksize); - - if (padding != 0) + /* Pad up to multiple of encryption blocksize. + * See the description associated with the definition of + * struct isakmp_hdr in packet.h. + */ { - if (!out_zero(padding, pbs, "encryption padding")) - return FALSE; - enc_len += padding; + size_t padding = pad_up(enc_len, e->enc_blocksize); + + if (padding != 0) + { + if (!out_zero(padding, pbs, "encryption padding")) + return FALSE; + enc_len += padding; + } } - } - DBG(DBG_CRYPT, DBG_log("encrypting using %s", enum_show(&oakley_enc_names, st->st_oakley.encrypt))); + DBG(DBG_CRYPT, DBG_log("encrypting using %s", enum_show(&oakley_enc_names, st->st_oakley.encrypt))); - /* e->crypt(TRUE, enc_start, enc_len, st); */ - crypto_cbc_encrypt(e, TRUE, enc_start, enc_len, st); + /* e->crypt(TRUE, enc_start, enc_len, st); */ + crypto_cbc_encrypt(e, TRUE, enc_start, enc_len, st); - update_iv(st); - DBG_cond_dump(DBG_CRYPT, "next IV:", st->st_iv, st->st_iv_len); - close_message(pbs); - return TRUE; + update_iv(st); + DBG_cond_dump(DBG_CRYPT, "next IV:", st->st_iv, st->st_iv_len); + close_message(pbs); + return TRUE; } /* Compute HASH(1), HASH(2) of Quick Mode. @@ -1908,26 +1908,26 @@ static size_t quick_mode_hash12(u_char *dest, const u_char *start, const u_char *roof , const struct state *st, const msgid_t *msgid, bool hash2) { - struct hmac_ctx ctx; + struct hmac_ctx ctx; -#if 0 /* if desperate to debug hashing */ +#if 0 /* if desperate to debug hashing */ # define hmac_update(ctx, ptr, len) { \ - DBG_dump("hash input", (ptr), (len)); \ - (hmac_update)((ctx), (ptr), (len)); \ - } - DBG_dump("hash key", st->st_skeyid_a.ptr, st->st_skeyid_a.len); + DBG_dump("hash input", (ptr), (len)); \ + (hmac_update)((ctx), (ptr), (len)); \ + } + DBG_dump("hash key", st->st_skeyid_a.ptr, st->st_skeyid_a.len); #endif - hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid_a); - hmac_update(&ctx, (const void *) msgid, sizeof(msgid_t)); - if (hash2) - hmac_update_chunk(&ctx, st->st_ni); /* include Ni_b in the hash */ - hmac_update(&ctx, start, roof-start); - hmac_final(dest, &ctx); + hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid_a); + hmac_update(&ctx, (const void *) msgid, sizeof(msgid_t)); + if (hash2) + hmac_update_chunk(&ctx, st->st_ni); /* include Ni_b in the hash */ + hmac_update(&ctx, start, roof-start); + hmac_final(dest, &ctx); - DBG(DBG_CRYPT, - DBG_log("HASH(%d) computed:", hash2 + 1); - DBG_dump("", dest, ctx.hmac_digest_size)); - return ctx.hmac_digest_size; + DBG(DBG_CRYPT, + DBG_log("HASH(%d) computed:", hash2 + 1); + DBG_dump("", dest, ctx.hmac_digest_size)); + return ctx.hmac_digest_size; # undef hmac_update } @@ -1940,16 +1940,16 @@ quick_mode_hash12(u_char *dest, const u_char *start, const u_char *roof static size_t quick_mode_hash3(u_char *dest, struct state *st) { - struct hmac_ctx ctx; + struct hmac_ctx ctx; - hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid_a); - hmac_update(&ctx, "\0", 1); - hmac_update(&ctx, (u_char *) &st->st_msgid, sizeof(st->st_msgid)); - hmac_update_chunk(&ctx, st->st_ni); - hmac_update_chunk(&ctx, st->st_nr); - hmac_final(dest, &ctx); - DBG_cond_dump(DBG_CRYPT, "HASH(3) computed:", dest, ctx.hmac_digest_size); - return ctx.hmac_digest_size; + hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid_a); + hmac_update(&ctx, "\0", 1); + hmac_update(&ctx, (u_char *) &st->st_msgid, sizeof(st->st_msgid)); + hmac_update_chunk(&ctx, st->st_ni); + hmac_update_chunk(&ctx, st->st_nr); + hmac_final(dest, &ctx); + DBG_cond_dump(DBG_CRYPT, "HASH(3) computed:", dest, ctx.hmac_digest_size); + return ctx.hmac_digest_size; } /* Compute Phase 2 IV. @@ -1958,23 +1958,23 @@ quick_mode_hash3(u_char *dest, struct state *st) void init_phase2_iv(struct state *st, const msgid_t *msgid) { - const struct hash_desc *h = st->st_oakley.hasher; - union hash_ctx ctx; + const struct hash_desc *h = st->st_oakley.hasher; + union hash_ctx ctx; - DBG_cond_dump(DBG_CRYPT, "last Phase 1 IV:" - , st->st_ph1_iv, st->st_ph1_iv_len); + DBG_cond_dump(DBG_CRYPT, "last Phase 1 IV:" + , st->st_ph1_iv, st->st_ph1_iv_len); - st->st_new_iv_len = h->hash_digest_size; - passert(st->st_new_iv_len <= sizeof(st->st_new_iv)); + st->st_new_iv_len = h->hash_digest_size; + passert(st->st_new_iv_len <= sizeof(st->st_new_iv)); - h->hash_init(&ctx); - h->hash_update(&ctx, st->st_ph1_iv, st->st_ph1_iv_len); - passert(*msgid != 0); - h->hash_update(&ctx, (const u_char *)msgid, sizeof(*msgid)); - h->hash_final(st->st_new_iv, &ctx); + h->hash_init(&ctx); + h->hash_update(&ctx, st->st_ph1_iv, st->st_ph1_iv_len); + passert(*msgid != 0); + h->hash_update(&ctx, (const u_char *)msgid, sizeof(*msgid)); + h->hash_final(st->st_new_iv, &ctx); - DBG_cond_dump(DBG_CRYPT, "computed Phase 2 IV:" - , st->st_new_iv, st->st_new_iv_len); + DBG_cond_dump(DBG_CRYPT, "computed Phase 2 IV:" + , st->st_new_iv, st->st_new_iv_len); } /* Initiate quick mode. @@ -1987,37 +1987,37 @@ static bool emit_subnet_id(ip_subnet *net , u_int8_t np, u_int8_t protoid, u_int16_t port, pb_stream *outs) { - struct isakmp_ipsec_id id; - pb_stream id_pbs; - ip_address ta; - const unsigned char *tbp; - size_t tal; + struct isakmp_ipsec_id id; + pb_stream id_pbs; + ip_address ta; + const unsigned char *tbp; + size_t tal; - id.isaiid_np = np; - id.isaiid_idtype = subnetishost(net) - ? aftoinfo(subnettypeof(net))->id_addr - : aftoinfo(subnettypeof(net))->id_subnet; - id.isaiid_protoid = protoid; - id.isaiid_port = port; + id.isaiid_np = np; + id.isaiid_idtype = subnetishost(net) + ? aftoinfo(subnettypeof(net))->id_addr + : aftoinfo(subnettypeof(net))->id_subnet; + id.isaiid_protoid = protoid; + id.isaiid_port = port; - if (!out_struct(&id, &isakmp_ipsec_identification_desc, outs, &id_pbs)) - return FALSE; + if (!out_struct(&id, &isakmp_ipsec_identification_desc, outs, &id_pbs)) + return FALSE; - networkof(net, &ta); - tal = addrbytesptr(&ta, &tbp); - if (!out_raw(tbp, tal, &id_pbs, "client network")) - return FALSE; - - if (!subnetishost(net)) - { - maskof(net, &ta); + networkof(net, &ta); tal = addrbytesptr(&ta, &tbp); - if (!out_raw(tbp, tal, &id_pbs, "client mask")) - return FALSE; - } + if (!out_raw(tbp, tal, &id_pbs, "client network")) + return FALSE; - close_output_pbs(&id_pbs); - return TRUE; + if (!subnetishost(net)) + { + maskof(net, &ta); + tal = addrbytesptr(&ta, &tbp); + if (!out_raw(tbp, tal, &id_pbs, "client mask")) + return FALSE; + } + + close_output_pbs(&id_pbs); + return TRUE; } stf_status @@ -2028,210 +2028,210 @@ quick_outI1(int whack_sock , unsigned long try , so_serial_t replacing) { - struct state *st = duplicate_state(isakmp_sa); - pb_stream reply; /* not really a reply */ - pb_stream rbody; - u_char /* set by START_HASH_PAYLOAD: */ - *r_hashval, /* where in reply to jam hash value */ - *r_hash_start; /* start of what is to be hashed */ - bool has_client = c->spd.this.has_client || c->spd.that.has_client || - c->spd.this.protocol || c->spd.that.protocol || - c->spd.this.port || c->spd.that.port; - - bool send_natoa = FALSE; - u_int8_t np = ISAKMP_NEXT_NONE; + struct state *st = duplicate_state(isakmp_sa); + pb_stream reply; /* not really a reply */ + pb_stream rbody; + u_char /* set by START_HASH_PAYLOAD: */ + *r_hashval, /* where in reply to jam hash value */ + *r_hash_start; /* start of what is to be hashed */ + bool has_client = c->spd.this.has_client || c->spd.that.has_client || + c->spd.this.protocol || c->spd.that.protocol || + c->spd.this.port || c->spd.that.port; + + bool send_natoa = FALSE; + u_int8_t np = ISAKMP_NEXT_NONE; - st->st_whack_sock = whack_sock; - st->st_connection = c; - set_cur_state(st); /* we must reset before exit */ - st->st_policy = policy; - st->st_try = try; + st->st_whack_sock = whack_sock; + st->st_connection = c; + set_cur_state(st); /* we must reset before exit */ + st->st_policy = policy; + st->st_try = try; - st->st_myuserprotoid = c->spd.this.protocol; - st->st_peeruserprotoid = c->spd.that.protocol; - st->st_myuserport = c->spd.this.port; - st->st_peeruserport = c->spd.that.port; + st->st_myuserprotoid = c->spd.this.protocol; + st->st_peeruserprotoid = c->spd.that.protocol; + st->st_myuserport = c->spd.this.port; + st->st_peeruserport = c->spd.that.port; - st->st_msgid = generate_msgid(isakmp_sa); - st->st_state = STATE_QUICK_I1; + st->st_msgid = generate_msgid(isakmp_sa); + st->st_state = STATE_QUICK_I1; - insert_state(st); /* needs cookies, connection, and msgid */ + insert_state(st); /* needs cookies, connection, and msgid */ - if (replacing == SOS_NOBODY) - plog("initiating Quick Mode %s {using isakmp#%lu}" - , prettypolicy(policy) - , isakmp_sa->st_serialno); - else - plog("initiating Quick Mode %s to replace #%lu {using isakmp#%lu}" - , prettypolicy(policy) - , replacing - , isakmp_sa->st_serialno); + if (replacing == SOS_NOBODY) + plog("initiating Quick Mode %s {using isakmp#%lu}" + , prettypolicy(policy) + , isakmp_sa->st_serialno); + else + plog("initiating Quick Mode %s to replace #%lu {using isakmp#%lu}" + , prettypolicy(policy) + , replacing + , isakmp_sa->st_serialno); - if (isakmp_sa->nat_traversal & NAT_T_DETECTED) - { - /* Duplicate nat_traversal status in new state */ - st->nat_traversal = isakmp_sa->nat_traversal; - - if (isakmp_sa->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_ME)) - has_client = TRUE; - - nat_traversal_change_port_lookup(NULL, st); - } - else - st->nat_traversal = 0; - - /* are we going to send a NAT-OA payload? */ - if ((st->nat_traversal & NAT_T_WITH_NATOA) - && !(st->st_policy & POLICY_TUNNEL) - && (st->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_ME))) - { - send_natoa = TRUE; - np = (st->nat_traversal & NAT_T_WITH_RFC_VALUES) ? - ISAKMP_NEXT_NATOA_RFC : ISAKMP_NEXT_NATOA_DRAFTS; - } - - /* set up reply */ - init_pbs(&reply, reply_buffer, sizeof(reply_buffer), "reply packet"); - - /* HDR* out */ - { - struct isakmp_hdr hdr; - - hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION; - hdr.isa_np = ISAKMP_NEXT_HASH; - hdr.isa_xchg = ISAKMP_XCHG_QUICK; - hdr.isa_msgid = st->st_msgid; - hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION; - memcpy(hdr.isa_icookie, st->st_icookie, COOKIE_SIZE); - memcpy(hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE); - if (!out_struct(&hdr, &isakmp_hdr_desc, &reply, &rbody)) + if (isakmp_sa->nat_traversal & NAT_T_DETECTED) { - reset_cur_state(); - return STF_INTERNAL_ERROR; + /* Duplicate nat_traversal status in new state */ + st->nat_traversal = isakmp_sa->nat_traversal; + + if (isakmp_sa->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_ME)) + has_client = TRUE; + + nat_traversal_change_port_lookup(NULL, st); } - } + else + st->nat_traversal = 0; - /* HASH(1) -- create and note space to be filled later */ - START_HASH_PAYLOAD(rbody, ISAKMP_NEXT_SA); + /* are we going to send a NAT-OA payload? */ + if ((st->nat_traversal & NAT_T_WITH_NATOA) + && !(st->st_policy & POLICY_TUNNEL) + && (st->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_ME))) + { + send_natoa = TRUE; + np = (st->nat_traversal & NAT_T_WITH_RFC_VALUES) ? + ISAKMP_NEXT_NATOA_RFC : ISAKMP_NEXT_NATOA_DRAFTS; + } - /* SA out */ + /* set up reply */ + init_pbs(&reply, reply_buffer, sizeof(reply_buffer), "reply packet"); - /* - * See if pfs_group has been specified for this conn, - * if not, fallback to old use-same-as-P1 behaviour - */ + /* HDR* out */ + { + struct isakmp_hdr hdr; + + hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION; + hdr.isa_np = ISAKMP_NEXT_HASH; + hdr.isa_xchg = ISAKMP_XCHG_QUICK; + hdr.isa_msgid = st->st_msgid; + hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION; + memcpy(hdr.isa_icookie, st->st_icookie, COOKIE_SIZE); + memcpy(hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE); + if (!out_struct(&hdr, &isakmp_hdr_desc, &reply, &rbody)) + { + reset_cur_state(); + return STF_INTERNAL_ERROR; + } + } + + /* HASH(1) -- create and note space to be filled later */ + START_HASH_PAYLOAD(rbody, ISAKMP_NEXT_SA); + + /* SA out */ + + /* + * See if pfs_group has been specified for this conn, + * if not, fallback to old use-same-as-P1 behaviour + */ #ifndef NO_IKE_ALG - if (st->st_connection) - st->st_pfs_group = ike_alg_pfsgroup(st->st_connection, policy); - if (!st->st_pfs_group) + if (st->st_connection) + st->st_pfs_group = ike_alg_pfsgroup(st->st_connection, policy); + if (!st->st_pfs_group) #endif - /* If PFS specified, use the same group as during Phase 1: - * since no negotiation is possible, we pick one that is - * very likely supported. - */ - st->st_pfs_group = policy & POLICY_PFS? isakmp_sa->st_oakley.group : NULL; + /* If PFS specified, use the same group as during Phase 1: + * since no negotiation is possible, we pick one that is + * very likely supported. + */ + st->st_pfs_group = policy & POLICY_PFS? isakmp_sa->st_oakley.group : NULL; - /* Emit SA payload based on a subset of the policy bits. - * POLICY_COMPRESS is considered iff we can do IPcomp. - */ - { - lset_t pm = POLICY_ENCRYPT | POLICY_AUTHENTICATE; - - if (can_do_IPcomp) - pm |= POLICY_COMPRESS; - - if (!out_sa(&rbody - , &ipsec_sadb[(st->st_policy & pm) >> POLICY_IPSEC_SHIFT] - , st, FALSE, ISAKMP_NEXT_NONCE)) + /* Emit SA payload based on a subset of the policy bits. + * POLICY_COMPRESS is considered iff we can do IPcomp. + */ { - reset_cur_state(); - return STF_INTERNAL_ERROR; - } - } + lset_t pm = POLICY_ENCRYPT | POLICY_AUTHENTICATE; - /* Ni out */ - if (!build_and_ship_nonce(&st->st_ni, &rbody - , policy & POLICY_PFS? ISAKMP_NEXT_KE : has_client? ISAKMP_NEXT_ID : np - , "Ni")) - { + if (can_do_IPcomp) + pm |= POLICY_COMPRESS; + + if (!out_sa(&rbody + , &ipsec_sadb[(st->st_policy & pm) >> POLICY_IPSEC_SHIFT] + , st, FALSE, ISAKMP_NEXT_NONCE)) + { + reset_cur_state(); + return STF_INTERNAL_ERROR; + } + } + + /* Ni out */ + if (!build_and_ship_nonce(&st->st_ni, &rbody + , policy & POLICY_PFS? ISAKMP_NEXT_KE : has_client? ISAKMP_NEXT_ID : np + , "Ni")) + { + reset_cur_state(); + return STF_INTERNAL_ERROR; + } + + /* [ KE ] out (for PFS) */ + + if (st->st_pfs_group != NULL) + { + if (!build_and_ship_KE(st, &st->st_gi, st->st_pfs_group + , &rbody, has_client? ISAKMP_NEXT_ID : np)) + { + reset_cur_state(); + return STF_INTERNAL_ERROR; + } + } + + /* [ IDci, IDcr ] out */ + if (has_client) + { + /* IDci (we are initiator), then IDcr (peer is responder) */ + if (!emit_subnet_id(&c->spd.this.client + , ISAKMP_NEXT_ID, st->st_myuserprotoid, st->st_myuserport, &rbody) + || !emit_subnet_id(&c->spd.that.client + , np, st->st_peeruserprotoid, st->st_peeruserport, &rbody)) + { + reset_cur_state(); + return STF_INTERNAL_ERROR; + } + } + + /* Send NAT-OA if our address is NATed */ + if (send_natoa) + { + if (!nat_traversal_add_natoa(ISAKMP_NEXT_NONE, &rbody, st)) + { + reset_cur_state(); + return STF_INTERNAL_ERROR; + } + } + + /* finish computing HASH(1), inserting it in output */ + (void) quick_mode_hash12(r_hashval, r_hash_start, rbody.cur + , st, &st->st_msgid, FALSE); + + /* encrypt message, except for fixed part of header */ + + init_phase2_iv(isakmp_sa, &st->st_msgid); + st->st_new_iv_len = isakmp_sa->st_new_iv_len; + memcpy(st->st_new_iv, isakmp_sa->st_new_iv, st->st_new_iv_len); + + if (!encrypt_message(&rbody, st)) + { + reset_cur_state(); + return STF_INTERNAL_ERROR; + } + + /* save packet, now that we know its size */ + st->st_tpacket = chunk_create(reply.start, pbs_offset(&reply)); + st->st_tpacket = chunk_clone(st->st_tpacket); + + /* send the packet */ + + send_packet(st, "quick_outI1"); + + delete_event(st); + event_schedule(EVENT_RETRANSMIT, EVENT_RETRANSMIT_DELAY_0, st); + + if (replacing == SOS_NOBODY) + whack_log(RC_NEW_STATE + STATE_QUICK_I1 + , "%s: initiate" + , enum_name(&state_names, st->st_state)); + else + whack_log(RC_NEW_STATE + STATE_QUICK_I1 + , "%s: initiate to replace #%lu" + , enum_name(&state_names, st->st_state) + , replacing); reset_cur_state(); - return STF_INTERNAL_ERROR; - } - - /* [ KE ] out (for PFS) */ - - if (st->st_pfs_group != NULL) - { - if (!build_and_ship_KE(st, &st->st_gi, st->st_pfs_group - , &rbody, has_client? ISAKMP_NEXT_ID : np)) - { - reset_cur_state(); - return STF_INTERNAL_ERROR; - } - } - - /* [ IDci, IDcr ] out */ - if (has_client) - { - /* IDci (we are initiator), then IDcr (peer is responder) */ - if (!emit_subnet_id(&c->spd.this.client - , ISAKMP_NEXT_ID, st->st_myuserprotoid, st->st_myuserport, &rbody) - || !emit_subnet_id(&c->spd.that.client - , np, st->st_peeruserprotoid, st->st_peeruserport, &rbody)) - { - reset_cur_state(); - return STF_INTERNAL_ERROR; - } - } - - /* Send NAT-OA if our address is NATed */ - if (send_natoa) - { - if (!nat_traversal_add_natoa(ISAKMP_NEXT_NONE, &rbody, st)) - { - reset_cur_state(); - return STF_INTERNAL_ERROR; - } - } - - /* finish computing HASH(1), inserting it in output */ - (void) quick_mode_hash12(r_hashval, r_hash_start, rbody.cur - , st, &st->st_msgid, FALSE); - - /* encrypt message, except for fixed part of header */ - - init_phase2_iv(isakmp_sa, &st->st_msgid); - st->st_new_iv_len = isakmp_sa->st_new_iv_len; - memcpy(st->st_new_iv, isakmp_sa->st_new_iv, st->st_new_iv_len); - - if (!encrypt_message(&rbody, st)) - { - reset_cur_state(); - return STF_INTERNAL_ERROR; - } - - /* save packet, now that we know its size */ - st->st_tpacket = chunk_create(reply.start, pbs_offset(&reply)); - st->st_tpacket = chunk_clone(st->st_tpacket); - - /* send the packet */ - - send_packet(st, "quick_outI1"); - - delete_event(st); - event_schedule(EVENT_RETRANSMIT, EVENT_RETRANSMIT_DELAY_0, st); - - if (replacing == SOS_NOBODY) - whack_log(RC_NEW_STATE + STATE_QUICK_I1 - , "%s: initiate" - , enum_name(&state_names, st->st_state)); - else - whack_log(RC_NEW_STATE + STATE_QUICK_I1 - , "%s: initiate to replace #%lu" - , enum_name(&state_names, st->st_state) - , replacing); - reset_cur_state(); - return STF_OK; + return STF_OK; } @@ -2241,53 +2241,53 @@ quick_outI1(int whack_sock static void decode_cert(struct msg_digest *md) { - struct payload_digest *p; + struct payload_digest *p; - for (p = md->chain[ISAKMP_NEXT_CERT]; p != NULL; p = p->next) - { - struct isakmp_cert *const cert = &p->payload.cert; - chunk_t blob; - time_t valid_until; - blob.ptr = p->pbs.cur; - blob.len = pbs_left(&p->pbs); - if (cert->isacert_type == CERT_X509_SIGNATURE) + for (p = md->chain[ISAKMP_NEXT_CERT]; p != NULL; p = p->next) { - x509cert_t cert = empty_x509cert; - if (parse_x509cert(blob, 0, &cert)) - { - if (verify_x509cert(&cert, strict_crl_policy, &valid_until)) + struct isakmp_cert *const cert = &p->payload.cert; + chunk_t blob; + time_t valid_until; + blob.ptr = p->pbs.cur; + blob.len = pbs_left(&p->pbs); + if (cert->isacert_type == CERT_X509_SIGNATURE) { - DBG(DBG_PARSING, - DBG_log("Public key validated") - ) - add_x509_public_key(&cert, valid_until, DAL_SIGNED); + x509cert_t cert = empty_x509cert; + if (parse_x509cert(blob, 0, &cert)) + { + if (verify_x509cert(&cert, strict_crl_policy, &valid_until)) + { + DBG(DBG_PARSING, + DBG_log("Public key validated") + ) + add_x509_public_key(&cert, valid_until, DAL_SIGNED); + } + else + { + plog("X.509 certificate rejected"); + } + free_generalNames(cert.subjectAltName, FALSE); + free_generalNames(cert.crlDistributionPoints, FALSE); + } + else + plog("Syntax error in X.509 certificate"); + } + else if (cert->isacert_type == CERT_PKCS7_WRAPPED_X509) + { + x509cert_t *cert = NULL; + + if (pkcs7_parse_signedData(blob, NULL, &cert, NULL, NULL)) + store_x509certs(&cert, strict_crl_policy); + else + plog("Syntax error in PKCS#7 wrapped X.509 certificates"); } else { - plog("X.509 certificate rejected"); + loglog(RC_LOG_SERIOUS, "ignoring %s certificate payload", + enum_show(&cert_type_names, cert->isacert_type)); + DBG_cond_dump_chunk(DBG_PARSING, "CERT:\n", blob); } - free_generalNames(cert.subjectAltName, FALSE); - free_generalNames(cert.crlDistributionPoints, FALSE); - } - else - plog("Syntax error in X.509 certificate"); } - else if (cert->isacert_type == CERT_PKCS7_WRAPPED_X509) - { - x509cert_t *cert = NULL; - - if (pkcs7_parse_signedData(blob, NULL, &cert, NULL, NULL)) - store_x509certs(&cert, strict_crl_policy); - else - plog("Syntax error in PKCS#7 wrapped X.509 certificates"); - } - else - { - loglog(RC_LOG_SERIOUS, "ignoring %s certificate payload", - enum_show(&cert_type_names, cert->isacert_type)); - DBG_cond_dump_chunk(DBG_PARSING, "CERT:\n", blob); - } - } } /* @@ -2296,47 +2296,47 @@ decode_cert(struct msg_digest *md) static void decode_cr(struct msg_digest *md, struct connection *c) { - struct payload_digest *p; + struct payload_digest *p; - for (p = md->chain[ISAKMP_NEXT_CR]; p != NULL; p = p->next) - { - struct isakmp_cr *const cr = &p->payload.cr; - chunk_t ca_name; - - ca_name.len = pbs_left(&p->pbs); - ca_name.ptr = (ca_name.len > 0)? p->pbs.cur : NULL; - - DBG_cond_dump_chunk(DBG_PARSING, "CR", ca_name); - - if (cr->isacr_type == CERT_X509_SIGNATURE) + for (p = md->chain[ISAKMP_NEXT_CR]; p != NULL; p = p->next) { - char buf[BUF_LEN]; - - if (ca_name.len > 0) - { - generalName_t *gn; + struct isakmp_cr *const cr = &p->payload.cr; + chunk_t ca_name; - if (!is_asn1(ca_name)) - continue; + ca_name.len = pbs_left(&p->pbs); + ca_name.ptr = (ca_name.len > 0)? p->pbs.cur : NULL; - gn = malloc_thing(generalName_t); - ca_name = chunk_clone(ca_name); - gn->kind = GN_DIRECTORY_NAME; - gn->name = ca_name; - gn->next = c->requested_ca; - c->requested_ca = gn; - } - c->got_certrequest = TRUE; + DBG_cond_dump_chunk(DBG_PARSING, "CR", ca_name); - DBG(DBG_PARSING | DBG_CONTROL, - dntoa_or_null(buf, BUF_LEN, ca_name, "%any"); - DBG_log("requested CA: '%s'", buf); - ) + if (cr->isacr_type == CERT_X509_SIGNATURE) + { + char buf[BUF_LEN]; + + if (ca_name.len > 0) + { + generalName_t *gn; + + if (!is_asn1(ca_name)) + continue; + + gn = malloc_thing(generalName_t); + ca_name = chunk_clone(ca_name); + gn->kind = GN_DIRECTORY_NAME; + gn->name = ca_name; + gn->next = c->requested_ca; + c->requested_ca = gn; + } + c->got_certrequest = TRUE; + + DBG(DBG_PARSING | DBG_CONTROL, + dntoa_or_null(buf, BUF_LEN, ca_name, "%any"); + DBG_log("requested CA: '%s'", buf); + ) + } + else + loglog(RC_LOG_SERIOUS, "ignoring %s certificate request payload", + enum_show(&cert_type_names, cr->isacr_type)); } - else - loglog(RC_LOG_SERIOUS, "ignoring %s certificate request payload", - enum_show(&cert_type_names, cr->isacr_type)); - } } /* Decode the ID payload of Phase 1 (main_inI3_outR3 and main_inR3) @@ -2347,110 +2347,110 @@ decode_cr(struct msg_digest *md, struct connection *c) static bool decode_peer_id(struct msg_digest *md, struct id *peer) { - struct state *const st = md->st; - struct payload_digest *const id_pld = md->chain[ISAKMP_NEXT_ID]; - const pb_stream *const id_pbs = &id_pld->pbs; - struct isakmp_id *const id = &id_pld->payload.id; + struct state *const st = md->st; + struct payload_digest *const id_pld = md->chain[ISAKMP_NEXT_ID]; + const pb_stream *const id_pbs = &id_pld->pbs; + struct isakmp_id *const id = &id_pld->payload.id; - /* I think that RFC2407 (IPSEC DOI) 4.6.2 is confused. - * It talks about the protocol ID and Port fields of the ID - * Payload, but they don't exist as such in Phase 1. - * We use more appropriate names. - * isaid_doi_specific_a is in place of Protocol ID. - * isaid_doi_specific_b is in place of Port. - * Besides, there is no good reason for allowing these to be - * other than 0 in Phase 1. - */ - if ((st->nat_traversal & NAT_T_WITH_PORT_FLOATING) - && id->isaid_doi_specific_a == IPPROTO_UDP - && (id->isaid_doi_specific_b == 0 || id->isaid_doi_specific_b == NAT_T_IKE_FLOAT_PORT)) - { - DBG_log("protocol/port in Phase 1 ID Payload is %d/%d. " - "accepted with port_floating NAT-T", - id->isaid_doi_specific_a, id->isaid_doi_specific_b); - } - else if (!(id->isaid_doi_specific_a == 0 && id->isaid_doi_specific_b == 0) - && !(id->isaid_doi_specific_a == IPPROTO_UDP && id->isaid_doi_specific_b == IKE_UDP_PORT)) - { - loglog(RC_LOG_SERIOUS, "protocol/port in Phase 1 ID Payload must be 0/0 or %d/%d" - " but are %d/%d" - , IPPROTO_UDP, IKE_UDP_PORT - , id->isaid_doi_specific_a, id->isaid_doi_specific_b); - return FALSE; - } - - peer->kind = id->isaid_idtype; - - switch (peer->kind) - { - case ID_IPV4_ADDR: - case ID_IPV6_ADDR: - /* failure mode for initaddr is probably inappropriate address length */ + /* I think that RFC2407 (IPSEC DOI) 4.6.2 is confused. + * It talks about the protocol ID and Port fields of the ID + * Payload, but they don't exist as such in Phase 1. + * We use more appropriate names. + * isaid_doi_specific_a is in place of Protocol ID. + * isaid_doi_specific_b is in place of Port. + * Besides, there is no good reason for allowing these to be + * other than 0 in Phase 1. + */ + if ((st->nat_traversal & NAT_T_WITH_PORT_FLOATING) + && id->isaid_doi_specific_a == IPPROTO_UDP + && (id->isaid_doi_specific_b == 0 || id->isaid_doi_specific_b == NAT_T_IKE_FLOAT_PORT)) { - err_t ugh = initaddr(id_pbs->cur, pbs_left(id_pbs) - , peer->kind == ID_IPV4_ADDR? AF_INET : AF_INET6 - , &peer->ip_addr); - - if (ugh != NULL) - { - loglog(RC_LOG_SERIOUS, "improper %s identification payload: %s" - , enum_show(&ident_names, peer->kind), ugh); - /* XXX Could send notification back */ + DBG_log("protocol/port in Phase 1 ID Payload is %d/%d. " + "accepted with port_floating NAT-T", + id->isaid_doi_specific_a, id->isaid_doi_specific_b); + } + else if (!(id->isaid_doi_specific_a == 0 && id->isaid_doi_specific_b == 0) + && !(id->isaid_doi_specific_a == IPPROTO_UDP && id->isaid_doi_specific_b == IKE_UDP_PORT)) + { + loglog(RC_LOG_SERIOUS, "protocol/port in Phase 1 ID Payload must be 0/0 or %d/%d" + " but are %d/%d" + , IPPROTO_UDP, IKE_UDP_PORT + , id->isaid_doi_specific_a, id->isaid_doi_specific_b); return FALSE; - } } - break; - case ID_USER_FQDN: - if (memchr(id_pbs->cur, '@', pbs_left(id_pbs)) == NULL) + peer->kind = id->isaid_idtype; + + switch (peer->kind) { - loglog(RC_LOG_SERIOUS, "peer's ID_USER_FQDN contains no @"); - return FALSE; + case ID_IPV4_ADDR: + case ID_IPV6_ADDR: + /* failure mode for initaddr is probably inappropriate address length */ + { + err_t ugh = initaddr(id_pbs->cur, pbs_left(id_pbs) + , peer->kind == ID_IPV4_ADDR? AF_INET : AF_INET6 + , &peer->ip_addr); + + if (ugh != NULL) + { + loglog(RC_LOG_SERIOUS, "improper %s identification payload: %s" + , enum_show(&ident_names, peer->kind), ugh); + /* XXX Could send notification back */ + return FALSE; + } + } + break; + + case ID_USER_FQDN: + if (memchr(id_pbs->cur, '@', pbs_left(id_pbs)) == NULL) + { + loglog(RC_LOG_SERIOUS, "peer's ID_USER_FQDN contains no @"); + return FALSE; + } + /* FALLTHROUGH */ + case ID_FQDN: + if (memchr(id_pbs->cur, '\0', pbs_left(id_pbs)) != NULL) + { + loglog(RC_LOG_SERIOUS, "Phase 1 ID Payload of type %s contains a NUL" + , enum_show(&ident_names, peer->kind)); + return FALSE; + } + + /* ??? ought to do some more sanity check, but what? */ + + peer->name = chunk_create(id_pbs->cur, pbs_left(id_pbs)); + break; + + case ID_KEY_ID: + peer->name = chunk_create(id_pbs->cur, pbs_left(id_pbs)); + DBG(DBG_PARSING, + DBG_dump_chunk("KEY ID:", peer->name)); + break; + + case ID_DER_ASN1_DN: + peer->name = chunk_create(id_pbs->cur, pbs_left(id_pbs)); + DBG(DBG_PARSING, + DBG_dump_chunk("DER ASN1 DN:", peer->name)); + break; + + default: + /* XXX Could send notification back */ + loglog(RC_LOG_SERIOUS, "Unacceptable identity type (%s) in Phase 1 ID Payload" + , enum_show(&ident_names, peer->kind)); + return FALSE; } - /* FALLTHROUGH */ - case ID_FQDN: - if (memchr(id_pbs->cur, '\0', pbs_left(id_pbs)) != NULL) + { - loglog(RC_LOG_SERIOUS, "Phase 1 ID Payload of type %s contains a NUL" - , enum_show(&ident_names, peer->kind)); - return FALSE; + char buf[BUF_LEN]; + + idtoa(peer, buf, sizeof(buf)); + plog("Peer ID is %s: '%s'", + enum_show(&ident_names, id->isaid_idtype), buf); } - /* ??? ought to do some more sanity check, but what? */ - - peer->name = chunk_create(id_pbs->cur, pbs_left(id_pbs)); - break; - - case ID_KEY_ID: - peer->name = chunk_create(id_pbs->cur, pbs_left(id_pbs)); - DBG(DBG_PARSING, - DBG_dump_chunk("KEY ID:", peer->name)); - break; - - case ID_DER_ASN1_DN: - peer->name = chunk_create(id_pbs->cur, pbs_left(id_pbs)); - DBG(DBG_PARSING, - DBG_dump_chunk("DER ASN1 DN:", peer->name)); - break; - - default: - /* XXX Could send notification back */ - loglog(RC_LOG_SERIOUS, "Unacceptable identity type (%s) in Phase 1 ID Payload" - , enum_show(&ident_names, peer->kind)); - return FALSE; - } - - { - char buf[BUF_LEN]; - - idtoa(peer, buf, sizeof(buf)); - plog("Peer ID is %s: '%s'", - enum_show(&ident_names, id->isaid_idtype), buf); - } - - /* check for certificates */ - decode_cert(md); - return TRUE; + /* check for certificates */ + decode_cert(md); + return TRUE; } /* Now that we've decoded the ID payload, let's see if we @@ -2462,108 +2462,108 @@ decode_peer_id(struct msg_digest *md, struct id *peer) static bool switch_connection(struct msg_digest *md, struct id *peer, bool initiator) { - struct state *const st = md->st; - struct connection *c = st->st_connection; + struct state *const st = md->st; + struct connection *c = st->st_connection; - chunk_t peer_ca = (st->st_peer_pubkey != NULL) - ? st->st_peer_pubkey->issuer : chunk_empty; - - DBG(DBG_CONTROL, - char buf[BUF_LEN]; - - dntoa_or_null(buf, BUF_LEN, peer_ca, "%none"); - DBG_log("peer CA: '%s'", buf); - ) - - if (initiator) - { - int pathlen; - - if (!same_id(&c->spd.that.id, peer)) - { - char expect[BUF_LEN] - , found[BUF_LEN]; - - idtoa(&c->spd.that.id, expect, sizeof(expect)); - idtoa(peer, found, sizeof(found)); - loglog(RC_LOG_SERIOUS - , "we require peer to have ID '%s', but peer declares '%s'" - , expect, found); - return FALSE; - } + chunk_t peer_ca = (st->st_peer_pubkey != NULL) + ? st->st_peer_pubkey->issuer : chunk_empty; DBG(DBG_CONTROL, - char buf[BUF_LEN]; + char buf[BUF_LEN]; - dntoa_or_null(buf, BUF_LEN, c->spd.that.ca, "%none"); - DBG_log("required CA: '%s'", buf); - ) - - if (!trusted_ca(peer_ca, c->spd.that.ca, &pathlen)) - { - loglog(RC_LOG_SERIOUS - , "we don't accept the peer's CA"); - return FALSE; - } - } - else - { - struct connection *r; - - /* check for certificate requests */ - decode_cr(md, c); - - r = refine_host_connection(st, peer, peer_ca); - - /* delete the collected certificate requests */ - free_generalNames(c->requested_ca, TRUE); - c->requested_ca = NULL; - - if (r == NULL) - { - char buf[BUF_LEN]; - - idtoa(peer, buf, sizeof(buf)); - loglog(RC_LOG_SERIOUS, "no suitable connection for peer '%s'", buf); - return FALSE; - } - - DBG(DBG_CONTROL, - char buf[BUF_LEN]; - - dntoa_or_null(buf, BUF_LEN, r->spd.this.ca, "%none"); - DBG_log("offered CA: '%s'", buf); + dntoa_or_null(buf, BUF_LEN, peer_ca, "%none"); + DBG_log("peer CA: '%s'", buf); ) - if (r != c) + if (initiator) { - /* apparently, r is an improvement on c -- replace */ + int pathlen; - DBG(DBG_CONTROL - , DBG_log("switched from \"%s\" to \"%s\"", c->name, r->name)); - if (r->kind == CK_TEMPLATE) - { - /* instantiate it, filling in peer's ID */ - r = rw_instantiate(r, &c->spd.that.host_addr - , c->spd.that.host_port, NULL, peer); - } + if (!same_id(&c->spd.that.id, peer)) + { + char expect[BUF_LEN] + , found[BUF_LEN]; - /* copy certificate request info */ - r->got_certrequest = c->got_certrequest; + idtoa(&c->spd.that.id, expect, sizeof(expect)); + idtoa(peer, found, sizeof(found)); + loglog(RC_LOG_SERIOUS + , "we require peer to have ID '%s', but peer declares '%s'" + , expect, found); + return FALSE; + } - st->st_connection = r; /* kill reference to c */ - set_cur_connection(r); - connection_discard(c); + DBG(DBG_CONTROL, + char buf[BUF_LEN]; + + dntoa_or_null(buf, BUF_LEN, c->spd.that.ca, "%none"); + DBG_log("required CA: '%s'", buf); + ) + + if (!trusted_ca(peer_ca, c->spd.that.ca, &pathlen)) + { + loglog(RC_LOG_SERIOUS + , "we don't accept the peer's CA"); + return FALSE; + } } - else if (c->spd.that.has_id_wildcards) + else { - free_id_content(&c->spd.that.id); - c->spd.that.id = *peer; - c->spd.that.has_id_wildcards = FALSE; - unshare_id_content(&c->spd.that.id); + struct connection *r; + + /* check for certificate requests */ + decode_cr(md, c); + + r = refine_host_connection(st, peer, peer_ca); + + /* delete the collected certificate requests */ + free_generalNames(c->requested_ca, TRUE); + c->requested_ca = NULL; + + if (r == NULL) + { + char buf[BUF_LEN]; + + idtoa(peer, buf, sizeof(buf)); + loglog(RC_LOG_SERIOUS, "no suitable connection for peer '%s'", buf); + return FALSE; + } + + DBG(DBG_CONTROL, + char buf[BUF_LEN]; + + dntoa_or_null(buf, BUF_LEN, r->spd.this.ca, "%none"); + DBG_log("offered CA: '%s'", buf); + ) + + if (r != c) + { + /* apparently, r is an improvement on c -- replace */ + + DBG(DBG_CONTROL + , DBG_log("switched from \"%s\" to \"%s\"", c->name, r->name)); + if (r->kind == CK_TEMPLATE) + { + /* instantiate it, filling in peer's ID */ + r = rw_instantiate(r, &c->spd.that.host_addr + , c->spd.that.host_port, NULL, peer); + } + + /* copy certificate request info */ + r->got_certrequest = c->got_certrequest; + + st->st_connection = r; /* kill reference to c */ + set_cur_connection(r); + connection_discard(c); + } + else if (c->spd.that.has_id_wildcards) + { + free_id_content(&c->spd.that.id); + c->spd.that.id = *peer; + c->spd.that.has_id_wildcards = FALSE; + unshare_id_content(&c->spd.that.id); + } } - } - return TRUE; + return TRUE; } /* Decode the variable part of an ID packet (during Quick Mode). @@ -2577,165 +2577,165 @@ decode_net_id(struct isakmp_ipsec_id *id , ip_subnet *net , const char *which) { - const struct af_info *afi = NULL; + const struct af_info *afi = NULL; - /* Note: the following may be a pointer into static memory - * that may be recycled, but only if the type is not known. - * That case is disposed of very early -- in the first switch. - */ - const char *idtypename = enum_show(&ident_names, id->isaiid_idtype); + /* Note: the following may be a pointer into static memory + * that may be recycled, but only if the type is not known. + * That case is disposed of very early -- in the first switch. + */ + const char *idtypename = enum_show(&ident_names, id->isaiid_idtype); - switch (id->isaiid_idtype) - { - case ID_IPV4_ADDR: - case ID_IPV4_ADDR_SUBNET: - case ID_IPV4_ADDR_RANGE: - afi = &af_inet4_info; - break; - case ID_IPV6_ADDR: - case ID_IPV6_ADDR_SUBNET: - case ID_IPV6_ADDR_RANGE: - afi = &af_inet6_info; - break; - case ID_FQDN: - return TRUE; - default: - /* XXX support more */ - loglog(RC_LOG_SERIOUS, "unsupported ID type %s" - , idtypename); - /* XXX Could send notification back */ - return FALSE; - } - - switch (id->isaiid_idtype) - { - case ID_IPV4_ADDR: - case ID_IPV6_ADDR: + switch (id->isaiid_idtype) { - ip_address temp_address; - err_t ugh; - - ugh = initaddr(id_pbs->cur, pbs_left(id_pbs), afi->af, &temp_address); - - if (ugh != NULL) - { - loglog(RC_LOG_SERIOUS, "%s ID payload %s has wrong length in Quick I1 (%s)" - , which, idtypename, ugh); - /* XXX Could send notification back */ - return FALSE; - } - if (isanyaddr(&temp_address)) - { - loglog(RC_LOG_SERIOUS, "%s ID payload %s is invalid (%s) in Quick I1" - , which, idtypename, ip_str(&temp_address)); - /* XXX Could send notification back */ - return FALSE; - } - happy(addrtosubnet(&temp_address, net)); - DBG(DBG_PARSING | DBG_CONTROL - , DBG_log("%s is %s", which, ip_str(&temp_address))); - break; + case ID_IPV4_ADDR: + case ID_IPV4_ADDR_SUBNET: + case ID_IPV4_ADDR_RANGE: + afi = &af_inet4_info; + break; + case ID_IPV6_ADDR: + case ID_IPV6_ADDR_SUBNET: + case ID_IPV6_ADDR_RANGE: + afi = &af_inet6_info; + break; + case ID_FQDN: + return TRUE; + default: + /* XXX support more */ + loglog(RC_LOG_SERIOUS, "unsupported ID type %s" + , idtypename); + /* XXX Could send notification back */ + return FALSE; } - case ID_IPV4_ADDR_SUBNET: - case ID_IPV6_ADDR_SUBNET: + switch (id->isaiid_idtype) { - ip_address temp_address, temp_mask; - err_t ugh; - - if (pbs_left(id_pbs) != 2 * afi->ia_sz) - { - loglog(RC_LOG_SERIOUS, "%s ID payload %s wrong length in Quick I1" - , which, idtypename); - /* XXX Could send notification back */ - return FALSE; - } - ugh = initaddr(id_pbs->cur - , afi->ia_sz, afi->af, &temp_address); - if (ugh == NULL) - ugh = initaddr(id_pbs->cur + afi->ia_sz - , afi->ia_sz, afi->af, &temp_mask); - if (ugh == NULL) - ugh = initsubnet(&temp_address, masktocount(&temp_mask) - , '0', net); - if (ugh == NULL && subnetisnone(net)) - ugh = "contains only anyaddr"; - if (ugh != NULL) - { - loglog(RC_LOG_SERIOUS, "%s ID payload %s bad subnet in Quick I1 (%s)" - , which, idtypename, ugh); - /* XXX Could send notification back */ - return FALSE; - } - DBG(DBG_PARSING | DBG_CONTROL, + case ID_IPV4_ADDR: + case ID_IPV6_ADDR: { - char temp_buff[SUBNETTOT_BUF]; + ip_address temp_address; + err_t ugh; - subnettot(net, 0, temp_buff, sizeof(temp_buff)); - DBG_log("%s is subnet %s", which, temp_buff); - }); - break; - } + ugh = initaddr(id_pbs->cur, pbs_left(id_pbs), afi->af, &temp_address); - case ID_IPV4_ADDR_RANGE: - case ID_IPV6_ADDR_RANGE: - { - ip_address temp_address_from, temp_address_to; - err_t ugh; + if (ugh != NULL) + { + loglog(RC_LOG_SERIOUS, "%s ID payload %s has wrong length in Quick I1 (%s)" + , which, idtypename, ugh); + /* XXX Could send notification back */ + return FALSE; + } + if (isanyaddr(&temp_address)) + { + loglog(RC_LOG_SERIOUS, "%s ID payload %s is invalid (%s) in Quick I1" + , which, idtypename, ip_str(&temp_address)); + /* XXX Could send notification back */ + return FALSE; + } + happy(addrtosubnet(&temp_address, net)); + DBG(DBG_PARSING | DBG_CONTROL + , DBG_log("%s is %s", which, ip_str(&temp_address))); + break; + } - if (pbs_left(id_pbs) != 2 * afi->ia_sz) - { - loglog(RC_LOG_SERIOUS, "%s ID payload %s wrong length in Quick I1" - , which, idtypename); - /* XXX Could send notification back */ - return FALSE; - } - ugh = initaddr(id_pbs->cur, afi->ia_sz, afi->af, &temp_address_from); - if (ugh == NULL) - ugh = initaddr(id_pbs->cur + afi->ia_sz - , afi->ia_sz, afi->af, &temp_address_to); - if (ugh != NULL) - { - loglog(RC_LOG_SERIOUS, "%s ID payload %s malformed (%s) in Quick I1" - , which, idtypename, ugh); - /* XXX Could send notification back */ - return FALSE; - } - - ugh = rangetosubnet(&temp_address_from, &temp_address_to, net); - if (ugh == NULL && subnetisnone(net)) - ugh = "contains only anyaddr"; - if (ugh != NULL) - { - char temp_buff1[ADDRTOT_BUF], temp_buff2[ADDRTOT_BUF]; - - addrtot(&temp_address_from, 0, temp_buff1, sizeof(temp_buff1)); - addrtot(&temp_address_to, 0, temp_buff2, sizeof(temp_buff2)); - loglog(RC_LOG_SERIOUS, "%s ID payload in Quick I1, %s" - " %s - %s unacceptable: %s" - , which, idtypename, temp_buff1, temp_buff2, ugh); - return FALSE; - } - DBG(DBG_PARSING | DBG_CONTROL, + case ID_IPV4_ADDR_SUBNET: + case ID_IPV6_ADDR_SUBNET: { - char temp_buff[SUBNETTOT_BUF]; + ip_address temp_address, temp_mask; + err_t ugh; - subnettot(net, 0, temp_buff, sizeof(temp_buff)); - DBG_log("%s is subnet %s (received as range)" - , which, temp_buff); - }); - break; + if (pbs_left(id_pbs) != 2 * afi->ia_sz) + { + loglog(RC_LOG_SERIOUS, "%s ID payload %s wrong length in Quick I1" + , which, idtypename); + /* XXX Could send notification back */ + return FALSE; + } + ugh = initaddr(id_pbs->cur + , afi->ia_sz, afi->af, &temp_address); + if (ugh == NULL) + ugh = initaddr(id_pbs->cur + afi->ia_sz + , afi->ia_sz, afi->af, &temp_mask); + if (ugh == NULL) + ugh = initsubnet(&temp_address, masktocount(&temp_mask) + , '0', net); + if (ugh == NULL && subnetisnone(net)) + ugh = "contains only anyaddr"; + if (ugh != NULL) + { + loglog(RC_LOG_SERIOUS, "%s ID payload %s bad subnet in Quick I1 (%s)" + , which, idtypename, ugh); + /* XXX Could send notification back */ + return FALSE; + } + DBG(DBG_PARSING | DBG_CONTROL, + { + char temp_buff[SUBNETTOT_BUF]; + + subnettot(net, 0, temp_buff, sizeof(temp_buff)); + DBG_log("%s is subnet %s", which, temp_buff); + }); + break; + } + + case ID_IPV4_ADDR_RANGE: + case ID_IPV6_ADDR_RANGE: + { + ip_address temp_address_from, temp_address_to; + err_t ugh; + + if (pbs_left(id_pbs) != 2 * afi->ia_sz) + { + loglog(RC_LOG_SERIOUS, "%s ID payload %s wrong length in Quick I1" + , which, idtypename); + /* XXX Could send notification back */ + return FALSE; + } + ugh = initaddr(id_pbs->cur, afi->ia_sz, afi->af, &temp_address_from); + if (ugh == NULL) + ugh = initaddr(id_pbs->cur + afi->ia_sz + , afi->ia_sz, afi->af, &temp_address_to); + if (ugh != NULL) + { + loglog(RC_LOG_SERIOUS, "%s ID payload %s malformed (%s) in Quick I1" + , which, idtypename, ugh); + /* XXX Could send notification back */ + return FALSE; + } + + ugh = rangetosubnet(&temp_address_from, &temp_address_to, net); + if (ugh == NULL && subnetisnone(net)) + ugh = "contains only anyaddr"; + if (ugh != NULL) + { + char temp_buff1[ADDRTOT_BUF], temp_buff2[ADDRTOT_BUF]; + + addrtot(&temp_address_from, 0, temp_buff1, sizeof(temp_buff1)); + addrtot(&temp_address_to, 0, temp_buff2, sizeof(temp_buff2)); + loglog(RC_LOG_SERIOUS, "%s ID payload in Quick I1, %s" + " %s - %s unacceptable: %s" + , which, idtypename, temp_buff1, temp_buff2, ugh); + return FALSE; + } + DBG(DBG_PARSING | DBG_CONTROL, + { + char temp_buff[SUBNETTOT_BUF]; + + subnettot(net, 0, temp_buff, sizeof(temp_buff)); + DBG_log("%s is subnet %s (received as range)" + , which, temp_buff); + }); + break; + } } - } - /* set the port selector */ - setportof(htons(id->isaiid_port), &net->addr); + /* set the port selector */ + setportof(htons(id->isaiid_port), &net->addr); - DBG(DBG_PARSING | DBG_CONTROL, - DBG_log("%s protocol/port is %d/%d", which, id->isaiid_protoid, id->isaiid_port) - ) + DBG(DBG_PARSING | DBG_CONTROL, + DBG_log("%s protocol/port is %d/%d", which, id->isaiid_protoid, id->isaiid_port) + ) - return TRUE; + return TRUE; } /* like decode, but checks that what is received matches what was sent */ @@ -2748,18 +2748,18 @@ check_net_id(struct isakmp_ipsec_id *id , ip_subnet *net , const char *which) { - ip_subnet net_temp; + ip_subnet net_temp; - if (!decode_net_id(id, id_pbs, &net_temp, which)) - return FALSE; + if (!decode_net_id(id, id_pbs, &net_temp, which)) + return FALSE; - if (!samesubnet(net, &net_temp) - || *protoid != id->isaiid_protoid || *port != id->isaiid_port) - { - loglog(RC_LOG_SERIOUS, "%s ID returned doesn't match my proposal", which); - return FALSE; - } - return TRUE; + if (!samesubnet(net, &net_temp) + || *protoid != id->isaiid_protoid || *port != id->isaiid_port) + { + loglog(RC_LOG_SERIOUS, "%s ID returned doesn't match my proposal", which); + return FALSE; + } + return TRUE; } /* @@ -2768,30 +2768,30 @@ check_net_id(struct isakmp_ipsec_id *id static bool has_preloaded_public_key(struct state *st) { - struct connection *c = st->st_connection; + struct connection *c = st->st_connection; - /* do not consider rw connections since - * the peer's identity must be known - */ - if (c->kind == CK_PERMANENT) - { - pubkey_list_t *p; - - /* look for a matching RSA public key */ - for (p = pubkeys; p != NULL; p = p->next) + /* do not consider rw connections since + * the peer's identity must be known + */ + if (c->kind == CK_PERMANENT) { - pubkey_t *key = p->key; + pubkey_list_t *p; - if (key->alg == PUBKEY_ALG_RSA && - same_id(&c->spd.that.id, &key->id) && - key->until_time == UNDEFINED_TIME) - { - /* found a preloaded public key */ - return TRUE; - } + /* look for a matching RSA public key */ + for (p = pubkeys; p != NULL; p = p->next) + { + pubkey_t *key = p->key; + + if (key->alg == PUBKEY_ALG_RSA && + same_id(&c->spd.that.id, &key->id) && + key->until_time == UNDEFINED_TIME) + { + /* found a preloaded public key */ + return TRUE; + } + } } - } - return FALSE; + return FALSE; } /* @@ -2804,156 +2804,156 @@ compute_proto_keymat(struct state *st , u_int8_t protoid , struct ipsec_proto_info *pi) { - size_t needed_len = 0; /* bytes of keying material needed */ + size_t needed_len = 0; /* bytes of keying material needed */ - /* Add up the requirements for keying material - * (It probably doesn't matter if we produce too much!) - */ - switch (protoid) - { - case PROTO_IPSEC_ESP: - switch (pi->attrs.transid) - { - case ESP_NULL: - needed_len = 0; - break; - case ESP_DES: - needed_len = DES_CBC_BLOCK_SIZE; - break; - case ESP_3DES: - needed_len = DES_CBC_BLOCK_SIZE * 3; - break; - default: + /* Add up the requirements for keying material + * (It probably doesn't matter if we produce too much!) + */ + switch (protoid) + { + case PROTO_IPSEC_ESP: + switch (pi->attrs.transid) + { + case ESP_NULL: + needed_len = 0; + break; + case ESP_DES: + needed_len = DES_CBC_BLOCK_SIZE; + break; + case ESP_3DES: + needed_len = DES_CBC_BLOCK_SIZE * 3; + break; + default: #ifndef NO_KERNEL_ALG - if((needed_len=kernel_alg_esp_enc_keylen(pi->attrs.transid))>0) { - /* XXX: check key_len "coupling with kernel.c's */ - if (pi->attrs.key_len) { - needed_len=pi->attrs.key_len/8; - DBG(DBG_PARSING, DBG_log("compute_proto_keymat:" - "key_len=%d from peer", - (int)needed_len)); + if((needed_len=kernel_alg_esp_enc_keylen(pi->attrs.transid))>0) { + /* XXX: check key_len "coupling with kernel.c's */ + if (pi->attrs.key_len) { + needed_len=pi->attrs.key_len/8; + DBG(DBG_PARSING, DBG_log("compute_proto_keymat:" + "key_len=%d from peer", + (int)needed_len)); + } + break; + } +#endif + bad_case(pi->attrs.transid); + } + +#ifndef NO_KERNEL_ALG + DBG(DBG_PARSING, DBG_log("compute_proto_keymat:" + "needed_len (after ESP enc)=%d", + (int)needed_len)); + if (kernel_alg_esp_auth_ok(pi->attrs.auth, NULL)) { + needed_len += kernel_alg_esp_auth_keylen(pi->attrs.auth); + } else +#endif + switch (pi->attrs.auth) + { + case AUTH_ALGORITHM_NONE: + break; + case AUTH_ALGORITHM_HMAC_MD5: + needed_len += HMAC_MD5_KEY_LEN; + break; + case AUTH_ALGORITHM_HMAC_SHA1: + needed_len += HMAC_SHA1_KEY_LEN; + break; + case AUTH_ALGORITHM_DES_MAC: + default: + bad_case(pi->attrs.auth); + } + DBG(DBG_PARSING, DBG_log("compute_proto_keymat:" + "needed_len (after ESP auth)=%d", + (int)needed_len)); + break; + + case PROTO_IPSEC_AH: + switch (pi->attrs.transid) + { + case AH_MD5: + needed_len = HMAC_MD5_KEY_LEN; + break; + case AH_SHA: + needed_len = HMAC_SHA1_KEY_LEN; + break; + default: + bad_case(pi->attrs.transid); } break; - } -#endif - bad_case(pi->attrs.transid); - } -#ifndef NO_KERNEL_ALG - DBG(DBG_PARSING, DBG_log("compute_proto_keymat:" - "needed_len (after ESP enc)=%d", - (int)needed_len)); - if (kernel_alg_esp_auth_ok(pi->attrs.auth, NULL)) { - needed_len += kernel_alg_esp_auth_keylen(pi->attrs.auth); - } else -#endif - switch (pi->attrs.auth) - { - case AUTH_ALGORITHM_NONE: - break; - case AUTH_ALGORITHM_HMAC_MD5: - needed_len += HMAC_MD5_KEY_LEN; - break; - case AUTH_ALGORITHM_HMAC_SHA1: - needed_len += HMAC_SHA1_KEY_LEN; - break; - case AUTH_ALGORITHM_DES_MAC: - default: - bad_case(pi->attrs.auth); - } - DBG(DBG_PARSING, DBG_log("compute_proto_keymat:" - "needed_len (after ESP auth)=%d", - (int)needed_len)); - break; - - case PROTO_IPSEC_AH: - switch (pi->attrs.transid) - { - case AH_MD5: - needed_len = HMAC_MD5_KEY_LEN; - break; - case AH_SHA: - needed_len = HMAC_SHA1_KEY_LEN; - break; - default: - bad_case(pi->attrs.transid); - } - break; - - default: - bad_case(protoid); - } - - pi->keymat_len = needed_len; - - /* Allocate space for the keying material. - * Although only needed_len bytes are desired, we - * must round up to a multiple of ctx.hmac_digest_size - * so that our buffer isn't overrun. - */ - { - struct hmac_ctx ctx_me, ctx_peer; - size_t needed_space; /* space needed for keying material (rounded up) */ - size_t i; - - hmac_init_chunk(&ctx_me, st->st_oakley.hasher, st->st_skeyid_d); - ctx_peer = ctx_me; /* duplicate initial conditions */ - - needed_space = needed_len + pad_up(needed_len, ctx_me.hmac_digest_size); - replace(pi->our_keymat, malloc(needed_space)); - replace(pi->peer_keymat, malloc(needed_space)); - - for (i = 0;; ) - { - if (st->st_shared.ptr != NULL) - { - /* PFS: include the g^xy */ - hmac_update_chunk(&ctx_me, st->st_shared); - hmac_update_chunk(&ctx_peer, st->st_shared); - } - hmac_update(&ctx_me, &protoid, sizeof(protoid)); - hmac_update(&ctx_peer, &protoid, sizeof(protoid)); - - hmac_update(&ctx_me, (u_char *)&pi->our_spi, sizeof(pi->our_spi)); - hmac_update(&ctx_peer, (u_char *)&pi->attrs.spi, sizeof(pi->attrs.spi)); - - hmac_update_chunk(&ctx_me, st->st_ni); - hmac_update_chunk(&ctx_peer, st->st_ni); - - hmac_update_chunk(&ctx_me, st->st_nr); - hmac_update_chunk(&ctx_peer, st->st_nr); - - hmac_final(pi->our_keymat + i, &ctx_me); - hmac_final(pi->peer_keymat + i, &ctx_peer); - - i += ctx_me.hmac_digest_size; - if (i >= needed_space) - break; - - /* more keying material needed: prepare to go around again */ - - hmac_reinit(&ctx_me); - hmac_reinit(&ctx_peer); - - hmac_update(&ctx_me, pi->our_keymat + i - ctx_me.hmac_digest_size - , ctx_me.hmac_digest_size); - hmac_update(&ctx_peer, pi->peer_keymat + i - ctx_peer.hmac_digest_size - , ctx_peer.hmac_digest_size); + default: + bad_case(protoid); } - } - DBG(DBG_CRYPT, - DBG_dump("KEYMAT computed:\n", pi->our_keymat, pi->keymat_len); - DBG_dump("Peer KEYMAT computed:\n", pi->peer_keymat, pi->keymat_len)); + pi->keymat_len = needed_len; + + /* Allocate space for the keying material. + * Although only needed_len bytes are desired, we + * must round up to a multiple of ctx.hmac_digest_size + * so that our buffer isn't overrun. + */ + { + struct hmac_ctx ctx_me, ctx_peer; + size_t needed_space; /* space needed for keying material (rounded up) */ + size_t i; + + hmac_init_chunk(&ctx_me, st->st_oakley.hasher, st->st_skeyid_d); + ctx_peer = ctx_me; /* duplicate initial conditions */ + + needed_space = needed_len + pad_up(needed_len, ctx_me.hmac_digest_size); + replace(pi->our_keymat, malloc(needed_space)); + replace(pi->peer_keymat, malloc(needed_space)); + + for (i = 0;; ) + { + if (st->st_shared.ptr != NULL) + { + /* PFS: include the g^xy */ + hmac_update_chunk(&ctx_me, st->st_shared); + hmac_update_chunk(&ctx_peer, st->st_shared); + } + hmac_update(&ctx_me, &protoid, sizeof(protoid)); + hmac_update(&ctx_peer, &protoid, sizeof(protoid)); + + hmac_update(&ctx_me, (u_char *)&pi->our_spi, sizeof(pi->our_spi)); + hmac_update(&ctx_peer, (u_char *)&pi->attrs.spi, sizeof(pi->attrs.spi)); + + hmac_update_chunk(&ctx_me, st->st_ni); + hmac_update_chunk(&ctx_peer, st->st_ni); + + hmac_update_chunk(&ctx_me, st->st_nr); + hmac_update_chunk(&ctx_peer, st->st_nr); + + hmac_final(pi->our_keymat + i, &ctx_me); + hmac_final(pi->peer_keymat + i, &ctx_peer); + + i += ctx_me.hmac_digest_size; + if (i >= needed_space) + break; + + /* more keying material needed: prepare to go around again */ + + hmac_reinit(&ctx_me); + hmac_reinit(&ctx_peer); + + hmac_update(&ctx_me, pi->our_keymat + i - ctx_me.hmac_digest_size + , ctx_me.hmac_digest_size); + hmac_update(&ctx_peer, pi->peer_keymat + i - ctx_peer.hmac_digest_size + , ctx_peer.hmac_digest_size); + } + } + + DBG(DBG_CRYPT, + DBG_dump("KEYMAT computed:\n", pi->our_keymat, pi->keymat_len); + DBG_dump("Peer KEYMAT computed:\n", pi->peer_keymat, pi->keymat_len)); } static void compute_keymats(struct state *st) { - if (st->st_ah.present) - compute_proto_keymat(st, PROTO_IPSEC_AH, &st->st_ah); - if (st->st_esp.present) - compute_proto_keymat(st, PROTO_IPSEC_ESP, &st->st_esp); + if (st->st_ah.present) + compute_proto_keymat(st, PROTO_IPSEC_AH, &st->st_ah); + if (st->st_esp.present) + compute_proto_keymat(st, PROTO_IPSEC_ESP, &st->st_esp); } /* State Transition Functions. @@ -2981,260 +2981,260 @@ compute_keymats(struct state *st) stf_status main_inI1_outR1(struct msg_digest *md) { - struct payload_digest *const sa_pd = md->chain[ISAKMP_NEXT_SA]; - struct state *st; - struct connection *c; - struct isakmp_proposal proposal; - pb_stream proposal_pbs; - pb_stream r_sa_pbs; - u_int32_t ipsecdoisit; - lset_t policy = LEMPTY; - int vids_to_send = 0; + struct payload_digest *const sa_pd = md->chain[ISAKMP_NEXT_SA]; + struct state *st; + struct connection *c; + struct isakmp_proposal proposal; + pb_stream proposal_pbs; + pb_stream r_sa_pbs; + u_int32_t ipsecdoisit; + lset_t policy = LEMPTY; + int vids_to_send = 0; - /* We preparse the peer's proposal in order to determine - * the requested authentication policy (RSA or PSK) - */ - RETURN_STF_FAILURE(preparse_isakmp_sa_body(&sa_pd->payload.sa - , &sa_pd->pbs, &ipsecdoisit, &proposal_pbs, &proposal)); - - backup_pbs(&proposal_pbs); - RETURN_STF_FAILURE(parse_isakmp_policy(&proposal_pbs - , proposal.isap_notrans, &policy)); - restore_pbs(&proposal_pbs); - - /* We are only considering candidate connections that match - * the requested authentication policy (RSA or PSK) - */ - c = find_host_connection(&md->iface->addr, pluto_port - , &md->sender, md->sender_port, policy); - - if (c == NULL && md->iface->ike_float) - { - c = find_host_connection(&md->iface->addr, NAT_T_IKE_FLOAT_PORT - , &md->sender, md->sender_port, policy); - } - - if (c == NULL) - { - /* See if a wildcarded connection can be found. - * We cannot pick the right connection, so we're making a guess. - * All Road Warrior connections are fair game: - * we pick the first we come across (if any). - * If we don't find any, we pick the first opportunistic - * with the smallest subnet that includes the peer. - * There is, of course, no necessary relationship between - * an Initiator's address and that of its client, - * but Food Groups kind of assumes one. + /* We preparse the peer's proposal in order to determine + * the requested authentication policy (RSA or PSK) */ + RETURN_STF_FAILURE(preparse_isakmp_sa_body(&sa_pd->payload.sa + , &sa_pd->pbs, &ipsecdoisit, &proposal_pbs, &proposal)); + + backup_pbs(&proposal_pbs); + RETURN_STF_FAILURE(parse_isakmp_policy(&proposal_pbs + , proposal.isap_notrans, &policy)); + restore_pbs(&proposal_pbs); + + /* We are only considering candidate connections that match + * the requested authentication policy (RSA or PSK) + */ + c = find_host_connection(&md->iface->addr, pluto_port + , &md->sender, md->sender_port, policy); + + if (c == NULL && md->iface->ike_float) { - struct connection *d; - - d = find_host_connection(&md->iface->addr - , pluto_port, (ip_address*)NULL, md->sender_port, policy); - - for (; d != NULL; d = d->hp_next) - { - if (d->kind == CK_GROUP) - { - /* ignore */ - } - else - { - if (d->kind == CK_TEMPLATE && !(d->policy & POLICY_OPPO)) - { - /* must be Road Warrior: we have a winner */ - c = d; - break; - } - - /* Opportunistic or Shunt: pick tightest match */ - if (addrinsubnet(&md->sender, &d->spd.that.client) - && (c == NULL || !subnetinsubnet(&c->spd.that.client, &d->spd.that.client))) - c = d; - } - } + c = find_host_connection(&md->iface->addr, NAT_T_IKE_FLOAT_PORT + , &md->sender, md->sender_port, policy); } if (c == NULL) { - loglog(RC_LOG_SERIOUS, "initial Main Mode message received on %s:%u" - " but no connection has been authorized%s%s" - , ip_str(&md->iface->addr), ntohs(portof(&md->iface->addr)) - , (policy != LEMPTY) ? " with policy=" : "" - , (policy != LEMPTY) ? bitnamesof(sa_policy_bit_names, policy) : ""); - /* XXX notification is in order! */ - return STF_IGNORE; + /* See if a wildcarded connection can be found. + * We cannot pick the right connection, so we're making a guess. + * All Road Warrior connections are fair game: + * we pick the first we come across (if any). + * If we don't find any, we pick the first opportunistic + * with the smallest subnet that includes the peer. + * There is, of course, no necessary relationship between + * an Initiator's address and that of its client, + * but Food Groups kind of assumes one. + */ + { + struct connection *d; + + d = find_host_connection(&md->iface->addr + , pluto_port, (ip_address*)NULL, md->sender_port, policy); + + for (; d != NULL; d = d->hp_next) + { + if (d->kind == CK_GROUP) + { + /* ignore */ + } + else + { + if (d->kind == CK_TEMPLATE && !(d->policy & POLICY_OPPO)) + { + /* must be Road Warrior: we have a winner */ + c = d; + break; + } + + /* Opportunistic or Shunt: pick tightest match */ + if (addrinsubnet(&md->sender, &d->spd.that.client) + && (c == NULL || !subnetinsubnet(&c->spd.that.client, &d->spd.that.client))) + c = d; + } + } + } + + if (c == NULL) + { + loglog(RC_LOG_SERIOUS, "initial Main Mode message received on %s:%u" + " but no connection has been authorized%s%s" + , ip_str(&md->iface->addr), ntohs(portof(&md->iface->addr)) + , (policy != LEMPTY) ? " with policy=" : "" + , (policy != LEMPTY) ? bitnamesof(sa_policy_bit_names, policy) : ""); + /* XXX notification is in order! */ + return STF_IGNORE; + } + else if (c->kind != CK_TEMPLATE) + { + loglog(RC_LOG_SERIOUS, "initial Main Mode message received on %s:%u" + " but \"%s\" forbids connection" + , ip_str(&md->iface->addr), pluto_port, c->name); + /* XXX notification is in order! */ + return STF_IGNORE; + } + else + { + /* Create a temporary connection that is a copy of this one. + * His ID isn't declared yet. + */ + c = rw_instantiate(c, &md->sender, md->sender_port, NULL, NULL); + } } - else if (c->kind != CK_TEMPLATE) + else if (c->kind == CK_TEMPLATE) { - loglog(RC_LOG_SERIOUS, "initial Main Mode message received on %s:%u" - " but \"%s\" forbids connection" - , ip_str(&md->iface->addr), pluto_port, c->name); - /* XXX notification is in order! */ - return STF_IGNORE; + /* Create an instance + * This is a rare case: wildcard peer ID but static peer IP address + */ + c = rw_instantiate(c, &md->sender, md->sender_port, NULL, &c->spd.that.id); + } + + /* Set up state */ + md->st = st = new_state(); + st->st_connection = c; + set_cur_state(st); /* (caller will reset cur_state) */ + st->st_try = 0; /* not our job to try again from start */ + st->st_policy = c->policy & ~POLICY_IPSEC_MASK; /* only as accurate as connection */ + + memcpy(st->st_icookie, md->hdr.isa_icookie, COOKIE_SIZE); + get_cookie(FALSE, st->st_rcookie, COOKIE_SIZE, &md->sender); + + insert_state(st); /* needs cookies, connection, and msgid (0) */ + + st->st_doi = ISAKMP_DOI_IPSEC; + st->st_situation = SIT_IDENTITY_ONLY; /* We only support this */ + + if ((c->kind == CK_INSTANCE) && (c->spd.that.host_port != pluto_port)) + { + plog("responding to Main Mode from unknown peer %s:%u" + , ip_str(&c->spd.that.host_addr), c->spd.that.host_port); + } + else if (c->kind == CK_INSTANCE) + { + plog("responding to Main Mode from unknown peer %s" + , ip_str(&c->spd.that.host_addr)); } else { - /* Create a temporary connection that is a copy of this one. - * His ID isn't declared yet. - */ - c = rw_instantiate(c, &md->sender, md->sender_port, NULL, NULL); + plog("responding to Main Mode"); } - } - else if (c->kind == CK_TEMPLATE) - { - /* Create an instance - * This is a rare case: wildcard peer ID but static peer IP address + + /* parse_isakmp_sa also spits out a winning SA into our reply, + * so we have to build our md->reply and emit HDR before calling it. */ - c = rw_instantiate(c, &md->sender, md->sender_port, NULL, &c->spd.that.id); - } - /* Set up state */ - md->st = st = new_state(); - st->st_connection = c; - set_cur_state(st); /* (caller will reset cur_state) */ - st->st_try = 0; /* not our job to try again from start */ - st->st_policy = c->policy & ~POLICY_IPSEC_MASK; /* only as accurate as connection */ + /* determine how many Vendor ID payloads we will be sending */ + if (SEND_PLUTO_VID) + vids_to_send++; + if (SEND_CISCO_UNITY_VID) + vids_to_send++; + if (md->openpgp) + vids_to_send++; + if (SEND_XAUTH_VID) + vids_to_send++; + /* always send DPD Vendor ID */ + vids_to_send++; + if (md->nat_traversal_vid && nat_traversal_enabled) + vids_to_send++; - memcpy(st->st_icookie, md->hdr.isa_icookie, COOKIE_SIZE); - get_cookie(FALSE, st->st_rcookie, COOKIE_SIZE, &md->sender); + /* HDR out. + * We can't leave this to comm_handle() because we must + * fill in the cookie. + */ + { + struct isakmp_hdr r_hdr = md->hdr; - insert_state(st); /* needs cookies, connection, and msgid (0) */ + r_hdr.isa_flags &= ~ISAKMP_FLAG_COMMIT; /* we won't ever turn on this bit */ + memcpy(r_hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE); + r_hdr.isa_np = ISAKMP_NEXT_SA; + if (!out_struct(&r_hdr, &isakmp_hdr_desc, &md->reply, &md->rbody)) + return STF_INTERNAL_ERROR; + } - st->st_doi = ISAKMP_DOI_IPSEC; - st->st_situation = SIT_IDENTITY_ONLY; /* We only support this */ + /* start of SA out */ + { + struct isakmp_sa r_sa = sa_pd->payload.sa; - if ((c->kind == CK_INSTANCE) && (c->spd.that.host_port != pluto_port)) - { - plog("responding to Main Mode from unknown peer %s:%u" - , ip_str(&c->spd.that.host_addr), c->spd.that.host_port); - } - else if (c->kind == CK_INSTANCE) - { - plog("responding to Main Mode from unknown peer %s" - , ip_str(&c->spd.that.host_addr)); - } - else - { - plog("responding to Main Mode"); - } + r_sa.isasa_np = vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE; - /* parse_isakmp_sa also spits out a winning SA into our reply, - * so we have to build our md->reply and emit HDR before calling it. - */ + if (!out_struct(&r_sa, &isakmp_sa_desc, &md->rbody, &r_sa_pbs)) + return STF_INTERNAL_ERROR; + } - /* determine how many Vendor ID payloads we will be sending */ - if (SEND_PLUTO_VID) - vids_to_send++; - if (SEND_CISCO_UNITY_VID) - vids_to_send++; - if (md->openpgp) - vids_to_send++; - if (SEND_XAUTH_VID) - vids_to_send++; - /* always send DPD Vendor ID */ - vids_to_send++; - if (md->nat_traversal_vid && nat_traversal_enabled) - vids_to_send++; + /* SA body in and out */ + RETURN_STF_FAILURE(parse_isakmp_sa_body(ipsecdoisit, &proposal_pbs + ,&proposal, &r_sa_pbs, st, FALSE)); - /* HDR out. - * We can't leave this to comm_handle() because we must - * fill in the cookie. - */ - { - struct isakmp_hdr r_hdr = md->hdr; + /* if enabled send Pluto Vendor ID */ + if (SEND_PLUTO_VID) + { + if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE + , &md->rbody, VID_STRONGSWAN)) + { + return STF_INTERNAL_ERROR; + } + } - r_hdr.isa_flags &= ~ISAKMP_FLAG_COMMIT; /* we won't ever turn on this bit */ - memcpy(r_hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE); - r_hdr.isa_np = ISAKMP_NEXT_SA; - if (!out_struct(&r_hdr, &isakmp_hdr_desc, &md->reply, &md->rbody)) - return STF_INTERNAL_ERROR; - } + /* if enabled send Cisco Unity Vendor ID */ + if (SEND_CISCO_UNITY_VID) + { + if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE + , &md->rbody, VID_CISCO_UNITY)) + { + return STF_INTERNAL_ERROR; + } + } - /* start of SA out */ - { - struct isakmp_sa r_sa = sa_pd->payload.sa; + /* + * if the peer sent an OpenPGP Vendor ID we offer the same capability + */ + if (md->openpgp) + { + if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE + , &md->rbody, VID_OPENPGP)) + { + return STF_INTERNAL_ERROR; + } + } - r_sa.isasa_np = vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE; + /* Announce our ability to do eXtended AUTHentication to the peer */ + if (SEND_XAUTH_VID) + { + if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE + , &md->rbody, VID_MISC_XAUTH)) + { + return STF_INTERNAL_ERROR; + } + } - if (!out_struct(&r_sa, &isakmp_sa_desc, &md->rbody, &r_sa_pbs)) - return STF_INTERNAL_ERROR; - } - - /* SA body in and out */ - RETURN_STF_FAILURE(parse_isakmp_sa_body(ipsecdoisit, &proposal_pbs - ,&proposal, &r_sa_pbs, st, FALSE)); - - /* if enabled send Pluto Vendor ID */ - if (SEND_PLUTO_VID) - { + /* Announce our ability to do Dead Peer Detection to the peer */ if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE - , &md->rbody, VID_STRONGSWAN)) + , &md->rbody, VID_MISC_DPD)) { - return STF_INTERNAL_ERROR; + return STF_INTERNAL_ERROR; } - } - /* if enabled send Cisco Unity Vendor ID */ - if (SEND_CISCO_UNITY_VID) - { - if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE - , &md->rbody, VID_CISCO_UNITY)) + if (md->nat_traversal_vid && nat_traversal_enabled) { - return STF_INTERNAL_ERROR; + /* reply if NAT-Traversal draft is supported */ + st->nat_traversal = nat_traversal_vid_to_method(md->nat_traversal_vid); + + if (st->nat_traversal + && !out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE + , &md->rbody, md->nat_traversal_vid)) + { + return STF_INTERNAL_ERROR; + } } - } - /* - * if the peer sent an OpenPGP Vendor ID we offer the same capability - */ - if (md->openpgp) - { - if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE - , &md->rbody, VID_OPENPGP)) - { - return STF_INTERNAL_ERROR; - } - } + close_message(&md->rbody); - /* Announce our ability to do eXtended AUTHentication to the peer */ - if (SEND_XAUTH_VID) - { - if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE - , &md->rbody, VID_MISC_XAUTH)) - { - return STF_INTERNAL_ERROR; - } - } + /* save initiator SA for HASH */ + free(st->st_p1isa.ptr); + st->st_p1isa = chunk_create(sa_pd->pbs.start, pbs_room(&sa_pd->pbs)); + st->st_p1isa = chunk_clone(st->st_p1isa); - /* Announce our ability to do Dead Peer Detection to the peer */ - if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE - , &md->rbody, VID_MISC_DPD)) - { - return STF_INTERNAL_ERROR; - } - - if (md->nat_traversal_vid && nat_traversal_enabled) - { - /* reply if NAT-Traversal draft is supported */ - st->nat_traversal = nat_traversal_vid_to_method(md->nat_traversal_vid); - - if (st->nat_traversal - && !out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE - , &md->rbody, md->nat_traversal_vid)) - { - return STF_INTERNAL_ERROR; - } - } - - close_message(&md->rbody); - - /* save initiator SA for HASH */ - free(st->st_p1isa.ptr); - st->st_p1isa = chunk_create(sa_pd->pbs.start, pbs_room(&sa_pd->pbs)); - st->st_p1isa = chunk_clone(st->st_p1isa); - - return STF_OK; + return STF_OK; } /* STATE_MAIN_I1: HDR, SA --> auth dependent @@ -3250,92 +3250,92 @@ main_inI1_outR1(struct msg_digest *md) stf_status main_inR1_outI2(struct msg_digest *md) { - struct state *const st = md->st; + struct state *const st = md->st; - u_int8_t np = ISAKMP_NEXT_NONE; + u_int8_t np = ISAKMP_NEXT_NONE; - /* verify echoed SA */ - { - u_int32_t ipsecdoisit; - pb_stream proposal_pbs; - struct isakmp_proposal proposal; - struct payload_digest *const sapd = md->chain[ISAKMP_NEXT_SA]; - - RETURN_STF_FAILURE(preparse_isakmp_sa_body(&sapd->payload.sa - ,&sapd->pbs, &ipsecdoisit, &proposal_pbs, &proposal)); - if (proposal.isap_notrans != 1) + /* verify echoed SA */ { - loglog(RC_LOG_SERIOUS, "a single Transform is required in a selecting Oakley Proposal; found %u" - , (unsigned)proposal.isap_notrans); - RETURN_STF_FAILURE(BAD_PROPOSAL_SYNTAX); - } - RETURN_STF_FAILURE(parse_isakmp_sa_body(ipsecdoisit - , &proposal_pbs, &proposal, NULL, st, TRUE)); - } + u_int32_t ipsecdoisit; + pb_stream proposal_pbs; + struct isakmp_proposal proposal; + struct payload_digest *const sapd = md->chain[ISAKMP_NEXT_SA]; - if (nat_traversal_enabled && md->nat_traversal_vid) - { - st->nat_traversal = nat_traversal_vid_to_method(md->nat_traversal_vid); - plog("enabling possible NAT-traversal with method %s" - , bitnamesof(natt_type_bitnames, st->nat_traversal)); - } - if (st->nat_traversal & NAT_T_WITH_NATD) - { - np = (st->nat_traversal & NAT_T_WITH_RFC_VALUES) ? - ISAKMP_NEXT_NATD_RFC : ISAKMP_NEXT_NATD_DRAFTS; - } + RETURN_STF_FAILURE(preparse_isakmp_sa_body(&sapd->payload.sa + ,&sapd->pbs, &ipsecdoisit, &proposal_pbs, &proposal)); + if (proposal.isap_notrans != 1) + { + loglog(RC_LOG_SERIOUS, "a single Transform is required in a selecting Oakley Proposal; found %u" + , (unsigned)proposal.isap_notrans); + RETURN_STF_FAILURE(BAD_PROPOSAL_SYNTAX); + } + RETURN_STF_FAILURE(parse_isakmp_sa_body(ipsecdoisit + , &proposal_pbs, &proposal, NULL, st, TRUE)); + } - /**************** build output packet HDR;KE;Ni ****************/ + if (nat_traversal_enabled && md->nat_traversal_vid) + { + st->nat_traversal = nat_traversal_vid_to_method(md->nat_traversal_vid); + plog("enabling possible NAT-traversal with method %s" + , bitnamesof(natt_type_bitnames, st->nat_traversal)); + } + if (st->nat_traversal & NAT_T_WITH_NATD) + { + np = (st->nat_traversal & NAT_T_WITH_RFC_VALUES) ? + ISAKMP_NEXT_NATD_RFC : ISAKMP_NEXT_NATD_DRAFTS; + } - /* HDR out. - * We can't leave this to comm_handle() because the isa_np - * depends on the type of Auth (eventually). - */ - echo_hdr(md, FALSE, ISAKMP_NEXT_KE); + /**************** build output packet HDR;KE;Ni ****************/ - /* KE out */ - if (!build_and_ship_KE(st, &st->st_gi, st->st_oakley.group - , &md->rbody, ISAKMP_NEXT_NONCE)) - return STF_INTERNAL_ERROR; + /* HDR out. + * We can't leave this to comm_handle() because the isa_np + * depends on the type of Auth (eventually). + */ + echo_hdr(md, FALSE, ISAKMP_NEXT_KE); + + /* KE out */ + if (!build_and_ship_KE(st, &st->st_gi, st->st_oakley.group + , &md->rbody, ISAKMP_NEXT_NONCE)) + return STF_INTERNAL_ERROR; #ifdef DEBUG - /* Ni out */ - if (!build_and_ship_nonce(&st->st_ni, &md->rbody - , (cur_debugging & IMPAIR_BUST_MI2)? ISAKMP_NEXT_VID : np, "Ni")) - return STF_INTERNAL_ERROR; + /* Ni out */ + if (!build_and_ship_nonce(&st->st_ni, &md->rbody + , (cur_debugging & IMPAIR_BUST_MI2)? ISAKMP_NEXT_VID : np, "Ni")) + return STF_INTERNAL_ERROR; - if (cur_debugging & IMPAIR_BUST_MI2) - { - /* generate a pointless large VID payload to push message over MTU */ - pb_stream vid_pbs; + if (cur_debugging & IMPAIR_BUST_MI2) + { + /* generate a pointless large VID payload to push message over MTU */ + pb_stream vid_pbs; - if (!out_generic(np, &isakmp_vendor_id_desc, &md->rbody, &vid_pbs)) - return STF_INTERNAL_ERROR; - if (!out_zero(1500 /*MTU?*/, &vid_pbs, "Filler VID")) - return STF_INTERNAL_ERROR; - close_output_pbs(&vid_pbs); - } + if (!out_generic(np, &isakmp_vendor_id_desc, &md->rbody, &vid_pbs)) + return STF_INTERNAL_ERROR; + if (!out_zero(1500 /*MTU?*/, &vid_pbs, "Filler VID")) + return STF_INTERNAL_ERROR; + close_output_pbs(&vid_pbs); + } #else - /* Ni out */ - if (!build_and_ship_nonce(&st->st_ni, &md->rbody, np, "Ni")) - return STF_INTERNAL_ERROR; + /* Ni out */ + if (!build_and_ship_nonce(&st->st_ni, &md->rbody, np, "Ni")) + return STF_INTERNAL_ERROR; #endif - if (st->nat_traversal & NAT_T_WITH_NATD) - { - if (!nat_traversal_add_natd(ISAKMP_NEXT_NONE, &md->rbody, md)) - return STF_INTERNAL_ERROR; - } + if (st->nat_traversal & NAT_T_WITH_NATD) + { + if (!nat_traversal_add_natd(ISAKMP_NEXT_NONE, &md->rbody, md)) + return STF_INTERNAL_ERROR; + } - /* finish message */ - close_message(&md->rbody); + /* finish message */ + close_message(&md->rbody); - /* Reinsert the state, using the responder cookie we just received */ - unhash_state(st); - memcpy(st->st_rcookie, md->hdr.isa_rcookie, COOKIE_SIZE); - insert_state(st); /* needs cookies, connection, and msgid (0) */ + /* Reinsert the state, using the responder cookie we just received */ + unhash_state(st); + memcpy(st->st_rcookie, md->hdr.isa_rcookie, COOKIE_SIZE); + insert_state(st); /* needs cookies, connection, and msgid (0) */ - return STF_OK; + return STF_OK; } /* STATE_MAIN_R1: @@ -3343,140 +3343,140 @@ main_inR1_outI2(struct msg_digest *md) * * The following are not yet implemented: * PKE_AUTH: HDR, KE, [ HASH(1), ] PubKey_r, PubKey_r - * --> HDR, KE, PubKey_i, PubKey_i + * --> HDR, KE, PubKey_i, PubKey_i * RPKE_AUTH: - * HDR, [ HASH(1), ] Pubkey_r, Ke_i, Ke_i [,<Ke_i] - * --> HDR, PubKey_i, Ke_r, Ke_r + * HDR, [ HASH(1), ] Pubkey_r, Ke_i, Ke_i [,<Ke_i] + * --> HDR, PubKey_i, Ke_r, Ke_r */ stf_status main_inI2_outR2(struct msg_digest *md) { - struct state *const st = md->st; - pb_stream *keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs; - - /* send CR if auth is RSA and no preloaded RSA public key exists*/ - bool RSA_auth = st->st_oakley.auth == OAKLEY_RSA_SIG - || st->st_oakley.auth == XAUTHInitRSA - || st->st_oakley.auth == XAUTHRespRSA; - bool send_cr = !no_cr_send && RSA_auth && !has_preloaded_public_key(st); + struct state *const st = md->st; + pb_stream *keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs; - u_int8_t np = ISAKMP_NEXT_NONE; + /* send CR if auth is RSA and no preloaded RSA public key exists*/ + bool RSA_auth = st->st_oakley.auth == OAKLEY_RSA_SIG + || st->st_oakley.auth == XAUTHInitRSA + || st->st_oakley.auth == XAUTHRespRSA; + bool send_cr = !no_cr_send && RSA_auth && !has_preloaded_public_key(st); - /* KE in */ - RETURN_STF_FAILURE(accept_KE(&st->st_gi, "Gi", st->st_oakley.group, keyex_pbs)); + u_int8_t np = ISAKMP_NEXT_NONE; - /* Ni in */ - RETURN_STF_FAILURE(accept_nonce(md, &st->st_ni, "Ni")); + /* KE in */ + RETURN_STF_FAILURE(accept_KE(&st->st_gi, "Gi", st->st_oakley.group, keyex_pbs)); - if (st->nat_traversal & NAT_T_WITH_NATD) - { - nat_traversal_natd_lookup(md); + /* Ni in */ + RETURN_STF_FAILURE(accept_nonce(md, &st->st_ni, "Ni")); - np = (st->nat_traversal & NAT_T_WITH_RFC_VALUES) ? - ISAKMP_NEXT_NATD_RFC : ISAKMP_NEXT_NATD_DRAFTS; - } - if (st->nat_traversal) - { - nat_traversal_show_result(st->nat_traversal, md->sender_port); - } - if (st->nat_traversal & NAT_T_WITH_KA) - { - nat_traversal_new_ka_event(); - } + if (st->nat_traversal & NAT_T_WITH_NATD) + { + nat_traversal_natd_lookup(md); - /* decode certificate requests */ - st->st_connection->got_certrequest = FALSE; - decode_cr(md, st->st_connection); + np = (st->nat_traversal & NAT_T_WITH_RFC_VALUES) ? + ISAKMP_NEXT_NATD_RFC : ISAKMP_NEXT_NATD_DRAFTS; + } + if (st->nat_traversal) + { + nat_traversal_show_result(st->nat_traversal, md->sender_port); + } + if (st->nat_traversal & NAT_T_WITH_KA) + { + nat_traversal_new_ka_event(); + } - /**************** build output packet HDR;KE;Nr ****************/ + /* decode certificate requests */ + st->st_connection->got_certrequest = FALSE; + decode_cr(md, st->st_connection); - /* HDR out done */ + /**************** build output packet HDR;KE;Nr ****************/ - /* KE out */ - if (!build_and_ship_KE(st, &st->st_gr, st->st_oakley.group - , &md->rbody, ISAKMP_NEXT_NONCE)) - return STF_INTERNAL_ERROR; + /* HDR out done */ + + /* KE out */ + if (!build_and_ship_KE(st, &st->st_gr, st->st_oakley.group + , &md->rbody, ISAKMP_NEXT_NONCE)) + return STF_INTERNAL_ERROR; #ifdef DEBUG - /* Nr out */ - if (!build_and_ship_nonce(&st->st_nr, &md->rbody - , (cur_debugging & IMPAIR_BUST_MR2)? ISAKMP_NEXT_VID - : (send_cr? ISAKMP_NEXT_CR : np), "Nr")) - return STF_INTERNAL_ERROR; + /* Nr out */ + if (!build_and_ship_nonce(&st->st_nr, &md->rbody + , (cur_debugging & IMPAIR_BUST_MR2)? ISAKMP_NEXT_VID + : (send_cr? ISAKMP_NEXT_CR : np), "Nr")) + return STF_INTERNAL_ERROR; - if (cur_debugging & IMPAIR_BUST_MR2) - { - /* generate a pointless large VID payload to push message over MTU */ - pb_stream vid_pbs; + if (cur_debugging & IMPAIR_BUST_MR2) + { + /* generate a pointless large VID payload to push message over MTU */ + pb_stream vid_pbs; - if (!out_generic((send_cr)? ISAKMP_NEXT_CR : np, - &isakmp_vendor_id_desc, &md->rbody, &vid_pbs)) - return STF_INTERNAL_ERROR; - if (!out_zero(1500 /*MTU?*/, &vid_pbs, "Filler VID")) - return STF_INTERNAL_ERROR; - close_output_pbs(&vid_pbs); - } + if (!out_generic((send_cr)? ISAKMP_NEXT_CR : np, + &isakmp_vendor_id_desc, &md->rbody, &vid_pbs)) + return STF_INTERNAL_ERROR; + if (!out_zero(1500 /*MTU?*/, &vid_pbs, "Filler VID")) + return STF_INTERNAL_ERROR; + close_output_pbs(&vid_pbs); + } #else - /* Nr out */ - if (!build_and_ship_nonce(&st->st_nr, &md->rbody, - (send_cr)? ISAKMP_NEXT_CR : np, "Nr")) - return STF_INTERNAL_ERROR; + /* Nr out */ + if (!build_and_ship_nonce(&st->st_nr, &md->rbody, + (send_cr)? ISAKMP_NEXT_CR : np, "Nr")) + return STF_INTERNAL_ERROR; #endif - /* CR out */ - if (send_cr) - { - if (st->st_connection->kind == CK_PERMANENT) + /* CR out */ + if (send_cr) { - if (!build_and_ship_CR(CERT_X509_SIGNATURE - , st->st_connection->spd.that.ca - , &md->rbody, np)) - return STF_INTERNAL_ERROR; - } - else - { - generalName_t *ca = NULL; - - if (collect_rw_ca_candidates(md, &ca)) - { - generalName_t *gn; - - for (gn = ca; gn != NULL; gn = gn->next) + if (st->st_connection->kind == CK_PERMANENT) { - if (!build_and_ship_CR(CERT_X509_SIGNATURE, gn->name - , &md->rbody - , gn->next == NULL ? np : ISAKMP_NEXT_CR)) - return STF_INTERNAL_ERROR; + if (!build_and_ship_CR(CERT_X509_SIGNATURE + , st->st_connection->spd.that.ca + , &md->rbody, np)) + return STF_INTERNAL_ERROR; + } + else + { + generalName_t *ca = NULL; + + if (collect_rw_ca_candidates(md, &ca)) + { + generalName_t *gn; + + for (gn = ca; gn != NULL; gn = gn->next) + { + if (!build_and_ship_CR(CERT_X509_SIGNATURE, gn->name + , &md->rbody + , gn->next == NULL ? np : ISAKMP_NEXT_CR)) + return STF_INTERNAL_ERROR; + } + free_generalNames(ca, FALSE); + } + else + { + if (!build_and_ship_CR(CERT_X509_SIGNATURE, chunk_empty + , &md->rbody, np)) + return STF_INTERNAL_ERROR; + } } - free_generalNames(ca, FALSE); - } - else - { - if (!build_and_ship_CR(CERT_X509_SIGNATURE, chunk_empty - , &md->rbody, np)) - return STF_INTERNAL_ERROR; - } } - } - if (st->nat_traversal & NAT_T_WITH_NATD) - { - if (!nat_traversal_add_natd(ISAKMP_NEXT_NONE, &md->rbody, md)) - return STF_INTERNAL_ERROR; - } + if (st->nat_traversal & NAT_T_WITH_NATD) + { + if (!nat_traversal_add_natd(ISAKMP_NEXT_NONE, &md->rbody, md)) + return STF_INTERNAL_ERROR; + } - /* finish message */ - close_message(&md->rbody); + /* finish message */ + close_message(&md->rbody); - /* next message will be encrypted, but not this one. - * We could defer this calculation. - */ - compute_dh_shared(st, st->st_gi, st->st_oakley.group); - if (!generate_skeyids_iv(st)) - return STF_FAIL + AUTHENTICATION_FAILED; - update_iv(st); + /* next message will be encrypted, but not this one. + * We could defer this calculation. + */ + compute_dh_shared(st, st->st_gi, st->st_oakley.group); + if (!generate_skeyids_iv(st)) + return STF_FAIL + AUTHENTICATION_FAILED; + update_iv(st); - return STF_OK; + return STF_OK; } /* STATE_MAIN_I2: @@ -3485,172 +3485,172 @@ main_inI2_outR2(struct msg_digest *md) * * The following are not yet implemented. * SMF_PKE_AUTH: HDR, KE, PubKey_i, PubKey_i - * --> HDR*, HASH_I + * --> HDR*, HASH_I * SMF_RPKE_AUTH: HDR, PubKey_i, Ke_r, Ke_r - * --> HDR*, HASH_I + * --> HDR*, HASH_I */ stf_status main_inR2_outI3(struct msg_digest *md) { - struct state *const st = md->st; - pb_stream *const keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs; - pb_stream id_pbs; /* ID Payload; also used for hash calculation */ + struct state *const st = md->st; + pb_stream *const keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs; + pb_stream id_pbs; /* ID Payload; also used for hash calculation */ - certpolicy_t cert_policy = st->st_connection->spd.this.sendcert; - cert_t mycert = st->st_connection->spd.this.cert; - bool requested, send_cert, send_cr; + certpolicy_t cert_policy = st->st_connection->spd.this.sendcert; + cert_t mycert = st->st_connection->spd.this.cert; + bool requested, send_cert, send_cr; - bool RSA_auth = st->st_oakley.auth == OAKLEY_RSA_SIG - || st->st_oakley.auth == XAUTHInitRSA - || st->st_oakley.auth == XAUTHRespRSA; + bool RSA_auth = st->st_oakley.auth == OAKLEY_RSA_SIG + || st->st_oakley.auth == XAUTHInitRSA + || st->st_oakley.auth == XAUTHRespRSA; - int auth_payload = RSA_auth ? ISAKMP_NEXT_SIG : ISAKMP_NEXT_HASH; + int auth_payload = RSA_auth ? ISAKMP_NEXT_SIG : ISAKMP_NEXT_HASH; - /* KE in */ - RETURN_STF_FAILURE(accept_KE(&st->st_gr, "Gr", st->st_oakley.group, keyex_pbs)); + /* KE in */ + RETURN_STF_FAILURE(accept_KE(&st->st_gr, "Gr", st->st_oakley.group, keyex_pbs)); - /* Nr in */ - RETURN_STF_FAILURE(accept_nonce(md, &st->st_nr, "Nr")); + /* Nr in */ + RETURN_STF_FAILURE(accept_nonce(md, &st->st_nr, "Nr")); - /* decode certificate requests */ - st->st_connection->got_certrequest = FALSE; - decode_cr(md, st->st_connection); + /* decode certificate requests */ + st->st_connection->got_certrequest = FALSE; + decode_cr(md, st->st_connection); - /* free collected certificate requests since as initiator - * we don't heed them anyway - */ - free_generalNames(st->st_connection->requested_ca, TRUE); - st->st_connection->requested_ca = NULL; + /* free collected certificate requests since as initiator + * we don't heed them anyway + */ + free_generalNames(st->st_connection->requested_ca, TRUE); + st->st_connection->requested_ca = NULL; - /* send certificate if auth is RSA, we have one and we want - * or are requested to send it - */ - requested = cert_policy == CERT_SEND_IF_ASKED - && st->st_connection->got_certrequest; - send_cert = RSA_auth && mycert.type != CERT_NONE - && (cert_policy == CERT_ALWAYS_SEND || requested); + /* send certificate if auth is RSA, we have one and we want + * or are requested to send it + */ + requested = cert_policy == CERT_SEND_IF_ASKED + && st->st_connection->got_certrequest; + send_cert = RSA_auth && mycert.type != CERT_NONE + && (cert_policy == CERT_ALWAYS_SEND || requested); - /* send certificate request if we don't have a preloaded RSA public key */ - send_cr = !no_cr_send && send_cert && !has_preloaded_public_key(st); + /* send certificate request if we don't have a preloaded RSA public key */ + send_cr = !no_cr_send && send_cert && !has_preloaded_public_key(st); - /* done parsing; initialize crypto */ - compute_dh_shared(st, st->st_gr, st->st_oakley.group); - if (!generate_skeyids_iv(st)) - return STF_FAIL + AUTHENTICATION_FAILED; + /* done parsing; initialize crypto */ + compute_dh_shared(st, st->st_gr, st->st_oakley.group); + if (!generate_skeyids_iv(st)) + return STF_FAIL + AUTHENTICATION_FAILED; - if (st->nat_traversal & NAT_T_WITH_NATD) - { - nat_traversal_natd_lookup(md); - } - if (st->nat_traversal) - { - nat_traversal_show_result(st->nat_traversal, md->sender_port); - } - if (st->nat_traversal & NAT_T_WITH_KA) - { - nat_traversal_new_ka_event(); - } - - /*************** build output packet HDR*;IDii;HASH/SIG_I ***************/ - /* ??? NOTE: this is almost the same as main_inI3_outR3's code */ - - /* HDR* out done */ - - /* IDii out */ - { - struct isakmp_ipsec_id id_hd; - chunk_t id_b; - - build_id_payload(&id_hd, &id_b, &st->st_connection->spd.this); - id_hd.isaiid_np = (send_cert)? ISAKMP_NEXT_CERT : auth_payload; - if (!out_struct(&id_hd, &isakmp_ipsec_identification_desc, &md->rbody, &id_pbs) - || !out_chunk(id_b, &id_pbs, "my identity")) - return STF_INTERNAL_ERROR; - close_output_pbs(&id_pbs); - } - - /* CERT out */ - if (RSA_auth) - { - DBG(DBG_CONTROL, - DBG_log("our certificate policy is %s" - , enum_name(&cert_policy_names, cert_policy)) - ) - if (mycert.type != CERT_NONE) + if (st->nat_traversal & NAT_T_WITH_NATD) { - const char *request_text = ""; - - if (cert_policy == CERT_SEND_IF_ASKED) - request_text = (send_cert)? "upon request":"without request"; - plog("we have a cert %s sending it %s" - , send_cert? "and are":"but are not", request_text); + nat_traversal_natd_lookup(md); } - else + if (st->nat_traversal) { - plog("we don't have a cert"); + nat_traversal_show_result(st->nat_traversal, md->sender_port); + } + if (st->nat_traversal & NAT_T_WITH_KA) + { + nat_traversal_new_ka_event(); } - } - if (send_cert) - { - pb_stream cert_pbs; - struct isakmp_cert cert_hd; - cert_hd.isacert_np = (send_cr)? ISAKMP_NEXT_CR : ISAKMP_NEXT_SIG; - cert_hd.isacert_type = mycert.type; + /*************** build output packet HDR*;IDii;HASH/SIG_I ***************/ + /* ??? NOTE: this is almost the same as main_inI3_outR3's code */ - if (!out_struct(&cert_hd, &isakmp_ipsec_certificate_desc, &md->rbody, &cert_pbs)) - return STF_INTERNAL_ERROR; - if (!out_chunk(get_mycert(mycert), &cert_pbs, "CERT")) - return STF_INTERNAL_ERROR; - close_output_pbs(&cert_pbs); - } + /* HDR* out done */ - /* CR out */ - if (send_cr) - { - if (!build_and_ship_CR(mycert.type, st->st_connection->spd.that.ca - , &md->rbody, ISAKMP_NEXT_SIG)) - return STF_INTERNAL_ERROR; - } + /* IDii out */ + { + struct isakmp_ipsec_id id_hd; + chunk_t id_b; + + build_id_payload(&id_hd, &id_b, &st->st_connection->spd.this); + id_hd.isaiid_np = (send_cert)? ISAKMP_NEXT_CERT : auth_payload; + if (!out_struct(&id_hd, &isakmp_ipsec_identification_desc, &md->rbody, &id_pbs) + || !out_chunk(id_b, &id_pbs, "my identity")) + return STF_INTERNAL_ERROR; + close_output_pbs(&id_pbs); + } + + /* CERT out */ + if (RSA_auth) + { + DBG(DBG_CONTROL, + DBG_log("our certificate policy is %s" + , enum_name(&cert_policy_names, cert_policy)) + ) + if (mycert.type != CERT_NONE) + { + const char *request_text = ""; + + if (cert_policy == CERT_SEND_IF_ASKED) + request_text = (send_cert)? "upon request":"without request"; + plog("we have a cert %s sending it %s" + , send_cert? "and are":"but are not", request_text); + } + else + { + plog("we don't have a cert"); + } + } + if (send_cert) + { + pb_stream cert_pbs; + + struct isakmp_cert cert_hd; + cert_hd.isacert_np = (send_cr)? ISAKMP_NEXT_CR : ISAKMP_NEXT_SIG; + cert_hd.isacert_type = mycert.type; + + if (!out_struct(&cert_hd, &isakmp_ipsec_certificate_desc, &md->rbody, &cert_pbs)) + return STF_INTERNAL_ERROR; + if (!out_chunk(get_mycert(mycert), &cert_pbs, "CERT")) + return STF_INTERNAL_ERROR; + close_output_pbs(&cert_pbs); + } + + /* CR out */ + if (send_cr) + { + if (!build_and_ship_CR(mycert.type, st->st_connection->spd.that.ca + , &md->rbody, ISAKMP_NEXT_SIG)) + return STF_INTERNAL_ERROR; + } /* HASH_I or SIG_I out */ - { - u_char hash_val[MAX_DIGEST_LEN]; - size_t hash_len = main_mode_hash(st, hash_val, TRUE, &id_pbs); - - if (auth_payload == ISAKMP_NEXT_HASH) { - /* HASH_I out */ - if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_hash_desc, &md->rbody - , hash_val, hash_len, "HASH_I")) - return STF_INTERNAL_ERROR; + u_char hash_val[MAX_DIGEST_LEN]; + size_t hash_len = main_mode_hash(st, hash_val, TRUE, &id_pbs); + + if (auth_payload == ISAKMP_NEXT_HASH) + { + /* HASH_I out */ + if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_hash_desc, &md->rbody + , hash_val, hash_len, "HASH_I")) + return STF_INTERNAL_ERROR; + } + else + { + /* SIG_I out */ + u_char sig_val[RSA_MAX_OCTETS]; + size_t sig_len = RSA_sign_hash(st->st_connection + , sig_val, hash_val, hash_len); + + if (sig_len == 0) + { + loglog(RC_LOG_SERIOUS, "unable to locate my private key for RSA Signature"); + return STF_FAIL + AUTHENTICATION_FAILED; + } + + if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_signature_desc + , &md->rbody, sig_val, sig_len, "SIG_I")) + return STF_INTERNAL_ERROR; + } } - else - { - /* SIG_I out */ - u_char sig_val[RSA_MAX_OCTETS]; - size_t sig_len = RSA_sign_hash(st->st_connection - , sig_val, hash_val, hash_len); - if (sig_len == 0) - { - loglog(RC_LOG_SERIOUS, "unable to locate my private key for RSA Signature"); - return STF_FAIL + AUTHENTICATION_FAILED; - } + /* encrypt message, except for fixed part of header */ - if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_signature_desc - , &md->rbody, sig_val, sig_len, "SIG_I")) - return STF_INTERNAL_ERROR; - } - } + /* st_new_iv was computed by generate_skeyids_iv */ + if (!encrypt_message(&md->rbody, st)) + return STF_INTERNAL_ERROR; /* ??? we may be partly committed */ - /* encrypt message, except for fixed part of header */ - - /* st_new_iv was computed by generate_skeyids_iv */ - if (!encrypt_message(&md->rbody, st)) - return STF_INTERNAL_ERROR; /* ??? we may be partly committed */ - - return STF_OK; + return STF_OK; } /* Shared logic for asynchronous lookup of DNS KEY records. @@ -3658,31 +3658,31 @@ main_inR2_outI3(struct msg_digest *md) */ enum key_oppo_step { - kos_null, - kos_his_txt + kos_null, + kos_his_txt #ifdef USE_KEYRR - , kos_his_key + , kos_his_key #endif }; struct key_continuation { - struct adns_continuation ac; /* common prefix */ - struct msg_digest *md; - enum key_oppo_step step; - bool failure_ok; - err_t last_ugh; + struct adns_continuation ac; /* common prefix */ + struct msg_digest *md; + enum key_oppo_step step; + bool failure_ok; + err_t last_ugh; }; typedef stf_status (key_tail_fn)(struct msg_digest *md - , struct key_continuation *kc); + , struct key_continuation *kc); static void report_key_dns_failure(struct id *id, err_t ugh) { - char id_buf[BUF_LEN]; /* arbitrary limit on length of ID reported */ + char id_buf[BUF_LEN]; /* arbitrary limit on length of ID reported */ - (void) idtoa(id, id_buf, sizeof(id_buf)); - loglog(RC_LOG_SERIOUS, "no RSA public key known for '%s'" - "; DNS search for KEY failed (%s)", id_buf, ugh); + (void) idtoa(id, id_buf, sizeof(id_buf)); + loglog(RC_LOG_SERIOUS, "no RSA public key known for '%s'" + "; DNS search for KEY failed (%s)", id_buf, ugh); } @@ -3695,134 +3695,134 @@ report_key_dns_failure(struct id *id, err_t ugh) */ static stf_status main_id_and_auth(struct msg_digest *md - , bool initiator /* are we the Initiator? */ - , cont_fn_t cont_fn /* continuation function */ - , const struct key_continuation *kc /* current state, can be NULL */ + , bool initiator /* are we the Initiator? */ + , cont_fn_t cont_fn /* continuation function */ + , const struct key_continuation *kc /* current state, can be NULL */ ) { - struct state *st = md->st; - u_char hash_val[MAX_DIGEST_LEN]; - size_t hash_len; - struct id peer; - stf_status r = STF_OK; + struct state *st = md->st; + u_char hash_val[MAX_DIGEST_LEN]; + size_t hash_len; + struct id peer; + stf_status r = STF_OK; - /* ID Payload in */ - if (!decode_peer_id(md, &peer)) - return STF_FAIL + INVALID_ID_INFORMATION; + /* ID Payload in */ + if (!decode_peer_id(md, &peer)) + return STF_FAIL + INVALID_ID_INFORMATION; - /* Hash the ID Payload. - * main_mode_hash requires idpl->cur to be at end of payload - * so we temporarily set if so. - */ - { - pb_stream *idpl = &md->chain[ISAKMP_NEXT_ID]->pbs; - u_int8_t *old_cur = idpl->cur; - - idpl->cur = idpl->roof; - hash_len = main_mode_hash(st, hash_val, !initiator, idpl); - idpl->cur = old_cur; - } - - switch (st->st_oakley.auth) - { - case OAKLEY_PRESHARED_KEY: - case XAUTHInitPreShared: - case XAUTHRespPreShared: + /* Hash the ID Payload. + * main_mode_hash requires idpl->cur to be at end of payload + * so we temporarily set if so. + */ { - pb_stream *const hash_pbs = &md->chain[ISAKMP_NEXT_HASH]->pbs; + pb_stream *idpl = &md->chain[ISAKMP_NEXT_ID]->pbs; + u_int8_t *old_cur = idpl->cur; - if (pbs_left(hash_pbs) != hash_len - || memcmp(hash_pbs->cur, hash_val, hash_len) != 0) - { - DBG_cond_dump(DBG_CRYPT, "received HASH:" - , hash_pbs->cur, pbs_left(hash_pbs)); - loglog(RC_LOG_SERIOUS, "received Hash Payload does not match computed value"); - /* XXX Could send notification back */ - r = STF_FAIL + INVALID_HASH_INFORMATION; - } + idpl->cur = idpl->roof; + hash_len = main_mode_hash(st, hash_val, !initiator, idpl); + idpl->cur = old_cur; } - break; - case OAKLEY_RSA_SIG: - case XAUTHInitRSA: - case XAUTHRespRSA: - r = RSA_check_signature(&peer, st, hash_val, hash_len - , &md->chain[ISAKMP_NEXT_SIG]->pbs -#ifdef USE_KEYRR - , kc == NULL? NULL : kc->ac.keys_from_dns -#endif /* USE_KEYRR */ - , kc == NULL? NULL : kc->ac.gateways_from_dns - ); - - if (r == STF_SUSPEND) + switch (st->st_oakley.auth) { - /* initiate/resume asynchronous DNS lookup for key */ - struct key_continuation *nkc = malloc_thing(struct key_continuation); - enum key_oppo_step step_done = kc == NULL? kos_null : kc->step; - err_t ugh = NULL; + case OAKLEY_PRESHARED_KEY: + case XAUTHInitPreShared: + case XAUTHRespPreShared: + { + pb_stream *const hash_pbs = &md->chain[ISAKMP_NEXT_HASH]->pbs; - /* Record that state is used by a suspended md */ - passert(st->st_suspended_md == NULL); - st->st_suspended_md = md; + if (pbs_left(hash_pbs) != hash_len + || memcmp(hash_pbs->cur, hash_val, hash_len) != 0) + { + DBG_cond_dump(DBG_CRYPT, "received HASH:" + , hash_pbs->cur, pbs_left(hash_pbs)); + loglog(RC_LOG_SERIOUS, "received Hash Payload does not match computed value"); + /* XXX Could send notification back */ + r = STF_FAIL + INVALID_HASH_INFORMATION; + } + } + break; - nkc->failure_ok = FALSE; - nkc->md = md; - - switch (step_done) - { - case kos_null: - /* first try: look for the TXT records */ - nkc->step = kos_his_txt; + case OAKLEY_RSA_SIG: + case XAUTHInitRSA: + case XAUTHRespRSA: + r = RSA_check_signature(&peer, st, hash_val, hash_len + , &md->chain[ISAKMP_NEXT_SIG]->pbs #ifdef USE_KEYRR - nkc->failure_ok = TRUE; + , kc == NULL? NULL : kc->ac.keys_from_dns +#endif /* USE_KEYRR */ + , kc == NULL? NULL : kc->ac.gateways_from_dns + ); + + if (r == STF_SUSPEND) + { + /* initiate/resume asynchronous DNS lookup for key */ + struct key_continuation *nkc = malloc_thing(struct key_continuation); + enum key_oppo_step step_done = kc == NULL? kos_null : kc->step; + err_t ugh = NULL; + + /* Record that state is used by a suspended md */ + passert(st->st_suspended_md == NULL); + st->st_suspended_md = md; + + nkc->failure_ok = FALSE; + nkc->md = md; + + switch (step_done) + { + case kos_null: + /* first try: look for the TXT records */ + nkc->step = kos_his_txt; +#ifdef USE_KEYRR + nkc->failure_ok = TRUE; #endif - ugh = start_adns_query(&peer - , &peer /* SG itself */ - , T_TXT - , cont_fn - , &nkc->ac); - break; + ugh = start_adns_query(&peer + , &peer /* SG itself */ + , T_TXT + , cont_fn + , &nkc->ac); + break; #ifdef USE_KEYRR - case kos_his_txt: - /* second try: look for the KEY records */ - nkc->step = kos_his_key; - ugh = start_adns_query(&peer - , NULL /* no sgw for KEY */ - , T_KEY - , cont_fn - , &nkc->ac); - break; + case kos_his_txt: + /* second try: look for the KEY records */ + nkc->step = kos_his_key; + ugh = start_adns_query(&peer + , NULL /* no sgw for KEY */ + , T_KEY + , cont_fn + , &nkc->ac); + break; #endif /* USE_KEYRR */ - default: - bad_case(step_done); - } + default: + bad_case(step_done); + } - if (ugh != NULL) - { - report_key_dns_failure(&peer, ugh); - st->st_suspended_md = NULL; - r = STF_FAIL + INVALID_KEY_INFORMATION; - } + if (ugh != NULL) + { + report_key_dns_failure(&peer, ugh); + st->st_suspended_md = NULL; + r = STF_FAIL + INVALID_KEY_INFORMATION; + } + } + break; + + default: + bad_case(st->st_oakley.auth); } - break; + if (r != STF_OK) + return r; + + DBG(DBG_CRYPT, DBG_log("authentication succeeded")); + + /* + * With the peer ID known, let's see if we need to switch connections. + */ + if (!switch_connection(md, &peer, initiator)) + return STF_FAIL + INVALID_ID_INFORMATION; - default: - bad_case(st->st_oakley.auth); - } - if (r != STF_OK) return r; - - DBG(DBG_CRYPT, DBG_log("authentication succeeded")); - - /* - * With the peer ID known, let's see if we need to switch connections. - */ - if (!switch_connection(md, &peer, initiator)) - return STF_FAIL + INVALID_ID_INFORMATION; - - return r; } /* This continuation is called as part of either @@ -3851,41 +3851,41 @@ key_continue(struct adns_continuation *cr , err_t ugh , key_tail_fn *tail) { - struct key_continuation *kc = (void *)cr; - struct state *st = kc->md->st; + struct key_continuation *kc = (void *)cr; + struct state *st = kc->md->st; - passert(cur_state == NULL); + passert(cur_state == NULL); - /* if st == NULL, our state has been deleted -- just clean up */ - if (st != NULL) - { - stf_status r; - - passert(st->st_suspended_md == kc->md); - st->st_suspended_md = NULL; /* no longer connected or suspended */ - cur_state = st; - - if (!kc->failure_ok && ugh != NULL) - { - report_key_dns_failure(&st->st_connection->spd.that.id, ugh); - r = STF_FAIL + INVALID_KEY_INFORMATION; - } - else + /* if st == NULL, our state has been deleted -- just clean up */ + if (st != NULL) { + stf_status r; + + passert(st->st_suspended_md == kc->md); + st->st_suspended_md = NULL; /* no longer connected or suspended */ + cur_state = st; + + if (!kc->failure_ok && ugh != NULL) + { + report_key_dns_failure(&st->st_connection->spd.that.id, ugh); + r = STF_FAIL + INVALID_KEY_INFORMATION; + } + else + { #ifdef USE_KEYRR - passert(kc->step == kos_his_txt || kc->step == kos_his_key); + passert(kc->step == kos_his_txt || kc->step == kos_his_key); #else - passert(kc->step == kos_his_txt); + passert(kc->step == kos_his_txt); #endif - kc->last_ugh = ugh; /* record previous error in case we need it */ - r = (*tail)(kc->md, kc); + kc->last_ugh = ugh; /* record previous error in case we need it */ + r = (*tail)(kc->md, kc); + } + complete_state_transition(&kc->md, r); } - complete_state_transition(&kc->md, r); - } - if (kc->md != NULL) - release_md(kc->md); - cur_state = NULL; + if (kc->md != NULL) + release_md(kc->md); + cur_state = NULL; } /* STATE_MAIN_R2: @@ -3899,174 +3899,174 @@ key_continue(struct adns_continuation *cr * - main_inI3_outR3_tail to finish or suspend for DNS lookup * - main_inI3_outR3_continue to start main_inI3_outR3_tail again */ -static key_tail_fn main_inI3_outR3_tail; /* forward */ +static key_tail_fn main_inI3_outR3_tail; /* forward */ stf_status main_inI3_outR3(struct msg_digest *md) { - return main_inI3_outR3_tail(md, NULL); + return main_inI3_outR3_tail(md, NULL); } static void main_inI3_outR3_continue(struct adns_continuation *cr, err_t ugh) { - key_continue(cr, ugh, main_inI3_outR3_tail); + key_continue(cr, ugh, main_inI3_outR3_tail); } static stf_status main_inI3_outR3_tail(struct msg_digest *md , struct key_continuation *kc) { - struct state *const st = md->st; - u_int8_t auth_payload; - pb_stream r_id_pbs; /* ID Payload; also used for hash calculation */ - certpolicy_t cert_policy; - cert_t mycert; - bool RSA_auth; - bool send_cert; - bool requested; + struct state *const st = md->st; + u_int8_t auth_payload; + pb_stream r_id_pbs; /* ID Payload; also used for hash calculation */ + certpolicy_t cert_policy; + cert_t mycert; + bool RSA_auth; + bool send_cert; + bool requested; - /* ID and HASH_I or SIG_I in - * Note: this may switch the connection being used! - */ - { - stf_status r = main_id_and_auth(md, FALSE - , main_inI3_outR3_continue - , kc); - - if (r != STF_OK) - return r; - } - - /* send certificate if auth is RSA, we have one and we want - * or are requested to send it - */ - cert_policy = st->st_connection->spd.this.sendcert; - mycert = st->st_connection->spd.this.cert; - requested = cert_policy == CERT_SEND_IF_ASKED - && st->st_connection->got_certrequest; - RSA_auth = st->st_oakley.auth == OAKLEY_RSA_SIG - || st->st_oakley.auth == XAUTHInitRSA - || st->st_oakley.auth == XAUTHRespRSA; - send_cert = RSA_auth - && mycert.type != CERT_NONE - && (cert_policy == CERT_ALWAYS_SEND || requested); - - /*************** build output packet HDR*;IDir;HASH/SIG_R ***************/ - /* proccess_packet() would automatically generate the HDR* - * payload if smc->first_out_payload is not ISAKMP_NEXT_NONE. - * We don't do this because we wish there to be no partially - * built output packet if we need to suspend for asynch DNS. - */ - /* ??? NOTE: this is almost the same as main_inR2_outI3's code */ - - /* HDR* out - * If auth were PKE_AUTH or RPKE_AUTH, ISAKMP_NEXT_HASH would - * be first payload. - */ - echo_hdr(md, TRUE, ISAKMP_NEXT_ID); - - auth_payload = RSA_auth ? ISAKMP_NEXT_SIG : ISAKMP_NEXT_HASH; - - /* IDir out */ - { - /* id_hd should be struct isakmp_id, but struct isakmp_ipsec_id - * allows build_id_payload() to work for both phases. + /* ID and HASH_I or SIG_I in + * Note: this may switch the connection being used! */ - struct isakmp_ipsec_id id_hd; - chunk_t id_b; - - build_id_payload(&id_hd, &id_b, &st->st_connection->spd.this); - id_hd.isaiid_np = (send_cert)? ISAKMP_NEXT_CERT : auth_payload; - if (!out_struct(&id_hd, &isakmp_ipsec_identification_desc, &md->rbody, &r_id_pbs) - || !out_chunk(id_b, &r_id_pbs, "my identity")) - return STF_INTERNAL_ERROR; - close_output_pbs(&r_id_pbs); - } - - /* CERT out */ - if (RSA_auth) - { - DBG(DBG_CONTROL, - DBG_log("our certificate policy is %s" - , enum_name(&cert_policy_names, cert_policy)) - ) - if (mycert.type != CERT_NONE) { - const char *request_text = ""; + stf_status r = main_id_and_auth(md, FALSE + , main_inI3_outR3_continue + , kc); - if (cert_policy == CERT_SEND_IF_ASKED) - request_text = (send_cert)? "upon request":"without request"; - plog("we have a cert %s sending it %s" - , send_cert? "and are":"but are not", request_text); + if (r != STF_OK) + return r; } - else + + /* send certificate if auth is RSA, we have one and we want + * or are requested to send it + */ + cert_policy = st->st_connection->spd.this.sendcert; + mycert = st->st_connection->spd.this.cert; + requested = cert_policy == CERT_SEND_IF_ASKED + && st->st_connection->got_certrequest; + RSA_auth = st->st_oakley.auth == OAKLEY_RSA_SIG + || st->st_oakley.auth == XAUTHInitRSA + || st->st_oakley.auth == XAUTHRespRSA; + send_cert = RSA_auth + && mycert.type != CERT_NONE + && (cert_policy == CERT_ALWAYS_SEND || requested); + + /*************** build output packet HDR*;IDir;HASH/SIG_R ***************/ + /* proccess_packet() would automatically generate the HDR* + * payload if smc->first_out_payload is not ISAKMP_NEXT_NONE. + * We don't do this because we wish there to be no partially + * built output packet if we need to suspend for asynch DNS. + */ + /* ??? NOTE: this is almost the same as main_inR2_outI3's code */ + + /* HDR* out + * If auth were PKE_AUTH or RPKE_AUTH, ISAKMP_NEXT_HASH would + * be first payload. + */ + echo_hdr(md, TRUE, ISAKMP_NEXT_ID); + + auth_payload = RSA_auth ? ISAKMP_NEXT_SIG : ISAKMP_NEXT_HASH; + + /* IDir out */ { - plog("we don't have a cert"); + /* id_hd should be struct isakmp_id, but struct isakmp_ipsec_id + * allows build_id_payload() to work for both phases. + */ + struct isakmp_ipsec_id id_hd; + chunk_t id_b; + + build_id_payload(&id_hd, &id_b, &st->st_connection->spd.this); + id_hd.isaiid_np = (send_cert)? ISAKMP_NEXT_CERT : auth_payload; + if (!out_struct(&id_hd, &isakmp_ipsec_identification_desc, &md->rbody, &r_id_pbs) + || !out_chunk(id_b, &r_id_pbs, "my identity")) + return STF_INTERNAL_ERROR; + close_output_pbs(&r_id_pbs); } - } - if (send_cert) - { - pb_stream cert_pbs; - struct isakmp_cert cert_hd; - cert_hd.isacert_np = ISAKMP_NEXT_SIG; - cert_hd.isacert_type = mycert.type; - - if (!out_struct(&cert_hd, &isakmp_ipsec_certificate_desc, &md->rbody, &cert_pbs)) - return STF_INTERNAL_ERROR; - if (!out_chunk(get_mycert(mycert), &cert_pbs, "CERT")) - return STF_INTERNAL_ERROR; - close_output_pbs(&cert_pbs); - } - - /* HASH_R or SIG_R out */ - { - u_char hash_val[MAX_DIGEST_LEN]; - size_t hash_len = main_mode_hash(st, hash_val, FALSE, &r_id_pbs); - - if (auth_payload == ISAKMP_NEXT_HASH) + /* CERT out */ + if (RSA_auth) { - /* HASH_R out */ - if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_hash_desc, &md->rbody - , hash_val, hash_len, "HASH_R")) + DBG(DBG_CONTROL, + DBG_log("our certificate policy is %s" + , enum_name(&cert_policy_names, cert_policy)) + ) + if (mycert.type != CERT_NONE) + { + const char *request_text = ""; + + if (cert_policy == CERT_SEND_IF_ASKED) + request_text = (send_cert)? "upon request":"without request"; + plog("we have a cert %s sending it %s" + , send_cert? "and are":"but are not", request_text); + } + else + { + plog("we don't have a cert"); + } + } + if (send_cert) + { + pb_stream cert_pbs; + + struct isakmp_cert cert_hd; + cert_hd.isacert_np = ISAKMP_NEXT_SIG; + cert_hd.isacert_type = mycert.type; + + if (!out_struct(&cert_hd, &isakmp_ipsec_certificate_desc, &md->rbody, &cert_pbs)) return STF_INTERNAL_ERROR; + if (!out_chunk(get_mycert(mycert), &cert_pbs, "CERT")) + return STF_INTERNAL_ERROR; + close_output_pbs(&cert_pbs); } - else + + /* HASH_R or SIG_R out */ { - /* SIG_R out */ - u_char sig_val[RSA_MAX_OCTETS]; - size_t sig_len = RSA_sign_hash(st->st_connection - , sig_val, hash_val, hash_len); + u_char hash_val[MAX_DIGEST_LEN]; + size_t hash_len = main_mode_hash(st, hash_val, FALSE, &r_id_pbs); - if (sig_len == 0) - { - loglog(RC_LOG_SERIOUS, "unable to locate my private key for RSA Signature"); - return STF_FAIL + AUTHENTICATION_FAILED; - } + if (auth_payload == ISAKMP_NEXT_HASH) + { + /* HASH_R out */ + if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_hash_desc, &md->rbody + , hash_val, hash_len, "HASH_R")) + return STF_INTERNAL_ERROR; + } + else + { + /* SIG_R out */ + u_char sig_val[RSA_MAX_OCTETS]; + size_t sig_len = RSA_sign_hash(st->st_connection + , sig_val, hash_val, hash_len); - if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_signature_desc - , &md->rbody, sig_val, sig_len, "SIG_R")) - return STF_INTERNAL_ERROR; + if (sig_len == 0) + { + loglog(RC_LOG_SERIOUS, "unable to locate my private key for RSA Signature"); + return STF_FAIL + AUTHENTICATION_FAILED; + } + + if (!out_generic_raw(ISAKMP_NEXT_NONE, &isakmp_signature_desc + , &md->rbody, sig_val, sig_len, "SIG_R")) + return STF_INTERNAL_ERROR; + } } - } - /* encrypt message, sans fixed part of header */ + /* encrypt message, sans fixed part of header */ - if (!encrypt_message(&md->rbody, st)) - return STF_INTERNAL_ERROR; /* ??? we may be partly committed */ + if (!encrypt_message(&md->rbody, st)) + return STF_INTERNAL_ERROR; /* ??? we may be partly committed */ - /* Last block of Phase 1 (R3), kept for Phase 2 IV generation */ - DBG_cond_dump(DBG_CRYPT, "last encrypted block of Phase 1:" - , st->st_new_iv, st->st_new_iv_len); + /* Last block of Phase 1 (R3), kept for Phase 2 IV generation */ + DBG_cond_dump(DBG_CRYPT, "last encrypted block of Phase 1:" + , st->st_new_iv, st->st_new_iv_len); - ISAKMP_SA_established(st->st_connection, st->st_serialno); + ISAKMP_SA_established(st->st_connection, st->st_serialno); - /* Save Phase 1 IV */ - st->st_ph1_iv_len = st->st_new_iv_len; - set_ph1_iv(st, st->st_new_iv); + /* Save Phase 1 IV */ + st->st_ph1_iv_len = st->st_new_iv_len; + set_ph1_iv(st, st->st_new_iv); - return STF_OK; + return STF_OK; } /* STATE_MAIN_I3: @@ -4079,48 +4079,48 @@ main_inI3_outR3_tail(struct msg_digest *md * - main_inR3_continue to start main_inR3_tail again */ -static key_tail_fn main_inR3_tail; /* forward */ +static key_tail_fn main_inR3_tail; /* forward */ stf_status main_inR3(struct msg_digest *md) { - return main_inR3_tail(md, NULL); + return main_inR3_tail(md, NULL); } static void main_inR3_continue(struct adns_continuation *cr, err_t ugh) { - key_continue(cr, ugh, main_inR3_tail); + key_continue(cr, ugh, main_inR3_tail); } static stf_status main_inR3_tail(struct msg_digest *md , struct key_continuation *kc) { - struct state *const st = md->st; + struct state *const st = md->st; - /* ID and HASH_R or SIG_R in - * Note: this may switch the connection being used! - */ - { - stf_status r = main_id_and_auth(md, TRUE, main_inR3_continue, kc); + /* ID and HASH_R or SIG_R in + * Note: this may switch the connection being used! + */ + { + stf_status r = main_id_and_auth(md, TRUE, main_inR3_continue, kc); - if (r != STF_OK) - return r; - } + if (r != STF_OK) + return r; + } - /**************** done input ****************/ + /**************** done input ****************/ - ISAKMP_SA_established(st->st_connection, st->st_serialno); + ISAKMP_SA_established(st->st_connection, st->st_serialno); - /* Save Phase 1 IV */ - st->st_ph1_iv_len = st->st_new_iv_len; - set_ph1_iv(st, st->st_new_iv); + /* Save Phase 1 IV */ + st->st_ph1_iv_len = st->st_new_iv_len; + set_ph1_iv(st, st->st_new_iv); - update_iv(st); /* finalize our Phase 1 IV */ + update_iv(st); /* finalize our Phase 1 IV */ - return STF_OK; + return STF_OK; } /* Handle first message of Phase 2 -- Quick Mode. @@ -4188,15 +4188,15 @@ main_inR3_tail(struct msg_digest *md */ enum verify_oppo_step { - vos_fail, - vos_start, - vos_our_client, - vos_our_txt, + vos_fail, + vos_start, + vos_our_client, + vos_our_txt, #ifdef USE_KEYRR - vos_our_key, + vos_our_key, #endif /* USE_KEYRR */ - vos_his_client, - vos_done + vos_his_client, + vos_done }; static const char *const verify_step_name[] = { @@ -4213,284 +4213,284 @@ static const char *const verify_step_name[] = { /* hold anything we can handle of a Phase 2 ID */ struct p2id { - ip_subnet net; - u_int8_t proto; - u_int16_t port; + ip_subnet net; + u_int8_t proto; + u_int16_t port; }; struct verify_oppo_bundle { - enum verify_oppo_step step; - bool failure_ok; /* if true, quick_inI1_outR1_continue will try - * other things on DNS failure */ - struct msg_digest *md; - struct p2id my, his; - unsigned int new_iv_len; /* p1st's might change */ - u_char new_iv[MAX_DIGEST_LEN]; - /* int whackfd; */ /* not needed because we are Responder */ + enum verify_oppo_step step; + bool failure_ok; /* if true, quick_inI1_outR1_continue will try + * other things on DNS failure */ + struct msg_digest *md; + struct p2id my, his; + unsigned int new_iv_len; /* p1st's might change */ + u_char new_iv[MAX_DIGEST_LEN]; + /* int whackfd; */ /* not needed because we are Responder */ }; struct verify_oppo_continuation { - struct adns_continuation ac; /* common prefix */ - struct verify_oppo_bundle b; + struct adns_continuation ac; /* common prefix */ + struct verify_oppo_bundle b; }; static stf_status quick_inI1_outR1_tail(struct verify_oppo_bundle *b - , struct adns_continuation *ac); + , struct adns_continuation *ac); stf_status quick_inI1_outR1(struct msg_digest *md) { - const struct state *const p1st = md->st; - struct connection *c = p1st->st_connection; - struct payload_digest *const id_pd = md->chain[ISAKMP_NEXT_ID]; - struct verify_oppo_bundle b; + const struct state *const p1st = md->st; + struct connection *c = p1st->st_connection; + struct payload_digest *const id_pd = md->chain[ISAKMP_NEXT_ID]; + struct verify_oppo_bundle b; - /* HASH(1) in */ - CHECK_QUICK_HASH(md - , quick_mode_hash12(hash_val, hash_pbs->roof, md->message_pbs.roof - , p1st, &md->hdr.isa_msgid, FALSE) - , "HASH(1)", "Quick I1"); + /* HASH(1) in */ + CHECK_QUICK_HASH(md + , quick_mode_hash12(hash_val, hash_pbs->roof, md->message_pbs.roof + , p1st, &md->hdr.isa_msgid, FALSE) + , "HASH(1)", "Quick I1"); - /* [ IDci, IDcr ] in - * We do this now (probably out of physical order) because - * we wish to select the correct connection before we consult - * it for policy. - */ + /* [ IDci, IDcr ] in + * We do this now (probably out of physical order) because + * we wish to select the correct connection before we consult + * it for policy. + */ - if (id_pd != NULL) - { - /* ??? we are assuming IPSEC_DOI */ + if (id_pd != NULL) + { + /* ??? we are assuming IPSEC_DOI */ - /* IDci (initiator is peer) */ + /* IDci (initiator is peer) */ - if (!decode_net_id(&id_pd->payload.ipsec_id, &id_pd->pbs - , &b.his.net, "peer client")) - return STF_FAIL + INVALID_ID_INFORMATION; + if (!decode_net_id(&id_pd->payload.ipsec_id, &id_pd->pbs + , &b.his.net, "peer client")) + return STF_FAIL + INVALID_ID_INFORMATION; - /* Hack for MS 818043 NAT-T Update */ + /* Hack for MS 818043 NAT-T Update */ - if (id_pd->payload.ipsec_id.isaiid_idtype == ID_FQDN) - happy(addrtosubnet(&c->spd.that.host_addr, &b.his.net)); + if (id_pd->payload.ipsec_id.isaiid_idtype == ID_FQDN) + happy(addrtosubnet(&c->spd.that.host_addr, &b.his.net)); - /* End Hack for MS 818043 NAT-T Update */ + /* End Hack for MS 818043 NAT-T Update */ - b.his.proto = id_pd->payload.ipsec_id.isaiid_protoid; - b.his.port = id_pd->payload.ipsec_id.isaiid_port; - b.his.net.addr.u.v4.sin_port = htons(b.his.port); + b.his.proto = id_pd->payload.ipsec_id.isaiid_protoid; + b.his.port = id_pd->payload.ipsec_id.isaiid_port; + b.his.net.addr.u.v4.sin_port = htons(b.his.port); - /* IDcr (we are responder) */ + /* IDcr (we are responder) */ - if (!decode_net_id(&id_pd->next->payload.ipsec_id, &id_pd->next->pbs - , &b.my.net, "our client")) - return STF_FAIL + INVALID_ID_INFORMATION; - - b.my.proto = id_pd->next->payload.ipsec_id.isaiid_protoid; - b.my.port = id_pd->next->payload.ipsec_id.isaiid_port; - b.my.net.addr.u.v4.sin_port = htons(b.my.port); - } - else - { - /* implicit IDci and IDcr: peer and self */ - if (!sameaddrtype(&c->spd.this.host_addr, &c->spd.that.host_addr)) - return STF_FAIL; + if (!decode_net_id(&id_pd->next->payload.ipsec_id, &id_pd->next->pbs + , &b.my.net, "our client")) + return STF_FAIL + INVALID_ID_INFORMATION; + + b.my.proto = id_pd->next->payload.ipsec_id.isaiid_protoid; + b.my.port = id_pd->next->payload.ipsec_id.isaiid_port; + b.my.net.addr.u.v4.sin_port = htons(b.my.port); + } + else + { + /* implicit IDci and IDcr: peer and self */ + if (!sameaddrtype(&c->spd.this.host_addr, &c->spd.that.host_addr)) + return STF_FAIL; - happy(addrtosubnet(&c->spd.this.host_addr, &b.my.net)); - happy(addrtosubnet(&c->spd.that.host_addr, &b.his.net)); - b.his.proto = b.my.proto = 0; - b.his.port = b.my.port = 0; - } - b.step = vos_start; - b.md = md; - b.new_iv_len = p1st->st_new_iv_len; - memcpy(b.new_iv, p1st->st_new_iv, p1st->st_new_iv_len); - return quick_inI1_outR1_tail(&b, NULL); + happy(addrtosubnet(&c->spd.this.host_addr, &b.my.net)); + happy(addrtosubnet(&c->spd.that.host_addr, &b.his.net)); + b.his.proto = b.my.proto = 0; + b.his.port = b.my.port = 0; + } + b.step = vos_start; + b.md = md; + b.new_iv_len = p1st->st_new_iv_len; + memcpy(b.new_iv, p1st->st_new_iv, p1st->st_new_iv_len); + return quick_inI1_outR1_tail(&b, NULL); } static void report_verify_failure(struct verify_oppo_bundle *b, err_t ugh) { - struct state *st = b->md->st; - char fgwb[ADDRTOT_BUF] - , cb[ADDRTOT_BUF]; - ip_address client; - err_t which = NULL; + struct state *st = b->md->st; + char fgwb[ADDRTOT_BUF] + , cb[ADDRTOT_BUF]; + ip_address client; + err_t which = NULL; - switch (b->step) - { - case vos_our_client: - case vos_our_txt: + switch (b->step) + { + case vos_our_client: + case vos_our_txt: #ifdef USE_KEYRR - case vos_our_key: + case vos_our_key: #endif /* USE_KEYRR */ - which = "our"; - networkof(&b->my.net, &client); - break; + which = "our"; + networkof(&b->my.net, &client); + break; - case vos_his_client: - which = "his"; - networkof(&b->his.net, &client); - break; + case vos_his_client: + which = "his"; + networkof(&b->his.net, &client); + break; - case vos_start: - case vos_done: - case vos_fail: - default: - bad_case(b->step); - } + case vos_start: + case vos_done: + case vos_fail: + default: + bad_case(b->step); + } - addrtot(&st->st_connection->spd.that.host_addr, 0, fgwb, sizeof(fgwb)); - addrtot(&client, 0, cb, sizeof(cb)); - loglog(RC_OPPOFAILURE - , "gateway %s wants connection with %s as %s client, but DNS fails to confirm delegation: %s" - , fgwb, cb, which, ugh); + addrtot(&st->st_connection->spd.that.host_addr, 0, fgwb, sizeof(fgwb)); + addrtot(&client, 0, cb, sizeof(cb)); + loglog(RC_OPPOFAILURE + , "gateway %s wants connection with %s as %s client, but DNS fails to confirm delegation: %s" + , fgwb, cb, which, ugh); } static void quick_inI1_outR1_continue(struct adns_continuation *cr, err_t ugh) { - stf_status r; - struct verify_oppo_continuation *vc = (void *)cr; - struct verify_oppo_bundle *b = &vc->b; - struct state *st = b->md->st; + stf_status r; + struct verify_oppo_continuation *vc = (void *)cr; + struct verify_oppo_bundle *b = &vc->b; + struct state *st = b->md->st; - passert(cur_state == NULL); - /* if st == NULL, our state has been deleted -- just clean up */ - if (st != NULL) - { - passert(st->st_suspended_md == b->md); - st->st_suspended_md = NULL; /* no longer connected or suspended */ - cur_state = st; - if (!b->failure_ok && ugh != NULL) + passert(cur_state == NULL); + /* if st == NULL, our state has been deleted -- just clean up */ + if (st != NULL) { - report_verify_failure(b, ugh); - r = STF_FAIL + INVALID_ID_INFORMATION; + passert(st->st_suspended_md == b->md); + st->st_suspended_md = NULL; /* no longer connected or suspended */ + cur_state = st; + if (!b->failure_ok && ugh != NULL) + { + report_verify_failure(b, ugh); + r = STF_FAIL + INVALID_ID_INFORMATION; + } + else + { + r = quick_inI1_outR1_tail(b, cr); + } + complete_state_transition(&b->md, r); } - else - { - r = quick_inI1_outR1_tail(b, cr); - } - complete_state_transition(&b->md, r); - } - if (b->md != NULL) - release_md(b->md); - cur_state = NULL; + if (b->md != NULL) + release_md(b->md); + cur_state = NULL; } static stf_status quick_inI1_outR1_start_query(struct verify_oppo_bundle *b , enum verify_oppo_step next_step) { - struct msg_digest *md = b->md; - struct state *p1st = md->st; - struct connection *c = p1st->st_connection; - struct verify_oppo_continuation *vc = malloc_thing(struct verify_oppo_continuation); - struct id id /* subject of query */ - , *our_id /* needed for myid playing */ - , our_id_space; /* ephemeral: no need for unshare_id_content */ - ip_address client; - err_t ugh = NULL; + struct msg_digest *md = b->md; + struct state *p1st = md->st; + struct connection *c = p1st->st_connection; + struct verify_oppo_continuation *vc = malloc_thing(struct verify_oppo_continuation); + struct id id /* subject of query */ + , *our_id /* needed for myid playing */ + , our_id_space; /* ephemeral: no need for unshare_id_content */ + ip_address client; + err_t ugh = NULL; - /* Record that state is used by a suspended md */ - b->step = next_step; /* not just vc->b.step */ - vc->b = *b; - passert(p1st->st_suspended_md == NULL); - p1st->st_suspended_md = b->md; + /* Record that state is used by a suspended md */ + b->step = next_step; /* not just vc->b.step */ + vc->b = *b; + passert(p1st->st_suspended_md == NULL); + p1st->st_suspended_md = b->md; - DBG(DBG_CONTROL, + DBG(DBG_CONTROL, + { + char ours[SUBNETTOT_BUF]; + char his[SUBNETTOT_BUF]; + + subnettot(&c->spd.this.client, 0, ours, sizeof(ours)); + subnettot(&c->spd.that.client, 0, his, sizeof(his)); + + DBG_log("responding with DNS query - from %s to %s new state: %s" + , ours, his, verify_step_name[b->step]); + }); + + /* Resolve %myid in a cheesy way. + * We have to do the resolution because start_adns_query + * et al have insufficient information to do so. + * If %myid is already known, we'll use that value + * (XXX this may be a mistake: it could be stale). + * If %myid is unknown, we should check to see if + * there are credentials for the IP address or the FQDN. + * Instead, we'll just assume the IP address since we are + * acting as the responder and only the IP address would + * have gotten it to us. + * We don't even try to do this for the other side: + * %myid makes no sense for the other side (but it is syntactically + * legal). + */ + our_id = resolve_myid(&c->spd.this.id); + if (our_id->kind == ID_NONE) { - char ours[SUBNETTOT_BUF]; - char his[SUBNETTOT_BUF]; + iptoid(&c->spd.this.host_addr, &our_id_space); + our_id = &our_id_space; + } - subnettot(&c->spd.this.client, 0, ours, sizeof(ours)); - subnettot(&c->spd.that.client, 0, his, sizeof(his)); + switch (next_step) + { + case vos_our_client: + networkof(&b->my.net, &client); + iptoid(&client, &id); + vc->b.failure_ok = b->failure_ok = FALSE; + ugh = start_adns_query(&id + , our_id + , T_TXT + , quick_inI1_outR1_continue + , &vc->ac); + break; - DBG_log("responding with DNS query - from %s to %s new state: %s" - , ours, his, verify_step_name[b->step]); - }); - - /* Resolve %myid in a cheesy way. - * We have to do the resolution because start_adns_query - * et al have insufficient information to do so. - * If %myid is already known, we'll use that value - * (XXX this may be a mistake: it could be stale). - * If %myid is unknown, we should check to see if - * there are credentials for the IP address or the FQDN. - * Instead, we'll just assume the IP address since we are - * acting as the responder and only the IP address would - * have gotten it to us. - * We don't even try to do this for the other side: - * %myid makes no sense for the other side (but it is syntactically - * legal). - */ - our_id = resolve_myid(&c->spd.this.id); - if (our_id->kind == ID_NONE) - { - iptoid(&c->spd.this.host_addr, &our_id_space); - our_id = &our_id_space; - } - - switch (next_step) - { - case vos_our_client: - networkof(&b->my.net, &client); - iptoid(&client, &id); - vc->b.failure_ok = b->failure_ok = FALSE; - ugh = start_adns_query(&id - , our_id - , T_TXT - , quick_inI1_outR1_continue - , &vc->ac); - break; - - case vos_our_txt: - vc->b.failure_ok = b->failure_ok = TRUE; - ugh = start_adns_query(our_id - , our_id /* self as SG */ - , T_TXT - , quick_inI1_outR1_continue - , &vc->ac); - break; + case vos_our_txt: + vc->b.failure_ok = b->failure_ok = TRUE; + ugh = start_adns_query(our_id + , our_id /* self as SG */ + , T_TXT + , quick_inI1_outR1_continue + , &vc->ac); + break; #ifdef USE_KEYRR - case vos_our_key: - vc->b.failure_ok = b->failure_ok = FALSE; - ugh = start_adns_query(our_id - , NULL - , T_KEY - , quick_inI1_outR1_continue - , &vc->ac); - break; + case vos_our_key: + vc->b.failure_ok = b->failure_ok = FALSE; + ugh = start_adns_query(our_id + , NULL + , T_KEY + , quick_inI1_outR1_continue + , &vc->ac); + break; #endif - case vos_his_client: - networkof(&b->his.net, &client); - iptoid(&client, &id); - vc->b.failure_ok = b->failure_ok = FALSE; - ugh = start_adns_query(&id - , &c->spd.that.id - , T_TXT - , quick_inI1_outR1_continue - , &vc->ac); - break; + case vos_his_client: + networkof(&b->his.net, &client); + iptoid(&client, &id); + vc->b.failure_ok = b->failure_ok = FALSE; + ugh = start_adns_query(&id + , &c->spd.that.id + , T_TXT + , quick_inI1_outR1_continue + , &vc->ac); + break; - default: - bad_case(next_step); - } + default: + bad_case(next_step); + } - if (ugh != NULL) - { - /* note: we'd like to use vc->b but vc has been freed - * so we have to use b. This is why we plunked next_state - * into b, not just vc->b. - */ - report_verify_failure(b, ugh); - p1st->st_suspended_md = NULL; - return STF_FAIL + INVALID_ID_INFORMATION; - } - else - { - return STF_SUSPEND; - } + if (ugh != NULL) + { + /* note: we'd like to use vc->b but vc has been freed + * so we have to use b. This is why we plunked next_state + * into b, not just vc->b. + */ + report_verify_failure(b, ugh); + p1st->st_suspended_md = NULL; + return STF_FAIL + INVALID_ID_INFORMATION; + } + else + { + return STF_SUSPEND; + } } static enum verify_oppo_step @@ -4498,526 +4498,526 @@ quick_inI1_outR1_process_answer(struct verify_oppo_bundle *b , struct adns_continuation *ac , struct state *p1st) { - struct connection *c = p1st->st_connection; - enum verify_oppo_step next_step = vos_our_client; - err_t ugh = NULL; + struct connection *c = p1st->st_connection; + enum verify_oppo_step next_step = vos_our_client; + err_t ugh = NULL; - DBG(DBG_CONTROL, + DBG(DBG_CONTROL, + { + char ours[SUBNETTOT_BUF]; + char his[SUBNETTOT_BUF]; + + subnettot(&c->spd.this.client, 0, ours, sizeof(ours)); + subnettot(&c->spd.that.client, 0, his, sizeof(his)); + DBG_log("responding on demand from %s to %s state: %s" + , ours, his, verify_step_name[b->step]); + }); + + /* process just completed DNS query (if any) */ + switch (b->step) { - char ours[SUBNETTOT_BUF]; - char his[SUBNETTOT_BUF]; - - subnettot(&c->spd.this.client, 0, ours, sizeof(ours)); - subnettot(&c->spd.that.client, 0, his, sizeof(his)); - DBG_log("responding on demand from %s to %s state: %s" - , ours, his, verify_step_name[b->step]); - }); - - /* process just completed DNS query (if any) */ - switch (b->step) - { - case vos_start: - /* no query to digest */ - next_step = vos_our_client; - break; - - case vos_our_client: - next_step = vos_his_client; - { - const struct RSA_private_key *pri = get_RSA_private_key(c); - struct gw_info *gwp; - - if (pri == NULL) - { - ugh = "we don't know our own key"; + case vos_start: + /* no query to digest */ + next_step = vos_our_client; break; - } - ugh = "our client does not delegate us as its Security Gateway"; - for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next) - { - ugh = "our client delegates us as its Security Gateway but with the wrong public key"; - /* If there is no key in the TXT record, - * we count it as a win, but we will have - * to separately fetch and check the KEY record. - * If there is a key from the TXT record, - * we count it as a win if we match the key. - */ - if (!gwp->gw_key_present) + + case vos_our_client: + next_step = vos_his_client; { - next_step = vos_our_txt; - ugh = NULL; /* good! */ - break; - } - else if (same_RSA_public_key(&pri->pub, &gwp->key->u.rsa)) - { - ugh = NULL; /* good! */ - break; - } - } - } - break; + const struct RSA_private_key *pri = get_RSA_private_key(c); + struct gw_info *gwp; - case vos_our_txt: - next_step = vos_his_client; - { - const struct RSA_private_key *pri = get_RSA_private_key(c); - - if (pri == NULL) - { - ugh = "we don't know our own key"; - break; - } - { - struct gw_info *gwp; - - for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next) - { -#ifdef USE_KEYRR - /* not an error yet, because we have to check KEY RR as well */ - ugh = NULL; -#else - ugh = "our client delegation depends on our " RRNAME " record, but it has the wrong public key"; -#endif - if (gwp->gw_key_present - && same_RSA_public_key(&pri->pub, &gwp->key->u.rsa)) - { - ugh = NULL; /* good! */ - break; - } -#ifdef USE_KEYRR - next_step = vos_our_key; -#endif - } - } - } - break; - -#ifdef USE_KEYRR - case vos_our_key: - next_step = vos_his_client; - { - const struct RSA_private_key *pri = get_RSA_private_key(c); - - if (pri == NULL) - { - ugh = "we don't know our own key"; - break; - } - { - pubkey_list_t *kp; - - ugh = "our client delegation depends on our missing " RRNAME " record"; - for (kp = ac->keys_from_dns; kp != NULL; kp = kp->next) - { - ugh = "our client delegation depends on our " RRNAME " record, but it has the wrong public key"; - if (same_RSA_public_key(&pri->pub, &kp->key->u.rsa)) - { - /* do this only once a day */ - if (!logged_txt_warning) + if (pri == NULL) { - loglog(RC_LOG_SERIOUS, "found KEY RR but not TXT RR. See http://www.freeswan.org/err/txt-change.html."); - logged_txt_warning = TRUE; + ugh = "we don't know our own key"; + break; + } + ugh = "our client does not delegate us as its Security Gateway"; + for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next) + { + ugh = "our client delegates us as its Security Gateway but with the wrong public key"; + /* If there is no key in the TXT record, + * we count it as a win, but we will have + * to separately fetch and check the KEY record. + * If there is a key from the TXT record, + * we count it as a win if we match the key. + */ + if (!gwp->gw_key_present) + { + next_step = vos_our_txt; + ugh = NULL; /* good! */ + break; + } + else if (same_RSA_public_key(&pri->pub, &gwp->key->u.rsa)) + { + ugh = NULL; /* good! */ + break; + } } - ugh = NULL; /* good! */ - break; - } } - } - } - break; + break; + + case vos_our_txt: + next_step = vos_his_client; + { + const struct RSA_private_key *pri = get_RSA_private_key(c); + + if (pri == NULL) + { + ugh = "we don't know our own key"; + break; + } + { + struct gw_info *gwp; + + for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next) + { +#ifdef USE_KEYRR + /* not an error yet, because we have to check KEY RR as well */ + ugh = NULL; +#else + ugh = "our client delegation depends on our " RRNAME " record, but it has the wrong public key"; +#endif + if (gwp->gw_key_present + && same_RSA_public_key(&pri->pub, &gwp->key->u.rsa)) + { + ugh = NULL; /* good! */ + break; + } +#ifdef USE_KEYRR + next_step = vos_our_key; +#endif + } + } + } + break; + +#ifdef USE_KEYRR + case vos_our_key: + next_step = vos_his_client; + { + const struct RSA_private_key *pri = get_RSA_private_key(c); + + if (pri == NULL) + { + ugh = "we don't know our own key"; + break; + } + { + pubkey_list_t *kp; + + ugh = "our client delegation depends on our missing " RRNAME " record"; + for (kp = ac->keys_from_dns; kp != NULL; kp = kp->next) + { + ugh = "our client delegation depends on our " RRNAME " record, but it has the wrong public key"; + if (same_RSA_public_key(&pri->pub, &kp->key->u.rsa)) + { + /* do this only once a day */ + if (!logged_txt_warning) + { + loglog(RC_LOG_SERIOUS, "found KEY RR but not TXT RR. See http://www.freeswan.org/err/txt-change.html."); + logged_txt_warning = TRUE; + } + ugh = NULL; /* good! */ + break; + } + } + } + } + break; #endif /* USE_KEYRR */ - case vos_his_client: - next_step = vos_done; - { - struct gw_info *gwp; - - /* check that the public key that authenticated - * the ISAKMP SA (p1st) will do for this gateway. - */ - - ugh = "peer's client does not delegate to peer"; - for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next) - { - ugh = "peer and its client disagree about public key"; - /* If there is a key from the TXT record, - * we count it as a win if we match the key. - * If there was no key, we claim a match since - * it implies fetching a KEY from the same - * place we must have gotten it. - */ - if (!gwp->gw_key_present - || same_RSA_public_key(&p1st->st_peer_pubkey->u.rsa - , &gwp->key->u.rsa)) + case vos_his_client: + next_step = vos_done; { - ugh = NULL; /* good! */ - break; + struct gw_info *gwp; + + /* check that the public key that authenticated + * the ISAKMP SA (p1st) will do for this gateway. + */ + + ugh = "peer's client does not delegate to peer"; + for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next) + { + ugh = "peer and its client disagree about public key"; + /* If there is a key from the TXT record, + * we count it as a win if we match the key. + * If there was no key, we claim a match since + * it implies fetching a KEY from the same + * place we must have gotten it. + */ + if (!gwp->gw_key_present + || same_RSA_public_key(&p1st->st_peer_pubkey->u.rsa + , &gwp->key->u.rsa)) + { + ugh = NULL; /* good! */ + break; + } + } } - } + break; + + default: + bad_case(b->step); } - break; - default: - bad_case(b->step); - } - - if (ugh != NULL) - { - report_verify_failure(b, ugh); - next_step = vos_fail; - } - return next_step; + if (ugh != NULL) + { + report_verify_failure(b, ugh); + next_step = vos_fail; + } + return next_step; } static stf_status quick_inI1_outR1_tail(struct verify_oppo_bundle *b , struct adns_continuation *ac) { - struct msg_digest *md = b->md; - struct state *const p1st = md->st; - struct connection *c = p1st->st_connection; - struct payload_digest *const id_pd = md->chain[ISAKMP_NEXT_ID]; - ip_subnet *our_net = &b->my.net - , *his_net = &b->his.net; + struct msg_digest *md = b->md; + struct state *const p1st = md->st; + struct connection *c = p1st->st_connection; + struct payload_digest *const id_pd = md->chain[ISAKMP_NEXT_ID]; + ip_subnet *our_net = &b->my.net + , *his_net = &b->his.net; - u_char /* set by START_HASH_PAYLOAD: */ - *r_hashval, /* where in reply to jam hash value */ - *r_hash_start; /* from where to start hashing */ + u_char /* set by START_HASH_PAYLOAD: */ + *r_hashval, /* where in reply to jam hash value */ + *r_hash_start; /* from where to start hashing */ - /* Now that we have identities of client subnets, we must look for - * a suitable connection (our current one only matches for hosts). - */ - { - struct connection *p = find_client_connection(c - , our_net, his_net, b->my.proto, b->my.port, b->his.proto, b->his.port); - - if (p == NULL) + /* Now that we have identities of client subnets, we must look for + * a suitable connection (our current one only matches for hosts). + */ { - /* This message occurs in very puzzling circumstances - * so we must add as much information and beauty as we can. - */ - struct end - me = c->spd.this, - he = c->spd.that; - char buf[2*SUBNETTOT_BUF + 2*ADDRTOT_BUF + 2*BUF_LEN + 2*ADDRTOT_BUF + 12]; /* + 12 for separating */ - size_t l; + struct connection *p = find_client_connection(c + , our_net, his_net, b->my.proto, b->my.port, b->his.proto, b->his.port); - me.client = *our_net; - me.has_client = !subnetisaddr(our_net, &me.host_addr); - me.protocol = b->my.proto; - me.port = b->my.port; - - he.client = *his_net; - he.has_client = !subnetisaddr(his_net, &he.host_addr); - he.protocol = b->his.proto; - he.port = b->his.port; - - l = format_end(buf, sizeof(buf), &me, NULL, TRUE, LEMPTY); - l += snprintf(buf + l, sizeof(buf) - l, "..."); - (void)format_end(buf + l, sizeof(buf) - l, &he, NULL, FALSE, LEMPTY); - plog("cannot respond to IPsec SA request" - " because no connection is known for %s" - , buf); - return STF_FAIL + INVALID_ID_INFORMATION; - } - else if (p != c) - { - /* We've got a better connection: it can support the - * specified clients. But it may need instantiation. - */ - if (p->kind == CK_TEMPLATE) - { - /* Yup, it needs instantiation. How much? - * Is it a Road Warrior connection (simple) - * or is it an Opportunistic connection (needing gw validation)? - */ - if (p->policy & POLICY_OPPO) + if (p == NULL) { - /* Opportunistic case: delegation must be verified. - * Here be dragons. - */ - enum verify_oppo_step next_step; - ip_address our_client, his_client; + /* This message occurs in very puzzling circumstances + * so we must add as much information and beauty as we can. + */ + struct end + me = c->spd.this, + he = c->spd.that; + char buf[2*SUBNETTOT_BUF + 2*ADDRTOT_BUF + 2*BUF_LEN + 2*ADDRTOT_BUF + 12]; /* + 12 for separating */ + size_t l; - passert(subnetishost(our_net) && subnetishost(his_net)); - networkof(our_net, &our_client); - networkof(his_net, &his_client); + me.client = *our_net; + me.has_client = !subnetisaddr(our_net, &me.host_addr); + me.protocol = b->my.proto; + me.port = b->my.port; - next_step = quick_inI1_outR1_process_answer(b, ac, p1st); - if (next_step == vos_fail) + he.client = *his_net; + he.has_client = !subnetisaddr(his_net, &he.host_addr); + he.protocol = b->his.proto; + he.port = b->his.port; + + l = format_end(buf, sizeof(buf), &me, NULL, TRUE, LEMPTY); + l += snprintf(buf + l, sizeof(buf) - l, "..."); + (void)format_end(buf + l, sizeof(buf) - l, &he, NULL, FALSE, LEMPTY); + plog("cannot respond to IPsec SA request" + " because no connection is known for %s" + , buf); return STF_FAIL + INVALID_ID_INFORMATION; - - /* short circuit: if peer's client is self, - * accept that we've verified delegation in Phase 1 - */ - if (next_step == vos_his_client - && sameaddr(&c->spd.that.host_addr, &his_client)) - next_step = vos_done; - - /* the second chunk: initiate the next DNS query (if any) */ - DBG(DBG_CONTROL, + } + else if (p != c) + { + /* We've got a better connection: it can support the + * specified clients. But it may need instantiation. + */ + if (p->kind == CK_TEMPLATE) { - char ours[SUBNETTOT_BUF]; - char his[SUBNETTOT_BUF]; + /* Yup, it needs instantiation. How much? + * Is it a Road Warrior connection (simple) + * or is it an Opportunistic connection (needing gw validation)? + */ + if (p->policy & POLICY_OPPO) + { + /* Opportunistic case: delegation must be verified. + * Here be dragons. + */ + enum verify_oppo_step next_step; + ip_address our_client, his_client; - subnettot(&c->spd.this.client, 0, ours, sizeof(ours)); - subnettot(&c->spd.that.client, 0, his, sizeof(his)); + passert(subnetishost(our_net) && subnetishost(his_net)); + networkof(our_net, &our_client); + networkof(his_net, &his_client); - DBG_log("responding on demand from %s to %s new state: %s" - , ours, his, verify_step_name[next_step]); - }); + next_step = quick_inI1_outR1_process_answer(b, ac, p1st); + if (next_step == vos_fail) + return STF_FAIL + INVALID_ID_INFORMATION; - /* start next DNS query and suspend (if necessary) */ - if (next_step != vos_done) - return quick_inI1_outR1_start_query(b, next_step); + /* short circuit: if peer's client is self, + * accept that we've verified delegation in Phase 1 + */ + if (next_step == vos_his_client + && sameaddr(&c->spd.that.host_addr, &his_client)) + next_step = vos_done; - /* Instantiate inbound Opportunistic connection, - * carrying over authenticated peer ID - * and filling in a few more details. - * We used to include gateways_from_dns, but that - * seems pointless at this stage of negotiation. - * We should record DNS sec use, if any -- belongs in - * state during perhaps. - */ - p = oppo_instantiate(p, &c->spd.that.host_addr, &c->spd.that.id - , NULL, &our_client, &his_client); + /* the second chunk: initiate the next DNS query (if any) */ + DBG(DBG_CONTROL, + { + char ours[SUBNETTOT_BUF]; + char his[SUBNETTOT_BUF]; + + subnettot(&c->spd.this.client, 0, ours, sizeof(ours)); + subnettot(&c->spd.that.client, 0, his, sizeof(his)); + + DBG_log("responding on demand from %s to %s new state: %s" + , ours, his, verify_step_name[next_step]); + }); + + /* start next DNS query and suspend (if necessary) */ + if (next_step != vos_done) + return quick_inI1_outR1_start_query(b, next_step); + + /* Instantiate inbound Opportunistic connection, + * carrying over authenticated peer ID + * and filling in a few more details. + * We used to include gateways_from_dns, but that + * seems pointless at this stage of negotiation. + * We should record DNS sec use, if any -- belongs in + * state during perhaps. + */ + p = oppo_instantiate(p, &c->spd.that.host_addr, &c->spd.that.id + , NULL, &our_client, &his_client); + } + else + { + /* Plain Road Warrior: + * instantiate, carrying over authenticated peer ID + */ + p = rw_instantiate(p, &c->spd.that.host_addr, md->sender_port + , his_net, &c->spd.that.id); + } + } +#ifdef DEBUG + /* temporarily bump up cur_debugging to get "using..." message + * printed if we'd want it with new connection. + */ + { + lset_t old_cur_debugging = cur_debugging; + + cur_debugging |= p->extra_debugging; + DBG(DBG_CONTROL, DBG_log("using connection \"%s\"", p->name)); + cur_debugging = old_cur_debugging; + } +#endif + c = p; + } + /* fill in the client's true ip address/subnet */ + if (p->spd.that.has_client_wildcard) + { + p->spd.that.client = *his_net; + p->spd.that.has_client_wildcard = FALSE; + } + else if (is_virtual_connection(c)) + { + c->spd.that.client = *his_net; + c->spd.that.virt = NULL; + if (subnetishost(his_net) && addrinsubnet(&c->spd.that.host_addr, his_net)) + c->spd.that.has_client = FALSE; + } + + /* fill in the client's true port */ + if (p->spd.that.has_port_wildcard) + { + int port = htons(b->his.port); + + setportof(port, &p->spd.that.host_addr); + setportof(port, &p->spd.that.client.addr); + + p->spd.that.port = b->his.port; + p->spd.that.has_port_wildcard = FALSE; + } + } + + /* now that we are sure of our connection, create our new state */ + { + struct state *const st = duplicate_state(p1st); + + /* first: fill in missing bits of our new state object + * note: we don't copy over st_peer_pubkey, the public key + * that authenticated the ISAKMP SA. We only need it in this + * routine, so we can "reach back" to p1st to get it. + */ + + if (st->st_connection != c) + { + struct connection *t = st->st_connection; + + st->st_connection = c; + set_cur_connection(c); + connection_discard(t); + } + + st->st_try = 0; /* not our job to try again from start */ + + st->st_msgid = md->hdr.isa_msgid; + + st->st_new_iv_len = b->new_iv_len; + memcpy(st->st_new_iv, b->new_iv, b->new_iv_len); + + set_cur_state(st); /* (caller will reset) */ + md->st = st; /* feed back new state */ + + st->st_peeruserprotoid = b->his.proto; + st->st_peeruserport = b->his.port; + st->st_myuserprotoid = b->my.proto; + st->st_myuserport = b->my.port; + + insert_state(st); /* needs cookies, connection, and msgid */ + + /* copy the connection's + * IPSEC policy into our state. The ISAKMP policy is water under + * the bridge, I think. It will reflect the ISAKMP SA that we + * are using. + */ + st->st_policy = (p1st->st_policy & POLICY_ISAKMP_MASK) + | (c->policy & ~POLICY_ISAKMP_MASK); + + if (p1st->nat_traversal & NAT_T_DETECTED) + { + st->nat_traversal = p1st->nat_traversal; + nat_traversal_change_port_lookup(md, md->st); } else { - /* Plain Road Warrior: - * instantiate, carrying over authenticated peer ID - */ - p = rw_instantiate(p, &c->spd.that.host_addr, md->sender_port - , his_net, &c->spd.that.id); + st->nat_traversal = 0; + } + if ((st->nat_traversal & NAT_T_DETECTED) + && (st->nat_traversal & NAT_T_WITH_NATOA)) + { + nat_traversal_natoa_lookup(md); } - } -#ifdef DEBUG - /* temporarily bump up cur_debugging to get "using..." message - * printed if we'd want it with new connection. - */ - { - lset_t old_cur_debugging = cur_debugging; - cur_debugging |= p->extra_debugging; - DBG(DBG_CONTROL, DBG_log("using connection \"%s\"", p->name)); - cur_debugging = old_cur_debugging; - } -#endif - c = p; + /* Start the output packet. + * + * proccess_packet() would automatically generate the HDR* + * payload if smc->first_out_payload is not ISAKMP_NEXT_NONE. + * We don't do this because we wish there to be no partially + * built output packet if we need to suspend for asynch DNS. + * + * We build the reply packet as we parse the message since + * the parse_ipsec_sa_body emits the reply SA + */ + + /* HDR* out */ + echo_hdr(md, TRUE, ISAKMP_NEXT_HASH); + + /* HASH(2) out -- first pass */ + START_HASH_PAYLOAD(md->rbody, ISAKMP_NEXT_SA); + + /* process SA (in and out) */ + { + struct payload_digest *const sapd = md->chain[ISAKMP_NEXT_SA]; + pb_stream r_sa_pbs; + struct isakmp_sa sa = sapd->payload.sa; + + /* sa header is unchanged -- except for np */ + sa.isasa_np = ISAKMP_NEXT_NONCE; + if (!out_struct(&sa, &isakmp_sa_desc, &md->rbody, &r_sa_pbs)) + return STF_INTERNAL_ERROR; + + /* parse and accept body */ + st->st_pfs_group = &unset_group; + RETURN_STF_FAILURE(parse_ipsec_sa_body(&sapd->pbs + , &sapd->payload.sa, &r_sa_pbs, FALSE, st)); + } + + passert(st->st_pfs_group != &unset_group); + + if ((st->st_policy & POLICY_PFS) && st->st_pfs_group == NULL) + { + loglog(RC_LOG_SERIOUS, "we require PFS but Quick I1 SA specifies no GROUP_DESCRIPTION"); + return STF_FAIL + NO_PROPOSAL_CHOSEN; /* ??? */ + } + + /* Ni in */ + RETURN_STF_FAILURE(accept_nonce(md, &st->st_ni, "Ni")); + + /* [ KE ] in (for PFS) */ + RETURN_STF_FAILURE(accept_PFS_KE(md, &st->st_gi, "Gi", "Quick Mode I1")); + + plog("responding to Quick Mode"); + + /**** finish reply packet: Nr [, KE ] [, IDci, IDcr ] ****/ + + /* Nr out */ + if (!build_and_ship_nonce(&st->st_nr, &md->rbody + , st->st_pfs_group != NULL? ISAKMP_NEXT_KE : id_pd != NULL? ISAKMP_NEXT_ID : ISAKMP_NEXT_NONE + , "Nr")) + return STF_INTERNAL_ERROR; + + /* [ KE ] out (for PFS) */ + + if (st->st_pfs_group != NULL) + { + if (!build_and_ship_KE(st, &st->st_gr, st->st_pfs_group + , &md->rbody, id_pd != NULL? ISAKMP_NEXT_ID : ISAKMP_NEXT_NONE)) + return STF_INTERNAL_ERROR; + + /* MPZ-Operations might be done after sending the packet... */ + compute_dh_shared(st, st->st_gi, st->st_pfs_group); + } + + /* [ IDci, IDcr ] out */ + if (id_pd != NULL) + { + struct isakmp_ipsec_id *p = (void *)md->rbody.cur; /* UGH! */ + + if (!out_raw(id_pd->pbs.start, pbs_room(&id_pd->pbs), &md->rbody, "IDci")) + return STF_INTERNAL_ERROR; + p->isaiid_np = ISAKMP_NEXT_ID; + + p = (void *)md->rbody.cur; /* UGH! */ + + if (!out_raw(id_pd->next->pbs.start, pbs_room(&id_pd->next->pbs), &md->rbody, "IDcr")) + return STF_INTERNAL_ERROR; + p->isaiid_np = ISAKMP_NEXT_NONE; + } + + if ((st->nat_traversal & NAT_T_WITH_NATOA) + && (st->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_ME)) + && (st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TRANSPORT)) + { + /** Send NAT-OA if our address is NATed and if we use Transport Mode */ + if (!nat_traversal_add_natoa(ISAKMP_NEXT_NONE, &md->rbody, md->st)) + { + return STF_INTERNAL_ERROR; + } + } + if ((st->nat_traversal & NAT_T_DETECTED) + && (st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TRANSPORT) + && (c->spd.that.has_client)) + { + /** Remove client **/ + addrtosubnet(&c->spd.that.host_addr, &c->spd.that.client); + c->spd.that.has_client = FALSE; + } + + /* Compute reply HASH(2) and insert in output */ + (void)quick_mode_hash12(r_hashval, r_hash_start, md->rbody.cur + , st, &st->st_msgid, TRUE); + + /* Derive new keying material */ + compute_keymats(st); + + /* Tell the kernel to establish the new inbound SA + * (unless the commit bit is set -- which we don't support). + * We do this before any state updating so that + * failure won't look like success. + */ + if (!install_inbound_ipsec_sa(st)) + return STF_INTERNAL_ERROR; /* ??? we may be partly committed */ + + /* encrypt message, except for fixed part of header */ + + if (!encrypt_message(&md->rbody, st)) + return STF_INTERNAL_ERROR; /* ??? we may be partly committed */ + + return STF_OK; } - /* fill in the client's true ip address/subnet */ - if (p->spd.that.has_client_wildcard) - { - p->spd.that.client = *his_net; - p->spd.that.has_client_wildcard = FALSE; - } - else if (is_virtual_connection(c)) - { - c->spd.that.client = *his_net; - c->spd.that.virt = NULL; - if (subnetishost(his_net) && addrinsubnet(&c->spd.that.host_addr, his_net)) - c->spd.that.has_client = FALSE; - } - - /* fill in the client's true port */ - if (p->spd.that.has_port_wildcard) - { - int port = htons(b->his.port); - - setportof(port, &p->spd.that.host_addr); - setportof(port, &p->spd.that.client.addr); - - p->spd.that.port = b->his.port; - p->spd.that.has_port_wildcard = FALSE; - } - } - - /* now that we are sure of our connection, create our new state */ - { - struct state *const st = duplicate_state(p1st); - - /* first: fill in missing bits of our new state object - * note: we don't copy over st_peer_pubkey, the public key - * that authenticated the ISAKMP SA. We only need it in this - * routine, so we can "reach back" to p1st to get it. - */ - - if (st->st_connection != c) - { - struct connection *t = st->st_connection; - - st->st_connection = c; - set_cur_connection(c); - connection_discard(t); - } - - st->st_try = 0; /* not our job to try again from start */ - - st->st_msgid = md->hdr.isa_msgid; - - st->st_new_iv_len = b->new_iv_len; - memcpy(st->st_new_iv, b->new_iv, b->new_iv_len); - - set_cur_state(st); /* (caller will reset) */ - md->st = st; /* feed back new state */ - - st->st_peeruserprotoid = b->his.proto; - st->st_peeruserport = b->his.port; - st->st_myuserprotoid = b->my.proto; - st->st_myuserport = b->my.port; - - insert_state(st); /* needs cookies, connection, and msgid */ - - /* copy the connection's - * IPSEC policy into our state. The ISAKMP policy is water under - * the bridge, I think. It will reflect the ISAKMP SA that we - * are using. - */ - st->st_policy = (p1st->st_policy & POLICY_ISAKMP_MASK) - | (c->policy & ~POLICY_ISAKMP_MASK); - - if (p1st->nat_traversal & NAT_T_DETECTED) - { - st->nat_traversal = p1st->nat_traversal; - nat_traversal_change_port_lookup(md, md->st); - } - else - { - st->nat_traversal = 0; - } - if ((st->nat_traversal & NAT_T_DETECTED) - && (st->nat_traversal & NAT_T_WITH_NATOA)) - { - nat_traversal_natoa_lookup(md); - } - - /* Start the output packet. - * - * proccess_packet() would automatically generate the HDR* - * payload if smc->first_out_payload is not ISAKMP_NEXT_NONE. - * We don't do this because we wish there to be no partially - * built output packet if we need to suspend for asynch DNS. - * - * We build the reply packet as we parse the message since - * the parse_ipsec_sa_body emits the reply SA - */ - - /* HDR* out */ - echo_hdr(md, TRUE, ISAKMP_NEXT_HASH); - - /* HASH(2) out -- first pass */ - START_HASH_PAYLOAD(md->rbody, ISAKMP_NEXT_SA); - - /* process SA (in and out) */ - { - struct payload_digest *const sapd = md->chain[ISAKMP_NEXT_SA]; - pb_stream r_sa_pbs; - struct isakmp_sa sa = sapd->payload.sa; - - /* sa header is unchanged -- except for np */ - sa.isasa_np = ISAKMP_NEXT_NONCE; - if (!out_struct(&sa, &isakmp_sa_desc, &md->rbody, &r_sa_pbs)) - return STF_INTERNAL_ERROR; - - /* parse and accept body */ - st->st_pfs_group = &unset_group; - RETURN_STF_FAILURE(parse_ipsec_sa_body(&sapd->pbs - , &sapd->payload.sa, &r_sa_pbs, FALSE, st)); - } - - passert(st->st_pfs_group != &unset_group); - - if ((st->st_policy & POLICY_PFS) && st->st_pfs_group == NULL) - { - loglog(RC_LOG_SERIOUS, "we require PFS but Quick I1 SA specifies no GROUP_DESCRIPTION"); - return STF_FAIL + NO_PROPOSAL_CHOSEN; /* ??? */ - } - - /* Ni in */ - RETURN_STF_FAILURE(accept_nonce(md, &st->st_ni, "Ni")); - - /* [ KE ] in (for PFS) */ - RETURN_STF_FAILURE(accept_PFS_KE(md, &st->st_gi, "Gi", "Quick Mode I1")); - - plog("responding to Quick Mode"); - - /**** finish reply packet: Nr [, KE ] [, IDci, IDcr ] ****/ - - /* Nr out */ - if (!build_and_ship_nonce(&st->st_nr, &md->rbody - , st->st_pfs_group != NULL? ISAKMP_NEXT_KE : id_pd != NULL? ISAKMP_NEXT_ID : ISAKMP_NEXT_NONE - , "Nr")) - return STF_INTERNAL_ERROR; - - /* [ KE ] out (for PFS) */ - - if (st->st_pfs_group != NULL) - { - if (!build_and_ship_KE(st, &st->st_gr, st->st_pfs_group - , &md->rbody, id_pd != NULL? ISAKMP_NEXT_ID : ISAKMP_NEXT_NONE)) - return STF_INTERNAL_ERROR; - - /* MPZ-Operations might be done after sending the packet... */ - compute_dh_shared(st, st->st_gi, st->st_pfs_group); - } - - /* [ IDci, IDcr ] out */ - if (id_pd != NULL) - { - struct isakmp_ipsec_id *p = (void *)md->rbody.cur; /* UGH! */ - - if (!out_raw(id_pd->pbs.start, pbs_room(&id_pd->pbs), &md->rbody, "IDci")) - return STF_INTERNAL_ERROR; - p->isaiid_np = ISAKMP_NEXT_ID; - - p = (void *)md->rbody.cur; /* UGH! */ - - if (!out_raw(id_pd->next->pbs.start, pbs_room(&id_pd->next->pbs), &md->rbody, "IDcr")) - return STF_INTERNAL_ERROR; - p->isaiid_np = ISAKMP_NEXT_NONE; - } - - if ((st->nat_traversal & NAT_T_WITH_NATOA) - && (st->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_ME)) - && (st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TRANSPORT)) - { - /** Send NAT-OA if our address is NATed and if we use Transport Mode */ - if (!nat_traversal_add_natoa(ISAKMP_NEXT_NONE, &md->rbody, md->st)) - { - return STF_INTERNAL_ERROR; - } - } - if ((st->nat_traversal & NAT_T_DETECTED) - && (st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TRANSPORT) - && (c->spd.that.has_client)) - { - /** Remove client **/ - addrtosubnet(&c->spd.that.host_addr, &c->spd.that.client); - c->spd.that.has_client = FALSE; - } - - /* Compute reply HASH(2) and insert in output */ - (void)quick_mode_hash12(r_hashval, r_hash_start, md->rbody.cur - , st, &st->st_msgid, TRUE); - - /* Derive new keying material */ - compute_keymats(st); - - /* Tell the kernel to establish the new inbound SA - * (unless the commit bit is set -- which we don't support). - * We do this before any state updating so that - * failure won't look like success. - */ - if (!install_inbound_ipsec_sa(st)) - return STF_INTERNAL_ERROR; /* ??? we may be partly committed */ - - /* encrypt message, except for fixed part of header */ - - if (!encrypt_message(&md->rbody, st)) - return STF_INTERNAL_ERROR; /* ??? we may be partly committed */ - - return STF_OK; - } } /* @@ -5026,20 +5026,20 @@ quick_inI1_outR1_tail(struct verify_oppo_bundle *b static void dpd_init(struct state *st) { - struct state *p1st = find_state(st->st_icookie, st->st_rcookie - , &st->st_connection->spd.that.host_addr, 0); - - if (p1st == NULL) - loglog(RC_LOG_SERIOUS, "could not find phase 1 state for DPD"); - else if (p1st->st_dpd) - { - plog("Dead Peer Detection (RFC 3706) enabled"); - /* randomize the first DPD event */ - - event_schedule(EVENT_DPD - , (0.5 + rand()/(RAND_MAX + 1.E0)) * st->st_connection->dpd_delay - , st); - } + struct state *p1st = find_state(st->st_icookie, st->st_rcookie + , &st->st_connection->spd.that.host_addr, 0); + + if (p1st == NULL) + loglog(RC_LOG_SERIOUS, "could not find phase 1 state for DPD"); + else if (p1st->st_dpd) + { + plog("Dead Peer Detection (RFC 3706) enabled"); + /* randomize the first DPD event */ + + event_schedule(EVENT_DPD + , (0.5 + rand()/(RAND_MAX + 1.E0)) * st->st_connection->dpd_delay + , st); + } } /* Handle (the single) message from Responder in Quick Mode. @@ -5051,149 +5051,149 @@ dpd_init(struct state *st) stf_status quick_inR1_outI2(struct msg_digest *md) { - struct state *const st = md->st; - const struct connection *c = st->st_connection; + struct state *const st = md->st; + const struct connection *c = st->st_connection; - /* HASH(2) in */ - CHECK_QUICK_HASH(md - , quick_mode_hash12(hash_val, hash_pbs->roof, md->message_pbs.roof - , st, &st->st_msgid, TRUE) - , "HASH(2)", "Quick R1"); + /* HASH(2) in */ + CHECK_QUICK_HASH(md + , quick_mode_hash12(hash_val, hash_pbs->roof, md->message_pbs.roof + , st, &st->st_msgid, TRUE) + , "HASH(2)", "Quick R1"); - /* SA in */ - { - struct payload_digest *const sa_pd = md->chain[ISAKMP_NEXT_SA]; - - RETURN_STF_FAILURE(parse_ipsec_sa_body(&sa_pd->pbs - , &sa_pd->payload.sa, NULL, TRUE, st)); - } - - /* Nr in */ - RETURN_STF_FAILURE(accept_nonce(md, &st->st_nr, "Nr")); - - /* [ KE ] in (for PFS) */ - RETURN_STF_FAILURE(accept_PFS_KE(md, &st->st_gr, "Gr", "Quick Mode R1")); - - if (st->st_pfs_group != NULL) - compute_dh_shared(st, st->st_gr, st->st_pfs_group); - - /* [ IDci, IDcr ] in; these must match what we sent */ - - { - struct payload_digest *const id_pd = md->chain[ISAKMP_NEXT_ID]; - - if (id_pd != NULL) + /* SA in */ { - /* ??? we are assuming IPSEC_DOI */ + struct payload_digest *const sa_pd = md->chain[ISAKMP_NEXT_SA]; - /* IDci (we are initiator) */ - - if (!check_net_id(&id_pd->payload.ipsec_id, &id_pd->pbs - , &st->st_myuserprotoid, &st->st_myuserport - , &st->st_connection->spd.this.client - , "our client")) - return STF_FAIL + INVALID_ID_INFORMATION; - - /* IDcr (responder is peer) */ - - if (!check_net_id(&id_pd->next->payload.ipsec_id, &id_pd->next->pbs - , &st->st_peeruserprotoid, &st->st_peeruserport - , &st->st_connection->spd.that.client - , "peer client")) - return STF_FAIL + INVALID_ID_INFORMATION; + RETURN_STF_FAILURE(parse_ipsec_sa_body(&sa_pd->pbs + , &sa_pd->payload.sa, NULL, TRUE, st)); } - else + + /* Nr in */ + RETURN_STF_FAILURE(accept_nonce(md, &st->st_nr, "Nr")); + + /* [ KE ] in (for PFS) */ + RETURN_STF_FAILURE(accept_PFS_KE(md, &st->st_gr, "Gr", "Quick Mode R1")); + + if (st->st_pfs_group != NULL) + compute_dh_shared(st, st->st_gr, st->st_pfs_group); + + /* [ IDci, IDcr ] in; these must match what we sent */ + { - /* no IDci, IDcr: we must check that the defaults match our proposal */ - if (!subnetisaddr(&c->spd.this.client, &c->spd.this.host_addr) - || !subnetisaddr(&c->spd.that.client, &c->spd.that.host_addr)) - { - loglog(RC_LOG_SERIOUS, "IDci, IDcr payloads missing in message" - " but default does not match proposal"); - return STF_FAIL + INVALID_ID_INFORMATION; - } - } - } + struct payload_digest *const id_pd = md->chain[ISAKMP_NEXT_ID]; - /* check the peer's group attributes */ - - { - const ietfAttrList_t *peer_list = NULL; + if (id_pd != NULL) + { + /* ??? we are assuming IPSEC_DOI */ + + /* IDci (we are initiator) */ + + if (!check_net_id(&id_pd->payload.ipsec_id, &id_pd->pbs + , &st->st_myuserprotoid, &st->st_myuserport + , &st->st_connection->spd.this.client + , "our client")) + return STF_FAIL + INVALID_ID_INFORMATION; + + /* IDcr (responder is peer) */ + + if (!check_net_id(&id_pd->next->payload.ipsec_id, &id_pd->next->pbs + , &st->st_peeruserprotoid, &st->st_peeruserport + , &st->st_connection->spd.that.client + , "peer client")) + return STF_FAIL + INVALID_ID_INFORMATION; + } + else + { + /* no IDci, IDcr: we must check that the defaults match our proposal */ + if (!subnetisaddr(&c->spd.this.client, &c->spd.this.host_addr) + || !subnetisaddr(&c->spd.that.client, &c->spd.that.host_addr)) + { + loglog(RC_LOG_SERIOUS, "IDci, IDcr payloads missing in message" + " but default does not match proposal"); + return STF_FAIL + INVALID_ID_INFORMATION; + } + } + } + + /* check the peer's group attributes */ - get_peer_ca_and_groups(st->st_connection, &peer_list); - - if (!group_membership(peer_list, st->st_connection->name - , st->st_connection->spd.that.groups)) { - char buf[BUF_LEN]; + const ietfAttrList_t *peer_list = NULL; + + get_peer_ca_and_groups(st->st_connection, &peer_list); - format_groups(st->st_connection->spd.that.groups, buf, BUF_LEN); - loglog(RC_LOG_SERIOUS, "peer is not member of one of the groups: %s" - , buf); - return STF_FAIL + INVALID_ID_INFORMATION; - } - } + if (!group_membership(peer_list, st->st_connection->name + , st->st_connection->spd.that.groups)) + { + char buf[BUF_LEN]; - if ((st->nat_traversal & NAT_T_DETECTED) - && (st->nat_traversal & NAT_T_WITH_NATOA)) - { - nat_traversal_natoa_lookup(md); + format_groups(st->st_connection->spd.that.groups, buf, BUF_LEN); + loglog(RC_LOG_SERIOUS, "peer is not member of one of the groups: %s" + , buf); + return STF_FAIL + INVALID_ID_INFORMATION; + } } - /* ??? We used to copy the accepted proposal into the state, but it was - * never used. From sa_pd->pbs.start, length pbs_room(&sa_pd->pbs). - */ + if ((st->nat_traversal & NAT_T_DETECTED) + && (st->nat_traversal & NAT_T_WITH_NATOA)) + { + nat_traversal_natoa_lookup(md); + } - /**************** build reply packet HDR*, HASH(3) ****************/ + /* ??? We used to copy the accepted proposal into the state, but it was + * never used. From sa_pd->pbs.start, length pbs_room(&sa_pd->pbs). + */ - /* HDR* out done */ + /**************** build reply packet HDR*, HASH(3) ****************/ - /* HASH(3) out -- since this is the only content, no passes needed */ - { - u_char /* set by START_HASH_PAYLOAD: */ - *r_hashval, /* where in reply to jam hash value */ - *r_hash_start; /* start of what is to be hashed */ + /* HDR* out done */ - START_HASH_PAYLOAD(md->rbody, ISAKMP_NEXT_NONE); - (void)quick_mode_hash3(r_hashval, st); - } + /* HASH(3) out -- since this is the only content, no passes needed */ + { + u_char /* set by START_HASH_PAYLOAD: */ + *r_hashval, /* where in reply to jam hash value */ + *r_hash_start; /* start of what is to be hashed */ - /* Derive new keying material */ - compute_keymats(st); + START_HASH_PAYLOAD(md->rbody, ISAKMP_NEXT_NONE); + (void)quick_mode_hash3(r_hashval, st); + } - /* Tell the kernel to establish the inbound, outbound, and routing part - * of the new SA (unless the commit bit is set -- which we don't support). - * We do this before any state updating so that - * failure won't look like success. - */ - if (!install_ipsec_sa(st, TRUE)) - return STF_INTERNAL_ERROR; + /* Derive new keying material */ + compute_keymats(st); - /* encrypt message, except for fixed part of header */ + /* Tell the kernel to establish the inbound, outbound, and routing part + * of the new SA (unless the commit bit is set -- which we don't support). + * We do this before any state updating so that + * failure won't look like success. + */ + if (!install_ipsec_sa(st, TRUE)) + return STF_INTERNAL_ERROR; - if (!encrypt_message(&md->rbody, st)) - return STF_INTERNAL_ERROR; /* ??? we may be partly committed */ + /* encrypt message, except for fixed part of header */ - { - DBG(DBG_CONTROLMORE, DBG_log("inR1_outI2: instance %s[%ld], setting newest_ipsec_sa to #%ld (was #%ld) (spd.eroute=#%ld)" - , st->st_connection->name - , st->st_connection->instance_serial - , st->st_serialno - , st->st_connection->newest_ipsec_sa - , st->st_connection->spd.eroute_owner)); - } - - st->st_connection->newest_ipsec_sa = st->st_serialno; + if (!encrypt_message(&md->rbody, st)) + return STF_INTERNAL_ERROR; /* ??? we may be partly committed */ - /* note (presumed) success */ - if (c->gw_info != NULL) - c->gw_info->key->last_worked_time = now(); + { + DBG(DBG_CONTROLMORE, DBG_log("inR1_outI2: instance %s[%ld], setting newest_ipsec_sa to #%ld (was #%ld) (spd.eroute=#%ld)" + , st->st_connection->name + , st->st_connection->instance_serial + , st->st_serialno + , st->st_connection->newest_ipsec_sa + , st->st_connection->spd.eroute_owner)); + } + + st->st_connection->newest_ipsec_sa = st->st_serialno; - /* If we want DPD on this connection then initialize it */ - if (st->st_connection->dpd_action != DPD_ACTION_NONE) - dpd_init(st); + /* note (presumed) success */ + if (c->gw_info != NULL) + c->gw_info->key->last_worked_time = now(); - return STF_OK; + /* If we want DPD on this connection then initialize it */ + if (st->st_connection->dpd_action != DPD_ACTION_NONE) + dpd_init(st); + + return STF_OK; } /* Handle last message of Quick Mode. @@ -5204,151 +5204,151 @@ quick_inR1_outI2(struct msg_digest *md) stf_status quick_inI2(struct msg_digest *md) { - struct state *const st = md->st; + struct state *const st = md->st; - /* HASH(3) in */ - CHECK_QUICK_HASH(md, quick_mode_hash3(hash_val, st) - , "HASH(3)", "Quick I2"); + /* HASH(3) in */ + CHECK_QUICK_HASH(md, quick_mode_hash3(hash_val, st) + , "HASH(3)", "Quick I2"); - /* Tell the kernel to establish the outbound and routing part of the new SA - * (the previous state established inbound) - * (unless the commit bit is set -- which we don't support). - * We do this before any state updating so that - * failure won't look like success. - */ - if (!install_ipsec_sa(st, FALSE)) - return STF_INTERNAL_ERROR; + /* Tell the kernel to establish the outbound and routing part of the new SA + * (the previous state established inbound) + * (unless the commit bit is set -- which we don't support). + * We do this before any state updating so that + * failure won't look like success. + */ + if (!install_ipsec_sa(st, FALSE)) + return STF_INTERNAL_ERROR; - { - DBG(DBG_CONTROLMORE, DBG_log("inI2: instance %s[%ld], setting newest_ipsec_sa to #%ld (was #%ld) (spd.eroute=#%ld)" - , st->st_connection->name - , st->st_connection->instance_serial - , st->st_serialno - , st->st_connection->newest_ipsec_sa - , st->st_connection->spd.eroute_owner)); - } + { + DBG(DBG_CONTROLMORE, DBG_log("inI2: instance %s[%ld], setting newest_ipsec_sa to #%ld (was #%ld) (spd.eroute=#%ld)" + , st->st_connection->name + , st->st_connection->instance_serial + , st->st_serialno + , st->st_connection->newest_ipsec_sa + , st->st_connection->spd.eroute_owner)); + } - st->st_connection->newest_ipsec_sa = st->st_serialno; + st->st_connection->newest_ipsec_sa = st->st_serialno; - update_iv(st); /* not actually used, but tidy */ + update_iv(st); /* not actually used, but tidy */ - /* note (presumed) success */ - { - struct gw_info *gw = st->st_connection->gw_info; + /* note (presumed) success */ + { + struct gw_info *gw = st->st_connection->gw_info; - if (gw != NULL) - gw->key->last_worked_time = now(); - } + if (gw != NULL) + gw->key->last_worked_time = now(); + } - /* If we want DPD on this connection then initialize it */ - if (st->st_connection->dpd_action != DPD_ACTION_NONE) - dpd_init(st); + /* If we want DPD on this connection then initialize it */ + if (st->st_connection->dpd_action != DPD_ACTION_NONE) + dpd_init(st); - return STF_OK; + return STF_OK; } static stf_status send_isakmp_notification(struct state *st, u_int16_t type - , const void *data, size_t len) + , const void *data, size_t len) { - msgid_t msgid; - pb_stream reply; - pb_stream rbody; - u_char - *r_hashval, /* where in reply to jam hash value */ - *r_hash_start; /* start of what is to be hashed */ - - msgid = generate_msgid(st); - - init_pbs(&reply, reply_buffer, sizeof(reply_buffer), "ISAKMP notify"); + msgid_t msgid; + pb_stream reply; + pb_stream rbody; + u_char + *r_hashval, /* where in reply to jam hash value */ + *r_hash_start; /* start of what is to be hashed */ + + msgid = generate_msgid(st); + + init_pbs(&reply, reply_buffer, sizeof(reply_buffer), "ISAKMP notify"); - /* HDR* */ - { - struct isakmp_hdr hdr; + /* HDR* */ + { + struct isakmp_hdr hdr; - hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION; - hdr.isa_np = ISAKMP_NEXT_HASH; - hdr.isa_xchg = ISAKMP_XCHG_INFO; - hdr.isa_msgid = msgid; - hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION; - memcpy(hdr.isa_icookie, st->st_icookie, COOKIE_SIZE); - memcpy(hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE); - if (!out_struct(&hdr, &isakmp_hdr_desc, &reply, &rbody)) - impossible(); - } - /* HASH -- create and note space to be filled later */ - START_HASH_PAYLOAD(rbody, ISAKMP_NEXT_N); + hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION; + hdr.isa_np = ISAKMP_NEXT_HASH; + hdr.isa_xchg = ISAKMP_XCHG_INFO; + hdr.isa_msgid = msgid; + hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION; + memcpy(hdr.isa_icookie, st->st_icookie, COOKIE_SIZE); + memcpy(hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE); + if (!out_struct(&hdr, &isakmp_hdr_desc, &reply, &rbody)) + impossible(); + } + /* HASH -- create and note space to be filled later */ + START_HASH_PAYLOAD(rbody, ISAKMP_NEXT_N); - /* NOTIFY */ - { - pb_stream notify_pbs; - struct isakmp_notification isan; + /* NOTIFY */ + { + pb_stream notify_pbs; + struct isakmp_notification isan; - isan.isan_np = ISAKMP_NEXT_NONE; - isan.isan_doi = ISAKMP_DOI_IPSEC; - isan.isan_protoid = PROTO_ISAKMP; - isan.isan_spisize = COOKIE_SIZE * 2; - isan.isan_type = type; - if (!out_struct(&isan, &isakmp_notification_desc, &rbody, ¬ify_pbs)) - return STF_INTERNAL_ERROR; - if (!out_raw(st->st_icookie, COOKIE_SIZE, ¬ify_pbs, "notify icookie")) - return STF_INTERNAL_ERROR; - if (!out_raw(st->st_rcookie, COOKIE_SIZE, ¬ify_pbs, "notify rcookie")) - return STF_INTERNAL_ERROR; - if (data != NULL && len > 0) - if (!out_raw(data, len, ¬ify_pbs, "notify data")) - return STF_INTERNAL_ERROR; - close_output_pbs(¬ify_pbs); - } - - { - /* finish computing HASH */ - struct hmac_ctx ctx; - hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid_a); - hmac_update(&ctx, (const u_char *) &msgid, sizeof(msgid_t)); - hmac_update(&ctx, r_hash_start, rbody.cur-r_hash_start); - hmac_final(r_hashval, &ctx); + isan.isan_np = ISAKMP_NEXT_NONE; + isan.isan_doi = ISAKMP_DOI_IPSEC; + isan.isan_protoid = PROTO_ISAKMP; + isan.isan_spisize = COOKIE_SIZE * 2; + isan.isan_type = type; + if (!out_struct(&isan, &isakmp_notification_desc, &rbody, ¬ify_pbs)) + return STF_INTERNAL_ERROR; + if (!out_raw(st->st_icookie, COOKIE_SIZE, ¬ify_pbs, "notify icookie")) + return STF_INTERNAL_ERROR; + if (!out_raw(st->st_rcookie, COOKIE_SIZE, ¬ify_pbs, "notify rcookie")) + return STF_INTERNAL_ERROR; + if (data != NULL && len > 0) + if (!out_raw(data, len, ¬ify_pbs, "notify data")) + return STF_INTERNAL_ERROR; + close_output_pbs(¬ify_pbs); + } + + { + /* finish computing HASH */ + struct hmac_ctx ctx; + hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid_a); + hmac_update(&ctx, (const u_char *) &msgid, sizeof(msgid_t)); + hmac_update(&ctx, r_hash_start, rbody.cur-r_hash_start); + hmac_final(r_hashval, &ctx); - DBG(DBG_CRYPT, - DBG_log("HASH computed:"); - DBG_dump("", r_hashval, ctx.hmac_digest_size)); - } + DBG(DBG_CRYPT, + DBG_log("HASH computed:"); + DBG_dump("", r_hashval, ctx.hmac_digest_size)); + } - /* Encrypt message (preserve st_iv and st_new_iv) */ - { - u_char old_iv[MAX_DIGEST_LEN]; - u_char new_iv[MAX_DIGEST_LEN]; + /* Encrypt message (preserve st_iv and st_new_iv) */ + { + u_char old_iv[MAX_DIGEST_LEN]; + u_char new_iv[MAX_DIGEST_LEN]; - u_int old_iv_len = st->st_iv_len; - u_int new_iv_len = st->st_new_iv_len; + u_int old_iv_len = st->st_iv_len; + u_int new_iv_len = st->st_new_iv_len; - if (old_iv_len > MAX_DIGEST_LEN || new_iv_len > MAX_DIGEST_LEN) - return STF_INTERNAL_ERROR; + if (old_iv_len > MAX_DIGEST_LEN || new_iv_len > MAX_DIGEST_LEN) + return STF_INTERNAL_ERROR; - memcpy(old_iv, st->st_iv, old_iv_len); - memcpy(new_iv, st->st_new_iv, new_iv_len); + memcpy(old_iv, st->st_iv, old_iv_len); + memcpy(new_iv, st->st_new_iv, new_iv_len); - init_phase2_iv(st, &msgid); - if (!encrypt_message(&rbody, st)) - return STF_INTERNAL_ERROR; - - /* restore preserved st_iv and st_new_iv */ - memcpy(st->st_iv, old_iv, old_iv_len); - memcpy(st->st_new_iv, new_iv, new_iv_len); - st->st_iv_len = old_iv_len; - st->st_new_iv_len = new_iv_len; - } + init_phase2_iv(st, &msgid); + if (!encrypt_message(&rbody, st)) + return STF_INTERNAL_ERROR; + + /* restore preserved st_iv and st_new_iv */ + memcpy(st->st_iv, old_iv, old_iv_len); + memcpy(st->st_new_iv, new_iv, new_iv_len); + st->st_iv_len = old_iv_len; + st->st_new_iv_len = new_iv_len; + } - /* Send packet (preserve st_tpacket) */ - { - chunk_t saved_tpacket = st->st_tpacket; + /* Send packet (preserve st_tpacket) */ + { + chunk_t saved_tpacket = st->st_tpacket; - st->st_tpacket = chunk_create(reply.start, pbs_offset(&reply)); - send_packet(st, "ISAKMP notify"); - st->st_tpacket = saved_tpacket; - } + st->st_tpacket = chunk_create(reply.start, pbs_offset(&reply)); + send_packet(st, "ISAKMP notify"); + st->st_tpacket = saved_tpacket; + } - return STF_IGNORE; + return STF_IGNORE; } /* @@ -5357,89 +5357,89 @@ send_isakmp_notification(struct state *st, u_int16_t type void dpd_outI(struct state *p2st) { - struct state *st; - u_int32_t seqno; - time_t tm; - time_t idle_time; - time_t delay = p2st->st_connection->dpd_delay; - time_t timeout = p2st->st_connection->dpd_timeout; + struct state *st; + u_int32_t seqno; + time_t tm; + time_t idle_time; + time_t delay = p2st->st_connection->dpd_delay; + time_t timeout = p2st->st_connection->dpd_timeout; - /* find the newest related Phase 1 state */ - st = find_phase1_state(p2st->st_connection, ISAKMP_SA_ESTABLISHED_STATES); + /* find the newest related Phase 1 state */ + st = find_phase1_state(p2st->st_connection, ISAKMP_SA_ESTABLISHED_STATES); - if (st == NULL) - { - loglog(RC_LOG_SERIOUS, "DPD: Could not find newest phase 1 state"); - return; - } + if (st == NULL) + { + loglog(RC_LOG_SERIOUS, "DPD: Could not find newest phase 1 state"); + return; + } - /* If no DPD, then get out of here */ - if (!st->st_dpd) - return; + /* If no DPD, then get out of here */ + if (!st->st_dpd) + return; - /* schedule the next periodic DPD event */ - event_schedule(EVENT_DPD, delay, p2st); + /* schedule the next periodic DPD event */ + event_schedule(EVENT_DPD, delay, p2st); - /* Current time */ - tm = now(); + /* Current time */ + tm = now(); - /* Make sure we really need to invoke DPD */ - if (!was_eroute_idle(p2st, delay, &idle_time)) - { + /* Make sure we really need to invoke DPD */ + if (!was_eroute_idle(p2st, delay, &idle_time)) + { + DBG(DBG_CONTROL, + DBG_log("recent eroute activity %u seconds ago, " + "no need to send DPD notification" + , (int)idle_time) + ) + st->st_last_dpd = tm; + delete_dpd_event(st); + return; + } + + /* If an R_U_THERE has been sent or received recently, or if a + * companion Phase 2 SA has shown eroute activity, + * then we don't need to invoke DPD. + */ + if (tm < st->st_last_dpd + delay) + { + DBG(DBG_CONTROL, + DBG_log("recent DPD activity %u seconds ago, " + "no need to send DPD notification" + , (int)(tm - st->st_last_dpd)) + ) + return; + } + + if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state)) + return; + + if (!st->st_dpd_seqno) + { + /* Get a non-zero random value that has room to grow */ + get_rnd_bytes((u_char *)&st->st_dpd_seqno, sizeof(st->st_dpd_seqno)); + st->st_dpd_seqno &= 0x7fff; + st->st_dpd_seqno++; + } + seqno = htonl(st->st_dpd_seqno); + + if (send_isakmp_notification(st, R_U_THERE, &seqno, sizeof(seqno)) != STF_IGNORE) + { + loglog(RC_LOG_SERIOUS, "DPD: Could not send R_U_THERE"); + return; + } DBG(DBG_CONTROL, - DBG_log("recent eroute activity %u seconds ago, " - "no need to send DPD notification" - , (int)idle_time) + DBG_log("sent DPD notification R_U_THERE with seqno = %u", st->st_dpd_seqno) ) + st->st_dpd_expectseqno = st->st_dpd_seqno++; st->st_last_dpd = tm; - delete_dpd_event(st); - return; - } - - /* If an R_U_THERE has been sent or received recently, or if a - * companion Phase 2 SA has shown eroute activity, - * then we don't need to invoke DPD. - */ - if (tm < st->st_last_dpd + delay) - { - DBG(DBG_CONTROL, - DBG_log("recent DPD activity %u seconds ago, " - "no need to send DPD notification" - , (int)(tm - st->st_last_dpd)) - ) - return; - } - - if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state)) - return; - - if (!st->st_dpd_seqno) - { - /* Get a non-zero random value that has room to grow */ - get_rnd_bytes((u_char *)&st->st_dpd_seqno, sizeof(st->st_dpd_seqno)); - st->st_dpd_seqno &= 0x7fff; - st->st_dpd_seqno++; - } - seqno = htonl(st->st_dpd_seqno); - - if (send_isakmp_notification(st, R_U_THERE, &seqno, sizeof(seqno)) != STF_IGNORE) - { - loglog(RC_LOG_SERIOUS, "DPD: Could not send R_U_THERE"); - return; - } - DBG(DBG_CONTROL, - DBG_log("sent DPD notification R_U_THERE with seqno = %u", st->st_dpd_seqno) - ) - st->st_dpd_expectseqno = st->st_dpd_seqno++; - st->st_last_dpd = tm; - /* Only schedule a new timeout if there isn't one currently, - * or if it would be sooner than the current timeout. */ - if (st->st_dpd_event == NULL - || st->st_dpd_event->ev_time > tm + timeout) - { - delete_dpd_event(st); - event_schedule(EVENT_DPD_TIMEOUT, timeout, st); - } + /* Only schedule a new timeout if there isn't one currently, + * or if it would be sooner than the current timeout. */ + if (st->st_dpd_event == NULL + || st->st_dpd_event->ev_time > tm + timeout) + { + delete_dpd_event(st); + event_schedule(EVENT_DPD_TIMEOUT, timeout, st); + } } /* @@ -5449,68 +5449,68 @@ stf_status dpd_inI_outR(struct state *st, struct isakmp_notification *const n, pb_stream *pbs) { time_t tm = now(); - u_int32_t seqno; + u_int32_t seqno; - if (st == NULL || !IS_ISAKMP_SA_ESTABLISHED(st->st_state)) - { - loglog(RC_LOG_SERIOUS, "DPD: Received R_U_THERE for unestablished ISAKMP SA"); - return STF_IGNORE; - } - if (n->isan_spisize != COOKIE_SIZE * 2 || pbs_left(pbs) < COOKIE_SIZE * 2) - { - loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE has invalid SPI length (%d)", n->isan_spisize); - return STF_FAIL + PAYLOAD_MALFORMED; - } + if (st == NULL || !IS_ISAKMP_SA_ESTABLISHED(st->st_state)) + { + loglog(RC_LOG_SERIOUS, "DPD: Received R_U_THERE for unestablished ISAKMP SA"); + return STF_IGNORE; + } + if (n->isan_spisize != COOKIE_SIZE * 2 || pbs_left(pbs) < COOKIE_SIZE * 2) + { + loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE has invalid SPI length (%d)", n->isan_spisize); + return STF_FAIL + PAYLOAD_MALFORMED; + } - if (memcmp(pbs->cur, st->st_icookie, COOKIE_SIZE) != 0) - { + if (memcmp(pbs->cur, st->st_icookie, COOKIE_SIZE) != 0) + { #ifdef APPLY_CRISCO - /* Ignore it, cisco sends odd icookies */ + /* Ignore it, cisco sends odd icookies */ #else - loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE has invalid icookie (broken Cisco?)"); - return STF_FAIL + INVALID_COOKIE; + loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE has invalid icookie (broken Cisco?)"); + return STF_FAIL + INVALID_COOKIE; #endif - } - pbs->cur += COOKIE_SIZE; + } + pbs->cur += COOKIE_SIZE; - if (memcmp(pbs->cur, st->st_rcookie, COOKIE_SIZE) != 0) - { - loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE has invalid rcookie (broken Cisco?)"); - return STF_FAIL + INVALID_COOKIE; - } - pbs->cur += COOKIE_SIZE; + if (memcmp(pbs->cur, st->st_rcookie, COOKIE_SIZE) != 0) + { + loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE has invalid rcookie (broken Cisco?)"); + return STF_FAIL + INVALID_COOKIE; + } + pbs->cur += COOKIE_SIZE; - if (pbs_left(pbs) != sizeof(seqno)) - { - loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE has invalid data length (%d)" - , (int) pbs_left(pbs)); - return STF_FAIL + PAYLOAD_MALFORMED; - } + if (pbs_left(pbs) != sizeof(seqno)) + { + loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE has invalid data length (%d)" + , (int) pbs_left(pbs)); + return STF_FAIL + PAYLOAD_MALFORMED; + } - seqno = ntohl(*(u_int32_t *)pbs->cur); - DBG(DBG_CONTROL, - DBG_log("received DPD notification R_U_THERE with seqno = %u", seqno) - ) + seqno = ntohl(*(u_int32_t *)pbs->cur); + DBG(DBG_CONTROL, + DBG_log("received DPD notification R_U_THERE with seqno = %u", seqno) + ) - if (st->st_dpd_peerseqno && seqno <= st->st_dpd_peerseqno) { - loglog(RC_LOG_SERIOUS, "DPD: Received old or duplicate R_U_THERE"); - return STF_IGNORE; - } + if (st->st_dpd_peerseqno && seqno <= st->st_dpd_peerseqno) { + loglog(RC_LOG_SERIOUS, "DPD: Received old or duplicate R_U_THERE"); + return STF_IGNORE; + } - st->st_dpd_peerseqno = seqno; - delete_dpd_event(st); + st->st_dpd_peerseqno = seqno; + delete_dpd_event(st); - if (send_isakmp_notification(st, R_U_THERE_ACK, pbs->cur, pbs_left(pbs)) != STF_IGNORE) - { - loglog(RC_LOG_SERIOUS, "DPD Info: could not send R_U_THERE_ACK"); - return STF_IGNORE; - } - DBG(DBG_CONTROL, - DBG_log("sent DPD notification R_U_THERE_ACK with seqno = %u", seqno) - ) + if (send_isakmp_notification(st, R_U_THERE_ACK, pbs->cur, pbs_left(pbs)) != STF_IGNORE) + { + loglog(RC_LOG_SERIOUS, "DPD Info: could not send R_U_THERE_ACK"); + return STF_IGNORE; + } + DBG(DBG_CONTROL, + DBG_log("sent DPD notification R_U_THERE_ACK with seqno = %u", seqno) + ) - st->st_last_dpd = tm; - return STF_IGNORE; + st->st_last_dpd = tm; + return STF_IGNORE; } /* @@ -5519,69 +5519,69 @@ dpd_inI_outR(struct state *st, struct isakmp_notification *const n, pb_stream *p stf_status dpd_inR(struct state *st, struct isakmp_notification *const n, pb_stream *pbs) { - u_int32_t seqno; + u_int32_t seqno; - if (st == NULL || !IS_ISAKMP_SA_ESTABLISHED(st->st_state)) - { - loglog(RC_LOG_SERIOUS - , "DPD: Received R_U_THERE_ACK for unestablished ISAKMP SA"); - return STF_FAIL; - } + if (st == NULL || !IS_ISAKMP_SA_ESTABLISHED(st->st_state)) + { + loglog(RC_LOG_SERIOUS + , "DPD: Received R_U_THERE_ACK for unestablished ISAKMP SA"); + return STF_FAIL; + } if (n->isan_spisize != COOKIE_SIZE * 2 || pbs_left(pbs) < COOKIE_SIZE * 2) - { - loglog(RC_LOG_SERIOUS - , "DPD: R_U_THERE_ACK has invalid SPI length (%d)" - , n->isan_spisize); - return STF_FAIL + PAYLOAD_MALFORMED; - } + { + loglog(RC_LOG_SERIOUS + , "DPD: R_U_THERE_ACK has invalid SPI length (%d)" + , n->isan_spisize); + return STF_FAIL + PAYLOAD_MALFORMED; + } - if (memcmp(pbs->cur, st->st_icookie, COOKIE_SIZE) != 0) - { + if (memcmp(pbs->cur, st->st_icookie, COOKIE_SIZE) != 0) + { #ifdef APPLY_CRISCO - /* Ignore it, cisco sends odd icookies */ + /* Ignore it, cisco sends odd icookies */ #else - loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE_ACK has invalid icookie"); - return STF_FAIL + INVALID_COOKIE; + loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE_ACK has invalid icookie"); + return STF_FAIL + INVALID_COOKIE; #endif - } - pbs->cur += COOKIE_SIZE; + } + pbs->cur += COOKIE_SIZE; - if (memcmp(pbs->cur, st->st_rcookie, COOKIE_SIZE) != 0) - { + if (memcmp(pbs->cur, st->st_rcookie, COOKIE_SIZE) != 0) + { #ifdef APPLY_CRISCO - /* Ignore it, cisco sends odd icookies */ + /* Ignore it, cisco sends odd icookies */ #else - loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE_ACK has invalid rcookie"); - return STF_FAIL + INVALID_COOKIE; + loglog(RC_LOG_SERIOUS, "DPD: R_U_THERE_ACK has invalid rcookie"); + return STF_FAIL + INVALID_COOKIE; #endif - } - pbs->cur += COOKIE_SIZE; + } + pbs->cur += COOKIE_SIZE; - if (pbs_left(pbs) != sizeof(seqno)) - { - loglog(RC_LOG_SERIOUS - , " DPD: R_U_THERE_ACK has invalid data length (%d)" - , (int) pbs_left(pbs)); - return STF_FAIL + PAYLOAD_MALFORMED; - } + if (pbs_left(pbs) != sizeof(seqno)) + { + loglog(RC_LOG_SERIOUS + , " DPD: R_U_THERE_ACK has invalid data length (%d)" + , (int) pbs_left(pbs)); + return STF_FAIL + PAYLOAD_MALFORMED; + } - seqno = ntohl(*(u_int32_t *)pbs->cur); - DBG(DBG_CONTROL, - DBG_log("received DPD notification R_U_THERE_ACK with seqno = %u" - , seqno) - ) + seqno = ntohl(*(u_int32_t *)pbs->cur); + DBG(DBG_CONTROL, + DBG_log("received DPD notification R_U_THERE_ACK with seqno = %u" + , seqno) + ) - if (!st->st_dpd_expectseqno && seqno != st->st_dpd_expectseqno) - { - loglog(RC_LOG_SERIOUS - , "DPD: R_U_THERE_ACK has unexpected sequence number"); - return STF_FAIL + PAYLOAD_MALFORMED; - } + if (!st->st_dpd_expectseqno && seqno != st->st_dpd_expectseqno) + { + loglog(RC_LOG_SERIOUS + , "DPD: R_U_THERE_ACK has unexpected sequence number"); + return STF_FAIL + PAYLOAD_MALFORMED; + } - st->st_dpd_expectseqno = 0; - delete_dpd_event(st); - return STF_IGNORE; + st->st_dpd_expectseqno = 0; + delete_dpd_event(st); + return STF_IGNORE; } /* @@ -5594,67 +5594,67 @@ dpd_inR(struct state *st, struct isakmp_notification *const n, pb_stream *pbs) void dpd_timeout(struct state *st) { - struct state *newest_phase1_st; - struct connection *c = st->st_connection; - int action = st->st_connection->dpd_action; - char cname[BUF_LEN]; + struct state *newest_phase1_st; + struct connection *c = st->st_connection; + int action = st->st_connection->dpd_action; + char cname[BUF_LEN]; - passert(action == DPD_ACTION_HOLD - || action == DPD_ACTION_CLEAR - || DPD_ACTION_RESTART); + passert(action == DPD_ACTION_HOLD + || action == DPD_ACTION_CLEAR + || DPD_ACTION_RESTART); - /* is there a newer phase1_state? */ - newest_phase1_st = find_phase1_state(c, ISAKMP_SA_ESTABLISHED_STATES); - if (newest_phase1_st != NULL && newest_phase1_st != st) - { - plog("DPD: Phase1 state #%ld has been superseded by #%ld" - " - timeout ignored" - , st->st_serialno, newest_phase1_st->st_serialno); - return; - } + /* is there a newer phase1_state? */ + newest_phase1_st = find_phase1_state(c, ISAKMP_SA_ESTABLISHED_STATES); + if (newest_phase1_st != NULL && newest_phase1_st != st) + { + plog("DPD: Phase1 state #%ld has been superseded by #%ld" + " - timeout ignored" + , st->st_serialno, newest_phase1_st->st_serialno); + return; + } - loglog(RC_LOG_SERIOUS, "DPD: No response from peer - declaring peer dead"); + loglog(RC_LOG_SERIOUS, "DPD: No response from peer - declaring peer dead"); - /* delete the state, which is probably in phase 2 */ - set_cur_connection(c); - plog("DPD: Terminating all SAs using this connection"); - delete_states_by_connection(c, TRUE); - reset_cur_connection(); + /* delete the state, which is probably in phase 2 */ + set_cur_connection(c); + plog("DPD: Terminating all SAs using this connection"); + delete_states_by_connection(c, TRUE); + reset_cur_connection(); - switch (action) - { - case DPD_ACTION_HOLD: - /* dpdaction=hold - Wipe the SA's but %trap the eroute so we don't - * leak traffic. Also, being in %trap means new packets will - * force an initiation of the conn again. - */ - loglog(RC_LOG_SERIOUS, "DPD: Putting connection \"%s\" into %%trap", c->name); - if (c->kind == CK_INSTANCE) - delete_connection(c, TRUE); - break; - case DPD_ACTION_CLEAR: - /* dpdaction=clear - Wipe the SA & eroute - everything */ - loglog(RC_LOG_SERIOUS, "DPD: Clearing connection \"%s\"", c->name); - unroute_connection(c); - if (c->kind == CK_INSTANCE) - delete_connection(c, TRUE); - break; - case DPD_ACTION_RESTART: - /* dpdaction=restart - Restart connection, - * except if roadwarrior connection - */ - loglog(RC_LOG_SERIOUS, "DPD: Restarting connection \"%s\"", c->name); - unroute_connection(c); + switch (action) + { + case DPD_ACTION_HOLD: + /* dpdaction=hold - Wipe the SA's but %trap the eroute so we don't + * leak traffic. Also, being in %trap means new packets will + * force an initiation of the conn again. + */ + loglog(RC_LOG_SERIOUS, "DPD: Putting connection \"%s\" into %%trap", c->name); + if (c->kind == CK_INSTANCE) + delete_connection(c, TRUE); + break; + case DPD_ACTION_CLEAR: + /* dpdaction=clear - Wipe the SA & eroute - everything */ + loglog(RC_LOG_SERIOUS, "DPD: Clearing connection \"%s\"", c->name); + unroute_connection(c); + if (c->kind == CK_INSTANCE) + delete_connection(c, TRUE); + break; + case DPD_ACTION_RESTART: + /* dpdaction=restart - Restart connection, + * except if roadwarrior connection + */ + loglog(RC_LOG_SERIOUS, "DPD: Restarting connection \"%s\"", c->name); + unroute_connection(c); - /* caching the connection name before deletion */ - strncpy(cname, c->name, BUF_LEN); + /* caching the connection name before deletion */ + strncpy(cname, c->name, BUF_LEN); - if (c->kind == CK_INSTANCE) - delete_connection(c, TRUE); - initiate_connection(cname, NULL_FD); - break; - default: - loglog(RC_LOG_SERIOUS, "DPD: unknown action"); - } + if (c->kind == CK_INSTANCE) + delete_connection(c, TRUE); + initiate_connection(cname, NULL_FD); + break; + default: + loglog(RC_LOG_SERIOUS, "DPD: unknown action"); + } } diff --git a/src/pluto/ipsec_doi.h b/src/pluto/ipsec_doi.h index a05f44291..0abd07697 100644 --- a/src/pluto/ipsec_doi.h +++ b/src/pluto/ipsec_doi.h @@ -17,48 +17,48 @@ extern void echo_hdr(struct msg_digest *md, bool enc, u_int8_t np); extern void ipsecdoi_initiate(int whack_sock, struct connection *c - , lset_t policy, unsigned long try, so_serial_t replacing); + , lset_t policy, unsigned long try, so_serial_t replacing); extern void ipsecdoi_replace(struct state *st, unsigned long try); extern void init_phase2_iv(struct state *st, const msgid_t *msgid); extern stf_status quick_outI1(int whack_sock - , struct state *isakmp_sa - , struct connection *c - , lset_t policy - , unsigned long try - , so_serial_t replacing); + , struct state *isakmp_sa + , struct connection *c + , lset_t policy + , unsigned long try + , so_serial_t replacing); extern state_transition_fn - main_inI1_outR1, - main_inR1_outI2, - main_inI2_outR2, - main_inR2_outI3, - main_inI3_outR3, - main_inR3, - quick_inI1_outR1, - quick_inR1_outI2, - quick_inI2; + main_inI1_outR1, + main_inR1_outI2, + main_inI2_outR2, + main_inR2_outI3, + main_inI3_outR3, + main_inR3, + quick_inI1_outR1, + quick_inR1_outI2, + quick_inI2; extern void send_delete(struct state *st); extern void accept_delete(struct state *st, struct msg_digest *md - , struct payload_digest *p); + , struct payload_digest *p); extern void close_message(pb_stream *pbs); extern bool encrypt_message(pb_stream *pbs, struct state *st); extern void send_notification_from_state(struct state *st, - enum state_kind state, u_int16_t type); + enum state_kind state, u_int16_t type); extern void send_notification_from_md(struct msg_digest *md, u_int16_t type); extern const char *init_pluto_vendorid(void); extern void dpd_outI(struct state *st); extern stf_status dpd_inI_outR(struct state *st - , struct isakmp_notification *const n, pb_stream *n_pbs); + , struct isakmp_notification *const n, pb_stream *n_pbs); extern stf_status dpd_inR(struct state *st - , struct isakmp_notification *const n, pb_stream *n_pbs); + , struct isakmp_notification *const n, pb_stream *n_pbs); extern void dpd_timeout(struct state *st); /* START_HASH_PAYLOAD @@ -70,14 +70,14 @@ extern void dpd_timeout(struct state *st); * - it references variables local to the caller (r_hashval, r_hash_start, st) */ #define START_HASH_PAYLOAD(rbody, np) { \ - pb_stream hash_pbs; \ - if (!out_generic(np, &isakmp_hash_desc, &(rbody), &hash_pbs)) \ - return STF_INTERNAL_ERROR; \ - r_hashval = hash_pbs.cur; /* remember where to plant value */ \ - if (!out_zero(st->st_oakley.hasher->hash_digest_size, &hash_pbs, "HASH")) \ - return STF_INTERNAL_ERROR; \ - close_output_pbs(&hash_pbs); \ - r_hash_start = (rbody).cur; /* hash from after HASH payload */ \ + pb_stream hash_pbs; \ + if (!out_generic(np, &isakmp_hash_desc, &(rbody), &hash_pbs)) \ + return STF_INTERNAL_ERROR; \ + r_hashval = hash_pbs.cur; /* remember where to plant value */ \ + if (!out_zero(st->st_oakley.hasher->hash_digest_size, &hash_pbs, "HASH")) \ + return STF_INTERNAL_ERROR; \ + close_output_pbs(&hash_pbs); \ + r_hash_start = (rbody).cur; /* hash from after HASH payload */ \ } /* CHECK_QUICK_HASH @@ -88,17 +88,17 @@ extern void dpd_timeout(struct state *st); * expression to reference them (hash_val, hash_pbs) */ #define CHECK_QUICK_HASH(md, do_hash, hash_name, msg_name) { \ - pb_stream *const hash_pbs = &md->chain[ISAKMP_NEXT_HASH]->pbs; \ - u_char hash_val[MAX_DIGEST_LEN]; \ - size_t hash_len = do_hash; \ - if (pbs_left(hash_pbs) != hash_len \ - || memcmp(hash_pbs->cur, hash_val, hash_len) != 0) \ - { \ - DBG_cond_dump(DBG_CRYPT, "received " hash_name ":", hash_pbs->cur, pbs_left(hash_pbs)); \ - loglog(RC_LOG_SERIOUS, "received " hash_name " does not match computed value in " msg_name); \ - /* XXX Could send notification back */ \ - return STF_FAIL + INVALID_HASH_INFORMATION; \ - } \ - } + pb_stream *const hash_pbs = &md->chain[ISAKMP_NEXT_HASH]->pbs; \ + u_char hash_val[MAX_DIGEST_LEN]; \ + size_t hash_len = do_hash; \ + if (pbs_left(hash_pbs) != hash_len \ + || memcmp(hash_pbs->cur, hash_val, hash_len) != 0) \ + { \ + DBG_cond_dump(DBG_CRYPT, "received " hash_name ":", hash_pbs->cur, pbs_left(hash_pbs)); \ + loglog(RC_LOG_SERIOUS, "received " hash_name " does not match computed value in " msg_name); \ + /* XXX Could send notification back */ \ + return STF_FAIL + INVALID_HASH_INFORMATION; \ + } \ + } diff --git a/src/pluto/kameipsec.h b/src/pluto/kameipsec.h index 5f08c7d38..5e9d8ce99 100644 --- a/src/pluto/kameipsec.h +++ b/src/pluto/kameipsec.h @@ -3,45 +3,45 @@ /* The definitions, required to talk to KAME racoon IKE. */ -#define IPSEC_PORT_ANY 0 -#define IPSEC_ULPROTO_ANY 255 -#define IPSEC_PROTO_ANY 255 +#define IPSEC_PORT_ANY 0 +#define IPSEC_ULPROTO_ANY 255 +#define IPSEC_PROTO_ANY 255 enum { - IPSEC_MODE_ANY = 0, /* We do not support this for SA */ - IPSEC_MODE_TRANSPORT = 1, - IPSEC_MODE_TUNNEL = 2 + IPSEC_MODE_ANY = 0, /* We do not support this for SA */ + IPSEC_MODE_TRANSPORT = 1, + IPSEC_MODE_TUNNEL = 2 }; enum { - IPSEC_DIR_ANY = 0, - IPSEC_DIR_INBOUND = 1, - IPSEC_DIR_OUTBOUND = 2, - IPSEC_DIR_FWD = 3, /* It is our own */ - IPSEC_DIR_MAX = 4, - IPSEC_DIR_INVALID = 5 + IPSEC_DIR_ANY = 0, + IPSEC_DIR_INBOUND = 1, + IPSEC_DIR_OUTBOUND = 2, + IPSEC_DIR_FWD = 3, /* It is our own */ + IPSEC_DIR_MAX = 4, + IPSEC_DIR_INVALID = 5 }; enum { - IPSEC_POLICY_DISCARD = 0, - IPSEC_POLICY_NONE = 1, - IPSEC_POLICY_IPSEC = 2, - IPSEC_POLICY_ENTRUST = 3, - IPSEC_POLICY_BYPASS = 4 + IPSEC_POLICY_DISCARD = 0, + IPSEC_POLICY_NONE = 1, + IPSEC_POLICY_IPSEC = 2, + IPSEC_POLICY_ENTRUST = 3, + IPSEC_POLICY_BYPASS = 4 }; enum { - IPSEC_LEVEL_DEFAULT = 0, - IPSEC_LEVEL_USE = 1, - IPSEC_LEVEL_REQUIRE = 2, - IPSEC_LEVEL_UNIQUE = 3 + IPSEC_LEVEL_DEFAULT = 0, + IPSEC_LEVEL_USE = 1, + IPSEC_LEVEL_REQUIRE = 2, + IPSEC_LEVEL_UNIQUE = 3 }; -#define IPSEC_MANUAL_REQID_MAX 0x3fff +#define IPSEC_MANUAL_REQID_MAX 0x3fff #define IPSEC_REPLAYWSIZE 32 #define IP_IPSEC_POLICY 16 #define IPV6_IPSEC_POLICY 34 -#endif /* __IPSEC_H */ +#endif /* __IPSEC_H */ diff --git a/src/pluto/kernel.c b/src/pluto/kernel.c index 9a3715ee3..a6a8b1c90 100644 --- a/src/pluto/kernel.c +++ b/src/pluto/kernel.c @@ -35,8 +35,8 @@ #ifdef KLIPS #include -#include /* for select(2) */ -#include /* for select(2) */ +#include /* for select(2) */ +#include /* for select(2) */ #include #include #include "kameipsec.h" @@ -56,7 +56,7 @@ #include "log.h" #include "ca.h" #include "server.h" -#include "whack.h" /* for RC_LOG_SERIOUS */ +#include "whack.h" /* for RC_LOG_SERIOUS */ #include "keys.h" #include "nat_traversal.h" #include "alg_info.h" @@ -69,7 +69,7 @@ bool can_do_IPcomp = TRUE; /* can system actually perform IPCOMP? */ * logic loses track and swats them? 64 is the best KLIPS can do. * And 32 is the best XFRM can do... */ -#define REPLAY_WINDOW 64 +#define REPLAY_WINDOW 64 #define REPLAY_WINDOW_XFRM 32 /* test if the routes required for two different connections agree @@ -77,11 +77,11 @@ bool can_do_IPcomp = TRUE; /* can system actually perform IPCOMP? */ * testing that the interfaces and nexthops match. */ #define routes_agree(c, d) ((c)->interface == (d)->interface \ - && sameaddr(&(c)->spd.this.host_nexthop, &(d)->spd.this.host_nexthop)) + && sameaddr(&(c)->spd.this.host_nexthop, &(d)->spd.this.host_nexthop)) #ifndef KLIPS -bool no_klips = TRUE; /* don't actually use KLIPS */ +bool no_klips = TRUE; /* don't actually use KLIPS */ #else /* !KLIPS */ @@ -96,25 +96,25 @@ bool no_klips = TRUE; /* don't actually use KLIPS */ * which %holds are news and which others should expire. */ -#define SHUNT_SCAN_INTERVAL (60 * 2) /* time between scans of eroutes */ +#define SHUNT_SCAN_INTERVAL (60 * 2) /* time between scans of eroutes */ /* SHUNT_PATIENCE only has resolution down to a multiple of the sample rate, * SHUNT_SCAN_INTERVAL. * By making SHUNT_PATIENCE an odd multiple of half of SHUNT_SCAN_INTERVAL, * we minimize the effects of jitter. */ -#define SHUNT_PATIENCE (SHUNT_SCAN_INTERVAL * 15 / 2) /* inactivity timeout */ +#define SHUNT_PATIENCE (SHUNT_SCAN_INTERVAL * 15 / 2) /* inactivity timeout */ struct bare_shunt { - policy_prio_t policy_prio; - ip_subnet ours; - ip_subnet his; - ip_said said; - int transport_proto; - unsigned long count; - time_t last_activity; - char *why; - struct bare_shunt *next; + policy_prio_t policy_prio; + ip_subnet ours; + ip_subnet his; + ip_said said; + int transport_proto; + unsigned long count; + time_t last_activity; + char *why; + struct bare_shunt *next; }; static struct bare_shunt *bare_shunts = NULL; @@ -123,23 +123,23 @@ static struct bare_shunt *bare_shunts = NULL; static void DBG_bare_shunt(const char *op, const struct bare_shunt *bs) { - DBG(DBG_KLIPS, - { - int ourport = ntohs(portof(&(bs)->ours.addr)); - int hisport = ntohs(portof(&(bs)->his.addr)); - char ourst[SUBNETTOT_BUF]; - char hist[SUBNETTOT_BUF]; - char sat[SATOT_BUF]; - char prio[POLICY_PRIO_BUF]; + DBG(DBG_KLIPS, + { + int ourport = ntohs(portof(&(bs)->ours.addr)); + int hisport = ntohs(portof(&(bs)->his.addr)); + char ourst[SUBNETTOT_BUF]; + char hist[SUBNETTOT_BUF]; + char sat[SATOT_BUF]; + char prio[POLICY_PRIO_BUF]; - subnettot(&(bs)->ours, 0, ourst, sizeof(ourst)); - subnettot(&(bs)->his, 0, hist, sizeof(hist)); - satot(&(bs)->said, 0, sat, sizeof(sat)); - fmt_policy_prio(bs->policy_prio, prio); - DBG_log("%s bare shunt %p %s:%d -> %s:%d => %s:%d %s %s" - , op, (const void *)(bs), ourst, ourport, hist, hisport - , sat, (bs)->transport_proto, prio, (bs)->why); - }); + subnettot(&(bs)->ours, 0, ourst, sizeof(ourst)); + subnettot(&(bs)->his, 0, hist, sizeof(hist)); + satot(&(bs)->said, 0, sat, sizeof(sat)); + fmt_policy_prio(bs->policy_prio, prio); + DBG_log("%s bare shunt %p %s:%d -> %s:%d => %s:%d %s %s" + , op, (const void *)(bs), ourst, ourport, hist, hisport + , sat, (bs)->transport_proto, prio, (bs)->why); + }); } #else /* !DEBUG */ #define DBG_bare_shunt(op, bs) {} @@ -153,111 +153,111 @@ struct eroute_info *orphaned_holds = NULL; /* forward declaration */ static bool shunt_eroute(struct connection *c - , struct spd_route *sr - , enum routing_t rt_kind - , unsigned int op, const char *opname); + , struct spd_route *sr + , enum routing_t rt_kind + , unsigned int op, const char *opname); static void set_text_said(char *text_said - , const ip_address *dst - , ipsec_spi_t spi - , int proto); + , const ip_address *dst + , ipsec_spi_t spi + , int proto); -bool no_klips = FALSE; /* don't actually use KLIPS */ +bool no_klips = FALSE; /* don't actually use KLIPS */ static const struct pfkey_proto_info null_proto_info[2] = { - { - proto: IPPROTO_ESP, - encapsulation: ENCAPSULATION_MODE_TRANSPORT, - reqid: 0 - }, - { - proto: 0, - encapsulation: 0, - reqid: 0 - } + { + proto: IPPROTO_ESP, + encapsulation: ENCAPSULATION_MODE_TRANSPORT, + reqid: 0 + }, + { + proto: 0, + encapsulation: 0, + reqid: 0 + } }; void record_and_initiate_opportunistic(const ip_subnet *ours - , const ip_subnet *his - , int transport_proto - , const char *why) + , const ip_subnet *his + , int transport_proto + , const char *why) { - passert(samesubnettype(ours, his)); + passert(samesubnettype(ours, his)); - /* Add to bare shunt list. - * We need to do this because the shunt was installed by KLIPS - * which can't do this itself. - */ - { - struct bare_shunt *bs = malloc_thing(struct bare_shunt); - - bs->why = clone_str(why); - bs->ours = *ours; - bs->his = *his; - bs->transport_proto = transport_proto; - bs->policy_prio = BOTTOM_PRIO; - - bs->said.proto = SA_INT; - bs->said.spi = htonl(SPI_HOLD); - bs->said.dst = *aftoinfo(subnettypeof(ours))->any; - - bs->count = 0; - bs->last_activity = now(); - - bs->next = bare_shunts; - bare_shunts = bs; - DBG_bare_shunt("add", bs); - } - - /* actually initiate opportunism */ - { - ip_address src, dst; - - networkof(ours, &src); - networkof(his, &dst); - initiate_opportunistic(&src, &dst, transport_proto, TRUE, NULL_FD); - } - - /* if present, remove from orphaned_holds list. - * NOTE: we do this last in case ours or his is a pointer into a member. - */ - { - struct eroute_info **pp, *p; - - for (pp = &orphaned_holds; (p = *pp) != NULL; pp = &p->next) + /* Add to bare shunt list. + * We need to do this because the shunt was installed by KLIPS + * which can't do this itself. + */ { - if (samesubnet(ours, &p->ours) - && samesubnet(his, &p->his) - && transport_proto == p->transport_proto - && portof(&ours->addr) == portof(&p->ours.addr) - && portof(&his->addr) == portof(&p->his.addr)) - { - *pp = p->next; - free(p); - break; - } + struct bare_shunt *bs = malloc_thing(struct bare_shunt); + + bs->why = clone_str(why); + bs->ours = *ours; + bs->his = *his; + bs->transport_proto = transport_proto; + bs->policy_prio = BOTTOM_PRIO; + + bs->said.proto = SA_INT; + bs->said.spi = htonl(SPI_HOLD); + bs->said.dst = *aftoinfo(subnettypeof(ours))->any; + + bs->count = 0; + bs->last_activity = now(); + + bs->next = bare_shunts; + bare_shunts = bs; + DBG_bare_shunt("add", bs); + } + + /* actually initiate opportunism */ + { + ip_address src, dst; + + networkof(ours, &src); + networkof(his, &dst); + initiate_opportunistic(&src, &dst, transport_proto, TRUE, NULL_FD); + } + + /* if present, remove from orphaned_holds list. + * NOTE: we do this last in case ours or his is a pointer into a member. + */ + { + struct eroute_info **pp, *p; + + for (pp = &orphaned_holds; (p = *pp) != NULL; pp = &p->next) + { + if (samesubnet(ours, &p->ours) + && samesubnet(his, &p->his) + && transport_proto == p->transport_proto + && portof(&ours->addr) == portof(&p->ours.addr) + && portof(&his->addr) == portof(&p->his.addr)) + { + *pp = p->next; + free(p); + break; + } + } } - } } #endif /* KLIPS */ static unsigned get_proto_reqid(unsigned base, int proto) { - switch (proto) - { - default: - case IPPROTO_COMP: - base++; - /* fall through */ - case IPPROTO_ESP: - base++; - /* fall through */ - case IPPROTO_AH: - break; - } + switch (proto) + { + default: + case IPPROTO_COMP: + base++; + /* fall through */ + case IPPROTO_ESP: + base++; + /* fall through */ + case IPPROTO_AH: + break; + } - return base; + return base; } /* Generate Unique SPI numbers. @@ -284,30 +284,30 @@ static unsigned get_proto_reqid(unsigned base, int proto) ipsec_spi_t get_ipsec_spi(ipsec_spi_t avoid, int proto, struct spd_route *sr, bool tunnel) { - static ipsec_spi_t spi = 0; /* host order, so not returned directly! */ - char text_said[SATOT_BUF]; + static ipsec_spi_t spi = 0; /* host order, so not returned directly! */ + char text_said[SATOT_BUF]; - set_text_said(text_said, &sr->this.host_addr, 0, proto); + set_text_said(text_said, &sr->this.host_addr, 0, proto); - if (kernel_ops->get_spi) - return kernel_ops->get_spi(&sr->that.host_addr - , &sr->this.host_addr, proto, tunnel - , get_proto_reqid(sr->reqid, proto) - , IPSEC_DOI_SPI_OUR_MIN, 0xffffffff - , text_said); + if (kernel_ops->get_spi) + return kernel_ops->get_spi(&sr->that.host_addr + , &sr->this.host_addr, proto, tunnel + , get_proto_reqid(sr->reqid, proto) + , IPSEC_DOI_SPI_OUR_MIN, 0xffffffff + , text_said); - spi++; - while (spi < IPSEC_DOI_SPI_OUR_MIN || spi == ntohl(avoid)) - get_rnd_bytes((u_char *)&spi, sizeof(spi)); + spi++; + while (spi < IPSEC_DOI_SPI_OUR_MIN || spi == ntohl(avoid)) + get_rnd_bytes((u_char *)&spi, sizeof(spi)); - DBG(DBG_CONTROL, - { - ipsec_spi_t spi_net = htonl(spi); + DBG(DBG_CONTROL, + { + ipsec_spi_t spi_net = htonl(spi); - DBG_dump("generate SPI:", (u_char *)&spi_net, sizeof(spi_net)); - }); + DBG_dump("generate SPI:", (u_char *)&spi_net, sizeof(spi_net)); + }); - return htonl(spi); + return htonl(spi); } /* Generate Unique CPI numbers. @@ -321,35 +321,35 @@ get_ipsec_spi(ipsec_spi_t avoid, int proto, struct spd_route *sr, bool tunnel) ipsec_spi_t get_my_cpi(struct spd_route *sr, bool tunnel) { - static cpi_t - first_busy_cpi = 0, - latest_cpi; - char text_said[SATOT_BUF]; + static cpi_t + first_busy_cpi = 0, + latest_cpi; + char text_said[SATOT_BUF]; - set_text_said(text_said, &sr->this.host_addr, 0, IPPROTO_COMP); + set_text_said(text_said, &sr->this.host_addr, 0, IPPROTO_COMP); - if (kernel_ops->get_spi) - return kernel_ops->get_spi(&sr->that.host_addr - , &sr->this.host_addr, IPPROTO_COMP, tunnel - , get_proto_reqid(sr->reqid, IPPROTO_COMP) - , IPCOMP_FIRST_NEGOTIATED, IPCOMP_LAST_NEGOTIATED - , text_said); + if (kernel_ops->get_spi) + return kernel_ops->get_spi(&sr->that.host_addr + , &sr->this.host_addr, IPPROTO_COMP, tunnel + , get_proto_reqid(sr->reqid, IPPROTO_COMP) + , IPCOMP_FIRST_NEGOTIATED, IPCOMP_LAST_NEGOTIATED + , text_said); - while (!(IPCOMP_FIRST_NEGOTIATED <= first_busy_cpi && first_busy_cpi < IPCOMP_LAST_NEGOTIATED)) - { - get_rnd_bytes((u_char *)&first_busy_cpi, sizeof(first_busy_cpi)); - latest_cpi = first_busy_cpi; - } + while (!(IPCOMP_FIRST_NEGOTIATED <= first_busy_cpi && first_busy_cpi < IPCOMP_LAST_NEGOTIATED)) + { + get_rnd_bytes((u_char *)&first_busy_cpi, sizeof(first_busy_cpi)); + latest_cpi = first_busy_cpi; + } - latest_cpi++; + latest_cpi++; - if (latest_cpi == first_busy_cpi) - find_my_cpi_gap(&latest_cpi, &first_busy_cpi); + if (latest_cpi == first_busy_cpi) + find_my_cpi_gap(&latest_cpi, &first_busy_cpi); - if (latest_cpi > IPCOMP_LAST_NEGOTIATED) - latest_cpi = IPCOMP_FIRST_NEGOTIATED; + if (latest_cpi > IPCOMP_LAST_NEGOTIATED) + latest_cpi = IPCOMP_FIRST_NEGOTIATED; - return htonl((ipsec_spi_t)latest_cpi); + return htonl((ipsec_spi_t)latest_cpi); } /* invoke the updown script to do the routing and firewall commands required @@ -386,466 +386,466 @@ get_my_cpi(struct spd_route *sr, bool tunnel) */ #ifndef DEFAULT_UPDOWN -# define DEFAULT_UPDOWN "ipsec _updown" +# define DEFAULT_UPDOWN "ipsec _updown" #endif static bool do_command(struct connection *c, struct spd_route *sr, const char *verb) { - char cmd[1536]; /* arbitrary limit on shell command length */ - const char *verb_suffix; + char cmd[1536]; /* arbitrary limit on shell command length */ + const char *verb_suffix; - /* figure out which verb suffix applies */ - { - const char *hs, *cs; - - switch (addrtypeof(&sr->this.host_addr)) + /* figure out which verb suffix applies */ { - case AF_INET: - hs = "-host"; - cs = "-client"; - break; - case AF_INET6: - hs = "-host-v6"; - cs = "-client-v6"; - break; - default: - loglog(RC_LOG_SERIOUS, "unknown address family"); - return FALSE; - } - verb_suffix = subnetisaddr(&sr->this.client, &sr->this.host_addr) - ? hs : cs; - } + const char *hs, *cs; - /* form the command string */ - { - char - nexthop_str[sizeof("PLUTO_NEXT_HOP='' ") +ADDRTOT_BUF] = "", - srcip_str[sizeof("PLUTO_MY_SOURCEIP='' ")+ADDRTOT_BUF] = "", - me_str[ADDRTOT_BUF], - myid_str[BUF_LEN], - myclient_str[SUBNETTOT_BUF], - myclientnet_str[ADDRTOT_BUF], - myclientmask_str[ADDRTOT_BUF], - peer_str[ADDRTOT_BUF], - peerid_str[BUF_LEN], - peerclient_str[SUBNETTOT_BUF], - peerclientnet_str[ADDRTOT_BUF], - peerclientmask_str[ADDRTOT_BUF], - peerca_str[BUF_LEN], - secure_myid_str[BUF_LEN] = "", - secure_peerid_str[BUF_LEN] = "", - secure_peerca_str[BUF_LEN] = ""; - ip_address ta; - pubkey_list_t *p; - - if (addrbytesptr(&sr->this.host_nexthop, NULL) - && !isanyaddr(&sr->this.host_nexthop)) - { - char *n; - - strcpy(nexthop_str, "PLUTO_NEXT_HOP='"); - n = nexthop_str + strlen(nexthop_str); - - addrtot(&sr->this.host_nexthop, 0 - ,n , sizeof(nexthop_str)-strlen(nexthop_str)); - strncat(nexthop_str, "' ", sizeof(nexthop_str)); + switch (addrtypeof(&sr->this.host_addr)) + { + case AF_INET: + hs = "-host"; + cs = "-client"; + break; + case AF_INET6: + hs = "-host-v6"; + cs = "-client-v6"; + break; + default: + loglog(RC_LOG_SERIOUS, "unknown address family"); + return FALSE; + } + verb_suffix = subnetisaddr(&sr->this.client, &sr->this.host_addr) + ? hs : cs; } - if (addrbytesptr(&sr->this.host_srcip, NULL) - && !isanyaddr(&sr->this.host_srcip)) - { - char *n; - - strcpy(srcip_str, "PLUTO_MY_SOURCEIP='"); - n = srcip_str + strlen(srcip_str); - - addrtot(&sr->this.host_srcip, 0 - ,n , sizeof(srcip_str)-strlen(srcip_str)); - strncat(srcip_str, "' ", sizeof(srcip_str)); - } - - addrtot(&sr->this.host_addr, 0, me_str, sizeof(me_str)); - idtoa(&sr->this.id, myid_str, sizeof(myid_str)); - escape_metachar(myid_str, secure_myid_str, sizeof(secure_myid_str)); - subnettot(&sr->this.client, 0, myclient_str, sizeof(myclientnet_str)); - networkof(&sr->this.client, &ta); - addrtot(&ta, 0, myclientnet_str, sizeof(myclientnet_str)); - maskof(&sr->this.client, &ta); - addrtot(&ta, 0, myclientmask_str, sizeof(myclientmask_str)); - - addrtot(&sr->that.host_addr, 0, peer_str, sizeof(peer_str)); - idtoa(&sr->that.id, peerid_str, sizeof(peerid_str)); - escape_metachar(peerid_str, secure_peerid_str, sizeof(secure_peerid_str)); - subnettot(&sr->that.client, 0, peerclient_str, sizeof(peerclientnet_str)); - networkof(&sr->that.client, &ta); - addrtot(&ta, 0, peerclientnet_str, sizeof(peerclientnet_str)); - maskof(&sr->that.client, &ta); - addrtot(&ta, 0, peerclientmask_str, sizeof(peerclientmask_str)); - - for (p = pubkeys; p != NULL; p = p->next) + /* form the command string */ { - pubkey_t *key = p->key; - int pathlen; + char + nexthop_str[sizeof("PLUTO_NEXT_HOP='' ") +ADDRTOT_BUF] = "", + srcip_str[sizeof("PLUTO_MY_SOURCEIP='' ")+ADDRTOT_BUF] = "", + me_str[ADDRTOT_BUF], + myid_str[BUF_LEN], + myclient_str[SUBNETTOT_BUF], + myclientnet_str[ADDRTOT_BUF], + myclientmask_str[ADDRTOT_BUF], + peer_str[ADDRTOT_BUF], + peerid_str[BUF_LEN], + peerclient_str[SUBNETTOT_BUF], + peerclientnet_str[ADDRTOT_BUF], + peerclientmask_str[ADDRTOT_BUF], + peerca_str[BUF_LEN], + secure_myid_str[BUF_LEN] = "", + secure_peerid_str[BUF_LEN] = "", + secure_peerca_str[BUF_LEN] = ""; + ip_address ta; + pubkey_list_t *p; - if (key->alg == PUBKEY_ALG_RSA && same_id(&sr->that.id, &key->id) - && trusted_ca(key->issuer, sr->that.ca, &pathlen)) - { - dntoa_or_null(peerca_str, BUF_LEN, key->issuer, ""); - escape_metachar(peerca_str, secure_peerca_str, sizeof(secure_peerca_str)); - break; - } + if (addrbytesptr(&sr->this.host_nexthop, NULL) + && !isanyaddr(&sr->this.host_nexthop)) + { + char *n; + + strcpy(nexthop_str, "PLUTO_NEXT_HOP='"); + n = nexthop_str + strlen(nexthop_str); + + addrtot(&sr->this.host_nexthop, 0 + ,n , sizeof(nexthop_str)-strlen(nexthop_str)); + strncat(nexthop_str, "' ", sizeof(nexthop_str)); + } + + if (addrbytesptr(&sr->this.host_srcip, NULL) + && !isanyaddr(&sr->this.host_srcip)) + { + char *n; + + strcpy(srcip_str, "PLUTO_MY_SOURCEIP='"); + n = srcip_str + strlen(srcip_str); + + addrtot(&sr->this.host_srcip, 0 + ,n , sizeof(srcip_str)-strlen(srcip_str)); + strncat(srcip_str, "' ", sizeof(srcip_str)); + } + + addrtot(&sr->this.host_addr, 0, me_str, sizeof(me_str)); + idtoa(&sr->this.id, myid_str, sizeof(myid_str)); + escape_metachar(myid_str, secure_myid_str, sizeof(secure_myid_str)); + subnettot(&sr->this.client, 0, myclient_str, sizeof(myclientnet_str)); + networkof(&sr->this.client, &ta); + addrtot(&ta, 0, myclientnet_str, sizeof(myclientnet_str)); + maskof(&sr->this.client, &ta); + addrtot(&ta, 0, myclientmask_str, sizeof(myclientmask_str)); + + addrtot(&sr->that.host_addr, 0, peer_str, sizeof(peer_str)); + idtoa(&sr->that.id, peerid_str, sizeof(peerid_str)); + escape_metachar(peerid_str, secure_peerid_str, sizeof(secure_peerid_str)); + subnettot(&sr->that.client, 0, peerclient_str, sizeof(peerclientnet_str)); + networkof(&sr->that.client, &ta); + addrtot(&ta, 0, peerclientnet_str, sizeof(peerclientnet_str)); + maskof(&sr->that.client, &ta); + addrtot(&ta, 0, peerclientmask_str, sizeof(peerclientmask_str)); + + for (p = pubkeys; p != NULL; p = p->next) + { + pubkey_t *key = p->key; + int pathlen; + + if (key->alg == PUBKEY_ALG_RSA && same_id(&sr->that.id, &key->id) + && trusted_ca(key->issuer, sr->that.ca, &pathlen)) + { + dntoa_or_null(peerca_str, BUF_LEN, key->issuer, ""); + escape_metachar(peerca_str, secure_peerca_str, sizeof(secure_peerca_str)); + break; + } + } + + if (-1 == snprintf(cmd, sizeof(cmd) + , "2>&1 " /* capture stderr along with stdout */ + "PLUTO_VERSION='1.1' " /* change VERSION when interface spec changes */ + "PLUTO_VERB='%s%s' " + "PLUTO_CONNECTION='%s' " + "%s" /* optional PLUTO_NEXT_HOP */ + "PLUTO_INTERFACE='%s' " + "%s" /* optional PLUTO_HOST_ACCESS */ + "PLUTO_REQID='%u' " + "PLUTO_ME='%s' " + "PLUTO_MY_ID='%s' " + "PLUTO_MY_CLIENT='%s' " + "PLUTO_MY_CLIENT_NET='%s' " + "PLUTO_MY_CLIENT_MASK='%s' " + "PLUTO_MY_PORT='%u' " + "PLUTO_MY_PROTOCOL='%u' " + "PLUTO_PEER='%s' " + "PLUTO_PEER_ID='%s' " + "PLUTO_PEER_CLIENT='%s' " + "PLUTO_PEER_CLIENT_NET='%s' " + "PLUTO_PEER_CLIENT_MASK='%s' " + "PLUTO_PEER_PORT='%u' " + "PLUTO_PEER_PROTOCOL='%u' " + "PLUTO_PEER_CA='%s' " + "%s" /* optional PLUTO_MY_SRCIP */ + "%s" /* actual script */ + , verb, verb_suffix + , c->name + , nexthop_str + , c->interface->vname + , sr->this.hostaccess? "PLUTO_HOST_ACCESS='1' " : "" + , sr->reqid + 1 /* ESP requid */ + , me_str + , secure_myid_str + , myclient_str + , myclientnet_str + , myclientmask_str + , sr->this.port + , sr->this.protocol + , peer_str + , secure_peerid_str + , peerclient_str + , peerclientnet_str + , peerclientmask_str + , sr->that.port + , sr->that.protocol + , secure_peerca_str + , srcip_str + , sr->this.updown == NULL? DEFAULT_UPDOWN : sr->this.updown)) + { + loglog(RC_LOG_SERIOUS, "%s%s command too long!", verb, verb_suffix); + return FALSE; + } } - if (-1 == snprintf(cmd, sizeof(cmd) - , "2>&1 " /* capture stderr along with stdout */ - "PLUTO_VERSION='1.1' " /* change VERSION when interface spec changes */ - "PLUTO_VERB='%s%s' " - "PLUTO_CONNECTION='%s' " - "%s" /* optional PLUTO_NEXT_HOP */ - "PLUTO_INTERFACE='%s' " - "%s" /* optional PLUTO_HOST_ACCESS */ - "PLUTO_REQID='%u' " - "PLUTO_ME='%s' " - "PLUTO_MY_ID='%s' " - "PLUTO_MY_CLIENT='%s' " - "PLUTO_MY_CLIENT_NET='%s' " - "PLUTO_MY_CLIENT_MASK='%s' " - "PLUTO_MY_PORT='%u' " - "PLUTO_MY_PROTOCOL='%u' " - "PLUTO_PEER='%s' " - "PLUTO_PEER_ID='%s' " - "PLUTO_PEER_CLIENT='%s' " - "PLUTO_PEER_CLIENT_NET='%s' " - "PLUTO_PEER_CLIENT_MASK='%s' " - "PLUTO_PEER_PORT='%u' " - "PLUTO_PEER_PROTOCOL='%u' " - "PLUTO_PEER_CA='%s' " - "%s" /* optional PLUTO_MY_SRCIP */ - "%s" /* actual script */ - , verb, verb_suffix - , c->name - , nexthop_str - , c->interface->vname - , sr->this.hostaccess? "PLUTO_HOST_ACCESS='1' " : "" - , sr->reqid + 1 /* ESP requid */ - , me_str - , secure_myid_str - , myclient_str - , myclientnet_str - , myclientmask_str - , sr->this.port - , sr->this.protocol - , peer_str - , secure_peerid_str - , peerclient_str - , peerclientnet_str - , peerclientmask_str - , sr->that.port - , sr->that.protocol - , secure_peerca_str - , srcip_str - , sr->this.updown == NULL? DEFAULT_UPDOWN : sr->this.updown)) - { - loglog(RC_LOG_SERIOUS, "%s%s command too long!", verb, verb_suffix); - return FALSE; - } - } - - DBG(DBG_CONTROL, DBG_log("executing %s%s: %s" - , verb, verb_suffix, cmd)); + DBG(DBG_CONTROL, DBG_log("executing %s%s: %s" + , verb, verb_suffix, cmd)); #ifdef KLIPS - if (!no_klips) - { - /* invoke the script, catching stderr and stdout - * It may be of concern that some file descriptors will - * be inherited. For the ones under our control, we - * have done fcntl(fd, F_SETFD, FD_CLOEXEC) to prevent this. - * Any used by library routines (perhaps the resolver or syslog) - * will remain. - */ - FILE *f = popen(cmd, "r"); - - if (f == NULL) + if (!no_klips) { - loglog(RC_LOG_SERIOUS, "unable to popen %s%s command", verb, verb_suffix); - return FALSE; - } + /* invoke the script, catching stderr and stdout + * It may be of concern that some file descriptors will + * be inherited. For the ones under our control, we + * have done fcntl(fd, F_SETFD, FD_CLOEXEC) to prevent this. + * Any used by library routines (perhaps the resolver or syslog) + * will remain. + */ + FILE *f = popen(cmd, "r"); - /* log any output */ - for (;;) - { - /* if response doesn't fit in this buffer, it will be folded */ - char resp[256]; - - if (fgets(resp, sizeof(resp), f) == NULL) - { - if (ferror(f)) + if (f == NULL) { - log_errno((e, "fgets failed on output of %s%s command" - , verb, verb_suffix)); - return FALSE; + loglog(RC_LOG_SERIOUS, "unable to popen %s%s command", verb, verb_suffix); + return FALSE; } - else + + /* log any output */ + for (;;) { - passert(feof(f)); - break; + /* if response doesn't fit in this buffer, it will be folded */ + char resp[256]; + + if (fgets(resp, sizeof(resp), f) == NULL) + { + if (ferror(f)) + { + log_errno((e, "fgets failed on output of %s%s command" + , verb, verb_suffix)); + return FALSE; + } + else + { + passert(feof(f)); + break; + } + } + else + { + char *e = resp + strlen(resp); + + if (e > resp && e[-1] == '\n') + e[-1] = '\0'; /* trim trailing '\n' */ + plog("%s%s output: %s", verb, verb_suffix, resp); + } } - } - else - { - char *e = resp + strlen(resp); - if (e > resp && e[-1] == '\n') - e[-1] = '\0'; /* trim trailing '\n' */ - plog("%s%s output: %s", verb, verb_suffix, resp); - } - } - - /* report on and react to return code */ - { - int r = pclose(f); - - if (r == -1) - { - log_errno((e, "pclose failed for %s%s command" - , verb, verb_suffix)); - return FALSE; - } - else if (WIFEXITED(r)) - { - if (WEXITSTATUS(r) != 0) + /* report on and react to return code */ { - loglog(RC_LOG_SERIOUS, "%s%s command exited with status %d" - , verb, verb_suffix, WEXITSTATUS(r)); - return FALSE; + int r = pclose(f); + + if (r == -1) + { + log_errno((e, "pclose failed for %s%s command" + , verb, verb_suffix)); + return FALSE; + } + else if (WIFEXITED(r)) + { + if (WEXITSTATUS(r) != 0) + { + loglog(RC_LOG_SERIOUS, "%s%s command exited with status %d" + , verb, verb_suffix, WEXITSTATUS(r)); + return FALSE; + } + } + else if (WIFSIGNALED(r)) + { + loglog(RC_LOG_SERIOUS, "%s%s command exited with signal %d" + , verb, verb_suffix, WTERMSIG(r)); + return FALSE; + } + else + { + loglog(RC_LOG_SERIOUS, "%s%s command exited with unknown status %d" + , verb, verb_suffix, r); + return FALSE; + } } - } - else if (WIFSIGNALED(r)) - { - loglog(RC_LOG_SERIOUS, "%s%s command exited with signal %d" - , verb, verb_suffix, WTERMSIG(r)); - return FALSE; - } - else - { - loglog(RC_LOG_SERIOUS, "%s%s command exited with unknown status %d" - , verb, verb_suffix, r); - return FALSE; - } } - } #endif /* KLIPS */ - return TRUE; + return TRUE; } /* Check that we can route (and eroute). Diagnose if we cannot. */ enum routability { - route_impossible = 0, - route_easy = 1, - route_nearconflict = 2, - route_farconflict = 3 + route_impossible = 0, + route_easy = 1, + route_nearconflict = 2, + route_farconflict = 3 }; static enum routability could_route(struct connection *c) { - struct spd_route *esr, *rosr; - struct connection *ero /* who, if anyone, owns our eroute? */ - , *ro = route_owner(c, &rosr, &ero, &esr); /* who owns our route? */ + struct spd_route *esr, *rosr; + struct connection *ero /* who, if anyone, owns our eroute? */ + , *ro = route_owner(c, &rosr, &ero, &esr); /* who owns our route? */ - /* it makes no sense to route a connection that is ISAKMP-only */ - if (!NEVER_NEGOTIATE(c->policy) && !HAS_IPSEC_POLICY(c->policy)) - { - loglog(RC_ROUTE, "cannot route an ISAKMP-only connection"); - return route_impossible; - } + /* it makes no sense to route a connection that is ISAKMP-only */ + if (!NEVER_NEGOTIATE(c->policy) && !HAS_IPSEC_POLICY(c->policy)) + { + loglog(RC_ROUTE, "cannot route an ISAKMP-only connection"); + return route_impossible; + } - /* if this is a Road Warrior template, we cannot route. - * Opportunistic template is OK. - */ - if (c->kind == CK_TEMPLATE && !(c->policy & POLICY_OPPO)) - { - loglog(RC_ROUTE, "cannot route Road Warrior template"); - return route_impossible; - } + /* if this is a Road Warrior template, we cannot route. + * Opportunistic template is OK. + */ + if (c->kind == CK_TEMPLATE && !(c->policy & POLICY_OPPO)) + { + loglog(RC_ROUTE, "cannot route Road Warrior template"); + return route_impossible; + } - /* if we don't know nexthop, we cannot route */ - if (isanyaddr(&c->spd.this.host_nexthop)) - { - loglog(RC_ROUTE, "cannot route connection without knowing our nexthop"); - return route_impossible; - } + /* if we don't know nexthop, we cannot route */ + if (isanyaddr(&c->spd.this.host_nexthop)) + { + loglog(RC_ROUTE, "cannot route connection without knowing our nexthop"); + return route_impossible; + } - /* if routing would affect IKE messages, reject */ - if (!no_klips - && c->spd.this.host_port != NAT_T_IKE_FLOAT_PORT - && c->spd.this.host_port != IKE_UDP_PORT - && addrinsubnet(&c->spd.that.host_addr, &c->spd.that.client)) - { - loglog(RC_LOG_SERIOUS, "cannot install route: peer is within its client"); - return route_impossible; - } + /* if routing would affect IKE messages, reject */ + if (!no_klips + && c->spd.this.host_port != NAT_T_IKE_FLOAT_PORT + && c->spd.this.host_port != IKE_UDP_PORT + && addrinsubnet(&c->spd.that.host_addr, &c->spd.that.client)) + { + loglog(RC_LOG_SERIOUS, "cannot install route: peer is within its client"); + return route_impossible; + } - /* If there is already a route for peer's client subnet - * and it disagrees about interface or nexthop, we cannot steal it. - * Note: if this connection is already routed (perhaps for another - * state object), the route will agree. - * This is as it should be -- it will arise during rekeying. - */ - if (ro != NULL && !routes_agree(ro, c)) - { - loglog(RC_LOG_SERIOUS, "cannot route -- route already in use for \"%s\"" - , ro->name); - return route_impossible; /* another connection already - using the eroute */ - } + /* If there is already a route for peer's client subnet + * and it disagrees about interface or nexthop, we cannot steal it. + * Note: if this connection is already routed (perhaps for another + * state object), the route will agree. + * This is as it should be -- it will arise during rekeying. + */ + if (ro != NULL && !routes_agree(ro, c)) + { + loglog(RC_LOG_SERIOUS, "cannot route -- route already in use for \"%s\"" + , ro->name); + return route_impossible; /* another connection already + using the eroute */ + } #ifdef KLIPS - /* if there is an eroute for another connection, there is a problem */ - if (ero != NULL && ero != c) - { - struct connection *ero2, *ero_top; - struct connection *inside, *outside; - - /* - * note, wavesec (PERMANENT) goes *outside* and - * OE goes *inside* (TEMPLATE) - */ - inside = NULL; - outside= NULL; - if (ero->kind == CK_PERMANENT - && c->kind == CK_TEMPLATE) + /* if there is an eroute for another connection, there is a problem */ + if (ero != NULL && ero != c) { - outside = ero; - inside = c; + struct connection *ero2, *ero_top; + struct connection *inside, *outside; + + /* + * note, wavesec (PERMANENT) goes *outside* and + * OE goes *inside* (TEMPLATE) + */ + inside = NULL; + outside= NULL; + if (ero->kind == CK_PERMANENT + && c->kind == CK_TEMPLATE) + { + outside = ero; + inside = c; + } + else if (c->kind == CK_PERMANENT + && ero->kind == CK_TEMPLATE) + { + outside = c; + inside = ero; + } + + /* okay, check again, with correct order */ + if (outside && outside->kind == CK_PERMANENT + && inside && inside->kind == CK_TEMPLATE) + { + char inst[CONN_INST_BUF]; + + /* this is a co-terminal attempt of the "near" kind. */ + /* when chaining, we chain from inside to outside */ + + /* XXX permit multiple deep connections? */ + passert(inside->policy_next == NULL); + + inside->policy_next = outside; + + /* since we are going to steal the eroute from the secondary + * policy, we need to make sure that it no longer thinks that + * it owns the eroute. + */ + outside->spd.eroute_owner = SOS_NOBODY; + outside->spd.routing = RT_UNROUTED_KEYED; + + /* set the priority of the new eroute owner to be higher + * than that of the current eroute owner + */ + inside->prio = outside->prio + 1; + + fmt_conn_instance(inside, inst); + + loglog(RC_LOG_SERIOUS + , "conflict on eroute (%s), switching eroute to %s and linking %s" + , inst, inside->name, outside->name); + + return route_nearconflict; + } + + /* look along the chain of policies for one with the same name */ + ero_top = ero; + + for (ero2 = ero; ero2 != NULL; ero2 = ero->policy_next) + { + if (ero2->kind == CK_TEMPLATE + && streq(ero2->name, c->name)) + break; + } + + /* If we fell of the end of the list, then we found no TEMPLATE + * so there must be a conflict that we can't resolve. + * As the names are not equal, then we aren't replacing/rekeying. + */ + if (ero2 == NULL) + { + char inst[CONN_INST_BUF]; + + fmt_conn_instance(ero, inst); + + loglog(RC_LOG_SERIOUS + , "cannot install eroute -- it is in use for \"%s\"%s #%lu" + , ero->name, inst, esr->eroute_owner); + return FALSE; /* another connection already using the eroute */ + } } - else if (c->kind == CK_PERMANENT - && ero->kind == CK_TEMPLATE) - { - outside = c; - inside = ero; - } - - /* okay, check again, with correct order */ - if (outside && outside->kind == CK_PERMANENT - && inside && inside->kind == CK_TEMPLATE) - { - char inst[CONN_INST_BUF]; - - /* this is a co-terminal attempt of the "near" kind. */ - /* when chaining, we chain from inside to outside */ - - /* XXX permit multiple deep connections? */ - passert(inside->policy_next == NULL); - - inside->policy_next = outside; - - /* since we are going to steal the eroute from the secondary - * policy, we need to make sure that it no longer thinks that - * it owns the eroute. - */ - outside->spd.eroute_owner = SOS_NOBODY; - outside->spd.routing = RT_UNROUTED_KEYED; - - /* set the priority of the new eroute owner to be higher - * than that of the current eroute owner - */ - inside->prio = outside->prio + 1; - - fmt_conn_instance(inside, inst); - - loglog(RC_LOG_SERIOUS - , "conflict on eroute (%s), switching eroute to %s and linking %s" - , inst, inside->name, outside->name); - - return route_nearconflict; - } - - /* look along the chain of policies for one with the same name */ - ero_top = ero; - - for (ero2 = ero; ero2 != NULL; ero2 = ero->policy_next) - { - if (ero2->kind == CK_TEMPLATE - && streq(ero2->name, c->name)) - break; - } - - /* If we fell of the end of the list, then we found no TEMPLATE - * so there must be a conflict that we can't resolve. - * As the names are not equal, then we aren't replacing/rekeying. - */ - if (ero2 == NULL) - { - char inst[CONN_INST_BUF]; - - fmt_conn_instance(ero, inst); - - loglog(RC_LOG_SERIOUS - , "cannot install eroute -- it is in use for \"%s\"%s #%lu" - , ero->name, inst, esr->eroute_owner); - return FALSE; /* another connection already using the eroute */ - } - } #endif /* KLIPS */ - return route_easy; + return route_easy; } bool trap_connection(struct connection *c) { - switch (could_route(c)) - { - case route_impossible: - return FALSE; - - case route_nearconflict: - case route_easy: - /* RT_ROUTED_TUNNEL is treated specially: we don't override - * because we don't want to lose track of the IPSEC_SAs etc. - */ - if (c->spd.routing < RT_ROUTED_TUNNEL) + switch (could_route(c)) { - return route_and_eroute(c, &c->spd, NULL); + case route_impossible: + return FALSE; + + case route_nearconflict: + case route_easy: + /* RT_ROUTED_TUNNEL is treated specially: we don't override + * because we don't want to lose track of the IPSEC_SAs etc. + */ + if (c->spd.routing < RT_ROUTED_TUNNEL) + { + return route_and_eroute(c, &c->spd, NULL); + } + return TRUE; + + case route_farconflict: + return FALSE; } - return TRUE; - case route_farconflict: return FALSE; - } - - return FALSE; } /* delete any eroute for a connection and unroute it if route isn't shared */ void unroute_connection(struct connection *c) { - struct spd_route *sr; - enum routing_t cr; + struct spd_route *sr; + enum routing_t cr; - for (sr = &c->spd; sr; sr = sr->next) - { - cr = sr->routing; - - if (erouted(cr)) + for (sr = &c->spd; sr; sr = sr->next) { - /* cannot handle a live one */ - passert(sr->routing != RT_ROUTED_TUNNEL); + cr = sr->routing; + + if (erouted(cr)) + { + /* cannot handle a live one */ + passert(sr->routing != RT_ROUTED_TUNNEL); #ifdef KLIPS - shunt_eroute(c, sr, RT_UNROUTED, ERO_DELETE, "delete"); + shunt_eroute(c, sr, RT_UNROUTED, ERO_DELETE, "delete"); #endif + } + + sr->routing = RT_UNROUTED; /* do now so route_owner won't find us */ + + /* only unroute if no other connection shares it */ + if (routed(cr) && route_owner(c, NULL, NULL, NULL) == NULL) + (void) do_command(c, sr, "unroute"); } - - sr->routing = RT_UNROUTED; /* do now so route_owner won't find us */ - - /* only unroute if no other connection shares it */ - if (routed(cr) && route_owner(c, NULL, NULL, NULL) == NULL) - (void) do_command(c, sr, "unroute"); - } } @@ -854,10 +854,10 @@ unroute_connection(struct connection *c) static void set_text_said(char *text_said, const ip_address *dst, ipsec_spi_t spi, int proto) { - ip_said said; + ip_said said; - initsaid(dst, spi, proto, &said); - satot(&said, 0, text_said, SATOT_BUF); + initsaid(dst, spi, proto, &said); + satot(&said, 0, text_said, SATOT_BUF); } /* find an entry in the bare_shunt table. @@ -867,68 +867,68 @@ set_text_said(char *text_said, const ip_address *dst, ipsec_spi_t spi, int proto static struct bare_shunt ** bare_shunt_ptr(const ip_subnet *ours, const ip_subnet *his, int transport_proto) { - struct bare_shunt *p, **pp; + struct bare_shunt *p, **pp; - for (pp = &bare_shunts; (p = *pp) != NULL; pp = &p->next) - { - if (samesubnet(ours, &p->ours) - && samesubnet(his, &p->his) - && transport_proto == p->transport_proto - && portof(&ours->addr) == portof(&p->ours.addr) - && portof(&his->addr) == portof(&p->his.addr)) - return pp; - } - return NULL; + for (pp = &bare_shunts; (p = *pp) != NULL; pp = &p->next) + { + if (samesubnet(ours, &p->ours) + && samesubnet(his, &p->his) + && transport_proto == p->transport_proto + && portof(&ours->addr) == portof(&p->ours.addr) + && portof(&his->addr) == portof(&p->his.addr)) + return pp; + } + return NULL; } /* free a bare_shunt entry, given a pointer to the pointer */ static void free_bare_shunt(struct bare_shunt **pp) { - if (pp == NULL) - { - DBG(DBG_CONTROL, - DBG_log("delete bare shunt: null pointer") - ) - } - else - { - struct bare_shunt *p = *pp; + if (pp == NULL) + { + DBG(DBG_CONTROL, + DBG_log("delete bare shunt: null pointer") + ) + } + else + { + struct bare_shunt *p = *pp; - *pp = p->next; - DBG_bare_shunt("delete", p); - free(p->why); - free(p); - } + *pp = p->next; + DBG_bare_shunt("delete", p); + free(p->why); + free(p); + } } void show_shunt_status(void) { - struct bare_shunt *bs; + struct bare_shunt *bs; - for (bs = bare_shunts; bs != NULL; bs = bs->next) - { - /* Print interesting fields. Ignore count and last_active. */ + for (bs = bare_shunts; bs != NULL; bs = bs->next) + { + /* Print interesting fields. Ignore count and last_active. */ - int ourport = ntohs(portof(&bs->ours.addr)); - int hisport = ntohs(portof(&bs->his.addr)); - char ourst[SUBNETTOT_BUF]; - char hist[SUBNETTOT_BUF]; - char sat[SATOT_BUF]; - char prio[POLICY_PRIO_BUF]; + int ourport = ntohs(portof(&bs->ours.addr)); + int hisport = ntohs(portof(&bs->his.addr)); + char ourst[SUBNETTOT_BUF]; + char hist[SUBNETTOT_BUF]; + char sat[SATOT_BUF]; + char prio[POLICY_PRIO_BUF]; - subnettot(&(bs)->ours, 0, ourst, sizeof(ourst)); - subnettot(&(bs)->his, 0, hist, sizeof(hist)); - satot(&(bs)->said, 0, sat, sizeof(sat)); - fmt_policy_prio(bs->policy_prio, prio); + subnettot(&(bs)->ours, 0, ourst, sizeof(ourst)); + subnettot(&(bs)->his, 0, hist, sizeof(hist)); + satot(&(bs)->said, 0, sat, sizeof(sat)); + fmt_policy_prio(bs->policy_prio, prio); - whack_log(RC_COMMENT, "%s:%d -> %s:%d => %s:%d %s %s" - , ourst, ourport, hist, hisport, sat, bs->transport_proto - , prio, bs->why); - } - if (bare_shunts != NULL) - whack_log(RC_COMMENT, BLANK_FORMAT); /* spacer */ + whack_log(RC_COMMENT, "%s:%d -> %s:%d => %s:%d %s %s" + , ourst, ourport, hist, hisport, sat, bs->transport_proto + , prio, bs->why); + } + if (bare_shunts != NULL) + whack_log(RC_COMMENT, BLANK_FORMAT); /* spacer */ } /* Setup an IPsec route entry. @@ -937,54 +937,54 @@ show_shunt_status(void) static bool raw_eroute(const ip_address *this_host - , const ip_subnet *this_client - , const ip_address *that_host - , const ip_subnet *that_client - , ipsec_spi_t spi - , unsigned int proto - , unsigned int satype - , unsigned int transport_proto - , const struct pfkey_proto_info *proto_info - , time_t use_lifetime - , unsigned int op - , const char *opname USED_BY_DEBUG) + , const ip_subnet *this_client + , const ip_address *that_host + , const ip_subnet *that_client + , ipsec_spi_t spi + , unsigned int proto + , unsigned int satype + , unsigned int transport_proto + , const struct pfkey_proto_info *proto_info + , time_t use_lifetime + , unsigned int op + , const char *opname USED_BY_DEBUG) { - char text_said[SATOT_BUF]; + char text_said[SATOT_BUF]; - set_text_said(text_said, that_host, spi, proto); + set_text_said(text_said, that_host, spi, proto); - DBG(DBG_CONTROL | DBG_KLIPS, - { - int sport = ntohs(portof(&this_client->addr)); - int dport = ntohs(portof(&that_client->addr)); - char mybuf[SUBNETTOT_BUF]; - char peerbuf[SUBNETTOT_BUF]; + DBG(DBG_CONTROL | DBG_KLIPS, + { + int sport = ntohs(portof(&this_client->addr)); + int dport = ntohs(portof(&that_client->addr)); + char mybuf[SUBNETTOT_BUF]; + char peerbuf[SUBNETTOT_BUF]; - subnettot(this_client, 0, mybuf, sizeof(mybuf)); - subnettot(that_client, 0, peerbuf, sizeof(peerbuf)); - DBG_log("%s eroute %s:%d -> %s:%d => %s:%d" - , opname, mybuf, sport, peerbuf, dport - , text_said, transport_proto); - }); + subnettot(this_client, 0, mybuf, sizeof(mybuf)); + subnettot(that_client, 0, peerbuf, sizeof(peerbuf)); + DBG_log("%s eroute %s:%d -> %s:%d => %s:%d" + , opname, mybuf, sport, peerbuf, dport + , text_said, transport_proto); + }); - return kernel_ops->raw_eroute(this_host, this_client - , that_host, that_client, spi, satype, transport_proto, proto_info - , use_lifetime, op, text_said); + return kernel_ops->raw_eroute(this_host, this_client + , that_host, that_client, spi, satype, transport_proto, proto_info + , use_lifetime, op, text_said); } /* test to see if %hold remains */ bool has_bare_hold(const ip_address *src, const ip_address *dst, int transport_proto) { - ip_subnet this_client, that_client; - struct bare_shunt **bspp; + ip_subnet this_client, that_client; + struct bare_shunt **bspp; - passert(addrtypeof(src) == addrtypeof(dst)); - happy(addrtosubnet(src, &this_client)); - happy(addrtosubnet(dst, &that_client)); - bspp = bare_shunt_ptr(&this_client, &that_client, transport_proto); - return bspp != NULL - && (*bspp)->said.proto == SA_INT && (*bspp)->said.spi == htonl(SPI_HOLD); + passert(addrtypeof(src) == addrtypeof(dst)); + happy(addrtosubnet(src, &this_client)); + happy(addrtosubnet(dst, &that_client)); + bspp = bare_shunt_ptr(&this_client, &that_client, transport_proto); + return bspp != NULL + && (*bspp)->said.proto == SA_INT && (*bspp)->said.spi == htonl(SPI_HOLD); } @@ -993,73 +993,73 @@ has_bare_hold(const ip_address *src, const ip_address *dst, int transport_proto) */ bool replace_bare_shunt(const ip_address *src, const ip_address *dst - , policy_prio_t policy_prio - , ipsec_spi_t shunt_spi /* in host order! */ - , bool repl /* if TRUE, replace; if FALSE, delete */ - , unsigned int transport_proto - , const char *why) + , policy_prio_t policy_prio + , ipsec_spi_t shunt_spi /* in host order! */ + , bool repl /* if TRUE, replace; if FALSE, delete */ + , unsigned int transport_proto + , const char *why) { - ip_subnet this_client, that_client; - ip_subnet this_broad_client, that_broad_client; - const ip_address *null_host = aftoinfo(addrtypeof(src))->any; + ip_subnet this_client, that_client; + ip_subnet this_broad_client, that_broad_client; + const ip_address *null_host = aftoinfo(addrtypeof(src))->any; - passert(addrtypeof(src) == addrtypeof(dst)); - happy(addrtosubnet(src, &this_client)); - happy(addrtosubnet(dst, &that_client)); - this_broad_client = this_client; - that_broad_client = that_client; - setportof(0, &this_broad_client.addr); - setportof(0, &that_broad_client.addr); + passert(addrtypeof(src) == addrtypeof(dst)); + happy(addrtosubnet(src, &this_client)); + happy(addrtosubnet(dst, &that_client)); + this_broad_client = this_client; + that_broad_client = that_client; + setportof(0, &this_broad_client.addr); + setportof(0, &that_broad_client.addr); - if (repl) - { - struct bare_shunt **bs_pp = bare_shunt_ptr(&this_broad_client - , &that_broad_client, 0); - - /* is there already a broad host-to-host bare shunt? */ - if (bs_pp == NULL) + if (repl) { - if (raw_eroute(null_host, &this_broad_client, null_host, &that_broad_client - , htonl(shunt_spi), SA_INT, SADB_X_SATYPE_INT - , 0, null_proto_info - , SHUNT_PATIENCE, ERO_ADD, why)) - { - struct bare_shunt *bs = malloc_thing(struct bare_shunt); + struct bare_shunt **bs_pp = bare_shunt_ptr(&this_broad_client + , &that_broad_client, 0); - bs->ours = this_broad_client; - bs->his = that_broad_client; - bs->transport_proto = 0; - bs->said.proto = SA_INT; - bs->why = clone_str(why); - bs->policy_prio = policy_prio; - bs->said.spi = htonl(shunt_spi); - bs->said.dst = *null_host; - bs->count = 0; - bs->last_activity = now(); - bs->next = bare_shunts; - bare_shunts = bs; - DBG_bare_shunt("add", bs); - } + /* is there already a broad host-to-host bare shunt? */ + if (bs_pp == NULL) + { + if (raw_eroute(null_host, &this_broad_client, null_host, &that_broad_client + , htonl(shunt_spi), SA_INT, SADB_X_SATYPE_INT + , 0, null_proto_info + , SHUNT_PATIENCE, ERO_ADD, why)) + { + struct bare_shunt *bs = malloc_thing(struct bare_shunt); + + bs->ours = this_broad_client; + bs->his = that_broad_client; + bs->transport_proto = 0; + bs->said.proto = SA_INT; + bs->why = clone_str(why); + bs->policy_prio = policy_prio; + bs->said.spi = htonl(shunt_spi); + bs->said.dst = *null_host; + bs->count = 0; + bs->last_activity = now(); + bs->next = bare_shunts; + bare_shunts = bs; + DBG_bare_shunt("add", bs); + } + } + shunt_spi = SPI_HOLD; } - shunt_spi = SPI_HOLD; - } - if (raw_eroute(null_host, &this_client, null_host, &that_client - , htonl(shunt_spi), SA_INT, SADB_X_SATYPE_INT - , transport_proto, null_proto_info - , SHUNT_PATIENCE, ERO_DELETE, why)) - { - struct bare_shunt **bs_pp = bare_shunt_ptr(&this_client, &that_client - , transport_proto); + if (raw_eroute(null_host, &this_client, null_host, &that_client + , htonl(shunt_spi), SA_INT, SADB_X_SATYPE_INT + , transport_proto, null_proto_info + , SHUNT_PATIENCE, ERO_DELETE, why)) + { + struct bare_shunt **bs_pp = bare_shunt_ptr(&this_client, &that_client + , transport_proto); - /* delete bare eroute */ - free_bare_shunt(bs_pp); - return TRUE; - } - else - { - return FALSE; - } + /* delete bare eroute */ + free_bare_shunt(bs_pp); + return TRUE; + } + else + { + return FALSE; + } } static bool @@ -1068,190 +1068,190 @@ eroute_connection(struct spd_route *sr , const struct pfkey_proto_info *proto_info , unsigned int op, const char *opname) { - const ip_address *peer = &sr->that.host_addr; - char buf2[256]; + const ip_address *peer = &sr->that.host_addr; + char buf2[256]; - snprintf(buf2, sizeof(buf2) - , "eroute_connection %s", opname); + snprintf(buf2, sizeof(buf2) + , "eroute_connection %s", opname); - if (proto == SA_INT) - peer = aftoinfo(addrtypeof(peer))->any; + if (proto == SA_INT) + peer = aftoinfo(addrtypeof(peer))->any; - return raw_eroute(&sr->this.host_addr, &sr->this.client - , peer - , &sr->that.client - , spi, proto, satype - , sr->this.protocol, proto_info, 0, op, buf2); + return raw_eroute(&sr->this.host_addr, &sr->this.client + , peer + , &sr->that.client + , spi, proto, satype + , sr->this.protocol, proto_info, 0, op, buf2); } /* assign a bare hold to a connection */ bool assign_hold(struct connection *c USED_BY_DEBUG - , struct spd_route *sr - , int transport_proto - , const ip_address *src, const ip_address *dst) + , struct spd_route *sr + , int transport_proto + , const ip_address *src, const ip_address *dst) { - /* either the automatically installed %hold eroute is broad enough - * or we try to add a broader one and delete the automatic one. - * Beware: this %hold might be already handled, but still squeak - * through because of a race. - */ - enum routing_t ro = sr->routing /* routing, old */ - , rn = ro; /* routing, new */ + /* either the automatically installed %hold eroute is broad enough + * or we try to add a broader one and delete the automatic one. + * Beware: this %hold might be already handled, but still squeak + * through because of a race. + */ + enum routing_t ro = sr->routing /* routing, old */ + , rn = ro; /* routing, new */ - passert(LHAS(LELEM(CK_PERMANENT) | LELEM(CK_INSTANCE), c->kind)); - /* figure out what routing should become */ - switch (ro) - { - case RT_UNROUTED: - rn = RT_UNROUTED_HOLD; - break; - case RT_ROUTED_PROSPECTIVE: - rn = RT_ROUTED_HOLD; - break; - default: - /* no change: this %hold is old news and should just be deleted */ - break; - } - - /* we need a broad %hold, not the narrow one. - * First we ensure that there is a broad %hold. - * There may already be one (race condition): no need to create one. - * There may already be a %trap: replace it. - * There may not be any broad eroute: add %hold. - * Once the broad %hold is in place, delete the narrow one. - */ - if (rn != ro) - { - if (erouted(ro) - ? !eroute_connection(sr, htonl(SPI_HOLD), SA_INT, SADB_X_SATYPE_INT - , null_proto_info - , ERO_REPLACE, "replace %trap with broad %hold") - : !eroute_connection(sr, htonl(SPI_HOLD), SA_INT, SADB_X_SATYPE_INT - , null_proto_info - , ERO_ADD, "add broad %hold")) + passert(LHAS(LELEM(CK_PERMANENT) | LELEM(CK_INSTANCE), c->kind)); + /* figure out what routing should become */ + switch (ro) { - return FALSE; + case RT_UNROUTED: + rn = RT_UNROUTED_HOLD; + break; + case RT_ROUTED_PROSPECTIVE: + rn = RT_ROUTED_HOLD; + break; + default: + /* no change: this %hold is old news and should just be deleted */ + break; } - } - if (!replace_bare_shunt(src, dst, BOTTOM_PRIO, SPI_HOLD, FALSE - , transport_proto, "delete narrow %hold")) - { - return FALSE; - } - sr->routing = rn; - return TRUE; + + /* we need a broad %hold, not the narrow one. + * First we ensure that there is a broad %hold. + * There may already be one (race condition): no need to create one. + * There may already be a %trap: replace it. + * There may not be any broad eroute: add %hold. + * Once the broad %hold is in place, delete the narrow one. + */ + if (rn != ro) + { + if (erouted(ro) + ? !eroute_connection(sr, htonl(SPI_HOLD), SA_INT, SADB_X_SATYPE_INT + , null_proto_info + , ERO_REPLACE, "replace %trap with broad %hold") + : !eroute_connection(sr, htonl(SPI_HOLD), SA_INT, SADB_X_SATYPE_INT + , null_proto_info + , ERO_ADD, "add broad %hold")) + { + return FALSE; + } + } + if (!replace_bare_shunt(src, dst, BOTTOM_PRIO, SPI_HOLD, FALSE + , transport_proto, "delete narrow %hold")) + { + return FALSE; + } + sr->routing = rn; + return TRUE; } /* install or remove eroute for SA Group */ static bool sag_eroute(struct state *st, struct spd_route *sr - , unsigned op, const char *opname) + , unsigned op, const char *opname) { - u_int inner_proto = 0; - u_int inner_satype = 0; - ipsec_spi_t inner_spi = 0; - struct pfkey_proto_info proto_info[4]; - int i; - bool tunnel; + u_int inner_proto = 0; + u_int inner_satype = 0; + ipsec_spi_t inner_spi = 0; + struct pfkey_proto_info proto_info[4]; + int i; + bool tunnel; - /* figure out the SPI and protocol (in two forms) - * for the innermost transformation. - */ + /* figure out the SPI and protocol (in two forms) + * for the innermost transformation. + */ - i = sizeof(proto_info) / sizeof(proto_info[0]) - 1; - proto_info[i].proto = 0; - tunnel = FALSE; + i = sizeof(proto_info) / sizeof(proto_info[0]) - 1; + proto_info[i].proto = 0; + tunnel = FALSE; - if (st->st_ah.present) - { - inner_spi = st->st_ah.attrs.spi; - inner_proto = SA_AH; - inner_satype = SADB_SATYPE_AH; - - i--; - proto_info[i].proto = IPPROTO_AH; - proto_info[i].encapsulation = st->st_ah.attrs.encapsulation; - tunnel |= proto_info[i].encapsulation == ENCAPSULATION_MODE_TUNNEL; - proto_info[i].reqid = sr->reqid; - } - - if (st->st_esp.present) - { - inner_spi = st->st_esp.attrs.spi; - inner_proto = SA_ESP; - inner_satype = SADB_SATYPE_ESP; - - i--; - proto_info[i].proto = IPPROTO_ESP; - proto_info[i].encapsulation = st->st_esp.attrs.encapsulation; - tunnel |= proto_info[i].encapsulation == ENCAPSULATION_MODE_TUNNEL; - proto_info[i].reqid = sr->reqid + 1; - } - - if (st->st_ipcomp.present) - { - inner_spi = st->st_ipcomp.attrs.spi; - inner_proto = SA_COMP; - inner_satype = SADB_X_SATYPE_COMP; - - i--; - proto_info[i].proto = IPPROTO_COMP; - proto_info[i].encapsulation = st->st_ipcomp.attrs.encapsulation; - tunnel |= proto_info[i].encapsulation == ENCAPSULATION_MODE_TUNNEL; - proto_info[i].reqid = sr->reqid + 2; - } - - if (i == sizeof(proto_info) / sizeof(proto_info[0]) - 1) - { - impossible(); /* no transform at all! */ - } - - if (tunnel) - { - int j; - - inner_spi = st->st_tunnel_out_spi; - inner_proto = SA_IPIP; - inner_satype = SADB_X_SATYPE_IPIP; - - proto_info[i].encapsulation = ENCAPSULATION_MODE_TUNNEL; - for (j = i + 1; proto_info[j].proto; j++) + if (st->st_ah.present) { - proto_info[j].encapsulation = ENCAPSULATION_MODE_TRANSPORT; - } - } + inner_spi = st->st_ah.attrs.spi; + inner_proto = SA_AH; + inner_satype = SADB_SATYPE_AH; - return eroute_connection(sr - , inner_spi, inner_proto, inner_satype, proto_info + i - , op, opname); + i--; + proto_info[i].proto = IPPROTO_AH; + proto_info[i].encapsulation = st->st_ah.attrs.encapsulation; + tunnel |= proto_info[i].encapsulation == ENCAPSULATION_MODE_TUNNEL; + proto_info[i].reqid = sr->reqid; + } + + if (st->st_esp.present) + { + inner_spi = st->st_esp.attrs.spi; + inner_proto = SA_ESP; + inner_satype = SADB_SATYPE_ESP; + + i--; + proto_info[i].proto = IPPROTO_ESP; + proto_info[i].encapsulation = st->st_esp.attrs.encapsulation; + tunnel |= proto_info[i].encapsulation == ENCAPSULATION_MODE_TUNNEL; + proto_info[i].reqid = sr->reqid + 1; + } + + if (st->st_ipcomp.present) + { + inner_spi = st->st_ipcomp.attrs.spi; + inner_proto = SA_COMP; + inner_satype = SADB_X_SATYPE_COMP; + + i--; + proto_info[i].proto = IPPROTO_COMP; + proto_info[i].encapsulation = st->st_ipcomp.attrs.encapsulation; + tunnel |= proto_info[i].encapsulation == ENCAPSULATION_MODE_TUNNEL; + proto_info[i].reqid = sr->reqid + 2; + } + + if (i == sizeof(proto_info) / sizeof(proto_info[0]) - 1) + { + impossible(); /* no transform at all! */ + } + + if (tunnel) + { + int j; + + inner_spi = st->st_tunnel_out_spi; + inner_proto = SA_IPIP; + inner_satype = SADB_X_SATYPE_IPIP; + + proto_info[i].encapsulation = ENCAPSULATION_MODE_TUNNEL; + for (j = i + 1; proto_info[j].proto; j++) + { + proto_info[j].encapsulation = ENCAPSULATION_MODE_TRANSPORT; + } + } + + return eroute_connection(sr + , inner_spi, inner_proto, inner_satype, proto_info + i + , op, opname); } /* compute a (host-order!) SPI to implement the policy in connection c */ ipsec_spi_t shunt_policy_spi(struct connection *c, bool prospective) { - /* note: these are in host order :-( */ - static const ipsec_spi_t shunt_spi[] = - { - SPI_TRAP, /* --initiateontraffic */ - SPI_PASS, /* --pass */ - SPI_DROP, /* --drop */ - SPI_REJECT, /* --reject */ - }; + /* note: these are in host order :-( */ + static const ipsec_spi_t shunt_spi[] = + { + SPI_TRAP, /* --initiateontraffic */ + SPI_PASS, /* --pass */ + SPI_DROP, /* --drop */ + SPI_REJECT, /* --reject */ + }; - static const ipsec_spi_t fail_spi[] = - { - 0, /* --none*/ - SPI_PASS, /* --failpass */ - SPI_DROP, /* --faildrop */ - SPI_REJECT, /* --failreject */ - }; + static const ipsec_spi_t fail_spi[] = + { + 0, /* --none*/ + SPI_PASS, /* --failpass */ + SPI_DROP, /* --faildrop */ + SPI_REJECT, /* --failreject */ + }; - return prospective - ? shunt_spi[(c->policy & POLICY_SHUNT_MASK) >> POLICY_SHUNT_SHIFT] - : fail_spi[(c->policy & POLICY_FAIL_MASK) >> POLICY_FAIL_SHIFT]; + return prospective + ? shunt_spi[(c->policy & POLICY_SHUNT_MASK) >> POLICY_SHUNT_SHIFT] + : fail_spi[(c->policy & POLICY_FAIL_MASK) >> POLICY_FAIL_SHIFT]; } /* Add/replace/delete a shunt eroute. @@ -1267,83 +1267,83 @@ shunt_eroute(struct connection *c , enum routing_t rt_kind , unsigned int op, const char *opname) { - /* We are constructing a special SAID for the eroute. - * The destination doesn't seem to matter, but the family does. - * The protocol is SA_INT -- mark this as shunt. - * The satype has no meaning, but is required for PF_KEY header! - * The SPI signifies the kind of shunt. - */ - ipsec_spi_t spi = shunt_policy_spi(c, rt_kind == RT_ROUTED_PROSPECTIVE); - bool ok; - - if (spi == 0) - { - /* we're supposed to end up with no eroute: rejig op and opname */ - switch (op) - { - case ERO_REPLACE: - /* replace with nothing == delete */ - op = ERO_DELETE; - opname = "delete"; - break; - case ERO_ADD: - /* add nothing == do nothing */ - return TRUE; - case ERO_DELETE: - /* delete remains delete */ - break; - default: - bad_case(op); - } - } - if (sr->routing == RT_ROUTED_ECLIPSED && c->kind == CK_TEMPLATE) - { - /* We think that we have an eroute, but we don't. - * Adjust the request and account for eclipses. + /* We are constructing a special SAID for the eroute. + * The destination doesn't seem to matter, but the family does. + * The protocol is SA_INT -- mark this as shunt. + * The satype has no meaning, but is required for PF_KEY header! + * The SPI signifies the kind of shunt. */ - passert(eclipsable(sr)); - switch (op) - { - case ERO_REPLACE: - /* really an add */ - op = ERO_ADD; - opname = "replace eclipsed"; - eclipse_count--; - break; - case ERO_DELETE: - /* delete unnecessary: we don't actually have an eroute */ - eclipse_count--; - return TRUE; - case ERO_ADD: - default: - bad_case(op); - } - } - else if (eclipse_count > 0 && op == ERO_DELETE && eclipsable(sr)) - { - /* maybe we are uneclipsing something */ - struct spd_route *esr; - struct connection *ue = eclipsed(c, &esr); + ipsec_spi_t spi = shunt_policy_spi(c, rt_kind == RT_ROUTED_PROSPECTIVE); + bool ok; - if (ue != NULL) + if (spi == 0) { - esr->routing = RT_ROUTED_PROSPECTIVE; - return shunt_eroute(ue, esr - , RT_ROUTED_PROSPECTIVE, ERO_REPLACE, "restoring eclipsed"); + /* we're supposed to end up with no eroute: rejig op and opname */ + switch (op) + { + case ERO_REPLACE: + /* replace with nothing == delete */ + op = ERO_DELETE; + opname = "delete"; + break; + case ERO_ADD: + /* add nothing == do nothing */ + return TRUE; + case ERO_DELETE: + /* delete remains delete */ + break; + default: + bad_case(op); + } } - } + if (sr->routing == RT_ROUTED_ECLIPSED && c->kind == CK_TEMPLATE) + { + /* We think that we have an eroute, but we don't. + * Adjust the request and account for eclipses. + */ + passert(eclipsable(sr)); + switch (op) + { + case ERO_REPLACE: + /* really an add */ + op = ERO_ADD; + opname = "replace eclipsed"; + eclipse_count--; + break; + case ERO_DELETE: + /* delete unnecessary: we don't actually have an eroute */ + eclipse_count--; + return TRUE; + case ERO_ADD: + default: + bad_case(op); + } + } + else if (eclipse_count > 0 && op == ERO_DELETE && eclipsable(sr)) + { + /* maybe we are uneclipsing something */ + struct spd_route *esr; + struct connection *ue = eclipsed(c, &esr); - ok = TRUE; - if (kernel_ops->inbound_eroute) - { - ok = raw_eroute(&c->spd.that.host_addr, &c->spd.that.client - , &c->spd.this.host_addr, &c->spd.this.client - , htonl(spi), SA_INT, SADB_X_SATYPE_INT - , 0, null_proto_info, 0 - , op | (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT), opname); - } - return eroute_connection(sr, htonl(spi), SA_INT, SADB_X_SATYPE_INT - , null_proto_info, op, opname) && ok; + if (ue != NULL) + { + esr->routing = RT_ROUTED_PROSPECTIVE; + return shunt_eroute(ue, esr + , RT_ROUTED_PROSPECTIVE, ERO_REPLACE, "restoring eclipsed"); + } + } + + ok = TRUE; + if (kernel_ops->inbound_eroute) + { + ok = raw_eroute(&c->spd.that.host_addr, &c->spd.that.client + , &c->spd.this.host_addr, &c->spd.this.client + , htonl(spi), SA_INT, SADB_X_SATYPE_INT + , 0, null_proto_info, 0 + , op | (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT), opname); + } + return eroute_connection(sr, htonl(spi), SA_INT, SADB_X_SATYPE_INT + , null_proto_info, op, opname) && ok; } @@ -1360,25 +1360,25 @@ shunt_eroute(struct connection *c static const char * read_proto(const char * s, size_t * len, int * transport_proto) { - const char * p; - const char * ugh; - unsigned long proto; - size_t l; + const char * p; + const char * ugh; + unsigned long proto; + size_t l; - l = *len; - p = memchr(s, ':', l); - if (p == 0) { - *transport_proto = 0; - return 0; - } - ugh = ttoul(p+1, l-((p-s)+1), 10, &proto); - if (ugh != 0) - return ugh; - if (proto > 65535) - return "protocol number is too large, legal range is 0-65535"; - *len = p-s; - *transport_proto = proto; - return 0; + l = *len; + p = memchr(s, ':', l); + if (p == 0) { + *transport_proto = 0; + return 0; + } + ugh = ttoul(p+1, l-((p-s)+1), 10, &proto); + if (ugh != 0) + return ugh; + if (proto > 65535) + return "protocol number is too large, legal range is 0-65535"; + *len = p-s; + *transport_proto = proto; + return 0; } @@ -1410,262 +1410,262 @@ read_proto(const char * s, size_t * len, int * transport_proto) void scan_proc_shunts(void) { - static const char procname[] = "/proc/net/ipsec_eroute"; - FILE *f; - time_t nw = now(); - int lino; - struct eroute_info *expired = NULL; + static const char procname[] = "/proc/net/ipsec_eroute"; + FILE *f; + time_t nw = now(); + int lino; + struct eroute_info *expired = NULL; - event_schedule(EVENT_SHUNT_SCAN, SHUNT_SCAN_INTERVAL, NULL); + event_schedule(EVENT_SHUNT_SCAN, SHUNT_SCAN_INTERVAL, NULL); - DBG(DBG_CONTROL, - DBG_log("scanning for shunt eroutes") - ) + DBG(DBG_CONTROL, + DBG_log("scanning for shunt eroutes") + ) - /* free any leftover entries: they will be refreshed if still current */ - while (orphaned_holds != NULL) - { - struct eroute_info *p = orphaned_holds; - - orphaned_holds = p->next; - free(orphaned_holds); - } - - /* decode the /proc file. Don't do anything strenuous to it - * (certainly no PF_KEY stuff) to minimize the chance that it - * might change underfoot. - */ - - f = fopen(procname, "r"); - if (f == NULL) - return; - - /* for each line... */ - for (lino = 1; ; lino++) - { - unsigned char buf[1024]; /* should be big enough */ - chunk_t field[10]; /* 10 is loose upper bound */ - chunk_t *ff = NULL; /* fixed fields (excluding optional count) */ - int fi; - struct eroute_info eri; - char *cp; - err_t context = "" - , ugh = NULL; - - cp = fgets(buf, sizeof(buf), f); - if (cp == NULL) - break; - - /* break out each field - * Note: if there are too many fields, just stop; - * it will be diagnosed a little later. - */ - for (fi = 0; fi < (int)countof(field); fi++) + /* free any leftover entries: they will be refreshed if still current */ + while (orphaned_holds != NULL) { - static const char sep[] = " \t\n"; /* field-separating whitespace */ - size_t w; + struct eroute_info *p = orphaned_holds; - cp += strspn(cp, sep); /* find start of field */ - w = strcspn(cp, sep); /* find width of field */ - field[fi] = chunk_create(cp, w); - cp += w; - if (w == 0) - break; + orphaned_holds = p->next; + free(orphaned_holds); } - /* This odd do-hickey is to share error reporting code. - * A break will get to that common code. The setting - * of "ugh" and "context" parameterize it. + /* decode the /proc file. Don't do anything strenuous to it + * (certainly no PF_KEY stuff) to minimize the chance that it + * might change underfoot. */ - do { - /* Old entries have no packet count; new ones do. - * check if things are as they should be. - */ - if (fi == 5) - ff = &field[0]; /* old form, with no count */ - else if (fi == 6) - ff = &field[1]; /* new form, with count */ - else - { - ugh = "has wrong number of fields"; - break; - } - if (ff[1].len != 2 - || strncmp(ff[1].ptr, "->", 2) != 0 - || ff[3].len != 2 - || strncmp(ff[3].ptr, "=>", 2) != 0) - { - ugh = "is missing -> or =>"; - break; - } + f = fopen(procname, "r"); + if (f == NULL) + return; - /* actually digest fields of interest */ + /* for each line... */ + for (lino = 1; ; lino++) + { + unsigned char buf[1024]; /* should be big enough */ + chunk_t field[10]; /* 10 is loose upper bound */ + chunk_t *ff = NULL; /* fixed fields (excluding optional count) */ + int fi; + struct eroute_info eri; + char *cp; + err_t context = "" + , ugh = NULL; - /* packet count */ + cp = fgets(buf, sizeof(buf), f); + if (cp == NULL) + break; + + /* break out each field + * Note: if there are too many fields, just stop; + * it will be diagnosed a little later. + */ + for (fi = 0; fi < (int)countof(field); fi++) + { + static const char sep[] = " \t\n"; /* field-separating whitespace */ + size_t w; + + cp += strspn(cp, sep); /* find start of field */ + w = strcspn(cp, sep); /* find width of field */ + field[fi] = chunk_create(cp, w); + cp += w; + if (w == 0) + break; + } + + /* This odd do-hickey is to share error reporting code. + * A break will get to that common code. The setting + * of "ugh" and "context" parameterize it. + */ + do { + /* Old entries have no packet count; new ones do. + * check if things are as they should be. + */ + if (fi == 5) + ff = &field[0]; /* old form, with no count */ + else if (fi == 6) + ff = &field[1]; /* new form, with count */ + else + { + ugh = "has wrong number of fields"; + break; + } + + if (ff[1].len != 2 + || strncmp(ff[1].ptr, "->", 2) != 0 + || ff[3].len != 2 + || strncmp(ff[3].ptr, "=>", 2) != 0) + { + ugh = "is missing -> or =>"; + break; + } + + /* actually digest fields of interest */ + + /* packet count */ + + eri.count = 0; + if (ff != field) + { + context = "count field is malformed: "; + ugh = ttoul(field[0].ptr, field[0].len, 10, &eri.count); + if (ugh != NULL) + break; + } + + /* our client */ + + context = "source subnet field malformed: "; + ugh = ttosubnet(ff[0].ptr, ff[0].len, AF_INET, &eri.ours); + if (ugh != NULL) + break; + + /* his client */ + + context = "destination subnet field malformed: "; + ugh = ttosubnet(ff[2].ptr, ff[2].len, AF_INET, &eri.his); + if (ugh != NULL) + break; + + /* SAID */ + + context = "SA ID field malformed: "; + ugh = read_proto(ff[4].ptr, &ff[4].len, &eri.transport_proto); + if (ugh != NULL) + break; + ugh = ttosa(ff[4].ptr, ff[4].len, &eri.said); + } while (FALSE); - eri.count = 0; - if (ff != field) - { - context = "count field is malformed: "; - ugh = ttoul(field[0].ptr, field[0].len, 10, &eri.count); if (ugh != NULL) - break; - } + { + plog("INTERNAL ERROR: %s line %d %s%s" + , procname, lino, context, ugh); + continue; /* ignore rest of line */ + } - /* our client */ + /* Now we have decoded eroute, let's consider it. + * For shunt eroutes: + * + * %hold: if not known, add to orphaned_holds list for initiation + * because ACQUIRE might have been lost. + * + * %pass, %drop, %reject: determine if idle; if so, blast it away. + * Can occur bare (if DNS provided insufficient information) + * or with a connection (failure context). + * Could even be installed by ipsec manual. + * + * %trap: always welcome. + * + * For other eroutes: find state and record count change + */ + if (eri.said.proto == SA_INT) + { + /* shunt eroute */ + switch (ntohl(eri.said.spi)) + { + case SPI_HOLD: + if (bare_shunt_ptr(&eri.ours, &eri.his, eri.transport_proto) == NULL + && shunt_owner(&eri.ours, &eri.his) == NULL) + { + int ourport = ntohs(portof(&eri.ours.addr)); + int hisport = ntohs(portof(&eri.his.addr)); + char ourst[SUBNETTOT_BUF]; + char hist[SUBNETTOT_BUF]; + char sat[SATOT_BUF]; - context = "source subnet field malformed: "; - ugh = ttosubnet(ff[0].ptr, ff[0].len, AF_INET, &eri.ours); - if (ugh != NULL) - break; + subnettot(&eri.ours, 0, ourst, sizeof(ourst)); + subnettot(&eri.his, 0, hist, sizeof(hist)); + satot(&eri.said, 0, sat, sizeof(sat)); - /* his client */ + DBG(DBG_CONTROL, + DBG_log("add orphaned shunt %s:%d -> %s:%d => %s:%d" + , ourst, ourport, hist, hisport, sat, eri.transport_proto) + ) + eri.next = orphaned_holds; + orphaned_holds = clone_thing(eri); + } + break; - context = "destination subnet field malformed: "; - ugh = ttosubnet(ff[2].ptr, ff[2].len, AF_INET, &eri.his); - if (ugh != NULL) - break; + case SPI_PASS: + case SPI_DROP: + case SPI_REJECT: + /* nothing sensible to do if we don't have counts */ + if (ff != field) + { + struct bare_shunt **bs_pp + = bare_shunt_ptr(&eri.ours, &eri.his, eri.transport_proto); - /* SAID */ + if (bs_pp != NULL) + { + struct bare_shunt *bs = *bs_pp; - context = "SA ID field malformed: "; - ugh = read_proto(ff[4].ptr, &ff[4].len, &eri.transport_proto); - if (ugh != NULL) - break; - ugh = ttosa(ff[4].ptr, ff[4].len, &eri.said); - } while (FALSE); + if (eri.count != bs->count) + { + bs->count = eri.count; + bs->last_activity = nw; + } + else if (nw - bs->last_activity > SHUNT_PATIENCE) + { + eri.next = expired; + expired = clone_thing(eri); + } + } + } + break; - if (ugh != NULL) - { - plog("INTERNAL ERROR: %s line %d %s%s" - , procname, lino, context, ugh); - continue; /* ignore rest of line */ - } + case SPI_TRAP: + break; - /* Now we have decoded eroute, let's consider it. - * For shunt eroutes: - * - * %hold: if not known, add to orphaned_holds list for initiation - * because ACQUIRE might have been lost. - * - * %pass, %drop, %reject: determine if idle; if so, blast it away. - * Can occur bare (if DNS provided insufficient information) - * or with a connection (failure context). - * Could even be installed by ipsec manual. - * - * %trap: always welcome. - * - * For other eroutes: find state and record count change + default: + bad_case(ntohl(eri.said.spi)); + } + } + else + { + /* regular (non-shunt) eroute */ + state_eroute_usage(&eri.ours, &eri.his, eri.count, nw); + } + } /* for each line */ + fclose(f); + + /* Now that we've finished processing the /proc file, + * it is safe to delete the expired %pass shunts. */ - if (eri.said.proto == SA_INT) + while (expired != NULL) { - /* shunt eroute */ - switch (ntohl(eri.said.spi)) - { - case SPI_HOLD: - if (bare_shunt_ptr(&eri.ours, &eri.his, eri.transport_proto) == NULL - && shunt_owner(&eri.ours, &eri.his) == NULL) - { - int ourport = ntohs(portof(&eri.ours.addr)); - int hisport = ntohs(portof(&eri.his.addr)); - char ourst[SUBNETTOT_BUF]; - char hist[SUBNETTOT_BUF]; - char sat[SATOT_BUF]; + struct eroute_info *p = expired; + ip_address src, dst; - subnettot(&eri.ours, 0, ourst, sizeof(ourst)); - subnettot(&eri.his, 0, hist, sizeof(hist)); - satot(&eri.said, 0, sat, sizeof(sat)); - - DBG(DBG_CONTROL, - DBG_log("add orphaned shunt %s:%d -> %s:%d => %s:%d" - , ourst, ourport, hist, hisport, sat, eri.transport_proto) - ) - eri.next = orphaned_holds; - orphaned_holds = clone_thing(eri); - } - break; - - case SPI_PASS: - case SPI_DROP: - case SPI_REJECT: - /* nothing sensible to do if we don't have counts */ - if (ff != field) - { - struct bare_shunt **bs_pp - = bare_shunt_ptr(&eri.ours, &eri.his, eri.transport_proto); - - if (bs_pp != NULL) - { - struct bare_shunt *bs = *bs_pp; - - if (eri.count != bs->count) - { - bs->count = eri.count; - bs->last_activity = nw; - } - else if (nw - bs->last_activity > SHUNT_PATIENCE) - { - eri.next = expired; - expired = clone_thing(eri); - } - } - } - break; - - case SPI_TRAP: - break; - - default: - bad_case(ntohl(eri.said.spi)); - } + networkof(&p->ours, &src); + networkof(&p->his, &dst); + (void) replace_bare_shunt(&src, &dst + , BOTTOM_PRIO /* not used because we are deleting. This value is a filler */ + , SPI_PASS /* not used because we are deleting. This value is a filler */ + , FALSE, p->transport_proto, "delete expired bare shunts"); + expired = p->next; + free(p); } - else - { - /* regular (non-shunt) eroute */ - state_eroute_usage(&eri.ours, &eri.his, eri.count, nw); - } - } /* for each line */ - fclose(f); - - /* Now that we've finished processing the /proc file, - * it is safe to delete the expired %pass shunts. - */ - while (expired != NULL) - { - struct eroute_info *p = expired; - ip_address src, dst; - - networkof(&p->ours, &src); - networkof(&p->his, &dst); - (void) replace_bare_shunt(&src, &dst - , BOTTOM_PRIO /* not used because we are deleting. This value is a filler */ - , SPI_PASS /* not used because we are deleting. This value is a filler */ - , FALSE, p->transport_proto, "delete expired bare shunts"); - expired = p->next; - free(p); - } } static bool del_spi(ipsec_spi_t spi, int proto , const ip_address *src, const ip_address *dest) { - char text_said[SATOT_BUF]; - struct kernel_sa sa; + char text_said[SATOT_BUF]; + struct kernel_sa sa; - set_text_said(text_said, dest, spi, proto); + set_text_said(text_said, dest, spi, proto); - DBG(DBG_KLIPS, DBG_log("delete %s", text_said)); + DBG(DBG_KLIPS, DBG_log("delete %s", text_said)); - memset(&sa, 0, sizeof(sa)); - sa.spi = spi; - sa.proto = proto; - sa.src = src; - sa.dst = dest; - sa.text_said = text_said; + memset(&sa, 0, sizeof(sa)); + sa.spi = spi; + sa.proto = proto; + sa.src = src; + sa.dst = dest; + sa.text_said = text_said; - return kernel_ops->del_sa(&sa); + return kernel_ops->del_sa(&sa); } /* Setup a pair of SAs. Code taken from setsa.c and spigrp.c, in @@ -1675,451 +1675,451 @@ del_spi(ipsec_spi_t spi, int proto static bool setup_half_ipsec_sa(struct state *st, bool inbound) { - /* Build an inbound or outbound SA */ + /* Build an inbound or outbound SA */ - struct connection *c = st->st_connection; - ip_subnet src, dst; - ip_subnet src_client, dst_client; - ipsec_spi_t inner_spi = 0; - u_int proto = 0; - u_int satype = SADB_SATYPE_UNSPEC; - bool replace; + struct connection *c = st->st_connection; + ip_subnet src, dst; + ip_subnet src_client, dst_client; + ipsec_spi_t inner_spi = 0; + u_int proto = 0; + u_int satype = SADB_SATYPE_UNSPEC; + bool replace; - /* SPIs, saved for spigrouping or undoing, if necessary */ - struct kernel_sa - said[EM_MAXRELSPIS], - *said_next = said; + /* SPIs, saved for spigrouping or undoing, if necessary */ + struct kernel_sa + said[EM_MAXRELSPIS], + *said_next = said; - char text_said[SATOT_BUF]; - int encapsulation; + char text_said[SATOT_BUF]; + int encapsulation; - replace = inbound && (kernel_ops->get_spi != NULL); + replace = inbound && (kernel_ops->get_spi != NULL); - src.maskbits = 0; - dst.maskbits = 0; + src.maskbits = 0; + dst.maskbits = 0; - if (inbound) - { - src.addr = c->spd.that.host_addr; - dst.addr = c->spd.this.host_addr; - src_client = c->spd.that.client; - dst_client = c->spd.this.client; - } - else - { - src.addr = c->spd.this.host_addr, - dst.addr = c->spd.that.host_addr; - src_client = c->spd.this.client; - dst_client = c->spd.that.client; - } - - encapsulation = ENCAPSULATION_MODE_TRANSPORT; - if (st->st_ah.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL - || st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL - || st->st_ipcomp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL) - { - encapsulation = ENCAPSULATION_MODE_TUNNEL; - } - - memset(said, 0, sizeof(said)); - - /* If we are tunnelling, set up IP in IP pseudo SA */ - - if (kernel_ops->inbound_eroute) - { - inner_spi = 256; - proto = SA_IPIP; - satype = SADB_SATYPE_UNSPEC; - } - else if (encapsulation == ENCAPSULATION_MODE_TUNNEL) - { - /* XXX hack alert -- we SHOULD NOT HAVE TO HAVE A DIFFERENT SPI - * XXX FOR IP-in-IP ENCAPSULATION! - */ - - ipsec_spi_t ipip_spi; - - /* Allocate an SPI for the tunnel. - * Since our peer will never see this, - * and it comes from its own number space, - * it is purely a local implementation wart. - */ + if (inbound) { - static ipsec_spi_t last_tunnel_spi = IPSEC_DOI_SPI_OUR_MIN; - - ipip_spi = htonl(++last_tunnel_spi); - if (inbound) - st->st_tunnel_in_spi = ipip_spi; - else - st->st_tunnel_out_spi = ipip_spi; - } - - set_text_said(text_said - , &c->spd.that.host_addr, ipip_spi, SA_IPIP); - - said_next->src = &src.addr; - said_next->dst = &dst.addr; - said_next->src_client = &src_client; - said_next->dst_client = &dst_client; - said_next->spi = ipip_spi; - said_next->satype = SADB_X_SATYPE_IPIP; - said_next->text_said = text_said; - - if (!kernel_ops->add_sa(said_next, replace)) - goto fail; - - said_next++; - - inner_spi = ipip_spi; - proto = SA_IPIP; - satype = SADB_X_SATYPE_IPIP; - } - - /* set up IPCOMP SA, if any */ - - if (st->st_ipcomp.present) - { - ipsec_spi_t ipcomp_spi = inbound? st->st_ipcomp.our_spi : st->st_ipcomp.attrs.spi; - unsigned compalg; - - switch (st->st_ipcomp.attrs.transid) - { - case IPCOMP_DEFLATE: - compalg = SADB_X_CALG_DEFLATE; - break; - - default: - loglog(RC_LOG_SERIOUS, "IPCOMP transform %s not implemented" - , enum_name(&ipcomp_transformid_names, st->st_ipcomp.attrs.transid)); - goto fail; - } - - set_text_said(text_said, &dst.addr, ipcomp_spi, SA_COMP); - - said_next->src = &src.addr; - said_next->dst = &dst.addr; - said_next->src_client = &src_client; - said_next->dst_client = &dst_client; - said_next->spi = ipcomp_spi; - said_next->satype = SADB_X_SATYPE_COMP; - said_next->compalg = compalg; - said_next->encapsulation = encapsulation; - said_next->reqid = c->spd.reqid + 2; - said_next->text_said = text_said; - - if (!kernel_ops->add_sa(said_next, replace)) - goto fail; - - said_next++; - - encapsulation = ENCAPSULATION_MODE_TRANSPORT; - } - - /* set up ESP SA, if any */ - - if (st->st_esp.present) - { - ipsec_spi_t esp_spi = inbound? st->st_esp.our_spi : st->st_esp.attrs.spi; - u_char *esp_dst_keymat = inbound? st->st_esp.our_keymat : st->st_esp.peer_keymat; - const struct esp_info *ei; - u_int16_t key_len; - - static const struct esp_info esp_info[] = { - { ESP_NULL, AUTH_ALGORITHM_HMAC_MD5, - 0, HMAC_MD5_KEY_LEN, - SADB_EALG_NULL, SADB_AALG_MD5HMAC }, - { ESP_NULL, AUTH_ALGORITHM_HMAC_SHA1, - 0, HMAC_SHA1_KEY_LEN, - SADB_EALG_NULL, SADB_AALG_SHA1HMAC }, - - { ESP_DES, AUTH_ALGORITHM_NONE, - DES_CBC_BLOCK_SIZE, 0, - SADB_EALG_DESCBC, SADB_AALG_NONE }, - { ESP_DES, AUTH_ALGORITHM_HMAC_MD5, - DES_CBC_BLOCK_SIZE, HMAC_MD5_KEY_LEN, - SADB_EALG_DESCBC, SADB_AALG_MD5HMAC }, - { ESP_DES, AUTH_ALGORITHM_HMAC_SHA1, - DES_CBC_BLOCK_SIZE, - HMAC_SHA1_KEY_LEN, SADB_EALG_DESCBC, SADB_AALG_SHA1HMAC }, - - { ESP_3DES, AUTH_ALGORITHM_NONE, - DES_CBC_BLOCK_SIZE * 3, 0, - SADB_EALG_3DESCBC, SADB_AALG_NONE }, - { ESP_3DES, AUTH_ALGORITHM_HMAC_MD5, - DES_CBC_BLOCK_SIZE * 3, HMAC_MD5_KEY_LEN, - SADB_EALG_3DESCBC, SADB_AALG_MD5HMAC }, - { ESP_3DES, AUTH_ALGORITHM_HMAC_SHA1, - DES_CBC_BLOCK_SIZE * 3, HMAC_SHA1_KEY_LEN, - SADB_EALG_3DESCBC, SADB_AALG_SHA1HMAC }, - }; - - u_int8_t natt_type = 0; - u_int16_t natt_sport = 0; - u_int16_t natt_dport = 0; - ip_address natt_oa; - - if (st->nat_traversal & NAT_T_DETECTED) - { - natt_type = (st->nat_traversal & NAT_T_WITH_PORT_FLOATING) ? - ESPINUDP_WITH_NON_ESP : ESPINUDP_WITH_NON_IKE; - natt_sport = inbound? c->spd.that.host_port : c->spd.this.host_port; - natt_dport = inbound? c->spd.this.host_port : c->spd.that.host_port; - natt_oa = st->nat_oa; - } - - for (ei = esp_info; ; ei++) - { - if (ei == &esp_info[countof(esp_info)]) - { - /* Check for additional kernel alg */ -#ifndef NO_KERNEL_ALG - if ((ei=kernel_alg_esp_info(st->st_esp.attrs.transid, - st->st_esp.attrs.auth))!=NULL) { - break; - } -#endif - - /* note: enum_show may use a static buffer, so two - * calls in one printf would be a mistake. - * enum_name does the same job, without a static buffer, - * assuming the name will be found. - */ - loglog(RC_LOG_SERIOUS, "ESP transform %s / auth %s not implemented yet" - , enum_name(&esp_transformid_names, st->st_esp.attrs.transid) - , enum_name(&auth_alg_names, st->st_esp.attrs.auth)); - goto fail; - } - - if (st->st_esp.attrs.transid == ei->transid - && st->st_esp.attrs.auth == ei->auth) - break; - } - - key_len = st->st_esp.attrs.key_len/8; - if (key_len) - { - /* XXX: must change to check valid _range_ key_len */ - if (key_len > ei->enckeylen) - { - loglog(RC_LOG_SERIOUS, "ESP transform %s passed key_len=%d > %d", - enum_name(&esp_transformid_names, st->st_esp.attrs.transid), - (int)key_len, (int)ei->enckeylen); - goto fail; - } + src.addr = c->spd.that.host_addr; + dst.addr = c->spd.this.host_addr; + src_client = c->spd.that.client; + dst_client = c->spd.this.client; } else { - key_len = ei->enckeylen; - } - /* Grrrrr.... f*cking 7 bits jurassic algos */ - - /* 168 bits in kernel, need 192 bits for keymat_len */ - if (ei->transid == ESP_3DES && key_len == 21) - key_len = 24; - - /* 56 bits in kernel, need 64 bits for keymat_len */ - if (ei->transid == ESP_DES && key_len == 7) - key_len = 8; - - /* divide up keying material */ - /* passert(st->st_esp.keymat_len == ei->enckeylen + ei->authkeylen); */ - DBG(DBG_KLIPS|DBG_CONTROL|DBG_PARSING, - if(st->st_esp.keymat_len != key_len + ei->authkeylen) - DBG_log("keymat_len=%d key_len=%d authkeylen=%d", - st->st_esp.keymat_len, (int)key_len, (int)ei->authkeylen); - ) - passert(st->st_esp.keymat_len == key_len + ei->authkeylen); - - set_text_said(text_said, &dst.addr, esp_spi, SA_ESP); - - said_next->src = &src.addr; - said_next->dst = &dst.addr; - said_next->src_client = &src_client; - said_next->dst_client = &dst_client; - said_next->spi = esp_spi; - said_next->satype = SADB_SATYPE_ESP; - said_next->replay_window = (kernel_ops->type == KERNEL_TYPE_KLIPS) ? REPLAY_WINDOW : REPLAY_WINDOW_XFRM; - said_next->authalg = ei->authalg; - said_next->authkeylen = ei->authkeylen; - /* said_next->authkey = esp_dst_keymat + ei->enckeylen; */ - said_next->authkey = esp_dst_keymat + key_len; - said_next->encalg = ei->encryptalg; - /* said_next->enckeylen = ei->enckeylen; */ - said_next->enckeylen = key_len; - said_next->enckey = esp_dst_keymat; - said_next->encapsulation = encapsulation; - said_next->reqid = c->spd.reqid + 1; - said_next->natt_sport = natt_sport; - said_next->natt_dport = natt_dport; - said_next->transid = st->st_esp.attrs.transid; - said_next->natt_type = natt_type; - said_next->natt_oa = &natt_oa; - said_next->text_said = text_said; - - if (!kernel_ops->add_sa(said_next, replace)) - goto fail; - - said_next++; - - encapsulation = ENCAPSULATION_MODE_TRANSPORT; - } - - /* set up AH SA, if any */ - - if (st->st_ah.present) - { - ipsec_spi_t ah_spi = inbound? st->st_ah.our_spi : st->st_ah.attrs.spi; - u_char *ah_dst_keymat = inbound? st->st_ah.our_keymat : st->st_ah.peer_keymat; - - unsigned char authalg; - - switch (st->st_ah.attrs.auth) - { - case AUTH_ALGORITHM_HMAC_MD5: - authalg = SADB_AALG_MD5HMAC; - break; - - case AUTH_ALGORITHM_HMAC_SHA1: - authalg = SADB_AALG_SHA1HMAC; - break; - - default: - loglog(RC_LOG_SERIOUS, "%s not implemented yet" - , enum_show(&auth_alg_names, st->st_ah.attrs.auth)); - goto fail; + src.addr = c->spd.this.host_addr, + dst.addr = c->spd.that.host_addr; + src_client = c->spd.this.client; + dst_client = c->spd.that.client; } - set_text_said(text_said, &dst.addr, ah_spi, SA_AH); - - said_next->src = &src.addr; - said_next->dst = &dst.addr; - said_next->src_client = &src_client; - said_next->dst_client = &dst_client; - said_next->spi = ah_spi; - said_next->satype = SADB_SATYPE_AH; - said_next->replay_window = (kernel_ops->type == KERNEL_TYPE_KLIPS) ? REPLAY_WINDOW : REPLAY_WINDOW_XFRM; - said_next->authalg = authalg; - said_next->authkeylen = st->st_ah.keymat_len; - said_next->authkey = ah_dst_keymat; - said_next->encapsulation = encapsulation; - said_next->reqid = c->spd.reqid; - said_next->text_said = text_said; - - if (!kernel_ops->add_sa(said_next, replace)) - goto fail; - - said_next++; - encapsulation = ENCAPSULATION_MODE_TRANSPORT; - } - - if (st->st_ah.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL - || st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL - || st->st_ipcomp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL) - { - encapsulation = ENCAPSULATION_MODE_TUNNEL; - } - - if (kernel_ops->inbound_eroute ? c->spd.eroute_owner == SOS_NOBODY - : encapsulation == ENCAPSULATION_MODE_TUNNEL) - { - /* If inbound, and policy does not specifie DISABLEARRIVALCHECK, - * tell KLIPS to enforce the IP addresses appropriate for this tunnel. - * Note reversed ends. - * Not much to be done on failure. - */ - if (inbound && (c->policy & POLICY_DISABLEARRIVALCHECK) == 0) + if (st->st_ah.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL + || st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL + || st->st_ipcomp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL) { - struct pfkey_proto_info proto_info[4]; - int i = 0; - - if (st->st_ipcomp.present) - { - proto_info[i].proto = IPPROTO_COMP; - proto_info[i].encapsulation = st->st_ipcomp.attrs.encapsulation; - proto_info[i].reqid = c->spd.reqid + 2; - i++; - } - - if (st->st_esp.present) - { - proto_info[i].proto = IPPROTO_ESP; - proto_info[i].encapsulation = st->st_esp.attrs.encapsulation; - proto_info[i].reqid = c->spd.reqid + 1; - i++; - } - - if (st->st_ah.present) - { - proto_info[i].proto = IPPROTO_AH; - proto_info[i].encapsulation = st->st_ah.attrs.encapsulation; - proto_info[i].reqid = c->spd.reqid; - i++; - } - - proto_info[i].proto = 0; - - if (kernel_ops->inbound_eroute - && encapsulation == ENCAPSULATION_MODE_TUNNEL) - { - proto_info[0].encapsulation = ENCAPSULATION_MODE_TUNNEL; - for (i = 1; proto_info[i].proto; i++) + encapsulation = ENCAPSULATION_MODE_TUNNEL; + } + + memset(said, 0, sizeof(said)); + + /* If we are tunnelling, set up IP in IP pseudo SA */ + + if (kernel_ops->inbound_eroute) + { + inner_spi = 256; + proto = SA_IPIP; + satype = SADB_SATYPE_UNSPEC; + } + else if (encapsulation == ENCAPSULATION_MODE_TUNNEL) + { + /* XXX hack alert -- we SHOULD NOT HAVE TO HAVE A DIFFERENT SPI + * XXX FOR IP-in-IP ENCAPSULATION! + */ + + ipsec_spi_t ipip_spi; + + /* Allocate an SPI for the tunnel. + * Since our peer will never see this, + * and it comes from its own number space, + * it is purely a local implementation wart. + */ { - proto_info[i].encapsulation = ENCAPSULATION_MODE_TRANSPORT; + static ipsec_spi_t last_tunnel_spi = IPSEC_DOI_SPI_OUR_MIN; + + ipip_spi = htonl(++last_tunnel_spi); + if (inbound) + st->st_tunnel_in_spi = ipip_spi; + else + st->st_tunnel_out_spi = ipip_spi; } - } - - /* MCR - should be passed a spd_eroute structure here */ - (void) raw_eroute(&c->spd.that.host_addr, &c->spd.that.client - , &c->spd.this.host_addr, &c->spd.this.client - , inner_spi, proto, satype, c->spd.this.protocol - , proto_info, 0 - , ERO_ADD_INBOUND, "add inbound"); - } - } - /* If there are multiple SPIs, group them. */ - - if (kernel_ops->grp_sa && said_next > &said[1]) - { - struct kernel_sa *s; - - /* group SAs, two at a time, inner to outer (backwards in said[]) - * The grouping is by pairs. So if said[] contains ah esp ipip, - * the grouping would be ipip:esp, esp:ah. - */ - for (s = said; s < said_next-1; s++) + set_text_said(text_said + , &c->spd.that.host_addr, ipip_spi, SA_IPIP); + + said_next->src = &src.addr; + said_next->dst = &dst.addr; + said_next->src_client = &src_client; + said_next->dst_client = &dst_client; + said_next->spi = ipip_spi; + said_next->satype = SADB_X_SATYPE_IPIP; + said_next->text_said = text_said; + + if (!kernel_ops->add_sa(said_next, replace)) + goto fail; + + said_next++; + + inner_spi = ipip_spi; + proto = SA_IPIP; + satype = SADB_X_SATYPE_IPIP; + } + + /* set up IPCOMP SA, if any */ + + if (st->st_ipcomp.present) { - char - text_said0[SATOT_BUF], - text_said1[SATOT_BUF]; + ipsec_spi_t ipcomp_spi = inbound? st->st_ipcomp.our_spi : st->st_ipcomp.attrs.spi; + unsigned compalg; - /* group s[1] and s[0], in that order */ - - set_text_said(text_said0, s[0].dst, s[0].spi, s[0].proto); - set_text_said(text_said1, s[1].dst, s[1].spi, s[1].proto); - - DBG(DBG_KLIPS, DBG_log("grouping %s and %s", text_said1, text_said0)); - - s[0].text_said = text_said0; - s[1].text_said = text_said1; - - if (!kernel_ops->grp_sa(s + 1, s)) - goto fail; + switch (st->st_ipcomp.attrs.transid) + { + case IPCOMP_DEFLATE: + compalg = SADB_X_CALG_DEFLATE; + break; + + default: + loglog(RC_LOG_SERIOUS, "IPCOMP transform %s not implemented" + , enum_name(&ipcomp_transformid_names, st->st_ipcomp.attrs.transid)); + goto fail; + } + + set_text_said(text_said, &dst.addr, ipcomp_spi, SA_COMP); + + said_next->src = &src.addr; + said_next->dst = &dst.addr; + said_next->src_client = &src_client; + said_next->dst_client = &dst_client; + said_next->spi = ipcomp_spi; + said_next->satype = SADB_X_SATYPE_COMP; + said_next->compalg = compalg; + said_next->encapsulation = encapsulation; + said_next->reqid = c->spd.reqid + 2; + said_next->text_said = text_said; + + if (!kernel_ops->add_sa(said_next, replace)) + goto fail; + + said_next++; + + encapsulation = ENCAPSULATION_MODE_TRANSPORT; } - /* could update said, but it will not be used */ - } - return TRUE; + /* set up ESP SA, if any */ + + if (st->st_esp.present) + { + ipsec_spi_t esp_spi = inbound? st->st_esp.our_spi : st->st_esp.attrs.spi; + u_char *esp_dst_keymat = inbound? st->st_esp.our_keymat : st->st_esp.peer_keymat; + const struct esp_info *ei; + u_int16_t key_len; + + static const struct esp_info esp_info[] = { + { ESP_NULL, AUTH_ALGORITHM_HMAC_MD5, + 0, HMAC_MD5_KEY_LEN, + SADB_EALG_NULL, SADB_AALG_MD5HMAC }, + { ESP_NULL, AUTH_ALGORITHM_HMAC_SHA1, + 0, HMAC_SHA1_KEY_LEN, + SADB_EALG_NULL, SADB_AALG_SHA1HMAC }, + + { ESP_DES, AUTH_ALGORITHM_NONE, + DES_CBC_BLOCK_SIZE, 0, + SADB_EALG_DESCBC, SADB_AALG_NONE }, + { ESP_DES, AUTH_ALGORITHM_HMAC_MD5, + DES_CBC_BLOCK_SIZE, HMAC_MD5_KEY_LEN, + SADB_EALG_DESCBC, SADB_AALG_MD5HMAC }, + { ESP_DES, AUTH_ALGORITHM_HMAC_SHA1, + DES_CBC_BLOCK_SIZE, + HMAC_SHA1_KEY_LEN, SADB_EALG_DESCBC, SADB_AALG_SHA1HMAC }, + + { ESP_3DES, AUTH_ALGORITHM_NONE, + DES_CBC_BLOCK_SIZE * 3, 0, + SADB_EALG_3DESCBC, SADB_AALG_NONE }, + { ESP_3DES, AUTH_ALGORITHM_HMAC_MD5, + DES_CBC_BLOCK_SIZE * 3, HMAC_MD5_KEY_LEN, + SADB_EALG_3DESCBC, SADB_AALG_MD5HMAC }, + { ESP_3DES, AUTH_ALGORITHM_HMAC_SHA1, + DES_CBC_BLOCK_SIZE * 3, HMAC_SHA1_KEY_LEN, + SADB_EALG_3DESCBC, SADB_AALG_SHA1HMAC }, + }; + + u_int8_t natt_type = 0; + u_int16_t natt_sport = 0; + u_int16_t natt_dport = 0; + ip_address natt_oa; + + if (st->nat_traversal & NAT_T_DETECTED) + { + natt_type = (st->nat_traversal & NAT_T_WITH_PORT_FLOATING) ? + ESPINUDP_WITH_NON_ESP : ESPINUDP_WITH_NON_IKE; + natt_sport = inbound? c->spd.that.host_port : c->spd.this.host_port; + natt_dport = inbound? c->spd.this.host_port : c->spd.that.host_port; + natt_oa = st->nat_oa; + } + + for (ei = esp_info; ; ei++) + { + if (ei == &esp_info[countof(esp_info)]) + { + /* Check for additional kernel alg */ +#ifndef NO_KERNEL_ALG + if ((ei=kernel_alg_esp_info(st->st_esp.attrs.transid, + st->st_esp.attrs.auth))!=NULL) { + break; + } +#endif + + /* note: enum_show may use a static buffer, so two + * calls in one printf would be a mistake. + * enum_name does the same job, without a static buffer, + * assuming the name will be found. + */ + loglog(RC_LOG_SERIOUS, "ESP transform %s / auth %s not implemented yet" + , enum_name(&esp_transformid_names, st->st_esp.attrs.transid) + , enum_name(&auth_alg_names, st->st_esp.attrs.auth)); + goto fail; + } + + if (st->st_esp.attrs.transid == ei->transid + && st->st_esp.attrs.auth == ei->auth) + break; + } + + key_len = st->st_esp.attrs.key_len/8; + if (key_len) + { + /* XXX: must change to check valid _range_ key_len */ + if (key_len > ei->enckeylen) + { + loglog(RC_LOG_SERIOUS, "ESP transform %s passed key_len=%d > %d", + enum_name(&esp_transformid_names, st->st_esp.attrs.transid), + (int)key_len, (int)ei->enckeylen); + goto fail; + } + } + else + { + key_len = ei->enckeylen; + } + /* Grrrrr.... f*cking 7 bits jurassic algos */ + + /* 168 bits in kernel, need 192 bits for keymat_len */ + if (ei->transid == ESP_3DES && key_len == 21) + key_len = 24; + + /* 56 bits in kernel, need 64 bits for keymat_len */ + if (ei->transid == ESP_DES && key_len == 7) + key_len = 8; + + /* divide up keying material */ + /* passert(st->st_esp.keymat_len == ei->enckeylen + ei->authkeylen); */ + DBG(DBG_KLIPS|DBG_CONTROL|DBG_PARSING, + if(st->st_esp.keymat_len != key_len + ei->authkeylen) + DBG_log("keymat_len=%d key_len=%d authkeylen=%d", + st->st_esp.keymat_len, (int)key_len, (int)ei->authkeylen); + ) + passert(st->st_esp.keymat_len == key_len + ei->authkeylen); + + set_text_said(text_said, &dst.addr, esp_spi, SA_ESP); + + said_next->src = &src.addr; + said_next->dst = &dst.addr; + said_next->src_client = &src_client; + said_next->dst_client = &dst_client; + said_next->spi = esp_spi; + said_next->satype = SADB_SATYPE_ESP; + said_next->replay_window = (kernel_ops->type == KERNEL_TYPE_KLIPS) ? REPLAY_WINDOW : REPLAY_WINDOW_XFRM; + said_next->authalg = ei->authalg; + said_next->authkeylen = ei->authkeylen; + /* said_next->authkey = esp_dst_keymat + ei->enckeylen; */ + said_next->authkey = esp_dst_keymat + key_len; + said_next->encalg = ei->encryptalg; + /* said_next->enckeylen = ei->enckeylen; */ + said_next->enckeylen = key_len; + said_next->enckey = esp_dst_keymat; + said_next->encapsulation = encapsulation; + said_next->reqid = c->spd.reqid + 1; + said_next->natt_sport = natt_sport; + said_next->natt_dport = natt_dport; + said_next->transid = st->st_esp.attrs.transid; + said_next->natt_type = natt_type; + said_next->natt_oa = &natt_oa; + said_next->text_said = text_said; + + if (!kernel_ops->add_sa(said_next, replace)) + goto fail; + + said_next++; + + encapsulation = ENCAPSULATION_MODE_TRANSPORT; + } + + /* set up AH SA, if any */ + + if (st->st_ah.present) + { + ipsec_spi_t ah_spi = inbound? st->st_ah.our_spi : st->st_ah.attrs.spi; + u_char *ah_dst_keymat = inbound? st->st_ah.our_keymat : st->st_ah.peer_keymat; + + unsigned char authalg; + + switch (st->st_ah.attrs.auth) + { + case AUTH_ALGORITHM_HMAC_MD5: + authalg = SADB_AALG_MD5HMAC; + break; + + case AUTH_ALGORITHM_HMAC_SHA1: + authalg = SADB_AALG_SHA1HMAC; + break; + + default: + loglog(RC_LOG_SERIOUS, "%s not implemented yet" + , enum_show(&auth_alg_names, st->st_ah.attrs.auth)); + goto fail; + } + + set_text_said(text_said, &dst.addr, ah_spi, SA_AH); + + said_next->src = &src.addr; + said_next->dst = &dst.addr; + said_next->src_client = &src_client; + said_next->dst_client = &dst_client; + said_next->spi = ah_spi; + said_next->satype = SADB_SATYPE_AH; + said_next->replay_window = (kernel_ops->type == KERNEL_TYPE_KLIPS) ? REPLAY_WINDOW : REPLAY_WINDOW_XFRM; + said_next->authalg = authalg; + said_next->authkeylen = st->st_ah.keymat_len; + said_next->authkey = ah_dst_keymat; + said_next->encapsulation = encapsulation; + said_next->reqid = c->spd.reqid; + said_next->text_said = text_said; + + if (!kernel_ops->add_sa(said_next, replace)) + goto fail; + + said_next++; + + encapsulation = ENCAPSULATION_MODE_TRANSPORT; + } + + if (st->st_ah.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL + || st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL + || st->st_ipcomp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL) + { + encapsulation = ENCAPSULATION_MODE_TUNNEL; + } + + if (kernel_ops->inbound_eroute ? c->spd.eroute_owner == SOS_NOBODY + : encapsulation == ENCAPSULATION_MODE_TUNNEL) + { + /* If inbound, and policy does not specifie DISABLEARRIVALCHECK, + * tell KLIPS to enforce the IP addresses appropriate for this tunnel. + * Note reversed ends. + * Not much to be done on failure. + */ + if (inbound && (c->policy & POLICY_DISABLEARRIVALCHECK) == 0) + { + struct pfkey_proto_info proto_info[4]; + int i = 0; + + if (st->st_ipcomp.present) + { + proto_info[i].proto = IPPROTO_COMP; + proto_info[i].encapsulation = st->st_ipcomp.attrs.encapsulation; + proto_info[i].reqid = c->spd.reqid + 2; + i++; + } + + if (st->st_esp.present) + { + proto_info[i].proto = IPPROTO_ESP; + proto_info[i].encapsulation = st->st_esp.attrs.encapsulation; + proto_info[i].reqid = c->spd.reqid + 1; + i++; + } + + if (st->st_ah.present) + { + proto_info[i].proto = IPPROTO_AH; + proto_info[i].encapsulation = st->st_ah.attrs.encapsulation; + proto_info[i].reqid = c->spd.reqid; + i++; + } + + proto_info[i].proto = 0; + + if (kernel_ops->inbound_eroute + && encapsulation == ENCAPSULATION_MODE_TUNNEL) + { + proto_info[0].encapsulation = ENCAPSULATION_MODE_TUNNEL; + for (i = 1; proto_info[i].proto; i++) + { + proto_info[i].encapsulation = ENCAPSULATION_MODE_TRANSPORT; + } + } + + /* MCR - should be passed a spd_eroute structure here */ + (void) raw_eroute(&c->spd.that.host_addr, &c->spd.that.client + , &c->spd.this.host_addr, &c->spd.this.client + , inner_spi, proto, satype, c->spd.this.protocol + , proto_info, 0 + , ERO_ADD_INBOUND, "add inbound"); + } + } + + /* If there are multiple SPIs, group them. */ + + if (kernel_ops->grp_sa && said_next > &said[1]) + { + struct kernel_sa *s; + + /* group SAs, two at a time, inner to outer (backwards in said[]) + * The grouping is by pairs. So if said[] contains ah esp ipip, + * the grouping would be ipip:esp, esp:ah. + */ + for (s = said; s < said_next-1; s++) + { + char + text_said0[SATOT_BUF], + text_said1[SATOT_BUF]; + + /* group s[1] and s[0], in that order */ + + set_text_said(text_said0, s[0].dst, s[0].spi, s[0].proto); + set_text_said(text_said1, s[1].dst, s[1].spi, s[1].proto); + + DBG(DBG_KLIPS, DBG_log("grouping %s and %s", text_said1, text_said0)); + + s[0].text_said = text_said0; + s[1].text_said = text_said1; + + if (!kernel_ops->grp_sa(s + 1, s)) + goto fail; + } + /* could update said, but it will not be used */ + } + + return TRUE; fail: - { - /* undo the done SPIs */ - while (said_next-- != said) - (void) del_spi(said_next->spi, said_next->proto - , &src.addr, said_next->dst); - return FALSE; - } + { + /* undo the done SPIs */ + while (said_next-- != said) + (void) del_spi(said_next->spi, said_next->proto + , &src.addr, said_next->dst); + return FALSE; + } } /* teardown_ipsec_sa is a canibalized version of setup_ipsec_sa */ @@ -2127,94 +2127,94 @@ fail: static bool teardown_half_ipsec_sa(struct state *st, bool inbound) { - /* We need to delete AH, ESP, and IP in IP SPIs. - * But if there is more than one, they have been grouped - * so deleting any one will do. So we just delete the - * first one found. It may or may not be the only one. - */ - struct connection *c = st->st_connection; - struct { - unsigned proto; - struct ipsec_proto_info *info; - } protos[4]; - int i; - bool result; + /* We need to delete AH, ESP, and IP in IP SPIs. + * But if there is more than one, they have been grouped + * so deleting any one will do. So we just delete the + * first one found. It may or may not be the only one. + */ + struct connection *c = st->st_connection; + struct { + unsigned proto; + struct ipsec_proto_info *info; + } protos[4]; + int i; + bool result; - i = 0; - if (kernel_ops->inbound_eroute && inbound - && c->spd.eroute_owner == SOS_NOBODY) - { - (void) raw_eroute(&c->spd.that.host_addr, &c->spd.that.client - , &c->spd.this.host_addr, &c->spd.this.client - , 256, IPSEC_PROTO_ANY, SADB_SATYPE_UNSPEC, c->spd.this.protocol - , null_proto_info, 0 - , ERO_DEL_INBOUND, "delete inbound"); - } - - if (!kernel_ops->grp_sa) - { - if (st->st_ah.present) + i = 0; + if (kernel_ops->inbound_eroute && inbound + && c->spd.eroute_owner == SOS_NOBODY) { - protos[i].info = &st->st_ah; - protos[i].proto = SA_AH; - i++; + (void) raw_eroute(&c->spd.that.host_addr, &c->spd.that.client + , &c->spd.this.host_addr, &c->spd.this.client + , 256, IPSEC_PROTO_ANY, SADB_SATYPE_UNSPEC, c->spd.this.protocol + , null_proto_info, 0 + , ERO_DEL_INBOUND, "delete inbound"); } - if (st->st_esp.present) + if (!kernel_ops->grp_sa) { - protos[i].info = &st->st_esp; - protos[i].proto = SA_ESP; - i++; + if (st->st_ah.present) + { + protos[i].info = &st->st_ah; + protos[i].proto = SA_AH; + i++; + } + + if (st->st_esp.present) + { + protos[i].info = &st->st_esp; + protos[i].proto = SA_ESP; + i++; + } + + if (st->st_ipcomp.present) + { + protos[i].info = &st->st_ipcomp; + protos[i].proto = SA_COMP; + i++; + } } - - if (st->st_ipcomp.present) + else if (st->st_ah.present) { - protos[i].info = &st->st_ipcomp; - protos[i].proto = SA_COMP; - i++; + protos[i].info = &st->st_ah; + protos[i].proto = SA_AH; + i++; } - } - else if (st->st_ah.present) - { - protos[i].info = &st->st_ah; - protos[i].proto = SA_AH; - i++; - } - else if (st->st_esp.present) - { - protos[i].info = &st->st_esp; - protos[i].proto = SA_ESP; - i++; - } - else - { - impossible(); /* neither AH nor ESP in outbound SA bundle! */ - } - protos[i].proto = 0; - - result = TRUE; - for (i = 0; protos[i].proto; i++) - { - unsigned proto = protos[i].proto; - ipsec_spi_t spi; - const ip_address *src, *dst; - - if (inbound) + else if (st->st_esp.present) { - spi = protos[i].info->our_spi; - src = &c->spd.that.host_addr; - dst = &c->spd.this.host_addr; + protos[i].info = &st->st_esp; + protos[i].proto = SA_ESP; + i++; } else { - spi = protos[i].info->attrs.spi; - src = &c->spd.this.host_addr; - dst = &c->spd.that.host_addr; + impossible(); /* neither AH nor ESP in outbound SA bundle! */ } + protos[i].proto = 0; - result &= del_spi(spi, proto, src, dst); - } - return result; + result = TRUE; + for (i = 0; protos[i].proto; i++) + { + unsigned proto = protos[i].proto; + ipsec_spi_t spi; + const ip_address *src, *dst; + + if (inbound) + { + spi = protos[i].info->our_spi; + src = &c->spd.that.host_addr; + dst = &c->spd.this.host_addr; + } + else + { + spi = protos[i].info->attrs.spi; + src = &c->spd.this.host_addr; + dst = &c->spd.that.host_addr; + } + + result &= del_spi(spi, proto, src, dst); + } + return result; } /* @@ -2223,69 +2223,69 @@ teardown_half_ipsec_sa(struct state *st, bool inbound) bool get_sa_info(struct state *st, bool inbound, u_int *bytes, time_t *use_time) { - char text_said[SATOT_BUF]; - struct kernel_sa sa; - struct connection *c = st->st_connection; + char text_said[SATOT_BUF]; + struct kernel_sa sa; + struct connection *c = st->st_connection; - *use_time = UNDEFINED_TIME; + *use_time = UNDEFINED_TIME; - if (kernel_ops->get_sa == NULL || !st->st_esp.present) - return FALSE; + if (kernel_ops->get_sa == NULL || !st->st_esp.present) + return FALSE; - memset(&sa, 0, sizeof(sa)); - sa.proto = SA_ESP; - - if (inbound) - { - sa.src = &c->spd.that.host_addr; - sa.dst = &c->spd.this.host_addr; - sa.spi = st->st_esp.our_spi; - } - else - { - sa.src = &c->spd.this.host_addr; - sa.dst = &c->spd.that.host_addr; - sa.spi = st->st_esp.attrs.spi; - } - set_text_said(text_said, sa.dst, sa.spi, sa.proto); - - sa.text_said = text_said; - - DBG(DBG_KLIPS, - DBG_log("get %s", text_said) - ) - if (!kernel_ops->get_sa(&sa, bytes)) - return FALSE; - DBG(DBG_KLIPS, - DBG_log(" current: %d bytes", *bytes) - ) - - if (st->st_serialno == c->spd.eroute_owner) - { - DBG(DBG_KLIPS, - DBG_log("get %sbound policy with reqid %u" - , inbound? "in":"out", (u_int)c->spd.reqid + 1) - ) - sa.transport_proto = c->spd.this.protocol; - sa.encapsulation = st->st_esp.attrs.encapsulation; + memset(&sa, 0, sizeof(sa)); + sa.proto = SA_ESP; if (inbound) { - sa.src_client = &c->spd.that.client; - sa.dst_client = &c->spd.this.client; + sa.src = &c->spd.that.host_addr; + sa.dst = &c->spd.this.host_addr; + sa.spi = st->st_esp.our_spi; } else { - sa.src_client = &c->spd.this.client; - sa.dst_client = &c->spd.that.client; + sa.src = &c->spd.this.host_addr; + sa.dst = &c->spd.that.host_addr; + sa.spi = st->st_esp.attrs.spi; } - if (!kernel_ops->get_policy(&sa, inbound, use_time)) - return FALSE; + set_text_said(text_said, sa.dst, sa.spi, sa.proto); + + sa.text_said = text_said; + DBG(DBG_KLIPS, - DBG_log(" use_time: %T", use_time, FALSE) + DBG_log("get %s", text_said) ) - } - return TRUE; + if (!kernel_ops->get_sa(&sa, bytes)) + return FALSE; + DBG(DBG_KLIPS, + DBG_log(" current: %d bytes", *bytes) + ) + + if (st->st_serialno == c->spd.eroute_owner) + { + DBG(DBG_KLIPS, + DBG_log("get %sbound policy with reqid %u" + , inbound? "in":"out", (u_int)c->spd.reqid + 1) + ) + sa.transport_proto = c->spd.this.protocol; + sa.encapsulation = st->st_esp.attrs.encapsulation; + + if (inbound) + { + sa.src_client = &c->spd.that.client; + sa.dst_client = &c->spd.this.client; + } + else + { + sa.src_client = &c->spd.this.client; + sa.dst_client = &c->spd.that.client; + } + if (!kernel_ops->get_policy(&sa, inbound, use_time)) + return FALSE; + DBG(DBG_KLIPS, + DBG_log(" use_time: %T", use_time, FALSE) + ) + } + return TRUE; } const struct kernel_ops *kernel_ops; @@ -2297,47 +2297,47 @@ init_kernel(void) { #ifdef KLIPS - if (no_klips) - { - kernel_ops = &noklips_kernel_ops; - return; - } + if (no_klips) + { + kernel_ops = &noklips_kernel_ops; + return; + } - init_pfkey(); + init_pfkey(); - kernel_ops = &klips_kernel_ops; + kernel_ops = &klips_kernel_ops; #if defined(linux) && defined(KERNEL26_SUPPORT) - { - bool linux_ipsec = 0; - struct stat buf; + { + bool linux_ipsec = 0; + struct stat buf; - linux_ipsec = (stat("/proc/net/pfkey", &buf) == 0); - if (linux_ipsec) - { - plog("Using Linux 2.6 IPsec interface code"); - kernel_ops = &linux_kernel_ops; - } - else - { - plog("Using KLIPS IPsec interface code"); - } - } + linux_ipsec = (stat("/proc/net/pfkey", &buf) == 0); + if (linux_ipsec) + { + plog("Using Linux 2.6 IPsec interface code"); + kernel_ops = &linux_kernel_ops; + } + else + { + plog("Using KLIPS IPsec interface code"); + } + } #endif - if (kernel_ops->init) - { - kernel_ops->init(); - } + if (kernel_ops->init) + { + kernel_ops->init(); + } - /* register SA types that we can negotiate */ - can_do_IPcomp = FALSE; /* until we get a response from KLIPS */ - kernel_ops->pfkey_register(); + /* register SA types that we can negotiate */ + can_do_IPcomp = FALSE; /* until we get a response from KLIPS */ + kernel_ops->pfkey_register(); - if (!kernel_ops->policy_lifetime) - { - event_schedule(EVENT_SHUNT_SCAN, SHUNT_SCAN_INTERVAL, NULL); - } + if (!kernel_ops->policy_lifetime) + { + event_schedule(EVENT_SHUNT_SCAN, SHUNT_SCAN_INTERVAL, NULL); + } #endif } @@ -2348,57 +2348,57 @@ init_kernel(void) bool install_inbound_ipsec_sa(struct state *st) { - struct connection *const c = st->st_connection; + struct connection *const c = st->st_connection; - /* If our peer has a fixed-address client, check if we already - * have a route for that client that conflicts. We will take this - * as proof that that route and the connections using it are - * obsolete and should be eliminated. Interestingly, this is - * the only case in which we can tell that a connection is obsolete. - */ - passert(c->kind == CK_PERMANENT || c->kind == CK_INSTANCE); - if (c->spd.that.has_client) - { - for (;;) + /* If our peer has a fixed-address client, check if we already + * have a route for that client that conflicts. We will take this + * as proof that that route and the connections using it are + * obsolete and should be eliminated. Interestingly, this is + * the only case in which we can tell that a connection is obsolete. + */ + passert(c->kind == CK_PERMANENT || c->kind == CK_INSTANCE); + if (c->spd.that.has_client) { - struct spd_route *esr; - struct connection *o = route_owner(c, &esr, NULL, NULL); + for (;;) + { + struct spd_route *esr; + struct connection *o = route_owner(c, &esr, NULL, NULL); - if (o == NULL) - break; /* nobody has a route */ + if (o == NULL) + break; /* nobody has a route */ - /* note: we ignore the client addresses at this end */ - if (sameaddr(&o->spd.that.host_addr, &c->spd.that.host_addr) - && o->interface == c->interface) - break; /* existing route is compatible */ + /* note: we ignore the client addresses at this end */ + if (sameaddr(&o->spd.that.host_addr, &c->spd.that.host_addr) + && o->interface == c->interface) + break; /* existing route is compatible */ - if (o->kind == CK_TEMPLATE && streq(o->name, c->name)) - break; /* ??? is this good enough?? */ + if (o->kind == CK_TEMPLATE && streq(o->name, c->name)) + break; /* ??? is this good enough?? */ - loglog(RC_LOG_SERIOUS, "route to peer's client conflicts with \"%s\" %s; releasing old connection to free the route" - , o->name, ip_str(&o->spd.that.host_addr)); - release_connection(o, FALSE); + loglog(RC_LOG_SERIOUS, "route to peer's client conflicts with \"%s\" %s; releasing old connection to free the route" + , o->name, ip_str(&o->spd.that.host_addr)); + release_connection(o, FALSE); + } } - } - DBG(DBG_CONTROL, DBG_log("install_inbound_ipsec_sa() checking if we can route")); - /* check that we will be able to route and eroute */ - switch (could_route(c)) - { - case route_easy: - case route_nearconflict: - break; + DBG(DBG_CONTROL, DBG_log("install_inbound_ipsec_sa() checking if we can route")); + /* check that we will be able to route and eroute */ + switch (could_route(c)) + { + case route_easy: + case route_nearconflict: + break; - default: - return FALSE; - } + default: + return FALSE; + } #ifdef KLIPS - /* (attempt to) actually set up the SAs */ - return setup_half_ipsec_sa(st, TRUE); + /* (attempt to) actually set up the SAs */ + return setup_half_ipsec_sa(st, TRUE); #else /* !KLIPS */ - DBG(DBG_CONTROL, DBG_log("install_inbound_ipsec_sa()")); - return TRUE; + DBG(DBG_CONTROL, DBG_log("install_inbound_ipsec_sa()")); + return TRUE; #endif /* !KLIPS */ } @@ -2409,284 +2409,284 @@ install_inbound_ipsec_sa(struct state *st) */ bool route_and_eroute(struct connection *c USED_BY_KLIPS - , struct spd_route *sr USED_BY_KLIPS - , struct state *st USED_BY_KLIPS) + , struct spd_route *sr USED_BY_KLIPS + , struct state *st USED_BY_KLIPS) { #ifdef KLIPS - struct spd_route *esr; - struct spd_route *rosr; - struct connection *ero /* who, if anyone, owns our eroute? */ - , *ro = route_owner(c, &rosr, &ero, &esr); - bool eroute_installed = FALSE - , firewall_notified = FALSE - , route_installed = FALSE; + struct spd_route *esr; + struct spd_route *rosr; + struct connection *ero /* who, if anyone, owns our eroute? */ + , *ro = route_owner(c, &rosr, &ero, &esr); + bool eroute_installed = FALSE + , firewall_notified = FALSE + , route_installed = FALSE; - struct connection *ero_top; - struct bare_shunt **bspp; + struct connection *ero_top; + struct bare_shunt **bspp; - DBG(DBG_CONTROLMORE, - DBG_log("route_and_eroute with c: %s (next: %s) ero:%s esr:{%p} ro:%s rosr:{%p} and state: %lu" - , c->name - , (c->policy_next ? c->policy_next->name : "none") - , ero ? ero->name : "null" - , esr - , ro ? ro->name : "null" - , rosr - , st ? st->st_serialno : 0)); + DBG(DBG_CONTROLMORE, + DBG_log("route_and_eroute with c: %s (next: %s) ero:%s esr:{%p} ro:%s rosr:{%p} and state: %lu" + , c->name + , (c->policy_next ? c->policy_next->name : "none") + , ero ? ero->name : "null" + , esr + , ro ? ro->name : "null" + , rosr + , st ? st->st_serialno : 0)); - /* look along the chain of policies for one with the same name */ - ero_top = ero; + /* look along the chain of policies for one with the same name */ + ero_top = ero; #if 0 - /* XXX - mcr this made sense before, and likely will make sense - * again, so I'l leaving this to remind me what is up */ - if (ero!= NULL && ero->routing == RT_UNROUTED_KEYED) - ero = NULL; + /* XXX - mcr this made sense before, and likely will make sense + * again, so I'l leaving this to remind me what is up */ + if (ero!= NULL && ero->routing == RT_UNROUTED_KEYED) + ero = NULL; - for (ero2 = ero; ero2 != NULL; ero2 = ero->policy_next) - if ((ero2->kind == CK_TEMPLATE || ero2->kind==CK_SECONDARY) - && streq(ero2->name, c->name)) - break; + for (ero2 = ero; ero2 != NULL; ero2 = ero->policy_next) + if ((ero2->kind == CK_TEMPLATE || ero2->kind==CK_SECONDARY) + && streq(ero2->name, c->name)) + break; #endif - bspp = (ero == NULL) - ? bare_shunt_ptr(&sr->this.client, &sr->that.client, sr->this.protocol) - : NULL; + bspp = (ero == NULL) + ? bare_shunt_ptr(&sr->this.client, &sr->that.client, sr->this.protocol) + : NULL; - /* install the eroute */ + /* install the eroute */ - passert(bspp == NULL || ero == NULL); /* only one non-NULL */ + passert(bspp == NULL || ero == NULL); /* only one non-NULL */ - if (bspp != NULL || ero != NULL) - { - /* We're replacing an eroute */ + if (bspp != NULL || ero != NULL) + { + /* We're replacing an eroute */ - /* if no state provided, then install a shunt for later */ - if (st == NULL) - eroute_installed = shunt_eroute(c, sr, RT_ROUTED_PROSPECTIVE - , ERO_REPLACE, "replace"); - else - eroute_installed = sag_eroute(st, sr, ERO_REPLACE, "replace"); + /* if no state provided, then install a shunt for later */ + if (st == NULL) + eroute_installed = shunt_eroute(c, sr, RT_ROUTED_PROSPECTIVE + , ERO_REPLACE, "replace"); + else + eroute_installed = sag_eroute(st, sr, ERO_REPLACE, "replace"); #if 0 - /* XXX - MCR. I previously felt that this was a bogus check */ - if (ero != NULL && ero != c && esr != sr) - { - /* By elimination, we must be eclipsing ero. Check. */ - passert(ero->kind == CK_TEMPLATE && streq(ero->name, c->name)); - passert(LHAS(LELEM(RT_ROUTED_PROSPECTIVE) | LELEM(RT_ROUTED_ECLIPSED) - , esr->routing)); - passert(samesubnet(&esr->this.client, &sr->this.client) - && samesubnet(&esr->that.client, &sr->that.client)); - } -#endif - /* remember to free bspp iff we make it out of here alive */ - } - else - { - /* we're adding an eroute */ - - /* if no state provided, then install a shunt for later */ - if (st == NULL) - eroute_installed = shunt_eroute(c, sr, RT_ROUTED_PROSPECTIVE - , ERO_ADD, "add"); - else - eroute_installed = sag_eroute(st, sr, ERO_ADD, "add"); - } - - /* notify the firewall of a new tunnel */ - - if (eroute_installed) - { - /* do we have to notify the firewall? Yes, if we are installing - * a tunnel eroute and the firewall wasn't notified - * for a previous tunnel with the same clients. Any Previous - * tunnel would have to be for our connection, so the actual - * test is simple. - */ - firewall_notified = st == NULL /* not a tunnel eroute */ - || sr->eroute_owner != SOS_NOBODY /* already notified */ - || do_command(c, sr, "up"); /* go ahead and notify */ - } - - /* install the route */ - - DBG(DBG_CONTROL, - DBG_log("route_and_eroute: firewall_notified: %s" - , firewall_notified ? "true" : "false")); - if (!firewall_notified) - { - /* we're in trouble -- don't do routing */ - } - else if (ro == NULL) - { - /* a new route: no deletion required, but preparation is */ - (void) do_command(c, sr, "prepare"); /* just in case; ignore failure */ - route_installed = do_command(c, sr, "route"); - } - else if (routed(sr->routing) - || routes_agree(ro, c)) - { - route_installed = TRUE; /* nothing to be done */ - } - else - { - /* Some other connection must own the route - * and the route must disagree. But since could_route - * must have allowed our stealing it, we'll do so. - * - * A feature of LINUX allows us to install the new route - * before deleting the old if the nexthops differ. - * This reduces the "window of vulnerability" when packets - * might flow in the clear. - */ - if (sameaddr(&sr->this.host_nexthop, &esr->this.host_nexthop)) - { - (void) do_command(ro, sr, "unroute"); - route_installed = do_command(c, sr, "route"); - } - else - { - route_installed = do_command(c, sr, "route"); - (void) do_command(ro, sr, "unroute"); - } - - /* record unrouting */ - if (route_installed) - { - do { - passert(!erouted(rosr->routing)); - rosr->routing = RT_UNROUTED; - - /* no need to keep old value */ - ro = route_owner(c, &rosr, NULL, NULL); - } while (ro != NULL); - } - } - - /* all done -- clean up */ - if (route_installed) - { - /* Success! */ - - if (bspp != NULL) - { - free_bare_shunt(bspp); - } - else if (ero != NULL && ero != c) - { - /* check if ero is an ancestor of c. */ - struct connection *ero2; - - for (ero2 = c; ero2 != NULL && ero2 != c; ero2 = ero2->policy_next) - ; - - if (ero2 == NULL) - { - /* By elimination, we must be eclipsing ero. Checked above. */ - if (ero->spd.routing != RT_ROUTED_ECLIPSED) + /* XXX - MCR. I previously felt that this was a bogus check */ + if (ero != NULL && ero != c && esr != sr) { - ero->spd.routing = RT_ROUTED_ECLIPSED; - eclipse_count++; + /* By elimination, we must be eclipsing ero. Check. */ + passert(ero->kind == CK_TEMPLATE && streq(ero->name, c->name)); + passert(LHAS(LELEM(RT_ROUTED_PROSPECTIVE) | LELEM(RT_ROUTED_ECLIPSED) + , esr->routing)); + passert(samesubnet(&esr->this.client, &sr->this.client) + && samesubnet(&esr->that.client, &sr->that.client)); } - } - } - - if (st == NULL) - { - passert(sr->eroute_owner == SOS_NOBODY); - sr->routing = RT_ROUTED_PROSPECTIVE; +#endif + /* remember to free bspp iff we make it out of here alive */ } else { - char cib[CONN_INST_BUF]; - sr->routing = RT_ROUTED_TUNNEL; + /* we're adding an eroute */ - DBG(DBG_CONTROL, - DBG_log("route_and_eroute: instance \"%s\"%s, setting eroute_owner {spd=%p,sr=%p} to #%ld (was #%ld) (newest_ipsec_sa=#%ld)" - , st->st_connection->name - , (fmt_conn_instance(st->st_connection, cib), cib) - , &st->st_connection->spd, sr - , st->st_serialno - , sr->eroute_owner - , st->st_connection->newest_ipsec_sa)); - sr->eroute_owner = st->st_serialno; + /* if no state provided, then install a shunt for later */ + if (st == NULL) + eroute_installed = shunt_eroute(c, sr, RT_ROUTED_PROSPECTIVE + , ERO_ADD, "add"); + else + eroute_installed = sag_eroute(st, sr, ERO_ADD, "add"); } - return TRUE; - } - else - { - /* Failure! Unwind our work. */ - if (firewall_notified && sr->eroute_owner == SOS_NOBODY) - (void) do_command(c, sr, "down"); + /* notify the firewall of a new tunnel */ if (eroute_installed) { - /* Restore original eroute, if we can. - * Since there is nothing much to be done if the restoration - * fails, ignore success or failure. - */ - if (bspp != NULL) - { - /* Restore old bare_shunt. - * I don't think that this case is very likely. - * Normally a bare shunt would have been assigned - * to a connection before we've gotten this far. + /* do we have to notify the firewall? Yes, if we are installing + * a tunnel eroute and the firewall wasn't notified + * for a previous tunnel with the same clients. Any Previous + * tunnel would have to be for our connection, so the actual + * test is simple. */ - struct bare_shunt *bs = *bspp; - - (void) raw_eroute(&bs->said.dst /* should be useless */ - , &bs->ours - , &bs->said.dst /* should be useless */ - , &bs->his - , bs->said.spi /* network order */ - , SA_INT - , SADB_X_SATYPE_INT - , 0 - , null_proto_info - , SHUNT_PATIENCE - , ERO_REPLACE, "restore"); - } - else if (ero != NULL) - { - /* restore ero's former glory */ - if (esr->eroute_owner == SOS_NOBODY) - { - /* note: normal or eclipse case */ - (void) shunt_eroute(ero, esr - , esr->routing, ERO_REPLACE, "restore"); - } - else - { - /* Try to find state that owned eroute. - * Don't do anything if it cannot be found. - * This case isn't likely since we don't run - * the updown script when replacing a SA group - * with its successor (for the same conn). - */ - struct state *ost = state_with_serialno(esr->eroute_owner); - - if (ost != NULL) - (void) sag_eroute(ost, esr, ERO_REPLACE, "restore"); - } - } - else - { - /* there was no previous eroute: delete whatever we installed */ - if (st == NULL) - (void) shunt_eroute(c, sr - , sr->routing, ERO_DELETE, "delete"); - else - (void) sag_eroute(st, sr - , ERO_DELETE, "delete"); - } + firewall_notified = st == NULL /* not a tunnel eroute */ + || sr->eroute_owner != SOS_NOBODY /* already notified */ + || do_command(c, sr, "up"); /* go ahead and notify */ } - return FALSE; - } + /* install the route */ + + DBG(DBG_CONTROL, + DBG_log("route_and_eroute: firewall_notified: %s" + , firewall_notified ? "true" : "false")); + if (!firewall_notified) + { + /* we're in trouble -- don't do routing */ + } + else if (ro == NULL) + { + /* a new route: no deletion required, but preparation is */ + (void) do_command(c, sr, "prepare"); /* just in case; ignore failure */ + route_installed = do_command(c, sr, "route"); + } + else if (routed(sr->routing) + || routes_agree(ro, c)) + { + route_installed = TRUE; /* nothing to be done */ + } + else + { + /* Some other connection must own the route + * and the route must disagree. But since could_route + * must have allowed our stealing it, we'll do so. + * + * A feature of LINUX allows us to install the new route + * before deleting the old if the nexthops differ. + * This reduces the "window of vulnerability" when packets + * might flow in the clear. + */ + if (sameaddr(&sr->this.host_nexthop, &esr->this.host_nexthop)) + { + (void) do_command(ro, sr, "unroute"); + route_installed = do_command(c, sr, "route"); + } + else + { + route_installed = do_command(c, sr, "route"); + (void) do_command(ro, sr, "unroute"); + } + + /* record unrouting */ + if (route_installed) + { + do { + passert(!erouted(rosr->routing)); + rosr->routing = RT_UNROUTED; + + /* no need to keep old value */ + ro = route_owner(c, &rosr, NULL, NULL); + } while (ro != NULL); + } + } + + /* all done -- clean up */ + if (route_installed) + { + /* Success! */ + + if (bspp != NULL) + { + free_bare_shunt(bspp); + } + else if (ero != NULL && ero != c) + { + /* check if ero is an ancestor of c. */ + struct connection *ero2; + + for (ero2 = c; ero2 != NULL && ero2 != c; ero2 = ero2->policy_next) + ; + + if (ero2 == NULL) + { + /* By elimination, we must be eclipsing ero. Checked above. */ + if (ero->spd.routing != RT_ROUTED_ECLIPSED) + { + ero->spd.routing = RT_ROUTED_ECLIPSED; + eclipse_count++; + } + } + } + + if (st == NULL) + { + passert(sr->eroute_owner == SOS_NOBODY); + sr->routing = RT_ROUTED_PROSPECTIVE; + } + else + { + char cib[CONN_INST_BUF]; + sr->routing = RT_ROUTED_TUNNEL; + + DBG(DBG_CONTROL, + DBG_log("route_and_eroute: instance \"%s\"%s, setting eroute_owner {spd=%p,sr=%p} to #%ld (was #%ld) (newest_ipsec_sa=#%ld)" + , st->st_connection->name + , (fmt_conn_instance(st->st_connection, cib), cib) + , &st->st_connection->spd, sr + , st->st_serialno + , sr->eroute_owner + , st->st_connection->newest_ipsec_sa)); + sr->eroute_owner = st->st_serialno; + } + + return TRUE; + } + else + { + /* Failure! Unwind our work. */ + if (firewall_notified && sr->eroute_owner == SOS_NOBODY) + (void) do_command(c, sr, "down"); + + if (eroute_installed) + { + /* Restore original eroute, if we can. + * Since there is nothing much to be done if the restoration + * fails, ignore success or failure. + */ + if (bspp != NULL) + { + /* Restore old bare_shunt. + * I don't think that this case is very likely. + * Normally a bare shunt would have been assigned + * to a connection before we've gotten this far. + */ + struct bare_shunt *bs = *bspp; + + (void) raw_eroute(&bs->said.dst /* should be useless */ + , &bs->ours + , &bs->said.dst /* should be useless */ + , &bs->his + , bs->said.spi /* network order */ + , SA_INT + , SADB_X_SATYPE_INT + , 0 + , null_proto_info + , SHUNT_PATIENCE + , ERO_REPLACE, "restore"); + } + else if (ero != NULL) + { + /* restore ero's former glory */ + if (esr->eroute_owner == SOS_NOBODY) + { + /* note: normal or eclipse case */ + (void) shunt_eroute(ero, esr + , esr->routing, ERO_REPLACE, "restore"); + } + else + { + /* Try to find state that owned eroute. + * Don't do anything if it cannot be found. + * This case isn't likely since we don't run + * the updown script when replacing a SA group + * with its successor (for the same conn). + */ + struct state *ost = state_with_serialno(esr->eroute_owner); + + if (ost != NULL) + (void) sag_eroute(ost, esr, ERO_REPLACE, "restore"); + } + } + else + { + /* there was no previous eroute: delete whatever we installed */ + if (st == NULL) + (void) shunt_eroute(c, sr + , sr->routing, ERO_DELETE, "delete"); + else + (void) sag_eroute(st, sr + , ERO_DELETE, "delete"); + } + } + + return FALSE; + } #else /* !KLIPS */ - return TRUE; + return TRUE; #endif /* !KLIPS */ } @@ -2694,72 +2694,72 @@ bool install_ipsec_sa(struct state *st, bool inbound_also USED_BY_KLIPS) { #ifdef KLIPS - struct spd_route *sr; + struct spd_route *sr; - DBG(DBG_CONTROL, DBG_log("install_ipsec_sa() for #%ld: %s" - , st->st_serialno - , inbound_also? - "inbound and outbound" : "outbound only")); + DBG(DBG_CONTROL, DBG_log("install_ipsec_sa() for #%ld: %s" + , st->st_serialno + , inbound_also? + "inbound and outbound" : "outbound only")); - switch (could_route(st->st_connection)) - { - case route_easy: - case route_nearconflict: - break; - - default: - return FALSE; - } - - /* (attempt to) actually set up the SA group */ - if ((inbound_also && !setup_half_ipsec_sa(st, TRUE)) - || !setup_half_ipsec_sa(st, FALSE)) - return FALSE; - - for (sr = &st->st_connection->spd; sr != NULL; sr = sr->next) - { - DBG(DBG_CONTROL, DBG_log("sr for #%ld: %s" - , st->st_serialno - , enum_name(&routing_story, sr->routing))); - - /* - * if the eroute owner is not us, then make it us. - * See test co-terminal-02, pluto-rekey-01, pluto-unit-02/oppo-twice - */ - pexpect(sr->eroute_owner == SOS_NOBODY - || sr->routing >= RT_ROUTED_TUNNEL); - - if (sr->eroute_owner != st->st_serialno - && sr->routing != RT_UNROUTED_KEYED) + switch (could_route(st->st_connection)) { - if (!route_and_eroute(st->st_connection, sr, st)) - { - delete_ipsec_sa(st, FALSE); - /* XXX go and unroute any SRs that were successfully - * routed already. - */ + case route_easy: + case route_nearconflict: + break; + + default: return FALSE; - } } - } + + /* (attempt to) actually set up the SA group */ + if ((inbound_also && !setup_half_ipsec_sa(st, TRUE)) + || !setup_half_ipsec_sa(st, FALSE)) + return FALSE; + + for (sr = &st->st_connection->spd; sr != NULL; sr = sr->next) + { + DBG(DBG_CONTROL, DBG_log("sr for #%ld: %s" + , st->st_serialno + , enum_name(&routing_story, sr->routing))); + + /* + * if the eroute owner is not us, then make it us. + * See test co-terminal-02, pluto-rekey-01, pluto-unit-02/oppo-twice + */ + pexpect(sr->eroute_owner == SOS_NOBODY + || sr->routing >= RT_ROUTED_TUNNEL); + + if (sr->eroute_owner != st->st_serialno + && sr->routing != RT_UNROUTED_KEYED) + { + if (!route_and_eroute(st->st_connection, sr, st)) + { + delete_ipsec_sa(st, FALSE); + /* XXX go and unroute any SRs that were successfully + * routed already. + */ + return FALSE; + } + } + } #else /* !KLIPS */ - DBG(DBG_CONTROL, DBG_log("install_ipsec_sa() %s" - , inbound_also? "inbound and oubound" : "outbound only")); + DBG(DBG_CONTROL, DBG_log("install_ipsec_sa() %s" + , inbound_also? "inbound and oubound" : "outbound only")); - switch (could_route(st->st_connection)) - { - case route_easy: - case route_nearconflict: - break; + switch (could_route(st->st_connection)) + { + case route_easy: + case route_nearconflict: + break; - default: - return FALSE; - } + default: + return FALSE; + } #endif /* !KLIPS */ - return TRUE; + return TRUE; } /* delete an IPSEC SA. @@ -2770,118 +2770,118 @@ void delete_ipsec_sa(struct state *st USED_BY_KLIPS, bool inbound_only USED_BY_KLIPS) { #ifdef KLIPS - if (!inbound_only) - { - /* If the state is the eroute owner, we must adjust - * the routing for the connection. - */ - struct connection *c = st->st_connection; - struct spd_route *sr; - - passert(st->st_connection); - - for (sr = &c->spd; sr; sr = sr->next) + if (!inbound_only) { - if (sr->eroute_owner == st->st_serialno - && sr->routing == RT_ROUTED_TUNNEL) - { - sr->eroute_owner = SOS_NOBODY; - - /* Routing should become RT_ROUTED_FAILURE, - * but if POLICY_FAIL_NONE, then we just go - * right back to RT_ROUTED_PROSPECTIVE as if no - * failure happened. + /* If the state is the eroute owner, we must adjust + * the routing for the connection. */ - sr->routing = (c->policy & POLICY_FAIL_MASK) == POLICY_FAIL_NONE - ? RT_ROUTED_PROSPECTIVE : RT_ROUTED_FAILURE; + struct connection *c = st->st_connection; + struct spd_route *sr; - (void) do_command(c, sr, "down"); - if ((c->policy & POLICY_DONT_REKEY) - && c->kind == CK_INSTANCE) + passert(st->st_connection); + + for (sr = &c->spd; sr; sr = sr->next) { - /* in this special case, even if the connection - * is still alive (due to an ISAKMP SA), - * we get rid of routing. - * Even though there is still an eroute, the c->routing - * setting will convince unroute_connection to delete it. - * unroute_connection would be upset if c->routing == RT_ROUTED_TUNNEL - */ - unroute_connection(c); + if (sr->eroute_owner == st->st_serialno + && sr->routing == RT_ROUTED_TUNNEL) + { + sr->eroute_owner = SOS_NOBODY; + + /* Routing should become RT_ROUTED_FAILURE, + * but if POLICY_FAIL_NONE, then we just go + * right back to RT_ROUTED_PROSPECTIVE as if no + * failure happened. + */ + sr->routing = (c->policy & POLICY_FAIL_MASK) == POLICY_FAIL_NONE + ? RT_ROUTED_PROSPECTIVE : RT_ROUTED_FAILURE; + + (void) do_command(c, sr, "down"); + if ((c->policy & POLICY_DONT_REKEY) + && c->kind == CK_INSTANCE) + { + /* in this special case, even if the connection + * is still alive (due to an ISAKMP SA), + * we get rid of routing. + * Even though there is still an eroute, the c->routing + * setting will convince unroute_connection to delete it. + * unroute_connection would be upset if c->routing == RT_ROUTED_TUNNEL + */ + unroute_connection(c); + } + else + { + (void) shunt_eroute(c, sr, sr->routing, ERO_REPLACE, "replace with shunt"); + } + } } - else - { - (void) shunt_eroute(c, sr, sr->routing, ERO_REPLACE, "replace with shunt"); - } - } + (void) teardown_half_ipsec_sa(st, FALSE); } - (void) teardown_half_ipsec_sa(st, FALSE); - } - (void) teardown_half_ipsec_sa(st, TRUE); + (void) teardown_half_ipsec_sa(st, TRUE); #else /* !KLIPS */ - DBG(DBG_CONTROL, DBG_log("if I knew how, I'd eroute() and teardown_ipsec_sa()")); + DBG(DBG_CONTROL, DBG_log("if I knew how, I'd eroute() and teardown_ipsec_sa()")); #endif /* !KLIPS */ } #ifdef KLIPS static bool update_nat_t_ipsec_esp_sa (struct state *st, bool inbound) { - struct connection *c = st->st_connection; - char text_said[SATOT_BUF]; - struct kernel_sa sa; - ip_address - src = inbound? c->spd.that.host_addr : c->spd.this.host_addr, - dst = inbound? c->spd.this.host_addr : c->spd.that.host_addr; + struct connection *c = st->st_connection; + char text_said[SATOT_BUF]; + struct kernel_sa sa; + ip_address + src = inbound? c->spd.that.host_addr : c->spd.this.host_addr, + dst = inbound? c->spd.this.host_addr : c->spd.that.host_addr; - ipsec_spi_t esp_spi = inbound? st->st_esp.our_spi : st->st_esp.attrs.spi; + ipsec_spi_t esp_spi = inbound? st->st_esp.our_spi : st->st_esp.attrs.spi; - u_int16_t - natt_sport = inbound? c->spd.that.host_port : c->spd.this.host_port, - natt_dport = inbound? c->spd.this.host_port : c->spd.that.host_port; + u_int16_t + natt_sport = inbound? c->spd.that.host_port : c->spd.this.host_port, + natt_dport = inbound? c->spd.this.host_port : c->spd.that.host_port; - set_text_said(text_said, &dst, esp_spi, SA_ESP); + set_text_said(text_said, &dst, esp_spi, SA_ESP); - memset(&sa, 0, sizeof(sa)); - sa.spi = esp_spi; - sa.src = &src; - sa.dst = &dst; - sa.text_said = text_said; - sa.authalg = alg_info_esp_aa2sadb(st->st_esp.attrs.auth); - sa.natt_sport = natt_sport; - sa.natt_dport = natt_dport; - sa.transid = st->st_esp.attrs.transid; + memset(&sa, 0, sizeof(sa)); + sa.spi = esp_spi; + sa.src = &src; + sa.dst = &dst; + sa.text_said = text_said; + sa.authalg = alg_info_esp_aa2sadb(st->st_esp.attrs.auth); + sa.natt_sport = natt_sport; + sa.natt_dport = natt_dport; + sa.transid = st->st_esp.attrs.transid; - return kernel_ops->add_sa(&sa, TRUE); + return kernel_ops->add_sa(&sa, TRUE); } #endif bool update_ipsec_sa (struct state *st USED_BY_KLIPS) { #ifdef KLIPS - if (IS_IPSEC_SA_ESTABLISHED(st->st_state)) - { - if (st->st_esp.present && ( - (!update_nat_t_ipsec_esp_sa (st, TRUE)) || - (!update_nat_t_ipsec_esp_sa (st, FALSE)))) + if (IS_IPSEC_SA_ESTABLISHED(st->st_state)) { - return FALSE; + if (st->st_esp.present && ( + (!update_nat_t_ipsec_esp_sa (st, TRUE)) || + (!update_nat_t_ipsec_esp_sa (st, FALSE)))) + { + return FALSE; + } } - } - else if (IS_ONLY_INBOUND_IPSEC_SA_ESTABLISHED(st->st_state)) - { - if (st->st_esp.present && !update_nat_t_ipsec_esp_sa (st, FALSE)) + else if (IS_ONLY_INBOUND_IPSEC_SA_ESTABLISHED(st->st_state)) { - return FALSE; + if (st->st_esp.present && !update_nat_t_ipsec_esp_sa (st, FALSE)) + { + return FALSE; + } } - } - else - { - DBG_log("assert failed at %s:%d st_state=%d", __FILE__, __LINE__, st->st_state); - return FALSE; - } - return TRUE; + else + { + DBG_log("assert failed at %s:%d st_state=%d", __FILE__, __LINE__, st->st_state); + return FALSE; + } + return TRUE; #else /* !KLIPS */ - DBG(DBG_CONTROL, DBG_log("if I knew how, I'd update_ipsec_sa()")); - return TRUE; + DBG(DBG_CONTROL, DBG_log("if I knew how, I'd update_ipsec_sa()")); + return TRUE; #endif /* !KLIPS */ } @@ -2893,103 +2893,103 @@ bool update_ipsec_sa (struct state *st USED_BY_KLIPS) bool was_eroute_idle(struct state *st, time_t idle_max, time_t *idle_time) { - static const char procname[] = "/proc/net/ipsec_spi"; - FILE *f; - char buf[1024]; - u_int bytes; - int ret = TRUE; + static const char procname[] = "/proc/net/ipsec_spi"; + FILE *f; + char buf[1024]; + u_int bytes; + int ret = TRUE; - passert(st != NULL); + passert(st != NULL); - f = fopen(procname, "r"); - if (f == NULL) - { - /* Can't open the file, perhaps were are on 26sec? */ - time_t use_time; - - if (get_sa_info(st, TRUE, &bytes, &use_time) - && use_time != UNDEFINED_TIME) + f = fopen(procname, "r"); + if (f == NULL) { - *idle_time = time(NULL) - use_time; - ret = *idle_time >= idle_max; + /* Can't open the file, perhaps were are on 26sec? */ + time_t use_time; + + if (get_sa_info(st, TRUE, &bytes, &use_time) + && use_time != UNDEFINED_TIME) + { + *idle_time = time(NULL) - use_time; + ret = *idle_time >= idle_max; + } } - } - else - { - while (f != NULL) + else { - char *line; - char text_said[SATOT_BUF]; - u_int8_t proto = 0; - ip_address dst; - ip_said said; - ipsec_spi_t spi = 0; - static const char idle[] = "idle="; - - dst = st->st_connection->spd.this.host_addr; /* inbound SA */ - if (st->st_ah.present) - { - proto = SA_AH; - spi = st->st_ah.our_spi; - } - if (st->st_esp.present) - { - proto = SA_ESP; - spi = st->st_esp.our_spi; - } - - if (proto == 0 && spi == 0) - { - ret = TRUE; - break; - } - - initsaid(&dst, spi, proto, &said); - satot(&said, 'x', text_said, SATOT_BUF); - - line = fgets(buf, sizeof(buf), f); - if (line == NULL) - { - /* Reached end of list */ - ret = TRUE; - break; - } - - if (strneq(line, text_said, strlen(text_said))) - { - /* we found a match, now try to find idle= */ - char *p = strstr(line, idle); - - if (p == NULL) + while (f != NULL) { - /* SAs which haven't been used yet don't have it */ - ret = TRUE; /* it didn't have traffic */ - break; + char *line; + char text_said[SATOT_BUF]; + u_int8_t proto = 0; + ip_address dst; + ip_said said; + ipsec_spi_t spi = 0; + static const char idle[] = "idle="; + + dst = st->st_connection->spd.this.host_addr; /* inbound SA */ + if (st->st_ah.present) + { + proto = SA_AH; + spi = st->st_ah.our_spi; + } + if (st->st_esp.present) + { + proto = SA_ESP; + spi = st->st_esp.our_spi; + } + + if (proto == 0 && spi == 0) + { + ret = TRUE; + break; + } + + initsaid(&dst, spi, proto, &said); + satot(&said, 'x', text_said, SATOT_BUF); + + line = fgets(buf, sizeof(buf), f); + if (line == NULL) + { + /* Reached end of list */ + ret = TRUE; + break; + } + + if (strneq(line, text_said, strlen(text_said))) + { + /* we found a match, now try to find idle= */ + char *p = strstr(line, idle); + + if (p == NULL) + { + /* SAs which haven't been used yet don't have it */ + ret = TRUE; /* it didn't have traffic */ + break; + } + p += sizeof(idle)-1; + if (*p == '\0') + { + ret = TRUE; /* be paranoid */ + break; + } + if (sscanf(p, "%d", (int *) idle_time) <= 0) + { + ret = TRUE; + break; + } + if (*idle_time >= idle_max) + { + ret = TRUE; + break; + } + else + { + ret = FALSE; + break; + } + } } - p += sizeof(idle)-1; - if (*p == '\0') - { - ret = TRUE; /* be paranoid */ - break; - } - if (sscanf(p, "%d", (int *) idle_time) <= 0) - { - ret = TRUE; - break; - } - if (*idle_time >= idle_max) - { - ret = TRUE; - break; - } - else - { - ret = FALSE; - break; - } - } + fclose(f); } - fclose(f); - } - return ret; + return ret; } diff --git a/src/pluto/kernel.h b/src/pluto/kernel.h index c2333fac8..01a455941 100644 --- a/src/pluto/kernel.h +++ b/src/pluto/kernel.h @@ -16,7 +16,7 @@ #include "connections.h" -extern bool no_klips; /* don't actually use KLIPS */ +extern bool no_klips; /* don't actually use KLIPS */ extern bool can_do_IPcomp; /* can system actually perform IPCOMP? */ #ifdef KLIPS @@ -28,96 +28,96 @@ extern bool can_do_IPcomp; /* can system actually perform IPCOMP? */ * limited to appropriate source and destination addresses. */ -#define ERO_MASK 0xFF -#define ERO_FLAG_SHIFT 8 +#define ERO_MASK 0xFF +#define ERO_FLAG_SHIFT 8 -#define ERO_DELETE SADB_X_DELFLOW -#define ERO_ADD SADB_X_ADDFLOW -#define ERO_REPLACE (SADB_X_ADDFLOW | (SADB_X_SAFLAGS_REPLACEFLOW << ERO_FLAG_SHIFT)) -#define ERO_ADD_INBOUND (SADB_X_ADDFLOW | (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT)) -#define ERO_DEL_INBOUND (SADB_X_DELFLOW | (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT)) +#define ERO_DELETE SADB_X_DELFLOW +#define ERO_ADD SADB_X_ADDFLOW +#define ERO_REPLACE (SADB_X_ADDFLOW | (SADB_X_SAFLAGS_REPLACEFLOW << ERO_FLAG_SHIFT)) +#define ERO_ADD_INBOUND (SADB_X_ADDFLOW | (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT)) +#define ERO_DEL_INBOUND (SADB_X_DELFLOW | (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT)) struct pfkey_proto_info { - int proto; - int encapsulation; - unsigned reqid; + int proto; + int encapsulation; + unsigned reqid; }; struct sadb_msg; struct kernel_sa { - const ip_address *src; - const ip_address *dst; + const ip_address *src; + const ip_address *dst; - const ip_subnet *src_client; - const ip_subnet *dst_client; + const ip_subnet *src_client; + const ip_subnet *dst_client; - ipsec_spi_t spi; - unsigned proto; - unsigned satype; - unsigned transport_proto; - unsigned replay_window; - unsigned reqid; + ipsec_spi_t spi; + unsigned proto; + unsigned satype; + unsigned transport_proto; + unsigned replay_window; + unsigned reqid; - unsigned authalg; - unsigned authkeylen; - char *authkey; + unsigned authalg; + unsigned authkeylen; + char *authkey; - unsigned encalg; - unsigned enckeylen; - char *enckey; + unsigned encalg; + unsigned enckeylen; + char *enckey; - unsigned compalg; + unsigned compalg; - int encapsulation; + int encapsulation; - u_int16_t natt_sport, natt_dport; - u_int8_t transid, natt_type; - ip_address *natt_oa; + u_int16_t natt_sport, natt_dport; + u_int8_t transid, natt_type; + ip_address *natt_oa; - const char *text_said; + const char *text_said; }; struct kernel_ops { - enum { - KERNEL_TYPE_NONE, - KERNEL_TYPE_KLIPS, - KERNEL_TYPE_LINUX, - } type; - bool inbound_eroute; - bool policy_lifetime; - int *async_fdp; + enum { + KERNEL_TYPE_NONE, + KERNEL_TYPE_KLIPS, + KERNEL_TYPE_LINUX, + } type; + bool inbound_eroute; + bool policy_lifetime; + int *async_fdp; - void (*init)(void); - void (*pfkey_register)(void); - void (*pfkey_register_response)(const struct sadb_msg *msg); - void (*process_queue)(void); - void (*process_msg)(void); - bool (*raw_eroute)(const ip_address *this_host, - const ip_subnet *this_client, - const ip_address *that_host, - const ip_subnet *that_client, - ipsec_spi_t spi, - unsigned int satype, - unsigned int transport_proto, - const struct pfkey_proto_info *proto_info, - time_t use_lifetime, - unsigned int op, - const char *text_said); - bool (*get_policy)(const struct kernel_sa *sa, bool inbound, - time_t *use_time); - bool (*add_sa)(const struct kernel_sa *sa, bool replace); - bool (*grp_sa)(const struct kernel_sa *sa_outer, - const struct kernel_sa *sa_inner); - bool (*del_sa)(const struct kernel_sa *sa); - bool (*get_sa)(const struct kernel_sa *sa, u_int *bytes); - ipsec_spi_t (*get_spi)(const ip_address *src, - const ip_address *dst, - int proto, - bool tunnel_mode, - unsigned reqid, - ipsec_spi_t min, - ipsec_spi_t max, - const char *text_said); + void (*init)(void); + void (*pfkey_register)(void); + void (*pfkey_register_response)(const struct sadb_msg *msg); + void (*process_queue)(void); + void (*process_msg)(void); + bool (*raw_eroute)(const ip_address *this_host, + const ip_subnet *this_client, + const ip_address *that_host, + const ip_subnet *that_client, + ipsec_spi_t spi, + unsigned int satype, + unsigned int transport_proto, + const struct pfkey_proto_info *proto_info, + time_t use_lifetime, + unsigned int op, + const char *text_said); + bool (*get_policy)(const struct kernel_sa *sa, bool inbound, + time_t *use_time); + bool (*add_sa)(const struct kernel_sa *sa, bool replace); + bool (*grp_sa)(const struct kernel_sa *sa_outer, + const struct kernel_sa *sa_inner); + bool (*del_sa)(const struct kernel_sa *sa); + bool (*get_sa)(const struct kernel_sa *sa, u_int *bytes); + ipsec_spi_t (*get_spi)(const ip_address *src, + const ip_address *dst, + int proto, + bool tunnel_mode, + unsigned reqid, + ipsec_spi_t min, + ipsec_spi_t max, + const char *text_said); }; @@ -126,13 +126,13 @@ extern const struct kernel_ops *kernel_ops; /* information from /proc/net/ipsec_eroute */ struct eroute_info { - unsigned long count; - ip_subnet ours; - ip_subnet his; - ip_address dst; - ip_said said; - int transport_proto; - struct eroute_info *next; + unsigned long count; + ip_subnet ours; + ip_subnet his; + ip_address dst; + ip_said said; + int transport_proto; + struct eroute_info *next; }; extern struct eroute_info *orphaned_holds; @@ -144,13 +144,13 @@ extern void show_shunt_status(void); * Is there a PF_KEY equivalent? */ #ifndef EM_MAXRELSPIS -# define EM_MAXRELSPIS 4 /* AH ESP IPCOMP IPIP */ +# define EM_MAXRELSPIS 4 /* AH ESP IPCOMP IPIP */ #endif extern void record_and_initiate_opportunistic(const ip_subnet * - , const ip_subnet * - , int transport_proto - , const char *why); + , const ip_subnet * + , int transport_proto + , const char *why); extern void init_kernel(void); @@ -160,39 +160,39 @@ extern bool trap_connection(struct connection *c); extern void unroute_connection(struct connection *c); extern bool has_bare_hold(const ip_address *src, const ip_address *dst - , int transport_proto); + , int transport_proto); extern bool replace_bare_shunt(const ip_address *src, const ip_address *dst - , policy_prio_t policy_prio - , ipsec_spi_t shunt_spi /* in host order! */ - , bool repl - , unsigned int transport_proto - , const char *why); + , policy_prio_t policy_prio + , ipsec_spi_t shunt_spi /* in host order! */ + , bool repl + , unsigned int transport_proto + , const char *why); extern bool assign_hold(struct connection *c - , struct spd_route *sr - , int transport_proto - , const ip_address *src, const ip_address *dst); + , struct spd_route *sr + , int transport_proto + , const ip_address *src, const ip_address *dst); extern ipsec_spi_t shunt_policy_spi(struct connection *c, bool prospective); -struct state; /* forward declaration of tag */ +struct state; /* forward declaration of tag */ extern ipsec_spi_t get_ipsec_spi(ipsec_spi_t avoid - , int proto - , struct spd_route *sr - , bool tunnel_mode); + , int proto + , struct spd_route *sr + , bool tunnel_mode); extern ipsec_spi_t get_my_cpi(struct spd_route *sr, bool tunnel_mode); extern bool install_inbound_ipsec_sa(struct state *st); extern bool install_ipsec_sa(struct state *st, bool inbound_also); extern void delete_ipsec_sa(struct state *st, bool inbound_only); extern bool route_and_eroute(struct connection *c - , struct spd_route *sr - , struct state *st); + , struct spd_route *sr + , struct state *st); extern bool was_eroute_idle(struct state *st, time_t idle_max - , time_t *idle_time); + , time_t *idle_time); extern bool get_sa_info(struct state *st, bool inbound, u_int *bytes - , time_t *use_time); + , time_t *use_time); extern bool update_ipsec_sa(struct state *st); diff --git a/src/pluto/kernel_alg.c b/src/pluto/kernel_alg.c index 885890f39..0e146a2e2 100644 --- a/src/pluto/kernel_alg.c +++ b/src/pluto/kernel_alg.c @@ -50,153 +50,153 @@ static int esp_aalg_num = 0; #define ESP_EALG_PRESENT(algo) (((algo)<=SADB_EALG_MAX)&&(esp_ealg[(algo)].sadb_alg_id==(algo))) #define ESP_EALG_FOR_EACH_UPDOWN(algo) \ - for (algo=SADB_EALG_MAX; algo >0 ; algo--) \ - if (ESP_EALG_PRESENT(algo)) + for (algo=SADB_EALG_MAX; algo >0 ; algo--) \ + if (ESP_EALG_PRESENT(algo)) #define ESP_AALG_PRESENT(algo) ((algo<=SADB_AALG_MAX)&&(esp_aalg[(algo)].sadb_alg_id==(algo))) #define ESP_AALG_FOR_EACH_UPDOWN(algo) \ - for (algo=SADB_AALG_MAX; algo >0 ; algo--) \ - if (ESP_AALG_PRESENT(algo)) + for (algo=SADB_AALG_MAX; algo >0 ; algo--) \ + if (ESP_AALG_PRESENT(algo)) static struct sadb_alg* sadb_alg_ptr (int satype, int exttype, int alg_id, int rw) { - struct sadb_alg *alg_p = NULL; + struct sadb_alg *alg_p = NULL; - switch (exttype) - { - case SADB_EXT_SUPPORTED_AUTH: - if (alg_id > SADB_AALG_MAX) - return NULL; - break; - case SADB_EXT_SUPPORTED_ENCRYPT: - if (alg_id > SADB_EALG_MAX) - return NULL; - break; - default: - return NULL; - } - - switch (satype) - { - case SADB_SATYPE_ESP: - alg_p = (exttype == SADB_EXT_SUPPORTED_ENCRYPT)? - &esp_ealg[alg_id] : &esp_aalg[alg_id]; - /* get for write: increment elem count */ - if (rw) + switch (exttype) { - (exttype == SADB_EXT_SUPPORTED_ENCRYPT)? - esp_ealg_num++ : esp_aalg_num++; + case SADB_EXT_SUPPORTED_AUTH: + if (alg_id > SADB_AALG_MAX) + return NULL; + break; + case SADB_EXT_SUPPORTED_ENCRYPT: + if (alg_id > SADB_EALG_MAX) + return NULL; + break; + default: + return NULL; } - break; - case SADB_SATYPE_AH: - default: - return NULL; - } - - return alg_p; + + switch (satype) + { + case SADB_SATYPE_ESP: + alg_p = (exttype == SADB_EXT_SUPPORTED_ENCRYPT)? + &esp_ealg[alg_id] : &esp_aalg[alg_id]; + /* get for write: increment elem count */ + if (rw) + { + (exttype == SADB_EXT_SUPPORTED_ENCRYPT)? + esp_ealg_num++ : esp_aalg_num++; + } + break; + case SADB_SATYPE_AH: + default: + return NULL; + } + + return alg_p; } const struct sadb_alg * kernel_alg_sadb_alg_get(int satype, int exttype, int alg_id) { - return sadb_alg_ptr(satype, exttype, alg_id, 0); + return sadb_alg_ptr(satype, exttype, alg_id, 0); } /* - * Forget previous registration + * Forget previous registration */ static void kernel_alg_init(void) { - DBG(DBG_KLIPS, - DBG_log("alg_init(): memset(%p, 0, %d) memset(%p, 0, %d)", - &esp_aalg, (int)sizeof (esp_aalg), - &esp_ealg, (int)sizeof (esp_ealg)) - ) - memset (&esp_aalg, 0, sizeof (esp_aalg)); - memset (&esp_ealg, 0, sizeof (esp_ealg)); - esp_ealg_num=esp_aalg_num = 0; + DBG(DBG_KLIPS, + DBG_log("alg_init(): memset(%p, 0, %d) memset(%p, 0, %d)", + &esp_aalg, (int)sizeof (esp_aalg), + &esp_ealg, (int)sizeof (esp_ealg)) + ) + memset (&esp_aalg, 0, sizeof (esp_aalg)); + memset (&esp_ealg, 0, sizeof (esp_ealg)); + esp_ealg_num=esp_aalg_num = 0; } static int kernel_alg_add(int satype, int exttype, const struct sadb_alg *sadb_alg) { - struct sadb_alg *alg_p = NULL; - int alg_id = sadb_alg->sadb_alg_id; + struct sadb_alg *alg_p = NULL; + int alg_id = sadb_alg->sadb_alg_id; - DBG(DBG_KLIPS, - DBG_log("kernel_alg_add(): satype=%d, exttype=%d, alg_id=%d", - satype, exttype, sadb_alg->sadb_alg_id) - ) - if (!(alg_p = sadb_alg_ptr(satype, exttype, alg_id, 1))) - return -1; - - /* This logic "mimics" KLIPS: first algo implementation will be used */ - if (alg_p->sadb_alg_id) - { DBG(DBG_KLIPS, - DBG_log("kernel_alg_add(): discarding already setup " - "satype=%d, exttype=%d, alg_id=%d", - satype, exttype, sadb_alg->sadb_alg_id) + DBG_log("kernel_alg_add(): satype=%d, exttype=%d, alg_id=%d", + satype, exttype, sadb_alg->sadb_alg_id) ) - return 0; - } - *alg_p = *sadb_alg; - return 1; + if (!(alg_p = sadb_alg_ptr(satype, exttype, alg_id, 1))) + return -1; + + /* This logic "mimics" KLIPS: first algo implementation will be used */ + if (alg_p->sadb_alg_id) + { + DBG(DBG_KLIPS, + DBG_log("kernel_alg_add(): discarding already setup " + "satype=%d, exttype=%d, alg_id=%d", + satype, exttype, sadb_alg->sadb_alg_id) + ) + return 0; + } + *alg_p = *sadb_alg; + return 1; } bool kernel_alg_esp_enc_ok(u_int alg_id, u_int key_len, - struct alg_info_esp *alg_info __attribute__((unused))) + struct alg_info_esp *alg_info __attribute__((unused))) { - struct sadb_alg *alg_p = NULL; + struct sadb_alg *alg_p = NULL; - /* - * test #1: encrypt algo must be present - */ - int ret = ESP_EALG_PRESENT(alg_id); - if (!ret) goto out; + /* + * test #1: encrypt algo must be present + */ + int ret = ESP_EALG_PRESENT(alg_id); + if (!ret) goto out; - alg_p = &esp_ealg[alg_id]; - - /* - * test #2: if key_len specified, it must be in range - */ - if (key_len - && (key_len < alg_p->sadb_alg_minbits || key_len > alg_p->sadb_alg_maxbits)) - { - plog("kernel_alg_db_add() key_len not in range: alg_id=%d, " - "key_len=%d, alg_minbits=%d, alg_maxbits=%d" - , alg_id, key_len - , alg_p->sadb_alg_minbits - , alg_p->sadb_alg_maxbits); - ret = FALSE; - } + alg_p = &esp_ealg[alg_id]; + + /* + * test #2: if key_len specified, it must be in range + */ + if (key_len + && (key_len < alg_p->sadb_alg_minbits || key_len > alg_p->sadb_alg_maxbits)) + { + plog("kernel_alg_db_add() key_len not in range: alg_id=%d, " + "key_len=%d, alg_minbits=%d, alg_maxbits=%d" + , alg_id, key_len + , alg_p->sadb_alg_minbits + , alg_p->sadb_alg_maxbits); + ret = FALSE; + } out: - if (ret) - { - DBG(DBG_KLIPS, - DBG_log("kernel_alg_esp_enc_ok(%d,%d): " - "alg_id=%d, " - "alg_ivlen=%d, alg_minbits=%d, alg_maxbits=%d, " - "res=%d, ret=%d" - , alg_id, key_len - , alg_p->sadb_alg_id - , alg_p->sadb_alg_ivlen - , alg_p->sadb_alg_minbits - , alg_p->sadb_alg_maxbits - , alg_p->sadb_alg_reserved - , ret); - ) - } - else - { - DBG(DBG_KLIPS, - DBG_log("kernel_alg_esp_enc_ok(%d,%d): NO", alg_id, key_len); - ) - } - return ret; + if (ret) + { + DBG(DBG_KLIPS, + DBG_log("kernel_alg_esp_enc_ok(%d,%d): " + "alg_id=%d, " + "alg_ivlen=%d, alg_minbits=%d, alg_maxbits=%d, " + "res=%d, ret=%d" + , alg_id, key_len + , alg_p->sadb_alg_id + , alg_p->sadb_alg_ivlen + , alg_p->sadb_alg_minbits + , alg_p->sadb_alg_maxbits + , alg_p->sadb_alg_reserved + , ret); + ) + } + else + { + DBG(DBG_KLIPS, + DBG_log("kernel_alg_esp_enc_ok(%d,%d): NO", alg_id, key_len); + ) + } + return ret; } /* @@ -206,558 +206,558 @@ out: bool kernel_alg_esp_ok_final(u_int ealg, u_int key_len, u_int aalg, struct alg_info_esp *alg_info) { - int ealg_insecure; + int ealg_insecure; - /* - * key_len passed comes from esp_attrs read from peer - * For many older algoritms (eg 3DES) this key_len is fixed - * and get passed as 0. - * ... then get default key_len - */ - if (key_len == 0) - key_len = kernel_alg_esp_enc_keylen(ealg) * BITS_PER_BYTE; + /* + * key_len passed comes from esp_attrs read from peer + * For many older algoritms (eg 3DES) this key_len is fixed + * and get passed as 0. + * ... then get default key_len + */ + if (key_len == 0) + key_len = kernel_alg_esp_enc_keylen(ealg) * BITS_PER_BYTE; - /* - * simple test to toss low key_len, will accept it only - * if specified in "esp" string - */ - ealg_insecure = (key_len < 128) ; + /* + * simple test to toss low key_len, will accept it only + * if specified in "esp" string + */ + ealg_insecure = (key_len < 128) ; - if (ealg_insecure - || (alg_info && alg_info->alg_info_flags & ALG_INFO_F_STRICT)) - { - int i; - struct esp_info *esp_info; - - if (alg_info) + if (ealg_insecure + || (alg_info && alg_info->alg_info_flags & ALG_INFO_F_STRICT)) { - ALG_INFO_ESP_FOREACH(alg_info, esp_info, i) - { - if (esp_info->esp_ealg_id == ealg - && (esp_info->esp_ealg_keylen == 0 || key_len == 0 - || esp_info->esp_ealg_keylen == key_len) - && esp_info->esp_aalg_id == aalg) + int i; + struct esp_info *esp_info; + + if (alg_info) { - if (ealg_insecure) - { - loglog(RC_LOG_SERIOUS - , "You should NOT use insecure ESP algorithms [%s (%d)]!" - , enum_name(&esp_transformid_names, ealg), key_len); - } - return TRUE; + ALG_INFO_ESP_FOREACH(alg_info, esp_info, i) + { + if (esp_info->esp_ealg_id == ealg + && (esp_info->esp_ealg_keylen == 0 || key_len == 0 + || esp_info->esp_ealg_keylen == key_len) + && esp_info->esp_aalg_id == aalg) + { + if (ealg_insecure) + { + loglog(RC_LOG_SERIOUS + , "You should NOT use insecure ESP algorithms [%s (%d)]!" + , enum_name(&esp_transformid_names, ealg), key_len); + } + return TRUE; + } + } } - } + plog("IPSec Transform [%s (%d), %s] refused due to %s", + enum_name(&esp_transformid_names, ealg), key_len, + enum_name(&auth_alg_names, aalg), + ealg_insecure ? "insecure key_len and enc. alg. not listed in \"esp\" string" : "strict flag"); + return FALSE; } - plog("IPSec Transform [%s (%d), %s] refused due to %s", - enum_name(&esp_transformid_names, ealg), key_len, - enum_name(&auth_alg_names, aalg), - ealg_insecure ? "insecure key_len and enc. alg. not listed in \"esp\" string" : "strict flag"); - return FALSE; - } - return TRUE; + return TRUE; } #endif /* NO_PLUTO */ -/* - * Load kernel_alg arrays from /proc - * used in manual mode from klips/utils/spi.c +/* + * Load kernel_alg arrays from /proc + * used in manual mode from klips/utils/spi.c */ int kernel_alg_proc_read(void) { - int satype; - int supp_exttype; - int alg_id, ivlen, minbits, maxbits; - struct sadb_alg sadb_alg; - int ret; - char buf[128]; + int satype; + int supp_exttype; + int alg_id, ivlen, minbits, maxbits; + struct sadb_alg sadb_alg; + int ret; + char buf[128]; - FILE *fp=fopen("/proc/net/pf_key_supported", "r"); + FILE *fp=fopen("/proc/net/pf_key_supported", "r"); - if (!fp) - return -1; + if (!fp) + return -1; - kernel_alg_init(); + kernel_alg_init(); - while (fgets(buf, sizeof(buf), fp)) - { - if (buf[0] != ' ') /* skip titles */ - continue; - - sscanf(buf, "%d %d %d %d %d %d" - ,&satype, &supp_exttype - , &alg_id, &ivlen - , &minbits, &maxbits); - - switch (satype) + while (fgets(buf, sizeof(buf), fp)) { - case SADB_SATYPE_ESP: - switch(supp_exttype) - { - case SADB_EXT_SUPPORTED_AUTH: - case SADB_EXT_SUPPORTED_ENCRYPT: - sadb_alg.sadb_alg_id = alg_id; - sadb_alg.sadb_alg_ivlen = ivlen; - sadb_alg.sadb_alg_minbits = minbits; - sadb_alg.sadb_alg_maxbits = maxbits; - ret = kernel_alg_add(satype, supp_exttype, &sadb_alg); - DBG(DBG_CRYPT, - DBG_log("kernel_alg_proc_read() alg_id=%d, " - "alg_ivlen=%d, alg_minbits=%d, alg_maxbits=%d, " - "ret=%d" - , sadb_alg.sadb_alg_id - , sadb_alg.sadb_alg_ivlen - , sadb_alg.sadb_alg_minbits - , sadb_alg.sadb_alg_maxbits - , ret) - ) - } - default: - continue; + if (buf[0] != ' ') /* skip titles */ + continue; + + sscanf(buf, "%d %d %d %d %d %d" + ,&satype, &supp_exttype + , &alg_id, &ivlen + , &minbits, &maxbits); + + switch (satype) + { + case SADB_SATYPE_ESP: + switch(supp_exttype) + { + case SADB_EXT_SUPPORTED_AUTH: + case SADB_EXT_SUPPORTED_ENCRYPT: + sadb_alg.sadb_alg_id = alg_id; + sadb_alg.sadb_alg_ivlen = ivlen; + sadb_alg.sadb_alg_minbits = minbits; + sadb_alg.sadb_alg_maxbits = maxbits; + ret = kernel_alg_add(satype, supp_exttype, &sadb_alg); + DBG(DBG_CRYPT, + DBG_log("kernel_alg_proc_read() alg_id=%d, " + "alg_ivlen=%d, alg_minbits=%d, alg_maxbits=%d, " + "ret=%d" + , sadb_alg.sadb_alg_id + , sadb_alg.sadb_alg_ivlen + , sadb_alg.sadb_alg_minbits + , sadb_alg.sadb_alg_maxbits + , ret) + ) + } + default: + continue; + } } - } - fclose(fp); - return 0; + fclose(fp); + return 0; } -/* - * Load kernel_alg arrays pluto's SADB_REGISTER - * user by pluto/kernel.c +/* + * Load kernel_alg arrays pluto's SADB_REGISTER + * user by pluto/kernel.c */ void kernel_alg_register_pfkey(const struct sadb_msg *msg_buf, int buflen) { - /* Trick: one 'type-mangle-able' pointer to ease offset/assign */ - union { - const struct sadb_msg *msg; - const struct sadb_supported *supported; - const struct sadb_ext *ext; - const struct sadb_alg *alg; - const char *ch; - } sadb; + /* Trick: one 'type-mangle-able' pointer to ease offset/assign */ + union { + const struct sadb_msg *msg; + const struct sadb_supported *supported; + const struct sadb_ext *ext; + const struct sadb_alg *alg; + const char *ch; + } sadb; - int satype; - int msglen; - int i = 0; + int satype; + int msglen; + int i = 0; - /* Initialize alg arrays */ - kernel_alg_init(); - satype = msg_buf->sadb_msg_satype; - sadb.msg = msg_buf; - msglen = sadb.msg->sadb_msg_len*IPSEC_PFKEYv2_ALIGN; - msglen -= sizeof(struct sadb_msg); - buflen -= sizeof(struct sadb_msg); - passert(buflen > 0); + /* Initialize alg arrays */ + kernel_alg_init(); + satype = msg_buf->sadb_msg_satype; + sadb.msg = msg_buf; + msglen = sadb.msg->sadb_msg_len*IPSEC_PFKEYv2_ALIGN; + msglen -= sizeof(struct sadb_msg); + buflen -= sizeof(struct sadb_msg); + passert(buflen > 0); - sadb.msg++; + sadb.msg++; - while(msglen) - { - int supp_exttype = sadb.supported->sadb_supported_exttype; - int supp_len = sadb.supported->sadb_supported_len*IPSEC_PFKEYv2_ALIGN; - - DBG(DBG_KLIPS, - DBG_log("kernel_alg_register_pfkey(): SADB_SATYPE_%s: " - "sadb_msg_len=%d sadb_supported_len=%d" - , satype==SADB_SATYPE_ESP? "ESP" : "AH" - , msg_buf->sadb_msg_len, supp_len) - ) - sadb.supported++; - msglen -= supp_len; - buflen -= supp_len; - passert(buflen >= 0); - - for (supp_len -= sizeof(struct sadb_supported); - supp_len; - supp_len -= sizeof(struct sadb_alg), sadb.alg++,i++) + while(msglen) { - int ret = kernel_alg_add(satype, supp_exttype, sadb.alg); + int supp_exttype = sadb.supported->sadb_supported_exttype; + int supp_len = sadb.supported->sadb_supported_len*IPSEC_PFKEYv2_ALIGN; - DBG(DBG_KLIPS, - DBG_log("kernel_alg_register_pfkey(): SADB_SATYPE_%s: " - "alg[%d], exttype=%d, satype=%d, alg_id=%d, " - "alg_ivlen=%d, alg_minbits=%d, alg_maxbits=%d, " - "res=%d, ret=%d" - , satype==SADB_SATYPE_ESP? "ESP" : "AH" - , i - , supp_exttype - , satype - , sadb.alg->sadb_alg_id - , sadb.alg->sadb_alg_ivlen - , sadb.alg->sadb_alg_minbits - , sadb.alg->sadb_alg_maxbits - , sadb.alg->sadb_alg_reserved - , ret) - ) + DBG(DBG_KLIPS, + DBG_log("kernel_alg_register_pfkey(): SADB_SATYPE_%s: " + "sadb_msg_len=%d sadb_supported_len=%d" + , satype==SADB_SATYPE_ESP? "ESP" : "AH" + , msg_buf->sadb_msg_len, supp_len) + ) + sadb.supported++; + msglen -= supp_len; + buflen -= supp_len; + passert(buflen >= 0); + + for (supp_len -= sizeof(struct sadb_supported); + supp_len; + supp_len -= sizeof(struct sadb_alg), sadb.alg++,i++) + { + int ret = kernel_alg_add(satype, supp_exttype, sadb.alg); + + DBG(DBG_KLIPS, + DBG_log("kernel_alg_register_pfkey(): SADB_SATYPE_%s: " + "alg[%d], exttype=%d, satype=%d, alg_id=%d, " + "alg_ivlen=%d, alg_minbits=%d, alg_maxbits=%d, " + "res=%d, ret=%d" + , satype==SADB_SATYPE_ESP? "ESP" : "AH" + , i + , supp_exttype + , satype + , sadb.alg->sadb_alg_id + , sadb.alg->sadb_alg_ivlen + , sadb.alg->sadb_alg_minbits + , sadb.alg->sadb_alg_maxbits + , sadb.alg->sadb_alg_reserved + , ret) + ) + } } - } } u_int kernel_alg_esp_enc_keylen(u_int alg_id) { - u_int keylen = 0; + u_int keylen = 0; - if (!ESP_EALG_PRESENT(alg_id)) - goto none; + if (!ESP_EALG_PRESENT(alg_id)) + goto none; - keylen = esp_ealg[alg_id].sadb_alg_maxbits/BITS_PER_BYTE; + keylen = esp_ealg[alg_id].sadb_alg_maxbits/BITS_PER_BYTE; - switch (alg_id) - { - /* - * this is veryUgly[TM] - * Peer should have sent KEY_LENGTH attribute for ESP_AES - * but if not do force it to 128 instead of using sadb_alg_maxbits - * from kernel. - */ - case ESP_AES: - keylen = 128/BITS_PER_BYTE; - break; - } + switch (alg_id) + { + /* + * this is veryUgly[TM] + * Peer should have sent KEY_LENGTH attribute for ESP_AES + * but if not do force it to 128 instead of using sadb_alg_maxbits + * from kernel. + */ + case ESP_AES: + keylen = 128/BITS_PER_BYTE; + break; + } -none: - DBG(DBG_KLIPS, - DBG_log("kernel_alg_esp_enc_keylen():" - "alg_id=%d, keylen=%d", - alg_id, keylen) - ) - return keylen; +none: + DBG(DBG_KLIPS, + DBG_log("kernel_alg_esp_enc_keylen():" + "alg_id=%d, keylen=%d", + alg_id, keylen) + ) + return keylen; } struct sadb_alg * kernel_alg_esp_sadb_alg(u_int alg_id) { - struct sadb_alg *sadb_alg = (ESP_EALG_PRESENT(alg_id)) - ? &esp_ealg[alg_id] : NULL; + struct sadb_alg *sadb_alg = (ESP_EALG_PRESENT(alg_id)) + ? &esp_ealg[alg_id] : NULL; - DBG(DBG_KLIPS, - DBG_log("kernel_alg_esp_sadb_alg(): alg_id=%d, sadb_alg=%p" - , alg_id, sadb_alg) - ) - return sadb_alg; + DBG(DBG_KLIPS, + DBG_log("kernel_alg_esp_sadb_alg(): alg_id=%d, sadb_alg=%p" + , alg_id, sadb_alg) + ) + return sadb_alg; } #ifndef NO_PLUTO void kernel_alg_list(void) { - u_int sadb_id; + u_int sadb_id; - whack_log(RC_COMMENT, " "); - whack_log(RC_COMMENT, "List of registered ESP Encryption Algorithms:"); - whack_log(RC_COMMENT, " "); + whack_log(RC_COMMENT, " "); + whack_log(RC_COMMENT, "List of registered ESP Encryption Algorithms:"); + whack_log(RC_COMMENT, " "); - for (sadb_id = 1; sadb_id <= SADB_EALG_MAX; sadb_id++) - { - if (ESP_EALG_PRESENT(sadb_id)) + for (sadb_id = 1; sadb_id <= SADB_EALG_MAX; sadb_id++) { - struct sadb_alg *alg_p = &esp_ealg[sadb_id]; + if (ESP_EALG_PRESENT(sadb_id)) + { + struct sadb_alg *alg_p = &esp_ealg[sadb_id]; - whack_log(RC_COMMENT, "#%-5d %s, blocksize: %d, keylen: %d-%d" - , sadb_id - , enum_name(&esp_transformid_names, sadb_id) - , alg_p->sadb_alg_ivlen - , alg_p->sadb_alg_minbits - , alg_p->sadb_alg_maxbits - ); + whack_log(RC_COMMENT, "#%-5d %s, blocksize: %d, keylen: %d-%d" + , sadb_id + , enum_name(&esp_transformid_names, sadb_id) + , alg_p->sadb_alg_ivlen + , alg_p->sadb_alg_minbits + , alg_p->sadb_alg_maxbits + ); + } } - } - - whack_log(RC_COMMENT, " "); - whack_log(RC_COMMENT, "List of registered ESP Authentication Algorithms:"); - whack_log(RC_COMMENT, " "); + + whack_log(RC_COMMENT, " "); + whack_log(RC_COMMENT, "List of registered ESP Authentication Algorithms:"); + whack_log(RC_COMMENT, " "); - for (sadb_id = 1; sadb_id <= SADB_AALG_MAX; sadb_id++) - { - if (ESP_AALG_PRESENT(sadb_id)) + for (sadb_id = 1; sadb_id <= SADB_AALG_MAX; sadb_id++) { - u_int aaid = alg_info_esp_sadb2aa(sadb_id); - struct sadb_alg *alg_p = &esp_aalg[sadb_id]; + if (ESP_AALG_PRESENT(sadb_id)) + { + u_int aaid = alg_info_esp_sadb2aa(sadb_id); + struct sadb_alg *alg_p = &esp_aalg[sadb_id]; - whack_log(RC_COMMENT, "#%-5d %s, keylen: %d-%d" - , aaid - , enum_name(&auth_alg_names, aaid) - , alg_p->sadb_alg_minbits - , alg_p->sadb_alg_maxbits - ); + whack_log(RC_COMMENT, "#%-5d %s, keylen: %d-%d" + , aaid + , enum_name(&auth_alg_names, aaid) + , alg_p->sadb_alg_minbits + , alg_p->sadb_alg_maxbits + ); + } } - } } void kernel_alg_show_connection(struct connection *c, const char *instance) { - char buf[256]; - struct state *st; + char buf[256]; + struct state *st; - if (c->alg_info_esp) - { - alg_info_snprint(buf, sizeof(buf), (struct alg_info *)c->alg_info_esp); - whack_log(RC_COMMENT - , "\"%s\"%s: ESP algorithms wanted: %s" - , c->name - , instance - , buf); - } - if (c->alg_info_esp) - { - alg_info_snprint_esp(buf, sizeof(buf), c->alg_info_esp); - whack_log(RC_COMMENT - , "\"%s\"%s: ESP algorithms loaded: %s" - , c->name - , instance - , buf); - } - st = state_with_serialno(c->newest_ipsec_sa); - if (st && st->st_esp.present) - whack_log(RC_COMMENT - , "\"%s\"%s: ESP algorithm newest: %s_%d-%s; pfsgroup=%s" - , c->name - , instance - , enum_show(&esp_transformid_names, st->st_esp.attrs.transid) - +4 /* strlen("ESP_") */ - , st->st_esp.attrs.key_len - , enum_show(&auth_alg_names, st->st_esp.attrs.auth)+ - +15 /* strlen("AUTH_ALGORITHM_") */ - , c->policy & POLICY_PFS ? - c->alg_info_esp->esp_pfsgroup ? - enum_show(&oakley_group_names, - c->alg_info_esp->esp_pfsgroup) - +13 /*strlen("OAKLEY_GROUP_")*/ - : "" - : "" - ); + if (c->alg_info_esp) + { + alg_info_snprint(buf, sizeof(buf), (struct alg_info *)c->alg_info_esp); + whack_log(RC_COMMENT + , "\"%s\"%s: ESP algorithms wanted: %s" + , c->name + , instance + , buf); + } + if (c->alg_info_esp) + { + alg_info_snprint_esp(buf, sizeof(buf), c->alg_info_esp); + whack_log(RC_COMMENT + , "\"%s\"%s: ESP algorithms loaded: %s" + , c->name + , instance + , buf); + } + st = state_with_serialno(c->newest_ipsec_sa); + if (st && st->st_esp.present) + whack_log(RC_COMMENT + , "\"%s\"%s: ESP algorithm newest: %s_%d-%s; pfsgroup=%s" + , c->name + , instance + , enum_show(&esp_transformid_names, st->st_esp.attrs.transid) + +4 /* strlen("ESP_") */ + , st->st_esp.attrs.key_len + , enum_show(&auth_alg_names, st->st_esp.attrs.auth)+ + +15 /* strlen("AUTH_ALGORITHM_") */ + , c->policy & POLICY_PFS ? + c->alg_info_esp->esp_pfsgroup ? + enum_show(&oakley_group_names, + c->alg_info_esp->esp_pfsgroup) + +13 /*strlen("OAKLEY_GROUP_")*/ + : "" + : "" + ); } #endif /* NO_PLUTO */ bool kernel_alg_esp_auth_ok(u_int auth, - struct alg_info_esp *alg_info __attribute__((unused))) + struct alg_info_esp *alg_info __attribute__((unused))) { - return ESP_AALG_PRESENT(alg_info_esp_aa2sadb(auth)); + return ESP_AALG_PRESENT(alg_info_esp_aa2sadb(auth)); } u_int kernel_alg_esp_auth_keylen(u_int auth) { - u_int sadb_aalg = alg_info_esp_aa2sadb(auth); + u_int sadb_aalg = alg_info_esp_aa2sadb(auth); - u_int a_keylen = (sadb_aalg) - ? esp_aalg[sadb_aalg].sadb_alg_maxbits/BITS_PER_BYTE - : 0; + u_int a_keylen = (sadb_aalg) + ? esp_aalg[sadb_aalg].sadb_alg_maxbits/BITS_PER_BYTE + : 0; - DBG(DBG_CONTROL | DBG_CRYPT | DBG_PARSING, - DBG_log("kernel_alg_esp_auth_keylen(auth=%d, sadb_aalg=%d): " - "a_keylen=%d", auth, sadb_aalg, a_keylen) - ) - return a_keylen; + DBG(DBG_CONTROL | DBG_CRYPT | DBG_PARSING, + DBG_log("kernel_alg_esp_auth_keylen(auth=%d, sadb_aalg=%d): " + "a_keylen=%d", auth, sadb_aalg, a_keylen) + ) + return a_keylen; } struct esp_info * kernel_alg_esp_info(int transid, int auth) { - int sadb_aalg, sadb_ealg; - static struct esp_info ei_buf; + int sadb_aalg, sadb_ealg; + static struct esp_info ei_buf; - sadb_ealg = transid; - sadb_aalg = alg_info_esp_aa2sadb(auth); + sadb_ealg = transid; + sadb_aalg = alg_info_esp_aa2sadb(auth); - if (!ESP_EALG_PRESENT(sadb_ealg)) - goto none; - if (!ESP_AALG_PRESENT(sadb_aalg)) - goto none; + if (!ESP_EALG_PRESENT(sadb_ealg)) + goto none; + if (!ESP_AALG_PRESENT(sadb_aalg)) + goto none; - memset(&ei_buf, 0, sizeof (ei_buf)); - ei_buf.transid = transid; - ei_buf.auth = auth; + memset(&ei_buf, 0, sizeof (ei_buf)); + ei_buf.transid = transid; + ei_buf.auth = auth; - /* don't return "default" keylen because this value is used from - * setup_half_ipsec_sa() to "validate" keylen - * In effect, enckeylen will be used as "max" value - */ - ei_buf.enckeylen = esp_ealg[sadb_ealg].sadb_alg_maxbits/BITS_PER_BYTE; - ei_buf.authkeylen = esp_aalg[sadb_aalg].sadb_alg_maxbits/BITS_PER_BYTE; - ei_buf.encryptalg = sadb_ealg; - ei_buf.authalg = sadb_aalg; + /* don't return "default" keylen because this value is used from + * setup_half_ipsec_sa() to "validate" keylen + * In effect, enckeylen will be used as "max" value + */ + ei_buf.enckeylen = esp_ealg[sadb_ealg].sadb_alg_maxbits/BITS_PER_BYTE; + ei_buf.authkeylen = esp_aalg[sadb_aalg].sadb_alg_maxbits/BITS_PER_BYTE; + ei_buf.encryptalg = sadb_ealg; + ei_buf.authalg = sadb_aalg; - DBG(DBG_PARSING, - DBG_log("kernel_alg_esp_info():" - "transid=%d, auth=%d, ei=%p, " - "enckeylen=%d, authkeylen=%d, encryptalg=%d, authalg=%d", - transid, auth, &ei_buf, - (int)ei_buf.enckeylen, (int)ei_buf.authkeylen, - ei_buf.encryptalg, ei_buf.authalg) - ) - return &ei_buf; + DBG(DBG_PARSING, + DBG_log("kernel_alg_esp_info():" + "transid=%d, auth=%d, ei=%p, " + "enckeylen=%d, authkeylen=%d, encryptalg=%d, authalg=%d", + transid, auth, &ei_buf, + (int)ei_buf.enckeylen, (int)ei_buf.authkeylen, + ei_buf.encryptalg, ei_buf.authalg) + ) + return &ei_buf; none: - DBG(DBG_PARSING, - DBG_log("kernel_alg_esp_info():" - "transid=%d, auth=%d, ei=NULL", - transid, auth) - ) - return NULL; + DBG(DBG_PARSING, + DBG_log("kernel_alg_esp_info():" + "transid=%d, auth=%d, ei=NULL", + transid, auth) + ) + return NULL; } #ifndef NO_PLUTO static void kernel_alg_policy_algorithms(struct esp_info *esp_info) { - u_int ealg_id = esp_info->esp_ealg_id; + u_int ealg_id = esp_info->esp_ealg_id; - switch(ealg_id) - { - case 0: - case ESP_DES: - case ESP_3DES: - case ESP_NULL: - case ESP_CAST: - break; - default: - if (!esp_info->esp_ealg_keylen) + switch(ealg_id) { - /* algos that need KEY_LENGTH - * - * Note: this is a very dirty hack ;-) - * Idea: Add a key_length_needed attribute to - * esp_ealg ?? - */ - esp_info->esp_ealg_keylen = esp_ealg[ealg_id].sadb_alg_maxbits; + case 0: + case ESP_DES: + case ESP_3DES: + case ESP_NULL: + case ESP_CAST: + break; + default: + if (!esp_info->esp_ealg_keylen) + { + /* algos that need KEY_LENGTH + * + * Note: this is a very dirty hack ;-) + * Idea: Add a key_length_needed attribute to + * esp_ealg ?? + */ + esp_info->esp_ealg_keylen = esp_ealg[ealg_id].sadb_alg_maxbits; + } } - } } static bool kernel_alg_db_add(struct db_context *db_ctx, struct esp_info *esp_info, lset_t policy) { - u_int ealg_id, aalg_id; + u_int ealg_id, aalg_id; - ealg_id = esp_info->esp_ealg_id; + ealg_id = esp_info->esp_ealg_id; - if (!ESP_EALG_PRESENT(ealg_id)) - { - DBG_log("kernel_alg_db_add() kernel enc ealg_id=%d not present", ealg_id); - return FALSE; - } - - if (!(policy & POLICY_AUTHENTICATE)) /* skip ESP auth attrs for AH */ - { - aalg_id = alg_info_esp_aa2sadb(esp_info->esp_aalg_id); - - if (!ESP_AALG_PRESENT(aalg_id)) + if (!ESP_EALG_PRESENT(ealg_id)) { - DBG_log("kernel_alg_db_add() kernel auth " - "aalg_id=%d not present", aalg_id); - return FALSE; + DBG_log("kernel_alg_db_add() kernel enc ealg_id=%d not present", ealg_id); + return FALSE; } - } - - /* do algo policy */ - kernel_alg_policy_algorithms(esp_info); - - /* open new transformation */ - db_trans_add(db_ctx, ealg_id); - - /* add ESP auth attr */ - if (!(policy & POLICY_AUTHENTICATE)) - db_attr_add_values(db_ctx, AUTH_ALGORITHM, esp_info->esp_aalg_id); - - /* add keylegth if specified in esp= string */ - if (esp_info->esp_ealg_keylen) - db_attr_add_values(db_ctx, KEY_LENGTH, esp_info->esp_ealg_keylen); - return TRUE; + if (!(policy & POLICY_AUTHENTICATE)) /* skip ESP auth attrs for AH */ + { + aalg_id = alg_info_esp_aa2sadb(esp_info->esp_aalg_id); + + if (!ESP_AALG_PRESENT(aalg_id)) + { + DBG_log("kernel_alg_db_add() kernel auth " + "aalg_id=%d not present", aalg_id); + return FALSE; + } + } + + /* do algo policy */ + kernel_alg_policy_algorithms(esp_info); + + /* open new transformation */ + db_trans_add(db_ctx, ealg_id); + + /* add ESP auth attr */ + if (!(policy & POLICY_AUTHENTICATE)) + db_attr_add_values(db_ctx, AUTH_ALGORITHM, esp_info->esp_aalg_id); + + /* add keylegth if specified in esp= string */ + if (esp_info->esp_ealg_keylen) + db_attr_add_values(db_ctx, KEY_LENGTH, esp_info->esp_ealg_keylen); + + return TRUE; } -/* - * Create proposal with runtime kernel algos, merging - * with passed proposal if not NULL +/* + * Create proposal with runtime kernel algos, merging + * with passed proposal if not NULL * - * for now this function does free() previous returned - * malloced pointer (this quirk allows easier spdb.c change) + * for now this function does free() previous returned + * malloced pointer (this quirk allows easier spdb.c change) */ struct db_context * kernel_alg_db_new(struct alg_info_esp *alg_info, lset_t policy ) { - const struct esp_info *esp_info; - struct esp_info tmp_esp_info; - struct db_context *ctx_new=NULL; - struct db_trans *t; - struct db_prop *prop; - u_int trans_cnt; - int tn = 0; + const struct esp_info *esp_info; + struct esp_info tmp_esp_info; + struct db_context *ctx_new=NULL; + struct db_trans *t; + struct db_prop *prop; + u_int trans_cnt; + int tn = 0; - if (!(policy & POLICY_ENCRYPT)) /* not possible, I think */ - return NULL; + if (!(policy & POLICY_ENCRYPT)) /* not possible, I think */ + return NULL; - trans_cnt = esp_ealg_num * esp_aalg_num; - DBG(DBG_EMITTING, - DBG_log("kernel_alg_db_prop_new() initial trans_cnt=%d" - , trans_cnt) - ) - - /* pass aprox. number of transforms and attributes */ - ctx_new = db_prop_new(PROTO_IPSEC_ESP, trans_cnt, trans_cnt * 2); - - /* - * Loop: for each element (struct esp_info) of alg_info, - * if kernel support is present then build the transform (and attrs) - * if NULL alg_info, propose everything ... - */ - - if (alg_info) - { - int i; - - ALG_INFO_ESP_FOREACH(alg_info, esp_info, i) - { - tmp_esp_info = *esp_info; - kernel_alg_db_add(ctx_new, &tmp_esp_info, policy); - } - } - else - { - u_int ealg_id; - - ESP_EALG_FOR_EACH_UPDOWN(ealg_id) - { - u_int aalg_id; - - tmp_esp_info.esp_ealg_id = ealg_id; - tmp_esp_info.esp_ealg_keylen = 0; - - for (aalg_id = 1; aalg_id <= SADB_AALG_MAX; aalg_id++) - { - if (ESP_AALG_PRESENT(aalg_id)) - { - tmp_esp_info.esp_aalg_id = alg_info_esp_sadb2aa(aalg_id); - tmp_esp_info.esp_aalg_keylen = 0; - kernel_alg_db_add(ctx_new, &tmp_esp_info, policy); - } - } - } - } - - prop = db_prop_get(ctx_new); - - DBG(DBG_CONTROL|DBG_EMITTING, - DBG_log("kernel_alg_db_prop_new() " - "will return p_new->protoid=%d, p_new->trans_cnt=%d" - , prop->protoid, prop->trans_cnt) - ) - - for (t = prop->trans, tn = 0; tn < prop->trans_cnt; tn++) - { - DBG(DBG_CONTROL|DBG_EMITTING, - DBG_log("kernel_alg_db_prop_new() " - " trans[%d]: transid=%d, attr_cnt=%d, " - "attrs[0].type=%d, attrs[0].val=%d" - , tn - , t[tn].transid, t[tn].attr_cnt - , t[tn].attrs[0].type, t[tn].attrs[0].val) + trans_cnt = esp_ealg_num * esp_aalg_num; + DBG(DBG_EMITTING, + DBG_log("kernel_alg_db_prop_new() initial trans_cnt=%d" + , trans_cnt) ) - } - return ctx_new; + + /* pass aprox. number of transforms and attributes */ + ctx_new = db_prop_new(PROTO_IPSEC_ESP, trans_cnt, trans_cnt * 2); + + /* + * Loop: for each element (struct esp_info) of alg_info, + * if kernel support is present then build the transform (and attrs) + * if NULL alg_info, propose everything ... + */ + + if (alg_info) + { + int i; + + ALG_INFO_ESP_FOREACH(alg_info, esp_info, i) + { + tmp_esp_info = *esp_info; + kernel_alg_db_add(ctx_new, &tmp_esp_info, policy); + } + } + else + { + u_int ealg_id; + + ESP_EALG_FOR_EACH_UPDOWN(ealg_id) + { + u_int aalg_id; + + tmp_esp_info.esp_ealg_id = ealg_id; + tmp_esp_info.esp_ealg_keylen = 0; + + for (aalg_id = 1; aalg_id <= SADB_AALG_MAX; aalg_id++) + { + if (ESP_AALG_PRESENT(aalg_id)) + { + tmp_esp_info.esp_aalg_id = alg_info_esp_sadb2aa(aalg_id); + tmp_esp_info.esp_aalg_keylen = 0; + kernel_alg_db_add(ctx_new, &tmp_esp_info, policy); + } + } + } + } + + prop = db_prop_get(ctx_new); + + DBG(DBG_CONTROL|DBG_EMITTING, + DBG_log("kernel_alg_db_prop_new() " + "will return p_new->protoid=%d, p_new->trans_cnt=%d" + , prop->protoid, prop->trans_cnt) + ) + + for (t = prop->trans, tn = 0; tn < prop->trans_cnt; tn++) + { + DBG(DBG_CONTROL|DBG_EMITTING, + DBG_log("kernel_alg_db_prop_new() " + " trans[%d]: transid=%d, attr_cnt=%d, " + "attrs[0].type=%d, attrs[0].val=%d" + , tn + , t[tn].transid, t[tn].attr_cnt + , t[tn].attrs[0].type, t[tn].attrs[0].val) + ) + } + return ctx_new; } #endif /* NO_PLUTO */ diff --git a/src/pluto/kernel_netlink.c b/src/pluto/kernel_netlink.c index d550ab73c..d0fdeeef5 100644 --- a/src/pluto/kernel_netlink.c +++ b/src/pluto/kernel_netlink.c @@ -39,7 +39,7 @@ #include "kernel_netlink.h" #include "kernel_pfkey.h" #include "log.h" -#include "whack.h" /* for RC_LOG_SERIOUS */ +#include "whack.h" /* for RC_LOG_SERIOUS */ #include "kernel_alg.h" /* Minimum priority number in SPD used by pluto. */ @@ -48,72 +48,72 @@ static int netlinkfd = NULL_FD; static int netlink_bcast_fd = NULL_FD; -#define NE(x) { x, #x } /* Name Entry -- shorthand for sparse_names */ +#define NE(x) { x, #x } /* Name Entry -- shorthand for sparse_names */ static sparse_names xfrm_type_names = { - NE(NLMSG_NOOP), - NE(NLMSG_ERROR), - NE(NLMSG_DONE), - NE(NLMSG_OVERRUN), + NE(NLMSG_NOOP), + NE(NLMSG_ERROR), + NE(NLMSG_DONE), + NE(NLMSG_OVERRUN), - NE(XFRM_MSG_NEWSA), - NE(XFRM_MSG_DELSA), - NE(XFRM_MSG_GETSA), + NE(XFRM_MSG_NEWSA), + NE(XFRM_MSG_DELSA), + NE(XFRM_MSG_GETSA), - NE(XFRM_MSG_NEWPOLICY), - NE(XFRM_MSG_DELPOLICY), - NE(XFRM_MSG_GETPOLICY), + NE(XFRM_MSG_NEWPOLICY), + NE(XFRM_MSG_DELPOLICY), + NE(XFRM_MSG_GETPOLICY), - NE(XFRM_MSG_ALLOCSPI), - NE(XFRM_MSG_ACQUIRE), - NE(XFRM_MSG_EXPIRE), + NE(XFRM_MSG_ALLOCSPI), + NE(XFRM_MSG_ACQUIRE), + NE(XFRM_MSG_EXPIRE), - NE(XFRM_MSG_UPDPOLICY), - NE(XFRM_MSG_UPDSA), + NE(XFRM_MSG_UPDPOLICY), + NE(XFRM_MSG_UPDSA), - NE(XFRM_MSG_POLEXPIRE), + NE(XFRM_MSG_POLEXPIRE), - NE(XFRM_MSG_MAX), + NE(XFRM_MSG_MAX), - { 0, sparse_end } + { 0, sparse_end } }; #undef NE /* Authentication algorithms */ static sparse_names aalg_list = { - { SADB_X_AALG_NULL, "digest_null" }, - { SADB_AALG_MD5HMAC, "md5" }, - { SADB_AALG_SHA1HMAC, "sha1" }, - { SADB_X_AALG_SHA2_256HMAC, "sha256" }, - { SADB_X_AALG_SHA2_384HMAC, "sha384" }, - { SADB_X_AALG_SHA2_512HMAC, "sha512" }, - { SADB_X_AALG_RIPEMD160HMAC, "ripemd160" }, - { SADB_X_AALG_AES_XCBC_MAC, "xcbc(aes)"}, - { SADB_X_AALG_NULL, "null" }, - { 0, sparse_end } + { SADB_X_AALG_NULL, "digest_null" }, + { SADB_AALG_MD5HMAC, "md5" }, + { SADB_AALG_SHA1HMAC, "sha1" }, + { SADB_X_AALG_SHA2_256HMAC, "sha256" }, + { SADB_X_AALG_SHA2_384HMAC, "sha384" }, + { SADB_X_AALG_SHA2_512HMAC, "sha512" }, + { SADB_X_AALG_RIPEMD160HMAC, "ripemd160" }, + { SADB_X_AALG_AES_XCBC_MAC, "xcbc(aes)"}, + { SADB_X_AALG_NULL, "null" }, + { 0, sparse_end } }; /* Encryption algorithms */ static sparse_names ealg_list = { - { SADB_EALG_NULL, "cipher_null" }, - { SADB_EALG_DESCBC, "des" }, - { SADB_EALG_3DESCBC, "des3_ede" }, - { SADB_X_EALG_CASTCBC, "cast128" }, - { SADB_X_EALG_BLOWFISHCBC, "blowfish" }, - { SADB_X_EALG_AESCBC, "aes" }, - { SADB_X_EALG_CAMELLIACBC, "cbc(camellia)" }, - { SADB_X_EALG_SERPENTCBC, "serpent" }, - { SADB_X_EALG_TWOFISHCBC, "twofish" }, - { 0, sparse_end } + { SADB_EALG_NULL, "cipher_null" }, + { SADB_EALG_DESCBC, "des" }, + { SADB_EALG_3DESCBC, "des3_ede" }, + { SADB_X_EALG_CASTCBC, "cast128" }, + { SADB_X_EALG_BLOWFISHCBC, "blowfish" }, + { SADB_X_EALG_AESCBC, "aes" }, + { SADB_X_EALG_CAMELLIACBC, "cbc(camellia)" }, + { SADB_X_EALG_SERPENTCBC, "serpent" }, + { SADB_X_EALG_TWOFISHCBC, "twofish" }, + { 0, sparse_end } }; /* Compression algorithms */ static sparse_names calg_list = { - { SADB_X_CALG_DEFLATE, "deflate" }, - { SADB_X_CALG_LZS, "lzs" }, - { SADB_X_CALG_LZJH, "lzjh" }, - { 0, sparse_end } + { SADB_X_CALG_DEFLATE, "deflate" }, + { SADB_X_CALG_LZS, "lzs" }, + { SADB_X_CALG_LZJH, "lzjh" }, + { 0, sparse_end } }; /** ip2xfrm - Take an IP address and convert to an xfrm. @@ -124,14 +124,14 @@ static sparse_names calg_list = { static void ip2xfrm(const ip_address *addr, xfrm_address_t *xaddr) { - if (addr->u.v4.sin_family == AF_INET) - { - xaddr->a4 = addr->u.v4.sin_addr.s_addr; - } - else - { - memcpy(xaddr->a6, &addr->u.v6.sin6_addr, sizeof(xaddr->a6)); - } + if (addr->u.v4.sin_family == AF_INET) + { + xaddr->a4 = addr->u.v4.sin_addr.s_addr; + } + else + { + memcpy(xaddr->a6, &addr->u.v6.sin6_addr, sizeof(xaddr->a6)); + } } /** init_netlink - Initialize the netlink inferface. Opens the sockets and @@ -140,32 +140,32 @@ ip2xfrm(const ip_address *addr, xfrm_address_t *xaddr) static void init_netlink(void) { - struct sockaddr_nl addr; + struct sockaddr_nl addr; - netlinkfd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_XFRM); + netlinkfd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_XFRM); - if (netlinkfd < 0) - exit_log_errno((e, "socket() in init_netlink()")); + if (netlinkfd < 0) + exit_log_errno((e, "socket() in init_netlink()")); - if (fcntl(netlinkfd, F_SETFD, FD_CLOEXEC) != 0) - exit_log_errno((e, "fcntl(FD_CLOEXEC) in init_netlink()")); + if (fcntl(netlinkfd, F_SETFD, FD_CLOEXEC) != 0) + exit_log_errno((e, "fcntl(FD_CLOEXEC) in init_netlink()")); - netlink_bcast_fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_XFRM); + netlink_bcast_fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_XFRM); - if (netlink_bcast_fd < 0) - exit_log_errno((e, "socket() for bcast in init_netlink()")); + if (netlink_bcast_fd < 0) + exit_log_errno((e, "socket() for bcast in init_netlink()")); - if (fcntl(netlink_bcast_fd, F_SETFD, FD_CLOEXEC) != 0) - exit_log_errno((e, "fcntl(FD_CLOEXEC) for bcast in init_netlink()")); + if (fcntl(netlink_bcast_fd, F_SETFD, FD_CLOEXEC) != 0) + exit_log_errno((e, "fcntl(FD_CLOEXEC) for bcast in init_netlink()")); - if (fcntl(netlink_bcast_fd, F_SETFL, O_NONBLOCK) != 0) - exit_log_errno((e, "fcntl(O_NONBLOCK) for bcast in init_netlink()")); + if (fcntl(netlink_bcast_fd, F_SETFL, O_NONBLOCK) != 0) + exit_log_errno((e, "fcntl(O_NONBLOCK) for bcast in init_netlink()")); - addr.nl_family = AF_NETLINK; - addr.nl_pid = getpid(); - addr.nl_groups = XFRMGRP_ACQUIRE | XFRMGRP_EXPIRE; - if (bind(netlink_bcast_fd, (struct sockaddr *)&addr, sizeof(addr)) != 0) - exit_log_errno((e, "Failed to bind bcast socket in init_netlink()")); + addr.nl_family = AF_NETLINK; + addr.nl_pid = getpid(); + addr.nl_groups = XFRMGRP_ACQUIRE | XFRMGRP_EXPIRE; + if (bind(netlink_bcast_fd, (struct sockaddr *)&addr, sizeof(addr)) != 0) + exit_log_errno((e, "Failed to bind bcast socket in init_netlink()")); } /** send_netlink_msg @@ -182,139 +182,139 @@ static bool send_netlink_msg(struct nlmsghdr *hdr, struct nlmsghdr *rbuf, size_t rbuf_len , const char *description, const char *text_said) { - struct { - struct nlmsghdr n; - struct nlmsgerr e; - char data[1024]; - } rsp; + struct { + struct nlmsghdr n; + struct nlmsgerr e; + char data[1024]; + } rsp; - size_t len; - ssize_t r; - struct sockaddr_nl addr; - static uint32_t seq; + size_t len; + ssize_t r; + struct sockaddr_nl addr; + static uint32_t seq; - if (no_klips) - { - return TRUE; - } + if (no_klips) + { + return TRUE; + } - hdr->nlmsg_seq = ++seq; - len = hdr->nlmsg_len; - do { - r = write(netlinkfd, hdr, len); - } while (r < 0 && errno == EINTR); - if (r < 0) - { - log_errno((e - , "netlink write() of %s message" - " for %s %s failed" - , sparse_val_show(xfrm_type_names, hdr->nlmsg_type) - , description, text_said)); - return FALSE; - } - else if ((size_t)r != len) - { - loglog(RC_LOG_SERIOUS - , "ERROR: netlink write() of %s message" - " for %s %s truncated: %ld instead of %lu" - , sparse_val_show(xfrm_type_names, hdr->nlmsg_type) - , description, text_said - , (long)r, (unsigned long)len); - return FALSE; - } - - for (;;) { - socklen_t alen; - - alen = sizeof(addr); - r = recvfrom(netlinkfd, &rsp, sizeof(rsp), 0 - , (struct sockaddr *)&addr, &alen); + hdr->nlmsg_seq = ++seq; + len = hdr->nlmsg_len; + do { + r = write(netlinkfd, hdr, len); + } while (r < 0 && errno == EINTR); if (r < 0) { - if (errno == EINTR) - { - continue; - } - log_errno((e - , "netlink recvfrom() of response to our %s message" - " for %s %s failed" - , sparse_val_show(xfrm_type_names, hdr->nlmsg_type) - , description, text_said)); - return FALSE; + log_errno((e + , "netlink write() of %s message" + " for %s %s failed" + , sparse_val_show(xfrm_type_names, hdr->nlmsg_type) + , description, text_said)); + return FALSE; } - else if ((size_t) r < sizeof(rsp.n)) + else if ((size_t)r != len) { - plog("netlink read truncated message: %ld bytes; ignore message" - , (long) r); - continue; + loglog(RC_LOG_SERIOUS + , "ERROR: netlink write() of %s message" + " for %s %s truncated: %ld instead of %lu" + , sparse_val_show(xfrm_type_names, hdr->nlmsg_type) + , description, text_said + , (long)r, (unsigned long)len); + return FALSE; } - else if (addr.nl_pid != 0) - { - /* not for us: ignore */ - DBG(DBG_KLIPS, - DBG_log("netlink: ignoring %s message from process %u" - , sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type) - , addr.nl_pid)); - continue; - } - else if (rsp.n.nlmsg_seq != seq) - { - DBG(DBG_KLIPS, - DBG_log("netlink: ignoring out of sequence (%u/%u) message %s" - , rsp.n.nlmsg_seq, seq - , sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type))); - continue; - } - break; - } - if (rsp.n.nlmsg_len > (size_t) r) - { - loglog(RC_LOG_SERIOUS - , "netlink recvfrom() of response to our %s message" - " for %s %s was truncated: %ld instead of %lu" - , sparse_val_show(xfrm_type_names, hdr->nlmsg_type) - , description, text_said - , (long) len, (unsigned long) rsp.n.nlmsg_len); - return FALSE; - } - else if (rsp.n.nlmsg_type != NLMSG_ERROR - && (rbuf && rsp.n.nlmsg_type != rbuf->nlmsg_type)) - { - loglog(RC_LOG_SERIOUS - , "netlink recvfrom() of response to our %s message" - " for %s %s was of wrong type (%s)" - , sparse_val_show(xfrm_type_names, hdr->nlmsg_type) - , description, text_said - , sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type)); - return FALSE; - } - else if (rbuf) - { - if ((size_t) r > rbuf_len) - { - loglog(RC_LOG_SERIOUS - , "netlink recvfrom() of response to our %s message" - " for %s %s was too long: %ld > %lu" - , sparse_val_show(xfrm_type_names, hdr->nlmsg_type) - , description, text_said - , (long)r, (unsigned long)rbuf_len); - return FALSE; + for (;;) { + socklen_t alen; + + alen = sizeof(addr); + r = recvfrom(netlinkfd, &rsp, sizeof(rsp), 0 + , (struct sockaddr *)&addr, &alen); + if (r < 0) + { + if (errno == EINTR) + { + continue; + } + log_errno((e + , "netlink recvfrom() of response to our %s message" + " for %s %s failed" + , sparse_val_show(xfrm_type_names, hdr->nlmsg_type) + , description, text_said)); + return FALSE; + } + else if ((size_t) r < sizeof(rsp.n)) + { + plog("netlink read truncated message: %ld bytes; ignore message" + , (long) r); + continue; + } + else if (addr.nl_pid != 0) + { + /* not for us: ignore */ + DBG(DBG_KLIPS, + DBG_log("netlink: ignoring %s message from process %u" + , sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type) + , addr.nl_pid)); + continue; + } + else if (rsp.n.nlmsg_seq != seq) + { + DBG(DBG_KLIPS, + DBG_log("netlink: ignoring out of sequence (%u/%u) message %s" + , rsp.n.nlmsg_seq, seq + , sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type))); + continue; + } + break; } - memcpy(rbuf, &rsp, r); + + if (rsp.n.nlmsg_len > (size_t) r) + { + loglog(RC_LOG_SERIOUS + , "netlink recvfrom() of response to our %s message" + " for %s %s was truncated: %ld instead of %lu" + , sparse_val_show(xfrm_type_names, hdr->nlmsg_type) + , description, text_said + , (long) len, (unsigned long) rsp.n.nlmsg_len); + return FALSE; + } + else if (rsp.n.nlmsg_type != NLMSG_ERROR + && (rbuf && rsp.n.nlmsg_type != rbuf->nlmsg_type)) + { + loglog(RC_LOG_SERIOUS + , "netlink recvfrom() of response to our %s message" + " for %s %s was of wrong type (%s)" + , sparse_val_show(xfrm_type_names, hdr->nlmsg_type) + , description, text_said + , sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type)); + return FALSE; + } + else if (rbuf) + { + if ((size_t) r > rbuf_len) + { + loglog(RC_LOG_SERIOUS + , "netlink recvfrom() of response to our %s message" + " for %s %s was too long: %ld > %lu" + , sparse_val_show(xfrm_type_names, hdr->nlmsg_type) + , description, text_said + , (long)r, (unsigned long)rbuf_len); + return FALSE; + } + memcpy(rbuf, &rsp, r); + return TRUE; + } + else if (rsp.n.nlmsg_type == NLMSG_ERROR && rsp.e.error) + { + loglog(RC_LOG_SERIOUS + , "ERROR: netlink response for %s %s included errno %d: %s" + , description, text_said + , -rsp.e.error + , strerror(-rsp.e.error)); + return FALSE; + } + return TRUE; - } - else if (rsp.n.nlmsg_type == NLMSG_ERROR && rsp.e.error) - { - loglog(RC_LOG_SERIOUS - , "ERROR: netlink response for %s %s included errno %d: %s" - , description, text_said - , -rsp.e.error - , strerror(-rsp.e.error)); - return FALSE; - } - - return TRUE; } /** netlink_policy - @@ -327,36 +327,36 @@ send_netlink_msg(struct nlmsghdr *hdr, struct nlmsghdr *rbuf, size_t rbuf_len static bool netlink_policy(struct nlmsghdr *hdr, bool enoent_ok, const char *text_said) { - struct { - struct nlmsghdr n; - struct nlmsgerr e; - } rsp; - int error; + struct { + struct nlmsghdr n; + struct nlmsgerr e; + } rsp; + int error; - rsp.n.nlmsg_type = NLMSG_ERROR; - if (!send_netlink_msg(hdr, &rsp.n, sizeof(rsp), "policy", text_said)) - { + rsp.n.nlmsg_type = NLMSG_ERROR; + if (!send_netlink_msg(hdr, &rsp.n, sizeof(rsp), "policy", text_said)) + { + return FALSE; + } + + error = -rsp.e.error; + if (!error) + { + return TRUE; + } + + if (error == ENOENT && enoent_ok) + { + return TRUE; + } + + loglog(RC_LOG_SERIOUS + , "ERROR: netlink %s response for flow %s included errno %d: %s" + , sparse_val_show(xfrm_type_names, hdr->nlmsg_type) + , text_said + , error + , strerror(error)); return FALSE; - } - - error = -rsp.e.error; - if (!error) - { - return TRUE; - } - - if (error == ENOENT && enoent_ok) - { - return TRUE; - } - - loglog(RC_LOG_SERIOUS - , "ERROR: netlink %s response for flow %s included errno %d: %s" - , sparse_val_show(xfrm_type_names, hdr->nlmsg_type) - , text_said - , error - , strerror(error)); - return FALSE; } /** netlink_raw_eroute @@ -376,192 +376,192 @@ netlink_policy(struct nlmsghdr *hdr, bool enoent_ok, const char *text_said) */ static bool netlink_raw_eroute(const ip_address *this_host - , const ip_subnet *this_client - , const ip_address *that_host - , const ip_subnet *that_client - , ipsec_spi_t spi - , unsigned int satype - , unsigned int transport_proto - , const struct pfkey_proto_info *proto_info - , time_t use_lifetime UNUSED - , unsigned int op - , const char *text_said) + , const ip_subnet *this_client + , const ip_address *that_host + , const ip_subnet *that_client + , ipsec_spi_t spi + , unsigned int satype + , unsigned int transport_proto + , const struct pfkey_proto_info *proto_info + , time_t use_lifetime UNUSED + , unsigned int op + , const char *text_said) { - struct { - struct nlmsghdr n; - union { - struct xfrm_userpolicy_info p; - struct xfrm_userpolicy_id id; - } u; - char data[1024]; - } req; - int shift; - int dir; - int family; - int policy; - bool ok; - bool enoent_ok; + struct { + struct nlmsghdr n; + union { + struct xfrm_userpolicy_info p; + struct xfrm_userpolicy_id id; + } u; + char data[1024]; + } req; + int shift; + int dir; + int family; + int policy; + bool ok; + bool enoent_ok; - policy = IPSEC_POLICY_IPSEC; + policy = IPSEC_POLICY_IPSEC; - if (satype == SADB_X_SATYPE_INT) - { - /* shunt route */ - switch (ntohl(spi)) + if (satype == SADB_X_SATYPE_INT) { - case SPI_PASS: - policy = IPSEC_POLICY_NONE; - break; - case SPI_DROP: - case SPI_REJECT: - default: - policy = IPSEC_POLICY_DISCARD; - break; - case SPI_TRAP: - case SPI_TRAPSUBNET: - case SPI_HOLD: - if (op & (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT)) - { - return TRUE; - } - break; - } - } - - memset(&req, 0, sizeof(req)); - req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; - - family = that_client->addr.u.v4.sin_family; - shift = (family == AF_INET) ? 5 : 7; - - req.u.p.sel.sport = portof(&this_client->addr); - req.u.p.sel.dport = portof(&that_client->addr); - req.u.p.sel.sport_mask = (req.u.p.sel.sport) ? ~0:0; - req.u.p.sel.dport_mask = (req.u.p.sel.dport) ? ~0:0; - ip2xfrm(&this_client->addr, &req.u.p.sel.saddr); - ip2xfrm(&that_client->addr, &req.u.p.sel.daddr); - req.u.p.sel.prefixlen_s = this_client->maskbits; - req.u.p.sel.prefixlen_d = that_client->maskbits; - req.u.p.sel.proto = transport_proto; - req.u.p.sel.family = family; - - dir = XFRM_POLICY_OUT; - if (op & (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT)) - { - dir = XFRM_POLICY_IN; - } - - if ((op & ERO_MASK) == ERO_DELETE) - { - req.u.id.dir = dir; - req.n.nlmsg_type = XFRM_MSG_DELPOLICY; - req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.u.id))); - } - else - { - int src, dst; - - req.u.p.dir = dir; - - src = req.u.p.sel.prefixlen_s; - dst = req.u.p.sel.prefixlen_d; - if (dir != XFRM_POLICY_OUT) { - src = req.u.p.sel.prefixlen_d; - dst = req.u.p.sel.prefixlen_s; - } - req.u.p.priority = MIN_SPD_PRIORITY - + (((2 << shift) - src) << shift) - + (2 << shift) - dst; - - req.u.p.action = XFRM_POLICY_ALLOW; - if (policy == IPSEC_POLICY_DISCARD) - { - req.u.p.action = XFRM_POLICY_BLOCK; - } - req.u.p.lft.soft_use_expires_seconds = use_lifetime; - req.u.p.lft.soft_byte_limit = XFRM_INF; - req.u.p.lft.soft_packet_limit = XFRM_INF; - req.u.p.lft.hard_byte_limit = XFRM_INF; - req.u.p.lft.hard_packet_limit = XFRM_INF; - - req.n.nlmsg_type = XFRM_MSG_NEWPOLICY; - if (op & (SADB_X_SAFLAGS_REPLACEFLOW << ERO_FLAG_SHIFT)) - { - req.n.nlmsg_type = XFRM_MSG_UPDPOLICY; - } - req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.u.p))); - } - - if (policy == IPSEC_POLICY_IPSEC && (op & ERO_MASK) != ERO_DELETE) - { - struct rtattr *attr; - struct xfrm_user_tmpl tmpl[4]; - int i; - - memset(tmpl, 0, sizeof(tmpl)); - for (i = 0; proto_info[i].proto; i++) - { - tmpl[i].reqid = proto_info[i].reqid; - tmpl[i].id.proto = proto_info[i].proto; - tmpl[i].optional = - proto_info[i].proto == IPPROTO_COMP && dir != XFRM_POLICY_OUT; - tmpl[i].aalgos = tmpl[i].ealgos = tmpl[i].calgos = ~0; - tmpl[i].mode = - proto_info[i].encapsulation == ENCAPSULATION_MODE_TUNNEL; - - if (!tmpl[i].mode) - { - continue; - } - - ip2xfrm(this_host, &tmpl[i].saddr); - ip2xfrm(that_host, &tmpl[i].id.daddr); + /* shunt route */ + switch (ntohl(spi)) + { + case SPI_PASS: + policy = IPSEC_POLICY_NONE; + break; + case SPI_DROP: + case SPI_REJECT: + default: + policy = IPSEC_POLICY_DISCARD; + break; + case SPI_TRAP: + case SPI_TRAPSUBNET: + case SPI_HOLD: + if (op & (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT)) + { + return TRUE; + } + break; + } } - attr = (struct rtattr *)((char *)&req + req.n.nlmsg_len); - attr->rta_type = XFRMA_TMPL; - attr->rta_len = i * sizeof(tmpl[0]); - memcpy(RTA_DATA(attr), tmpl, attr->rta_len); - attr->rta_len = RTA_LENGTH(attr->rta_len); - req.n.nlmsg_len += attr->rta_len; - } + memset(&req, 0, sizeof(req)); + req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; - enoent_ok = FALSE; - if (op == ERO_DEL_INBOUND) - { - enoent_ok = TRUE; - } - else if (op == ERO_DELETE && ntohl(spi) == SPI_HOLD) - { - enoent_ok = TRUE; - } + family = that_client->addr.u.v4.sin_family; + shift = (family == AF_INET) ? 5 : 7; - ok = netlink_policy(&req.n, enoent_ok, text_said); - switch (dir) - { - case XFRM_POLICY_IN: - if (req.n.nlmsg_type == XFRM_MSG_DELPOLICY) + req.u.p.sel.sport = portof(&this_client->addr); + req.u.p.sel.dport = portof(&that_client->addr); + req.u.p.sel.sport_mask = (req.u.p.sel.sport) ? ~0:0; + req.u.p.sel.dport_mask = (req.u.p.sel.dport) ? ~0:0; + ip2xfrm(&this_client->addr, &req.u.p.sel.saddr); + ip2xfrm(&that_client->addr, &req.u.p.sel.daddr); + req.u.p.sel.prefixlen_s = this_client->maskbits; + req.u.p.sel.prefixlen_d = that_client->maskbits; + req.u.p.sel.proto = transport_proto; + req.u.p.sel.family = family; + + dir = XFRM_POLICY_OUT; + if (op & (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT)) { - req.u.id.dir = XFRM_POLICY_FWD; + dir = XFRM_POLICY_IN; } - else if (!ok) + + if ((op & ERO_MASK) == ERO_DELETE) { - break; - } - else if (proto_info[0].encapsulation != ENCAPSULATION_MODE_TUNNEL - && satype != SADB_X_SATYPE_INT) - { - break; + req.u.id.dir = dir; + req.n.nlmsg_type = XFRM_MSG_DELPOLICY; + req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.u.id))); } else { - req.u.p.dir = XFRM_POLICY_FWD; - } - ok &= netlink_policy(&req.n, enoent_ok, text_said); - break; - } + int src, dst; - return ok; + req.u.p.dir = dir; + + src = req.u.p.sel.prefixlen_s; + dst = req.u.p.sel.prefixlen_d; + if (dir != XFRM_POLICY_OUT) { + src = req.u.p.sel.prefixlen_d; + dst = req.u.p.sel.prefixlen_s; + } + req.u.p.priority = MIN_SPD_PRIORITY + + (((2 << shift) - src) << shift) + + (2 << shift) - dst; + + req.u.p.action = XFRM_POLICY_ALLOW; + if (policy == IPSEC_POLICY_DISCARD) + { + req.u.p.action = XFRM_POLICY_BLOCK; + } + req.u.p.lft.soft_use_expires_seconds = use_lifetime; + req.u.p.lft.soft_byte_limit = XFRM_INF; + req.u.p.lft.soft_packet_limit = XFRM_INF; + req.u.p.lft.hard_byte_limit = XFRM_INF; + req.u.p.lft.hard_packet_limit = XFRM_INF; + + req.n.nlmsg_type = XFRM_MSG_NEWPOLICY; + if (op & (SADB_X_SAFLAGS_REPLACEFLOW << ERO_FLAG_SHIFT)) + { + req.n.nlmsg_type = XFRM_MSG_UPDPOLICY; + } + req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.u.p))); + } + + if (policy == IPSEC_POLICY_IPSEC && (op & ERO_MASK) != ERO_DELETE) + { + struct rtattr *attr; + struct xfrm_user_tmpl tmpl[4]; + int i; + + memset(tmpl, 0, sizeof(tmpl)); + for (i = 0; proto_info[i].proto; i++) + { + tmpl[i].reqid = proto_info[i].reqid; + tmpl[i].id.proto = proto_info[i].proto; + tmpl[i].optional = + proto_info[i].proto == IPPROTO_COMP && dir != XFRM_POLICY_OUT; + tmpl[i].aalgos = tmpl[i].ealgos = tmpl[i].calgos = ~0; + tmpl[i].mode = + proto_info[i].encapsulation == ENCAPSULATION_MODE_TUNNEL; + + if (!tmpl[i].mode) + { + continue; + } + + ip2xfrm(this_host, &tmpl[i].saddr); + ip2xfrm(that_host, &tmpl[i].id.daddr); + } + + attr = (struct rtattr *)((char *)&req + req.n.nlmsg_len); + attr->rta_type = XFRMA_TMPL; + attr->rta_len = i * sizeof(tmpl[0]); + memcpy(RTA_DATA(attr), tmpl, attr->rta_len); + attr->rta_len = RTA_LENGTH(attr->rta_len); + req.n.nlmsg_len += attr->rta_len; + } + + enoent_ok = FALSE; + if (op == ERO_DEL_INBOUND) + { + enoent_ok = TRUE; + } + else if (op == ERO_DELETE && ntohl(spi) == SPI_HOLD) + { + enoent_ok = TRUE; + } + + ok = netlink_policy(&req.n, enoent_ok, text_said); + switch (dir) + { + case XFRM_POLICY_IN: + if (req.n.nlmsg_type == XFRM_MSG_DELPOLICY) + { + req.u.id.dir = XFRM_POLICY_FWD; + } + else if (!ok) + { + break; + } + else if (proto_info[0].encapsulation != ENCAPSULATION_MODE_TUNNEL + && satype != SADB_X_SATYPE_INT) + { + break; + } + else + { + req.u.p.dir = XFRM_POLICY_FWD; + } + ok &= netlink_policy(&req.n, enoent_ok, text_said); + break; + } + + return ok; } /** netlink_add_sa - Add an SA into the kernel SPDB via netlink @@ -573,130 +573,130 @@ netlink_raw_eroute(const ip_address *this_host static bool netlink_add_sa(const struct kernel_sa *sa, bool replace) { - struct { - struct nlmsghdr n; - struct xfrm_usersa_info p; - char data[1024]; - } req; - struct rtattr *attr; + struct { + struct nlmsghdr n; + struct xfrm_usersa_info p; + char data[1024]; + } req; + struct rtattr *attr; - memset(&req, 0, sizeof(req)); - req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; - req.n.nlmsg_type = replace ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA; + memset(&req, 0, sizeof(req)); + req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + req.n.nlmsg_type = replace ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA; - ip2xfrm(sa->src, &req.p.saddr); - ip2xfrm(sa->dst, &req.p.id.daddr); + ip2xfrm(sa->src, &req.p.saddr); + ip2xfrm(sa->dst, &req.p.id.daddr); - req.p.id.spi = sa->spi; - req.p.id.proto = satype2proto(sa->satype); - req.p.family = sa->src->u.v4.sin_family; - req.p.mode = (sa->encapsulation == ENCAPSULATION_MODE_TUNNEL); - req.p.replay_window = sa->replay_window; - req.p.reqid = sa->reqid; - req.p.lft.soft_byte_limit = XFRM_INF; - req.p.lft.soft_packet_limit = XFRM_INF; - req.p.lft.hard_byte_limit = XFRM_INF; - req.p.lft.hard_packet_limit = XFRM_INF; + req.p.id.spi = sa->spi; + req.p.id.proto = satype2proto(sa->satype); + req.p.family = sa->src->u.v4.sin_family; + req.p.mode = (sa->encapsulation == ENCAPSULATION_MODE_TUNNEL); + req.p.replay_window = sa->replay_window; + req.p.reqid = sa->reqid; + req.p.lft.soft_byte_limit = XFRM_INF; + req.p.lft.soft_packet_limit = XFRM_INF; + req.p.lft.hard_byte_limit = XFRM_INF; + req.p.lft.hard_packet_limit = XFRM_INF; - req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.p))); + req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.p))); - attr = (struct rtattr *)((char *)&req + req.n.nlmsg_len); + attr = (struct rtattr *)((char *)&req + req.n.nlmsg_len); - if (sa->authalg) - { - struct xfrm_algo algo; - const char *name; + if (sa->authalg) + { + struct xfrm_algo algo; + const char *name; - name = sparse_name(aalg_list, sa->authalg); - if (!name) { - loglog(RC_LOG_SERIOUS, "unknown authentication algorithm: %u" - , sa->authalg); - return FALSE; + name = sparse_name(aalg_list, sa->authalg); + if (!name) { + loglog(RC_LOG_SERIOUS, "unknown authentication algorithm: %u" + , sa->authalg); + return FALSE; + } + + strcpy(algo.alg_name, name); + algo.alg_key_len = sa->authkeylen * BITS_PER_BYTE; + + attr->rta_type = XFRMA_ALG_AUTH; + attr->rta_len = RTA_LENGTH(sizeof(algo) + sa->authkeylen); + + memcpy(RTA_DATA(attr), &algo, sizeof(algo)); + memcpy((char *)RTA_DATA(attr) + sizeof(algo), sa->authkey + , sa->authkeylen); + + req.n.nlmsg_len += attr->rta_len; + attr = (struct rtattr *)((char *)attr + attr->rta_len); } - strcpy(algo.alg_name, name); - algo.alg_key_len = sa->authkeylen * BITS_PER_BYTE; + if (sa->encalg) + { + struct xfrm_algo algo; + const char *name; - attr->rta_type = XFRMA_ALG_AUTH; - attr->rta_len = RTA_LENGTH(sizeof(algo) + sa->authkeylen); + name = sparse_name(ealg_list, sa->encalg); + if (!name) { + loglog(RC_LOG_SERIOUS, "unknown encryption algorithm: %u" + , sa->encalg); + return FALSE; + } - memcpy(RTA_DATA(attr), &algo, sizeof(algo)); - memcpy((char *)RTA_DATA(attr) + sizeof(algo), sa->authkey - , sa->authkeylen); + strcpy(algo.alg_name, name); + algo.alg_key_len = sa->enckeylen * BITS_PER_BYTE; - req.n.nlmsg_len += attr->rta_len; - attr = (struct rtattr *)((char *)attr + attr->rta_len); - } + attr->rta_type = XFRMA_ALG_CRYPT; + attr->rta_len = RTA_LENGTH(sizeof(algo) + sa->enckeylen); - if (sa->encalg) - { - struct xfrm_algo algo; - const char *name; + memcpy(RTA_DATA(attr), &algo, sizeof(algo)); + memcpy((char *)RTA_DATA(attr) + sizeof(algo), sa->enckey + , sa->enckeylen); - name = sparse_name(ealg_list, sa->encalg); - if (!name) { - loglog(RC_LOG_SERIOUS, "unknown encryption algorithm: %u" - , sa->encalg); - return FALSE; + req.n.nlmsg_len += attr->rta_len; + attr = (struct rtattr *)((char *)attr + attr->rta_len); } - strcpy(algo.alg_name, name); - algo.alg_key_len = sa->enckeylen * BITS_PER_BYTE; + if (sa->compalg) + { + struct xfrm_algo algo; + const char *name; - attr->rta_type = XFRMA_ALG_CRYPT; - attr->rta_len = RTA_LENGTH(sizeof(algo) + sa->enckeylen); + name = sparse_name(calg_list, sa->compalg); + if (!name) { + loglog(RC_LOG_SERIOUS, "unknown compression algorithm: %u" + , sa->compalg); + return FALSE; + } - memcpy(RTA_DATA(attr), &algo, sizeof(algo)); - memcpy((char *)RTA_DATA(attr) + sizeof(algo), sa->enckey - , sa->enckeylen); + strcpy(algo.alg_name, name); + algo.alg_key_len = 0; - req.n.nlmsg_len += attr->rta_len; - attr = (struct rtattr *)((char *)attr + attr->rta_len); - } + attr->rta_type = XFRMA_ALG_COMP; + attr->rta_len = RTA_LENGTH(sizeof(algo)); - if (sa->compalg) - { - struct xfrm_algo algo; - const char *name; + memcpy(RTA_DATA(attr), &algo, sizeof(algo)); - name = sparse_name(calg_list, sa->compalg); - if (!name) { - loglog(RC_LOG_SERIOUS, "unknown compression algorithm: %u" - , sa->compalg); - return FALSE; + req.n.nlmsg_len += attr->rta_len; + attr = (struct rtattr *)((char *)attr + attr->rta_len); } - strcpy(algo.alg_name, name); - algo.alg_key_len = 0; + if (sa->natt_type) + { + struct xfrm_encap_tmpl natt; - attr->rta_type = XFRMA_ALG_COMP; - attr->rta_len = RTA_LENGTH(sizeof(algo)); + natt.encap_type = sa->natt_type; + natt.encap_sport = ntohs(sa->natt_sport); + natt.encap_dport = ntohs(sa->natt_dport); + memset (&natt.encap_oa, 0, sizeof (natt.encap_oa)); - memcpy(RTA_DATA(attr), &algo, sizeof(algo)); + attr->rta_type = XFRMA_ENCAP; + attr->rta_len = RTA_LENGTH(sizeof(natt)); - req.n.nlmsg_len += attr->rta_len; - attr = (struct rtattr *)((char *)attr + attr->rta_len); - } + memcpy(RTA_DATA(attr), &natt, sizeof(natt)); - if (sa->natt_type) - { - struct xfrm_encap_tmpl natt; + req.n.nlmsg_len += attr->rta_len; + attr = (struct rtattr *)((char *)attr + attr->rta_len); + } - natt.encap_type = sa->natt_type; - natt.encap_sport = ntohs(sa->natt_sport); - natt.encap_dport = ntohs(sa->natt_dport); - memset (&natt.encap_oa, 0, sizeof (natt.encap_oa)); - - attr->rta_type = XFRMA_ENCAP; - attr->rta_len = RTA_LENGTH(sizeof(natt)); - - memcpy(RTA_DATA(attr), &natt, sizeof(natt)); - - req.n.nlmsg_len += attr->rta_len; - attr = (struct rtattr *)((char *)attr + attr->rta_len); - } - - return send_netlink_msg(&req.n, NULL, 0, "Add SA", sa->text_said); + return send_netlink_msg(&req.n, NULL, 0, "Add SA", sa->text_said); } /** netlink_del_sa - Delete an SA from the Kernel @@ -707,113 +707,113 @@ netlink_add_sa(const struct kernel_sa *sa, bool replace) static bool netlink_del_sa(const struct kernel_sa *sa) { - struct { - struct nlmsghdr n; - struct xfrm_usersa_id id; - char data[1024]; - } req; + struct { + struct nlmsghdr n; + struct xfrm_usersa_id id; + char data[1024]; + } req; - memset(&req, 0, sizeof(req)); - req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; - req.n.nlmsg_type = XFRM_MSG_DELSA; + memset(&req, 0, sizeof(req)); + req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + req.n.nlmsg_type = XFRM_MSG_DELSA; - ip2xfrm(sa->dst, &req.id.daddr); + ip2xfrm(sa->dst, &req.id.daddr); - req.id.spi = sa->spi; - req.id.family = sa->src->u.v4.sin_family; - req.id.proto = sa->proto; + req.id.spi = sa->spi; + req.id.family = sa->src->u.v4.sin_family; + req.id.proto = sa->proto; - req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.id))); + req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.id))); - return send_netlink_msg(&req.n, NULL, 0, "Del SA", sa->text_said); + return send_netlink_msg(&req.n, NULL, 0, "Del SA", sa->text_said); } static bool netlink_error(const char *req_type, const struct nlmsghdr *n , const struct nlmsgerr *e, int rsp_size) { - if (n->nlmsg_type == NLMSG_ERROR) - { - DBG(DBG_KLIPS, - DBG_log("%s returned with errno %d: %s" - , req_type - , -e->error - , strerror(-e->error)) - ) - return TRUE; - } - if (n->nlmsg_len < NLMSG_LENGTH(rsp_size)) - { - plog("%s returned message with length %lu < %lu bytes" - , req_type - , (unsigned long) n->nlmsg_len - , (unsigned long) rsp_size); - return TRUE; - } - return FALSE; + if (n->nlmsg_type == NLMSG_ERROR) + { + DBG(DBG_KLIPS, + DBG_log("%s returned with errno %d: %s" + , req_type + , -e->error + , strerror(-e->error)) + ) + return TRUE; + } + if (n->nlmsg_len < NLMSG_LENGTH(rsp_size)) + { + plog("%s returned message with length %lu < %lu bytes" + , req_type + , (unsigned long) n->nlmsg_len + , (unsigned long) rsp_size); + return TRUE; + } + return FALSE; } static bool netlink_get_policy(const struct kernel_sa *sa, bool inbound, time_t *use_time) { - struct { - struct nlmsghdr n; - struct xfrm_userpolicy_id id; - } req; + struct { + struct nlmsghdr n; + struct xfrm_userpolicy_id id; + } req; - struct { - struct nlmsghdr n; - union { - struct nlmsgerr e; - struct xfrm_userpolicy_info info; - } u; - char data[1024]; - } rsp; + struct { + struct nlmsghdr n; + union { + struct nlmsgerr e; + struct xfrm_userpolicy_info info; + } u; + char data[1024]; + } rsp; - memset(&req, 0, sizeof(req)); - req.n.nlmsg_flags = NLM_F_REQUEST; - req.n.nlmsg_type = XFRM_MSG_GETPOLICY; + memset(&req, 0, sizeof(req)); + req.n.nlmsg_flags = NLM_F_REQUEST; + req.n.nlmsg_type = XFRM_MSG_GETPOLICY; - req.id.sel.sport = portof(&sa->src_client->addr); - req.id.sel.dport = portof(&sa->dst_client->addr); - req.id.sel.sport_mask = (req.id.sel.sport) ? ~0:0; - req.id.sel.dport_mask = (req.id.sel.dport) ? ~0:0; - ip2xfrm(&sa->src_client->addr, &req.id.sel.saddr); - ip2xfrm(&sa->dst_client->addr, &req.id.sel.daddr); - req.id.sel.prefixlen_s = sa->src_client->maskbits; - req.id.sel.prefixlen_d = sa->dst_client->maskbits; - req.id.sel.proto = sa->transport_proto; - req.id.sel.family = sa->dst_client->addr.u.v4.sin_family; + req.id.sel.sport = portof(&sa->src_client->addr); + req.id.sel.dport = portof(&sa->dst_client->addr); + req.id.sel.sport_mask = (req.id.sel.sport) ? ~0:0; + req.id.sel.dport_mask = (req.id.sel.dport) ? ~0:0; + ip2xfrm(&sa->src_client->addr, &req.id.sel.saddr); + ip2xfrm(&sa->dst_client->addr, &req.id.sel.daddr); + req.id.sel.prefixlen_s = sa->src_client->maskbits; + req.id.sel.prefixlen_d = sa->dst_client->maskbits; + req.id.sel.proto = sa->transport_proto; + req.id.sel.family = sa->dst_client->addr.u.v4.sin_family; - req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.id))); - rsp.n.nlmsg_type = XFRM_MSG_NEWPOLICY; + req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.id))); + rsp.n.nlmsg_type = XFRM_MSG_NEWPOLICY; - req.id.dir = (inbound)? XFRM_POLICY_IN:XFRM_POLICY_OUT; - - if (!send_netlink_msg(&req.n, &rsp.n, sizeof(rsp), "Get policy", "?")) - return FALSE; - - if (netlink_error("XFRM_MSG_GETPOLICY", &rsp.n, &rsp.u.e, sizeof(rsp.u.info))) - return FALSE; - - *use_time = (time_t)rsp.u.info.curlft.use_time; - - if (inbound && sa->encapsulation == ENCAPSULATION_MODE_TUNNEL) - { - time_t use_time_fwd; - - req.id.dir = XFRM_POLICY_FWD; + req.id.dir = (inbound)? XFRM_POLICY_IN:XFRM_POLICY_OUT; if (!send_netlink_msg(&req.n, &rsp.n, sizeof(rsp), "Get policy", "?")) - return FALSE; + return FALSE; if (netlink_error("XFRM_MSG_GETPOLICY", &rsp.n, &rsp.u.e, sizeof(rsp.u.info))) - return FALSE; + return FALSE; - use_time_fwd = (time_t)rsp.u.info.curlft.use_time; - *use_time = (*use_time > use_time_fwd)? *use_time : use_time_fwd; - } - return TRUE; + *use_time = (time_t)rsp.u.info.curlft.use_time; + + if (inbound && sa->encapsulation == ENCAPSULATION_MODE_TUNNEL) + { + time_t use_time_fwd; + + req.id.dir = XFRM_POLICY_FWD; + + if (!send_netlink_msg(&req.n, &rsp.n, sizeof(rsp), "Get policy", "?")) + return FALSE; + + if (netlink_error("XFRM_MSG_GETPOLICY", &rsp.n, &rsp.u.e, sizeof(rsp.u.info))) + return FALSE; + + use_time_fwd = (time_t)rsp.u.info.curlft.use_time; + *use_time = (*use_time > use_time_fwd)? *use_time : use_time_fwd; + } + return TRUE; } @@ -825,60 +825,60 @@ netlink_get_policy(const struct kernel_sa *sa, bool inbound, time_t *use_time) static bool netlink_get_sa(const struct kernel_sa *sa, u_int *bytes) { - struct { - struct nlmsghdr n; - struct xfrm_usersa_id id; - } req; + struct { + struct nlmsghdr n; + struct xfrm_usersa_id id; + } req; - struct { - struct nlmsghdr n; - union { - struct nlmsgerr e; - struct xfrm_usersa_info info; - } u; - char data[1024]; - } rsp; + struct { + struct nlmsghdr n; + union { + struct nlmsgerr e; + struct xfrm_usersa_info info; + } u; + char data[1024]; + } rsp; - memset(&req, 0, sizeof(req)); - req.n.nlmsg_flags = NLM_F_REQUEST; - req.n.nlmsg_type = XFRM_MSG_GETSA; + memset(&req, 0, sizeof(req)); + req.n.nlmsg_flags = NLM_F_REQUEST; + req.n.nlmsg_type = XFRM_MSG_GETSA; - ip2xfrm(sa->dst, &req.id.daddr); + ip2xfrm(sa->dst, &req.id.daddr); - req.id.spi = sa->spi; - req.id.family = sa->src->u.v4.sin_family; - req.id.proto = sa->proto; + req.id.spi = sa->spi; + req.id.family = sa->src->u.v4.sin_family; + req.id.proto = sa->proto; - req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.id))); - rsp.n.nlmsg_type = XFRM_MSG_NEWSA; + req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.id))); + rsp.n.nlmsg_type = XFRM_MSG_NEWSA; - if (!send_netlink_msg(&req.n, &rsp.n, sizeof(rsp), "Get SA", sa->text_said)) - return FALSE; + if (!send_netlink_msg(&req.n, &rsp.n, sizeof(rsp), "Get SA", sa->text_said)) + return FALSE; - if (netlink_error("XFRM_MSG_GETSA", &rsp.n, &rsp.u.e, sizeof(rsp.u.info))) - return FALSE; + if (netlink_error("XFRM_MSG_GETSA", &rsp.n, &rsp.u.e, sizeof(rsp.u.info))) + return FALSE; - *bytes = (u_int) rsp.u.info.curlft.bytes; + *bytes = (u_int) rsp.u.info.curlft.bytes; - return TRUE; + return TRUE; } static void linux_pfkey_register_response(const struct sadb_msg *msg) { - switch (msg->sadb_msg_satype) - { - case SADB_SATYPE_ESP: + switch (msg->sadb_msg_satype) + { + case SADB_SATYPE_ESP: #ifndef NO_KERNEL_ALG - kernel_alg_register_pfkey(msg, msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN); + kernel_alg_register_pfkey(msg, msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN); #endif - break; - case SADB_X_SATYPE_IPCOMP: - can_do_IPcomp = TRUE; - break; - default: - break; - } + break; + case SADB_X_SATYPE_IPCOMP: + can_do_IPcomp = TRUE; + break; + default: + break; + } } /** linux_pfkey_register - Register via PFKEY our capabilities @@ -887,10 +887,10 @@ linux_pfkey_register_response(const struct sadb_msg *msg) static void linux_pfkey_register(void) { - pfkey_register_proto(SADB_SATYPE_AH, "AH"); - pfkey_register_proto(SADB_SATYPE_ESP, "ESP"); - pfkey_register_proto(SADB_X_SATYPE_IPCOMP, "IPCOMP"); - pfkey_close(); + pfkey_register_proto(SADB_SATYPE_AH, "AH"); + pfkey_register_proto(SADB_SATYPE_ESP, "ESP"); + pfkey_register_proto(SADB_X_SATYPE_IPCOMP, "IPCOMP"); + pfkey_close(); } /** Create ip_address out of xfrm_address_t. @@ -903,18 +903,18 @@ linux_pfkey_register(void) static err_t xfrm_to_ip_address(unsigned family, const xfrm_address_t *src, ip_address *dst) { - switch (family) - { - case AF_INET: /* IPv4 */ - case AF_UNSPEC: /* Unspecified, we assume IPv4 */ - initaddr((const void *) &src->a4, sizeof(src->a4), AF_INET, dst); - return NULL; - case AF_INET6: /* IPv6 */ - initaddr((const void *) &src->a6, sizeof(src->a6), AF_INET6, dst); - return NULL; - default: - return "unknown address family"; - } + switch (family) + { + case AF_INET: /* IPv4 */ + case AF_UNSPEC: /* Unspecified, we assume IPv4 */ + initaddr((const void *) &src->a4, sizeof(src->a4), AF_INET, dst); + return NULL; + case AF_INET6: /* IPv6 */ + initaddr((const void *) &src->a6, sizeof(src->a6), AF_INET6, dst); + return NULL; + default: + return "unknown address family"; + } } /* Create a pair of ip_address's out of xfrm_sel. @@ -926,29 +926,29 @@ xfrm_to_ip_address(unsigned family, const xfrm_address_t *src, ip_address *dst) */ static err_t xfrm_sel_to_ip_pair(const struct xfrm_selector *sel - , ip_address *src - , ip_address *dst) + , ip_address *src + , ip_address *dst) { - int family; - err_t ugh; + int family; + err_t ugh; - family = sel->family; + family = sel->family; - if ((ugh = xfrm_to_ip_address(family, &sel->saddr, src)) - || (ugh = xfrm_to_ip_address(family, &sel->daddr, dst))) - return ugh; + if ((ugh = xfrm_to_ip_address(family, &sel->saddr, src)) + || (ugh = xfrm_to_ip_address(family, &sel->daddr, dst))) + return ugh; - /* family has been verified in xfrm_to_ip_address. */ - if (family == AF_INET) - { - src->u.v4.sin_port = sel->sport; - dst->u.v4.sin_port = sel->dport; - } - else - { - src->u.v6.sin6_port = sel->sport; - dst->u.v6.sin6_port = sel->dport; - } + /* family has been verified in xfrm_to_ip_address. */ + if (family == AF_INET) + { + src->u.v4.sin_port = sel->sport; + dst->u.v4.sin_port = sel->dport; + } + else + { + src->u.v6.sin6_port = sel->sport; + dst->u.v6.sin6_port = sel->dport; + } return NULL; } @@ -956,194 +956,194 @@ xfrm_sel_to_ip_pair(const struct xfrm_selector *sel static void netlink_acquire(struct nlmsghdr *n) { - struct xfrm_user_acquire *acquire; - ip_address src, dst; - ip_subnet ours, his; - unsigned transport_proto; - err_t ugh = NULL; + struct xfrm_user_acquire *acquire; + ip_address src, dst; + ip_subnet ours, his; + unsigned transport_proto; + err_t ugh = NULL; - if (n->nlmsg_len < NLMSG_LENGTH(sizeof(*acquire))) - { - plog("netlink_acquire got message with length %lu < %lu bytes; ignore message" - , (unsigned long) n->nlmsg_len - , (unsigned long) sizeof(*acquire)); - return; - } + if (n->nlmsg_len < NLMSG_LENGTH(sizeof(*acquire))) + { + plog("netlink_acquire got message with length %lu < %lu bytes; ignore message" + , (unsigned long) n->nlmsg_len + , (unsigned long) sizeof(*acquire)); + return; + } - acquire = NLMSG_DATA(n); - transport_proto = acquire->sel.proto; + acquire = NLMSG_DATA(n); + transport_proto = acquire->sel.proto; - /* XXX also the type of src/dst should be checked to make sure - * that they aren't v4 to v6 or something goofy - */ - - if (!(ugh = xfrm_sel_to_ip_pair(&acquire->sel, &src, &dst)) - && !(ugh = addrtosubnet(&src, &ours)) - && !(ugh = addrtosubnet(&dst, &his))) - record_and_initiate_opportunistic(&ours, &his, transport_proto - , "%acquire-netlink"); + /* XXX also the type of src/dst should be checked to make sure + * that they aren't v4 to v6 or something goofy + */ - if (ugh != NULL) - plog("XFRM_MSG_ACQUIRE message from kernel malformed: %s", ugh); + if (!(ugh = xfrm_sel_to_ip_pair(&acquire->sel, &src, &dst)) + && !(ugh = addrtosubnet(&src, &ours)) + && !(ugh = addrtosubnet(&dst, &his))) + record_and_initiate_opportunistic(&ours, &his, transport_proto + , "%acquire-netlink"); + + if (ugh != NULL) + plog("XFRM_MSG_ACQUIRE message from kernel malformed: %s", ugh); } static void netlink_shunt_expire(struct xfrm_userpolicy_info *pol) { - ip_address src, dst; - unsigned transport_proto; - err_t ugh = NULL; - - transport_proto = pol->sel.proto; + ip_address src, dst; + unsigned transport_proto; + err_t ugh = NULL; - if (!(ugh = xfrm_sel_to_ip_pair(&pol->sel, &src, &dst))) - { - plog("XFRM_MSG_POLEXPIRE message from kernel malformed: %s", ugh); - return; - } + transport_proto = pol->sel.proto; - replace_bare_shunt(&src, &dst, BOTTOM_PRIO, SPI_PASS, FALSE, transport_proto - , "delete expired bare shunt"); + if (!(ugh = xfrm_sel_to_ip_pair(&pol->sel, &src, &dst))) + { + plog("XFRM_MSG_POLEXPIRE message from kernel malformed: %s", ugh); + return; + } + + replace_bare_shunt(&src, &dst, BOTTOM_PRIO, SPI_PASS, FALSE, transport_proto + , "delete expired bare shunt"); } static void netlink_policy_expire(struct nlmsghdr *n) { - struct xfrm_user_polexpire *upe; - struct { - struct nlmsghdr n; - struct xfrm_userpolicy_id id; - } req; + struct xfrm_user_polexpire *upe; + struct { + struct nlmsghdr n; + struct xfrm_userpolicy_id id; + } req; - struct { - struct nlmsghdr n; - union { - struct nlmsgerr e; - struct xfrm_userpolicy_info pol; - } u; - char data[1024]; - } rsp; + struct { + struct nlmsghdr n; + union { + struct nlmsgerr e; + struct xfrm_userpolicy_info pol; + } u; + char data[1024]; + } rsp; - if (n->nlmsg_len < NLMSG_LENGTH(sizeof(*upe))) - { - plog("netlink_policy_expire got message with length %lu < %lu bytes; ignore message" - , (unsigned long) n->nlmsg_len - , (unsigned long) sizeof(*upe)); - return; - } + if (n->nlmsg_len < NLMSG_LENGTH(sizeof(*upe))) + { + plog("netlink_policy_expire got message with length %lu < %lu bytes; ignore message" + , (unsigned long) n->nlmsg_len + , (unsigned long) sizeof(*upe)); + return; + } - upe = NLMSG_DATA(n); - req.id.dir = upe->pol.dir; - req.id.index = upe->pol.index; - req.n.nlmsg_flags = NLM_F_REQUEST; - req.n.nlmsg_type = XFRM_MSG_GETPOLICY; - req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.id))); + upe = NLMSG_DATA(n); + req.id.dir = upe->pol.dir; + req.id.index = upe->pol.index; + req.n.nlmsg_flags = NLM_F_REQUEST; + req.n.nlmsg_type = XFRM_MSG_GETPOLICY; + req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.id))); - rsp.n.nlmsg_type = XFRM_MSG_NEWPOLICY; + rsp.n.nlmsg_type = XFRM_MSG_NEWPOLICY; - if (!send_netlink_msg(&req.n, &rsp.n, sizeof(rsp), "Get policy", "?")) - return; + if (!send_netlink_msg(&req.n, &rsp.n, sizeof(rsp), "Get policy", "?")) + return; - if (netlink_error("XFRM_MSG_GETPOLICY", &rsp.n, &rsp.u.e, sizeof(rsp.u.pol))) - return; + if (netlink_error("XFRM_MSG_GETPOLICY", &rsp.n, &rsp.u.e, sizeof(rsp.u.pol))) + return; - if (req.id.index != rsp.u.pol.index) - { - DBG(DBG_KLIPS, - DBG_log("netlink_policy_expire: policy was replaced: " - "dir=%d, oldindex=%d, newindex=%d" - , req.id.dir, req.id.index, rsp.u.pol.index)); - return; - } + if (req.id.index != rsp.u.pol.index) + { + DBG(DBG_KLIPS, + DBG_log("netlink_policy_expire: policy was replaced: " + "dir=%d, oldindex=%d, newindex=%d" + , req.id.dir, req.id.index, rsp.u.pol.index)); + return; + } - if (upe->pol.curlft.add_time != rsp.u.pol.curlft.add_time) - { - DBG(DBG_KLIPS, - DBG_log("netlink_policy_expire: policy was replaced " - " and you have won the lottery: " - "dir=%d, index=%d" - , req.id.dir, req.id.index)); - return; - } + if (upe->pol.curlft.add_time != rsp.u.pol.curlft.add_time) + { + DBG(DBG_KLIPS, + DBG_log("netlink_policy_expire: policy was replaced " + " and you have won the lottery: " + "dir=%d, index=%d" + , req.id.dir, req.id.index)); + return; + } - switch (upe->pol.dir) - { - case XFRM_POLICY_OUT: - netlink_shunt_expire(&rsp.u.pol); - break; - } + switch (upe->pol.dir) + { + case XFRM_POLICY_OUT: + netlink_shunt_expire(&rsp.u.pol); + break; + } } static bool netlink_get(void) { - struct { - struct nlmsghdr n; - char data[1024]; - } rsp; - ssize_t r; - struct sockaddr_nl addr; - socklen_t alen; + struct { + struct nlmsghdr n; + char data[1024]; + } rsp; + ssize_t r; + struct sockaddr_nl addr; + socklen_t alen; + + alen = sizeof(addr); + r = recvfrom(netlink_bcast_fd, &rsp, sizeof(rsp), 0 + , (struct sockaddr *)&addr, &alen); + if (r < 0) + { + if (errno == EAGAIN) + return FALSE; + if (errno != EINTR) + log_errno((e, "recvfrom() failed in netlink_get")); + return TRUE; + } + else if ((size_t) r < sizeof(rsp.n)) + { + plog("netlink_get read truncated message: %ld bytes; ignore message" + , (long) r); + return TRUE; + } + else if (addr.nl_pid != 0) + { + /* not for us: ignore */ + DBG(DBG_KLIPS, + DBG_log("netlink_get: ignoring %s message from process %u" + , sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type) + , addr.nl_pid)); + return TRUE; + } + else if ((size_t) r != rsp.n.nlmsg_len) + { + plog("netlink_get read message with length %ld that doesn't equal nlmsg_len %lu bytes; ignore message" + , (long) r + , (unsigned long) rsp.n.nlmsg_len); + return TRUE; + } - alen = sizeof(addr); - r = recvfrom(netlink_bcast_fd, &rsp, sizeof(rsp), 0 - , (struct sockaddr *)&addr, &alen); - if (r < 0) - { - if (errno == EAGAIN) - return FALSE; - if (errno != EINTR) - log_errno((e, "recvfrom() failed in netlink_get")); - return TRUE; - } - else if ((size_t) r < sizeof(rsp.n)) - { - plog("netlink_get read truncated message: %ld bytes; ignore message" - , (long) r); - return TRUE; - } - else if (addr.nl_pid != 0) - { - /* not for us: ignore */ DBG(DBG_KLIPS, - DBG_log("netlink_get: ignoring %s message from process %u" - , sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type) - , addr.nl_pid)); + DBG_log("netlink_get: %s message" + , sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type))); + + switch (rsp.n.nlmsg_type) + { + case XFRM_MSG_ACQUIRE: + netlink_acquire(&rsp.n); + break; + case XFRM_MSG_POLEXPIRE: + netlink_policy_expire(&rsp.n); + break; + default: + /* ignored */ + break; + } + return TRUE; - } - else if ((size_t) r != rsp.n.nlmsg_len) - { - plog("netlink_get read message with length %ld that doesn't equal nlmsg_len %lu bytes; ignore message" - , (long) r - , (unsigned long) rsp.n.nlmsg_len); - return TRUE; - } - - DBG(DBG_KLIPS, - DBG_log("netlink_get: %s message" - , sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type))); - - switch (rsp.n.nlmsg_type) - { - case XFRM_MSG_ACQUIRE: - netlink_acquire(&rsp.n); - break; - case XFRM_MSG_POLEXPIRE: - netlink_policy_expire(&rsp.n); - break; - default: - /* ignored */ - break; - } - - return TRUE; } static void netlink_process_msg(void) { - while (netlink_get()) - ; + while (netlink_get()) + ; } static ipsec_spi_t @@ -1156,65 +1156,65 @@ netlink_get_spi(const ip_address *src , ipsec_spi_t max , const char *text_said) { - struct { - struct nlmsghdr n; - struct xfrm_userspi_info spi; - } req; + struct { + struct nlmsghdr n; + struct xfrm_userspi_info spi; + } req; - struct { - struct nlmsghdr n; - union { - struct nlmsgerr e; - struct xfrm_usersa_info sa; - } u; - char data[1024]; - } rsp; + struct { + struct nlmsghdr n; + union { + struct nlmsgerr e; + struct xfrm_usersa_info sa; + } u; + char data[1024]; + } rsp; - memset(&req, 0, sizeof(req)); - req.n.nlmsg_flags = NLM_F_REQUEST; - req.n.nlmsg_type = XFRM_MSG_ALLOCSPI; + memset(&req, 0, sizeof(req)); + req.n.nlmsg_flags = NLM_F_REQUEST; + req.n.nlmsg_type = XFRM_MSG_ALLOCSPI; - ip2xfrm(src, &req.spi.info.saddr); - ip2xfrm(dst, &req.spi.info.id.daddr); - req.spi.info.mode = tunnel_mode; - req.spi.info.reqid = reqid; - req.spi.info.id.proto = proto; - req.spi.info.family = src->u.v4.sin_family; - req.spi.min = min; - req.spi.max = max; + ip2xfrm(src, &req.spi.info.saddr); + ip2xfrm(dst, &req.spi.info.id.daddr); + req.spi.info.mode = tunnel_mode; + req.spi.info.reqid = reqid; + req.spi.info.id.proto = proto; + req.spi.info.family = src->u.v4.sin_family; + req.spi.min = min; + req.spi.max = max; - req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.spi))); - rsp.n.nlmsg_type = XFRM_MSG_NEWSA; + req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.spi))); + rsp.n.nlmsg_type = XFRM_MSG_NEWSA; - if (!send_netlink_msg(&req.n, &rsp.n, sizeof(rsp), "Get SPI", text_said)) - return 0; + if (!send_netlink_msg(&req.n, &rsp.n, sizeof(rsp), "Get SPI", text_said)) + return 0; - if (netlink_error("XFRM_MSG_ALLOCSPI", &rsp.n, &rsp.u.e, sizeof(rsp.u.sa))) - return 0; + if (netlink_error("XFRM_MSG_ALLOCSPI", &rsp.n, &rsp.u.e, sizeof(rsp.u.sa))) + return 0; - DBG(DBG_KLIPS, - DBG_log("netlink_get_spi: allocated 0x%x for %s" - , ntohl(rsp.u.sa.id.spi), text_said)); - return rsp.u.sa.id.spi; + DBG(DBG_KLIPS, + DBG_log("netlink_get_spi: allocated 0x%x for %s" + , ntohl(rsp.u.sa.id.spi), text_said)); + return rsp.u.sa.id.spi; } const struct kernel_ops linux_kernel_ops = { - type: KERNEL_TYPE_LINUX, - inbound_eroute: 1, - policy_lifetime: 1, - async_fdp: &netlink_bcast_fd, + type: KERNEL_TYPE_LINUX, + inbound_eroute: 1, + policy_lifetime: 1, + async_fdp: &netlink_bcast_fd, - init: init_netlink, - pfkey_register: linux_pfkey_register, - pfkey_register_response: linux_pfkey_register_response, - process_msg: netlink_process_msg, - raw_eroute: netlink_raw_eroute, - get_policy: netlink_get_policy, - add_sa: netlink_add_sa, - del_sa: netlink_del_sa, - get_sa: netlink_get_sa, - process_queue: NULL, - grp_sa: NULL, - get_spi: netlink_get_spi, + init: init_netlink, + pfkey_register: linux_pfkey_register, + pfkey_register_response: linux_pfkey_register_response, + process_msg: netlink_process_msg, + raw_eroute: netlink_raw_eroute, + get_policy: netlink_get_policy, + add_sa: netlink_add_sa, + del_sa: netlink_del_sa, + get_sa: netlink_get_sa, + process_queue: NULL, + grp_sa: NULL, + get_spi: netlink_get_spi, }; #endif /* linux && KLIPS */ diff --git a/src/pluto/kernel_noklips.c b/src/pluto/kernel_noklips.c index 7ded9faf8..4664fc3fe 100644 --- a/src/pluto/kernel_noklips.c +++ b/src/pluto/kernel_noklips.c @@ -39,7 +39,7 @@ #include "kernel.h" #include "kernel_noklips.h" #include "log.h" -#include "whack.h" /* for RC_LOG_SERIOUS */ +#include "whack.h" /* for RC_LOG_SERIOUS */ void init_noklips(void) @@ -71,30 +71,30 @@ noklips_register(void) static bool noklips_raw_eroute(const ip_address *this_host UNUSED - , const ip_subnet *this_client UNUSED - , const ip_address *that_host UNUSED - , const ip_subnet *that_client UNUSED - , ipsec_spi_t spi UNUSED - , unsigned int satype UNUSED - , unsigned int transport_proto UNUSED - , const struct pfkey_proto_info *proto_info UNUSED - , time_t use_lifetime UNUSED - , unsigned int op UNUSED - , const char *text_said UNUSED) + , const ip_subnet *this_client UNUSED + , const ip_address *that_host UNUSED + , const ip_subnet *that_client UNUSED + , ipsec_spi_t spi UNUSED + , unsigned int satype UNUSED + , unsigned int transport_proto UNUSED + , const struct pfkey_proto_info *proto_info UNUSED + , time_t use_lifetime UNUSED + , unsigned int op UNUSED + , const char *text_said UNUSED) { return TRUE; } static bool noklips_add_sa(const struct kernel_sa *sa UNUSED - , bool replace UNUSED) + , bool replace UNUSED) { return TRUE; } static bool noklips_grp_sa(const struct kernel_sa *sa0 UNUSED - , const struct kernel_sa *sa1 UNUSED) + , const struct kernel_sa *sa1 UNUSED) { return TRUE; } @@ -107,20 +107,20 @@ noklips_del_sa(const struct kernel_sa *sa UNUSED) const struct kernel_ops noklips_kernel_ops = { - type: KERNEL_TYPE_NONE, - async_fdp: NULL, - - init: init_noklips, - pfkey_register: noklips_register, - pfkey_register_response: noklips_register_response, - process_queue: noklips_dequeue, - process_msg: noklips_event, - raw_eroute: noklips_raw_eroute, - add_sa: noklips_add_sa, - grp_sa: noklips_grp_sa, - del_sa: noklips_del_sa, - get_sa: NULL, - get_spi: NULL, - inbound_eroute: FALSE, - policy_lifetime: FALSE + type: KERNEL_TYPE_NONE, + async_fdp: NULL, + + init: init_noklips, + pfkey_register: noklips_register, + pfkey_register_response: noklips_register_response, + process_queue: noklips_dequeue, + process_msg: noklips_event, + raw_eroute: noklips_raw_eroute, + add_sa: noklips_add_sa, + grp_sa: noklips_grp_sa, + del_sa: noklips_del_sa, + get_sa: NULL, + get_spi: NULL, + inbound_eroute: FALSE, + policy_lifetime: FALSE }; diff --git a/src/pluto/kernel_pfkey.c b/src/pluto/kernel_pfkey.c index 04c24f5f2..817eb7b6d 100644 --- a/src/pluto/kernel_pfkey.c +++ b/src/pluto/kernel_pfkey.c @@ -40,7 +40,7 @@ #include "kernel.h" #include "kernel_pfkey.h" #include "log.h" -#include "whack.h" /* for RC_LOG_SERIOUS */ +#include "whack.h" /* for RC_LOG_SERIOUS */ #include "demux.h" #include "nat_traversal.h" #include "alg_info.h" @@ -50,64 +50,64 @@ static int pfkeyfd = NULL_FD; typedef u_int32_t pfkey_seq_t; -static pfkey_seq_t pfkey_seq = 0; /* sequence number for our PF_KEY messages */ +static pfkey_seq_t pfkey_seq = 0; /* sequence number for our PF_KEY messages */ static pid_t pid; -#define NE(x) { x, #x } /* Name Entry -- shorthand for sparse_names */ +#define NE(x) { x, #x } /* Name Entry -- shorthand for sparse_names */ static sparse_names pfkey_type_names = { - NE(SADB_RESERVED), - NE(SADB_GETSPI), - NE(SADB_UPDATE), - NE(SADB_ADD), - NE(SADB_DELETE), - NE(SADB_GET), - NE(SADB_ACQUIRE), - NE(SADB_REGISTER), - NE(SADB_EXPIRE), - NE(SADB_FLUSH), - NE(SADB_DUMP), - NE(SADB_X_PROMISC), - NE(SADB_X_PCHANGE), - NE(SADB_X_GRPSA), - NE(SADB_X_ADDFLOW), - NE(SADB_X_DELFLOW), - NE(SADB_X_DEBUG), - NE(SADB_X_NAT_T_NEW_MAPPING), - NE(SADB_MAX), - { 0, sparse_end } + NE(SADB_RESERVED), + NE(SADB_GETSPI), + NE(SADB_UPDATE), + NE(SADB_ADD), + NE(SADB_DELETE), + NE(SADB_GET), + NE(SADB_ACQUIRE), + NE(SADB_REGISTER), + NE(SADB_EXPIRE), + NE(SADB_FLUSH), + NE(SADB_DUMP), + NE(SADB_X_PROMISC), + NE(SADB_X_PCHANGE), + NE(SADB_X_GRPSA), + NE(SADB_X_ADDFLOW), + NE(SADB_X_DELFLOW), + NE(SADB_X_DEBUG), + NE(SADB_X_NAT_T_NEW_MAPPING), + NE(SADB_MAX), + { 0, sparse_end } }; #ifdef NEVER /* not needed yet */ static sparse_names pfkey_ext_names = { - NE(SADB_EXT_RESERVED), - NE(SADB_EXT_SA), - NE(SADB_EXT_LIFETIME_CURRENT), - NE(SADB_EXT_LIFETIME_HARD), - NE(SADB_EXT_LIFETIME_SOFT), - NE(SADB_EXT_ADDRESS_SRC), - NE(SADB_EXT_ADDRESS_DST), - NE(SADB_EXT_ADDRESS_PROXY), - NE(SADB_EXT_KEY_AUTH), - NE(SADB_EXT_KEY_ENCRYPT), - NE(SADB_EXT_IDENTITY_SRC), - NE(SADB_EXT_IDENTITY_DST), - NE(SADB_EXT_SENSITIVITY), - NE(SADB_EXT_PROPOSAL), - NE(SADB_EXT_SUPPORTED_AUTH), - NE(SADB_EXT_SUPPORTED_ENCRYPT), - NE(SADB_EXT_SPIRANGE), - NE(SADB_X_EXT_KMPRIVATE), - NE(SADB_X_EXT_SATYPE2), - NE(SADB_X_EXT_SA2), - NE(SADB_X_EXT_ADDRESS_DST2), - NE(SADB_X_EXT_ADDRESS_SRC_FLOW), - NE(SADB_X_EXT_ADDRESS_DST_FLOW), - NE(SADB_X_EXT_ADDRESS_SRC_MASK), - NE(SADB_X_EXT_ADDRESS_DST_MASK), - NE(SADB_X_EXT_DEBUG), - { 0, sparse_end } + NE(SADB_EXT_RESERVED), + NE(SADB_EXT_SA), + NE(SADB_EXT_LIFETIME_CURRENT), + NE(SADB_EXT_LIFETIME_HARD), + NE(SADB_EXT_LIFETIME_SOFT), + NE(SADB_EXT_ADDRESS_SRC), + NE(SADB_EXT_ADDRESS_DST), + NE(SADB_EXT_ADDRESS_PROXY), + NE(SADB_EXT_KEY_AUTH), + NE(SADB_EXT_KEY_ENCRYPT), + NE(SADB_EXT_IDENTITY_SRC), + NE(SADB_EXT_IDENTITY_DST), + NE(SADB_EXT_SENSITIVITY), + NE(SADB_EXT_PROPOSAL), + NE(SADB_EXT_SUPPORTED_AUTH), + NE(SADB_EXT_SUPPORTED_ENCRYPT), + NE(SADB_EXT_SPIRANGE), + NE(SADB_X_EXT_KMPRIVATE), + NE(SADB_X_EXT_SATYPE2), + NE(SADB_X_EXT_SA2), + NE(SADB_X_EXT_ADDRESS_DST2), + NE(SADB_X_EXT_ADDRESS_SRC_FLOW), + NE(SADB_X_EXT_ADDRESS_DST_FLOW), + NE(SADB_X_EXT_ADDRESS_SRC_MASK), + NE(SADB_X_EXT_ADDRESS_DST_MASK), + NE(SADB_X_EXT_DEBUG), + { 0, sparse_end } }; #endif /* NEVER */ @@ -116,24 +116,24 @@ static sparse_names pfkey_ext_names = { void init_pfkey(void) { - pid = getpid(); + pid = getpid(); - /* open PF_KEY socket */ + /* open PF_KEY socket */ - pfkeyfd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2); + pfkeyfd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2); - if (pfkeyfd == -1) - exit_log_errno((e, "socket() in init_pfkeyfd()")); + if (pfkeyfd == -1) + exit_log_errno((e, "socket() in init_pfkeyfd()")); -#ifdef NEVER /* apparently unsupported! */ - if (fcntl(pfkeyfd, F_SETFL, O_NONBLOCK) != 0) - exit_log_errno((e, "fcntl(O_NONBLOCK) in init_pfkeyfd()")); +#ifdef NEVER /* apparently unsupported! */ + if (fcntl(pfkeyfd, F_SETFL, O_NONBLOCK) != 0) + exit_log_errno((e, "fcntl(O_NONBLOCK) in init_pfkeyfd()")); #endif - if (fcntl(pfkeyfd, F_SETFD, FD_CLOEXEC) != 0) - exit_log_errno((e, "fcntl(FD_CLOEXEC) in init_pfkeyfd()")); + if (fcntl(pfkeyfd, F_SETFD, FD_CLOEXEC) != 0) + exit_log_errno((e, "fcntl(FD_CLOEXEC) in init_pfkeyfd()")); - DBG(DBG_KLIPS, - DBG_log("process %u listening for PF_KEY_V2 on file descriptor %d", (unsigned)pid, pfkeyfd)); + DBG(DBG_KLIPS, + DBG_log("process %u listening for PF_KEY_V2 on file descriptor %d", (unsigned)pid, pfkeyfd)); } /* Kinds of PF_KEY message from the kernel: @@ -153,9 +153,9 @@ init_pfkey(void) */ typedef union { - unsigned char bytes[PFKEYv2_MAX_MSGSIZE]; - struct sadb_msg msg; - } pfkey_buf; + unsigned char bytes[PFKEYv2_MAX_MSGSIZE]; + struct sadb_msg msg; + } pfkey_buf; /* queue of unprocessed PF_KEY messages input from kernel * Note that the pfkey_buf may be partly allocated, reflecting @@ -163,41 +163,41 @@ typedef union { * must come first. */ typedef struct pfkey_item { - struct pfkey_item *next; - pfkey_buf buf; - } pfkey_item; + struct pfkey_item *next; + pfkey_buf buf; + } pfkey_item; -static pfkey_item *pfkey_iq_head = NULL; /* oldest */ -static pfkey_item *pfkey_iq_tail; /* youngest */ +static pfkey_item *pfkey_iq_head = NULL; /* oldest */ +static pfkey_item *pfkey_iq_tail; /* youngest */ static bool pfkey_input_ready(void) { - fd_set readfds; - int ndes; - struct timeval tm; + fd_set readfds; + int ndes; + struct timeval tm; - tm.tv_sec = 0; /* don't wait at all */ - tm.tv_usec = 0; + tm.tv_sec = 0; /* don't wait at all */ + tm.tv_usec = 0; - FD_ZERO(&readfds); /* we only care about pfkeyfd */ - FD_SET(pfkeyfd, &readfds); + FD_ZERO(&readfds); /* we only care about pfkeyfd */ + FD_SET(pfkeyfd, &readfds); - do { - ndes = select(pfkeyfd + 1, &readfds, NULL, NULL, &tm); - } while (ndes == -1 && errno == EINTR); + do { + ndes = select(pfkeyfd + 1, &readfds, NULL, NULL, &tm); + } while (ndes == -1 && errno == EINTR); - if (ndes < 0) - { - log_errno((e, "select() failed in pfkey_get()")); - return FALSE; - } + if (ndes < 0) + { + log_errno((e, "select() failed in pfkey_get()")); + return FALSE; + } - if (ndes == 0) - return FALSE; /* nothing to read */ + if (ndes == 0) + return FALSE; /* nothing to read */ - passert(ndes == 1 && FD_ISSET(pfkeyfd, &readfds)); - return TRUE; + passert(ndes == 1 && FD_ISSET(pfkeyfd, &readfds)); + return TRUE; } /* get a PF_KEY message from kernel. @@ -210,93 +210,93 @@ pfkey_input_ready(void) static bool pfkey_get(pfkey_buf *buf) { - for (;;) - { - /* len must be less than PFKEYv2_MAX_MSGSIZE, - * so it should fit in an int. We use this fact when printing it. - */ - ssize_t len; + for (;;) + { + /* len must be less than PFKEYv2_MAX_MSGSIZE, + * so it should fit in an int. We use this fact when printing it. + */ + ssize_t len; - if (!pfkey_input_ready()) - return FALSE; + if (!pfkey_input_ready()) + return FALSE; - len = read(pfkeyfd, buf->bytes, sizeof(buf->bytes)); + len = read(pfkeyfd, buf->bytes, sizeof(buf->bytes)); - if (len < 0) - { - if (errno == EAGAIN) - return FALSE; + if (len < 0) + { + if (errno == EAGAIN) + return FALSE; - log_errno((e, "read() failed in pfkey_get()")); - return FALSE; + log_errno((e, "read() failed in pfkey_get()")); + return FALSE; + } + else if ((size_t) len < sizeof(buf->msg)) + { + plog("pfkey_get read truncated PF_KEY message: %d bytes; ignoring message" + , (int) len); + } + else if ((size_t) len != buf->msg.sadb_msg_len * IPSEC_PFKEYv2_ALIGN) + { + plog("pfkey_get read PF_KEY message with length %d that doesn't equal sadb_msg_len %u * %u; ignoring message" + , (int) len + , (unsigned) buf->msg.sadb_msg_len + , (unsigned) IPSEC_PFKEYv2_ALIGN); + } + else if (!(buf->msg.sadb_msg_pid == (unsigned)pid + || (buf->msg.sadb_msg_pid == 0 && buf->msg.sadb_msg_type == SADB_ACQUIRE) + || (buf->msg.sadb_msg_type == SADB_REGISTER) + || (buf->msg.sadb_msg_pid == 0 && buf->msg.sadb_msg_type == SADB_X_NAT_T_NEW_MAPPING))) + { + /* not for us: ignore */ + DBG(DBG_KLIPS, + DBG_log("pfkey_get: ignoring PF_KEY %s message %u for process %u" + , sparse_val_show(pfkey_type_names, buf->msg.sadb_msg_type) + , buf->msg.sadb_msg_seq + , buf->msg.sadb_msg_pid)); + } + else + { + DBG(DBG_KLIPS, + DBG_log("pfkey_get: %s message %u" + , sparse_val_show(pfkey_type_names, buf->msg.sadb_msg_type) + , buf->msg.sadb_msg_seq)); + return TRUE; + } } - else if ((size_t) len < sizeof(buf->msg)) - { - plog("pfkey_get read truncated PF_KEY message: %d bytes; ignoring message" - , (int) len); - } - else if ((size_t) len != buf->msg.sadb_msg_len * IPSEC_PFKEYv2_ALIGN) - { - plog("pfkey_get read PF_KEY message with length %d that doesn't equal sadb_msg_len %u * %u; ignoring message" - , (int) len - , (unsigned) buf->msg.sadb_msg_len - , (unsigned) IPSEC_PFKEYv2_ALIGN); - } - else if (!(buf->msg.sadb_msg_pid == (unsigned)pid - || (buf->msg.sadb_msg_pid == 0 && buf->msg.sadb_msg_type == SADB_ACQUIRE) - || (buf->msg.sadb_msg_type == SADB_REGISTER) - || (buf->msg.sadb_msg_pid == 0 && buf->msg.sadb_msg_type == SADB_X_NAT_T_NEW_MAPPING))) - { - /* not for us: ignore */ - DBG(DBG_KLIPS, - DBG_log("pfkey_get: ignoring PF_KEY %s message %u for process %u" - , sparse_val_show(pfkey_type_names, buf->msg.sadb_msg_type) - , buf->msg.sadb_msg_seq - , buf->msg.sadb_msg_pid)); - } - else - { - DBG(DBG_KLIPS, - DBG_log("pfkey_get: %s message %u" - , sparse_val_show(pfkey_type_names, buf->msg.sadb_msg_type) - , buf->msg.sadb_msg_seq)); - return TRUE; - } - } } /* get a response to a specific message */ static bool pfkey_get_response(pfkey_buf *buf, pfkey_seq_t seq) { - while (pfkey_get(buf)) - { - if (buf->msg.sadb_msg_pid == (unsigned)pid - && buf->msg.sadb_msg_seq == seq) + while (pfkey_get(buf)) { - return TRUE; - } - else - { - /* Not for us: queue it. */ - size_t bl = buf->msg.sadb_msg_len * IPSEC_PFKEYv2_ALIGN; - pfkey_item *it = malloc(offsetof(pfkey_item, buf) + bl); + if (buf->msg.sadb_msg_pid == (unsigned)pid + && buf->msg.sadb_msg_seq == seq) + { + return TRUE; + } + else + { + /* Not for us: queue it. */ + size_t bl = buf->msg.sadb_msg_len * IPSEC_PFKEYv2_ALIGN; + pfkey_item *it = malloc(offsetof(pfkey_item, buf) + bl); - memcpy(&it->buf, buf, bl); + memcpy(&it->buf, buf, bl); - it->next = NULL; - if (pfkey_iq_head == NULL) - { - pfkey_iq_head = it; - } - else - { - pfkey_iq_tail->next = it; - } - pfkey_iq_tail = it; + it->next = NULL; + if (pfkey_iq_head == NULL) + { + pfkey_iq_head = it; + } + else + { + pfkey_iq_tail->next = it; + } + pfkey_iq_tail = it; + } } - } - return FALSE; + return FALSE; } /* Process a SADB_REGISTER message from the kernel. @@ -307,34 +307,34 @@ pfkey_get_response(pfkey_buf *buf, pfkey_seq_t seq) static void klips_pfkey_register_response(const struct sadb_msg *msg) { - /* Find out what the kernel can support. - * In fact, the only question at the moment - * is whether it can support IPcomp. - * So we ignore the rest. - * ??? we really should pay attention to what transforms are supported. - */ - switch (msg->sadb_msg_satype) - { - case SADB_SATYPE_AH: - break; - case SADB_SATYPE_ESP: -#ifndef NO_KERNEL_ALG - kernel_alg_register_pfkey(msg, sizeof (pfkey_buf)); -#endif - break; - case SADB_X_SATYPE_COMP: - /* ??? There ought to be an extension to list the - * supported algorithms, but RFC 2367 doesn't - * list one for IPcomp. KLIPS uses SADB_X_CALG_DEFLATE. - * Since we only implement deflate, we'll assume this. + /* Find out what the kernel can support. + * In fact, the only question at the moment + * is whether it can support IPcomp. + * So we ignore the rest. + * ??? we really should pay attention to what transforms are supported. */ - can_do_IPcomp = TRUE; - break; - case SADB_X_SATYPE_IPIP: - break; - default: - break; - } + switch (msg->sadb_msg_satype) + { + case SADB_SATYPE_AH: + break; + case SADB_SATYPE_ESP: +#ifndef NO_KERNEL_ALG + kernel_alg_register_pfkey(msg, sizeof (pfkey_buf)); +#endif + break; + case SADB_X_SATYPE_COMP: + /* ??? There ought to be an extension to list the + * supported algorithms, but RFC 2367 doesn't + * list one for IPcomp. KLIPS uses SADB_X_CALG_DEFLATE. + * Since we only implement deflate, we'll assume this. + */ + can_do_IPcomp = TRUE; + break; + case SADB_X_SATYPE_IPIP: + break; + default: + break; + } } /* Processs a SADB_ACQUIRE message from KLIPS. @@ -357,33 +357,33 @@ klips_pfkey_register_response(const struct sadb_msg *msg) static void process_pfkey_acquire(pfkey_buf *buf, struct sadb_ext *extensions[SADB_EXT_MAX + 1]) { - struct sadb_address *srcx = (void *) extensions[SADB_EXT_ADDRESS_SRC]; - struct sadb_address *dstx = (void *) extensions[SADB_EXT_ADDRESS_DST]; - int src_proto = srcx->sadb_address_proto; - int dst_proto = dstx->sadb_address_proto; - ip_address *src = (ip_address*)&srcx[1]; - ip_address *dst = (ip_address*)&dstx[1]; - ip_subnet ours, his; - err_t ugh = NULL; + struct sadb_address *srcx = (void *) extensions[SADB_EXT_ADDRESS_SRC]; + struct sadb_address *dstx = (void *) extensions[SADB_EXT_ADDRESS_DST]; + int src_proto = srcx->sadb_address_proto; + int dst_proto = dstx->sadb_address_proto; + ip_address *src = (ip_address*)&srcx[1]; + ip_address *dst = (ip_address*)&dstx[1]; + ip_subnet ours, his; + err_t ugh = NULL; - /* assumption: we're only catching our own outgoing packets - * so source is our end and destination is the other end. - * Verifying this is not actually convenient. - * - * This stylized control structure yields a complaint or - * desired results. For compactness, a pointer value is - * treated as a boolean. Logically, the structure is: - * keep going as long as things are OK. - */ - if (buf->msg.sadb_msg_pid == 0 /* we only wish to hear from kernel */ - && !(ugh = src_proto == dst_proto? NULL : "src and dst protocols differ") - && !(ugh = addrtypeof(src) == addrtypeof(dst)? NULL : "conflicting address types") - && !(ugh = addrtosubnet(src, &ours)) - && !(ugh = addrtosubnet(dst, &his))) - record_and_initiate_opportunistic(&ours, &his, src_proto, "%acquire"); + /* assumption: we're only catching our own outgoing packets + * so source is our end and destination is the other end. + * Verifying this is not actually convenient. + * + * This stylized control structure yields a complaint or + * desired results. For compactness, a pointer value is + * treated as a boolean. Logically, the structure is: + * keep going as long as things are OK. + */ + if (buf->msg.sadb_msg_pid == 0 /* we only wish to hear from kernel */ + && !(ugh = src_proto == dst_proto? NULL : "src and dst protocols differ") + && !(ugh = addrtypeof(src) == addrtypeof(dst)? NULL : "conflicting address types") + && !(ugh = addrtosubnet(src, &ours)) + && !(ugh = addrtosubnet(dst, &his))) + record_and_initiate_opportunistic(&ours, &his, src_proto, "%acquire"); - if (ugh != NULL) - plog("SADB_ACQUIRE message from KLIPS malformed: %s", ugh); + if (ugh != NULL) + plog("SADB_ACQUIRE message from KLIPS malformed: %s", ugh); } @@ -394,73 +394,73 @@ process_pfkey_acquire(pfkey_buf *buf, struct sadb_ext *extensions[SADB_EXT_MAX + static void pfkey_async(pfkey_buf *buf) { - struct sadb_ext *extensions[SADB_EXT_MAX + 1]; + struct sadb_ext *extensions[SADB_EXT_MAX + 1]; - if (pfkey_msg_parse(&buf->msg, NULL, extensions, EXT_BITS_OUT)) - { - plog("pfkey_async:" - " unparseable PF_KEY message:" - " %s len=%d, errno=%d, seq=%d, pid=%d; message ignored" - , sparse_val_show(pfkey_type_names, buf->msg.sadb_msg_type) - , buf->msg.sadb_msg_len - , buf->msg.sadb_msg_errno - , buf->msg.sadb_msg_seq - , buf->msg.sadb_msg_pid); - } - else - { - DBG(DBG_CONTROL | DBG_KLIPS, DBG_log("pfkey_async:" - " %s len=%u, errno=%u, satype=%u, seq=%u, pid=%u" - , sparse_val_show(pfkey_type_names, buf->msg.sadb_msg_type) - , buf->msg.sadb_msg_len - , buf->msg.sadb_msg_errno - , buf->msg.sadb_msg_satype - , buf->msg.sadb_msg_seq - , buf->msg.sadb_msg_pid)); - - switch (buf->msg.sadb_msg_type) + if (pfkey_msg_parse(&buf->msg, NULL, extensions, EXT_BITS_OUT)) { - case SADB_REGISTER: - kernel_ops->pfkey_register_response(&buf->msg); - break; - case SADB_ACQUIRE: - /* to simulate loss of ACQUIRE, delete this call */ - process_pfkey_acquire(buf, extensions); - break; - case SADB_X_NAT_T_NEW_MAPPING: - process_pfkey_nat_t_new_mapping(&(buf->msg), extensions); - break; - default: - /* ignored */ - break; + plog("pfkey_async:" + " unparseable PF_KEY message:" + " %s len=%d, errno=%d, seq=%d, pid=%d; message ignored" + , sparse_val_show(pfkey_type_names, buf->msg.sadb_msg_type) + , buf->msg.sadb_msg_len + , buf->msg.sadb_msg_errno + , buf->msg.sadb_msg_seq + , buf->msg.sadb_msg_pid); + } + else + { + DBG(DBG_CONTROL | DBG_KLIPS, DBG_log("pfkey_async:" + " %s len=%u, errno=%u, satype=%u, seq=%u, pid=%u" + , sparse_val_show(pfkey_type_names, buf->msg.sadb_msg_type) + , buf->msg.sadb_msg_len + , buf->msg.sadb_msg_errno + , buf->msg.sadb_msg_satype + , buf->msg.sadb_msg_seq + , buf->msg.sadb_msg_pid)); + + switch (buf->msg.sadb_msg_type) + { + case SADB_REGISTER: + kernel_ops->pfkey_register_response(&buf->msg); + break; + case SADB_ACQUIRE: + /* to simulate loss of ACQUIRE, delete this call */ + process_pfkey_acquire(buf, extensions); + break; + case SADB_X_NAT_T_NEW_MAPPING: + process_pfkey_nat_t_new_mapping(&(buf->msg), extensions); + break; + default: + /* ignored */ + break; + } } - } } /* asynchronous messages from our queue */ static void pfkey_dequeue(void) { - while (pfkey_iq_head != NULL) - { - pfkey_item *it = pfkey_iq_head; + while (pfkey_iq_head != NULL) + { + pfkey_item *it = pfkey_iq_head; - pfkey_async(&it->buf); - pfkey_iq_head = it->next; - free(it); - } + pfkey_async(&it->buf); + pfkey_iq_head = it->next; + free(it); + } - /* Handle any orphaned holds, but only if no pfkey input is pending. - * For each, we initiate Opportunistic. - * note: we don't need to advance the pointer because - * record_and_initiate_opportunistic will remove the current - * record each time we call it. - */ - while (orphaned_holds != NULL && !pfkey_input_ready()) - record_and_initiate_opportunistic(&orphaned_holds->ours - , &orphaned_holds->his - , orphaned_holds->transport_proto - , "%hold found-pfkey"); + /* Handle any orphaned holds, but only if no pfkey input is pending. + * For each, we initiate Opportunistic. + * note: we don't need to advance the pointer because + * record_and_initiate_opportunistic will remove the current + * record each time we call it. + */ + while (orphaned_holds != NULL && !pfkey_input_ready()) + record_and_initiate_opportunistic(&orphaned_holds->ours + , &orphaned_holds->his + , orphaned_holds->transport_proto + , "%hold found-pfkey"); } @@ -468,10 +468,10 @@ pfkey_dequeue(void) static void pfkey_event(void) { - pfkey_buf buf; + pfkey_buf buf; - if (pfkey_get(&buf)) - pfkey_async(&buf); + if (pfkey_get(&buf)) + pfkey_async(&buf); } static bool @@ -480,17 +480,17 @@ pfkey_build(int error , const char *text_said , struct sadb_ext *extensions[SADB_EXT_MAX + 1]) { - if (error == 0) - { - return TRUE; - } - else - { - loglog(RC_LOG_SERIOUS, "building of %s %s failed, code %d" - , description, text_said, error); - pfkey_extensions_free(extensions); - return FALSE; - } + if (error == 0) + { + return TRUE; + } + else + { + loglog(RC_LOG_SERIOUS, "building of %s %s failed, code %d" + , description, text_said, error); + pfkey_extensions_free(extensions); + return FALSE; + } } /* pfkey_extensions_init + pfkey_build + pfkey_msg_hdr_build */ @@ -501,10 +501,10 @@ pfkey_msg_start(u_int8_t msg_type , const char *text_said , struct sadb_ext *extensions[SADB_EXT_MAX + 1]) { - pfkey_extensions_init(extensions); - return pfkey_build(pfkey_msg_hdr_build(&extensions[0], msg_type - , satype, 0, ++pfkey_seq, pid) - , description, text_said, extensions); + pfkey_extensions_init(extensions); + return pfkey_build(pfkey_msg_hdr_build(&extensions[0], msg_type + , satype, 0, ++pfkey_seq, pid) + , description, text_said, extensions); } /* pfkey_build + pfkey_address_build */ @@ -515,15 +515,15 @@ pfkeyext_address(u_int16_t exttype , const char *text_said , struct sadb_ext *extensions[SADB_EXT_MAX + 1]) { - /* the following variable is only needed to silence - * a warning caused by the fact that the argument - * to sockaddrof is NOT pointer to const! - */ - ip_address t = *address; + /* the following variable is only needed to silence + * a warning caused by the fact that the argument + * to sockaddrof is NOT pointer to const! + */ + ip_address t = *address; - return pfkey_build(pfkey_address_build(extensions + exttype - , exttype, 0, 0, sockaddrof(&t)) - , description, text_said, extensions); + return pfkey_build(pfkey_address_build(extensions + exttype + , exttype, 0, 0, sockaddrof(&t)) + , description, text_said, extensions); } /* pfkey_build + pfkey_x_protocol_build */ @@ -533,10 +533,10 @@ pfkeyext_protocol(int transport_proto , const char *text_said , struct sadb_ext *extensions[SADB_EXT_MAX + 1]) { - return (transport_proto == 0)? TRUE - : pfkey_build( - pfkey_x_protocol_build(extensions + SADB_X_EXT_PROTOCOL, transport_proto) - , description, text_said, extensions); + return (transport_proto == 0)? TRUE + : pfkey_build( + pfkey_x_protocol_build(extensions + SADB_X_EXT_PROTOCOL, transport_proto) + , description, text_said, extensions); } @@ -551,376 +551,376 @@ finish_pfkey_msg(struct sadb_ext *extensions[SADB_EXT_MAX + 1] , const char *text_said , pfkey_buf *response) { - struct sadb_msg *pfkey_msg; - bool success = TRUE; - int error; + struct sadb_msg *pfkey_msg; + bool success = TRUE; + int error; - error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_IN); + error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_IN); - if (error != 0) - { - loglog(RC_LOG_SERIOUS, "pfkey_msg_build of %s %s failed, code %d" - , description, text_said, error); - success = FALSE; - } - else - { - size_t len = pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN; - - DBG(DBG_KLIPS, - DBG_log("finish_pfkey_msg: %s message %u for %s %s" - , sparse_val_show(pfkey_type_names, pfkey_msg->sadb_msg_type) - , pfkey_msg->sadb_msg_seq - , description, text_said); - DBG_dump(NULL, (void *) pfkey_msg, len)); - - if (!no_klips) + if (error != 0) { - ssize_t r = write(pfkeyfd, pfkey_msg, len); - - if (r != (ssize_t)len) - { - if (r < 0) - { - log_errno((e - , "pfkey write() of %s message %u" - " for %s %s failed" - , sparse_val_show(pfkey_type_names - , pfkey_msg->sadb_msg_type) - , pfkey_msg->sadb_msg_seq - , description, text_said)); - } - else - { - loglog(RC_LOG_SERIOUS - , "ERROR: pfkey write() of %s message %u" - " for %s %s truncated: %ld instead of %ld" - , sparse_val_show(pfkey_type_names - , pfkey_msg->sadb_msg_type) - , pfkey_msg->sadb_msg_seq - , description, text_said - , (long)r, (long)len); - } + loglog(RC_LOG_SERIOUS, "pfkey_msg_build of %s %s failed, code %d" + , description, text_said, error); success = FALSE; - - /* if we were compiled with debugging, but we haven't already - * dumped the KLIPS command, do so. - */ -#ifdef DEBUG - if ((cur_debugging & DBG_KLIPS) == 0) - DBG_dump(NULL, (void *) pfkey_msg, len); -#endif - } - else - { - /* Check response from KLIPS. - * It ought to be an echo, perhaps with additional info. - * If the caller wants it, response will point to space. - */ - pfkey_buf b; - pfkey_buf *bp = response != NULL? response : &b; - - if (!pfkey_get_response(bp, ((struct sadb_msg *) extensions[0])->sadb_msg_seq)) - { - loglog(RC_LOG_SERIOUS - , "ERROR: no response to our PF_KEY %s message for %s %s" - , sparse_val_show(pfkey_type_names, pfkey_msg->sadb_msg_type) - , description, text_said); - success = FALSE; - } - else if (pfkey_msg->sadb_msg_type != bp->msg.sadb_msg_type) - { - loglog(RC_LOG_SERIOUS - , "FreeS/WAN ERROR: response to our PF_KEY %s message for %s %s was of wrong type (%s)" - , sparse_name(pfkey_type_names, pfkey_msg->sadb_msg_type) - , description, text_said - , sparse_val_show(pfkey_type_names, bp->msg.sadb_msg_type)); - success = FALSE; - } - else if (response == NULL && bp->msg.sadb_msg_errno != 0) - { - /* KLIPS is signalling a problem */ - loglog(RC_LOG_SERIOUS - , "ERROR: PF_KEY %s response for %s %s included errno %u: %s" - , sparse_val_show(pfkey_type_names, pfkey_msg->sadb_msg_type) - , description, text_said - , (unsigned) bp->msg.sadb_msg_errno - , strerror(bp->msg.sadb_msg_errno)); - success = FALSE; - } - } } - } + else + { + size_t len = pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN; - /* all paths must exit this way to free resources */ - pfkey_extensions_free(extensions); - pfkey_msg_free(&pfkey_msg); - return success; + DBG(DBG_KLIPS, + DBG_log("finish_pfkey_msg: %s message %u for %s %s" + , sparse_val_show(pfkey_type_names, pfkey_msg->sadb_msg_type) + , pfkey_msg->sadb_msg_seq + , description, text_said); + DBG_dump(NULL, (void *) pfkey_msg, len)); + + if (!no_klips) + { + ssize_t r = write(pfkeyfd, pfkey_msg, len); + + if (r != (ssize_t)len) + { + if (r < 0) + { + log_errno((e + , "pfkey write() of %s message %u" + " for %s %s failed" + , sparse_val_show(pfkey_type_names + , pfkey_msg->sadb_msg_type) + , pfkey_msg->sadb_msg_seq + , description, text_said)); + } + else + { + loglog(RC_LOG_SERIOUS + , "ERROR: pfkey write() of %s message %u" + " for %s %s truncated: %ld instead of %ld" + , sparse_val_show(pfkey_type_names + , pfkey_msg->sadb_msg_type) + , pfkey_msg->sadb_msg_seq + , description, text_said + , (long)r, (long)len); + } + success = FALSE; + + /* if we were compiled with debugging, but we haven't already + * dumped the KLIPS command, do so. + */ +#ifdef DEBUG + if ((cur_debugging & DBG_KLIPS) == 0) + DBG_dump(NULL, (void *) pfkey_msg, len); +#endif + } + else + { + /* Check response from KLIPS. + * It ought to be an echo, perhaps with additional info. + * If the caller wants it, response will point to space. + */ + pfkey_buf b; + pfkey_buf *bp = response != NULL? response : &b; + + if (!pfkey_get_response(bp, ((struct sadb_msg *) extensions[0])->sadb_msg_seq)) + { + loglog(RC_LOG_SERIOUS + , "ERROR: no response to our PF_KEY %s message for %s %s" + , sparse_val_show(pfkey_type_names, pfkey_msg->sadb_msg_type) + , description, text_said); + success = FALSE; + } + else if (pfkey_msg->sadb_msg_type != bp->msg.sadb_msg_type) + { + loglog(RC_LOG_SERIOUS + , "FreeS/WAN ERROR: response to our PF_KEY %s message for %s %s was of wrong type (%s)" + , sparse_name(pfkey_type_names, pfkey_msg->sadb_msg_type) + , description, text_said + , sparse_val_show(pfkey_type_names, bp->msg.sadb_msg_type)); + success = FALSE; + } + else if (response == NULL && bp->msg.sadb_msg_errno != 0) + { + /* KLIPS is signalling a problem */ + loglog(RC_LOG_SERIOUS + , "ERROR: PF_KEY %s response for %s %s included errno %u: %s" + , sparse_val_show(pfkey_type_names, pfkey_msg->sadb_msg_type) + , description, text_said + , (unsigned) bp->msg.sadb_msg_errno + , strerror(bp->msg.sadb_msg_errno)); + success = FALSE; + } + } + } + } + + /* all paths must exit this way to free resources */ + pfkey_extensions_free(extensions); + pfkey_msg_free(&pfkey_msg); + return success; } /* register SA types that can be negotiated */ void pfkey_register_proto(unsigned satype, const char *satypename) { - struct sadb_ext *extensions[SADB_EXT_MAX + 1]; - pfkey_buf pfb; + struct sadb_ext *extensions[SADB_EXT_MAX + 1]; + pfkey_buf pfb; - if (!(pfkey_msg_start(SADB_REGISTER - , satype - , satypename, NULL, extensions) - && finish_pfkey_msg(extensions, satypename, "", &pfb))) - { - /* ??? should this be loglog */ - plog("no KLIPS support for %s", satypename); - } - else - { - kernel_ops->pfkey_register_response(&pfb.msg); - DBG(DBG_KLIPS, - DBG_log("%s registered with kernel.", satypename)); - } + if (!(pfkey_msg_start(SADB_REGISTER + , satype + , satypename, NULL, extensions) + && finish_pfkey_msg(extensions, satypename, "", &pfb))) + { + /* ??? should this be loglog */ + plog("no KLIPS support for %s", satypename); + } + else + { + kernel_ops->pfkey_register_response(&pfb.msg); + DBG(DBG_KLIPS, + DBG_log("%s registered with kernel.", satypename)); + } } static void klips_pfkey_register(void) { - pfkey_register_proto(SADB_SATYPE_AH, "AH"); - pfkey_register_proto(SADB_SATYPE_ESP, "ESP"); - can_do_IPcomp = FALSE; /* until we get a response from KLIPS */ - pfkey_register_proto(SADB_X_SATYPE_COMP, "IPCOMP"); - pfkey_register_proto(SADB_X_SATYPE_IPIP, "IPIP"); + pfkey_register_proto(SADB_SATYPE_AH, "AH"); + pfkey_register_proto(SADB_SATYPE_ESP, "ESP"); + can_do_IPcomp = FALSE; /* until we get a response from KLIPS */ + pfkey_register_proto(SADB_X_SATYPE_COMP, "IPCOMP"); + pfkey_register_proto(SADB_X_SATYPE_IPIP, "IPIP"); } static bool pfkey_raw_eroute(const ip_address *this_host - , const ip_subnet *this_client - , const ip_address *that_host - , const ip_subnet *that_client - , ipsec_spi_t spi - , unsigned int satype - , unsigned int transport_proto - , const struct pfkey_proto_info *proto_info UNUSED - , time_t use_lifetime UNUSED - , unsigned int op - , const char *text_said) + , const ip_subnet *this_client + , const ip_address *that_host + , const ip_subnet *that_client + , ipsec_spi_t spi + , unsigned int satype + , unsigned int transport_proto + , const struct pfkey_proto_info *proto_info UNUSED + , time_t use_lifetime UNUSED + , unsigned int op + , const char *text_said) { - struct sadb_ext *extensions[SADB_EXT_MAX + 1]; - ip_address - sflow_ska, - dflow_ska, - smask_ska, - dmask_ska; - int sport = ntohs(portof(&this_client->addr)); - int dport = ntohs(portof(&that_client->addr)); + struct sadb_ext *extensions[SADB_EXT_MAX + 1]; + ip_address + sflow_ska, + dflow_ska, + smask_ska, + dmask_ska; + int sport = ntohs(portof(&this_client->addr)); + int dport = ntohs(portof(&that_client->addr)); - networkof(this_client, &sflow_ska); - maskof(this_client, &smask_ska); - setportof(sport ? ~0:0, &smask_ska); + networkof(this_client, &sflow_ska); + maskof(this_client, &smask_ska); + setportof(sport ? ~0:0, &smask_ska); - networkof(that_client, &dflow_ska); - maskof(that_client, &dmask_ska); - setportof(dport ? ~0:0, &dmask_ska); + networkof(that_client, &dflow_ska); + maskof(that_client, &dmask_ska); + setportof(dport ? ~0:0, &dmask_ska); - if (!pfkey_msg_start(op & ERO_MASK, satype - , "pfkey_msg_hdr flow", text_said, extensions)) - { - return FALSE; - } - - if (op != ERO_DELETE) - { - if (!(pfkey_build(pfkey_sa_build(&extensions[SADB_EXT_SA] - , SADB_EXT_SA - , spi /* in network order */ - , 0, 0, 0, 0, op >> ERO_FLAG_SHIFT) - , "pfkey_sa add flow", text_said, extensions) - - && pfkeyext_address(SADB_EXT_ADDRESS_SRC, this_host - , "pfkey_addr_s add flow", text_said, extensions) - - && pfkeyext_address(SADB_EXT_ADDRESS_DST, that_host - , "pfkey_addr_d add flow", text_said - , extensions))) + if (!pfkey_msg_start(op & ERO_MASK, satype + , "pfkey_msg_hdr flow", text_said, extensions)) { - return FALSE; + return FALSE; } - } - if (!pfkeyext_address(SADB_X_EXT_ADDRESS_SRC_FLOW, &sflow_ska - , "pfkey_addr_sflow", text_said, extensions)) - { - return FALSE; - } + if (op != ERO_DELETE) + { + if (!(pfkey_build(pfkey_sa_build(&extensions[SADB_EXT_SA] + , SADB_EXT_SA + , spi /* in network order */ + , 0, 0, 0, 0, op >> ERO_FLAG_SHIFT) + , "pfkey_sa add flow", text_said, extensions) - if (!pfkeyext_address(SADB_X_EXT_ADDRESS_DST_FLOW, &dflow_ska - , "pfkey_addr_dflow", text_said, extensions)) - { - return FALSE; - } + && pfkeyext_address(SADB_EXT_ADDRESS_SRC, this_host + , "pfkey_addr_s add flow", text_said, extensions) - if (!pfkeyext_address(SADB_X_EXT_ADDRESS_SRC_MASK, &smask_ska - , "pfkey_addr_smask", text_said, extensions)) - { - return FALSE; - } + && pfkeyext_address(SADB_EXT_ADDRESS_DST, that_host + , "pfkey_addr_d add flow", text_said + , extensions))) + { + return FALSE; + } + } - if (!pfkeyext_address(SADB_X_EXT_ADDRESS_DST_MASK, &dmask_ska - , "pfkey_addr_dmask", text_said, extensions)) - { - return FALSE; - } + if (!pfkeyext_address(SADB_X_EXT_ADDRESS_SRC_FLOW, &sflow_ska + , "pfkey_addr_sflow", text_said, extensions)) + { + return FALSE; + } - if (!pfkeyext_protocol(transport_proto - , "pfkey_x_protocol", text_said, extensions)) - { - return FALSE; - } + if (!pfkeyext_address(SADB_X_EXT_ADDRESS_DST_FLOW, &dflow_ska + , "pfkey_addr_dflow", text_said, extensions)) + { + return FALSE; + } - return finish_pfkey_msg(extensions, "flow", text_said, NULL); + if (!pfkeyext_address(SADB_X_EXT_ADDRESS_SRC_MASK, &smask_ska + , "pfkey_addr_smask", text_said, extensions)) + { + return FALSE; + } + + if (!pfkeyext_address(SADB_X_EXT_ADDRESS_DST_MASK, &dmask_ska + , "pfkey_addr_dmask", text_said, extensions)) + { + return FALSE; + } + + if (!pfkeyext_protocol(transport_proto + , "pfkey_x_protocol", text_said, extensions)) + { + return FALSE; + } + + return finish_pfkey_msg(extensions, "flow", text_said, NULL); } static bool pfkey_add_sa(const struct kernel_sa *sa, bool replace) { - struct sadb_ext *extensions[SADB_EXT_MAX + 1]; + struct sadb_ext *extensions[SADB_EXT_MAX + 1]; - return pfkey_msg_start(replace ? SADB_UPDATE : SADB_ADD, sa->satype - , "pfkey_msg_hdr Add SA", sa->text_said, extensions) + return pfkey_msg_start(replace ? SADB_UPDATE : SADB_ADD, sa->satype + , "pfkey_msg_hdr Add SA", sa->text_said, extensions) - && pfkey_build(pfkey_sa_build(&extensions[SADB_EXT_SA] - , SADB_EXT_SA - , sa->spi /* in network order */ - , sa->replay_window, SADB_SASTATE_MATURE - , sa->authalg, sa->encalg ? sa->encalg: sa->compalg, 0) - , "pfkey_sa Add SA", sa->text_said, extensions) + && pfkey_build(pfkey_sa_build(&extensions[SADB_EXT_SA] + , SADB_EXT_SA + , sa->spi /* in network order */ + , sa->replay_window, SADB_SASTATE_MATURE + , sa->authalg, sa->encalg ? sa->encalg: sa->compalg, 0) + , "pfkey_sa Add SA", sa->text_said, extensions) - && pfkeyext_address(SADB_EXT_ADDRESS_SRC, sa->src - , "pfkey_addr_s Add SA", sa->text_said, extensions) + && pfkeyext_address(SADB_EXT_ADDRESS_SRC, sa->src + , "pfkey_addr_s Add SA", sa->text_said, extensions) - && pfkeyext_address(SADB_EXT_ADDRESS_DST, sa->dst - , "pfkey_addr_d Add SA", sa->text_said, extensions) + && pfkeyext_address(SADB_EXT_ADDRESS_DST, sa->dst + , "pfkey_addr_d Add SA", sa->text_said, extensions) - && (sa->authkeylen == 0 - || pfkey_build(pfkey_key_build(&extensions[SADB_EXT_KEY_AUTH] - , SADB_EXT_KEY_AUTH, sa->authkeylen * BITS_PER_BYTE - , sa->authkey) - , "pfkey_key_a Add SA", sa->text_said, extensions)) + && (sa->authkeylen == 0 + || pfkey_build(pfkey_key_build(&extensions[SADB_EXT_KEY_AUTH] + , SADB_EXT_KEY_AUTH, sa->authkeylen * BITS_PER_BYTE + , sa->authkey) + , "pfkey_key_a Add SA", sa->text_said, extensions)) - && (sa->enckeylen == 0 - || pfkey_build(pfkey_key_build(&extensions[SADB_EXT_KEY_ENCRYPT] - , SADB_EXT_KEY_ENCRYPT, sa->enckeylen * BITS_PER_BYTE - , sa->enckey) - , "pfkey_key_e Add SA", sa->text_said, extensions)) + && (sa->enckeylen == 0 + || pfkey_build(pfkey_key_build(&extensions[SADB_EXT_KEY_ENCRYPT] + , SADB_EXT_KEY_ENCRYPT, sa->enckeylen * BITS_PER_BYTE + , sa->enckey) + , "pfkey_key_e Add SA", sa->text_said, extensions)) - && (sa->natt_type == 0 - || pfkey_build(pfkey_x_nat_t_type_build( - &extensions[SADB_X_EXT_NAT_T_TYPE], sa->natt_type), - "pfkey_nat_t_type Add ESP SA", sa->text_said, extensions)) - && (sa->natt_sport == 0 - || pfkey_build(pfkey_x_nat_t_port_build( - &extensions[SADB_X_EXT_NAT_T_SPORT], SADB_X_EXT_NAT_T_SPORT, - sa->natt_sport), "pfkey_nat_t_sport Add ESP SA", sa->text_said, - extensions)) - && (sa->natt_dport == 0 - || pfkey_build(pfkey_x_nat_t_port_build( - &extensions[SADB_X_EXT_NAT_T_DPORT], SADB_X_EXT_NAT_T_DPORT, - sa->natt_dport), "pfkey_nat_t_dport Add ESP SA", sa->text_said, - extensions)) - && (sa->natt_type == 0 || isanyaddr(sa->natt_oa) - || pfkeyext_address(SADB_X_EXT_NAT_T_OA, sa->natt_oa - , "pfkey_nat_t_oa Add ESP SA", sa->text_said, extensions)) + && (sa->natt_type == 0 + || pfkey_build(pfkey_x_nat_t_type_build( + &extensions[SADB_X_EXT_NAT_T_TYPE], sa->natt_type), + "pfkey_nat_t_type Add ESP SA", sa->text_said, extensions)) + && (sa->natt_sport == 0 + || pfkey_build(pfkey_x_nat_t_port_build( + &extensions[SADB_X_EXT_NAT_T_SPORT], SADB_X_EXT_NAT_T_SPORT, + sa->natt_sport), "pfkey_nat_t_sport Add ESP SA", sa->text_said, + extensions)) + && (sa->natt_dport == 0 + || pfkey_build(pfkey_x_nat_t_port_build( + &extensions[SADB_X_EXT_NAT_T_DPORT], SADB_X_EXT_NAT_T_DPORT, + sa->natt_dport), "pfkey_nat_t_dport Add ESP SA", sa->text_said, + extensions)) + && (sa->natt_type == 0 || isanyaddr(sa->natt_oa) + || pfkeyext_address(SADB_X_EXT_NAT_T_OA, sa->natt_oa + , "pfkey_nat_t_oa Add ESP SA", sa->text_said, extensions)) - && finish_pfkey_msg(extensions, "Add SA", sa->text_said, NULL); + && finish_pfkey_msg(extensions, "Add SA", sa->text_said, NULL); } static bool pfkey_grp_sa(const struct kernel_sa *sa0, const struct kernel_sa *sa1) { - struct sadb_ext *extensions[SADB_EXT_MAX + 1]; + struct sadb_ext *extensions[SADB_EXT_MAX + 1]; - return pfkey_msg_start(SADB_X_GRPSA, sa1->satype - , "pfkey_msg_hdr group", sa1->text_said, extensions) + return pfkey_msg_start(SADB_X_GRPSA, sa1->satype + , "pfkey_msg_hdr group", sa1->text_said, extensions) - && pfkey_build(pfkey_sa_build(&extensions[SADB_EXT_SA] - , SADB_EXT_SA - , sa1->spi /* in network order */ - , 0, 0, 0, 0, 0) - , "pfkey_sa group", sa1->text_said, extensions) + && pfkey_build(pfkey_sa_build(&extensions[SADB_EXT_SA] + , SADB_EXT_SA + , sa1->spi /* in network order */ + , 0, 0, 0, 0, 0) + , "pfkey_sa group", sa1->text_said, extensions) - && pfkeyext_address(SADB_EXT_ADDRESS_DST, sa1->dst - , "pfkey_addr_d group", sa1->text_said, extensions) + && pfkeyext_address(SADB_EXT_ADDRESS_DST, sa1->dst + , "pfkey_addr_d group", sa1->text_said, extensions) - && pfkey_build(pfkey_x_satype_build(&extensions[SADB_X_EXT_SATYPE2] - , sa0->satype) - , "pfkey_satype group", sa0->text_said, extensions) + && pfkey_build(pfkey_x_satype_build(&extensions[SADB_X_EXT_SATYPE2] + , sa0->satype) + , "pfkey_satype group", sa0->text_said, extensions) - && pfkey_build(pfkey_sa_build(&extensions[SADB_X_EXT_SA2] - , SADB_X_EXT_SA2 - , sa0->spi /* in network order */ - , 0, 0, 0, 0, 0) - , "pfkey_sa2 group", sa0->text_said, extensions) + && pfkey_build(pfkey_sa_build(&extensions[SADB_X_EXT_SA2] + , SADB_X_EXT_SA2 + , sa0->spi /* in network order */ + , 0, 0, 0, 0, 0) + , "pfkey_sa2 group", sa0->text_said, extensions) - && pfkeyext_address(SADB_X_EXT_ADDRESS_DST2, sa0->dst - , "pfkey_addr_d2 group", sa0->text_said, extensions) + && pfkeyext_address(SADB_X_EXT_ADDRESS_DST2, sa0->dst + , "pfkey_addr_d2 group", sa0->text_said, extensions) - && finish_pfkey_msg(extensions, "group", sa1->text_said, NULL); + && finish_pfkey_msg(extensions, "group", sa1->text_said, NULL); } static bool pfkey_del_sa(const struct kernel_sa *sa) { - struct sadb_ext *extensions[SADB_EXT_MAX + 1]; + struct sadb_ext *extensions[SADB_EXT_MAX + 1]; - return pfkey_msg_start(SADB_DELETE, proto2satype(sa->proto) - , "pfkey_msg_hdr delete SA", sa->text_said, extensions) + return pfkey_msg_start(SADB_DELETE, proto2satype(sa->proto) + , "pfkey_msg_hdr delete SA", sa->text_said, extensions) - && pfkey_build(pfkey_sa_build(&extensions[SADB_EXT_SA] - , SADB_EXT_SA - , sa->spi /* in host order */ - , 0, SADB_SASTATE_MATURE, 0, 0, 0) - , "pfkey_sa delete SA", sa->text_said, extensions) + && pfkey_build(pfkey_sa_build(&extensions[SADB_EXT_SA] + , SADB_EXT_SA + , sa->spi /* in host order */ + , 0, SADB_SASTATE_MATURE, 0, 0, 0) + , "pfkey_sa delete SA", sa->text_said, extensions) - && pfkeyext_address(SADB_EXT_ADDRESS_SRC, sa->src - , "pfkey_addr_s delete SA", sa->text_said, extensions) + && pfkeyext_address(SADB_EXT_ADDRESS_SRC, sa->src + , "pfkey_addr_s delete SA", sa->text_said, extensions) - && pfkeyext_address(SADB_EXT_ADDRESS_DST, sa->dst - , "pfkey_addr_d delete SA", sa->text_said, extensions) + && pfkeyext_address(SADB_EXT_ADDRESS_DST, sa->dst + , "pfkey_addr_d delete SA", sa->text_said, extensions) - && finish_pfkey_msg(extensions, "Delete SA", sa->text_said, NULL); + && finish_pfkey_msg(extensions, "Delete SA", sa->text_said, NULL); } void pfkey_close(void) { - while (pfkey_iq_head != NULL) - { - pfkey_item *it = pfkey_iq_head; + while (pfkey_iq_head != NULL) + { + pfkey_item *it = pfkey_iq_head; - pfkey_iq_head = it->next; - free(it); - } + pfkey_iq_head = it->next; + free(it); + } - close(pfkeyfd); - pfkeyfd = NULL_FD; + close(pfkeyfd); + pfkeyfd = NULL_FD; } const struct kernel_ops klips_kernel_ops = { - type: KERNEL_TYPE_KLIPS, - async_fdp: &pfkeyfd, + type: KERNEL_TYPE_KLIPS, + async_fdp: &pfkeyfd, - pfkey_register: klips_pfkey_register, - pfkey_register_response: klips_pfkey_register_response, - process_queue: pfkey_dequeue, - process_msg: pfkey_event, - raw_eroute: pfkey_raw_eroute, - add_sa: pfkey_add_sa, - grp_sa: pfkey_grp_sa, - del_sa: pfkey_del_sa, - get_sa: NULL, - get_spi: NULL, - inbound_eroute: FALSE, - policy_lifetime: FALSE, - init: NULL + pfkey_register: klips_pfkey_register, + pfkey_register_response: klips_pfkey_register_response, + process_queue: pfkey_dequeue, + process_msg: pfkey_event, + raw_eroute: pfkey_raw_eroute, + add_sa: pfkey_add_sa, + grp_sa: pfkey_grp_sa, + del_sa: pfkey_del_sa, + get_sa: NULL, + get_spi: NULL, + inbound_eroute: FALSE, + policy_lifetime: FALSE, + init: NULL }; #endif /* KLIPS */ diff --git a/src/pluto/keys.c b/src/pluto/keys.c index 1e0bbc37f..69b9bca8b 100644 --- a/src/pluto/keys.c +++ b/src/pluto/keys.c @@ -25,12 +25,12 @@ #include #include #include -#include /* missing from on old systems */ +#include /* missing from on old systems */ #include #include #ifndef GLOB_ABORTED -# define GLOB_ABORTED GLOB_ABEND /* fix for old versions */ +# define GLOB_ABORTED GLOB_ABEND /* fix for old versions */ #endif #include @@ -48,10 +48,10 @@ #include "state.h" #include "lex.h" #include "keys.h" -#include "adns.h" /* needs */ -#include "dnskey.h" /* needs keys.h and adns.h */ +#include "adns.h" /* needs */ +#include "dnskey.h" /* needs keys.h and adns.h */ #include "log.h" -#include "whack.h" /* for RC_LOG_SERIOUS */ +#include "whack.h" /* for RC_LOG_SERIOUS */ #include "timer.h" #include "fetch.h" #include "xauth.h" @@ -61,56 +61,56 @@ const char *shared_secrets_file = SHARED_SECRETS_FILE; typedef struct id_list id_list_t; struct id_list { - struct id id; - id_list_t *next; + struct id id; + id_list_t *next; }; typedef struct secret secret_t; struct secret { - id_list_t *ids; - enum PrivateKeyKind kind; - union { - chunk_t preshared_secret; - RSA_private_key_t RSA_private_key; - xauth_t xauth_secret; - smartcard_t *smartcard; - } u; - secret_t *next; + id_list_t *ids; + enum PrivateKeyKind kind; + union { + chunk_t preshared_secret; + RSA_private_key_t RSA_private_key; + xauth_t xauth_secret; + smartcard_t *smartcard; + } u; + secret_t *next; }; static pubkey_t* allocate_RSA_public_key(const cert_t cert) { - pubkey_t *pk = malloc_thing(pubkey_t); - chunk_t e = chunk_empty, n = chunk_empty; + pubkey_t *pk = malloc_thing(pubkey_t); + chunk_t e = chunk_empty, n = chunk_empty; - switch (cert.type) - { - case CERT_PGP: - e = cert.u.pgp->publicExponent; - n = cert.u.pgp->modulus; - break; - case CERT_X509_SIGNATURE: - e = cert.u.x509->publicExponent; - n = cert.u.x509->modulus; - break; - default: - plog("RSA public key allocation error"); - } + switch (cert.type) + { + case CERT_PGP: + e = cert.u.pgp->publicExponent; + n = cert.u.pgp->modulus; + break; + case CERT_X509_SIGNATURE: + e = cert.u.x509->publicExponent; + n = cert.u.x509->modulus; + break; + default: + plog("RSA public key allocation error"); + } - zero(pk); - init_RSA_public_key(&pk->u.rsa, e, n); - DBG(DBG_RAW, - RSA_show_public_key(&pk->u.rsa) - ) + zero(pk); + init_RSA_public_key(&pk->u.rsa, e, n); + DBG(DBG_RAW, + RSA_show_public_key(&pk->u.rsa) + ) - pk->alg = PUBKEY_ALG_RSA; - pk->id = empty_id; - pk->issuer = chunk_empty; - pk->serial = chunk_empty; + pk->alg = PUBKEY_ALG_RSA; + pk->id = empty_id; + pk->issuer = chunk_empty; + pk->serial = chunk_empty; - return pk; + return pk; } /* @@ -119,20 +119,20 @@ allocate_RSA_public_key(const cert_t cert) static void free_public_key(pubkey_t *pk) { - free_id_content(&pk->id); - free(pk->issuer.ptr); - free(pk->serial.ptr); + free_id_content(&pk->id); + free(pk->issuer.ptr); + free(pk->serial.ptr); - /* algorithm-specific freeing */ - switch (pk->alg) - { - case PUBKEY_ALG_RSA: - free_RSA_public_content(&pk->u.rsa); - break; - default: - bad_case(pk->alg); - } - free(pk); + /* algorithm-specific freeing */ + switch (pk->alg) + { + case PUBKEY_ALG_RSA: + free_RSA_public_content(&pk->u.rsa); + break; + default: + bad_case(pk->alg); + } + free(pk); } secret_t *secrets = NULL; @@ -144,147 +144,147 @@ secret_t *secrets = NULL; static const secret_t * get_secret(const struct connection *c, enum PrivateKeyKind kind, bool asym) { - enum { /* bits */ - match_default = 01, - match_him = 02, - match_me = 04 - }; + enum { /* bits */ + match_default = 01, + match_him = 02, + match_me = 04 + }; - unsigned int best_match = 0; - secret_t *best = NULL; - secret_t *s; - const struct id *my_id = &c->spd.this.id - , *his_id = &c->spd.that.id; - struct id rw_id; + unsigned int best_match = 0; + secret_t *best = NULL; + secret_t *s; + const struct id *my_id = &c->spd.this.id + , *his_id = &c->spd.that.id; + struct id rw_id; - /* is there a certificate assigned to this connection? */ - if (kind == PPK_RSA && c->spd.this.cert.type != CERT_NONE) - { - pubkey_t *my_public_key = allocate_RSA_public_key(c->spd.this.cert); + /* is there a certificate assigned to this connection? */ + if (kind == PPK_RSA && c->spd.this.cert.type != CERT_NONE) + { + pubkey_t *my_public_key = allocate_RSA_public_key(c->spd.this.cert); + + for (s = secrets; s != NULL; s = s->next) + { + if (s->kind == kind && + same_RSA_public_key(&s->u.RSA_private_key.pub, &my_public_key->u.rsa)) + { + best = s; + break; /* we have found the private key - no sense in searching further */ + } + } + free_public_key(my_public_key); + return best; + } + + if (his_id_was_instantiated(c)) + { + /* roadwarrior: replace him with 0.0.0.0 */ + rw_id.kind = c->spd.that.id.kind; + rw_id.name = chunk_empty; + happy(anyaddr(addrtypeof(&c->spd.that.host_addr), &rw_id.ip_addr)); + his_id = &rw_id; + } + else if (kind == PPK_PSK + && (c->policy & (POLICY_PSK | POLICY_XAUTH_PSK)) + && ((c->kind == CK_TEMPLATE && c->spd.that.id.kind == ID_NONE) || + (c->kind == CK_INSTANCE && id_is_ipaddr(&c->spd.that.id)))) + { + /* roadwarrior: replace him with 0.0.0.0 */ + rw_id.kind = ID_IPV4_ADDR; + happy(anyaddr(addrtypeof(&c->spd.that.host_addr), &rw_id.ip_addr)); + his_id = &rw_id; + } for (s = secrets; s != NULL; s = s->next) { - if (s->kind == kind && - same_RSA_public_key(&s->u.RSA_private_key.pub, &my_public_key->u.rsa)) - { - best = s; - break; /* we have found the private key - no sense in searching further */ - } + if (s->kind == kind) + { + unsigned int match = 0; + + if (s->ids == NULL) + { + /* a default (signified by lack of ids): + * accept if no more specific match found + */ + match = match_default; + } + else + { + /* check if both ends match ids */ + id_list_t *i; + + for (i = s->ids; i != NULL; i = i->next) + { + if (same_id(my_id, &i->id)) + match |= match_me; + + if (same_id(his_id, &i->id)) + match |= match_him; + } + + /* If our end matched the only id in the list, + * default to matching any peer. + * A more specific match will trump this. + */ + if (match == match_me + && s->ids->next == NULL) + match |= match_default; + } + + switch (match) + { + case match_me: + /* if this is an asymmetric (eg. public key) system, + * allow this-side-only match to count, even if + * there are other ids in the list. + */ + if (!asym) + break; + /* FALLTHROUGH */ + case match_default: /* default all */ + case match_me | match_default: /* default peer */ + case match_me | match_him: /* explicit */ + if (match == best_match) + { + /* two good matches are equally good: + * do they agree? + */ + bool same = FALSE; + + switch (kind) + { + case PPK_PSK: + same = s->u.preshared_secret.len == best->u.preshared_secret.len + && memeq(s->u.preshared_secret.ptr, best->u.preshared_secret.ptr, s->u.preshared_secret.len); + break; + case PPK_RSA: + /* Dirty trick: since we have code to compare + * RSA public keys, but not private keys, we + * make the assumption that equal public keys + * mean equal private keys. This ought to work. + */ + same = same_RSA_public_key(&s->u.RSA_private_key.pub + , &best->u.RSA_private_key.pub); + break; + default: + bad_case(kind); + } + if (!same) + { + loglog(RC_LOG_SERIOUS, "multiple ipsec.secrets entries with distinct secrets match endpoints:" + " first secret used"); + best = s; /* list is backwards: take latest in list */ + } + } + else if (match > best_match) + { + /* this is the best match so far */ + best_match = match; + best = s; + } + } + } } - free_public_key(my_public_key); return best; - } - - if (his_id_was_instantiated(c)) - { - /* roadwarrior: replace him with 0.0.0.0 */ - rw_id.kind = c->spd.that.id.kind; - rw_id.name = chunk_empty; - happy(anyaddr(addrtypeof(&c->spd.that.host_addr), &rw_id.ip_addr)); - his_id = &rw_id; - } - else if (kind == PPK_PSK - && (c->policy & (POLICY_PSK | POLICY_XAUTH_PSK)) - && ((c->kind == CK_TEMPLATE && c->spd.that.id.kind == ID_NONE) || - (c->kind == CK_INSTANCE && id_is_ipaddr(&c->spd.that.id)))) - { - /* roadwarrior: replace him with 0.0.0.0 */ - rw_id.kind = ID_IPV4_ADDR; - happy(anyaddr(addrtypeof(&c->spd.that.host_addr), &rw_id.ip_addr)); - his_id = &rw_id; - } - - for (s = secrets; s != NULL; s = s->next) - { - if (s->kind == kind) - { - unsigned int match = 0; - - if (s->ids == NULL) - { - /* a default (signified by lack of ids): - * accept if no more specific match found - */ - match = match_default; - } - else - { - /* check if both ends match ids */ - id_list_t *i; - - for (i = s->ids; i != NULL; i = i->next) - { - if (same_id(my_id, &i->id)) - match |= match_me; - - if (same_id(his_id, &i->id)) - match |= match_him; - } - - /* If our end matched the only id in the list, - * default to matching any peer. - * A more specific match will trump this. - */ - if (match == match_me - && s->ids->next == NULL) - match |= match_default; - } - - switch (match) - { - case match_me: - /* if this is an asymmetric (eg. public key) system, - * allow this-side-only match to count, even if - * there are other ids in the list. - */ - if (!asym) - break; - /* FALLTHROUGH */ - case match_default: /* default all */ - case match_me | match_default: /* default peer */ - case match_me | match_him: /* explicit */ - if (match == best_match) - { - /* two good matches are equally good: - * do they agree? - */ - bool same = FALSE; - - switch (kind) - { - case PPK_PSK: - same = s->u.preshared_secret.len == best->u.preshared_secret.len - && memeq(s->u.preshared_secret.ptr, best->u.preshared_secret.ptr, s->u.preshared_secret.len); - break; - case PPK_RSA: - /* Dirty trick: since we have code to compare - * RSA public keys, but not private keys, we - * make the assumption that equal public keys - * mean equal private keys. This ought to work. - */ - same = same_RSA_public_key(&s->u.RSA_private_key.pub - , &best->u.RSA_private_key.pub); - break; - default: - bad_case(kind); - } - if (!same) - { - loglog(RC_LOG_SERIOUS, "multiple ipsec.secrets entries with distinct secrets match endpoints:" - " first secret used"); - best = s; /* list is backwards: take latest in list */ - } - } - else if (match > best_match) - { - /* this is the best match so far */ - best_match = match; - best = s; - } - } - } - } - return best; } /* find the appropriate preshared key (see get_secret). @@ -294,15 +294,15 @@ get_secret(const struct connection *c, enum PrivateKeyKind kind, bool asym) const chunk_t * get_preshared_secret(const struct connection *c) { - const secret_t *s = get_secret(c, PPK_PSK, FALSE); + const secret_t *s = get_secret(c, PPK_PSK, FALSE); - DBG(DBG_PRIVATE, - if (s == NULL) - DBG_log("no Preshared Key Found"); - else - DBG_dump_chunk("Preshared Key", s->u.preshared_secret); - ) - return s == NULL? NULL : &s->u.preshared_secret; + DBG(DBG_PRIVATE, + if (s == NULL) + DBG_log("no Preshared Key Found"); + else + DBG_dump_chunk("Preshared Key", s->u.preshared_secret); + ) + return s == NULL? NULL : &s->u.preshared_secret; } /* check the existence of an RSA private key matching an RSA public @@ -311,21 +311,21 @@ get_preshared_secret(const struct connection *c) bool has_private_key(cert_t cert) { - secret_t *s; - bool has_key = FALSE; - pubkey_t *pubkey = allocate_RSA_public_key(cert); + secret_t *s; + bool has_key = FALSE; + pubkey_t *pubkey = allocate_RSA_public_key(cert); - for (s = secrets; s != NULL; s = s->next) - { - if (s->kind == PPK_RSA && - same_RSA_public_key(&s->u.RSA_private_key.pub, &pubkey->u.rsa)) + for (s = secrets; s != NULL; s = s->next) { - has_key = TRUE; - break; + if (s->kind == PPK_RSA && + same_RSA_public_key(&s->u.RSA_private_key.pub, &pubkey->u.rsa)) + { + has_key = TRUE; + break; + } } - } - free_public_key(pubkey); - return has_key; + free_public_key(pubkey); + return has_key; } /* @@ -334,23 +334,23 @@ has_private_key(cert_t cert) const RSA_private_key_t* get_x509_private_key(const x509cert_t *cert) { - secret_t *s; - const RSA_private_key_t *pri = NULL; - const cert_t c = {CERT_X509_SIGNATURE, {(x509cert_t*)cert}}; + secret_t *s; + const RSA_private_key_t *pri = NULL; + const cert_t c = {CERT_X509_SIGNATURE, {(x509cert_t*)cert}}; - pubkey_t *pubkey = allocate_RSA_public_key(c); + pubkey_t *pubkey = allocate_RSA_public_key(c); - for (s = secrets; s != NULL; s = s->next) - { - if (s->kind == PPK_RSA && - same_RSA_public_key(&s->u.RSA_private_key.pub, &pubkey->u.rsa)) + for (s = secrets; s != NULL; s = s->next) { - pri = &s->u.RSA_private_key; - break; + if (s->kind == PPK_RSA && + same_RSA_public_key(&s->u.RSA_private_key.pub, &pubkey->u.rsa)) + { + pri = &s->u.RSA_private_key; + break; + } } - } - free_public_key(pubkey); - return pri; + free_public_key(pubkey); + return pri; } /* find the appropriate RSA private key (see get_secret). @@ -359,9 +359,9 @@ get_x509_private_key(const x509cert_t *cert) const RSA_private_key_t * get_RSA_private_key(const struct connection *c) { - const secret_t *s = get_secret(c, PPK_RSA, TRUE); + const secret_t *s = get_secret(c, PPK_RSA, TRUE); - return s == NULL? NULL : &s->u.RSA_private_key; + return s == NULL? NULL : &s->u.RSA_private_key; } /* digest a secrets file @@ -407,35 +407,35 @@ get_RSA_private_key(const struct connection *c) static err_t process_psk_secret(chunk_t *psk) { - err_t ugh = NULL; + err_t ugh = NULL; - if (*tok == '"' || *tok == '\'') - { - chunk_t secret = { tok + 1, flp->cur - tok -2 }; - - *psk = chunk_clone(secret); - (void) shift(); - } - else - { - char buf[BUF_LEN]; /* limit on size of binary representation of key */ - size_t sz; - - ugh = ttodatav(tok, flp->cur - tok, 0, buf, sizeof(buf), &sz - , diag_space, sizeof(diag_space), TTODATAV_SPACECOUNTS); - if (ugh != NULL) + if (*tok == '"' || *tok == '\'') { - /* ttodata didn't like PSK data */ - ugh = builddiag("PSK data malformed (%s): %s", ugh, tok); + chunk_t secret = { tok + 1, flp->cur - tok -2 }; + + *psk = chunk_clone(secret); + (void) shift(); } else { - chunk_t secret = { buf, sz }; - *psk = chunk_clone(secret); - (void) shift(); + char buf[BUF_LEN]; /* limit on size of binary representation of key */ + size_t sz; + + ugh = ttodatav(tok, flp->cur - tok, 0, buf, sizeof(buf), &sz + , diag_space, sizeof(diag_space), TTODATAV_SPACECOUNTS); + if (ugh != NULL) + { + /* ttodata didn't like PSK data */ + ugh = builddiag("PSK data malformed (%s): %s", ugh, tok); + } + else + { + chunk_t secret = { buf, sz }; + *psk = chunk_clone(secret); + (void) shift(); + } } - } - return ugh; + return ugh; } /* Parse fields of RSA private key. @@ -446,94 +446,94 @@ process_psk_secret(chunk_t *psk) static err_t process_rsa_secret(RSA_private_key_t *rsak) { - char buf[RSA_MAX_ENCODING_BYTES]; /* limit on size of binary representation of key */ - const struct fld *p; + char buf[RSA_MAX_ENCODING_BYTES]; /* limit on size of binary representation of key */ + const struct fld *p; - /* save bytes of Modulus and PublicExponent for keyid calculation */ - unsigned char ebytes[sizeof(buf)]; - unsigned char *eb_next = ebytes; - chunk_t pub_bytes[2]; - chunk_t *pb_next = &pub_bytes[0]; + /* save bytes of Modulus and PublicExponent for keyid calculation */ + unsigned char ebytes[sizeof(buf)]; + unsigned char *eb_next = ebytes; + chunk_t pub_bytes[2]; + chunk_t *pb_next = &pub_bytes[0]; - for (p = RSA_private_field; p < &RSA_private_field[RSA_PRIVATE_FIELD_ELEMENTS]; p++) - { - size_t sz; - err_t ugh; + for (p = RSA_private_field; p < &RSA_private_field[RSA_PRIVATE_FIELD_ELEMENTS]; p++) + { + size_t sz; + err_t ugh; - if (!shift()) - { - return "premature end of RSA key"; + if (!shift()) + { + return "premature end of RSA key"; + } + else if (!tokeqword(p->name)) + { + return builddiag("%s keyword not found where expected in RSA key" + , p->name); + } + else if (!(shift() + && (!tokeq(":") || shift()))) /* ignore optional ":" */ + { + return "premature end of RSA key"; + } + else if (NULL != (ugh = ttodatav(tok, flp->cur - tok + , 0, buf, sizeof(buf), &sz, diag_space, sizeof(diag_space) + , TTODATAV_SPACECOUNTS))) + { + /* in RSA key, ttodata didn't like */ + return builddiag("RSA data malformed (%s): %s", ugh, tok); + } + else + { + MP_INT *n = (MP_INT *) ((char *)rsak + p->offset); + + n_to_mpz(n, buf, sz); + if (pb_next < &pub_bytes[countof(pub_bytes)]) + { + if (eb_next - ebytes + sz > sizeof(ebytes)) + return "public key takes too many bytes"; + + *pb_next = chunk_create(eb_next, sz); + memcpy(eb_next, buf, sz); + eb_next += sz; + pb_next++; + } +#if 0 /* debugging info that compromises security */ + { + size_t sz = mpz_sizeinbase(n, 16); + char buf[RSA_MAX_OCTETS * 2 + 2]; /* ought to be big enough */ + + passert(sz <= sizeof(buf)); + mpz_get_str(buf, 16, n); + + loglog(RC_LOG_SERIOUS, "%s: %s", p->name, buf); + } +#endif + } } - else if (!tokeqword(p->name)) + + /* We require an (indented) '}' and the end of the record. + * We break down the test so that the diagnostic will be + * more helpful. Some people don't seem to wish to indent + * the brace! + */ + if (!shift() || !tokeq("}")) { - return builddiag("%s keyword not found where expected in RSA key" - , p->name); + return "malformed end of RSA private key -- indented '}' required"; } - else if (!(shift() - && (!tokeq(":") || shift()))) /* ignore optional ":" */ + else if (shift()) { - return "premature end of RSA key"; - } - else if (NULL != (ugh = ttodatav(tok, flp->cur - tok - , 0, buf, sizeof(buf), &sz, diag_space, sizeof(diag_space) - , TTODATAV_SPACECOUNTS))) - { - /* in RSA key, ttodata didn't like */ - return builddiag("RSA data malformed (%s): %s", ugh, tok); + return "malformed end of RSA private key -- unexpected token after '}'"; } else { - MP_INT *n = (MP_INT *) ((char *)rsak + p->offset); + unsigned bits = mpz_sizeinbase(&rsak->pub.n, 2); - n_to_mpz(n, buf, sz); - if (pb_next < &pub_bytes[countof(pub_bytes)]) - { - if (eb_next - ebytes + sz > sizeof(ebytes)) - return "public key takes too many bytes"; - - *pb_next = chunk_create(eb_next, sz); - memcpy(eb_next, buf, sz); - eb_next += sz; - pb_next++; - } -#if 0 /* debugging info that compromises security */ - { - size_t sz = mpz_sizeinbase(n, 16); - char buf[RSA_MAX_OCTETS * 2 + 2]; /* ought to be big enough */ - - passert(sz <= sizeof(buf)); - mpz_get_str(buf, 16, n); - - loglog(RC_LOG_SERIOUS, "%s: %s", p->name, buf); - } -#endif + rsak->pub.k = (bits + BITS_PER_BYTE - 1) / BITS_PER_BYTE; + rsak->pub.keyid[0] = '\0'; /* in case of splitkeytoid failure */ + splitkeytoid(pub_bytes[1].ptr, pub_bytes[1].len + , pub_bytes[0].ptr, pub_bytes[0].len + , rsak->pub.keyid, sizeof(rsak->pub.keyid)); + return RSA_private_key_sanity(rsak); } - } - - /* We require an (indented) '}' and the end of the record. - * We break down the test so that the diagnostic will be - * more helpful. Some people don't seem to wish to indent - * the brace! - */ - if (!shift() || !tokeq("}")) - { - return "malformed end of RSA private key -- indented '}' required"; - } - else if (shift()) - { - return "malformed end of RSA private key -- unexpected token after '}'"; - } - else - { - unsigned bits = mpz_sizeinbase(&rsak->pub.n, 2); - - rsak->pub.k = (bits + BITS_PER_BYTE - 1) / BITS_PER_BYTE; - rsak->pub.keyid[0] = '\0'; /* in case of splitkeytoid failure */ - splitkeytoid(pub_bytes[1].ptr, pub_bytes[1].len - , pub_bytes[0].ptr, pub_bytes[0].len - , rsak->pub.keyid, sizeof(rsak->pub.keyid)); - return RSA_private_key_sanity(rsak); - } } /* process rsa key file protected with optional passphrase which can either be @@ -542,49 +542,49 @@ process_rsa_secret(RSA_private_key_t *rsak) static err_t process_rsa_keyfile(RSA_private_key_t *rsak, int whackfd) { - char filename[BUF_LEN]; - prompt_pass_t pass; + char filename[BUF_LEN]; + prompt_pass_t pass; - memset(filename,'\0', BUF_LEN); - memset(pass.secret,'\0', sizeof(pass.secret)); - pass.prompt = FALSE; - pass.fd = whackfd; + memset(filename,'\0', BUF_LEN); + memset(pass.secret,'\0', sizeof(pass.secret)); + pass.prompt = FALSE; + pass.fd = whackfd; - /* we expect the filename of a PKCS#1 private key file */ + /* we expect the filename of a PKCS#1 private key file */ - if (*tok == '"' || *tok == '\'') /* quoted filename */ - memcpy(filename, tok+1, flp->cur - tok - 2); - else - memcpy(filename, tok, flp->cur - tok); - - if (shift()) - { - /* we expect an appended passphrase or passphrase prompt*/ - if (tokeqword("%prompt")) - { - if (pass.fd == NULL_FD) - return "RSA private key file -- enter passphrase using 'ipsec secrets'"; - pass.prompt = TRUE; - } + if (*tok == '"' || *tok == '\'') /* quoted filename */ + memcpy(filename, tok+1, flp->cur - tok - 2); else - { - char *passphrase = tok; - size_t len = flp->cur - passphrase; + memcpy(filename, tok, flp->cur - tok); - if (*tok == '"' || *tok == '\'') /* quoted passphrase */ - { - passphrase++; - len -= 2; - } - if (len > PROMPT_PASS_LEN) - return "RSA private key file -- passphrase exceeds 64 characters"; - - memcpy(pass.secret, passphrase, len); - } if (shift()) - return "RSA private key file -- unexpected token after passphrase"; - } - return load_rsa_private_key(filename, &pass, rsak); + { + /* we expect an appended passphrase or passphrase prompt*/ + if (tokeqword("%prompt")) + { + if (pass.fd == NULL_FD) + return "RSA private key file -- enter passphrase using 'ipsec secrets'"; + pass.prompt = TRUE; + } + else + { + char *passphrase = tok; + size_t len = flp->cur - passphrase; + + if (*tok == '"' || *tok == '\'') /* quoted passphrase */ + { + passphrase++; + len -= 2; + } + if (len > PROMPT_PASS_LEN) + return "RSA private key file -- passphrase exceeds 64 characters"; + + memcpy(pass.secret, passphrase, len); + } + if (shift()) + return "RSA private key file -- unexpected token after passphrase"; + } + return load_rsa_private_key(filename, &pass, rsak); } /* @@ -593,30 +593,30 @@ process_rsa_keyfile(RSA_private_key_t *rsak, int whackfd) static err_t process_xauth(secret_t *s) { - chunk_t user_name; + chunk_t user_name; - s->kind = PPK_XAUTH; + s->kind = PPK_XAUTH; - if (!shift()) - return "missing xauth user name"; - if (*tok == '"' || *tok == '\'') /* quoted user name */ - { - user_name.ptr = tok + 1; - user_name.len = flp->cur - tok - 2; - } - else - { - user_name.ptr = tok; - user_name.len = flp->cur - tok; - } - plog(" loaded xauth credentials of user '%.*s'" - , user_name.len - , user_name.ptr); - s->u.xauth_secret.user_name = chunk_clone(user_name); + if (!shift()) + return "missing xauth user name"; + if (*tok == '"' || *tok == '\'') /* quoted user name */ + { + user_name.ptr = tok + 1; + user_name.len = flp->cur - tok - 2; + } + else + { + user_name.ptr = tok; + user_name.len = flp->cur - tok; + } + plog(" loaded xauth credentials of user '%.*s'" + , user_name.len + , user_name.ptr); + s->u.xauth_secret.user_name = chunk_clone(user_name); - if (!shift()) - return "missing xauth user password"; - return process_psk_secret(&s->u.xauth_secret.user_password); + if (!shift()) + return "missing xauth user password"; + return process_psk_secret(&s->u.xauth_secret.user_password); } /* get XAUTH secret from chained secrets lists @@ -625,25 +625,25 @@ process_xauth(secret_t *s) static bool xauth_get_secret(xauth_t *xauth_secret) { - secret_t *s; - bool found = FALSE; + secret_t *s; + bool found = FALSE; - for (s = secrets; s != NULL; s = s->next) - { - if (s->kind == PPK_XAUTH) + for (s = secrets; s != NULL; s = s->next) { - if (found) - { - plog("found multiple xauth secrets - first selected"); - } - else - { - found = TRUE; - *xauth_secret = s->u.xauth_secret; - } + if (s->kind == PPK_XAUTH) + { + if (found) + { + plog("found multiple xauth secrets - first selected"); + } + else + { + found = TRUE; + *xauth_secret = s->u.xauth_secret; + } + } } - } - return found; + return found; } /* @@ -652,24 +652,24 @@ xauth_get_secret(xauth_t *xauth_secret) static bool xauth_verify_secret(const xauth_peer_t *peer, const xauth_t *xauth_secret) { - bool found = FALSE; - secret_t *s; + bool found = FALSE; + secret_t *s; - for (s = secrets; s != NULL; s = s->next) - { - if (s->kind == PPK_XAUTH) + for (s = secrets; s != NULL; s = s->next) { - if (!chunk_equals(xauth_secret->user_name, s->u.xauth_secret.user_name)) - continue; - found = TRUE; - if (chunk_equals(xauth_secret->user_password, s->u.xauth_secret.user_password)) - return TRUE; + if (s->kind == PPK_XAUTH) + { + if (!chunk_equals(xauth_secret->user_name, s->u.xauth_secret.user_name)) + continue; + found = TRUE; + if (chunk_equals(xauth_secret->user_password, s->u.xauth_secret.user_password)) + return TRUE; + } } - } - plog("xauth user '%.*s' %s" - , xauth_secret->user_name.len, xauth_secret->user_name.ptr - , found? "sent wrong password":"not found"); - return FALSE; + plog("xauth user '%.*s' %s" + , xauth_secret->user_name.len, xauth_secret->user_name.ptr + , found? "sent wrong password":"not found"); + return FALSE; } /* @@ -683,20 +683,20 @@ xauth_module_t xauth_module; void xauth_defaults(void) { - if (xauth_module.get_secret == NULL) - { - DBG(DBG_CONTROL, - DBG_log("xauth module: using default get_secret() function") - ) - xauth_module.get_secret = xauth_get_secret; - } - if (xauth_module.verify_secret == NULL) - { - DBG(DBG_CONTROL, - DBG_log("xauth module: using default verify_secret() function") - ) - xauth_module.verify_secret = xauth_verify_secret; - } + if (xauth_module.get_secret == NULL) + { + DBG(DBG_CONTROL, + DBG_log("xauth module: using default get_secret() function") + ) + xauth_module.get_secret = xauth_get_secret; + } + if (xauth_module.verify_secret == NULL) + { + DBG(DBG_CONTROL, + DBG_log("xauth module: using default verify_secret() function") + ) + xauth_module.verify_secret = xauth_verify_secret; + } }; /* @@ -705,432 +705,432 @@ xauth_defaults(void) static err_t process_pin(secret_t *s, int whackfd) { - smartcard_t *sc; - const char *pin_status = "no pin"; + smartcard_t *sc; + const char *pin_status = "no pin"; - s->kind = PPK_PIN; + s->kind = PPK_PIN; - /* looking for the smartcard keyword */ - if (!shift() || strncmp(tok, SCX_TOKEN, strlen(SCX_TOKEN)) != 0) - return "PIN keyword must be followed by %smartcard:"; + /* looking for the smartcard keyword */ + if (!shift() || strncmp(tok, SCX_TOKEN, strlen(SCX_TOKEN)) != 0) + return "PIN keyword must be followed by %smartcard:"; - sc = scx_add(scx_parse_number_slot_id(tok + strlen(SCX_TOKEN))); - s->u.smartcard = sc; - scx_share(sc); - if (sc->pin.ptr != NULL) - { - scx_release_context(sc); - scx_free_pin(&sc->pin); - } - sc->valid = FALSE; - - if (!shift()) - return "PIN statement must be terminated either by , %pinpad or %prompt"; - - if (tokeqword("%prompt")) - { - shift(); - /* if whackfd exists, whack will be used to prompt for a pin */ - if (whackfd != NULL_FD) - pin_status = scx_get_pin(sc, whackfd) ? "valid pin" : "invalid pin"; - else - pin_status = "pin entry via prompt"; - } - else if (tokeqword("%pinpad")) - { - chunk_t empty_pin = { "", 0 }; - - shift(); - - /* pin will be entered via pin pad during verification */ - sc->pin = chunk_clone(empty_pin); - sc->pinpad = TRUE; - sc->valid = TRUE; - pin_status = "pin entry via pad"; - if (pkcs11_keep_state) + sc = scx_add(scx_parse_number_slot_id(tok + strlen(SCX_TOKEN))); + s->u.smartcard = sc; + scx_share(sc); + if (sc->pin.ptr != NULL) { - scx_verify_pin(sc); + scx_release_context(sc); + scx_free_pin(&sc->pin); } - } - else - { - /* we read the pin directly from ipsec.secrets */ - err_t ugh = process_psk_secret(&sc->pin); - if (ugh != NULL) - return ugh; - /* verify the pin */ - pin_status = scx_verify_pin(sc) ? "valid PIN" : "invalid PIN"; - } -#ifdef SMARTCARD - { - char buf[BUF_LEN]; + sc->valid = FALSE; - if (sc->any_slot) - snprintf(buf, BUF_LEN, "any slot"); + if (!shift()) + return "PIN statement must be terminated either by , %pinpad or %prompt"; + + if (tokeqword("%prompt")) + { + shift(); + /* if whackfd exists, whack will be used to prompt for a pin */ + if (whackfd != NULL_FD) + pin_status = scx_get_pin(sc, whackfd) ? "valid pin" : "invalid pin"; + else + pin_status = "pin entry via prompt"; + } + else if (tokeqword("%pinpad")) + { + chunk_t empty_pin = { "", 0 }; + + shift(); + + /* pin will be entered via pin pad during verification */ + sc->pin = chunk_clone(empty_pin); + sc->pinpad = TRUE; + sc->valid = TRUE; + pin_status = "pin entry via pad"; + if (pkcs11_keep_state) + { + scx_verify_pin(sc); + } + } else - snprintf(buf, BUF_LEN, "slot: %lu", sc->slot); + { + /* we read the pin directly from ipsec.secrets */ + err_t ugh = process_psk_secret(&sc->pin); + if (ugh != NULL) + return ugh; + /* verify the pin */ + pin_status = scx_verify_pin(sc) ? "valid PIN" : "invalid PIN"; + } +#ifdef SMARTCARD + { + char buf[BUF_LEN]; - plog(" %s for #%d (%s, id: %s)" - , pin_status, sc->number, scx_print_slot(sc, ""), sc->id); - } + if (sc->any_slot) + snprintf(buf, BUF_LEN, "any slot"); + else + snprintf(buf, BUF_LEN, "slot: %lu", sc->slot); + + plog(" %s for #%d (%s, id: %s)" + , pin_status, sc->number, scx_print_slot(sc, ""), sc->id); + } #else - plog(" warning: SMARTCARD support is deactivated in pluto/Makefile!"); + plog(" warning: SMARTCARD support is deactivated in pluto/Makefile!"); #endif - return NULL; + return NULL; } static void log_psk(secret_t *s) { - int n = 0; - char buf[BUF_LEN]; - id_list_t *id_list = s->ids; + int n = 0; + char buf[BUF_LEN]; + id_list_t *id_list = s->ids; - if (id_list == NULL) - { - n = snprintf(buf, BUF_LEN, "%%any"); - } - else - { - do + if (id_list == NULL) { - n += idtoa(&id_list->id, buf + n, BUF_LEN - n); - if (n >= BUF_LEN) - { - n = BUF_LEN - 1; - break; - } - else if (n < BUF_LEN - 1) - { - n += snprintf(buf + n, BUF_LEN - n, " "); - } - id_list = id_list->next; + n = snprintf(buf, BUF_LEN, "%%any"); } - while (id_list); - } - plog(" loaded shared key for %.*s", n, buf); + else + { + do + { + n += idtoa(&id_list->id, buf + n, BUF_LEN - n); + if (n >= BUF_LEN) + { + n = BUF_LEN - 1; + break; + } + else if (n < BUF_LEN - 1) + { + n += snprintf(buf + n, BUF_LEN - n, " "); + } + id_list = id_list->next; + } + while (id_list); + } + plog(" loaded shared key for %.*s", n, buf); } static void process_secret(secret_t *s, int whackfd) { - err_t ugh = NULL; + err_t ugh = NULL; - s->kind = PPK_PSK; /* default */ - if (*tok == '"' || *tok == '\'') - { - /* old PSK format: just a string */ - log_psk(s); - ugh = process_psk_secret(&s->u.preshared_secret); - } - else if (tokeqword("psk")) - { - /* preshared key: quoted string or ttodata format */ - log_psk(s); - ugh = !shift()? "unexpected end of record in PSK" - : process_psk_secret(&s->u.preshared_secret); - } - else if (tokeqword("rsa")) - { - /* RSA key: the fun begins. - * A braced list of keyword and value pairs. - */ - s->kind = PPK_RSA; - if (!shift()) + s->kind = PPK_PSK; /* default */ + if (*tok == '"' || *tok == '\'') { - ugh = "bad RSA key syntax"; + /* old PSK format: just a string */ + log_psk(s); + ugh = process_psk_secret(&s->u.preshared_secret); } - else if (tokeq("{")) + else if (tokeqword("psk")) { - ugh = process_rsa_secret(&s->u.RSA_private_key); + /* preshared key: quoted string or ttodata format */ + log_psk(s); + ugh = !shift()? "unexpected end of record in PSK" + : process_psk_secret(&s->u.preshared_secret); + } + else if (tokeqword("rsa")) + { + /* RSA key: the fun begins. + * A braced list of keyword and value pairs. + */ + s->kind = PPK_RSA; + if (!shift()) + { + ugh = "bad RSA key syntax"; + } + else if (tokeq("{")) + { + ugh = process_rsa_secret(&s->u.RSA_private_key); + } + else + { + ugh = process_rsa_keyfile(&s->u.RSA_private_key, whackfd); + } + } + else if (tokeqword("xauth")) + { + ugh = process_xauth(s); + } + else if (tokeqword("pin")) + { + ugh = process_pin(s, whackfd); } else { - ugh = process_rsa_keyfile(&s->u.RSA_private_key, whackfd); + ugh = builddiag("unrecognized key format: %s", tok); } - } - else if (tokeqword("xauth")) - { - ugh = process_xauth(s); - } - else if (tokeqword("pin")) - { - ugh = process_pin(s, whackfd); - } - else - { - ugh = builddiag("unrecognized key format: %s", tok); - } - if (ugh != NULL) - { - loglog(RC_LOG_SERIOUS, "\"%s\" line %d: %s" - , flp->filename, flp->lino, ugh); - free(s); - } - else if (flushline("expected record boundary in key")) - { - /* gauntlet has been run: install new secret */ - lock_certs_and_keys("process_secret"); - s->next = secrets; - secrets = s; - unlock_certs_and_keys("process_secrets"); - } + if (ugh != NULL) + { + loglog(RC_LOG_SERIOUS, "\"%s\" line %d: %s" + , flp->filename, flp->lino, ugh); + free(s); + } + else if (flushline("expected record boundary in key")) + { + /* gauntlet has been run: install new secret */ + lock_certs_and_keys("process_secret"); + s->next = secrets; + secrets = s; + unlock_certs_and_keys("process_secrets"); + } } -static void process_secrets_file(const char *file_pat, int whackfd); /* forward declaration */ +static void process_secrets_file(const char *file_pat, int whackfd); /* forward declaration */ static void process_secret_records(int whackfd) { - /* read records from ipsec.secrets and load them into our table */ - for (;;) - { - (void)flushline(NULL); /* silently ditch leftovers, if any */ - if (flp->bdry == B_file) - break; - - flp->bdry = B_none; /* eat the Record Boundary */ - (void)shift(); /* get real first token */ - - if (tokeqword("include")) + /* read records from ipsec.secrets and load them into our table */ + for (;;) { - /* an include directive */ - char fn[MAX_TOK_LEN]; /* space for filename (I hope) */ - char *p = fn; - char *end_prefix = strrchr(flp->filename, '/'); + (void)flushline(NULL); /* silently ditch leftovers, if any */ + if (flp->bdry == B_file) + break; - if (!shift()) - { - loglog(RC_LOG_SERIOUS, "\"%s\" line %d: unexpected end of include directive" - , flp->filename, flp->lino); - continue; /* abandon this record */ - } + flp->bdry = B_none; /* eat the Record Boundary */ + (void)shift(); /* get real first token */ - /* if path is relative and including file's pathname has - * a non-empty dirname, prefix this path with that dirname. - */ - if (tok[0] != '/' && end_prefix != NULL) - { - size_t pl = end_prefix - flp->filename + 1; - - /* "clamp" length to prevent problems now; - * will be rediscovered and reported later. - */ - if (pl > sizeof(fn)) - pl = sizeof(fn); - memcpy(fn, flp->filename, pl); - p += pl; - } - if (flp->cur - tok >= &fn[sizeof(fn)] - p) - { - loglog(RC_LOG_SERIOUS, "\"%s\" line %d: include pathname too long" - , flp->filename, flp->lino); - continue; /* abandon this record */ - } - strcpy(p, tok); - (void) shift(); /* move to Record Boundary, we hope */ - if (flushline("ignoring malformed INCLUDE -- expected Record Boundary after filename")) - { - process_secrets_file(fn, whackfd); - tok = NULL; /* correct, but probably redundant */ - } - } - else - { - /* expecting a list of indices and then the key info */ - secret_t *s = malloc_thing(secret_t); - - zero(s); - s->ids = NULL; - s->kind = PPK_PSK; /* default */ - s->u.preshared_secret = chunk_empty; - s->next = NULL; - - for (;;) - { - if (tok[0] == '"' || tok[0] == '\'') + if (tokeqword("include")) { - /* found key part */ - process_secret(s, whackfd); - break; - } - else if (tokeq(":")) - { - /* found key part */ - shift(); /* discard explicit separator */ - process_secret(s, whackfd); - break; + /* an include directive */ + char fn[MAX_TOK_LEN]; /* space for filename (I hope) */ + char *p = fn; + char *end_prefix = strrchr(flp->filename, '/'); + + if (!shift()) + { + loglog(RC_LOG_SERIOUS, "\"%s\" line %d: unexpected end of include directive" + , flp->filename, flp->lino); + continue; /* abandon this record */ + } + + /* if path is relative and including file's pathname has + * a non-empty dirname, prefix this path with that dirname. + */ + if (tok[0] != '/' && end_prefix != NULL) + { + size_t pl = end_prefix - flp->filename + 1; + + /* "clamp" length to prevent problems now; + * will be rediscovered and reported later. + */ + if (pl > sizeof(fn)) + pl = sizeof(fn); + memcpy(fn, flp->filename, pl); + p += pl; + } + if (flp->cur - tok >= &fn[sizeof(fn)] - p) + { + loglog(RC_LOG_SERIOUS, "\"%s\" line %d: include pathname too long" + , flp->filename, flp->lino); + continue; /* abandon this record */ + } + strcpy(p, tok); + (void) shift(); /* move to Record Boundary, we hope */ + if (flushline("ignoring malformed INCLUDE -- expected Record Boundary after filename")) + { + process_secrets_file(fn, whackfd); + tok = NULL; /* correct, but probably redundant */ + } } else { - /* an id - * See RFC2407 IPsec Domain of Interpretation 4.6.2 - */ - struct id id; - err_t ugh; + /* expecting a list of indices and then the key info */ + secret_t *s = malloc_thing(secret_t); - if (tokeq("%any")) - { - id = empty_id; - id.kind = ID_IPV4_ADDR; - ugh = anyaddr(AF_INET, &id.ip_addr); - } - else if (tokeq("%any6")) - { - id = empty_id; - id.kind = ID_IPV6_ADDR; - ugh = anyaddr(AF_INET6, &id.ip_addr); - } - else - { - ugh = atoid(tok, &id, FALSE); - } + zero(s); + s->ids = NULL; + s->kind = PPK_PSK; /* default */ + s->u.preshared_secret = chunk_empty; + s->next = NULL; - if (ugh != NULL) - { - loglog(RC_LOG_SERIOUS - , "ERROR \"%s\" line %d: index \"%s\" %s" - , flp->filename, flp->lino, tok, ugh); - } - else - { - id_list_t *i = malloc_thing(id_list_t); + for (;;) + { + if (tok[0] == '"' || tok[0] == '\'') + { + /* found key part */ + process_secret(s, whackfd); + break; + } + else if (tokeq(":")) + { + /* found key part */ + shift(); /* discard explicit separator */ + process_secret(s, whackfd); + break; + } + else + { + /* an id + * See RFC2407 IPsec Domain of Interpretation 4.6.2 + */ + struct id id; + err_t ugh; - i->id = id; - unshare_id_content(&i->id); - i->next = s->ids; - s->ids = i; - /* DBG_log("id type %d: %s %.*s", i->kind, ip_str(&i->ip_addr), (int)i->name.len, i->name.ptr); */ - } - if (!shift()) - { - /* unexpected Record Boundary or EOF */ - loglog(RC_LOG_SERIOUS, "\"%s\" line %d: unexpected end of id list" - , flp->filename, flp->lino); - break; - } + if (tokeq("%any")) + { + id = empty_id; + id.kind = ID_IPV4_ADDR; + ugh = anyaddr(AF_INET, &id.ip_addr); + } + else if (tokeq("%any6")) + { + id = empty_id; + id.kind = ID_IPV6_ADDR; + ugh = anyaddr(AF_INET6, &id.ip_addr); + } + else + { + ugh = atoid(tok, &id, FALSE); + } + + if (ugh != NULL) + { + loglog(RC_LOG_SERIOUS + , "ERROR \"%s\" line %d: index \"%s\" %s" + , flp->filename, flp->lino, tok, ugh); + } + else + { + id_list_t *i = malloc_thing(id_list_t); + + i->id = id; + unshare_id_content(&i->id); + i->next = s->ids; + s->ids = i; + /* DBG_log("id type %d: %s %.*s", i->kind, ip_str(&i->ip_addr), (int)i->name.len, i->name.ptr); */ + } + if (!shift()) + { + /* unexpected Record Boundary or EOF */ + loglog(RC_LOG_SERIOUS, "\"%s\" line %d: unexpected end of id list" + , flp->filename, flp->lino); + break; + } + } + } } - } } - } } static int globugh(const char *epath, int eerrno) { - log_errno_routine(eerrno, "problem with secrets file \"%s\"", epath); - return 1; /* stop glob */ + log_errno_routine(eerrno, "problem with secrets file \"%s\"", epath); + return 1; /* stop glob */ } static void process_secrets_file(const char *file_pat, int whackfd) { - struct file_lex_position pos; - char **fnp; - glob_t globbuf; + struct file_lex_position pos; + char **fnp; + glob_t globbuf; - pos.depth = flp == NULL? 0 : flp->depth + 1; + pos.depth = flp == NULL? 0 : flp->depth + 1; - if (pos.depth > 10) - { - loglog(RC_LOG_SERIOUS, "preshared secrets file \"%s\" nested too deeply", file_pat); - return; - } - - /* do globbing */ - { - int r = glob(file_pat, GLOB_ERR, globugh, &globbuf); - - if (r != 0) + if (pos.depth > 10) { - switch (r) - { - case GLOB_NOSPACE: - loglog(RC_LOG_SERIOUS, "out of space processing secrets filename \"%s\"", file_pat); - break; - case GLOB_ABORTED: - break; /* already logged */ - case GLOB_NOMATCH: - loglog(RC_LOG_SERIOUS, "no secrets filename matched \"%s\"", file_pat); - break; - default: - loglog(RC_LOG_SERIOUS, "unknown glob error %d", r); - break; - } - globfree(&globbuf); - return; + loglog(RC_LOG_SERIOUS, "preshared secrets file \"%s\" nested too deeply", file_pat); + return; } - } - /* for each file... */ - for (fnp = globbuf.gl_pathv; *fnp != NULL; fnp++) - { - if (lexopen(&pos, *fnp, FALSE)) + /* do globbing */ { - plog("loading secrets from \"%s\"", *fnp); - (void) flushline("file starts with indentation (continuation notation)"); - process_secret_records(whackfd); - lexclose(); - } - } + int r = glob(file_pat, GLOB_ERR, globugh, &globbuf); - globfree(&globbuf); + if (r != 0) + { + switch (r) + { + case GLOB_NOSPACE: + loglog(RC_LOG_SERIOUS, "out of space processing secrets filename \"%s\"", file_pat); + break; + case GLOB_ABORTED: + break; /* already logged */ + case GLOB_NOMATCH: + loglog(RC_LOG_SERIOUS, "no secrets filename matched \"%s\"", file_pat); + break; + default: + loglog(RC_LOG_SERIOUS, "unknown glob error %d", r); + break; + } + globfree(&globbuf); + return; + } + } + + /* for each file... */ + for (fnp = globbuf.gl_pathv; *fnp != NULL; fnp++) + { + if (lexopen(&pos, *fnp, FALSE)) + { + plog("loading secrets from \"%s\"", *fnp); + (void) flushline("file starts with indentation (continuation notation)"); + process_secret_records(whackfd); + lexclose(); + } + } + + globfree(&globbuf); } void free_preshared_secrets(void) { - lock_certs_and_keys("free_preshared_secrets"); + lock_certs_and_keys("free_preshared_secrets"); - if (secrets != NULL) - { - secret_t *s, *ns; - - plog("forgetting secrets"); - - for (s = secrets; s != NULL; s = ns) + if (secrets != NULL) { - id_list_t *i, *ni; + secret_t *s, *ns; - ns = s->next; /* grab before freeing s */ - for (i = s->ids; i != NULL; i = ni) - { - ni = i->next; /* grab before freeing i */ - free_id_content(&i->id); - free(i); - } - switch (s->kind) - { - case PPK_PSK: - free(s->u.preshared_secret.ptr); - break; - case PPK_RSA: - free_RSA_private_content(&s->u.RSA_private_key); - break; - case PPK_XAUTH: - free(s->u.xauth_secret.user_name.ptr); - free(s->u.xauth_secret.user_password.ptr); - break; - case PPK_PIN: - scx_release(s->u.smartcard); - break; - default: - bad_case(s->kind); - } - free(s); + plog("forgetting secrets"); + + for (s = secrets; s != NULL; s = ns) + { + id_list_t *i, *ni; + + ns = s->next; /* grab before freeing s */ + for (i = s->ids; i != NULL; i = ni) + { + ni = i->next; /* grab before freeing i */ + free_id_content(&i->id); + free(i); + } + switch (s->kind) + { + case PPK_PSK: + free(s->u.preshared_secret.ptr); + break; + case PPK_RSA: + free_RSA_private_content(&s->u.RSA_private_key); + break; + case PPK_XAUTH: + free(s->u.xauth_secret.user_name.ptr); + free(s->u.xauth_secret.user_password.ptr); + break; + case PPK_PIN: + scx_release(s->u.smartcard); + break; + default: + bad_case(s->kind); + } + free(s); + } + secrets = NULL; } - secrets = NULL; - } - unlock_certs_and_keys("free_preshard_secrets"); + unlock_certs_and_keys("free_preshard_secrets"); } void load_preshared_secrets(int whackfd) { - free_preshared_secrets(); - (void) process_secrets_file(shared_secrets_file, whackfd); + free_preshared_secrets(); + (void) process_secrets_file(shared_secrets_file, whackfd); } /* public key machinery @@ -1140,25 +1140,25 @@ load_preshared_secrets(int whackfd) pubkey_t * public_key_from_rsa(const RSA_public_key_t *k) { - pubkey_t *p = malloc_thing(pubkey_t); + pubkey_t *p = malloc_thing(pubkey_t); - zero(p); - p->id = empty_id; /* don't know, doesn't matter */ - p->issuer = chunk_empty; - p->serial = chunk_empty; - p->alg = PUBKEY_ALG_RSA; + zero(p); + p->id = empty_id; /* don't know, doesn't matter */ + p->issuer = chunk_empty; + p->serial = chunk_empty; + p->alg = PUBKEY_ALG_RSA; - memcpy(p->u.rsa.keyid, k->keyid, sizeof(p->u.rsa.keyid)); - p->u.rsa.k = k->k; - mpz_init_set(&p->u.rsa.e, &k->e); - mpz_init_set(&p->u.rsa.n, &k->n); + memcpy(p->u.rsa.keyid, k->keyid, sizeof(p->u.rsa.keyid)); + p->u.rsa.k = k->k; + mpz_init_set(&p->u.rsa.e, &k->e); + mpz_init_set(&p->u.rsa.n, &k->n); - /* note that we return a 1 reference count upon creation: - * invariant: recount > 0. - */ - p->refcnt = 1; - time(&p->installed_time); - return p; + /* note that we return a 1 reference count upon creation: + * invariant: recount > 0. + */ + p->refcnt = 1; + time(&p->installed_time); + return p; } /* Free a public key record. @@ -1167,29 +1167,29 @@ public_key_from_rsa(const RSA_public_key_t *k) pubkey_list_t * free_public_keyentry(pubkey_list_t *p) { - pubkey_list_t *nxt = p->next; + pubkey_list_t *nxt = p->next; - if (p->key != NULL) - unreference_key(&p->key); - free(p); - return nxt; + if (p->key != NULL) + unreference_key(&p->key); + free(p); + return nxt; } void free_public_keys(pubkey_list_t **keys) { - while (*keys != NULL) - *keys = free_public_keyentry(*keys); + while (*keys != NULL) + *keys = free_public_keyentry(*keys); } /* root of chained public key list */ -pubkey_list_t *pubkeys = NULL; /* keys from ipsec.conf */ +pubkey_list_t *pubkeys = NULL; /* keys from ipsec.conf */ void free_remembered_public_keys(void) { - free_public_keys(&pubkeys); + free_public_keys(&pubkeys); } /* transfer public keys from *keys list to front of pubkeys list */ @@ -1200,30 +1200,30 @@ transfer_to_public_keys(struct gw_info *gateways_from_dns #endif /* USE_KEYRR */ ) { - { - struct gw_info *gwp; - - for (gwp = gateways_from_dns; gwp != NULL; gwp = gwp->next) { - pubkey_list_t *pl = malloc_thing(pubkey_list_t); + struct gw_info *gwp; - pl->key = gwp->key; /* note: this is a transfer */ - gwp->key = NULL; /* really, it is! */ - pl->next = pubkeys; - pubkeys = pl; + for (gwp = gateways_from_dns; gwp != NULL; gwp = gwp->next) + { + pubkey_list_t *pl = malloc_thing(pubkey_list_t); + + pl->key = gwp->key; /* note: this is a transfer */ + gwp->key = NULL; /* really, it is! */ + pl->next = pubkeys; + pubkeys = pl; + } } - } #ifdef USE_KEYRR - { - pubkey_list_t **pp = keys; + { + pubkey_list_t **pp = keys; - while (*pp != NULL) - pp = &(*pp)->next; - *pp = pubkeys; - pubkeys = *keys; - *keys = NULL; - } + while (*pp != NULL) + pp = &(*pp)->next; + *pp = pubkeys; + pubkeys = *keys; + *keys = NULL; + } #endif /* USE_KEYRR */ } @@ -1238,73 +1238,73 @@ transfer_to_public_keys(struct gw_info *gateways_from_dns err_t unpack_RSA_public_key(RSA_public_key_t *rsa, const chunk_t *pubkey) { - chunk_t exp; - chunk_t mod; + chunk_t exp; + chunk_t mod; - if (pubkey->len < 3) - return "RSA public key blob way to short"; /* not even room for length! */ + if (pubkey->len < 3) + return "RSA public key blob way to short"; /* not even room for length! */ - if (pubkey->ptr[0] != 0x00) - { - exp = chunk_create(pubkey->ptr + 1, pubkey->ptr[0]); - } - else - { - exp = chunk_create(pubkey->ptr + 3, - (pubkey->ptr[1] << BITS_PER_BYTE) + pubkey->ptr[2]); - } + if (pubkey->ptr[0] != 0x00) + { + exp = chunk_create(pubkey->ptr + 1, pubkey->ptr[0]); + } + else + { + exp = chunk_create(pubkey->ptr + 3, + (pubkey->ptr[1] << BITS_PER_BYTE) + pubkey->ptr[2]); + } - if (pubkey->len - (exp.ptr - pubkey->ptr) < exp.len + RSA_MIN_OCTETS_RFC) - { - return "RSA public key blob too short"; - } + if (pubkey->len - (exp.ptr - pubkey->ptr) < exp.len + RSA_MIN_OCTETS_RFC) + { + return "RSA public key blob too short"; + } - mod.ptr = exp.ptr + exp.len; - mod.len = &pubkey->ptr[pubkey->len] - mod.ptr; + mod.ptr = exp.ptr + exp.len; + mod.len = &pubkey->ptr[pubkey->len] - mod.ptr; - if (mod.len < RSA_MIN_OCTETS) - return RSA_MIN_OCTETS_UGH; + if (mod.len < RSA_MIN_OCTETS) + return RSA_MIN_OCTETS_UGH; - if (mod.len > RSA_MAX_OCTETS) - return RSA_MAX_OCTETS_UGH; + if (mod.len > RSA_MAX_OCTETS) + return RSA_MAX_OCTETS_UGH; - init_RSA_public_key(rsa, exp, mod); - rsa->k = mpz_sizeinbase(&rsa->n, 2); /* size in bits, for a start */ - rsa->k = (rsa->k + BITS_PER_BYTE - 1) / BITS_PER_BYTE; /* now octets */ - DBG(DBG_RAW, - RSA_show_public_key(rsa) - ) + init_RSA_public_key(rsa, exp, mod); + rsa->k = mpz_sizeinbase(&rsa->n, 2); /* size in bits, for a start */ + rsa->k = (rsa->k + BITS_PER_BYTE - 1) / BITS_PER_BYTE; /* now octets */ + DBG(DBG_RAW, + RSA_show_public_key(rsa) + ) - if (rsa->k != mod.len) - { - mpz_clear(&rsa->e); - mpz_clear(&rsa->n); - return "RSA modulus shorter than specified"; - } + if (rsa->k != mod.len) + { + mpz_clear(&rsa->e); + mpz_clear(&rsa->n); + return "RSA modulus shorter than specified"; + } - return NULL; + return NULL; } static void install_public_key(pubkey_t *pk, pubkey_list_t **head) { - pubkey_list_t *p = malloc_thing(pubkey_list_t); + pubkey_list_t *p = malloc_thing(pubkey_list_t); - unshare_id_content(&pk->id); + unshare_id_content(&pk->id); - /* copy issuer dn */ - pk->issuer = chunk_clone(pk->issuer); + /* copy issuer dn */ + pk->issuer = chunk_clone(pk->issuer); - /* copy serial number */ - pk->serial = chunk_clone(pk->serial); + /* copy serial number */ + pk->serial = chunk_clone(pk->serial); - /* store the time the public key was installed */ - time(&pk->installed_time); + /* store the time the public key was installed */ + time(&pk->installed_time); - /* install new key at front */ - p->key = reference_key(pk); - p->next = *head; - *head = p; + /* install new key at front */ + p->key = reference_key(pk); + p->next = *head; + *head = p; } @@ -1312,89 +1312,89 @@ void delete_public_keys(const struct id *id, enum pubkey_alg alg , chunk_t issuer, chunk_t serial) { - pubkey_list_t **pp, *p; - pubkey_t *pk; + pubkey_list_t **pp, *p; + pubkey_t *pk; - for (pp = &pubkeys; (p = *pp) != NULL; ) - { - pk = p->key; + for (pp = &pubkeys; (p = *pp) != NULL; ) + { + pk = p->key; - if (same_id(id, &pk->id) && pk->alg == alg - && (issuer.ptr == NULL || pk->issuer.ptr == NULL - || same_dn(issuer, pk->issuer)) - && same_serial(serial, pk->serial)) - *pp = free_public_keyentry(p); - else - pp = &p->next; - } + if (same_id(id, &pk->id) && pk->alg == alg + && (issuer.ptr == NULL || pk->issuer.ptr == NULL + || same_dn(issuer, pk->issuer)) + && same_serial(serial, pk->serial)) + *pp = free_public_keyentry(p); + else + pp = &p->next; + } } pubkey_t * reference_key(pubkey_t *pk) { - pk->refcnt++; - return pk; + pk->refcnt++; + return pk; } void unreference_key(pubkey_t **pkp) { - pubkey_t *pk = *pkp; - char b[BUF_LEN]; + pubkey_t *pk = *pkp; + char b[BUF_LEN]; - if (pk == NULL) - return; + if (pk == NULL) + return; - /* print stuff */ - DBG(DBG_CONTROLMORE, - idtoa(&pk->id, b, sizeof(b)); - DBG_log("unreference key: %p %s cnt %d--", pk, b, pk->refcnt) - ) + /* print stuff */ + DBG(DBG_CONTROLMORE, + idtoa(&pk->id, b, sizeof(b)); + DBG_log("unreference key: %p %s cnt %d--", pk, b, pk->refcnt) + ) - /* cancel out the pointer */ - *pkp = NULL; + /* cancel out the pointer */ + *pkp = NULL; - passert(pk->refcnt != 0); - pk->refcnt--; - if (pk->refcnt == 0) - free_public_key(pk); + passert(pk->refcnt != 0); + pk->refcnt--; + if (pk->refcnt == 0) + free_public_key(pk); } err_t add_public_key(const struct id *id, enum dns_auth_level dns_auth_level, - enum pubkey_alg alg, const chunk_t *key, pubkey_list_t **head) + enum pubkey_alg alg, const chunk_t *key, pubkey_list_t **head) { - pubkey_t *pk; + pubkey_t *pk; - pk = malloc_thing(pubkey_t); zero(pk); + pk = malloc_thing(pubkey_t); zero(pk); /* first: algorithm-specific decoding of key chunk */ - switch (alg) - { - case PUBKEY_ALG_RSA: + switch (alg) { - err_t ugh = unpack_RSA_public_key(&pk->u.rsa, key); + case PUBKEY_ALG_RSA: + { + err_t ugh = unpack_RSA_public_key(&pk->u.rsa, key); - if (ugh != NULL) - { - free(pk); - return ugh; - } + if (ugh != NULL) + { + free(pk); + return ugh; + } + } + break; + default: + bad_case(alg); } - break; - default: - bad_case(alg); - } - pk->id = *id; - pk->dns_auth_level = dns_auth_level; - pk->alg = alg; - pk->until_time = UNDEFINED_TIME; - pk->issuer = chunk_empty; - pk->serial = chunk_empty; - - install_public_key(pk, head); - return NULL; + pk->id = *id; + pk->dns_auth_level = dns_auth_level; + pk->alg = alg; + pk->until_time = UNDEFINED_TIME; + pk->issuer = chunk_empty; + pk->serial = chunk_empty; + + install_public_key(pk, head); + return NULL; } /* extract id and public key from x.509 certificate and @@ -1402,47 +1402,47 @@ add_public_key(const struct id *id, enum dns_auth_level dns_auth_level, */ void add_x509_public_key(x509cert_t *cert , time_t until - , enum dns_auth_level dns_auth_level) + , enum dns_auth_level dns_auth_level) { - generalName_t *gn; - pubkey_t *pk; - cert_t c = { CERT_X509_SIGNATURE, {cert} }; + generalName_t *gn; + pubkey_t *pk; + cert_t c = { CERT_X509_SIGNATURE, {cert} }; - /* we support RSA only */ - if (cert->subjectPublicKeyAlgorithm != PUBKEY_ALG_RSA) - return; + /* we support RSA only */ + if (cert->subjectPublicKeyAlgorithm != PUBKEY_ALG_RSA) + return; - /* ID type: ID_DER_ASN1_DN (X.509 subject field) */ - pk = allocate_RSA_public_key(c); - pk->id.kind = ID_DER_ASN1_DN; - pk->id.name = cert->subject; - pk->dns_auth_level = dns_auth_level; - pk->until_time = until; - pk->issuer = cert->issuer; - pk->serial = cert->serialNumber; - delete_public_keys(&pk->id, pk->alg, pk->issuer, pk->serial); - install_public_key(pk, &pubkeys); + /* ID type: ID_DER_ASN1_DN (X.509 subject field) */ + pk = allocate_RSA_public_key(c); + pk->id.kind = ID_DER_ASN1_DN; + pk->id.name = cert->subject; + pk->dns_auth_level = dns_auth_level; + pk->until_time = until; + pk->issuer = cert->issuer; + pk->serial = cert->serialNumber; + delete_public_keys(&pk->id, pk->alg, pk->issuer, pk->serial); + install_public_key(pk, &pubkeys); - gn = cert->subjectAltName; + gn = cert->subjectAltName; - while (gn != NULL) /* insert all subjectAltNames */ - { - struct id id = empty_id; - - gntoid(&id, gn); - if (id.kind != ID_NONE) + while (gn != NULL) /* insert all subjectAltNames */ { - pk = allocate_RSA_public_key(c); - pk->id = id; - pk->dns_auth_level = dns_auth_level; - pk->until_time = until; - pk->issuer = cert->issuer; - pk->serial = cert->serialNumber; - delete_public_keys(&pk->id, pk->alg, pk->issuer, pk->serial); - install_public_key(pk, &pubkeys); + struct id id = empty_id; + + gntoid(&id, gn); + if (id.kind != ID_NONE) + { + pk = allocate_RSA_public_key(c); + pk->id = id; + pk->dns_auth_level = dns_auth_level; + pk->until_time = until; + pk->issuer = cert->issuer; + pk->serial = cert->serialNumber; + delete_public_keys(&pk->id, pk->alg, pk->issuer, pk->serial); + install_public_key(pk, &pubkeys); + } + gn = gn->next; } - gn = gn->next; - } } /* extract id and public key from OpenPGP certificate and @@ -1450,29 +1450,29 @@ add_x509_public_key(x509cert_t *cert , time_t until */ void add_pgp_public_key(pgpcert_t *cert , time_t until - , enum dns_auth_level dns_auth_level) + , enum dns_auth_level dns_auth_level) { - pubkey_t *pk; - cert_t c; + pubkey_t *pk; + cert_t c; - c.type = CERT_PGP; - c.u.pgp = cert; + c.type = CERT_PGP; + c.u.pgp = cert; - /* we support RSA only */ - if (cert->pubkeyAlg != PUBKEY_ALG_RSA) - { - plog(" RSA public keys supported only"); - return; - } + /* we support RSA only */ + if (cert->pubkeyAlg != PUBKEY_ALG_RSA) + { + plog(" RSA public keys supported only"); + return; + } - pk = allocate_RSA_public_key(c); - pk->id.kind = ID_KEY_ID; - pk->id.name.ptr = cert->fingerprint; - pk->id.name.len = PGP_FINGERPRINT_SIZE; - pk->dns_auth_level = dns_auth_level; - pk->until_time = until; - delete_public_keys(&pk->id, pk->alg, chunk_empty, chunk_empty); - install_public_key(pk, &pubkeys); + pk = allocate_RSA_public_key(c); + pk->id.kind = ID_KEY_ID; + pk->id.name.ptr = cert->fingerprint; + pk->id.name.len = PGP_FINGERPRINT_SIZE; + pk->dns_auth_level = dns_auth_level; + pk->until_time = until; + delete_public_keys(&pk->id, pk->alg, chunk_empty, chunk_empty); + install_public_key(pk, &pubkeys); } /* when a X.509 certificate gets revoked, all instances of @@ -1481,30 +1481,30 @@ add_pgp_public_key(pgpcert_t *cert , time_t until void remove_x509_public_key(const x509cert_t *cert) { - const cert_t c = {CERT_X509_SIGNATURE, {(x509cert_t*)cert}}; - pubkey_list_t *p, **pp; - pubkey_t *revoked_pk; + const cert_t c = {CERT_X509_SIGNATURE, {(x509cert_t*)cert}}; + pubkey_list_t *p, **pp; + pubkey_t *revoked_pk; - revoked_pk = allocate_RSA_public_key(c); - p = pubkeys; - pp = &pubkeys; + revoked_pk = allocate_RSA_public_key(c); + p = pubkeys; + pp = &pubkeys; - while(p != NULL) + while(p != NULL) { - if (same_RSA_public_key(&p->key->u.rsa, &revoked_pk->u.rsa)) - { - /* remove p from list and free memory */ - *pp = free_public_keyentry(p); - loglog(RC_LOG_SERIOUS, - "invalid RSA public key deleted"); + if (same_RSA_public_key(&p->key->u.rsa, &revoked_pk->u.rsa)) + { + /* remove p from list and free memory */ + *pp = free_public_keyentry(p); + loglog(RC_LOG_SERIOUS, + "invalid RSA public key deleted"); + } + else + { + pp = &p->next; + } + p =*pp; } - else - { - pp = &p->next; - } - p =*pp; - } - free_public_key(revoked_pk); + free_public_key(revoked_pk); } /* @@ -1512,43 +1512,43 @@ remove_x509_public_key(const x509cert_t *cert) */ void list_public_keys(bool utc) { - pubkey_list_t *p = pubkeys; + pubkey_list_t *p = pubkeys; - if (p != NULL) - { - whack_log(RC_COMMENT, " "); - whack_log(RC_COMMENT, "List of Public Keys:"); - whack_log(RC_COMMENT, " "); - } - - while (p != NULL) - { - pubkey_t *key = p->key; - - if (key->alg == PUBKEY_ALG_RSA) + if (p != NULL) { - char buf[BUF_LEN]; + whack_log(RC_COMMENT, " "); + whack_log(RC_COMMENT, "List of Public Keys:"); + whack_log(RC_COMMENT, " "); + } - idtoa(&key->id, buf, BUF_LEN); - whack_log(RC_COMMENT, "%T, %4d RSA Key %s, until %T %s", - &key->installed_time, utc, - 8*key->u.rsa.k, key->u.rsa.keyid, - &key->until_time, utc, - check_expiry(key->until_time, PUBKEY_WARNING_INTERVAL, TRUE)); - whack_log(RC_COMMENT," %s '%s'", - enum_show(&ident_names, key->id.kind), buf); - if (key->issuer.len > 0) - { - dntoa(buf, BUF_LEN, key->issuer); - whack_log(RC_COMMENT," issuer: '%s'", buf); - } - if (key->serial.len > 0) - { - datatot(key->serial.ptr, key->serial.len, ':' - , buf, BUF_LEN); - whack_log(RC_COMMENT," serial: %s", buf); - } + while (p != NULL) + { + pubkey_t *key = p->key; + + if (key->alg == PUBKEY_ALG_RSA) + { + char buf[BUF_LEN]; + + idtoa(&key->id, buf, BUF_LEN); + whack_log(RC_COMMENT, "%T, %4d RSA Key %s, until %T %s", + &key->installed_time, utc, + 8*key->u.rsa.k, key->u.rsa.keyid, + &key->until_time, utc, + check_expiry(key->until_time, PUBKEY_WARNING_INTERVAL, TRUE)); + whack_log(RC_COMMENT," %s '%s'", + enum_show(&ident_names, key->id.kind), buf); + if (key->issuer.len > 0) + { + dntoa(buf, BUF_LEN, key->issuer); + whack_log(RC_COMMENT," issuer: '%s'", buf); + } + if (key->serial.len > 0) + { + datatot(key->serial.ptr, key->serial.len, ':' + , buf, BUF_LEN); + whack_log(RC_COMMENT," serial: %s", buf); + } + } + p = p->next; } - p = p->next; - } } diff --git a/src/pluto/keys.h b/src/pluto/keys.h index 6ee4560a1..362bab738 100644 --- a/src/pluto/keys.h +++ b/src/pluto/keys.h @@ -32,11 +32,11 @@ extern void load_preshared_secrets(int whackfd); extern void free_preshared_secrets(void); enum PrivateKeyKind { - PPK_PSK, - /* PPK_DSS, */ /* not implemented */ - PPK_RSA, - PPK_XAUTH, - PPK_PIN + PPK_PSK, + /* PPK_DSS, */ /* not implemented */ + PPK_RSA, + PPK_XAUTH, + PPK_PIN }; extern void xauth_defaults(void); @@ -54,60 +54,60 @@ extern const RSA_private_key_t *get_x509_private_key(const x509cert_t *cert); typedef struct pubkey pubkey_t; struct pubkey { - struct id id; - unsigned refcnt; /* reference counted! */ - enum dns_auth_level dns_auth_level; - char *dns_sig; - time_t installed_time - , last_tried_time - , last_worked_time - , until_time; - chunk_t issuer; - chunk_t serial; - enum pubkey_alg alg; - union { - RSA_public_key_t rsa; - } u; + struct id id; + unsigned refcnt; /* reference counted! */ + enum dns_auth_level dns_auth_level; + char *dns_sig; + time_t installed_time + , last_tried_time + , last_worked_time + , until_time; + chunk_t issuer; + chunk_t serial; + enum pubkey_alg alg; + union { + RSA_public_key_t rsa; + } u; }; typedef struct pubkey_list pubkey_list_t; struct pubkey_list { - pubkey_t *key; - pubkey_list_t *next; + pubkey_t *key; + pubkey_list_t *next; }; -extern pubkey_list_t *pubkeys; /* keys from ipsec.conf or from certs */ +extern pubkey_list_t *pubkeys; /* keys from ipsec.conf or from certs */ extern pubkey_t *public_key_from_rsa(const RSA_public_key_t *k); extern pubkey_list_t *free_public_keyentry(pubkey_list_t *p); extern void free_public_keys(pubkey_list_t **keys); extern void free_remembered_public_keys(void); extern void delete_public_keys(const struct id *id, enum pubkey_alg alg - , chunk_t issuer, chunk_t serial); + , chunk_t issuer, chunk_t serial); extern pubkey_t *reference_key(pubkey_t *pk); extern void unreference_key(pubkey_t **pkp); extern err_t add_public_key(const struct id *id - , enum dns_auth_level dns_auth_level - , enum pubkey_alg alg - , const chunk_t *key - , pubkey_list_t **head); + , enum dns_auth_level dns_auth_level + , enum pubkey_alg alg + , const chunk_t *key + , pubkey_list_t **head); extern bool has_private_key(cert_t cert); extern void add_x509_public_key(x509cert_t *cert, time_t until - , enum dns_auth_level dns_auth_level); + , enum dns_auth_level dns_auth_level); extern void add_pgp_public_key(pgpcert_t *cert, time_t until - , enum dns_auth_level dns_auth_level); + , enum dns_auth_level dns_auth_level); extern void remove_x509_public_key(const x509cert_t *cert); extern void list_public_keys(bool utc); -struct gw_info; /* forward declaration of tag (defined in dnskey.h) */ +struct gw_info; /* forward declaration of tag (defined in dnskey.h) */ extern void transfer_to_public_keys(struct gw_info *gateways_from_dns #ifdef USE_KEYRR - , pubkey_list_t **keys + , pubkey_list_t **keys #endif /* USE_KEYRR */ - ); + ); #endif /* _KEYS_H */ diff --git a/src/pluto/lex.c b/src/pluto/lex.c index 31abea498..71d1711f2 100644 --- a/src/pluto/lex.c +++ b/src/pluto/lex.c @@ -27,7 +27,7 @@ #include "constants.h" #include "defs.h" #include "log.h" -#include "whack.h" /* for RC_LOG_SERIOUS */ +#include "whack.h" /* for RC_LOG_SERIOUS */ #include "lex.h" struct file_lex_position *flp = NULL; @@ -39,36 +39,36 @@ struct file_lex_position *flp = NULL; bool lexopen(struct file_lex_position *new_flp, const char *name, bool optional) { - FILE *f = fopen(name, "r"); + FILE *f = fopen(name, "r"); - if (f == NULL) - { - if (!optional || errno != ENOENT) - log_errno((e, "could not open \"%s\"", name)); - return FALSE; - } - else - { - new_flp->previous = flp; - flp = new_flp; - flp->filename = name; - flp->fp = f; - flp->lino = 0; - flp->bdry = B_none; + if (f == NULL) + { + if (!optional || errno != ENOENT) + log_errno((e, "could not open \"%s\"", name)); + return FALSE; + } + else + { + new_flp->previous = flp; + flp = new_flp; + flp->filename = name; + flp->fp = f; + flp->lino = 0; + flp->bdry = B_none; - flp->cur = flp->buffer; /* nothing loaded yet */ - flp->under = *flp->cur = '\0'; + flp->cur = flp->buffer; /* nothing loaded yet */ + flp->under = *flp->cur = '\0'; - (void) shift(); /* prime tok */ - return TRUE; - } + (void) shift(); /* prime tok */ + return TRUE; + } } void lexclose(void) { - fclose(flp->fp); - flp = flp->previous; + fclose(flp->fp); + flp = flp->previous; } /* Token decoding: shift() loads the next token into tok. @@ -88,110 +88,110 @@ char *tok; bool shift(void) { - char *p = flp->cur; - char *sor = NULL; /* start of record for any new lines */ + char *p = flp->cur; + char *sor = NULL; /* start of record for any new lines */ - passert(flp->bdry == B_none); + passert(flp->bdry == B_none); - *p = flp->under; - flp->under = '\0'; + *p = flp->under; + flp->under = '\0'; - for (;;) - { - switch (*p) + for (;;) { - case '\0': /* end of line */ - case '#': /* comment to end of line: treat as end of line */ - /* get the next line */ - if (fgets(flp->buffer, sizeof(flp->buffer)-1, flp->fp) == NULL) - { - flp->bdry = B_file; - tok = flp->cur = NULL; - return FALSE; - } - else - { - /* strip trailing whitespace, including \n */ - - for (p = flp->buffer+strlen(flp->buffer)-1 - ; p>flp->buffer && isspace(p[-1]); p--) - ; - *p = '\0'; - - flp->lino++; - sor = p = flp->buffer; - } - break; /* try again for a token */ - - case ' ': /* whitespace */ - case '\t': - p++; - break; /* try again for a token */ - - case '"': /* quoted token */ - case '\'': - if (p != sor) - { - /* we have a quoted token: note and advance to its end */ - tok = p; - p = strchr(p+1, *p); - if (p == NULL) + switch (*p) { - loglog(RC_LOG_SERIOUS, "\"%s\" line %d: unterminated string" - , flp->filename, flp->lino); - p = tok + strlen(tok); - } - else - { - p++; /* include delimiter in token */ - } + case '\0': /* end of line */ + case '#': /* comment to end of line: treat as end of line */ + /* get the next line */ + if (fgets(flp->buffer, sizeof(flp->buffer)-1, flp->fp) == NULL) + { + flp->bdry = B_file; + tok = flp->cur = NULL; + return FALSE; + } + else + { + /* strip trailing whitespace, including \n */ - /* remember token delimiter and replace with '\0' */ - flp->under = *p; - *p = '\0'; - flp->cur = p; - return TRUE; - } - /* FALL THROUGH */ - default: - if (p != sor) - { - /* we seem to have a token: note and advance to its end */ - tok = p; + for (p = flp->buffer+strlen(flp->buffer)-1 + ; p>flp->buffer && isspace(p[-1]); p--) + ; + *p = '\0'; - if (p[0] == '0' && p[1] == 't') - { - /* 0t... token goes to end of line */ - p += strlen(p); - } - else - { - /* "ordinary" token: up to whitespace or end of line */ - do { + flp->lino++; + sor = p = flp->buffer; + } + break; /* try again for a token */ + + case ' ': /* whitespace */ + case '\t': p++; - } while (*p != '\0' && !isspace(*p)) - ; + break; /* try again for a token */ - /* fudge to separate ':' from a preceding adjacent token */ - if (p-1 > tok && p[-1] == ':') - p--; + case '"': /* quoted token */ + case '\'': + if (p != sor) + { + /* we have a quoted token: note and advance to its end */ + tok = p; + p = strchr(p+1, *p); + if (p == NULL) + { + loglog(RC_LOG_SERIOUS, "\"%s\" line %d: unterminated string" + , flp->filename, flp->lino); + p = tok + strlen(tok); + } + else + { + p++; /* include delimiter in token */ + } + + /* remember token delimiter and replace with '\0' */ + flp->under = *p; + *p = '\0'; + flp->cur = p; + return TRUE; + } + /* FALL THROUGH */ + default: + if (p != sor) + { + /* we seem to have a token: note and advance to its end */ + tok = p; + + if (p[0] == '0' && p[1] == 't') + { + /* 0t... token goes to end of line */ + p += strlen(p); + } + else + { + /* "ordinary" token: up to whitespace or end of line */ + do { + p++; + } while (*p != '\0' && !isspace(*p)) + ; + + /* fudge to separate ':' from a preceding adjacent token */ + if (p-1 > tok && p[-1] == ':') + p--; + } + + /* remember token delimiter and replace with '\0' */ + flp->under = *p; + *p = '\0'; + flp->cur = p; + return TRUE; + } + + /* we have a start-of-record: return it, deferring "real" token */ + flp->bdry = B_record; + tok = NULL; + flp->under = *p; + flp->cur = p; + return FALSE; } - - /* remember token delimiter and replace with '\0' */ - flp->under = *p; - *p = '\0'; - flp->cur = p; - return TRUE; - } - - /* we have a start-of-record: return it, deferring "real" token */ - flp->bdry = B_record; - tok = NULL; - flp->under = *p; - flp->cur = p; - return FALSE; } - } } /* ensures we are at a Record (or File) boundary, optionally warning if not */ @@ -199,15 +199,15 @@ shift(void) bool flushline(const char *m) { - if (flp->bdry != B_none) - { - return TRUE; - } - else - { - if (m != NULL) - loglog(RC_LOG_SERIOUS, "\"%s\" line %d: %s", flp->filename, flp->lino, m); - do ; while (shift()); - return FALSE; - } + if (flp->bdry != B_none) + { + return TRUE; + } + else + { + if (m != NULL) + loglog(RC_LOG_SERIOUS, "\"%s\" line %d: %s", flp->filename, flp->lino, m); + do ; while (shift()); + return FALSE; + } } diff --git a/src/pluto/lex.h b/src/pluto/lex.h index 297672965..c5194ed3a 100644 --- a/src/pluto/lex.h +++ b/src/pluto/lex.h @@ -17,15 +17,15 @@ #define MAX_TOK_LEN 2048 /* includes terminal '\0' */ struct file_lex_position { - int depth; /* how deeply we are nested */ - const char *filename; - FILE *fp; - enum { B_none, B_record, B_file } bdry; /* current boundary */ - int lino; /* line number in file */ - char buffer[MAX_TOK_LEN + 1]; /* note: one extra char for our use (jamming '"') */ - char *cur; /* cursor */ - char under; /* except in shift(): character orignally at *cur */ - struct file_lex_position *previous; + int depth; /* how deeply we are nested */ + const char *filename; + FILE *fp; + enum { B_none, B_record, B_file } bdry; /* current boundary */ + int lino; /* line number in file */ + char buffer[MAX_TOK_LEN + 1]; /* note: one extra char for our use (jamming '"') */ + char *cur; /* cursor */ + char under; /* except in shift(): character orignally at *cur */ + struct file_lex_position *previous; }; extern struct file_lex_position *flp; diff --git a/src/pluto/library.c b/src/pluto/library.c index 29e57e130..83a1e9918 100644 --- a/src/pluto/library.c +++ b/src/pluto/library.c @@ -33,16 +33,16 @@ typedef struct private_library_t private_library_t; */ struct private_library_t { - /** - * public functions - */ - library_t public; + /** + * public functions + */ + library_t public; #ifdef LEAK_DETECTIVE - /** - * Memory leak detective, if enabled - */ - leak_detective_t *detective; + /** + * Memory leak detective, if enabled + */ + leak_detective_t *detective; #endif /* LEAK_DETECTIVE */ }; @@ -56,19 +56,19 @@ library_t *lib; */ void library_deinit() { - private_library_t *this = (private_library_t*)lib; + private_library_t *this = (private_library_t*)lib; - this->public.settings->destroy(this->public.settings); - this->public.printf_hook->destroy(this->public.printf_hook); - + this->public.settings->destroy(this->public.settings); + this->public.printf_hook->destroy(this->public.printf_hook); + #ifdef LEAK_DETECTIVE - if (this->detective) - { - this->detective->destroy(this->detective); - } + if (this->detective) + { + this->detective->destroy(this->detective); + } #endif /* LEAK_DETECTIVE */ - free(this); - lib = NULL; + free(this); + lib = NULL; } /* @@ -76,31 +76,31 @@ void library_deinit() */ void library_init(char *settings) { - printf_hook_t *pfh; - private_library_t *this = malloc_thing(private_library_t); - lib = &this->public; - - lib->leak_detective = FALSE; - + printf_hook_t *pfh; + private_library_t *this = malloc_thing(private_library_t); + lib = &this->public; + + lib->leak_detective = FALSE; + #ifdef LEAK_DETECTIVE - this->detective = leak_detective_create(); + this->detective = leak_detective_create(); #endif /* LEAK_DETECTIVE */ - pfh = printf_hook_create(); - this->public.printf_hook = pfh; - - pfh->add_handler(pfh, 'b', mem_printf_hook, - PRINTF_HOOK_ARGTYPE_POINTER, PRINTF_HOOK_ARGTYPE_INT, - PRINTF_HOOK_ARGTYPE_END); - pfh->add_handler(pfh, 'B', chunk_printf_hook, - PRINTF_HOOK_ARGTYPE_POINTER, PRINTF_HOOK_ARGTYPE_END); - pfh->add_handler(pfh, 'T', time_printf_hook, - PRINTF_HOOK_ARGTYPE_POINTER, PRINTF_HOOK_ARGTYPE_INT, - PRINTF_HOOK_ARGTYPE_END); - pfh->add_handler(pfh, 'V', time_delta_printf_hook, - PRINTF_HOOK_ARGTYPE_POINTER, PRINTF_HOOK_ARGTYPE_POINTER, - PRINTF_HOOK_ARGTYPE_END); + pfh = printf_hook_create(); + this->public.printf_hook = pfh; + + pfh->add_handler(pfh, 'b', mem_printf_hook, + PRINTF_HOOK_ARGTYPE_POINTER, PRINTF_HOOK_ARGTYPE_INT, + PRINTF_HOOK_ARGTYPE_END); + pfh->add_handler(pfh, 'B', chunk_printf_hook, + PRINTF_HOOK_ARGTYPE_POINTER, PRINTF_HOOK_ARGTYPE_END); + pfh->add_handler(pfh, 'T', time_printf_hook, + PRINTF_HOOK_ARGTYPE_POINTER, PRINTF_HOOK_ARGTYPE_INT, + PRINTF_HOOK_ARGTYPE_END); + pfh->add_handler(pfh, 'V', time_delta_printf_hook, + PRINTF_HOOK_ARGTYPE_POINTER, PRINTF_HOOK_ARGTYPE_POINTER, + PRINTF_HOOK_ARGTYPE_END); - this->public.settings = settings_create(settings); + this->public.settings = settings_create(settings); } diff --git a/src/pluto/library.h b/src/pluto/library.h index 921c5f256..ce141ccfd 100644 --- a/src/pluto/library.h +++ b/src/pluto/library.h @@ -28,26 +28,26 @@ typedef struct library_t library_t; */ struct library_t { - /** - * Printf hook registering facility - */ - printf_hook_t *printf_hook; - - /** - * various settings loaded from settings file - */ - settings_t *settings; - - /** - * is leak detective running? - */ - bool leak_detective; + /** + * Printf hook registering facility + */ + printf_hook_t *printf_hook; + + /** + * various settings loaded from settings file + */ + settings_t *settings; + + /** + * is leak detective running? + */ + bool leak_detective; }; /** * Initialize library, creates "lib" instance. * - * @param settings file to read settings from, may be NULL for none + * @param settings file to read settings from, may be NULL for none */ void library_init(char *settings); diff --git a/src/pluto/log.c b/src/pluto/log.c index 7a30d7e31..ed815ca68 100644 --- a/src/pluto/log.c +++ b/src/pluto/log.c @@ -23,7 +23,7 @@ #include #include #include -#include /* used only if MSG_NOSIGNAL not defined */ +#include /* used only if MSG_NOSIGNAL not defined */ #include #include #include @@ -38,27 +38,27 @@ #include "state.h" #include "connections.h" #include "kernel.h" -#include "whack.h" /* needs connections.h */ +#include "whack.h" /* needs connections.h */ #include "timer.h" /* close one per-peer log */ -static void perpeer_logclose(struct connection *c); /* forward */ +static void perpeer_logclose(struct connection *c); /* forward */ bool - log_to_stderr = TRUE, /* should log go to stderr? */ - log_to_syslog = TRUE, /* should log go to syslog? */ - log_to_perpeer= FALSE; /* should log go to per-IP file? */ + log_to_stderr = TRUE, /* should log go to stderr? */ + log_to_syslog = TRUE, /* should log go to syslog? */ + log_to_perpeer= FALSE; /* should log go to per-IP file? */ bool - logged_txt_warning = FALSE; /* should we complain about finding KEY? */ + logged_txt_warning = FALSE; /* should we complain about finding KEY? */ /* should we complain when we find no local id */ bool - logged_myid_fqdn_txt_warning = FALSE, - logged_myid_ip_txt_warning = FALSE, - logged_myid_fqdn_key_warning = FALSE, - logged_myid_ip_key_warning = FALSE; + logged_myid_fqdn_txt_warning = FALSE, + logged_myid_ip_txt_warning = FALSE, + logged_myid_fqdn_key_warning = FALSE, + logged_myid_ip_key_warning = FALSE; /* may include trailing / */ const char *base_perpeer_logdir = PERPEERLOGDIR; @@ -74,42 +74,42 @@ static TAILQ_HEAD(perpeer, connection) perpeer_list; * If the context provides a whack file descriptor, messages * should be copied to it -- see whack_log() */ -int whack_log_fd = NULL_FD; /* only set during whack_handle() */ -struct state *cur_state = NULL; /* current state, for diagnostics */ -struct connection *cur_connection = NULL; /* current connection, for diagnostics */ -const ip_address *cur_from = NULL; /* source of current current message */ -u_int16_t cur_from_port; /* host order */ +int whack_log_fd = NULL_FD; /* only set during whack_handle() */ +struct state *cur_state = NULL; /* current state, for diagnostics */ +struct connection *cur_connection = NULL; /* current connection, for diagnostics */ +const ip_address *cur_from = NULL; /* source of current current message */ +u_int16_t cur_from_port; /* host order */ void init_log(const char *program) { - if (log_to_stderr) - setbuf(stderr, NULL); - if (log_to_syslog) - openlog(program, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_AUTHPRIV); + if (log_to_stderr) + setbuf(stderr, NULL); + if (log_to_syslog) + openlog(program, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_AUTHPRIV); - TAILQ_INIT(&perpeer_list); + TAILQ_INIT(&perpeer_list); } void close_peerlog(void) { - /* exit if the queue has not been initialized */ - if (perpeer_list.tqh_first == NULL) - return; + /* exit if the queue has not been initialized */ + if (perpeer_list.tqh_first == NULL) + return; - /* end of queue is given by pointer to "HEAD" */ - while (TAILQ_LAST(&perpeer_list, perpeer) != (void *)&perpeer_list) - perpeer_logclose(TAILQ_LAST(&perpeer_list, perpeer)); + /* end of queue is given by pointer to "HEAD" */ + while (TAILQ_LAST(&perpeer_list, perpeer) != (void *)&perpeer_list) + perpeer_logclose(TAILQ_LAST(&perpeer_list, perpeer)); } void close_log(void) { - if (log_to_syslog) - closelog(); + if (log_to_syslog) + closelog(); - close_peerlog(); + close_peerlog(); } /* Sanitize character string in situ: turns dangerous characters into \OOO. @@ -120,50 +120,50 @@ close_log(void) static size_t sanitize(char *buf, size_t size) { -# define UGLY_WIDTH 4 /* width for ugly character: \OOO */ - size_t len; - size_t added = 0; - char *p; +# define UGLY_WIDTH 4 /* width for ugly character: \OOO */ + size_t len; + size_t added = 0; + char *p; - passert(size >= UGLY_WIDTH); /* need room to swing cat */ + passert(size >= UGLY_WIDTH); /* need room to swing cat */ - /* find right side of string to be sanitized and count - * number of columns to be added. Stop on end of string - * or lack of room for more result. - */ - for (p = buf; *p != '\0' && &p[added] < &buf[size - UGLY_WIDTH]; ) - { - unsigned char c = *p++; + /* find right side of string to be sanitized and count + * number of columns to be added. Stop on end of string + * or lack of room for more result. + */ + for (p = buf; *p != '\0' && &p[added] < &buf[size - UGLY_WIDTH]; ) + { + unsigned char c = *p++; - if (c == '\\' || !isprint(c)) - added += UGLY_WIDTH - 1; - } + if (c == '\\' || !isprint(c)) + added += UGLY_WIDTH - 1; + } - /* at this point, p points after last original character to be - * included. added is how many characters are added to sanitize. - * so p[added] will point after last sanitized character. - */ + /* at this point, p points after last original character to be + * included. added is how many characters are added to sanitize. + * so p[added] will point after last sanitized character. + */ - p[added] = '\0'; - len = &p[added] - buf; + p[added] = '\0'; + len = &p[added] - buf; - /* scan backwards, copying characters to their new home - * and inserting the expansions for ugly characters. - * It is finished when no more shifting is required. - * This is a predecrement loop. - */ - while (added != 0) - { - char fmtd[UGLY_WIDTH + 1]; - unsigned char c; + /* scan backwards, copying characters to their new home + * and inserting the expansions for ugly characters. + * It is finished when no more shifting is required. + * This is a predecrement loop. + */ + while (added != 0) + { + char fmtd[UGLY_WIDTH + 1]; + unsigned char c; - while ((c = *--p) != '\\' && isprint(c)) - p[added] = c; - added -= UGLY_WIDTH - 1; - snprintf(fmtd, sizeof(fmtd), "\\%03o", c); - memcpy(p + added, fmtd, UGLY_WIDTH); - } - return len; + while ((c = *--p) != '\\' && isprint(c)) + p[added] = c; + added -= UGLY_WIDTH - 1; + snprintf(fmtd, sizeof(fmtd), "\\%03o", c); + memcpy(p + added, fmtd, UGLY_WIDTH); + } + return len; # undef UGLY_WIDTH } @@ -174,348 +174,348 @@ sanitize(char *buf, size_t size) static void fmt_log(char *buf, size_t buf_len, const char *fmt, va_list ap) { - bool reproc = *fmt == '~'; - size_t ps; - struct connection *c = cur_state != NULL ? cur_state->st_connection - : cur_connection; + bool reproc = *fmt == '~'; + size_t ps; + struct connection *c = cur_state != NULL ? cur_state->st_connection + : cur_connection; - buf[0] = '\0'; - if (reproc) - fmt++; /* ~ at start of format suppresses this prefix */ - else if (c != NULL) - { - /* start with name of connection */ - char *const be = buf + buf_len; - char *bp = buf; - - snprintf(bp, be - bp, "\"%s\"", c->name); - bp += strlen(bp); - - /* if it fits, put in any connection instance information */ - if (be - bp > CONN_INST_BUF) + buf[0] = '\0'; + if (reproc) + fmt++; /* ~ at start of format suppresses this prefix */ + else if (c != NULL) { - fmt_conn_instance(c, bp); - bp += strlen(bp); + /* start with name of connection */ + char *const be = buf + buf_len; + char *bp = buf; + + snprintf(bp, be - bp, "\"%s\"", c->name); + bp += strlen(bp); + + /* if it fits, put in any connection instance information */ + if (be - bp > CONN_INST_BUF) + { + fmt_conn_instance(c, bp); + bp += strlen(bp); + } + + if (cur_state != NULL) + { + /* state number */ + snprintf(bp, be - bp, " #%lu", cur_state->st_serialno); + bp += strlen(bp); + } + snprintf(bp, be - bp, ": "); + } + else if (cur_from != NULL) + { + /* peer's IP address */ + /* Note: must not use ip_str() because our caller might! */ + char ab[ADDRTOT_BUF]; + + (void) addrtot(cur_from, 0, ab, sizeof(ab)); + snprintf(buf, buf_len, "packet from %s:%u: " + , ab, (unsigned)cur_from_port); } - if (cur_state != NULL) - { - /* state number */ - snprintf(bp, be - bp, " #%lu", cur_state->st_serialno); - bp += strlen(bp); - } - snprintf(bp, be - bp, ": "); - } - else if (cur_from != NULL) - { - /* peer's IP address */ - /* Note: must not use ip_str() because our caller might! */ - char ab[ADDRTOT_BUF]; - - (void) addrtot(cur_from, 0, ab, sizeof(ab)); - snprintf(buf, buf_len, "packet from %s:%u: " - , ab, (unsigned)cur_from_port); - } - - ps = strlen(buf); - vsnprintf(buf + ps, buf_len - ps, fmt, ap); - if (!reproc) - (void)sanitize(buf, buf_len); + ps = strlen(buf); + vsnprintf(buf + ps, buf_len - ps, fmt, ap); + if (!reproc) + (void)sanitize(buf, buf_len); } static void perpeer_logclose(struct connection *c) { - /* only free/close things if we had used them! */ - if (c->log_file != NULL) - { - passert(perpeer_count > 0); + /* only free/close things if we had used them! */ + if (c->log_file != NULL) + { + passert(perpeer_count > 0); - TAILQ_REMOVE(&perpeer_list, c, log_link); - perpeer_count--; - fclose(c->log_file); - c->log_file=NULL; - } + TAILQ_REMOVE(&perpeer_list, c, log_link); + perpeer_count--; + fclose(c->log_file); + c->log_file=NULL; + } } void perpeer_logfree(struct connection *c) { - perpeer_logclose(c); - if (c->log_file_name != NULL) - { - free(c->log_file_name); - c->log_file_name = NULL; - c->log_file_err = FALSE; - } + perpeer_logclose(c); + if (c->log_file_name != NULL) + { + free(c->log_file_name); + c->log_file_name = NULL; + c->log_file_err = FALSE; + } } /* open the per-peer log */ static void open_peerlog(struct connection *c) { - syslog(LOG_INFO, "opening log file for conn %s", c->name); + syslog(LOG_INFO, "opening log file for conn %s", c->name); - if (c->log_file_name == NULL) - { - char peername[ADDRTOT_BUF], dname[ADDRTOT_BUF]; - int peernamelen, lf_len; - - addrtot(&c->spd.that.host_addr, 'Q', peername, sizeof(peername)); - peernamelen = strlen(peername); - - /* copy IP address, turning : and . into / */ + if (c->log_file_name == NULL) { - char c, *p, *q; + char peername[ADDRTOT_BUF], dname[ADDRTOT_BUF]; + int peernamelen, lf_len; - p = peername; - q = dname; - do { - c = *p++; - if (c == '.' || c == ':') - c = '/'; - *q++ = c; - } while (c != '\0'); + addrtot(&c->spd.that.host_addr, 'Q', peername, sizeof(peername)); + peernamelen = strlen(peername); + + /* copy IP address, turning : and . into / */ + { + char c, *p, *q; + + p = peername; + q = dname; + do { + c = *p++; + if (c == '.' || c == ':') + c = '/'; + *q++ = c; + } while (c != '\0'); + } + + lf_len = peernamelen * 2 + + strlen(base_perpeer_logdir) + + sizeof("//.log") + + 1; + c->log_file_name = malloc(lf_len); + + fprintf(stderr, "base dir |%s| dname |%s| peername |%s|" + , base_perpeer_logdir, dname, peername); + snprintf(c->log_file_name, lf_len, "%s/%s/%s.log" + , base_perpeer_logdir, dname, peername); + + syslog(LOG_DEBUG, "conn %s logfile is %s", c->name, c->log_file_name); } - lf_len = peernamelen * 2 - + strlen(base_perpeer_logdir) - + sizeof("//.log") - + 1; - c->log_file_name = malloc(lf_len); + /* now open the file, creating directories if necessary */ - fprintf(stderr, "base dir |%s| dname |%s| peername |%s|" - , base_perpeer_logdir, dname, peername); - snprintf(c->log_file_name, lf_len, "%s/%s/%s.log" - , base_perpeer_logdir, dname, peername); + { /* create the directory */ + char *dname; + int bpl_len = strlen(base_perpeer_logdir); + char *slashloc; - syslog(LOG_DEBUG, "conn %s logfile is %s", c->name, c->log_file_name); - } + dname = clone_str(c->log_file_name); + dname = dirname(dname); - /* now open the file, creating directories if necessary */ + if (access(dname, W_OK) != 0) + { + if (errno != ENOENT) + { + if (c->log_file_err) + { + syslog(LOG_CRIT, "can not write to %s: %s" + , dname, strerror(errno)); + c->log_file_err = TRUE; + free(dname); + return; + } + } - { /* create the directory */ - char *dname; - int bpl_len = strlen(base_perpeer_logdir); - char *slashloc; + /* directory does not exist, walk path creating dirs */ + /* start at base_perpeer_logdir */ + slashloc = dname + bpl_len; + slashloc++; /* since, by construction there is a slash + right there */ - dname = clone_str(c->log_file_name); - dname = dirname(dname); + while (*slashloc != '\0') + { + char saveslash; - if (access(dname, W_OK) != 0) + /* look for next slash */ + while (*slashloc != '\0' && *slashloc != '/') slashloc++; + + saveslash = *slashloc; + + *slashloc = '\0'; + + if (mkdir(dname, 0750) != 0 && errno != EEXIST) + { + syslog(LOG_CRIT, "can not create dir %s: %s" + , dname, strerror(errno)); + c->log_file_err = TRUE; + free(dname); + return; + } + syslog(LOG_DEBUG, "created new directory %s", dname); + *slashloc = saveslash; + slashloc++; + } + } + free(dname); + } + + c->log_file = fopen(c->log_file_name, "a"); + if (c->log_file == NULL) { - if (errno != ENOENT) - { if (c->log_file_err) { - syslog(LOG_CRIT, "can not write to %s: %s" - , dname, strerror(errno)); - c->log_file_err = TRUE; - free(dname); - return; + syslog(LOG_CRIT, "logging system can not open %s: %s" + , c->log_file_name, strerror(errno)); + c->log_file_err = TRUE; } - } - - /* directory does not exist, walk path creating dirs */ - /* start at base_perpeer_logdir */ - slashloc = dname + bpl_len; - slashloc++; /* since, by construction there is a slash - right there */ - - while (*slashloc != '\0') - { - char saveslash; - - /* look for next slash */ - while (*slashloc != '\0' && *slashloc != '/') slashloc++; - - saveslash = *slashloc; - - *slashloc = '\0'; - - if (mkdir(dname, 0750) != 0 && errno != EEXIST) - { - syslog(LOG_CRIT, "can not create dir %s: %s" - , dname, strerror(errno)); - c->log_file_err = TRUE; - free(dname); - return; - } - syslog(LOG_DEBUG, "created new directory %s", dname); - *slashloc = saveslash; - slashloc++; - } + return; } - free(dname); - } - c->log_file = fopen(c->log_file_name, "a"); - if (c->log_file == NULL) - { - if (c->log_file_err) + /* look for a connection to close! */ + while (perpeer_count >= MAX_PEERLOG_COUNT) { - syslog(LOG_CRIT, "logging system can not open %s: %s" - , c->log_file_name, strerror(errno)); - c->log_file_err = TRUE; + /* can not be NULL because perpeer_count > 0 */ + passert(TAILQ_LAST(&perpeer_list, perpeer) != (void *)&perpeer_list); + + perpeer_logclose(TAILQ_LAST(&perpeer_list, perpeer)); } - return; - } - /* look for a connection to close! */ - while (perpeer_count >= MAX_PEERLOG_COUNT) - { - /* can not be NULL because perpeer_count > 0 */ - passert(TAILQ_LAST(&perpeer_list, perpeer) != (void *)&perpeer_list); - - perpeer_logclose(TAILQ_LAST(&perpeer_list, perpeer)); - } - - /* insert this into the list */ - TAILQ_INSERT_HEAD(&perpeer_list, c, log_link); - passert(c->log_file != NULL); - perpeer_count++; + /* insert this into the list */ + TAILQ_INSERT_HEAD(&perpeer_list, c, log_link); + passert(c->log_file != NULL); + perpeer_count++; } /* log a line to cur_connection's log */ static void peerlog(const char *prefix, const char *m) { - if (cur_connection == NULL) - { - /* we can not log it in this case. Oh well. */ - return; - } + if (cur_connection == NULL) + { + /* we can not log it in this case. Oh well. */ + return; + } - if (cur_connection->log_file == NULL) - { - open_peerlog(cur_connection); - } + if (cur_connection->log_file == NULL) + { + open_peerlog(cur_connection); + } - /* despite our attempts above, we may not be able to open the file. */ - if (cur_connection->log_file != NULL) - { - char datebuf[32]; - time_t n; - struct tm *t; + /* despite our attempts above, we may not be able to open the file. */ + if (cur_connection->log_file != NULL) + { + char datebuf[32]; + time_t n; + struct tm *t; - time(&n); - t = localtime(&n); + time(&n); + t = localtime(&n); - strftime(datebuf, sizeof(datebuf), "%Y-%m-%d %T", t); - fprintf(cur_connection->log_file, "%s %s%s\n", datebuf, prefix, m); + strftime(datebuf, sizeof(datebuf), "%Y-%m-%d %T", t); + fprintf(cur_connection->log_file, "%s %s%s\n", datebuf, prefix, m); - /* now move it to the front of the list */ - TAILQ_REMOVE(&perpeer_list, cur_connection, log_link); - TAILQ_INSERT_HEAD(&perpeer_list, cur_connection, log_link); - } + /* now move it to the front of the list */ + TAILQ_REMOVE(&perpeer_list, cur_connection, log_link); + TAILQ_INSERT_HEAD(&perpeer_list, cur_connection, log_link); + } } void plog(const char *message, ...) { - va_list args; - char m[LOG_WIDTH]; /* longer messages will be truncated */ + va_list args; + char m[LOG_WIDTH]; /* longer messages will be truncated */ - va_start(args, message); - fmt_log(m, sizeof(m), message, args); - va_end(args); + va_start(args, message); + fmt_log(m, sizeof(m), message, args); + va_end(args); - if (log_to_stderr) - fprintf(stderr, "%s\n", m); - if (log_to_syslog) - syslog(LOG_WARNING, "%s", m); - if (log_to_perpeer) - peerlog("", m); + if (log_to_stderr) + fprintf(stderr, "%s\n", m); + if (log_to_syslog) + syslog(LOG_WARNING, "%s", m); + if (log_to_perpeer) + peerlog("", m); - whack_log(RC_LOG, "~%s", m); + whack_log(RC_LOG, "~%s", m); } void loglog(int mess_no, const char *message, ...) { - va_list args; - char m[LOG_WIDTH]; /* longer messages will be truncated */ + va_list args; + char m[LOG_WIDTH]; /* longer messages will be truncated */ - va_start(args, message); - fmt_log(m, sizeof(m), message, args); - va_end(args); + va_start(args, message); + fmt_log(m, sizeof(m), message, args); + va_end(args); - if (log_to_stderr) - fprintf(stderr, "%s\n", m); - if (log_to_syslog) - syslog(LOG_WARNING, "%s", m); - if (log_to_perpeer) - peerlog("", m); + if (log_to_stderr) + fprintf(stderr, "%s\n", m); + if (log_to_syslog) + syslog(LOG_WARNING, "%s", m); + if (log_to_perpeer) + peerlog("", m); - whack_log(mess_no, "~%s", m); + whack_log(mess_no, "~%s", m); } void log_errno_routine(int e, const char *message, ...) { - va_list args; - char m[LOG_WIDTH]; /* longer messages will be truncated */ + va_list args; + char m[LOG_WIDTH]; /* longer messages will be truncated */ - va_start(args, message); - fmt_log(m, sizeof(m), message, args); - va_end(args); + va_start(args, message); + fmt_log(m, sizeof(m), message, args); + va_end(args); - if (log_to_stderr) - fprintf(stderr, "ERROR: %s. Errno %d: %s\n", m, e, strerror(e)); - if (log_to_syslog) - syslog(LOG_ERR, "ERROR: %s. Errno %d: %s", m, e, strerror(e)); - if (log_to_perpeer) - { - peerlog(strerror(e), m); - } + if (log_to_stderr) + fprintf(stderr, "ERROR: %s. Errno %d: %s\n", m, e, strerror(e)); + if (log_to_syslog) + syslog(LOG_ERR, "ERROR: %s. Errno %d: %s", m, e, strerror(e)); + if (log_to_perpeer) + { + peerlog(strerror(e), m); + } - whack_log(RC_LOG_SERIOUS - , "~ERROR: %s. Errno %d: %s", m, e, strerror(e)); + whack_log(RC_LOG_SERIOUS + , "~ERROR: %s. Errno %d: %s", m, e, strerror(e)); } void exit_log(const char *message, ...) { - va_list args; - char m[LOG_WIDTH]; /* longer messages will be truncated */ + va_list args; + char m[LOG_WIDTH]; /* longer messages will be truncated */ - va_start(args, message); - fmt_log(m, sizeof(m), message, args); - va_end(args); + va_start(args, message); + fmt_log(m, sizeof(m), message, args); + va_end(args); - if (log_to_stderr) - fprintf(stderr, "FATAL ERROR: %s\n", m); - if (log_to_syslog) - syslog(LOG_ERR, "FATAL ERROR: %s", m); - if (log_to_perpeer) - peerlog("FATAL ERROR: ", m); + if (log_to_stderr) + fprintf(stderr, "FATAL ERROR: %s\n", m); + if (log_to_syslog) + syslog(LOG_ERR, "FATAL ERROR: %s", m); + if (log_to_perpeer) + peerlog("FATAL ERROR: ", m); - whack_log(RC_LOG_SERIOUS, "~FATAL ERROR: %s", m); + whack_log(RC_LOG_SERIOUS, "~FATAL ERROR: %s", m); - exit_pluto(1); + exit_pluto(1); } void exit_log_errno_routine(int e, const char *message, ...) { - va_list args; - char m[LOG_WIDTH]; /* longer messages will be truncated */ + va_list args; + char m[LOG_WIDTH]; /* longer messages will be truncated */ - va_start(args, message); - fmt_log(m, sizeof(m), message, args); - va_end(args); + va_start(args, message); + fmt_log(m, sizeof(m), message, args); + va_end(args); - if (log_to_stderr) - fprintf(stderr, "FATAL ERROR: %s. Errno %d: %s\n", m, e, strerror(e)); - if (log_to_syslog) - syslog(LOG_ERR, "FATAL ERROR: %s. Errno %d: %s", m, e, strerror(e)); - if (log_to_perpeer) - peerlog(strerror(e), m); + if (log_to_stderr) + fprintf(stderr, "FATAL ERROR: %s. Errno %d: %s\n", m, e, strerror(e)); + if (log_to_syslog) + syslog(LOG_ERR, "FATAL ERROR: %s. Errno %d: %s", m, e, strerror(e)); + if (log_to_perpeer) + peerlog(strerror(e), m); - whack_log(RC_LOG_SERIOUS - , "~FATAL ERROR: %s. Errno %d: %s", m, e, strerror(e)); + whack_log(RC_LOG_SERIOUS + , "~FATAL ERROR: %s. Errno %d: %s", m, e, strerror(e)); - exit_pluto(1); + exit_pluto(1); } /* emit message to whack. @@ -530,65 +530,65 @@ static volatile sig_atomic_t dying_breath = FALSE; void whack_log(int mess_no, const char *message, ...) { - int wfd = whack_log_fd != NULL_FD ? whack_log_fd - : cur_state != NULL ? cur_state->st_whack_sock - : NULL_FD; + int wfd = whack_log_fd != NULL_FD ? whack_log_fd + : cur_state != NULL ? cur_state->st_whack_sock + : NULL_FD; - if (wfd != NULL_FD + if (wfd != NULL_FD #ifdef DEBUG - || dying_breath + || dying_breath #endif - ) - { - va_list args; - char m[LOG_WIDTH]; /* longer messages will be truncated */ - int prelen = snprintf(m, sizeof(m), "%03d ", mess_no); + ) + { + va_list args; + char m[LOG_WIDTH]; /* longer messages will be truncated */ + int prelen = snprintf(m, sizeof(m), "%03d ", mess_no); - passert(prelen >= 0); + passert(prelen >= 0); - va_start(args, message); - fmt_log(m+prelen, sizeof(m)-prelen, message, args); - va_end(args); + va_start(args, message); + fmt_log(m+prelen, sizeof(m)-prelen, message, args); + va_end(args); #if DEBUG - if (dying_breath) - { - /* status output copied to log */ - if (log_to_stderr) - fprintf(stderr, "%s\n", m + prelen); - if (log_to_syslog) - syslog(LOG_WARNING, "%s", m + prelen); - if (log_to_perpeer) - peerlog("", m); - } + if (dying_breath) + { + /* status output copied to log */ + if (log_to_stderr) + fprintf(stderr, "%s\n", m + prelen); + if (log_to_syslog) + syslog(LOG_WARNING, "%s", m + prelen); + if (log_to_perpeer) + peerlog("", m); + } #endif - if (wfd != NULL_FD) - { - /* write to whack socket, but suppress possible SIGPIPE */ - size_t len = strlen(m); -#ifdef MSG_NOSIGNAL /* depends on version of glibc??? */ - m[len] = '\n'; /* don't need NUL, do need NL */ - (void) send(wfd, m, len + 1, MSG_NOSIGNAL); + if (wfd != NULL_FD) + { + /* write to whack socket, but suppress possible SIGPIPE */ + size_t len = strlen(m); +#ifdef MSG_NOSIGNAL /* depends on version of glibc??? */ + m[len] = '\n'; /* don't need NUL, do need NL */ + (void) send(wfd, m, len + 1, MSG_NOSIGNAL); #else /* !MSG_NOSIGNAL */ - int r; - struct sigaction act - , oldact; + int r; + struct sigaction act + , oldact; - m[len] = '\n'; /* don't need NUL, do need NL */ - act.sa_handler = SIG_IGN; - sigemptyset(&act.sa_mask); - act.sa_flags = 0; /* no nothing */ - r = sigaction(SIGPIPE, &act, &oldact); - passert(r == 0); + m[len] = '\n'; /* don't need NUL, do need NL */ + act.sa_handler = SIG_IGN; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; /* no nothing */ + r = sigaction(SIGPIPE, &act, &oldact); + passert(r == 0); - (void) write(wfd, m, len + 1); + (void) write(wfd, m, len + 1); - r = sigaction(SIGPIPE, &oldact, NULL); - passert(r == 0); + r = sigaction(SIGPIPE, &oldact, NULL); + passert(r == 0); #endif /* !MSG_NOSIGNAL */ + } } - } } /* Build up a diagnostic in a static buffer. @@ -606,16 +606,16 @@ char diag_space[sizeof(diag_space)]; err_t builddiag(const char *fmt, ...) { - static char diag_space[LOG_WIDTH]; /* longer messages will be truncated */ - char t[sizeof(diag_space)]; /* build result here first */ - va_list args; + static char diag_space[LOG_WIDTH]; /* longer messages will be truncated */ + char t[sizeof(diag_space)]; /* build result here first */ + va_list args; - va_start(args, fmt); - t[0] = '\0'; /* in case nothing terminates string */ - vsnprintf(t, sizeof(t), fmt, args); - va_end(args); - strcpy(diag_space, t); - return diag_space; + va_start(args, fmt); + t[0] = '\0'; /* in case nothing terminates string */ + vsnprintf(t, sizeof(t), fmt, args); + va_end(args); + strcpy(diag_space, t); + return diag_space; } /* Debugging message support */ @@ -625,51 +625,51 @@ builddiag(const char *fmt, ...) void switch_fail(int n, const char *file_str, unsigned long line_no) { - char buf[30]; + char buf[30]; - snprintf(buf, sizeof(buf), "case %d unexpected", n); - passert_fail(buf, file_str, line_no); + snprintf(buf, sizeof(buf), "case %d unexpected", n); + passert_fail(buf, file_str, line_no); } void passert_fail(const char *pred_str, const char *file_str, unsigned long line_no) { - /* we will get a possibly unplanned prefix. Hope it works */ - loglog(RC_LOG_SERIOUS, "ASSERTION FAILED at %s:%lu: %s", file_str, line_no, pred_str); - if (!dying_breath) - { - dying_breath = TRUE; - show_status(TRUE, NULL); - } - abort(); /* exiting correctly doesn't always work */ + /* we will get a possibly unplanned prefix. Hope it works */ + loglog(RC_LOG_SERIOUS, "ASSERTION FAILED at %s:%lu: %s", file_str, line_no, pred_str); + if (!dying_breath) + { + dying_breath = TRUE; + show_status(TRUE, NULL); + } + abort(); /* exiting correctly doesn't always work */ } void pexpect_log(const char *pred_str, const char *file_str, unsigned long line_no) { - /* we will get a possibly unplanned prefix. Hope it works */ - loglog(RC_LOG_SERIOUS, "EXPECTATION FAILED at %s:%lu: %s", file_str, line_no, pred_str); + /* we will get a possibly unplanned prefix. Hope it works */ + loglog(RC_LOG_SERIOUS, "EXPECTATION FAILED at %s:%lu: %s", file_str, line_no, pred_str); } lset_t - base_debugging = DBG_NONE, /* default to reporting nothing */ - cur_debugging = DBG_NONE; + base_debugging = DBG_NONE, /* default to reporting nothing */ + cur_debugging = DBG_NONE; void extra_debugging(const struct connection *c) { - if(c == NULL) - { - reset_debugging(); - return; - } + if(c == NULL) + { + reset_debugging(); + return; + } - if (c!= NULL && c->extra_debugging != 0) - { - plog("enabling for connection: %s" - , bitnamesof(debug_bit_names, c->extra_debugging & ~cur_debugging)); - cur_debugging |= c->extra_debugging; - } + if (c!= NULL && c->extra_debugging != 0) + { + plog("enabling for connection: %s" + , bitnamesof(debug_bit_names, c->extra_debugging & ~cur_debugging)); + cur_debugging |= c->extra_debugging; + } } /* log a debugging message (prefixed by "| ") */ @@ -677,21 +677,21 @@ extra_debugging(const struct connection *c) void DBG_log(const char *message, ...) { - va_list args; - char m[LOG_WIDTH]; /* longer messages will be truncated */ + va_list args; + char m[LOG_WIDTH]; /* longer messages will be truncated */ - va_start(args, message); - vsnprintf(m, sizeof(m), message, args); - va_end(args); + va_start(args, message); + vsnprintf(m, sizeof(m), message, args); + va_end(args); - (void)sanitize(m, sizeof(m)); + (void)sanitize(m, sizeof(m)); - if (log_to_stderr) - fprintf(stderr, "| %s\n", m); - if (log_to_syslog) - syslog(LOG_DEBUG, "| %s", m); - if (log_to_perpeer) - peerlog("| ", m); + if (log_to_stderr) + fprintf(stderr, "| %s\n", m); + if (log_to_syslog) + syslog(LOG_DEBUG, "| %s", m); + if (log_to_perpeer) + peerlog("| ", m); } /* dump raw bytes in hex to stderr (for lack of any better destination) */ @@ -699,62 +699,62 @@ DBG_log(const char *message, ...) void DBG_dump(const char *label, const void *p, size_t len) { -# define DUMP_LABEL_WIDTH 20 /* arbitrary modest boundary */ -# define DUMP_WIDTH (4 * (1 + 4 * 3) + 1) - char buf[DUMP_LABEL_WIDTH + DUMP_WIDTH]; - char *bp; - const unsigned char *cp = p; +# define DUMP_LABEL_WIDTH 20 /* arbitrary modest boundary */ +# define DUMP_WIDTH (4 * (1 + 4 * 3) + 1) + char buf[DUMP_LABEL_WIDTH + DUMP_WIDTH]; + char *bp; + const unsigned char *cp = p; - bp = buf; - - if (label != NULL && label[0] != '\0') - { - /* Handle the label. Care must be taken to avoid buffer overrun. */ - size_t llen = strlen(label); - - if (llen + 1 > sizeof(buf)) - { - DBG_log("%s", label); - } - else - { - strcpy(buf, label); - if (buf[llen-1] == '\n') - { - buf[llen-1] = '\0'; /* get rid of newline */ - DBG_log("%s", buf); - } - else if (llen < DUMP_LABEL_WIDTH) - { - bp = buf + llen; - } - else - { - DBG_log("%s", buf); - } - } - } - - do { - int i, j; - - for (i = 0; len!=0 && i!=4; i++) - { - *bp++ = ' '; - for (j = 0; len!=0 && j!=4; len--, j++) - { - static const char hexdig[] = "0123456789abcdef"; - - *bp++ = ' '; - *bp++ = hexdig[(*cp >> 4) & 0xF]; - *bp++ = hexdig[*cp & 0xF]; - cp++; - } - } - *bp = '\0'; - DBG_log("%s", buf); bp = buf; - } while (len != 0); + + if (label != NULL && label[0] != '\0') + { + /* Handle the label. Care must be taken to avoid buffer overrun. */ + size_t llen = strlen(label); + + if (llen + 1 > sizeof(buf)) + { + DBG_log("%s", label); + } + else + { + strcpy(buf, label); + if (buf[llen-1] == '\n') + { + buf[llen-1] = '\0'; /* get rid of newline */ + DBG_log("%s", buf); + } + else if (llen < DUMP_LABEL_WIDTH) + { + bp = buf + llen; + } + else + { + DBG_log("%s", buf); + } + } + } + + do { + int i, j; + + for (i = 0; len!=0 && i!=4; i++) + { + *bp++ = ' '; + for (j = 0; len!=0 && j!=4; len--, j++) + { + static const char hexdig[] = "0123456789abcdef"; + + *bp++ = ' '; + *bp++ = hexdig[(*cp >> 4) & 0xF]; + *bp++ = hexdig[*cp & 0xF]; + cp++; + } + } + *bp = '\0'; + DBG_log("%s", buf); + bp = buf; + } while (len != 0); # undef DUMP_LABEL_WIDTH # undef DUMP_WIDTH } @@ -764,17 +764,17 @@ DBG_dump(const char *label, const void *p, size_t len) void show_status(bool all, const char *name) { - if (all) - { - show_ifaces_status(); - show_myid_status(); - show_debug_status(); - whack_log(RC_COMMENT, BLANK_FORMAT); /* spacer */ - } - show_connections_status(all, name); - show_states_status(all, name); + if (all) + { + show_ifaces_status(); + show_myid_status(); + show_debug_status(); + whack_log(RC_COMMENT, BLANK_FORMAT); /* spacer */ + } + show_connections_status(all, name); + show_states_status(all, name); #ifdef KLIPS - show_shunt_status(); + show_shunt_status(); #endif } @@ -787,10 +787,10 @@ show_status(bool all, const char *name) const char * ip_str(const ip_address *src) { - static char buf[ADDRTOT_BUF]; + static char buf[ADDRTOT_BUF]; - addrtot(src, 0, buf, sizeof(buf)); - return buf; + addrtot(src, 0, buf, sizeof(buf)); + return buf; } /* @@ -801,35 +801,35 @@ ip_str(const ip_address *src) void daily_log_reset(void) { - /* now perform actions */ - logged_txt_warning = FALSE; + /* now perform actions */ + logged_txt_warning = FALSE; - logged_myid_fqdn_txt_warning = FALSE; - logged_myid_ip_txt_warning = FALSE; - logged_myid_fqdn_key_warning = FALSE; - logged_myid_ip_key_warning = FALSE; + logged_myid_fqdn_txt_warning = FALSE; + logged_myid_ip_txt_warning = FALSE; + logged_myid_fqdn_key_warning = FALSE; + logged_myid_ip_key_warning = FALSE; } void daily_log_event(void) { - struct tm *ltime; - time_t n, interval; + struct tm *ltime; + time_t n, interval; - /* attempt to schedule oneself to midnight, local time - * do this by getting seconds in the day, and delaying - * by 86400 - hour*3600+minutes*60+seconds. - */ - time(&n); - ltime = localtime(&n); - interval = (24 * 60 * 60) - - (ltime->tm_sec - + ltime->tm_min * 60 - + ltime->tm_hour * 3600); + /* attempt to schedule oneself to midnight, local time + * do this by getting seconds in the day, and delaying + * by 86400 - hour*3600+minutes*60+seconds. + */ + time(&n); + ltime = localtime(&n); + interval = (24 * 60 * 60) + - (ltime->tm_sec + + ltime->tm_min * 60 + + ltime->tm_hour * 3600); - event_schedule(EVENT_LOG_DAILY, interval, NULL); + event_schedule(EVENT_LOG_DAILY, interval, NULL); - daily_log_reset(); + daily_log_reset(); } /* diff --git a/src/pluto/log.h b/src/pluto/log.h index 680c4aa87..86a3ce8f8 100644 --- a/src/pluto/log.h +++ b/src/pluto/log.h @@ -27,49 +27,49 @@ #ifdef DEBUG extern void passert_fail(const char *pred_str - , const char *file_str, unsigned long line_no) NEVER_RETURNS; + , const char *file_str, unsigned long line_no) NEVER_RETURNS; extern void pexpect_log(const char *pred_str - , const char *file_str, unsigned long line_no); + , const char *file_str, unsigned long line_no); # define impossible() passert_fail("impossible", __FILE__, __LINE__) extern void switch_fail(int n - , const char *file_str, unsigned long line_no) NEVER_RETURNS; + , const char *file_str, unsigned long line_no) NEVER_RETURNS; # define bad_case(n) switch_fail((int) n, __FILE__, __LINE__) # define passert(pred) { \ - if (!(pred)) \ - passert_fail(#pred, __FILE__, __LINE__); \ - } + if (!(pred)) \ + passert_fail(#pred, __FILE__, __LINE__); \ + } # define pexpect(pred) { \ - if (!(pred)) \ - pexpect_log(#pred, __FILE__, __LINE__); \ - } + if (!(pred)) \ + pexpect_log(#pred, __FILE__, __LINE__); \ + } /* assert that an err_t is NULL; evaluate exactly once */ # define happy(x) { \ - err_t ugh = x; \ - if (ugh != NULL) \ - passert_fail(ugh, __FILE__, __LINE__); \ - } + err_t ugh = x; \ + if (ugh != NULL) \ + passert_fail(ugh, __FILE__, __LINE__); \ + } #else /*!DEBUG*/ # define impossible() abort() # define bad_case(n) abort() -# define passert(pred) { } /* do nothing */ -# define happy(x) { (void) x; } /* evaluate non-judgementally */ +# define passert(pred) { } /* do nothing */ +# define happy(x) { (void) x; } /* evaluate non-judgementally */ #endif /*!DEBUG*/ extern bool - log_to_stderr, /* should log go to stderr? */ - log_to_syslog, /* should log go to syslog? */ - log_to_perpeer; /* should log go to per-IP file? */ + log_to_stderr, /* should log go to stderr? */ + log_to_syslog, /* should log go to syslog? */ + log_to_perpeer; /* should log go to per-IP file? */ extern const char *base_perpeer_logdir; @@ -84,25 +84,25 @@ extern const char *base_perpeer_logdir; * If the context provides a whack file descriptor, messages * should be copied to it -- see whack_log() */ -extern int whack_log_fd; /* only set during whack_handle() */ -extern struct state *cur_state; /* current state, for diagnostics */ -extern struct connection *cur_connection; /* current connection, for diagnostics */ -extern const ip_address *cur_from; /* source of current current message */ -extern u_int16_t cur_from_port; /* host order */ +extern int whack_log_fd; /* only set during whack_handle() */ +extern struct state *cur_state; /* current state, for diagnostics */ +extern struct connection *cur_connection; /* current connection, for diagnostics */ +extern const ip_address *cur_from; /* source of current current message */ +extern u_int16_t cur_from_port; /* host order */ #ifdef DEBUG - extern lset_t cur_debugging; /* current debugging level */ + extern lset_t cur_debugging; /* current debugging level */ extern void extra_debugging(const struct connection *c); # define reset_debugging() { cur_debugging = base_debugging; } # define GLOBALS_ARE_RESET() (whack_log_fd == NULL_FD \ - && cur_state == NULL \ - && cur_connection == NULL \ - && cur_from == NULL \ - && cur_debugging == base_debugging) + && cur_state == NULL \ + && cur_connection == NULL \ + && cur_from == NULL \ + && cur_debugging == base_debugging) #else /*!DEBUG*/ @@ -111,40 +111,40 @@ extern u_int16_t cur_from_port; /* host order */ # define reset_debugging() { } # define GLOBALS_ARE_RESET() (whack_log_fd == NULL_FD \ - && cur_state == NULL \ - && cur_connection == NULL \ - && cur_from == NULL) + && cur_state == NULL \ + && cur_connection == NULL \ + && cur_from == NULL) #endif /*!DEBUG*/ #define reset_globals() { \ - whack_log_fd = NULL_FD; \ - cur_state = NULL; \ - cur_from = NULL; \ - reset_cur_connection(); \ - } + whack_log_fd = NULL_FD; \ + cur_state = NULL; \ + cur_from = NULL; \ + reset_cur_connection(); \ + } #define set_cur_connection(c) { \ - cur_connection = (c); \ - extra_debugging(c); \ - } + cur_connection = (c); \ + extra_debugging(c); \ + } #define reset_cur_connection() { \ - cur_connection = NULL; \ - reset_debugging(); \ - } + cur_connection = NULL; \ + reset_debugging(); \ + } #define set_cur_state(s) { \ - cur_state = (s); \ - extra_debugging((s)->st_connection); \ - } + cur_state = (s); \ + extra_debugging((s)->st_connection); \ + } #define reset_cur_state() { \ - cur_state = NULL; \ - reset_debugging(); \ - } + cur_state = NULL; \ + reset_debugging(); \ + } extern void init_log(const char *program); extern void close_log(void); @@ -188,12 +188,12 @@ extern void show_status(bool all, const char *name); * restriction is not checked in any way: violators will produce * confusing results (without crashing!). */ -extern char diag_space[LOG_WIDTH]; /* output buffer, but can be occupied at call */ +extern char diag_space[LOG_WIDTH]; /* output buffer, but can be occupied at call */ extern err_t builddiag(const char *fmt, ...) PRINTF_LIKE(1); #ifdef DEBUG -extern lset_t base_debugging; /* bits selecting what to report */ +extern lset_t base_debugging; /* bits selecting what to report */ #define DBGP(cond) (cur_debugging & (cond)) #define DBG(cond, action) { if (DBGP(cond)) { action ; } } @@ -204,7 +204,7 @@ extern void DBG_dump(const char *label, const void *p, size_t len); #else /*!DEBUG*/ -#define DBG(cond, action) { } /* do nothing */ +#define DBG(cond, action) { } /* do nothing */ #endif /*!DEBUG*/ diff --git a/src/pluto/md2.c b/src/pluto/md2.c index d6465477d..8b0f166a5 100644 --- a/src/pluto/md2.c +++ b/src/pluto/md2.c @@ -21,15 +21,15 @@ #include "md2.h" -#define HAVEMEMCOPY 1 /* use ISO C's memcpy and memset */ +#define HAVEMEMCOPY 1 /* use ISO C's memcpy and memset */ static void MD2Transform PROTO_LIST ((unsigned char [16], unsigned char [16], const unsigned char [16])); #ifdef HAVEMEMCOPY #include -#define MD2_memcpy memcpy -#define MD2_memset memset +#define MD2_memcpy memcpy +#define MD2_memset memset #else #ifdef HAVEBCOPY #define MD2_memcpy(_a,_b,_c) memcpy((_a), (_b),(_c)) @@ -79,13 +79,13 @@ static const unsigned char *PADDING[] = { (const unsigned char *)"\013\013\013\013\013\013\013\013\013\013\013", (const unsigned char *)"\014\014\014\014\014\014\014\014\014\014\014\014", (const unsigned char *) - "\015\015\015\015\015\015\015\015\015\015\015\015\015", + "\015\015\015\015\015\015\015\015\015\015\015\015\015", (const unsigned char *) - "\016\016\016\016\016\016\016\016\016\016\016\016\016\016", + "\016\016\016\016\016\016\016\016\016\016\016\016\016\016", (const unsigned char *) - "\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017", + "\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017", (const unsigned char *) - "\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020" + "\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020" }; /* MD2 initialization. Begins an MD2 operation, writing a new context. @@ -96,12 +96,12 @@ MD2_CTX *context; /* context */ context->count = 0; MD2_memset ((POINTER)context->state, 0, sizeof (context->state)); MD2_memset - ((POINTER)context->checksum, 0, sizeof (context->checksum)); + ((POINTER)context->checksum, 0, sizeof (context->checksum)); } /* MD2 block update operation. Continues an MD2 message-digest - operation, processing another message block, and updating the - context. + operation, processing another message block, and updating the + context. */ void MD2Update (context, input, inputLen) MD2_CTX *context; /* context */ @@ -117,28 +117,28 @@ unsigned int inputLen; /* length of input block */ partLen = 16 - index; /* Transform as many times as possible. - */ + */ if (inputLen >= partLen) { - MD2_memcpy - ((POINTER)&context->buffer[index], (CONST_POINTER)input, partLen); - MD2Transform (context->state, context->checksum, context->buffer); + MD2_memcpy + ((POINTER)&context->buffer[index], (CONST_POINTER)input, partLen); + MD2Transform (context->state, context->checksum, context->buffer); - for (i = partLen; i + 15 < inputLen; i += 16) - MD2Transform (context->state, context->checksum, &input[i]); + for (i = partLen; i + 15 < inputLen; i += 16) + MD2Transform (context->state, context->checksum, &input[i]); - index = 0; + index = 0; } else - i = 0; + i = 0; /* Buffer remaining input */ MD2_memcpy - ((POINTER)&context->buffer[index], (CONST_POINTER)&input[i], - inputLen-i); + ((POINTER)&context->buffer[index], (CONST_POINTER)&input[i], + inputLen-i); } /* MD2 finalization. Ends an MD2 message-digest operation, writing the - message digest and zeroizing the context. + message digest and zeroizing the context. */ void MD2Final (digest, context) @@ -165,7 +165,7 @@ MD2_CTX *context; /* context */ } /* MD2 basic transformation. Transforms state and updates checksum - based on block. + based on block. */ static void MD2Transform (state, checksum, block) unsigned char state[16]; @@ -180,15 +180,15 @@ const unsigned char block[16]; MD2_memcpy ((POINTER)x, (CONST_POINTER)state, 16); MD2_memcpy ((POINTER)x+16, (CONST_POINTER)block, 16); for (i = 0; i < 16; i++) - x[i+32] = state[i] ^ block[i]; + x[i+32] = state[i] ^ block[i]; /* Encrypt block (18 rounds). */ t = 0; for (i = 0; i < 18; i++) { - for (j = 0; j < 48; j++) - t = x[j] ^= PI_SUBST[t]; - t = (t + i) & 0xff; + for (j = 0; j < 48; j++) + t = x[j] ^= PI_SUBST[t]; + t = (t + i) & 0xff; } /* Save new state */ @@ -198,7 +198,7 @@ const unsigned char block[16]; */ t = checksum[15]; for (i = 0; i < 16; i++) - t = checksum[i] ^= PI_SUBST[block[i] ^ t]; + t = checksum[i] ^= PI_SUBST[block[i] ^ t]; /* Zeroize sensitive information. */ @@ -217,7 +217,7 @@ unsigned int len; unsigned int i; for (i = 0; i < len; i++) - output[i] = input[i]; + output[i] = input[i]; } /* Note: Replace "for loop" with standard memset if possible. @@ -230,7 +230,7 @@ unsigned int len; unsigned int i; for (i = 0; i < len; i++) - ((char *)output)[i] = (char)value; + ((char *)output)[i] = (char)value; } #endif #endif diff --git a/src/pluto/md2.h b/src/pluto/md2.h index b3b48dd92..52a7328d5 100644 --- a/src/pluto/md2.h +++ b/src/pluto/md2.h @@ -4,9 +4,9 @@ */ /* PROTOTYPES should be set to one if and only if the compiler supports - function argument prototyping. + function argument prototyping. The following makes PROTOTYPES default to 0 if it has not already - been defined with C compiler flags. + been defined with C compiler flags. */ #ifndef PROTOTYPES #define PROTOTYPES 1 @@ -24,7 +24,7 @@ typedef unsigned long int UINT4; /* PROTO_LIST is defined depending on how PROTOTYPES is defined above. If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it - returns an empty list. + returns an empty list. */ #if PROTOTYPES diff --git a/src/pluto/md5.c b/src/pluto/md5.c index 5d75e38a4..b220af551 100644 --- a/src/pluto/md5.c +++ b/src/pluto/md5.c @@ -41,12 +41,12 @@ documentation and/or software. #include #include -#include /* for u_int*_t */ -#include /* sets BYTE_ORDER, LITTLE_ENDIAN, and BIG_ENDIAN */ +#include /* for u_int*_t */ +#include /* sets BYTE_ORDER, LITTLE_ENDIAN, and BIG_ENDIAN */ #include "md5.h" -#define HAVEMEMCOPY 1 /* use ISO C's memcpy and memset */ +#define HAVEMEMCOPY 1 /* use ISO C's memcpy and memset */ /* Constants for MD5Transform routine. */ @@ -84,8 +84,8 @@ static void Decode PROTO_LIST #ifdef HAVEMEMCOPY #include -#define MD5_memcpy memcpy -#define MD5_memset memset +#define MD5_memcpy memcpy +#define MD5_memset memset #else #ifdef HAVEBCOPY #define MD5_memcpy(_a,_b,_c) memcpy((_a), (_b),(_c)) @@ -167,23 +167,23 @@ UINT4 inputLen; /* length of input block */ /* Update number of bits */ if ((context->count[0] += (inputLen << 3)) < (inputLen << 3)) - context->count[1]++; + context->count[1]++; context->count[1] += (inputLen >> 29); partLen = 64 - index; /* Transform as many times as possible. */ if (inputLen >= partLen) { - MD5_memcpy((POINTER)&context->buffer[index], (CONSTPOINTER)input, partLen); - MD5Transform (context->state, context->buffer); + MD5_memcpy((POINTER)&context->buffer[index], (CONSTPOINTER)input, partLen); + MD5Transform (context->state, context->buffer); - for (i = partLen; i + 63 < inputLen; i += 64) - MD5Transform (context->state, &input[i]); + for (i = partLen; i + 63 < inputLen; i += 64) + MD5Transform (context->state, &input[i]); - index = 0; + index = 0; } else - i = 0; + i = 0; /* Buffer remaining input */ MD5_memcpy((POINTER)&context->buffer[index], (CONSTPOINTER)&input[i], inputLen-i); @@ -211,14 +211,14 @@ MD5_CTX *context; /* context */ /* Append length (before padding) */ MD5Update (context, bits, 8); - if (digest != NULL) /* Bill Simpson's padding */ + if (digest != NULL) /* Bill Simpson's padding */ { - /* store state in digest */ - Encode (digest, context->state, 16); + /* store state in digest */ + Encode (digest, context->state, 16); - /* Zeroize sensitive information. - */ - MD5_memset ((POINTER)context, 0, sizeof (*context)); + /* Zeroize sensitive information. + */ + MD5_memset ((POINTER)context, 0, sizeof (*context)); } } diff --git a/src/pluto/md5.h b/src/pluto/md5.h index 9b29bc46e..a2c503cc7 100644 --- a/src/pluto/md5.h +++ b/src/pluto/md5.h @@ -4,9 +4,9 @@ */ /* PROTOTYPES should be set to one if and only if the compiler supports - function argument prototyping. + function argument prototyping. The following makes PROTOTYPES default to 0 if it has not already - been defined with C compiler flags. + been defined with C compiler flags. */ #ifndef PROTOTYPES #define PROTOTYPES 1 @@ -24,7 +24,7 @@ typedef u_int32_t UINT4; /* PROTO_LIST is defined depending on how PROTOTYPES is defined above. If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it - returns an empty list. + returns an empty list. */ #if PROTOTYPES diff --git a/src/pluto/modecfg.c b/src/pluto/modecfg.c index 4707de34b..04ee5b23c 100644 --- a/src/pluto/modecfg.c +++ b/src/pluto/modecfg.c @@ -42,18 +42,18 @@ #include "whack.h" #include "xauth.h" -#define MAX_XAUTH_TRIES 3 -#define DNS_SERVER_MAX 2 -#define NBNS_SERVER_MAX 2 +#define MAX_XAUTH_TRIES 3 +#define DNS_SERVER_MAX 2 +#define NBNS_SERVER_MAX 2 #define SUPPORTED_ATTR_SET ( LELEM(INTERNAL_IP4_ADDRESS) \ - | LELEM(INTERNAL_IP4_NETMASK) \ - | LELEM(INTERNAL_IP4_DNS) \ - | LELEM(INTERNAL_IP4_NBNS) \ - | LELEM(APPLICATION_VERSION) \ - | LELEM(INTERNAL_IP6_DNS) \ - | LELEM(INTERNAL_IP6_NBNS) \ - ) + | LELEM(INTERNAL_IP4_NETMASK) \ + | LELEM(INTERNAL_IP4_DNS) \ + | LELEM(INTERNAL_IP4_NBNS) \ + | LELEM(APPLICATION_VERSION) \ + | LELEM(INTERNAL_IP6_DNS) \ + | LELEM(INTERNAL_IP6_NBNS) \ + ) #define SUPPORTED_UNITY_ATTR_SET ( LELEM(UNITY_BANNER - UNITY_BASE) ) @@ -66,21 +66,21 @@ typedef struct internal_addr internal_addr_t; struct internal_addr { - lset_t attr_set; - lset_t xauth_attr_set; - lset_t unity_attr_set; + lset_t attr_set; + lset_t xauth_attr_set; + lset_t unity_attr_set; - /* ModeCfg variables */ - ip_address ipaddr; - ip_address dns[DNS_SERVER_MAX]; - ip_address nbns[NBNS_SERVER_MAX]; + /* ModeCfg variables */ + ip_address ipaddr; + ip_address dns[DNS_SERVER_MAX]; + ip_address nbns[NBNS_SERVER_MAX]; - char *unity_banner; + char *unity_banner; - /* XAUTH variables */ - u_int16_t xauth_type; - xauth_t xauth_secret; - bool xauth_status; + /* XAUTH variables */ + u_int16_t xauth_type; + xauth_t xauth_secret; + bool xauth_status; }; /* @@ -89,30 +89,30 @@ struct internal_addr static void init_internal_addr(internal_addr_t *ia) { - int i; + int i; - ia->attr_set = LEMPTY; - ia->xauth_attr_set = LEMPTY; - ia->xauth_secret.user_name = chunk_empty; - ia->xauth_secret.user_password = chunk_empty; - ia->xauth_type = XAUTH_TYPE_GENERIC; - ia->xauth_status = XAUTH_STATUS_FAIL; - ia->unity_attr_set = LEMPTY; - ia->unity_banner = NULL; + ia->attr_set = LEMPTY; + ia->xauth_attr_set = LEMPTY; + ia->xauth_secret.user_name = chunk_empty; + ia->xauth_secret.user_password = chunk_empty; + ia->xauth_type = XAUTH_TYPE_GENERIC; + ia->xauth_status = XAUTH_STATUS_FAIL; + ia->unity_attr_set = LEMPTY; + ia->unity_banner = NULL; - anyaddr(AF_INET, &ia->ipaddr); + anyaddr(AF_INET, &ia->ipaddr); - /* initialize DNS server information */ - for (i = 0; i < DNS_SERVER_MAX; i++) - { - anyaddr(AF_INET, &ia->dns[i]); - } + /* initialize DNS server information */ + for (i = 0; i < DNS_SERVER_MAX; i++) + { + anyaddr(AF_INET, &ia->dns[i]); + } - /* initialize WINS server information */ - for (i = 0; i < NBNS_SERVER_MAX; i++) - { - anyaddr(AF_INET, &ia->nbns[i]); - } + /* initialize WINS server information */ + for (i = 0; i < NBNS_SERVER_MAX; i++) + { + anyaddr(AF_INET, &ia->nbns[i]); + } } /* @@ -121,83 +121,83 @@ init_internal_addr(internal_addr_t *ia) static void get_internal_addr(struct connection *c, internal_addr_t *ia) { - int i, dns_idx = 0, nbns_idx = 0; + int i, dns_idx = 0, nbns_idx = 0; - if (isanyaddr(&c->spd.that.host_srcip)) - { - /* not defined in connection - fetch it from LDAP */ - } - else - { - char srcip[ADDRTOT_BUF]; - - ia->ipaddr = c->spd.that.host_srcip; - - addrtot(&ia->ipaddr, 0, srcip, sizeof(srcip)); - plog("assigning virtual IP source address %s", srcip); - } - - if (!isanyaddr(&ia->ipaddr)) /* We got an IP address, send it */ - { - c->spd.that.client.addr = ia->ipaddr; - c->spd.that.client.maskbits = 32; - c->spd.that.has_client = TRUE; - - ia->attr_set = LELEM(INTERNAL_IP4_ADDRESS) - | LELEM(INTERNAL_IP4_NETMASK); - } - - /* assign DNS servers */ - for (i = 1; i <= DNS_SERVER_MAX; i++) - { - char dns_key[16], *dns_str; - - snprintf(dns_key, sizeof(dns_key), "pluto.dns%d", i); - dns_str = lib->settings->get_str(lib->settings, dns_key, NULL); - if (dns_str) + if (isanyaddr(&c->spd.that.host_srcip)) { - err_t ugh; - sa_family_t family = strchr(dns_str, ':') ? AF_INET6 : AF_INET; - - ugh = ttoaddr(dns_str, 0, family, &ia->dns[dns_idx]); - if (ugh != NULL) - { - plog("error in DNS server address: %s", ugh); - continue; - } - plog("assigning DNS server %s to peer", dns_str); - - /* differentiate between IP4 and IP6 in modecfg_build_msg() */ - ia->attr_set |= LELEM(INTERNAL_IP4_DNS); - dns_idx++; + /* not defined in connection - fetch it from LDAP */ } - } - - /* assign WINS servers */ - for (i = 1; i <= NBNS_SERVER_MAX; i++) - { - char nbns_key[16], *nbns_str; - - snprintf(nbns_key, sizeof(nbns_key), "pluto.nbns%d", i); - nbns_str = lib->settings->get_str(lib->settings, nbns_key, NULL); - if (nbns_str) + else { - err_t ugh; - sa_family_t family = strchr(nbns_str, ':') ? AF_INET6 : AF_INET; + char srcip[ADDRTOT_BUF]; - ugh = ttoaddr(nbns_str, 0, family, &ia->nbns[nbns_idx]); - if (ugh != NULL) - { - plog("error in WINS server address: %s", ugh); - continue; - } - plog("assigning NBNS server %s to peer", nbns_str); + ia->ipaddr = c->spd.that.host_srcip; - /* differentiate between IP4 and IP6 in modecfg_build_msg() */ - ia->attr_set |= LELEM(INTERNAL_IP4_NBNS); - nbns_idx++; + addrtot(&ia->ipaddr, 0, srcip, sizeof(srcip)); + plog("assigning virtual IP source address %s", srcip); + } + + if (!isanyaddr(&ia->ipaddr)) /* We got an IP address, send it */ + { + c->spd.that.client.addr = ia->ipaddr; + c->spd.that.client.maskbits = 32; + c->spd.that.has_client = TRUE; + + ia->attr_set = LELEM(INTERNAL_IP4_ADDRESS) + | LELEM(INTERNAL_IP4_NETMASK); + } + + /* assign DNS servers */ + for (i = 1; i <= DNS_SERVER_MAX; i++) + { + char dns_key[16], *dns_str; + + snprintf(dns_key, sizeof(dns_key), "pluto.dns%d", i); + dns_str = lib->settings->get_str(lib->settings, dns_key, NULL); + if (dns_str) + { + err_t ugh; + sa_family_t family = strchr(dns_str, ':') ? AF_INET6 : AF_INET; + + ugh = ttoaddr(dns_str, 0, family, &ia->dns[dns_idx]); + if (ugh != NULL) + { + plog("error in DNS server address: %s", ugh); + continue; + } + plog("assigning DNS server %s to peer", dns_str); + + /* differentiate between IP4 and IP6 in modecfg_build_msg() */ + ia->attr_set |= LELEM(INTERNAL_IP4_DNS); + dns_idx++; + } + } + + /* assign WINS servers */ + for (i = 1; i <= NBNS_SERVER_MAX; i++) + { + char nbns_key[16], *nbns_str; + + snprintf(nbns_key, sizeof(nbns_key), "pluto.nbns%d", i); + nbns_str = lib->settings->get_str(lib->settings, nbns_key, NULL); + if (nbns_str) + { + err_t ugh; + sa_family_t family = strchr(nbns_str, ':') ? AF_INET6 : AF_INET; + + ugh = ttoaddr(nbns_str, 0, family, &ia->nbns[nbns_idx]); + if (ugh != NULL) + { + plog("error in WINS server address: %s", ugh); + continue; + } + plog("assigning NBNS server %s to peer", nbns_str); + + /* differentiate between IP4 and IP6 in modecfg_build_msg() */ + ia->attr_set |= LELEM(INTERNAL_IP4_NBNS); + nbns_idx++; + } } - } } @@ -207,39 +207,39 @@ get_internal_addr(struct connection *c, internal_addr_t *ia) static bool set_internal_addr(struct connection *c, internal_addr_t *ia) { - if (ia->attr_set & LELEM(INTERNAL_IP4_ADDRESS) - && !isanyaddr(&ia->ipaddr)) - { - if (addrbytesptr(&c->spd.this.host_srcip, NULL) == 0 - || isanyaddr(&c->spd.this.host_srcip) - || sameaddr(&c->spd.this.host_srcip, &ia->ipaddr)) + if (ia->attr_set & LELEM(INTERNAL_IP4_ADDRESS) + && !isanyaddr(&ia->ipaddr)) { - char srcip[ADDRTOT_BUF]; + if (addrbytesptr(&c->spd.this.host_srcip, NULL) == 0 + || isanyaddr(&c->spd.this.host_srcip) + || sameaddr(&c->spd.this.host_srcip, &ia->ipaddr)) + { + char srcip[ADDRTOT_BUF]; - addrtot(&ia->ipaddr, 0, srcip, sizeof(srcip)); - plog("setting virtual IP source address to %s", srcip); + addrtot(&ia->ipaddr, 0, srcip, sizeof(srcip)); + plog("setting virtual IP source address to %s", srcip); + } + else + { + char old_srcip[ADDRTOT_BUF]; + char new_srcip[ADDRTOT_BUF]; + + addrtot(&c->spd.this.host_srcip, 0, old_srcip, sizeof(old_srcip)); + addrtot(&ia->ipaddr, 0, new_srcip, sizeof(new_srcip)); + plog("replacing virtual IP source address %s by %s" + , old_srcip, new_srcip); + } + + /* setting srcip */ + c->spd.this.host_srcip = ia->ipaddr; + + /* setting client subnet to srcip/32 */ + addrtosubnet(&ia->ipaddr, &c->spd.this.client); + setportof(0, &c->spd.this.client.addr); + c->spd.this.has_client = TRUE; + return TRUE; } - else - { - char old_srcip[ADDRTOT_BUF]; - char new_srcip[ADDRTOT_BUF]; - - addrtot(&c->spd.this.host_srcip, 0, old_srcip, sizeof(old_srcip)); - addrtot(&ia->ipaddr, 0, new_srcip, sizeof(new_srcip)); - plog("replacing virtual IP source address %s by %s" - , old_srcip, new_srcip); - } - - /* setting srcip */ - c->spd.this.host_srcip = ia->ipaddr; - - /* setting client subnet to srcip/32 */ - addrtosubnet(&ia->ipaddr, &c->spd.this.client); - setportof(0, &c->spd.this.client.addr); - c->spd.this.has_client = TRUE; - return TRUE; - } - return FALSE; + return FALSE; } /* @@ -247,20 +247,20 @@ set_internal_addr(struct connection *c, internal_addr_t *ia) */ static size_t modecfg_hash(u_char *dest, const u_char *start, const u_char *roof - , const struct state *st) + , const struct state *st) { - struct hmac_ctx ctx; + struct hmac_ctx ctx; - hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid_a); - hmac_update(&ctx, (const u_char *) &st->st_msgid, sizeof(st->st_msgid)); - hmac_update(&ctx, start, roof-start); - hmac_final(dest, &ctx); + hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid_a); + hmac_update(&ctx, (const u_char *) &st->st_msgid, sizeof(st->st_msgid)); + hmac_update(&ctx, start, roof-start); + hmac_final(dest, &ctx); - DBG(DBG_CRYPT, - DBG_log("ModeCfg HASH computed:"); - DBG_dump("", dest, ctx.hmac_digest_size) - ) - return ctx.hmac_digest_size; + DBG(DBG_CRYPT, + DBG_log("ModeCfg HASH computed:"); + DBG_dump("", dest, ctx.hmac_digest_size) + ) + return ctx.hmac_digest_size; } @@ -269,222 +269,222 @@ modecfg_hash(u_char *dest, const u_char *start, const u_char *roof */ static stf_status modecfg_build_msg(struct state *st, pb_stream *rbody - , u_int16_t msg_type - , internal_addr_t *ia - , u_int16_t ap_id) + , u_int16_t msg_type + , internal_addr_t *ia + , u_int16_t ap_id) { - u_char *r_hash_start, *r_hashval; + u_char *r_hash_start, *r_hashval; - START_HASH_PAYLOAD(*rbody, ISAKMP_NEXT_ATTR); + START_HASH_PAYLOAD(*rbody, ISAKMP_NEXT_ATTR); - /* ATTR out */ - { - struct isakmp_mode_attr attrh; - struct isakmp_attribute attr; - pb_stream strattr,attrval; - int attr_type, dns_attr_type, nbns_attr_type; - int dns_idx, nbns_idx; - bool dont_advance; - bool is_xauth_attr_set = ia->xauth_attr_set != LEMPTY; - bool is_unity_attr_set = ia->unity_attr_set != LEMPTY; - lset_t attr_set = ia->attr_set; - - attrh.isama_np = ISAKMP_NEXT_NONE; - attrh.isama_type = msg_type; - attrh.isama_identifier = ap_id; - - if (!out_struct(&attrh, &isakmp_attr_desc, rbody, &strattr)) + /* ATTR out */ { - return STF_INTERNAL_ERROR; - } - attr_type = 0; - dns_idx = 0; - nbns_idx = 0; + struct isakmp_mode_attr attrh; + struct isakmp_attribute attr; + pb_stream strattr,attrval; + int attr_type, dns_attr_type, nbns_attr_type; + int dns_idx, nbns_idx; + bool dont_advance; + bool is_xauth_attr_set = ia->xauth_attr_set != LEMPTY; + bool is_unity_attr_set = ia->unity_attr_set != LEMPTY; + lset_t attr_set = ia->attr_set; - while (attr_set != LEMPTY || is_xauth_attr_set || is_unity_attr_set) - { - if (attr_set == LEMPTY) - { - if (is_xauth_attr_set) - { - attr_set = ia->xauth_attr_set; - attr_type = XAUTH_BASE; - is_xauth_attr_set = FALSE; - } - else - { - attr_set = ia->unity_attr_set; - attr_type = UNITY_BASE; - is_unity_attr_set = FALSE; - } - } - - dont_advance = FALSE; + attrh.isama_np = ISAKMP_NEXT_NONE; + attrh.isama_type = msg_type; + attrh.isama_identifier = ap_id; - if (attr_set & 1) - { - const u_char *byte_ptr; - u_int len; + if (!out_struct(&attrh, &isakmp_attr_desc, rbody, &strattr)) + { + return STF_INTERNAL_ERROR; + } + attr_type = 0; + dns_idx = 0; + nbns_idx = 0; - /* ISAKMP attr out */ - if (attr_type == XAUTH_TYPE) + while (attr_set != LEMPTY || is_xauth_attr_set || is_unity_attr_set) { - attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TV; - attr.isaat_lv = ia->xauth_type; - } - else if (attr_type == XAUTH_STATUS) - { - attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TV; - attr.isaat_lv = ia->xauth_status; - } - else if (attr_type == INTERNAL_IP4_DNS && !isanyaddr(&ia->dns[dns_idx])) - { - dns_attr_type = (addrtypeof(&ia->dns[dns_idx]) == AF_INET) ? - INTERNAL_IP4_DNS : INTERNAL_IP6_DNS; - attr.isaat_af_type = dns_attr_type | ISAKMP_ATTR_AF_TLV; + if (attr_set == LEMPTY) + { + if (is_xauth_attr_set) + { + attr_set = ia->xauth_attr_set; + attr_type = XAUTH_BASE; + is_xauth_attr_set = FALSE; + } + else + { + attr_set = ia->unity_attr_set; + attr_type = UNITY_BASE; + is_unity_attr_set = FALSE; + } + } + + dont_advance = FALSE; - } - else if (attr_type == INTERNAL_IP4_NBNS && !isanyaddr(&ia->nbns[nbns_idx])) - { - nbns_attr_type = (addrtypeof(&ia->nbns[nbns_idx]) == AF_INET) ? - INTERNAL_IP4_NBNS : INTERNAL_IP6_NBNS; - attr.isaat_af_type = nbns_attr_type | ISAKMP_ATTR_AF_TLV; + if (attr_set & 1) + { + const u_char *byte_ptr; + u_int len; - } - else - { - attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TLV; - } - out_struct(&attr, &isakmp_modecfg_attribute_desc, &strattr, &attrval); + /* ISAKMP attr out */ + if (attr_type == XAUTH_TYPE) + { + attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TV; + attr.isaat_lv = ia->xauth_type; + } + else if (attr_type == XAUTH_STATUS) + { + attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TV; + attr.isaat_lv = ia->xauth_status; + } + else if (attr_type == INTERNAL_IP4_DNS && !isanyaddr(&ia->dns[dns_idx])) + { + dns_attr_type = (addrtypeof(&ia->dns[dns_idx]) == AF_INET) ? + INTERNAL_IP4_DNS : INTERNAL_IP6_DNS; + attr.isaat_af_type = dns_attr_type | ISAKMP_ATTR_AF_TLV; - switch (attr_type) - { - case INTERNAL_IP4_ADDRESS: - if (!isanyaddr(&ia->ipaddr)) - { - len = addrbytesptr(&ia->ipaddr, &byte_ptr); - out_raw(byte_ptr, len, &attrval, "IP4_addr"); - } - break; - case INTERNAL_IP4_NETMASK: - { - u_int mask; + } + else if (attr_type == INTERNAL_IP4_NBNS && !isanyaddr(&ia->nbns[nbns_idx])) + { + nbns_attr_type = (addrtypeof(&ia->nbns[nbns_idx]) == AF_INET) ? + INTERNAL_IP4_NBNS : INTERNAL_IP6_NBNS; + attr.isaat_af_type = nbns_attr_type | ISAKMP_ATTR_AF_TLV; + + } + else + { + attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TLV; + } + out_struct(&attr, &isakmp_modecfg_attribute_desc, &strattr, &attrval); + + switch (attr_type) + { + case INTERNAL_IP4_ADDRESS: + if (!isanyaddr(&ia->ipaddr)) + { + len = addrbytesptr(&ia->ipaddr, &byte_ptr); + out_raw(byte_ptr, len, &attrval, "IP4_addr"); + } + break; + case INTERNAL_IP4_NETMASK: + { + u_int mask; #if 0 - char mask[4],bits[8]={0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe}; - int t,m=st->st_connection->that.host_addr.maskbit; - for (t=0; t<4; t++) - { - if (m < 8) - mask[t] = bits[m]; - else - mask[t] = 0xff; - m -= 8; - } -#endif - if (st->st_connection->spd.this.client.maskbits == 0) - { - mask = 0; - } - else - { - mask = 0xffffffff * 1; - out_raw(&mask, 4, &attrval, "IP4_mask"); - } - } - break; - case INTERNAL_IP4_SUBNET: - { - char mask[4]; - char bits[8] = {0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe}; - int t; - int m = st->st_connection->spd.this.client.maskbits; + char mask[4],bits[8]={0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe}; + int t,m=st->st_connection->that.host_addr.maskbit; + for (t=0; t<4; t++) + { + if (m < 8) + mask[t] = bits[m]; + else + mask[t] = 0xff; + m -= 8; + } +#endif + if (st->st_connection->spd.this.client.maskbits == 0) + { + mask = 0; + } + else + { + mask = 0xffffffff * 1; + out_raw(&mask, 4, &attrval, "IP4_mask"); + } + } + break; + case INTERNAL_IP4_SUBNET: + { + char mask[4]; + char bits[8] = {0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe}; + int t; + int m = st->st_connection->spd.this.client.maskbits; - for (t = 0; t < 4; t++) + for (t = 0; t < 4; t++) + { + mask[t] = (m < 8) ? bits[m] : 0xff; + m -= 8; + if (m < 0) + { + m = 0; + } + } + len = addrbytesptr(&st->st_connection->spd.this.client.addr, &byte_ptr); + out_raw(byte_ptr, len, &attrval, "IP4_subnet"); + out_raw(mask, sizeof(mask), &attrval, "IP4_submsk"); + } + break; + case INTERNAL_IP4_DNS: + case INTERNAL_IP6_DNS: + if (!isanyaddr(&ia->dns[dns_idx])) + { + len = addrbytesptr(&ia->dns[dns_idx++], &byte_ptr); + out_raw(byte_ptr, len, &attrval, "IP_dns"); + } + if (dns_idx < DNS_SERVER_MAX && !isanyaddr(&ia->dns[dns_idx])) + { + dont_advance = TRUE; + } + break; + case INTERNAL_IP4_NBNS: + case INTERNAL_IP6_NBNS: + if (!isanyaddr(&ia->nbns[nbns_idx])) + { + len = addrbytesptr(&ia->nbns[nbns_idx++], &byte_ptr); + out_raw(byte_ptr, len, &attrval, "IP_nbns"); + } + if (nbns_idx < NBNS_SERVER_MAX && !isanyaddr(&ia->nbns[nbns_idx])) + { + dont_advance = TRUE; + } + break; + case XAUTH_TYPE: + break; + case XAUTH_USER_NAME: + if (ia->xauth_secret.user_name.ptr != NULL) + { + out_raw(ia->xauth_secret.user_name.ptr + , ia->xauth_secret.user_name.len + , &attrval, "xauth_user_name"); + } + break; + case XAUTH_USER_PASSWORD: + if (ia->xauth_secret.user_password.ptr != NULL) + { + out_raw(ia->xauth_secret.user_password.ptr + , ia->xauth_secret.user_password.len + , &attrval, "xauth_user_password"); + } + break; + case XAUTH_STATUS: + break; + case UNITY_BANNER: + if (ia->unity_banner != NULL) + { + out_raw(ia->unity_banner + , strlen(ia->unity_banner) + , &attrval, "UNITY_BANNER"); + } + break; + default: + plog("attempt to send unsupported mode cfg attribute %s." + , enum_show(&modecfg_attr_names, attr_type)); + break; + } + close_output_pbs(&attrval); + } + if (!dont_advance) { - mask[t] = (m < 8) ? bits[m] : 0xff; - m -= 8; - if (m < 0) - { - m = 0; - } + attr_type++; + attr_set >>= 1; } - len = addrbytesptr(&st->st_connection->spd.this.client.addr, &byte_ptr); - out_raw(byte_ptr, len, &attrval, "IP4_subnet"); - out_raw(mask, sizeof(mask), &attrval, "IP4_submsk"); - } - break; - case INTERNAL_IP4_DNS: - case INTERNAL_IP6_DNS: - if (!isanyaddr(&ia->dns[dns_idx])) - { - len = addrbytesptr(&ia->dns[dns_idx++], &byte_ptr); - out_raw(byte_ptr, len, &attrval, "IP_dns"); - } - if (dns_idx < DNS_SERVER_MAX && !isanyaddr(&ia->dns[dns_idx])) - { - dont_advance = TRUE; - } - break; - case INTERNAL_IP4_NBNS: - case INTERNAL_IP6_NBNS: - if (!isanyaddr(&ia->nbns[nbns_idx])) - { - len = addrbytesptr(&ia->nbns[nbns_idx++], &byte_ptr); - out_raw(byte_ptr, len, &attrval, "IP_nbns"); - } - if (nbns_idx < NBNS_SERVER_MAX && !isanyaddr(&ia->nbns[nbns_idx])) - { - dont_advance = TRUE; - } - break; - case XAUTH_TYPE: - break; - case XAUTH_USER_NAME: - if (ia->xauth_secret.user_name.ptr != NULL) - { - out_raw(ia->xauth_secret.user_name.ptr - , ia->xauth_secret.user_name.len - , &attrval, "xauth_user_name"); - } - break; - case XAUTH_USER_PASSWORD: - if (ia->xauth_secret.user_password.ptr != NULL) - { - out_raw(ia->xauth_secret.user_password.ptr - , ia->xauth_secret.user_password.len - , &attrval, "xauth_user_password"); - } - break; - case XAUTH_STATUS: - break; - case UNITY_BANNER: - if (ia->unity_banner != NULL) - { - out_raw(ia->unity_banner - , strlen(ia->unity_banner) - , &attrval, "UNITY_BANNER"); - } - break; - default: - plog("attempt to send unsupported mode cfg attribute %s." - , enum_show(&modecfg_attr_names, attr_type)); - break; } - close_output_pbs(&attrval); - } - if (!dont_advance) - { - attr_type++; - attr_set >>= 1; - } + close_message(&strattr); } - close_message(&strattr); - } - modecfg_hash(r_hashval, r_hash_start, rbody->cur, st); - close_message(rbody); - encrypt_message(rbody, st); - return STF_OK; + modecfg_hash(r_hashval, r_hash_start, rbody->cur, st); + close_message(rbody); + encrypt_message(rbody, st); + return STF_OK; } /* @@ -493,56 +493,56 @@ modecfg_build_msg(struct state *st, pb_stream *rbody static stf_status modecfg_send_msg(struct state *st, int isama_type, internal_addr_t *ia) { - pb_stream msg; - pb_stream rbody; - char buf[BUF_LEN]; + pb_stream msg; + pb_stream rbody; + char buf[BUF_LEN]; - /* set up attr */ - init_pbs(&msg, buf, sizeof(buf), "ModeCfg msg buffer"); + /* set up attr */ + init_pbs(&msg, buf, sizeof(buf), "ModeCfg msg buffer"); - /* this is the beginning of a new exchange */ - st->st_msgid = generate_msgid(st); - init_phase2_iv(st, &st->st_msgid); + /* this is the beginning of a new exchange */ + st->st_msgid = generate_msgid(st); + init_phase2_iv(st, &st->st_msgid); - /* HDR out */ - { - struct isakmp_hdr hdr; - - zero(&hdr); /* default to 0 */ - hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION; - hdr.isa_np = ISAKMP_NEXT_HASH; - hdr.isa_xchg = ISAKMP_XCHG_MODE_CFG; - hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION; - memcpy(hdr.isa_icookie, st->st_icookie, COOKIE_SIZE); - memcpy(hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE); - hdr.isa_msgid = st->st_msgid; - - if (!out_struct(&hdr, &isakmp_hdr_desc, &msg, &rbody)) + /* HDR out */ { - return STF_INTERNAL_ERROR; + struct isakmp_hdr hdr; + + zero(&hdr); /* default to 0 */ + hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION; + hdr.isa_np = ISAKMP_NEXT_HASH; + hdr.isa_xchg = ISAKMP_XCHG_MODE_CFG; + hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION; + memcpy(hdr.isa_icookie, st->st_icookie, COOKIE_SIZE); + memcpy(hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE); + hdr.isa_msgid = st->st_msgid; + + if (!out_struct(&hdr, &isakmp_hdr_desc, &msg, &rbody)) + { + return STF_INTERNAL_ERROR; + } } - } - /* ATTR out */ - modecfg_build_msg(st, &rbody - , isama_type - , ia - , 0 /* XXX isama_id */ - ); + /* ATTR out */ + modecfg_build_msg(st, &rbody + , isama_type + , ia + , 0 /* XXX isama_id */ + ); - free(st->st_tpacket.ptr); - st->st_tpacket = chunk_create(msg.start, pbs_offset(&msg)); - st->st_tpacket = chunk_clone(st->st_tpacket); + free(st->st_tpacket.ptr); + st->st_tpacket = chunk_create(msg.start, pbs_offset(&msg)); + st->st_tpacket = chunk_clone(st->st_tpacket); - /* Transmit */ - send_packet(st, "ModeCfg msg"); + /* Transmit */ + send_packet(st, "ModeCfg msg"); - if (st->st_event->ev_type != EVENT_RETRANSMIT) - { - delete_event(st); - event_schedule(EVENT_RETRANSMIT, EVENT_RETRANSMIT_DELAY_0, st); - } - return STF_OK; + if (st->st_event->ev_type != EVENT_RETRANSMIT) + { + delete_event(st); + event_schedule(EVENT_RETRANSMIT, EVENT_RETRANSMIT_DELAY_0, st); + } + return STF_OK; } /* @@ -551,184 +551,184 @@ modecfg_send_msg(struct state *st, int isama_type, internal_addr_t *ia) static stf_status modecfg_parse_attributes(pb_stream *attrs, internal_addr_t *ia) { - struct isakmp_attribute attr; - pb_stream strattr; - err_t ugh; - char buf[BUF_LEN]; - int dns_idx = 0; - int nbns_idx = 0; + struct isakmp_attribute attr; + pb_stream strattr; + err_t ugh; + char buf[BUF_LEN]; + int dns_idx = 0; + int nbns_idx = 0; - while (pbs_left(attrs) >= sizeof(struct isakmp_attribute)) - { - u_int16_t attr_type; - u_int16_t attr_len; - - if (!in_struct(&attr, &isakmp_modecfg_attribute_desc, attrs, &strattr)) + while (pbs_left(attrs) >= sizeof(struct isakmp_attribute)) { - return STF_FAIL; - } - attr_type = attr.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK; - attr_len = attr.isaat_lv; + u_int16_t attr_type; + u_int16_t attr_len; - switch (attr_type) - { - case INTERNAL_IP4_ADDRESS: - if (attr_len == 4) - { - ugh = initaddr((char *)(strattr.cur), 4, AF_INET, &ia->ipaddr); - if (ugh != NULL) + if (!in_struct(&attr, &isakmp_modecfg_attribute_desc, attrs, &strattr)) { - plog("received invalid virtual IPv4 address: %s", ugh); + return STF_FAIL; } - } - ia->attr_set |= LELEM(attr_type); - break; - case INTERNAL_IP4_DNS: - if (attr_len == 4 && dns_idx < DNS_SERVER_MAX) - { - ugh = initaddr((char *)(strattr.cur), 4, AF_INET, &ia->dns[dns_idx]); - if (ugh != NULL) + attr_type = attr.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK; + attr_len = attr.isaat_lv; + + switch (attr_type) { - plog("received invalid IPv4 DNS server address: %s", ugh); + case INTERNAL_IP4_ADDRESS: + if (attr_len == 4) + { + ugh = initaddr((char *)(strattr.cur), 4, AF_INET, &ia->ipaddr); + if (ugh != NULL) + { + plog("received invalid virtual IPv4 address: %s", ugh); + } + } + ia->attr_set |= LELEM(attr_type); + break; + case INTERNAL_IP4_DNS: + if (attr_len == 4 && dns_idx < DNS_SERVER_MAX) + { + ugh = initaddr((char *)(strattr.cur), 4, AF_INET, &ia->dns[dns_idx]); + if (ugh != NULL) + { + plog("received invalid IPv4 DNS server address: %s", ugh); + } + else + { + addrtot(&ia->dns[dns_idx], 0, buf, BUF_LEN); + plog("received IPv4 DNS server address %s", buf); + dns_idx++; + } + } + ia->attr_set |= LELEM(attr_type); + break; + case INTERNAL_IP4_NBNS: + if (attr_len == 4 && nbns_idx < NBNS_SERVER_MAX) + { + ugh = initaddr((char *)(strattr.cur), 4, AF_INET, &ia->nbns[nbns_idx]); + if (ugh != NULL) + { + plog("received invalid IPv4 WINS server address: %s", ugh); + } + else + { + addrtot(&ia->nbns[nbns_idx], 0, buf, BUF_LEN); + plog("received IPv4 WINS server address %s", buf); + nbns_idx++; + } + } + ia->attr_set |= LELEM(attr_type); + break; + case INTERNAL_IP6_DNS: + if (attr_len == 16 && dns_idx < DNS_SERVER_MAX) + { + ugh = initaddr((char *)(strattr.cur), 16, AF_INET6, &ia->dns[dns_idx]); + if (ugh != NULL) + { + plog("received invalid IPv6 DNS server address: %s", ugh); + } + else + { + addrtot(&ia->dns[dns_idx], 0, buf, BUF_LEN); + plog("received IPv6 DNS server address %s", buf); + dns_idx++; + } + } + ia->attr_set |= LELEM(attr_type); + break; + case INTERNAL_IP6_NBNS: + if (attr_len == 16 && nbns_idx < NBNS_SERVER_MAX) + { + ugh = initaddr((char *)(strattr.cur), 16, AF_INET6, &ia->nbns[nbns_idx]); + if (ugh != NULL) + { + plog("received invalid IPv6 WINS server address: %s", ugh); + } + else + { + addrtot(&ia->nbns[nbns_idx], 0, buf, BUF_LEN); + plog("received IPv6 WINS server address %s", buf); + nbns_idx++; + } + } + ia->attr_set |= LELEM(attr_type); + break; + case INTERNAL_IP4_NETMASK: + case INTERNAL_IP4_SUBNET: + case INTERNAL_ADDRESS_EXPIRY: + case INTERNAL_IP4_DHCP: + case INTERNAL_IP6_ADDRESS: + case INTERNAL_IP6_NETMASK: + case INTERNAL_IP6_DHCP: + case SUPPORTED_ATTRIBUTES: + case INTERNAL_IP6_SUBNET: + ia->attr_set |= LELEM(attr_type); + break; + case APPLICATION_VERSION: + if (attr_len > 0) + { + DBG(DBG_PARSING, + DBG_log(" '%.*s'", attr_len, strattr.cur) + ) + } + ia->attr_set |= LELEM(attr_type); + break; + case XAUTH_TYPE: + ia->xauth_type = attr.isaat_lv; + ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE); + break; + case XAUTH_USER_NAME: + ia->xauth_secret.user_name = chunk_create(strattr.cur, attr_len); + ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE); + break; + case XAUTH_USER_PASSWORD: + ia->xauth_secret.user_password = chunk_create(strattr.cur, attr_len); + ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE); + break; + case XAUTH_STATUS: + ia->xauth_status = attr.isaat_lv; + ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE); + break; + case XAUTH_MESSAGE: + if (attr_len > 0) + { + DBG(DBG_PARSING, + DBG_log(" '%.*s'", attr_len, strattr.cur) + ) + } + /* fall through to set attribute flag */ + case XAUTH_PASSCODE: + case XAUTH_CHALLENGE: + case XAUTH_DOMAIN: + case XAUTH_NEXT_PIN: + case XAUTH_ANSWER: + ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE); + break; + case UNITY_DDNS_HOSTNAME: + if (attr_len > 0) + { + DBG(DBG_PARSING, + DBG_log(" '%.*s'", attr_len, strattr.cur) + ) + } + /* fall through to set attribute flag */ + case UNITY_BANNER: + case UNITY_SAVE_PASSWD: + case UNITY_DEF_DOMAIN: + case UNITY_SPLITDNS_NAME: + case UNITY_SPLIT_INCLUDE: + case UNITY_NATT_PORT: + case UNITY_LOCAL_LAN: + case UNITY_PFS: + case UNITY_FW_TYPE: + case UNITY_BACKUP_SERVERS: + ia->unity_attr_set |= LELEM(attr_type - UNITY_BASE); + break; + default: + plog("unsupported ModeCfg attribute %s received." + , enum_show(&modecfg_attr_names, attr_type)); + break; } - else - { - addrtot(&ia->dns[dns_idx], 0, buf, BUF_LEN); - plog("received IPv4 DNS server address %s", buf); - dns_idx++; - } - } - ia->attr_set |= LELEM(attr_type); - break; - case INTERNAL_IP4_NBNS: - if (attr_len == 4 && nbns_idx < NBNS_SERVER_MAX) - { - ugh = initaddr((char *)(strattr.cur), 4, AF_INET, &ia->nbns[nbns_idx]); - if (ugh != NULL) - { - plog("received invalid IPv4 WINS server address: %s", ugh); - } - else - { - addrtot(&ia->nbns[nbns_idx], 0, buf, BUF_LEN); - plog("received IPv4 WINS server address %s", buf); - nbns_idx++; - } - } - ia->attr_set |= LELEM(attr_type); - break; - case INTERNAL_IP6_DNS: - if (attr_len == 16 && dns_idx < DNS_SERVER_MAX) - { - ugh = initaddr((char *)(strattr.cur), 16, AF_INET6, &ia->dns[dns_idx]); - if (ugh != NULL) - { - plog("received invalid IPv6 DNS server address: %s", ugh); - } - else - { - addrtot(&ia->dns[dns_idx], 0, buf, BUF_LEN); - plog("received IPv6 DNS server address %s", buf); - dns_idx++; - } - } - ia->attr_set |= LELEM(attr_type); - break; - case INTERNAL_IP6_NBNS: - if (attr_len == 16 && nbns_idx < NBNS_SERVER_MAX) - { - ugh = initaddr((char *)(strattr.cur), 16, AF_INET6, &ia->nbns[nbns_idx]); - if (ugh != NULL) - { - plog("received invalid IPv6 WINS server address: %s", ugh); - } - else - { - addrtot(&ia->nbns[nbns_idx], 0, buf, BUF_LEN); - plog("received IPv6 WINS server address %s", buf); - nbns_idx++; - } - } - ia->attr_set |= LELEM(attr_type); - break; - case INTERNAL_IP4_NETMASK: - case INTERNAL_IP4_SUBNET: - case INTERNAL_ADDRESS_EXPIRY: - case INTERNAL_IP4_DHCP: - case INTERNAL_IP6_ADDRESS: - case INTERNAL_IP6_NETMASK: - case INTERNAL_IP6_DHCP: - case SUPPORTED_ATTRIBUTES: - case INTERNAL_IP6_SUBNET: - ia->attr_set |= LELEM(attr_type); - break; - case APPLICATION_VERSION: - if (attr_len > 0) - { - DBG(DBG_PARSING, - DBG_log(" '%.*s'", attr_len, strattr.cur) - ) - } - ia->attr_set |= LELEM(attr_type); - break; - case XAUTH_TYPE: - ia->xauth_type = attr.isaat_lv; - ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE); - break; - case XAUTH_USER_NAME: - ia->xauth_secret.user_name = chunk_create(strattr.cur, attr_len); - ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE); - break; - case XAUTH_USER_PASSWORD: - ia->xauth_secret.user_password = chunk_create(strattr.cur, attr_len); - ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE); - break; - case XAUTH_STATUS: - ia->xauth_status = attr.isaat_lv; - ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE); - break; - case XAUTH_MESSAGE: - if (attr_len > 0) - { - DBG(DBG_PARSING, - DBG_log(" '%.*s'", attr_len, strattr.cur) - ) - } - /* fall through to set attribute flag */ - case XAUTH_PASSCODE: - case XAUTH_CHALLENGE: - case XAUTH_DOMAIN: - case XAUTH_NEXT_PIN: - case XAUTH_ANSWER: - ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE); - break; - case UNITY_DDNS_HOSTNAME: - if (attr_len > 0) - { - DBG(DBG_PARSING, - DBG_log(" '%.*s'", attr_len, strattr.cur) - ) - } - /* fall through to set attribute flag */ - case UNITY_BANNER: - case UNITY_SAVE_PASSWD: - case UNITY_DEF_DOMAIN: - case UNITY_SPLITDNS_NAME: - case UNITY_SPLIT_INCLUDE: - case UNITY_NATT_PORT: - case UNITY_LOCAL_LAN: - case UNITY_PFS: - case UNITY_FW_TYPE: - case UNITY_BACKUP_SERVERS: - ia->unity_attr_set |= LELEM(attr_type - UNITY_BASE); - break; - default: - plog("unsupported ModeCfg attribute %s received." - , enum_show(&modecfg_attr_names, attr_type)); - break; } - } - return STF_OK; + return STF_OK; } /* @@ -736,52 +736,52 @@ modecfg_parse_attributes(pb_stream *attrs, internal_addr_t *ia) */ static stf_status modecfg_parse_msg(struct msg_digest *md, int isama_type, u_int16_t *isama_id - , internal_addr_t *ia) + , internal_addr_t *ia) { - struct state *const st = md->st; - struct payload_digest *p; - stf_status stat; + struct state *const st = md->st; + struct payload_digest *p; + stf_status stat; - st->st_msgid = md->hdr.isa_msgid; + st->st_msgid = md->hdr.isa_msgid; - CHECK_QUICK_HASH(md, modecfg_hash(hash_val - , hash_pbs->roof - , md->message_pbs.roof, st) - , "MODECFG-HASH", "ISAKMP_CFG_MSG"); + CHECK_QUICK_HASH(md, modecfg_hash(hash_val + , hash_pbs->roof + , md->message_pbs.roof, st) + , "MODECFG-HASH", "ISAKMP_CFG_MSG"); - /* process the ModeCfg payloads received */ - for (p = md->chain[ISAKMP_NEXT_ATTR]; p != NULL; p = p->next) - { - internal_addr_t ia_candidate; - - init_internal_addr(&ia_candidate); - - if (p->payload.attribute.isama_type == isama_type) + /* process the ModeCfg payloads received */ + for (p = md->chain[ISAKMP_NEXT_ATTR]; p != NULL; p = p->next) { - *isama_id = p->payload.attribute.isama_identifier; + internal_addr_t ia_candidate; - stat = modecfg_parse_attributes(&p->pbs, &ia_candidate); - if (stat == STF_OK) - { - /* return with a valid set of attributes */ - *ia = ia_candidate; - return STF_OK; - } - } - else - { - plog("expected %s, got %s instead (ignored)" - , enum_name(&attr_msg_type_names, isama_type) - , enum_name(&attr_msg_type_names, p->payload.attribute.isama_type)); + init_internal_addr(&ia_candidate); - stat = modecfg_parse_attributes(&p->pbs, &ia_candidate); + if (p->payload.attribute.isama_type == isama_type) + { + *isama_id = p->payload.attribute.isama_identifier; + + stat = modecfg_parse_attributes(&p->pbs, &ia_candidate); + if (stat == STF_OK) + { + /* return with a valid set of attributes */ + *ia = ia_candidate; + return STF_OK; + } + } + else + { + plog("expected %s, got %s instead (ignored)" + , enum_name(&attr_msg_type_names, isama_type) + , enum_name(&attr_msg_type_names, p->payload.attribute.isama_type)); + + stat = modecfg_parse_attributes(&p->pbs, &ia_candidate); + } + if (stat != STF_OK) + { + return stat; + } } - if (stat != STF_OK) - { - return stat; - } - } - return STF_IGNORE; + return STF_IGNORE; } /* @@ -790,22 +790,22 @@ modecfg_parse_msg(struct msg_digest *md, int isama_type, u_int16_t *isama_id stf_status modecfg_send_request(struct state *st) { - stf_status stat; - internal_addr_t ia; + stf_status stat; + internal_addr_t ia; - init_internal_addr(&ia); + init_internal_addr(&ia); - ia.attr_set = LELEM(INTERNAL_IP4_ADDRESS) - | LELEM(INTERNAL_IP4_NETMASK); + ia.attr_set = LELEM(INTERNAL_IP4_ADDRESS) + | LELEM(INTERNAL_IP4_NETMASK); - plog("sending ModeCfg request"); - st->st_state = STATE_MODE_CFG_I1; - stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia); - if (stat == STF_OK) - { - st->st_modecfg.started = TRUE; - } - return stat; + plog("sending ModeCfg request"); + st->st_state = STATE_MODE_CFG_I1; + stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia); + if (stat == STF_OK) + { + st->st_modecfg.started = TRUE; + } + return stat; } /* STATE_MODE_CFG_R0: @@ -816,40 +816,40 @@ modecfg_send_request(struct state *st) stf_status modecfg_inR0(struct msg_digest *md) { - struct state *const st = md->st; - u_int16_t isama_id; - internal_addr_t ia; - bool want_unity_banner; - stf_status stat, stat_build; + struct state *const st = md->st; + u_int16_t isama_id; + internal_addr_t ia; + bool want_unity_banner; + stf_status stat, stat_build; - stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia); - if (stat != STF_OK) - { - return stat; - } + stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia); + if (stat != STF_OK) + { + return stat; + } - want_unity_banner = (ia.unity_attr_set & LELEM(UNITY_BANNER - UNITY_BASE)) != LEMPTY; - init_internal_addr(&ia); - get_internal_addr(st->st_connection, &ia); + want_unity_banner = (ia.unity_attr_set & LELEM(UNITY_BANNER - UNITY_BASE)) != LEMPTY; + init_internal_addr(&ia); + get_internal_addr(st->st_connection, &ia); - if (want_unity_banner) - { - ia.unity_banner = UNITY_BANNER_STR; - ia.unity_attr_set |= LELEM(UNITY_BANNER - UNITY_BASE); - } + if (want_unity_banner) + { + ia.unity_banner = UNITY_BANNER_STR; + ia.unity_attr_set |= LELEM(UNITY_BANNER - UNITY_BASE); + } - plog("sending ModeCfg reply"); + plog("sending ModeCfg reply"); - stat_build = modecfg_build_msg(st, &md->rbody - , ISAKMP_CFG_REPLY - , &ia - , isama_id); - if (stat_build != STF_OK) - { - return stat_build; - } - st->st_msgid = 0; - return STF_OK; + stat_build = modecfg_build_msg(st, &md->rbody + , ISAKMP_CFG_REPLY + , &ia + , isama_id); + if (stat_build != STF_OK) + { + return stat_build; + } + st->st_msgid = 0; + return STF_OK; } /* STATE_MODE_CFG_I1: @@ -860,21 +860,21 @@ modecfg_inR0(struct msg_digest *md) stf_status modecfg_inI1(struct msg_digest *md) { - struct state *const st = md->st; - u_int16_t isama_id; - internal_addr_t ia; - stf_status stat; + struct state *const st = md->st; + u_int16_t isama_id; + internal_addr_t ia; + stf_status stat; - plog("parsing ModeCfg reply"); + plog("parsing ModeCfg reply"); - stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia); - if (stat != STF_OK) - { - return stat; - } - st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia); - st->st_msgid = 0; - return STF_OK; + stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia); + if (stat != STF_OK) + { + return stat; + } + st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia); + st->st_msgid = 0; + return STF_OK; } @@ -884,25 +884,25 @@ modecfg_inI1(struct msg_digest *md) stf_status modecfg_send_set(struct state *st) { - stf_status stat; - internal_addr_t ia; + stf_status stat; + internal_addr_t ia; - init_internal_addr(&ia); - get_internal_addr(st->st_connection, &ia); + init_internal_addr(&ia); + get_internal_addr(st->st_connection, &ia); #ifdef CISCO_QUIRKS - ia.unity_banner = UNITY_BANNER_STR; - ia.unity_attr_set |= LELEM(UNITY_BANNER - UNITY_BASE); + ia.unity_banner = UNITY_BANNER_STR; + ia.unity_attr_set |= LELEM(UNITY_BANNER - UNITY_BASE); #endif plog("sending ModeCfg set"); - st->st_state = STATE_MODE_CFG_R3; - stat = modecfg_send_msg(st, ISAKMP_CFG_SET, &ia); - if (stat == STF_OK) - { - st->st_modecfg.started = TRUE; - } - return stat; + st->st_state = STATE_MODE_CFG_R3; + stat = modecfg_send_msg(st, ISAKMP_CFG_SET, &ia); + if (stat == STF_OK) + { + st->st_modecfg.started = TRUE; + } + return stat; } /* STATE_MODE_CFG_I0: @@ -913,40 +913,40 @@ modecfg_send_set(struct state *st) stf_status modecfg_inI0(struct msg_digest *md) { - struct state *const st = md->st; - u_int16_t isama_id; - internal_addr_t ia; - lset_t attr_set, unity_attr_set; - stf_status stat, stat_build; + struct state *const st = md->st; + u_int16_t isama_id; + internal_addr_t ia; + lset_t attr_set, unity_attr_set; + stf_status stat, stat_build; - plog("parsing ModeCfg set"); + plog("parsing ModeCfg set"); - stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, &ia); - if (stat != STF_OK) - { - return stat; - } - st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia); + stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, &ia); + if (stat != STF_OK) + { + return stat; + } + st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia); - /* prepare ModeCfg ack which sends zero length attributes */ - attr_set = ia.attr_set; - unity_attr_set = ia.unity_attr_set; - init_internal_addr(&ia); - ia.attr_set = attr_set & SUPPORTED_ATTR_SET; - ia.unity_attr_set = unity_attr_set & SUPPORTED_UNITY_ATTR_SET; + /* prepare ModeCfg ack which sends zero length attributes */ + attr_set = ia.attr_set; + unity_attr_set = ia.unity_attr_set; + init_internal_addr(&ia); + ia.attr_set = attr_set & SUPPORTED_ATTR_SET; + ia.unity_attr_set = unity_attr_set & SUPPORTED_UNITY_ATTR_SET; - plog("sending ModeCfg ack"); + plog("sending ModeCfg ack"); - stat_build = modecfg_build_msg(st, &md->rbody - , ISAKMP_CFG_ACK - , &ia - , isama_id); - if (stat_build != STF_OK) - { - return stat_build; - } - st->st_msgid = 0; - return STF_OK; + stat_build = modecfg_build_msg(st, &md->rbody + , ISAKMP_CFG_ACK + , &ia + , isama_id); + if (stat_build != STF_OK) + { + return stat_build; + } + st->st_msgid = 0; + return STF_OK; } /* STATE_MODE_CFG_R3: @@ -957,20 +957,20 @@ modecfg_inI0(struct msg_digest *md) stf_status modecfg_inR3(struct msg_digest *md) { - struct state *const st = md->st; - u_int16_t isama_id; - internal_addr_t ia; - stf_status stat; + struct state *const st = md->st; + u_int16_t isama_id; + internal_addr_t ia; + stf_status stat; - plog("parsing ModeCfg ack"); + plog("parsing ModeCfg ack"); - stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia); - if (stat != STF_OK) - { - return stat; - } - st->st_msgid = 0; - return STF_OK; + stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia); + if (stat != STF_OK) + { + return stat; + } + st->st_msgid = 0; + return STF_OK; } /* @@ -979,21 +979,21 @@ modecfg_inR3(struct msg_digest *md) stf_status xauth_send_request(struct state *st) { - stf_status stat; - internal_addr_t ia; + stf_status stat; + internal_addr_t ia; - init_internal_addr(&ia); - ia.xauth_attr_set = LELEM(XAUTH_USER_NAME - XAUTH_BASE) - | LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE); + init_internal_addr(&ia); + ia.xauth_attr_set = LELEM(XAUTH_USER_NAME - XAUTH_BASE) + | LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE); - plog("sending XAUTH request"); - st->st_state = STATE_XAUTH_R1; - stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia); - if (stat == STF_OK) - { - st->st_xauth.started = TRUE; - } - return stat; + plog("sending XAUTH request"); + st->st_state = STATE_XAUTH_R1; + stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia); + if (stat == STF_OK) + { + st->st_xauth.started = TRUE; + } + return stat; } /* STATE_XAUTH_I0: @@ -1004,102 +1004,102 @@ xauth_send_request(struct state *st) stf_status xauth_inI0(struct msg_digest *md) { - struct state *const st = md->st; - u_int16_t isama_id; - internal_addr_t ia; - stf_status stat, stat_build; - bool xauth_type_present; + struct state *const st = md->st; + u_int16_t isama_id; + internal_addr_t ia; + stf_status stat, stat_build; + bool xauth_type_present; - plog("parsing XAUTH request"); + plog("parsing XAUTH request"); - stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia); - if (stat != STF_OK) - { - return stat; - } - - /* check XAUTH attributes */ - xauth_type_present = (ia.xauth_attr_set & LELEM(XAUTH_TYPE - XAUTH_BASE)) != LEMPTY; - - if (xauth_type_present && ia.xauth_type != XAUTH_TYPE_GENERIC) - { - plog("xauth type %s is not supported", enum_name(&xauth_type_names, ia.xauth_type)); - stat = STF_FAIL; - } - else if ((ia.xauth_attr_set & LELEM(XAUTH_USER_NAME - XAUTH_BASE)) == LEMPTY) - { - plog("user name attribute is missing in XAUTH request"); - stat = STF_FAIL; - } - else if ((ia.xauth_attr_set & LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE)) == LEMPTY) - { - plog("user password attribute is missing in XAUTH request"); - stat = STF_FAIL; - } - - /* prepare XAUTH reply */ - init_internal_addr(&ia); - - if (stat == STF_OK) - { - /* get user credentials using a plugin function */ - if (!xauth_module.get_secret(&ia.xauth_secret)) + stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia); + if (stat != STF_OK) { - plog("xauth user credentials not found"); - stat = STF_FAIL; + return stat; } - } - if (stat == STF_OK) - { - DBG(DBG_CONTROL, - DBG_log("my xauth user name is '%.*s'" - , ia.xauth_secret.user_name.len - , ia.xauth_secret.user_name.ptr) - ) - DBG(DBG_PRIVATE, - DBG_log("my xauth user password is '%.*s'" - , ia.xauth_secret.user_password.len - , ia.xauth_secret.user_password.ptr) - ) - ia.xauth_attr_set = LELEM(XAUTH_USER_NAME - XAUTH_BASE) - | LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE); - if (xauth_type_present) + + /* check XAUTH attributes */ + xauth_type_present = (ia.xauth_attr_set & LELEM(XAUTH_TYPE - XAUTH_BASE)) != LEMPTY; + + if (xauth_type_present && ia.xauth_type != XAUTH_TYPE_GENERIC) { - ia.xauth_attr_set |= LELEM(XAUTH_TYPE - XAUTH_BASE); + plog("xauth type %s is not supported", enum_name(&xauth_type_names, ia.xauth_type)); + stat = STF_FAIL; + } + else if ((ia.xauth_attr_set & LELEM(XAUTH_USER_NAME - XAUTH_BASE)) == LEMPTY) + { + plog("user name attribute is missing in XAUTH request"); + stat = STF_FAIL; + } + else if ((ia.xauth_attr_set & LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE)) == LEMPTY) + { + plog("user password attribute is missing in XAUTH request"); + stat = STF_FAIL; } - } - else - { - ia.xauth_attr_set = LELEM(XAUTH_STATUS - XAUTH_BASE); - ia.xauth_status = XAUTH_STATUS_FAIL; - } - plog("sending XAUTH reply"); + /* prepare XAUTH reply */ + init_internal_addr(&ia); - stat_build = modecfg_build_msg(st, &md->rbody - , ISAKMP_CFG_REPLY - , &ia - , isama_id); - if (stat_build != STF_OK) - { - return stat_build; - } - if (stat == STF_OK) - { - st->st_xauth.started = TRUE; - st->st_msgid = 0; - return STF_OK; - } - else - { - /* send XAUTH reply msg and then delete ISAKMP SA */ - free(st->st_tpacket.ptr); - st->st_tpacket = chunk_create(md->reply.start, pbs_offset(&md->reply)); - st->st_tpacket = chunk_clone(st->st_tpacket); - send_packet(st, "XAUTH reply msg"); - delete_state(st); - return STF_IGNORE; - } + if (stat == STF_OK) + { + /* get user credentials using a plugin function */ + if (!xauth_module.get_secret(&ia.xauth_secret)) + { + plog("xauth user credentials not found"); + stat = STF_FAIL; + } + } + if (stat == STF_OK) + { + DBG(DBG_CONTROL, + DBG_log("my xauth user name is '%.*s'" + , ia.xauth_secret.user_name.len + , ia.xauth_secret.user_name.ptr) + ) + DBG(DBG_PRIVATE, + DBG_log("my xauth user password is '%.*s'" + , ia.xauth_secret.user_password.len + , ia.xauth_secret.user_password.ptr) + ) + ia.xauth_attr_set = LELEM(XAUTH_USER_NAME - XAUTH_BASE) + | LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE); + if (xauth_type_present) + { + ia.xauth_attr_set |= LELEM(XAUTH_TYPE - XAUTH_BASE); + } + } + else + { + ia.xauth_attr_set = LELEM(XAUTH_STATUS - XAUTH_BASE); + ia.xauth_status = XAUTH_STATUS_FAIL; + } + + plog("sending XAUTH reply"); + + stat_build = modecfg_build_msg(st, &md->rbody + , ISAKMP_CFG_REPLY + , &ia + , isama_id); + if (stat_build != STF_OK) + { + return stat_build; + } + if (stat == STF_OK) + { + st->st_xauth.started = TRUE; + st->st_msgid = 0; + return STF_OK; + } + else + { + /* send XAUTH reply msg and then delete ISAKMP SA */ + free(st->st_tpacket.ptr); + st->st_tpacket = chunk_create(md->reply.start, pbs_offset(&md->reply)); + st->st_tpacket = chunk_clone(st->st_tpacket); + send_packet(st, "XAUTH reply msg"); + delete_state(st); + return STF_IGNORE; + } } /* STATE_XAUTH_R1: @@ -1110,76 +1110,76 @@ xauth_inI0(struct msg_digest *md) stf_status xauth_inR1(struct msg_digest *md) { - struct state *const st = md->st; - u_int16_t isama_id; - internal_addr_t ia; - stf_status stat, stat_build; + struct state *const st = md->st; + u_int16_t isama_id; + internal_addr_t ia; + stf_status stat, stat_build; - plog("parsing XAUTH reply"); + plog("parsing XAUTH reply"); - stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia); - if (stat != STF_OK) - { - return stat; - } + stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia); + if (stat != STF_OK) + { + return stat; + } - /* did the client return an XAUTH FAIL status? */ - if ((ia.xauth_attr_set & LELEM(XAUTH_STATUS - XAUTH_BASE)) != LEMPTY) - { - plog("received FAIL status in XAUTH reply"); + /* did the client return an XAUTH FAIL status? */ + if ((ia.xauth_attr_set & LELEM(XAUTH_STATUS - XAUTH_BASE)) != LEMPTY) + { + plog("received FAIL status in XAUTH reply"); - /* client is not able to do XAUTH, delete ISAKMP SA */ - delete_state(st); - return STF_IGNORE; - } + /* client is not able to do XAUTH, delete ISAKMP SA */ + delete_state(st); + return STF_IGNORE; + } - /* check XAUTH reply */ - if ((ia.xauth_attr_set & LELEM(XAUTH_USER_NAME - XAUTH_BASE)) == LEMPTY) - { - plog("user name attribute is missing in XAUTH reply"); - st->st_xauth.status = FALSE; - } - else if ((ia.xauth_attr_set & LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE)) == LEMPTY) - { - plog("user password attribute is missing in XAUTH reply"); - st->st_xauth.status = FALSE; - } - else - { - xauth_peer_t peer; + /* check XAUTH reply */ + if ((ia.xauth_attr_set & LELEM(XAUTH_USER_NAME - XAUTH_BASE)) == LEMPTY) + { + plog("user name attribute is missing in XAUTH reply"); + st->st_xauth.status = FALSE; + } + else if ((ia.xauth_attr_set & LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE)) == LEMPTY) + { + plog("user password attribute is missing in XAUTH reply"); + st->st_xauth.status = FALSE; + } + else + { + xauth_peer_t peer; - peer.conn_name = st->st_connection->name; - addrtot(&md->sender, 0, peer.ip_address, sizeof(peer.ip_address)); - idtoa(&md->st->st_connection->spd.that.id, peer.id, sizeof(peer.id)); + peer.conn_name = st->st_connection->name; + addrtot(&md->sender, 0, peer.ip_address, sizeof(peer.ip_address)); + idtoa(&md->st->st_connection->spd.that.id, peer.id, sizeof(peer.id)); - DBG(DBG_CONTROL, - DBG_log("peer xauth user name is '%.*s'" - , ia.xauth_secret.user_name.len - , ia.xauth_secret.user_name.ptr) - ) - DBG(DBG_PRIVATE, - DBG_log("peer xauth user password is '%.*s'" - , ia.xauth_secret.user_password.len - , ia.xauth_secret.user_password.ptr) - ) - /* verify the user credentials using a plugin function */ - st->st_xauth.status = xauth_module.verify_secret(&peer, &ia.xauth_secret); - plog("extended authentication %s", st->st_xauth.status? "was successful":"failed"); - } + DBG(DBG_CONTROL, + DBG_log("peer xauth user name is '%.*s'" + , ia.xauth_secret.user_name.len + , ia.xauth_secret.user_name.ptr) + ) + DBG(DBG_PRIVATE, + DBG_log("peer xauth user password is '%.*s'" + , ia.xauth_secret.user_password.len + , ia.xauth_secret.user_password.ptr) + ) + /* verify the user credentials using a plugin function */ + st->st_xauth.status = xauth_module.verify_secret(&peer, &ia.xauth_secret); + plog("extended authentication %s", st->st_xauth.status? "was successful":"failed"); + } - /* prepare XAUTH set which sends the authentication status */ - init_internal_addr(&ia); - ia.xauth_attr_set = LELEM(XAUTH_STATUS - XAUTH_BASE); - ia.xauth_status = (st->st_xauth.status)? XAUTH_STATUS_OK : XAUTH_STATUS_FAIL; + /* prepare XAUTH set which sends the authentication status */ + init_internal_addr(&ia); + ia.xauth_attr_set = LELEM(XAUTH_STATUS - XAUTH_BASE); + ia.xauth_status = (st->st_xauth.status)? XAUTH_STATUS_OK : XAUTH_STATUS_FAIL; - plog("sending XAUTH status:"); + plog("sending XAUTH status:"); - stat_build = modecfg_send_msg(st, ISAKMP_CFG_SET, &ia); - if (stat_build != STF_OK) - { - return stat_build; - } - return STF_OK; + stat_build = modecfg_send_msg(st, ISAKMP_CFG_SET, &ia); + if (stat_build != STF_OK) + { + return stat_build; + } + return STF_OK; } /* STATE_XAUTH_I1: @@ -1190,48 +1190,48 @@ xauth_inR1(struct msg_digest *md) stf_status xauth_inI1(struct msg_digest *md) { - struct state *const st = md->st; - u_int16_t isama_id; - internal_addr_t ia; - stf_status stat, stat_build; + struct state *const st = md->st; + u_int16_t isama_id; + internal_addr_t ia; + stf_status stat, stat_build; - plog("parsing XAUTH status"); - stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, &ia); - if (stat != STF_OK) - { - /* notification payload - not exactly the right choice, but okay */ - md->note = ATTRIBUTES_NOT_SUPPORTED; - return stat; - } + plog("parsing XAUTH status"); + stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, &ia); + if (stat != STF_OK) + { + /* notification payload - not exactly the right choice, but okay */ + md->note = ATTRIBUTES_NOT_SUPPORTED; + return stat; + } - st->st_xauth.status = ia.xauth_status; - plog("extended authentication %s", st->st_xauth.status? "was successful":"failed"); + st->st_xauth.status = ia.xauth_status; + plog("extended authentication %s", st->st_xauth.status? "was successful":"failed"); - plog("sending XAUTH ack"); - init_internal_addr(&ia); - stat_build = modecfg_build_msg(st, &md->rbody - , ISAKMP_CFG_ACK - , &ia - , isama_id); - if (stat_build != STF_OK) - { - return stat_build; - } - if (st->st_xauth.status) - { - st->st_msgid = 0; - return STF_OK; - } - else - { - /* send XAUTH ack msg and then delete ISAKMP SA */ - free(st->st_tpacket.ptr); - st->st_tpacket = chunk_create(md->reply.start, pbs_offset(&md->reply)); - st->st_tpacket = chunk_clone(st->st_tpacket); - send_packet(st, "XAUTH ack msg"); - delete_state(st); - return STF_IGNORE; - } + plog("sending XAUTH ack"); + init_internal_addr(&ia); + stat_build = modecfg_build_msg(st, &md->rbody + , ISAKMP_CFG_ACK + , &ia + , isama_id); + if (stat_build != STF_OK) + { + return stat_build; + } + if (st->st_xauth.status) + { + st->st_msgid = 0; + return STF_OK; + } + else + { + /* send XAUTH ack msg and then delete ISAKMP SA */ + free(st->st_tpacket.ptr); + st->st_tpacket = chunk_create(md->reply.start, pbs_offset(&md->reply)); + st->st_tpacket = chunk_clone(st->st_tpacket); + send_packet(st, "XAUTH ack msg"); + delete_state(st); + return STF_IGNORE; + } } /* STATE_XAUTH_R2: @@ -1242,26 +1242,26 @@ xauth_inI1(struct msg_digest *md) stf_status xauth_inR2(struct msg_digest *md) { - struct state *const st = md->st; - u_int16_t isama_id; - internal_addr_t ia; - stf_status stat; + struct state *const st = md->st; + u_int16_t isama_id; + internal_addr_t ia; + stf_status stat; - plog("parsing XAUTH ack"); + plog("parsing XAUTH ack"); - stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia); - if (stat != STF_OK) - { - return stat; - } - st->st_msgid = 0; - if (st->st_xauth.status) - { - return STF_OK; - } - else - { - delete_state(st); - return STF_IGNORE; - } + stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia); + if (stat != STF_OK) + { + return stat; + } + st->st_msgid = 0; + if (st->st_xauth.status) + { + return STF_OK; + } + else + { + delete_state(st); + return STF_IGNORE; + } } diff --git a/src/pluto/mp_defs.c b/src/pluto/mp_defs.c index 66b4717c1..201effc29 100644 --- a/src/pluto/mp_defs.c +++ b/src/pluto/mp_defs.c @@ -27,29 +27,29 @@ chunk_t mpz_to_n(const MP_INT *mp, size_t bytes) { - chunk_t r; - MP_INT temp1, temp2; - int i; + chunk_t r; + MP_INT temp1, temp2; + int i; - r.len = bytes; - r.ptr = malloc(r.len); + r.len = bytes; + r.ptr = malloc(r.len); - mpz_init(&temp1); - mpz_init(&temp2); + mpz_init(&temp1); + mpz_init(&temp2); - mpz_set(&temp1, mp); + mpz_set(&temp1, mp); - for (i = r.len-1; i >= 0; i--) - { - r.ptr[i] = mpz_mdivmod_ui(&temp2, NULL, &temp1, 1 << BITS_PER_BYTE); - mpz_set(&temp1, &temp2); - } + for (i = r.len-1; i >= 0; i--) + { + r.ptr[i] = mpz_mdivmod_ui(&temp2, NULL, &temp1, 1 << BITS_PER_BYTE); + mpz_set(&temp1, &temp2); + } - passert(mpz_sgn(&temp1) == 0); /* we must have done all the bits */ - mpz_clear(&temp1); - mpz_clear(&temp2); + passert(mpz_sgn(&temp1) == 0); /* we must have done all the bits */ + mpz_clear(&temp1); + mpz_clear(&temp2); - return r; + return r; } /* Convert network form (binary bytes, big-endian) to MP_INT. @@ -58,13 +58,13 @@ mpz_to_n(const MP_INT *mp, size_t bytes) void n_to_mpz(MP_INT *mp, const u_char *nbytes, size_t nlen) { - size_t i; + size_t i; - mpz_init_set_ui(mp, 0); + mpz_init_set_ui(mp, 0); - for (i = 0; i != nlen; i++) - { - mpz_mul_ui(mp, mp, 1 << BITS_PER_BYTE); - mpz_add_ui(mp, mp, nbytes[i]); - } + for (i = 0; i != nlen; i++) + { + mpz_mul_ui(mp, mp, 1 << BITS_PER_BYTE); + mpz_add_ui(mp, mp, nbytes[i]); + } } diff --git a/src/pluto/mp_defs.h b/src/pluto/mp_defs.h index 85a766e25..7b3b569ed 100644 --- a/src/pluto/mp_defs.h +++ b/src/pluto/mp_defs.h @@ -27,10 +27,10 @@ extern chunk_t mpz_to_n(const MP_INT *mp, size_t bytes); /* var := mod(base ** exp, mod), ensuring var is mpz_inited */ #define mpz_init_powm(flag, var, base, exp, mod) { \ - if (!(flag)) \ - mpz_init(&(var)); \ - (flag) = TRUE; \ - mpz_powm(&(var), &(base), &(exp), (mod)); \ - } + if (!(flag)) \ + mpz_init(&(var)); \ + (flag) = TRUE; \ + mpz_powm(&(var), &(base), &(exp), (mod)); \ + } #endif /* _MP_DEFS_H */ diff --git a/src/pluto/nat_traversal.c b/src/pluto/nat_traversal.c index 3317d30f4..fc090e432 100644 --- a/src/pluto/nat_traversal.c +++ b/src/pluto/nat_traversal.c @@ -79,80 +79,80 @@ static bool _force_ka = 0; static const char *natt_version = "0.6c"; void init_nat_traversal (bool activate, unsigned int keep_alive_period, - bool fka, bool spf) + bool fka, bool spf) { - nat_traversal_enabled = activate; - nat_traversal_support_non_ike = activate; + nat_traversal_enabled = activate; + nat_traversal_support_non_ike = activate; #ifdef NAT_T_SUPPORT_LAST_DRAFTS - nat_traversal_support_port_floating = activate ? spf : FALSE; + nat_traversal_support_port_floating = activate ? spf : FALSE; #endif - _force_ka = fka; - _kap = keep_alive_period ? keep_alive_period : DEFAULT_KEEP_ALIVE_PERIOD; - plog(" including NAT-Traversal patch (Version %s)%s%s%s" - , natt_version, activate ? "" : " [disabled]" - , activate & fka ? " [Force KeepAlive]" : "" - , activate & !spf ? " [Port Floating disabled]" : ""); + _force_ka = fka; + _kap = keep_alive_period ? keep_alive_period : DEFAULT_KEEP_ALIVE_PERIOD; + plog(" including NAT-Traversal patch (Version %s)%s%s%s" + , natt_version, activate ? "" : " [disabled]" + , activate & fka ? " [Force KeepAlive]" : "" + , activate & !spf ? " [Port Floating disabled]" : ""); } static void disable_nat_traversal (int type) { - if (type == ESPINUDP_WITH_NON_IKE) - nat_traversal_support_non_ike = FALSE; - else - nat_traversal_support_port_floating = FALSE; + if (type == ESPINUDP_WITH_NON_IKE) + nat_traversal_support_non_ike = FALSE; + else + nat_traversal_support_port_floating = FALSE; - if (!nat_traversal_support_non_ike && - !nat_traversal_support_port_floating) - nat_traversal_enabled = FALSE; + if (!nat_traversal_support_non_ike && + !nat_traversal_support_port_floating) + nat_traversal_enabled = FALSE; } static void _natd_hash(const struct hash_desc *hasher, char *hash, - u_int8_t *icookie, u_int8_t *rcookie, - const ip_address *ip, u_int16_t port) + u_int8_t *icookie, u_int8_t *rcookie, + const ip_address *ip, u_int16_t port) { - union hash_ctx ctx; + union hash_ctx ctx; - if (is_zero_cookie(icookie)) - DBG_log("_natd_hash: Warning, icookie is zero !!"); - if (is_zero_cookie(rcookie)) - DBG_log("_natd_hash: Warning, rcookie is zero !!"); + if (is_zero_cookie(icookie)) + DBG_log("_natd_hash: Warning, icookie is zero !!"); + if (is_zero_cookie(rcookie)) + DBG_log("_natd_hash: Warning, rcookie is zero !!"); - /** - * draft-ietf-ipsec-nat-t-ike-01.txt - * - * HASH = HASH(CKY-I | CKY-R | IP | Port) - * - * All values in network order - */ - hasher->hash_init(&ctx); - hasher->hash_update(&ctx, icookie, COOKIE_SIZE); - hasher->hash_update(&ctx, rcookie, COOKIE_SIZE); - switch (addrtypeof(ip)) { - case AF_INET: - hasher->hash_update(&ctx, (const u_char *)&ip->u.v4.sin_addr.s_addr - , sizeof(ip->u.v4.sin_addr.s_addr)); - break; - case AF_INET6: - hasher->hash_update(&ctx, (const u_char *)&ip->u.v6.sin6_addr.s6_addr - , sizeof(ip->u.v6.sin6_addr.s6_addr)); - break; - } - hasher->hash_update(&ctx, (const u_char *)&port, sizeof(u_int16_t)); - hasher->hash_final(hash, &ctx); -#ifdef NAT_D_DEBUG - DBG(DBG_NATT, - DBG_log("_natd_hash: hasher=%p(%d)", hasher, (int)hasher->hash_digest_len); - DBG_dump("_natd_hash: icookie=", icookie, COOKIE_SIZE); - DBG_dump("_natd_hash: rcookie=", rcookie, COOKIE_SIZE); + /** + * draft-ietf-ipsec-nat-t-ike-01.txt + * + * HASH = HASH(CKY-I | CKY-R | IP | Port) + * + * All values in network order + */ + hasher->hash_init(&ctx); + hasher->hash_update(&ctx, icookie, COOKIE_SIZE); + hasher->hash_update(&ctx, rcookie, COOKIE_SIZE); switch (addrtypeof(ip)) { case AF_INET: - DBG_dump("_natd_hash: ip=", &ip->u.v4.sin_addr.s_addr - , sizeof(ip->u.v4.sin_addr.s_addr)); - break; + hasher->hash_update(&ctx, (const u_char *)&ip->u.v4.sin_addr.s_addr + , sizeof(ip->u.v4.sin_addr.s_addr)); + break; + case AF_INET6: + hasher->hash_update(&ctx, (const u_char *)&ip->u.v6.sin6_addr.s6_addr + , sizeof(ip->u.v6.sin6_addr.s6_addr)); + break; } - DBG_log("_natd_hash: port=%d", port); - DBG_dump("_natd_hash: hash=", hash, hasher->hash_digest_len); - ); + hasher->hash_update(&ctx, (const u_char *)&port, sizeof(u_int16_t)); + hasher->hash_final(hash, &ctx); +#ifdef NAT_D_DEBUG + DBG(DBG_NATT, + DBG_log("_natd_hash: hasher=%p(%d)", hasher, (int)hasher->hash_digest_len); + DBG_dump("_natd_hash: icookie=", icookie, COOKIE_SIZE); + DBG_dump("_natd_hash: rcookie=", rcookie, COOKIE_SIZE); + switch (addrtypeof(ip)) { + case AF_INET: + DBG_dump("_natd_hash: ip=", &ip->u.v4.sin_addr.s_addr + , sizeof(ip->u.v4.sin_addr.s_addr)); + break; + } + DBG_log("_natd_hash: port=%d", port); + DBG_dump("_natd_hash: hash=", hash, hasher->hash_digest_len); + ); #endif } @@ -161,180 +161,180 @@ static void _natd_hash(const struct hash_desc *hasher, char *hash, */ bool nat_traversal_add_vid(u_int8_t np, pb_stream *outs) { - bool r = TRUE; + bool r = TRUE; - if (nat_traversal_support_port_floating) - { - u_int8_t last_np = nat_traversal_support_non_ike ? - ISAKMP_NEXT_VID : np; + if (nat_traversal_support_port_floating) + { + u_int8_t last_np = nat_traversal_support_non_ike ? + ISAKMP_NEXT_VID : np; - if (r) - r = out_vendorid(ISAKMP_NEXT_VID, outs, VID_NATT_RFC); - if (r) - r = out_vendorid(ISAKMP_NEXT_VID, outs, VID_NATT_IETF_03); - if (r) - r = out_vendorid(ISAKMP_NEXT_VID, outs, VID_NATT_IETF_02); - if (r) - r = out_vendorid(last_np, outs, VID_NATT_IETF_02_N); - } - if (nat_traversal_support_non_ike) - { - if (r) - r = out_vendorid(np, outs, VID_NATT_IETF_00); - } - return r; + if (r) + r = out_vendorid(ISAKMP_NEXT_VID, outs, VID_NATT_RFC); + if (r) + r = out_vendorid(ISAKMP_NEXT_VID, outs, VID_NATT_IETF_03); + if (r) + r = out_vendorid(ISAKMP_NEXT_VID, outs, VID_NATT_IETF_02); + if (r) + r = out_vendorid(last_np, outs, VID_NATT_IETF_02_N); + } + if (nat_traversal_support_non_ike) + { + if (r) + r = out_vendorid(np, outs, VID_NATT_IETF_00); + } + return r; } u_int32_t nat_traversal_vid_to_method(unsigned short nat_t_vid) { - switch (nat_t_vid) - { - case VID_NATT_IETF_00: - return LELEM(NAT_TRAVERSAL_IETF_00_01); - case VID_NATT_IETF_02: - case VID_NATT_IETF_02_N: - case VID_NATT_IETF_03: - return LELEM(NAT_TRAVERSAL_IETF_02_03); - case VID_NATT_RFC: - return LELEM(NAT_TRAVERSAL_RFC); - } - return 0; + switch (nat_t_vid) + { + case VID_NATT_IETF_00: + return LELEM(NAT_TRAVERSAL_IETF_00_01); + case VID_NATT_IETF_02: + case VID_NATT_IETF_02_N: + case VID_NATT_IETF_03: + return LELEM(NAT_TRAVERSAL_IETF_02_03); + case VID_NATT_RFC: + return LELEM(NAT_TRAVERSAL_RFC); + } + return 0; } void nat_traversal_natd_lookup(struct msg_digest *md) { - char hash[MAX_DIGEST_LEN]; - struct payload_digest *p; - struct state *st = md->st; - int i; + char hash[MAX_DIGEST_LEN]; + struct payload_digest *p; + struct state *st = md->st; + int i; - if (!st || !md->iface || !st->st_oakley.hasher) - { - loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d" - , __FILE__, __LINE__); - return; - } - - /** Count NAT-D **/ - for (p = md->chain[ISAKMP_NEXT_NATD_RFC], i=0; p != NULL; p = p->next, i++); - - /* - * We need at least 2 NAT-D (1 for us, many for peer) - */ - if (i < 2) - { - loglog(RC_LOG_SERIOUS, - "NAT-Traversal: Only %d NAT-D - Aborting NAT-Traversal negociation", i); - st->nat_traversal = 0; - return; - } - - /* - * First one with my IP & port - */ - p = md->chain[ISAKMP_NEXT_NATD_RFC]; - _natd_hash(st->st_oakley.hasher, hash, st->st_icookie, st->st_rcookie, - &(md->iface->addr), ntohs(st->st_connection->spd.this.host_port)); - - if (!(pbs_left(&p->pbs) == st->st_oakley.hasher->hash_digest_len && - memeq(p->pbs.cur, hash, st->st_oakley.hasher->hash_digest_len))) - { -#ifdef NAT_D_DEBUG - DBG(DBG_NATT, - DBG_log("NAT_TRAVERSAL_NAT_BHND_ME"); - DBG_dump("expected NAT-D:", hash - , st->st_oakley.hasher->hash_digest_len); - DBG_dump("received NAT-D:", p->pbs.cur, pbs_left(&p->pbs)); - ) -#endif - st->nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_ME); - } - - /* - * The others with sender IP & port - */ - _natd_hash(st->st_oakley.hasher, hash, st->st_icookie, st->st_rcookie, - &(md->sender), ntohs(md->sender_port)); - for (p = p->next, i=0 ; p != NULL; p = p->next) - { - if (pbs_left(&p->pbs) == st->st_oakley.hasher->hash_digest_len && - memeq(p->pbs.cur, hash, st->st_oakley.hasher->hash_digest_len)) + if (!st || !md->iface || !st->st_oakley.hasher) { - i++; + loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d" + , __FILE__, __LINE__); + return; } - } - if (!i) - { + + /** Count NAT-D **/ + for (p = md->chain[ISAKMP_NEXT_NATD_RFC], i=0; p != NULL; p = p->next, i++); + + /* + * We need at least 2 NAT-D (1 for us, many for peer) + */ + if (i < 2) + { + loglog(RC_LOG_SERIOUS, + "NAT-Traversal: Only %d NAT-D - Aborting NAT-Traversal negociation", i); + st->nat_traversal = 0; + return; + } + + /* + * First one with my IP & port + */ + p = md->chain[ISAKMP_NEXT_NATD_RFC]; + _natd_hash(st->st_oakley.hasher, hash, st->st_icookie, st->st_rcookie, + &(md->iface->addr), ntohs(st->st_connection->spd.this.host_port)); + + if (!(pbs_left(&p->pbs) == st->st_oakley.hasher->hash_digest_len && + memeq(p->pbs.cur, hash, st->st_oakley.hasher->hash_digest_len))) + { #ifdef NAT_D_DEBUG - DBG(DBG_NATT, - DBG_log("NAT_TRAVERSAL_NAT_BHND_PEER"); - DBG_dump("expected NAT-D:", hash - , st->st_oakley.hasher->hash_digest_len); - p = md->chain[ISAKMP_NEXT_NATD_RFC]; - for (p = p->next, i=0 ; p != NULL; p = p->next) - { - DBG_dump("received NAT-D:", p->pbs.cur, pbs_left(&p->pbs)); - } - ) + DBG(DBG_NATT, + DBG_log("NAT_TRAVERSAL_NAT_BHND_ME"); + DBG_dump("expected NAT-D:", hash + , st->st_oakley.hasher->hash_digest_len); + DBG_dump("received NAT-D:", p->pbs.cur, pbs_left(&p->pbs)); + ) #endif - st->nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_PEER); - } + st->nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_ME); + } + + /* + * The others with sender IP & port + */ + _natd_hash(st->st_oakley.hasher, hash, st->st_icookie, st->st_rcookie, + &(md->sender), ntohs(md->sender_port)); + for (p = p->next, i=0 ; p != NULL; p = p->next) + { + if (pbs_left(&p->pbs) == st->st_oakley.hasher->hash_digest_len && + memeq(p->pbs.cur, hash, st->st_oakley.hasher->hash_digest_len)) + { + i++; + } + } + if (!i) + { +#ifdef NAT_D_DEBUG + DBG(DBG_NATT, + DBG_log("NAT_TRAVERSAL_NAT_BHND_PEER"); + DBG_dump("expected NAT-D:", hash + , st->st_oakley.hasher->hash_digest_len); + p = md->chain[ISAKMP_NEXT_NATD_RFC]; + for (p = p->next, i=0 ; p != NULL; p = p->next) + { + DBG_dump("received NAT-D:", p->pbs.cur, pbs_left(&p->pbs)); + } + ) +#endif + st->nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_PEER); + } #ifdef FORCE_NAT_TRAVERSAL - st->nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_PEER); - st->nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_ME); + st->nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_PEER); + st->nat_traversal |= LELEM(NAT_TRAVERSAL_NAT_BHND_ME); #endif } bool nat_traversal_add_natd(u_int8_t np, pb_stream *outs, - struct msg_digest *md) + struct msg_digest *md) { - char hash[MAX_DIGEST_LEN]; - struct state *st = md->st; + char hash[MAX_DIGEST_LEN]; + struct state *st = md->st; - if (!st || !st->st_oakley.hasher) - { - loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d" - , __FILE__, __LINE__); - return FALSE; - } + if (!st || !st->st_oakley.hasher) + { + loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d" + , __FILE__, __LINE__); + return FALSE; + } - DBG(DBG_EMITTING, - DBG_log("sending NATD payloads") - ) - - /* - * First one with sender IP & port - */ - _natd_hash(st->st_oakley.hasher, hash, st->st_icookie, - is_zero_cookie(st->st_rcookie) ? md->hdr.isa_rcookie : st->st_rcookie, - &(md->sender), + DBG(DBG_EMITTING, + DBG_log("sending NATD payloads") + ) + + /* + * First one with sender IP & port + */ + _natd_hash(st->st_oakley.hasher, hash, st->st_icookie, + is_zero_cookie(st->st_rcookie) ? md->hdr.isa_rcookie : st->st_rcookie, + &(md->sender), #ifdef FORCE_NAT_TRAVERSAL - 0 + 0 #else - ntohs(md->sender_port) + ntohs(md->sender_port) #endif - ); - if (!out_generic_raw((st->nat_traversal & NAT_T_WITH_RFC_VALUES - ? ISAKMP_NEXT_NATD_RFC : ISAKMP_NEXT_NATD_DRAFTS), &isakmp_nat_d, outs, - hash, st->st_oakley.hasher->hash_digest_len, "NAT-D")) - { - return FALSE; - } + ); + if (!out_generic_raw((st->nat_traversal & NAT_T_WITH_RFC_VALUES + ? ISAKMP_NEXT_NATD_RFC : ISAKMP_NEXT_NATD_DRAFTS), &isakmp_nat_d, outs, + hash, st->st_oakley.hasher->hash_digest_len, "NAT-D")) + { + return FALSE; + } - /* - * Second one with my IP & port - */ - _natd_hash(st->st_oakley.hasher, hash, st->st_icookie, - is_zero_cookie(st->st_rcookie) ? md->hdr.isa_rcookie : st->st_rcookie, - &(md->iface->addr), + /* + * Second one with my IP & port + */ + _natd_hash(st->st_oakley.hasher, hash, st->st_icookie, + is_zero_cookie(st->st_rcookie) ? md->hdr.isa_rcookie : st->st_rcookie, + &(md->iface->addr), #ifdef FORCE_NAT_TRAVERSAL - 0 + 0 #else - ntohs(st->st_connection->spd.this.host_port) + ntohs(st->st_connection->spd.this.host_port) #endif - ); - return (out_generic_raw(np, &isakmp_nat_d, outs, - hash, st->st_oakley.hasher->hash_digest_len, "NAT-D")); + ); + return (out_generic_raw(np, &isakmp_nat_d, outs, + hash, st->st_oakley.hasher->hash_digest_len, "NAT-D")); } /* @@ -344,245 +344,245 @@ bool nat_traversal_add_natd(u_int8_t np, pb_stream *outs, */ void nat_traversal_natoa_lookup(struct msg_digest *md) { - struct payload_digest *p; - struct state *st = md->st; - int i; - ip_address ip; + struct payload_digest *p; + struct state *st = md->st; + int i; + ip_address ip; - if (!st || !md->iface) - { - loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d" - , __FILE__, __LINE__); - return; - } - - /* Initialize NAT-OA */ - anyaddr(AF_INET, &st->nat_oa); - - /* Count NAT-OA **/ - for (p = md->chain[ISAKMP_NEXT_NATOA_RFC], i=0; p != NULL; p = p->next, i++); - - DBG(DBG_NATT, - DBG_log("NAT-Traversal: received %d NAT-OA.", i) - ) - - if (i == 0) - return; - - if (!(st->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_PEER))) - { - loglog(RC_LOG_SERIOUS, "NAT-Traversal: received %d NAT-OA. " - "ignored because peer is not NATed", i); - return; - } - - if (i > 1) - { - loglog(RC_LOG_SERIOUS, "NAT-Traversal: received %d NAT-OA. " - "using first, ignoring others", i); - } - - /* Take first */ - p = md->chain[ISAKMP_NEXT_NATOA_RFC]; - - DBG(DBG_PARSING, - DBG_dump("NAT-OA:", p->pbs.start, pbs_room(&p->pbs)); - ); - - switch (p->payload.nat_oa.isanoa_idtype) - { - case ID_IPV4_ADDR: - if (pbs_left(&p->pbs) == sizeof(struct in_addr)) + if (!st || !md->iface) { - initaddr(p->pbs.cur, pbs_left(&p->pbs), AF_INET, &ip); + loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d" + , __FILE__, __LINE__); + return; } + + /* Initialize NAT-OA */ + anyaddr(AF_INET, &st->nat_oa); + + /* Count NAT-OA **/ + for (p = md->chain[ISAKMP_NEXT_NATOA_RFC], i=0; p != NULL; p = p->next, i++); + + DBG(DBG_NATT, + DBG_log("NAT-Traversal: received %d NAT-OA.", i) + ) + + if (i == 0) + return; + + if (!(st->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_PEER))) + { + loglog(RC_LOG_SERIOUS, "NAT-Traversal: received %d NAT-OA. " + "ignored because peer is not NATed", i); + return; + } + + if (i > 1) + { + loglog(RC_LOG_SERIOUS, "NAT-Traversal: received %d NAT-OA. " + "using first, ignoring others", i); + } + + /* Take first */ + p = md->chain[ISAKMP_NEXT_NATOA_RFC]; + + DBG(DBG_PARSING, + DBG_dump("NAT-OA:", p->pbs.start, pbs_room(&p->pbs)); + ); + + switch (p->payload.nat_oa.isanoa_idtype) + { + case ID_IPV4_ADDR: + if (pbs_left(&p->pbs) == sizeof(struct in_addr)) + { + initaddr(p->pbs.cur, pbs_left(&p->pbs), AF_INET, &ip); + } + else + { + loglog(RC_LOG_SERIOUS, "NAT-Traversal: received IPv4 NAT-OA " + "with invalid IP size (%d)", (int)pbs_left(&p->pbs)); + return; + } + break; + case ID_IPV6_ADDR: + if (pbs_left(&p->pbs) == sizeof(struct in6_addr)) + { + initaddr(p->pbs.cur, pbs_left(&p->pbs), AF_INET6, &ip); + } + else + { + loglog(RC_LOG_SERIOUS, "NAT-Traversal: received IPv6 NAT-OA " + "with invalid IP size (%d)", (int)pbs_left(&p->pbs)); + return; + } + break; + default: + loglog(RC_LOG_SERIOUS, "NAT-Traversal: " + "invalid ID Type (%d) in NAT-OA - ignored", + p->payload.nat_oa.isanoa_idtype); + return; + } + + DBG(DBG_NATT, + { + char ip_t[ADDRTOT_BUF]; + addrtot(&ip, 0, ip_t, sizeof(ip_t)); + + DBG_log("received NAT-OA: %s", ip_t); + } + ) + + if (isanyaddr(&ip)) + loglog(RC_LOG_SERIOUS, "NAT-Traversal: received %%any NAT-OA..."); else - { - loglog(RC_LOG_SERIOUS, "NAT-Traversal: received IPv4 NAT-OA " - "with invalid IP size (%d)", (int)pbs_left(&p->pbs)); - return; - } - break; - case ID_IPV6_ADDR: - if (pbs_left(&p->pbs) == sizeof(struct in6_addr)) - { - initaddr(p->pbs.cur, pbs_left(&p->pbs), AF_INET6, &ip); - } - else - { - loglog(RC_LOG_SERIOUS, "NAT-Traversal: received IPv6 NAT-OA " - "with invalid IP size (%d)", (int)pbs_left(&p->pbs)); - return; - } - break; - default: - loglog(RC_LOG_SERIOUS, "NAT-Traversal: " - "invalid ID Type (%d) in NAT-OA - ignored", - p->payload.nat_oa.isanoa_idtype); - return; - } - - DBG(DBG_NATT, - { - char ip_t[ADDRTOT_BUF]; - addrtot(&ip, 0, ip_t, sizeof(ip_t)); - - DBG_log("received NAT-OA: %s", ip_t); - } - ) - - if (isanyaddr(&ip)) - loglog(RC_LOG_SERIOUS, "NAT-Traversal: received %%any NAT-OA..."); - else - st->nat_oa = ip; + st->nat_oa = ip; } bool nat_traversal_add_natoa(u_int8_t np, pb_stream *outs, - struct state *st) + struct state *st) { - struct isakmp_nat_oa natoa; - pb_stream pbs; - unsigned char ip_val[sizeof(struct in6_addr)]; - size_t ip_len = 0; - ip_address *ip; + struct isakmp_nat_oa natoa; + pb_stream pbs; + unsigned char ip_val[sizeof(struct in6_addr)]; + size_t ip_len = 0; + ip_address *ip; - if ((!st) || (!st->st_connection)) - { - loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d" - , __FILE__, __LINE__); - return FALSE; - } - ip = &(st->st_connection->spd.this.host_addr); + if ((!st) || (!st->st_connection)) + { + loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d" + , __FILE__, __LINE__); + return FALSE; + } + ip = &(st->st_connection->spd.this.host_addr); - memset(&natoa, 0, sizeof(natoa)); - natoa.isanoa_np = np; + memset(&natoa, 0, sizeof(natoa)); + natoa.isanoa_np = np; - switch (addrtypeof(ip)) - { - case AF_INET: - ip_len = sizeof(ip->u.v4.sin_addr.s_addr); - memcpy(ip_val, &ip->u.v4.sin_addr.s_addr, ip_len); - natoa.isanoa_idtype = ID_IPV4_ADDR; - break; - case AF_INET6: - ip_len = sizeof(ip->u.v6.sin6_addr.s6_addr); - memcpy(ip_val, &ip->u.v6.sin6_addr.s6_addr, ip_len); - natoa.isanoa_idtype = ID_IPV6_ADDR; - break; - default: - loglog(RC_LOG_SERIOUS, "NAT-Traversal: " - "invalid addrtypeof()=%d", addrtypeof(ip)); - return FALSE; - } + switch (addrtypeof(ip)) + { + case AF_INET: + ip_len = sizeof(ip->u.v4.sin_addr.s_addr); + memcpy(ip_val, &ip->u.v4.sin_addr.s_addr, ip_len); + natoa.isanoa_idtype = ID_IPV4_ADDR; + break; + case AF_INET6: + ip_len = sizeof(ip->u.v6.sin6_addr.s6_addr); + memcpy(ip_val, &ip->u.v6.sin6_addr.s6_addr, ip_len); + natoa.isanoa_idtype = ID_IPV6_ADDR; + break; + default: + loglog(RC_LOG_SERIOUS, "NAT-Traversal: " + "invalid addrtypeof()=%d", addrtypeof(ip)); + return FALSE; + } - if (!out_struct(&natoa, &isakmp_nat_oa, outs, &pbs)) - return FALSE; + if (!out_struct(&natoa, &isakmp_nat_oa, outs, &pbs)) + return FALSE; - if (!out_raw(ip_val, ip_len, &pbs, "NAT-OA")) - return FALSE; + if (!out_raw(ip_val, ip_len, &pbs, "NAT-OA")) + return FALSE; - DBG(DBG_NATT, - DBG_dump("NAT-OA (S):", ip_val, ip_len) - ) + DBG(DBG_NATT, + DBG_dump("NAT-OA (S):", ip_val, ip_len) + ) - close_output_pbs(&pbs); - return TRUE; + close_output_pbs(&pbs); + return TRUE; } void nat_traversal_show_result (u_int32_t nt, u_int16_t sport) { - const char *mth = NULL, *rslt = NULL; + const char *mth = NULL, *rslt = NULL; - switch (nt & NAT_TRAVERSAL_METHOD) - { - case LELEM(NAT_TRAVERSAL_IETF_00_01): - mth = natt_type_bitnames[0]; - break; - case LELEM(NAT_TRAVERSAL_IETF_02_03): - mth = natt_type_bitnames[1]; - break; - case LELEM(NAT_TRAVERSAL_RFC): - mth = natt_type_bitnames[2]; - break; - } - - switch (nt & NAT_T_DETECTED) - { - case 0: - rslt = "no NAT detected"; - break; - case LELEM(NAT_TRAVERSAL_NAT_BHND_ME): - rslt = "i am NATed"; - break; - case LELEM(NAT_TRAVERSAL_NAT_BHND_PEER): - rslt = "peer is NATed"; - break; - case LELEM(NAT_TRAVERSAL_NAT_BHND_ME) | LELEM(NAT_TRAVERSAL_NAT_BHND_PEER): - rslt = "both are NATed"; - break; - } + switch (nt & NAT_TRAVERSAL_METHOD) + { + case LELEM(NAT_TRAVERSAL_IETF_00_01): + mth = natt_type_bitnames[0]; + break; + case LELEM(NAT_TRAVERSAL_IETF_02_03): + mth = natt_type_bitnames[1]; + break; + case LELEM(NAT_TRAVERSAL_RFC): + mth = natt_type_bitnames[2]; + break; + } + + switch (nt & NAT_T_DETECTED) + { + case 0: + rslt = "no NAT detected"; + break; + case LELEM(NAT_TRAVERSAL_NAT_BHND_ME): + rslt = "i am NATed"; + break; + case LELEM(NAT_TRAVERSAL_NAT_BHND_PEER): + rslt = "peer is NATed"; + break; + case LELEM(NAT_TRAVERSAL_NAT_BHND_ME) | LELEM(NAT_TRAVERSAL_NAT_BHND_PEER): + rslt = "both are NATed"; + break; + } - loglog(RC_LOG_SERIOUS, - "NAT-Traversal: Result using %s: %s", - mth ? mth : "unknown method", - rslt ? rslt : "unknown result" - ); - - if ((nt & LELEM(NAT_TRAVERSAL_NAT_BHND_PEER)) - && (sport == IKE_UDP_PORT) - && ((nt & NAT_T_WITH_PORT_FLOATING)==0)) - { loglog(RC_LOG_SERIOUS, - "Warning: peer is NATed but source port is still udp/%d. " - "Ipsec-passthrough NAT device suspected -- NAT-T may not work.", - IKE_UDP_PORT + "NAT-Traversal: Result using %s: %s", + mth ? mth : "unknown method", + rslt ? rslt : "unknown result" ); - } + + if ((nt & LELEM(NAT_TRAVERSAL_NAT_BHND_PEER)) + && (sport == IKE_UDP_PORT) + && ((nt & NAT_T_WITH_PORT_FLOATING)==0)) + { + loglog(RC_LOG_SERIOUS, + "Warning: peer is NATed but source port is still udp/%d. " + "Ipsec-passthrough NAT device suspected -- NAT-T may not work.", + IKE_UDP_PORT + ); + } } int nat_traversal_espinudp_socket (int sk, u_int32_t type) { - int r = setsockopt(sk, SOL_UDP, UDP_ESPINUDP, &type, sizeof(type)); + int r = setsockopt(sk, SOL_UDP, UDP_ESPINUDP, &type, sizeof(type)); - if (r < 0 && errno == ENOPROTOOPT) - { - loglog(RC_LOG_SERIOUS, - "NAT-Traversal: ESPINUDP(%d) not supported by kernel -- " - "NAT-T disabled", type); - disable_nat_traversal(type); - } - return r; + if (r < 0 && errno == ENOPROTOOPT) + { + loglog(RC_LOG_SERIOUS, + "NAT-Traversal: ESPINUDP(%d) not supported by kernel -- " + "NAT-T disabled", type); + disable_nat_traversal(type); + } + return r; } void nat_traversal_new_ka_event (void) { - if (_ka_evt) - return; /* event already scheduled */ + if (_ka_evt) + return; /* event already scheduled */ - event_schedule(EVENT_NAT_T_KEEPALIVE, _kap, NULL); - _ka_evt = 1; + event_schedule(EVENT_NAT_T_KEEPALIVE, _kap, NULL); + _ka_evt = 1; } static void nat_traversal_send_ka (struct state *st) { - static unsigned char ka_payload = 0xff; - chunk_t sav; + static unsigned char ka_payload = 0xff; + chunk_t sav; - DBG(DBG_NATT, - DBG_log("ka_event: send NAT-KA to %s:%d", - ip_str(&st->st_connection->spd.that.host_addr), - st->st_connection->spd.that.host_port); - ) + DBG(DBG_NATT, + DBG_log("ka_event: send NAT-KA to %s:%d", + ip_str(&st->st_connection->spd.that.host_addr), + st->st_connection->spd.that.host_port); + ) - /* save state chunk */ - sav = st->st_tpacket; + /* save state chunk */ + sav = st->st_tpacket; - /* send keep alive */ - st->st_tpacket = chunk_create(&ka_payload, 1); - send_packet(st, "NAT-T Keep Alive"); + /* send keep alive */ + st->st_tpacket = chunk_create(&ka_payload, 1); + send_packet(st, "NAT-T Keep Alive"); - /* restore state chunk */ - st->st_tpacket = sav; + /* restore state chunk */ + st->st_tpacket = sav; } /** @@ -590,277 +590,277 @@ static void nat_traversal_send_ka (struct state *st) */ static void nat_traversal_ka_event_state (struct state *st, void *data) { - unsigned int *_kap_st = (unsigned int *)data; - const struct connection *c = st->st_connection; + unsigned int *_kap_st = (unsigned int *)data; + const struct connection *c = st->st_connection; - if (!c) - return; - - if ((st->st_state == STATE_MAIN_R3 || st->st_state == STATE_MAIN_I4) - && (st->nat_traversal & NAT_T_DETECTED) - && ((st->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_ME)) || _force_ka)) - { - /* - * - ISAKMP established - * - NAT-Traversal detected - * - NAT-KeepAlive needed (we are NATed) - */ - if (c->newest_isakmp_sa != st->st_serialno) - { - /* - * if newest is also valid, ignore this one, we will only use - * newest. - */ - struct state *st_newest; - - st_newest = state_with_serialno(c->newest_isakmp_sa); - if (st_newest - && (st_newest->st_state == STATE_MAIN_R3 || st_newest->st_state == STATE_MAIN_I4) - && (st_newest->nat_traversal & NAT_T_DETECTED) - && ((st_newest->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_ME)) || _force_ka)) - { + if (!c) return; - } + + if ((st->st_state == STATE_MAIN_R3 || st->st_state == STATE_MAIN_I4) + && (st->nat_traversal & NAT_T_DETECTED) + && ((st->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_ME)) || _force_ka)) + { + /* + * - ISAKMP established + * - NAT-Traversal detected + * - NAT-KeepAlive needed (we are NATed) + */ + if (c->newest_isakmp_sa != st->st_serialno) + { + /* + * if newest is also valid, ignore this one, we will only use + * newest. + */ + struct state *st_newest; + + st_newest = state_with_serialno(c->newest_isakmp_sa); + if (st_newest + && (st_newest->st_state == STATE_MAIN_R3 || st_newest->st_state == STATE_MAIN_I4) + && (st_newest->nat_traversal & NAT_T_DETECTED) + && ((st_newest->nat_traversal & LELEM(NAT_TRAVERSAL_NAT_BHND_ME)) || _force_ka)) + { + return; + } + } + set_cur_state(st); + nat_traversal_send_ka(st); + reset_cur_state(); + (*_kap_st)++; } - set_cur_state(st); - nat_traversal_send_ka(st); - reset_cur_state(); - (*_kap_st)++; - } } void nat_traversal_ka_event (void) { - unsigned int _kap_st = 0; + unsigned int _kap_st = 0; - _ka_evt = 0; /* ready to be reschedule */ + _ka_evt = 0; /* ready to be reschedule */ - for_each_state((void *)nat_traversal_ka_event_state, &_kap_st); + for_each_state((void *)nat_traversal_ka_event_state, &_kap_st); - /* if there are still states who needs Keep-Alive, schedule new event */ - if (_kap_st) - nat_traversal_new_ka_event(); + /* if there are still states who needs Keep-Alive, schedule new event */ + if (_kap_st) + nat_traversal_new_ka_event(); } struct _new_mapp_nfo { - ip_address addr; - u_int16_t sport, dport; + ip_address addr; + u_int16_t sport, dport; }; static void nat_traversal_find_new_mapp_state (struct state *st, void *data) { - struct connection *c = st->st_connection; - struct _new_mapp_nfo *nfo = (struct _new_mapp_nfo *)data; + struct connection *c = st->st_connection; + struct _new_mapp_nfo *nfo = (struct _new_mapp_nfo *)data; - if (c != NULL - && sameaddr(&c->spd.that.host_addr, &(nfo->addr)) - && c->spd.that.host_port == nfo->sport) - { - - /* change host port */ - c->spd.that.host_port = nfo->dport; - - if (IS_IPSEC_SA_ESTABLISHED(st->st_state) - || IS_ONLY_INBOUND_IPSEC_SA_ESTABLISHED(st->st_state)) + if (c != NULL + && sameaddr(&c->spd.that.host_addr, &(nfo->addr)) + && c->spd.that.host_port == nfo->sport) { - if (!update_ipsec_sa(st)) - { - /* - * If ipsec update failed, restore old port or we'll - * not be able to update anymore. - */ - c->spd.that.host_port = nfo->sport; - } + + /* change host port */ + c->spd.that.host_port = nfo->dport; + + if (IS_IPSEC_SA_ESTABLISHED(st->st_state) + || IS_ONLY_INBOUND_IPSEC_SA_ESTABLISHED(st->st_state)) + { + if (!update_ipsec_sa(st)) + { + /* + * If ipsec update failed, restore old port or we'll + * not be able to update anymore. + */ + c->spd.that.host_port = nfo->sport; + } + } } - } } static int nat_traversal_new_mapping(const ip_address *src, u_int16_t sport, - const ip_address *dst, u_int16_t dport) + const ip_address *dst, u_int16_t dport) { - char srca[ADDRTOT_BUF], dsta[ADDRTOT_BUF]; - struct _new_mapp_nfo nfo; + char srca[ADDRTOT_BUF], dsta[ADDRTOT_BUF]; + struct _new_mapp_nfo nfo; - addrtot(src, 0, srca, ADDRTOT_BUF); - addrtot(dst, 0, dsta, ADDRTOT_BUF); + addrtot(src, 0, srca, ADDRTOT_BUF); + addrtot(dst, 0, dsta, ADDRTOT_BUF); - if (!sameaddr(src, dst)) - { - loglog(RC_LOG_SERIOUS, "nat_traversal_new_mapping: " - "address change currently not supported [%s:%d,%s:%d]", - srca, sport, dsta, dport); - return -1; - } + if (!sameaddr(src, dst)) + { + loglog(RC_LOG_SERIOUS, "nat_traversal_new_mapping: " + "address change currently not supported [%s:%d,%s:%d]", + srca, sport, dsta, dport); + return -1; + } + + if (sport == dport) + { + /* no change */ + return 0; + } + + DBG_log("NAT-T: new mapping %s:%d/%d)", srca, sport, dport); + + nfo.addr = *src; + nfo.sport = sport; + nfo.dport = dport; + + for_each_state((void *)nat_traversal_find_new_mapp_state, &nfo); - if (sport == dport) - { - /* no change */ return 0; - } - - DBG_log("NAT-T: new mapping %s:%d/%d)", srca, sport, dport); - - nfo.addr = *src; - nfo.sport = sport; - nfo.dport = dport; - - for_each_state((void *)nat_traversal_find_new_mapp_state, &nfo); - - return 0; } void nat_traversal_change_port_lookup(struct msg_digest *md, struct state *st) { - struct connection *c = st ? st->st_connection : NULL; - struct iface *i = NULL; + struct connection *c = st ? st->st_connection : NULL; + struct iface *i = NULL; - if ((st == NULL) || (c == NULL)) - return; + if ((st == NULL) || (c == NULL)) + return; - if (md) - { - /* - * If source port has changed, update (including other states and - * established kernel SA) - */ - if (c->spd.that.host_port != md->sender_port) + if (md) { - nat_traversal_new_mapping(&c->spd.that.host_addr, c->spd.that.host_port, - &c->spd.that.host_addr, md->sender_port); + /* + * If source port has changed, update (including other states and + * established kernel SA) + */ + if (c->spd.that.host_port != md->sender_port) + { + nat_traversal_new_mapping(&c->spd.that.host_addr, c->spd.that.host_port, + &c->spd.that.host_addr, md->sender_port); + } + + /* + * If interface type has changed, update local port (500/4500) + */ + if ((c->spd.this.host_port == NAT_T_IKE_FLOAT_PORT && !md->iface->ike_float) + || (c->spd.this.host_port != NAT_T_IKE_FLOAT_PORT && md->iface->ike_float)) + { + c->spd.this.host_port = (md->iface->ike_float) + ? NAT_T_IKE_FLOAT_PORT : pluto_port; + + DBG(DBG_NATT, + DBG_log("NAT-T: updating local port to %d", c->spd.this.host_port); + ); + } } /* - * If interface type has changed, update local port (500/4500) + * If we're initiator and NAT-T (with port floating) is detected, we + * need to change port (MAIN_I3 or QUICK_I1) */ - if ((c->spd.this.host_port == NAT_T_IKE_FLOAT_PORT && !md->iface->ike_float) - || (c->spd.this.host_port != NAT_T_IKE_FLOAT_PORT && md->iface->ike_float)) + if ((st->st_state == STATE_MAIN_I3 || st->st_state == STATE_QUICK_I1) + && (st->nat_traversal & NAT_T_WITH_PORT_FLOATING) + && (st->nat_traversal & NAT_T_DETECTED) + && (c->spd.this.host_port != NAT_T_IKE_FLOAT_PORT)) { - c->spd.this.host_port = (md->iface->ike_float) - ? NAT_T_IKE_FLOAT_PORT : pluto_port; - - DBG(DBG_NATT, - DBG_log("NAT-T: updating local port to %d", c->spd.this.host_port); - ); - } - } - - /* - * If we're initiator and NAT-T (with port floating) is detected, we - * need to change port (MAIN_I3 or QUICK_I1) - */ - if ((st->st_state == STATE_MAIN_I3 || st->st_state == STATE_QUICK_I1) - && (st->nat_traversal & NAT_T_WITH_PORT_FLOATING) - && (st->nat_traversal & NAT_T_DETECTED) - && (c->spd.this.host_port != NAT_T_IKE_FLOAT_PORT)) - { - DBG(DBG_NATT, - DBG_log("NAT-T: floating to port %d", NAT_T_IKE_FLOAT_PORT); - ) - c->spd.this.host_port = NAT_T_IKE_FLOAT_PORT; - c->spd.that.host_port = NAT_T_IKE_FLOAT_PORT; - /* - * Also update pending connections or they will be deleted if uniqueids - * option is set. - */ - update_pending(st, st); - } - - /* - * Find valid interface according to local port (500/4500) - */ - if ((c->spd.this.host_port == NAT_T_IKE_FLOAT_PORT && !c->interface->ike_float) - || (c->spd.this.host_port != NAT_T_IKE_FLOAT_PORT && c->interface->ike_float)) - { - for (i = interfaces; i != NULL; i = i->next) - { - if (sameaddr(&c->interface->addr, &i->addr) - && i->ike_float != c->interface->ike_float) - { DBG(DBG_NATT, - DBG_log("NAT-T: using interface %s:%d", i->rname, - i->ike_float ? NAT_T_IKE_FLOAT_PORT : pluto_port); + DBG_log("NAT-T: floating to port %d", NAT_T_IKE_FLOAT_PORT); ) - c->interface = i; - break; - } + c->spd.this.host_port = NAT_T_IKE_FLOAT_PORT; + c->spd.that.host_port = NAT_T_IKE_FLOAT_PORT; + /* + * Also update pending connections or they will be deleted if uniqueids + * option is set. + */ + update_pending(st, st); + } + + /* + * Find valid interface according to local port (500/4500) + */ + if ((c->spd.this.host_port == NAT_T_IKE_FLOAT_PORT && !c->interface->ike_float) + || (c->spd.this.host_port != NAT_T_IKE_FLOAT_PORT && c->interface->ike_float)) + { + for (i = interfaces; i != NULL; i = i->next) + { + if (sameaddr(&c->interface->addr, &i->addr) + && i->ike_float != c->interface->ike_float) + { + DBG(DBG_NATT, + DBG_log("NAT-T: using interface %s:%d", i->rname, + i->ike_float ? NAT_T_IKE_FLOAT_PORT : pluto_port); + ) + c->interface = i; + break; + } + } } - } } struct _new_klips_mapp_nfo { - struct sadb_sa *sa; - ip_address src, dst; - u_int16_t sport, dport; + struct sadb_sa *sa; + ip_address src, dst; + u_int16_t sport, dport; }; static void nat_t_new_klips_mapp (struct state *st, void *data) { - struct connection *c = st->st_connection; - struct _new_klips_mapp_nfo *nfo = (struct _new_klips_mapp_nfo *)data; + struct connection *c = st->st_connection; + struct _new_klips_mapp_nfo *nfo = (struct _new_klips_mapp_nfo *)data; - if (c != NULL && st->st_esp.present - && sameaddr(&c->spd.that.host_addr, &(nfo->src)) - && st->st_esp.our_spi == nfo->sa->sadb_sa_spi) - { - nat_traversal_new_mapping(&c->spd.that.host_addr, c->spd.that.host_port, - &(nfo->dst), nfo->dport); - } + if (c != NULL && st->st_esp.present + && sameaddr(&c->spd.that.host_addr, &(nfo->src)) + && st->st_esp.our_spi == nfo->sa->sadb_sa_spi) + { + nat_traversal_new_mapping(&c->spd.that.host_addr, c->spd.that.host_port, + &(nfo->dst), nfo->dport); + } } void process_pfkey_nat_t_new_mapping( - struct sadb_msg *msg __attribute__ ((unused)), - struct sadb_ext *extensions[SADB_EXT_MAX + 1]) + struct sadb_msg *msg __attribute__ ((unused)), + struct sadb_ext *extensions[SADB_EXT_MAX + 1]) { - struct _new_klips_mapp_nfo nfo; - struct sadb_address *srcx = (void *) extensions[SADB_EXT_ADDRESS_SRC]; - struct sadb_address *dstx = (void *) extensions[SADB_EXT_ADDRESS_DST]; - struct sockaddr *srca, *dsta; - err_t ugh = NULL; + struct _new_klips_mapp_nfo nfo; + struct sadb_address *srcx = (void *) extensions[SADB_EXT_ADDRESS_SRC]; + struct sadb_address *dstx = (void *) extensions[SADB_EXT_ADDRESS_DST]; + struct sockaddr *srca, *dsta; + err_t ugh = NULL; - nfo.sa = (void *) extensions[SADB_EXT_SA]; + nfo.sa = (void *) extensions[SADB_EXT_SA]; - if (!nfo.sa || !srcx || !dstx) - { - plog("SADB_X_NAT_T_NEW_MAPPING message from KLIPS malformed: " - "got NULL params"); - return; - } + if (!nfo.sa || !srcx || !dstx) + { + plog("SADB_X_NAT_T_NEW_MAPPING message from KLIPS malformed: " + "got NULL params"); + return; + } - srca = ((struct sockaddr *)(void *)&srcx[1]); - dsta = ((struct sockaddr *)(void *)&dstx[1]); + srca = ((struct sockaddr *)(void *)&srcx[1]); + dsta = ((struct sockaddr *)(void *)&dstx[1]); - if (srca->sa_family != AF_INET || dsta->sa_family != AF_INET) - { - ugh = "only AF_INET supported"; - } - else - { - char text_said[SATOT_BUF]; - char _srca[ADDRTOT_BUF], _dsta[ADDRTOT_BUF]; - ip_said said; + if (srca->sa_family != AF_INET || dsta->sa_family != AF_INET) + { + ugh = "only AF_INET supported"; + } + else + { + char text_said[SATOT_BUF]; + char _srca[ADDRTOT_BUF], _dsta[ADDRTOT_BUF]; + ip_said said; - initaddr((const void *) &((const struct sockaddr_in *)srca)->sin_addr, - sizeof(((const struct sockaddr_in *)srca)->sin_addr), - srca->sa_family, &(nfo.src)); - nfo.sport = ntohs(((const struct sockaddr_in *)srca)->sin_port); - initaddr((const void *) &((const struct sockaddr_in *)dsta)->sin_addr, - sizeof(((const struct sockaddr_in *)dsta)->sin_addr), - dsta->sa_family, &(nfo.dst)); - nfo.dport = ntohs(((const struct sockaddr_in *)dsta)->sin_port); + initaddr((const void *) &((const struct sockaddr_in *)srca)->sin_addr, + sizeof(((const struct sockaddr_in *)srca)->sin_addr), + srca->sa_family, &(nfo.src)); + nfo.sport = ntohs(((const struct sockaddr_in *)srca)->sin_port); + initaddr((const void *) &((const struct sockaddr_in *)dsta)->sin_addr, + sizeof(((const struct sockaddr_in *)dsta)->sin_addr), + dsta->sa_family, &(nfo.dst)); + nfo.dport = ntohs(((const struct sockaddr_in *)dsta)->sin_port); - DBG(DBG_NATT, - initsaid(&nfo.src, nfo.sa->sadb_sa_spi, SA_ESP, &said); - satot(&said, 0, text_said, SATOT_BUF); - addrtot(&nfo.src, 0, _srca, ADDRTOT_BUF); - addrtot(&nfo.dst, 0, _dsta, ADDRTOT_BUF); - DBG_log("new klips mapping %s %s:%d %s:%d", - text_said, _srca, nfo.sport, _dsta, nfo.dport); - ) + DBG(DBG_NATT, + initsaid(&nfo.src, nfo.sa->sadb_sa_spi, SA_ESP, &said); + satot(&said, 0, text_said, SATOT_BUF); + addrtot(&nfo.src, 0, _srca, ADDRTOT_BUF); + addrtot(&nfo.dst, 0, _dsta, ADDRTOT_BUF); + DBG_log("new klips mapping %s %s:%d %s:%d", + text_said, _srca, nfo.sport, _dsta, nfo.dport); + ) - for_each_state((void *)nat_t_new_klips_mapp, &nfo); - } + for_each_state((void *)nat_t_new_klips_mapp, &nfo); + } - if (ugh != NULL) - plog("SADB_X_NAT_T_NEW_MAPPING message from KLIPS malformed: %s", ugh); + if (ugh != NULL) + plog("SADB_X_NAT_T_NEW_MAPPING message from KLIPS malformed: %s", ugh); } diff --git a/src/pluto/nat_traversal.h b/src/pluto/nat_traversal.h index 0ce1d49aa..b2a80f87e 100644 --- a/src/pluto/nat_traversal.h +++ b/src/pluto/nat_traversal.h @@ -32,37 +32,37 @@ * NAT-Traversal methods which need NAT-D */ #define NAT_T_WITH_NATD \ - ( LELEM(NAT_TRAVERSAL_IETF_00_01) | LELEM(NAT_TRAVERSAL_IETF_02_03) | \ - LELEM(NAT_TRAVERSAL_RFC) ) + ( LELEM(NAT_TRAVERSAL_IETF_00_01) | LELEM(NAT_TRAVERSAL_IETF_02_03) | \ + LELEM(NAT_TRAVERSAL_RFC) ) /** * NAT-Traversal methods which need NAT-OA */ #define NAT_T_WITH_NATOA \ - ( LELEM(NAT_TRAVERSAL_IETF_00_01) | LELEM(NAT_TRAVERSAL_IETF_02_03) | \ - LELEM(NAT_TRAVERSAL_RFC) ) + ( LELEM(NAT_TRAVERSAL_IETF_00_01) | LELEM(NAT_TRAVERSAL_IETF_02_03) | \ + LELEM(NAT_TRAVERSAL_RFC) ) /** * NAT-Traversal methods which use NAT-KeepAlive */ #define NAT_T_WITH_KA \ - ( LELEM(NAT_TRAVERSAL_IETF_00_01) | LELEM(NAT_TRAVERSAL_IETF_02_03) | \ - LELEM(NAT_TRAVERSAL_RFC) ) + ( LELEM(NAT_TRAVERSAL_IETF_00_01) | LELEM(NAT_TRAVERSAL_IETF_02_03) | \ + LELEM(NAT_TRAVERSAL_RFC) ) /** * NAT-Traversal methods which use floating port */ #define NAT_T_WITH_PORT_FLOATING \ - ( LELEM(NAT_TRAVERSAL_IETF_02_03) | LELEM(NAT_TRAVERSAL_RFC) ) + ( LELEM(NAT_TRAVERSAL_IETF_02_03) | LELEM(NAT_TRAVERSAL_RFC) ) /** * NAT-Traversal methods which use officials values (RFC) */ #define NAT_T_WITH_RFC_VALUES \ - ( LELEM(NAT_TRAVERSAL_RFC) ) + ( LELEM(NAT_TRAVERSAL_RFC) ) /** * NAT-Traversal detected */ #define NAT_T_DETECTED \ - ( LELEM(NAT_TRAVERSAL_NAT_BHND_ME) | LELEM(NAT_TRAVERSAL_NAT_BHND_PEER) ) + ( LELEM(NAT_TRAVERSAL_NAT_BHND_ME) | LELEM(NAT_TRAVERSAL_NAT_BHND_PEER) ) /** * NAT-T Port Floating @@ -70,7 +70,7 @@ #define NAT_T_IKE_FLOAT_PORT 4500 void init_nat_traversal (bool activate, unsigned int keep_alive_period, - bool fka, bool spf); + bool fka, bool spf); extern bool nat_traversal_enabled; extern bool nat_traversal_support_non_ike; @@ -82,7 +82,7 @@ extern bool nat_traversal_support_port_floating; void nat_traversal_natd_lookup(struct msg_digest *md); #ifndef PB_STREAM_UNDEFINED bool nat_traversal_add_natd(u_int8_t np, pb_stream *outs, - struct msg_digest *md); + struct msg_digest *md); #endif /** @@ -91,7 +91,7 @@ bool nat_traversal_add_natd(u_int8_t np, pb_stream *outs, void nat_traversal_natoa_lookup(struct msg_digest *md); #ifndef PB_STREAM_UNDEFINED bool nat_traversal_add_natoa(u_int8_t np, pb_stream *outs, - struct state *st); + struct state *st); #endif /** @@ -119,8 +119,8 @@ void nat_traversal_change_port_lookup(struct msg_digest *md, struct state *st); */ #ifdef __PFKEY_V2_H void process_pfkey_nat_t_new_mapping( - struct sadb_msg *, - struct sadb_ext *[SADB_EXT_MAX + 1]); + struct sadb_msg *, + struct sadb_ext *[SADB_EXT_MAX + 1]); #endif /** @@ -133,22 +133,22 @@ nat_traversal_port_float(struct state *st, struct msg_digest *md, bool in); * Encapsulation mode macro (see demux.c) */ #define NAT_T_ENCAPSULATION_MODE(st,nat_t_policy) ( \ - ((st)->nat_traversal & NAT_T_DETECTED) \ - ? ( ((nat_t_policy) & POLICY_TUNNEL) \ - ? ( ((st)->nat_traversal & NAT_T_WITH_RFC_VALUES) \ - ? (ENCAPSULATION_MODE_UDP_TUNNEL_RFC) \ - : (ENCAPSULATION_MODE_UDP_TUNNEL_DRAFTS) \ - ) \ - : ( ((st)->nat_traversal & NAT_T_WITH_RFC_VALUES) \ - ? (ENCAPSULATION_MODE_UDP_TRANSPORT_RFC) \ - : (ENCAPSULATION_MODE_UDP_TRANSPORT_DRAFTS) \ - ) \ - ) \ - : ( ((st)->st_policy & POLICY_TUNNEL) \ - ? (ENCAPSULATION_MODE_TUNNEL) \ - : (ENCAPSULATION_MODE_TRANSPORT) \ - ) \ - ) + ((st)->nat_traversal & NAT_T_DETECTED) \ + ? ( ((nat_t_policy) & POLICY_TUNNEL) \ + ? ( ((st)->nat_traversal & NAT_T_WITH_RFC_VALUES) \ + ? (ENCAPSULATION_MODE_UDP_TUNNEL_RFC) \ + : (ENCAPSULATION_MODE_UDP_TUNNEL_DRAFTS) \ + ) \ + : ( ((st)->nat_traversal & NAT_T_WITH_RFC_VALUES) \ + ? (ENCAPSULATION_MODE_UDP_TRANSPORT_RFC) \ + : (ENCAPSULATION_MODE_UDP_TRANSPORT_DRAFTS) \ + ) \ + ) \ + : ( ((st)->st_policy & POLICY_TUNNEL) \ + ? (ENCAPSULATION_MODE_TUNNEL) \ + : (ENCAPSULATION_MODE_TRANSPORT) \ + ) \ + ) #endif /* _NAT_TRAVERSAL_H */ diff --git a/src/pluto/ocsp.c b/src/pluto/ocsp.c index 256c447d9..ce6df896d 100644 --- a/src/pluto/ocsp.c +++ b/src/pluto/ocsp.c @@ -43,106 +43,106 @@ #include "fetch.h" #include "ocsp.h" -#define NONCE_LENGTH 16 +#define NONCE_LENGTH 16 static const char *const cert_status_names[] = { - "good", - "revoked", - "unknown", - "undefined" + "good", + "revoked", + "unknown", + "undefined" }; static const char *const response_status_names[] = { - "successful", - "malformed request", - "internal error", - "try later", - "status #4", - "signature required", - "unauthorized" + "successful", + "malformed request", + "internal error", + "try later", + "status #4", + "signature required", + "unauthorized" }; /* response container */ typedef struct response response_t; struct response { - chunk_t tbs; - chunk_t responder_id_name; - chunk_t responder_id_key; - time_t produced_at; - chunk_t responses; - chunk_t nonce; - int algorithm; - chunk_t signature; + chunk_t tbs; + chunk_t responder_id_name; + chunk_t responder_id_key; + time_t produced_at; + chunk_t responses; + chunk_t nonce; + int algorithm; + chunk_t signature; }; const response_t empty_response = { - { NULL, 0 } , /* tbs */ - { NULL, 0 } , /* responder_id_name */ - { NULL, 0 } , /* responder_id_key */ - UNDEFINED_TIME, /* produced_at */ - { NULL, 0 } , /* single_response */ - { NULL, 0 } , /* nonce */ - OID_UNKNOWN , /* signature_algorithm */ - { NULL, 0 } /* signature */ + { NULL, 0 } , /* tbs */ + { NULL, 0 } , /* responder_id_name */ + { NULL, 0 } , /* responder_id_key */ + UNDEFINED_TIME, /* produced_at */ + { NULL, 0 } , /* single_response */ + { NULL, 0 } , /* nonce */ + OID_UNKNOWN , /* signature_algorithm */ + { NULL, 0 } /* signature */ }; /* single response container */ typedef struct single_response single_response_t; struct single_response { - single_response_t *next; - int hash_algorithm; - chunk_t issuer_name_hash; - chunk_t issuer_key_hash; - chunk_t serialNumber; - cert_status_t status; - time_t revocationTime; - crl_reason_t revocationReason; - time_t thisUpdate; - time_t nextUpdate; + single_response_t *next; + int hash_algorithm; + chunk_t issuer_name_hash; + chunk_t issuer_key_hash; + chunk_t serialNumber; + cert_status_t status; + time_t revocationTime; + crl_reason_t revocationReason; + time_t thisUpdate; + time_t nextUpdate; }; const single_response_t empty_single_response = { - NULL , /* *next */ - OID_UNKNOWN , /* hash_algorithm */ - { NULL, 0 } , /* issuer_name_hash */ - { NULL, 0 } , /* issuer_key_hash */ - { NULL, 0 } , /* serial_number */ - CERT_UNDEFINED , /* status */ - UNDEFINED_TIME , /* revocationTime */ - REASON_UNSPECIFIED, /* revocationReason */ - UNDEFINED_TIME , /* this_update */ - UNDEFINED_TIME /* next_update */ + NULL , /* *next */ + OID_UNKNOWN , /* hash_algorithm */ + { NULL, 0 } , /* issuer_name_hash */ + { NULL, 0 } , /* issuer_key_hash */ + { NULL, 0 } , /* serial_number */ + CERT_UNDEFINED , /* status */ + UNDEFINED_TIME , /* revocationTime */ + REASON_UNSPECIFIED, /* revocationReason */ + UNDEFINED_TIME , /* this_update */ + UNDEFINED_TIME /* next_update */ }; /* list of single requests */ typedef struct request_list request_list_t; struct request_list { - chunk_t request; - request_list_t *next; + chunk_t request; + request_list_t *next; }; /* some OCSP specific prefabricated ASN.1 constants */ static u_char ASN1_nonce_oid_str[] = { - 0x06, 0x09, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02 + 0x06, 0x09, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02 }; static const chunk_t ASN1_nonce_oid = chunk_from_buf(ASN1_nonce_oid_str); static u_char ASN1_response_oid_str[] = { - 0x06, 0x09, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x04 + 0x06, 0x09, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x04 }; static const chunk_t ASN1_response_oid = chunk_from_buf(ASN1_response_oid_str); static u_char ASN1_response_content_str[] = { - 0x04, 0x0D, - 0x30, 0x0B, - 0x06, 0x09, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01 + 0x04, 0x0D, + 0x30, 0x0B, + 0x06, 0x09, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01 }; static const chunk_t ASN1_response_content = chunk_from_buf(ASN1_response_content_str); @@ -172,16 +172,16 @@ static const asn1Object_t ocspResponseObjects[] = { { 1, "end opt", ASN1_EOC, ASN1_END } /* 6 */ }; -#define OCSP_RESPONSE_STATUS 1 -#define OCSP_RESPONSE_TYPE 4 -#define OCSP_RESPONSE 5 -#define OCSP_RESPONSE_ROOF 7 +#define OCSP_RESPONSE_STATUS 1 +#define OCSP_RESPONSE_TYPE 4 +#define OCSP_RESPONSE 5 +#define OCSP_RESPONSE_ROOF 7 static const asn1Object_t basicResponseObjects[] = { { 0, "BasicOCSPResponse", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ { 1, "tbsResponseData", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */ { 2, "versionContext", ASN1_CONTEXT_C_0, ASN1_NONE | - ASN1_DEF }, /* 2 */ + ASN1_DEF }, /* 2 */ { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 3 */ { 2, "responderIdContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 4 */ { 3, "responderIdByName", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */ @@ -196,7 +196,7 @@ static const asn1Object_t basicResponseObjects[] = { { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 14 */ { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 15 */ { 5, "critical", ASN1_BOOLEAN, ASN1_BODY | - ASN1_DEF }, /* 16 */ + ASN1_DEF }, /* 16 */ { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 17 */ { 4, "end loop", ASN1_EOC, ASN1_END }, /* 18 */ { 2, "end opt", ASN1_EOC, ASN1_END }, /* 19 */ @@ -205,23 +205,23 @@ static const asn1Object_t basicResponseObjects[] = { { 1, "certsContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 22 */ { 2, "certs", ASN1_SEQUENCE, ASN1_LOOP }, /* 23 */ { 3, "certificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 24 */ - { 2, "end loop", ASN1_EOC, ASN1_END }, /* 25 */ + { 2, "end loop", ASN1_EOC, ASN1_END }, /* 25 */ { 1, "end opt", ASN1_EOC, ASN1_END } /* 26 */ }; -#define BASIC_RESPONSE_TBS_DATA 1 -#define BASIC_RESPONSE_VERSION 3 -#define BASIC_RESPONSE_ID_BY_NAME 5 -#define BASIC_RESPONSE_ID_BY_KEY 8 -#define BASIC_RESPONSE_PRODUCED_AT 10 -#define BASIC_RESPONSE_RESPONSES 11 -#define BASIC_RESPONSE_EXT_ID 15 -#define BASIC_RESPONSE_CRITICAL 16 -#define BASIC_RESPONSE_EXT_VALUE 17 -#define BASIC_RESPONSE_ALGORITHM 20 -#define BASIC_RESPONSE_SIGNATURE 21 -#define BASIC_RESPONSE_CERTIFICATE 24 -#define BASIC_RESPONSE_ROOF 27 +#define BASIC_RESPONSE_TBS_DATA 1 +#define BASIC_RESPONSE_VERSION 3 +#define BASIC_RESPONSE_ID_BY_NAME 5 +#define BASIC_RESPONSE_ID_BY_KEY 8 +#define BASIC_RESPONSE_PRODUCED_AT 10 +#define BASIC_RESPONSE_RESPONSES 11 +#define BASIC_RESPONSE_EXT_ID 15 +#define BASIC_RESPONSE_CRITICAL 16 +#define BASIC_RESPONSE_EXT_VALUE 17 +#define BASIC_RESPONSE_ALGORITHM 20 +#define BASIC_RESPONSE_SIGNATURE 21 +#define BASIC_RESPONSE_CERTIFICATE 24 +#define BASIC_RESPONSE_ROOF 27 static const asn1Object_t responsesObjects[] = { { 0, "responses", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */ @@ -229,8 +229,8 @@ static const asn1Object_t responsesObjects[] = { { 0, "end loop", ASN1_EOC, ASN1_END } /* 2 */ }; -#define RESPONSES_SINGLE_RESPONSE 1 -#define RESPONSES_ROOF 3 +#define RESPONSES_SINGLE_RESPONSE 1 +#define RESPONSES_ROOF 3 static const asn1Object_t singleResponseObjects[] = { { 0, "singleResponse", ASN1_SEQUENCE, ASN1_BODY }, /* 0 */ @@ -258,27 +258,27 @@ static const asn1Object_t singleResponseObjects[] = { { 3, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */ { 4, "extnID", ASN1_OID, ASN1_BODY }, /* 23 */ { 4, "critical", ASN1_BOOLEAN, ASN1_BODY | - ASN1_DEF }, /* 24 */ + ASN1_DEF }, /* 24 */ { 4, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 25 */ { 2, "end loop", ASN1_EOC, ASN1_END }, /* 26 */ { 1, "end opt", ASN1_EOC, ASN1_END } /* 27 */ }; -#define SINGLE_RESPONSE_ALGORITHM 2 -#define SINGLE_RESPONSE_ISSUER_NAME_HASH 3 -#define SINGLE_RESPONSE_ISSUER_KEY_HASH 4 -#define SINGLE_RESPONSE_SERIAL_NUMBER 5 -#define SINGLE_RESPONSE_CERT_STATUS_GOOD 6 -#define SINGLE_RESPONSE_CERT_STATUS_REVOKED 8 -#define SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME 9 -#define SINGLE_RESPONSE_CERT_STATUS_CRL_REASON 11 -#define SINGLE_RESPONSE_CERT_STATUS_UNKNOWN 14 -#define SINGLE_RESPONSE_THIS_UPDATE 16 -#define SINGLE_RESPONSE_NEXT_UPDATE 18 -#define SINGLE_RESPONSE_EXT_ID 23 -#define SINGLE_RESPONSE_CRITICAL 24 -#define SINGLE_RESPONSE_EXT_VALUE 25 -#define SINGLE_RESPONSE_ROOF 28 +#define SINGLE_RESPONSE_ALGORITHM 2 +#define SINGLE_RESPONSE_ISSUER_NAME_HASH 3 +#define SINGLE_RESPONSE_ISSUER_KEY_HASH 4 +#define SINGLE_RESPONSE_SERIAL_NUMBER 5 +#define SINGLE_RESPONSE_CERT_STATUS_GOOD 6 +#define SINGLE_RESPONSE_CERT_STATUS_REVOKED 8 +#define SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME 9 +#define SINGLE_RESPONSE_CERT_STATUS_CRL_REASON 11 +#define SINGLE_RESPONSE_CERT_STATUS_UNKNOWN 14 +#define SINGLE_RESPONSE_THIS_UPDATE 16 +#define SINGLE_RESPONSE_NEXT_UPDATE 18 +#define SINGLE_RESPONSE_EXT_ID 23 +#define SINGLE_RESPONSE_CRITICAL 24 +#define SINGLE_RESPONSE_EXT_VALUE 25 +#define SINGLE_RESPONSE_ROOF 28 /* build an ocsp location from certificate information * without unsharing its contents @@ -286,48 +286,48 @@ static const asn1Object_t singleResponseObjects[] = { static bool build_ocsp_location(const x509cert_t *cert, ocsp_location_t *location) { - static u_char digest[SHA1_DIGEST_SIZE]; /* temporary storage */ + static u_char digest[SHA1_DIGEST_SIZE]; /* temporary storage */ - location->uri = cert->accessLocation; + location->uri = cert->accessLocation; - if (location->uri.ptr == NULL) - { - ca_info_t *ca = get_ca_info(cert->issuer, cert->authKeySerialNumber - , cert->authKeyID); - if (ca != NULL && ca->ocspuri != NULL) + if (location->uri.ptr == NULL) { - location->uri = chunk_create(ca->ocspuri, strlen(ca->ocspuri)); + ca_info_t *ca = get_ca_info(cert->issuer, cert->authKeySerialNumber + , cert->authKeyID); + if (ca != NULL && ca->ocspuri != NULL) + { + location->uri = chunk_create(ca->ocspuri, strlen(ca->ocspuri)); + } + else + { /* abort if no ocsp location uri is defined */ + return FALSE; + } } - else - { /* abort if no ocsp location uri is defined */ - return FALSE; - } - } - - location->authNameID = chunk_create(digest, SHA1_DIGEST_SIZE); - compute_digest(cert->issuer, OID_SHA1, &location->authNameID); + + location->authNameID = chunk_create(digest, SHA1_DIGEST_SIZE); + compute_digest(cert->issuer, OID_SHA1, &location->authNameID); - location->next = NULL; - location->issuer = cert->issuer; - location->authKeyID = cert->authKeyID; - location->authKeySerialNumber = cert->authKeySerialNumber; - - if (cert->authKeyID.ptr == NULL) - { - x509cert_t *authcert = get_authcert(cert->issuer - , cert->authKeySerialNumber, cert->authKeyID, AUTH_CA); - - if (authcert != NULL) + location->next = NULL; + location->issuer = cert->issuer; + location->authKeyID = cert->authKeyID; + location->authKeySerialNumber = cert->authKeySerialNumber; + + if (cert->authKeyID.ptr == NULL) { - location->authKeyID = authcert->subjectKeyID; - location->authKeySerialNumber = authcert->serialNumber; + x509cert_t *authcert = get_authcert(cert->issuer + , cert->authKeySerialNumber, cert->authKeyID, AUTH_CA); + + if (authcert != NULL) + { + location->authKeyID = authcert->subjectKeyID; + location->authKeySerialNumber = authcert->serialNumber; + } } - } - location->nonce = chunk_empty; - location->certinfo = NULL; + location->nonce = chunk_empty; + location->certinfo = NULL; - return TRUE; + return TRUE; } /* @@ -336,11 +336,11 @@ build_ocsp_location(const x509cert_t *cert, ocsp_location_t *location) static bool same_ocsp_location(const ocsp_location_t *a, const ocsp_location_t *b) { - return ((a->authKeyID.ptr != NULL) - ? same_keyid(a->authKeyID, b->authKeyID) - : (same_dn(a->issuer, b->issuer) - && same_serial(a->authKeySerialNumber, b->authKeySerialNumber))) - && chunk_equals(a->uri, b->uri); + return ((a->authKeyID.ptr != NULL) + ? same_keyid(a->authKeyID, b->authKeyID) + : (same_dn(a->issuer, b->issuer) + && same_serial(a->authKeySerialNumber, b->authKeySerialNumber))) + && chunk_equals(a->uri, b->uri); } /* @@ -350,53 +350,53 @@ ocsp_location_t* get_ocsp_location(const ocsp_location_t * loc, ocsp_location_t *chain) { - while (chain != NULL) - { - if (same_ocsp_location(loc, chain)) - return chain; - chain = chain->next; - } - return NULL; + while (chain != NULL) + { + if (same_ocsp_location(loc, chain)) + return chain; + chain = chain->next; + } + return NULL; } - + /* retrieves the status of a cert from the ocsp cache * returns CERT_UNDEFINED if no status is found */ static cert_status_t get_ocsp_status(const ocsp_location_t *loc, chunk_t serialNumber - ,time_t *nextUpdate, time_t *revocationTime, crl_reason_t *revocationReason) + ,time_t *nextUpdate, time_t *revocationTime, crl_reason_t *revocationReason) { - ocsp_certinfo_t *certinfo, **certinfop; - int cmp = -1; + ocsp_certinfo_t *certinfo, **certinfop; + int cmp = -1; - /* find location */ - ocsp_location_t *location = get_ocsp_location(loc, ocsp_cache); + /* find location */ + ocsp_location_t *location = get_ocsp_location(loc, ocsp_cache); - if (location == NULL) - return CERT_UNDEFINED; + if (location == NULL) + return CERT_UNDEFINED; - /* traverse list of certinfos in increasing order */ - certinfop = &location->certinfo; - certinfo = *certinfop; - - while (certinfo != NULL) - { - cmp = chunk_compare(serialNumber, certinfo->serialNumber); - if (cmp <= 0) - break; - certinfop = &certinfo->next; + /* traverse list of certinfos in increasing order */ + certinfop = &location->certinfo; certinfo = *certinfop; - } - if (cmp == 0) - { - *nextUpdate = certinfo->nextUpdate; - *revocationTime = certinfo->revocationTime; - *revocationReason = certinfo->revocationReason; - return certinfo->status; - } + while (certinfo != NULL) + { + cmp = chunk_compare(serialNumber, certinfo->serialNumber); + if (cmp <= 0) + break; + certinfop = &certinfo->next; + certinfo = *certinfop; + } - return CERT_UNDEFINED; + if (cmp == 0) + { + *nextUpdate = certinfo->nextUpdate; + *revocationTime = certinfo->revocationTime; + *revocationReason = certinfo->revocationReason; + return certinfo->status; + } + + return CERT_UNDEFINED; } /* @@ -406,32 +406,32 @@ cert_status_t verify_by_ocsp(const x509cert_t *cert, time_t *until , time_t *revocationDate, crl_reason_t *revocationReason) { - cert_status_t status; - ocsp_location_t location; - time_t nextUpdate = 0; + cert_status_t status; + ocsp_location_t location; + time_t nextUpdate = 0; - *revocationDate = UNDEFINED_TIME; - *revocationReason = REASON_UNSPECIFIED; - - /* is an ocsp location defined? */ - if (!build_ocsp_location(cert, &location)) - return CERT_UNDEFINED; + *revocationDate = UNDEFINED_TIME; + *revocationReason = REASON_UNSPECIFIED; + + /* is an ocsp location defined? */ + if (!build_ocsp_location(cert, &location)) + return CERT_UNDEFINED; - lock_ocsp_cache("verify_by_ocsp"); - status = get_ocsp_status(&location, cert->serialNumber, &nextUpdate - , revocationDate, revocationReason); - unlock_ocsp_cache("verify_by_ocsp"); + lock_ocsp_cache("verify_by_ocsp"); + status = get_ocsp_status(&location, cert->serialNumber, &nextUpdate + , revocationDate, revocationReason); + unlock_ocsp_cache("verify_by_ocsp"); - if (status == CERT_UNDEFINED || nextUpdate < time(NULL)) - { - plog("ocsp status is stale or not in cache"); - add_ocsp_fetch_request(&location, cert->serialNumber); + if (status == CERT_UNDEFINED || nextUpdate < time(NULL)) + { + plog("ocsp status is stale or not in cache"); + add_ocsp_fetch_request(&location, cert->serialNumber); - /* inititate fetching of ocsp status */ - wake_fetch_thread("verify_by_ocsp"); - } - *until = nextUpdate; - return status; + /* inititate fetching of ocsp status */ + wake_fetch_thread("verify_by_ocsp"); + } + *until = nextUpdate; + return status; } /* @@ -440,49 +440,49 @@ verify_by_ocsp(const x509cert_t *cert, time_t *until void check_ocsp(void) { - ocsp_location_t *location; + ocsp_location_t *location; - lock_ocsp_cache("check_ocsp"); - location = ocsp_cache; - - while (location != NULL) - { - char buf[BUF_LEN]; - bool first = TRUE; - ocsp_certinfo_t *certinfo = location->certinfo; - - while (certinfo != NULL) + lock_ocsp_cache("check_ocsp"); + location = ocsp_cache; + + while (location != NULL) { - if (!certinfo->once) - { - time_t time_left = certinfo->nextUpdate - time(NULL); + char buf[BUF_LEN]; + bool first = TRUE; + ocsp_certinfo_t *certinfo = location->certinfo; - DBG(DBG_CONTROL, - if (first) - { - dntoa(buf, BUF_LEN, location->issuer); - DBG_log("issuer: '%s'", buf); - if (location->authKeyID.ptr != NULL) + while (certinfo != NULL) + { + if (!certinfo->once) { - datatot(location->authKeyID.ptr, location->authKeyID.len - , ':', buf, BUF_LEN); - DBG_log("authkey: %s", buf); - } - first = FALSE; - } - datatot(certinfo->serialNumber.ptr, certinfo->serialNumber.len - , ':', buf, BUF_LEN); - DBG_log("serial: %s, %ld seconds left", buf, time_left) - ) + time_t time_left = certinfo->nextUpdate - time(NULL); - if (time_left < 2*crl_check_interval) - add_ocsp_fetch_request(location, certinfo->serialNumber); - } - certinfo = certinfo->next; + DBG(DBG_CONTROL, + if (first) + { + dntoa(buf, BUF_LEN, location->issuer); + DBG_log("issuer: '%s'", buf); + if (location->authKeyID.ptr != NULL) + { + datatot(location->authKeyID.ptr, location->authKeyID.len + , ':', buf, BUF_LEN); + DBG_log("authkey: %s", buf); + } + first = FALSE; + } + datatot(certinfo->serialNumber.ptr, certinfo->serialNumber.len + , ':', buf, BUF_LEN); + DBG_log("serial: %s, %ld seconds left", buf, time_left) + ) + + if (time_left < 2*crl_check_interval) + add_ocsp_fetch_request(location, certinfo->serialNumber); + } + certinfo = certinfo->next; + } + location = location->next; } - location = location->next; - } - unlock_ocsp_cache("check_ocsp"); + unlock_ocsp_cache("check_ocsp"); } /* @@ -491,8 +491,8 @@ check_ocsp(void) static void free_certinfo(ocsp_certinfo_t *certinfo) { - free(certinfo->serialNumber.ptr); - free(certinfo); + free(certinfo->serialNumber.ptr); + free(certinfo); } /* @@ -501,14 +501,14 @@ free_certinfo(ocsp_certinfo_t *certinfo) static void free_certinfos(ocsp_certinfo_t *chain) { - ocsp_certinfo_t *certinfo; + ocsp_certinfo_t *certinfo; - while (chain != NULL) - { - certinfo = chain; - chain = chain->next; - free_certinfo(certinfo); - } + while (chain != NULL) + { + certinfo = chain; + chain = chain->next; + free_certinfo(certinfo); + } } /* @@ -517,13 +517,13 @@ free_certinfos(ocsp_certinfo_t *chain) static void free_ocsp_location(ocsp_location_t* location) { - free(location->issuer.ptr); - free(location->authNameID.ptr); - free(location->authKeyID.ptr); - free(location->authKeySerialNumber.ptr); - free(location->uri.ptr); - free_certinfos(location->certinfo); - free(location); + free(location->issuer.ptr); + free(location->authNameID.ptr); + free(location->authKeyID.ptr); + free(location->authKeySerialNumber.ptr); + free(location->uri.ptr); + free_certinfos(location->certinfo); + free(location); } /* @@ -532,12 +532,12 @@ free_ocsp_location(ocsp_location_t* location) void free_ocsp_locations(ocsp_location_t **chain) { - while (*chain != NULL) - { - ocsp_location_t *location = *chain; - *chain = location->next; - free_ocsp_location(location); - } + while (*chain != NULL) + { + ocsp_location_t *location = *chain; + *chain = location->next; + free_ocsp_location(location); + } } /* @@ -546,9 +546,9 @@ free_ocsp_locations(ocsp_location_t **chain) void free_ocsp_cache(void) { - lock_ocsp_cache("free_ocsp_cache"); - free_ocsp_locations(&ocsp_cache); - unlock_ocsp_cache("free_ocsp_cache"); + lock_ocsp_cache("free_ocsp_cache"); + free_ocsp_locations(&ocsp_cache); + unlock_ocsp_cache("free_ocsp_cache"); } /* @@ -557,8 +557,8 @@ free_ocsp_cache(void) void free_ocsp(void) { - free(ocsp_default_uri.ptr); - free_ocsp_cache(); + free(ocsp_default_uri.ptr); + free_ocsp_cache(); } /* @@ -568,80 +568,80 @@ void list_ocsp_locations(ocsp_location_t *location, bool requests, bool utc , bool strict) { - bool first = TRUE; + bool first = TRUE; - while (location != NULL) - { - ocsp_certinfo_t *certinfo = location->certinfo; - - if (certinfo != NULL) + while (location != NULL) { - u_char buf[BUF_LEN]; + ocsp_certinfo_t *certinfo = location->certinfo; - if (first) - { - whack_log(RC_COMMENT, " "); - whack_log(RC_COMMENT, "List of OCSP %s:", requests? - "fetch requests":"responses"); - first = FALSE; - } - whack_log(RC_COMMENT, " "); - if (location->issuer.ptr != NULL) - { - dntoa(buf, BUF_LEN, location->issuer); - whack_log(RC_COMMENT, " issuer: '%s'", buf); - } - whack_log(RC_COMMENT, " uri: '%.*s'", (int)location->uri.len - , location->uri.ptr); - if (location->authNameID.ptr != NULL) - { - datatot(location->authNameID.ptr, location->authNameID.len, ':' - , buf, BUF_LEN); - whack_log(RC_COMMENT, " authname: %s", buf); - } - if (location->authKeyID.ptr != NULL) - { - datatot(location->authKeyID.ptr, location->authKeyID.len, ':' - , buf, BUF_LEN); - whack_log(RC_COMMENT, " authkey: %s", buf); - } - if (location->authKeySerialNumber.ptr != NULL) - { - datatot(location->authKeySerialNumber.ptr - , location->authKeySerialNumber.len, ':', buf, BUF_LEN); - whack_log(RC_COMMENT, " aserial: %s", buf); - } - while (certinfo != NULL) - { - char thisUpdate[TIMETOA_BUF]; + if (certinfo != NULL) + { + u_char buf[BUF_LEN]; - snprintf(thisUpdate, TIMETOA_BUF, "%T", &certinfo->thisUpdate, utc); + if (first) + { + whack_log(RC_COMMENT, " "); + whack_log(RC_COMMENT, "List of OCSP %s:", requests? + "fetch requests":"responses"); + first = FALSE; + } + whack_log(RC_COMMENT, " "); + if (location->issuer.ptr != NULL) + { + dntoa(buf, BUF_LEN, location->issuer); + whack_log(RC_COMMENT, " issuer: '%s'", buf); + } + whack_log(RC_COMMENT, " uri: '%.*s'", (int)location->uri.len + , location->uri.ptr); + if (location->authNameID.ptr != NULL) + { + datatot(location->authNameID.ptr, location->authNameID.len, ':' + , buf, BUF_LEN); + whack_log(RC_COMMENT, " authname: %s", buf); + } + if (location->authKeyID.ptr != NULL) + { + datatot(location->authKeyID.ptr, location->authKeyID.len, ':' + , buf, BUF_LEN); + whack_log(RC_COMMENT, " authkey: %s", buf); + } + if (location->authKeySerialNumber.ptr != NULL) + { + datatot(location->authKeySerialNumber.ptr + , location->authKeySerialNumber.len, ':', buf, BUF_LEN); + whack_log(RC_COMMENT, " aserial: %s", buf); + } + while (certinfo != NULL) + { + char thisUpdate[TIMETOA_BUF]; - if (requests) - { - whack_log(RC_COMMENT, "%s, trials: %d", thisUpdate - , certinfo->trials); + snprintf(thisUpdate, TIMETOA_BUF, "%T", &certinfo->thisUpdate, utc); + + if (requests) + { + whack_log(RC_COMMENT, "%s, trials: %d", thisUpdate + , certinfo->trials); + } + else if (certinfo->once) + { + whack_log(RC_COMMENT, "%s, onetime use%s", thisUpdate + , (certinfo->nextUpdate < time(NULL))? " (expired)": ""); + } + else + { + whack_log(RC_COMMENT, "%s, until %T %s", thisUpdate + , &certinfo->nextUpdate, utc + , check_expiry(certinfo->nextUpdate, OCSP_WARNING_INTERVAL, strict)); + } + datatot(certinfo->serialNumber.ptr, certinfo->serialNumber.len, ':' + , buf, BUF_LEN); + whack_log(RC_COMMENT, " serial: %s, %s", buf + , cert_status_names[certinfo->status]); + certinfo = certinfo->next; + } } - else if (certinfo->once) - { - whack_log(RC_COMMENT, "%s, onetime use%s", thisUpdate - , (certinfo->nextUpdate < time(NULL))? " (expired)": ""); - } - else - { - whack_log(RC_COMMENT, "%s, until %T %s", thisUpdate - , &certinfo->nextUpdate, utc - , check_expiry(certinfo->nextUpdate, OCSP_WARNING_INTERVAL, strict)); - } - datatot(certinfo->serialNumber.ptr, certinfo->serialNumber.len, ':' - , buf, BUF_LEN); - whack_log(RC_COMMENT, " serial: %s, %s", buf - , cert_status_names[certinfo->status]); - certinfo = certinfo->next; - } + location = location->next; } - location = location->next; - } } /* @@ -650,121 +650,121 @@ list_ocsp_locations(ocsp_location_t *location, bool requests, bool utc void list_ocsp_cache(bool utc, bool strict) { - lock_ocsp_cache("list_ocsp_cache"); - list_ocsp_locations(ocsp_cache, FALSE, utc, strict); - unlock_ocsp_cache("list_ocsp_cache"); + lock_ocsp_cache("list_ocsp_cache"); + list_ocsp_locations(ocsp_cache, FALSE, utc, strict); + unlock_ocsp_cache("list_ocsp_cache"); } static bool get_ocsp_requestor_cert(ocsp_location_t *location) { - x509cert_t *cert = NULL; + x509cert_t *cert = NULL; - /* initialize temporary static storage */ - ocsp_requestor_cert = NULL; - ocsp_requestor_sc = NULL; - ocsp_requestor_pri = NULL; + /* initialize temporary static storage */ + ocsp_requestor_cert = NULL; + ocsp_requestor_sc = NULL; + ocsp_requestor_pri = NULL; - for (;;) - { - char buf[BUF_LEN]; - - /* looking for a certificate from the same issuer */ - cert = get_x509cert(location->issuer, location->authKeySerialNumber - ,location->authKeyID, cert); - if (cert == NULL) - break; - - DBG(DBG_CONTROL, - dntoa(buf, BUF_LEN, cert->subject); - DBG_log("candidate: '%s'", buf); - ) - - if (cert->smartcard) + for (;;) { - /* look for a matching private key on a smartcard */ - smartcard_t *sc = scx_get(cert); + char buf[BUF_LEN]; + + /* looking for a certificate from the same issuer */ + cert = get_x509cert(location->issuer, location->authKeySerialNumber + ,location->authKeyID, cert); + if (cert == NULL) + break; - if (sc != NULL) - { DBG(DBG_CONTROL, - DBG_log("matching smartcard found") + dntoa(buf, BUF_LEN, cert->subject); + DBG_log("candidate: '%s'", buf); ) - if (sc->valid) + + if (cert->smartcard) { - ocsp_requestor_cert = cert; - ocsp_requestor_sc = sc; - return TRUE; - } - plog("unable to sign ocsp request without PIN"); - } - } - else - { - /* look for a matching private key in the chained list */ - const struct RSA_private_key *pri = get_x509_private_key(cert); + /* look for a matching private key on a smartcard */ + smartcard_t *sc = scx_get(cert); - if (pri != NULL) - { - DBG(DBG_CONTROL, - DBG_log("matching private key found") - ) - ocsp_requestor_cert = cert; - ocsp_requestor_pri = pri; - return TRUE; - } + if (sc != NULL) + { + DBG(DBG_CONTROL, + DBG_log("matching smartcard found") + ) + if (sc->valid) + { + ocsp_requestor_cert = cert; + ocsp_requestor_sc = sc; + return TRUE; + } + plog("unable to sign ocsp request without PIN"); + } + } + else + { + /* look for a matching private key in the chained list */ + const struct RSA_private_key *pri = get_x509_private_key(cert); + + if (pri != NULL) + { + DBG(DBG_CONTROL, + DBG_log("matching private key found") + ) + ocsp_requestor_cert = cert; + ocsp_requestor_pri = pri; + return TRUE; + } + } } - } - return FALSE; + return FALSE; } static chunk_t generate_signature(chunk_t digest, smartcard_t *sc - , const RSA_private_key_t *pri) + , const RSA_private_key_t *pri) { - chunk_t sigdata; - u_char *pos; - size_t siglen = 0; + chunk_t sigdata; + u_char *pos; + size_t siglen = 0; - if (sc != NULL) - { - /* RSA signature is done on smartcard */ - - if (!scx_establish_context(sc) || !scx_login(sc)) + if (sc != NULL) { - scx_release_context(sc); - return chunk_empty; + /* RSA signature is done on smartcard */ + + if (!scx_establish_context(sc) || !scx_login(sc)) + { + scx_release_context(sc); + return chunk_empty; + } + + siglen = scx_get_keylength(sc); + + if (siglen == 0) + { + plog("failed to get keylength from smartcard"); + scx_release_context(sc); + return chunk_empty; + } + + DBG(DBG_CONTROL | DBG_CRYPT, + DBG_log("signing hash with RSA key from smartcard (slot: %d, id: %s)" + , (int)sc->slot, sc->id) + ) + + pos = build_asn1_object(&sigdata, ASN1_BIT_STRING, 1 + siglen); + *pos++ = 0x00; + scx_sign_hash(sc, digest.ptr, digest.len, pos, siglen); + if (!pkcs11_keep_state) + scx_release_context(sc); } - - siglen = scx_get_keylength(sc); - - if (siglen == 0) + else { - plog("failed to get keylength from smartcard"); - scx_release_context(sc); - return chunk_empty; + /* RSA signature is done in software */ + siglen = pri->pub.k; + pos = build_asn1_object(&sigdata, ASN1_BIT_STRING, 1 + siglen); + *pos++ = 0x00; + sign_hash(pri, digest.ptr, digest.len, pos, siglen); } - - DBG(DBG_CONTROL | DBG_CRYPT, - DBG_log("signing hash with RSA key from smartcard (slot: %d, id: %s)" - , (int)sc->slot, sc->id) - ) - - pos = build_asn1_object(&sigdata, ASN1_BIT_STRING, 1 + siglen); - *pos++ = 0x00; - scx_sign_hash(sc, digest.ptr, digest.len, pos, siglen); - if (!pkcs11_keep_state) - scx_release_context(sc); - } - else - { - /* RSA signature is done in software */ - siglen = pri->pub.k; - pos = build_asn1_object(&sigdata, ASN1_BIT_STRING, 1 + siglen); - *pos++ = 0x00; - sign_hash(pri, digest.ptr, digest.len, pos, siglen); - } - return sigdata; + return sigdata; } /* @@ -775,47 +775,47 @@ generate_signature(chunk_t digest, smartcard_t *sc static chunk_t build_signature(chunk_t tbsRequest) { - chunk_t sigdata, certs; - chunk_t digest_info; + chunk_t sigdata, certs; + chunk_t digest_info; - u_char digest_buf[MAX_DIGEST_LEN]; - chunk_t digest_raw = { digest_buf, MAX_DIGEST_LEN }; + u_char digest_buf[MAX_DIGEST_LEN]; + chunk_t digest_raw = { digest_buf, MAX_DIGEST_LEN }; - if (!compute_digest(tbsRequest, OID_SHA1, &digest_raw)) - return chunk_empty; + if (!compute_digest(tbsRequest, OID_SHA1, &digest_raw)) + return chunk_empty; - /* according to PKCS#1 v2.1 digest must be packaged into - * an ASN.1 structure for encryption - */ - digest_info = asn1_wrap(ASN1_SEQUENCE, "cm" - , ASN1_sha1_id - , asn1_simple_object(ASN1_OCTET_STRING, digest_raw)); + /* according to PKCS#1 v2.1 digest must be packaged into + * an ASN.1 structure for encryption + */ + digest_info = asn1_wrap(ASN1_SEQUENCE, "cm" + , ASN1_sha1_id + , asn1_simple_object(ASN1_OCTET_STRING, digest_raw)); - /* generate the RSA signature */ - sigdata = generate_signature(digest_info - , ocsp_requestor_sc - , ocsp_requestor_pri); - free(digest_info.ptr); + /* generate the RSA signature */ + sigdata = generate_signature(digest_info + , ocsp_requestor_sc + , ocsp_requestor_pri); + free(digest_info.ptr); - /* has the RSA signature generation been successful? */ - if (sigdata.ptr == NULL) - return chunk_empty; + /* has the RSA signature generation been successful? */ + if (sigdata.ptr == NULL) + return chunk_empty; - /* include our certificate */ - certs = asn1_wrap(ASN1_CONTEXT_C_0, "m" - , asn1_simple_object(ASN1_SEQUENCE - , ocsp_requestor_cert->certificate - ) - ); + /* include our certificate */ + certs = asn1_wrap(ASN1_CONTEXT_C_0, "m" + , asn1_simple_object(ASN1_SEQUENCE + , ocsp_requestor_cert->certificate + ) + ); - /* build signature comprising algorithm, signature and cert */ - return asn1_wrap(ASN1_CONTEXT_C_0, "m" - , asn1_wrap(ASN1_SEQUENCE, "cmm" - , ASN1_sha1WithRSA_id - , sigdata - , certs - ) - ); + /* build signature comprising algorithm, signature and cert */ + return asn1_wrap(ASN1_CONTEXT_C_0, "m" + , asn1_wrap(ASN1_SEQUENCE, "cmm" + , ASN1_sha1WithRSA_id + , sigdata + , certs + ) + ); } /* build request (into requestList) @@ -824,13 +824,13 @@ build_signature(chunk_t tbsRequest) static chunk_t build_request(ocsp_location_t *location, ocsp_certinfo_t *certinfo) { - chunk_t reqCert = asn1_wrap(ASN1_SEQUENCE, "cmmm" - , ASN1_sha1_id - , asn1_simple_object(ASN1_OCTET_STRING, location->authNameID) - , asn1_simple_object(ASN1_OCTET_STRING, location->authKeyID) - , asn1_simple_object(ASN1_INTEGER, certinfo->serialNumber)); + chunk_t reqCert = asn1_wrap(ASN1_SEQUENCE, "cmmm" + , ASN1_sha1_id + , asn1_simple_object(ASN1_OCTET_STRING, location->authNameID) + , asn1_simple_object(ASN1_OCTET_STRING, location->authKeyID) + , asn1_simple_object(ASN1_INTEGER, certinfo->serialNumber)); - return asn1_wrap(ASN1_SEQUENCE, "m", reqCert); + return asn1_wrap(ASN1_SEQUENCE, "m", reqCert); } /* @@ -839,43 +839,43 @@ build_request(ocsp_location_t *location, ocsp_certinfo_t *certinfo) static chunk_t build_request_list(ocsp_location_t *location) { - chunk_t requestList; - request_list_t *reqs = NULL; - ocsp_certinfo_t *certinfo = location->certinfo; - u_char *pos; + chunk_t requestList; + request_list_t *reqs = NULL; + ocsp_certinfo_t *certinfo = location->certinfo; + u_char *pos; - size_t datalen = 0; + size_t datalen = 0; - /* build content */ - while (certinfo != NULL) - { - /* build request for every certificate in list - * and store them in a chained list - */ - request_list_t *req = malloc_thing(request_list_t); + /* build content */ + while (certinfo != NULL) + { + /* build request for every certificate in list + * and store them in a chained list + */ + request_list_t *req = malloc_thing(request_list_t); - req->request = build_request(location, certinfo); - req->next = reqs; - reqs = req; + req->request = build_request(location, certinfo); + req->next = reqs; + reqs = req; - datalen += req->request.len; - certinfo = certinfo->next; - } + datalen += req->request.len; + certinfo = certinfo->next; + } - pos = build_asn1_object(&requestList, ASN1_SEQUENCE - , datalen); + pos = build_asn1_object(&requestList, ASN1_SEQUENCE + , datalen); - /* copy all in chained list, free list afterwards */ - while (reqs != NULL) - { - request_list_t *req = reqs; + /* copy all in chained list, free list afterwards */ + while (reqs != NULL) + { + request_list_t *req = reqs; - mv_chunk(&pos, req->request); - reqs = reqs->next; - free(req); - } + mv_chunk(&pos, req->request); + reqs = reqs->next; + free(req); + } - return requestList; + return requestList; } /* @@ -884,9 +884,9 @@ build_request_list(ocsp_location_t *location) static chunk_t build_requestor_name(void) { - return asn1_wrap(ASN1_CONTEXT_C_1, "m" - , asn1_simple_object(ASN1_CONTEXT_C_4 - , ocsp_requestor_cert->subject)); + return asn1_wrap(ASN1_CONTEXT_C_1, "m" + , asn1_simple_object(ASN1_CONTEXT_C_4 + , ocsp_requestor_cert->subject)); } /* @@ -895,14 +895,14 @@ build_requestor_name(void) static chunk_t build_nonce_extension(ocsp_location_t *location) { - /* generate a random nonce */ - location->nonce.ptr = malloc(NONCE_LENGTH), - location->nonce.len = NONCE_LENGTH; - get_rnd_bytes(location->nonce.ptr, NONCE_LENGTH); + /* generate a random nonce */ + location->nonce.ptr = malloc(NONCE_LENGTH), + location->nonce.len = NONCE_LENGTH; + get_rnd_bytes(location->nonce.ptr, NONCE_LENGTH); - return asn1_wrap(ASN1_SEQUENCE, "cm" - , ASN1_nonce_oid - , asn1_simple_object(ASN1_OCTET_STRING, location->nonce)); + return asn1_wrap(ASN1_SEQUENCE, "cm" + , ASN1_nonce_oid + , asn1_simple_object(ASN1_OCTET_STRING, location->nonce)); } /* @@ -911,15 +911,15 @@ build_nonce_extension(ocsp_location_t *location) static chunk_t build_request_ext(ocsp_location_t *location) { - return asn1_wrap(ASN1_CONTEXT_C_2, "m" - , asn1_wrap(ASN1_SEQUENCE, "mm" - , build_nonce_extension(location) - , asn1_wrap(ASN1_SEQUENCE, "cc" - , ASN1_response_oid - , ASN1_response_content - ) - ) - ); + return asn1_wrap(ASN1_CONTEXT_C_2, "m" + , asn1_wrap(ASN1_SEQUENCE, "mm" + , build_nonce_extension(location) + , asn1_wrap(ASN1_SEQUENCE, "cc" + , ASN1_response_oid + , ASN1_response_content + ) + ) + ); } /* @@ -928,13 +928,13 @@ build_request_ext(ocsp_location_t *location) static chunk_t build_tbs_request(ocsp_location_t *location, bool has_requestor_cert) { - /* version is skipped since the default is ok */ - return asn1_wrap(ASN1_SEQUENCE, "mmm" - , (has_requestor_cert) - ? build_requestor_name() - : chunk_empty - , build_request_list(location) - , build_request_ext(location)); + /* version is skipped since the default is ok */ + return asn1_wrap(ASN1_SEQUENCE, "mmm" + , (has_requestor_cert) + ? build_requestor_name() + : chunk_empty + , build_request_list(location) + , build_request_ext(location)); } /* assembles an ocsp request to given location @@ -943,38 +943,38 @@ build_tbs_request(ocsp_location_t *location, bool has_requestor_cert) chunk_t build_ocsp_request(ocsp_location_t *location) { - bool has_requestor_cert; - chunk_t tbsRequest, signature; - char buf[BUF_LEN]; + bool has_requestor_cert; + chunk_t tbsRequest, signature; + char buf[BUF_LEN]; - DBG(DBG_CONTROL, - DBG_log("assembling ocsp request"); - dntoa(buf, BUF_LEN, location->issuer); - DBG_log("issuer: '%s'", buf); - if (location->authKeyID.ptr != NULL) - { - datatot(location->authKeyID.ptr, location->authKeyID.len, ':' - , buf, BUF_LEN); - DBG_log("authkey: %s", buf); - } - ) - lock_certs_and_keys("build_ocsp_request"); + DBG(DBG_CONTROL, + DBG_log("assembling ocsp request"); + dntoa(buf, BUF_LEN, location->issuer); + DBG_log("issuer: '%s'", buf); + if (location->authKeyID.ptr != NULL) + { + datatot(location->authKeyID.ptr, location->authKeyID.len, ':' + , buf, BUF_LEN); + DBG_log("authkey: %s", buf); + } + ) + lock_certs_and_keys("build_ocsp_request"); - /* looks for requestor cert and matching private key */ - has_requestor_cert = get_ocsp_requestor_cert(location); + /* looks for requestor cert and matching private key */ + has_requestor_cert = get_ocsp_requestor_cert(location); - /* build content */ - tbsRequest = build_tbs_request(location, has_requestor_cert); + /* build content */ + tbsRequest = build_tbs_request(location, has_requestor_cert); - /* sign tbsReuqest */ - signature = (has_requestor_cert)? build_signature(tbsRequest) - : chunk_empty; + /* sign tbsReuqest */ + signature = (has_requestor_cert)? build_signature(tbsRequest) + : chunk_empty; - unlock_certs_and_keys("build_ocsp_request"); + unlock_certs_and_keys("build_ocsp_request"); - return asn1_wrap(ASN1_SEQUENCE, "mm" - , tbsRequest - , signature); + return asn1_wrap(ASN1_SEQUENCE, "mm" + , tbsRequest + , signature); } /* @@ -983,107 +983,107 @@ build_ocsp_request(ocsp_location_t *location) static bool valid_ocsp_response(response_t *res) { - int pathlen; - x509cert_t *authcert; + int pathlen; + x509cert_t *authcert; - lock_authcert_list("valid_ocsp_response"); + lock_authcert_list("valid_ocsp_response"); - authcert = get_authcert(res->responder_id_name, chunk_empty - , res->responder_id_key, AUTH_OCSP | AUTH_CA); - - if (authcert == NULL) - { - plog("no matching ocsp signer cert found"); - unlock_authcert_list("valid_ocsp_response"); - return FALSE; - } - DBG(DBG_CONTROL, - DBG_log("ocsp signer cert found") - ) - - if (!check_signature(res->tbs, res->signature, res->algorithm - , res->algorithm, authcert)) - { - plog("signature of ocsp response is invalid"); - unlock_authcert_list("valid_ocsp_response"); - return FALSE; - } - DBG(DBG_CONTROL, - DBG_log("signature of ocsp response is valid") - ) - - - for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++) - { - u_char buf[BUF_LEN]; - err_t ugh = NULL; - time_t until; - - x509cert_t *cert = authcert; - - DBG(DBG_CONTROL, - dntoa(buf, BUF_LEN, cert->subject); - DBG_log("subject: '%s'",buf); - dntoa(buf, BUF_LEN, cert->issuer); - DBG_log("issuer: '%s'",buf); - if (cert->authKeyID.ptr != NULL) - { - datatot(cert->authKeyID.ptr, cert->authKeyID.len, ':' - , buf, BUF_LEN); - DBG_log("authkey: %s", buf); - } - ) - - ugh = check_validity(authcert, &until); - - if (ugh != NULL) - { - plog("%s", ugh); - unlock_authcert_list("valid_ocsp_response"); - return FALSE; - } - - DBG(DBG_CONTROL, - DBG_log("certificate is valid") - ) - - authcert = get_authcert(cert->issuer, cert->authKeySerialNumber - , cert->authKeyID, AUTH_CA); + authcert = get_authcert(res->responder_id_name, chunk_empty + , res->responder_id_key, AUTH_OCSP | AUTH_CA); if (authcert == NULL) { - plog("issuer cacert not found"); - unlock_authcert_list("valid_ocsp_response"); - return FALSE; + plog("no matching ocsp signer cert found"); + unlock_authcert_list("valid_ocsp_response"); + return FALSE; } DBG(DBG_CONTROL, - DBG_log("issuer cacert found") + DBG_log("ocsp signer cert found") ) - if (!check_signature(cert->tbsCertificate, cert->signature - , cert->algorithm, cert->algorithm, authcert)) + if (!check_signature(res->tbs, res->signature, res->algorithm + , res->algorithm, authcert)) { - plog("certificate signature is invalid"); - unlock_authcert_list("valid_ocsp_response"); - return FALSE; + plog("signature of ocsp response is invalid"); + unlock_authcert_list("valid_ocsp_response"); + return FALSE; } DBG(DBG_CONTROL, - DBG_log("certificate signature is valid") + DBG_log("signature of ocsp response is valid") ) - /* check if cert is self-signed */ - if (same_dn(cert->issuer, cert->subject)) + + for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++) { - DBG(DBG_CONTROL, - DBG_log("reached self-signed root ca") - ) - unlock_authcert_list("valid_ocsp_response"); - return TRUE; + u_char buf[BUF_LEN]; + err_t ugh = NULL; + time_t until; + + x509cert_t *cert = authcert; + + DBG(DBG_CONTROL, + dntoa(buf, BUF_LEN, cert->subject); + DBG_log("subject: '%s'",buf); + dntoa(buf, BUF_LEN, cert->issuer); + DBG_log("issuer: '%s'",buf); + if (cert->authKeyID.ptr != NULL) + { + datatot(cert->authKeyID.ptr, cert->authKeyID.len, ':' + , buf, BUF_LEN); + DBG_log("authkey: %s", buf); + } + ) + + ugh = check_validity(authcert, &until); + + if (ugh != NULL) + { + plog("%s", ugh); + unlock_authcert_list("valid_ocsp_response"); + return FALSE; + } + + DBG(DBG_CONTROL, + DBG_log("certificate is valid") + ) + + authcert = get_authcert(cert->issuer, cert->authKeySerialNumber + , cert->authKeyID, AUTH_CA); + + if (authcert == NULL) + { + plog("issuer cacert not found"); + unlock_authcert_list("valid_ocsp_response"); + return FALSE; + } + DBG(DBG_CONTROL, + DBG_log("issuer cacert found") + ) + + if (!check_signature(cert->tbsCertificate, cert->signature + , cert->algorithm, cert->algorithm, authcert)) + { + plog("certificate signature is invalid"); + unlock_authcert_list("valid_ocsp_response"); + return FALSE; + } + DBG(DBG_CONTROL, + DBG_log("certificate signature is valid") + ) + + /* check if cert is self-signed */ + if (same_dn(cert->issuer, cert->subject)) + { + DBG(DBG_CONTROL, + DBG_log("reached self-signed root ca") + ) + unlock_authcert_list("valid_ocsp_response"); + return TRUE; + } } - } - plog("maximum ca path length of %d levels exceeded", MAX_CA_PATH_LEN); - unlock_authcert_list("valid_ocsp_response"); - return FALSE; + plog("maximum ca path length of %d levels exceeded", MAX_CA_PATH_LEN); + unlock_authcert_list("valid_ocsp_response"); + return FALSE; } /* @@ -1092,95 +1092,95 @@ valid_ocsp_response(response_t *res) static bool parse_basic_ocsp_response(chunk_t blob, int level0, response_t *res) { - asn1_ctx_t ctx; - bool critical; - chunk_t object; - u_int level, version; - u_char buf[BUF_LEN]; - int objectID = 0; - int extn_oid = OID_UNKNOWN; + asn1_ctx_t ctx; + bool critical; + chunk_t object; + u_int level, version; + u_char buf[BUF_LEN]; + int objectID = 0; + int extn_oid = OID_UNKNOWN; - asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); + asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); - while (objectID < BASIC_RESPONSE_ROOF) - { - if (!extract_object(basicResponseObjects, &objectID, &object, &level, &ctx)) - return FALSE; - - switch (objectID) + while (objectID < BASIC_RESPONSE_ROOF) { - case BASIC_RESPONSE_TBS_DATA: - res->tbs = object; - break; - case BASIC_RESPONSE_VERSION: - version = (object.len)? (1 + (u_int)*object.ptr) : 1; - if (version != OCSP_BASIC_RESPONSE_VERSION) - { - plog("wrong ocsp basic response version (version= %i)", version); - return FALSE; - } - break; - case BASIC_RESPONSE_ID_BY_NAME: - res->responder_id_name = object; - DBG(DBG_PARSING, - dntoa(buf, BUF_LEN, object); - DBG_log(" '%s'",buf) - ) - break; - case BASIC_RESPONSE_ID_BY_KEY: - res->responder_id_key = object; - break; - case BASIC_RESPONSE_PRODUCED_AT: - res->produced_at = asn1totime(&object, ASN1_GENERALIZEDTIME); - break; - case BASIC_RESPONSE_RESPONSES: - res->responses = object; - break; - case BASIC_RESPONSE_EXT_ID: - extn_oid = asn1_known_oid(object); - break; - case BASIC_RESPONSE_CRITICAL: - critical = object.len && *object.ptr; - DBG(DBG_PARSING, - DBG_log(" %s",(critical)?"TRUE":"FALSE"); - ) - break; - case BASIC_RESPONSE_EXT_VALUE: - if (extn_oid == OID_NONCE) - res->nonce = object; - break; - case BASIC_RESPONSE_ALGORITHM: - res->algorithm = parse_algorithmIdentifier(object, level+1, NULL); - break; - case BASIC_RESPONSE_SIGNATURE: - res->signature = object; - break; - case BASIC_RESPONSE_CERTIFICATE: - { - chunk_t blob = chunk_clone(object); - x509cert_t *cert = malloc_thing(x509cert_t); - - *cert = empty_x509cert; - - if (parse_x509cert(blob, level+1, cert) - && cert->isOcspSigner - && trust_authcert_candidate(cert, NULL)) + if (!extract_object(basicResponseObjects, &objectID, &object, &level, &ctx)) + return FALSE; + + switch (objectID) { - add_authcert(cert, AUTH_OCSP); + case BASIC_RESPONSE_TBS_DATA: + res->tbs = object; + break; + case BASIC_RESPONSE_VERSION: + version = (object.len)? (1 + (u_int)*object.ptr) : 1; + if (version != OCSP_BASIC_RESPONSE_VERSION) + { + plog("wrong ocsp basic response version (version= %i)", version); + return FALSE; + } + break; + case BASIC_RESPONSE_ID_BY_NAME: + res->responder_id_name = object; + DBG(DBG_PARSING, + dntoa(buf, BUF_LEN, object); + DBG_log(" '%s'",buf) + ) + break; + case BASIC_RESPONSE_ID_BY_KEY: + res->responder_id_key = object; + break; + case BASIC_RESPONSE_PRODUCED_AT: + res->produced_at = asn1totime(&object, ASN1_GENERALIZEDTIME); + break; + case BASIC_RESPONSE_RESPONSES: + res->responses = object; + break; + case BASIC_RESPONSE_EXT_ID: + extn_oid = asn1_known_oid(object); + break; + case BASIC_RESPONSE_CRITICAL: + critical = object.len && *object.ptr; + DBG(DBG_PARSING, + DBG_log(" %s",(critical)?"TRUE":"FALSE"); + ) + break; + case BASIC_RESPONSE_EXT_VALUE: + if (extn_oid == OID_NONCE) + res->nonce = object; + break; + case BASIC_RESPONSE_ALGORITHM: + res->algorithm = parse_algorithmIdentifier(object, level+1, NULL); + break; + case BASIC_RESPONSE_SIGNATURE: + res->signature = object; + break; + case BASIC_RESPONSE_CERTIFICATE: + { + chunk_t blob = chunk_clone(object); + x509cert_t *cert = malloc_thing(x509cert_t); + + *cert = empty_x509cert; + + if (parse_x509cert(blob, level+1, cert) + && cert->isOcspSigner + && trust_authcert_candidate(cert, NULL)) + { + add_authcert(cert, AUTH_OCSP); + } + else + { + DBG(DBG_CONTROL | DBG_PARSING, + DBG_log("embedded ocsp certificate rejected") + ) + free_x509cert(cert); + } + } + break; } - else - { - DBG(DBG_CONTROL | DBG_PARSING, - DBG_log("embedded ocsp certificate rejected") - ) - free_x509cert(cert); - } - } - break; + objectID++; } - objectID++; - } - return TRUE; + return TRUE; } @@ -1190,63 +1190,63 @@ parse_basic_ocsp_response(chunk_t blob, int level0, response_t *res) static response_status parse_ocsp_response(chunk_t blob, response_t * res) { - asn1_ctx_t ctx; - chunk_t object; - u_int level; - int objectID = 0; - int ocspResponseType = OID_UNKNOWN; - response_status rStatus = STATUS_INTERNALERROR; + asn1_ctx_t ctx; + chunk_t object; + u_int level; + int objectID = 0; + int ocspResponseType = OID_UNKNOWN; + response_status rStatus = STATUS_INTERNALERROR; - asn1_init(&ctx, blob, 0, FALSE, DBG_RAW); + asn1_init(&ctx, blob, 0, FALSE, DBG_RAW); - while (objectID < OCSP_RESPONSE_ROOF) - { - if (!extract_object(ocspResponseObjects, &objectID, &object, &level, &ctx)) - return STATUS_INTERNALERROR; - - switch (objectID) { - case OCSP_RESPONSE_STATUS: - rStatus = (response_status) *object.ptr; - - switch (rStatus) - { - case STATUS_SUCCESSFUL: - break; - case STATUS_MALFORMEDREQUEST: - case STATUS_INTERNALERROR: - case STATUS_TRYLATER: - case STATUS_SIGREQUIRED: - case STATUS_UNAUTHORIZED: - plog("ocsp response: server said '%s'" - , response_status_names[rStatus]); - return rStatus; - default: - return STATUS_INTERNALERROR; - } - break; - case OCSP_RESPONSE_TYPE: - ocspResponseType = asn1_known_oid(object); - break; - case OCSP_RESPONSE: - { - switch (ocspResponseType) { - case OID_BASIC: - if (!parse_basic_ocsp_response(object, level+1, res)) + while (objectID < OCSP_RESPONSE_ROOF) + { + if (!extract_object(ocspResponseObjects, &objectID, &object, &level, &ctx)) return STATUS_INTERNALERROR; - break; - default: - DBG(DBG_CONTROL, - DBG_log("ocsp response is not of type BASIC"); - DBG_dump_chunk("ocsp response OID: ", object); - ) - return STATUS_INTERNALERROR; + + switch (objectID) { + case OCSP_RESPONSE_STATUS: + rStatus = (response_status) *object.ptr; + + switch (rStatus) + { + case STATUS_SUCCESSFUL: + break; + case STATUS_MALFORMEDREQUEST: + case STATUS_INTERNALERROR: + case STATUS_TRYLATER: + case STATUS_SIGREQUIRED: + case STATUS_UNAUTHORIZED: + plog("ocsp response: server said '%s'" + , response_status_names[rStatus]); + return rStatus; + default: + return STATUS_INTERNALERROR; + } + break; + case OCSP_RESPONSE_TYPE: + ocspResponseType = asn1_known_oid(object); + break; + case OCSP_RESPONSE: + { + switch (ocspResponseType) { + case OID_BASIC: + if (!parse_basic_ocsp_response(object, level+1, res)) + return STATUS_INTERNALERROR; + break; + default: + DBG(DBG_CONTROL, + DBG_log("ocsp response is not of type BASIC"); + DBG_dump_chunk("ocsp response OID: ", object); + ) + return STATUS_INTERNALERROR; + } + } + break; } - } - break; + objectID++; } - objectID++; - } - return rStatus; + return rStatus; } /* @@ -1255,69 +1255,69 @@ parse_ocsp_response(chunk_t blob, response_t * res) static bool parse_ocsp_single_response(chunk_t blob, int level0, single_response_t *sres) { - u_int level, extn_oid; - asn1_ctx_t ctx; - bool critical; - chunk_t object; - int objectID = 0; + u_int level, extn_oid; + asn1_ctx_t ctx; + bool critical; + chunk_t object; + int objectID = 0; - asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); + asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); - while (objectID < SINGLE_RESPONSE_ROOF) - { - if (!extract_object(singleResponseObjects, &objectID, &object, &level, &ctx)) - return FALSE; - - switch (objectID) + while (objectID < SINGLE_RESPONSE_ROOF) { - case SINGLE_RESPONSE_ALGORITHM: - sres->hash_algorithm = parse_algorithmIdentifier(object, level+1, NULL); - break; - case SINGLE_RESPONSE_ISSUER_NAME_HASH: - sres->issuer_name_hash = object; - break; - case SINGLE_RESPONSE_ISSUER_KEY_HASH: - sres->issuer_key_hash = object; - break; - case SINGLE_RESPONSE_SERIAL_NUMBER: - sres->serialNumber = object; - break; - case SINGLE_RESPONSE_CERT_STATUS_GOOD: - sres->status = CERT_GOOD; - break; - case SINGLE_RESPONSE_CERT_STATUS_REVOKED: - sres->status = CERT_REVOKED; - break; - case SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME: - sres->revocationTime = asn1totime(&object, ASN1_GENERALIZEDTIME); - break; - case SINGLE_RESPONSE_CERT_STATUS_CRL_REASON: - sres->revocationReason = (object.len == 1) - ? *object.ptr : REASON_UNSPECIFIED; - break; - case SINGLE_RESPONSE_CERT_STATUS_UNKNOWN: - sres->status = CERT_UNKNOWN; - break; - case SINGLE_RESPONSE_THIS_UPDATE: - sres->thisUpdate = asn1totime(&object, ASN1_GENERALIZEDTIME); - break; - case SINGLE_RESPONSE_NEXT_UPDATE: - sres->nextUpdate = asn1totime(&object, ASN1_GENERALIZEDTIME); - break; - case SINGLE_RESPONSE_EXT_ID: - extn_oid = asn1_known_oid(object); - break; - case SINGLE_RESPONSE_CRITICAL: - critical = object.len && *object.ptr; - DBG(DBG_PARSING, - DBG_log(" %s",(critical)?"TRUE":"FALSE"); - ) - case SINGLE_RESPONSE_EXT_VALUE: - break; + if (!extract_object(singleResponseObjects, &objectID, &object, &level, &ctx)) + return FALSE; + + switch (objectID) + { + case SINGLE_RESPONSE_ALGORITHM: + sres->hash_algorithm = parse_algorithmIdentifier(object, level+1, NULL); + break; + case SINGLE_RESPONSE_ISSUER_NAME_HASH: + sres->issuer_name_hash = object; + break; + case SINGLE_RESPONSE_ISSUER_KEY_HASH: + sres->issuer_key_hash = object; + break; + case SINGLE_RESPONSE_SERIAL_NUMBER: + sres->serialNumber = object; + break; + case SINGLE_RESPONSE_CERT_STATUS_GOOD: + sres->status = CERT_GOOD; + break; + case SINGLE_RESPONSE_CERT_STATUS_REVOKED: + sres->status = CERT_REVOKED; + break; + case SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME: + sres->revocationTime = asn1totime(&object, ASN1_GENERALIZEDTIME); + break; + case SINGLE_RESPONSE_CERT_STATUS_CRL_REASON: + sres->revocationReason = (object.len == 1) + ? *object.ptr : REASON_UNSPECIFIED; + break; + case SINGLE_RESPONSE_CERT_STATUS_UNKNOWN: + sres->status = CERT_UNKNOWN; + break; + case SINGLE_RESPONSE_THIS_UPDATE: + sres->thisUpdate = asn1totime(&object, ASN1_GENERALIZEDTIME); + break; + case SINGLE_RESPONSE_NEXT_UPDATE: + sres->nextUpdate = asn1totime(&object, ASN1_GENERALIZEDTIME); + break; + case SINGLE_RESPONSE_EXT_ID: + extn_oid = asn1_known_oid(object); + break; + case SINGLE_RESPONSE_CRITICAL: + critical = object.len && *object.ptr; + DBG(DBG_PARSING, + DBG_log(" %s",(critical)?"TRUE":"FALSE"); + ) + case SINGLE_RESPONSE_EXT_VALUE: + break; + } + objectID++; } - objectID++; - } - return TRUE; + return TRUE; } /* @@ -1326,25 +1326,25 @@ parse_ocsp_single_response(chunk_t blob, int level0, single_response_t *sres) ocsp_location_t* add_ocsp_location(const ocsp_location_t *loc, ocsp_location_t **chain) { - ocsp_location_t *location = malloc_thing(ocsp_location_t); + ocsp_location_t *location = malloc_thing(ocsp_location_t); - /* unshare location fields */ - location->issuer = chunk_clone(loc->issuer); - location->authNameID = chunk_clone(loc->authNameID); - location->authKeyID = chunk_clone(loc->authKeyID); - location->authKeySerialNumber = chunk_clone(loc->authKeySerialNumber); - location->uri = chunk_clone(loc->uri); - location->certinfo = NULL; + /* unshare location fields */ + location->issuer = chunk_clone(loc->issuer); + location->authNameID = chunk_clone(loc->authNameID); + location->authKeyID = chunk_clone(loc->authKeyID); + location->authKeySerialNumber = chunk_clone(loc->authKeySerialNumber); + location->uri = chunk_clone(loc->uri); + location->certinfo = NULL; - /* insert new ocsp location in front of chain */ - location->next = *chain; - *chain = location; + /* insert new ocsp location in front of chain */ + location->next = *chain; + *chain = location; - DBG(DBG_CONTROL, - DBG_log("new ocsp location added") - ) + DBG(DBG_CONTROL, + DBG_log("new ocsp location added") + ) - return location; + return location; } /* @@ -1352,76 +1352,76 @@ add_ocsp_location(const ocsp_location_t *loc, ocsp_location_t **chain) */ void add_certinfo(ocsp_location_t *loc, ocsp_certinfo_t *info, ocsp_location_t **chain - , bool request) + , bool request) { - ocsp_location_t *location; - ocsp_certinfo_t *certinfo, **certinfop; - char buf[BUF_LEN]; - time_t now; - int cmp = -1; + ocsp_location_t *location; + ocsp_certinfo_t *certinfo, **certinfop; + char buf[BUF_LEN]; + time_t now; + int cmp = -1; - location = get_ocsp_location(loc, *chain); - if (location == NULL) - location = add_ocsp_location(loc, chain); + location = get_ocsp_location(loc, *chain); + if (location == NULL) + location = add_ocsp_location(loc, chain); - /* traverse list of certinfos in increasing order */ - certinfop = &location->certinfo; - certinfo = *certinfop; - - while (certinfo != NULL) - { - cmp = chunk_compare(info->serialNumber, certinfo->serialNumber); - if (cmp <= 0) - break; - certinfop = &certinfo->next; + /* traverse list of certinfos in increasing order */ + certinfop = &location->certinfo; certinfo = *certinfop; - } - if (cmp != 0) - { - /* add a new certinfo entry */ - ocsp_certinfo_t *cnew = malloc_thing(ocsp_certinfo_t); + while (certinfo != NULL) + { + cmp = chunk_compare(info->serialNumber, certinfo->serialNumber); + if (cmp <= 0) + break; + certinfop = &certinfo->next; + certinfo = *certinfop; + } - cnew->serialNumber = chunk_clone(info->serialNumber); - cnew->next = certinfo; - *certinfop = cnew; - certinfo = cnew; - } - - DBG(DBG_CONTROL, - datatot(info->serialNumber.ptr, info->serialNumber.len, ':' - , buf, BUF_LEN); - DBG_log("ocsp %s for serial %s %s" - , request?"fetch request":"certinfo" - , buf - , (cmp == 0)? (request?"already exists":"updated"):"added") - ) - - time(&now); - - if (request) - { - certinfo->status = CERT_UNDEFINED; - if (cmp != 0) - certinfo->thisUpdate = now; + { + /* add a new certinfo entry */ + ocsp_certinfo_t *cnew = malloc_thing(ocsp_certinfo_t); - certinfo->nextUpdate = UNDEFINED_TIME; - } - else - { - certinfo->status = info->status; - certinfo->revocationTime = info->revocationTime; - certinfo->revocationReason = info->revocationReason; - - certinfo->thisUpdate = (info->thisUpdate != UNDEFINED_TIME)? - info->thisUpdate : now; + cnew->serialNumber = chunk_clone(info->serialNumber); + cnew->next = certinfo; + *certinfop = cnew; + certinfo = cnew; + } + + DBG(DBG_CONTROL, + datatot(info->serialNumber.ptr, info->serialNumber.len, ':' + , buf, BUF_LEN); + DBG_log("ocsp %s for serial %s %s" + , request?"fetch request":"certinfo" + , buf + , (cmp == 0)? (request?"already exists":"updated"):"added") + ) - certinfo->once = (info->nextUpdate == UNDEFINED_TIME); + time(&now); - certinfo->nextUpdate = (certinfo->once)? - (now + OCSP_DEFAULT_VALID_TIME) : info->nextUpdate; - } + if (request) + { + certinfo->status = CERT_UNDEFINED; + + if (cmp != 0) + certinfo->thisUpdate = now; + + certinfo->nextUpdate = UNDEFINED_TIME; + } + else + { + certinfo->status = info->status; + certinfo->revocationTime = info->revocationTime; + certinfo->revocationReason = info->revocationReason; + + certinfo->thisUpdate = (info->thisUpdate != UNDEFINED_TIME)? + info->thisUpdate : now; + + certinfo->once = (info->nextUpdate == UNDEFINED_TIME); + + certinfo->nextUpdate = (certinfo->once)? + (now + OCSP_DEFAULT_VALID_TIME) : info->nextUpdate; + } } /* @@ -1430,57 +1430,57 @@ add_certinfo(ocsp_location_t *loc, ocsp_certinfo_t *info, ocsp_location_t **chai static void process_single_response(ocsp_location_t *location, single_response_t *sres) { - ocsp_certinfo_t *certinfo, **certinfop; - int cmp = -1; + ocsp_certinfo_t *certinfo, **certinfop; + int cmp = -1; - if (sres->hash_algorithm != OID_SHA1) - { - plog("only SHA-1 hash supported in OCSP single response"); - return; - } - if (!(chunk_equals(sres->issuer_name_hash, location->authNameID) - && chunk_equals(sres->issuer_key_hash, location->authKeyID))) - { - plog("ocsp single response has wrong issuer"); - return; - } - - /* traverse list of certinfos in increasing order */ - certinfop = &location->certinfo; - certinfo = *certinfop; - - while (certinfo != NULL) - { - cmp = chunk_compare(sres->serialNumber, certinfo->serialNumber); - if (cmp <= 0) - break; - certinfop = &certinfo->next; + if (sres->hash_algorithm != OID_SHA1) + { + plog("only SHA-1 hash supported in OCSP single response"); + return; + } + if (!(chunk_equals(sres->issuer_name_hash, location->authNameID) + && chunk_equals(sres->issuer_key_hash, location->authKeyID))) + { + plog("ocsp single response has wrong issuer"); + return; + } + + /* traverse list of certinfos in increasing order */ + certinfop = &location->certinfo; certinfo = *certinfop; - } - if (cmp != 0) - { - plog("received unrequested cert status from ocsp server"); - return; - } + while (certinfo != NULL) + { + cmp = chunk_compare(sres->serialNumber, certinfo->serialNumber); + if (cmp <= 0) + break; + certinfop = &certinfo->next; + certinfo = *certinfop; + } - /* unlink cert from ocsp fetch request list */ - *certinfop = certinfo->next; - - /* update certinfo using the single response information */ - certinfo->thisUpdate = sres->thisUpdate; - certinfo->nextUpdate = sres->nextUpdate; - certinfo->status = sres->status; - certinfo->revocationTime = sres->revocationTime; - certinfo->revocationReason = sres->revocationReason; - - /* add or update certinfo in ocsp cache */ - lock_ocsp_cache("process_single_response"); - add_certinfo(location, certinfo, &ocsp_cache, FALSE); - unlock_ocsp_cache("process_single_response"); + if (cmp != 0) + { + plog("received unrequested cert status from ocsp server"); + return; + } - /* free certinfo unlinked from ocsp fetch request list */ - free_certinfo(certinfo); + /* unlink cert from ocsp fetch request list */ + *certinfop = certinfo->next; + + /* update certinfo using the single response information */ + certinfo->thisUpdate = sres->thisUpdate; + certinfo->nextUpdate = sres->nextUpdate; + certinfo->status = sres->status; + certinfo->revocationTime = sres->revocationTime; + certinfo->revocationReason = sres->revocationReason; + + /* add or update certinfo in ocsp cache */ + lock_ocsp_cache("process_single_response"); + add_certinfo(location, certinfo, &ocsp_cache, FALSE); + unlock_ocsp_cache("process_single_response"); + + /* free certinfo unlinked from ocsp fetch request list */ + free_certinfo(certinfo); } @@ -1490,61 +1490,61 @@ process_single_response(ocsp_location_t *location, single_response_t *sres) void parse_ocsp(ocsp_location_t *location, chunk_t blob) { - response_t res = empty_response; + response_t res = empty_response; - /* parse the ocsp response without looking at the single responses yet */ - response_status status = parse_ocsp_response(blob, &res); + /* parse the ocsp response without looking at the single responses yet */ + response_status status = parse_ocsp_response(blob, &res); - if (status != STATUS_SUCCESSFUL) - { - plog("error in ocsp response"); - return; - } - /* check if there was a nonce in the request */ - if (location->nonce.ptr != NULL && res.nonce.ptr == NULL) - { - plog("ocsp response contains no nonce, replay attack possible"); - } - /* check if the nonce is identical */ - if (res.nonce.ptr != NULL && !chunk_equals(res.nonce, location->nonce)) - { - plog("invalid nonce in ocsp response"); - return; - } - /* check if the response is signed by a trusted key */ - if (!valid_ocsp_response(&res)) - { - plog("invalid ocsp response"); - return; - } - DBG(DBG_CONTROL, - DBG_log("valid ocsp response") - ) - - /* now parse the single responses one at a time */ - { - u_int level; - asn1_ctx_t ctx; - chunk_t object; - int objectID = 0; - - asn1_init(&ctx, res.responses, 0, FALSE, DBG_RAW); - - while (objectID < RESPONSES_ROOF) + if (status != STATUS_SUCCESSFUL) { - if (!extract_object(responsesObjects, &objectID, &object, &level, &ctx)) + plog("error in ocsp response"); return; - - if (objectID == RESPONSES_SINGLE_RESPONSE) - { - single_response_t sres = empty_single_response; - - if (parse_ocsp_single_response(object, level+1, &sres)) - { - process_single_response(location, &sres); - } - } - objectID++; } - } + /* check if there was a nonce in the request */ + if (location->nonce.ptr != NULL && res.nonce.ptr == NULL) + { + plog("ocsp response contains no nonce, replay attack possible"); + } + /* check if the nonce is identical */ + if (res.nonce.ptr != NULL && !chunk_equals(res.nonce, location->nonce)) + { + plog("invalid nonce in ocsp response"); + return; + } + /* check if the response is signed by a trusted key */ + if (!valid_ocsp_response(&res)) + { + plog("invalid ocsp response"); + return; + } + DBG(DBG_CONTROL, + DBG_log("valid ocsp response") + ) + + /* now parse the single responses one at a time */ + { + u_int level; + asn1_ctx_t ctx; + chunk_t object; + int objectID = 0; + + asn1_init(&ctx, res.responses, 0, FALSE, DBG_RAW); + + while (objectID < RESPONSES_ROOF) + { + if (!extract_object(responsesObjects, &objectID, &object, &level, &ctx)) + return; + + if (objectID == RESPONSES_SINGLE_RESPONSE) + { + single_response_t sres = empty_single_response; + + if (parse_ocsp_single_response(object, level+1, &sres)) + { + process_single_response(location, &sres); + } + } + objectID++; + } + } } diff --git a/src/pluto/ocsp.h b/src/pluto/ocsp.h index 2db0d7b9c..bc189d481 100644 --- a/src/pluto/ocsp.h +++ b/src/pluto/ocsp.h @@ -19,19 +19,19 @@ /* constants */ -#define OCSP_BASIC_RESPONSE_VERSION 1 -#define OCSP_DEFAULT_VALID_TIME 120 /* validity of one-time response in seconds */ -#define OCSP_WARNING_INTERVAL 2 /* days */ +#define OCSP_BASIC_RESPONSE_VERSION 1 +#define OCSP_DEFAULT_VALID_TIME 120 /* validity of one-time response in seconds */ +#define OCSP_WARNING_INTERVAL 2 /* days */ /* OCSP response status */ typedef enum { - STATUS_SUCCESSFUL = 0, - STATUS_MALFORMEDREQUEST = 1, - STATUS_INTERNALERROR = 2, - STATUS_TRYLATER = 3, - STATUS_SIGREQUIRED = 5, - STATUS_UNAUTHORIZED= 6 + STATUS_SUCCESSFUL = 0, + STATUS_MALFORMEDREQUEST = 1, + STATUS_INTERNALERROR = 2, + STATUS_TRYLATER = 3, + STATUS_SIGREQUIRED = 5, + STATUS_UNAUTHORIZED= 6 } response_status; /* OCSP access structures */ @@ -39,46 +39,46 @@ typedef enum { typedef struct ocsp_certinfo ocsp_certinfo_t; struct ocsp_certinfo { - ocsp_certinfo_t *next; - int trials; - chunk_t serialNumber; - cert_status_t status; - bool once; - crl_reason_t revocationReason; - time_t revocationTime; - time_t thisUpdate; - time_t nextUpdate; + ocsp_certinfo_t *next; + int trials; + chunk_t serialNumber; + cert_status_t status; + bool once; + crl_reason_t revocationReason; + time_t revocationTime; + time_t thisUpdate; + time_t nextUpdate; }; typedef struct ocsp_location ocsp_location_t; struct ocsp_location { - ocsp_location_t *next; - chunk_t issuer; - chunk_t authNameID; - chunk_t authKeyID; - chunk_t authKeySerialNumber; - chunk_t uri; - chunk_t nonce; - ocsp_certinfo_t *certinfo; + ocsp_location_t *next; + chunk_t issuer; + chunk_t authNameID; + chunk_t authKeyID; + chunk_t authKeySerialNumber; + chunk_t uri; + chunk_t nonce; + ocsp_certinfo_t *certinfo; }; extern ocsp_location_t* get_ocsp_location(const ocsp_location_t *loc - , ocsp_location_t *chain); + , ocsp_location_t *chain); extern ocsp_location_t* add_ocsp_location(const ocsp_location_t *loc - , ocsp_location_t **chain); + , ocsp_location_t **chain); extern void add_certinfo(ocsp_location_t *loc, ocsp_certinfo_t *info - , ocsp_location_t **chain, bool request); + , ocsp_location_t **chain, bool request); extern void check_ocsp(void); extern cert_status_t verify_by_ocsp(const x509cert_t *cert, time_t *until - , time_t *revocationTime, crl_reason_t *revocationReason); + , time_t *revocationTime, crl_reason_t *revocationReason); extern bool ocsp_set_request_cert(char* path); extern void ocsp_set_default_uri(char* uri); extern void ocsp_cache_add_cert(const x509cert_t* cert); extern chunk_t build_ocsp_request(ocsp_location_t* location); extern void parse_ocsp(ocsp_location_t* location, chunk_t blob); extern void list_ocsp_locations(ocsp_location_t *location, bool requests - , bool utc, bool strict); + , bool utc, bool strict); extern void list_ocsp_cache(bool utc, bool strict); extern void free_ocsp_locations(ocsp_location_t **chain); extern void free_ocsp_cache(void); diff --git a/src/pluto/packet.c b/src/pluto/packet.c index 2ebccbdf4..595b2cc79 100644 --- a/src/pluto/packet.c +++ b/src/pluto/packet.c @@ -27,7 +27,7 @@ #include "defs.h" #include "log.h" #include "packet.h" -#include "whack.h" /* for RC_LOG_SERIOUS */ +#include "whack.h" /* for RC_LOG_SERIOUS */ /* ISAKMP Header: for all messages * layout from RFC 2408 "ISAKMP" section 3.1 @@ -49,15 +49,15 @@ */ static field_desc isa_fields[] = { - { ft_raw, COOKIE_SIZE, "initiator cookie", NULL }, - { ft_raw, COOKIE_SIZE, "responder cookie", NULL }, - { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, - { ft_enum, 8/BITS_PER_BYTE, "ISAKMP version", &version_names }, - { ft_enum, 8/BITS_PER_BYTE, "exchange type", &exchange_names }, - { ft_set, 8/BITS_PER_BYTE, "flags", flag_bit_names }, - { ft_raw, 32/BITS_PER_BYTE, "message ID", NULL }, - { ft_len, 32/BITS_PER_BYTE, "length", NULL }, - { ft_end, 0, NULL, NULL } + { ft_raw, COOKIE_SIZE, "initiator cookie", NULL }, + { ft_raw, COOKIE_SIZE, "responder cookie", NULL }, + { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, + { ft_enum, 8/BITS_PER_BYTE, "ISAKMP version", &version_names }, + { ft_enum, 8/BITS_PER_BYTE, "exchange type", &exchange_names }, + { ft_set, 8/BITS_PER_BYTE, "flags", flag_bit_names }, + { ft_raw, 32/BITS_PER_BYTE, "message ID", NULL }, + { ft_len, 32/BITS_PER_BYTE, "length", NULL }, + { ft_end, 0, NULL, NULL } }; struct_desc isakmp_hdr_desc = { "ISAKMP Message", isa_fields, sizeof(struct isakmp_hdr) }; @@ -74,10 +74,10 @@ struct_desc isakmp_hdr_desc = { "ISAKMP Message", isa_fields, sizeof(struct isak */ static field_desc isag_fields[] = { - { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, - { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, - { ft_len, 16/BITS_PER_BYTE, "length", NULL }, - { ft_end, 0, NULL, NULL } + { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, + { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, + { ft_len, 16/BITS_PER_BYTE, "length", NULL }, + { ft_end, 0, NULL, NULL } }; struct_desc isakmp_generic_desc = { "ISAKMP Generic Payload", isag_fields, sizeof(struct isakmp_generic) }; @@ -100,36 +100,36 @@ struct_desc isakmp_generic_desc = { "ISAKMP Generic Payload", isag_fields, sizeo /* Oakley Attributes */ static field_desc isaat_fields_oakley[] = { - { ft_af_enum, 16/BITS_PER_BYTE, "af+type", &oakley_attr_names }, - { ft_lv, 16/BITS_PER_BYTE, "length/value", NULL }, - { ft_end, 0, NULL, NULL } + { ft_af_enum, 16/BITS_PER_BYTE, "af+type", &oakley_attr_names }, + { ft_lv, 16/BITS_PER_BYTE, "length/value", NULL }, + { ft_end, 0, NULL, NULL } }; struct_desc isakmp_oakley_attribute_desc = { - "ISAKMP Oakley attribute", - isaat_fields_oakley, sizeof(struct isakmp_attribute) }; + "ISAKMP Oakley attribute", + isaat_fields_oakley, sizeof(struct isakmp_attribute) }; /* IPsec DOI Attributes */ static field_desc isaat_fields_ipsec[] = { - { ft_af_enum, 16/BITS_PER_BYTE, "af+type", &ipsec_attr_names }, - { ft_lv, 16/BITS_PER_BYTE, "length/value", NULL }, - { ft_end, 0, NULL, NULL } + { ft_af_enum, 16/BITS_PER_BYTE, "af+type", &ipsec_attr_names }, + { ft_lv, 16/BITS_PER_BYTE, "length/value", NULL }, + { ft_end, 0, NULL, NULL } }; struct_desc isakmp_ipsec_attribute_desc = { - "ISAKMP IPsec DOI attribute", - isaat_fields_ipsec, sizeof(struct isakmp_attribute) }; + "ISAKMP IPsec DOI attribute", + isaat_fields_ipsec, sizeof(struct isakmp_attribute) }; /* Mode Config Attributes */ static field_desc isaat_fields_modecfg[] = { - { ft_af_loose_enum, 16/BITS_PER_BYTE, "ModeCfg attr type", &modecfg_attr_names }, - { ft_lv, 16/BITS_PER_BYTE, "length/value", NULL }, - { ft_end, 0, NULL, NULL } + { ft_af_loose_enum, 16/BITS_PER_BYTE, "ModeCfg attr type", &modecfg_attr_names }, + { ft_lv, 16/BITS_PER_BYTE, "length/value", NULL }, + { ft_end, 0, NULL, NULL } }; struct_desc isakmp_modecfg_attribute_desc = { - "ISAKMP ModeCfg attribute", - isaat_fields_modecfg, sizeof(struct isakmp_attribute) }; + "ISAKMP ModeCfg attribute", + isaat_fields_modecfg, sizeof(struct isakmp_attribute) }; /* ISAKMP Security Association Payload * layout from RFC 2408 "ISAKMP" section 3.4 @@ -148,18 +148,18 @@ struct_desc isakmp_modecfg_attribute_desc = { * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ static field_desc isasa_fields[] = { - { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, - { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, - { ft_len, 16/BITS_PER_BYTE, "length", NULL }, - { ft_enum, 32/BITS_PER_BYTE, "DOI", &doi_names }, - { ft_end, 0, NULL, NULL } + { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, + { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, + { ft_len, 16/BITS_PER_BYTE, "length", NULL }, + { ft_enum, 32/BITS_PER_BYTE, "DOI", &doi_names }, + { ft_end, 0, NULL, NULL } }; struct_desc isakmp_sa_desc = { "ISAKMP Security Association Payload", isasa_fields, sizeof(struct isakmp_sa) }; static field_desc ipsec_sit_field[] = { - { ft_set, 32/BITS_PER_BYTE, "IPsec DOI SIT", &sit_bit_names }, - { ft_end, 0, NULL, NULL } + { ft_set, 32/BITS_PER_BYTE, "IPsec DOI SIT", &sit_bit_names }, + { ft_end, 0, NULL, NULL } }; struct_desc ipsec_sit_desc = { "IPsec DOI SIT", ipsec_sit_field, sizeof(u_int32_t) }; @@ -179,14 +179,14 @@ struct_desc ipsec_sit_desc = { "IPsec DOI SIT", ipsec_sit_field, sizeof(u_int32_ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ static field_desc isap_fields[] = { - { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, - { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, - { ft_len, 16/BITS_PER_BYTE, "length", NULL }, - { ft_nat, 8/BITS_PER_BYTE, "proposal number", NULL }, - { ft_enum, 8/BITS_PER_BYTE, "protocol ID", &protocol_names }, - { ft_nat, 8/BITS_PER_BYTE, "SPI size", NULL }, - { ft_nat, 8/BITS_PER_BYTE, "number of transforms", NULL }, - { ft_end, 0, NULL, NULL } + { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, + { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, + { ft_len, 16/BITS_PER_BYTE, "length", NULL }, + { ft_nat, 8/BITS_PER_BYTE, "proposal number", NULL }, + { ft_enum, 8/BITS_PER_BYTE, "protocol ID", &protocol_names }, + { ft_nat, 8/BITS_PER_BYTE, "SPI size", NULL }, + { ft_nat, 8/BITS_PER_BYTE, "number of transforms", NULL }, + { ft_end, 0, NULL, NULL } }; struct_desc isakmp_proposal_desc = { "ISAKMP Proposal Payload", isap_fields, sizeof(struct isakmp_proposal) }; @@ -210,63 +210,63 @@ struct_desc isakmp_proposal_desc = { "ISAKMP Proposal Payload", isap_fields, siz /* PROTO_ISAKMP */ static field_desc isat_fields_isakmp[] = { - { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, - { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, - { ft_len, 16/BITS_PER_BYTE, "length", NULL }, - { ft_nat, 8/BITS_PER_BYTE, "transform number", NULL }, - { ft_enum, 8/BITS_PER_BYTE, "transform ID", &isakmp_transformid_names }, - { ft_mbz, 16/BITS_PER_BYTE, NULL, NULL }, - { ft_end, 0, NULL, NULL } + { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, + { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, + { ft_len, 16/BITS_PER_BYTE, "length", NULL }, + { ft_nat, 8/BITS_PER_BYTE, "transform number", NULL }, + { ft_enum, 8/BITS_PER_BYTE, "transform ID", &isakmp_transformid_names }, + { ft_mbz, 16/BITS_PER_BYTE, NULL, NULL }, + { ft_end, 0, NULL, NULL } }; struct_desc isakmp_isakmp_transform_desc = { - "ISAKMP Transform Payload (ISAKMP)", - isat_fields_isakmp, sizeof(struct isakmp_transform) }; + "ISAKMP Transform Payload (ISAKMP)", + isat_fields_isakmp, sizeof(struct isakmp_transform) }; /* PROTO_IPSEC_AH */ static field_desc isat_fields_ah[] = { - { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, - { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, - { ft_len, 16/BITS_PER_BYTE, "length", NULL }, - { ft_nat, 8/BITS_PER_BYTE, "transform number", NULL }, - { ft_enum, 8/BITS_PER_BYTE, "transform ID", &ah_transformid_names }, - { ft_mbz, 16/BITS_PER_BYTE, NULL, NULL }, - { ft_end, 0, NULL, NULL } + { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, + { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, + { ft_len, 16/BITS_PER_BYTE, "length", NULL }, + { ft_nat, 8/BITS_PER_BYTE, "transform number", NULL }, + { ft_enum, 8/BITS_PER_BYTE, "transform ID", &ah_transformid_names }, + { ft_mbz, 16/BITS_PER_BYTE, NULL, NULL }, + { ft_end, 0, NULL, NULL } }; struct_desc isakmp_ah_transform_desc = { - "ISAKMP Transform Payload (AH)", - isat_fields_ah, sizeof(struct isakmp_transform) }; + "ISAKMP Transform Payload (AH)", + isat_fields_ah, sizeof(struct isakmp_transform) }; /* PROTO_IPSEC_ESP */ static field_desc isat_fields_esp[] = { - { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, - { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, - { ft_len, 16/BITS_PER_BYTE, "length", NULL }, - { ft_nat, 8/BITS_PER_BYTE, "transform number", NULL }, - { ft_enum, 8/BITS_PER_BYTE, "transform ID", &esp_transformid_names }, - { ft_mbz, 16/BITS_PER_BYTE, NULL, NULL }, - { ft_end, 0, NULL, NULL } + { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, + { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, + { ft_len, 16/BITS_PER_BYTE, "length", NULL }, + { ft_nat, 8/BITS_PER_BYTE, "transform number", NULL }, + { ft_enum, 8/BITS_PER_BYTE, "transform ID", &esp_transformid_names }, + { ft_mbz, 16/BITS_PER_BYTE, NULL, NULL }, + { ft_end, 0, NULL, NULL } }; struct_desc isakmp_esp_transform_desc = { - "ISAKMP Transform Payload (ESP)", - isat_fields_esp, sizeof(struct isakmp_transform) }; + "ISAKMP Transform Payload (ESP)", + isat_fields_esp, sizeof(struct isakmp_transform) }; /* PROTO_IPCOMP */ static field_desc isat_fields_ipcomp[] = { - { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, - { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, - { ft_len, 16/BITS_PER_BYTE, "length", NULL }, - { ft_nat, 8/BITS_PER_BYTE, "transform number", NULL }, - { ft_enum, 8/BITS_PER_BYTE, "transform ID", &ipcomp_transformid_names }, - { ft_mbz, 16/BITS_PER_BYTE, NULL, NULL }, - { ft_end, 0, NULL, NULL } + { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, + { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, + { ft_len, 16/BITS_PER_BYTE, "length", NULL }, + { ft_nat, 8/BITS_PER_BYTE, "transform number", NULL }, + { ft_enum, 8/BITS_PER_BYTE, "transform ID", &ipcomp_transformid_names }, + { ft_mbz, 16/BITS_PER_BYTE, NULL, NULL }, + { ft_end, 0, NULL, NULL } }; struct_desc isakmp_ipcomp_transform_desc = { - "ISAKMP Transform Payload (COMP)", - isat_fields_ipcomp, sizeof(struct isakmp_transform) }; + "ISAKMP Transform Payload (COMP)", + isat_fields_ipcomp, sizeof(struct isakmp_transform) }; /* ISAKMP Key Exchange Payload: no fixed fields beyond the generic ones. @@ -303,13 +303,13 @@ struct_desc isakmp_keyex_desc = { "ISAKMP Key Exchange Payload", isag_fields, si * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ static field_desc isaid_fields[] = { - { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, - { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, - { ft_len, 16/BITS_PER_BYTE, "length", NULL }, - { ft_enum, 8/BITS_PER_BYTE, "ID type", &ident_names }, /* ??? depends on DOI? */ - { ft_nat, 8/BITS_PER_BYTE, "DOI specific A", NULL }, /* ??? depends on DOI? */ - { ft_nat, 16/BITS_PER_BYTE, "DOI specific B", NULL }, /* ??? depends on DOI? */ - { ft_end, 0, NULL, NULL } + { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, + { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, + { ft_len, 16/BITS_PER_BYTE, "length", NULL }, + { ft_enum, 8/BITS_PER_BYTE, "ID type", &ident_names }, /* ??? depends on DOI? */ + { ft_nat, 8/BITS_PER_BYTE, "DOI specific A", NULL }, /* ??? depends on DOI? */ + { ft_nat, 16/BITS_PER_BYTE, "DOI specific B", NULL }, /* ??? depends on DOI? */ + { ft_end, 0, NULL, NULL } }; struct_desc isakmp_identification_desc = { "ISAKMP Identification Payload", isaid_fields, sizeof(struct isakmp_id) }; @@ -330,13 +330,13 @@ struct_desc isakmp_identification_desc = { "ISAKMP Identification Payload", isai * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ static field_desc isaiid_fields[] = { - { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, - { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, - { ft_len, 16/BITS_PER_BYTE, "length", NULL }, - { ft_enum, 8/BITS_PER_BYTE, "ID type", &ident_names }, - { ft_nat, 8/BITS_PER_BYTE, "Protocol ID", NULL }, /* ??? UDP/TCP or 0? */ - { ft_nat, 16/BITS_PER_BYTE, "port", NULL }, - { ft_end, 0, NULL, NULL } + { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, + { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, + { ft_len, 16/BITS_PER_BYTE, "length", NULL }, + { ft_enum, 8/BITS_PER_BYTE, "ID type", &ident_names }, + { ft_nat, 8/BITS_PER_BYTE, "Protocol ID", NULL }, /* ??? UDP/TCP or 0? */ + { ft_nat, 16/BITS_PER_BYTE, "port", NULL }, + { ft_end, 0, NULL, NULL } }; struct_desc isakmp_ipsec_identification_desc = { "ISAKMP Identification Payload (IPsec DOI)", isaiid_fields, sizeof(struct isakmp_ipsec_id) }; @@ -357,11 +357,11 @@ struct_desc isakmp_ipsec_identification_desc = { "ISAKMP Identification Payload * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ static field_desc isacert_fields[] = { - { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, - { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, - { ft_len, 16/BITS_PER_BYTE, "length", NULL }, - { ft_enum, 8/BITS_PER_BYTE, "cert encoding", &cert_type_names }, - { ft_end, 0, NULL, NULL } + { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, + { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, + { ft_len, 16/BITS_PER_BYTE, "length", NULL }, + { ft_enum, 8/BITS_PER_BYTE, "cert encoding", &cert_type_names }, + { ft_end, 0, NULL, NULL } }; /* Note: the size field of isakmp_ipsec_certificate_desc cannot be @@ -385,11 +385,11 @@ static field_desc isacert_fields[] = { * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ static field_desc isacr_fields[] = { - { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, - { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, - { ft_len, 16/BITS_PER_BYTE, "length", NULL }, - { ft_enum, 8/BITS_PER_BYTE, "cert type", &cert_type_names }, - { ft_end, 0, NULL, NULL } + { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, + { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, + { ft_len, 16/BITS_PER_BYTE, "length", NULL }, + { ft_enum, 8/BITS_PER_BYTE, "cert type", &cert_type_names }, + { ft_end, 0, NULL, NULL } }; /* Note: the size field of isakmp_ipsec_cert_req_desc cannot be @@ -469,14 +469,14 @@ struct_desc isakmp_nonce_desc = { "ISAKMP Nonce Payload", isag_fields, sizeof(st * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ static field_desc isan_fields[] = { - { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, - { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, - { ft_len, 16/BITS_PER_BYTE, "length", NULL }, - { ft_enum, 32/BITS_PER_BYTE, "DOI", &doi_names }, - { ft_nat, 8/BITS_PER_BYTE, "protocol ID", NULL }, /* ??? really enum: ISAKMP, IPSEC, ESP, ... */ - { ft_nat, 8/BITS_PER_BYTE, "SPI size", NULL }, - { ft_enum, 16/BITS_PER_BYTE, "Notify Message Type", ¬ification_names }, - { ft_end, 0, NULL, NULL } + { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, + { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, + { ft_len, 16/BITS_PER_BYTE, "length", NULL }, + { ft_enum, 32/BITS_PER_BYTE, "DOI", &doi_names }, + { ft_nat, 8/BITS_PER_BYTE, "protocol ID", NULL }, /* ??? really enum: ISAKMP, IPSEC, ESP, ... */ + { ft_nat, 8/BITS_PER_BYTE, "SPI size", NULL }, + { ft_enum, 16/BITS_PER_BYTE, "Notify Message Type", ¬ification_names }, + { ft_end, 0, NULL, NULL } }; struct_desc isakmp_notification_desc = { "ISAKMP Notification Payload", isan_fields, sizeof(struct isakmp_notification) }; @@ -500,14 +500,14 @@ struct_desc isakmp_notification_desc = { "ISAKMP Notification Payload", isan_fie * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ static field_desc isad_fields[] = { - { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, - { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, - { ft_len, 16/BITS_PER_BYTE, "length", NULL }, - { ft_enum, 32/BITS_PER_BYTE, "DOI", &doi_names }, - { ft_nat, 8/BITS_PER_BYTE, "protocol ID", NULL }, /* ??? really enum: ISAKMP, IPSEC */ - { ft_nat, 8/BITS_PER_BYTE, "SPI size", NULL }, - { ft_nat, 16/BITS_PER_BYTE, "number of SPIs", NULL }, - { ft_end, 0, NULL, NULL } + { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, + { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, + { ft_len, 16/BITS_PER_BYTE, "length", NULL }, + { ft_enum, 32/BITS_PER_BYTE, "DOI", &doi_names }, + { ft_nat, 8/BITS_PER_BYTE, "protocol ID", NULL }, /* ??? really enum: ISAKMP, IPSEC */ + { ft_nat, 8/BITS_PER_BYTE, "SPI size", NULL }, + { ft_nat, 16/BITS_PER_BYTE, "number of SPIs", NULL }, + { ft_end, 0, NULL, NULL } }; struct_desc isakmp_delete_desc = { "ISAKMP Delete Payload", isad_fields, sizeof(struct isakmp_delete) }; @@ -532,26 +532,26 @@ struct_desc isakmp_vendor_id_desc = { "ISAKMP Vendor ID Payload", isag_fields, s /* * From draft-dukes-ike-mode-cfg 3.2. Attribute Payload - 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Next Payload ! RESERVED ! Payload Length ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Type ! RESERVED ! Identifier ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! ! - ~ Attributes ~ - ! ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Next Payload ! RESERVED ! Payload Length ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Type ! RESERVED ! Identifier ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! ! + ~ Attributes ~ + ! ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ static field_desc isaattr_fields[] = { - { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, - { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, - { ft_len, 16/BITS_PER_BYTE, "length", NULL }, - { ft_enum, 8/BITS_PER_BYTE, "Attr Msg Type", &attr_msg_type_names }, - { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, - { ft_nat, 16/BITS_PER_BYTE, "Identifier", NULL }, - { ft_end, 0, NULL, NULL } + { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, + { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, + { ft_len, 16/BITS_PER_BYTE, "length", NULL }, + { ft_enum, 8/BITS_PER_BYTE, "Attr Msg Type", &attr_msg_type_names }, + { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, + { ft_nat, 16/BITS_PER_BYTE, "Identifier", NULL }, + { ft_end, 0, NULL, NULL } }; struct_desc isakmp_attr_desc = { "ISAKMP Mode Attribute", isaattr_fields, sizeof(struct isakmp_mode_attr) }; @@ -581,12 +581,12 @@ struct_desc isakmp_nat_d = { "ISAKMP NAT-D Payload", isag_fields, sizeof(struct * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ static field_desc isanat_oa_fields[] = { - { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, - { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, - { ft_len, 16/BITS_PER_BYTE, "length", NULL }, - { ft_enum, 8/BITS_PER_BYTE, "ID type", &ident_names }, - { ft_mbz, 24/BITS_PER_BYTE, NULL, NULL }, - { ft_end, 0, NULL, NULL } + { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names }, + { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL }, + { ft_len, 16/BITS_PER_BYTE, "length", NULL }, + { ft_enum, 8/BITS_PER_BYTE, "ID type", &ident_names }, + { ft_mbz, 24/BITS_PER_BYTE, NULL, NULL }, + { ft_end, 0, NULL, NULL } }; struct_desc isakmp_nat_oa = { "ISAKMP NAT-OA Payload", isanat_oa_fields, sizeof(struct isakmp_nat_oa) }; @@ -600,40 +600,40 @@ struct_desc isakmp_nat_oa = { "ISAKMP NAT-OA Payload", isanat_oa_fields, sizeof( * We make all these entries NULL */ struct_desc *const payload_descs[ISAKMP_NEXT_ROOF] = { - NULL, /* 0 ISAKMP_NEXT_NONE (No other payload following) */ - &isakmp_sa_desc, /* 1 ISAKMP_NEXT_SA (Security Association) */ - NULL, /* 2 ISAKMP_NEXT_P (Proposal) */ - NULL, /* 3 ISAKMP_NEXT_T (Transform) */ - &isakmp_keyex_desc, /* 4 ISAKMP_NEXT_KE (Key Exchange) */ - NULL, /* 5 ISAKMP_NEXT_ID (Identification) */ - &isakmp_ipsec_certificate_desc, /* 6 ISAKMP_NEXT_CERT (Certificate) */ - &isakmp_ipsec_cert_req_desc, /* 7 ISAKMP_NEXT_CR (Certificate Request) */ - &isakmp_hash_desc, /* 8 ISAKMP_NEXT_HASH (Hash) */ - &isakmp_signature_desc, /* 9 ISAKMP_NEXT_SIG (Signature) */ - &isakmp_nonce_desc, /* 10 ISAKMP_NEXT_NONCE (Nonce) */ - &isakmp_notification_desc, /* 11 ISAKMP_NEXT_N (Notification) */ - &isakmp_delete_desc, /* 12 ISAKMP_NEXT_D (Delete) */ - &isakmp_vendor_id_desc, /* 13 ISAKMP_NEXT_VID (Vendor ID) */ - &isakmp_attr_desc, /* 14 ISAKMP_NEXT_ATTR (Mode Config) */ - NULL, /* 15 */ - NULL, /* 16 */ - NULL, /* 17 */ - NULL, /* 18 */ - NULL, /* 19 */ - &isakmp_nat_d, /* 20=130 ISAKMP_NEXT_NATD (NAT-D) */ - &isakmp_nat_oa, /* 20=131 ISAKMP_NEXT_NATOA (NAT-OA) */ + NULL, /* 0 ISAKMP_NEXT_NONE (No other payload following) */ + &isakmp_sa_desc, /* 1 ISAKMP_NEXT_SA (Security Association) */ + NULL, /* 2 ISAKMP_NEXT_P (Proposal) */ + NULL, /* 3 ISAKMP_NEXT_T (Transform) */ + &isakmp_keyex_desc, /* 4 ISAKMP_NEXT_KE (Key Exchange) */ + NULL, /* 5 ISAKMP_NEXT_ID (Identification) */ + &isakmp_ipsec_certificate_desc, /* 6 ISAKMP_NEXT_CERT (Certificate) */ + &isakmp_ipsec_cert_req_desc, /* 7 ISAKMP_NEXT_CR (Certificate Request) */ + &isakmp_hash_desc, /* 8 ISAKMP_NEXT_HASH (Hash) */ + &isakmp_signature_desc, /* 9 ISAKMP_NEXT_SIG (Signature) */ + &isakmp_nonce_desc, /* 10 ISAKMP_NEXT_NONCE (Nonce) */ + &isakmp_notification_desc, /* 11 ISAKMP_NEXT_N (Notification) */ + &isakmp_delete_desc, /* 12 ISAKMP_NEXT_D (Delete) */ + &isakmp_vendor_id_desc, /* 13 ISAKMP_NEXT_VID (Vendor ID) */ + &isakmp_attr_desc, /* 14 ISAKMP_NEXT_ATTR (Mode Config) */ + NULL, /* 15 */ + NULL, /* 16 */ + NULL, /* 17 */ + NULL, /* 18 */ + NULL, /* 19 */ + &isakmp_nat_d, /* 20=130 ISAKMP_NEXT_NATD (NAT-D) */ + &isakmp_nat_oa, /* 20=131 ISAKMP_NEXT_NATOA (NAT-OA) */ }; void init_pbs(pb_stream *pbs, u_int8_t *start, size_t len, const char *name) { - pbs->container = NULL; - pbs->desc = NULL; - pbs->name = name; - pbs->start = pbs->cur = start; - pbs->roof = start + len; - pbs->lenfld = NULL; - pbs->lenfld_desc = NULL; + pbs->container = NULL; + pbs->desc = NULL; + pbs->name = name; + pbs->start = pbs->cur = start; + pbs->roof = start + len; + pbs->lenfld = NULL; + pbs->lenfld_desc = NULL; } #ifdef DEBUG @@ -648,85 +648,85 @@ void DBG_print_struct(const char *label, const void *struct_ptr , struct_desc *sd, bool len_meaningful) { - bool immediate = FALSE; - const u_int8_t *inp = struct_ptr; - field_desc *fp; + bool immediate = FALSE; + const u_int8_t *inp = struct_ptr; + field_desc *fp; - DBG_log("%s%s:", label, sd->name); + DBG_log("%s%s:", label, sd->name); - for (fp = sd->fields; fp->field_type != ft_end; fp++) - { - int i = fp->size; - u_int32_t n = 0; - - switch (fp->field_type) + for (fp = sd->fields; fp->field_type != ft_end; fp++) { - case ft_mbz: /* must be zero */ - inp += i; - break; - case ft_nat: /* natural number (may be 0) */ - case ft_len: /* length of this struct and any following crud */ - case ft_lv: /* length/value field of attribute */ - case ft_enum: /* value from an enumeration */ - case ft_loose_enum: /* value from an enumeration with only some names known */ - case ft_af_enum: /* Attribute Format + value from an enumeration */ - case ft_af_loose_enum: /* Attribute Format + value from an enumeration */ - case ft_set: /* bits representing set */ - switch (i) - { - case 8/BITS_PER_BYTE: - n = *(const u_int8_t *)inp; - break; - case 16/BITS_PER_BYTE: - n = *(const u_int16_t *)inp; - break; - case 32/BITS_PER_BYTE: - n = *(const u_int32_t *)inp; - break; - default: - bad_case(i); - } - switch (fp->field_type) - { - case ft_len: /* length of this struct and any following crud */ - case ft_lv: /* length/value field of attribute */ - if (!immediate && !len_meaningful) - break; - /* FALL THROUGH */ - case ft_nat: /* natural number (may be 0) */ - DBG_log(" %s: %lu", fp->name, (unsigned long)n); - break; - case ft_af_enum: /* Attribute Format + value from an enumeration */ - case ft_af_loose_enum: /* Attribute Format + value from an enumeration */ - if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV) - immediate = TRUE; - /* FALL THROUGH */ - case ft_enum: /* value from an enumeration */ - case ft_loose_enum: /* value from an enumeration with only some names known */ - DBG_log(" %s: %s", fp->name, enum_show(fp->desc, n)); - break; - case ft_set: /* bits representing set */ - DBG_log(" %s: %s", fp->name, bitnamesof(fp->desc, n)); - break; - default: - bad_case(fp->field_type); - } - inp += i; - break; + int i = fp->size; + u_int32_t n = 0; - case ft_raw: /* bytes to be left in network-order */ - { - char m[50]; /* arbitrary limit on name width in log */ + switch (fp->field_type) + { + case ft_mbz: /* must be zero */ + inp += i; + break; + case ft_nat: /* natural number (may be 0) */ + case ft_len: /* length of this struct and any following crud */ + case ft_lv: /* length/value field of attribute */ + case ft_enum: /* value from an enumeration */ + case ft_loose_enum: /* value from an enumeration with only some names known */ + case ft_af_enum: /* Attribute Format + value from an enumeration */ + case ft_af_loose_enum: /* Attribute Format + value from an enumeration */ + case ft_set: /* bits representing set */ + switch (i) + { + case 8/BITS_PER_BYTE: + n = *(const u_int8_t *)inp; + break; + case 16/BITS_PER_BYTE: + n = *(const u_int16_t *)inp; + break; + case 32/BITS_PER_BYTE: + n = *(const u_int32_t *)inp; + break; + default: + bad_case(i); + } + switch (fp->field_type) + { + case ft_len: /* length of this struct and any following crud */ + case ft_lv: /* length/value field of attribute */ + if (!immediate && !len_meaningful) + break; + /* FALL THROUGH */ + case ft_nat: /* natural number (may be 0) */ + DBG_log(" %s: %lu", fp->name, (unsigned long)n); + break; + case ft_af_enum: /* Attribute Format + value from an enumeration */ + case ft_af_loose_enum: /* Attribute Format + value from an enumeration */ + if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV) + immediate = TRUE; + /* FALL THROUGH */ + case ft_enum: /* value from an enumeration */ + case ft_loose_enum: /* value from an enumeration with only some names known */ + DBG_log(" %s: %s", fp->name, enum_show(fp->desc, n)); + break; + case ft_set: /* bits representing set */ + DBG_log(" %s: %s", fp->name, bitnamesof(fp->desc, n)); + break; + default: + bad_case(fp->field_type); + } + inp += i; + break; - snprintf(m, sizeof(m), " %s:", fp->name); - DBG_dump(m, inp, i); - inp += i; - } - break; - default: - bad_case(fp->field_type); + case ft_raw: /* bytes to be left in network-order */ + { + char m[50]; /* arbitrary limit on name width in log */ + + snprintf(m, sizeof(m), " %s:", fp->name); + DBG_dump(m, inp, i); + inp += i; + } + break; + default: + bad_case(fp->field_type); + } } - } } static void @@ -734,35 +734,35 @@ DBG_prefix_print_struct(const pb_stream *pbs , const char *label, const void *struct_ptr , struct_desc *sd, bool len_meaningful) { - /* print out a title, with a prefix of asterisks to show - * the nesting level. - */ - char space[40]; /* arbitrary limit on label+flock-of-* */ - size_t len = strlen(label); + /* print out a title, with a prefix of asterisks to show + * the nesting level. + */ + char space[40]; /* arbitrary limit on label+flock-of-* */ + size_t len = strlen(label); - if (sizeof(space) <= len) - { - DBG_print_struct(label, struct_ptr, sd, len_meaningful); - } - else - { - const pb_stream *p = pbs; - char *pre = &space[sizeof(space) - (len + 1)]; - - strcpy(pre, label); - - /* put at least one * out */ - for (;;) + if (sizeof(space) <= len) { - if (pre <= space) - break; - *--pre = '*'; - if (p == NULL) - break; - p = p->container; + DBG_print_struct(label, struct_ptr, sd, len_meaningful); + } + else + { + const pb_stream *p = pbs; + char *pre = &space[sizeof(space) - (len + 1)]; + + strcpy(pre, label); + + /* put at least one * out */ + for (;;) + { + if (pre <= space) + break; + *--pre = '*'; + if (p == NULL) + break; + p = p->container; + } + DBG_print_struct(pre, struct_ptr, sd, len_meaningful); } - DBG_print_struct(pre, struct_ptr, sd, len_meaningful); - } } #endif @@ -785,191 +785,191 @@ bool in_struct(void *struct_ptr, struct_desc *sd , pb_stream *ins, pb_stream *obj_pbs) { - err_t ugh = NULL; - u_int8_t *cur = ins->cur; + err_t ugh = NULL; + u_int8_t *cur = ins->cur; - if (ins->roof - cur < (ptrdiff_t)sd->size) - { - ugh = builddiag("not enough room in input packet for %s", sd->name); - } - else - { - u_int8_t *roof = cur + sd->size; /* may be changed by a length field */ - u_int8_t *outp = struct_ptr; - bool immediate = FALSE; - field_desc *fp; - - for (fp = sd->fields; ugh == NULL; fp++) + if (ins->roof - cur < (ptrdiff_t)sd->size) { - size_t i = fp->size; + ugh = builddiag("not enough room in input packet for %s", sd->name); + } + else + { + u_int8_t *roof = cur + sd->size; /* may be changed by a length field */ + u_int8_t *outp = struct_ptr; + bool immediate = FALSE; + field_desc *fp; - passert(ins->roof - cur >= (ptrdiff_t)i); - passert(cur - ins->cur <= (ptrdiff_t)(sd->size - i)); - passert(outp - (cur - ins->cur) == struct_ptr); + for (fp = sd->fields; ugh == NULL; fp++) + { + size_t i = fp->size; + + passert(ins->roof - cur >= (ptrdiff_t)i); + passert(cur - ins->cur <= (ptrdiff_t)(sd->size - i)); + passert(outp - (cur - ins->cur) == struct_ptr); #if 0 - DBG(DBG_PARSING, DBG_log("%d %s" - , (int) (cur - ins->cur), fp->name == NULL? "" : fp->name)); + DBG(DBG_PARSING, DBG_log("%d %s" + , (int) (cur - ins->cur), fp->name == NULL? "" : fp->name)); #endif - switch (fp->field_type) - { - case ft_mbz: /* must be zero */ - for (; i != 0; i--) - { - if (*cur++ != 0) - { - ugh = builddiag("byte %d of %s must be zero, but is not" - , (int) (cur - ins->cur), sd->name); - break; - } - *outp++ = '\0'; /* probably redundant */ + switch (fp->field_type) + { + case ft_mbz: /* must be zero */ + for (; i != 0; i--) + { + if (*cur++ != 0) + { + ugh = builddiag("byte %d of %s must be zero, but is not" + , (int) (cur - ins->cur), sd->name); + break; + } + *outp++ = '\0'; /* probably redundant */ + } + break; + + case ft_nat: /* natural number (may be 0) */ + case ft_len: /* length of this struct and any following crud */ + case ft_lv: /* length/value field of attribute */ + case ft_enum: /* value from an enumeration */ + case ft_loose_enum: /* value from an enumeration with only some names known */ + case ft_af_enum: /* Attribute Format + value from an enumeration */ + case ft_af_loose_enum: /* Attribute Format + value from an enumeration */ + case ft_set: /* bits representing set */ + { + u_int32_t n = 0; + + for (; i != 0; i--) + n = (n << BITS_PER_BYTE) | *cur++; + + switch (fp->field_type) + { + case ft_len: /* length of this struct and any following crud */ + case ft_lv: /* length/value field of attribute */ + { + u_int32_t len = fp->field_type == ft_len? n + : immediate? sd->size : n + sd->size; + + if (len < sd->size) + { + ugh = builddiag("%s of %s is smaller than minimum" + , fp->name, sd->name); + } + else if (pbs_left(ins) < len) + { + ugh = builddiag("%s of %s is larger than can fit" + , fp->name, sd->name); + } + else + { + roof = ins->cur + len; + } + break; + } + case ft_af_loose_enum: /* Attribute Format + value from an enumeration */ + if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV) + immediate = TRUE; + break; + case ft_af_enum: /* Attribute Format + value from an enumeration */ + if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV) + immediate = TRUE; + /* FALL THROUGH */ + case ft_enum: /* value from an enumeration */ + if (enum_name(fp->desc, n) == NULL) + { + ugh = builddiag("%s of %s has an unknown value: %lu" + , fp->name, sd->name, (unsigned long)n); + } + /* FALL THROUGH */ + case ft_loose_enum: /* value from an enumeration with only some names known */ + break; + case ft_set: /* bits representing set */ + if (!testset(fp->desc, n)) + { + ugh = builddiag("bitset %s of %s has unknown member(s): %s" + , fp->name, sd->name, bitnamesof(fp->desc, n)); + } + break; + default: + break; + } + i = fp->size; + switch (i) + { + case 8/BITS_PER_BYTE: + *(u_int8_t *)outp = n; + break; + case 16/BITS_PER_BYTE: + *(u_int16_t *)outp = n; + break; + case 32/BITS_PER_BYTE: + *(u_int32_t *)outp = n; + break; + default: + bad_case(i); + } + outp += i; + break; + } + + case ft_raw: /* bytes to be left in network-order */ + for (; i != 0; i--) + { + *outp++ = *cur++; + } + break; + + case ft_end: /* end of field list */ + passert(cur == ins->cur + sd->size); + if (obj_pbs != NULL) + { + init_pbs(obj_pbs, ins->cur, roof - ins->cur, sd->name); + obj_pbs->container = ins; + obj_pbs->desc = sd; + obj_pbs->cur = cur; + } + ins->cur = roof; + DBG(DBG_PARSING + , DBG_prefix_print_struct(ins, "parse ", struct_ptr, sd, TRUE)); + return TRUE; + + default: + bad_case(fp->field_type); + } } - break; - - case ft_nat: /* natural number (may be 0) */ - case ft_len: /* length of this struct and any following crud */ - case ft_lv: /* length/value field of attribute */ - case ft_enum: /* value from an enumeration */ - case ft_loose_enum: /* value from an enumeration with only some names known */ - case ft_af_enum: /* Attribute Format + value from an enumeration */ - case ft_af_loose_enum: /* Attribute Format + value from an enumeration */ - case ft_set: /* bits representing set */ - { - u_int32_t n = 0; - - for (; i != 0; i--) - n = (n << BITS_PER_BYTE) | *cur++; - - switch (fp->field_type) - { - case ft_len: /* length of this struct and any following crud */ - case ft_lv: /* length/value field of attribute */ - { - u_int32_t len = fp->field_type == ft_len? n - : immediate? sd->size : n + sd->size; - - if (len < sd->size) - { - ugh = builddiag("%s of %s is smaller than minimum" - , fp->name, sd->name); - } - else if (pbs_left(ins) < len) - { - ugh = builddiag("%s of %s is larger than can fit" - , fp->name, sd->name); - } - else - { - roof = ins->cur + len; - } - break; - } - case ft_af_loose_enum: /* Attribute Format + value from an enumeration */ - if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV) - immediate = TRUE; - break; - case ft_af_enum: /* Attribute Format + value from an enumeration */ - if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV) - immediate = TRUE; - /* FALL THROUGH */ - case ft_enum: /* value from an enumeration */ - if (enum_name(fp->desc, n) == NULL) - { - ugh = builddiag("%s of %s has an unknown value: %lu" - , fp->name, sd->name, (unsigned long)n); - } - /* FALL THROUGH */ - case ft_loose_enum: /* value from an enumeration with only some names known */ - break; - case ft_set: /* bits representing set */ - if (!testset(fp->desc, n)) - { - ugh = builddiag("bitset %s of %s has unknown member(s): %s" - , fp->name, sd->name, bitnamesof(fp->desc, n)); - } - break; - default: - break; - } - i = fp->size; - switch (i) - { - case 8/BITS_PER_BYTE: - *(u_int8_t *)outp = n; - break; - case 16/BITS_PER_BYTE: - *(u_int16_t *)outp = n; - break; - case 32/BITS_PER_BYTE: - *(u_int32_t *)outp = n; - break; - default: - bad_case(i); - } - outp += i; - break; - } - - case ft_raw: /* bytes to be left in network-order */ - for (; i != 0; i--) - { - *outp++ = *cur++; - } - break; - - case ft_end: /* end of field list */ - passert(cur == ins->cur + sd->size); - if (obj_pbs != NULL) - { - init_pbs(obj_pbs, ins->cur, roof - ins->cur, sd->name); - obj_pbs->container = ins; - obj_pbs->desc = sd; - obj_pbs->cur = cur; - } - ins->cur = roof; - DBG(DBG_PARSING - , DBG_prefix_print_struct(ins, "parse ", struct_ptr, sd, TRUE)); - return TRUE; - - default: - bad_case(fp->field_type); - } } - } - /* some failure got us here: report it */ - loglog(RC_LOG_SERIOUS, ugh); - return FALSE; + /* some failure got us here: report it */ + loglog(RC_LOG_SERIOUS, ugh); + return FALSE; } bool in_raw(void *bytes, size_t len, pb_stream *ins, const char *name) { - if (pbs_left(ins) < len) - { - loglog(RC_LOG_SERIOUS, "not enough bytes left to get %s from %s", name, ins->name); - return FALSE; - } - else - { - if (bytes == NULL) + if (pbs_left(ins) < len) { - DBG(DBG_PARSING - , DBG_log("skipping %u raw bytes of %s (%s)" - , (unsigned) len, ins->name, name); - DBG_dump(name, ins->cur, len)); + loglog(RC_LOG_SERIOUS, "not enough bytes left to get %s from %s", name, ins->name); + return FALSE; } else { - memcpy(bytes, ins->cur, len); - DBG(DBG_PARSING - , DBG_log("parsing %u raw bytes of %s into %s" - , (unsigned) len, ins->name, name); - DBG_dump(name, bytes, len)); + if (bytes == NULL) + { + DBG(DBG_PARSING + , DBG_log("skipping %u raw bytes of %s (%s)" + , (unsigned) len, ins->name, name); + DBG_dump(name, ins->cur, len)); + } + else + { + memcpy(bytes, ins->cur, len); + DBG(DBG_PARSING + , DBG_log("parsing %u raw bytes of %s into %s" + , (unsigned) len, ins->name, name); + DBG_dump(name, bytes, len)); + } + ins->cur += len; + return TRUE; } - ins->cur += len; - return TRUE; - } } /* "emit" a host struct into a network packet. @@ -994,227 +994,227 @@ bool out_struct(const void *struct_ptr, struct_desc *sd , pb_stream *outs, pb_stream *obj_pbs) { - err_t ugh = NULL; - const u_int8_t *inp = struct_ptr; - u_int8_t *cur = outs->cur; + err_t ugh = NULL; + const u_int8_t *inp = struct_ptr; + u_int8_t *cur = outs->cur; - DBG(DBG_EMITTING - , DBG_prefix_print_struct(outs, "emit ", struct_ptr, sd, obj_pbs==NULL)); + DBG(DBG_EMITTING + , DBG_prefix_print_struct(outs, "emit ", struct_ptr, sd, obj_pbs==NULL)); - if (outs->roof - cur < (ptrdiff_t)sd->size) - { - ugh = builddiag("not enough room left in output packet to place %s" - , sd->name); - } - else - { - bool immediate = FALSE; - pb_stream obj; - field_desc *fp; - - obj.lenfld = NULL; /* until a length field is discovered */ - obj.lenfld_desc = NULL; - - for (fp = sd->fields; ugh == NULL; fp++) + if (outs->roof - cur < (ptrdiff_t)sd->size) { - size_t i = fp->size; + ugh = builddiag("not enough room left in output packet to place %s" + , sd->name); + } + else + { + bool immediate = FALSE; + pb_stream obj; + field_desc *fp; - passert(outs->roof - cur >= (ptrdiff_t)i); - passert(cur - outs->cur <= (ptrdiff_t)(sd->size - i)); - passert(inp - (cur - outs->cur) == struct_ptr); + obj.lenfld = NULL; /* until a length field is discovered */ + obj.lenfld_desc = NULL; + + for (fp = sd->fields; ugh == NULL; fp++) + { + size_t i = fp->size; + + passert(outs->roof - cur >= (ptrdiff_t)i); + passert(cur - outs->cur <= (ptrdiff_t)(sd->size - i)); + passert(inp - (cur - outs->cur) == struct_ptr); #if 0 - DBG(DBG_EMITTING, DBG_log("%d %s" - , (int) (cur - outs->cur), fp->name == NULL? "" : fp->name); + DBG(DBG_EMITTING, DBG_log("%d %s" + , (int) (cur - outs->cur), fp->name == NULL? "" : fp->name); #endif - switch (fp->field_type) - { - case ft_mbz: /* must be zero */ - inp += i; - for (; i != 0; i--) - *cur++ = '\0'; - break; - case ft_nat: /* natural number (may be 0) */ - case ft_len: /* length of this struct and any following crud */ - case ft_lv: /* length/value field of attribute */ - case ft_enum: /* value from an enumeration */ - case ft_loose_enum: /* value from an enumeration with only some names known */ - case ft_af_enum: /* Attribute Format + value from an enumeration */ - case ft_af_loose_enum: /* Attribute Format + value from an enumeration */ - case ft_set: /* bits representing set */ - { - u_int32_t n = 0; + switch (fp->field_type) + { + case ft_mbz: /* must be zero */ + inp += i; + for (; i != 0; i--) + *cur++ = '\0'; + break; + case ft_nat: /* natural number (may be 0) */ + case ft_len: /* length of this struct and any following crud */ + case ft_lv: /* length/value field of attribute */ + case ft_enum: /* value from an enumeration */ + case ft_loose_enum: /* value from an enumeration with only some names known */ + case ft_af_enum: /* Attribute Format + value from an enumeration */ + case ft_af_loose_enum: /* Attribute Format + value from an enumeration */ + case ft_set: /* bits representing set */ + { + u_int32_t n = 0; - switch (i) - { - case 8/BITS_PER_BYTE: - n = *(const u_int8_t *)inp; - break; - case 16/BITS_PER_BYTE: - n = *(const u_int16_t *)inp; - break; - case 32/BITS_PER_BYTE: - n = *(const u_int32_t *)inp; - break; - default: - bad_case(i); + switch (i) + { + case 8/BITS_PER_BYTE: + n = *(const u_int8_t *)inp; + break; + case 16/BITS_PER_BYTE: + n = *(const u_int16_t *)inp; + break; + case 32/BITS_PER_BYTE: + n = *(const u_int32_t *)inp; + break; + default: + bad_case(i); + } + + switch (fp->field_type) + { + case ft_len: /* length of this struct and any following crud */ + case ft_lv: /* length/value field of attribute */ + if (immediate) + break; /* not a length */ + /* We can't check the length because it will likely + * be filled in after variable part is supplied. + * We do record where this is so that it can be + * filled in by a subsequent close_output_pbs(). + */ + passert(obj.lenfld == NULL); /* only one ft_len allowed */ + obj.lenfld = cur; + obj.lenfld_desc = fp; + break; + case ft_af_loose_enum: /* Attribute Format + value from an enumeration */ + if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV) + immediate = TRUE; + break; + case ft_af_enum: /* Attribute Format + value from an enumeration */ + if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV) + immediate = TRUE; + /* FALL THROUGH */ + case ft_enum: /* value from an enumeration */ + if (enum_name(fp->desc, n) == NULL) + { + ugh = builddiag("%s of %s has an unknown value: %lu" + , fp->name, sd->name, (unsigned long)n); + } + /* FALL THROUGH */ + case ft_loose_enum: /* value from an enumeration with only some names known */ + break; + case ft_set: /* bits representing set */ + if (!testset(fp->desc, n)) + { + ugh = builddiag("bitset %s of %s has unknown member(s): %s" + , fp->name, sd->name, bitnamesof(fp->desc, n)); + } + break; + default: + break; + } + + while (i-- != 0) + { + cur[i] = (u_int8_t)n; + n >>= BITS_PER_BYTE; + } + inp += fp->size; + cur += fp->size; + break; + } + case ft_raw: /* bytes to be left in network-order */ + for (; i != 0; i--) + *cur++ = *inp++; + break; + case ft_end: /* end of field list */ + passert(cur == outs->cur + sd->size); + + obj.container = outs; + obj.desc = sd; + obj.name = sd->name; + obj.start = outs->cur; + obj.cur = cur; + obj.roof = outs->roof; /* limit of possible */ + /* obj.lenfld and obj.lenfld_desc already set */ + + if (obj_pbs == NULL) + { + close_output_pbs(&obj); /* fill in length field, if any */ + } + else + { + /* We set outs->cur to outs->roof so that + * any attempt to output something into outs + * before obj is closed will trigger an error. + */ + outs->cur = outs->roof; + + *obj_pbs = obj; + } + return TRUE; + + default: + bad_case(fp->field_type); + } } - - switch (fp->field_type) - { - case ft_len: /* length of this struct and any following crud */ - case ft_lv: /* length/value field of attribute */ - if (immediate) - break; /* not a length */ - /* We can't check the length because it will likely - * be filled in after variable part is supplied. - * We do record where this is so that it can be - * filled in by a subsequent close_output_pbs(). - */ - passert(obj.lenfld == NULL); /* only one ft_len allowed */ - obj.lenfld = cur; - obj.lenfld_desc = fp; - break; - case ft_af_loose_enum: /* Attribute Format + value from an enumeration */ - if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV) - immediate = TRUE; - break; - case ft_af_enum: /* Attribute Format + value from an enumeration */ - if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV) - immediate = TRUE; - /* FALL THROUGH */ - case ft_enum: /* value from an enumeration */ - if (enum_name(fp->desc, n) == NULL) - { - ugh = builddiag("%s of %s has an unknown value: %lu" - , fp->name, sd->name, (unsigned long)n); - } - /* FALL THROUGH */ - case ft_loose_enum: /* value from an enumeration with only some names known */ - break; - case ft_set: /* bits representing set */ - if (!testset(fp->desc, n)) - { - ugh = builddiag("bitset %s of %s has unknown member(s): %s" - , fp->name, sd->name, bitnamesof(fp->desc, n)); - } - break; - default: - break; - } - - while (i-- != 0) - { - cur[i] = (u_int8_t)n; - n >>= BITS_PER_BYTE; - } - inp += fp->size; - cur += fp->size; - break; - } - case ft_raw: /* bytes to be left in network-order */ - for (; i != 0; i--) - *cur++ = *inp++; - break; - case ft_end: /* end of field list */ - passert(cur == outs->cur + sd->size); - - obj.container = outs; - obj.desc = sd; - obj.name = sd->name; - obj.start = outs->cur; - obj.cur = cur; - obj.roof = outs->roof; /* limit of possible */ - /* obj.lenfld and obj.lenfld_desc already set */ - - if (obj_pbs == NULL) - { - close_output_pbs(&obj); /* fill in length field, if any */ - } - else - { - /* We set outs->cur to outs->roof so that - * any attempt to output something into outs - * before obj is closed will trigger an error. - */ - outs->cur = outs->roof; - - *obj_pbs = obj; - } - return TRUE; - - default: - bad_case(fp->field_type); - } } - } - /* some failure got us here: report it */ - loglog(RC_LOG_SERIOUS, ugh); /* ??? serious, but errno not relevant */ - return FALSE; + /* some failure got us here: report it */ + loglog(RC_LOG_SERIOUS, ugh); /* ??? serious, but errno not relevant */ + return FALSE; } bool out_generic(u_int8_t np, struct_desc *sd , pb_stream *outs, pb_stream *obj_pbs) { - struct isakmp_generic gen; + struct isakmp_generic gen; - passert(sd->fields == isakmp_generic_desc.fields); - gen.isag_np = np; - return out_struct(&gen, sd, outs, obj_pbs); + passert(sd->fields == isakmp_generic_desc.fields); + gen.isag_np = np; + return out_struct(&gen, sd, outs, obj_pbs); } bool out_generic_raw(u_int8_t np, struct_desc *sd , pb_stream *outs, const void *bytes, size_t len, const char *name) { - pb_stream pbs; + pb_stream pbs; - if (!out_generic(np, sd, outs, &pbs) - || !out_raw(bytes, len, &pbs, name)) - return FALSE; - close_output_pbs(&pbs); - return TRUE; + if (!out_generic(np, sd, outs, &pbs) + || !out_raw(bytes, len, &pbs, name)) + return FALSE; + close_output_pbs(&pbs); + return TRUE; } bool out_raw(const void *bytes, size_t len, pb_stream *outs, const char *name) { - if (pbs_left(outs) < len) - { - loglog(RC_LOG_SERIOUS, "not enough room left to place %lu bytes of %s in %s" - , (unsigned long) len, name, outs->name); - return FALSE; - } - else - { - DBG(DBG_EMITTING - , DBG_log("emitting %u raw bytes of %s into %s" - , (unsigned) len, name, outs->name); - DBG_dump(name, bytes, len)); - memcpy(outs->cur, bytes, len); - outs->cur += len; - return TRUE; - } + if (pbs_left(outs) < len) + { + loglog(RC_LOG_SERIOUS, "not enough room left to place %lu bytes of %s in %s" + , (unsigned long) len, name, outs->name); + return FALSE; + } + else + { + DBG(DBG_EMITTING + , DBG_log("emitting %u raw bytes of %s into %s" + , (unsigned) len, name, outs->name); + DBG_dump(name, bytes, len)); + memcpy(outs->cur, bytes, len); + outs->cur += len; + return TRUE; + } } bool out_zero(size_t len, pb_stream *outs, const char *name) { - if (pbs_left(outs) < len) - { - loglog(RC_LOG_SERIOUS, "not enough room left to place %s in %s", name, outs->name); - return FALSE; - } - else - { - DBG(DBG_EMITTING, DBG_log("emitting %u zero bytes of %s into %s" - , (unsigned) len, name, outs->name)); - memset(outs->cur, 0x00, len); - outs->cur += len; - return TRUE; - } + if (pbs_left(outs) < len) + { + loglog(RC_LOG_SERIOUS, "not enough room left to place %s in %s", name, outs->name); + return FALSE; + } + else + { + DBG(DBG_EMITTING, DBG_log("emitting %u zero bytes of %s into %s" + , (unsigned) len, name, outs->name)); + memset(outs->cur, 0x00, len); + outs->cur += len; + return TRUE; + } } /* Record current length. @@ -1224,21 +1224,21 @@ out_zero(size_t len, pb_stream *outs, const char *name) void close_output_pbs(pb_stream *pbs) { - if (pbs->lenfld != NULL) - { - u_int32_t len = pbs_offset(pbs); - int i = pbs->lenfld_desc->size; - - if (pbs->lenfld_desc->field_type == ft_lv) - len -= sizeof(struct isakmp_attribute); - DBG(DBG_EMITTING, DBG_log("emitting length of %s: %lu" - , pbs->name, (unsigned long) len)); - while (i-- != 0) + if (pbs->lenfld != NULL) { - pbs->lenfld[i] = (u_int8_t)len; - len >>= BITS_PER_BYTE; + u_int32_t len = pbs_offset(pbs); + int i = pbs->lenfld_desc->size; + + if (pbs->lenfld_desc->field_type == ft_lv) + len -= sizeof(struct isakmp_attribute); + DBG(DBG_EMITTING, DBG_log("emitting length of %s: %lu" + , pbs->name, (unsigned long) len)); + while (i-- != 0) + { + pbs->lenfld[i] = (u_int8_t)len; + len >>= BITS_PER_BYTE; + } } - } - if (pbs->container != NULL) - pbs->container->cur = pbs->cur; /* pass space utilization up */ + if (pbs->container != NULL) + pbs->container->cur = pbs->cur; /* pass space utilization up */ } diff --git a/src/pluto/packet.h b/src/pluto/packet.h index a515d3890..d5ff7ef7f 100644 --- a/src/pluto/packet.h +++ b/src/pluto/packet.h @@ -23,9 +23,9 @@ */ typedef const struct struct_desc { - const char *name; - const struct field_desc *fields; - size_t size; + const char *name; + const struct field_desc *fields; + size_t size; } struct_desc; /* Note: if an ft_af_enum field has the ISAKMP_ATTR_AF_TV bit set, @@ -35,24 +35,24 @@ typedef const struct struct_desc { */ enum field_type { - ft_mbz, /* must be zero */ - ft_nat, /* natural number (may be 0) */ - ft_len, /* length of this struct and any following crud */ - ft_lv, /* length/value field of attribute */ - ft_enum, /* value from an enumeration */ - ft_loose_enum, /* value from an enumeration with only some names known */ - ft_af_loose_enum, /* Attribute Format + enumeration, some names known */ - ft_af_enum, /* Attribute Format + value from an enumeration */ - ft_set, /* bits representing set */ - ft_raw, /* bytes to be left in network-order */ - ft_end, /* end of field list */ + ft_mbz, /* must be zero */ + ft_nat, /* natural number (may be 0) */ + ft_len, /* length of this struct and any following crud */ + ft_lv, /* length/value field of attribute */ + ft_enum, /* value from an enumeration */ + ft_loose_enum, /* value from an enumeration with only some names known */ + ft_af_loose_enum, /* Attribute Format + enumeration, some names known */ + ft_af_enum, /* Attribute Format + value from an enumeration */ + ft_set, /* bits representing set */ + ft_raw, /* bytes to be left in network-order */ + ft_end, /* end of field list */ }; typedef const struct field_desc { - enum field_type field_type; - int size; /* size, in bytes, of field */ - const char *name; - const void *desc; /* enum_names for enum or char *[] for bits */ + enum field_type field_type; + int size; /* size, in bytes, of field */ + const char *name; + const void *desc; /* enum_names for enum or char *[] for bits */ } field_desc; /* The formatting of input and output of packets is done @@ -62,18 +62,18 @@ typedef const struct field_desc { * Actual packet transfer is done elsewhere. */ typedef struct packet_byte_stream { - struct packet_byte_stream *container; /* PBS of which we are part */ - struct_desc *desc; - const char *name; /* what does this PBS represent? */ - u_int8_t - *start, - *cur, /* current position in stream */ - *roof; /* byte after last in PBS (actually just a limit on output) */ - /* For an output PBS, the length field will be filled in later so - * we need to record its particulars. Note: it may not be aligned. - */ - u_int8_t *lenfld; - field_desc *lenfld_desc; + struct packet_byte_stream *container; /* PBS of which we are part */ + struct_desc *desc; + const char *name; /* what does this PBS represent? */ + u_int8_t + *start, + *cur, /* current position in stream */ + *roof; /* byte after last in PBS (actually just a limit on output) */ + /* For an output PBS, the length field will be filled in later so + * we need to record its particulars. Note: it may not be aligned. + */ + u_int8_t *lenfld; + field_desc *lenfld_desc; } pb_stream; /* For an input PBS, pbs_offset is amount of stream processed. @@ -88,17 +88,17 @@ typedef struct packet_byte_stream { extern void init_pbs(pb_stream *pbs, u_int8_t *start, size_t len, const char *name); extern bool in_struct(void *struct_ptr, struct_desc *sd, - pb_stream *ins, pb_stream *obj_pbs); + pb_stream *ins, pb_stream *obj_pbs); extern bool in_raw(void *bytes, size_t len, pb_stream *ins, const char *name); extern bool out_struct(const void *struct_ptr, struct_desc *sd, - pb_stream *outs, pb_stream *obj_pbs); + pb_stream *outs, pb_stream *obj_pbs); extern bool out_generic(u_int8_t np, struct_desc *sd, - pb_stream *outs, pb_stream *obj_pbs); + pb_stream *outs, pb_stream *obj_pbs); extern bool out_generic_raw(u_int8_t np, struct_desc *sd, - pb_stream *outs, const void *bytes, size_t len, const char *name); + pb_stream *outs, const void *bytes, size_t len, const char *name); #define out_generic_chunk(np, sd, outs, ch, name) \ - out_generic_raw(np, sd, outs, (ch).ptr, (ch).len, name) + out_generic_raw(np, sd, outs, (ch).ptr, (ch).len, name) extern bool out_zero(size_t len, pb_stream *outs, const char *name); extern bool out_raw(const void *bytes, size_t len, pb_stream *outs, const char *name); #define out_chunk(ch, outs, name) out_raw((ch).ptr, (ch).len, (outs), (name)) @@ -106,7 +106,7 @@ extern void close_output_pbs(pb_stream *pbs); #ifdef DEBUG extern void DBG_print_struct(const char *label, const void *struct_ptr, - struct_desc *sd, bool len_meaningful); + struct_desc *sd, bool len_meaningful); #endif /* ISAKMP Header: for all messages @@ -160,16 +160,16 @@ extern void DBG_print_struct(const char *label, const void *struct_ptr, struct isakmp_hdr { - u_int8_t isa_icookie[COOKIE_SIZE]; - u_int8_t isa_rcookie[COOKIE_SIZE]; - u_int8_t isa_np; /* Next payload */ - u_int8_t isa_version; /* high-order 4 bits: Major; low order 4: Minor */ -#define ISA_MAJ_SHIFT 4 -#define ISA_MIN_MASK (~((~0u) << ISA_MAJ_SHIFT)) - u_int8_t isa_xchg; /* Exchange type */ - u_int8_t isa_flags; - u_int32_t isa_msgid; /* Message ID (RAW) */ - u_int32_t isa_length; /* Length of message */ + u_int8_t isa_icookie[COOKIE_SIZE]; + u_int8_t isa_rcookie[COOKIE_SIZE]; + u_int8_t isa_np; /* Next payload */ + u_int8_t isa_version; /* high-order 4 bits: Major; low order 4: Minor */ +#define ISA_MAJ_SHIFT 4 +#define ISA_MIN_MASK (~((~0u) << ISA_MAJ_SHIFT)) + u_int8_t isa_xchg; /* Exchange type */ + u_int8_t isa_flags; + u_int32_t isa_msgid; /* Message ID (RAW) */ + u_int32_t isa_length; /* Length of message */ }; extern struct_desc isakmp_hdr_desc; @@ -186,9 +186,9 @@ extern struct_desc isakmp_hdr_desc; */ struct isakmp_generic { - u_int8_t isag_np; - u_int8_t isag_reserved; - u_int16_t isag_length; + u_int8_t isag_np; + u_int8_t isag_reserved; + u_int16_t isag_length; }; extern struct_desc isakmp_generic_desc; @@ -209,17 +209,17 @@ extern struct_desc isakmp_generic_desc; */ struct isakmp_attribute { - /* The high order bit of isaat_af_type is the Attribute Format - * If it is off, the format is TLV: lv is the length of the following - * attribute value. - * If it is on, the format is TV: lv is the value of the attribute. - * ISAKMP_ATTR_AF_MASK is the mask in host form. - * - * The low order 15 bits of isaat_af_type is the Attribute Type. - * ISAKMP_ATTR_RTYPE_MASK is the mask in host form. - */ - u_int16_t isaat_af_type; /* high order bit: AF; lower 15: rtype */ - u_int16_t isaat_lv; /* Length or value */ + /* The high order bit of isaat_af_type is the Attribute Format + * If it is off, the format is TLV: lv is the length of the following + * attribute value. + * If it is on, the format is TV: lv is the value of the attribute. + * ISAKMP_ATTR_AF_MASK is the mask in host form. + * + * The low order 15 bits of isaat_af_type is the Attribute Type. + * ISAKMP_ATTR_RTYPE_MASK is the mask in host form. + */ + u_int16_t isaat_af_type; /* high order bit: AF; lower 15: rtype */ + u_int16_t isaat_lv; /* Length or value */ }; #define ISAKMP_ATTR_AF_MASK 0x8000 @@ -229,8 +229,8 @@ struct isakmp_attribute #define ISAKMP_ATTR_RTYPE_MASK 0x7FFF extern struct_desc - isakmp_oakley_attribute_desc, - isakmp_ipsec_attribute_desc; + isakmp_oakley_attribute_desc, + isakmp_ipsec_attribute_desc; /* ISAKMP Security Association Payload * layout from RFC 2408 "ISAKMP" section 3.4 @@ -250,10 +250,10 @@ extern struct_desc */ struct isakmp_sa { - u_int8_t isasa_np; /* Next payload */ - u_int8_t isasa_reserved; - u_int16_t isasa_length; /* Payload length */ - u_int32_t isasa_doi; /* DOI */ + u_int8_t isasa_np; /* Next payload */ + u_int8_t isasa_reserved; + u_int16_t isasa_length; /* Payload length */ + u_int32_t isasa_doi; /* DOI */ }; extern struct_desc isakmp_sa_desc; @@ -276,13 +276,13 @@ extern struct_desc ipsec_sit_desc; */ struct isakmp_proposal { - u_int8_t isap_np; - u_int8_t isap_reserved; - u_int16_t isap_length; - u_int8_t isap_proposal; - u_int8_t isap_protoid; - u_int8_t isap_spisize; - u_int8_t isap_notrans; /* Number of transforms */ + u_int8_t isap_np; + u_int8_t isap_reserved; + u_int16_t isap_length; + u_int8_t isap_proposal; + u_int8_t isap_protoid; + u_int8_t isap_spisize; + u_int8_t isap_notrans; /* Number of transforms */ }; extern struct_desc isakmp_proposal_desc; @@ -305,19 +305,19 @@ extern struct_desc isakmp_proposal_desc; */ struct isakmp_transform { - u_int8_t isat_np; - u_int8_t isat_reserved; - u_int16_t isat_length; - u_int8_t isat_transnum; /* Number of the transform */ - u_int8_t isat_transid; - u_int16_t isat_reserved2; + u_int8_t isat_np; + u_int8_t isat_reserved; + u_int16_t isat_length; + u_int8_t isat_transnum; /* Number of the transform */ + u_int8_t isat_transid; + u_int16_t isat_reserved2; }; extern struct_desc - isakmp_isakmp_transform_desc, - isakmp_ah_transform_desc, - isakmp_esp_transform_desc, - isakmp_ipcomp_transform_desc; + isakmp_isakmp_transform_desc, + isakmp_ah_transform_desc, + isakmp_esp_transform_desc, + isakmp_ipcomp_transform_desc; /* ISAKMP Key Exchange Payload: no fixed fields beyond the generic ones. * layout from RFC 2408 "ISAKMP" section 3.7 @@ -354,12 +354,12 @@ extern struct_desc isakmp_keyex_desc; */ struct isakmp_id { - u_int8_t isaid_np; - u_int8_t isaid_reserved; - u_int16_t isaid_length; - u_int8_t isaid_idtype; - u_int8_t isaid_doi_specific_a; - u_int16_t isaid_doi_specific_b; + u_int8_t isaid_np; + u_int8_t isaid_reserved; + u_int16_t isaid_length; + u_int8_t isaid_idtype; + u_int8_t isaid_doi_specific_a; + u_int16_t isaid_doi_specific_b; }; extern struct_desc isakmp_identification_desc; @@ -381,12 +381,12 @@ extern struct_desc isakmp_identification_desc; */ struct isakmp_ipsec_id { - u_int8_t isaiid_np; - u_int8_t isaiid_reserved; - u_int16_t isaiid_length; - u_int8_t isaiid_idtype; - u_int8_t isaiid_protoid; - u_int16_t isaiid_port; + u_int8_t isaiid_np; + u_int8_t isaiid_reserved; + u_int16_t isaiid_length; + u_int8_t isaiid_idtype; + u_int8_t isaiid_protoid; + u_int16_t isaiid_port; }; extern struct_desc isakmp_ipsec_identification_desc; @@ -408,17 +408,17 @@ extern struct_desc isakmp_ipsec_identification_desc; */ struct isakmp_cert { - u_int8_t isacert_np; - u_int8_t isacert_reserved; - u_int16_t isacert_length; - u_int8_t isacert_type; + u_int8_t isacert_np; + u_int8_t isacert_reserved; + u_int16_t isacert_length; + u_int8_t isacert_type; }; /* NOTE: this packet type has a fixed portion that is not a * multiple of 4 octets. This means that sizeof(struct isakmp_cert) * yields the wrong value for the length. */ -#define ISAKMP_CERT_SIZE 5 +#define ISAKMP_CERT_SIZE 5 extern struct_desc isakmp_ipsec_certificate_desc; @@ -439,17 +439,17 @@ extern struct_desc isakmp_ipsec_certificate_desc; */ struct isakmp_cr { - u_int8_t isacr_np; - u_int8_t isacr_reserved; - u_int16_t isacr_length; - u_int8_t isacr_type; + u_int8_t isacr_np; + u_int8_t isacr_reserved; + u_int16_t isacr_length; + u_int8_t isacr_type; }; /* NOTE: this packet type has a fixed portion that is not a * multiple of 4 octets. This means that sizeof(struct isakmp_cr) * yields the wrong value for the length. */ -#define ISAKMP_CR_SIZE 5 +#define ISAKMP_CR_SIZE 5 extern struct_desc isakmp_ipsec_cert_req_desc; @@ -526,13 +526,13 @@ extern struct_desc isakmp_nonce_desc; */ struct isakmp_notification { - u_int8_t isan_np; - u_int8_t isan_reserved; - u_int16_t isan_length; - u_int32_t isan_doi; - u_int8_t isan_protoid; - u_int8_t isan_spisize; - u_int16_t isan_type; + u_int8_t isan_np; + u_int8_t isan_reserved; + u_int16_t isan_length; + u_int32_t isan_doi; + u_int8_t isan_protoid; + u_int8_t isan_spisize; + u_int16_t isan_type; }; extern struct_desc isakmp_notification_desc; @@ -557,40 +557,40 @@ extern struct_desc isakmp_notification_desc; */ struct isakmp_delete { - u_int8_t isad_np; - u_int8_t isad_reserved; - u_int16_t isad_length; - u_int32_t isad_doi; - u_int8_t isad_protoid; - u_int8_t isad_spisize; - u_int16_t isad_nospi; + u_int8_t isad_np; + u_int8_t isad_reserved; + u_int16_t isad_length; + u_int32_t isad_doi; + u_int8_t isad_protoid; + u_int8_t isad_spisize; + u_int16_t isad_nospi; }; extern struct_desc isakmp_delete_desc; /* From draft-dukes-ike-mode-cfg 3.2. Attribute Payload - 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Next Payload ! RESERVED ! Payload Length ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! Type ! RESERVED ! Identifier ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ! ! - ! ! - ~ Attributes ~ - ! ! - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Next Payload ! RESERVED ! Payload Length ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Type ! RESERVED ! Identifier ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! ! + ! ! + ~ Attributes ~ + ! ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ struct isakmp_mode_attr { - u_int8_t isama_np; - u_int8_t isama_reserved; - u_int16_t isama_length; - u_int8_t isama_type; - u_int8_t isama_reserved2; - u_int16_t isama_identifier; + u_int8_t isama_np; + u_int8_t isama_reserved; + u_int16_t isama_length; + u_int8_t isama_type; + u_int8_t isama_reserved2; + u_int16_t isama_identifier; }; extern struct_desc isakmp_attr_desc; @@ -614,12 +614,12 @@ extern struct_desc isakmp_vendor_id_desc; struct isakmp_nat_oa { - u_int8_t isanoa_np; - u_int8_t isanoa_reserved_1; - u_int16_t isanoa_length; - u_int8_t isanoa_idtype; - u_int8_t isanoa_reserved_2; - u_int16_t isanoa_reserved_3; + u_int8_t isanoa_np; + u_int8_t isanoa_reserved_1; + u_int16_t isanoa_length; + u_int8_t isanoa_idtype; + u_int8_t isanoa_reserved_2; + u_int16_t isanoa_reserved_3; }; extern struct_desc isakmp_nat_d; @@ -628,18 +628,18 @@ extern struct_desc isakmp_nat_oa; /* union of all payloads */ union payload { - struct isakmp_generic generic; - struct isakmp_sa sa; - struct isakmp_proposal proposal; - struct isakmp_transform transform; - struct isakmp_id id; /* Main Mode */ - struct isakmp_cert cert; - struct isakmp_cr cr; - struct isakmp_ipsec_id ipsec_id; /* Quick Mode */ - struct isakmp_notification notification; - struct isakmp_delete delete; - struct isakmp_nat_oa nat_oa; - struct isakmp_mode_attr attribute; + struct isakmp_generic generic; + struct isakmp_sa sa; + struct isakmp_proposal proposal; + struct isakmp_transform transform; + struct isakmp_id id; /* Main Mode */ + struct isakmp_cert cert; + struct isakmp_cr cr; + struct isakmp_ipsec_id ipsec_id; /* Quick Mode */ + struct isakmp_notification notification; + struct isakmp_delete delete; + struct isakmp_nat_oa nat_oa; + struct isakmp_mode_attr attribute; }; /* descriptor for each payload type diff --git a/src/pluto/pem.c b/src/pluto/pem.c index 8c607cfa4..47b8a50dc 100644 --- a/src/pluto/pem.c +++ b/src/pluto/pem.c @@ -43,15 +43,15 @@ static bool present(const char* pattern, chunk_t* ch) { - u_int pattern_len = strlen(pattern); + u_int pattern_len = strlen(pattern); - if (ch->len >= pattern_len && strneq(ch->ptr, pattern, pattern_len)) - { - ch->ptr += pattern_len; - ch->len -= pattern_len; - return TRUE; - } - return FALSE; + if (ch->len >= pattern_len && strneq(ch->ptr, pattern, pattern_len)) + { + ch->ptr += pattern_len; + ch->len -= pattern_len; + return TRUE; + } + return FALSE; } /* @@ -60,7 +60,7 @@ present(const char* pattern, chunk_t* ch) static bool match(const char *pattern, const chunk_t *ch) { - return ch->len == strlen(pattern) && strneq(pattern, ch->ptr, ch->len); + return ch->len == strlen(pattern) && strneq(pattern, ch->ptr, ch->len); } /* @@ -69,31 +69,31 @@ match(const char *pattern, const chunk_t *ch) static bool find_boundary(const char* tag, chunk_t *line) { - chunk_t name = chunk_empty; + chunk_t name = chunk_empty; - if (!present("-----", line)) - return FALSE; - if (!present(tag, line)) - return FALSE; - if (*line->ptr != ' ') - return FALSE; - line->ptr++; line->len--; + if (!present("-----", line)) + return FALSE; + if (!present(tag, line)) + return FALSE; + if (*line->ptr != ' ') + return FALSE; + line->ptr++; line->len--; - /* extract name */ - name.ptr = line->ptr; - while (line->len > 0) - { - if (present("-----", line)) + /* extract name */ + name.ptr = line->ptr; + while (line->len > 0) { - DBG(DBG_PARSING, - DBG_log(" -----%s %.*s-----", - tag, (int)name.len, name.ptr); - ) - return TRUE; + if (present("-----", line)) + { + DBG(DBG_PARSING, + DBG_log(" -----%s %.*s-----", + tag, (int)name.len, name.ptr); + ) + return TRUE; + } + line->ptr++; line->len--; name.len++; } - line->ptr++; line->len--; name.len++; - } - return FALSE; + return FALSE; } /* @@ -102,10 +102,10 @@ find_boundary(const char* tag, chunk_t *line) static void eat_whitespace(chunk_t *src) { - while (src->len > 0 && (*src->ptr == ' ' || *src->ptr == '\t')) - { - src->ptr++; src->len--; - } + while (src->len > 0 && (*src->ptr == ' ' || *src->ptr == '\t')) + { + src->ptr++; src->len--; + } } /* @@ -114,21 +114,21 @@ eat_whitespace(chunk_t *src) static bool extract_token(chunk_t *token, char termination, chunk_t *src) { - u_char *eot = memchr(src->ptr, termination, src->len); + u_char *eot = memchr(src->ptr, termination, src->len); - /* initialize empty token */ - *token = chunk_empty; + /* initialize empty token */ + *token = chunk_empty; - if (eot == NULL) /* termination symbol not found */ - return FALSE; + if (eot == NULL) /* termination symbol not found */ + return FALSE; - /* extract token */ - token->ptr = src->ptr; - token->len = (u_int)(eot - src->ptr); + /* extract token */ + token->ptr = src->ptr; + token->len = (u_int)(eot - src->ptr); - /* advance src pointer after termination symbol */ - src->ptr = eot + 1; - src->len -= (token->len + 1); + /* advance src pointer after termination symbol */ + src->ptr = eot + 1; + src->len -= (token->len + 1); return TRUE; } @@ -139,19 +139,19 @@ extract_token(chunk_t *token, char termination, chunk_t *src) static bool extract_parameter(chunk_t *name, chunk_t *value, chunk_t *line) { - DBG(DBG_PARSING, - DBG_log(" %.*s", (int)line->len, line->ptr); - ) + DBG(DBG_PARSING, + DBG_log(" %.*s", (int)line->len, line->ptr); + ) - /* extract name */ - if (!extract_token(name,':', line)) - return FALSE; + /* extract name */ + if (!extract_token(name,':', line)) + return FALSE; - eat_whitespace(line); + eat_whitespace(line); - /* extract value */ - *value = *line; - return TRUE; + /* extract value */ + *value = *line; + return TRUE; } /* @@ -160,21 +160,21 @@ extract_parameter(chunk_t *name, chunk_t *value, chunk_t *line) static bool fetchline(chunk_t *src, chunk_t *line) { - if (src->len == 0) /* end of src reached */ - return FALSE; + if (src->len == 0) /* end of src reached */ + return FALSE; - if (extract_token(line, '\n', src)) - { - if (line->len > 0 && *(line->ptr + line->len -1) == '\r') - line->len--; /* remove optional \r */ - } - else /*last line ends without newline */ - { - *line = *src; - src->ptr += src->len; - src->len = 0; - } - return TRUE; + if (extract_token(line, '\n', src)) + { + if (line->len > 0 && *(line->ptr + line->len -1) == '\r') + line->len--; /* remove optional \r */ + } + else /*last line ends without newline */ + { + *line = *src; + src->ptr += src->len; + src->len = 0; + } + return TRUE; } /* @@ -183,55 +183,55 @@ fetchline(chunk_t *src, chunk_t *line) static bool pem_decrypt_3des(chunk_t *blob, chunk_t *iv, const char *passphrase) { - MD5_CTX context; - u_char digest[MD5_DIGEST_SIZE]; - u_char des_iv[DES_CBC_BLOCK_SIZE]; - u_char key[24]; - des_cblock *deskey = (des_cblock *)key; - des_key_schedule ks[3]; - u_char padding, *last_padding_pos, *first_padding_pos; + MD5_CTX context; + u_char digest[MD5_DIGEST_SIZE]; + u_char des_iv[DES_CBC_BLOCK_SIZE]; + u_char key[24]; + des_cblock *deskey = (des_cblock *)key; + des_key_schedule ks[3]; + u_char padding, *last_padding_pos, *first_padding_pos; - /* Convert passphrase to 3des key */ - MD5Init(&context); - MD5Update(&context, passphrase, strlen(passphrase)); - MD5Update(&context, iv->ptr, iv->len); - MD5Final(digest, &context); + /* Convert passphrase to 3des key */ + MD5Init(&context); + MD5Update(&context, passphrase, strlen(passphrase)); + MD5Update(&context, iv->ptr, iv->len); + MD5Final(digest, &context); - memcpy(key, digest, MD5_DIGEST_SIZE); + memcpy(key, digest, MD5_DIGEST_SIZE); - MD5Init(&context); - MD5Update(&context, digest, MD5_DIGEST_SIZE); - MD5Update(&context, passphrase, strlen(passphrase)); - MD5Update(&context, iv->ptr, iv->len); - MD5Final(digest, &context); + MD5Init(&context); + MD5Update(&context, digest, MD5_DIGEST_SIZE); + MD5Update(&context, passphrase, strlen(passphrase)); + MD5Update(&context, iv->ptr, iv->len); + MD5Final(digest, &context); - memcpy(key + MD5_DIGEST_SIZE, digest, 24 - MD5_DIGEST_SIZE); + memcpy(key + MD5_DIGEST_SIZE, digest, 24 - MD5_DIGEST_SIZE); - (void) des_set_key(&deskey[0], ks[0]); - (void) des_set_key(&deskey[1], ks[1]); - (void) des_set_key(&deskey[2], ks[2]); + (void) des_set_key(&deskey[0], ks[0]); + (void) des_set_key(&deskey[1], ks[1]); + (void) des_set_key(&deskey[2], ks[2]); - /* decrypt data block */ - memcpy(des_iv, iv->ptr, DES_CBC_BLOCK_SIZE); - des_ede3_cbc_encrypt((des_cblock *)blob->ptr, (des_cblock *)blob->ptr, - blob->len, ks[0], ks[1], ks[2], (des_cblock *)des_iv, FALSE); + /* decrypt data block */ + memcpy(des_iv, iv->ptr, DES_CBC_BLOCK_SIZE); + des_ede3_cbc_encrypt((des_cblock *)blob->ptr, (des_cblock *)blob->ptr, + blob->len, ks[0], ks[1], ks[2], (des_cblock *)des_iv, FALSE); - /* determine amount of padding */ - last_padding_pos = blob->ptr + blob->len - 1; - padding = *last_padding_pos; - first_padding_pos = (padding > blob->len)? - blob->ptr : last_padding_pos - padding; + /* determine amount of padding */ + last_padding_pos = blob->ptr + blob->len - 1; + padding = *last_padding_pos; + first_padding_pos = (padding > blob->len)? + blob->ptr : last_padding_pos - padding; - /* check the padding pattern */ - while (--last_padding_pos > first_padding_pos) - { - if (*last_padding_pos != padding) - return FALSE; - } + /* check the padding pattern */ + while (--last_padding_pos > first_padding_pos) + { + if (*last_padding_pos != padding) + return FALSE; + } - /* remove padding */ - blob->len -= padding; - return TRUE; + /* remove padding */ + blob->len -= padding; + return TRUE; } /* @@ -241,74 +241,74 @@ pem_decrypt_3des(chunk_t *blob, chunk_t *iv, const char *passphrase) static err_t pem_decrypt(chunk_t *blob, chunk_t *iv, prompt_pass_t *pass, const char* label) { - DBG(DBG_CRYPT, - DBG_log(" decrypting file using 'DES-EDE3-CBC'"); - ) - if (iv->len != DES_CBC_BLOCK_SIZE) - return "size of DES-EDE3-CBC IV is not 8 bytes"; + DBG(DBG_CRYPT, + DBG_log(" decrypting file using 'DES-EDE3-CBC'"); + ) + if (iv->len != DES_CBC_BLOCK_SIZE) + return "size of DES-EDE3-CBC IV is not 8 bytes"; - if (pass == NULL) - return "no passphrase available"; + if (pass == NULL) + return "no passphrase available"; - /* do we prompt for the passphrase? */ - if (pass->prompt && pass->fd != NULL_FD) - { - int i; - chunk_t blob_copy; - err_t ugh = "invalid passphrase, too many trials"; - - whack_log(RC_ENTERSECRET, "need passphrase for '%s'", label); - - for (i = 0; i < MAX_PROMPT_PASS_TRIALS; i++) + /* do we prompt for the passphrase? */ + if (pass->prompt && pass->fd != NULL_FD) { - int n; + int i; + chunk_t blob_copy; + err_t ugh = "invalid passphrase, too many trials"; - if (i > 0) - whack_log(RC_ENTERSECRET, "invalid passphrase, please try again"); + whack_log(RC_ENTERSECRET, "need passphrase for '%s'", label); - n = read(pass->fd, pass->secret, PROMPT_PASS_LEN); + for (i = 0; i < MAX_PROMPT_PASS_TRIALS; i++) + { + int n; - if (n == -1) - { - err_t ugh = "read(whackfd) failed"; + if (i > 0) + whack_log(RC_ENTERSECRET, "invalid passphrase, please try again"); - whack_log(RC_LOG_SERIOUS,ugh); - return ugh; - } + n = read(pass->fd, pass->secret, PROMPT_PASS_LEN); - pass->secret[n-1] = '\0'; - - if (strlen(pass->secret) == 0) - { - err_t ugh = "no passphrase entered, aborted"; + if (n == -1) + { + err_t ugh = "read(whackfd) failed"; + whack_log(RC_LOG_SERIOUS,ugh); + return ugh; + } + + pass->secret[n-1] = '\0'; + + if (strlen(pass->secret) == 0) + { + err_t ugh = "no passphrase entered, aborted"; + + whack_log(RC_LOG_SERIOUS, ugh); + return ugh; + } + + blob_copy = chunk_clone(*blob); + + if (pem_decrypt_3des(blob, iv, pass->secret)) + { + whack_log(RC_SUCCESS, "valid passphrase"); + free(blob_copy.ptr); + return NULL; + } + + /* blob is useless after wrong decryption, restore the original */ + free(blob->ptr); + *blob = blob_copy; + } whack_log(RC_LOG_SERIOUS, ugh); return ugh; - } - - blob_copy = chunk_clone(*blob); - - if (pem_decrypt_3des(blob, iv, pass->secret)) - { - whack_log(RC_SUCCESS, "valid passphrase"); - free(blob_copy.ptr); - return NULL; - } - - /* blob is useless after wrong decryption, restore the original */ - free(blob->ptr); - *blob = blob_copy; } - whack_log(RC_LOG_SERIOUS, ugh); - return ugh; - } - else - { - if (pem_decrypt_3des(blob, iv, pass->secret)) - return NULL; else - return "invalid passphrase"; - } + { + if (pem_decrypt_3des(blob, iv, pass->secret)) + return NULL; + else + return "invalid passphrase"; + } } /* Converts a PEM encoded file into its binary form @@ -319,144 +319,144 @@ pem_decrypt(chunk_t *blob, chunk_t *iv, prompt_pass_t *pass, const char* label) err_t pemtobin(chunk_t *blob, prompt_pass_t *pass, const char* label, bool *pgp) { - typedef enum { - PEM_PRE = 0, - PEM_MSG = 1, - PEM_HEADER = 2, - PEM_BODY = 3, - PEM_POST = 4, - PEM_ABORT = 5 - } state_t; + typedef enum { + PEM_PRE = 0, + PEM_MSG = 1, + PEM_HEADER = 2, + PEM_BODY = 3, + PEM_POST = 4, + PEM_ABORT = 5 + } state_t; - bool encrypted = FALSE; + bool encrypted = FALSE; - state_t state = PEM_PRE; + state_t state = PEM_PRE; - chunk_t src = *blob; - chunk_t dst = *blob; - chunk_t line = chunk_empty; - chunk_t iv = chunk_empty; + chunk_t src = *blob; + chunk_t dst = *blob; + chunk_t line = chunk_empty; + chunk_t iv = chunk_empty; - u_char iv_buf[MAX_DIGEST_LEN]; + u_char iv_buf[MAX_DIGEST_LEN]; - /* zero size of converted blob */ - dst.len = 0; + /* zero size of converted blob */ + dst.len = 0; - /* zero size of IV */ - iv.ptr = iv_buf; - iv.len = 0; + /* zero size of IV */ + iv.ptr = iv_buf; + iv.len = 0; - while (fetchline(&src, &line)) - { - if (state == PEM_PRE) + while (fetchline(&src, &line)) { - if (find_boundary("BEGIN", &line)) - { - *pgp = FALSE; - state = PEM_MSG; - } - continue; - } - else - { - if (find_boundary("END", &line)) - { - state = PEM_POST; - break; - } - if (state == PEM_MSG) - { - state = (memchr(line.ptr, ':', line.len) == NULL)? - PEM_BODY : PEM_HEADER; - } - if (state == PEM_HEADER) - { - chunk_t name = chunk_empty; - chunk_t value = chunk_empty; - - /* an empty line separates HEADER and BODY */ - if (line.len == 0) + if (state == PEM_PRE) { - state = PEM_BODY; - continue; - } - - /* we are looking for a name: value pair */ - if (!extract_parameter(&name, &value, &line)) - continue; - - if (match("Proc-Type", &name) && *value.ptr == '4') - encrypted = TRUE; - else if (match("DEK-Info", &name)) - { - const char *ugh = NULL; - size_t len = 0; - chunk_t dek; - - if (!extract_token(&dek, ',', &value)) - dek = value; - - /* we support DES-EDE3-CBC encrypted files, only */ - if (!match("DES-EDE3-CBC", &dek)) - return "we support DES-EDE3-CBC encrypted files, only"; - - eat_whitespace(&value); - ugh = ttodata(value.ptr, value.len, 16, - iv.ptr, MAX_DIGEST_LEN, &len); - if (ugh) - return "error in IV"; - - iv.len = len; - } - } - else /* state is PEM_BODY */ - { - const char *ugh = NULL; - size_t len = 0; - chunk_t data; - - /* remove any trailing whitespace */ - if (!extract_token(&data ,' ', &line)) - data = line; - - /* check for PGP armor checksum */ - if (*data.ptr == '=') - { - *pgp = TRUE; - data.ptr++; - data.len--; - DBG(DBG_PARSING, - DBG_log(" Armor checksum: %.*s", (int)data.len, data.ptr); - ) - continue; - } - - ugh = ttodata(data.ptr, data.len, 64, - dst.ptr, blob->len - dst.len, &len); - if (ugh) - { - DBG(DBG_PARSING, - DBG_log(" %s", ugh); - ) - state = PEM_ABORT; - break; + if (find_boundary("BEGIN", &line)) + { + *pgp = FALSE; + state = PEM_MSG; + } + continue; } else { - dst.ptr += len; - dst.len += len; + if (find_boundary("END", &line)) + { + state = PEM_POST; + break; + } + if (state == PEM_MSG) + { + state = (memchr(line.ptr, ':', line.len) == NULL)? + PEM_BODY : PEM_HEADER; + } + if (state == PEM_HEADER) + { + chunk_t name = chunk_empty; + chunk_t value = chunk_empty; + + /* an empty line separates HEADER and BODY */ + if (line.len == 0) + { + state = PEM_BODY; + continue; + } + + /* we are looking for a name: value pair */ + if (!extract_parameter(&name, &value, &line)) + continue; + + if (match("Proc-Type", &name) && *value.ptr == '4') + encrypted = TRUE; + else if (match("DEK-Info", &name)) + { + const char *ugh = NULL; + size_t len = 0; + chunk_t dek; + + if (!extract_token(&dek, ',', &value)) + dek = value; + + /* we support DES-EDE3-CBC encrypted files, only */ + if (!match("DES-EDE3-CBC", &dek)) + return "we support DES-EDE3-CBC encrypted files, only"; + + eat_whitespace(&value); + ugh = ttodata(value.ptr, value.len, 16, + iv.ptr, MAX_DIGEST_LEN, &len); + if (ugh) + return "error in IV"; + + iv.len = len; + } + } + else /* state is PEM_BODY */ + { + const char *ugh = NULL; + size_t len = 0; + chunk_t data; + + /* remove any trailing whitespace */ + if (!extract_token(&data ,' ', &line)) + data = line; + + /* check for PGP armor checksum */ + if (*data.ptr == '=') + { + *pgp = TRUE; + data.ptr++; + data.len--; + DBG(DBG_PARSING, + DBG_log(" Armor checksum: %.*s", (int)data.len, data.ptr); + ) + continue; + } + + ugh = ttodata(data.ptr, data.len, 64, + dst.ptr, blob->len - dst.len, &len); + if (ugh) + { + DBG(DBG_PARSING, + DBG_log(" %s", ugh); + ) + state = PEM_ABORT; + break; + } + else + { + dst.ptr += len; + dst.len += len; + } + } } - } } - } - /* set length to size of binary blob */ - blob->len = dst.len; + /* set length to size of binary blob */ + blob->len = dst.len; - if (state != PEM_POST) - return "file coded in unknown format, discarded"; + if (state != PEM_POST) + return "file coded in unknown format, discarded"; - if (encrypted) - return pem_decrypt(blob, &iv, pass, label); - else - return NULL; + if (encrypted) + return pem_decrypt(blob, &iv, pass, label); + else + return NULL; } diff --git a/src/pluto/pem.h b/src/pluto/pem.h index b87b922e2..889063d62 100644 --- a/src/pluto/pem.h +++ b/src/pluto/pem.h @@ -15,4 +15,4 @@ */ extern err_t pemtobin(chunk_t *blob, prompt_pass_t *pass, const char* label - , bool *pgp); + , bool *pgp); diff --git a/src/pluto/pgp.c b/src/pluto/pgp.c index a3efdad9c..1336ca667 100644 --- a/src/pluto/pgp.c +++ b/src/pluto/pgp.c @@ -41,110 +41,110 @@ static pgpcert_t *pgpcerts = NULL; /* * OpenPGP packet tags defined in section 4.3 of RFC 2440 */ -#define PGP_PKT_RESERVED 0 -#define PGP_PKT_PUBKEY_ENC_SESSION_KEY 1 -#define PGP_PKT_SIGNATURE 2 -#define PGP_PKT_SYMKEY_ENC_SESSION_KEY 3 -#define PGP_PKT_ONE_PASS_SIGNATURE_PKT 4 -#define PGP_PKT_SECRET_KEY 5 -#define PGP_PKT_PUBLIC_KEY 6 -#define PGP_PKT_SECRET_SUBKEY 7 -#define PGP_PKT_COMPRESSED_DATA 8 -#define PGP_PKT_SYMKEY_ENC_DATA 9 -#define PGP_PKT_MARKER 10 -#define PGP_PKT_LITERAL_DATA 11 -#define PGP_PKT_TRUST 12 -#define PGP_PKT_USER_ID 13 -#define PGP_PKT_PUBLIC_SUBKEY 14 -#define PGP_PKT_ROOF 15 +#define PGP_PKT_RESERVED 0 +#define PGP_PKT_PUBKEY_ENC_SESSION_KEY 1 +#define PGP_PKT_SIGNATURE 2 +#define PGP_PKT_SYMKEY_ENC_SESSION_KEY 3 +#define PGP_PKT_ONE_PASS_SIGNATURE_PKT 4 +#define PGP_PKT_SECRET_KEY 5 +#define PGP_PKT_PUBLIC_KEY 6 +#define PGP_PKT_SECRET_SUBKEY 7 +#define PGP_PKT_COMPRESSED_DATA 8 +#define PGP_PKT_SYMKEY_ENC_DATA 9 +#define PGP_PKT_MARKER 10 +#define PGP_PKT_LITERAL_DATA 11 +#define PGP_PKT_TRUST 12 +#define PGP_PKT_USER_ID 13 +#define PGP_PKT_PUBLIC_SUBKEY 14 +#define PGP_PKT_ROOF 15 static const char *const pgp_packet_type_name[] = { - "Reserved", - "Public-Key Encrypted Session Key Packet", - "Signature Packet", - "Symmetric-Key Encrypted Session Key Packet", - "One-Pass Signature Packet", - "Secret Key Packet", - "Public Key Packet", - "Secret Subkey Packet", - "Compressed Data Packet", - "Symmetrically Encrypted Data Packet", - "Marker Packet", - "Literal Data Packet", - "Trust Packet", - "User ID Packet", - "Public Subkey Packet" + "Reserved", + "Public-Key Encrypted Session Key Packet", + "Signature Packet", + "Symmetric-Key Encrypted Session Key Packet", + "One-Pass Signature Packet", + "Secret Key Packet", + "Public Key Packet", + "Secret Subkey Packet", + "Compressed Data Packet", + "Symmetrically Encrypted Data Packet", + "Marker Packet", + "Literal Data Packet", + "Trust Packet", + "User ID Packet", + "Public Subkey Packet" }; /* * OpenPGP public key algorithms defined in section 9.1 of RFC 2440 */ -#define PGP_PUBKEY_ALG_RSA 1 -#define PGP_PUBKEY_ALG_RSA_ENC_ONLY 2 -#define PGP_PUBKEY_ALG_RSA_SIGN_ONLY 3 -#define PGP_PUBKEY_ALG_ELGAMAL_ENC_ONLY 16 -#define PGP_PUBKEY_ALG_DSA 17 -#define PGP_PUBKEY_ALG_ECC 18 -#define PGP_PUBKEY_ALG_ECDSA 19 -#define PGP_PUBKEY_ALG_ELGAMAL 20 +#define PGP_PUBKEY_ALG_RSA 1 +#define PGP_PUBKEY_ALG_RSA_ENC_ONLY 2 +#define PGP_PUBKEY_ALG_RSA_SIGN_ONLY 3 +#define PGP_PUBKEY_ALG_ELGAMAL_ENC_ONLY 16 +#define PGP_PUBKEY_ALG_DSA 17 +#define PGP_PUBKEY_ALG_ECC 18 +#define PGP_PUBKEY_ALG_ECDSA 19 +#define PGP_PUBKEY_ALG_ELGAMAL 20 /* * OpenPGP symmetric key algorithms defined in section 9.2 of RFC 2440 */ -#define PGP_SYM_ALG_PLAIN 0 -#define PGP_SYM_ALG_IDEA 1 -#define PGP_SYM_ALG_3DES 2 -#define PGP_SYM_ALG_CAST5 3 -#define PGP_SYM_ALG_BLOWFISH 4 -#define PGP_SYM_ALG_SAFER 5 -#define PGP_SYM_ALG_DES 6 -#define PGP_SYM_ALG_AES 7 -#define PGP_SYM_ALG_AES_192 8 -#define PGP_SYM_ALG_AES_256 9 -#define PGP_SYM_ALG_TWOFISH 10 -#define PGP_SYM_ALG_ROOF 11 +#define PGP_SYM_ALG_PLAIN 0 +#define PGP_SYM_ALG_IDEA 1 +#define PGP_SYM_ALG_3DES 2 +#define PGP_SYM_ALG_CAST5 3 +#define PGP_SYM_ALG_BLOWFISH 4 +#define PGP_SYM_ALG_SAFER 5 +#define PGP_SYM_ALG_DES 6 +#define PGP_SYM_ALG_AES 7 +#define PGP_SYM_ALG_AES_192 8 +#define PGP_SYM_ALG_AES_256 9 +#define PGP_SYM_ALG_TWOFISH 10 +#define PGP_SYM_ALG_ROOF 11 static const char *const pgp_sym_alg_name[] = { - "Plaintext", - "IDEA", - "3DES", - "CAST5", - "Blowfish", - "SAFER", - "DES", - "AES", - "AES-192", - "AES-256", - "Twofish" + "Plaintext", + "IDEA", + "3DES", + "CAST5", + "Blowfish", + "SAFER", + "DES", + "AES", + "AES-192", + "AES-256", + "Twofish" }; /* * Size of PGP Key ID */ -#define PGP_KEYID_SIZE 8 +#define PGP_KEYID_SIZE 8 const pgpcert_t empty_pgpcert = { - NULL , /* *next */ - 0 , /* installed */ - 0 , /* count */ - { NULL, 0 }, /* certificate */ - 0 , /* created */ - 0 , /* until */ - 0 , /* pubkeyAlgorithm */ - { NULL, 0 }, /* modulus */ - { NULL, 0 }, /* publicExponent */ - "" /* fingerprint */ + NULL , /* *next */ + 0 , /* installed */ + 0 , /* count */ + { NULL, 0 }, /* certificate */ + 0 , /* created */ + 0 , /* until */ + 0 , /* pubkeyAlgorithm */ + { NULL, 0 }, /* modulus */ + { NULL, 0 }, /* publicExponent */ + "" /* fingerprint */ }; static size_t pgp_size(chunk_t *blob, int len) { - size_t size = 0; + size_t size = 0; - blob->len -= len; - while (len-- > 0) - size = 256*size + *blob->ptr++; - return size; + blob->len -= len; + while (len-- > 0) + size = 256*size + *blob->ptr++; + return size; } /* @@ -153,13 +153,13 @@ pgp_size(chunk_t *blob, int len) static size_t pgp_old_packet_length(chunk_t *blob) { - /* bits 0 and 1 define the packet length type */ - int len_type = 0x03 & *blob->ptr++; + /* bits 0 and 1 define the packet length type */ + int len_type = 0x03 & *blob->ptr++; - blob->len--; + blob->len--; - /* len_type: 0 -> 1 byte, 1 -> 2 bytes, 2 -> 4 bytes */ - return pgp_size(blob, (len_type == 0)? 1: len_type << 1); + /* len_type: 0 -> 1 byte, 1 -> 2 bytes, 2 -> 4 bytes */ + return pgp_size(blob, (len_type == 0)? 1: len_type << 1); } /* @@ -168,13 +168,13 @@ pgp_old_packet_length(chunk_t *blob) static u_char pgp_version(chunk_t *blob) { - u_char version = *blob->ptr++; - blob->len--; - DBG(DBG_PARSING, - DBG_log("L3 - version:"); - DBG_log(" V%d", version) - ) - return version; + u_char version = *blob->ptr++; + blob->len--; + DBG(DBG_PARSING, + DBG_log("L3 - version:"); + DBG_log(" V%d", version) + ) + return version; } /* @@ -183,99 +183,99 @@ pgp_version(chunk_t *blob) static bool parse_pgp_pubkey_packet(chunk_t *packet, pgpcert_t *cert) { - u_char version = pgp_version(packet); + u_char version = pgp_version(packet); - if (version < 3 || version > 4) - { - plog("PGP packet version V%d not supported", version); - return FALSE; - } - - /* creation date - 4 bytes */ - cert->created = (time_t)pgp_size(packet, 4); - DBG(DBG_PARSING, - DBG_log("L3 - created:"); - DBG_log(" %T", &cert->created, TRUE) - ) - - if (version == 3) - { - /* validity in days - 2 bytes */ - cert->until = (time_t)pgp_size(packet, 2); - - /* validity of 0 days means that the key never expires */ - if (cert->until > 0) - cert->until = cert->created + 24*3600*cert->until; + if (version < 3 || version > 4) + { + plog("PGP packet version V%d not supported", version); + return FALSE; + } + /* creation date - 4 bytes */ + cert->created = (time_t)pgp_size(packet, 4); DBG(DBG_PARSING, - DBG_log("L3 - until:"); - DBG_log(" %T", &cert->until, TRUE); + DBG_log("L3 - created:"); + DBG_log(" %T", &cert->created, TRUE) ) - } - - /* public key algorithm - 1 byte */ - DBG(DBG_PARSING, - DBG_log("L3 - public key algorithm:") - ) - - switch (pgp_size(packet, 1)) - { - case PGP_PUBKEY_ALG_RSA: - case PGP_PUBKEY_ALG_RSA_SIGN_ONLY: - cert->pubkeyAlg = PUBKEY_ALG_RSA; - DBG(DBG_PARSING, - DBG_log(" RSA") - ) - /* modulus n */ - cert->modulus.len = (pgp_size(packet, 2)+7) / BITS_PER_BYTE; - cert->modulus.ptr = packet->ptr; - packet->ptr += cert->modulus.len; - packet->len -= cert->modulus.len; - DBG(DBG_PARSING, - DBG_log("L3 - modulus:") - ) - DBG_cond_dump_chunk(DBG_RAW, "", cert->modulus); - - /* public exponent e */ - cert->publicExponent.len = (pgp_size(packet, 2)+7) / BITS_PER_BYTE; - cert->publicExponent.ptr = packet->ptr; - packet->ptr += cert->publicExponent.len; - packet->len -= cert->publicExponent.len; - DBG(DBG_PARSING, - DBG_log("L3 - public exponent:") - ) - DBG_cond_dump_chunk(DBG_RAW, "", cert->publicExponent); if (version == 3) { - /* a V3 fingerprint is the MD5 hash of modulus and public exponent */ - MD5_CTX context; - MD5Init(&context); - MD5Update(&context, cert->modulus.ptr, cert->modulus.len); - MD5Update(&context, cert->publicExponent.ptr, cert->publicExponent.len); - MD5Final(cert->fingerprint, &context); + /* validity in days - 2 bytes */ + cert->until = (time_t)pgp_size(packet, 2); + + /* validity of 0 days means that the key never expires */ + if (cert->until > 0) + cert->until = cert->created + 24*3600*cert->until; + + DBG(DBG_PARSING, + DBG_log("L3 - until:"); + DBG_log(" %T", &cert->until, TRUE); + ) } - else + + /* public key algorithm - 1 byte */ + DBG(DBG_PARSING, + DBG_log("L3 - public key algorithm:") + ) + + switch (pgp_size(packet, 1)) { - plog(" computation of V4 key ID not implemented yet"); + case PGP_PUBKEY_ALG_RSA: + case PGP_PUBKEY_ALG_RSA_SIGN_ONLY: + cert->pubkeyAlg = PUBKEY_ALG_RSA; + DBG(DBG_PARSING, + DBG_log(" RSA") + ) + /* modulus n */ + cert->modulus.len = (pgp_size(packet, 2)+7) / BITS_PER_BYTE; + cert->modulus.ptr = packet->ptr; + packet->ptr += cert->modulus.len; + packet->len -= cert->modulus.len; + DBG(DBG_PARSING, + DBG_log("L3 - modulus:") + ) + DBG_cond_dump_chunk(DBG_RAW, "", cert->modulus); + + /* public exponent e */ + cert->publicExponent.len = (pgp_size(packet, 2)+7) / BITS_PER_BYTE; + cert->publicExponent.ptr = packet->ptr; + packet->ptr += cert->publicExponent.len; + packet->len -= cert->publicExponent.len; + DBG(DBG_PARSING, + DBG_log("L3 - public exponent:") + ) + DBG_cond_dump_chunk(DBG_RAW, "", cert->publicExponent); + + if (version == 3) + { + /* a V3 fingerprint is the MD5 hash of modulus and public exponent */ + MD5_CTX context; + MD5Init(&context); + MD5Update(&context, cert->modulus.ptr, cert->modulus.len); + MD5Update(&context, cert->publicExponent.ptr, cert->publicExponent.len); + MD5Final(cert->fingerprint, &context); + } + else + { + plog(" computation of V4 key ID not implemented yet"); + } + break; + case PGP_PUBKEY_ALG_DSA: + cert->pubkeyAlg = PUBKEY_ALG_DSA; + DBG(DBG_PARSING, + DBG_log(" DSA") + ) + plog(" DSA public keys not supported"); + return FALSE; + default: + cert->pubkeyAlg = 0; + DBG(DBG_PARSING, + DBG_log(" other") + ) + plog(" exotic not RSA public keys not supported"); + return FALSE; } - break; - case PGP_PUBKEY_ALG_DSA: - cert->pubkeyAlg = PUBKEY_ALG_DSA; - DBG(DBG_PARSING, - DBG_log(" DSA") - ) - plog(" DSA public keys not supported"); - return FALSE; - default: - cert->pubkeyAlg = 0; - DBG(DBG_PARSING, - DBG_log(" other") - ) - plog(" exotic not RSA public keys not supported"); - return FALSE; - } - return TRUE; + return TRUE; } /* @@ -284,91 +284,91 @@ parse_pgp_pubkey_packet(chunk_t *packet, pgpcert_t *cert) static bool parse_pgp_secretkey_packet(chunk_t *packet, RSA_private_key_t *key) { - int i, s2k; - pgpcert_t cert = empty_pgpcert; + int i, s2k; + pgpcert_t cert = empty_pgpcert; - if (!parse_pgp_pubkey_packet(packet, &cert)) - return FALSE; + if (!parse_pgp_pubkey_packet(packet, &cert)) + return FALSE; - init_RSA_public_key((RSA_public_key_t *)key, cert.publicExponent - , cert.modulus); + init_RSA_public_key((RSA_public_key_t *)key, cert.publicExponent + , cert.modulus); - /* string-to-key usage */ - s2k = pgp_size(packet, 1); + /* string-to-key usage */ + s2k = pgp_size(packet, 1); - DBG(DBG_PARSING, - DBG_log("L3 - string-to-key: %d", s2k) - ) + DBG(DBG_PARSING, + DBG_log("L3 - string-to-key: %d", s2k) + ) - if (s2k == 255) - { - plog(" string-to-key specifiers not supported"); - return FALSE; - } - - if (s2k >= PGP_SYM_ALG_ROOF) - { - plog(" undefined symmetric key algorithm"); - return FALSE; - } - - /* a known symmetric key algorithm is specified*/ - DBG(DBG_PARSING, - DBG_log(" %s", pgp_sym_alg_name[s2k]) - ) - - /* private key is unencrypted */ - if (s2k == PGP_SYM_ALG_PLAIN) - { - for (i = 2; i < RSA_PRIVATE_FIELD_ELEMENTS; i++) + if (s2k == 255) { - mpz_t u; /* auxiliary variable */ - - /* compute offset to private key component i*/ - MP_INT *n = (MP_INT*)((char *)key + RSA_private_field[i].offset); - - switch (i) - { - case 2: - case 3: - case 4: - { - size_t len = (pgp_size(packet, 2)+7) / BITS_PER_BYTE; - - n_to_mpz(n, packet->ptr, len); - DBG(DBG_PARSING, - DBG_log("L3 - %s:", RSA_private_field[i].name) - ) - DBG_cond_dump(DBG_PRIVATE, "", packet->ptr, len); - packet->ptr += len; - packet->len -= len; - } - break; - case 5: /* dP = d mod (p-1) */ - mpz_init(u); - mpz_sub_ui(u, &key->p, 1); - mpz_mod(n, &key->d, u); - mpz_clear(u); - break; - case 6: /* dQ = d mod (q-1) */ - mpz_init(u); - mpz_sub_ui(u, &key->q, 1); - mpz_mod(n, &key->d, u); - mpz_clear(u); - break; - case 7: /* qInv = (q^-1) mod p */ - mpz_invert(n, &key->q, &key->p); - if (mpz_cmp_ui(n, 0) < 0) - mpz_add(n, n, &key->p); - passert(mpz_cmp(n, &key->p) < 0); - break; - } + plog(" string-to-key specifiers not supported"); + return FALSE; } - return TRUE; - } - plog(" %s encryption not supported", pgp_sym_alg_name[s2k]); - return FALSE; + if (s2k >= PGP_SYM_ALG_ROOF) + { + plog(" undefined symmetric key algorithm"); + return FALSE; + } + + /* a known symmetric key algorithm is specified*/ + DBG(DBG_PARSING, + DBG_log(" %s", pgp_sym_alg_name[s2k]) + ) + + /* private key is unencrypted */ + if (s2k == PGP_SYM_ALG_PLAIN) + { + for (i = 2; i < RSA_PRIVATE_FIELD_ELEMENTS; i++) + { + mpz_t u; /* auxiliary variable */ + + /* compute offset to private key component i*/ + MP_INT *n = (MP_INT*)((char *)key + RSA_private_field[i].offset); + + switch (i) + { + case 2: + case 3: + case 4: + { + size_t len = (pgp_size(packet, 2)+7) / BITS_PER_BYTE; + + n_to_mpz(n, packet->ptr, len); + DBG(DBG_PARSING, + DBG_log("L3 - %s:", RSA_private_field[i].name) + ) + DBG_cond_dump(DBG_PRIVATE, "", packet->ptr, len); + packet->ptr += len; + packet->len -= len; + } + break; + case 5: /* dP = d mod (p-1) */ + mpz_init(u); + mpz_sub_ui(u, &key->p, 1); + mpz_mod(n, &key->d, u); + mpz_clear(u); + break; + case 6: /* dQ = d mod (q-1) */ + mpz_init(u); + mpz_sub_ui(u, &key->q, 1); + mpz_mod(n, &key->d, u); + mpz_clear(u); + break; + case 7: /* qInv = (q^-1) mod p */ + mpz_invert(n, &key->q, &key->p); + if (mpz_cmp_ui(n, 0) < 0) + mpz_add(n, n, &key->p); + passert(mpz_cmp(n, &key->p) < 0); + break; + } + } + return TRUE; + } + + plog(" %s encryption not supported", pgp_sym_alg_name[s2k]); + return FALSE; } /* @@ -377,39 +377,39 @@ parse_pgp_secretkey_packet(chunk_t *packet, RSA_private_key_t *key) static bool parse_pgp_signature_packet(chunk_t *packet, pgpcert_t *cert) { - time_t created; - chunk_t keyid; - u_char sig_type; - u_char version = pgp_version(packet); + time_t created; + chunk_t keyid; + u_char sig_type; + u_char version = pgp_version(packet); - /* we parse only V3 signature packets */ - if (version != 3) - return TRUE; + /* we parse only V3 signature packets */ + if (version != 3) + return TRUE; - /* size byte must have the value 5 */ - if (pgp_size(packet, 1) != 5) - { - plog(" size must be 5"); - return FALSE; - } + /* size byte must have the value 5 */ + if (pgp_size(packet, 1) != 5) + { + plog(" size must be 5"); + return FALSE; + } - /* signature type - 1 byte */ - sig_type = (u_char)pgp_size(packet, 1); - DBG(DBG_PARSING, - DBG_log("L3 - signature type: 0x%2x", sig_type) - ) + /* signature type - 1 byte */ + sig_type = (u_char)pgp_size(packet, 1); + DBG(DBG_PARSING, + DBG_log("L3 - signature type: 0x%2x", sig_type) + ) - /* creation date - 4 bytes */ - created = (time_t)pgp_size(packet, 4); - DBG(DBG_PARSING, - DBG_log("L3 - created:"); - DBG_log(" %T", &cert->created, TRUE) - ) + /* creation date - 4 bytes */ + created = (time_t)pgp_size(packet, 4); + DBG(DBG_PARSING, + DBG_log("L3 - created:"); + DBG_log(" %T", &cert->created, TRUE) + ) - /* key ID of signer - 8 bytes */ - keyid.ptr = packet->ptr; - keyid.len = PGP_KEYID_SIZE; - DBG_cond_dump_chunk(DBG_PARSING, "L3 - key ID of signer", keyid); + /* key ID of signer - 8 bytes */ + keyid.ptr = packet->ptr; + keyid.len = PGP_KEYID_SIZE; + DBG_cond_dump_chunk(DBG_PARSING, "L3 - key ID of signer", keyid); return TRUE; } @@ -417,101 +417,101 @@ parse_pgp_signature_packet(chunk_t *packet, pgpcert_t *cert) bool parse_pgp(chunk_t blob, pgpcert_t *cert, RSA_private_key_t *key) { - DBG(DBG_PARSING, - DBG_log("L0 - PGP file:") - ) - DBG_cond_dump_chunk(DBG_RAW, "", blob); - - if (cert != NULL) - { - /* parse a PGP certificate file */ - cert->certificate = blob; - time(&cert->installed); - } - else if (key == NULL) - { - /* should not occur, nothing to parse */ - return FALSE; - } - - while (blob.len > 0) - { - chunk_t packet = chunk_empty; - u_char packet_tag = *blob.ptr; - DBG(DBG_PARSING, - DBG_log("L1 - PGP packet: tag= 0x%2x", packet_tag) + DBG_log("L0 - PGP file:") ) + DBG_cond_dump_chunk(DBG_RAW, "", blob); - /* bit 7 must be set */ - if (!(packet_tag & 0x80)) + if (cert != NULL) { - plog(" incorrect Packet Tag"); - return FALSE; + /* parse a PGP certificate file */ + cert->certificate = blob; + time(&cert->installed); + } + else if (key == NULL) + { + /* should not occur, nothing to parse */ + return FALSE; } - /* bit 6 set defines new packet format */ - if (packet_tag & 0x40) + while (blob.len > 0) { - plog(" new PGP packet format not supported"); - return FALSE; - } - else - { - int packet_type = (packet_tag & 0x3C) >> 2; + chunk_t packet = chunk_empty; + u_char packet_tag = *blob.ptr; - packet.len = pgp_old_packet_length(&blob); - packet.ptr = blob.ptr; - blob.ptr += packet.len; - blob.len -= packet.len; - DBG(DBG_PARSING, - DBG_log(" %s (%d), old format, %d bytes", - (packet_type < PGP_PKT_ROOF) ? - pgp_packet_type_name[packet_type] : - "Undefined Packet Type", packet_type, (int)packet.len); - DBG_log("L2 - body:") - ) - DBG_cond_dump_chunk(DBG_RAW, "", packet); + DBG(DBG_PARSING, + DBG_log("L1 - PGP packet: tag= 0x%2x", packet_tag) + ) - if (cert != NULL) - { - /* parse a PGP certificate */ - switch (packet_type) + /* bit 7 must be set */ + if (!(packet_tag & 0x80)) { - case PGP_PKT_PUBLIC_KEY: - if (!parse_pgp_pubkey_packet(&packet, cert)) + plog(" incorrect Packet Tag"); return FALSE; - break; - case PGP_PKT_SIGNATURE: - if (!parse_pgp_signature_packet(&packet, cert)) - return FALSE; - break; - case PGP_PKT_USER_ID: - DBG(DBG_PARSING, - DBG_log("L3 - user ID:"); - DBG_log(" '%.*s'", (int)packet.len, packet.ptr) - ) - break; - default: - break; } - } - else - { - /* parse a PGP private key file */ - switch (packet_type) + + /* bit 6 set defines new packet format */ + if (packet_tag & 0x40) { - case PGP_PKT_SECRET_KEY: - if (!parse_pgp_secretkey_packet(&packet, key)) + plog(" new PGP packet format not supported"); return FALSE; - break; - default: - break; } - } + else + { + int packet_type = (packet_tag & 0x3C) >> 2; + + packet.len = pgp_old_packet_length(&blob); + packet.ptr = blob.ptr; + blob.ptr += packet.len; + blob.len -= packet.len; + DBG(DBG_PARSING, + DBG_log(" %s (%d), old format, %d bytes", + (packet_type < PGP_PKT_ROOF) ? + pgp_packet_type_name[packet_type] : + "Undefined Packet Type", packet_type, (int)packet.len); + DBG_log("L2 - body:") + ) + DBG_cond_dump_chunk(DBG_RAW, "", packet); + + if (cert != NULL) + { + /* parse a PGP certificate */ + switch (packet_type) + { + case PGP_PKT_PUBLIC_KEY: + if (!parse_pgp_pubkey_packet(&packet, cert)) + return FALSE; + break; + case PGP_PKT_SIGNATURE: + if (!parse_pgp_signature_packet(&packet, cert)) + return FALSE; + break; + case PGP_PKT_USER_ID: + DBG(DBG_PARSING, + DBG_log("L3 - user ID:"); + DBG_log(" '%.*s'", (int)packet.len, packet.ptr) + ) + break; + default: + break; + } + } + else + { + /* parse a PGP private key file */ + switch (packet_type) + { + case PGP_PKT_SECRET_KEY: + if (!parse_pgp_secretkey_packet(&packet, key)) + return FALSE; + break; + default: + break; + } + } + } } - } - return TRUE; + return TRUE; } /* @@ -520,8 +520,8 @@ parse_pgp(chunk_t blob, pgpcert_t *cert, RSA_private_key_t *key) static bool same_pgpcert(pgpcert_t *a, pgpcert_t *b) { - return a->certificate.len == b->certificate.len && - memeq(a->certificate.ptr, b->certificate.ptr, b->certificate.len); + return a->certificate.len == b->certificate.len && + memeq(a->certificate.ptr, b->certificate.ptr, b->certificate.len); } /* @@ -530,10 +530,10 @@ same_pgpcert(pgpcert_t *a, pgpcert_t *b) void share_pgpcert(pgpcert_t *cert) { - if (cert != NULL) - { - cert->count++; - } + if (cert != NULL) + { + cert->count++; + } } /* @@ -542,11 +542,11 @@ share_pgpcert(pgpcert_t *cert) void select_pgpcert_id(pgpcert_t *cert, struct id *end_id) { - end_id->kind = ID_KEY_ID; - end_id->name.len = PGP_FINGERPRINT_SIZE; - end_id->name.ptr = cert->fingerprint; - end_id->name.ptr = temporary_cyclic_buffer(); - memcpy(end_id->name.ptr, cert->fingerprint, PGP_FINGERPRINT_SIZE); + end_id->kind = ID_KEY_ID; + end_id->name.len = PGP_FINGERPRINT_SIZE; + end_id->name.ptr = cert->fingerprint; + end_id->name.ptr = temporary_cyclic_buffer(); + memcpy(end_id->name.ptr, cert->fingerprint, PGP_FINGERPRINT_SIZE); } /* @@ -555,25 +555,25 @@ select_pgpcert_id(pgpcert_t *cert, struct id *end_id) pgpcert_t* add_pgpcert(pgpcert_t *cert) { - pgpcert_t *c = pgpcerts; + pgpcert_t *c = pgpcerts; - while (c != NULL) - { - if (same_pgpcert(c, cert)) /* already in chain, free cert */ + while (c != NULL) { - free_pgpcert(cert); - return c; + if (same_pgpcert(c, cert)) /* already in chain, free cert */ + { + free_pgpcert(cert); + return c; + } + c = c->next; } - c = c->next; - } - /* insert new cert at the root of the chain */ - cert->next = pgpcerts; - pgpcerts = cert; - DBG(DBG_CONTROL | DBG_PARSING, - DBG_log(" pgp cert inserted") - ) - return cert; + /* insert new cert at the root of the chain */ + cert->next = pgpcerts; + pgpcerts = cert; + DBG(DBG_CONTROL | DBG_PARSING, + DBG_log(" pgp cert inserted") + ) + return cert; } /* release of a certificate decreases the count by one @@ -582,14 +582,14 @@ add_pgpcert(pgpcert_t *cert) void release_pgpcert(pgpcert_t *cert) { - if (cert != NULL && --cert->count == 0) - { - pgpcert_t **pp = &pgpcerts; - while (*pp != cert) - pp = &(*pp)->next; - *pp = cert->next; - free_pgpcert(cert); - } + if (cert != NULL && --cert->count == 0) + { + pgpcert_t **pp = &pgpcerts; + while (*pp != cert) + pp = &(*pp)->next; + *pp = cert->next; + free_pgpcert(cert); + } } /* @@ -598,11 +598,11 @@ release_pgpcert(pgpcert_t *cert) void free_pgpcert(pgpcert_t *cert) { - if (cert != NULL) - { - free(cert->certificate.ptr); - free(cert); - } + if (cert != NULL) + { + free(cert->certificate.ptr); + free(cert); + } } /* @@ -614,35 +614,35 @@ list_pgp_end_certs(bool utc) pgpcert_t *cert = pgpcerts; time_t now; - /* determine the current time */ - time(&now); + /* determine the current time */ + time(&now); - if (cert != NULL) - { - whack_log(RC_COMMENT, " "); - whack_log(RC_COMMENT, "List of PGP End certificates:"); - whack_log(RC_COMMENT, " "); - } + if (cert != NULL) + { + whack_log(RC_COMMENT, " "); + whack_log(RC_COMMENT, "List of PGP End certificates:"); + whack_log(RC_COMMENT, " "); + } - while (cert != NULL) - { - unsigned keysize; - char buf[BUF_LEN]; - cert_t c; + while (cert != NULL) + { + unsigned keysize; + char buf[BUF_LEN]; + cert_t c; - c.type = CERT_PGP; - c.u.pgp = cert; + c.type = CERT_PGP; + c.u.pgp = cert; - whack_log(RC_COMMENT, "%T, count: %d", &cert->installed, utc), cert->count; - datatot(cert->fingerprint, PGP_FINGERPRINT_SIZE, 'x', buf, BUF_LEN); - whack_log(RC_COMMENT, " fingerprint: %s", buf); - form_keyid(cert->publicExponent, cert->modulus, buf, &keysize); - whack_log(RC_COMMENT, " pubkey: %4d RSA Key %s%s", 8*keysize, buf, - (has_private_key(c))? ", has private key" : ""); - whack_log(RC_COMMENT, " created: %T", &cert->created, utc); - whack_log(RC_COMMENT, " until: %T %s", &cert->until, utc, - check_expiry(cert->until, CA_CERT_WARNING_INTERVAL, TRUE)); - cert = cert->next; - } + whack_log(RC_COMMENT, "%T, count: %d", &cert->installed, utc), cert->count; + datatot(cert->fingerprint, PGP_FINGERPRINT_SIZE, 'x', buf, BUF_LEN); + whack_log(RC_COMMENT, " fingerprint: %s", buf); + form_keyid(cert->publicExponent, cert->modulus, buf, &keysize); + whack_log(RC_COMMENT, " pubkey: %4d RSA Key %s%s", 8*keysize, buf, + (has_private_key(c))? ", has private key" : ""); + whack_log(RC_COMMENT, " created: %T", &cert->created, utc); + whack_log(RC_COMMENT, " until: %T %s", &cert->until, utc, + check_expiry(cert->until, CA_CERT_WARNING_INTERVAL, TRUE)); + cert = cert->next; + } } diff --git a/src/pluto/pgp.h b/src/pluto/pgp.h index 6d717fa4d..929792fe0 100644 --- a/src/pluto/pgp.h +++ b/src/pluto/pgp.h @@ -21,7 +21,7 @@ /* * Length of PGP V3 fingerprint */ -#define PGP_FINGERPRINT_SIZE MD5_DIGEST_SIZE +#define PGP_FINGERPRINT_SIZE MD5_DIGEST_SIZE typedef char fingerprint_t[PGP_FINGERPRINT_SIZE]; @@ -30,16 +30,16 @@ typedef char fingerprint_t[PGP_FINGERPRINT_SIZE]; typedef struct pgpcert pgpcert_t; struct pgpcert { - pgpcert_t *next; - time_t installed; - int count; - chunk_t certificate; - time_t created; - time_t until; + pgpcert_t *next; + time_t installed; + int count; + chunk_t certificate; + time_t created; + time_t until; enum pubkey_alg pubkeyAlg; - chunk_t modulus; - chunk_t publicExponent; - fingerprint_t fingerprint; + chunk_t modulus; + chunk_t publicExponent; + fingerprint_t fingerprint; }; extern const pgpcert_t empty_pgpcert; diff --git a/src/pluto/pkcs1.c b/src/pluto/pkcs1.c index 842896bf9..b7ef1072a 100644 --- a/src/pluto/pkcs1.c +++ b/src/pluto/pkcs1.c @@ -37,44 +37,44 @@ const struct fld RSA_private_field[] = { - { "Modulus", offsetof(RSA_private_key_t, pub.n) }, - { "PublicExponent", offsetof(RSA_private_key_t, pub.e) }, + { "Modulus", offsetof(RSA_private_key_t, pub.n) }, + { "PublicExponent", offsetof(RSA_private_key_t, pub.e) }, - { "PrivateExponent", offsetof(RSA_private_key_t, d) }, - { "Prime1", offsetof(RSA_private_key_t, p) }, - { "Prime2", offsetof(RSA_private_key_t, q) }, - { "Exponent1", offsetof(RSA_private_key_t, dP) }, - { "Exponent2", offsetof(RSA_private_key_t, dQ) }, - { "Coefficient", offsetof(RSA_private_key_t, qInv) }, + { "PrivateExponent", offsetof(RSA_private_key_t, d) }, + { "Prime1", offsetof(RSA_private_key_t, p) }, + { "Prime2", offsetof(RSA_private_key_t, q) }, + { "Exponent1", offsetof(RSA_private_key_t, dP) }, + { "Exponent2", offsetof(RSA_private_key_t, dQ) }, + { "Coefficient", offsetof(RSA_private_key_t, qInv) }, }; /* ASN.1 definition of a PKCS#1 RSA private key */ static const asn1Object_t privkeyObjects[] = { - { 0, "RSAPrivateKey", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */ - { 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 2 */ - { 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 3 */ - { 1, "privateExponent", ASN1_INTEGER, ASN1_BODY }, /* 4 */ - { 1, "prime1", ASN1_INTEGER, ASN1_BODY }, /* 5 */ - { 1, "prime2", ASN1_INTEGER, ASN1_BODY }, /* 6 */ - { 1, "exponent1", ASN1_INTEGER, ASN1_BODY }, /* 7 */ - { 1, "exponent2", ASN1_INTEGER, ASN1_BODY }, /* 8 */ - { 1, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 9 */ - { 1, "otherPrimeInfos", ASN1_SEQUENCE, ASN1_OPT | - ASN1_LOOP }, /* 10 */ - { 2, "otherPrimeInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 11 */ - { 3, "prime", ASN1_INTEGER, ASN1_BODY }, /* 12 */ - { 3, "exponent", ASN1_INTEGER, ASN1_BODY }, /* 13 */ - { 3, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 14 */ - { 1, "end opt or loop", ASN1_EOC, ASN1_END } /* 15 */ + { 0, "RSAPrivateKey", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ + { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */ + { 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 2 */ + { 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 3 */ + { 1, "privateExponent", ASN1_INTEGER, ASN1_BODY }, /* 4 */ + { 1, "prime1", ASN1_INTEGER, ASN1_BODY }, /* 5 */ + { 1, "prime2", ASN1_INTEGER, ASN1_BODY }, /* 6 */ + { 1, "exponent1", ASN1_INTEGER, ASN1_BODY }, /* 7 */ + { 1, "exponent2", ASN1_INTEGER, ASN1_BODY }, /* 8 */ + { 1, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 9 */ + { 1, "otherPrimeInfos", ASN1_SEQUENCE, ASN1_OPT | + ASN1_LOOP }, /* 10 */ + { 2, "otherPrimeInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 11 */ + { 3, "prime", ASN1_INTEGER, ASN1_BODY }, /* 12 */ + { 3, "exponent", ASN1_INTEGER, ASN1_BODY }, /* 13 */ + { 3, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 14 */ + { 1, "end opt or loop", ASN1_EOC, ASN1_END } /* 15 */ }; -#define PKCS1_PRIV_KEY_VERSION 1 -#define PKCS1_PRIV_KEY_MODULUS 2 -#define PKCS1_PRIV_KEY_PUB_EXP 3 -#define PKCS1_PRIV_KEY_COEFF 9 -#define PKCS1_PRIV_KEY_ROOF 16 +#define PKCS1_PRIV_KEY_VERSION 1 +#define PKCS1_PRIV_KEY_MODULUS 2 +#define PKCS1_PRIV_KEY_PUB_EXP 3 +#define PKCS1_PRIV_KEY_COEFF 9 +#define PKCS1_PRIV_KEY_ROOF 16 /* @@ -83,18 +83,18 @@ static const asn1Object_t privkeyObjects[] = { void form_keyid(chunk_t e, chunk_t n, char* keyid, unsigned *keysize) { - /* eliminate leading zero bytes in modulus from ASN.1 coding */ - while (n.len > 1 && *n.ptr == 0x00) - { - n.ptr++; n.len--; - } + /* eliminate leading zero bytes in modulus from ASN.1 coding */ + while (n.len > 1 && *n.ptr == 0x00) + { + n.ptr++; n.len--; + } - /* form the FreeS/WAN keyid */ - keyid[0] = '\0'; /* in case of splitkeytoid failure */ - splitkeytoid(e.ptr, e.len, n.ptr, n.len, keyid, KEYID_BUF); + /* form the FreeS/WAN keyid */ + keyid[0] = '\0'; /* in case of splitkeytoid failure */ + splitkeytoid(e.ptr, e.len, n.ptr, n.len, keyid, KEYID_BUF); - /* return the RSA modulus size in octets */ - *keysize = n.len; + /* return the RSA modulus size in octets */ + *keysize = n.len; } /* @@ -103,127 +103,127 @@ form_keyid(chunk_t e, chunk_t n, char* keyid, unsigned *keysize) void init_RSA_public_key(RSA_public_key_t *rsa, chunk_t e, chunk_t n) { - n_to_mpz(&rsa->e, e.ptr, e.len); - n_to_mpz(&rsa->n, n.ptr, n.len); + n_to_mpz(&rsa->e, e.ptr, e.len); + n_to_mpz(&rsa->n, n.ptr, n.len); - form_keyid(e, n, rsa->keyid, &rsa->k); + form_keyid(e, n, rsa->keyid, &rsa->k); } #ifdef DEBUG static void RSA_show_key_fields(RSA_private_key_t *k, int fieldcnt) { - const struct fld *p; + const struct fld *p; - DBG_log(" keyid: *%s", k->pub.keyid); + DBG_log(" keyid: *%s", k->pub.keyid); - for (p = RSA_private_field; p < &RSA_private_field[fieldcnt]; p++) - { - MP_INT *n = (MP_INT *) ((char *)k + p->offset); - size_t sz = mpz_sizeinbase(n, 16); - char buf[RSA_MAX_OCTETS * 2 + 2]; /* ought to be big enough */ + for (p = RSA_private_field; p < &RSA_private_field[fieldcnt]; p++) + { + MP_INT *n = (MP_INT *) ((char *)k + p->offset); + size_t sz = mpz_sizeinbase(n, 16); + char buf[RSA_MAX_OCTETS * 2 + 2]; /* ought to be big enough */ - passert(sz <= sizeof(buf)); - mpz_get_str(buf, 16, n); + passert(sz <= sizeof(buf)); + mpz_get_str(buf, 16, n); - DBG_log(" %s: 0x%s", p->name, buf); - } + DBG_log(" %s: 0x%s", p->name, buf); + } } /* debugging info that compromises security! */ void RSA_show_private_key(RSA_private_key_t *k) { - RSA_show_key_fields(k, countof(RSA_private_field)); + RSA_show_key_fields(k, countof(RSA_private_field)); } void RSA_show_public_key(RSA_public_key_t *k) { - /* Kludge: pretend that it is a private key, but only display the - * first two fields (which are the public key). - */ - passert(offsetof(RSA_private_key_t, pub) == 0); - RSA_show_key_fields((RSA_private_key_t *)k, 2); + /* Kludge: pretend that it is a private key, but only display the + * first two fields (which are the public key). + */ + passert(offsetof(RSA_private_key_t, pub) == 0); + RSA_show_key_fields((RSA_private_key_t *)k, 2); } #endif err_t RSA_private_key_sanity(RSA_private_key_t *k) { - /* note that the *last* error found is reported */ - err_t ugh = NULL; - mpz_t t, u, q1; + /* note that the *last* error found is reported */ + err_t ugh = NULL; + mpz_t t, u, q1; -#ifdef DEBUG /* debugging info that compromises security */ - DBG(DBG_PRIVATE, RSA_show_private_key(k)); +#ifdef DEBUG /* debugging info that compromises security */ + DBG(DBG_PRIVATE, RSA_show_private_key(k)); #endif - /* PKCS#1 1.5 section 6 requires modulus to have at least 12 octets. - * We actually require more (for security). - */ - if (k->pub.k < RSA_MIN_OCTETS) - return RSA_MIN_OCTETS_UGH; + /* PKCS#1 1.5 section 6 requires modulus to have at least 12 octets. + * We actually require more (for security). + */ + if (k->pub.k < RSA_MIN_OCTETS) + return RSA_MIN_OCTETS_UGH; - /* we picked a max modulus size to simplify buffer allocation */ - if (k->pub.k > RSA_MAX_OCTETS) - return RSA_MAX_OCTETS_UGH; + /* we picked a max modulus size to simplify buffer allocation */ + if (k->pub.k > RSA_MAX_OCTETS) + return RSA_MAX_OCTETS_UGH; - mpz_init(t); - mpz_init(u); - mpz_init(q1); + mpz_init(t); + mpz_init(u); + mpz_init(q1); - /* check that n == p * q */ - mpz_mul(u, &k->p, &k->q); - if (mpz_cmp(u, &k->pub.n) != 0) - ugh = "n != p * q"; + /* check that n == p * q */ + mpz_mul(u, &k->p, &k->q); + if (mpz_cmp(u, &k->pub.n) != 0) + ugh = "n != p * q"; - /* check that e divides neither p-1 nor q-1 */ - mpz_sub_ui(t, &k->p, 1); - mpz_mod(t, t, &k->pub.e); - if (mpz_cmp_ui(t, 0) == 0) - ugh = "e divides p-1"; + /* check that e divides neither p-1 nor q-1 */ + mpz_sub_ui(t, &k->p, 1); + mpz_mod(t, t, &k->pub.e); + if (mpz_cmp_ui(t, 0) == 0) + ugh = "e divides p-1"; - mpz_sub_ui(t, &k->q, 1); - mpz_mod(t, t, &k->pub.e); - if (mpz_cmp_ui(t, 0) == 0) - ugh = "e divides q-1"; + mpz_sub_ui(t, &k->q, 1); + mpz_mod(t, t, &k->pub.e); + if (mpz_cmp_ui(t, 0) == 0) + ugh = "e divides q-1"; - /* check that d is e^-1 (mod lcm(p-1, q-1)) */ - /* see PKCS#1v2, aka RFC 2437, for the "lcm" */ - mpz_sub_ui(q1, &k->q, 1); - mpz_sub_ui(u, &k->p, 1); - mpz_gcd(t, u, q1); /* t := gcd(p-1, q-1) */ - mpz_mul(u, u, q1); /* u := (p-1) * (q-1) */ - mpz_divexact(u, u, t); /* u := lcm(p-1, q-1) */ + /* check that d is e^-1 (mod lcm(p-1, q-1)) */ + /* see PKCS#1v2, aka RFC 2437, for the "lcm" */ + mpz_sub_ui(q1, &k->q, 1); + mpz_sub_ui(u, &k->p, 1); + mpz_gcd(t, u, q1); /* t := gcd(p-1, q-1) */ + mpz_mul(u, u, q1); /* u := (p-1) * (q-1) */ + mpz_divexact(u, u, t); /* u := lcm(p-1, q-1) */ - mpz_mul(t, &k->d, &k->pub.e); - mpz_mod(t, t, u); - if (mpz_cmp_ui(t, 1) != 0) - ugh = "(d * e) mod (lcm(p-1, q-1)) != 1"; + mpz_mul(t, &k->d, &k->pub.e); + mpz_mod(t, t, u); + if (mpz_cmp_ui(t, 1) != 0) + ugh = "(d * e) mod (lcm(p-1, q-1)) != 1"; - /* check that dP is d mod (p-1) */ - mpz_sub_ui(u, &k->p, 1); - mpz_mod(t, &k->d, u); - if (mpz_cmp(t, &k->dP) != 0) - ugh = "dP is not congruent to d mod (p-1)"; + /* check that dP is d mod (p-1) */ + mpz_sub_ui(u, &k->p, 1); + mpz_mod(t, &k->d, u); + if (mpz_cmp(t, &k->dP) != 0) + ugh = "dP is not congruent to d mod (p-1)"; - /* check that dQ is d mod (q-1) */ - mpz_sub_ui(u, &k->q, 1); - mpz_mod(t, &k->d, u); - if (mpz_cmp(t, &k->dQ) != 0) - ugh = "dQ is not congruent to d mod (q-1)"; + /* check that dQ is d mod (q-1) */ + mpz_sub_ui(u, &k->q, 1); + mpz_mod(t, &k->d, u); + if (mpz_cmp(t, &k->dQ) != 0) + ugh = "dQ is not congruent to d mod (q-1)"; - /* check that qInv is (q^-1) mod p */ - mpz_mul(t, &k->qInv, &k->q); - mpz_mod(t, t, &k->p); - if (mpz_cmp_ui(t, 1) != 0) - ugh = "qInv is not conguent ot (q^-1) mod p"; + /* check that qInv is (q^-1) mod p */ + mpz_mul(t, &k->qInv, &k->q); + mpz_mod(t, t, &k->p); + if (mpz_cmp_ui(t, 1) != 0) + ugh = "qInv is not conguent ot (q^-1) mod p"; - mpz_clear(t); - mpz_clear(u); - mpz_clear(q1); - return ugh; + mpz_clear(t); + mpz_clear(u); + mpz_clear(q1); + return ugh; } /* @@ -232,8 +232,8 @@ RSA_private_key_sanity(RSA_private_key_t *k) bool same_RSA_public_key(const RSA_public_key_t *a, const RSA_public_key_t *b) { - return a == b - || (a->k == b->k && mpz_cmp(&a->n, &b->n) == 0 && mpz_cmp(&a->e, &b->e) == 0); + return a == b + || (a->k == b->k && mpz_cmp(&a->n, &b->n) == 0 && mpz_cmp(&a->e, &b->e) == 0); } /* @@ -242,45 +242,45 @@ same_RSA_public_key(const RSA_public_key_t *a, const RSA_public_key_t *b) bool pkcs1_parse_private_key(chunk_t blob, RSA_private_key_t *key) { - err_t ugh = NULL; - asn1_ctx_t ctx; - chunk_t object, modulus, exp; - u_int level; - int objectID = 0; + err_t ugh = NULL; + asn1_ctx_t ctx; + chunk_t object, modulus, exp; + u_int level; + int objectID = 0; - asn1_init(&ctx, blob, 0, FALSE, DBG_PRIVATE); + asn1_init(&ctx, blob, 0, FALSE, DBG_PRIVATE); - while (objectID < PKCS1_PRIV_KEY_ROOF) { + while (objectID < PKCS1_PRIV_KEY_ROOF) { - if (!extract_object(privkeyObjects, &objectID, &object, &level, &ctx)) - return FALSE; + if (!extract_object(privkeyObjects, &objectID, &object, &level, &ctx)) + return FALSE; - if (objectID == PKCS1_PRIV_KEY_VERSION) - { - if (object.len > 0 && *object.ptr != 0) - { - plog(" wrong PKCS#1 private key version"); - return FALSE; - } + if (objectID == PKCS1_PRIV_KEY_VERSION) + { + if (object.len > 0 && *object.ptr != 0) + { + plog(" wrong PKCS#1 private key version"); + return FALSE; + } + } + else if (objectID >= PKCS1_PRIV_KEY_MODULUS && + objectID <= PKCS1_PRIV_KEY_COEFF) + { + MP_INT *u = (MP_INT *) ((char *)key + + RSA_private_field[objectID - PKCS1_PRIV_KEY_MODULUS].offset); + + n_to_mpz(u, object.ptr, object.len); + + if (objectID == PKCS1_PRIV_KEY_MODULUS) + modulus = object; + else if (objectID == PKCS1_PRIV_KEY_PUB_EXP) + exp = object; + } + objectID++; } - else if (objectID >= PKCS1_PRIV_KEY_MODULUS && - objectID <= PKCS1_PRIV_KEY_COEFF) - { - MP_INT *u = (MP_INT *) ((char *)key - + RSA_private_field[objectID - PKCS1_PRIV_KEY_MODULUS].offset); - - n_to_mpz(u, object.ptr, object.len); - - if (objectID == PKCS1_PRIV_KEY_MODULUS) - modulus = object; - else if (objectID == PKCS1_PRIV_KEY_PUB_EXP) - exp = object; - } - objectID++; - } - form_keyid(exp, modulus, key->pub.keyid, &key->pub.k); - ugh = RSA_private_key_sanity(key); - return (ugh == NULL); + form_keyid(exp, modulus, key->pub.keyid, &key->pub.k); + ugh = RSA_private_key_sanity(key); + return (ugh == NULL); } /* @@ -289,82 +289,82 @@ pkcs1_parse_private_key(chunk_t blob, RSA_private_key_t *key) bool compute_digest(chunk_t tbs, int alg, chunk_t *digest) { - switch (alg) - { - case OID_MD2: - case OID_MD2_WITH_RSA: + switch (alg) { - MD2_CTX context; + case OID_MD2: + case OID_MD2_WITH_RSA: + { + MD2_CTX context; - MD2Init(&context); - MD2Update(&context, tbs.ptr, tbs.len); - MD2Final(digest->ptr, &context); - digest->len = MD2_DIGEST_SIZE; - return TRUE; - } - case OID_MD5: - case OID_MD5_WITH_RSA: - { - MD5_CTX context; + MD2Init(&context); + MD2Update(&context, tbs.ptr, tbs.len); + MD2Final(digest->ptr, &context); + digest->len = MD2_DIGEST_SIZE; + return TRUE; + } + case OID_MD5: + case OID_MD5_WITH_RSA: + { + MD5_CTX context; - MD5Init(&context); - MD5Update(&context, tbs.ptr, tbs.len); - MD5Final(digest->ptr, &context); - digest->len = MD5_DIGEST_SIZE; - return TRUE; - } - case OID_SHA1: - case OID_SHA1_WITH_RSA: - case OID_SHA1_WITH_RSA_OIW: - { - SHA1_CTX context; + MD5Init(&context); + MD5Update(&context, tbs.ptr, tbs.len); + MD5Final(digest->ptr, &context); + digest->len = MD5_DIGEST_SIZE; + return TRUE; + } + case OID_SHA1: + case OID_SHA1_WITH_RSA: + case OID_SHA1_WITH_RSA_OIW: + { + SHA1_CTX context; - SHA1Init(&context); - SHA1Update(&context, tbs.ptr, tbs.len); - SHA1Final(digest->ptr, &context); - digest->len = SHA1_DIGEST_SIZE; - return TRUE; - } - case OID_SHA256: - case OID_SHA256_WITH_RSA: - { - sha256_context context; + SHA1Init(&context); + SHA1Update(&context, tbs.ptr, tbs.len); + SHA1Final(digest->ptr, &context); + digest->len = SHA1_DIGEST_SIZE; + return TRUE; + } + case OID_SHA256: + case OID_SHA256_WITH_RSA: + { + sha256_context context; - sha256_init(&context); - sha256_write(&context, tbs.ptr, tbs.len); - sha256_final(&context); - memcpy(digest->ptr, context.sha_out, SHA2_256_DIGEST_SIZE); - digest->len = SHA2_256_DIGEST_SIZE; - return TRUE; - } - case OID_SHA384: - case OID_SHA384_WITH_RSA: - { - sha512_context context; + sha256_init(&context); + sha256_write(&context, tbs.ptr, tbs.len); + sha256_final(&context); + memcpy(digest->ptr, context.sha_out, SHA2_256_DIGEST_SIZE); + digest->len = SHA2_256_DIGEST_SIZE; + return TRUE; + } + case OID_SHA384: + case OID_SHA384_WITH_RSA: + { + sha512_context context; - sha384_init(&context); - sha512_write(&context, tbs.ptr, tbs.len); - sha512_final(&context); - memcpy(digest->ptr, context.sha_out, SHA2_384_DIGEST_SIZE); - digest->len = SHA2_384_DIGEST_SIZE; - return TRUE; - } - case OID_SHA512: - case OID_SHA512_WITH_RSA: - { - sha512_context context; + sha384_init(&context); + sha512_write(&context, tbs.ptr, tbs.len); + sha512_final(&context); + memcpy(digest->ptr, context.sha_out, SHA2_384_DIGEST_SIZE); + digest->len = SHA2_384_DIGEST_SIZE; + return TRUE; + } + case OID_SHA512: + case OID_SHA512_WITH_RSA: + { + sha512_context context; - sha512_init(&context); - sha512_write(&context, tbs.ptr, tbs.len); - sha512_final(&context); - memcpy(digest->ptr, context.sha_out, SHA2_512_DIGEST_SIZE); - digest->len = SHA2_512_DIGEST_SIZE; - return TRUE; + sha512_init(&context); + sha512_write(&context, tbs.ptr, tbs.len); + sha512_final(&context); + memcpy(digest->ptr, context.sha_out, SHA2_512_DIGEST_SIZE); + digest->len = SHA2_512_DIGEST_SIZE; + return TRUE; + } + default: + digest->len = 0; + return FALSE; } - default: - digest->len = 0; - return FALSE; - } } /* @@ -372,55 +372,55 @@ compute_digest(chunk_t tbs, int alg, chunk_t *digest) */ void sign_hash(const RSA_private_key_t *k, const u_char *hash_val, size_t hash_len - , u_char *sig_val, size_t sig_len) + , u_char *sig_val, size_t sig_len) { - chunk_t ch; - mpz_t t1, t2; - size_t padlen; - u_char *p = sig_val; + chunk_t ch; + mpz_t t1, t2; + size_t padlen; + u_char *p = sig_val; - DBG(DBG_CONTROL | DBG_CRYPT, - DBG_log("signing hash with RSA Key *%s", k->pub.keyid) - ) - /* PKCS#1 v1.5 8.1 encryption-block formatting */ - *p++ = 0x00; - *p++ = 0x01; /* BT (block type) 01 */ - padlen = sig_len - 3 - hash_len; - memset(p, 0xFF, padlen); - p += padlen; - *p++ = 0x00; - memcpy(p, hash_val, hash_len); - passert(p + hash_len - sig_val == (ptrdiff_t)sig_len); + DBG(DBG_CONTROL | DBG_CRYPT, + DBG_log("signing hash with RSA Key *%s", k->pub.keyid) + ) + /* PKCS#1 v1.5 8.1 encryption-block formatting */ + *p++ = 0x00; + *p++ = 0x01; /* BT (block type) 01 */ + padlen = sig_len - 3 - hash_len; + memset(p, 0xFF, padlen); + p += padlen; + *p++ = 0x00; + memcpy(p, hash_val, hash_len); + passert(p + hash_len - sig_val == (ptrdiff_t)sig_len); - /* PKCS#1 v1.5 8.2 octet-string-to-integer conversion */ - n_to_mpz(t1, sig_val, sig_len); /* (could skip leading 0x00) */ + /* PKCS#1 v1.5 8.2 octet-string-to-integer conversion */ + n_to_mpz(t1, sig_val, sig_len); /* (could skip leading 0x00) */ - /* PKCS#1 v1.5 8.3 RSA computation y = x^c mod n - * Better described in PKCS#1 v2.0 5.1 RSADP. - * There are two methods, depending on the form of the private key. - * We use the one based on the Chinese Remainder Theorem. - */ - mpz_init(t2); + /* PKCS#1 v1.5 8.3 RSA computation y = x^c mod n + * Better described in PKCS#1 v2.0 5.1 RSADP. + * There are two methods, depending on the form of the private key. + * We use the one based on the Chinese Remainder Theorem. + */ + mpz_init(t2); - mpz_powm(t2, t1, &k->dP, &k->p); /* m1 = c^dP mod p */ + mpz_powm(t2, t1, &k->dP, &k->p); /* m1 = c^dP mod p */ - mpz_powm(t1, t1, &k->dQ, &k->q); /* m2 = c^dQ mod Q */ + mpz_powm(t1, t1, &k->dQ, &k->q); /* m2 = c^dQ mod Q */ - mpz_sub(t2, t2, t1); /* h = qInv (m1 - m2) mod p */ - mpz_mod(t2, t2, &k->p); - mpz_mul(t2, t2, &k->qInv); - mpz_mod(t2, t2, &k->p); + mpz_sub(t2, t2, t1); /* h = qInv (m1 - m2) mod p */ + mpz_mod(t2, t2, &k->p); + mpz_mul(t2, t2, &k->qInv); + mpz_mod(t2, t2, &k->p); - mpz_mul(t2, t2, &k->q); /* m = m2 + h q */ - mpz_add(t1, t1, t2); + mpz_mul(t2, t2, &k->q); /* m = m2 + h q */ + mpz_add(t1, t1, t2); - /* PKCS#1 v1.5 8.4 integer-to-octet-string conversion */ - ch = mpz_to_n(t1, sig_len); - memcpy(sig_val, ch.ptr, sig_len); - free(ch.ptr); + /* PKCS#1 v1.5 8.4 integer-to-octet-string conversion */ + ch = mpz_to_n(t1, sig_len); + memcpy(sig_val, ch.ptr, sig_len); + free(ch.ptr); - mpz_clear(t1); - mpz_clear(t2); + mpz_clear(t1); + mpz_clear(t2); } /* @@ -429,60 +429,60 @@ sign_hash(const RSA_private_key_t *k, const u_char *hash_val, size_t hash_len chunk_t RSA_encrypt(const RSA_public_key_t *key, chunk_t in) { - u_char padded[RSA_MAX_OCTETS]; - u_char *pos = padded; - int padding = key->k - in.len - 3; - int i; + u_char padded[RSA_MAX_OCTETS]; + u_char *pos = padded; + int padding = key->k - in.len - 3; + int i; - if (padding < 8 || key->k > RSA_MAX_OCTETS) - return chunk_empty; + if (padding < 8 || key->k > RSA_MAX_OCTETS) + return chunk_empty; - /* add padding according to PKCS#1 7.2.1 1.+2. */ - *pos++ = 0x00; - *pos++ = 0x02; + /* add padding according to PKCS#1 7.2.1 1.+2. */ + *pos++ = 0x00; + *pos++ = 0x02; - /* pad with pseudo random bytes unequal to zero */ - for (i = 0; i < padding; i++) - { - get_rnd_bytes(pos, padding); - while (!*pos) + /* pad with pseudo random bytes unequal to zero */ + for (i = 0; i < padding; i++) { - get_rnd_bytes(pos, 1); + get_rnd_bytes(pos, padding); + while (!*pos) + { + get_rnd_bytes(pos, 1); + } + pos++; } - pos++; - } - /* append the padding terminator */ - *pos++ = 0x00; - - /* now add the data */ - memcpy(pos, in.ptr, in.len); - DBG(DBG_RAW, - DBG_dump_chunk("data for rsa encryption:\n", in); - DBG_dump("padded data for rsa encryption:\n", padded, key->k) - ) - - /* convert chunk to integer (PKCS#1 7.2.1 3.a) */ - { - chunk_t out; - mpz_t m, c; - - mpz_init(c); - n_to_mpz(m, padded, key->k); - - /* encrypt(PKCS#1 7.2.1 3.b) */ - mpz_powm(c, m, &key->e, &key->n); - - /* convert integer back to a chunk (PKCS#1 7.2.1 3.c) */ - out = mpz_to_n(c, key->k); - mpz_clear(c); - mpz_clear(m); + /* append the padding terminator */ + *pos++ = 0x00; + /* now add the data */ + memcpy(pos, in.ptr, in.len); DBG(DBG_RAW, - DBG_dump_chunk("rsa encrypted data:\n", out) + DBG_dump_chunk("data for rsa encryption:\n", in); + DBG_dump("padded data for rsa encryption:\n", padded, key->k) ) - return out; - } + + /* convert chunk to integer (PKCS#1 7.2.1 3.a) */ + { + chunk_t out; + mpz_t m, c; + + mpz_init(c); + n_to_mpz(m, padded, key->k); + + /* encrypt(PKCS#1 7.2.1 3.b) */ + mpz_powm(c, m, &key->e, &key->n); + + /* convert integer back to a chunk (PKCS#1 7.2.1 3.c) */ + out = mpz_to_n(c, key->k); + mpz_clear(c); + mpz_clear(m); + + DBG(DBG_RAW, + DBG_dump_chunk("rsa encrypted data:\n", out) + ) + return out; + } } /* @@ -491,64 +491,64 @@ RSA_encrypt(const RSA_public_key_t *key, chunk_t in) bool RSA_decrypt(const RSA_private_key_t *key, chunk_t in, chunk_t *out) { - chunk_t padded, plaintext; - u_char *pos; - mpz_t t1, t2; + chunk_t padded, plaintext; + u_char *pos; + mpz_t t1, t2; - n_to_mpz(t1, in.ptr,in.len); + n_to_mpz(t1, in.ptr,in.len); - /* PKCS#1 v1.5 8.3 RSA computation y = x^c mod n - * Better described in PKCS#1 v2.0 5.1 RSADP. - * There are two methods, depending on the form of the private key. - * We use the one based on the Chinese Remainder Theorem. - */ - mpz_init(t2); + /* PKCS#1 v1.5 8.3 RSA computation y = x^c mod n + * Better described in PKCS#1 v2.0 5.1 RSADP. + * There are two methods, depending on the form of the private key. + * We use the one based on the Chinese Remainder Theorem. + */ + mpz_init(t2); - mpz_powm(t2, t1, &key->dP, &key->p); /* m1 = c^dP mod p */ - mpz_powm(t1, t1, &key->dQ, &key->q); /* m2 = c^dQ mod Q */ + mpz_powm(t2, t1, &key->dP, &key->p); /* m1 = c^dP mod p */ + mpz_powm(t1, t1, &key->dQ, &key->q); /* m2 = c^dQ mod Q */ - mpz_sub(t2, t2, t1); /* h = qInv (m1 - m2) mod p */ - mpz_mod(t2, t2, &key->p); - mpz_mul(t2, t2, &key->qInv); - mpz_mod(t2, t2, &key->p); + mpz_sub(t2, t2, t1); /* h = qInv (m1 - m2) mod p */ + mpz_mod(t2, t2, &key->p); + mpz_mul(t2, t2, &key->qInv); + mpz_mod(t2, t2, &key->p); - mpz_mul(t2, t2, &key->q); /* m = m2 + h q */ - mpz_add(t1, t1, t2); + mpz_mul(t2, t2, &key->q); /* m = m2 + h q */ + mpz_add(t1, t1, t2); - padded = mpz_to_n(t1, key->pub.k); - mpz_clear(t1); - mpz_clear(t2); + padded = mpz_to_n(t1, key->pub.k); + mpz_clear(t1); + mpz_clear(t2); - DBG(DBG_PRIVATE, - DBG_dump_chunk("rsa decrypted data with padding:\n", padded) - ) - pos = padded.ptr; + DBG(DBG_PRIVATE, + DBG_dump_chunk("rsa decrypted data with padding:\n", padded) + ) + pos = padded.ptr; - /* PKCS#1 v1.5 8.1 encryption-block formatting (EB = 00 || 02 || PS || 00 || D) */ + /* PKCS#1 v1.5 8.1 encryption-block formatting (EB = 00 || 02 || PS || 00 || D) */ - /* check for hex pattern 00 02 in decrypted message */ - if ((*pos++ != 0x00) || (*(pos++) != 0x02)) - { - plog("incorrect padding - probably wrong RSA key"); + /* check for hex pattern 00 02 in decrypted message */ + if ((*pos++ != 0x00) || (*(pos++) != 0x02)) + { + plog("incorrect padding - probably wrong RSA key"); + chunk_clear(&padded); + return FALSE; + } + padded.len -= 2; + + /* the plaintext data starts after first 0x00 byte */ + while (padded.len-- > 0 && *pos++ != 0x00) + + if (padded.len == 0) + { + plog("no plaintext data"); + free(padded.ptr); + return FALSE; + } + + plaintext = chunk_create(pos, padded.len); + *out = chunk_clone(plaintext); chunk_clear(&padded); - return FALSE; - } - padded.len -= 2; - - /* the plaintext data starts after first 0x00 byte */ - while (padded.len-- > 0 && *pos++ != 0x00) - - if (padded.len == 0) - { - plog("no plaintext data"); - free(padded.ptr); - return FALSE; - } - - plaintext = chunk_create(pos, padded.len); - *out = chunk_clone(plaintext); - chunk_clear(&padded); - return TRUE; + return TRUE; } /* @@ -559,49 +559,49 @@ pkcs1_build_signature(chunk_t tbs, int hash_alg, const RSA_private_key_t *key , bool bit_string) { - size_t siglen = key->pub.k; + size_t siglen = key->pub.k; - u_char digest_buf[MAX_DIGEST_LEN]; - chunk_t digest = { digest_buf, MAX_DIGEST_LEN }; - chunk_t digestInfo, alg_id, signatureValue; - u_char *pos; + u_char digest_buf[MAX_DIGEST_LEN]; + chunk_t digest = { digest_buf, MAX_DIGEST_LEN }; + chunk_t digestInfo, alg_id, signatureValue; + u_char *pos; - switch (hash_alg) - { - case OID_MD5: - case OID_MD5_WITH_RSA: - alg_id = ASN1_md5_id; - break; - case OID_SHA1: - case OID_SHA1_WITH_RSA: - alg_id = ASN1_sha1_id; - break; - default: - return chunk_empty; - } - compute_digest(tbs, hash_alg, &digest); + switch (hash_alg) + { + case OID_MD5: + case OID_MD5_WITH_RSA: + alg_id = ASN1_md5_id; + break; + case OID_SHA1: + case OID_SHA1_WITH_RSA: + alg_id = ASN1_sha1_id; + break; + default: + return chunk_empty; + } + compute_digest(tbs, hash_alg, &digest); - /* according to PKCS#1 v2.1 digest must be packaged into - * an ASN.1 structure for encryption - */ - digestInfo = asn1_wrap(ASN1_SEQUENCE, "cm" - , alg_id - , asn1_simple_object(ASN1_OCTET_STRING, digest)); + /* according to PKCS#1 v2.1 digest must be packaged into + * an ASN.1 structure for encryption + */ + digestInfo = asn1_wrap(ASN1_SEQUENCE, "cm" + , alg_id + , asn1_simple_object(ASN1_OCTET_STRING, digest)); - /* generate the RSA signature */ - if (bit_string) - { - pos = build_asn1_object(&signatureValue, ASN1_BIT_STRING, 1 + siglen); - *pos++ = 0x00; - } - else - { - pos = build_asn1_object(&signatureValue, ASN1_OCTET_STRING, siglen); - } - sign_hash(key, digestInfo.ptr, digestInfo.len, pos, siglen); - free(digestInfo.ptr); + /* generate the RSA signature */ + if (bit_string) + { + pos = build_asn1_object(&signatureValue, ASN1_BIT_STRING, 1 + siglen); + *pos++ = 0x00; + } + else + { + pos = build_asn1_object(&signatureValue, ASN1_OCTET_STRING, siglen); + } + sign_hash(key, digestInfo.ptr, digestInfo.len, pos, siglen); + free(digestInfo.ptr); - return signatureValue; + return signatureValue; } /* @@ -610,21 +610,21 @@ pkcs1_build_signature(chunk_t tbs, int hash_alg, const RSA_private_key_t *key chunk_t pkcs1_build_private_key(const RSA_private_key_t *key) { - chunk_t pkcs1 = asn1_wrap(ASN1_SEQUENCE, "cmmmmmmmm" - , ASN1_INTEGER_0 - , asn1_integer_from_mpz(&key->pub.n) - , asn1_integer_from_mpz(&key->pub.e) - , asn1_integer_from_mpz(&key->d) - , asn1_integer_from_mpz(&key->p) - , asn1_integer_from_mpz(&key->q) - , asn1_integer_from_mpz(&key->dP) - , asn1_integer_from_mpz(&key->dQ) - , asn1_integer_from_mpz(&key->qInv)); + chunk_t pkcs1 = asn1_wrap(ASN1_SEQUENCE, "cmmmmmmmm" + , ASN1_INTEGER_0 + , asn1_integer_from_mpz(&key->pub.n) + , asn1_integer_from_mpz(&key->pub.e) + , asn1_integer_from_mpz(&key->d) + , asn1_integer_from_mpz(&key->p) + , asn1_integer_from_mpz(&key->q) + , asn1_integer_from_mpz(&key->dP) + , asn1_integer_from_mpz(&key->dQ) + , asn1_integer_from_mpz(&key->qInv)); - DBG(DBG_PRIVATE, - DBG_dump_chunk("PKCS#1 encoded private key:", pkcs1) - ) - return pkcs1; + DBG(DBG_PRIVATE, + DBG_dump_chunk("PKCS#1 encoded private key:", pkcs1) + ) + return pkcs1; } /* @@ -633,9 +633,9 @@ pkcs1_build_private_key(const RSA_private_key_t *key) chunk_t pkcs1_build_public_key(const RSA_public_key_t *rsa) { - return asn1_wrap(ASN1_SEQUENCE, "mm" - , asn1_integer_from_mpz(&rsa->n) - , asn1_integer_from_mpz(&rsa->e)); + return asn1_wrap(ASN1_SEQUENCE, "mm" + , asn1_integer_from_mpz(&rsa->n) + , asn1_integer_from_mpz(&rsa->e)); } /* @@ -644,34 +644,34 @@ pkcs1_build_public_key(const RSA_public_key_t *rsa) chunk_t pkcs1_build_publicKeyInfo(const RSA_public_key_t *rsa) { - chunk_t publicKey; - chunk_t rawKey = pkcs1_build_public_key(rsa); + chunk_t publicKey; + chunk_t rawKey = pkcs1_build_public_key(rsa); - u_char *pos = build_asn1_object(&publicKey, ASN1_BIT_STRING - , 1 + rawKey.len); - *pos++ = 0x00; - mv_chunk(&pos, rawKey); + u_char *pos = build_asn1_object(&publicKey, ASN1_BIT_STRING + , 1 + rawKey.len); + *pos++ = 0x00; + mv_chunk(&pos, rawKey); - return asn1_wrap(ASN1_SEQUENCE, "cm" - , ASN1_rsaEncryption_id - , publicKey); + return asn1_wrap(ASN1_SEQUENCE, "cm" + , ASN1_rsaEncryption_id + , publicKey); } void free_RSA_public_content(RSA_public_key_t *rsa) { - mpz_clear(&rsa->n); - mpz_clear(&rsa->e); + mpz_clear(&rsa->n); + mpz_clear(&rsa->e); } void free_RSA_private_content(RSA_private_key_t *rsak) { - free_RSA_public_content(&rsak->pub); - mpz_clear(&rsak->d); - mpz_clear(&rsak->p); - mpz_clear(&rsak->q); - mpz_clear(&rsak->dP); - mpz_clear(&rsak->dQ); - mpz_clear(&rsak->qInv); + free_RSA_public_content(&rsak->pub); + mpz_clear(&rsak->d); + mpz_clear(&rsak->p); + mpz_clear(&rsak->q); + mpz_clear(&rsak->dP); + mpz_clear(&rsak->dQ); + mpz_clear(&rsak->qInv); } diff --git a/src/pluto/pkcs1.h b/src/pluto/pkcs1.h index 76f45a6b5..e7c204e87 100644 --- a/src/pluto/pkcs1.h +++ b/src/pluto/pkcs1.h @@ -27,39 +27,39 @@ typedef struct RSA_public_key RSA_public_key_t; struct RSA_public_key { - char keyid[KEYID_BUF]; /* see ipsec_keyblobtoid(3) */ + char keyid[KEYID_BUF]; /* see ipsec_keyblobtoid(3) */ - /* length of modulus n in octets: [RSA_MIN_OCTETS, RSA_MAX_OCTETS] */ - unsigned k; + /* length of modulus n in octets: [RSA_MIN_OCTETS, RSA_MAX_OCTETS] */ + unsigned k; - /* public: */ - MP_INT - n, /* modulus: p * q */ - e; /* exponent: relatively prime to (p-1) * (q-1) [probably small] */ + /* public: */ + MP_INT + n, /* modulus: p * q */ + e; /* exponent: relatively prime to (p-1) * (q-1) [probably small] */ }; typedef struct RSA_private_key RSA_private_key_t; struct RSA_private_key { - struct RSA_public_key pub; /* must be at start for RSA_show_public_key */ + struct RSA_public_key pub; /* must be at start for RSA_show_public_key */ - MP_INT - d, /* private exponent: (e^-1) mod ((p-1) * (q-1)) */ - /* help for Chinese Remainder Theorem speedup: */ - p, /* first secret prime */ - q, /* second secret prime */ - dP, /* first factor's exponent: (e^-1) mod (p-1) == d mod (p-1) */ - dQ, /* second factor's exponent: (e^-1) mod (q-1) == d mod (q-1) */ - qInv; /* (q^-1) mod p */ + MP_INT + d, /* private exponent: (e^-1) mod ((p-1) * (q-1)) */ + /* help for Chinese Remainder Theorem speedup: */ + p, /* first secret prime */ + q, /* second secret prime */ + dP, /* first factor's exponent: (e^-1) mod (p-1) == d mod (p-1) */ + dQ, /* second factor's exponent: (e^-1) mod (q-1) == d mod (q-1) */ + qInv; /* (q^-1) mod p */ }; struct fld { - const char *name; - size_t offset; + const char *name; + size_t offset; }; extern const struct fld RSA_private_field[]; -#define RSA_PRIVATE_FIELD_ELEMENTS 8 +#define RSA_PRIVATE_FIELD_ELEMENTS 8 extern void init_RSA_public_key(RSA_public_key_t *rsa, chunk_t e, chunk_t n); extern bool pkcs1_parse_private_key(chunk_t blob, RSA_private_key_t *key); @@ -67,15 +67,15 @@ extern chunk_t pkcs1_build_private_key(const RSA_private_key_t *key); extern chunk_t pkcs1_build_public_key(const RSA_public_key_t *rsa); extern chunk_t pkcs1_build_publicKeyInfo(const RSA_public_key_t *rsa); extern chunk_t pkcs1_build_signature(chunk_t tbs, int hash_alg - , const RSA_private_key_t *key, bool bit_string); + , const RSA_private_key_t *key, bool bit_string); extern bool compute_digest(chunk_t tbs, int alg, chunk_t *digest); extern void sign_hash(const RSA_private_key_t *k, const u_char *hash_val - , size_t hash_len, u_char *sig_val, size_t sig_len); + , size_t hash_len, u_char *sig_val, size_t sig_len); extern chunk_t RSA_encrypt(const RSA_public_key_t *key, chunk_t in); extern bool RSA_decrypt(const RSA_private_key_t *key, chunk_t in - , chunk_t *out); + , chunk_t *out); extern bool same_RSA_public_key(const RSA_public_key_t *a - , const RSA_public_key_t *b); + , const RSA_public_key_t *b); extern void form_keyid(chunk_t e, chunk_t n, char* keyid, unsigned *keysize); extern err_t RSA_private_key_sanity(RSA_private_key_t *k); #ifdef DEBUG diff --git a/src/pluto/pkcs7.c b/src/pluto/pkcs7.c index fc8790358..8283a0699 100644 --- a/src/pluto/pkcs7.c +++ b/src/pluto/pkcs7.c @@ -33,169 +33,169 @@ #include "rnd.h" const contentInfo_t empty_contentInfo = { - OID_UNKNOWN , /* type */ - { NULL, 0 } /* content */ + OID_UNKNOWN , /* type */ + { NULL, 0 } /* content */ }; /* ASN.1 definition of the PKCS#7 ContentInfo type */ static const asn1Object_t contentInfoObjects[] = { - { 0, "contentInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "contentType", ASN1_OID, ASN1_BODY }, /* 1 */ - { 1, "content", ASN1_CONTEXT_C_0, ASN1_OPT | - ASN1_BODY }, /* 2 */ - { 1, "end opt", ASN1_EOC, ASN1_END } /* 3 */ + { 0, "contentInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ + { 1, "contentType", ASN1_OID, ASN1_BODY }, /* 1 */ + { 1, "content", ASN1_CONTEXT_C_0, ASN1_OPT | + ASN1_BODY }, /* 2 */ + { 1, "end opt", ASN1_EOC, ASN1_END } /* 3 */ }; -#define PKCS7_INFO_TYPE 1 -#define PKCS7_INFO_CONTENT 2 -#define PKCS7_INFO_ROOF 4 +#define PKCS7_INFO_TYPE 1 +#define PKCS7_INFO_CONTENT 2 +#define PKCS7_INFO_ROOF 4 /* ASN.1 definition of the PKCS#7 signedData type */ static const asn1Object_t signedDataObjects[] = { - { 0, "signedData", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */ - { 1, "digestAlgorithms", ASN1_SET, ASN1_LOOP }, /* 2 */ - { 2, "algorithm", ASN1_EOC, ASN1_RAW }, /* 3 */ - { 1, "end loop", ASN1_EOC, ASN1_END }, /* 4 */ - { 1, "contentInfo", ASN1_EOC, ASN1_RAW }, /* 5 */ - { 1, "certificates", ASN1_CONTEXT_C_0, ASN1_OPT | - ASN1_LOOP }, /* 6 */ - { 2, "certificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 7 */ - { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 8 */ - { 1, "crls", ASN1_CONTEXT_C_1, ASN1_OPT | - ASN1_LOOP }, /* 9 */ - { 2, "crl", ASN1_SEQUENCE, ASN1_OBJ }, /* 10 */ - { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 11 */ - { 1, "signerInfos", ASN1_SET, ASN1_LOOP }, /* 12 */ - { 2, "signerInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 13 */ - { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 14 */ - { 3, "issuerAndSerialNumber", ASN1_SEQUENCE, ASN1_BODY }, /* 15 */ - { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 16 */ - { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 17 */ - { 3, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 18 */ - { 3, "authenticatedAttributes", ASN1_CONTEXT_C_0, ASN1_OPT | - ASN1_OBJ }, /* 19 */ - { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */ - { 3, "digestEncryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 21 */ - { 3, "encryptedDigest", ASN1_OCTET_STRING, ASN1_BODY }, /* 22 */ + { 0, "signedData", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ + { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */ + { 1, "digestAlgorithms", ASN1_SET, ASN1_LOOP }, /* 2 */ + { 2, "algorithm", ASN1_EOC, ASN1_RAW }, /* 3 */ + { 1, "end loop", ASN1_EOC, ASN1_END }, /* 4 */ + { 1, "contentInfo", ASN1_EOC, ASN1_RAW }, /* 5 */ + { 1, "certificates", ASN1_CONTEXT_C_0, ASN1_OPT | + ASN1_LOOP }, /* 6 */ + { 2, "certificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 7 */ + { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 8 */ + { 1, "crls", ASN1_CONTEXT_C_1, ASN1_OPT | + ASN1_LOOP }, /* 9 */ + { 2, "crl", ASN1_SEQUENCE, ASN1_OBJ }, /* 10 */ + { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 11 */ + { 1, "signerInfos", ASN1_SET, ASN1_LOOP }, /* 12 */ + { 2, "signerInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 13 */ + { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 14 */ + { 3, "issuerAndSerialNumber", ASN1_SEQUENCE, ASN1_BODY }, /* 15 */ + { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 16 */ + { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 17 */ + { 3, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 18 */ + { 3, "authenticatedAttributes", ASN1_CONTEXT_C_0, ASN1_OPT | + ASN1_OBJ }, /* 19 */ + { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */ + { 3, "digestEncryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 21 */ + { 3, "encryptedDigest", ASN1_OCTET_STRING, ASN1_BODY }, /* 22 */ { 3, "unauthenticatedAttributes", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 23 */ - { 3, "end opt", ASN1_EOC, ASN1_END }, /* 24 */ - { 1, "end loop", ASN1_EOC, ASN1_END } /* 25 */ + { 3, "end opt", ASN1_EOC, ASN1_END }, /* 24 */ + { 1, "end loop", ASN1_EOC, ASN1_END } /* 25 */ }; -#define PKCS7_DIGEST_ALG 3 -#define PKCS7_SIGNED_CONTENT_INFO 5 -#define PKCS7_SIGNED_CERT 7 -#define PKCS7_SIGNER_INFO 13 -#define PKCS7_SIGNED_ISSUER 16 -#define PKCS7_SIGNED_SERIAL_NUMBER 17 -#define PKCS7_DIGEST_ALGORITHM 18 -#define PKCS7_AUTH_ATTRIBUTES 19 -#define PKCS7_DIGEST_ENC_ALGORITHM 21 -#define PKCS7_ENCRYPTED_DIGEST 22 -#define PKCS7_SIGNED_ROOF 26 +#define PKCS7_DIGEST_ALG 3 +#define PKCS7_SIGNED_CONTENT_INFO 5 +#define PKCS7_SIGNED_CERT 7 +#define PKCS7_SIGNER_INFO 13 +#define PKCS7_SIGNED_ISSUER 16 +#define PKCS7_SIGNED_SERIAL_NUMBER 17 +#define PKCS7_DIGEST_ALGORITHM 18 +#define PKCS7_AUTH_ATTRIBUTES 19 +#define PKCS7_DIGEST_ENC_ALGORITHM 21 +#define PKCS7_ENCRYPTED_DIGEST 22 +#define PKCS7_SIGNED_ROOF 26 /* ASN.1 definition of the PKCS#7 envelopedData type */ static const asn1Object_t envelopedDataObjects[] = { - { 0, "envelopedData", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ - { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */ - { 1, "recipientInfos", ASN1_SET, ASN1_LOOP }, /* 2 */ - { 2, "recipientInfo", ASN1_SEQUENCE, ASN1_BODY }, /* 3 */ - { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 4 */ - { 3, "issuerAndSerialNumber", ASN1_SEQUENCE, ASN1_BODY }, /* 5 */ - { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 6 */ - { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 7 */ - { 3, "encryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 8 */ - { 3, "encryptedKey", ASN1_OCTET_STRING, ASN1_BODY }, /* 9 */ - { 1, "end loop", ASN1_EOC, ASN1_END }, /* 10 */ - { 1, "encryptedContentInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 11 */ - { 2, "contentType", ASN1_OID, ASN1_BODY }, /* 12 */ - { 2, "contentEncryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 13 */ - { 2, "encryptedContent", ASN1_CONTEXT_S_0, ASN1_BODY } /* 14 */ + { 0, "envelopedData", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ + { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */ + { 1, "recipientInfos", ASN1_SET, ASN1_LOOP }, /* 2 */ + { 2, "recipientInfo", ASN1_SEQUENCE, ASN1_BODY }, /* 3 */ + { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 4 */ + { 3, "issuerAndSerialNumber", ASN1_SEQUENCE, ASN1_BODY }, /* 5 */ + { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 6 */ + { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 7 */ + { 3, "encryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 8 */ + { 3, "encryptedKey", ASN1_OCTET_STRING, ASN1_BODY }, /* 9 */ + { 1, "end loop", ASN1_EOC, ASN1_END }, /* 10 */ + { 1, "encryptedContentInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 11 */ + { 2, "contentType", ASN1_OID, ASN1_BODY }, /* 12 */ + { 2, "contentEncryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 13 */ + { 2, "encryptedContent", ASN1_CONTEXT_S_0, ASN1_BODY } /* 14 */ }; -#define PKCS7_ENVELOPED_VERSION 1 -#define PKCS7_RECIPIENT_INFO_VERSION 4 -#define PKCS7_ISSUER 6 -#define PKCS7_SERIAL_NUMBER 7 -#define PKCS7_ENCRYPTION_ALG 8 -#define PKCS7_ENCRYPTED_KEY 9 -#define PKCS7_CONTENT_TYPE 12 -#define PKCS7_CONTENT_ENC_ALGORITHM 13 -#define PKCS7_ENCRYPTED_CONTENT 14 -#define PKCS7_ENVELOPED_ROOF 15 +#define PKCS7_ENVELOPED_VERSION 1 +#define PKCS7_RECIPIENT_INFO_VERSION 4 +#define PKCS7_ISSUER 6 +#define PKCS7_SERIAL_NUMBER 7 +#define PKCS7_ENCRYPTION_ALG 8 +#define PKCS7_ENCRYPTED_KEY 9 +#define PKCS7_CONTENT_TYPE 12 +#define PKCS7_CONTENT_ENC_ALGORITHM 13 +#define PKCS7_ENCRYPTED_CONTENT 14 +#define PKCS7_ENVELOPED_ROOF 15 /* PKCS7 contentInfo OIDs */ static u_char ASN1_pkcs7_data_oid_str[] = { - 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01 + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01 }; static u_char ASN1_pkcs7_signed_data_oid_str[] = { - 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02 + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02 }; static u_char ASN1_pkcs7_enveloped_data_oid_str[] = { - 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x03 + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x03 }; static u_char ASN1_pkcs7_signed_enveloped_data_oid_str[] = { - 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x04 + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x04 }; static u_char ASN1_pkcs7_digested_data_oid_str[] = { - 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x05 + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x05 }; static char ASN1_pkcs7_encrypted_data_oid_str[] = { - 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06 + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06 }; static const chunk_t ASN1_pkcs7_data_oid = - chunk_from_buf(ASN1_pkcs7_data_oid_str); + chunk_from_buf(ASN1_pkcs7_data_oid_str); static const chunk_t ASN1_pkcs7_signed_data_oid = - chunk_from_buf(ASN1_pkcs7_signed_data_oid_str); + chunk_from_buf(ASN1_pkcs7_signed_data_oid_str); static const chunk_t ASN1_pkcs7_enveloped_data_oid = - chunk_from_buf(ASN1_pkcs7_enveloped_data_oid_str); + chunk_from_buf(ASN1_pkcs7_enveloped_data_oid_str); static const chunk_t ASN1_pkcs7_signed_enveloped_data_oid = - chunk_from_buf(ASN1_pkcs7_signed_enveloped_data_oid_str); + chunk_from_buf(ASN1_pkcs7_signed_enveloped_data_oid_str); static const chunk_t ASN1_pkcs7_digested_data_oid = - chunk_from_buf(ASN1_pkcs7_digested_data_oid_str); + chunk_from_buf(ASN1_pkcs7_digested_data_oid_str); static const chunk_t ASN1_pkcs7_encrypted_data_oid = - chunk_from_buf(ASN1_pkcs7_encrypted_data_oid_str); + chunk_from_buf(ASN1_pkcs7_encrypted_data_oid_str); /* 3DES and DES encryption OIDs */ static u_char ASN1_3des_ede_cbc_oid_str[] = { - 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x03, 0x07 + 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x03, 0x07 }; static u_char ASN1_des_cbc_oid_str[] = { - 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x07 + 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x07 }; static const chunk_t ASN1_3des_ede_cbc_oid = - chunk_from_buf(ASN1_3des_ede_cbc_oid_str); + chunk_from_buf(ASN1_3des_ede_cbc_oid_str); static const chunk_t ASN1_des_cbc_oid = - chunk_from_buf(ASN1_des_cbc_oid_str); + chunk_from_buf(ASN1_des_cbc_oid_str); /* PKCS#7 attribute type OIDs */ static u_char ASN1_contentType_oid_str[] = { - 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x03 + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x03 }; static u_char ASN1_messageDigest_oid_str[] = { - 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x04 + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x04 }; static const chunk_t ASN1_contentType_oid = - chunk_from_buf(ASN1_contentType_oid_str); + chunk_from_buf(ASN1_contentType_oid_str); static const chunk_t ASN1_messageDigest_oid = - chunk_from_buf(ASN1_messageDigest_oid_str); + chunk_from_buf(ASN1_messageDigest_oid_str); /* * Parse PKCS#7 ContentInfo object @@ -203,35 +203,35 @@ static const chunk_t ASN1_messageDigest_oid = bool pkcs7_parse_contentInfo(chunk_t blob, u_int level0, contentInfo_t *cInfo) { - asn1_ctx_t ctx; - chunk_t object; - u_int level; - int objectID = 0; + asn1_ctx_t ctx; + chunk_t object; + u_int level; + int objectID = 0; - asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); + asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); - while (objectID < PKCS7_INFO_ROOF) - { - if (!extract_object(contentInfoObjects, &objectID, &object, &level, &ctx)) - return FALSE; - - if (objectID == PKCS7_INFO_TYPE) + while (objectID < PKCS7_INFO_ROOF) { - cInfo->type = asn1_known_oid(object); - if (cInfo->type < OID_PKCS7_DATA - || cInfo->type > OID_PKCS7_ENCRYPTED_DATA) - { - plog("unknown pkcs7 content type"); - return FALSE; - } + if (!extract_object(contentInfoObjects, &objectID, &object, &level, &ctx)) + return FALSE; + + if (objectID == PKCS7_INFO_TYPE) + { + cInfo->type = asn1_known_oid(object); + if (cInfo->type < OID_PKCS7_DATA + || cInfo->type > OID_PKCS7_ENCRYPTED_DATA) + { + plog("unknown pkcs7 content type"); + return FALSE; + } + } + else if (objectID == PKCS7_INFO_CONTENT) + { + cInfo->content = object; + } + objectID++; } - else if (objectID == PKCS7_INFO_CONTENT) - { - cInfo->content = object; - } - objectID++; - } - return TRUE; + return TRUE; } /* @@ -241,130 +241,130 @@ bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data, x509cert_t **cert , chunk_t *attributes, const x509cert_t *cacert) { - u_char buf[BUF_LEN]; - asn1_ctx_t ctx; - chunk_t object; - u_int level; - int digest_alg = OID_UNKNOWN; - int enc_alg = OID_UNKNOWN; - int signerInfos = 0; - int objectID = 0; + u_char buf[BUF_LEN]; + asn1_ctx_t ctx; + chunk_t object; + u_int level; + int digest_alg = OID_UNKNOWN; + int enc_alg = OID_UNKNOWN; + int signerInfos = 0; + int objectID = 0; - contentInfo_t cInfo = empty_contentInfo; - chunk_t encrypted_digest = chunk_empty; + contentInfo_t cInfo = empty_contentInfo; + chunk_t encrypted_digest = chunk_empty; - if (!pkcs7_parse_contentInfo(blob, 0, &cInfo)) - return FALSE; + if (!pkcs7_parse_contentInfo(blob, 0, &cInfo)) + return FALSE; - if (cInfo.type != OID_PKCS7_SIGNED_DATA) - { - plog("pkcs7 content type is not signedData"); - return FALSE; - } + if (cInfo.type != OID_PKCS7_SIGNED_DATA) + { + plog("pkcs7 content type is not signedData"); + return FALSE; + } - asn1_init(&ctx, cInfo.content, 2, FALSE, DBG_RAW); + asn1_init(&ctx, cInfo.content, 2, FALSE, DBG_RAW); - while (objectID < PKCS7_SIGNED_ROOF) + while (objectID < PKCS7_SIGNED_ROOF) { - if (!extract_object(signedDataObjects, &objectID, &object, &level, &ctx)) - return FALSE; + if (!extract_object(signedDataObjects, &objectID, &object, &level, &ctx)) + return FALSE; - switch (objectID) - { - case PKCS7_DIGEST_ALG: - digest_alg = parse_algorithmIdentifier(object, level, NULL); - break; - case PKCS7_SIGNED_CONTENT_INFO: - if (data != NULL) - { - pkcs7_parse_contentInfo(object, level, data); - } - break; - case PKCS7_SIGNED_CERT: - if (cert != NULL) - { - chunk_t cert_blob = chunk_clone(object); - x509cert_t *newcert = malloc_thing(x509cert_t); - - *newcert = empty_x509cert; - - DBG(DBG_CONTROL | DBG_PARSING, - DBG_log("parsing pkcs7-wrapped certificate") - ) - if (parse_x509cert(cert_blob, level+1, newcert)) + switch (objectID) { - newcert->next = *cert; - *cert = newcert; + case PKCS7_DIGEST_ALG: + digest_alg = parse_algorithmIdentifier(object, level, NULL); + break; + case PKCS7_SIGNED_CONTENT_INFO: + if (data != NULL) + { + pkcs7_parse_contentInfo(object, level, data); + } + break; + case PKCS7_SIGNED_CERT: + if (cert != NULL) + { + chunk_t cert_blob = chunk_clone(object); + x509cert_t *newcert = malloc_thing(x509cert_t); + + *newcert = empty_x509cert; + + DBG(DBG_CONTROL | DBG_PARSING, + DBG_log("parsing pkcs7-wrapped certificate") + ) + if (parse_x509cert(cert_blob, level+1, newcert)) + { + newcert->next = *cert; + *cert = newcert; + } + else + { + free_x509cert(newcert); + } + } + break; + case PKCS7_SIGNER_INFO: + signerInfos++; + DBG(DBG_PARSING, + DBG_log(" signer #%d", signerInfos) + ) + break; + case PKCS7_SIGNED_ISSUER: + DBG(DBG_PARSING, + dntoa(buf, BUF_LEN, object); + DBG_log(" '%s'",buf) + ) + break; + case PKCS7_AUTH_ATTRIBUTES: + if (attributes != NULL) + { + *attributes = object; + *attributes->ptr = ASN1_SET; + } + break; + case PKCS7_DIGEST_ALGORITHM: + digest_alg = parse_algorithmIdentifier(object, level, NULL); + break; + case PKCS7_DIGEST_ENC_ALGORITHM: + enc_alg = parse_algorithmIdentifier(object, level, NULL); + break; + case PKCS7_ENCRYPTED_DIGEST: + encrypted_digest = object; } - else - { - free_x509cert(newcert); - } - } - break; - case PKCS7_SIGNER_INFO: - signerInfos++; - DBG(DBG_PARSING, - DBG_log(" signer #%d", signerInfos) - ) - break; - case PKCS7_SIGNED_ISSUER: - DBG(DBG_PARSING, - dntoa(buf, BUF_LEN, object); - DBG_log(" '%s'",buf) - ) - break; - case PKCS7_AUTH_ATTRIBUTES: - if (attributes != NULL) - { - *attributes = object; - *attributes->ptr = ASN1_SET; - } - break; - case PKCS7_DIGEST_ALGORITHM: - digest_alg = parse_algorithmIdentifier(object, level, NULL); - break; - case PKCS7_DIGEST_ENC_ALGORITHM: - enc_alg = parse_algorithmIdentifier(object, level, NULL); - break; - case PKCS7_ENCRYPTED_DIGEST: - encrypted_digest = object; + objectID++; } - objectID++; - } - /* check the signature only if a cacert is available */ - if (cacert != NULL) - { - if (signerInfos == 0) + /* check the signature only if a cacert is available */ + if (cacert != NULL) { - plog("no signerInfo object found"); - return FALSE; + if (signerInfos == 0) + { + plog("no signerInfo object found"); + return FALSE; + } + else if (signerInfos > 1) + { + plog("more than one signerInfo object found"); + return FALSE; + } + if (attributes->ptr == NULL) + { + plog("no authenticatedAttributes object found"); + return FALSE; + } + if (!check_signature(*attributes, encrypted_digest, digest_alg + , enc_alg, cacert)) + { + plog("invalid signature"); + return FALSE; + } + else + { + DBG(DBG_CONTROL, + DBG_log("signature is valid") + ) + } } - else if (signerInfos > 1) - { - plog("more than one signerInfo object found"); - return FALSE; - } - if (attributes->ptr == NULL) - { - plog("no authenticatedAttributes object found"); - return FALSE; - } - if (!check_signature(*attributes, encrypted_digest, digest_alg - , enc_alg, cacert)) - { - plog("invalid signature"); - return FALSE; - } - else - { - DBG(DBG_CONTROL, - DBG_log("signature is valid") - ) - } - } - return TRUE; + return TRUE; } /* @@ -374,198 +374,198 @@ bool pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data , chunk_t serialNumber, const RSA_private_key_t *key) { - asn1_ctx_t ctx; - chunk_t object; - chunk_t iv = chunk_empty; - chunk_t symmetric_key = chunk_empty; - chunk_t encrypted_content = chunk_empty; + asn1_ctx_t ctx; + chunk_t object; + chunk_t iv = chunk_empty; + chunk_t symmetric_key = chunk_empty; + chunk_t encrypted_content = chunk_empty; - u_char buf[BUF_LEN]; - u_int level; - u_int total_keys = 3; - int enc_alg = OID_UNKNOWN; - int content_enc_alg = OID_UNKNOWN; - int objectID = 0; + u_char buf[BUF_LEN]; + u_int level; + u_int total_keys = 3; + int enc_alg = OID_UNKNOWN; + int content_enc_alg = OID_UNKNOWN; + int objectID = 0; - contentInfo_t cInfo = empty_contentInfo; - *data = chunk_empty; + contentInfo_t cInfo = empty_contentInfo; + *data = chunk_empty; - if (!pkcs7_parse_contentInfo(blob, 0, &cInfo)) - goto failed; + if (!pkcs7_parse_contentInfo(blob, 0, &cInfo)) + goto failed; - if (cInfo.type != OID_PKCS7_ENVELOPED_DATA) - { - plog("pkcs7 content type is not envelopedData"); - return FALSE; - } - - asn1_init(&ctx, cInfo.content, 2, FALSE, DBG_RAW); - - while (objectID < PKCS7_ENVELOPED_ROOF) - { - if (!extract_object(envelopedDataObjects, &objectID, &object, &level, &ctx)) - goto failed; - - switch (objectID) + if (cInfo.type != OID_PKCS7_ENVELOPED_DATA) { - case PKCS7_ENVELOPED_VERSION: - if (*object.ptr != 0) - { - plog("envelopedData version is not 0"); - goto failed; + plog("pkcs7 content type is not envelopedData"); + return FALSE; } - break; - case PKCS7_RECIPIENT_INFO_VERSION: - if (*object.ptr != 0) - { - plog("recipient info version is not 0"); - goto failed; - } - break; - case PKCS7_ISSUER: - DBG(DBG_PARSING, - dntoa(buf, BUF_LEN, object); - DBG_log(" '%s'", buf) - ) - break; - case PKCS7_SERIAL_NUMBER: - if (!chunk_equals(serialNumber, object)) - { - plog("serial numbers do not match"); - goto failed; - } - break; - case PKCS7_ENCRYPTION_ALG: - enc_alg = parse_algorithmIdentifier(object, level, NULL); - if (enc_alg != OID_RSA_ENCRYPTION) - { - plog("only rsa encryption supported"); - goto failed; - } - break; - case PKCS7_ENCRYPTED_KEY: - if (!RSA_decrypt(key, object, &symmetric_key)) - { - plog("symmetric key could not be decrypted with rsa"); - goto failed; - } - DBG(DBG_PRIVATE, - DBG_dump_chunk("symmetric key :", symmetric_key) - ) - break; - case PKCS7_CONTENT_TYPE: - if (asn1_known_oid(object) != OID_PKCS7_DATA) - { - plog("encrypted content not of type pkcs7 data"); - goto failed; - } - break; - case PKCS7_CONTENT_ENC_ALGORITHM: - content_enc_alg = parse_algorithmIdentifier(object, level, &iv); - switch (content_enc_alg) - { - case OID_DES_CBC: - total_keys = 1; + asn1_init(&ctx, cInfo.content, 2, FALSE, DBG_RAW); + + while (objectID < PKCS7_ENVELOPED_ROOF) + { + if (!extract_object(envelopedDataObjects, &objectID, &object, &level, &ctx)) + goto failed; + + switch (objectID) + { + case PKCS7_ENVELOPED_VERSION: + if (*object.ptr != 0) + { + plog("envelopedData version is not 0"); + goto failed; + } break; - case OID_3DES_EDE_CBC: - total_keys = 3; - break; - default: - plog("Only DES and 3DES supported for symmetric encryption"); - goto failed; - } - if (symmetric_key.len != (total_keys * DES_CBC_BLOCK_SIZE)) - { - plog("key length is not %d",(total_keys * DES_CBC_BLOCK_SIZE)); - goto failed; - } - if (!parse_asn1_simple_object(&iv, ASN1_OCTET_STRING, level+1, "IV")) - { - plog("IV could not be parsed"); - goto failed; - } - if (iv.len != DES_CBC_BLOCK_SIZE) - { - plog("IV has wrong length"); - goto failed; - } - break; - case PKCS7_ENCRYPTED_CONTENT: - encrypted_content = object; - break; + case PKCS7_RECIPIENT_INFO_VERSION: + if (*object.ptr != 0) + { + plog("recipient info version is not 0"); + goto failed; + } + break; + case PKCS7_ISSUER: + DBG(DBG_PARSING, + dntoa(buf, BUF_LEN, object); + DBG_log(" '%s'", buf) + ) + break; + case PKCS7_SERIAL_NUMBER: + if (!chunk_equals(serialNumber, object)) + { + plog("serial numbers do not match"); + goto failed; + } + break; + case PKCS7_ENCRYPTION_ALG: + enc_alg = parse_algorithmIdentifier(object, level, NULL); + if (enc_alg != OID_RSA_ENCRYPTION) + { + plog("only rsa encryption supported"); + goto failed; + } + break; + case PKCS7_ENCRYPTED_KEY: + if (!RSA_decrypt(key, object, &symmetric_key)) + { + plog("symmetric key could not be decrypted with rsa"); + goto failed; + } + DBG(DBG_PRIVATE, + DBG_dump_chunk("symmetric key :", symmetric_key) + ) + break; + case PKCS7_CONTENT_TYPE: + if (asn1_known_oid(object) != OID_PKCS7_DATA) + { + plog("encrypted content not of type pkcs7 data"); + goto failed; + } + break; + case PKCS7_CONTENT_ENC_ALGORITHM: + content_enc_alg = parse_algorithmIdentifier(object, level, &iv); + + switch (content_enc_alg) + { + case OID_DES_CBC: + total_keys = 1; + break; + case OID_3DES_EDE_CBC: + total_keys = 3; + break; + default: + plog("Only DES and 3DES supported for symmetric encryption"); + goto failed; + } + if (symmetric_key.len != (total_keys * DES_CBC_BLOCK_SIZE)) + { + plog("key length is not %d",(total_keys * DES_CBC_BLOCK_SIZE)); + goto failed; + } + if (!parse_asn1_simple_object(&iv, ASN1_OCTET_STRING, level+1, "IV")) + { + plog("IV could not be parsed"); + goto failed; + } + if (iv.len != DES_CBC_BLOCK_SIZE) + { + plog("IV has wrong length"); + goto failed; + } + break; + case PKCS7_ENCRYPTED_CONTENT: + encrypted_content = object; + break; + } + objectID++; } - objectID++; - } - /* decrypt the content */ - { - u_int i; - des_cblock des_key[3], des_iv; - des_key_schedule key_s[3]; - - memcpy((char *)des_key, symmetric_key.ptr, symmetric_key.len); - memcpy((char *)des_iv, iv.ptr, iv.len); - - for (i = 0; i < total_keys; i++) + /* decrypt the content */ { - if (des_set_key(&des_key[i], key_s[i])) - { - plog("des key schedule failed"); - goto failed; - } + u_int i; + des_cblock des_key[3], des_iv; + des_key_schedule key_s[3]; + + memcpy((char *)des_key, symmetric_key.ptr, symmetric_key.len); + memcpy((char *)des_iv, iv.ptr, iv.len); + + for (i = 0; i < total_keys; i++) + { + if (des_set_key(&des_key[i], key_s[i])) + { + plog("des key schedule failed"); + goto failed; + } + } + + data->len = encrypted_content.len; + data->ptr = malloc(data->len); + + switch (content_enc_alg) + { + case OID_DES_CBC: + des_cbc_encrypt((des_cblock*)encrypted_content.ptr + , (des_cblock*)data->ptr, data->len + , key_s[0], &des_iv, DES_DECRYPT); + break; + case OID_3DES_EDE_CBC: + des_ede3_cbc_encrypt( (des_cblock*)encrypted_content.ptr + , (des_cblock*)data->ptr, data->len + , key_s[0], key_s[1], key_s[2] + , &des_iv, DES_DECRYPT); + } + DBG(DBG_PRIVATE, + DBG_dump_chunk("decrypted content with padding:\n", *data) + ) } - data->len = encrypted_content.len; - data->ptr = malloc(data->len); - - switch (content_enc_alg) + /* remove the padding */ { - case OID_DES_CBC: - des_cbc_encrypt((des_cblock*)encrypted_content.ptr - , (des_cblock*)data->ptr, data->len - , key_s[0], &des_iv, DES_DECRYPT); - break; - case OID_3DES_EDE_CBC: - des_ede3_cbc_encrypt( (des_cblock*)encrypted_content.ptr - , (des_cblock*)data->ptr, data->len - , key_s[0], key_s[1], key_s[2] - , &des_iv, DES_DECRYPT); - } - DBG(DBG_PRIVATE, - DBG_dump_chunk("decrypted content with padding:\n", *data) - ) - } - - /* remove the padding */ - { - u_char *pos = data->ptr + data->len - 1; - u_char pattern = *pos; - size_t padding = pattern; + u_char *pos = data->ptr + data->len - 1; + u_char pattern = *pos; + size_t padding = pattern; - if (padding > data->len) - { - plog("padding greater than data length"); - goto failed; - } - data->len -= padding; + if (padding > data->len) + { + plog("padding greater than data length"); + goto failed; + } + data->len -= padding; - while (padding-- > 0) - { - if (*pos-- != pattern) - { - plog("wrong padding pattern"); - goto failed; - } + while (padding-- > 0) + { + if (*pos-- != pattern) + { + plog("wrong padding pattern"); + goto failed; + } + } } - } - chunk_clear(&symmetric_key); - return TRUE; + chunk_clear(&symmetric_key); + return TRUE; failed: - chunk_clear(&symmetric_key); - free(data->ptr); - return FALSE; + chunk_clear(&symmetric_key); + free(data->ptr); + return FALSE; } /** @@ -576,9 +576,9 @@ failed: chunk_t pkcs7_contentType_attribute(void) { - return asn1_wrap(ASN1_SEQUENCE, "cm" - , ASN1_contentType_oid - , asn1_simple_object(ASN1_SET, ASN1_pkcs7_data_oid)); + return asn1_wrap(ASN1_SEQUENCE, "cm" + , ASN1_contentType_oid + , asn1_simple_object(ASN1_SET, ASN1_pkcs7_data_oid)); } /** @@ -593,17 +593,17 @@ pkcs7_contentType_attribute(void) chunk_t pkcs7_messageDigest_attribute(chunk_t content, int digest_alg) { - u_char digest_buf[MAX_DIGEST_LEN]; - chunk_t digest = { digest_buf, MAX_DIGEST_LEN }; + u_char digest_buf[MAX_DIGEST_LEN]; + chunk_t digest = { digest_buf, MAX_DIGEST_LEN }; - compute_digest(content, digest_alg, &digest); + compute_digest(content, digest_alg, &digest); - return asn1_wrap(ASN1_SEQUENCE, "cm" - , ASN1_messageDigest_oid - , asn1_wrap(ASN1_SET, "m" - , asn1_simple_object(ASN1_OCTET_STRING, digest) - ) - ); + return asn1_wrap(ASN1_SEQUENCE, "cm" + , ASN1_messageDigest_oid + , asn1_wrap(ASN1_SET, "m" + , asn1_simple_object(ASN1_OCTET_STRING, digest) + ) + ); } /* * build a DER-encoded contentInfo object @@ -611,41 +611,41 @@ pkcs7_messageDigest_attribute(chunk_t content, int digest_alg) static chunk_t pkcs7_build_contentInfo(contentInfo_t *cInfo) { - chunk_t content_type; + chunk_t content_type; - /* select DER-encoded OID for pkcs7 contentInfo type */ - switch(cInfo->type) - { - case OID_PKCS7_DATA: - content_type = ASN1_pkcs7_data_oid; - break; - case OID_PKCS7_SIGNED_DATA: - content_type = ASN1_pkcs7_signed_data_oid; - break; - case OID_PKCS7_ENVELOPED_DATA: - content_type = ASN1_pkcs7_enveloped_data_oid; - break; - case OID_PKCS7_SIGNED_ENVELOPED_DATA: - content_type = ASN1_pkcs7_signed_enveloped_data_oid; - break; - case OID_PKCS7_DIGESTED_DATA: - content_type = ASN1_pkcs7_digested_data_oid; - break; - case OID_PKCS7_ENCRYPTED_DATA: - content_type = ASN1_pkcs7_encrypted_data_oid; - break; - case OID_UNKNOWN: - default: - fprintf(stderr, "invalid pkcs7 contentInfo type"); - return chunk_empty; - } + /* select DER-encoded OID for pkcs7 contentInfo type */ + switch(cInfo->type) + { + case OID_PKCS7_DATA: + content_type = ASN1_pkcs7_data_oid; + break; + case OID_PKCS7_SIGNED_DATA: + content_type = ASN1_pkcs7_signed_data_oid; + break; + case OID_PKCS7_ENVELOPED_DATA: + content_type = ASN1_pkcs7_enveloped_data_oid; + break; + case OID_PKCS7_SIGNED_ENVELOPED_DATA: + content_type = ASN1_pkcs7_signed_enveloped_data_oid; + break; + case OID_PKCS7_DIGESTED_DATA: + content_type = ASN1_pkcs7_digested_data_oid; + break; + case OID_PKCS7_ENCRYPTED_DATA: + content_type = ASN1_pkcs7_encrypted_data_oid; + break; + case OID_UNKNOWN: + default: + fprintf(stderr, "invalid pkcs7 contentInfo type"); + return chunk_empty; + } - return (cInfo->content.ptr == NULL) - ? asn1_simple_object(ASN1_SEQUENCE, content_type) - : asn1_wrap(ASN1_SEQUENCE, "cm" - , content_type - , asn1_simple_object(ASN1_CONTEXT_C_0, cInfo->content) - ); + return (cInfo->content.ptr == NULL) + ? asn1_simple_object(ASN1_SEQUENCE, content_type) + : asn1_wrap(ASN1_SEQUENCE, "cm" + , content_type + , asn1_simple_object(ASN1_CONTEXT_C_0, cInfo->content) + ); } /* @@ -654,9 +654,9 @@ pkcs7_build_contentInfo(contentInfo_t *cInfo) chunk_t pkcs7_build_issuerAndSerialNumber(const x509cert_t *cert) { - return asn1_wrap(ASN1_SEQUENCE, "cm" - , cert->issuer - , asn1_simple_object(ASN1_INTEGER, cert->serialNumber)); + return asn1_wrap(ASN1_SEQUENCE, "cm" + , cert->issuer + , asn1_simple_object(ASN1_INTEGER, cert->serialNumber)); } /* @@ -666,53 +666,53 @@ chunk_t pkcs7_build_signedData(chunk_t data, chunk_t attributes, const x509cert_t *cert , int digest_alg, const RSA_private_key_t *key) { - contentInfo_t pkcs7Data, signedData; - chunk_t authenticatedAttributes, encryptedDigest, signerInfo, cInfo; + contentInfo_t pkcs7Data, signedData; + chunk_t authenticatedAttributes, encryptedDigest, signerInfo, cInfo; - chunk_t digestAlgorithm = asn1_algorithmIdentifier(digest_alg); + chunk_t digestAlgorithm = asn1_algorithmIdentifier(digest_alg); - if (attributes.ptr != NULL) - { - encryptedDigest = pkcs1_build_signature(attributes, digest_alg - , key, FALSE); - authenticatedAttributes = chunk_clone(attributes); - *authenticatedAttributes.ptr = ASN1_CONTEXT_C_0; - } - else - { - encryptedDigest = (data.ptr == NULL)? chunk_empty - : pkcs1_build_signature(data, digest_alg, key, FALSE); - authenticatedAttributes = chunk_empty; - } + if (attributes.ptr != NULL) + { + encryptedDigest = pkcs1_build_signature(attributes, digest_alg + , key, FALSE); + authenticatedAttributes = chunk_clone(attributes); + *authenticatedAttributes.ptr = ASN1_CONTEXT_C_0; + } + else + { + encryptedDigest = (data.ptr == NULL)? chunk_empty + : pkcs1_build_signature(data, digest_alg, key, FALSE); + authenticatedAttributes = chunk_empty; + } - signerInfo = asn1_wrap(ASN1_SEQUENCE, "cmcmcm" - , ASN1_INTEGER_1 - , pkcs7_build_issuerAndSerialNumber(cert) - , digestAlgorithm - , authenticatedAttributes - , ASN1_rsaEncryption_id - , encryptedDigest); + signerInfo = asn1_wrap(ASN1_SEQUENCE, "cmcmcm" + , ASN1_INTEGER_1 + , pkcs7_build_issuerAndSerialNumber(cert) + , digestAlgorithm + , authenticatedAttributes + , ASN1_rsaEncryption_id + , encryptedDigest); - pkcs7Data.type = OID_PKCS7_DATA; - pkcs7Data.content = (data.ptr == NULL)? chunk_empty - : asn1_simple_object(ASN1_OCTET_STRING, data); + pkcs7Data.type = OID_PKCS7_DATA; + pkcs7Data.content = (data.ptr == NULL)? chunk_empty + : asn1_simple_object(ASN1_OCTET_STRING, data); - signedData.type = OID_PKCS7_SIGNED_DATA; - signedData.content = asn1_wrap(ASN1_SEQUENCE, "cmmmm" - , ASN1_INTEGER_1 - , asn1_simple_object(ASN1_SET, digestAlgorithm) - , pkcs7_build_contentInfo(&pkcs7Data) - , asn1_simple_object(ASN1_CONTEXT_C_0, cert->certificate) - , asn1_wrap(ASN1_SET, "m", signerInfo)); + signedData.type = OID_PKCS7_SIGNED_DATA; + signedData.content = asn1_wrap(ASN1_SEQUENCE, "cmmmm" + , ASN1_INTEGER_1 + , asn1_simple_object(ASN1_SET, digestAlgorithm) + , pkcs7_build_contentInfo(&pkcs7Data) + , asn1_simple_object(ASN1_CONTEXT_C_0, cert->certificate) + , asn1_wrap(ASN1_SET, "m", signerInfo)); - cInfo = pkcs7_build_contentInfo(&signedData); - DBG(DBG_RAW, - DBG_dump_chunk("signedData:\n", cInfo) - ) + cInfo = pkcs7_build_contentInfo(&signedData); + DBG(DBG_RAW, + DBG_dump_chunk("signedData:\n", cInfo) + ) - free(pkcs7Data.content.ptr); - free(signedData.content.ptr); - return cInfo; + free(pkcs7Data.content.ptr); + free(signedData.content.ptr); + return cInfo; } /* @@ -721,137 +721,137 @@ pkcs7_build_signedData(chunk_t data, chunk_t attributes, const x509cert_t *cert chunk_t pkcs7_build_envelopedData(chunk_t data, const x509cert_t *cert, int cipher) { - bool des_check_key_save; - des_key_schedule ks[3]; - des_cblock key[3], des_iv, des_iv_buf; + bool des_check_key_save; + des_key_schedule ks[3]; + des_cblock key[3], des_iv, des_iv_buf; - chunk_t iv = { (u_char *)des_iv_buf, DES_CBC_BLOCK_SIZE }; - chunk_t out; - chunk_t cipher_oid; + chunk_t iv = { (u_char *)des_iv_buf, DES_CBC_BLOCK_SIZE }; + chunk_t out; + chunk_t cipher_oid; - u_int total_keys, i; - size_t padding = pad_up(data.len, DES_CBC_BLOCK_SIZE); + u_int total_keys, i; + size_t padding = pad_up(data.len, DES_CBC_BLOCK_SIZE); - RSA_public_key_t public_key; + RSA_public_key_t public_key; - init_RSA_public_key(&public_key, cert->publicExponent - , cert->modulus); + init_RSA_public_key(&public_key, cert->publicExponent + , cert->modulus); - if (padding == 0) - padding += DES_CBC_BLOCK_SIZE; + if (padding == 0) + padding += DES_CBC_BLOCK_SIZE; - out.len = data.len + padding; - out.ptr = malloc(out.len); + out.len = data.len + padding; + out.ptr = malloc(out.len); - DBG(DBG_CONTROL, - DBG_log("padding %d bytes of data to multiple DES block size of %d bytes" - , (int)data.len, (int)out.len) - ) - - /* copy data */ - memcpy(out.ptr, data.ptr, data.len); - /* append padding */ - memset(out.ptr + data.len, padding, padding); - - DBG(DBG_RAW, - DBG_dump_chunk("Padded unencrypted data:\n", out) - ) - - /* select OID and keylength for specified cipher */ - switch (cipher) - { - case OID_DES_CBC: - total_keys = 1; - cipher_oid = ASN1_des_cbc_oid; - break; - case OID_3DES_EDE_CBC: - default: - total_keys = 3; - cipher_oid = ASN1_3des_ede_cbc_oid; - } - DBG(DBG_CONTROLMORE, - DBG_log("pkcs7 encryption cipher: %s", oid_names[cipher].name) - ) - - /* generate a strong random key for DES/3DES */ - des_check_key_save = des_check_key; - des_check_key = TRUE; - for (i = 0; i < total_keys;i++) - { - for (;;) - { - get_rnd_bytes((char*)key[i], DES_CBC_BLOCK_SIZE); - des_set_odd_parity(&key[i]); - if (!des_set_key(&key[i], ks[i])) - break; - plog("weak DES key discarded - we try again"); - } - DBG(DBG_PRIVATE, - DBG_dump("DES key:", key[i], 8) + DBG(DBG_CONTROL, + DBG_log("padding %d bytes of data to multiple DES block size of %d bytes" + , (int)data.len, (int)out.len) ) - } - des_check_key = des_check_key_save; - /* generate an iv for DES/3DES CBC */ - get_rnd_bytes(des_iv, DES_CBC_BLOCK_SIZE); - memcpy(iv.ptr, des_iv, DES_CBC_BLOCK_SIZE); - DBG(DBG_RAW, - DBG_dump_chunk("DES IV :", iv) - ) + /* copy data */ + memcpy(out.ptr, data.ptr, data.len); + /* append padding */ + memset(out.ptr + data.len, padding, padding); - /* encryption using specified cipher */ - switch (cipher) - { - case OID_DES_CBC: - des_cbc_encrypt((des_cblock*)out.ptr, (des_cblock*)out.ptr, out.len - , ks[0], &des_iv, DES_ENCRYPT); - break; - case OID_3DES_EDE_CBC: - default: - des_ede3_cbc_encrypt((des_cblock*)out.ptr, (des_cblock*)out.ptr, out.len - , ks[0], ks[1], ks[2], &des_iv, DES_ENCRYPT); - } - DBG(DBG_RAW, - DBG_dump_chunk("Encrypted data:\n", out)); - - /* build pkcs7 enveloped data object */ - { - chunk_t contentEncryptionAlgorithm = asn1_wrap(ASN1_SEQUENCE, "cm" - , cipher_oid - , asn1_simple_object(ASN1_OCTET_STRING, iv)); - - chunk_t encryptedContentInfo = asn1_wrap(ASN1_SEQUENCE, "cmm" - , ASN1_pkcs7_data_oid - , contentEncryptionAlgorithm - , asn1_wrap(ASN1_CONTEXT_S_0, "m", out)); - - chunk_t plainKey = { (u_char *)key, DES_CBC_BLOCK_SIZE * total_keys }; - - chunk_t encryptedKey = asn1_wrap(ASN1_OCTET_STRING, "m" - , RSA_encrypt(&public_key, plainKey)); - - chunk_t recipientInfo = asn1_wrap(ASN1_SEQUENCE, "cmcm" - , ASN1_INTEGER_0 - , pkcs7_build_issuerAndSerialNumber(cert) - , ASN1_rsaEncryption_id - , encryptedKey); - - chunk_t cInfo; - contentInfo_t envelopedData; - - envelopedData.type = OID_PKCS7_ENVELOPED_DATA; - envelopedData.content = asn1_wrap(ASN1_SEQUENCE, "cmm" - , ASN1_INTEGER_0 - , asn1_wrap(ASN1_SET, "m", recipientInfo) - , encryptedContentInfo); - - cInfo = pkcs7_build_contentInfo(&envelopedData); DBG(DBG_RAW, - DBG_dump_chunk("envelopedData:\n", cInfo) + DBG_dump_chunk("Padded unencrypted data:\n", out) ) - free_RSA_public_content(&public_key); - free(envelopedData.content.ptr); - return cInfo; - } + /* select OID and keylength for specified cipher */ + switch (cipher) + { + case OID_DES_CBC: + total_keys = 1; + cipher_oid = ASN1_des_cbc_oid; + break; + case OID_3DES_EDE_CBC: + default: + total_keys = 3; + cipher_oid = ASN1_3des_ede_cbc_oid; + } + DBG(DBG_CONTROLMORE, + DBG_log("pkcs7 encryption cipher: %s", oid_names[cipher].name) + ) + + /* generate a strong random key for DES/3DES */ + des_check_key_save = des_check_key; + des_check_key = TRUE; + for (i = 0; i < total_keys;i++) + { + for (;;) + { + get_rnd_bytes((char*)key[i], DES_CBC_BLOCK_SIZE); + des_set_odd_parity(&key[i]); + if (!des_set_key(&key[i], ks[i])) + break; + plog("weak DES key discarded - we try again"); + } + DBG(DBG_PRIVATE, + DBG_dump("DES key:", key[i], 8) + ) + } + des_check_key = des_check_key_save; + + /* generate an iv for DES/3DES CBC */ + get_rnd_bytes(des_iv, DES_CBC_BLOCK_SIZE); + memcpy(iv.ptr, des_iv, DES_CBC_BLOCK_SIZE); + DBG(DBG_RAW, + DBG_dump_chunk("DES IV :", iv) + ) + + /* encryption using specified cipher */ + switch (cipher) + { + case OID_DES_CBC: + des_cbc_encrypt((des_cblock*)out.ptr, (des_cblock*)out.ptr, out.len + , ks[0], &des_iv, DES_ENCRYPT); + break; + case OID_3DES_EDE_CBC: + default: + des_ede3_cbc_encrypt((des_cblock*)out.ptr, (des_cblock*)out.ptr, out.len + , ks[0], ks[1], ks[2], &des_iv, DES_ENCRYPT); + } + DBG(DBG_RAW, + DBG_dump_chunk("Encrypted data:\n", out)); + + /* build pkcs7 enveloped data object */ + { + chunk_t contentEncryptionAlgorithm = asn1_wrap(ASN1_SEQUENCE, "cm" + , cipher_oid + , asn1_simple_object(ASN1_OCTET_STRING, iv)); + + chunk_t encryptedContentInfo = asn1_wrap(ASN1_SEQUENCE, "cmm" + , ASN1_pkcs7_data_oid + , contentEncryptionAlgorithm + , asn1_wrap(ASN1_CONTEXT_S_0, "m", out)); + + chunk_t plainKey = { (u_char *)key, DES_CBC_BLOCK_SIZE * total_keys }; + + chunk_t encryptedKey = asn1_wrap(ASN1_OCTET_STRING, "m" + , RSA_encrypt(&public_key, plainKey)); + + chunk_t recipientInfo = asn1_wrap(ASN1_SEQUENCE, "cmcm" + , ASN1_INTEGER_0 + , pkcs7_build_issuerAndSerialNumber(cert) + , ASN1_rsaEncryption_id + , encryptedKey); + + chunk_t cInfo; + contentInfo_t envelopedData; + + envelopedData.type = OID_PKCS7_ENVELOPED_DATA; + envelopedData.content = asn1_wrap(ASN1_SEQUENCE, "cmm" + , ASN1_INTEGER_0 + , asn1_wrap(ASN1_SET, "m", recipientInfo) + , encryptedContentInfo); + + cInfo = pkcs7_build_contentInfo(&envelopedData); + DBG(DBG_RAW, + DBG_dump_chunk("envelopedData:\n", cInfo) + ) + + free_RSA_public_content(&public_key); + free(envelopedData.content.ptr); + return cInfo; + } } diff --git a/src/pluto/pkcs7.h b/src/pluto/pkcs7.h index 56a6389af..404b4938a 100644 --- a/src/pluto/pkcs7.h +++ b/src/pluto/pkcs7.h @@ -28,24 +28,24 @@ typedef struct contentInfo contentInfo_t; struct contentInfo { - int type; - chunk_t content; + int type; + chunk_t content; }; extern const contentInfo_t empty_contentInfo; extern bool pkcs7_parse_contentInfo(chunk_t blob, u_int level0 - , contentInfo_t *cInfo); + , contentInfo_t *cInfo); extern bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data - , x509cert_t **cert, chunk_t *attributes, const x509cert_t *cacert); + , x509cert_t **cert, chunk_t *attributes, const x509cert_t *cacert); extern bool pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data - , chunk_t serialNumber, const RSA_private_key_t *key); + , chunk_t serialNumber, const RSA_private_key_t *key); extern chunk_t pkcs7_contentType_attribute(void); extern chunk_t pkcs7_messageDigest_attribute(chunk_t content, int digest_alg); extern chunk_t pkcs7_build_issuerAndSerialNumber(const x509cert_t *cert); extern chunk_t pkcs7_build_signedData(chunk_t data, chunk_t attributes - ,const x509cert_t *cert, int digest_alg, const RSA_private_key_t *key); + ,const x509cert_t *cert, int digest_alg, const RSA_private_key_t *key); extern chunk_t pkcs7_build_envelopedData(chunk_t data, const x509cert_t *cert - , int cipher); + , int cipher); #endif /* _PKCS7_H */ diff --git a/src/pluto/plutomain.c b/src/pluto/plutomain.c index 75f4cab8b..fa973fc11 100644 --- a/src/pluto/plutomain.c +++ b/src/pluto/plutomain.c @@ -29,7 +29,7 @@ #include #include #include -#include /* missing from on old systems */ +#include /* missing from on old systems */ #include #include #include @@ -55,91 +55,91 @@ #include "connections.h" #include "foodgroups.h" #include "packet.h" -#include "demux.h" /* needs packet.h */ +#include "demux.h" /* needs packet.h */ #include "server.h" #include "kernel.h" #include "log.h" #include "keys.h" -#include "adns.h" /* needs */ -#include "dnskey.h" /* needs keys.h and adns.h */ +#include "adns.h" /* needs */ +#include "dnskey.h" /* needs keys.h and adns.h */ #include "rnd.h" #include "state.h" -#include "ipsec_doi.h" /* needs demux.h and state.h */ +#include "ipsec_doi.h" /* needs demux.h and state.h */ #include "ocsp.h" #include "crl.h" #include "fetch.h" #include "xauth.h" #include "sha1.h" #include "md5.h" -#include "crypto.h" /* requires sha1.h and md5.h */ +#include "crypto.h" /* requires sha1.h and md5.h */ #include "nat_traversal.h" #include "virtual.h" static void usage(const char *mess) { - if (mess != NULL && *mess != '\0') - fprintf(stderr, "%s\n", mess); - fprintf(stderr - , "Usage: pluto" - " [--help]" - " [--version]" - " [--optionsfrom ]" - " \\\n\t" - "[--nofork]" - " [--stderrlog]" - " [--noklips]" - " [--nocrsend]" - " \\\n\t" - "[--strictcrlpolicy]" - " [--crlcheckinterval ]" - " [--cachecrls]" - " [--uniqueids]" - " \\\n\t" - "[--interface ]" - " [--ikeport ]" - " \\\n\t" - "[--ctlbase ]" - " \\\n\t" - "[--perpeerlogbase ] [--perpeerlog]" - " \\\n\t" - "[--secretsfile ]" - " [--policygroupsdir ]" - " \\\n\t" - "[--adns ]" - "[--pkcs11module ]" - "[--pkcs11keepstate]" - "[--pkcs11initargs ]" + if (mess != NULL && *mess != '\0') + fprintf(stderr, "%s\n", mess); + fprintf(stderr + , "Usage: pluto" + " [--help]" + " [--version]" + " [--optionsfrom ]" + " \\\n\t" + "[--nofork]" + " [--stderrlog]" + " [--noklips]" + " [--nocrsend]" + " \\\n\t" + "[--strictcrlpolicy]" + " [--crlcheckinterval ]" + " [--cachecrls]" + " [--uniqueids]" + " \\\n\t" + "[--interface ]" + " [--ikeport ]" + " \\\n\t" + "[--ctlbase ]" + " \\\n\t" + "[--perpeerlogbase ] [--perpeerlog]" + " \\\n\t" + "[--secretsfile ]" + " [--policygroupsdir ]" + " \\\n\t" + "[--adns ]" + "[--pkcs11module ]" + "[--pkcs11keepstate]" + "[--pkcs11initargs ]" #ifdef DEBUG - " \\\n\t" - "[--debug-none]" - " [--debug-all]" - " \\\n\t" - "[--debug-raw]" - " [--debug-crypt]" - " [--debug-parsing]" - " [--debug-emitting]" - " \\\n\t" - "[--debug-control]" - " [--debug-lifecycle]" - " [--debug-klips]" - " [--debug-dns]" - " \\\n\t" - "[--debug-oppo]" - " [--debug-controlmore]" - " [--debug-private]" + " \\\n\t" + "[--debug-none]" + " [--debug-all]" + " \\\n\t" + "[--debug-raw]" + " [--debug-crypt]" + " [--debug-parsing]" + " [--debug-emitting]" + " \\\n\t" + "[--debug-control]" + " [--debug-lifecycle]" + " [--debug-klips]" + " [--debug-dns]" + " \\\n\t" + "[--debug-oppo]" + " [--debug-controlmore]" + " [--debug-private]" #endif - " [ --debug-natt]" - " \\\n\t" - "[--nat_traversal] [--keep_alive ]" - " \\\n\t" - "[--force_keepalive] [--disable_port_floating]" - " \\\n\t" - "[--virtual_private ]" - "\n" - "strongSwan %s\n" - , ipsec_version_code()); - exit_pluto(mess == NULL? 0 : 1); + " [ --debug-natt]" + " \\\n\t" + "[--nat_traversal] [--keep_alive ]" + " \\\n\t" + "[--force_keepalive] [--disable_port_floating]" + " \\\n\t" + "[--virtual_private ]" + "\n" + "strongSwan %s\n" + , ipsec_version_code()); + exit_pluto(mess == NULL? 0 : 1); } @@ -157,47 +157,47 @@ static bool pluto_lock_created = FALSE; static int create_lock(void) { - int fd = open(pluto_lock, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC - , S_IRUSR | S_IRGRP | S_IROTH); + int fd = open(pluto_lock, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC + , S_IRUSR | S_IRGRP | S_IROTH); - if (fd < 0) - { - if (errno == EEXIST) + if (fd < 0) { - fprintf(stderr, "pluto: lock file \"%s\" already exists\n" - , pluto_lock); - exit_pluto(10); + if (errno == EEXIST) + { + fprintf(stderr, "pluto: lock file \"%s\" already exists\n" + , pluto_lock); + exit_pluto(10); + } + else + { + fprintf(stderr + , "pluto: unable to create lock file \"%s\" (%d %s)\n" + , pluto_lock, errno, strerror(errno)); + exit_pluto(1); + } } - else - { - fprintf(stderr - , "pluto: unable to create lock file \"%s\" (%d %s)\n" - , pluto_lock, errno, strerror(errno)); - exit_pluto(1); - } - } - pluto_lock_created = TRUE; - return fd; + pluto_lock_created = TRUE; + return fd; } static bool fill_lock(int lockfd, pid_t pid) { - char buf[30]; /* holds "\n" */ - int len = snprintf(buf, sizeof(buf), "%u\n", (unsigned int) pid); - bool ok = len > 0 && write(lockfd, buf, len) == len; + char buf[30]; /* holds "\n" */ + int len = snprintf(buf, sizeof(buf), "%u\n", (unsigned int) pid); + bool ok = len > 0 && write(lockfd, buf, len) == len; - close(lockfd); - return ok; + close(lockfd); + return ok; } static void delete_lock(void) { - if (pluto_lock_created) - { - delete_ctl_socket(); - unlink(pluto_lock); /* is noting failure useful? */ - } + if (pluto_lock_created) + { + delete_ctl_socket(); + unlink(pluto_lock); /* is noting failure useful? */ + } } static int debug_level = 1; @@ -207,39 +207,39 @@ static int debug_level = 1; */ static void pluto_dbg(int level, char *fmt, ...) { - int priority = LOG_INFO; - char buffer[8192]; - char *current = buffer, *next; - va_list args; - - if (level <= debug_level) - { - va_start(args, fmt); - - if (log_to_stderr) + int priority = LOG_INFO; + char buffer[8192]; + char *current = buffer, *next; + va_list args; + + if (level <= debug_level) { - vfprintf(stderr, fmt, args); - fprintf(stderr, "\n"); - } - if (log_to_syslog) - { - /* write in memory buffer first */ - vsnprintf(buffer, sizeof(buffer), fmt, args); + va_start(args, fmt); - /* do a syslog with every line */ - while (current) - { - next = strchr(current, '\n'); - if (next) - { - *(next++) = '\0'; + if (log_to_stderr) + { + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); } - syslog(priority, "%s\n", current); - current = next; - } + if (log_to_syslog) + { + /* write in memory buffer first */ + vsnprintf(buffer, sizeof(buffer), fmt, args); + + /* do a syslog with every line */ + while (current) + { + next = strchr(current, '\n'); + if (next) + { + *(next++) = '\0'; + } + syslog(priority, "%s\n", current); + current = next; + } + } + va_end(args); } - va_end(args); - } } /* by default pluto sends certificate requests to its peers */ @@ -271,464 +271,464 @@ static const char *pkcs11_init_args = NULL; int main(int argc, char **argv) { - bool fork_desired = TRUE; - bool log_to_stderr_desired = FALSE; - bool nat_traversal = FALSE; - bool nat_t_spf = TRUE; /* support port floating */ - unsigned int keep_alive = 0; - bool force_keepalive = FALSE; - char *virtual_private = NULL; - int lockfd; + bool fork_desired = TRUE; + bool log_to_stderr_desired = FALSE; + bool nat_traversal = FALSE; + bool nat_t_spf = TRUE; /* support port floating */ + unsigned int keep_alive = 0; + bool force_keepalive = FALSE; + char *virtual_private = NULL; + int lockfd; #ifdef CAPABILITIES - cap_t caps; - int keep[] = { CAP_NET_ADMIN, CAP_NET_BIND_SERVICE }; + cap_t caps; + int keep[] = { CAP_NET_ADMIN, CAP_NET_BIND_SERVICE }; #endif /* CAPABILITIES */ - library_init(STRONGSWAN_CONF); + library_init(STRONGSWAN_CONF); - /* handle arguments */ - for (;;) - { -# define DBG_OFFSET 256 - static const struct option long_opts[] = { - /* name, has_arg, flag, val */ - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, 'v' }, - { "optionsfrom", required_argument, NULL, '+' }, - { "nofork", no_argument, NULL, 'd' }, - { "stderrlog", no_argument, NULL, 'e' }, - { "noklips", no_argument, NULL, 'n' }, - { "nocrsend", no_argument, NULL, 'c' }, - { "strictcrlpolicy", no_argument, NULL, 'r' }, - { "crlcheckinterval", required_argument, NULL, 'x'}, - { "cachecrls", no_argument, NULL, 'C' }, - { "uniqueids", no_argument, NULL, 'u' }, - { "interface", required_argument, NULL, 'i' }, - { "ikeport", required_argument, NULL, 'p' }, - { "ctlbase", required_argument, NULL, 'b' }, - { "secretsfile", required_argument, NULL, 's' }, - { "foodgroupsdir", required_argument, NULL, 'f' }, - { "perpeerlogbase", required_argument, NULL, 'P' }, - { "perpeerlog", no_argument, NULL, 'l' }, - { "policygroupsdir", required_argument, NULL, 'f' }, + /* handle arguments */ + for (;;) + { +# define DBG_OFFSET 256 + static const struct option long_opts[] = { + /* name, has_arg, flag, val */ + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'v' }, + { "optionsfrom", required_argument, NULL, '+' }, + { "nofork", no_argument, NULL, 'd' }, + { "stderrlog", no_argument, NULL, 'e' }, + { "noklips", no_argument, NULL, 'n' }, + { "nocrsend", no_argument, NULL, 'c' }, + { "strictcrlpolicy", no_argument, NULL, 'r' }, + { "crlcheckinterval", required_argument, NULL, 'x'}, + { "cachecrls", no_argument, NULL, 'C' }, + { "uniqueids", no_argument, NULL, 'u' }, + { "interface", required_argument, NULL, 'i' }, + { "ikeport", required_argument, NULL, 'p' }, + { "ctlbase", required_argument, NULL, 'b' }, + { "secretsfile", required_argument, NULL, 's' }, + { "foodgroupsdir", required_argument, NULL, 'f' }, + { "perpeerlogbase", required_argument, NULL, 'P' }, + { "perpeerlog", no_argument, NULL, 'l' }, + { "policygroupsdir", required_argument, NULL, 'f' }, #ifdef USE_LWRES - { "lwdnsq", required_argument, NULL, 'a' }, + { "lwdnsq", required_argument, NULL, 'a' }, #else /* !USE_LWRES */ - { "adns", required_argument, NULL, 'a' }, + { "adns", required_argument, NULL, 'a' }, #endif /* !USE_LWRES */ - { "pkcs11module", required_argument, NULL, 'm' }, - { "pkcs11keepstate", no_argument, NULL, 'k' }, - { "pkcs11initargs", required_argument, NULL, 'z' }, - { "pkcs11proxy", no_argument, NULL, 'y' }, - { "nat_traversal", no_argument, NULL, '1' }, - { "keep_alive", required_argument, NULL, '2' }, - { "force_keepalive", no_argument, NULL, '3' }, - { "disable_port_floating", no_argument, NULL, '4' }, - { "debug-natt", no_argument, NULL, '5' }, - { "virtual_private", required_argument, NULL, '6' }, + { "pkcs11module", required_argument, NULL, 'm' }, + { "pkcs11keepstate", no_argument, NULL, 'k' }, + { "pkcs11initargs", required_argument, NULL, 'z' }, + { "pkcs11proxy", no_argument, NULL, 'y' }, + { "nat_traversal", no_argument, NULL, '1' }, + { "keep_alive", required_argument, NULL, '2' }, + { "force_keepalive", no_argument, NULL, '3' }, + { "disable_port_floating", no_argument, NULL, '4' }, + { "debug-natt", no_argument, NULL, '5' }, + { "virtual_private", required_argument, NULL, '6' }, #ifdef DEBUG - { "debug-none", no_argument, NULL, 'N' }, - { "debug-all", no_argument, NULL, 'A' }, - { "debug-raw", no_argument, NULL, DBG_RAW + DBG_OFFSET }, - { "debug-crypt", no_argument, NULL, DBG_CRYPT + DBG_OFFSET }, - { "debug-parsing", no_argument, NULL, DBG_PARSING + DBG_OFFSET }, - { "debug-emitting", no_argument, NULL, DBG_EMITTING + DBG_OFFSET }, - { "debug-control", no_argument, NULL, DBG_CONTROL + DBG_OFFSET }, - { "debug-lifecycle", no_argument, NULL, DBG_LIFECYCLE + DBG_OFFSET }, - { "debug-klips", no_argument, NULL, DBG_KLIPS + DBG_OFFSET }, - { "debug-dns", no_argument, NULL, DBG_DNS + DBG_OFFSET }, - { "debug-oppo", no_argument, NULL, DBG_OPPO + DBG_OFFSET }, - { "debug-controlmore", no_argument, NULL, DBG_CONTROLMORE + DBG_OFFSET }, - { "debug-private", no_argument, NULL, DBG_PRIVATE + DBG_OFFSET }, + { "debug-none", no_argument, NULL, 'N' }, + { "debug-all", no_argument, NULL, 'A' }, + { "debug-raw", no_argument, NULL, DBG_RAW + DBG_OFFSET }, + { "debug-crypt", no_argument, NULL, DBG_CRYPT + DBG_OFFSET }, + { "debug-parsing", no_argument, NULL, DBG_PARSING + DBG_OFFSET }, + { "debug-emitting", no_argument, NULL, DBG_EMITTING + DBG_OFFSET }, + { "debug-control", no_argument, NULL, DBG_CONTROL + DBG_OFFSET }, + { "debug-lifecycle", no_argument, NULL, DBG_LIFECYCLE + DBG_OFFSET }, + { "debug-klips", no_argument, NULL, DBG_KLIPS + DBG_OFFSET }, + { "debug-dns", no_argument, NULL, DBG_DNS + DBG_OFFSET }, + { "debug-oppo", no_argument, NULL, DBG_OPPO + DBG_OFFSET }, + { "debug-controlmore", no_argument, NULL, DBG_CONTROLMORE + DBG_OFFSET }, + { "debug-private", no_argument, NULL, DBG_PRIVATE + DBG_OFFSET }, - { "impair-delay-adns-key-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_KEY_ANSWER + DBG_OFFSET }, - { "impair-delay-adns-txt-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_TXT_ANSWER + DBG_OFFSET }, - { "impair-bust-mi2", no_argument, NULL, IMPAIR_BUST_MI2 + DBG_OFFSET }, - { "impair-bust-mr2", no_argument, NULL, IMPAIR_BUST_MR2 + DBG_OFFSET }, + { "impair-delay-adns-key-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_KEY_ANSWER + DBG_OFFSET }, + { "impair-delay-adns-txt-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_TXT_ANSWER + DBG_OFFSET }, + { "impair-bust-mi2", no_argument, NULL, IMPAIR_BUST_MI2 + DBG_OFFSET }, + { "impair-bust-mr2", no_argument, NULL, IMPAIR_BUST_MR2 + DBG_OFFSET }, #endif - { 0,0,0,0 } - }; - /* Note: we don't like the way short options get parsed - * by getopt_long, so we simply pass an empty string as - * the list. It could be "hvdenp:l:s:" "NARXPECK". - */ - int c = getopt_long(argc, argv, "", long_opts, NULL); - - /* Note: "breaking" from case terminates loop */ - switch (c) - { - case EOF: /* end of flags */ - break; - - case 0: /* long option already handled */ - continue; - - case ':': /* diagnostic already printed by getopt_long */ - case '?': /* diagnostic already printed by getopt_long */ - usage(""); - break; /* not actually reached */ - - case 'h': /* --help */ - usage(NULL); - break; /* not actually reached */ - - case 'v': /* --version */ - { - const char **sp = ipsec_copyright_notice(); - - printf("%s%s\n", ipsec_version_string(), - compile_time_interop_options); - for (; *sp != NULL; sp++) - puts(*sp); - } - exit_pluto(0); - break; /* not actually reached */ - - case '+': /* --optionsfrom */ - optionsfrom(optarg, &argc, &argv, optind, stderr); - /* does not return on error */ - continue; - - case 'd': /* --nofork*/ - fork_desired = FALSE; - continue; - - case 'e': /* --stderrlog */ - log_to_stderr_desired = TRUE; - continue; - - case 'n': /* --noklips */ - no_klips = TRUE; - continue; - - case 'c': /* --nocrsend */ - no_cr_send = TRUE; - continue; - - case 'r': /* --strictcrlpolicy */ - strict_crl_policy = TRUE; - continue; - - case 'x': /* --crlcheckinterval