diff --git a/.travis.yml b/.travis.yml index 69237fa..6f05ff9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,11 @@ matrix: include: - os: linux - dist: trusty + dist: xenial sudo: required compiler: gcc - os: linux - dist: trusty + dist: xenial sudo: required compiler: clang - os: osx @@ -20,12 +20,12 @@ notifications: before_install: - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install openssl ; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install libtasn1 nettle gnutls; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get -qq update ; fi - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install -y libpcsclite-dev libxcursor-dev libao-dev libasound2-dev ; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install -y libpcsclite-dev libxcursor-dev libao-dev libasound2-dev libtasn1-dev nettle-dev libgnutls-dev ; fi script: - ./bootstrap - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then PKG_CONFIG_PATH=/opt/X11/lib/pkgconfig ./configure --with-openssl=/usr/local/opt/openssl ; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then PKG_CONFIG_PATH=/opt/X11/lib/pkgconfig ./configure ; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./configure ; fi - make diff --git a/asn.c b/asn.c index 1b9fea4..07e9804 100644 --- a/asn.c +++ b/asn.c @@ -2,6 +2,7 @@ rdesktop: A Remote Desktop Protocol client. ASN.1 utility functions Copyright 2012-2017 Henrik Andersson for Cendio AB + Copyright 2017 Alexander Zakharov 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 @@ -17,8 +18,20 @@ along with this program. If not, see . */ -#include "rdesktop.h" +#include +#include +#include +#include "rdesktop.h" +#include "asn.h" + +// Generated by asn1Parser +#include "pkix_asn1_tab.c" + +static asn1_node *asn_defs = NULL; + +#define MAX_ERROR_DESCRIPTION_SIZE 1024 +char errstr[MAX_ERROR_DESCRIPTION_SIZE]; /* Parse an ASN.1 BER header */ RD_BOOL @@ -118,3 +131,201 @@ ber_in_header(STREAM s, int *tagval, int *decoded_len) return False; } + + +int init_asn1_lib(void) +{ + int asn1_rv; + + if (asn_defs) { + return 0; + } + + asn_defs = malloc(sizeof(*asn_defs)); + + if (!asn_defs) { + logger(Core, Error, "%s:%s:%d Failed to allocate memory for ASN.1 parser\n", + __FILE__, __func__, __LINE__); + return 1; + } + + *asn_defs = NULL; + + if (ASN1_SUCCESS != (asn1_rv = asn1_array2tree(pkix_asn1_tab, asn_defs, errstr))) { + logger(Core, Error, "%s:%s:%d Failed to init ASN.1 parser. Error = 0x%x (%s)\n", + __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); + + return 1; + } + + return 0; +} + +/* Encode RSA public key into DER PKCS#1 */ +/* Returns; 0 - success, 1 - fatal error, 2 - insufficient space in buffer */ +int write_pkcs1_der_pubkey(const gnutls_datum_t *m, const gnutls_datum_t *e, uint8_t *out, int *out_len) +{ + int asn1_rv; + asn1_node asn_cert; + + if (!asn_defs) { + if (init_asn1_lib() != 0) { + return 1; + } + } + + if (ASN1_SUCCESS != (asn1_rv = asn1_create_element(*asn_defs, "PKIX1Implicit88.RSAPublicKey", &asn_cert))) { + logger(Core, Error, "%s:%s:%d Failed to create ASN.1 parser element for RSAPublicKey. Error = 0x%x (%s)\n", + __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); + return 1; + } + + if (ASN1_SUCCESS != (asn1_rv = asn1_write_value(asn_cert, "modulus", m->data, m->size))) { + logger(Core, Error, "%s:%s:%d Failed to write modulus. Error = 0x%x (%s)\n", + __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); + + return 1; + } + + if (ASN1_SUCCESS != (asn1_rv = asn1_write_value(asn_cert, "publicExponent", e->data, e->size))) { + logger(Core, Error, "%s:%s:%d Failed to write publicExponent. Error = 0x%x (%s)\n", + __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); + return 1; + } + + if (ASN1_SUCCESS != (asn1_rv = asn1_der_coding(asn_cert, "", out, out_len, errstr))) { + logger(Core, Error, "%s:%s:%d Failed to encode PKIX1Implicit88.RSAPublicKey. Error = 0x%x (%s)\n", + __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); + + if (asn1_rv == ASN1_MEM_ERROR) { + return 2; + } + + return 1; + } + + return 0; +} + +int libtasn_read_cert_pk_oid(uint8_t *data, size_t len, char *oid, size_t *oid_size) +{ + int asn1_rv; + asn1_node asn_cert; + + /* Parse DER encoded x.509 certificate */ + if (!asn_defs) { + if (init_asn1_lib() != 0) { + return 1; + } + } + + if (ASN1_SUCCESS != (asn1_rv = asn1_create_element(*asn_defs, "PKIX1Implicit88.Certificate", &asn_cert))) { + logger(Core, Error, "%s:%s:%d Failed to create ASN.1 parser element. Error = 0x%x (%s)\n", + __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); + return 1; + } + + if (ASN1_SUCCESS != (asn1_rv = asn1_der_decoding(&asn_cert, data, len, errstr))) { + logger(Core, Error, "%s:%s:%d Failed to decode certificate object. Error = 0x%x (%s)\n", + __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); + return 1; + } + + if (ASN1_SUCCESS != (asn1_rv = asn1_read_value(asn_cert, "tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm", + oid, (int *)oid_size))) + { + logger(Core, Error, "%s:%s:%d Failed to get cert's public key algorithm. Error = 0x%x (%s)\n", + __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); + return 1; + } + + return 0; +} + +int libtasn_read_cert_pk_parameters(uint8_t *data, size_t len, gnutls_datum_t *m, gnutls_datum_t *e) +{ + int asn1_rv; + asn1_node asn_cert; + + int buflen; + uint8_t buf[16384]; + + asn1_node asn_key; + int nblen; + uint8_t newbuf[16384]; + + /* Parse DER encoded x.509 certificate */ + init_asn1_lib(); + + if (ASN1_SUCCESS != (asn1_rv = asn1_create_element(*asn_defs, "PKIX1Implicit88.Certificate", &asn_cert))) { + logger(Core, Error, "%s:%s:%d Failed to create ASN.1 parser element. Error = 0x%x (%s)\n", + __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); + return 1; + } + + if (ASN1_SUCCESS != (asn1_rv = asn1_der_decoding(&asn_cert, data, len, errstr))) { + logger(Core, Error, "%s:%s:%d Failed to decode certificate object. Error = 0x%x (%s)\n", + __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); + return 1; + } + + buflen = sizeof(buf) - 1; + if (ASN1_SUCCESS != (asn1_rv = asn1_read_value(asn_cert, "tbsCertificate.subjectPublicKeyInfo.subjectPublicKey", buf, &buflen))) { + logger(Core, Error, "%s:%s:%d Failed to get cert's public key. Error = 0x%x (%s)\n", + __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); + return 1; + } + + if (ASN1_SUCCESS != (asn1_rv = asn1_create_element(*asn_defs, "PKIX1Implicit88.RSAPublicKey", &asn_key))) { + logger(Core, Error, "%s:%s:%d Failed to create ASN.1 parser element. Error = 0x%x (%s)\n", + __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); + return 1; + } + + // As it' a BIT STRING the len constitutes the number of BITS, not BYTES + if (ASN1_SUCCESS != (asn1_rv = asn1_der_decoding(&asn_key, buf, buflen / 8, errstr))) { + logger(Core, Error, "%s:%s:%d Failed to decode public key object. Error = 0x%x (%s)\n", + __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); + return 1; + } + + /* Get RSA public key's modulus and exponent */ + nblen = sizeof(newbuf); + + if (ASN1_SUCCESS != (asn1_rv = asn1_read_value(asn_key, "modulus", newbuf, &nblen))) { + logger(Core, Error, "%s:%s:%d Failed to get RSA public key's modulus. Error = 0x%x (%s)\n", + __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); + return 1; + } + + m->size = nblen; + + if (!(m->data = malloc(m->size))) { + logger(Core, Error, "%s:%s:%d Failed to allocate memory for modulus.\n", __FILE__, __func__, __LINE__); + return 1; + } + + memcpy((void *)m->data, newbuf, m->size); + + nblen = sizeof(newbuf); + + if (ASN1_SUCCESS != (asn1_rv = asn1_read_value(asn_key, "publicExponent", newbuf, &nblen))) { + logger(Core, Error, "%s:%s:%d Failed to get RSA public key's exponent. Error = 0x%x (%s)\n", + __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); + return 1; + } + + e->size = nblen; + + if (!(e->data = malloc(e->size))) { + logger(Core, Error, "%s:%s:%d Failed to allocate memory for exponent.\n", __FILE__, __func__, __LINE__); + if (m->data) { + free(m->data); + } + return 1; + } + + memcpy((void *)e->data, newbuf, m->size); + + return 0; +} diff --git a/asn.h b/asn.h new file mode 100644 index 0000000..f783900 --- /dev/null +++ b/asn.h @@ -0,0 +1,45 @@ +/* -*- c-basic-offset: 8 -*- + rdesktop: A Remote Desktop Protocol client. + ASN.1 utility functions header + Copyright 2017 Alexander Zakharov + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +#ifndef _RDASN_H +#define _RDASN_H + +#include +#include +#include + +#include "utils.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define OID_SHA_WITH_RSA_SIGNATURE "1.3.14.3.2.15" +#define OID_MD5_WITH_RSA_SIGNATURE "1.3.14.3.2.25" + +int init_asn1_lib(void); +int write_pkcs1_der_pubkey(const gnutls_datum_t *m, const gnutls_datum_t *e, uint8_t *out, int *out_len); + +int libtasn_read_cert_pk_oid(uint8_t *data, size_t len, char *oid, size_t *oid_size); +int libtasn_read_cert_pk_parameters(uint8_t *data, size_t len, gnutls_datum_t *m, gnutls_datum_t *e); + +#ifdef __cplusplus +} +#endif + +#endif /* _RDASN_H */ diff --git a/configure.ac b/configure.ac index 3cf1e7d..faf7281 100644 --- a/configure.ac +++ b/configure.ac @@ -29,6 +29,9 @@ fi AC_PATH_TOOL(PKG_CONFIG, pkg-config) +# no .pc for GMP +AC_SEARCH_LIBS([__gmpz_init], [gmp]) + AC_SEARCH_LIBS(socket, socket) AC_SEARCH_LIBS(inet_aton, resolv) @@ -61,74 +64,6 @@ AC_ARG_ENABLE([address-sanitizer], AS_HELP_STRING([--enable-address-sanitizer], [AC_MSG_ERROR([Address Sanitizer not available])]) ]) -# -# OpenSSL detection borrowed from stunnel -# -checkssldir() { : - if test -f "$1/include/openssl/ssl.h"; then - ssldir="$1" - return 0 - fi - return 1 -} -AC_MSG_CHECKING([for OpenSSL directory]) -AC_ARG_WITH(openssl, - [ --with-openssl=DIR look for OpenSSL at DIR/include, DIR/lib], - [ - dnl Check the specified location only - checkssldir "$withval" - ], - [ - dnl Search default locations of OpenSSL library - for maindir in /usr/local /usr/lib /usr/pkg /usr /var/ssl /opt; do - for dir in $maindir $maindir/openssl $maindir/ssl; do - checkssldir $dir && break 2 - done - done - ] -) -if test -z "$ssldir"; then - AC_MSG_RESULT([Not found]) - echo - echo "ERROR: Could not find OpenSSL headers/libraries." - if test -f /etc/debian_version; then - echo "Probably you need to install the libssl-dev package." - elif test -f /etc/redhat-release; then - echo "Probably you need to install the openssl-devel package." - fi - echo "To specify a path manually, use the --with-openssl option." - echo - exit 1 -fi -AC_MSG_RESULT([$ssldir]) -AC_SUBST(ssldir) -AC_DEFINE_UNQUOTED(ssldir, "$ssldir") - -dnl Add OpenSSL includes and libraries -CFLAGS="$CFLAGS -I$ssldir/include" -AC_ARG_ENABLE(static-openssl, - [ --enable-static-openssl link OpenSSL statically], - [static_openssl=yes], - [static_openssl=no]) -if test x"$static_openssl" = "xyes"; then - # OpenSSL generally relies on libz - AC_SEARCH_LIBS(deflate, z) - LIBS="-L$ssldir/lib -L$ssldir/lib64 -Wl,-Bstatic -lssl -lcrypto -Wl,-Bdynamic -ldl $LIBS" -else - LIBS="-L$ssldir/lib -L$ssldir/lib64 -lssl -lcrypto -ldl $LIBS" - - # - # target-specific stuff - # - case "$host" in - *-*-solaris*) - LDFLAGS="$LDFLAGS -R$ssldir/lib" - ;; - *-dec-osf*) - LDFLAGS="$LDFLAGS -Wl,-rpath,$ssldir/lib" - ;; - esac -fi dnl CredSSP feature AC_ARG_ENABLE([credssp], AS_HELP_STRING([--disable-credssp], [disable support for CredSSP])) @@ -201,6 +136,62 @@ else exit 1 fi +# libtasn1 +if test -n "$PKG_CONFIG"; then + PKG_CHECK_MODULES(LIBTASN1, libtasn1, [HAVE_LIBTASN1=1], [HAVE_LIBTASN1=0]) +fi +if test x"$HAVE_LIBTASN1" = "x1"; then + CFLAGS="$CFLAGS $LIBTASN1_CFLAGS" + LIBS="$LIBS $LIBTASN1_LIBS" +else + echo + echo "rdesktop requires libtasn1. Please install the dependency" + echo + exit 1 +fi + +# nettle +if test -n "$PKG_CONFIG"; then + PKG_CHECK_MODULES(NETTLE, nettle, [HAVE_NETTLE=1], [HAVE_NETTLE=0]) +fi +if test x"$HAVE_NETTLE" = "x1"; then + CFLAGS="$CFLAGS $NETTLE_CFLAGS" + LIBS="$LIBS $NETTLE_LIBS" +else + echo + echo "rdesktop requires Nettle. Please install the dependency" + echo + exit 1 +fi + +# hogweed +if test -n "$PKG_CONFIG"; then + PKG_CHECK_MODULES(HOGWEED, hogweed, [HAVE_HOGWEED=1], [HAVE_HOGWEED=0]) +fi +if test x"$HAVE_HOGWEED" = "x1"; then + CFLAGS="$CFLAGS $HOGWEED_CFLAGS" + LIBS="$LIBS $HOGWEED_LIBS" +else + echo + echo "rdesktop requires hogweed. Please install the dependency" + echo + exit 1 +fi + +# GnuTLS + +if test -n "$PKG_CONFIG"; then + PKG_CHECK_MODULES(GNUTLS, gnutls >= 3.2.0, [HAVE_GNUTLS=1], [HAVE_GNUTLS=0]) +fi +if test x"$HAVE_GNUTLS" = "x1"; then + CFLAGS="$CFLAGS $GNUTLS_CFLAGS" + LIBS="$LIBS $GNUTLS_LIBS" +else + echo + echo "rdesktop requires GnuTLS. Please install the dependency" + echo + exit 1 +fi dnl Smartcard support AC_ARG_ENABLE(smartcard, AS_HELP_STRING([--disable-smartcard], [disable support for smartcard])) diff --git a/pkix.asn b/pkix.asn new file mode 100644 index 0000000..977f947 --- /dev/null +++ b/pkix.asn @@ -0,0 +1,999 @@ + +PKIX1Implicit88 {iso(1) identified-organization(3) dod(6) internet(1) + security(5) mechanisms(5) pkix(7) id-mod(0) id-pkix1-implicit-88(2)} + +DEFINITIONS IMPLICIT TAGS ::= + +BEGIN + + +-- ISO arc for standard certificate and CRL extensions + +id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} + + +-- authority key identifier OID and syntax + +id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } + +AuthorityKeyIdentifier ::= SEQUENCE { + keyIdentifier [0] KeyIdentifier OPTIONAL, + authorityCertIssuer [1] GeneralNames OPTIONAL, + authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL } + -- authorityCertIssuer and authorityCertSerialNumber shall both + -- be present or both be absgent + +KeyIdentifier ::= OCTET STRING + +-- subject key identifier OID and syntax + +id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } + +SubjectKeyIdentifier ::= KeyIdentifier + +-- key usage extension OID and syntax + +id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } + +KeyUsage ::= BIT STRING { + digitalSignature (0), + nonRepudiation (1), + keyEncipherment (2), + dataEncipherment (3), + keyAgreement (4), + keyCertSign (5), + cRLSign (6), + encipherOnly (7), + decipherOnly (8) } + +-- private key usage period extension OID and syntax + +id-ce-privateKeyUsagePeriod OBJECT IDENTIFIER ::= { id-ce 16 } + +PrivateKeyUsagePeriod ::= SEQUENCE { + notBefore [0] GeneralizedTime OPTIONAL, + notAfter [1] GeneralizedTime OPTIONAL } + -- either notBefore or notAfter shall be present + +-- certificate policies extension OID and syntax + +id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } + +CertificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation + +PolicyInformation ::= SEQUENCE { + policyIdentifier CertPolicyId, + policyQualifiers SEQUENCE SIZE (1..MAX) OF + PolicyQualifierInfo OPTIONAL } + +CertPolicyId ::= OBJECT IDENTIFIER + +PolicyQualifierInfo ::= SEQUENCE { + policyQualifierId PolicyQualifierId, + qualifier ANY DEFINED BY policyQualifierId } + +-- Implementations that recognize additional policy qualifiers shall +-- augment the following definition for PolicyQualifierId + +PolicyQualifierId ::= + OBJECT IDENTIFIER -- ( id-qt-cps | id-qt-unotice ) + +-- CPS pointer qualifier + +CPSuri ::= IA5String + +-- user notice qualifier + +UserNotice ::= SEQUENCE { + noticeRef NoticeReference OPTIONAL, + explicitText DisplayText OPTIONAL} + +NoticeReference ::= SEQUENCE { + organization DisplayText, + noticeNumbers SEQUENCE OF INTEGER } + +DisplayText ::= CHOICE { + visibleString VisibleString (SIZE (1..200)), + bmpString BMPString (SIZE (1..200)), + utf8String UTF8String (SIZE (1..200)) } + +-- policy mapping extension OID and syntax + +id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } + +PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE { + issuerDomainPolicy CertPolicyId, + subjectDomainPolicy CertPolicyId } + +-- subject alternative name extension OID and syntax + +id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } + +SubjectAltName ::= GeneralNames + +GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName + +GeneralName ::= CHOICE { + otherName [0] AnotherName, + rfc822Name [1] IA5String, + dNSName [2] IA5String, + x400Address [3] ORAddress, + directoryName [4] Name, + ediPartyName [5] EDIPartyName, + uniformResourceIdentifier [6] IA5String, + iPAddress [7] OCTET STRING, + registeredID [8] OBJECT IDENTIFIER } + +-- AnotherName replaces OTHER-NAME ::= TYPE-IDENTIFIER, as +-- TYPE-IDENTIFIER is not supported in the '88 ASN.1 syntax + +AnotherName ::= SEQUENCE { + type-id OBJECT IDENTIFIER, + value [0] EXPLICIT ANY DEFINED BY type-id } + +EDIPartyName ::= SEQUENCE { + nameAssigner [0] DirectoryString OPTIONAL, + partyName [1] DirectoryString } + +-- issuer alternative name extension OID and syntax + +id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 } + +IssuerAltName ::= GeneralNames + +id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 } + +SubjectDirectoryAttributes ::= SEQUENCE SIZE (1..MAX) OF Attribute + +-- basic constraints extension OID and syntax + +id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } + +BasicConstraints ::= SEQUENCE { + cA BOOLEAN DEFAULT FALSE, + pathLenConstraint INTEGER (0..MAX) OPTIONAL } + +-- name constraints extension OID and syntax + +id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } + +NameConstraints ::= SEQUENCE { + permittedSubtrees [0] GeneralSubtrees OPTIONAL, + excludedSubtrees [1] GeneralSubtrees OPTIONAL } + +GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree + +GeneralSubtree ::= SEQUENCE { + base GeneralName, + minimum [0] BaseDistance DEFAULT 0, + maximum [1] BaseDistance OPTIONAL } + +BaseDistance ::= INTEGER (0..MAX) + +-- policy constraints extension OID and syntax + +id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } + +PolicyConstraints ::= SEQUENCE { + requireExplicitPolicy [0] SkipCerts OPTIONAL, + inhibitPolicyMapping [1] SkipCerts OPTIONAL } + +SkipCerts ::= INTEGER (0..MAX) + +-- CRL distribution points extension OID and syntax + +id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= {id-ce 31} + +CRLDistPointsSyntax ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint + +DistributionPoint ::= SEQUENCE { + distributionPoint [0] DistributionPointName OPTIONAL, + reasons [1] ReasonFlags OPTIONAL, + cRLIssuer [2] GeneralNames OPTIONAL } + +-- This was previously a CHOICE with two possible choices, +-- corresponding to the same names and types. However, this +-- rendered libtasn1 unable to interpret the certificate +-- revocation lists on the test SITHS certificate that I've +-- had. Turning it to a sequence with two optional members +-- made it work though, so I truly hope that this doesn't break +-- anything. + +DistributionPointName ::= SEQUENCE { + fullName [0] GeneralNames OPTIONAL, + nameRelativeToCRLIssuer [1] RelativeDistinguishedName OPTIONAL } + + + +ReasonFlags ::= BIT STRING { + unused (0), + keyCompromise (1), + cACompromise (2), + affiliationChanged (3), + superseded (4), + cessationOfOperation (5), + certificateHold (6) } + +-- extended key usage extension OID and syntax + +id-ce-extKeyUsage OBJECT IDENTIFIER ::= {id-ce 37} + +ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId + +KeyPurposeId ::= OBJECT IDENTIFIER + +-- extended key purpose OIDs +id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } +id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } +id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } +id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } +id-kp-ipsecEndSystem OBJECT IDENTIFIER ::= { id-kp 5 } +id-kp-ipsecTunnel OBJECT IDENTIFIER ::= { id-kp 6 } +id-kp-ipsecUser OBJECT IDENTIFIER ::= { id-kp 7 } +id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } + +-- authority info access + +id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 } + +AuthorityInfoAccessSyntax ::= + SEQUENCE SIZE (1..MAX) OF AccessDescription + +AccessDescription ::= SEQUENCE { + accessMethod OBJECT IDENTIFIER, + accessLocation GeneralName } + +-- CRL number extension OID and syntax + +id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } + +CRLNumber ::= INTEGER (0..MAX) + +-- issuing distribution point extension OID and syntax + +id-ce-issuingDistributionPoint OBJECT IDENTIFIER ::= { id-ce 28 } + +IssuingDistributionPoint ::= SEQUENCE { + distributionPoint [0] DistributionPointName OPTIONAL, + onlyContainsUserCerts [1] BOOLEAN DEFAULT FALSE, + onlyContainsCACerts [2] BOOLEAN DEFAULT FALSE, + onlySomeReasons [3] ReasonFlags OPTIONAL, + indirectCRL [4] BOOLEAN DEFAULT FALSE } + + +id-ce-deltaCRLIndicator OBJECT IDENTIFIER ::= { id-ce 27 } + +-- deltaCRLIndicator ::= BaseCRLNumber + +BaseCRLNumber ::= CRLNumber + +-- CRL reasons extension OID and syntax + +id-ce-cRLReasons OBJECT IDENTIFIER ::= { id-ce 21 } + +CRLReason ::= ENUMERATED { + unspecified (0), + keyCompromise (1), + cACompromise (2), + affiliationChanged (3), + superseded (4), + cessationOfOperation (5), + certificateHold (6), + removeFromCRL (8) } + +-- certificate issuer CRL entry extension OID and syntax + +id-ce-certificateIssuer OBJECT IDENTIFIER ::= { id-ce 29 } + +CertificateIssuer ::= GeneralNames + +-- hold instruction extension OID and syntax + +id-ce-holdInstructionCode OBJECT IDENTIFIER ::= { id-ce 23 } + +HoldInstructionCode ::= OBJECT IDENTIFIER + +-- ANSI x9 holdinstructions + +-- ANSI x9 arc holdinstruction arc +holdInstruction OBJECT IDENTIFIER ::= + {joint-iso-itu-t(2) member-body(2) us(840) x9cm(10040) 2} + +-- ANSI X9 holdinstructions referenced by this standard +id-holdinstruction-none OBJECT IDENTIFIER ::= + {holdInstruction 1} -- deprecated +id-holdinstruction-callissuer OBJECT IDENTIFIER ::= + {holdInstruction 2} +id-holdinstruction-reject OBJECT IDENTIFIER ::= + {holdInstruction 3} + +-- invalidity date CRL entry extension OID and syntax + +id-ce-invalidityDate OBJECT IDENTIFIER ::= { id-ce 24 } + +InvalidityDate ::= GeneralizedTime + +-- Netscape certificate type extension + +id-netscape OBJECT IDENTIFIER ::= { + joint-iso-itu-t(2) country(16) us(840) organization(1) netscape(113730) } + +id-netscape-certExtension OBJECT IDENTIFIER ::= { id-netscape 1 } + +id-netscape-certType OBJECT IDENTIFIER ::= { id-netscape-certExtension 1 } + +CertType ::= BIT STRING { + sslClient (0), + sslServer (1), + smime (2), + objectSigning (3), + reserved (4), + sslCA (5), + smimeCA (6), + objectSigningCA (7) } + + +-- -------------------------------------- +-- EXPLICIT +-- -------------------------------------- + +-- UNIVERSAL Types defined in '93 and '98 ASN.1 +-- but required by this specification + +VisibleString ::= [UNIVERSAL 26] IMPLICIT OCTET STRING + +NumericString ::= [UNIVERSAL 18] IMPLICIT OCTET STRING + +IA5String ::= [UNIVERSAL 22] IMPLICIT OCTET STRING + +TeletexString ::= [UNIVERSAL 20] IMPLICIT OCTET STRING + +PrintableString ::= [UNIVERSAL 19] IMPLICIT OCTET STRING + +UniversalString ::= [UNIVERSAL 28] IMPLICIT OCTET STRING + -- UniversalString is defined in ASN.1:1993 + +BMPString ::= [UNIVERSAL 30] IMPLICIT OCTET STRING + -- BMPString is the subtype of UniversalString and models + -- the Basic Multilingual Plane of ISO/IEC/ITU 10646-1 + +UTF8String ::= [UNIVERSAL 12] IMPLICIT OCTET STRING + -- The content of this type conforms to RFC 2279. + + +-- PKIX specific OIDs + +id-pkix OBJECT IDENTIFIER ::= + { iso(1) identified-organization(3) dod(6) internet(1) + security(5) mechanisms(5) pkix(7) } + +-- PKIX arcs + +id-pe OBJECT IDENTIFIER ::= { id-pkix 1 } + -- arc for private certificate extensions +id-qt OBJECT IDENTIFIER ::= { id-pkix 2 } + -- arc for policy qualifier types +id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } + -- arc for extended key purpose OIDS +id-ad OBJECT IDENTIFIER ::= { id-pkix 48 } + -- arc for access descriptors + +-- policyQualifierIds for Internet policy qualifiers + +id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 } + -- OID for CPS qualifier +id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 } + -- OID for user notice qualifier + +-- access descriptor definitions + +id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 } +id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 } + +-- attribute data types -- + +Attribute ::= SEQUENCE { + type AttributeType, + values SET OF AttributeValue + -- at least one value is required -- +} + +AttributeType ::= OBJECT IDENTIFIER + +AttributeValue ::= ANY + +AttributeTypeAndValue ::= SEQUENCE { + type AttributeType, + value AttributeValue } + +-- suggested naming attributes: Definition of the following +-- information object set may be augmented to meet local +-- requirements. Note that deleting members of the set may +-- prevent interoperability with conforming implementations. +-- presented in pairs: the AttributeType followed by the +-- type definition for the corresponding AttributeValue + +-- Arc for standard naming attributes +id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4} + +-- Attributes of type NameDirectoryString +id-at-name AttributeType ::= {id-at 41} +id-at-surname AttributeType ::= {id-at 4} +id-at-givenName AttributeType ::= {id-at 42} +id-at-initials AttributeType ::= {id-at 43} +id-at-generationQualifier AttributeType ::= {id-at 44} + +X520name ::= CHOICE { + teletexString TeletexString (SIZE (1..ub-name)), + printableString PrintableString (SIZE (1..ub-name)), + universalString UniversalString (SIZE (1..ub-name)), + utf8String UTF8String (SIZE (1..ub-name)), + bmpString BMPString (SIZE(1..ub-name)) } + +-- + +id-at-commonName AttributeType ::= {id-at 3} + +X520CommonName ::= CHOICE { + teletexString TeletexString (SIZE (1..ub-common-name)), + printableString PrintableString (SIZE (1..ub-common-name)), + universalString UniversalString (SIZE (1..ub-common-name)), + utf8String UTF8String (SIZE (1..ub-common-name)), + bmpString BMPString (SIZE(1..ub-common-name)) } + +-- + +id-at-localityName AttributeType ::= {id-at 7} + +X520LocalityName ::= CHOICE { + teletexString TeletexString (SIZE (1..ub-locality-name)), + printableString PrintableString (SIZE (1..ub-locality-name)), + universalString UniversalString (SIZE (1..ub-locality-name)), + utf8String UTF8String (SIZE (1..ub-locality-name)), + bmpString BMPString (SIZE(1..ub-locality-name)) } + +-- + +id-at-stateOrProvinceName AttributeType ::= {id-at 8} + +X520StateOrProvinceName ::= CHOICE { + teletexString TeletexString (SIZE (1..ub-state-name)), + printableString PrintableString (SIZE (1..ub-state-name)), + universalString UniversalString (SIZE (1..ub-state-name)), + utf8String UTF8String (SIZE (1..ub-state-name)), + bmpString BMPString (SIZE(1..ub-state-name)) } + +-- + +id-at-organizationName AttributeType ::= {id-at 10} + +X520OrganizationName ::= CHOICE { + teletexString TeletexString (SIZE (1..ub-organization-name)), + printableString PrintableString (SIZE (1..ub-organization-name)), + universalString UniversalString (SIZE (1..ub-organization-name)), + utf8String UTF8String (SIZE (1..ub-organization-name)), + bmpString BMPString (SIZE(1..ub-organization-name)) } + +-- + +id-at-organizationalUnitName AttributeType ::= {id-at 11} + +X520OrganizationalUnitName ::= CHOICE { + teletexString TeletexString (SIZE (1..ub-organizational-unit-name)), + printableString PrintableString + (SIZE (1..ub-organizational-unit-name)), + universalString UniversalString + (SIZE (1..ub-organizational-unit-name)), + utf8String UTF8String (SIZE (1..ub-organizational-unit-name)), + bmpString BMPString (SIZE(1..ub-organizational-unit-name)) } + +-- + +id-at-title AttributeType ::= {id-at 12} + +X520Title ::= CHOICE { + teletexString TeletexString (SIZE (1..ub-title)), + printableString PrintableString (SIZE (1..ub-title)), + universalString UniversalString (SIZE (1..ub-title)), + utf8String UTF8String (SIZE (1..ub-title)), + bmpString BMPString (SIZE(1..ub-title)) } + +-- + +id-at-dnQualifier AttributeType ::= {id-at 46} +X520dnQualifier ::= PrintableString + +id-at-countryName AttributeType ::= {id-at 6} +X520countryName ::= PrintableString (SIZE (2)) -- IS 3166 codes + + -- Legacy attributes + +pkcs-9 OBJECT IDENTIFIER ::= + { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } + +emailAddress AttributeType ::= { pkcs-9 1 } + +Pkcs9email ::= IA5String (SIZE (1..ub-emailaddress-length)) + +-- naming data types -- + +Name ::= CHOICE { -- only one possibility for now -- + rdnSequence RDNSequence } + +RDNSequence ::= SEQUENCE OF RelativeDistinguishedName + +DistinguishedName ::= RDNSequence + +RelativeDistinguishedName ::= + SET SIZE (1 .. MAX) OF AttributeTypeAndValue + +-- Directory string type -- + +DirectoryString ::= CHOICE { + teletexString TeletexString (SIZE (1..MAX)), + printableString PrintableString (SIZE (1..MAX)), + universalString UniversalString (SIZE (1..MAX)), + utf8String UTF8String (SIZE (1..MAX)), + bmpString BMPString (SIZE(1..MAX)) } + + +-- -------------------------------------------------------- +-- certificate and CRL specific structures begin here +-- -------------------------------------------------------- + +Certificate ::= SEQUENCE { + tbsCertificate TBSCertificate, + signatureAlgorithm AlgorithmIdentifier, + signature BIT STRING } + +TBSCertificate ::= SEQUENCE { + version [0] EXPLICIT Version DEFAULT v1, + serialNumber CertificateSerialNumber, + signature AlgorithmIdentifier, + issuer Name, + validity Validity, + subject Name, + subjectPublicKeyInfo SubjectPublicKeyInfo, + issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, + -- If present, version shall be v2 or v3 + subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, + -- If present, version shall be v2 or v3 + extensions [3] EXPLICIT Extensions OPTIONAL + -- If present, version shall be v3 -- +} + +Version ::= INTEGER { v1(0), v2(1), v3(2) } + +CertificateSerialNumber ::= INTEGER + +Validity ::= SEQUENCE { + notBefore Time, + notAfter Time } + +Time ::= CHOICE { + utcTime UTCTime, + generalTime GeneralizedTime } + +UniqueIdentifier ::= BIT STRING + +SubjectPublicKeyInfo ::= SEQUENCE { + algorithm AlgorithmIdentifier, + subjectPublicKey BIT STRING } + +Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + +Extension ::= SEQUENCE { + extnID OBJECT IDENTIFIER, + critical BOOLEAN DEFAULT FALSE, + extnValue OCTET STRING } + + +-- ------------------------------------------ +-- CRL structures +-- ------------------------------------------ + +CertificateList ::= SEQUENCE { + tbsCertList TBSCertList, + signatureAlgorithm AlgorithmIdentifier, + signature BIT STRING } + +TBSCertList ::= SEQUENCE { + version Version OPTIONAL, + -- if present, shall be v2 + signature AlgorithmIdentifier, + issuer Name, + thisUpdate Time, + nextUpdate Time OPTIONAL, + revokedCertificates SEQUENCE OF SEQUENCE { + userCertificate CertificateSerialNumber, + revocationDate Time, + crlEntryExtensions Extensions OPTIONAL + -- if present, shall be v2 + } OPTIONAL, + crlExtensions [0] EXPLICIT Extensions OPTIONAL + -- if present, shall be v2 -- +} + +-- Version, Time, CertificateSerialNumber, and Extensions were +-- defined earlier for use in the certificate structure + +AlgorithmIdentifier ::= SEQUENCE { + algorithm OBJECT IDENTIFIER, + parameters ANY DEFINED BY algorithm OPTIONAL } + -- contains a value of the type + -- registered for use with the + -- algorithm object identifier value + +-- Algorithm OIDs and parameter structures + +pkcs-1 OBJECT IDENTIFIER ::= { + iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } + +rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 } + +md2WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 2 } + +md5WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 4 } + +sha1WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 5 } + +-- Cendio additions: + +sha256WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 11 } + +sha384WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 12 } + +sha512WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 13 } + +RSAPublicKey ::= SEQUENCE { + modulus INTEGER, -- n + publicExponent INTEGER -- e +} + +RSAPrivateKey ::= SEQUENCE { + version Version, + modulus INTEGER, -- n + publicExponent INTEGER, -- e + privateExponent INTEGER, -- d + prime1 INTEGER, -- p + prime2 INTEGER, -- q + exponent1 INTEGER, -- d mod (p-1) + exponent2 INTEGER, -- d mod (q-1) + coefficient INTEGER -- (inverse of q) mod p +} + + +id-dsa-with-sha1 OBJECT IDENTIFIER ::= { + iso(1) member-body(2) us(840) x9-57 (10040) x9algorithm(4) 3 } + +Dss-Sig-Value ::= SEQUENCE { + r INTEGER, + s INTEGER } + +dhpublicnumber OBJECT IDENTIFIER ::= { + iso(1) member-body(2) us(840) ansi-x942(10046) number-type(2) 1 } + +DomainParameters ::= SEQUENCE { + p INTEGER, -- odd prime, p=jq +1 + g INTEGER, -- generator, g + q INTEGER, -- factor of p-1 + j INTEGER OPTIONAL, -- subgroup factor, j>= 2 + validationParms ValidationParms OPTIONAL } + +ValidationParms ::= SEQUENCE { + seed BIT STRING, + pgenCounter INTEGER } + +id-dsa OBJECT IDENTIFIER ::= { + iso(1) member-body(2) us(840) x9-57(10040) x9algorithm(4) 1 } + +Dss-Parms ::= SEQUENCE { + p INTEGER, + q INTEGER, + g INTEGER } + +-- x400 address syntax starts here +-- OR Names + +ORAddress ::= SEQUENCE { + built-in-standard-attributes BuiltInStandardAttributes, + built-in-domain-defined-attributes + BuiltInDomainDefinedAttributes OPTIONAL, + -- see also teletex-domain-defined-attributes + extension-attributes ExtensionAttributes OPTIONAL } +-- The OR-address is semantically absent from the OR-name if the +-- built-in-standard-attribute sequence is empty and the +-- built-in-domain-defined-attributes and extension-attributes are +-- both omitted. + +-- Built-in Standard Attributes + +BuiltInStandardAttributes ::= SEQUENCE { + country-name CountryName OPTIONAL, + administration-domain-name AdministrationDomainName OPTIONAL, + network-address [0] EXPLICIT NetworkAddress OPTIONAL, + -- see also extended-network-address + terminal-identifier [1] EXPLICIT TerminalIdentifier OPTIONAL, + private-domain-name [2] EXPLICIT PrivateDomainName OPTIONAL, + organization-name [3] EXPLICIT OrganizationName OPTIONAL, + -- see also teletex-organization-name + numeric-user-identifier [4] EXPLICIT NumericUserIdentifier OPTIONAL, + personal-name [5] EXPLICIT PersonalName OPTIONAL, + -- see also teletex-personal-name + organizational-unit-names [6] EXPLICIT OrganizationalUnitNames OPTIONAL + -- see also teletex-organizational-unit-names -- +} + +CountryName ::= [APPLICATION 1] CHOICE { + x121-dcc-code NumericString + (SIZE (ub-country-name-numeric-length)), + iso-3166-alpha2-code PrintableString + (SIZE (ub-country-name-alpha-length)) } + +AdministrationDomainName ::= [APPLICATION 2] EXPLICIT CHOICE { + numeric NumericString (SIZE (0..ub-domain-name-length)), + printable PrintableString (SIZE (0..ub-domain-name-length)) } + +NetworkAddress ::= X121Address -- see also extended-network-address + +X121Address ::= NumericString (SIZE (1..ub-x121-address-length)) + +TerminalIdentifier ::= PrintableString (SIZE (1..ub-terminal-id-length)) + +PrivateDomainName ::= CHOICE { + numeric NumericString (SIZE (1..ub-domain-name-length)), + printable PrintableString (SIZE (1..ub-domain-name-length)) } + +OrganizationName ::= PrintableString + (SIZE (1..ub-organization-name-length)) +-- see also teletex-organization-name + +NumericUserIdentifier ::= NumericString + (SIZE (1..ub-numeric-user-id-length)) + +PersonalName ::= SET { + surname [0] PrintableString (SIZE (1..ub-surname-length)), + given-name [1] PrintableString + (SIZE (1..ub-given-name-length)) OPTIONAL, + initials [2] PrintableString (SIZE (1..ub-initials-length)) OPTIONAL, + generation-qualifier [3] PrintableString + (SIZE (1..ub-generation-qualifier-length)) OPTIONAL } +-- see also teletex-personal-name + +OrganizationalUnitNames ::= SEQUENCE SIZE (1..ub-organizational-units) + OF OrganizationalUnitName +-- see also teletex-organizational-unit-names + +OrganizationalUnitName ::= PrintableString (SIZE + (1..ub-organizational-unit-name-length)) + +-- Built-in Domain-defined Attributes + +BuiltInDomainDefinedAttributes ::= SEQUENCE SIZE + (1..ub-domain-defined-attributes) OF + BuiltInDomainDefinedAttribute + +BuiltInDomainDefinedAttribute ::= SEQUENCE { + type PrintableString (SIZE + (1..ub-domain-defined-attribute-type-length)), + value PrintableString (SIZE + (1..ub-domain-defined-attribute-value-length))} + +-- Extension Attributes + +ExtensionAttributes ::= SET SIZE (1..ub-extension-attributes) OF + ExtensionAttribute + +ExtensionAttribute ::= SEQUENCE { + extension-attribute-type [0] EXPLICIT INTEGER (0..ub-extension-attributes), + extension-attribute-value [1] EXPLICIT + ANY DEFINED BY extension-attribute-type } + +-- Extension types and attribute values +-- + +common-name INTEGER ::= 1 + +CommonName ::= PrintableString (SIZE (1..ub-common-name-length)) + +teletex-common-name INTEGER ::= 2 + +TeletexCommonName ::= TeletexString (SIZE (1..ub-common-name-length)) + +teletex-organization-name INTEGER ::= 3 + +TeletexOrganizationName ::= + TeletexString (SIZE (1..ub-organization-name-length)) + +teletex-personal-name INTEGER ::= 4 + +TeletexPersonalName ::= SET { + surname [0] EXPLICIT TeletexString (SIZE (1..ub-surname-length)), + given-name [1] EXPLICIT TeletexString + (SIZE (1..ub-given-name-length)) OPTIONAL, + initials [2] EXPLICIT TeletexString (SIZE (1..ub-initials-length)) OPTIONAL, + generation-qualifier [3] EXPLICIT TeletexString (SIZE + (1..ub-generation-qualifier-length)) OPTIONAL } + +teletex-organizational-unit-names INTEGER ::= 5 + +TeletexOrganizationalUnitNames ::= SEQUENCE SIZE + (1..ub-organizational-units) OF TeletexOrganizationalUnitName + +TeletexOrganizationalUnitName ::= TeletexString + (SIZE (1..ub-organizational-unit-name-length)) + +pds-name INTEGER ::= 7 + +PDSName ::= PrintableString (SIZE (1..ub-pds-name-length)) + +physical-delivery-country-name INTEGER ::= 8 + +PhysicalDeliveryCountryName ::= CHOICE { + x121-dcc-code NumericString (SIZE (ub-country-name-numeric-length)), + iso-3166-alpha2-code PrintableString + (SIZE (ub-country-name-alpha-length)) } + +postal-code INTEGER ::= 9 + +PostalCode ::= CHOICE { + numeric-code NumericString (SIZE (1..ub-postal-code-length)), + printable-code PrintableString (SIZE (1..ub-postal-code-length)) } + +physical-delivery-office-name INTEGER ::= 10 + +PhysicalDeliveryOfficeName ::= PDSParameter + +physical-delivery-office-number INTEGER ::= 11 + +PhysicalDeliveryOfficeNumber ::= PDSParameter + +extension-OR-address-components INTEGER ::= 12 + +ExtensionORAddressComponents ::= PDSParameter + +physical-delivery-personal-name INTEGER ::= 13 + +PhysicalDeliveryPersonalName ::= PDSParameter + +physical-delivery-organization-name INTEGER ::= 14 + +PhysicalDeliveryOrganizationName ::= PDSParameter + +extension-physical-delivery-address-components INTEGER ::= 15 + +ExtensionPhysicalDeliveryAddressComponents ::= PDSParameter + +unformatted-postal-address INTEGER ::= 16 + +UnformattedPostalAddress ::= SET { + printable-address SEQUENCE SIZE (1..ub-pds-physical-address-lines) OF + PrintableString (SIZE (1..ub-pds-parameter-length)) OPTIONAL, + teletex-string TeletexString + (SIZE (1..ub-unformatted-address-length)) OPTIONAL } + +street-address INTEGER ::= 17 + +StreetAddress ::= PDSParameter + +post-office-box-address INTEGER ::= 18 + +PostOfficeBoxAddress ::= PDSParameter + +poste-restante-address INTEGER ::= 19 + +PosteRestanteAddress ::= PDSParameter + +unique-postal-name INTEGER ::= 20 + +UniquePostalName ::= PDSParameter + +local-postal-attributes INTEGER ::= 21 + +LocalPostalAttributes ::= PDSParameter + +PDSParameter ::= SET { + printable-string PrintableString + (SIZE(1..ub-pds-parameter-length)) OPTIONAL, + teletex-string TeletexString + (SIZE(1..ub-pds-parameter-length)) OPTIONAL } + +extended-network-address INTEGER ::= 22 + +ExtendedNetworkAddress ::= CHOICE { + e163-4-address SEQUENCE { + number [0] EXPLICIT NumericString (SIZE (1..ub-e163-4-number-length)), + sub-address [1] EXPLICIT NumericString + (SIZE (1..ub-e163-4-sub-address-length)) OPTIONAL }, + psap-address [0] EXPLICIT PresentationAddress } + +PresentationAddress ::= SEQUENCE { + pSelector [0] EXPLICIT OCTET STRING OPTIONAL, + sSelector [1] EXPLICIT OCTET STRING OPTIONAL, + tSelector [2] EXPLICIT OCTET STRING OPTIONAL, + nAddresses [3] EXPLICIT SET SIZE (1..MAX) OF OCTET STRING } + +terminal-type INTEGER ::= 23 + +TerminalType ::= INTEGER { + telex (3), + teletex (4), + g3-facsimile (5), + g4-facsimile (6), + ia5-terminal (7), + videotex (8) } (0..ub-integer-options) + +-- Extension Domain-defined Attributes + +teletex-domain-defined-attributes INTEGER ::= 6 + +TeletexDomainDefinedAttributes ::= SEQUENCE SIZE + (1..ub-domain-defined-attributes) OF TeletexDomainDefinedAttribute + +TeletexDomainDefinedAttribute ::= SEQUENCE { + type TeletexString + (SIZE (1..ub-domain-defined-attribute-type-length)), + value TeletexString + (SIZE (1..ub-domain-defined-attribute-value-length)) } + +-- specifications of Upper Bounds shall be regarded as mandatory +-- from Annex B of ITU-T X.411 Reference Definition of MTS Parameter +-- Upper Bounds + +-- Upper Bounds +ub-name INTEGER ::= 32768 +ub-common-name INTEGER ::= 64 +ub-locality-name INTEGER ::= 128 +ub-state-name INTEGER ::= 128 +ub-organization-name INTEGER ::= 64 +ub-organizational-unit-name INTEGER ::= 64 +ub-title INTEGER ::= 64 +ub-match INTEGER ::= 128 + +ub-emailaddress-length INTEGER ::= 128 + +ub-common-name-length INTEGER ::= 64 +ub-country-name-alpha-length INTEGER ::= 2 +ub-country-name-numeric-length INTEGER ::= 3 +ub-domain-defined-attributes INTEGER ::= 4 +ub-domain-defined-attribute-type-length INTEGER ::= 8 +ub-domain-defined-attribute-value-length INTEGER ::= 128 +ub-domain-name-length INTEGER ::= 16 +ub-extension-attributes INTEGER ::= 256 +ub-e163-4-number-length INTEGER ::= 15 +ub-e163-4-sub-address-length INTEGER ::= 40 +ub-generation-qualifier-length INTEGER ::= 3 +ub-given-name-length INTEGER ::= 16 +ub-initials-length INTEGER ::= 5 +ub-integer-options INTEGER ::= 256 +ub-numeric-user-id-length INTEGER ::= 32 +ub-organization-name-length INTEGER ::= 64 +ub-organizational-unit-name-length INTEGER ::= 32 +ub-organizational-units INTEGER ::= 4 +ub-pds-name-length INTEGER ::= 16 +ub-pds-parameter-length INTEGER ::= 30 +ub-pds-physical-address-lines INTEGER ::= 6 +ub-postal-code-length INTEGER ::= 16 +ub-surname-length INTEGER ::= 40 +ub-terminal-id-length INTEGER ::= 24 +ub-unformatted-address-length INTEGER ::= 180 +ub-x121-address-length INTEGER ::= 16 + +-- Note - upper bounds on string types, such as TeletexString, are +-- measured in characters. Excepting PrintableString or IA5String, a +-- significantly greater number of octets will be required to hold +-- such a value. As a minimum, 16 octets, or twice the specified upper +-- bound, whichever is the larger, should be allowed for TeletexString. +-- For UTF8String or UniversalString at least four times the upper +-- bound should be allowed. + +END + + + + + + + + + diff --git a/pkix_asn1_tab.c b/pkix_asn1_tab.c new file mode 100644 index 0000000..2da3fc5 --- /dev/null +++ b/pkix_asn1_tab.c @@ -0,0 +1,920 @@ +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +const asn1_static_node pkix_asn1_tab[] = { + { "PKIX1Implicit88", 536875024, NULL }, + { NULL, 1610612748, NULL }, + { "iso", 1073741825, "1"}, + { "identified-organization", 1073741825, "3"}, + { "dod", 1073741825, "6"}, + { "internet", 1073741825, "1"}, + { "security", 1073741825, "5"}, + { "mechanisms", 1073741825, "5"}, + { "pkix", 1073741825, "7"}, + { "id-mod", 1073741825, "0"}, + { "id-pkix1-implicit-88", 1, "2"}, + { "id-ce", 1879048204, NULL }, + { "joint-iso-ccitt", 1073741825, "2"}, + { "ds", 1073741825, "5"}, + { NULL, 1, "29"}, + { "id-ce-authorityKeyIdentifier", 1879048204, NULL }, + { NULL, 1073741825, "id-ce"}, + { NULL, 1, "35"}, + { "AuthorityKeyIdentifier", 1610612741, NULL }, + { "keyIdentifier", 1610637314, "KeyIdentifier"}, + { NULL, 4104, "0"}, + { "authorityCertIssuer", 1610637314, "GeneralNames"}, + { NULL, 4104, "1"}, + { "authorityCertSerialNumber", 536895490, "CertificateSerialNumber"}, + { NULL, 4104, "2"}, + { "KeyIdentifier", 1073741831, NULL }, + { "id-ce-subjectKeyIdentifier", 1879048204, NULL }, + { NULL, 1073741825, "id-ce"}, + { NULL, 1, "14"}, + { "SubjectKeyIdentifier", 1073741826, "KeyIdentifier"}, + { "id-ce-keyUsage", 1879048204, NULL }, + { NULL, 1073741825, "id-ce"}, + { NULL, 1, "15"}, + { "KeyUsage", 1610874886, NULL }, + { "digitalSignature", 1073741825, "0"}, + { "nonRepudiation", 1073741825, "1"}, + { "keyEncipherment", 1073741825, "2"}, + { "dataEncipherment", 1073741825, "3"}, + { "keyAgreement", 1073741825, "4"}, + { "keyCertSign", 1073741825, "5"}, + { "cRLSign", 1073741825, "6"}, + { "encipherOnly", 1073741825, "7"}, + { "decipherOnly", 1, "8"}, + { "id-ce-privateKeyUsagePeriod", 1879048204, NULL }, + { NULL, 1073741825, "id-ce"}, + { NULL, 1, "16"}, + { "PrivateKeyUsagePeriod", 1610612741, NULL }, + { "notBefore", 1610637349, NULL }, + { NULL, 4104, "0"}, + { "notAfter", 536895525, NULL }, + { NULL, 4104, "1"}, + { "id-ce-certificatePolicies", 1879048204, NULL }, + { NULL, 1073741825, "id-ce"}, + { NULL, 1, "32"}, + { "CertificatePolicies", 1612709899, NULL }, + { "MAX", 1074266122, "1"}, + { NULL, 2, "PolicyInformation"}, + { "PolicyInformation", 1610612741, NULL }, + { "policyIdentifier", 1073741826, "CertPolicyId"}, + { "policyQualifiers", 538984459, NULL }, + { "MAX", 1074266122, "1"}, + { NULL, 2, "PolicyQualifierInfo"}, + { "CertPolicyId", 1073741836, NULL }, + { "PolicyQualifierInfo", 1610612741, NULL }, + { "policyQualifierId", 1073741826, "PolicyQualifierId"}, + { "qualifier", 541065229, NULL }, + { "policyQualifierId", 1, NULL }, + { "PolicyQualifierId", 1073741836, NULL }, + { "CPSuri", 1073741853, NULL }, + { "UserNotice", 1610612741, NULL }, + { "noticeRef", 1073758210, "NoticeReference"}, + { "explicitText", 16386, "DisplayText"}, + { "NoticeReference", 1610612741, NULL }, + { "organization", 1073741826, "DisplayText"}, + { "noticeNumbers", 536870923, NULL }, + { NULL, 3, NULL }, + { "DisplayText", 1610612754, NULL }, + { "visibleString", 1612709923, NULL }, + { "200", 524298, "1"}, + { "bmpString", 1612709921, NULL }, + { "200", 524298, "1"}, + { "utf8String", 538968098, NULL }, + { "200", 524298, "1"}, + { "id-ce-policyMappings", 1879048204, NULL }, + { NULL, 1073741825, "id-ce"}, + { NULL, 1, "33"}, + { "PolicyMappings", 1612709899, NULL }, + { "MAX", 1074266122, "1"}, + { NULL, 536870917, NULL }, + { "issuerDomainPolicy", 1073741826, "CertPolicyId"}, + { "subjectDomainPolicy", 2, "CertPolicyId"}, + { "id-ce-subjectAltName", 1879048204, NULL }, + { NULL, 1073741825, "id-ce"}, + { NULL, 1, "17"}, + { "SubjectAltName", 1073741826, "GeneralNames"}, + { "GeneralNames", 1612709899, NULL }, + { "MAX", 1074266122, "1"}, + { NULL, 2, "GeneralName"}, + { "GeneralName", 1610612754, NULL }, + { "otherName", 1610620930, "AnotherName"}, + { NULL, 4104, "0"}, + { "rfc822Name", 1610620957, NULL }, + { NULL, 4104, "1"}, + { "dNSName", 1610620957, NULL }, + { NULL, 4104, "2"}, + { "x400Address", 1610620930, "ORAddress"}, + { NULL, 4104, "3"}, + { "directoryName", 1610620930, "Name"}, + { NULL, 4104, "4"}, + { "ediPartyName", 1610620930, "EDIPartyName"}, + { NULL, 4104, "5"}, + { "uniformResourceIdentifier", 1610620957, NULL }, + { NULL, 4104, "6"}, + { "iPAddress", 1610620935, NULL }, + { NULL, 4104, "7"}, + { "registeredID", 536879116, NULL }, + { NULL, 4104, "8"}, + { "AnotherName", 1610612741, NULL }, + { "type-id", 1073741836, NULL }, + { "value", 541073421, NULL }, + { NULL, 1073743880, "0"}, + { "type-id", 1, NULL }, + { "EDIPartyName", 1610612741, NULL }, + { "nameAssigner", 1610637314, "DirectoryString"}, + { NULL, 4104, "0"}, + { "partyName", 536879106, "DirectoryString"}, + { NULL, 4104, "1"}, + { "id-ce-issuerAltName", 1879048204, NULL }, + { NULL, 1073741825, "id-ce"}, + { NULL, 1, "18"}, + { "IssuerAltName", 1073741826, "GeneralNames"}, + { "id-ce-subjectDirectoryAttributes", 1879048204, NULL }, + { NULL, 1073741825, "id-ce"}, + { NULL, 1, "9"}, + { "SubjectDirectoryAttributes", 1612709899, NULL }, + { "MAX", 1074266122, "1"}, + { NULL, 2, "Attribute"}, + { "id-ce-basicConstraints", 1879048204, NULL }, + { NULL, 1073741825, "id-ce"}, + { NULL, 1, "19"}, + { "BasicConstraints", 1610612741, NULL }, + { "cA", 1610645508, NULL }, + { NULL, 131081, NULL }, + { "pathLenConstraint", 537411587, NULL }, + { "0", 10, "MAX"}, + { "id-ce-nameConstraints", 1879048204, NULL }, + { NULL, 1073741825, "id-ce"}, + { NULL, 1, "30"}, + { "NameConstraints", 1610612741, NULL }, + { "permittedSubtrees", 1610637314, "GeneralSubtrees"}, + { NULL, 4104, "0"}, + { "excludedSubtrees", 536895490, "GeneralSubtrees"}, + { NULL, 4104, "1"}, + { "GeneralSubtrees", 1612709899, NULL }, + { "MAX", 1074266122, "1"}, + { NULL, 2, "GeneralSubtree"}, + { "GeneralSubtree", 1610612741, NULL }, + { "base", 1073741826, "GeneralName"}, + { "minimum", 1610653698, "BaseDistance"}, + { NULL, 1073741833, "0"}, + { NULL, 4104, "0"}, + { "maximum", 536895490, "BaseDistance"}, + { NULL, 4104, "1"}, + { "BaseDistance", 1611137027, NULL }, + { "0", 10, "MAX"}, + { "id-ce-policyConstraints", 1879048204, NULL }, + { NULL, 1073741825, "id-ce"}, + { NULL, 1, "36"}, + { "PolicyConstraints", 1610612741, NULL }, + { "requireExplicitPolicy", 1610637314, "SkipCerts"}, + { NULL, 4104, "0"}, + { "inhibitPolicyMapping", 536895490, "SkipCerts"}, + { NULL, 4104, "1"}, + { "SkipCerts", 1611137027, NULL }, + { "0", 10, "MAX"}, + { "id-ce-cRLDistributionPoints", 1879048204, NULL }, + { NULL, 1073741825, "id-ce"}, + { NULL, 1, "31"}, + { "CRLDistPointsSyntax", 1612709899, NULL }, + { "MAX", 1074266122, "1"}, + { NULL, 2, "DistributionPoint"}, + { "DistributionPoint", 1610612741, NULL }, + { "distributionPoint", 1610637314, "DistributionPointName"}, + { NULL, 4104, "0"}, + { "reasons", 1610637314, "ReasonFlags"}, + { NULL, 4104, "1"}, + { "cRLIssuer", 536895490, "GeneralNames"}, + { NULL, 4104, "2"}, + { "DistributionPointName", 1610612741, NULL }, + { "fullName", 1610637314, "GeneralNames"}, + { NULL, 4104, "0"}, + { "nameRelativeToCRLIssuer", 536895490, "RelativeDistinguishedName"}, + { NULL, 4104, "1"}, + { "ReasonFlags", 1610874886, NULL }, + { "unused", 1073741825, "0"}, + { "keyCompromise", 1073741825, "1"}, + { "cACompromise", 1073741825, "2"}, + { "affiliationChanged", 1073741825, "3"}, + { "superseded", 1073741825, "4"}, + { "cessationOfOperation", 1073741825, "5"}, + { "certificateHold", 1, "6"}, + { "id-ce-extKeyUsage", 1879048204, NULL }, + { NULL, 1073741825, "id-ce"}, + { NULL, 1, "37"}, + { "ExtKeyUsageSyntax", 1612709899, NULL }, + { "MAX", 1074266122, "1"}, + { NULL, 2, "KeyPurposeId"}, + { "KeyPurposeId", 1073741836, NULL }, + { "id-kp-serverAuth", 1879048204, NULL }, + { NULL, 1073741825, "id-kp"}, + { NULL, 1, "1"}, + { "id-kp-clientAuth", 1879048204, NULL }, + { NULL, 1073741825, "id-kp"}, + { NULL, 1, "2"}, + { "id-kp-codeSigning", 1879048204, NULL }, + { NULL, 1073741825, "id-kp"}, + { NULL, 1, "3"}, + { "id-kp-emailProtection", 1879048204, NULL }, + { NULL, 1073741825, "id-kp"}, + { NULL, 1, "4"}, + { "id-kp-ipsecEndSystem", 1879048204, NULL }, + { NULL, 1073741825, "id-kp"}, + { NULL, 1, "5"}, + { "id-kp-ipsecTunnel", 1879048204, NULL }, + { NULL, 1073741825, "id-kp"}, + { NULL, 1, "6"}, + { "id-kp-ipsecUser", 1879048204, NULL }, + { NULL, 1073741825, "id-kp"}, + { NULL, 1, "7"}, + { "id-kp-timeStamping", 1879048204, NULL }, + { NULL, 1073741825, "id-kp"}, + { NULL, 1, "8"}, + { "id-pe-authorityInfoAccess", 1879048204, NULL }, + { NULL, 1073741825, "id-pe"}, + { NULL, 1, "1"}, + { "AuthorityInfoAccessSyntax", 1612709899, NULL }, + { "MAX", 1074266122, "1"}, + { NULL, 2, "AccessDescription"}, + { "AccessDescription", 1610612741, NULL }, + { "accessMethod", 1073741836, NULL }, + { "accessLocation", 2, "GeneralName"}, + { "id-ce-cRLNumber", 1879048204, NULL }, + { NULL, 1073741825, "id-ce"}, + { NULL, 1, "20"}, + { "CRLNumber", 1611137027, NULL }, + { "0", 10, "MAX"}, + { "id-ce-issuingDistributionPoint", 1879048204, NULL }, + { NULL, 1073741825, "id-ce"}, + { NULL, 1, "28"}, + { "IssuingDistributionPoint", 1610612741, NULL }, + { "distributionPoint", 1610637314, "DistributionPointName"}, + { NULL, 4104, "0"}, + { "onlyContainsUserCerts", 1610653700, NULL }, + { NULL, 1073872905, NULL }, + { NULL, 4104, "1"}, + { "onlyContainsCACerts", 1610653700, NULL }, + { NULL, 1073872905, NULL }, + { NULL, 4104, "2"}, + { "onlySomeReasons", 1610637314, "ReasonFlags"}, + { NULL, 4104, "3"}, + { "indirectCRL", 536911876, NULL }, + { NULL, 1073872905, NULL }, + { NULL, 4104, "4"}, + { "id-ce-deltaCRLIndicator", 1879048204, NULL }, + { NULL, 1073741825, "id-ce"}, + { NULL, 1, "27"}, + { "BaseCRLNumber", 1073741826, "CRLNumber"}, + { "id-ce-cRLReasons", 1879048204, NULL }, + { NULL, 1073741825, "id-ce"}, + { NULL, 1, "21"}, + { "CRLReason", 1610874901, NULL }, + { "unspecified", 1073741825, "0"}, + { "keyCompromise", 1073741825, "1"}, + { "cACompromise", 1073741825, "2"}, + { "affiliationChanged", 1073741825, "3"}, + { "superseded", 1073741825, "4"}, + { "cessationOfOperation", 1073741825, "5"}, + { "certificateHold", 1073741825, "6"}, + { "removeFromCRL", 1, "8"}, + { "id-ce-certificateIssuer", 1879048204, NULL }, + { NULL, 1073741825, "id-ce"}, + { NULL, 1, "29"}, + { "CertificateIssuer", 1073741826, "GeneralNames"}, + { "id-ce-holdInstructionCode", 1879048204, NULL }, + { NULL, 1073741825, "id-ce"}, + { NULL, 1, "23"}, + { "HoldInstructionCode", 1073741836, NULL }, + { "holdInstruction", 1879048204, NULL }, + { "joint-iso-itu-t", 1073741825, "2"}, + { "member-body", 1073741825, "2"}, + { "us", 1073741825, "840"}, + { "x9cm", 1073741825, "10040"}, + { NULL, 1, "2"}, + { "id-holdinstruction-none", 1879048204, NULL }, + { NULL, 1073741825, "holdInstruction"}, + { NULL, 1, "1"}, + { "id-holdinstruction-callissuer", 1879048204, NULL }, + { NULL, 1073741825, "holdInstruction"}, + { NULL, 1, "2"}, + { "id-holdinstruction-reject", 1879048204, NULL }, + { NULL, 1073741825, "holdInstruction"}, + { NULL, 1, "3"}, + { "id-ce-invalidityDate", 1879048204, NULL }, + { NULL, 1073741825, "id-ce"}, + { NULL, 1, "24"}, + { "InvalidityDate", 1073741861, NULL }, + { "id-netscape", 1879048204, NULL }, + { "joint-iso-itu-t", 1073741825, "2"}, + { "country", 1073741825, "16"}, + { "us", 1073741825, "840"}, + { "organization", 1073741825, "1"}, + { "netscape", 1, "113730"}, + { "id-netscape-certExtension", 1879048204, NULL }, + { NULL, 1073741825, "id-netscape"}, + { NULL, 1, "1"}, + { "id-netscape-certType", 1879048204, NULL }, + { NULL, 1073741825, "id-netscape-certExtension"}, + { NULL, 1, "1"}, + { "CertType", 1610874886, NULL }, + { "sslClient", 1073741825, "0"}, + { "sslServer", 1073741825, "1"}, + { "smime", 1073741825, "2"}, + { "objectSigning", 1073741825, "3"}, + { "reserved", 1073741825, "4"}, + { "sslCA", 1073741825, "5"}, + { "smimeCA", 1073741825, "6"}, + { "objectSigningCA", 1, "7"}, + { "VisibleString", 1610620935, NULL }, + { NULL, 4360, "26"}, + { "NumericString", 1610620935, NULL }, + { NULL, 4360, "18"}, + { "IA5String", 1610620935, NULL }, + { NULL, 4360, "22"}, + { "TeletexString", 1610620935, NULL }, + { NULL, 4360, "20"}, + { "PrintableString", 1610620935, NULL }, + { NULL, 4360, "19"}, + { "UniversalString", 1610620935, NULL }, + { NULL, 4360, "28"}, + { "BMPString", 1610620935, NULL }, + { NULL, 4360, "30"}, + { "UTF8String", 1610620935, NULL }, + { NULL, 4360, "12"}, + { "id-pkix", 1879048204, NULL }, + { "iso", 1073741825, "1"}, + { "identified-organization", 1073741825, "3"}, + { "dod", 1073741825, "6"}, + { "internet", 1073741825, "1"}, + { "security", 1073741825, "5"}, + { "mechanisms", 1073741825, "5"}, + { "pkix", 1, "7"}, + { "id-pe", 1879048204, NULL }, + { NULL, 1073741825, "id-pkix"}, + { NULL, 1, "1"}, + { "id-qt", 1879048204, NULL }, + { NULL, 1073741825, "id-pkix"}, + { NULL, 1, "2"}, + { "id-kp", 1879048204, NULL }, + { NULL, 1073741825, "id-pkix"}, + { NULL, 1, "3"}, + { "id-ad", 1879048204, NULL }, + { NULL, 1073741825, "id-pkix"}, + { NULL, 1, "48"}, + { "id-qt-cps", 1879048204, NULL }, + { NULL, 1073741825, "id-qt"}, + { NULL, 1, "1"}, + { "id-qt-unotice", 1879048204, NULL }, + { NULL, 1073741825, "id-qt"}, + { NULL, 1, "2"}, + { "id-ad-ocsp", 1879048204, NULL }, + { NULL, 1073741825, "id-ad"}, + { NULL, 1, "1"}, + { "id-ad-caIssuers", 1879048204, NULL }, + { NULL, 1073741825, "id-ad"}, + { NULL, 1, "2"}, + { "Attribute", 1610612741, NULL }, + { "type", 1073741826, "AttributeType"}, + { "values", 536870927, NULL }, + { NULL, 2, "AttributeValue"}, + { "AttributeType", 1073741836, NULL }, + { "AttributeValue", 1073741837, NULL }, + { "AttributeTypeAndValue", 1610612741, NULL }, + { "type", 1073741826, "AttributeType"}, + { "value", 2, "AttributeValue"}, + { "id-at", 1879048204, NULL }, + { "joint-iso-ccitt", 1073741825, "2"}, + { "ds", 1073741825, "5"}, + { NULL, 1, "4"}, + { "id-at-name", 1880096780, "AttributeType"}, + { NULL, 1073741825, "id-at"}, + { NULL, 1, "41"}, + { "id-at-surname", 1880096780, "AttributeType"}, + { NULL, 1073741825, "id-at"}, + { NULL, 1, "4"}, + { "id-at-givenName", 1880096780, "AttributeType"}, + { NULL, 1073741825, "id-at"}, + { NULL, 1, "42"}, + { "id-at-initials", 1880096780, "AttributeType"}, + { NULL, 1073741825, "id-at"}, + { NULL, 1, "43"}, + { "id-at-generationQualifier", 1880096780, "AttributeType"}, + { NULL, 1073741825, "id-at"}, + { NULL, 1, "44"}, + { "X520name", 1610612754, NULL }, + { "teletexString", 1612709918, NULL }, + { "ub-name", 524298, "1"}, + { "printableString", 1612709919, NULL }, + { "ub-name", 524298, "1"}, + { "universalString", 1612709920, NULL }, + { "ub-name", 524298, "1"}, + { "utf8String", 1612709922, NULL }, + { "ub-name", 524298, "1"}, + { "bmpString", 538968097, NULL }, + { "ub-name", 524298, "1"}, + { "id-at-commonName", 1880096780, "AttributeType"}, + { NULL, 1073741825, "id-at"}, + { NULL, 1, "3"}, + { "X520CommonName", 1610612754, NULL }, + { "teletexString", 1612709918, NULL }, + { "ub-common-name", 524298, "1"}, + { "printableString", 1612709919, NULL }, + { "ub-common-name", 524298, "1"}, + { "universalString", 1612709920, NULL }, + { "ub-common-name", 524298, "1"}, + { "utf8String", 1612709922, NULL }, + { "ub-common-name", 524298, "1"}, + { "bmpString", 538968097, NULL }, + { "ub-common-name", 524298, "1"}, + { "id-at-localityName", 1880096780, "AttributeType"}, + { NULL, 1073741825, "id-at"}, + { NULL, 1, "7"}, + { "X520LocalityName", 1610612754, NULL }, + { "teletexString", 1612709918, NULL }, + { "ub-locality-name", 524298, "1"}, + { "printableString", 1612709919, NULL }, + { "ub-locality-name", 524298, "1"}, + { "universalString", 1612709920, NULL }, + { "ub-locality-name", 524298, "1"}, + { "utf8String", 1612709922, NULL }, + { "ub-locality-name", 524298, "1"}, + { "bmpString", 538968097, NULL }, + { "ub-locality-name", 524298, "1"}, + { "id-at-stateOrProvinceName", 1880096780, "AttributeType"}, + { NULL, 1073741825, "id-at"}, + { NULL, 1, "8"}, + { "X520StateOrProvinceName", 1610612754, NULL }, + { "teletexString", 1612709918, NULL }, + { "ub-state-name", 524298, "1"}, + { "printableString", 1612709919, NULL }, + { "ub-state-name", 524298, "1"}, + { "universalString", 1612709920, NULL }, + { "ub-state-name", 524298, "1"}, + { "utf8String", 1612709922, NULL }, + { "ub-state-name", 524298, "1"}, + { "bmpString", 538968097, NULL }, + { "ub-state-name", 524298, "1"}, + { "id-at-organizationName", 1880096780, "AttributeType"}, + { NULL, 1073741825, "id-at"}, + { NULL, 1, "10"}, + { "X520OrganizationName", 1610612754, NULL }, + { "teletexString", 1612709918, NULL }, + { "ub-organization-name", 524298, "1"}, + { "printableString", 1612709919, NULL }, + { "ub-organization-name", 524298, "1"}, + { "universalString", 1612709920, NULL }, + { "ub-organization-name", 524298, "1"}, + { "utf8String", 1612709922, NULL }, + { "ub-organization-name", 524298, "1"}, + { "bmpString", 538968097, NULL }, + { "ub-organization-name", 524298, "1"}, + { "id-at-organizationalUnitName", 1880096780, "AttributeType"}, + { NULL, 1073741825, "id-at"}, + { NULL, 1, "11"}, + { "X520OrganizationalUnitName", 1610612754, NULL }, + { "teletexString", 1612709918, NULL }, + { "ub-organizational-unit-name", 524298, "1"}, + { "printableString", 1612709919, NULL }, + { "ub-organizational-unit-name", 524298, "1"}, + { "universalString", 1612709920, NULL }, + { "ub-organizational-unit-name", 524298, "1"}, + { "utf8String", 1612709922, NULL }, + { "ub-organizational-unit-name", 524298, "1"}, + { "bmpString", 538968097, NULL }, + { "ub-organizational-unit-name", 524298, "1"}, + { "id-at-title", 1880096780, "AttributeType"}, + { NULL, 1073741825, "id-at"}, + { NULL, 1, "12"}, + { "X520Title", 1610612754, NULL }, + { "teletexString", 1612709918, NULL }, + { "ub-title", 524298, "1"}, + { "printableString", 1612709919, NULL }, + { "ub-title", 524298, "1"}, + { "universalString", 1612709920, NULL }, + { "ub-title", 524298, "1"}, + { "utf8String", 1612709922, NULL }, + { "ub-title", 524298, "1"}, + { "bmpString", 538968097, NULL }, + { "ub-title", 524298, "1"}, + { "id-at-dnQualifier", 1880096780, "AttributeType"}, + { NULL, 1073741825, "id-at"}, + { NULL, 1, "46"}, + { "X520dnQualifier", 1073741855, NULL }, + { "id-at-countryName", 1880096780, "AttributeType"}, + { NULL, 1073741825, "id-at"}, + { NULL, 1, "6"}, + { "X520countryName", 1612709919, NULL }, + { NULL, 1048586, "2"}, + { "pkcs-9", 1879048204, NULL }, + { "iso", 1073741825, "1"}, + { "member-body", 1073741825, "2"}, + { "us", 1073741825, "840"}, + { "rsadsi", 1073741825, "113549"}, + { "pkcs", 1073741825, "1"}, + { NULL, 1, "9"}, + { "emailAddress", 1880096780, "AttributeType"}, + { NULL, 1073741825, "pkcs-9"}, + { NULL, 1, "1"}, + { "Pkcs9email", 1612709917, NULL }, + { "ub-emailaddress-length", 524298, "1"}, + { "Name", 1610612754, NULL }, + { "rdnSequence", 2, "RDNSequence"}, + { "RDNSequence", 1610612747, NULL }, + { NULL, 2, "RelativeDistinguishedName"}, + { "DistinguishedName", 1073741826, "RDNSequence"}, + { "RelativeDistinguishedName", 1612709903, NULL }, + { "MAX", 1074266122, "1"}, + { NULL, 2, "AttributeTypeAndValue"}, + { "DirectoryString", 1610612754, NULL }, + { "teletexString", 1612709918, NULL }, + { "MAX", 524298, "1"}, + { "printableString", 1612709919, NULL }, + { "MAX", 524298, "1"}, + { "universalString", 1612709920, NULL }, + { "MAX", 524298, "1"}, + { "utf8String", 1612709922, NULL }, + { "MAX", 524298, "1"}, + { "bmpString", 538968097, NULL }, + { "MAX", 524298, "1"}, + { "Certificate", 1610612741, NULL }, + { "tbsCertificate", 1073741826, "TBSCertificate"}, + { "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"}, + { "signature", 6, NULL }, + { "TBSCertificate", 1610612741, NULL }, + { "version", 1610653698, "Version"}, + { NULL, 1073741833, "v1"}, + { NULL, 2056, "0"}, + { "serialNumber", 1073741826, "CertificateSerialNumber"}, + { "signature", 1073741826, "AlgorithmIdentifier"}, + { "issuer", 1073741826, "Name"}, + { "validity", 1073741826, "Validity"}, + { "subject", 1073741826, "Name"}, + { "subjectPublicKeyInfo", 1073741826, "SubjectPublicKeyInfo"}, + { "issuerUniqueID", 1610637314, "UniqueIdentifier"}, + { NULL, 4104, "1"}, + { "subjectUniqueID", 1610637314, "UniqueIdentifier"}, + { NULL, 4104, "2"}, + { "extensions", 536895490, "Extensions"}, + { NULL, 2056, "3"}, + { "Version", 1610874883, NULL }, + { "v1", 1073741825, "0"}, + { "v2", 1073741825, "1"}, + { "v3", 1, "2"}, + { "CertificateSerialNumber", 1073741827, NULL }, + { "Validity", 1610612741, NULL }, + { "notBefore", 1073741826, "Time"}, + { "notAfter", 2, "Time"}, + { "Time", 1610612754, NULL }, + { "utcTime", 1073741860, NULL }, + { "generalTime", 37, NULL }, + { "UniqueIdentifier", 1073741830, NULL }, + { "SubjectPublicKeyInfo", 1610612741, NULL }, + { "algorithm", 1073741826, "AlgorithmIdentifier"}, + { "subjectPublicKey", 6, NULL }, + { "Extensions", 1612709899, NULL }, + { "MAX", 1074266122, "1"}, + { NULL, 2, "Extension"}, + { "Extension", 1610612741, NULL }, + { "extnID", 1073741836, NULL }, + { "critical", 1610645508, NULL }, + { NULL, 131081, NULL }, + { "extnValue", 7, NULL }, + { "CertificateList", 1610612741, NULL }, + { "tbsCertList", 1073741826, "TBSCertList"}, + { "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"}, + { "signature", 6, NULL }, + { "TBSCertList", 1610612741, NULL }, + { "version", 1073758210, "Version"}, + { "signature", 1073741826, "AlgorithmIdentifier"}, + { "issuer", 1073741826, "Name"}, + { "thisUpdate", 1073741826, "Time"}, + { "nextUpdate", 1073758210, "Time"}, + { "revokedCertificates", 1610629131, NULL }, + { NULL, 536870917, NULL }, + { "userCertificate", 1073741826, "CertificateSerialNumber"}, + { "revocationDate", 1073741826, "Time"}, + { "crlEntryExtensions", 16386, "Extensions"}, + { "crlExtensions", 536895490, "Extensions"}, + { NULL, 2056, "0"}, + { "AlgorithmIdentifier", 1610612741, NULL }, + { "algorithm", 1073741836, NULL }, + { "parameters", 541081613, NULL }, + { "algorithm", 1, NULL }, + { "pkcs-1", 1879048204, NULL }, + { "iso", 1073741825, "1"}, + { "member-body", 1073741825, "2"}, + { "us", 1073741825, "840"}, + { "rsadsi", 1073741825, "113549"}, + { "pkcs", 1073741825, "1"}, + { NULL, 1, "1"}, + { "rsaEncryption", 1879048204, NULL }, + { NULL, 1073741825, "pkcs-1"}, + { NULL, 1, "1"}, + { "md2WithRSAEncryption", 1879048204, NULL }, + { NULL, 1073741825, "pkcs-1"}, + { NULL, 1, "2"}, + { "md5WithRSAEncryption", 1879048204, NULL }, + { NULL, 1073741825, "pkcs-1"}, + { NULL, 1, "4"}, + { "sha1WithRSAEncryption", 1879048204, NULL }, + { NULL, 1073741825, "pkcs-1"}, + { NULL, 1, "5"}, + { "sha256WithRSAEncryption", 1879048204, NULL }, + { NULL, 1073741825, "pkcs-1"}, + { NULL, 1, "11"}, + { "sha384WithRSAEncryption", 1879048204, NULL }, + { NULL, 1073741825, "pkcs-1"}, + { NULL, 1, "12"}, + { "sha512WithRSAEncryption", 1879048204, NULL }, + { NULL, 1073741825, "pkcs-1"}, + { NULL, 1, "13"}, + { "RSAPublicKey", 1610612741, NULL }, + { "modulus", 1073741827, NULL }, + { "publicExponent", 3, NULL }, + { "RSAPrivateKey", 1610612741, NULL }, + { "version", 1073741826, "Version"}, + { "modulus", 1073741827, NULL }, + { "publicExponent", 1073741827, NULL }, + { "privateExponent", 1073741827, NULL }, + { "prime1", 1073741827, NULL }, + { "prime2", 1073741827, NULL }, + { "exponent1", 1073741827, NULL }, + { "exponent2", 1073741827, NULL }, + { "coefficient", 3, NULL }, + { "id-dsa-with-sha1", 1879048204, NULL }, + { "iso", 1073741825, "1"}, + { "member-body", 1073741825, "2"}, + { "us", 1073741825, "840"}, + { "x9-57", 1073741825, "10040"}, + { "x9algorithm", 1073741825, "4"}, + { NULL, 1, "3"}, + { "Dss-Sig-Value", 1610612741, NULL }, + { "r", 1073741827, NULL }, + { "s", 3, NULL }, + { "dhpublicnumber", 1879048204, NULL }, + { "iso", 1073741825, "1"}, + { "member-body", 1073741825, "2"}, + { "us", 1073741825, "840"}, + { "ansi-x942", 1073741825, "10046"}, + { "number-type", 1073741825, "2"}, + { NULL, 1, "1"}, + { "DomainParameters", 1610612741, NULL }, + { "p", 1073741827, NULL }, + { "g", 1073741827, NULL }, + { "q", 1073741827, NULL }, + { "j", 1073758211, NULL }, + { "validationParms", 16386, "ValidationParms"}, + { "ValidationParms", 1610612741, NULL }, + { "seed", 1073741830, NULL }, + { "pgenCounter", 3, NULL }, + { "id-dsa", 1879048204, NULL }, + { "iso", 1073741825, "1"}, + { "member-body", 1073741825, "2"}, + { "us", 1073741825, "840"}, + { "x9-57", 1073741825, "10040"}, + { "x9algorithm", 1073741825, "4"}, + { NULL, 1, "1"}, + { "Dss-Parms", 1610612741, NULL }, + { "p", 1073741827, NULL }, + { "q", 1073741827, NULL }, + { "g", 3, NULL }, + { "ORAddress", 1610612741, NULL }, + { "built-in-standard-attributes", 1073741826, "BuiltInStandardAttributes"}, + { "built-in-domain-defined-attributes", 1073758210, "BuiltInDomainDefinedAttributes"}, + { "extension-attributes", 16386, "ExtensionAttributes"}, + { "BuiltInStandardAttributes", 1610612741, NULL }, + { "country-name", 1073758210, "CountryName"}, + { "administration-domain-name", 1073758210, "AdministrationDomainName"}, + { "network-address", 1610637314, "NetworkAddress"}, + { NULL, 2056, "0"}, + { "terminal-identifier", 1610637314, "TerminalIdentifier"}, + { NULL, 2056, "1"}, + { "private-domain-name", 1610637314, "PrivateDomainName"}, + { NULL, 2056, "2"}, + { "organization-name", 1610637314, "OrganizationName"}, + { NULL, 2056, "3"}, + { "numeric-user-identifier", 1610637314, "NumericUserIdentifier"}, + { NULL, 2056, "4"}, + { "personal-name", 1610637314, "PersonalName"}, + { NULL, 2056, "5"}, + { "organizational-unit-names", 536895490, "OrganizationalUnitNames"}, + { NULL, 2056, "6"}, + { "CountryName", 1610620946, NULL }, + { NULL, 1073746952, "1"}, + { "x121-dcc-code", 1612709916, NULL }, + { NULL, 1048586, "ub-country-name-numeric-length"}, + { "iso-3166-alpha2-code", 538968095, NULL }, + { NULL, 1048586, "ub-country-name-alpha-length"}, + { "AdministrationDomainName", 1610620946, NULL }, + { NULL, 1073744904, "2"}, + { "numeric", 1612709916, NULL }, + { "ub-domain-name-length", 524298, "0"}, + { "printable", 538968095, NULL }, + { "ub-domain-name-length", 524298, "0"}, + { "NetworkAddress", 1073741826, "X121Address"}, + { "X121Address", 1612709916, NULL }, + { "ub-x121-address-length", 524298, "1"}, + { "TerminalIdentifier", 1612709919, NULL }, + { "ub-terminal-id-length", 524298, "1"}, + { "PrivateDomainName", 1610612754, NULL }, + { "numeric", 1612709916, NULL }, + { "ub-domain-name-length", 524298, "1"}, + { "printable", 538968095, NULL }, + { "ub-domain-name-length", 524298, "1"}, + { "OrganizationName", 1612709919, NULL }, + { "ub-organization-name-length", 524298, "1"}, + { "NumericUserIdentifier", 1612709916, NULL }, + { "ub-numeric-user-id-length", 524298, "1"}, + { "PersonalName", 1610612750, NULL }, + { "surname", 1814044703, NULL }, + { NULL, 1073745928, "0"}, + { "ub-surname-length", 524298, "1"}, + { "given-name", 1814061087, NULL }, + { NULL, 1073745928, "1"}, + { "ub-given-name-length", 524298, "1"}, + { "initials", 1814061087, NULL }, + { NULL, 1073745928, "2"}, + { "ub-initials-length", 524298, "1"}, + { "generation-qualifier", 740319263, NULL }, + { NULL, 1073745928, "3"}, + { "ub-generation-qualifier-length", 524298, "1"}, + { "OrganizationalUnitNames", 1612709899, NULL }, + { "ub-organizational-units", 1074266122, "1"}, + { NULL, 2, "OrganizationalUnitName"}, + { "OrganizationalUnitName", 1612709919, NULL }, + { "ub-organizational-unit-name-length", 524298, "1"}, + { "BuiltInDomainDefinedAttributes", 1612709899, NULL }, + { "ub-domain-defined-attributes", 1074266122, "1"}, + { NULL, 2, "BuiltInDomainDefinedAttribute"}, + { "BuiltInDomainDefinedAttribute", 1610612741, NULL }, + { "type", 1612709919, NULL }, + { "ub-domain-defined-attribute-type-length", 524298, "1"}, + { "value", 538968095, NULL }, + { "ub-domain-defined-attribute-value-length", 524298, "1"}, + { "ExtensionAttributes", 1612709903, NULL }, + { "ub-extension-attributes", 1074266122, "1"}, + { NULL, 2, "ExtensionAttribute"}, + { "ExtensionAttribute", 1610612741, NULL }, + { "extension-attribute-type", 1611145219, NULL }, + { NULL, 1073743880, "0"}, + { "0", 10, "ub-extension-attributes"}, + { "extension-attribute-value", 541073421, NULL }, + { NULL, 1073743880, "1"}, + { "extension-attribute-type", 1, NULL }, + { "common-name", 1342177283, "1"}, + { "CommonName", 1612709919, NULL }, + { "ub-common-name-length", 524298, "1"}, + { "teletex-common-name", 1342177283, "2"}, + { "TeletexCommonName", 1612709918, NULL }, + { "ub-common-name-length", 524298, "1"}, + { "teletex-organization-name", 1342177283, "3"}, + { "TeletexOrganizationName", 1612709918, NULL }, + { "ub-organization-name-length", 524298, "1"}, + { "teletex-personal-name", 1342177283, "4"}, + { "TeletexPersonalName", 1610612750, NULL }, + { "surname", 1814044702, NULL }, + { NULL, 1073743880, "0"}, + { "ub-surname-length", 524298, "1"}, + { "given-name", 1814061086, NULL }, + { NULL, 1073743880, "1"}, + { "ub-given-name-length", 524298, "1"}, + { "initials", 1814061086, NULL }, + { NULL, 1073743880, "2"}, + { "ub-initials-length", 524298, "1"}, + { "generation-qualifier", 740319262, NULL }, + { NULL, 1073743880, "3"}, + { "ub-generation-qualifier-length", 524298, "1"}, + { "teletex-organizational-unit-names", 1342177283, "5"}, + { "TeletexOrganizationalUnitNames", 1612709899, NULL }, + { "ub-organizational-units", 1074266122, "1"}, + { NULL, 2, "TeletexOrganizationalUnitName"}, + { "TeletexOrganizationalUnitName", 1612709918, NULL }, + { "ub-organizational-unit-name-length", 524298, "1"}, + { "pds-name", 1342177283, "7"}, + { "PDSName", 1612709919, NULL }, + { "ub-pds-name-length", 524298, "1"}, + { "physical-delivery-country-name", 1342177283, "8"}, + { "PhysicalDeliveryCountryName", 1610612754, NULL }, + { "x121-dcc-code", 1612709916, NULL }, + { NULL, 1048586, "ub-country-name-numeric-length"}, + { "iso-3166-alpha2-code", 538968095, NULL }, + { NULL, 1048586, "ub-country-name-alpha-length"}, + { "postal-code", 1342177283, "9"}, + { "PostalCode", 1610612754, NULL }, + { "numeric-code", 1612709916, NULL }, + { "ub-postal-code-length", 524298, "1"}, + { "printable-code", 538968095, NULL }, + { "ub-postal-code-length", 524298, "1"}, + { "physical-delivery-office-name", 1342177283, "10"}, + { "PhysicalDeliveryOfficeName", 1073741826, "PDSParameter"}, + { "physical-delivery-office-number", 1342177283, "11"}, + { "PhysicalDeliveryOfficeNumber", 1073741826, "PDSParameter"}, + { "extension-OR-address-components", 1342177283, "12"}, + { "ExtensionORAddressComponents", 1073741826, "PDSParameter"}, + { "physical-delivery-personal-name", 1342177283, "13"}, + { "PhysicalDeliveryPersonalName", 1073741826, "PDSParameter"}, + { "physical-delivery-organization-name", 1342177283, "14"}, + { "PhysicalDeliveryOrganizationName", 1073741826, "PDSParameter"}, + { "extension-physical-delivery-address-components", 1342177283, "15"}, + { "ExtensionPhysicalDeliveryAddressComponents", 1073741826, "PDSParameter"}, + { "unformatted-postal-address", 1342177283, "16"}, + { "UnformattedPostalAddress", 1610612750, NULL }, + { "printable-address", 1814052875, NULL }, + { "ub-pds-physical-address-lines", 1074266122, "1"}, + { NULL, 538968095, NULL }, + { "ub-pds-parameter-length", 524298, "1"}, + { "teletex-string", 740311070, NULL }, + { "ub-unformatted-address-length", 524298, "1"}, + { "street-address", 1342177283, "17"}, + { "StreetAddress", 1073741826, "PDSParameter"}, + { "post-office-box-address", 1342177283, "18"}, + { "PostOfficeBoxAddress", 1073741826, "PDSParameter"}, + { "poste-restante-address", 1342177283, "19"}, + { "PosteRestanteAddress", 1073741826, "PDSParameter"}, + { "unique-postal-name", 1342177283, "20"}, + { "UniquePostalName", 1073741826, "PDSParameter"}, + { "local-postal-attributes", 1342177283, "21"}, + { "LocalPostalAttributes", 1073741826, "PDSParameter"}, + { "PDSParameter", 1610612750, NULL }, + { "printable-string", 1814052895, NULL }, + { "ub-pds-parameter-length", 524298, "1"}, + { "teletex-string", 740311070, NULL }, + { "ub-pds-parameter-length", 524298, "1"}, + { "extended-network-address", 1342177283, "22"}, + { "ExtendedNetworkAddress", 1610612754, NULL }, + { "e163-4-address", 1610612741, NULL }, + { "number", 1612718108, NULL }, + { NULL, 1073743880, "0"}, + { "ub-e163-4-number-length", 524298, "1"}, + { "sub-address", 538992668, NULL }, + { NULL, 1073743880, "1"}, + { "ub-e163-4-sub-address-length", 524298, "1"}, + { "psap-address", 536879106, "PresentationAddress"}, + { NULL, 2056, "0"}, + { "PresentationAddress", 1610612741, NULL }, + { "pSelector", 1610637319, NULL }, + { NULL, 2056, "0"}, + { "sSelector", 1610637319, NULL }, + { NULL, 2056, "1"}, + { "tSelector", 1610637319, NULL }, + { NULL, 2056, "2"}, + { "nAddresses", 538976271, NULL }, + { NULL, 1073743880, "3"}, + { "MAX", 1074266122, "1"}, + { NULL, 7, NULL }, + { "terminal-type", 1342177283, "23"}, + { "TerminalType", 1611137027, NULL }, + { "0", 10, "ub-integer-options"}, + { "teletex-domain-defined-attributes", 1342177283, "6"}, + { "TeletexDomainDefinedAttributes", 1612709899, NULL }, + { "ub-domain-defined-attributes", 1074266122, "1"}, + { NULL, 2, "TeletexDomainDefinedAttribute"}, + { "TeletexDomainDefinedAttribute", 1610612741, NULL }, + { "type", 1612709918, NULL }, + { "ub-domain-defined-attribute-type-length", 524298, "1"}, + { "value", 538968094, NULL }, + { "ub-domain-defined-attribute-value-length", 524298, "1"}, + { "ub-name", 1342177283, "32768"}, + { "ub-common-name", 1342177283, "64"}, + { "ub-locality-name", 1342177283, "128"}, + { "ub-state-name", 1342177283, "128"}, + { "ub-organization-name", 1342177283, "64"}, + { "ub-organizational-unit-name", 1342177283, "64"}, + { "ub-title", 1342177283, "64"}, + { "ub-match", 1342177283, "128"}, + { "ub-emailaddress-length", 1342177283, "128"}, + { "ub-common-name-length", 1342177283, "64"}, + { "ub-country-name-alpha-length", 1342177283, "2"}, + { "ub-country-name-numeric-length", 1342177283, "3"}, + { "ub-domain-defined-attributes", 1342177283, "4"}, + { "ub-domain-defined-attribute-type-length", 1342177283, "8"}, + { "ub-domain-defined-attribute-value-length", 1342177283, "128"}, + { "ub-domain-name-length", 1342177283, "16"}, + { "ub-extension-attributes", 1342177283, "256"}, + { "ub-e163-4-number-length", 1342177283, "15"}, + { "ub-e163-4-sub-address-length", 1342177283, "40"}, + { "ub-generation-qualifier-length", 1342177283, "3"}, + { "ub-given-name-length", 1342177283, "16"}, + { "ub-initials-length", 1342177283, "5"}, + { "ub-integer-options", 1342177283, "256"}, + { "ub-numeric-user-id-length", 1342177283, "32"}, + { "ub-organization-name-length", 1342177283, "64"}, + { "ub-organizational-unit-name-length", 1342177283, "32"}, + { "ub-organizational-units", 1342177283, "4"}, + { "ub-pds-name-length", 1342177283, "16"}, + { "ub-pds-parameter-length", 1342177283, "30"}, + { "ub-pds-physical-address-lines", 1342177283, "6"}, + { "ub-postal-code-length", 1342177283, "16"}, + { "ub-surname-length", 1342177283, "40"}, + { "ub-terminal-id-length", 1342177283, "24"}, + { "ub-unformatted-address-length", 1342177283, "180"}, + { "ub-x121-address-length", 268435459, "16"}, + { NULL, 0, NULL } +}; diff --git a/proto.h b/proto.h index 0d6a6c9..bfb046a 100644 --- a/proto.h +++ b/proto.h @@ -138,6 +138,7 @@ int load_licence(unsigned char **data); void save_licence(unsigned char *data, int length); void rd_create_ui(void); RD_BOOL rd_pstcache_mkdir(void); +RD_BOOL rd_certcache_mkdir(void); int rd_open_file(char *filename); void rd_close_file(int fd); int rd_read_file(int fd, void *ptr, int len); diff --git a/rdesktop.c b/rdesktop.c index 010ddb6..ac24924 100644 --- a/rdesktop.c +++ b/rdesktop.c @@ -2025,6 +2025,52 @@ rd_create_ui() } } +/* TODO: Replace with recursive mkdir */ +RD_BOOL rd_certcache_mkdir(void) +{ + char *home; + char certcache_dir[PATH_MAX]; + + home = getenv("HOME"); + + if (home == NULL) + return False; + + snprintf(certcache_dir, sizeof(certcache_dir) - 1, "%s/%s", home, ".local"); + + if ((mkdir(certcache_dir, S_IRWXU) == -1) && errno != EEXIST) + { + logger(Core, Error, "%s: mkdir() failed: %s", __func__, strerror(errno)); + return False; + } + + snprintf(certcache_dir, sizeof(certcache_dir) - 1, "%s/%s", home, ".local/share"); + + if ((mkdir(certcache_dir, S_IRWXU) == -1) && errno != EEXIST) + { + logger(Core, Error, "%s: mkdir() failed: %s", __func__, strerror(errno)); + return False; + } + + snprintf(certcache_dir, sizeof(certcache_dir) - 1, "%s/%s", home, ".local/share/rdesktop"); + + if ((mkdir(certcache_dir, S_IRWXU) == -1) && errno != EEXIST) + { + logger(Core, Error, "%s: mkdir() failed: %s", __func__, strerror(errno)); + return False; + } + + snprintf(certcache_dir, sizeof(certcache_dir) - 1, "%s/%s", home, ".local/share/rdesktop/certs"); + + if ((mkdir(certcache_dir, S_IRWXU) == -1) && errno != EEXIST) + { + logger(Core, Error, "%s: mkdir() failed: %s", __func__, strerror(errno)); + return False; + } + + return True; +} + /* Create the bitmap cache directory */ RD_BOOL rd_pstcache_mkdir(void) diff --git a/ssl.c b/ssl.c index 334e57d..c860eb6 100644 --- a/ssl.c +++ b/ssl.c @@ -4,6 +4,7 @@ Copyright (C) Matthew Chapman 1999-2008 Copyright (C) Jay Sorg 2006-2008 Copyright 2016-2017 Henrik Andersson for Cendio AB + Copyright 2017 Alexander Zakharov 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 @@ -21,71 +22,56 @@ #include "rdesktop.h" #include "ssl.h" +#include "asn.h" -/* Helper function to log internal SSL errors using logger */ -void -rdssl_log_ssl_errors(const char *prefix) -{ - unsigned long err; - while (1) - { - err = ERR_get_error(); - if (err == 0) - break; - - logger(Protocol, Error, - "%s, 0x%.8x:%s:%s: %s", - prefix, err, ERR_lib_error_string(err), - ERR_func_error_string(err), ERR_reason_error_string(err)); - } -} +#include void rdssl_sha1_init(RDSSL_SHA1 * sha1) { - SHA1_Init(sha1); + sha1_init(sha1); } void rdssl_sha1_update(RDSSL_SHA1 * sha1, uint8 * data, uint32 len) { - SHA1_Update(sha1, data, len); + sha1_update(sha1, len, data); } void rdssl_sha1_final(RDSSL_SHA1 * sha1, uint8 * out_data) { - SHA1_Final(out_data, sha1); + sha1_digest(sha1, SHA1_DIGEST_SIZE, out_data); } void rdssl_md5_init(RDSSL_MD5 * md5) { - MD5_Init(md5); + md5_init(md5); } void rdssl_md5_update(RDSSL_MD5 * md5, uint8 * data, uint32 len) { - MD5_Update(md5, data, len); + md5_update(md5, len, data); } void rdssl_md5_final(RDSSL_MD5 * md5, uint8 * out_data) { - MD5_Final(out_data, md5); + md5_digest(md5, MD5_DIGEST_SIZE, out_data); } void rdssl_rc4_set_key(RDSSL_RC4 * rc4, uint8 * key, uint32 len) { - RC4_set_key(rc4, len, key); + arcfour_set_key(rc4, len, key); } void rdssl_rc4_crypt(RDSSL_RC4 * rc4, uint8 * in_data, uint8 * out_data, uint32 len) { - RC4(rc4, len, in_data, out_data); + arcfour_crypt(rc4, len, out_data, in_data); } static void @@ -106,145 +92,179 @@ void rdssl_rsa_encrypt(uint8 * out, uint8 * in, int len, uint32 modulus_size, uint8 * modulus, uint8 * exponent) { - BN_CTX *ctx; - BIGNUM *mod, *exp, *x, *y; - uint8 inr[SEC_MAX_MODULUS_SIZE]; - int outlen; + mpz_t exp, mod; - reverse(modulus, modulus_size); - reverse(exponent, SEC_EXPONENT_SIZE); - memcpy(inr, in, len); - reverse(inr, len); + mpz_t y; + mpz_t x; - ctx = BN_CTX_new(); - mod = BN_new(); - exp = BN_new(); - x = BN_new(); - y = BN_new(); + size_t outlen; + + mpz_init(y); + mpz_init(x); + mpz_init(exp); + mpz_init(mod); + + mpz_import(mod, modulus_size, 1, sizeof(modulus[0]), 0, 0, modulus); + // TODO: Need exponent size + mpz_import(exp, 3, 1, sizeof(exponent[0]), 0, 0, exponent); + + mpz_import(x, len, -1, sizeof(in[0]), 0, 0, in); + + mpz_powm(y, x, exp, mod); + + mpz_export(out, &outlen, -1, sizeof(out[0]), 0, 0, y); - BN_bin2bn(modulus, modulus_size, mod); - BN_bin2bn(exponent, SEC_EXPONENT_SIZE, exp); - BN_bin2bn(inr, len, x); - BN_mod_exp(y, x, exp, mod, ctx); - outlen = BN_bn2bin(y, out); - reverse(out, outlen); if (outlen < (int) modulus_size) memset(out + outlen, 0, modulus_size - outlen); - - BN_free(y); - BN_clear_free(x); - BN_free(exp); - BN_free(mod); - BN_CTX_free(ctx); } /* returns newly allocated RDSSL_CERT or NULL */ RDSSL_CERT * rdssl_cert_read(uint8 * data, uint32 len) { - /* this will move the data pointer but we don't care, we don't use it again */ - return d2i_X509(NULL, (D2I_X509_CONST unsigned char **) &data, len); + int ret; + gnutls_datum_t cert_data; + gnutls_x509_crt_t *cert; + + cert = malloc(sizeof(*cert)); + + if (!cert) { + logger(Protocol, Error, "%s:%s:%d: Failed to allocate memory for certificate structure.\n", + __FILE__, __func__, __LINE__); + return NULL; + } + + if ((ret = gnutls_x509_crt_init(cert)) != GNUTLS_E_SUCCESS) { + logger(Protocol, Error, "%s:%s:%d: Failed to init certificate structure. GnuTLS error = 0x%02x (%s)\n", + __FILE__, __func__, __LINE__, ret, gnutls_strerror(ret)); + + return NULL; + } + + cert_data.size = len; + cert_data.data = data; + + if ((ret = gnutls_x509_crt_import(*cert, &cert_data, GNUTLS_X509_FMT_DER)) != GNUTLS_E_SUCCESS) { + logger(Protocol, Error, "%s:%s:%d: Failed to import DER encoded certificate. GnuTLS error = 0x%02x (%s)\n", + __FILE__, __func__, __LINE__, ret, gnutls_strerror(ret)); + return NULL; + } + + return cert; } void rdssl_cert_free(RDSSL_CERT * cert) { - X509_free(cert); + gnutls_free(cert); } + +/* + * AFAIK, there's no way to alter the decoded certificate using GnuTLS. + * + * Upon detecting "problem" (wrong public RSA key OID) certificate + * we basically have two options: + * + * 1)) encode certificate back to DER, then parse it using libtasn1, + * fix public key OID (set it to 1.2.840.113549.1.1.1), encode to DER again + * and finally reparse using GnuTLS + * + * 2) encode cert back to DER, get RSA public key parameters using libtasn1 + * + * Or can rewrite the whole certificate related stuff later. + */ + /* returns newly allocated RDSSL_RKEY or NULL */ RDSSL_RKEY * rdssl_cert_to_rkey(RDSSL_CERT * cert, uint32 * key_len) { - EVP_PKEY *epk = NULL; - RDSSL_RKEY *lkey; - int nid; int ret; -#if OPENSSL_VERSION_NUMBER >= 0x10100000L - const unsigned char *p; - RSA *rsa = NULL; - int pklen; -#endif + RDSSL_RKEY *pkey; + gnutls_datum_t m, e; + + unsigned int algo, bits; + char oid[64]; + size_t oid_size = sizeof(oid); + + uint8_t data[2048]; + size_t len; + + algo = gnutls_x509_crt_get_pk_algorithm(*cert, &bits); /* By some reason, Microsoft sets the OID of the Public RSA key to the oid for "MD5 with RSA Encryption" instead of "RSA Encryption" - Kudos to Richard Levitte for the following (. intuitive .) - lines of code that resets the OID and let's us extract the key. */ + Kudos to Richard Levitte for the finding this and proposed the fix + using OpenSSL. */ - X509_PUBKEY *key = NULL; - X509_ALGOR *algor = NULL; + if (algo == GNUTLS_PK_RSA) { - key = X509_get_X509_PUBKEY(cert); - if (key == NULL) - { - logger(Protocol, Error, - "rdssl_cert_to_key(), failed to get public key from certificate"); - rdssl_log_ssl_errors("rdssl_cert_to_key()"); + if ((ret = gnutls_x509_crt_get_pk_rsa_raw(*cert, &m, &e)) != GNUTLS_E_SUCCESS) { + logger(Protocol, Error, "%s:%s:%d: Failed to get RSA public key parameters from certificate. GnuTLS error = 0x%02x (%s)\n", + __FILE__, __func__, __LINE__, ret, gnutls_strerror(ret)); + return NULL; + } - return NULL; - } + } else if (algo == GNUTLS_E_UNIMPLEMENTED_FEATURE) { - ret = X509_PUBKEY_get0_param(NULL, NULL, 0, &algor, key); - if (ret != 1) - { - logger(Protocol, Error, - "rdssl_cert_to_key(), failed to get algorithm used for public key"); - rdssl_log_ssl_errors("rdssl_cert_to_key()"); + len = sizeof(data); + if ((ret = gnutls_x509_crt_export(*cert, GNUTLS_X509_FMT_DER, data, &len)) != GNUTLS_E_SUCCESS) { + logger(Protocol, Error, "%s:%s:%d: Failed to encode X.509 certificate to DER. GnuTLS error = 0x%02x (%s)\n", + __FILE__, __func__, __LINE__, ret, gnutls_strerror(ret)); + return NULL; + } - return NULL; - } + /* Validate public key algorithm as OID_SHA_WITH_RSA_SIGNATURE + or OID_MD5_WITH_RSA_SIGNATURE + */ + if ((ret = libtasn_read_cert_pk_oid(data, len, oid, &oid_size)) != 0) { + logger(Protocol, Error, "%s:%s:%d: Failed to get OID of public key algorithm.\n", + __FILE__, __func__, __LINE__); + return NULL; + } - nid = OBJ_obj2nid(algor->algorithm); - - if ((nid == NID_md5WithRSAEncryption) || (nid == NID_shaWithRSAEncryption)) - { -#if OPENSSL_VERSION_NUMBER < 0x10100000L - logger(Protocol, Debug, - "rdssl_cert_to_key(), re-setting algorithm type to RSA in server certificate"); - X509_PUBKEY_set0_param(key, OBJ_nid2obj(NID_rsaEncryption), 0, NULL, NULL, 0); -#else - - if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, NULL, key)) + if (!(strncmp(oid, OID_SHA_WITH_RSA_SIGNATURE, strlen(OID_SHA_WITH_RSA_SIGNATURE)) == 0 + || strncmp(oid, OID_MD5_WITH_RSA_SIGNATURE, strlen(OID_MD5_WITH_RSA_SIGNATURE)) == 0)) { - logger(Protocol, Error, - "rdssl_cert_to_key(), failed to get algorithm used for public key"); - rdssl_log_ssl_errors("rdssl_cert_to_key()"); + logger(Protocol, Error, "%s:%s:%d: Wrong public key algorithm algo = 0x%02x (%s)\n", + __FILE__, __func__, __LINE__, algo, oid); + return NULL; + } + + /* Get public key parameters */ + if ((ret = libtasn_read_cert_pk_parameters(data, len, &m, &e)) != 0) { + logger(Protocol, Error, "%s:%s:%d: Failed to read RSA public key parameters\n", + __FILE__, __func__, __LINE__); return NULL; } - if (!(rsa = d2i_RSAPublicKey(NULL, &p, pklen))) - { - logger(Protocol, Error, - "rdssl_cert_to_key(), failed to extract public key from certificate"); - rdssl_log_ssl_errors("rdssl_cert_to_key()"); - - return NULL; - } - - lkey = RSAPublicKey_dup(rsa); - *key_len = RSA_size(lkey); - return lkey; -#endif - - } - - epk = X509_get_pubkey(cert); - if (NULL == epk) - { - logger(Protocol, Error, - "rdssl_cert_to_key(), failed to extract public key from certificate"); - rdssl_log_ssl_errors("rdssl_cert_to_key()"); - + } else { + logger(Protocol, Error, "%s:%s:%d: Failed to get public key algorithm from certificate. algo = 0x%02x (%d)\n", + __FILE__, __func__, __LINE__, algo, algo); return NULL; } - lkey = RSAPublicKey_dup(EVP_PKEY_get1_RSA(epk)); - EVP_PKEY_free(epk); - *key_len = RSA_size(lkey); - return lkey; + pkey = malloc(sizeof(*pkey)); + + if (!pkey) { + logger(Protocol, Error, "%s:%s:%d: Failed to allocate memory for RSA public key\n", + __FILE__, __func__, __LINE__); + return NULL; + } + + rsa_public_key_init(pkey); + + mpz_import(pkey->n, m.size, 1, sizeof(m.data[0]), 0, 0, m.data); + mpz_import(pkey->e, e.size, 1, sizeof(e.data[0]), 0, 0, e.data); + + rsa_public_key_prepare(pkey); + + *key_len = pkey->size; + + return pkey; } /* returns boolean */ @@ -268,40 +288,52 @@ rdssl_certs_ok(RDSSL_CERT * server_cert, RDSSL_CERT * cacert) int rdssl_cert_print_fp(FILE * fp, RDSSL_CERT * cert) { - return X509_print_fp(fp, cert); + int ret; + gnutls_datum_t cinfo; + + ret = gnutls_x509_crt_print(*cert, GNUTLS_CRT_PRINT_ONELINE, &cinfo); + + if (ret == 0) { + fprintf (fp, "\t%s\n", cinfo.data); + gnutls_free(cinfo.data); + } + + return 0; } void rdssl_rkey_free(RDSSL_RKEY * rkey) { - RSA_free(rkey); + rsa_public_key_clear(rkey); + free(rkey); } +/* Actually we can get rid of this function and use rsa_public)_key in rdssl_rsa_encrypt */ /* returns error */ int rdssl_rkey_get_exp_mod(RDSSL_RKEY * rkey, uint8 * exponent, uint32 max_exp_len, uint8 * modulus, uint32 max_mod_len) { - int len; + size_t outlen; - BIGNUM *e = NULL; - BIGNUM *n = NULL; + // TODO: Check size before exporing + mpz_export(modulus, &outlen, 1, sizeof(uint8), 0, 0, rkey->n); + mpz_export(exponent, &outlen, 1, sizeof(uint8), 0, 0, rkey->e); -#if OPENSSL_VERSION_NUMBER < 0x10100000L - e = rkey->e; - n = rkey->n; -#else - RSA_get0_key(rkey, &n, &e, NULL); -#endif + /* + * Note that gnutls_x509_crt_get_pk_rsa_raw() exports modulus with additional + * zero byte as signed bignum. We can easily import this value using mpz_import() + * After we use mpz_export() on pkey.n (modulus) it will (according to GMP docs) + * export data without sign byte. + * + * This is only important if you get modulus from certificate using GnuTLS, + * save it somewhere, import it into mpz and then export it from the said mpz to some + * buffer. If you then compare initiail (saved) modulus with newly exported one they + * will be different. + * + * On the other hand if we use mpz_t all the way, there will be no such situation. + */ - if ((BN_num_bytes(e) > (int) max_exp_len) || (BN_num_bytes(n) > (int) max_mod_len)) - { - return 1; - } - len = BN_bn2bin(e, exponent); - reverse(exponent, len); - len = BN_bn2bin(n, modulus); - reverse(modulus, len); return 0; } @@ -327,5 +359,9 @@ void rdssl_hmac_md5(const void *key, int key_len, const unsigned char *msg, int msg_len, unsigned char *md) { - HMAC(EVP_md5(), key, key_len, msg, msg_len, md, NULL); + struct hmac_md5_ctx ctx; + + hmac_md5_set_key(&ctx, key_len, key); + hmac_md5_update(&ctx, msg_len, msg); + hmac_md5_digest(&ctx, MD5_DIGEST_SIZE, md); } diff --git a/ssl.h b/ssl.h index b5d27fa..c10f09b 100644 --- a/ssl.h +++ b/ssl.h @@ -4,6 +4,7 @@ Copyright (C) Matthew Chapman 1999-2008 Copyright (C) Jay Sorg 2006-2008 Copyright 2017 Henrik Andersson for Cendio AB + Copyright 2017 Alexander Zakharov 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 @@ -22,25 +23,19 @@ #ifndef _RDSSL_H #define _RDSSL_H -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include -#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090800f) -#define D2I_X509_CONST const -#else -#define D2I_X509_CONST -#endif +#include -#define RDSSL_RC4 RC4_KEY -#define RDSSL_SHA1 SHA_CTX -#define RDSSL_MD5 MD5_CTX -#define RDSSL_CERT X509 -#define RDSSL_RKEY RSA +#define RDSSL_RC4 struct arcfour_ctx +#define RDSSL_SHA1 struct sha1_ctx +#define RDSSL_MD5 struct md5_ctx +#define RDSSL_CERT gnutls_x509_crt_t +#define RDSSL_RKEY struct rsa_public_key void rdssl_sha1_init(RDSSL_SHA1 * sha1); void rdssl_sha1_update(RDSSL_SHA1 * sha1, uint8 * data, uint32 len); @@ -65,5 +60,4 @@ RD_BOOL rdssl_sig_ok(uint8 * exponent, uint32 exp_len, uint8 * modulus, uint32 m void rdssl_hmac_md5(const void *key, int key_len, const unsigned char *msg, int msg_len, unsigned char *md); -void rdssl_log_ssl_errors(const char *prefix); #endif diff --git a/tcp.c b/tcp.c index 044be10..7d29f83 100644 --- a/tcp.c +++ b/tcp.c @@ -3,7 +3,8 @@ Protocol services - TCP layer Copyright (C) Matthew Chapman 1999-2008 Copyright 2005-2011 Peter Astrand for Cendio AB - Copyright 2012-2017 Henrik Andersson for Cendio AB + Copyright 2012-2019 Henrik Andersson for Cendio AB + Copyright 2017 Alexander Zakharov 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 @@ -23,19 +24,24 @@ #include /* select read write close */ #include /* socket connect setsockopt */ #include /* timeval */ +#include #include /* gethostbyname */ #include /* sockaddr_in */ #include /* TCP_NODELAY */ #include /* inet_addr */ #include /* errno */ +#include #endif -#include -#include -#include +#include +#include #include "rdesktop.h" #include "ssl.h" +#include "asn.h" + + +#define CHECK(x) assert((x)>=0) #ifdef _WIN32 #define socklen_t int @@ -66,8 +72,6 @@ struct sockaddr_in *g_server_address = NULL; static char *g_last_server_name = NULL; static RD_BOOL g_ssl_initialized = False; -static SSL *g_ssl = NULL; -static SSL_CTX *g_ssl_ctx = NULL; static int g_sock; static RD_BOOL g_run_ui = False; static struct stream g_in; @@ -79,6 +83,8 @@ extern RD_BOOL g_network_error; extern RD_BOOL g_reconnect_loop; extern char g_tls_version[]; +static gnutls_session_t g_tls_session; + /* wait till socket is ready to write or timeout */ static RD_BOOL tcp_can_send(int sck, int millis) @@ -123,7 +129,6 @@ tcp_init(uint32 maxlen) void tcp_send(STREAM s) { - int ssl_err; int length = s->end - s->data; int sent, total = 0; @@ -133,30 +138,22 @@ tcp_send(STREAM s) #ifdef WITH_SCARD scard_lock(SCARD_LOCK_TCP); #endif + while (total < length) { - if (g_ssl) - { - sent = SSL_write(g_ssl, s->data + total, length - total); - if (sent <= 0) - { - ssl_err = SSL_get_error(g_ssl, sent); - if (sent < 0 && (ssl_err == SSL_ERROR_WANT_READ || - ssl_err == SSL_ERROR_WANT_WRITE)) - { - tcp_can_send(g_sock, 100); - sent = 0; - } - else - { + if (g_ssl_initialized) { + sent = gnutls_record_send(g_tls_session, s->data + total, length - total); + if (sent <= 0) { + if (gnutls_error_is_fatal(sent)) { #ifdef WITH_SCARD scard_unlock(SCARD_LOCK_TCP); #endif - logger(Core, Error, - "tcp_send(), SSL_write() failed with %d: %s", - ssl_err, TCP_STRERROR); + logger(Core, Error, "tcp_send(), gnutls_record_send() failed with %d: %s\n", sent, gnutls_strerror(sent)); g_network_error = True; return; + } else { + tcp_can_send(g_sock, 100); + sent = 0; } } } @@ -194,7 +191,7 @@ STREAM tcp_recv(STREAM s, uint32 length) { uint32 new_length, end_offset, p_offset; - int rcvd = 0, ssl_err; + int rcvd = 0; if (g_network_error == True) return NULL; @@ -227,7 +224,8 @@ tcp_recv(STREAM s, uint32 length) while (length > 0) { - if ((!g_ssl || SSL_pending(g_ssl) <= 0) && g_run_ui) + + if ((!g_ssl_initialized || (gnutls_record_check_pending(g_tls_session) <= 0)) && g_run_ui) { ui_select(g_sock); @@ -237,35 +235,17 @@ tcp_recv(STREAM s, uint32 length) return NULL; } - if (g_ssl) - { - rcvd = SSL_read(g_ssl, s->end, length); - ssl_err = SSL_get_error(g_ssl, rcvd); + if (g_ssl_initialized) { + rcvd = gnutls_record_recv(g_tls_session, s->end, length); - if (ssl_err == SSL_ERROR_SSL) - { - if (SSL_get_shutdown(g_ssl) & SSL_RECEIVED_SHUTDOWN) - { - logger(Core, Error, - "tcp_recv(), remote peer initiated ssl shutdown"); + if (rcvd < 0) { + if (gnutls_error_is_fatal(rcvd)) { + logger(Core, Error, "tcp_recv(), gnutls_record_recv() failed with %d: %s\n", rcvd, gnutls_strerror(rcvd)); + g_network_error = True; return NULL; + } else { + rcvd = 0; } - - rdssl_log_ssl_errors("tcp_recv()"); - g_network_error = True; - return NULL; - } - - if (ssl_err == SSL_ERROR_WANT_READ || ssl_err == SSL_ERROR_WANT_WRITE) - { - rcvd = 0; - } - else if (ssl_err != SSL_ERROR_NONE) - { - logger(Core, Error, "tcp_recv(), SSL_read() failed with %d: %s", - ssl_err, TCP_STRERROR); - g_network_error = True; - return NULL; } } @@ -281,7 +261,7 @@ tcp_recv(STREAM s, uint32 length) else { logger(Core, Error, "tcp_recv(), recv() failed: %s", - TCP_STRERROR); + TCP_STRERROR); g_network_error = True; return NULL; } @@ -300,96 +280,144 @@ tcp_recv(STREAM s, uint32 length) return s; } -/* Establish a SSL/TLS 1.0-1-2 connection */ +/* + * Callback during handshake to verify peer certificate + */ +static int +cert_verify_callback(gnutls_session_t session) +{ + int rv; + int type; + RD_BOOL hostname_mismatch = False; + unsigned int status; + gnutls_x509_crt_t cert; + const gnutls_datum_t *cert_list; + unsigned int cert_list_size; + + /* + * verify certificate against system trust store + */ + rv = gnutls_certificate_verify_peers2(session, &status); + if (rv == GNUTLS_E_SUCCESS) + { + logger(Core, Debug, "%s(), certificate verify status flags: %x", __func__, status); + + if (status == 0) + { + /* get list of certificates */ + cert_list = NULL; + cert_list_size = 0; + + type = gnutls_certificate_type_get(session); + if (type == GNUTLS_CRT_X509) { + cert_list = gnutls_certificate_get_peers(session, &cert_list_size); + } + + if (cert_list_size > 0) + { + /* validate hostname */ + gnutls_x509_crt_init(&cert); + gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER); + if (gnutls_x509_crt_check_hostname(cert, g_last_server_name) != 0) + { + logger(Core, Debug, "%s(), certificate is valid", __func__); + return 0; + } + else + { + logger(Core, Warning, "%s(), certificate hostname mismatch", __func__); + hostname_mismatch = True; + } + } + else + { + logger(Core, Error, "%s(), failed to get certificate list for peers", __func__); + return 1; + } + } + } + + /* + * Use local store as fallback + */ + return utils_cert_handle_exception(session, status, hostname_mismatch, g_last_server_name); +} + +/* Establish a SSL/TLS 1.0 connection */ RD_BOOL tcp_tls_connect(void) { int err; - long options; + int type; + int status; + gnutls_datum_t out; + gnutls_certificate_credentials_t xcred; + + /* Initialize TLS session */ if (!g_ssl_initialized) { - SSL_load_error_strings(); - SSL_library_init(); + gnutls_global_init(); + CHECK(gnutls_init(&g_tls_session, GNUTLS_CLIENT)); g_ssl_initialized = True; } - /* create process context */ - if (g_ssl_ctx == NULL) - { + /* It is recommended to use the default priorities */ + //CHECK(gnutls_set_default_priority(g_tls_session)); + // Use compatible priority to overcome key validation error + // THIS IS TEMPORARY + CHECK(gnutls_priority_set_direct(g_tls_session, "NORMAL:%COMPAT", NULL)); + CHECK(gnutls_certificate_allocate_credentials(&xcred)); + CHECK(gnutls_credentials_set(g_tls_session, GNUTLS_CRD_CERTIFICATE, xcred)); + CHECK(gnutls_certificate_set_x509_system_trust(xcred)); + gnutls_certificate_set_verify_function(xcred, cert_verify_callback); + gnutls_transport_set_int(g_tls_session, g_sock); + gnutls_handshake_set_timeout(g_tls_session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT); - const SSL_METHOD *(*tlsmeth) (void) = NULL; - if (g_tls_version[0] == 0) - tlsmeth = TLSv1_method; - else if (!strcmp(g_tls_version, "1.0")) - tlsmeth = TLSv1_method; - else if (!strcmp(g_tls_version, "1.1")) - tlsmeth = TLSv1_1_method; - else if (!strcmp(g_tls_version, "1.2")) - tlsmeth = TLSv1_2_method; - if (tlsmeth == NULL) + /* Perform the TLS handshake */ + do { + err = gnutls_handshake(g_tls_session); + } while (err < 0 && gnutls_error_is_fatal(err) == 0); + + + if (err < 0) { + + if (err == GNUTLS_E_CERTIFICATE_ERROR) { - logger(Core, Error, - "tcp_tls_connect(), TLS method should be 1.0, 1.1, or 1.2\n"); - goto fail; + logger(Core, Error, "%s(): Certificate error during TLS handshake", __func__); + + /* TODO: Lookup if exit(1) is just plain wrong, its used here to breakout of + fallback code path for connection, eg. if TLS fails, a retry with plain + RDP is made. + */ + exit(1); } - g_ssl_ctx = SSL_CTX_new(tlsmeth()); - if (g_ssl_ctx == NULL) - { - logger(Core, Error, - "tcp_tls_connect(), SSL_CTX_new() failed to create TLS v1.x context\n"); - goto fail; - } + /* Handshake failed with unknown error, lets log */ + logger(Core, Error, "%s(), TLS handshake failed. GnuTLS error: %s", + __func__, gnutls_strerror(err)); - options = 0; -#ifdef SSL_OP_NO_COMPRESSION - options |= SSL_OP_NO_COMPRESSION; -#endif // __SSL_OP_NO_COMPRESSION - options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; - SSL_CTX_set_options(g_ssl_ctx, options); - } - - /* free old connection */ - if (g_ssl) - SSL_free(g_ssl); - - /* create new ssl connection */ - g_ssl = SSL_new(g_ssl_ctx); - if (g_ssl == NULL) - { - logger(Core, Error, "tcp_tls_connect(), SSL_new() failed"); goto fail; - } - if (SSL_set_fd(g_ssl, g_sock) < 1) - { - logger(Core, Error, "tcp_tls_connect(), SSL_set_fd() failed"); - goto fail; - } - - do - { - err = SSL_connect(g_ssl); - } - while (SSL_get_error(g_ssl, err) == SSL_ERROR_WANT_READ); - - if (err < 0) - { - rdssl_log_ssl_errors("tcp_tls_connect()"); - goto fail; + } else { + char *desc; + desc = gnutls_session_get_desc(g_tls_session); + logger(Core, Verbose, "TLS Session info: %s\n", desc); + gnutls_free(desc); } return True; - fail: - if (g_ssl) - SSL_free(g_ssl); - if (g_ssl_ctx) - SSL_CTX_free(g_ssl_ctx); +fail: + + if (g_ssl_initialized) { + gnutls_deinit(g_tls_session); + // Not needed since 3.3.0 + gnutls_global_deinit(); + + g_ssl_initialized = False; + } - g_ssl = NULL; - g_ssl_ctx = NULL; return False; } @@ -397,47 +425,85 @@ tcp_tls_connect(void) RD_BOOL tcp_tls_get_server_pubkey(STREAM s) { - X509 *cert = NULL; - EVP_PKEY *pkey = NULL; + int ret; + unsigned int list_size; + const gnutls_datum_t *cert_list; + gnutls_x509_crt_t cert; + + unsigned int algo, bits; + gnutls_datum_t m, e; + + int pk_size; + uint8_t pk_data[1024]; s->data = s->p = NULL; s->size = 0; - if (g_ssl == NULL) - goto out; + cert_list = gnutls_certificate_get_peers(g_tls_session, &list_size); - cert = SSL_get_peer_certificate(g_ssl); - if (cert == NULL) - { - logger(Core, Error, - "tcp_tls_get_server_pubkey(), SSL_get_peer_certificate() failed"); + if (!cert_list) { + logger(Core, Error, "%s:%s:%d Failed to get peer's certs' list\n", __FILE__, __func__, __LINE__); goto out; } - pkey = X509_get_pubkey(cert); - if (pkey == NULL) - { - logger(Core, Error, "tcp_tls_get_server_pubkey(), X509_get_pubkey() failed"); + if ((ret = gnutls_x509_crt_init(&cert)) != GNUTLS_E_SUCCESS) { + logger(Core, Error, "%s:%s:%d Failed to init certificate structure. GnuTLS error: %s\n", + __FILE__, __func__, __LINE__, gnutls_strerror(ret)); goto out; } - s->size = i2d_PublicKey(pkey, NULL); - if (s->size < 1) - { - logger(Core, Error, "tcp_tls_get_server_pubkey(), i2d_PublicKey() failed"); + if ((ret = gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER)) != GNUTLS_E_SUCCESS) { + logger(Core, Error, "%s:%s:%d Failed to import DER certificate. GnuTLS error:%s\n", + __FILE__, __func__, __LINE__, gnutls_strerror(ret)); goto out; } + algo = gnutls_x509_crt_get_pk_algorithm(cert, &bits); + + if (algo == GNUTLS_PK_RSA) { + if ((ret = gnutls_x509_crt_get_pk_rsa_raw(cert, &m, &e)) != GNUTLS_E_SUCCESS) { + logger(Core, Error, "%s:%s:%d Failed to get RSA public key parameters from certificate. GnuTLS error:%s\n", + __FILE__, __func__, __LINE__, gnutls_strerror(ret)); + goto out; + } + } else { + logger(Core, Error, "%s:%s:%d Peer's certificate public key algorithm is not RSA. GnuTLS error:%s\n", + __FILE__, __func__, __LINE__, gnutls_strerror(algo)); + goto out; + } + + pk_size = sizeof(pk_data); + + /* + * This key will be used further in cssp_connect() for server's key comparison. + * + * Note that we need to encode this RSA public key into PKCS#1 DER + * ATM there's no way to encode/export RSA public key to PKCS#1 using GnuTLS, + * gnutls_pubkey_export() encodes into PKCS#8. So besides fixing GnuTLS + * we can use libtasn1 for encoding. + */ + + if ((ret = write_pkcs1_der_pubkey(&m, &e, pk_data, &pk_size)) != 0) { + logger(Core, Error, "%s:%s:%d Failed to encode RSA public key to PKCS#1 DER\n", + __FILE__, __func__, __LINE__); + goto out; + } + + s->size = pk_size; s->data = s->p = xmalloc(s->size); - i2d_PublicKey(pkey, &s->p); + memcpy((void *)s->data, (void *)pk_data, pk_size); s->p = s->data; s->end = s->p + s->size; - out: - if (cert) - X509_free(cert); - if (pkey) - EVP_PKEY_free(pkey); +out: + if ((e.size != 0) && (e.data)) { + free(e.data); + } + + if ((m.size != 0) && (m.data)) { + free(m.data); + } + return (s->size != 0); } @@ -634,14 +700,13 @@ tcp_disconnect(void) { int i; - if (g_ssl) - { - if (!g_network_error) - (void) SSL_shutdown(g_ssl); - SSL_free(g_ssl); - g_ssl = NULL; - SSL_CTX_free(g_ssl_ctx); - g_ssl_ctx = NULL; + if (g_ssl_initialized) { + (void)gnutls_bye(g_tls_session, GNUTLS_SHUT_WR); + gnutls_deinit(g_tls_session); + // Not needed since 3.3.0 + gnutls_global_deinit(); + + g_ssl_initialized = False; } TCP_CLOSE(g_sock); diff --git a/utils.c b/utils.c index 713cab4..1544355 100644 --- a/utils.c +++ b/utils.c @@ -1,7 +1,7 @@ /* -*- c-basic-offset: 8 -*- rdesktop: A Remote Desktop Protocol client. Generic utility functions - Copyright 2013-2017 Henrik Andersson for Cendio AB + Copyright 2013-2019 Henrik Andersson for Cendio AB 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 @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include "rdesktop.h" @@ -277,11 +279,67 @@ utils_apply_session_size_limitations(uint32 * width, uint32 * height) *height = 200; } +#define MAX_CHOICES 10 +const char * +util_dialog_choice(const char *message, ...) +{ + int i; + va_list ap; + char *p; + const char *choice; + char response[512]; + const char *choices[MAX_CHOICES] = {0}; + + /* gather choices into array */ + va_start(ap, message); + for (i = 0; i < MAX_CHOICES; i++) + { + choices[i] = va_arg(ap, const char *); + if (choices[i] == NULL) + break; + } + va_end(ap); + + choice = NULL; + while (choice == NULL) + { + /* display message */ + fprintf(stderr,"\n%s", message); + + /* read input */ + if (fgets(response, sizeof(response), stdin) != NULL) + { + /* strip final newline */ + p = strchr(response, '\n'); + if (p != NULL) + *p = 0; + + for (i = 0; i < MAX_CHOICES; i++) + { + if (choices[i] == NULL) + break; + + if (strcmp(response, choices[i]) == 0) + { + choice = choices[i]; + break; + } + } + } + else + { + logger(Core, Error, "Failed to read response from stdin"); + break; + } + } + + return choice; +} + /* * component logging * */ -#include static char *level[] = { "debug", @@ -431,3 +489,535 @@ logger_set_subjects(char *subjects) free(pcs); } + +static size_t +_utils_data_to_hex(uint8 *data, size_t len, char *out, size_t size) +{ + size_t i; + char hex[4]; + + assert((len * 2) < size); + + memset(out, 0, size); + for (i = 0; i < len; i++) + { + snprintf(hex, sizeof(hex), "%.2x", data[i]); + strcat(out, hex); + } + + return (len*2); +} + +static size_t +_utils_oid_to_string(const char *oid, char *out, size_t size) +{ + memset(out, 0, size); + if (strcmp(oid, "0.9.2342.19200300.100.1.25") == 0) { + snprintf(out, size, "%s", "DC"); + } + else if (strcmp(oid, "2.5.4.3") == 0) { + snprintf(out, size, "%s", "CN"); + } + else if (strcmp(oid, "1.2.840.113549.1.1.13") == 0) + { + snprintf(out, size, "%s", "sha512WithRSAEncryption"); + } + else + { + snprintf(out, size, "%s", oid); + } + + return strlen(out); +} + +static int +_utils_dn_to_string(gnutls_x509_dn_t dn, RD_BOOL exclude_oid, + char *out, size_t size) +{ + int i, j; + char buf[128] = {0}; + char name[64] = {0}; + char result[1024] = {0}; + size_t left; + gnutls_x509_ava_st ava; + + left = sizeof(result); + + for (j = 0; j < 100; j++) + { + for (i = 0; i < 100; i++) + { + if (gnutls_x509_dn_get_rdn_ava(dn, j, i, &ava) != 0) + { + break; + } + + if (exclude_oid) + { + snprintf(buf, sizeof(buf), "%.*s", ava.value.size, ava.value.data); + strncat(result, buf, left); + left -= strlen(buf); + } + else + { + _utils_oid_to_string((char *)ava.oid.data, name, sizeof(name)); + snprintf(buf, sizeof(buf), "%s%s=%.*s", + (j > 0)?", ":"", name, ava.value.size, ava.value.data); + strncat(result, buf, left); + left -= strlen(buf); + } + } + + if (i == 0) + { + break; + } + } + + snprintf(out, size, "%s", result); + + return 0; +} + +static void +_utils_cert_get_info(gnutls_x509_crt_t cert, char *out, size_t size) +{ + char buf[128]; + size_t buf_size; + char digest[128]; + gnutls_x509_dn_t dn; + time_t expire_ts, activated_ts; + + char subject[256]; + char issuer[256]; + char valid_from[256]; + char valid_to[256]; + char sha1[256]; + char sha256[256]; + + /* get subject */ + gnutls_x509_crt_get_subject(cert, &dn); + if (_utils_dn_to_string(dn, False, buf, sizeof(buf)) == 0) + { + snprintf(subject, sizeof(subject), " Subject: %s", buf); + } + + /* get issuer */ + gnutls_x509_crt_get_issuer(cert, &dn); + if (_utils_dn_to_string(dn, False, buf, sizeof(buf)) == 0) + { + snprintf(issuer, sizeof(issuer), " Issuer: %s", buf); + } + + /* get activation / expiration time */ + activated_ts = gnutls_x509_crt_get_activation_time(cert); + snprintf(valid_from, sizeof(valid_from), " Valid From: %s", ctime(&activated_ts)); + + expire_ts = gnutls_x509_crt_get_expiration_time(cert); + snprintf(valid_to, sizeof(valid_to), " To: %s", ctime(&expire_ts)); + + /* get sha1 / sha256 fingerprint */ + buf_size = sizeof(buf); + gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA1, buf, &buf_size); + _utils_data_to_hex((uint8 *)buf, buf_size, digest, sizeof(digest)); + snprintf(sha1, sizeof(sha1), " sha1: %s", digest); + + buf_size = sizeof(buf); + gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA256, buf, &buf_size); + _utils_data_to_hex((uint8 *)buf, buf_size, digest, sizeof(digest)); + snprintf(sha256, sizeof(sha256), " sha256: %s", digest); + + /* render cert info into out */ + snprintf(out, size, + "%s\n" + "%s\n" + "%s" + "%s" + "\n" + " Certificate fingerprints:\n\n" + "%s\n" + "%s\n", subject, issuer, valid_from, valid_to, sha1, sha256); +} + +static int +_utils_cert_san_to_string(gnutls_x509_crt_t cert, char *out, size_t size) +{ + int i, res; + char entries[1024] = {0}; + char san[128] = {0}; + ssize_t left; + size_t san_size; + unsigned int san_type, critical; + + left = sizeof(entries); + + for(i = 0; i < 50; i++) + { + san_size = sizeof(san); + res = gnutls_x509_crt_get_subject_alt_name2(cert, i, san, &san_size, &san_type, &critical); + + /* break if there are no more SAN entries */ + if (res <= 0) + break; + + /* log if we cant handle more san entires in buffer */ + if (left <= 0) + { + logger(Core, Warning, "%s(), buffer is full, at least one SAN entry is missing from list", __func__); + break; + } + + /* add SAN entry to list */ + switch(san_type) + { + case GNUTLS_SAN_IPADDRESS: + case GNUTLS_SAN_DNSNAME: + + if (left < (ssize_t)sizeof(entries)) + { + strncat(entries, ", ", left); + left -= 2; + } + + strncat(entries, san, left); + left -= strlen(san); + + break; + } + } + + if (strlen(entries) == 0) + { + return 1; + } + snprintf(out, size, "%s", entries); + + return 0; +} + +static void +_utils_cert_get_status_report(gnutls_x509_crt_t cert, unsigned int status, + RD_BOOL hostname_mismatch, const char *hostname, + char *out, size_t size) +{ + int i; + char buf[1024]; + char str[1024 + 64]; + + i = 1; + + if (hostname_mismatch == True) + { + snprintf(buf, sizeof(buf), + " %d. The hostname used for this connection does not match any of the names\n" + " given in the certificate.\n\n" + " Hostname: %s\n" + , i++, hostname); + strncat(out, buf, size - 1); + size -= strlen(buf); + + /* parse subject dn */ + gnutls_x509_dn_t dn; + gnutls_x509_crt_get_subject(cert, &dn); + + memset(buf, 0, sizeof(buf)); + if (_utils_dn_to_string(dn, True, buf, sizeof(buf)) == 0) + { + snprintf(str, sizeof(str), " Common Name: %s\n", buf); + strncat(out, str, size); + size -= strlen(str); + } + + /* get SAN entries */ + if (_utils_cert_san_to_string(cert, buf, sizeof(buf)) == 0) + { + snprintf(str, sizeof(str), " Alternate names: %s\n", buf); + strncat(out, str, size); + size -= strlen(str); + } + + strcat(out, "\n"); + size -= 1; + } + + if (status & GNUTLS_CERT_REVOKED) { + snprintf(buf, sizeof(buf), + " %d. Certificate is revoked by its authority\n\n", i++); + strncat(out, buf, size); + size -= strlen(buf); + } + + if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { + snprintf(buf, sizeof(buf), + " %d. Certificate issuer is not trusted by this system.\n\n", i++); + strncat(out, buf, size); + size -= strlen(buf); + + /* parse subject dn */ + gnutls_x509_dn_t dn; + gnutls_x509_crt_get_issuer(cert, &dn); + + memset(buf, 0, sizeof(buf)); + if (_utils_dn_to_string(dn, False, buf, sizeof(buf)) == 0) + { + snprintf(str, sizeof(str), " Issuer: %s\n", buf); + strncat(out, str, size); + size -= strlen(str); + } + } + + if (status & GNUTLS_CERT_SIGNER_NOT_CA) { + snprintf(buf, sizeof(buf), + " %d. Certificate signer is not a CA.\n\n", i++); + strncat(out, buf, size); + size -= strlen(buf); + } + + if (status & GNUTLS_CERT_INSECURE_ALGORITHM) { + snprintf(buf, sizeof(buf), + " %d. Certificate was signed using an insecure algorithm.\n\n", i++); + strncat(out, buf, size); + size -= strlen(buf); + /* TODO: print algorithm*/ + } + + if (status & GNUTLS_CERT_NOT_ACTIVATED) { + snprintf(buf, sizeof(buf), + " %d. Certificate is not yet activated.\n\n", i++); + strncat(out, buf, size); + size -= strlen(buf); + /* TODO: print activation date */ + } + + if (status & GNUTLS_CERT_EXPIRED) { + snprintf(buf, sizeof(buf), + " %d. Certificate has expired.\n\n", i++); + strncat(out, buf, size); + size -= strlen(buf); + /* TODO: print expiration date */ + } + + if (status & GNUTLS_CERT_SIGNATURE_FAILURE) { + snprintf(buf, sizeof(buf), + " %d. Failed to verify the signature of the certificate.\n\n", i++); + strncat(out, buf, size); + size -= strlen(buf); + } + + if (status & GNUTLS_CERT_REVOCATION_DATA_SUPERSEDED) { + snprintf(buf, sizeof(buf), + " %d. Revocation data are old and have been superseded.\n\n", i++); + strncat(out, buf, size); + size -= strlen(buf); + } + + if (status & GNUTLS_CERT_UNEXPECTED_OWNER) { + snprintf(buf, sizeof(buf), + " %d. The owner is not the expected one.\n\n", i++); + strncat(out, buf, size); + size -= strlen(buf); + } + + if (status & GNUTLS_CERT_REVOCATION_DATA_ISSUED_IN_FUTURE) { + snprintf(buf, sizeof(buf), + " %d. The revocation data have a future issue date.\n\n", i++); + strncat(out, buf, size); + size -= strlen(buf); + } + + if (status & GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE) { + snprintf(buf, sizeof(buf), + " %d. The certificate's signer constraints were violated.\n\n", i++); + strncat(out, buf, size); + size -= strlen(buf); + } + + if (status & GNUTLS_CERT_MISMATCH) { + snprintf(buf, sizeof(buf), + " %d. The certificate presented isn't the expected one (TOFU)\n\n", i++); + strncat(out, buf, size); + size -= strlen(buf); + } + + if (status & GNUTLS_CERT_PURPOSE_MISMATCH) { + snprintf(buf, sizeof(buf), + " %d. The certificate or an intermediate does not match the\n" + " intended purpose (extended key usage).\n\n", i++); + strncat(out, buf, size); + size -= strlen(buf); + } +} + +static int +_utils_cert_store_get_filename(char *out, size_t size) +{ + int rv; + char *home; + char dir[PATH_MAX - 12]; + struct stat sb; + + home = getenv("HOME"); + + if (home == NULL) + return 1; + + if (snprintf(dir, sizeof(dir) - 1, "%s/%s", home, ".local/share/rdesktop/certs/") > (int)sizeof(dir)) + { + logger(Core, Error, "%s(), certificate store directory is truncated", __func__); + return 1; + } + + if ((rv = stat(dir, &sb)) == -1) + { + if (errno == ENOENT) + { + if (rd_certcache_mkdir() == False) { + logger(Core, Error, "%s(), failed to create directory '%s'", dir); + return 1; + } + } + } + else + { + if ((sb.st_mode & S_IFMT) != S_IFDIR) + { + logger(Core, Error, "%s(), %s exists but it's not a directory", + __func__, dir); + return 1; + } + } + + if (snprintf(out, size, "%s/known_certs", dir) > (int)size) + { + logger(Core, Error, "%s(), certificate store filename is truncated"); + return 1; + } + + return 0; +} + +#define TRUST_CERT_PROMPT_TEXT "Do you trust this certificate (yes/no)? " +#define REVIEW_CERT_TEXT \ + "Review the following certificate info before you trust it to be added as an exception.\n" \ + "If you do not trust the certificate the connection atempt will be aborted:" + +int +utils_cert_handle_exception(gnutls_session_t session, unsigned int status, + RD_BOOL hostname_mismatch, const char *hostname) +{ + int rv; + int type; + time_t exp_time; + gnutls_x509_crt_t cert; + const gnutls_datum_t *cert_list; + unsigned int cert_list_size = 0; + + char certcache_fn[PATH_MAX]; + char cert_info[2048] = {0}; + char cert_invalid_reasons[2048] = {0}; + char message[8192] = {0}; + const char *response; + + /* get filename for certificate exception store */ + if (_utils_cert_store_get_filename(certcache_fn, sizeof(certcache_fn)) != 0) + { + logger(Core, Error, "%s(), Failed to get certificate store file, " + "disabling exception handling.", __func__); + return 1; + } + + type = gnutls_certificate_type_get(session); + if (type != GNUTLS_CRT_X509) + { + logger(Core, Error, "%s(), Certificate for session is not an x509 certificate, " + "disabling exception handling.", __func__); + return 1; + } + + + cert_list = gnutls_certificate_get_peers(session, &cert_list_size); + if (cert_list_size == 0) + { + logger(Core, Error, "%s(), Failed to get certificate, " + "disabling exception handling.", __func__); + return 1; + } + + rv = gnutls_verify_stored_pubkey(certcache_fn, NULL, hostname, "rdesktop", type, &cert_list[0], 0); + if (rv == GNUTLS_E_SUCCESS) + { + /* Certificate found in store and matches server */ + logger(Core, Warning, "Certificate received from server is NOT trusted by this system, " + "an exception has been added by the user to trust this specific certificate."); + return 0; + } + else if (rv != GNUTLS_E_CERTIFICATE_KEY_MISMATCH && rv != GNUTLS_E_NO_CERTIFICATE_FOUND) + { + /* Unhandled errors */ + logger(Core, Error, "%s(), verification for host '%s' certificate failed. Error = 0x%x (%s)", + __func__, hostname, rv, gnutls_strerror(rv)); + return 1; + } + + /* + * Give user possibility to add / update certificate to store + */ + + gnutls_x509_crt_init(&cert); + gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER); + _utils_cert_get_info(cert, cert_info, sizeof(cert_info)); + + if (rv == GNUTLS_E_CERTIFICATE_KEY_MISMATCH) + { + /* Certificate from server mismatches the one in store */ + + snprintf(message, sizeof(message), + "ATTENTION! Found a certificate stored for host '%s', but it does not match the certificate\n" + "received from server.\n" + REVIEW_CERT_TEXT + "\n\n" + "%s" + "\n\n" + TRUST_CERT_PROMPT_TEXT + , hostname, cert_info); + + + } + else if (rv == GNUTLS_E_NO_CERTIFICATE_FOUND) + { + /* Certificate is not found in store, propose to add an exception */ + _utils_cert_get_status_report(cert, status, hostname_mismatch, hostname, + cert_invalid_reasons, sizeof(cert_invalid_reasons)); + + snprintf(message, sizeof(message), + "ATTENTION! The server uses and invalid security certificate which can not be trusted for\n" + "the following identified reasons(s);\n\n" + "%s" + "\n" + REVIEW_CERT_TEXT + "\n\n" + "%s" + "\n\n" + TRUST_CERT_PROMPT_TEXT, + cert_invalid_reasons, cert_info); + } + + /* show dialog */ + response = util_dialog_choice(message, "no", "yes", NULL); + if (strcmp(response, "no") == 0 || response == NULL) + { + return 1; + } + + /* user responded with yes, lets add certificate to store */ + logger(Core, Debug, "%s(), adding a new certificate for the host '%s'", __func__, hostname); + exp_time = gnutls_x509_crt_get_expiration_time(cert); + rv = gnutls_store_pubkey(certcache_fn, NULL, hostname, "rdesktop", type, &cert_list[0], exp_time, 0); + if (rv != GNUTLS_E_SUCCESS) + { + logger(Core, Error, "%s(), failed to store certificate. error = 0x%x (%s)", __func__, rv, gnutls_strerror(rv)); + return 1; + } + + return 0; +} diff --git a/utils.h b/utils.h index 0b28212..ab8b633 100644 --- a/utils.h +++ b/utils.h @@ -1,7 +1,7 @@ /* -*- c-basic-offset: 8 -*- rdesktop: A Remote Desktop Protocol client. - Copyright 2017 Henrik Andersson for Cendio AB + Copyright 2017-2019 Henrik Andersson for Cendio AB 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 @@ -20,6 +20,9 @@ #ifndef _utils_h #define _utils_h +#include +#include + #include "types.h" uint32 utils_djb2_hash(const char *str); @@ -33,6 +36,10 @@ void utils_calculate_dpi_scale_factors(uint32 width, uint32 height, uint32 dpi, uint32 * desktopscale, uint32 * devicescale); void utils_apply_session_size_limitations(uint32 * width, uint32 * height); +const char* util_dialog_choice(const char *message, ...); + +int utils_cert_handle_exception(gnutls_session_t session, unsigned int status, + RD_BOOL hostname_mismatch, const char *hostname); typedef enum log_level_t {