summaryrefslogtreecommitdiff
path: root/contrib/keychain-mcd
diff options
context:
space:
mode:
authorBernhard Schmidt <berni@debian.org>2018-03-04 22:22:32 +0100
committerBernhard Schmidt <berni@debian.org>2018-03-04 22:22:32 +0100
commitcf55ab99392458e723c7ebcc32c19bbd225b1f4b (patch)
treeb895b41b7629c9a31de5cc15e7aa7805ddac87ce /contrib/keychain-mcd
parent9683f890944ffb114f5f8214f694e0b339cf5a5a (diff)
New upstream version 2.4.5
Diffstat (limited to 'contrib/keychain-mcd')
-rw-r--r--contrib/keychain-mcd/Makefile13
-rw-r--r--contrib/keychain-mcd/cert_data.c866
-rw-r--r--contrib/keychain-mcd/cert_data.h50
-rw-r--r--contrib/keychain-mcd/common_osx.c100
-rw-r--r--contrib/keychain-mcd/common_osx.h38
-rw-r--r--contrib/keychain-mcd/crypto_osx.c79
-rw-r--r--contrib/keychain-mcd/crypto_osx.h44
-rw-r--r--contrib/keychain-mcd/keychain-mcd.8161
-rw-r--r--contrib/keychain-mcd/main.c310
9 files changed, 0 insertions, 1661 deletions
diff --git a/contrib/keychain-mcd/Makefile b/contrib/keychain-mcd/Makefile
deleted file mode 100644
index c6431df..0000000
--- a/contrib/keychain-mcd/Makefile
+++ /dev/null
@@ -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 $@
diff --git a/contrib/keychain-mcd/cert_data.c b/contrib/keychain-mcd/cert_data.c
deleted file mode 100644
index c04f68e..0000000
--- a/contrib/keychain-mcd/cert_data.c
+++ /dev/null
@@ -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;
-}
diff --git a/contrib/keychain-mcd/cert_data.h b/contrib/keychain-mcd/cert_data.h
deleted file mode 100644
index c01251f..0000000
--- a/contrib/keychain-mcd/cert_data.h
+++ /dev/null
@@ -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__ */
diff --git a/contrib/keychain-mcd/common_osx.c b/contrib/keychain-mcd/common_osx.c
deleted file mode 100644
index f817814..0000000
--- a/contrib/keychain-mcd/common_osx.c
+++ /dev/null
@@ -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);
-}
diff --git a/contrib/keychain-mcd/common_osx.h b/contrib/keychain-mcd/common_osx.h
deleted file mode 100644
index d37e059..0000000
--- a/contrib/keychain-mcd/common_osx.h
+++ /dev/null
@@ -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__ */
diff --git a/contrib/keychain-mcd/crypto_osx.c b/contrib/keychain-mcd/crypto_osx.c
deleted file mode 100644
index 27ac4f5..0000000
--- a/contrib/keychain-mcd/crypto_osx.c
+++ /dev/null
@@ -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;
- }
-}
diff --git a/contrib/keychain-mcd/crypto_osx.h b/contrib/keychain-mcd/crypto_osx.h
deleted file mode 100644
index 9f4b3f9..0000000
--- a/contrib/keychain-mcd/crypto_osx.h
+++ /dev/null
@@ -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__ */
diff --git a/contrib/keychain-mcd/keychain-mcd.8 b/contrib/keychain-mcd/keychain-mcd.8
deleted file mode 100644
index 676b164..0000000
--- a/contrib/keychain-mcd/keychain-mcd.8
+++ /dev/null
@@ -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)
diff --git a/contrib/keychain-mcd/main.c b/contrib/keychain-mcd/main.c
deleted file mode 100644
index c1d091e..0000000
--- a/contrib/keychain-mcd/main.c
+++ /dev/null
@@ -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);
-}