dotMacTpRpcGlue.cpp [plain text]
#include "dotMacTpRpcGlue.h"
#include "dotMacTpUtils.h"
#include "dotMacTpDebug.h"
#include "dotMacTpMutils.h"
#include <stdint.h>
#include <CoreFoundation/CoreFoundation.h>
#include "dotMacXmlRpc.h"
#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
#include <Security/cssmapple.h>
#if DICTIONARY_DEBUG
#define RESULTS_DICTIONARY_DEBUG 1
#define REQUEST_DICTIONARY_DEBUG 1
#else
#define RESULTS_DICTIONARY_DEBUG 0
#define REQUEST_DICTIONARY_DEBUG 0
#endif
#ifndef NDEBUG
#define FORCE_SUCCESS_QUEUED 0
#else
#define FORCE_SUCCESS_QUEUED 0
#endif
#if FORCE_SUCCESS_QUEUED
int forceQueued = 1;
#endif
#ifndef NDEBUG
#define FORCE_SUCCESS_QUEUED_ALWAYS 0
#else
#define FORCE_SUCCESS_QUEUED 0
#endif
#define CFRELEASE(cf) \
if(cf != NULL) { \
CFRelease(cf); \
}
static CFStringRef kMethodSignIChatEncrypt = CFSTR("sign." DOT_MAC_CERT_TYPE_ICHAT);
static CFStringRef kMethodSignSharedServices = CFSTR("sign." DOT_MAC_CERT_TYPE_SHARED_SERVICES);
static CFStringRef kMethodSignEmailSigning = CFSTR("sign." DOT_MAC_CERT_TYPE_EMAIL_SIGNING);
static CFStringRef kMethodSignEmailEncryption = CFSTR("sign." DOT_MAC_CERT_TYPE_EMAIL_ENCRYPT);
static CFStringRef kMethodStatusIChatEncrypt = CFSTR("status." DOT_MAC_CERT_TYPE_ICHAT);
static CFStringRef kMethodStatusSharedServices = CFSTR("status." DOT_MAC_CERT_TYPE_SHARED_SERVICES);
static CFStringRef kMethodStatusEmailSigning = CFSTR("status." DOT_MAC_CERT_TYPE_EMAIL_SIGNING);
static CFStringRef kMethodStatusEmailEncryption = CFSTR("status." DOT_MAC_CERT_TYPE_EMAIL_ENCRYPT);
static CFStringRef kMethodArchiveList = CFSTR("archive.list");
static CFStringRef kMethodArchiveSave = CFSTR("archive.save");
static CFStringRef kMethodArchiveFetch = CFSTR("archive.fetch");
static CFStringRef kMethodArchiveRemove = CFSTR("archive.remove");
static CFStringRef kParamSignIssue = CFSTR("issue");
static CFStringRef kParamCertTypeIChat = CFSTR(DOT_MAC_CERT_TYPE_ICHAT);
static CFStringRef kParamCertTypeSharedServices = CFSTR(DOT_MAC_CERT_TYPE_SHARED_SERVICES);
static CFStringRef kParamCertTypeEmailEncryption = CFSTR(DOT_MAC_CERT_TYPE_EMAIL_SIGNING);
static CFStringRef kParamCertTypeEmailSigning = CFSTR(DOT_MAC_CERT_TYPE_EMAIL_ENCRYPT);
static CFStringRef kResponseResultCode = CFSTR("resultCode");
static CFStringRef kResponseResultBody = CFSTR("resultBody");
static CFStringRef kArchiveListName = CFSTR("name");
static CFStringRef kArchiveListExpires = CFSTR("expires");
static CFStringRef kArchiveListType = CFSTR("type");
static CFStringRef kArchiveListSerialNumber = CFSTR("serial");
static CFStringRef kResultSuccess = CFSTR("Success");
static CFStringRef kResultQueued = CFSTR("SuccessQueued");
static CFStringRef kResultRedirected = CFSTR("SuccessRedirected");
static CFStringRef kResultFailed = CFSTR("Failed");
static CFStringRef kResultAlreadyExists = CFSTR("FailedAlreadyExists");
static CFStringRef kResultCertAlreadyExists = CFSTR("FailedCertAlreadyExists");
static CFStringRef kResultServiceError = CFSTR("FailedServiceError");
static CFStringRef kResultParameterError = CFSTR("FailedParameterError");
static CFStringRef kResultNotAllowed = CFSTR("FailedNotAllowed");
static CFStringRef kResultPendingCSR = CFSTR("FailedPendingCSR");
static CFStringRef kResultNoExistingCSR = CFSTR("FailedNoExistingCSR");
static CFStringRef kResultNotSupportForAccount = CFSTR("FailedNotSupportedForAccount");
static CFStringRef kResultCSRDidNotVerify = CFSTR("FailedCSRDidNotVerify");
static CFStringRef kResultNotImplemented = CFSTR("NotImplemented");
static CFStringRef kResultNotAuthorized = CFSTR("NotAuthorized");
static CFStringRef kResultNotAvailable = CFSTR("NotAvailable");
static CFStringRef kResultConsistencyCheck = CFSTR("FailedConsistencyCheck");
static CFStringRef kP1 = CFSTR("p1");
static CFStringRef kP2 = CFSTR("p2");
static CFStringRef kP3 = CFSTR("p3");
static CFStringRef kP4 = CFSTR("p4");
static CFStringRef kP5 = CFSTR("p5");
static OSStatus dotMacParseResult(
CFStringRef resultCode)
{
if(CFEqual(resultCode, kResultSuccess)) {
#if FORCE_SUCCESS_QUEUED
if(forceQueued) {
printf("...Forcing REQ_QUEUED status\n");
return CSSMERR_APPLE_DOTMAC_REQ_QUEUED;
}
#endif
return noErr;
}
else if(CFEqual(resultCode, kResultQueued)) {
return CSSMERR_APPLE_DOTMAC_REQ_QUEUED;
}
else if(CFEqual(resultCode, kResultRedirected)) {
return CSSMERR_APPLE_DOTMAC_REQ_REDIRECT;
}
else if(CFEqual(resultCode, kResultFailed)) {
return CSSMERR_APPLE_DOTMAC_REQ_SERVER_ERR;
}
else if(CFEqual(resultCode, kResultAlreadyExists) ||
CFEqual(resultCode, kResultCertAlreadyExists)) {
return CSSMERR_APPLE_DOTMAC_REQ_SERVER_ALREADY_EXIST;
}
else if(CFEqual(resultCode, kResultParameterError)) {
return CSSMERR_APPLE_DOTMAC_REQ_SERVER_PARAM;
}
else if(CFEqual(resultCode, kResultNotAllowed)) {
return CSSMERR_APPLE_DOTMAC_REQ_SERVER_AUTH;
}
else if(CFEqual(resultCode, kResultPendingCSR)) {
return CSSMERR_APPLE_DOTMAC_REQ_IS_PENDING;
}
else if(CFEqual(resultCode, kResultNoExistingCSR)) {
return CSSMERR_APPLE_DOTMAC_NO_REQ_PENDING;
}
else if(CFEqual(resultCode, kResultNotSupportForAccount)) {
return CSSMERR_TP_REQUEST_REJECTED;
}
else if(CFEqual(resultCode, kResultCSRDidNotVerify)) {
return CSSMERR_APPLE_DOTMAC_CSR_VERIFY_FAIL;
}
else if(CFEqual(resultCode, kResultServiceError)) {
return CSSMERR_APPLE_DOTMAC_REQ_SERVER_SERVICE_ERROR;
}
else if(CFEqual(resultCode, kResultNotImplemented)) {
return CSSMERR_APPLE_DOTMAC_REQ_SERVER_UNIMPL;
}
else if(CFEqual(resultCode, kResultNotAuthorized)) {
return CSSMERR_APPLE_DOTMAC_REQ_SERVER_AUTH;
}
else if(CFEqual(resultCode, kResultNotAvailable)) {
return CSSMERR_APPLE_DOTMAC_REQ_SERVER_NOT_AVAIL;
}
else if(CFEqual(resultCode, kResultConsistencyCheck)) {
return CSSMERR_APPLE_DOTMAC_FAILED_CONSISTENCY_CHECK;
}
else {
dotMacErrorLog("dotMacParseResult: unknown error\n");
return ioErr;
}
}
static inline CFStringRef cDataToCfstr(
const CSSM_DATA &cdata)
{
return CFStringCreateWithBytes(NULL,
cdata.Data, (CFIndex)cdata.Length,
kCFStringEncodingASCII, false);
}
static void cfstrToCdata(
const CFStringRef cfstr,
CSSM_DATA &cdata,
Allocator &alloc)
{
CFDataRef cfData = CFStringCreateExternalRepresentation(NULL,
cfstr, kCFStringEncodingUTF8, 0);
if(cfData == NULL) {
dotMacErrorLog("dotMac cfstrToCdatafailure");
CssmError::throwMe(internalComponentErr);
}
cdata.Length = CFDataGetLength(cfData);
cdata.Data = (uint8 *)alloc.malloc(cdata.Length);
memmove(cdata.Data, CFDataGetBytePtr(cfData), cdata.Length);
CFRelease(cfData);
}
static const char hexChars[] = "0123456789ABCDEF";
static CFStringRef cDataToCfAsciiStr(
const CSSM_DATA &cdata)
{
if(cdata.Length > sizeof(uint64)) {
char asciiData[(2 * cdata.Length) + 1];
const unsigned char *inp = (const unsigned char *)cdata.Data;
char *outp = asciiData;
for(unsigned dex=0; dex<cdata.Length; dex++) {
unsigned c = *inp++;
outp[1] = hexChars[c & 0xf];
c >>= 4;
outp[0] = hexChars[c];
outp += 2;
}
*outp = 0;
return CFStringCreateWithCString(NULL, asciiData, kCFStringEncodingASCII);
}
else {
uint64 value = 0;
for(unsigned i=0; i<cdata.Length; i++) {
value <<= 8;
value += cdata.Data[i];
}
char cStr[200];
snprintf(cStr, sizeof(cStr), "%llu", value);
return CFStringCreateWithCString(NULL, cStr, kCFStringEncodingASCII);
}
}
static void CfAsciiStrToCdata(
const CFStringRef cfStr,
CSSM_DATA &cdata,
Allocator &alloc)
{
CFDataRef strData = CFStringCreateExternalRepresentation(NULL, cfStr,
kCFStringEncodingASCII, 0);
if(strData == NULL) {
dotMacDebug("dotMac CfAsciiStrToCdata: ASCII conversion FAILED!");
return;
}
unsigned len = (unsigned)CFDataGetLength(strData);
const char *inp = (const char *)CFDataGetBytePtr(strData);
char cStr[len + 1];
memmove(cStr, inp, len);
cStr[len] = '\0';
uint64 val = 0;
sscanf(cStr, "%llu", &val);
int byteNum = 7; unsigned shift = 7*8; uint64 mask = 0xff00000000000000ULL;
while(val & mask) {
byteNum--;
shift -= 8;
mask >>= 8;
}
cdata.Data = (uint8 *)alloc.malloc(byteNum + 1);
cdata.Length = byteNum + 1;
uint8 *outp = cdata.Data;
do {
uint64 v = val >> shift;
*outp++ = v & 0xff;
shift -= 8;
byteNum--;
} while(byteNum >= 0);
CFRelease(strData);
}
static CFURLRef createUrl(
const char *schema,
const CSSM_DATA &hostName,
const char *path)
{
int schemaLen = strlen(schema);
int urlLength = schemaLen + hostName.Length + strlen(path) + 1;
char *urlStr = (char *)malloc(urlLength);
memmove(urlStr, schema, schemaLen);
memmove(urlStr + schemaLen, hostName.Data, hostName.Length);
urlStr[schemaLen + hostName.Length] = '\0';
strcat(urlStr, path);
CFURLRef url = CFURLCreateWithBytes(NULL, (const UInt8 *)urlStr, urlLength-1,
kCFStringEncodingASCII, NULL);
dotMacDebug("dotMac createUrl: URL %s", urlStr);
free(urlStr);
return url;
}
OSStatus dotMacPostCertReq(
DotMacCertTypeTag certType,
const CSSM_DATA &userName,
const CSSM_DATA &password,
const CSSM_DATA &hostName,
bool renew, const CSSM_DATA &csr, SecNssCoder &coder,
sint32 &estTime, CSSM_DATA &resultBodyData) {
resultBodyData.Data = NULL;
resultBodyData.Length = 0;
CFURLRef url = createUrl(DOT_MAC_SIGN_SCHEMA, hostName, DOT_MAC_SIGN_PATH);
CFStringRef userStr = cDataToCfstr(userName);
CFStringRef pwdStr = cDataToCfstr(password);
CFStringRef csrStr = cDataToCfstr(csr);
CFMutableDictionaryRef argDict;
CFMutableArrayRef argOrder;
CFStringRef method;
switch(certType) {
case CSSM_DOT_MAC_TYPE_ICHAT:
method = kMethodSignIChatEncrypt;
break;
case CSSM_DOT_MAC_TYPE_SHARED_SERVICES:
method = kMethodSignSharedServices;
break;
case CSSM_DOT_MAC_TYPE_EMAIL_ENCRYPT:
method = kMethodSignEmailEncryption;
break;
case CSSM_DOT_MAC_TYPE_EMAIL_SIGNING:
method = kMethodSignEmailSigning;
break;
default:
return paramErr;
}
argDict = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
argOrder = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
CFDictionaryAddValue(argDict, kP1, kParamSignIssue);
CFArrayAppendValue(argOrder, kP1);
CFDictionaryAddValue(argDict, kP2, csrStr);
CFArrayAppendValue(argOrder, kP2);
OSStatus ortn;
CFDictionaryRef resultDict = NULL;
uint32_t httpStat;
ortn = performAuthenticatedXMLRPC(url, method, argDict, argOrder, userStr, pwdStr,
&resultDict, &httpStat);
if(ortn) {
#if FORCE_SUCCESS_QUEUED_ALWAYS
dotMacErrorLog("dotMacPostCertReq: FORCING queued success\n");
ortn = CSSMERR_APPLE_DOTMAC_REQ_QUEUED;
goto proceedQueued;
#endif
dotMacErrorLog("dotMacPostCertReq: XMLRPC returned %ld\n", ortn);
goto errOut;
}
if(resultDict == NULL) {
dotMacErrorLog("dotMacPostCertReq: XMLRPC failed to return a dictionary\n");
ortn = ioErr;
goto errOut;
}
#if RESULTS_DICTIONARY_DEBUG
dumpDictionary("Results dictionary", resultDict);
#endif
CFStringRef resultCode;
resultCode = (CFStringRef)CFDictionaryGetValue(resultDict, kResponseResultCode);
if((resultCode == NULL) || (CFGetTypeID(resultCode) != CFStringGetTypeID())) {
dotMacErrorLog("dotMacPostCertReq: resultCode is not a string\n");
ortn = ioErr;
goto errOut;
}
ortn = dotMacParseResult(resultCode);
#if FORCE_SUCCESS_QUEUED_ALWAYS
proceedQueued:
#endif
switch(ortn) {
case noErr:
case CSSMERR_APPLE_DOTMAC_REQ_REDIRECT:
{
CFStringRef resultBody;
resultBody = (CFStringRef)CFDictionaryGetValue(resultDict,
kResponseResultBody);
if((resultBody == NULL) ||(CFGetTypeID(resultBody) != CFStringGetTypeID())) {
dotMacErrorLog("dotMacPostCertReq: resultBody is not a string\n");
ortn = ioErr;
goto errOut;
}
CFIndex len = CFStringGetLength(resultBody);
coder.allocItem(resultBodyData, (size_t)len + 1);
if(!CFStringGetCString(resultBody, (char *)resultBodyData.Data, len+1,
kCFStringEncodingUTF8)) {
dotMacErrorLog("dotMacPostCertReq: resultBody is not convertible to "
"UTF8\n");
ortn = ioErr;
}
break;
}
case CSSMERR_APPLE_DOTMAC_REQ_QUEUED:
{
CSSM_DATA host = { 0, NULL };
CSSM_DATA domain = { 0, NULL };
dotMacTokenizeHostName(hostName, host, domain);
ortn = dotMacEncodeRefId(userName, domain, certType, coder, resultBodyData);
if(ortn == noErr) {
ortn = CSSMERR_APPLE_DOTMAC_REQ_QUEUED;
}
CFStringRef resultBody;
resultBody = (CFStringRef)CFDictionaryGetValue(resultDict,
kResponseResultBody);
if((resultBody == NULL) ||(CFGetTypeID(resultBody) != CFStringGetTypeID())) {
dotMacErrorLog("dotMacPostCertReq: resultBody is not a string\n");
ortn = ioErr;
goto errOut;
}
SInt32 timeValue = CFStringGetIntValue(resultBody);
estTime = (sint32) timeValue;
break;
}
default:
dotMacErrorLog("dotMacPostCertReq: unhandled result %d\n", (int)ortn);
break;
}
errOut:
CFRelease(url);
CFRelease(userStr);
CFRelease(pwdStr);
CFRelease(csrStr);
CFRelease(argDict);
CFRelease(argOrder);
if(resultDict) {
CFRelease(resultDict);
}
return ortn;
}
static OSStatus dotMacReturnArchiveList_v1(
CFDictionaryRef resultDict,
unsigned *numArchives, DotMacArchive **archives, Allocator &alloc)
{
CFArrayRef archList;
archList = (CFArrayRef)CFDictionaryGetValue(resultDict,
kResponseResultBody);
if((archList == NULL) || (CFGetTypeID(archList) != CFArrayGetTypeID())) {
dotMacErrorLog("archive(list): resultBody is not an array\n");
return ioErr;
}
assert(numArchives != NULL);
assert(archives != NULL);
CFIndex numEntries = CFArrayGetCount(archList);
*archives = (DotMacArchive *)alloc.malloc(sizeof(DotMacArchive) * numEntries);
memset(*archives, 0, sizeof(DotMacArchive) * numEntries);
for(CFIndex dex=0; dex<numEntries; dex++) {
DotMacArchive *dmarc = &((*archives)[dex]);
CFDictionaryRef dict =
(CFDictionaryRef)CFArrayGetValueAtIndex(archList, dex);
if((dict == NULL) || (CFGetTypeID(dict) != CFDictionaryGetTypeID())) {
dotMacErrorLog("archive(list): result element is not a dict\n");
return ioErr;
}
CFStringRef cfstr = (CFStringRef)CFDictionaryGetValue(dict,
kArchiveListName);
if((cfstr == NULL) || (CFGetTypeID(cfstr) != CFStringGetTypeID())) {
dotMacErrorLog("archive(list): archiveName is not a string\n");
return ioErr;
}
cfstrToCdata(cfstr, dmarc->archiveName, alloc);
cfstr = (CFStringRef)CFDictionaryGetValue(dict, kArchiveListExpires);
if((cfstr == NULL) || (CFGetTypeID(cfstr) != CFStringGetTypeID())) {
dotMacErrorLog("archive(list): expires is not a string\n");
return ioErr;
}
cfstrToCdata(cfstr, dmarc->timeString, alloc);
}
*numArchives = numEntries;
return noErr;
}
static OSStatus dotMacReturnArchiveList_v2(
CFDictionaryRef resultDict,
unsigned *numArchives, DotMacArchive_v2 **archives, Allocator &alloc)
{
CFArrayRef archList;
archList = (CFArrayRef)CFDictionaryGetValue(resultDict,
kResponseResultBody);
if((archList == NULL) || (CFGetTypeID(archList) != CFArrayGetTypeID())) {
dotMacErrorLog("archive(list): resultBody is not an array\n");
return ioErr;
}
assert(numArchives != NULL);
assert(archives != NULL);
CFIndex numEntries = CFArrayGetCount(archList);
*archives = (DotMacArchive_v2 *)alloc.malloc(sizeof(DotMacArchive_v2) * numEntries);
memset(*archives, 0, sizeof(DotMacArchive_v2) * numEntries);
for(CFIndex dex=0; dex<numEntries; dex++) {
DotMacArchive_v2 *dmarc = &((*archives)[dex]);
CFDictionaryRef dict =
(CFDictionaryRef)CFArrayGetValueAtIndex(archList, dex);
if((dict == NULL) || (CFGetTypeID(dict) != CFDictionaryGetTypeID())) {
dotMacErrorLog("archive(list): result element is not a dict\n");
return ioErr;
}
CFStringRef cfstr = (CFStringRef)CFDictionaryGetValue(dict,
kArchiveListName);
if((cfstr == NULL) || (CFGetTypeID(cfstr) != CFStringGetTypeID())) {
dotMacErrorLog("archive(list): archiveName is not a string\n");
return ioErr;
}
cfstrToCdata(cfstr, dmarc->archiveName, alloc);
cfstr = (CFStringRef)CFDictionaryGetValue(dict, kArchiveListExpires);
if((cfstr == NULL) || (CFGetTypeID(cfstr) != CFStringGetTypeID())) {
dotMacErrorLog("archive(list): expires is not a string\n");
return ioErr;
}
cfstrToCdata(cfstr, dmarc->timeString, alloc);
cfstr = (CFStringRef)CFDictionaryGetValue(dict, kArchiveListType);
if((cfstr == NULL) || (CFGetTypeID(cfstr) != CFStringGetTypeID())) {
dotMacErrorLog("archive(list): CertType is not a string\n");
return ioErr;
}
if(CFEqual(cfstr, kParamCertTypeIChat)) {
dmarc->certTypeTag = CSSM_DOT_MAC_TYPE_ICHAT;
}
else if(CFEqual(cfstr, kParamCertTypeSharedServices)) {
dmarc->certTypeTag = CSSM_DOT_MAC_TYPE_SHARED_SERVICES;
}
else if(CFEqual(cfstr, kParamCertTypeEmailEncryption)) {
dmarc->certTypeTag = CSSM_DOT_MAC_TYPE_EMAIL_ENCRYPT;
}
else if(CFEqual(cfstr, kParamCertTypeEmailSigning)) {
dmarc->certTypeTag = CSSM_DOT_MAC_TYPE_EMAIL_SIGNING;
}
else {
dmarc->certTypeTag = CSSM_DOT_MAC_TYPE_UNSPECIFIED;
}
cfstr = (CFStringRef)CFDictionaryGetValue(dict, kArchiveListSerialNumber);
if((cfstr == NULL) || (CFGetTypeID(cfstr) != CFStringGetTypeID())) {
dotMacErrorLog("archive(list): Serial Number is not a string\n");
return ioErr;
}
CfAsciiStrToCdata(cfstr, dmarc->serialNumber, alloc);
}
*numArchives = numEntries;
return noErr;
}
OSStatus dotMacPostArchiveReq(
uint32 version,
DotMacCertTypeTag certTypeTag,
DotMacArchiveType archiveType,
const CSSM_DATA &userName,
const CSSM_DATA &password,
const CSSM_DATA &hostName,
const CSSM_DATA *archiveName,
const CSSM_DATA *pfxIn, const CSSM_DATA *timeString, const CSSM_DATA *serialNumber, CSSM_DATA *pfxOut, unsigned *numArchives, DotMacArchive **archives_v1, DotMacArchive_v2 **archives_v2,
Allocator &alloc)
{
if(pfxOut) {
pfxOut->Data = NULL;
pfxOut->Length = 0;
}
if(numArchives) {
*numArchives = 0;
}
if(archives_v1) {
*archives_v1 = NULL;
}
if(archives_v2) {
*archives_v2 = NULL;
}
CFURLRef url = createUrl(DOT_MAC_ARCHIVE_SCHEMA, hostName, DOT_MAC_ARCHIVE_PATH);
CFStringRef userStr = cDataToCfstr(userName);
CFStringRef pwdStr = cDataToCfstr(password);
CFStringRef pfxInStr = NULL;
if(pfxIn) {
pfxInStr = cDataToCfstr(*pfxIn);
}
CFStringRef archiveNameStr = NULL;
if(archiveName) {
archiveNameStr = cDataToCfstr(*archiveName);
}
CFStringRef timeStringStr = NULL;
if(timeString) {
timeStringStr = cDataToCfstr(*timeString);
}
uint8 zero = 0;
CSSM_DATA zeroData = {1, &zero};
CFStringRef serialNumberStr = NULL;
CFStringRef certTypeStr = NULL;
if(archiveType == DMAT_Store) {
if(serialNumber == NULL) {
serialNumber = &zeroData;
}
serialNumberStr = cDataToCfAsciiStr(*serialNumber);
switch(certTypeTag) {
case CSSM_DOT_MAC_TYPE_ICHAT:
certTypeStr = kParamCertTypeIChat;
break;
case CSSM_DOT_MAC_TYPE_SHARED_SERVICES:
certTypeStr = kParamCertTypeSharedServices;
break;
case CSSM_DOT_MAC_TYPE_EMAIL_ENCRYPT:
certTypeStr = kParamCertTypeEmailEncryption;
break;
case CSSM_DOT_MAC_TYPE_EMAIL_SIGNING:
certTypeStr = kParamCertTypeEmailSigning;
break;
default:
dotMacErrorLog("dotMacPostArchiveReq: Bad cert type\n");
return paramErr;
}
}
CFMutableDictionaryRef argDict;
CFMutableArrayRef argOrder;
CFStringRef method;
argDict = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
argOrder = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
switch(archiveType) {
case DMAT_List:
method = kMethodArchiveList;
break;
case DMAT_Store:
method = kMethodArchiveSave;
assert(archiveNameStr != NULL);
assert(timeStringStr != NULL);
assert(pfxInStr != NULL);
assert(serialNumberStr != NULL);
assert(certTypeStr != NULL);
CFDictionaryAddValue(argDict, kP1, archiveNameStr);
CFArrayAppendValue(argOrder, kP1);
CFDictionaryAddValue(argDict, kP2, pfxInStr);
CFArrayAppendValue(argOrder, kP2);
CFDictionaryAddValue(argDict, kP3, certTypeStr);
CFArrayAppendValue(argOrder, kP3);
CFDictionaryAddValue(argDict, kP4, timeStringStr);
CFArrayAppendValue(argOrder, kP4);
CFDictionaryAddValue(argDict, kP5, serialNumberStr);
CFArrayAppendValue(argOrder, kP5);
break;
case DMAT_Fetch:
method = kMethodArchiveFetch;
assert(archiveNameStr != NULL);
CFDictionaryAddValue(argDict, kP1, archiveNameStr);
CFArrayAppendValue(argOrder, kP1);
break;
case DMAT_Remove:
method = kMethodArchiveRemove;
assert(archiveNameStr != NULL);
CFDictionaryAddValue(argDict, kP1, archiveNameStr);
CFArrayAppendValue(argOrder, kP1);
break;
default:
return paramErr;
}
OSStatus ortn;
CFDictionaryRef resultDict = NULL;
uint32_t httpStat;
#if REQUEST_DICTIONARY_DEBUG
dumpDictionary("Arguments dictionary", argDict);
#endif
ortn = performAuthenticatedXMLRPC(url, method, argDict, argOrder, userStr, pwdStr,
&resultDict, &httpStat);
if(ortn) {
dotMacErrorLog("dotMacPostArchiveReq: XMLRPC returned %ld\n", ortn);
goto errOut;
}
if(resultDict == NULL) {
dotMacErrorLog("dotMacPostArchiveReq: XMLRPC failed to return a dictionary\n");
ortn = ioErr;
goto errOut;
}
#if RESULTS_DICTIONARY_DEBUG
dumpDictionary("Results dictionary", resultDict);
#endif
CFStringRef resultCode;
resultCode = (CFStringRef)CFDictionaryGetValue(resultDict, kResponseResultCode);
if((resultCode == NULL) || (CFGetTypeID(resultCode) != CFStringGetTypeID())) {
dotMacErrorLog("dotMacPostArchiveReq: resultCode is not a string\n");
ortn = ioErr;
goto errOut;
}
ortn = dotMacParseResult(resultCode);
if(ortn) {
goto errOut;
}
switch(archiveType) {
case DMAT_List:
{
if(version == CSSM_DOT_MAC_TP_ARCHIVE_REQ_VERSION_v1) {
assert(archives_v1 != NULL);
ortn = dotMacReturnArchiveList_v1(resultDict, numArchives, archives_v1, alloc);
}
else {
assert(archives_v2 != NULL);
ortn = dotMacReturnArchiveList_v2(resultDict, numArchives, archives_v2, alloc);
}
break;
}
case DMAT_Store:
break;
case DMAT_Fetch:
{
CFStringRef pfxStr;
pfxStr = (CFStringRef)CFDictionaryGetValue(resultDict,
kResponseResultBody);
if((pfxStr == NULL) ||(CFGetTypeID(pfxStr) != CFStringGetTypeID())) {
dotMacErrorLog("archive(fetch): resultBody is not a string\n");
ortn = ioErr;
goto errOut;
}
assert(pfxOut != NULL);
cfstrToCdata(pfxStr, *pfxOut, alloc);
break;
}
case DMAT_Remove:
break;
default:
return paramErr;
}
errOut:
CFRELEASE(url);
CFRELEASE(userStr);
CFRELEASE(pwdStr);
CFRELEASE(pfxInStr);
CFRELEASE(archiveNameStr);
CFRELEASE(timeStringStr);
CFRELEASE(argDict);
CFRELEASE(argOrder);
CFRELEASE(resultDict);
return ortn;
}
OSStatus dotMacPostReqPendingPing(
DotMacCertTypeTag certType,
const CSSM_DATA &userName,
const CSSM_DATA &password,
const CSSM_DATA &hostName)
{
CFURLRef url = createUrl(DOT_MAC_SIGN_SCHEMA, hostName, DOT_MAC_SIGN_PATH);
CFStringRef userStr = cDataToCfstr(userName);
CFStringRef pwdStr = cDataToCfstr(password);
CFStringRef method;
switch(certType) {
case CSSM_DOT_MAC_TYPE_ICHAT:
method = kMethodStatusIChatEncrypt;
break;
case CSSM_DOT_MAC_TYPE_SHARED_SERVICES:
method = kMethodStatusSharedServices;
break;
case CSSM_DOT_MAC_TYPE_EMAIL_ENCRYPT:
method = kMethodStatusEmailEncryption;
break;
case CSSM_DOT_MAC_TYPE_EMAIL_SIGNING:
method = kMethodStatusEmailSigning;
break;
default:
return paramErr;
}
CFMutableDictionaryRef argDict =
CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFMutableArrayRef argOrder = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
OSStatus ortn;
CFDictionaryRef resultDict = NULL;
uint32_t httpStat;
ortn = performAuthenticatedXMLRPC(url, method, argDict, argOrder,
userStr, pwdStr, &resultDict, &httpStat);
if(ortn) {
dotMacErrorLog("dotMacPostReqPendingPing: XMLRPC returned %ld\n", ortn);
goto errOut;
}
if(resultDict == NULL) {
dotMacErrorLog("dotMacPostReqPendingPing: XMLRPC failed to return a dictionary\n");
ortn = ioErr;
goto errOut;
}
#if RESULTS_DICTIONARY_DEBUG
dumpDictionary("Results dictionary", resultDict);
#endif
CFStringRef resultCode;
resultCode = (CFStringRef)CFDictionaryGetValue(resultDict, kResponseResultCode);
if((resultCode == NULL) || (CFGetTypeID(resultCode) != CFStringGetTypeID())) {
dotMacErrorLog("dotMacPostCertReq: resultCode is not a string\n");
ortn = ioErr;
goto errOut;
}
ortn = dotMacParseResult(resultCode);
dotMacDebug("dotMacPostReqPendingPing: ortn %lu", ortn);
errOut:
CFRELEASE(url);
CFRELEASE(userStr);
CFRELEASE(pwdStr);
CFRELEASE(argDict);
CFRELEASE(argOrder);
CFRELEASE(resultDict);
return ortn;
}