Merge pull request #298 from rdesktop/GnuTLS

Replace OpenSSL with GnuTLS Nettle, libtasn1
This commit is contained in:
Henrik Andersson 2019-01-30 17:34:07 +01:00 committed by GitHub
commit fcf3e923ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 3294 additions and 389 deletions

View File

@ -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

213
asn.c
View File

@ -2,6 +2,7 @@
rdesktop: A Remote Desktop Protocol client.
ASN.1 utility functions
Copyright 2012-2017 Henrik Andersson <hean01@cendio.se> for Cendio AB
Copyright 2017 Alexander Zakharov <uglym8@gmail.com>
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 <http://www.gnu.org/licenses/>.
*/
#include "rdesktop.h"
#include <gnutls/gnutls.h>
#include <libtasn1.h>
#include <stdlib.h>
#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;
}

45
asn.h Normal file
View File

@ -0,0 +1,45 @@
/* -*- c-basic-offset: 8 -*-
rdesktop: A Remote Desktop Protocol client.
ASN.1 utility functions header
Copyright 2017 Alexander Zakharov <uglym8@gmail.com>
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 <http://www.gnu.org/licenses/>.
*/
#ifndef _RDASN_H
#define _RDASN_H
#include <gnutls/gnutls.h>
#include <libtasn1.h>
#include <stdint.h>
#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 */

View File

@ -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]))

999
pkix.asn Normal file
View File

@ -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

920
pkix_asn1_tab.c Normal file
View File

@ -0,0 +1,920 @@
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <libtasn1.h>
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 }
};

View File

@ -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);

View File

@ -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)

312
ssl.c
View File

@ -4,6 +4,7 @@
Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
Copyright (C) Jay Sorg <j@american-data.com> 2006-2008
Copyright 2016-2017 Henrik Andersson <hean01@cendio.se> for Cendio AB
Copyright 2017 Alexander Zakharov <uglym8@gmail.com>
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 <gnutls/x509.h>
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)
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;
}
} else if (algo == GNUTLS_E_UNIMPLEMENTED_FEATURE) {
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;
}
/* 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;
}
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 public key from certificate");
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;
}
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()");
} 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;
}
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))
{
logger(Protocol, Error,
"rdssl_cert_to_key(), failed to get algorithm used for public key");
rdssl_log_ssl_errors("rdssl_cert_to_key()");
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;
}
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()");
rsa_public_key_init(pkey);
return NULL;
}
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);
lkey = RSAPublicKey_dup(rsa);
*key_len = RSA_size(lkey);
return lkey;
#endif
rsa_public_key_prepare(pkey);
}
*key_len = pkey->size;
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()");
return NULL;
}
lkey = RSAPublicKey_dup(EVP_PKEY_get1_RSA(epk));
EVP_PKEY_free(epk);
*key_len = RSA_size(lkey);
return lkey;
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);
}

30
ssl.h
View File

@ -4,6 +4,7 @@
Copyright (C) Matthew Chapman 1999-2008
Copyright (C) Jay Sorg 2006-2008
Copyright 2017 Henrik Andersson <hean01@cendio.se> for Cendio AB
Copyright 2017 Alexander Zakharov <uglym8@gmail.com>
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 <openssl/rc4.h>
#include <openssl/md5.h>
#include <openssl/sha.h>
#include <openssl/err.h>
#include <openssl/bn.h>
#include <openssl/x509v3.h>
#include <openssl/hmac.h>
#include <nettle/md5.h>
#include <nettle/sha1.h>
#include <nettle/arcfour.h>
#include <nettle/hmac.h>
#include <nettle/rsa.h>
#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090800f)
#define D2I_X509_CONST const
#else
#define D2I_X509_CONST
#endif
#include <gnutls/x509.h>
#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

369
tcp.c
View File

@ -3,7 +3,8 @@
Protocol services - TCP layer
Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
Copyright 2005-2011 Peter Astrand <astrand@cendio.se> for Cendio AB
Copyright 2012-2017 Henrik Andersson <hean01@cendio.se> for Cendio AB
Copyright 2012-2019 Henrik Andersson <hean01@cendio.se> for Cendio AB
Copyright 2017 Alexander Zakharov <uglym8@gmail.com>
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 <unistd.h> /* select read write close */
#include <sys/socket.h> /* socket connect setsockopt */
#include <sys/time.h> /* timeval */
#include <sys/stat.h>
#include <netdb.h> /* gethostbyname */
#include <netinet/in.h> /* sockaddr_in */
#include <netinet/tcp.h> /* TCP_NODELAY */
#include <arpa/inet.h> /* inet_addr */
#include <errno.h> /* errno */
#include <assert.h>
#endif
#include <openssl/ssl.h>
#include <openssl/x509.h>
#include <openssl/err.h>
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#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");
return NULL;
}
rdssl_log_ssl_errors("tcp_recv()");
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;
}
if (ssl_err == SSL_ERROR_WANT_READ || ssl_err == SSL_ERROR_WANT_WRITE)
{
} else {
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;
}
}
@ -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");
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);
}
/* Handshake failed with unknown error, lets log */
logger(Core, Error, "%s(), TLS handshake failed. GnuTLS error: %s",
__func__, gnutls_strerror(err));
goto fail;
}
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;
}
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);

594
utils.c
View File

@ -1,7 +1,7 @@
/* -*- c-basic-offset: 8 -*-
rdesktop: A Remote Desktop Protocol client.
Generic utility functions
Copyright 2013-2017 Henrik Andersson <hean01@cendio.se> for Cendio AB
Copyright 2013-2019 Henrik Andersson <hean01@cendio.se> 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 <sys/stat.h>
#include <errno.h>
#include <iconv.h>
#include <stdarg.h>
#include <assert.h>
#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 <stdarg.h>
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;
}

View File

@ -1,7 +1,7 @@
/* -*- c-basic-offset: 8 -*-
rdesktop: A Remote Desktop Protocol client.
Copyright 2017 Henrik Andersson <hean01@cendio.se> for Cendio AB
Copyright 2017-2019 Henrik Andersson <hean01@cendio.se> 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 <gnutls/gnutls.h>
#include <gnutls/x509.h>
#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
{