1//
2//  sc-130-resignationticket.c
3//  sec
4//
5//  Created by Richard Murphy on 5/1/13.
6//
7//
8
9#include <Security/SecBase.h>
10#include <Security/SecItem.h>
11#include <Security/SecKey.h>
12
13#include <SecureObjectSync/SOSCircle.h>
14#include <SecureObjectSync/SOSPeerInfo.h>
15#include <SecureObjectSync/SOSInternal.h>
16
17#include <utilities/SecCFWrappers.h>
18
19#include <CoreFoundation/CoreFoundation.h>
20
21#include <stdlib.h>
22#include <unistd.h>
23
24#include "SOSCircle_regressions.h"
25
26#include "SOSRegressionUtilities.h"
27
28typedef struct piStuff_t {
29    SecKeyRef signingKey;
30    SOSFullPeerInfoRef fpi;
31    SOSPeerInfoRef pi;
32    SOSPeerInfoRef resignation_ticket;
33} piStuff;
34
35static piStuff *makeSimplePeer(char *name) {
36    piStuff *pi = malloc(sizeof(piStuff));
37
38    if(!pi) return NULL;
39    pi->signingKey = NULL;
40    CFStringRef cfName = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingMacRoman);
41    pi->fpi = SOSCreateFullPeerInfoFromName(cfName, &pi->signingKey, NULL);
42    CFReleaseSafe(cfName);
43    pi->pi = SOSFullPeerInfoGetPeerInfo(pi->fpi);
44    pi->resignation_ticket = SOSPeerInfoCreateRetirementTicket(kCFAllocatorDefault, pi->signingKey, pi->pi, NULL);
45    return pi;
46}
47
48static inline bool retire_me(piStuff *pi, size_t seconds) {
49    return SOSPeerInfoRetireRetirementTicket(seconds, pi->resignation_ticket);
50}
51
52// Copied from SOSPeerInfo.c
53static CFStringRef sFlatticket = CFSTR("flatticket");
54static CFStringRef sSignature = CFSTR("RetirementPsig");
55static CFStringRef sPeerid = CFSTR("peerid");
56
57
58static inline bool chkBasicTicket(piStuff *pi) {
59    return CFEqual(SOSPeerInfoInspectRetirementTicket(pi->resignation_ticket, NULL), SOSPeerInfoGetPeerID(pi->pi));
60}
61
62static bool in_between_time(CFDateRef before, piStuff *pi, CFDateRef after) {
63    CFDateRef during = SOSPeerInfoGetRetirementDate(pi->resignation_ticket);
64    CFTimeInterval time1 = CFDateGetTimeIntervalSinceDate(before, during);
65    CFTimeInterval time2 = CFDateGetTimeIntervalSinceDate(during, after);
66    CFReleaseNull(during);
67    if(time1 >= 0.0) return false;
68    if(time2 >= 0.0) return false;
69    return true;
70}
71
72static void tests(void)
73{
74    CFDateRef before_time = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent());
75    sleep(1);
76    piStuff *iPhone = makeSimplePeer("iPhone");
77    piStuff *iPad = makeSimplePeer("iPad");
78    piStuff *iMac = makeSimplePeer("iMac");
79    piStuff *iDrone = makeSimplePeer("iDrone");
80    sleep(1);
81    CFDateRef after_time = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent());
82
83    ok(in_between_time(before_time, iPhone, after_time), "retirement date recorded correctly");
84    CFReleaseSafe(before_time);
85    CFReleaseSafe(after_time);
86    ok(chkBasicTicket(iPhone), "peer ID's Match");
87    ok(chkBasicTicket(iPad), "peer ID's Match");
88    ok(chkBasicTicket(iMac), "peer ID's Match");
89    ok(chkBasicTicket(iDrone), "peer ID's Match");
90
91    // ok(miss_signature(iDrone, iPad), "signature failure detected");
92
93    ok(!retire_me(iPhone, 10000), "ticket still valid");
94    sleep(2);
95    ok(retire_me(iPhone, 1), "ticket not valid");
96
97    CFDateRef retdate = NULL;
98    ok((retdate = SOSPeerInfoGetRetirementDate(iPhone->resignation_ticket)) != NULL, "got retirement date %@", retdate);
99    CFReleaseSafe(retdate);
100
101#if 0
102    CFDateRef appdate = NULL;
103    ok((appdate = SOSPeerInfoGetApplicationDate(iPhone->resignation_ticket)) != NULL, "got application date %@", appdate);
104    CFReleaseSafe(appdate);
105#endif
106}
107
108static int kTestTestCount = 20;
109
110int sc_130_resignationticket(int argc, char *const *argv)
111{
112    plan_tests(kTestTestCount);
113
114    tests();
115
116	return 0;
117}
118