mirror of
https://github.com/OpenVPN/openvpn.git
synced 2026-02-03 20:39:40 -05:00
Resolve merge conflict
This commit is contained in:
commit
6c178b43a3
64 changed files with 386 additions and 2086 deletions
|
|
@ -14,11 +14,11 @@ env:
|
|||
- PREFIX="${HOME}/opt"
|
||||
- TAP_WINDOWS_VERSION=9.21.2
|
||||
- LZO_VERSION=2.10
|
||||
- PKCS11_HELPER_VERSION=1.11
|
||||
- MBEDTLS_VERSION="2.4.0"
|
||||
- PKCS11_HELPER_VERSION=1.22
|
||||
- MBEDTLS_VERSION="2.5.1"
|
||||
- MBEDTLS_CFLAGS="-I${PREFIX}/include"
|
||||
- MBEDTLS_LIBS="-L${PREFIX}/lib -lmbedtls -lmbedx509 -lmbedcrypto"
|
||||
- OPENSSL_VERSION="1.0.2k"
|
||||
- OPENSSL_VERSION="1.0.2l"
|
||||
- OPENSSL_CFLAGS="-I${PREFIX}/include"
|
||||
- OPENSSL_LIBS="-L${PREFIX}/lib -lssl -lcrypto"
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ build_lzo () {
|
|||
download_pkcs11_helper () {
|
||||
if [ ! -f "pkcs11-helper-${PKCS11_HELPER_VERSION}.tar.bz2" ]; then
|
||||
wget -P download-cache/ \
|
||||
"http://downloads.sourceforge.net/project/opensc/pkcs11-helper/pkcs11-helper-${PKCS11_HELPER_VERSION}.tar.bz2"
|
||||
"https://github.com/OpenSC/pkcs11-helper/releases/download/pkcs11-helper-${PKCS11_HELPER_VERSION}/pkcs11-helper-${PKCS11_HELPER_VERSION}.tar.bz2"
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
@ -46,7 +46,11 @@ build_pkcs11_helper () {
|
|||
cd "pkcs11-helper-${PKCS11_HELPER_VERSION}"
|
||||
|
||||
./configure --host=${CHOST} --program-prefix='' --libdir=${PREFIX}/lib \
|
||||
--prefix=${PREFIX} --build=x86_64-pc-linux-gnu --disable-crypto-engine-gnutls --disable-crypto-engine-nss
|
||||
--prefix=${PREFIX} --build=x86_64-pc-linux-gnu \
|
||||
--disable-crypto-engine-gnutls \
|
||||
--disable-crypto-engine-nss \
|
||||
--disable-crypto-engine-polarssl \
|
||||
--disable-crypto-engine-mbedtls
|
||||
make all install
|
||||
)
|
||||
echo "${PKCS11_HELPER_VERSION}" > "${PREFIX}/.pkcs11_helper-version"
|
||||
|
|
|
|||
13
Changes.rst
13
Changes.rst
|
|
@ -44,6 +44,13 @@ ECDH key exchange
|
|||
The TLS control channel now supports for elliptic curve diffie-hellmann
|
||||
key exchange (ECDH).
|
||||
|
||||
Improved Certificate Revocation List (CRL) processing
|
||||
CRLs are now handled by the crypto library (OpenSSL or mbed TLS), instead
|
||||
of inside OpenVPN itself. The crypto library implementations are more
|
||||
strict than the OpenVPN implementation was. This might reject peer
|
||||
certificates that would previously be accepted. If this occurs, OpenVPN
|
||||
will log the crypto library's error description.
|
||||
|
||||
Dualstack round-robin DNS client connect
|
||||
Instead of only using the first address of each ``--remote`` OpenVPN
|
||||
will now try all addresses (IPv6 and IPv4) of a ``--remote`` entry.
|
||||
|
|
@ -160,12 +167,6 @@ Deprecated features
|
|||
will then use ``--key-method 2`` by default. Note that this requires changing
|
||||
the option in both the client and server side configs.
|
||||
|
||||
- CRLs are now handled by the crypto library (OpenSSL or mbed TLS), instead of
|
||||
inside OpenVPN itself. The crypto library implementations are more strict
|
||||
than the OpenVPN implementation was. This might reject peer certificates
|
||||
that would previously be accepted. If this occurs, OpenVPN will log the
|
||||
crypto library's error description.
|
||||
|
||||
- ``--tls-remote`` is removed in 2.4, as indicated in the 2.3 man-pages. Similar
|
||||
functionality is provided via ``--verify-x509-name``, which does the same job in
|
||||
a better way.
|
||||
|
|
|
|||
|
|
@ -668,7 +668,7 @@ AC_FUNC_FORK
|
|||
|
||||
AC_CHECK_FUNCS([ \
|
||||
daemon chroot getpwnam setuid nice system getpid dup dup2 \
|
||||
getpass strerror syslog openlog mlockall getgrnam setgid \
|
||||
getpass syslog openlog mlockall getgrnam setgid \
|
||||
setgroups stat flock readv writev time gettimeofday \
|
||||
ctime memset vsnprintf strdup \
|
||||
setsid chdir putenv getpeername unlink \
|
||||
|
|
@ -925,8 +925,6 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then
|
|||
|
||||
AC_CHECK_FUNCS(
|
||||
[ \
|
||||
EVP_CIPHER_CTX_new \
|
||||
EVP_CIPHER_CTX_free \
|
||||
HMAC_CTX_new \
|
||||
HMAC_CTX_free \
|
||||
HMAC_CTX_reset \
|
||||
|
|
@ -942,6 +940,7 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then
|
|||
EVP_PKEY_id \
|
||||
EVP_PKEY_get0_RSA \
|
||||
EVP_PKEY_get0_DSA \
|
||||
EVP_PKEY_get0_EC_KEY \
|
||||
RSA_set_flags \
|
||||
RSA_bits \
|
||||
RSA_get0_key \
|
||||
|
|
@ -957,6 +956,7 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then
|
|||
RSA_meth_set_init \
|
||||
RSA_meth_set_finish \
|
||||
RSA_meth_set0_app_data \
|
||||
EC_GROUP_order_bits
|
||||
]
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
CFILES = cert_data.c common_osx.c crypto_osx.c main.c
|
||||
OFILES = $(CFILES:.c=.o) ../../src/openvpn/base64.o
|
||||
prog = keychain-mcd
|
||||
|
||||
CC = gcc
|
||||
CFLAGS = -Wall
|
||||
LDFLAGS = -framework CoreFoundation -framework Security -framework CoreServices
|
||||
|
||||
$(prog): $(OFILES)
|
||||
$(CC) $(LDFLAGS) $(OFILES) -o $(prog)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
|
@ -1,866 +0,0 @@
|
|||
/*
|
||||
* OpenVPN -- An application to securely tunnel IP networks
|
||||
* over a single UDP port, with support for SSL/TLS-based
|
||||
* session authentication and key exchange,
|
||||
* packet encryption, packet authentication, and
|
||||
* packet compression.
|
||||
*
|
||||
* Copyright (C) 2010 Brian Raderman <brian@irregularexpression.org>
|
||||
* Copyright (C) 2013-2015 Vasily Kulikov <segoon@openwall.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* 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, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "cert_data.h"
|
||||
#include <CommonCrypto/CommonDigest.h>
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#include "common_osx.h"
|
||||
#include "crypto_osx.h"
|
||||
#include <err.h>
|
||||
|
||||
CFStringRef kCertDataSubjectName = CFSTR("subject"),
|
||||
kCertDataIssuerName = CFSTR("issuer"),
|
||||
kCertDataSha1Name = CFSTR("SHA1"),
|
||||
kCertDataMd5Name = CFSTR("MD5"),
|
||||
kCertDataSerialName = CFSTR("serial"),
|
||||
kCertNameFwdSlash = CFSTR("/"),
|
||||
kCertNameEquals = CFSTR("=");
|
||||
CFStringRef kCertNameOrganization = CFSTR("o"),
|
||||
kCertNameOrganizationalUnit = CFSTR("ou"),
|
||||
kCertNameCountry = CFSTR("c"),
|
||||
kCertNameLocality = CFSTR("l"),
|
||||
kCertNameState = CFSTR("st"),
|
||||
kCertNameCommonName = CFSTR("cn"),
|
||||
kCertNameEmail = CFSTR("e");
|
||||
CFStringRef kStringSpace = CFSTR(" "),
|
||||
kStringEmpty = CFSTR("");
|
||||
|
||||
typedef struct _CertName
|
||||
{
|
||||
CFArrayRef countryName, organization, organizationalUnit, commonName, description, emailAddress,
|
||||
stateName, localityName;
|
||||
} CertName, *CertNameRef;
|
||||
|
||||
typedef struct _DescData
|
||||
{
|
||||
CFStringRef name, value;
|
||||
} DescData, *DescDataRef;
|
||||
|
||||
void destroyDescData(DescDataRef pData);
|
||||
|
||||
CertNameRef
|
||||
createCertName()
|
||||
{
|
||||
CertNameRef pCertName = (CertNameRef)malloc(sizeof(CertName));
|
||||
pCertName->countryName = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
|
||||
pCertName->organization = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
|
||||
pCertName->organizationalUnit = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
|
||||
pCertName->commonName = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
|
||||
pCertName->description = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
|
||||
pCertName->emailAddress = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
|
||||
pCertName->stateName = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
|
||||
pCertName->localityName = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
|
||||
return pCertName;
|
||||
}
|
||||
|
||||
void
|
||||
destroyCertName(CertNameRef pCertName)
|
||||
{
|
||||
if (!pCertName)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CFRelease(pCertName->countryName);
|
||||
CFRelease(pCertName->organization);
|
||||
CFRelease(pCertName->organizationalUnit);
|
||||
CFRelease(pCertName->commonName);
|
||||
CFRelease(pCertName->description);
|
||||
CFRelease(pCertName->emailAddress);
|
||||
CFRelease(pCertName->stateName);
|
||||
CFRelease(pCertName->localityName);
|
||||
free(pCertName);
|
||||
}
|
||||
|
||||
bool
|
||||
CFStringRefCmpCString(CFStringRef cfstr, const char *str)
|
||||
{
|
||||
CFStringRef tmp = CFStringCreateWithCStringNoCopy(NULL, str, kCFStringEncodingUTF8, kCFAllocatorNull);
|
||||
CFComparisonResult cresult = CFStringCompare(cfstr, tmp, 0);
|
||||
bool result = cresult == kCFCompareEqualTo;
|
||||
CFRelease(tmp);
|
||||
return result;
|
||||
}
|
||||
|
||||
CFDateRef
|
||||
GetDateFieldFromCertificate(SecCertificateRef certificate, CFTypeRef oid)
|
||||
{
|
||||
const void *keys[] = { oid };
|
||||
CFDictionaryRef dict = NULL;
|
||||
CFErrorRef error;
|
||||
CFDateRef date = NULL;
|
||||
|
||||
CFArrayRef keySelection = CFArrayCreate(NULL, keys, sizeof(keys)/sizeof(keys[0]), &kCFTypeArrayCallBacks);
|
||||
dict = SecCertificateCopyValues(certificate, keySelection, &error);
|
||||
if (dict == NULL)
|
||||
{
|
||||
printErrorMsg("GetDateFieldFromCertificate: SecCertificateCopyValues", error);
|
||||
goto release_ks;
|
||||
}
|
||||
CFDictionaryRef vals = dict ? CFDictionaryGetValue(dict, oid) : NULL;
|
||||
CFNumberRef vals2 = vals ? CFDictionaryGetValue(vals, kSecPropertyKeyValue) : NULL;
|
||||
if (vals2 == NULL)
|
||||
{
|
||||
goto release_dict;
|
||||
}
|
||||
|
||||
CFAbsoluteTime validityNotBefore;
|
||||
if (CFNumberGetValue(vals2, kCFNumberDoubleType, &validityNotBefore))
|
||||
{
|
||||
date = CFDateCreate(kCFAllocatorDefault,validityNotBefore);
|
||||
}
|
||||
|
||||
release_dict:
|
||||
CFRelease(dict);
|
||||
release_ks:
|
||||
CFRelease(keySelection);
|
||||
return date;
|
||||
}
|
||||
|
||||
CFArrayRef
|
||||
GetFieldsFromCertificate(SecCertificateRef certificate, CFTypeRef oid)
|
||||
{
|
||||
CFMutableArrayRef fields = CFArrayCreateMutable(NULL, 0, NULL);
|
||||
CertNameRef pCertName = createCertName();
|
||||
const void *keys[] = { oid, };
|
||||
CFDictionaryRef dict;
|
||||
CFErrorRef error;
|
||||
|
||||
CFArrayRef keySelection = CFArrayCreate(NULL, keys, 1, NULL);
|
||||
|
||||
dict = SecCertificateCopyValues(certificate, keySelection, &error);
|
||||
if (dict == NULL)
|
||||
{
|
||||
printErrorMsg("GetFieldsFromCertificate: SecCertificateCopyValues", error);
|
||||
CFRelease(keySelection);
|
||||
CFRelease(fields);
|
||||
destroyCertName(pCertName);
|
||||
return NULL;
|
||||
}
|
||||
CFDictionaryRef vals = CFDictionaryGetValue(dict, oid);
|
||||
CFArrayRef vals2 = vals ? CFDictionaryGetValue(vals, kSecPropertyKeyValue) : NULL;
|
||||
if (vals2)
|
||||
{
|
||||
for (int i = 0; i < CFArrayGetCount(vals2); i++) {
|
||||
CFDictionaryRef subDict = CFArrayGetValueAtIndex(vals2, i);
|
||||
CFStringRef label = CFDictionaryGetValue(subDict, kSecPropertyKeyLabel);
|
||||
CFStringRef value = CFDictionaryGetValue(subDict, kSecPropertyKeyValue);
|
||||
|
||||
if (CFStringCompare(label, kSecOIDEmailAddress, 0) == kCFCompareEqualTo)
|
||||
{
|
||||
CFArrayAppendValue((CFMutableArrayRef)pCertName->emailAddress, value);
|
||||
}
|
||||
else if (CFStringCompare(label, kSecOIDCountryName, 0) == kCFCompareEqualTo)
|
||||
{
|
||||
CFArrayAppendValue((CFMutableArrayRef)pCertName->countryName, value);
|
||||
}
|
||||
else if (CFStringCompare(label, kSecOIDOrganizationName, 0) == kCFCompareEqualTo)
|
||||
{
|
||||
CFArrayAppendValue((CFMutableArrayRef)pCertName->organization, value);
|
||||
}
|
||||
else if (CFStringCompare(label, kSecOIDOrganizationalUnitName, 0) == kCFCompareEqualTo)
|
||||
{
|
||||
CFArrayAppendValue((CFMutableArrayRef)pCertName->organizationalUnit, value);
|
||||
}
|
||||
else if (CFStringCompare(label, kSecOIDCommonName, 0) == kCFCompareEqualTo)
|
||||
{
|
||||
CFArrayAppendValue((CFMutableArrayRef)pCertName->commonName, value);
|
||||
}
|
||||
else if (CFStringCompare(label, kSecOIDDescription, 0) == kCFCompareEqualTo)
|
||||
{
|
||||
CFArrayAppendValue((CFMutableArrayRef)pCertName->description, value);
|
||||
}
|
||||
else if (CFStringCompare(label, kSecOIDStateProvinceName, 0) == kCFCompareEqualTo)
|
||||
{
|
||||
CFArrayAppendValue((CFMutableArrayRef)pCertName->stateName, value);
|
||||
}
|
||||
else if (CFStringCompare(label, kSecOIDLocalityName, 0) == kCFCompareEqualTo)
|
||||
{
|
||||
CFArrayAppendValue((CFMutableArrayRef)pCertName->localityName, value);
|
||||
}
|
||||
}
|
||||
CFArrayAppendValue(fields, pCertName);
|
||||
}
|
||||
|
||||
CFRelease(dict);
|
||||
CFRelease(keySelection);
|
||||
return fields;
|
||||
}
|
||||
|
||||
CertDataRef
|
||||
createCertDataFromCertificate(SecCertificateRef certificate)
|
||||
{
|
||||
CertDataRef pCertData = (CertDataRef)malloc(sizeof(CertData));
|
||||
pCertData->subject = GetFieldsFromCertificate(certificate, kSecOIDX509V1SubjectName);
|
||||
pCertData->issuer = GetFieldsFromCertificate(certificate, kSecOIDX509V1IssuerName);
|
||||
|
||||
CFDataRef data = SecCertificateCopyData(certificate);
|
||||
if (data == NULL)
|
||||
{
|
||||
warnx("SecCertificateCopyData() returned NULL");
|
||||
destroyCertData(pCertData);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned char sha1[CC_SHA1_DIGEST_LENGTH];
|
||||
CC_SHA1(CFDataGetBytePtr(data), CFDataGetLength(data), sha1);
|
||||
pCertData->sha1 = createHexString(sha1, CC_SHA1_DIGEST_LENGTH);
|
||||
|
||||
unsigned char md5[CC_MD5_DIGEST_LENGTH];
|
||||
CC_MD5(CFDataGetBytePtr(data), CFDataGetLength(data), md5);
|
||||
pCertData->md5 = createHexString((unsigned char *)md5, CC_MD5_DIGEST_LENGTH);
|
||||
|
||||
CFDataRef serial = SecCertificateCopySerialNumber(certificate, NULL);
|
||||
pCertData->serial = createHexString((unsigned char *)CFDataGetBytePtr(serial), CFDataGetLength(serial));
|
||||
CFRelease(serial);
|
||||
|
||||
return pCertData;
|
||||
}
|
||||
|
||||
CFStringRef
|
||||
stringFromRange(const char *cstring, CFRange range)
|
||||
{
|
||||
CFStringRef str = CFStringCreateWithBytes(NULL, (uint8 *)&cstring[range.location], range.length, kCFStringEncodingUTF8, false);
|
||||
CFMutableStringRef mutableStr = CFStringCreateMutableCopy(NULL, 0, str);
|
||||
CFStringTrimWhitespace(mutableStr);
|
||||
CFRelease(str);
|
||||
return mutableStr;
|
||||
}
|
||||
|
||||
DescDataRef
|
||||
createDescData(const char *description, CFRange nameRange, CFRange valueRange)
|
||||
{
|
||||
DescDataRef pRetVal = (DescDataRef)malloc(sizeof(DescData));
|
||||
|
||||
memset(pRetVal, 0, sizeof(DescData));
|
||||
|
||||
if (nameRange.length > 0)
|
||||
{
|
||||
pRetVal->name = stringFromRange(description, nameRange);
|
||||
}
|
||||
|
||||
if (valueRange.length > 0)
|
||||
{
|
||||
pRetVal->value = stringFromRange(description, valueRange);
|
||||
}
|
||||
|
||||
#if 0
|
||||
fprintf(stderr, "name = '%s', value = '%s'\n",
|
||||
CFStringGetCStringPtr(pRetVal->name, kCFStringEncodingUTF8),
|
||||
CFStringGetCStringPtr(pRetVal->value, kCFStringEncodingUTF8));
|
||||
#endif
|
||||
return pRetVal;
|
||||
}
|
||||
|
||||
void
|
||||
destroyDescData(DescDataRef pData)
|
||||
{
|
||||
if (pData->name)
|
||||
{
|
||||
CFRelease(pData->name);
|
||||
}
|
||||
|
||||
if (pData->value)
|
||||
{
|
||||
CFRelease(pData->value);
|
||||
}
|
||||
|
||||
free(pData);
|
||||
}
|
||||
|
||||
CFArrayRef
|
||||
createDescDataPairs(const char *description)
|
||||
{
|
||||
int numChars = strlen(description);
|
||||
CFRange nameRange, valueRange;
|
||||
DescDataRef pData;
|
||||
CFMutableArrayRef retVal = CFArrayCreateMutable(NULL, 0, NULL);
|
||||
|
||||
int i = 0;
|
||||
|
||||
nameRange = CFRangeMake(0, 0);
|
||||
valueRange = CFRangeMake(0, 0);
|
||||
bool bInValue = false;
|
||||
|
||||
while (i < numChars)
|
||||
{
|
||||
if (!bInValue && (description[i] != ':'))
|
||||
{
|
||||
nameRange.length++;
|
||||
}
|
||||
else if (bInValue && (description[i] != ':'))
|
||||
{
|
||||
valueRange.length++;
|
||||
}
|
||||
else if (!bInValue)
|
||||
{
|
||||
bInValue = true;
|
||||
valueRange.location = i + 1;
|
||||
valueRange.length = 0;
|
||||
}
|
||||
else /*(bInValue) */
|
||||
{
|
||||
bInValue = false;
|
||||
while (description[i] != ' ')
|
||||
{
|
||||
valueRange.length--;
|
||||
i--;
|
||||
}
|
||||
|
||||
pData = createDescData(description, nameRange, valueRange);
|
||||
CFArrayAppendValue(retVal, pData);
|
||||
|
||||
nameRange.location = i + 1;
|
||||
nameRange.length = 0;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
pData = createDescData(description, nameRange, valueRange);
|
||||
CFArrayAppendValue(retVal, pData);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void
|
||||
arrayDestroyDescData(const void *val, void *context)
|
||||
{
|
||||
DescDataRef pData = (DescDataRef) val;
|
||||
destroyDescData(pData);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
parseNameComponent(CFStringRef dn, CFStringRef *pName, CFStringRef *pValue)
|
||||
{
|
||||
CFArrayRef nameStrings = CFStringCreateArrayBySeparatingStrings(NULL, dn, kCertNameEquals);
|
||||
|
||||
*pName = *pValue = NULL;
|
||||
|
||||
if (CFArrayGetCount(nameStrings) != 2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
CFMutableStringRef str;
|
||||
|
||||
str = CFStringCreateMutableCopy(NULL, 0, CFArrayGetValueAtIndex(nameStrings, 0));
|
||||
CFStringTrimWhitespace(str);
|
||||
*pName = str;
|
||||
|
||||
str = CFStringCreateMutableCopy(NULL, 0, CFArrayGetValueAtIndex(nameStrings, 1));
|
||||
CFStringTrimWhitespace(str);
|
||||
*pValue = str;
|
||||
|
||||
CFRelease(nameStrings);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
tryAppendSingleCertField(CertNameRef pCertName, CFArrayRef where, CFStringRef key,
|
||||
CFStringRef name, CFStringRef value)
|
||||
{
|
||||
if (CFStringCompareWithOptions(name, key, CFRangeMake(0, CFStringGetLength(name)), kCFCompareCaseInsensitive)
|
||||
== kCFCompareEqualTo)
|
||||
{
|
||||
CFArrayAppendValue((CFMutableArrayRef)where, value);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
appendCertField(CertNameRef pCert, CFStringRef name, CFStringRef value)
|
||||
{
|
||||
struct {
|
||||
CFArrayRef field;
|
||||
CFStringRef key;
|
||||
} fields[] = {
|
||||
{ pCert->organization, kCertNameOrganization},
|
||||
{ pCert->organizationalUnit, kCertNameOrganizationalUnit},
|
||||
{ pCert->countryName, kCertNameCountry},
|
||||
{ pCert->localityName, kCertNameLocality},
|
||||
{ pCert->stateName, kCertNameState},
|
||||
{ pCert->commonName, kCertNameCommonName},
|
||||
{ pCert->emailAddress, kCertNameEmail},
|
||||
};
|
||||
int i;
|
||||
int ret = 0;
|
||||
|
||||
for (i = 0; i<sizeof(fields)/sizeof(fields[0]); i++)
|
||||
ret += tryAppendSingleCertField(pCert, fields[i].field, fields[i].key, name, value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
parseCertName(CFStringRef nameDesc, CFMutableArrayRef names)
|
||||
{
|
||||
CFArrayRef nameStrings = CFStringCreateArrayBySeparatingStrings(NULL, nameDesc, kCertNameFwdSlash);
|
||||
int count = CFArrayGetCount(nameStrings);
|
||||
int i;
|
||||
int ret = 1;
|
||||
|
||||
CertNameRef pCertName = createCertName();
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
CFMutableStringRef dn = CFStringCreateMutableCopy(NULL, 0, CFArrayGetValueAtIndex(nameStrings, i));
|
||||
CFStringTrimWhitespace(dn);
|
||||
|
||||
CFStringRef name, value;
|
||||
|
||||
if (!parseNameComponent(dn, &name, &value))
|
||||
{
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (!name || !value)
|
||||
{
|
||||
if (name)
|
||||
{
|
||||
CFRelease(name);
|
||||
}
|
||||
|
||||
if (value)
|
||||
{
|
||||
CFRelease(value);
|
||||
}
|
||||
if (name && !value)
|
||||
{
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
CFRelease(dn);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!appendCertField(pCertName, name, value))
|
||||
{
|
||||
ret = 0;
|
||||
}
|
||||
CFRelease(name);
|
||||
CFRelease(value);
|
||||
CFRelease(dn);
|
||||
}
|
||||
|
||||
CFArrayAppendValue(names, pCertName);
|
||||
CFRelease(nameStrings);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
arrayParseDescDataPair(const void *val, void *context)
|
||||
{
|
||||
DescDataRef pDescData = (DescDataRef)val;
|
||||
CertDataRef pCertData = (CertDataRef)context;
|
||||
int ret = 1;
|
||||
|
||||
if (!pDescData->name || !pDescData->value)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CFStringCompareWithOptions(pDescData->name, kCertDataSubjectName, CFRangeMake(0, CFStringGetLength(pDescData->name)), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
|
||||
{
|
||||
ret = parseCertName(pDescData->value, (CFMutableArrayRef)pCertData->subject);
|
||||
}
|
||||
else if (CFStringCompareWithOptions(pDescData->name, kCertDataIssuerName, CFRangeMake(0, CFStringGetLength(pDescData->name)), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
|
||||
{
|
||||
ret = parseCertName(pDescData->value, (CFMutableArrayRef)pCertData->issuer);
|
||||
}
|
||||
else if (CFStringCompareWithOptions(pDescData->name, kCertDataSha1Name, CFRangeMake(0, CFStringGetLength(pDescData->name)), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
|
||||
{
|
||||
pCertData->sha1 = CFRetain(pDescData->value);
|
||||
}
|
||||
else if (CFStringCompareWithOptions(pDescData->name, kCertDataMd5Name, CFRangeMake(0, CFStringGetLength(pDescData->name)), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
|
||||
{
|
||||
pCertData->md5 = CFRetain(pDescData->value);
|
||||
}
|
||||
else if (CFStringCompareWithOptions(pDescData->name, kCertDataSerialName, CFRangeMake(0, CFStringGetLength(pDescData->name)), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
|
||||
{
|
||||
pCertData->serial = CFRetain(pDescData->value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
CertDataRef
|
||||
createCertDataFromString(const char *description)
|
||||
{
|
||||
CertDataRef pCertData = (CertDataRef)malloc(sizeof(CertData));
|
||||
pCertData->subject = CFArrayCreateMutable(NULL, 0, NULL);
|
||||
pCertData->issuer = CFArrayCreateMutable(NULL, 0, NULL);
|
||||
pCertData->sha1 = NULL;
|
||||
pCertData->md5 = NULL;
|
||||
pCertData->serial = NULL;
|
||||
|
||||
CFArrayRef pairs = createDescDataPairs(description);
|
||||
for (int i = 0; i<CFArrayGetCount(pairs); i++)
|
||||
if (!arrayParseDescDataPair(CFArrayGetValueAtIndex(pairs, i), pCertData))
|
||||
{
|
||||
arrayDestroyDescData(pCertData, NULL);
|
||||
CFArrayApplyFunction(pairs, CFRangeMake(0, CFArrayGetCount(pairs)), arrayDestroyDescData, NULL);
|
||||
CFRelease(pairs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CFArrayApplyFunction(pairs, CFRangeMake(0, CFArrayGetCount(pairs)), arrayDestroyDescData, NULL);
|
||||
CFRelease(pairs);
|
||||
return pCertData;
|
||||
}
|
||||
|
||||
void
|
||||
arrayDestroyCertName(const void *val, void *context)
|
||||
{
|
||||
CertNameRef pCertName = (CertNameRef)val;
|
||||
destroyCertName(pCertName);
|
||||
}
|
||||
|
||||
void
|
||||
destroyCertData(CertDataRef pCertData)
|
||||
{
|
||||
if (pCertData->subject)
|
||||
{
|
||||
CFArrayApplyFunction(pCertData->subject, CFRangeMake(0, CFArrayGetCount(pCertData->subject)), arrayDestroyCertName, NULL);
|
||||
CFRelease(pCertData->subject);
|
||||
}
|
||||
|
||||
if (pCertData->issuer)
|
||||
{
|
||||
CFArrayApplyFunction(pCertData->issuer, CFRangeMake(0, CFArrayGetCount(pCertData->issuer)), arrayDestroyCertName, NULL);
|
||||
CFRelease(pCertData->issuer);
|
||||
}
|
||||
|
||||
if (pCertData->sha1)
|
||||
{
|
||||
CFRelease(pCertData->sha1);
|
||||
}
|
||||
|
||||
if (pCertData->md5)
|
||||
{
|
||||
CFRelease(pCertData->md5);
|
||||
}
|
||||
|
||||
if (pCertData->serial)
|
||||
{
|
||||
CFRelease(pCertData->serial);
|
||||
}
|
||||
|
||||
free(pCertData);
|
||||
}
|
||||
|
||||
bool
|
||||
stringArrayMatchesTemplate(CFArrayRef strings, CFArrayRef templateArray)
|
||||
{
|
||||
int templateCount, stringCount, i;
|
||||
|
||||
templateCount = CFArrayGetCount(templateArray);
|
||||
|
||||
if (templateCount > 0)
|
||||
{
|
||||
stringCount = CFArrayGetCount(strings);
|
||||
if (stringCount != templateCount)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < stringCount; i++)
|
||||
{
|
||||
CFStringRef str, template;
|
||||
|
||||
template = (CFStringRef)CFArrayGetValueAtIndex(templateArray, i);
|
||||
str = (CFStringRef)CFArrayGetValueAtIndex(strings, i);
|
||||
|
||||
if (CFStringCompareWithOptions(template, str, CFRangeMake(0, CFStringGetLength(template)), kCFCompareCaseInsensitive) != kCFCompareEqualTo)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
certNameMatchesTemplate(CertNameRef pCertName, CertNameRef pTemplate)
|
||||
{
|
||||
if (!stringArrayMatchesTemplate(pCertName->countryName, pTemplate->countryName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!stringArrayMatchesTemplate(pCertName->organization, pTemplate->organization))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!stringArrayMatchesTemplate(pCertName->organizationalUnit, pTemplate->organizationalUnit))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!stringArrayMatchesTemplate(pCertName->commonName, pTemplate->commonName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!stringArrayMatchesTemplate(pCertName->emailAddress, pTemplate->emailAddress))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!stringArrayMatchesTemplate(pCertName->stateName, pTemplate->stateName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!stringArrayMatchesTemplate(pCertName->localityName, pTemplate->localityName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
certNameArrayMatchesTemplate(CFArrayRef certNameArray, CFArrayRef templateArray)
|
||||
{
|
||||
int templateCount, certCount, i;
|
||||
|
||||
templateCount = CFArrayGetCount(templateArray);
|
||||
|
||||
if (templateCount > 0)
|
||||
{
|
||||
certCount = CFArrayGetCount(certNameArray);
|
||||
if (certCount != templateCount)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < certCount; i++)
|
||||
{
|
||||
CertNameRef pName, pTemplateName;
|
||||
|
||||
pTemplateName = (CertNameRef)CFArrayGetValueAtIndex(templateArray, i);
|
||||
pName = (CertNameRef)CFArrayGetValueAtIndex(certNameArray, i);
|
||||
|
||||
if (!certNameMatchesTemplate(pName, pTemplateName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
hexStringMatchesTemplate(CFStringRef str, CFStringRef template)
|
||||
{
|
||||
if (template)
|
||||
{
|
||||
if (!str)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
CFMutableStringRef strMutable, templateMutable;
|
||||
|
||||
strMutable = CFStringCreateMutableCopy(NULL, 0, str);
|
||||
templateMutable = CFStringCreateMutableCopy(NULL, 0, template);
|
||||
|
||||
CFStringFindAndReplace(strMutable, kStringSpace, kStringEmpty, CFRangeMake(0, CFStringGetLength(strMutable)), 0);
|
||||
CFStringFindAndReplace(templateMutable, kStringSpace, kStringEmpty, CFRangeMake(0, CFStringGetLength(templateMutable)), 0);
|
||||
|
||||
CFComparisonResult result = CFStringCompareWithOptions(templateMutable, strMutable, CFRangeMake(0, CFStringGetLength(templateMutable)), kCFCompareCaseInsensitive);
|
||||
|
||||
CFRelease(strMutable);
|
||||
CFRelease(templateMutable);
|
||||
|
||||
if (result != kCFCompareEqualTo)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
certDataMatchesTemplate(CertDataRef pCertData, CertDataRef pTemplate)
|
||||
{
|
||||
if (!certNameArrayMatchesTemplate(pCertData->subject, pTemplate->subject))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!certNameArrayMatchesTemplate(pCertData->issuer, pTemplate->issuer))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!hexStringMatchesTemplate(pCertData->sha1, pTemplate->sha1))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!hexStringMatchesTemplate(pCertData->md5, pTemplate->md5))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!hexStringMatchesTemplate(pCertData->serial, pTemplate->serial))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
certExpired(SecCertificateRef certificate)
|
||||
{
|
||||
bool result;
|
||||
CFDateRef notAfter = GetDateFieldFromCertificate(certificate, kSecOIDX509V1ValidityNotAfter);
|
||||
CFDateRef notBefore = GetDateFieldFromCertificate(certificate, kSecOIDX509V1ValidityNotBefore);
|
||||
CFDateRef now = CFDateCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent());
|
||||
|
||||
if (!notAfter || !notBefore || !now)
|
||||
{
|
||||
warnx("GetDateFieldFromCertificate() returned NULL");
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (CFDateCompare(notBefore, now, NULL) != kCFCompareLessThan
|
||||
|| CFDateCompare(now, notAfter, NULL) != kCFCompareLessThan)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
CFRelease(notAfter);
|
||||
CFRelease(notBefore);
|
||||
CFRelease(now);
|
||||
return result;
|
||||
}
|
||||
|
||||
SecIdentityRef
|
||||
findIdentity(CertDataRef pCertDataTemplate)
|
||||
{
|
||||
const void *keys[] = {
|
||||
kSecClass,
|
||||
kSecReturnRef,
|
||||
kSecMatchLimit
|
||||
};
|
||||
const void *values[] = {
|
||||
kSecClassIdentity,
|
||||
kCFBooleanTrue,
|
||||
kSecMatchLimitAll
|
||||
};
|
||||
CFArrayRef result = NULL;
|
||||
|
||||
CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values,
|
||||
sizeof(keys) / sizeof(*keys),
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
OSStatus status = SecItemCopyMatching(query, (CFTypeRef *)&result);
|
||||
CFRelease(query);
|
||||
if (status != noErr)
|
||||
{
|
||||
warnx("No identities in keychain found");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SecIdentityRef bestIdentity = NULL;
|
||||
CFDateRef bestNotBeforeDate = NULL;
|
||||
|
||||
for (int i = 0; i<CFArrayGetCount(result); i++)
|
||||
{
|
||||
SecIdentityRef identity = (SecIdentityRef)CFArrayGetValueAtIndex(result, i);
|
||||
if (identity == NULL)
|
||||
{
|
||||
warnx("identity == NULL");
|
||||
continue;
|
||||
}
|
||||
|
||||
SecCertificateRef certificate = NULL;
|
||||
SecIdentityCopyCertificate(identity, &certificate);
|
||||
if (certificate == NULL)
|
||||
{
|
||||
warnx("SecIdentityCopyCertificate() returned NULL");
|
||||
continue;
|
||||
}
|
||||
|
||||
CertDataRef pCertData2 = createCertDataFromCertificate(certificate);
|
||||
if (pCertData2 == NULL)
|
||||
{
|
||||
warnx("createCertDataFromCertificate() returned NULL");
|
||||
goto release_cert;
|
||||
}
|
||||
bool bMatches = certDataMatchesTemplate(pCertData2, pCertDataTemplate);
|
||||
bool bExpired = certExpired(certificate);
|
||||
destroyCertData(pCertData2);
|
||||
|
||||
if (bMatches && !bExpired)
|
||||
{
|
||||
CFDateRef notBeforeDate = GetDateFieldFromCertificate(certificate, kSecOIDX509V1ValidityNotBefore);
|
||||
if (!notBeforeDate)
|
||||
{
|
||||
warnx("GetDateFieldFromCertificate() returned NULL");
|
||||
goto release_cert;
|
||||
}
|
||||
if (bestIdentity == NULL)
|
||||
{
|
||||
CFRetain(identity);
|
||||
bestIdentity = identity;
|
||||
|
||||
bestNotBeforeDate = notBeforeDate;
|
||||
CFRetain(notBeforeDate);
|
||||
}
|
||||
else if (CFDateCompare(bestNotBeforeDate, notBeforeDate, NULL) == kCFCompareLessThan)
|
||||
{
|
||||
CFRelease(bestIdentity);
|
||||
CFRetain(identity);
|
||||
bestIdentity = identity;
|
||||
|
||||
bestNotBeforeDate = notBeforeDate;
|
||||
CFRetain(notBeforeDate);
|
||||
}
|
||||
CFRelease(notBeforeDate);
|
||||
}
|
||||
release_cert:
|
||||
CFRelease(certificate);
|
||||
}
|
||||
CFRelease(result);
|
||||
|
||||
return bestIdentity;
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
* OpenVPN -- An application to securely tunnel IP networks
|
||||
* over a single UDP port, with support for SSL/TLS-based
|
||||
* session authentication and key exchange,
|
||||
* packet encryption, packet authentication, and
|
||||
* packet compression.
|
||||
*
|
||||
* Copyright (C) 2010 Brian Raderman <brian@irregularexpression.org>
|
||||
* Copyright (C) 2013-2015 Vasily Kulikov <segoon@openwall.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* 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, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#ifndef __cert_data_h__
|
||||
#define __cert_data_h__
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <Security/Security.h>
|
||||
|
||||
typedef struct _CertData
|
||||
{
|
||||
CFArrayRef subject;
|
||||
CFArrayRef issuer;
|
||||
CFStringRef serial;
|
||||
CFStringRef md5, sha1;
|
||||
} CertData, *CertDataRef;
|
||||
|
||||
CertDataRef createCertDataFromCertificate(SecCertificateRef certificate);
|
||||
|
||||
CertDataRef createCertDataFromString(const char *description);
|
||||
|
||||
void destroyCertData(CertDataRef pCertData);
|
||||
|
||||
bool certDataMatchesTemplate(CertDataRef pCertData, CertDataRef pTemplate);
|
||||
|
||||
void printCertData(CertDataRef pCertData);
|
||||
|
||||
SecIdentityRef findIdentity(CertDataRef pCertDataTemplate);
|
||||
|
||||
#endif /* ifndef __cert_data_h__ */
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
/*
|
||||
* OpenVPN -- An application to securely tunnel IP networks
|
||||
* over a single UDP port, with support for SSL/TLS-based
|
||||
* session authentication and key exchange,
|
||||
* packet encryption, packet authentication, and
|
||||
* packet compression.
|
||||
*
|
||||
* Copyright (C) 2010 Brian Raderman <brian@irregularexpression.org>
|
||||
* Copyright (C) 2013-2015 Vasily Kulikov <segoon@openwall.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* 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, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
#include "config.h"
|
||||
#include "syshead.h"
|
||||
#include "common.h"
|
||||
#include "buffer.h"
|
||||
#include "error.h"
|
||||
*/
|
||||
|
||||
#include "common_osx.h"
|
||||
#include <err.h>
|
||||
|
||||
void
|
||||
printCFString(CFStringRef str)
|
||||
{
|
||||
CFIndex bufferLength = CFStringGetLength(str) + 1;
|
||||
char *pBuffer = (char *)malloc(sizeof(char) * bufferLength);
|
||||
CFStringGetCString(str, pBuffer, bufferLength, kCFStringEncodingUTF8);
|
||||
warnx("%s\n", pBuffer);
|
||||
free(pBuffer);
|
||||
}
|
||||
|
||||
char *
|
||||
cfstringToCstr(CFStringRef str)
|
||||
{
|
||||
CFIndex bufferLength = CFStringGetLength(str) + 1;
|
||||
char *pBuffer = (char *)malloc(sizeof(char) * bufferLength);
|
||||
CFStringGetCString(str, pBuffer, bufferLength, kCFStringEncodingUTF8);
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
void
|
||||
appendHexChar(CFMutableStringRef str, unsigned char halfByte)
|
||||
{
|
||||
if (halfByte < 10)
|
||||
{
|
||||
CFStringAppendFormat(str, NULL, CFSTR("%d"), halfByte);
|
||||
}
|
||||
else
|
||||
{
|
||||
char tmp[2] = {'A'+halfByte-10, 0};
|
||||
CFStringAppendCString(str, tmp, kCFStringEncodingUTF8);
|
||||
}
|
||||
}
|
||||
|
||||
CFStringRef
|
||||
createHexString(unsigned char *pData, int length)
|
||||
{
|
||||
unsigned char byte, low, high;
|
||||
int i;
|
||||
CFMutableStringRef str = CFStringCreateMutable(NULL, 0);
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
byte = pData[i];
|
||||
low = byte & 0x0F;
|
||||
high = (byte >> 4);
|
||||
|
||||
appendHexChar(str, high);
|
||||
appendHexChar(str, low);
|
||||
|
||||
if (i != (length - 1))
|
||||
{
|
||||
CFStringAppendCString(str, " ", kCFStringEncodingUTF8);
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
void
|
||||
printHex(unsigned char *pData, int length)
|
||||
{
|
||||
CFStringRef hexStr = createHexString(pData, length);
|
||||
printCFString(hexStr);
|
||||
CFRelease(hexStr);
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* OpenVPN -- An application to securely tunnel IP networks
|
||||
* over a single UDP port, with support for SSL/TLS-based
|
||||
* session authentication and key exchange,
|
||||
* packet encryption, packet authentication, and
|
||||
* packet compression.
|
||||
*
|
||||
* Copyright (C) 2010 Brian Raderman <brian@irregularexpression.org>
|
||||
* Copyright (C) 2013-2015 Vasily Kulikov <segoon@openwall.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* 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, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef __common_osx_h__
|
||||
#define __common_osx_h__
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
void printCFString(CFStringRef str);
|
||||
|
||||
char *cfstringToCstr(CFStringRef str);
|
||||
|
||||
CFStringRef createHexString(unsigned char *pData, int length);
|
||||
|
||||
void printHex(unsigned char *pData, int length);
|
||||
|
||||
#endif /*__Common_osx_h__ */
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
/*
|
||||
* OpenVPN -- An application to securely tunnel IP networks
|
||||
* over a single UDP port, with support for SSL/TLS-based
|
||||
* session authentication and key exchange,
|
||||
* packet encryption, packet authentication, and
|
||||
* packet compression.
|
||||
*
|
||||
* Copyright (C) 2010 Brian Raderman <brian@irregularexpression.org>
|
||||
* Copyright (C) 2013-2015 Vasily Kulikov <segoon@openwall.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* 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, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
|
||||
#include <CommonCrypto/CommonDigest.h>
|
||||
#include <Security/SecKey.h>
|
||||
#include <Security/Security.h>
|
||||
|
||||
#include "crypto_osx.h"
|
||||
#include <err.h>
|
||||
|
||||
void
|
||||
printErrorMsg(const char *func, CFErrorRef error)
|
||||
{
|
||||
CFStringRef desc = CFErrorCopyDescription(error);
|
||||
warnx("%s failed: %s", func, CFStringGetCStringPtr(desc, kCFStringEncodingUTF8));
|
||||
CFRelease(desc);
|
||||
}
|
||||
|
||||
void
|
||||
printErrorStatusMsg(const char *func, OSStatus status)
|
||||
{
|
||||
CFStringRef error;
|
||||
error = SecCopyErrorMessageString(status, NULL);
|
||||
if (error)
|
||||
{
|
||||
warnx("%s failed: %s", func, CFStringGetCStringPtr(error, kCFStringEncodingUTF8));
|
||||
CFRelease(error);
|
||||
}
|
||||
else
|
||||
{
|
||||
warnx("%s failed: %X", func, (int)status);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
signData(SecIdentityRef identity, const uint8_t *from, int flen, uint8_t *to, size_t *tlen)
|
||||
{
|
||||
SecKeyRef privateKey = NULL;
|
||||
OSStatus status;
|
||||
|
||||
status = SecIdentityCopyPrivateKey(identity, &privateKey);
|
||||
if (status != noErr)
|
||||
{
|
||||
printErrorStatusMsg("signData: SecIdentityCopyPrivateKey", status);
|
||||
*tlen = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
status = SecKeyRawSign(privateKey, kSecPaddingPKCS1, from, flen, to, tlen);
|
||||
CFRelease(privateKey);
|
||||
if (status != noErr)
|
||||
{
|
||||
printErrorStatusMsg("signData: SecKeyRawSign", status);
|
||||
*tlen = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* OpenVPN -- An application to securely tunnel IP networks
|
||||
* over a single UDP port, with support for SSL/TLS-based
|
||||
* session authentication and key exchange,
|
||||
* packet encryption, packet authentication, and
|
||||
* packet compression.
|
||||
*
|
||||
* Copyright (C) 2010 Brian Raderman <brian@irregularexpression.org>
|
||||
* Copyright (C) 2013-2015 Vasily Kulikov <segoon@openwall.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* 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, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef __crypto_osx_h__
|
||||
#define __crypto_osx_h__
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <Security/Security.h>
|
||||
|
||||
extern OSStatus SecKeyRawSign(
|
||||
SecKeyRef key,
|
||||
SecPadding padding,
|
||||
const uint8_t *dataToSign,
|
||||
size_t dataToSignLen,
|
||||
uint8_t *sig,
|
||||
size_t *sigLen
|
||||
);
|
||||
|
||||
void signData(SecIdentityRef identity, const uint8_t *from, int flen, uint8_t *to, size_t *tlen);
|
||||
|
||||
void printErrorMsg(const char *func, CFErrorRef error);
|
||||
|
||||
#endif /*__crypto_osx_h__ */
|
||||
|
|
@ -1,161 +0,0 @@
|
|||
.TH keychain-mcd 8
|
||||
.SH NAME
|
||||
|
||||
keychain-mcd \- Mac OS X Keychain management daemon for OpenVPN
|
||||
|
||||
.SH SYNOPSIS
|
||||
|
||||
.B keychain-mcd
|
||||
.I identity-template management-server-ip management-server-port
|
||||
[
|
||||
.I password-file
|
||||
]
|
||||
|
||||
.SH DESCRIPTION
|
||||
|
||||
.B keychain-mcd
|
||||
is Mac OS X Keychain management daemon for OpenVPN.
|
||||
It loads the certificate and private key from the Mac OSX Keychain (Mac OSX Only).
|
||||
.B keychain-mcd
|
||||
connects to OpenVPN via management interface and handles
|
||||
certificate and private key commands (namely
|
||||
.B NEED-CERTIFICATE
|
||||
and
|
||||
.B RSA-SIGN
|
||||
commands).
|
||||
|
||||
.B keychain-mcd
|
||||
makes it possible to use any smart card supported by Mac OSX using the tokend interface, but also any
|
||||
kind of certificate, residing in the Keychain, where you have access to
|
||||
the private key. This option has been tested on the client side with an Aladdin eToken
|
||||
on Mac OSX Leopard and with software certificates stored in the Keychain on Mac OS X.
|
||||
|
||||
Note that Mac OS X might need to present the user with an authentication GUI when the Keychain
|
||||
is accessed by keychain-mcd.
|
||||
|
||||
Use
|
||||
.B keychain-mcd
|
||||
along with
|
||||
.B --management-external-key
|
||||
and/or
|
||||
.B --management-external-cert
|
||||
passed to
|
||||
.B openvpn.
|
||||
|
||||
.SH OPTIONS
|
||||
|
||||
.TP
|
||||
.BR identity-template
|
||||
|
||||
A select string which is used to choose a keychain identity from
|
||||
Mac OS X Keychain or
|
||||
.I auto
|
||||
if the identity template is passed from openvpn.
|
||||
|
||||
\fBSubject\fR, \fBIssuer\fR, \fBSerial\fR, \fBSHA1\fR, \fBMD5\fR selectors can be used.
|
||||
|
||||
To select a certificate based on a string search in the
|
||||
certificate's subject and/or issuer:
|
||||
|
||||
.nf
|
||||
|
||||
"SUBJECT:c=US/o=Apple Inc./ou=me.com/cn=username ISSUER:c=US/o=Apple Computer, Inc./ou=Apple Computer Certificate Authority/cn=Apple .Mac Certificate Authority"
|
||||
|
||||
.fi
|
||||
|
||||
.I "Distinguished Name Component Abbreviations:"
|
||||
.br
|
||||
o = organization
|
||||
.br
|
||||
ou = organizational unit
|
||||
.br
|
||||
c = country
|
||||
.br
|
||||
l = locality
|
||||
.br
|
||||
st = state
|
||||
.br
|
||||
cn = common name
|
||||
.br
|
||||
e = email
|
||||
.br
|
||||
|
||||
All of the distinguished name components are optional, although you do need to specify at least one of them. You can
|
||||
add spaces around the '/' and '=' characters, e.g. "SUBJECT: c = US / o = Apple Inc.". You do not need to specify
|
||||
both the subject and the issuer, one or the other will work fine.
|
||||
The identity searching algorithm will return the
|
||||
certificate it finds that matches all of the criteria you have specified.
|
||||
If there are several certificates matching all of the criteria then the youngest certificate is returned
|
||||
(i.e. with the greater "not before" validity field).
|
||||
You can also include the MD5 and/or SHA1 thumbprints and/or serial number
|
||||
along with the subject and issuer.
|
||||
|
||||
To select a certificate based on certificate's MD5 or SHA1 thumbprint:
|
||||
|
||||
.nf
|
||||
"SHA1: 30 F7 3A 7A B7 73 2A 98 54 33 4A A7 00 6F 6E AC EC D1 EF 02"
|
||||
|
||||
"MD5: D5 F5 11 F1 38 EB 5F 4D CF 23 B6 94 E8 33 D8 B5"
|
||||
.fi
|
||||
|
||||
Again, you can include both the SHA1 and the MD5 thumbprints, but you can also use just one of them.
|
||||
The thumbprint hex strings can easily be copy-and-pasted from the OSX Keychain Access GUI in the Applications/Utilities folder.
|
||||
The hex string comparison is not case sensitive.
|
||||
|
||||
To select a certificate based on certificate's serial number:
|
||||
|
||||
"Serial: 3E 9B 6F 02 00 00 00 01 1F 20"
|
||||
|
||||
If
|
||||
.BR identity-template
|
||||
equals to
|
||||
.I auto
|
||||
then the actual identity template is
|
||||
obtained from argument of NEED-CERTIFICATE notification of openvpn.
|
||||
In this case the argument of NEED-CERTIFICATE must begin with 'macosx-keychain:' prefix
|
||||
and the rest of it must contain the actual identity template in the format described above.
|
||||
|
||||
|
||||
.TP
|
||||
.BR management-server-ip
|
||||
OpenVPN management IP to connect to.
|
||||
Both IPv4 and IPv6 addresses can be used.
|
||||
|
||||
.TP
|
||||
.BR management-server-port
|
||||
OpenVPN management port to connect to.
|
||||
Use
|
||||
.B unix
|
||||
for
|
||||
.I management-server-port
|
||||
and socket path for
|
||||
.I management-server-ip
|
||||
to connect to a local unix socket.
|
||||
|
||||
.TP
|
||||
.BR password-file
|
||||
|
||||
Password file containing the management password on first line.
|
||||
The password will be used to connect to
|
||||
.B openvpn
|
||||
management interface.
|
||||
|
||||
Pass
|
||||
.I password-file
|
||||
to
|
||||
.B keychain-mcd
|
||||
if
|
||||
.I pw-file
|
||||
was specified in
|
||||
.B --management
|
||||
option to
|
||||
.B openvpn.
|
||||
|
||||
|
||||
.SH AUTHOR
|
||||
|
||||
Vasily Kulikov <segoon@openwall.com>
|
||||
|
||||
.SH "SEE ALSO"
|
||||
|
||||
.BR openvpn (8)
|
||||
|
|
@ -1,310 +0,0 @@
|
|||
/*
|
||||
* OpenVPN -- An application to securely tunnel IP networks
|
||||
* over a single UDP port, with support for SSL/TLS-based
|
||||
* session authentication and key exchange,
|
||||
* packet encryption, packet authentication, and
|
||||
* packet compression.
|
||||
*
|
||||
* Copyright (C) 2015 Vasily Kulikov <segoon@openwall.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* 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, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/un.h>
|
||||
#include <err.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <Security/Security.h>
|
||||
#include <CoreServices/CoreServices.h>
|
||||
|
||||
#include "cert_data.h"
|
||||
#include "crypto_osx.h"
|
||||
#include "../../src/openvpn/base64.h"
|
||||
|
||||
|
||||
SecIdentityRef
|
||||
template_to_identity(const char *template)
|
||||
{
|
||||
SecIdentityRef identity;
|
||||
CertDataRef pCertDataTemplate = createCertDataFromString(template);
|
||||
if (pCertDataTemplate == NULL)
|
||||
{
|
||||
errx(1, "Bad certificate template");
|
||||
}
|
||||
identity = findIdentity(pCertDataTemplate);
|
||||
if (identity == NULL)
|
||||
{
|
||||
errx(1, "No such identify");
|
||||
}
|
||||
fprintf(stderr, "Identity found\n");
|
||||
destroyCertData(pCertDataTemplate);
|
||||
return identity;
|
||||
}
|
||||
|
||||
int
|
||||
connect_to_management_server(const char *ip, const char *port)
|
||||
{
|
||||
int fd;
|
||||
struct sockaddr_un addr_un;
|
||||
struct sockaddr *addr;
|
||||
size_t addr_len;
|
||||
|
||||
if (strcmp(port, "unix") == 0)
|
||||
{
|
||||
addr = (struct sockaddr *)&addr_un;
|
||||
addr_len = sizeof(addr_un);
|
||||
|
||||
addr_un.sun_family = AF_UNIX;
|
||||
strncpy(addr_un.sun_path, ip, sizeof(addr_un.sun_path));
|
||||
fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
int rv;
|
||||
struct addrinfo *result;
|
||||
struct addrinfo hints;
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
rv = getaddrinfo(ip, port, &hints, &result);
|
||||
if (rv < 0)
|
||||
{
|
||||
errx(1, "getaddrinfo: %s", gai_strerror(rv));
|
||||
}
|
||||
if (result == NULL)
|
||||
{
|
||||
errx(1, "getaddrinfo returned 0 addressed");
|
||||
}
|
||||
|
||||
/* Use the first found address */
|
||||
fd = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
|
||||
addr = result->ai_addr;
|
||||
addr_len = result->ai_addrlen;
|
||||
}
|
||||
if (fd < 0)
|
||||
{
|
||||
err(1, "socket");
|
||||
}
|
||||
|
||||
if (connect(fd, addr, addr_len) < 0)
|
||||
{
|
||||
err(1, "connect");
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int
|
||||
is_prefix(const char *s, const char *prefix)
|
||||
{
|
||||
return strncmp(s, prefix, strlen(prefix)) == 0;
|
||||
}
|
||||
|
||||
void
|
||||
handle_rsasign(FILE *man_file, SecIdentityRef identity, const char *input)
|
||||
{
|
||||
const char *input_b64 = strchr(input, ':') + 1;
|
||||
char *input_binary;
|
||||
int input_len;
|
||||
char *output_binary;
|
||||
size_t output_len;
|
||||
char *output_b64;
|
||||
|
||||
input_len = strlen(input_b64)*8/6 + 4;
|
||||
input_binary = malloc(input_len);
|
||||
input_len = openvpn_base64_decode(input_b64, input_binary, input_len);
|
||||
if (input_len < 0)
|
||||
{
|
||||
errx(1, "openvpn_base64_decode: overflow");
|
||||
}
|
||||
|
||||
output_len = 1024;
|
||||
output_binary = malloc(output_len);
|
||||
signData(identity, (const uint8_t *)input_binary, input_len, (uint8_t *)output_binary, &output_len);
|
||||
if (output_len == 0)
|
||||
{
|
||||
errx(1, "handle_rsasign: failed to sign data");
|
||||
}
|
||||
|
||||
openvpn_base64_encode(output_binary, output_len, &output_b64);
|
||||
fprintf(man_file, "rsa-sig\n%s\nEND\n", output_b64);
|
||||
free(output_b64);
|
||||
free(input_binary);
|
||||
free(output_binary);
|
||||
|
||||
fprintf(stderr, "Handled RSA_SIGN command\n");
|
||||
}
|
||||
|
||||
void
|
||||
handle_needcertificate(FILE *man_file, SecIdentityRef identity)
|
||||
{
|
||||
OSStatus status;
|
||||
SecCertificateRef certificate = NULL;
|
||||
CFDataRef data;
|
||||
const unsigned char *cert;
|
||||
size_t cert_len;
|
||||
char *result_b64, *tmp_b64;
|
||||
|
||||
status = SecIdentityCopyCertificate(identity, &certificate);
|
||||
if (status != noErr)
|
||||
{
|
||||
const char *msg = GetMacOSStatusErrorString(status);
|
||||
err(1, "SecIdentityCopyCertificate() failed: %s", msg);
|
||||
}
|
||||
|
||||
data = SecCertificateCopyData(certificate);
|
||||
if (data == NULL)
|
||||
{
|
||||
err(1, "SecCertificateCopyData() returned NULL");
|
||||
}
|
||||
|
||||
cert = CFDataGetBytePtr(data);
|
||||
cert_len = CFDataGetLength(data);
|
||||
|
||||
openvpn_base64_encode(cert, cert_len, &result_b64);
|
||||
#if 0
|
||||
fprintf(stderr, "certificate %s\n", result_b64);
|
||||
#endif
|
||||
|
||||
fprintf(man_file, "certificate\n");
|
||||
fprintf(man_file, "-----BEGIN CERTIFICATE-----\n");
|
||||
tmp_b64 = result_b64;
|
||||
while (strlen(tmp_b64) > 64) {
|
||||
fprintf(man_file, "%.64s\n", tmp_b64);
|
||||
tmp_b64 += 64;
|
||||
}
|
||||
if (*tmp_b64)
|
||||
{
|
||||
fprintf(man_file, "%s\n", tmp_b64);
|
||||
}
|
||||
fprintf(man_file, "-----END CERTIFICATE-----\n");
|
||||
fprintf(man_file, "END\n");
|
||||
|
||||
free(result_b64);
|
||||
CFRelease(data);
|
||||
CFRelease(certificate);
|
||||
|
||||
fprintf(stderr, "Handled NEED 'cert' command\n");
|
||||
}
|
||||
|
||||
void
|
||||
management_loop(SecIdentityRef identity, int man_fd, const char *password)
|
||||
{
|
||||
char *buffer = NULL;
|
||||
size_t buffer_len = 0;
|
||||
FILE *man = fdopen(man_fd, "w+");
|
||||
if (man == 0)
|
||||
{
|
||||
err(1, "fdopen");
|
||||
}
|
||||
|
||||
if (password)
|
||||
{
|
||||
fprintf(man, "%s\n", password);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (getline(&buffer, &buffer_len, man) < 0)
|
||||
{
|
||||
err(1, "getline");
|
||||
}
|
||||
#if 0
|
||||
fprintf(stderr, "M: %s", buffer);
|
||||
#endif
|
||||
|
||||
if (is_prefix(buffer, ">RSA_SIGN:"))
|
||||
{
|
||||
handle_rsasign(man, identity, buffer);
|
||||
}
|
||||
if (is_prefix(buffer, ">NEED-CERTIFICATE"))
|
||||
{
|
||||
if (!identity)
|
||||
{
|
||||
const char prefix[] = ">NEED-CERTIFICATE:macosx-keychain:";
|
||||
if (!is_prefix(buffer, prefix))
|
||||
{
|
||||
errx(1, "No identity template is passed via command line and " \
|
||||
"NEED-CERTIFICATE management interface command " \
|
||||
"misses 'macosx-keychain' prefix.");
|
||||
}
|
||||
identity = template_to_identity(buffer+strlen(prefix));
|
||||
}
|
||||
handle_needcertificate(man, identity);
|
||||
}
|
||||
if (is_prefix(buffer, ">FATAL"))
|
||||
{
|
||||
fprintf(stderr, "Fatal message from OpenVPN: %s\n", buffer+7);
|
||||
}
|
||||
if (is_prefix(buffer, ">INFO"))
|
||||
{
|
||||
fprintf(stderr, "INFO message from OpenVPN: %s\n", buffer+6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
read_password(const char *fname)
|
||||
{
|
||||
char *password = NULL;
|
||||
FILE *pwf = fopen(fname, "r");
|
||||
size_t n = 0;
|
||||
|
||||
if (pwf == NULL)
|
||||
{
|
||||
errx(1, "fopen(%s) failed", fname);
|
||||
}
|
||||
if (getline(&password, &n, pwf) < 0)
|
||||
{
|
||||
err(1, "getline");
|
||||
}
|
||||
fclose(pwf);
|
||||
return password;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 4)
|
||||
{
|
||||
err(1, "usage: %s <identity_template> <management_ip> <management_port> [<pw-file>]", argv[0]);
|
||||
}
|
||||
|
||||
char *identity_template = argv[1];
|
||||
char *s_ip = argv[2];
|
||||
char *s_port = argv[3];
|
||||
char *password = NULL;
|
||||
int man_fd;
|
||||
|
||||
if (argc > 4)
|
||||
{
|
||||
char *s_pw_file = argv[4];
|
||||
password = read_password(s_pw_file);
|
||||
}
|
||||
|
||||
SecIdentityRef identity = NULL;
|
||||
if (strcmp(identity_template, "auto"))
|
||||
{
|
||||
identity = template_to_identity(identity_template);
|
||||
}
|
||||
man_fd = connect_to_management_server(s_ip, s_port);
|
||||
fprintf(stderr, "Successfully connected to openvpn\n");
|
||||
|
||||
management_loop(identity, man_fd, password);
|
||||
}
|
||||
|
|
@ -36,6 +36,7 @@
|
|||
#include "syshead.h"
|
||||
|
||||
#include "argv.h"
|
||||
#include "integer.h"
|
||||
#include "options.h"
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ buf_assign(struct buffer *dest, const struct buffer *src)
|
|||
}
|
||||
|
||||
struct buffer
|
||||
clear_buf()
|
||||
clear_buf(void)
|
||||
{
|
||||
struct buffer buf;
|
||||
CLEAR(buf);
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ struct _query_user query_user[QUERY_USER_NUMSLOTS]; /* GLOBAL */
|
|||
|
||||
|
||||
void
|
||||
query_user_clear()
|
||||
query_user_clear(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ extern struct _query_user query_user[]; /**< Global variable, declared in conso
|
|||
* Wipes all data put into all of the query_user structs
|
||||
*
|
||||
*/
|
||||
void query_user_clear();
|
||||
void query_user_clear(void);
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -72,7 +72,7 @@ void query_user_add(char *prompt, size_t prompt_len,
|
|||
*
|
||||
* @return True if executing all the defined steps completed successfully
|
||||
*/
|
||||
bool query_user_exec_builtin();
|
||||
bool query_user_exec_builtin(void);
|
||||
|
||||
|
||||
#if defined(ENABLE_SYSTEMD)
|
||||
|
|
@ -83,7 +83,7 @@ bool query_user_exec_builtin();
|
|||
*
|
||||
* @return True if executing all the defined steps completed successfully
|
||||
*/
|
||||
bool query_user_exec();
|
||||
bool query_user_exec(void);
|
||||
|
||||
#else /* ENABLE_SYSTEMD not defined*/
|
||||
/**
|
||||
|
|
@ -92,7 +92,7 @@ bool query_user_exec();
|
|||
*
|
||||
*/
|
||||
static bool
|
||||
query_user_exec()
|
||||
query_user_exec(void)
|
||||
{
|
||||
return query_user_exec_builtin();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@ get_console_input(const char *prompt, const bool echo, char *input, const int ca
|
|||
*
|
||||
*/
|
||||
bool
|
||||
query_user_exec_builtin()
|
||||
query_user_exec_builtin(void)
|
||||
{
|
||||
bool ret = true; /* Presume everything goes okay */
|
||||
int i;
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@
|
|||
*/
|
||||
|
||||
static bool
|
||||
check_systemd_running()
|
||||
check_systemd_running(void)
|
||||
{
|
||||
struct stat c;
|
||||
|
||||
|
|
@ -96,7 +96,7 @@ get_console_input_systemd(const char *prompt, const bool echo, char *input, cons
|
|||
*
|
||||
*/
|
||||
bool
|
||||
query_user_exec()
|
||||
query_user_exec(void)
|
||||
{
|
||||
bool ret = true; /* Presume everything goes okay */
|
||||
int i;
|
||||
|
|
|
|||
|
|
@ -820,7 +820,7 @@ init_key_type(struct key_type *kt, const char *ciphername,
|
|||
|
||||
/* given a key and key_type, build a key_ctx */
|
||||
void
|
||||
init_key_ctx(struct key_ctx *ctx, struct key *key,
|
||||
init_key_ctx(struct key_ctx *ctx, const struct key *key,
|
||||
const struct key_type *kt, int enc,
|
||||
const char *prefix)
|
||||
{
|
||||
|
|
@ -1261,7 +1261,7 @@ read_key_file(struct key2 *key2, const char *file, const unsigned int flags)
|
|||
fd = platform_open(file, O_RDONLY, 0);
|
||||
if (fd == -1)
|
||||
{
|
||||
msg(M_ERR, "Cannot open file key file '%s'", file);
|
||||
msg(M_ERR, "Cannot open key file '%s'", file);
|
||||
}
|
||||
size = platform_read(fd, in.data, in.capacity);
|
||||
if (size < 0)
|
||||
|
|
@ -1693,7 +1693,7 @@ static int nonce_secret_len = 0; /* GLOBAL */
|
|||
|
||||
/* Reset the nonce value, also done periodically to refresh entropy */
|
||||
static void
|
||||
prng_reset_nonce()
|
||||
prng_reset_nonce(void)
|
||||
{
|
||||
const int size = md_kt_size(nonce_md) + nonce_secret_len;
|
||||
#if 1 /* Must be 1 for real usage */
|
||||
|
|
@ -1772,7 +1772,7 @@ prng_bytes(uint8_t *output, int len)
|
|||
|
||||
/* an analogue to the random() function, but use prng_bytes */
|
||||
long int
|
||||
get_random()
|
||||
get_random(void)
|
||||
{
|
||||
long int l;
|
||||
prng_bytes((unsigned char *)&l, sizeof(l));
|
||||
|
|
|
|||
|
|
@ -312,7 +312,7 @@ void init_key_type(struct key_type *kt, const char *ciphername,
|
|||
* Key context functions
|
||||
*/
|
||||
|
||||
void init_key_ctx(struct key_ctx *ctx, struct key *key,
|
||||
void init_key_ctx(struct key_ctx *ctx, const struct key *key,
|
||||
const struct key_type *kt, int enc,
|
||||
const char *prefix);
|
||||
|
||||
|
|
@ -453,7 +453,7 @@ void prng_init(const char *md_name, const int nonce_secret_len_parm);
|
|||
*/
|
||||
void prng_bytes(uint8_t *output, int len);
|
||||
|
||||
void prng_uninit();
|
||||
void prng_uninit(void);
|
||||
|
||||
void test_crypto(struct crypto_options *co, struct frame *f);
|
||||
|
||||
|
|
|
|||
|
|
@ -323,7 +323,7 @@ void cipher_ctx_free(cipher_ctx_t *ctx);
|
|||
* @param enc Whether to encrypt or decrypt (either
|
||||
* \c MBEDTLS_OP_ENCRYPT or \c MBEDTLS_OP_DECRYPT).
|
||||
*/
|
||||
void cipher_ctx_init(cipher_ctx_t *ctx, uint8_t *key, int key_len,
|
||||
void cipher_ctx_init(cipher_ctx_t *ctx, const uint8_t *key, int key_len,
|
||||
const cipher_kt_t *kt, int enc);
|
||||
|
||||
/**
|
||||
|
|
@ -391,7 +391,7 @@ const cipher_kt_t *cipher_ctx_get_cipher_kt(const cipher_ctx_t *ctx);
|
|||
*
|
||||
* @return \c 0 on failure, \c 1 on success.
|
||||
*/
|
||||
int cipher_ctx_reset(cipher_ctx_t *ctx, uint8_t *iv_buf);
|
||||
int cipher_ctx_reset(cipher_ctx_t *ctx, const uint8_t *iv_buf);
|
||||
|
||||
/**
|
||||
* Updates the given cipher context, providing additional data (AD) for
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ print_cipher(const cipher_kt_t *info)
|
|||
}
|
||||
|
||||
void
|
||||
show_available_ciphers()
|
||||
show_available_ciphers(void)
|
||||
{
|
||||
const int *ciphers = mbedtls_cipher_list();
|
||||
|
||||
|
|
@ -196,7 +196,7 @@ show_available_ciphers()
|
|||
}
|
||||
|
||||
void
|
||||
show_available_digests()
|
||||
show_available_digests(void)
|
||||
{
|
||||
const int *digests = mbedtls_md_list();
|
||||
|
||||
|
|
@ -223,7 +223,7 @@ show_available_digests()
|
|||
}
|
||||
|
||||
void
|
||||
show_available_engines()
|
||||
show_available_engines(void)
|
||||
{
|
||||
printf("Sorry, mbed TLS hardware crypto engine functionality is not "
|
||||
"available\n");
|
||||
|
|
@ -243,7 +243,7 @@ show_available_engines()
|
|||
* entropy gathering function.
|
||||
*/
|
||||
mbedtls_ctr_drbg_context *
|
||||
rand_ctx_get()
|
||||
rand_ctx_get(void)
|
||||
{
|
||||
static mbedtls_entropy_context ec = {0};
|
||||
static mbedtls_ctr_drbg_context cd_ctx = {0};
|
||||
|
|
@ -280,7 +280,7 @@ rand_ctx_get()
|
|||
|
||||
#ifdef ENABLE_PREDICTION_RESISTANCE
|
||||
void
|
||||
rand_ctx_enable_prediction_resistance()
|
||||
rand_ctx_enable_prediction_resistance(void)
|
||||
{
|
||||
mbedtls_ctr_drbg_context *cd_ctx = rand_ctx_get();
|
||||
|
||||
|
|
@ -523,7 +523,7 @@ cipher_ctx_free(mbedtls_cipher_context_t *ctx)
|
|||
}
|
||||
|
||||
void
|
||||
cipher_ctx_init(mbedtls_cipher_context_t *ctx, uint8_t *key, int key_len,
|
||||
cipher_ctx_init(mbedtls_cipher_context_t *ctx, const uint8_t *key, int key_len,
|
||||
const mbedtls_cipher_info_t *kt, const mbedtls_operation_t operation)
|
||||
{
|
||||
ASSERT(NULL != kt && NULL != ctx);
|
||||
|
|
@ -597,7 +597,7 @@ cipher_ctx_get_cipher_kt(const cipher_ctx_t *ctx)
|
|||
}
|
||||
|
||||
int
|
||||
cipher_ctx_reset(mbedtls_cipher_context_t *ctx, uint8_t *iv_buf)
|
||||
cipher_ctx_reset(mbedtls_cipher_context_t *ctx, const uint8_t *iv_buf)
|
||||
{
|
||||
if (!mbed_ok(mbedtls_cipher_reset(ctx)))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -85,13 +85,13 @@ typedef mbedtls_md_context_t hmac_ctx_t;
|
|||
* added. During initialisation, a personalisation string will be added based
|
||||
* on the time, the PID, and a pointer to the random context.
|
||||
*/
|
||||
mbedtls_ctr_drbg_context *rand_ctx_get();
|
||||
mbedtls_ctr_drbg_context *rand_ctx_get(void);
|
||||
|
||||
#ifdef ENABLE_PREDICTION_RESISTANCE
|
||||
/**
|
||||
* Enable prediction resistance on the random number generator.
|
||||
*/
|
||||
void rand_ctx_enable_prediction_resistance();
|
||||
void rand_ctx_enable_prediction_resistance(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -280,7 +280,7 @@ print_cipher(const EVP_CIPHER *cipher)
|
|||
}
|
||||
|
||||
void
|
||||
show_available_ciphers()
|
||||
show_available_ciphers(void)
|
||||
{
|
||||
int nid;
|
||||
size_t i;
|
||||
|
|
@ -339,7 +339,7 @@ show_available_ciphers()
|
|||
}
|
||||
|
||||
void
|
||||
show_available_digests()
|
||||
show_available_digests(void)
|
||||
{
|
||||
int nid;
|
||||
|
||||
|
|
@ -364,7 +364,7 @@ show_available_digests()
|
|||
}
|
||||
|
||||
void
|
||||
show_available_engines()
|
||||
show_available_engines(void)
|
||||
{
|
||||
#if HAVE_OPENSSL_ENGINE /* Only defined for OpenSSL */
|
||||
ENGINE *e;
|
||||
|
|
@ -665,7 +665,7 @@ cipher_ctx_free(EVP_CIPHER_CTX *ctx)
|
|||
}
|
||||
|
||||
void
|
||||
cipher_ctx_init(EVP_CIPHER_CTX *ctx, uint8_t *key, int key_len,
|
||||
cipher_ctx_init(EVP_CIPHER_CTX *ctx, const uint8_t *key, int key_len,
|
||||
const EVP_CIPHER *kt, int enc)
|
||||
{
|
||||
ASSERT(NULL != kt && NULL != ctx);
|
||||
|
|
@ -732,7 +732,7 @@ cipher_ctx_get_cipher_kt(const cipher_ctx_t *ctx)
|
|||
|
||||
|
||||
int
|
||||
cipher_ctx_reset(EVP_CIPHER_CTX *ctx, uint8_t *iv_buf)
|
||||
cipher_ctx_reset(EVP_CIPHER_CTX *ctx, const uint8_t *iv_buf)
|
||||
{
|
||||
return EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv_buf, -1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ set_machine_readable_output(bool parsable)
|
|||
}
|
||||
|
||||
void
|
||||
error_reset()
|
||||
error_reset(void)
|
||||
{
|
||||
use_syslog = std_redir = false;
|
||||
suppress_timestamps = false;
|
||||
|
|
@ -278,7 +278,7 @@ x_msg_va(const unsigned int flags, const char *format, va_list arglist)
|
|||
if ((flags & M_ERRNO) && e)
|
||||
{
|
||||
openvpn_snprintf(m2, ERR_BUF_SIZE, "%s: %s (errno=%d)",
|
||||
m1, strerror_ts(e, &gc), e);
|
||||
m1, strerror(e), e);
|
||||
SWAP;
|
||||
}
|
||||
|
||||
|
|
@ -491,7 +491,7 @@ open_syslog(const char *pgmname, bool stdio_to_null)
|
|||
}
|
||||
|
||||
void
|
||||
close_syslog()
|
||||
close_syslog(void)
|
||||
{
|
||||
#if SYSLOG_CAPABILITY
|
||||
if (use_syslog)
|
||||
|
|
@ -646,7 +646,7 @@ unsigned int x_cs_verbose_level; /* GLOBAL */
|
|||
unsigned int x_cs_err_delay_ms; /* GLOBAL */
|
||||
|
||||
void
|
||||
reset_check_status()
|
||||
reset_check_status(void)
|
||||
{
|
||||
x_cs_info_level = 0;
|
||||
x_cs_verbose_level = 0;
|
||||
|
|
@ -704,20 +704,15 @@ x_check_status(int status,
|
|||
{
|
||||
if (extended_msg)
|
||||
{
|
||||
msg(x_cs_info_level, "%s %s [%s]: %s (code=%d)",
|
||||
description,
|
||||
msg(x_cs_info_level, "%s %s [%s]: %s (code=%d)", description,
|
||||
sock ? proto2ascii(sock->info.proto, sock->info.af, true) : "",
|
||||
extended_msg,
|
||||
strerror_ts(my_errno, &gc),
|
||||
my_errno);
|
||||
extended_msg, strerror(my_errno), my_errno);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg(x_cs_info_level, "%s %s: %s (code=%d)",
|
||||
description,
|
||||
msg(x_cs_info_level, "%s %s: %s (code=%d)", description,
|
||||
sock ? proto2ascii(sock->info.proto, sock->info.af, true) : "",
|
||||
strerror_ts(my_errno, &gc),
|
||||
my_errno);
|
||||
strerror(my_errno), my_errno);
|
||||
}
|
||||
|
||||
if (x_cs_err_delay_ms)
|
||||
|
|
|
|||
|
|
@ -261,7 +261,7 @@ void msg_forked(void);
|
|||
|
||||
void open_syslog(const char *pgmname, bool stdio_to_null);
|
||||
|
||||
void close_syslog();
|
||||
void close_syslog(void);
|
||||
|
||||
/* log file output */
|
||||
void redirect_stdout_stderr(const char *file, bool append);
|
||||
|
|
|
|||
|
|
@ -757,7 +757,7 @@ read_incoming_link(struct context *c)
|
|||
if (event_timeout_defined(&c->c2.explicit_exit_notification_interval))
|
||||
{
|
||||
msg(D_STREAM_ERRORS, "Connection reset during exit notification period, ignoring [%d]", status);
|
||||
openvpn_sleep(1);
|
||||
management_sleep(1);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -610,6 +610,7 @@ init_port_share(struct context *c)
|
|||
|
||||
#endif /* if PORT_SHARE */
|
||||
|
||||
|
||||
bool
|
||||
init_static(void)
|
||||
{
|
||||
|
|
@ -619,8 +620,20 @@ init_static(void)
|
|||
crypto_init_dmalloc();
|
||||
#endif
|
||||
|
||||
init_random_seed(); /* init random() function, only used as
|
||||
* source for weak random numbers */
|
||||
|
||||
/*
|
||||
* Initialize random number seed. random() is only used
|
||||
* when "weak" random numbers are acceptable.
|
||||
* SSL library routines are always used when cryptographically
|
||||
* strong random numbers are required.
|
||||
*/
|
||||
struct timeval tv;
|
||||
if (!gettimeofday(&tv, NULL))
|
||||
{
|
||||
const unsigned int seed = (unsigned int) tv.tv_sec ^ tv.tv_usec;
|
||||
srandom(seed);
|
||||
}
|
||||
|
||||
error_reset(); /* initialize error.c */
|
||||
reset_check_status(); /* initialize status check code in socket.c */
|
||||
|
||||
|
|
@ -1904,7 +1917,7 @@ do_close_tun(struct context *c, bool force)
|
|||
}
|
||||
|
||||
void
|
||||
tun_abort()
|
||||
tun_abort(void)
|
||||
{
|
||||
struct context *c = static_context;
|
||||
if (c)
|
||||
|
|
@ -1969,7 +1982,7 @@ do_up(struct context *c, bool pulled_options, unsigned int option_types_found)
|
|||
/* if so, close tun, delete routes, then reinitialize tun and add routes */
|
||||
msg(M_INFO, "NOTE: Pulled options changed on restart, will need to close and reopen TUN/TAP device.");
|
||||
do_close_tun(c, true);
|
||||
openvpn_sleep(1);
|
||||
management_sleep(1);
|
||||
c->c2.did_open_tun = do_open_tun(c);
|
||||
update_time();
|
||||
}
|
||||
|
|
@ -2263,7 +2276,7 @@ socket_restart_pause(struct context *c)
|
|||
if (sec)
|
||||
{
|
||||
msg(D_RESTART, "Restart pause, %d second(s)", sec);
|
||||
openvpn_sleep(sec);
|
||||
management_sleep(sec);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -118,6 +118,24 @@ modulo_add(int x, int y, int mod)
|
|||
return sum;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the next largest power of 2
|
||||
* or u if u is a power of 2.
|
||||
*/
|
||||
static inline size_t
|
||||
adjust_power_of_2(size_t u)
|
||||
{
|
||||
size_t ret = 1;
|
||||
|
||||
while (ret < u)
|
||||
{
|
||||
ret <<= 1;
|
||||
ASSERT(ret > 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int
|
||||
index_verify(int index, int size, const char *file, int line)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ event_timeout_clear(struct event_timeout *et)
|
|||
}
|
||||
|
||||
static inline struct event_timeout
|
||||
event_timeout_clear_ret()
|
||||
event_timeout_clear_ret(void)
|
||||
{
|
||||
struct event_timeout ret;
|
||||
event_timeout_clear(&ret);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
#if P2MP_SERVER
|
||||
|
||||
#include "integer.h"
|
||||
#include "list.h"
|
||||
#include "misc.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ static void man_output_standalone(struct management *man, volatile int *signal_r
|
|||
static void man_reset_client_socket(struct management *man, const bool exiting);
|
||||
|
||||
static void
|
||||
man_help()
|
||||
man_help(void)
|
||||
{
|
||||
msg(M_CLIENT, "Management Interface for %s", title_string);
|
||||
msg(M_CLIENT, "Commands:");
|
||||
|
|
@ -1878,17 +1878,15 @@ man_connect(struct management *man)
|
|||
#if UNIX_SOCK_SUPPORT
|
||||
if (man->settings.flags & MF_UNIX_SOCK)
|
||||
{
|
||||
msg(D_LINK_ERRORS,
|
||||
"MANAGEMENT: connect to unix socket %s failed: %s",
|
||||
sockaddr_unix_name(&man->settings.local_unix, "NULL"),
|
||||
strerror_ts(status, &gc));
|
||||
msg(D_LINK_ERRORS | M_ERRNO,
|
||||
"MANAGEMENT: connect to unix socket %s failed",
|
||||
sockaddr_unix_name(&man->settings.local_unix, "NULL"));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
msg(D_LINK_ERRORS,
|
||||
"MANAGEMENT: connect to %s failed: %s",
|
||||
print_sockaddr(man->settings.local->ai_addr, &gc),
|
||||
strerror_ts(status, &gc));
|
||||
msg(D_LINK_ERRORS | M_ERRNO,
|
||||
"MANAGEMENT: connect to %s failed",
|
||||
print_sockaddr(man->settings.local->ai_addr, &gc));
|
||||
throw_signal_soft(SIGTERM, "management-connect-failed");
|
||||
goto done;
|
||||
}
|
||||
|
|
@ -2008,9 +2006,8 @@ man_io_error(struct management *man, const char *prefix)
|
|||
if (!ignore_sys_error(err))
|
||||
{
|
||||
struct gc_arena gc = gc_new();
|
||||
msg(D_MANAGEMENT, "MANAGEMENT: TCP %s error: %s",
|
||||
prefix,
|
||||
strerror_ts(err, &gc));
|
||||
msg(D_MANAGEMENT, "MANAGEMENT: TCP %s error: %s", prefix,
|
||||
strerror(err));
|
||||
gc_free(&gc);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -3504,7 +3501,9 @@ management_query_user_pass(struct management *man,
|
|||
*/
|
||||
if (ret)
|
||||
{
|
||||
man->connection.up_query.nocache = up->nocache; /* preserve caller's nocache setting */
|
||||
/* preserve caller's settings */
|
||||
man->connection.up_query.nocache = up->nocache;
|
||||
man->connection.up_query.wait_for_push = up->wait_for_push;
|
||||
*up = man->connection.up_query;
|
||||
}
|
||||
secure_memzero(&man->connection.up_query, sizeof(man->connection.up_query));
|
||||
|
|
@ -4000,9 +3999,25 @@ log_history_ref(const struct log_history *h, const int index)
|
|||
}
|
||||
}
|
||||
|
||||
#else /* ifdef ENABLE_MANAGEMENT */
|
||||
static void
|
||||
dummy(void)
|
||||
void
|
||||
management_sleep(const int n)
|
||||
{
|
||||
if (management)
|
||||
{
|
||||
management_event_loop_n_seconds(management, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
sleep(n);
|
||||
}
|
||||
}
|
||||
|
||||
#else /* ifdef ENABLE_MANAGEMENT */
|
||||
|
||||
void
|
||||
management_sleep(const int n)
|
||||
{
|
||||
sleep(n);
|
||||
}
|
||||
|
||||
#endif /* ENABLE_MANAGEMENT */
|
||||
|
|
|
|||
|
|
@ -605,4 +605,11 @@ management_bytes_server(struct management *man,
|
|||
#endif /* MANAGEMENT_DEF_AUTH */
|
||||
|
||||
#endif /* ifdef ENABLE_MANAGEMENT */
|
||||
|
||||
/**
|
||||
* A sleep function that services the management layer for n seconds rather
|
||||
* than doing nothing.
|
||||
*/
|
||||
void management_sleep(const int n);
|
||||
|
||||
#endif /* ifndef MANAGE_H */
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include "buffer.h"
|
||||
#include "error.h"
|
||||
#include "integer.h"
|
||||
#include "misc.h"
|
||||
#include "mbuf.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -145,28 +145,6 @@ run_up_down(const char *command,
|
|||
gc_free(&gc);
|
||||
}
|
||||
|
||||
/* Write our PID to a file */
|
||||
void
|
||||
write_pid(const char *filename)
|
||||
{
|
||||
if (filename)
|
||||
{
|
||||
unsigned int pid = 0;
|
||||
FILE *fp = platform_fopen(filename, "w");
|
||||
if (!fp)
|
||||
{
|
||||
msg(M_ERR, "Open error on pid file %s", filename);
|
||||
}
|
||||
|
||||
pid = platform_getpid();
|
||||
fprintf(fp, "%u\n", pid);
|
||||
if (platform_fclose(fp))
|
||||
{
|
||||
msg(M_ERR, "Close error on pid file %s", filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set standard file descriptors to /dev/null
|
||||
*/
|
||||
|
|
@ -445,40 +423,6 @@ openvpn_popen(const struct argv *a, const struct env_set *es)
|
|||
|
||||
|
||||
|
||||
/*
|
||||
* Initialize random number seed. random() is only used
|
||||
* when "weak" random numbers are acceptable.
|
||||
* OpenSSL routines are always used when cryptographically
|
||||
* strong random numbers are required.
|
||||
*/
|
||||
|
||||
void
|
||||
init_random_seed(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
if (!gettimeofday(&tv, NULL))
|
||||
{
|
||||
const unsigned int seed = (unsigned int) tv.tv_sec ^ tv.tv_usec;
|
||||
srandom(seed);
|
||||
}
|
||||
}
|
||||
|
||||
/* thread-safe strerror */
|
||||
|
||||
const char *
|
||||
strerror_ts(int errnum, struct gc_arena *gc)
|
||||
{
|
||||
#ifdef HAVE_STRERROR
|
||||
struct buffer out = alloc_buf_gc(256, gc);
|
||||
|
||||
buf_printf(&out, "%s", openvpn_strerror(errnum, gc));
|
||||
return BSTR(&out);
|
||||
#else
|
||||
return "[error string unavailable]";
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Set environmental variable (int or string).
|
||||
*
|
||||
|
|
@ -504,29 +448,6 @@ construct_name_value(const char *name, const char *value, struct gc_arena *gc)
|
|||
return BSTR(&out);
|
||||
}
|
||||
|
||||
bool
|
||||
deconstruct_name_value(const char *str, const char **name, const char **value, struct gc_arena *gc)
|
||||
{
|
||||
char *cp;
|
||||
|
||||
ASSERT(str);
|
||||
ASSERT(name && value);
|
||||
|
||||
*name = cp = string_alloc(str, gc);
|
||||
*value = NULL;
|
||||
|
||||
while ((*cp))
|
||||
{
|
||||
if (*cp == '=' && !*value)
|
||||
{
|
||||
*cp = 0;
|
||||
*value = cp + 1;
|
||||
}
|
||||
++cp;
|
||||
}
|
||||
return *name && *value;
|
||||
}
|
||||
|
||||
static bool
|
||||
env_string_equal(const char *s1, const char *s2)
|
||||
{
|
||||
|
|
@ -948,10 +869,8 @@ create_temp_file(const char *directory, const char *prefix, struct gc_arena *gc)
|
|||
else if (fd == -1 && errno != EEXIST)
|
||||
{
|
||||
/* Something else went wrong, no need to retry. */
|
||||
struct gc_arena gcerr = gc_new();
|
||||
msg(M_FATAL, "Could not create temporary file '%s': %s",
|
||||
retfname, strerror_ts(errno, &gcerr));
|
||||
gc_free(&gcerr);
|
||||
msg(M_FATAL | M_ERRNO, "Could not create temporary file '%s'",
|
||||
retfname);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
|
@ -1652,37 +1571,6 @@ make_extended_arg_array(char **p, struct gc_arena *gc)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
openvpn_sleep(const int n)
|
||||
{
|
||||
#ifdef ENABLE_MANAGEMENT
|
||||
if (management)
|
||||
{
|
||||
management_event_loop_n_seconds(management, n);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
sleep(n);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the next largest power of 2
|
||||
* or u if u is a power of 2.
|
||||
*/
|
||||
size_t
|
||||
adjust_power_of_2(size_t u)
|
||||
{
|
||||
size_t ret = 1;
|
||||
|
||||
while (ret < u)
|
||||
{
|
||||
ret <<= 1;
|
||||
ASSERT(ret > 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove security-sensitive strings from control message
|
||||
* so that they will not be output to log file.
|
||||
|
|
|
|||
|
|
@ -68,8 +68,6 @@ void run_up_down(const char *command,
|
|||
const char *script_type,
|
||||
struct env_set *es);
|
||||
|
||||
void write_pid(const char *filename);
|
||||
|
||||
/* system flags */
|
||||
#define S_SCRIPT (1<<0)
|
||||
#define S_FATAL (1<<1)
|
||||
|
|
@ -95,12 +93,6 @@ openvpn_run_script(const struct argv *a, const struct env_set *es, const unsigne
|
|||
}
|
||||
|
||||
|
||||
#ifdef HAVE_STRERROR
|
||||
/* a thread-safe version of strerror */
|
||||
const char *strerror_ts(int errnum, struct gc_arena *gc);
|
||||
|
||||
#endif
|
||||
|
||||
/* Set standard file descriptors to /dev/null */
|
||||
void set_std_files_to_null(bool stdin_only);
|
||||
|
||||
|
|
@ -108,9 +100,6 @@ void set_std_files_to_null(bool stdin_only);
|
|||
extern int inetd_socket_descriptor;
|
||||
void save_inetd_socket_descriptor(void);
|
||||
|
||||
/* init random() function, only used as source for weak random numbers, when !ENABLE_CRYPTO */
|
||||
void init_random_seed(void);
|
||||
|
||||
/* set/delete environmental variable */
|
||||
void setenv_str_ex(struct env_set *es,
|
||||
const char *name,
|
||||
|
|
@ -298,12 +287,6 @@ bool env_safe_to_print(const char *str);
|
|||
/* returns true if environmental variable may be passed to an external program */
|
||||
bool env_allowed(const char *str);
|
||||
|
||||
/*
|
||||
* A sleep function that services the management layer for n
|
||||
* seconds rather than doing nothing.
|
||||
*/
|
||||
void openvpn_sleep(const int n);
|
||||
|
||||
void configure_path(void);
|
||||
|
||||
const char *sanitize_control_message(const char *str, struct gc_arena *gc);
|
||||
|
|
@ -327,8 +310,6 @@ extern const char *iproute_path;
|
|||
#define SSEC_PW_ENV 3 /* allow calling of built-in programs and user-defined scripts that may receive a password as an environmental variable */
|
||||
extern int script_security; /* GLOBAL */
|
||||
|
||||
/* return the next largest power of 2 */
|
||||
size_t adjust_power_of_2(size_t u);
|
||||
|
||||
#define COMPAT_FLAG_QUERY 0 /** compat_flags operator: Query for a flag */
|
||||
#define COMPAT_FLAG_SET (1<<0) /** compat_flags operator: Set a compat flag */
|
||||
|
|
|
|||
|
|
@ -797,7 +797,7 @@ tunnel_server_tcp(struct context *top)
|
|||
multi.top.c2.inotify_fd = inotify_init();
|
||||
if (multi.top.c2.inotify_fd < 0)
|
||||
{
|
||||
msg(D_MULTI_ERRORS, "MULTI: inotify_init error: %s", strerror(errno));
|
||||
msg(D_MULTI_ERRORS | M_ERRNO, "MULTI: inotify_init error");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -326,7 +326,7 @@ tunnel_server_udp_single_threaded(struct context *top)
|
|||
multi.top.c2.inotify_fd = inotify_init();
|
||||
if (multi.top.c2.inotify_fd < 0)
|
||||
{
|
||||
msg(D_MULTI_ERRORS, "MULTI: inotify_init error: %s", strerror(errno));
|
||||
msg(D_MULTI_ERRORS | M_ERRNO, "MULTI: inotify_init error");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -2356,7 +2356,7 @@ multi_process_post(struct multi_context *m, struct multi_instance *mi, const uns
|
|||
}
|
||||
else
|
||||
{
|
||||
msg(M_NONFATAL, "MULTI: inotify_add_watch error: %s", strerror(errno));
|
||||
msg(M_NONFATAL | M_ERRNO, "MULTI: inotify_add_watch error");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -60,45 +60,47 @@ static void
|
|||
create_des_keys(const unsigned char *hash, unsigned char *key)
|
||||
{
|
||||
key[0] = hash[0];
|
||||
key[1] = ((hash[0]&1)<<7)|(hash[1]>>1);
|
||||
key[2] = ((hash[1]&3)<<6)|(hash[2]>>2);
|
||||
key[3] = ((hash[2]&7)<<5)|(hash[3]>>3);
|
||||
key[4] = ((hash[3]&15)<<4)|(hash[4]>>4);
|
||||
key[5] = ((hash[4]&31)<<3)|(hash[5]>>5);
|
||||
key[6] = ((hash[5]&63)<<2)|(hash[6]>>6);
|
||||
key[7] = ((hash[6]&127)<<1);
|
||||
key[1] = ((hash[0] & 1) << 7) | (hash[1] >> 1);
|
||||
key[2] = ((hash[1] & 3) << 6) | (hash[2] >> 2);
|
||||
key[3] = ((hash[2] & 7) << 5) | (hash[3] >> 3);
|
||||
key[4] = ((hash[3] & 15) << 4) | (hash[4] >> 4);
|
||||
key[5] = ((hash[4] & 31) << 3) | (hash[5] >> 5);
|
||||
key[6] = ((hash[5] & 63) << 2) | (hash[6] >> 6);
|
||||
key[7] = ((hash[6] & 127) << 1);
|
||||
key_des_fixup(key, 8, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
gen_md4_hash(const char *data, int data_len, char *result)
|
||||
gen_md4_hash(const uint8_t *data, int data_len, uint8_t *result)
|
||||
{
|
||||
/* result is 16 byte md4 hash */
|
||||
const md_kt_t *md4_kt = md_kt_get("MD4");
|
||||
char md[MD4_DIGEST_LENGTH];
|
||||
uint8_t md[MD4_DIGEST_LENGTH];
|
||||
|
||||
md_full(md4_kt, data, data_len, md);
|
||||
memcpy(result, md, MD4_DIGEST_LENGTH);
|
||||
}
|
||||
|
||||
static void
|
||||
gen_hmac_md5(const char *data, int data_len, const char *key, int key_len,char *result)
|
||||
gen_hmac_md5(const uint8_t *data, int data_len, const uint8_t *key, int key_len,
|
||||
uint8_t *result)
|
||||
{
|
||||
const md_kt_t *md5_kt = md_kt_get("MD5");
|
||||
hmac_ctx_t *hmac_ctx = hmac_ctx_new();
|
||||
|
||||
hmac_ctx_init(hmac_ctx, key, key_len, md5_kt);
|
||||
hmac_ctx_update(hmac_ctx, (const unsigned char *)data, data_len);
|
||||
hmac_ctx_final(hmac_ctx, (unsigned char *)result);
|
||||
hmac_ctx_update(hmac_ctx, data, data_len);
|
||||
hmac_ctx_final(hmac_ctx, result);
|
||||
hmac_ctx_cleanup(hmac_ctx);
|
||||
hmac_ctx_free(hmac_ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
gen_timestamp(unsigned char *timestamp)
|
||||
gen_timestamp(uint8_t *timestamp)
|
||||
{
|
||||
/* Copies 8 bytes long timestamp into "timestamp" buffer.
|
||||
* Timestamp is Little-endian, 64-bit signed value representing the number of tenths of a microsecond since January 1, 1601.
|
||||
* Timestamp is Little-endian, 64-bit signed value representing the
|
||||
* number of tenths of a microsecond since January 1, 1601.
|
||||
*/
|
||||
|
||||
UINTEGER64 timestamp_ull;
|
||||
|
|
@ -130,7 +132,7 @@ gen_nonce(unsigned char *nonce)
|
|||
}
|
||||
|
||||
void
|
||||
my_strupr(unsigned char *str)
|
||||
my_strupr(char *str)
|
||||
{
|
||||
/* converts string to uppercase in place */
|
||||
|
||||
|
|
@ -150,16 +152,17 @@ unicodize(char *dst, const char *src)
|
|||
{
|
||||
dst[i++] = *src;
|
||||
dst[i++] = 0;
|
||||
}
|
||||
while (*src++);
|
||||
} while (*src++);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static void
|
||||
add_security_buffer(int sb_offset, void *data, int length, unsigned char *msg_buf, int *msg_bufpos)
|
||||
add_security_buffer(int sb_offset, void *data, int length,
|
||||
unsigned char *msg_buf, int *msg_bufpos)
|
||||
{
|
||||
/* Adds security buffer data to a message and sets security buffer's offset and length */
|
||||
/* Adds security buffer data to a message and sets security buffer's
|
||||
* offset and length */
|
||||
msg_buf[sb_offset] = (unsigned char)length;
|
||||
msg_buf[sb_offset + 2] = msg_buf[sb_offset];
|
||||
msg_buf[sb_offset + 4] = (unsigned char)(*msg_bufpos & 0xff);
|
||||
|
|
@ -186,7 +189,8 @@ ntlm_phase_1(const struct http_proxy_info *p, struct gc_arena *gc)
|
|||
}
|
||||
|
||||
const char *
|
||||
ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2, struct gc_arena *gc)
|
||||
ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2,
|
||||
struct gc_arena *gc)
|
||||
{
|
||||
/* NTLM handshake
|
||||
*
|
||||
|
|
@ -195,19 +199,19 @@ ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2, struct gc_are
|
|||
*/
|
||||
|
||||
char pwbuf[sizeof(p->up.password) * 2]; /* for unicode password */
|
||||
unsigned char buf2[128]; /* decoded reply from proxy */
|
||||
unsigned char phase3[464];
|
||||
uint8_t buf2[128]; /* decoded reply from proxy */
|
||||
uint8_t phase3[464];
|
||||
|
||||
char md4_hash[MD4_DIGEST_LENGTH+5];
|
||||
char challenge[8], ntlm_response[24];
|
||||
uint8_t md4_hash[MD4_DIGEST_LENGTH + 5];
|
||||
uint8_t challenge[8], ntlm_response[24];
|
||||
int i, ret_val;
|
||||
|
||||
char ntlmv2_response[144];
|
||||
uint8_t ntlmv2_response[144];
|
||||
char userdomain_u[256]; /* for uppercase unicode username and domain */
|
||||
char userdomain[128]; /* the same as previous but ascii */
|
||||
char ntlmv2_hash[MD5_DIGEST_LENGTH];
|
||||
char ntlmv2_hmacmd5[16];
|
||||
char *ntlmv2_blob = ntlmv2_response + 16; /* inside ntlmv2_response, length: 128 */
|
||||
uint8_t ntlmv2_hash[MD5_DIGEST_LENGTH];
|
||||
uint8_t ntlmv2_hmacmd5[16];
|
||||
uint8_t *ntlmv2_blob = ntlmv2_response + 16; /* inside ntlmv2_response, length: 128 */
|
||||
int ntlmv2_blob_size = 0;
|
||||
int phase3_bufpos = 0x40; /* offset to next security buffer data to be added */
|
||||
size_t len;
|
||||
|
|
@ -246,12 +250,13 @@ ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2, struct gc_are
|
|||
|
||||
|
||||
/* fill 1st 16 bytes with md4 hash, disregard terminating null */
|
||||
gen_md4_hash(pwbuf, unicodize(pwbuf, p->up.password) - 2, md4_hash);
|
||||
int unicode_len = unicodize(pwbuf, p->up.password) - 2;
|
||||
gen_md4_hash((uint8_t *)pwbuf, unicode_len, md4_hash);
|
||||
|
||||
/* pad to 21 bytes */
|
||||
memset(md4_hash + MD4_DIGEST_LENGTH, 0, 5);
|
||||
|
||||
ret_val = openvpn_base64_decode( phase_2, (void *)buf2, -1);
|
||||
ret_val = openvpn_base64_decode(phase_2, buf2, -1);
|
||||
if (ret_val < 0)
|
||||
{
|
||||
return NULL;
|
||||
|
|
@ -271,7 +276,8 @@ ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2, struct gc_are
|
|||
int tib_len;
|
||||
|
||||
/* NTLMv2 hash */
|
||||
my_strupr((unsigned char *)strcpy(userdomain, username));
|
||||
strcpy(userdomain, username);
|
||||
my_strupr(userdomain);
|
||||
if (strlen(username) + strlen(domain) < sizeof(userdomain))
|
||||
{
|
||||
strcat(userdomain, domain);
|
||||
|
|
@ -281,34 +287,40 @@ ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2, struct gc_are
|
|||
msg(M_INFO, "Warning: Username or domain too long");
|
||||
}
|
||||
unicodize(userdomain_u, userdomain);
|
||||
gen_hmac_md5(userdomain_u, 2 * strlen(userdomain), md4_hash, MD5_DIGEST_LENGTH, ntlmv2_hash);
|
||||
gen_hmac_md5((uint8_t *)userdomain_u, 2 * strlen(userdomain), md4_hash,
|
||||
MD5_DIGEST_LENGTH, ntlmv2_hash);
|
||||
|
||||
/* NTLMv2 Blob */
|
||||
memset(ntlmv2_blob, 0, 128); /* Clear blob buffer */
|
||||
ntlmv2_blob[0x00] = 1; /* Signature */
|
||||
ntlmv2_blob[0x01] = 1; /* Signature */
|
||||
ntlmv2_blob[0x04] = 0; /* Reserved */
|
||||
gen_timestamp((unsigned char *)&ntlmv2_blob[0x08]); /* 64-bit Timestamp */
|
||||
gen_nonce((unsigned char *)&ntlmv2_blob[0x10]); /* 64-bit Client Nonce */
|
||||
gen_timestamp(&ntlmv2_blob[0x08]); /* 64-bit Timestamp */
|
||||
gen_nonce(&ntlmv2_blob[0x10]); /* 64-bit Client Nonce */
|
||||
ntlmv2_blob[0x18] = 0; /* Unknown, zero should work */
|
||||
|
||||
/* Add target information block to the blob */
|
||||
if (( *((long *)&buf2[0x14]) & 0x00800000) == 0x00800000) /* Check for Target Information block */
|
||||
|
||||
/* Check for Target Information block */
|
||||
if ((*((long *)&buf2[0x14]) & 0x00800000) == 0x00800000)
|
||||
{
|
||||
tib_len = buf2[0x28]; /* Get Target Information block size */
|
||||
if (tib_len > 96)
|
||||
{
|
||||
tib_len = 96;
|
||||
}
|
||||
|
||||
{
|
||||
char *tib_ptr;
|
||||
int tib_pos = buf2[0x2c];
|
||||
uint8_t *tib_ptr;
|
||||
uint8_t tib_pos = buf2[0x2c];
|
||||
if (tib_pos + tib_len > sizeof(buf2))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
tib_ptr = buf2 + tib_pos; /* Get Target Information block pointer */
|
||||
memcpy(&ntlmv2_blob[0x1c], tib_ptr, tib_len); /* Copy Target Information block into the blob */
|
||||
/* Get Target Information block pointer */
|
||||
tib_ptr = buf2 + tib_pos;
|
||||
/* Copy Target Information block into the blob */
|
||||
memcpy(&ntlmv2_blob[0x1c], tib_ptr, tib_len);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -316,7 +328,8 @@ ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2, struct gc_are
|
|||
tib_len = 0;
|
||||
}
|
||||
|
||||
ntlmv2_blob[0x1c + tib_len] = 0; /* Unknown, zero works */
|
||||
/* Unknown, zero works */
|
||||
ntlmv2_blob[0x1c + tib_len] = 0;
|
||||
|
||||
/* Get blob length */
|
||||
ntlmv2_blob_size = 0x20 + tib_len;
|
||||
|
|
@ -325,24 +338,28 @@ ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2, struct gc_are
|
|||
memcpy(&ntlmv2_response[8], challenge, 8);
|
||||
|
||||
/* hmac-md5 */
|
||||
gen_hmac_md5(&ntlmv2_response[8], ntlmv2_blob_size + 8, ntlmv2_hash, MD5_DIGEST_LENGTH, ntlmv2_hmacmd5);
|
||||
|
||||
/* Add hmac-md5 result to the blob */
|
||||
memcpy(ntlmv2_response, ntlmv2_hmacmd5, MD5_DIGEST_LENGTH); /* Note: This overwrites challenge previously written at ntlmv2_response[8..15] */
|
||||
gen_hmac_md5(&ntlmv2_response[8], ntlmv2_blob_size + 8, ntlmv2_hash,
|
||||
MD5_DIGEST_LENGTH, ntlmv2_hmacmd5);
|
||||
|
||||
/* Add hmac-md5 result to the blob.
|
||||
* Note: This overwrites challenge previously written at
|
||||
* ntlmv2_response[8..15] */
|
||||
memcpy(ntlmv2_response, ntlmv2_hmacmd5, MD5_DIGEST_LENGTH);
|
||||
}
|
||||
else /* Generate NTLM response */
|
||||
else /* Generate NTLM response */
|
||||
{
|
||||
unsigned char key1[DES_KEY_LENGTH], key2[DES_KEY_LENGTH], key3[DES_KEY_LENGTH];
|
||||
unsigned char key1[DES_KEY_LENGTH], key2[DES_KEY_LENGTH];
|
||||
unsigned char key3[DES_KEY_LENGTH];
|
||||
|
||||
create_des_keys((unsigned char *)md4_hash, key1);
|
||||
create_des_keys(md4_hash, key1);
|
||||
cipher_des_encrypt_ecb(key1, challenge, ntlm_response);
|
||||
|
||||
create_des_keys((unsigned char *)&(md4_hash[DES_KEY_LENGTH-1]), key2);
|
||||
create_des_keys(&md4_hash[DES_KEY_LENGTH - 1], key2);
|
||||
cipher_des_encrypt_ecb(key2, challenge, &ntlm_response[DES_KEY_LENGTH]);
|
||||
|
||||
create_des_keys((unsigned char *)&(md4_hash[2*(DES_KEY_LENGTH-1)]), key3);
|
||||
cipher_des_encrypt_ecb(key3, challenge, &ntlm_response[DES_KEY_LENGTH*2]);
|
||||
create_des_keys(&md4_hash[2 * (DES_KEY_LENGTH - 1)], key3);
|
||||
cipher_des_encrypt_ecb(key3, challenge,
|
||||
&ntlm_response[DES_KEY_LENGTH * 2]);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -353,7 +370,8 @@ ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2, struct gc_are
|
|||
|
||||
if (ntlmv2_enabled) /* NTLMv2 response */
|
||||
{
|
||||
add_security_buffer(0x14, ntlmv2_response, ntlmv2_blob_size + 16, phase3, &phase3_bufpos);
|
||||
add_security_buffer(0x14, ntlmv2_response, ntlmv2_blob_size + 16,
|
||||
phase3, &phase3_bufpos);
|
||||
}
|
||||
else /* NTLM response */
|
||||
{
|
||||
|
|
@ -361,12 +379,13 @@ ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2, struct gc_are
|
|||
}
|
||||
|
||||
/* username in ascii */
|
||||
add_security_buffer(0x24, username, strlen(username), phase3, &phase3_bufpos);
|
||||
add_security_buffer(0x24, username, strlen(username), phase3,
|
||||
&phase3_bufpos);
|
||||
|
||||
/* Set domain. If <domain> is empty, default domain will be used (i.e. proxy's domain) */
|
||||
/* Set domain. If <domain> is empty, default domain will be used
|
||||
* (i.e. proxy's domain) */
|
||||
add_security_buffer(0x1c, domain, strlen(domain), phase3, &phase3_bufpos);
|
||||
|
||||
|
||||
/* other security buffers will be empty */
|
||||
phase3[0x10] = phase3_bufpos; /* lm not used */
|
||||
phase3[0x30] = phase3_bufpos; /* no workstation name supplied */
|
||||
|
|
@ -376,7 +395,8 @@ ntlm_phase_3(const struct http_proxy_info *p, const char *phase_2, struct gc_are
|
|||
phase3[0x3c] = 0x02; /* negotiate oem */
|
||||
phase3[0x3d] = 0x02; /* negotiate ntlm */
|
||||
|
||||
return ((const char *)make_base64_string2((unsigned char *)phase3, phase3_bufpos, gc));
|
||||
return ((const char *)make_base64_string2((unsigned char *)phase3,
|
||||
phase3_bufpos, gc));
|
||||
}
|
||||
|
||||
#else /* if NTLM */
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
*/
|
||||
|
||||
static inline int
|
||||
occ_reset_op()
|
||||
occ_reset_op(void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,34 +88,6 @@ EVP_MD_CTX_new(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_EVP_CIPHER_CTX_FREE)
|
||||
/**
|
||||
* Free an existing cipher context
|
||||
*
|
||||
* @param ctx The cipher context
|
||||
*/
|
||||
static inline void
|
||||
EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *c)
|
||||
{
|
||||
free(c);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_EVP_CIPHER_CTX_NEW)
|
||||
/**
|
||||
* Allocate a new cipher context object
|
||||
*
|
||||
* @return A zero'ed cipher context object
|
||||
*/
|
||||
static inline EVP_CIPHER_CTX *
|
||||
EVP_CIPHER_CTX_new(void)
|
||||
{
|
||||
EVP_CIPHER_CTX *ctx = NULL;
|
||||
ALLOC_OBJ_CLEAR(ctx, EVP_CIPHER_CTX);
|
||||
return ctx;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_HMAC_CTX_RESET)
|
||||
/**
|
||||
* Reset a HMAC context
|
||||
|
|
@ -272,6 +244,20 @@ EVP_PKEY_get0_RSA(EVP_PKEY *pkey)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_EVP_PKEY_GET0_EC_KEY) && !defined(OPENSSL_NO_EC)
|
||||
/**
|
||||
* Get the EC_KEY object of a public key
|
||||
*
|
||||
* @param pkey Public key object
|
||||
* @return The underlying EC_KEY object
|
||||
*/
|
||||
static inline EC_KEY *
|
||||
EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey)
|
||||
{
|
||||
return pkey ? pkey->pkey.ec : NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_EVP_PKEY_ID)
|
||||
/**
|
||||
* Get the PKEY type
|
||||
|
|
@ -638,6 +624,24 @@ RSA_meth_set0_app_data(RSA_METHOD *meth, void *app_data)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_EC_GROUP_ORDER_BITS) && !defined(OPENSSL_NO_EC)
|
||||
/**
|
||||
* Gets the number of bits of the order of an EC_GROUP
|
||||
*
|
||||
* @param group EC_GROUP object
|
||||
* @return number of bits of group order.
|
||||
*/
|
||||
static inline int
|
||||
EC_GROUP_order_bits(const EC_GROUP *group)
|
||||
{
|
||||
BIGNUM* order = BN_new();
|
||||
EC_GROUP_get_order(group, order, NULL);
|
||||
int bits = BN_num_bits(order);
|
||||
BN_free(order);
|
||||
return bits;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* SSLeay symbols have been renamed in OpenSSL 1.1 */
|
||||
#if !defined(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT)
|
||||
#define RSA_F_RSA_OSSL_PRIVATE_ENCRYPT RSA_F_RSA_EAY_PRIVATE_ENCRYPT
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include "forward.h"
|
||||
#include "multi.h"
|
||||
#include "win32.h"
|
||||
#include "platform.h"
|
||||
|
||||
#include "memdbg.h"
|
||||
|
||||
|
|
@ -47,6 +48,27 @@ process_signal_p2p(struct context *c)
|
|||
return process_signal(c);
|
||||
}
|
||||
|
||||
/* Write our PID to a file */
|
||||
static void
|
||||
write_pid(const char *filename)
|
||||
{
|
||||
if (filename)
|
||||
{
|
||||
unsigned int pid = 0;
|
||||
FILE *fp = platform_fopen(filename, "w");
|
||||
if (!fp)
|
||||
{
|
||||
msg(M_ERR, "Open error on pid file %s", filename);
|
||||
}
|
||||
|
||||
pid = platform_getpid();
|
||||
fprintf(fp, "%u\n", pid);
|
||||
if (fclose(fp))
|
||||
{
|
||||
msg(M_ERR, "Close error on pid file %s", filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
|
|
|
|||
|
|
@ -3137,8 +3137,7 @@ check_file_access(const int type, const char *file, const int mode, const char *
|
|||
/* Scream if an error is found */
|
||||
if (errcode > 0)
|
||||
{
|
||||
msg(M_NOPREFIX|M_OPTERR, "%s fails with '%s': %s",
|
||||
opt, file, strerror(errno));
|
||||
msg(M_NOPREFIX | M_OPTERR | M_ERRNO, "%s fails with '%s'", opt, file);
|
||||
}
|
||||
|
||||
/* Return true if an error occured */
|
||||
|
|
|
|||
|
|
@ -644,7 +644,7 @@ packet_id_debug_print(int msglevel,
|
|||
#ifdef PID_TEST
|
||||
|
||||
void
|
||||
packet_id_interactive_test()
|
||||
packet_id_interactive_test(void)
|
||||
{
|
||||
struct packet_id pid;
|
||||
struct packet_id_net pin;
|
||||
|
|
|
|||
|
|
@ -299,7 +299,7 @@ packet_id_persist_save_obj(struct packet_id_persist *p, const struct packet_id *
|
|||
const char *packet_id_net_print(const struct packet_id_net *pin, bool print_timestamp, struct gc_arena *gc);
|
||||
|
||||
#ifdef PID_TEST
|
||||
void packet_id_interactive_test();
|
||||
void packet_id_interactive_test(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -356,7 +356,7 @@ cleanup:
|
|||
}
|
||||
|
||||
void
|
||||
pkcs11_terminate()
|
||||
pkcs11_terminate(void)
|
||||
{
|
||||
dmsg(
|
||||
D_PKCS11_DEBUG,
|
||||
|
|
@ -422,13 +422,13 @@ pkcs11_addProvider(
|
|||
}
|
||||
|
||||
int
|
||||
pkcs11_logout()
|
||||
pkcs11_logout(void)
|
||||
{
|
||||
return pkcs11h_logout() == CKR_OK;
|
||||
}
|
||||
|
||||
int
|
||||
pkcs11_management_id_count()
|
||||
pkcs11_management_id_count(void)
|
||||
{
|
||||
pkcs11h_certificate_id_list_t id_list = NULL;
|
||||
pkcs11h_certificate_id_list_t t = NULL;
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ platform_nice(int niceval)
|
|||
errno = 0;
|
||||
if (nice(niceval) < 0 && errno != 0)
|
||||
{
|
||||
msg(M_WARN | M_ERRNO, "WARNING: nice %d failed: %s", niceval, strerror(errno));
|
||||
msg(M_WARN | M_ERRNO, "WARNING: nice %d failed", niceval);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -188,7 +188,7 @@ platform_nice(int niceval)
|
|||
|
||||
/* Get current PID */
|
||||
unsigned int
|
||||
platform_getpid()
|
||||
platform_getpid(void)
|
||||
{
|
||||
FUZZING_BLOCK;
|
||||
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ send_control(const socket_descriptor_t fd, int code)
|
|||
}
|
||||
|
||||
static int
|
||||
cmsg_size()
|
||||
cmsg_size(void)
|
||||
{
|
||||
return CMSG_SPACE(sizeof(socket_descriptor_t));
|
||||
}
|
||||
|
|
@ -923,7 +923,7 @@ port_share_open(const char *host,
|
|||
openvpn_close_socket(fd[1]);
|
||||
|
||||
exit(0);
|
||||
return 0; /* NOTREACHED */
|
||||
return NULL; /* NOTREACHED */
|
||||
}
|
||||
|
||||
error:
|
||||
|
|
|
|||
|
|
@ -3446,7 +3446,14 @@ get_default_gateway_ipv6(struct route_ipv6_gateway_info *rgi6,
|
|||
if (nh->nlmsg_type == NLMSG_ERROR)
|
||||
{
|
||||
struct nlmsgerr *ne = (struct nlmsgerr *)NLMSG_DATA(nh);
|
||||
msg(M_WARN, "GDG6: NLSMG_ERROR: error %d\n", ne->error);
|
||||
|
||||
/* since linux-4.11 -ENETUNREACH is returned when no route can be
|
||||
* found. Don't print any error message in this case */
|
||||
if (ne->error != -ENETUNREACH)
|
||||
{
|
||||
msg(M_WARN, "GDG6: NLMSG_ERROR: error %s\n",
|
||||
strerror(-ne->error));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -495,7 +495,7 @@ openvpn_getaddrinfo(unsigned int flags,
|
|||
goto done;
|
||||
}
|
||||
|
||||
openvpn_sleep(fail_wait_interval);
|
||||
management_sleep(fail_wait_interval);
|
||||
}
|
||||
|
||||
ASSERT(res);
|
||||
|
|
@ -1192,7 +1192,7 @@ socket_listen_accept(socket_descriptor_t sd,
|
|||
|
||||
if (status <= 0)
|
||||
{
|
||||
openvpn_sleep(1);
|
||||
management_sleep(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -1227,7 +1227,7 @@ socket_listen_accept(socket_descriptor_t sd,
|
|||
break;
|
||||
}
|
||||
}
|
||||
openvpn_sleep(1);
|
||||
management_sleep(1);
|
||||
}
|
||||
|
||||
if (!nowait && openvpn_close_socket(sd))
|
||||
|
|
@ -1296,11 +1296,9 @@ socket_bind(socket_descriptor_t sd,
|
|||
}
|
||||
if (bind(sd, cur->ai_addr, cur->ai_addrlen))
|
||||
{
|
||||
const int errnum = openvpn_errno();
|
||||
msg(M_FATAL, "%s: Socket bind failed on local address %s: %s",
|
||||
msg(M_FATAL | M_ERRNO, "%s: Socket bind failed on local address %s",
|
||||
prefix,
|
||||
print_sockaddr_ex(local->ai_addr, ":", PS_SHOW_PORT, &gc),
|
||||
strerror_ts(errnum, &gc));
|
||||
print_sockaddr_ex(local->ai_addr, ":", PS_SHOW_PORT, &gc));
|
||||
}
|
||||
gc_free(&gc);
|
||||
}
|
||||
|
|
@ -1376,7 +1374,7 @@ openvpn_connect(socket_descriptor_t sd,
|
|||
#endif
|
||||
break;
|
||||
}
|
||||
openvpn_sleep(1);
|
||||
management_sleep(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -1475,10 +1473,8 @@ socket_connect(socket_descriptor_t *sd,
|
|||
if (status)
|
||||
{
|
||||
|
||||
msg(D_LINK_ERRORS,
|
||||
"TCP: connect to %s failed: %s",
|
||||
print_sockaddr(dest, &gc),
|
||||
strerror_ts(status, &gc));
|
||||
msg(D_LINK_ERRORS, "TCP: connect to %s failed: %s",
|
||||
print_sockaddr(dest, &gc), strerror(status));
|
||||
|
||||
openvpn_close_socket(*sd);
|
||||
*sd = SOCKET_UNDEFINED;
|
||||
|
|
@ -3889,12 +3885,11 @@ socket_bind_unix(socket_descriptor_t sd,
|
|||
|
||||
if (bind(sd, (struct sockaddr *) local, sizeof(struct sockaddr_un)))
|
||||
{
|
||||
const int errnum = openvpn_errno();
|
||||
msg(M_FATAL, "%s: Socket bind[%d] failed on unix domain socket %s: %s",
|
||||
msg(M_FATAL | M_ERRNO,
|
||||
"%s: Socket bind[%d] failed on unix domain socket %s",
|
||||
prefix,
|
||||
(int)sd,
|
||||
sockaddr_unix_name(local, "NULL"),
|
||||
strerror_ts(errnum, &gc));
|
||||
sockaddr_unix_name(local, "NULL"));
|
||||
}
|
||||
|
||||
#ifdef HAVE_UMASK
|
||||
|
|
|
|||
|
|
@ -347,7 +347,7 @@ tls_init_control_channel_frame_parameters(const struct frame *data_channel_frame
|
|||
}
|
||||
|
||||
void
|
||||
init_ssl_lib()
|
||||
init_ssl_lib(void)
|
||||
{
|
||||
tls_init_lib();
|
||||
|
||||
|
|
@ -355,7 +355,7 @@ init_ssl_lib()
|
|||
}
|
||||
|
||||
void
|
||||
free_ssl_lib()
|
||||
free_ssl_lib(void)
|
||||
{
|
||||
crypto_uninit_lib();
|
||||
prng_uninit();
|
||||
|
|
@ -616,6 +616,11 @@ init_ssl(const struct options *options, struct tls_root_ctx *new_ctx)
|
|||
tls_ctx_client_new(new_ctx);
|
||||
}
|
||||
|
||||
/* Allowable ciphers */
|
||||
/* Since @SECLEVEL also influces loading of certificates, set the
|
||||
* cipher restrictions before loading certificates */
|
||||
tls_ctx_restrict_ciphers(new_ctx, options->cipher_list);
|
||||
|
||||
tls_ctx_set_options(new_ctx, options->ssl_flags);
|
||||
|
||||
if (options->pkcs12_file)
|
||||
|
|
@ -708,9 +713,6 @@ init_ssl(const struct options *options, struct tls_root_ctx *new_ctx)
|
|||
tls_ctx_load_ecdh_params(new_ctx, options->ecdh_curve);
|
||||
}
|
||||
|
||||
/* Allowable ciphers */
|
||||
tls_ctx_restrict_ciphers(new_ctx, options->cipher_list);
|
||||
|
||||
#ifdef ENABLE_CRYPTO_MBEDTLS
|
||||
/* Personalise the random by mixing in the certificate */
|
||||
tls_ctx_personalise_random(new_ctx);
|
||||
|
|
@ -1958,7 +1960,7 @@ cleanup:
|
|||
|
||||
bool
|
||||
tls_session_update_crypto_params(struct tls_session *session,
|
||||
const struct options *options, struct frame *frame)
|
||||
struct options *options, struct frame *frame)
|
||||
{
|
||||
if (!session->opt->server
|
||||
&& 0 != strcmp(options->ciphername, session->opt->config_ciphername)
|
||||
|
|
@ -1967,6 +1969,8 @@ tls_session_update_crypto_params(struct tls_session *session,
|
|||
msg(D_TLS_ERRORS, "Error: pushed cipher not allowed - %s not in %s or %s",
|
||||
options->ciphername, session->opt->config_ciphername,
|
||||
options->ncp_ciphers);
|
||||
/* undo cipher push, abort connection setup */
|
||||
options->ciphername = session->opt->config_ciphername;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -2186,16 +2190,6 @@ read_string_alloc(struct buffer *buf)
|
|||
return str;
|
||||
}
|
||||
|
||||
void
|
||||
read_string_discard(struct buffer *buf)
|
||||
{
|
||||
char *data = read_string_alloc(buf);
|
||||
if (data)
|
||||
{
|
||||
free(data);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle the reading and writing of key data to and from
|
||||
* the TLS control channel (cleartext).
|
||||
|
|
|
|||
|
|
@ -481,7 +481,7 @@ void tls_update_remote_addr(struct tls_multi *multi,
|
|||
* @return true if updating succeeded, false otherwise.
|
||||
*/
|
||||
bool tls_session_update_crypto_params(struct tls_session *session,
|
||||
const struct options *options, struct frame *frame);
|
||||
struct options *options, struct frame *frame);
|
||||
|
||||
/**
|
||||
* "Poor man's NCP": Use peer cipher if it is an allowed (NCP) cipher.
|
||||
|
|
|
|||
|
|
@ -88,17 +88,17 @@ int pem_password_callback(char *buf, int size, int rwflag, void *u);
|
|||
* Perform any static initialisation necessary by the library.
|
||||
* Called on OpenVPN initialisation
|
||||
*/
|
||||
void tls_init_lib();
|
||||
void tls_init_lib(void);
|
||||
|
||||
/**
|
||||
* Free any global SSL library-specific data structures.
|
||||
*/
|
||||
void tls_free_lib();
|
||||
void tls_free_lib(void);
|
||||
|
||||
/**
|
||||
* Clear the underlying SSL library's error state.
|
||||
*/
|
||||
void tls_clear_error();
|
||||
void tls_clear_error(void);
|
||||
|
||||
/**
|
||||
* Parse a TLS version specifier
|
||||
|
|
|
|||
|
|
@ -63,17 +63,17 @@
|
|||
#include <mbedtls/sha256.h>
|
||||
|
||||
void
|
||||
tls_init_lib()
|
||||
tls_init_lib(void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tls_free_lib()
|
||||
tls_free_lib(void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tls_clear_error()
|
||||
tls_clear_error(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@
|
|||
int mydata_index; /* GLOBAL */
|
||||
|
||||
void
|
||||
tls_init_lib()
|
||||
tls_init_lib(void)
|
||||
{
|
||||
SSL_library_init();
|
||||
#ifndef ENABLE_SMALL
|
||||
|
|
@ -82,7 +82,7 @@ tls_init_lib()
|
|||
}
|
||||
|
||||
void
|
||||
tls_free_lib()
|
||||
tls_free_lib(void)
|
||||
{
|
||||
EVP_cleanup();
|
||||
#ifndef ENABLE_SMALL
|
||||
|
|
@ -91,7 +91,7 @@ tls_free_lib()
|
|||
}
|
||||
|
||||
void
|
||||
tls_clear_error()
|
||||
tls_clear_error(void)
|
||||
{
|
||||
ERR_clear_error();
|
||||
}
|
||||
|
|
@ -484,15 +484,7 @@ tls_ctx_load_ecdh_params(struct tls_root_ctx *ctx, const char *curve_name
|
|||
|
||||
/* Generate a new ECDH key for each SSL session (for non-ephemeral ECDH) */
|
||||
SSL_CTX_set_options(ctx->ctx, SSL_OP_SINGLE_ECDH_USE);
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
/* OpenSSL 1.0.2 and newer can automatically handle ECDH parameter loading */
|
||||
if (NULL == curve_name)
|
||||
{
|
||||
SSL_CTX_set_ecdh_auto(ctx->ctx, 1);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
/* For older OpenSSL, we'll have to do the parameter loading on our own */
|
||||
|
||||
if (curve_name != NULL)
|
||||
{
|
||||
/* Use user supplied curve if given */
|
||||
|
|
@ -501,14 +493,17 @@ tls_ctx_load_ecdh_params(struct tls_root_ctx *ctx, const char *curve_name
|
|||
}
|
||||
else
|
||||
{
|
||||
/* Extract curve from key */
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
/* OpenSSL 1.0.2 and newer can automatically handle ECDH parameter
|
||||
* loading */
|
||||
SSL_CTX_set_ecdh_auto(ctx->ctx, 1);
|
||||
return;
|
||||
#else
|
||||
/* For older OpenSSL we have to extract the curve from key on our own */
|
||||
EC_KEY *eckey = NULL;
|
||||
const EC_GROUP *ecgrp = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)
|
||||
pkey = SSL_CTX_get0_privatekey(ctx->ctx);
|
||||
#else
|
||||
/* Little hack to get private key ref from SSL_CTX, yay OpenSSL... */
|
||||
SSL *ssl = SSL_new(ctx->ctx);
|
||||
if (!ssl)
|
||||
|
|
@ -517,7 +512,6 @@ tls_ctx_load_ecdh_params(struct tls_root_ctx *ctx, const char *curve_name
|
|||
}
|
||||
pkey = SSL_get_privatekey(ssl);
|
||||
SSL_free(ssl);
|
||||
#endif
|
||||
|
||||
msg(D_TLS_DEBUG, "Extracting ECDH curve from private key");
|
||||
|
||||
|
|
@ -526,6 +520,7 @@ tls_ctx_load_ecdh_params(struct tls_root_ctx *ctx, const char *curve_name
|
|||
{
|
||||
nid = EC_GROUP_get_curve_name(ecgrp);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Translate NID back to name , just for kicks */
|
||||
|
|
@ -710,7 +705,7 @@ tls_ctx_add_extra_certs(struct tls_root_ctx *ctx, BIO *bio)
|
|||
for (;; )
|
||||
{
|
||||
cert = NULL;
|
||||
if (!PEM_read_bio_X509(bio, &cert, 0, NULL)) /* takes ownership of cert */
|
||||
if (!PEM_read_bio_X509(bio, &cert, NULL, NULL)) /* takes ownership of cert */
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
|
@ -808,12 +803,6 @@ tls_ctx_load_cert_file(struct tls_root_ctx *ctx, const char *cert_file,
|
|||
tls_ctx_load_cert_file_and_copy(ctx, cert_file, cert_file_inline, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
tls_ctx_free_cert_file(X509 *x509)
|
||||
{
|
||||
X509_free(x509);
|
||||
}
|
||||
|
||||
int
|
||||
tls_ctx_load_priv_file(struct tls_root_ctx *ctx, const char *priv_key_file,
|
||||
const char *priv_key_file_inline
|
||||
|
|
@ -1077,6 +1066,13 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx,
|
|||
ASSERT(pkey); /* NULL before SSL_CTX_use_certificate() is called */
|
||||
pub_rsa = EVP_PKEY_get0_RSA(pkey);
|
||||
|
||||
/* Certificate might not be RSA but DSA or EC */
|
||||
if (!pub_rsa)
|
||||
{
|
||||
crypto_msg(M_WARN, "management-external-key requires a RSA certificate");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* initialize RSA object */
|
||||
const BIGNUM *n = NULL;
|
||||
const BIGNUM *e = NULL;
|
||||
|
|
@ -1327,7 +1323,7 @@ static time_t biofp_last_open; /* GLOBAL */
|
|||
static const int biofp_reopen_interval = 600; /* GLOBAL */
|
||||
|
||||
static void
|
||||
close_biofp()
|
||||
close_biofp(void)
|
||||
{
|
||||
if (biofp)
|
||||
{
|
||||
|
|
@ -1337,7 +1333,7 @@ close_biofp()
|
|||
}
|
||||
|
||||
static void
|
||||
open_biofp()
|
||||
open_biofp(void)
|
||||
{
|
||||
const time_t current = time(NULL);
|
||||
const pid_t pid = getpid();
|
||||
|
|
@ -1683,18 +1679,36 @@ print_details(struct key_state_ssl *ks_ssl, const char *prefix)
|
|||
EVP_PKEY *pkey = X509_get_pubkey(cert);
|
||||
if (pkey != NULL)
|
||||
{
|
||||
if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA && EVP_PKEY_get0_RSA(pkey) != NULL)
|
||||
if ((EVP_PKEY_id(pkey) == EVP_PKEY_RSA) && (EVP_PKEY_get0_RSA(pkey) != NULL))
|
||||
{
|
||||
RSA *rsa = EVP_PKEY_get0_RSA(pkey);
|
||||
openvpn_snprintf(s2, sizeof(s2), ", %d bit RSA",
|
||||
RSA_bits(rsa));
|
||||
}
|
||||
else if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA && EVP_PKEY_get0_DSA(pkey) != NULL)
|
||||
else if ((EVP_PKEY_id(pkey) == EVP_PKEY_DSA) && (EVP_PKEY_get0_DSA(pkey) != NULL))
|
||||
{
|
||||
DSA *dsa = EVP_PKEY_get0_DSA(pkey);
|
||||
openvpn_snprintf(s2, sizeof(s2), ", %d bit DSA",
|
||||
DSA_bits(dsa));
|
||||
}
|
||||
#ifndef OPENSSL_NO_EC
|
||||
else if ((EVP_PKEY_id(pkey) == EVP_PKEY_EC) && (EVP_PKEY_get0_EC_KEY(pkey) != NULL))
|
||||
{
|
||||
EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey);
|
||||
const EC_GROUP *group = EC_KEY_get0_group(ec);
|
||||
const char* curve;
|
||||
|
||||
int nid = EC_GROUP_get_curve_name(group);
|
||||
if (nid == 0 || (curve = OBJ_nid2sn(nid)) == NULL)
|
||||
{
|
||||
curve = "Error getting curve name";
|
||||
}
|
||||
|
||||
openvpn_snprintf(s2, sizeof(s2), ", %d bit EC, curve: %s",
|
||||
EC_GROUP_order_bits(group), curve);
|
||||
|
||||
}
|
||||
#endif
|
||||
EVP_PKEY_free(pkey);
|
||||
}
|
||||
X509_free(cert);
|
||||
|
|
@ -1755,7 +1769,7 @@ show_available_tls_ciphers(const char *cipher_list)
|
|||
* in the OpenSSL library.
|
||||
*/
|
||||
void
|
||||
show_available_curves()
|
||||
show_available_curves(void)
|
||||
{
|
||||
#ifndef OPENSSL_NO_EC
|
||||
EC_builtin_curve *curves = NULL;
|
||||
|
|
|
|||
|
|
@ -202,8 +202,8 @@ extract_x509_field_ssl(X509_NAME *x509, const char *field_name, char *out,
|
|||
{
|
||||
int lastpos = -1;
|
||||
int tmp = -1;
|
||||
X509_NAME_ENTRY *x509ne = 0;
|
||||
ASN1_STRING *asn1 = 0;
|
||||
X509_NAME_ENTRY *x509ne = NULL;
|
||||
ASN1_STRING *asn1 = NULL;
|
||||
unsigned char *buf = NULL;
|
||||
ASN1_OBJECT *field_name_obj = OBJ_txt2obj(field_name, 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ status_flush(struct status_output *so)
|
|||
const off_t off = lseek(so->fd, (off_t)0, SEEK_CUR);
|
||||
if (ftruncate(so->fd, off) != 0)
|
||||
{
|
||||
msg(M_WARN, "Failed to truncate status file: %s", strerror(errno));
|
||||
msg(M_WARN | M_ERRNO, "Failed to truncate status file");
|
||||
}
|
||||
}
|
||||
#elif defined(HAVE_CHSIZE)
|
||||
|
|
|
|||
|
|
@ -74,6 +74,8 @@
|
|||
#ifndef TLSCRYPT_H
|
||||
#define TLSCRYPT_H
|
||||
|
||||
#ifdef ENABLE_CRYPTO
|
||||
|
||||
#include "buffer.h"
|
||||
#include "crypto.h"
|
||||
#include "session_id.h"
|
||||
|
|
@ -140,4 +142,6 @@ bool tls_crypt_unwrap(const struct buffer *src, struct buffer *dst,
|
|||
|
||||
/** @} */
|
||||
|
||||
#endif /* ENABLE_CRYPTO */
|
||||
|
||||
#endif /* TLSCRYPT_H */
|
||||
|
|
|
|||
|
|
@ -1863,7 +1863,7 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun
|
|||
if (oldtunfd >=0 && android_method == ANDROID_OPEN_AFTER_CLOSE)
|
||||
{
|
||||
platform_close(oldtunfd);
|
||||
openvpn_sleep(2);
|
||||
management_sleep(2);
|
||||
}
|
||||
|
||||
if (oldtunfd >=0 && android_method == ANDROID_KEEP_OLD_TUN)
|
||||
|
|
@ -2564,8 +2564,7 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun
|
|||
|
||||
if (ioctl(tt->fd, TUNGIFINFO, &info) < 0)
|
||||
{
|
||||
msg(M_WARN | M_ERRNO, "Can't get interface info: %s",
|
||||
strerror(errno));
|
||||
msg(M_WARN | M_ERRNO, "Can't get interface info");
|
||||
}
|
||||
|
||||
#ifdef IFF_MULTICAST /* openbsd 4.x doesn't have this */
|
||||
|
|
@ -2574,8 +2573,7 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun
|
|||
|
||||
if (ioctl(tt->fd, TUNSIFINFO, &info) < 0)
|
||||
{
|
||||
msg(M_WARN | M_ERRNO, "Can't set interface info: %s",
|
||||
strerror(errno));
|
||||
msg(M_WARN | M_ERRNO, "Can't set interface info");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2664,7 +2662,7 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun
|
|||
i = 1;
|
||||
if (ioctl(tt->fd, TUNSIFHEAD, &i) < 0) /* multi-af mode on */
|
||||
{
|
||||
msg(M_WARN | M_ERRNO, "ioctl(TUNSIFHEAD): %s", strerror(errno));
|
||||
msg(M_WARN | M_ERRNO, "ioctl(TUNSIFHEAD)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2797,12 +2795,12 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun
|
|||
|
||||
if (ioctl(tt->fd, TUNSIFMODE, &i) < 0)
|
||||
{
|
||||
msg(M_WARN | M_ERRNO, "ioctl(TUNSIFMODE): %s", strerror(errno));
|
||||
msg(M_WARN | M_ERRNO, "ioctl(TUNSIFMODE)");
|
||||
}
|
||||
i = 1;
|
||||
if (ioctl(tt->fd, TUNSIFHEAD, &i) < 0)
|
||||
{
|
||||
msg(M_WARN | M_ERRNO, "ioctl(TUNSIFHEAD): %s", strerror(errno));
|
||||
msg(M_WARN | M_ERRNO, "ioctl(TUNSIFHEAD)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3023,16 +3021,14 @@ utun_open_helper(struct ctl_info ctlInfo, int utunnum)
|
|||
|
||||
if (fd < 0)
|
||||
{
|
||||
msg(M_INFO, "Opening utun (%s): %s", "socket(SYSPROTO_CONTROL)",
|
||||
strerror(errno));
|
||||
msg(M_INFO | M_ERRNO, "Opening utun (socket(SYSPROTO_CONTROL))");
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (ioctl(fd, CTLIOCGINFO, &ctlInfo) == -1)
|
||||
{
|
||||
platform_close(fd);
|
||||
msg(M_INFO, "Opening utun (%s): %s", "ioctl(CTLIOCGINFO)",
|
||||
strerror(errno));
|
||||
msg(M_INFO | M_ERRNO, "Opening utun (ioctl(CTLIOCGINFO))");
|
||||
return -2;
|
||||
}
|
||||
|
||||
|
|
@ -3050,8 +3046,7 @@ utun_open_helper(struct ctl_info ctlInfo, int utunnum)
|
|||
|
||||
if (connect(fd, (struct sockaddr *)&sc, sizeof(sc)) < 0)
|
||||
{
|
||||
msg(M_INFO, "Opening utun (%s): %s", "connect(AF_SYS_CONTROL)",
|
||||
strerror(errno));
|
||||
msg(M_INFO | M_ERRNO, "Opening utun (connect(AF_SYS_CONTROL))");
|
||||
platform_close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -5005,7 +5000,7 @@ netsh_command(const struct argv *a, int n, int msglevel)
|
|||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
bool status;
|
||||
openvpn_sleep(1);
|
||||
management_sleep(1);
|
||||
netcmd_semaphore_lock();
|
||||
argv_msg_prefix(M_INFO, a, "NETSH");
|
||||
status = openvpn_execve_check(a, NULL, 0, "ERROR: netsh command failed");
|
||||
|
|
@ -5014,7 +5009,7 @@ netsh_command(const struct argv *a, int n, int msglevel)
|
|||
{
|
||||
return;
|
||||
}
|
||||
openvpn_sleep(4);
|
||||
management_sleep(4);
|
||||
}
|
||||
msg(msglevel, "NETSH: command failed");
|
||||
}
|
||||
|
|
@ -5997,7 +5992,7 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun
|
|||
if (s > 0)
|
||||
{
|
||||
msg(M_INFO, "Sleeping for %d seconds...", s);
|
||||
openvpn_sleep(s);
|
||||
management_sleep(s);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1235,7 +1235,7 @@ set_win_sys_path_via_env(struct env_set *es)
|
|||
|
||||
|
||||
const char *
|
||||
win_get_tempdir()
|
||||
win_get_tempdir(void)
|
||||
{
|
||||
static char tmpdir[MAX_PATH];
|
||||
WCHAR wtmpdir[MAX_PATH];
|
||||
|
|
@ -1398,7 +1398,7 @@ win_wfp_uninit(const NET_IFINDEX index, const HANDLE msg_channel)
|
|||
}
|
||||
|
||||
int
|
||||
win32_version_info()
|
||||
win32_version_info(void)
|
||||
{
|
||||
if (!IsWindowsXPOrGreater())
|
||||
{
|
||||
|
|
@ -1426,7 +1426,7 @@ win32_version_info()
|
|||
}
|
||||
|
||||
bool
|
||||
win32_is_64bit()
|
||||
win32_is_64bit(void)
|
||||
{
|
||||
#if defined(_WIN64)
|
||||
return true; /* 64-bit programs run only on Win64 */
|
||||
|
|
|
|||
|
|
@ -285,7 +285,7 @@ char *get_win_sys_path(void);
|
|||
void fork_to_self(const char *cmdline);
|
||||
|
||||
/* Find temporary directory */
|
||||
const char *win_get_tempdir();
|
||||
const char *win_get_tempdir(void);
|
||||
|
||||
/* Convert a string from UTF-8 to UCS-2 */
|
||||
WCHAR *wide_string(const char *utf8, struct gc_arena *gc);
|
||||
|
|
@ -299,7 +299,7 @@ bool win_wfp_uninit(const NET_IFINDEX index, const HANDLE msg_channel);
|
|||
#define WIN_7 2
|
||||
#define WIN_8 3
|
||||
|
||||
int win32_version_info();
|
||||
int win32_version_info(void);
|
||||
|
||||
/*
|
||||
* String representation of Windows version number and name, see
|
||||
|
|
|
|||
|
|
@ -13,24 +13,6 @@
|
|||
#include "argv.h"
|
||||
#include "buffer.h"
|
||||
|
||||
/*
|
||||
* This is defined here to prevent #include'ing misc.h
|
||||
* which makes things difficult beyond any recognition
|
||||
*/
|
||||
size_t
|
||||
adjust_power_of_2(size_t u)
|
||||
{
|
||||
size_t ret = 1;
|
||||
|
||||
while (ret < u)
|
||||
{
|
||||
ret <<= 1;
|
||||
assert(ret > 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Defines for use in the tests and the mock parse_line() */
|
||||
#define PATH1 "/s p a c e"
|
||||
#define PATH2 "/foo bar/baz"
|
||||
|
|
|
|||
Loading…
Reference in a new issue