accountCirclesViewsPrint.m [plain text]
//
// accountCirclesViewsPrint.c
// Security
//
// Created by Richard Murphy on 12/8/16.
//
//
#include "accountCirclesViewsPrint.h"
//
// SOSSysdiagnose.c
// sec
//
// Created by Richard Murphy on 1/27/16.
//
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/utsname.h>
#include <sys/stat.h>
#include <time.h>
#include <notify.h>
#include <pwd.h>
#include <Security/SecItem.h>
#include <CoreFoundation/CoreFoundation.h>
#include <CoreFoundation/CFPriv.h>
#include <Security/SecureObjectSync/SOSCloudCircle.h>
#include <Security/SecureObjectSync/SOSCloudCircleInternal.h>
#include <Security/SecureObjectSync/SOSPeerInfo.h>
#include <Security/SecureObjectSync/SOSPeerInfoPriv.h>
#include <Security/SecureObjectSync/SOSPeerInfoV2.h>
#include <Security/SecureObjectSync/SOSUserKeygen.h>
#include <Security/SecureObjectSync/SOSKVSKeys.h>
#include <securityd/SOSCloudCircleServer.h>
#include <Security/SecOTRSession.h>
#include <SOSCircle/CKBridge/SOSCloudKeychainClient.h>
#include <utilities/SecCFWrappers.h>
#include <utilities/debugging.h>
#include <SecurityTool/readline.h>
#include "keychain_log.h"
#include "secToolFileIO.h"
#include "secViewDisplay.h"
#include <Security/SecPasswordGenerate.h>
#define MAXKVSKEYTYPE kUnknownKey
#define DATE_LENGTH 18
#include <utilities/SecCFWrappers.h>
static const char *getSOSCCStatusDescription(SOSCCStatus ccstatus)
{
switch (ccstatus)
{
case kSOSCCInCircle: return "In Circle";
case kSOSCCNotInCircle: return "Not in Circle";
case kSOSCCRequestPending: return "Request pending";
case kSOSCCCircleAbsent: return "Circle absent";
case kSOSCCError: return "Circle error";
default:
return "<unknown ccstatus>";
break;
}
}
static const char *
getSOSCCLastDepartureReasonDescription(enum DepartureReason reason)
{
switch (reason) {
#define CASE_REASON(x) case kSOS##x: return #x
CASE_REASON(DepartureReasonError);
CASE_REASON(NeverLeftCircle);
CASE_REASON(WithdrewMembership);
CASE_REASON(MembershipRevoked);
CASE_REASON(LeftUntrustedCircle);
CASE_REASON(NeverAppliedToCircle);
CASE_REASON(DiscoveredRetirement); // we should all be so lucky
CASE_REASON(LostPrivateKey);
CASE_REASON(PasswordChanged);
#undef CASE_REASON
default:
return "Unknown";
}
}
static void printPeerInfos(char *label, CFArrayRef (^getArray)(CFErrorRef *error)) {
CFErrorRef error = NULL;
CFArrayRef ppi = getArray(&error);
SOSPeerInfoRef me = SOSCCCopyMyPeerInfo(NULL);
CFStringRef mypeerID = SOSPeerInfoGetPeerID(me);
if(ppi) {
printmsg(CFSTR(" CFArrayForEach(ppi, ^(const void *value) {
char buf[160];
SOSPeerInfoRef peer = (SOSPeerInfoRef)value;
if(!peer) { return; }
CFIndex version = SOSPeerInfoGetVersion(peer);
CFStringRef peerName = SOSPeerInfoGetPeerName(peer);
CFStringRef devtype = SOSPeerInfoGetPeerDeviceType(peer);
CFStringRef peerID = SOSPeerInfoGetPeerID(peer);
CFStringRef transportType = CFSTR("KVS");
CFStringRef deviceID = CFSTR("");
CFStringRef machineID = CFSTR("");
CFDictionaryRef gestalt = SOSPeerInfoCopyPeerGestalt(peer);
CFStringRef osVersion = CFSTR("Unknown");
if(gestalt) {
osVersion = CFDictionaryGetValue(gestalt, CFSTR("OSVersion"));
}
if(version >= 2){
CFDictionaryRef v2Dictionary = peer->v2Dictionary;
if(v2Dictionary) {
transportType = CFDictionaryGetValue(v2Dictionary, CFSTR("TransportType"));
deviceID = CFDictionaryGetValue(v2Dictionary, CFSTR("DeviceID"));
machineID = CFDictionaryGetValue(v2Dictionary, CFSTR("MachineIDKey"));
}
}
char *pname = CFStringToCString(peerName);
char *dname = CFStringToCString(devtype);
char *tname = transportType ? CFStringToCString(transportType) : CFStringToCString(CFSTR("KVS"));
char *iname = CFStringToCString(deviceID);
char *mname = CFStringToCString(machineID);
const char *me = CFEqualSafe(mypeerID, peerID) ? "me>" : " ";
snprintf(buf, 160, "
free(pname);
free(dname);
free(tname);
free(iname);
free(mname);
// CFStringRef bufstr = CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8);
CFStringRef pid = SOSPeerInfoGetPeerID(peer);
CFIndex vers = SOSPeerInfoGetVersion(peer);
printmsg(CFSTR(" CFRelease(bufstr);
CFReleaseNull(gestalt);
});
} else {
printmsg(CFSTR("No }
CFReleaseNull(ppi);
CFReleaseNull(error);
CFReleaseNull(me);
}
void SOSCCDumpCircleInformation()
{
CFErrorRef error = NULL;
CFArrayRef generations = NULL;
bool is_accountKeyIsTrusted = false;
__block int count = 0;
SOSCCStatus ccstatus = SOSCCThisDeviceIsInCircle(&error);
printmsg(CFSTR("ccstatus: if (error != NULL) {
printmsg(CFSTR("Error checking circle status: }
CFReleaseNull(error);
enum DepartureReason departureReason = SOSCCGetLastDepartureReason(&error);
printmsg(CFSTR("LastDepartureReason: if (error != NULL) {
printmsg(CFSTR("Error checking last departure reason error: }
CFReleaseNull(error);
is_accountKeyIsTrusted = SOSCCValidateUserPublic(&error);
if(is_accountKeyIsTrusted)
printmsg(CFSTR("Account user public is trusted\n"));
else
printmsg(CFSTR("Account user public is not trusted error:( CFReleaseNull(error);
generations = SOSCCCopyGenerationPeerInfo(&error);
if(generations) {
CFArrayForEach(generations, ^(const void *value) {
count++;
if(count printmsg(CFSTR("Circle name:
if(count CFStringRef genDesc = SOSGenerationCountCopyDescription(value);
printmsg(CFSTR("Generation Count: CFReleaseNull(genDesc);
}
printmsg(CFSTR(" });
} else {
printmsg(CFSTR("No generation count: }
CFReleaseNull(generations);
CFReleaseNull(error);
printPeerInfos(" Peers", ^(CFErrorRef *error) { return SOSCCCopyValidPeerPeerInfo(error); });
printPeerInfos(" Invalid", ^(CFErrorRef *error) { return SOSCCCopyNotValidPeerPeerInfo(error); });
printPeerInfos(" Retired", ^(CFErrorRef *error) { return SOSCCCopyRetirementPeerInfo(error); });
printPeerInfos(" Concur", ^(CFErrorRef *error) { return SOSCCCopyConcurringPeerPeerInfo(error); });
printPeerInfos("Applicants", ^(CFErrorRef *error) { return SOSCCCopyApplicantPeerInfo(error); });
CFReleaseNull(error);
}
void
SOSCCDumpEngineInformation(void)
{
CFErrorRef error = NULL;
printmsg(CFSTR("Engine state:\n"));
if (!SOSCCForEachEngineStateAsString(&error, ^(CFStringRef oneStateString) {
printmsg(CFSTR(" })) {
printmsg(CFSTR("No engine state, got error: }
}
// security sync -o
void
SOSCCDumpViewUnwarePeers(void)
{
printPeerInfos("view-unaware", ^(CFErrorRef *error) { return SOSCCCopyViewUnawarePeerInfo(error); });
}
/* KVS Dumping Support for iCloud Keychain */
static CFTypeRef getObjectsFromCloud(CFArrayRef keysToGet, dispatch_queue_t processQueue, dispatch_group_t dgroup)
{
__block CFTypeRef object = NULL;
const uint64_t maxTimeToWaitInSeconds = 30ull * NSEC_PER_SEC;
dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0);
dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, maxTimeToWaitInSeconds);
dispatch_group_enter(dgroup);
CloudKeychainReplyBlock replyBlock =
^ (CFDictionaryRef returnedValues, CFErrorRef error)
{
secinfo("sync", "SOSCloudKeychainGetObjectsFromCloud returned: object = returnedValues;
if (object)
CFRetain(object);
if (error)
{
secerror("SOSCloudKeychainGetObjectsFromCloud returned error: }
dispatch_group_leave(dgroup);
secinfo("sync", "SOSCloudKeychainGetObjectsFromCloud block exit: dispatch_semaphore_signal(waitSemaphore);
};
if (!keysToGet)
SOSCloudKeychainGetAllObjectsFromCloud(processQueue, replyBlock);
else
SOSCloudKeychainGetObjectsFromCloud(keysToGet, processQueue, replyBlock);
dispatch_semaphore_wait(waitSemaphore, finishTime);
if (object && (CFGetTypeID(object) == CFNullGetTypeID())) // return a NULL instead of a CFNull
{
CFRelease(object);
object = NULL;
}
secerror("returned: return object;
}
static CFStringRef printFullDataString(CFDataRef data){
__block CFStringRef fullData = NULL;
BufferPerformWithHexString(CFDataGetBytePtr(data), CFDataGetLength(data), ^(CFStringRef dataHex) {
fullData = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR(" });
return fullData;
}
static void displayLastKeyParameters(CFTypeRef key, CFTypeRef value)
{
CFDataRef valueAsData = asData(value, NULL);
if(valueAsData){
CFDataRef dateData = CFDataCreateCopyFromRange(kCFAllocatorDefault, valueAsData, CFRangeMake(0, DATE_LENGTH));
CFDataRef keyParameterData = CFDataCreateCopyFromPositions(kCFAllocatorDefault, valueAsData, DATE_LENGTH, CFDataGetLength(valueAsData));
CFStringRef dateString = CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, dateData, kCFStringEncodingUTF8);
CFStringRef keyParameterDescription = UserParametersDescription(keyParameterData);
if(keyParameterDescription)
printmsg(CFSTR(" else
printmsg(CFSTR(" CFReleaseNull(dateString);
CFReleaseNull(keyParameterData);
CFReleaseNull(dateData);
CFReleaseNull(keyParameterDescription);
}
else{
printmsg(CFSTR(" }
}
static void displayKeyParameters(CFTypeRef key, CFTypeRef value)
{
if(isData(value)){
CFStringRef keyParameterDescription = UserParametersDescription((CFDataRef)value);
if(keyParameterDescription)
printmsg(CFSTR(" else
printmsg(CFSTR("
CFReleaseNull(keyParameterDescription);
}
else{
printmsg(CFSTR(" }
}
static void displayLastCircle(CFTypeRef key, CFTypeRef value)
{
CFDataRef valueAsData = asData(value, NULL);
if(valueAsData){
CFErrorRef localError = NULL;
CFDataRef dateData = CFDataCreateCopyFromRange(kCFAllocatorDefault, valueAsData, CFRangeMake(0, DATE_LENGTH));
CFDataRef circleData = CFDataCreateCopyFromPositions(kCFAllocatorDefault, valueAsData, DATE_LENGTH, CFDataGetLength(valueAsData));
CFStringRef dateString = CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, dateData, kCFStringEncodingUTF8);
SOSCircleRef circle = SOSCircleCreateFromData(NULL, (CFDataRef) circleData, &localError);
if(circle){
CFIndex size = 5;
CFNumberRef idLength = CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &size);
CFDictionaryRef format = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, CFSTR("SyncD"), CFSTR("SyncD"), CFSTR("idLength"), idLength, NULL);
printmsgWithFormatOptions(format, CFSTR(" CFReleaseNull(idLength);
CFReleaseNull(format);
}
else
printmsg(CFSTR("
CFReleaseNull(dateString);
CFReleaseNull(circleData);
CFReleaseSafe(circle);
CFReleaseNull(dateData);
CFReleaseNull(localError);
}
else{
printmsg(CFSTR(" }
}
static void displayCircle(CFTypeRef key, CFTypeRef value)
{
CFDataRef circleData = (CFDataRef)value;
CFErrorRef localError = NULL;
if (isData(circleData))
{
CFIndex size = 5;
CFNumberRef idLength = CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &size);
CFDictionaryRef format = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, CFSTR("SyncD"), CFSTR("SyncD"), CFSTR("idLength"), idLength, NULL);
SOSCircleRef circle = SOSCircleCreateFromData(NULL, circleData, &localError);
printmsgWithFormatOptions(format, CFSTR(" CFReleaseSafe(circle);
CFReleaseNull(idLength);
CFReleaseNull(format);
}
else
printmsg(CFSTR("}
static void displayMessage(CFTypeRef key, CFTypeRef value)
{
CFDataRef message = (CFDataRef)value;
if(isData(message)){
const char* messageType = SecOTRPacketTypeString(message);
printmsg(CFSTR(" }
else
printmsg(CFSTR("}
static void printEverything(CFTypeRef objects)
{
CFDictionaryForEach(objects, ^(const void *key, const void *value) {
if (isData(value))
{
printmsg(CFSTR(" }
else
printmsg(CFSTR(" });
}
static void decodeForKeyType(CFTypeRef key, CFTypeRef value, SOSKVSKeyType type){
switch (type) {
case kCircleKey:
displayCircle(key, value);
break;
case kRetirementKey:
case kMessageKey:
displayMessage(key, value);
break;
case kParametersKey:
displayKeyParameters(key, value);
break;
case kLastKeyParameterKey:
displayLastKeyParameters(key, value);
break;
case kLastCircleKey:
displayLastCircle(key, value);
break;
case kInitialSyncKey:
case kAccountChangedKey:
case kDebugInfoKey:
case kRingKey:
default:
printmsg(CFSTR(" break;
}
}
static void decodeAllTheValues(CFTypeRef objects){
SOSKVSKeyType keyType = 0;
__block bool didPrint = false;
for (keyType = 0; keyType <= MAXKVSKEYTYPE; keyType++){
CFDictionaryForEach(objects, ^(const void *key, const void *value) {
if(SOSKVSKeyGetKeyType(key) == keyType){
decodeForKeyType(key, value, keyType);
didPrint = true;
}
});
if(didPrint)
printmsg(CFSTR(" didPrint = false;
}
}
bool SOSCCDumpCircleKVSInformation(char *itemName) {
CFArrayRef keysToGet = NULL;
if (itemName)
{
CFStringRef itemStr = CFStringCreateWithCString(kCFAllocatorDefault, itemName, kCFStringEncodingUTF8);
fprintf(outFile, "Retrieving keysToGet = CFArrayCreateForCFTypes(kCFAllocatorDefault, itemStr, NULL);
CFReleaseSafe(itemStr);
}
dispatch_queue_t generalq = dispatch_queue_create("general", DISPATCH_QUEUE_SERIAL);
dispatch_group_t work_group = dispatch_group_create();
CFTypeRef objects = getObjectsFromCloud(keysToGet, generalq, work_group);
CFReleaseSafe(keysToGet);
if (objects)
{
fprintf(outFile, "All keys and values straight from KVS\n");
printEverything(objects);
fprintf(outFile, "\nAll values in decoded form...\n");
decodeAllTheValues(objects);
}
fprintf(outFile, "\n");
return true;
}