1/*
2 * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25#include <Security/SecBase.h>
26#include <Security/SecItem.h>
27#include <Security/SecKey.h>
28
29#include <SecureObjectSync/SOSCircle.h>
30#include <SecureObjectSync/SOSPeerInfo.h>
31#include <SecureObjectSync/SOSInternal.h>
32
33#include <utilities/SecCFWrappers.h>
34
35#include <CoreFoundation/CoreFoundation.h>
36
37#include <stdlib.h>
38#include <unistd.h>
39
40#include "SOSCircle_regressions.h"
41
42#include "SOSRegressionUtilities.h"
43
44typedef struct piStuff_t {
45    SecKeyRef signingKey;
46    SOSFullPeerInfoRef fpi;
47    SOSPeerInfoRef pi;
48    SOSPeerInfoRef resignation_ticket;
49} piStuff;
50
51static piStuff *makeSimplePeer(char *name) {
52    piStuff *pi = malloc(sizeof(piStuff));
53
54    if(!pi) return NULL;
55    pi->signingKey = NULL;
56    CFStringRef cfName = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingMacRoman);
57    pi->fpi = SOSCreateFullPeerInfoFromName(cfName, &pi->signingKey, NULL);
58    CFReleaseSafe(cfName);
59    pi->pi = SOSFullPeerInfoGetPeerInfo(pi->fpi);
60    pi->resignation_ticket = SOSPeerInfoCreateRetirementTicket(kCFAllocatorDefault, pi->signingKey, pi->pi, NULL);
61    return pi;
62}
63
64static inline bool retire_me(piStuff *pi, size_t seconds) {
65    return SOSPeerInfoRetireRetirementTicket(seconds, pi->resignation_ticket);
66}
67
68// Copied from SOSPeerInfo.c
69static CFStringRef sFlatticket = CFSTR("flatticket");
70static CFStringRef sSignature = CFSTR("RetirementPsig");
71static CFStringRef sPeerid = CFSTR("peerid");
72
73
74static inline bool chkBasicTicket(piStuff *pi) {
75    return CFEqual(SOSPeerInfoInspectRetirementTicket(pi->resignation_ticket, NULL), SOSPeerInfoGetPeerID(pi->pi));
76}
77
78static bool in_between_time(CFDateRef before, piStuff *pi, CFDateRef after) {
79    CFDateRef during = SOSPeerInfoGetRetirementDate(pi->resignation_ticket);
80    CFTimeInterval time1 = CFDateGetTimeIntervalSinceDate(before, during);
81    CFTimeInterval time2 = CFDateGetTimeIntervalSinceDate(during, after);
82    CFReleaseNull(during);
83    if(time1 >= 0.0) return false;
84    if(time2 >= 0.0) return false;
85    return true;
86}
87
88static void tests(void)
89{
90    CFDateRef before_time = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent());
91    sleep(1);
92    piStuff *iPhone = makeSimplePeer("iPhone");
93    piStuff *iPad = makeSimplePeer("iPad");
94    piStuff *iMac = makeSimplePeer("iMac");
95    piStuff *iDrone = makeSimplePeer("iDrone");
96    sleep(1);
97    CFDateRef after_time = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent());
98
99    ok(in_between_time(before_time, iPhone, after_time), "retirement date recorded correctly");
100    CFReleaseSafe(before_time);
101    CFReleaseSafe(after_time);
102    ok(chkBasicTicket(iPhone), "peer ID's Match");
103    ok(chkBasicTicket(iPad), "peer ID's Match");
104    ok(chkBasicTicket(iMac), "peer ID's Match");
105    ok(chkBasicTicket(iDrone), "peer ID's Match");
106
107    // ok(miss_signature(iDrone, iPad), "signature failure detected");
108
109    ok(!retire_me(iPhone, 10000), "ticket still valid");
110    sleep(2);
111    ok(retire_me(iPhone, 1), "ticket not valid");
112
113    CFDateRef retdate = NULL;
114    ok((retdate = SOSPeerInfoGetRetirementDate(iPhone->resignation_ticket)) != NULL, "got retirement date %@", retdate);
115    CFReleaseSafe(retdate);
116
117#if 0
118    CFDateRef appdate = NULL;
119    ok((appdate = SOSPeerInfoGetApplicationDate(iPhone->resignation_ticket)) != NULL, "got application date %@", appdate);
120    CFReleaseSafe(appdate);
121#endif
122}
123
124static int kTestTestCount = 8;
125
126int sc_130_resignationticket(int argc, char *const *argv)
127{
128    plan_tests(kTestTestCount);
129
130    tests();
131
132	return 0;
133}
134