]> git.saurik.com Git - apple/security.git/blob - Keychain/cssmdatetime.cpp
Security-30.1.tar.gz
[apple/security.git] / Keychain / cssmdatetime.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 /*
20 File: cssmdatetime.cpp
21
22 Contains: CSSM date and time utilities for the Mac
23
24 Written by: The Hindsight team
25
26 Copyright: © 1997-2000 by Apple Computer, Inc., all rights reserved.
27
28 Change History (most recent first):
29
30 To Do:
31 */
32
33 #ifdef __MWERKS__
34 #define _CPP_CSSM_DATE_TIME_UTILS
35 #endif
36
37 #include "cssmdatetime.h"
38
39 #include <string.h>
40 #include <stdio.h>
41 #include <Security/utilities.h>
42 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
43 #include <CoreFoundation/CFDate.h>
44 #include <CoreFoundation/CFTimeZone.h>
45
46 namespace Security
47 {
48
49 namespace CSSMDateTimeUtils
50 {
51
52 #define MAX_TIME_STR_LEN 30
53 #define UTC_TIME_STRLEN 13
54 #define GENERALIZED_TIME_STRLEN 15
55
56
57 void
58 GetCurrentMacLongDateTime(SInt64 &outMacDate)
59 {
60 CFTimeZoneRef timeZone = CFTimeZoneCopyDefault();
61 CFAbsoluteTime absTime = CFAbsoluteTimeGetCurrent();
62 absTime += CFTimeZoneGetSecondsFromGMT(timeZone, absTime);
63 CFRelease(timeZone);
64 outMacDate = SInt64(double(absTime + kCFAbsoluteTimeIntervalSince1904));
65 }
66
67 void
68 TimeStringToMacSeconds (const CSSM_DATA &inUTCTime, UInt32 &ioMacDate)
69 {
70 SInt64 ldt;
71 TimeStringToMacLongDateTime(inUTCTime, ldt);
72 ioMacDate = UInt32(ldt);
73 }
74
75 /*
76 * Given a CSSM_DATA containing either a UTC-style or "generalized time"
77 * time string, convert to 32-bit Mac time in seconds.
78 * Returns nonzero on error.
79 */
80 void
81 TimeStringToMacLongDateTime (const CSSM_DATA &inUTCTime, SInt64 &outMacDate)
82 {
83 char szTemp[5];
84 unsigned len;
85 int isUtc;
86 sint32 x;
87 sint32 i;
88 char *cp;
89
90 CFGregorianDate date;
91 ::memset( &date, 0, sizeof(date) );
92
93 if ((inUTCTime.Data == NULL) || (inUTCTime.Length == 0))
94 {
95 MacOSError::throwMe(paramErr);
96 }
97
98 /* tolerate NULL terminated or not */
99 len = inUTCTime.Length;
100 if (inUTCTime.Data[len - 1] == '\0')
101 len--;
102
103 switch(len)
104 {
105 case UTC_TIME_STRLEN: // 2-digit year, not Y2K compliant
106 isUtc = 1;
107 break;
108 case GENERALIZED_TIME_STRLEN: // 4-digit year
109 isUtc = 0;
110 break;
111 default: // unknown format
112 MacOSError::throwMe(paramErr);
113 }
114
115 cp = (char *)inUTCTime.Data;
116
117 /* check that all characters except last are digits */
118 for(i=0; i<(sint32)(len - 1); i++) {
119 if ( !(isdigit(cp[i])) ) {
120 MacOSError::throwMe(paramErr);
121 }
122 }
123
124 /* check last character is a 'Z' */
125 if(cp[len - 1] != 'Z' ) {
126 MacOSError::throwMe(paramErr);
127 }
128
129 /* YEAR */
130 szTemp[0] = *cp++;
131 szTemp[1] = *cp++;
132 if(!isUtc) {
133 /* two more digits */
134 szTemp[2] = *cp++;
135 szTemp[3] = *cp++;
136 szTemp[4] = '\0';
137 }
138 else {
139 szTemp[2] = '\0';
140 }
141 x = atoi( szTemp );
142 if(isUtc) {
143 /*
144 * 2-digit year.
145 * 0 <= year <= 50 : assume century 21
146 * 50 < year < 70 : illegal per PKIX
147 * 70 < year <= 99 : assume century 20
148 */
149 if(x <= 50) {
150 x += 100;
151 }
152 else if(x < 70) {
153 MacOSError::throwMe(paramErr);
154 }
155 /* else century 20, OK */
156
157 /* bug fix... we need to end up with a 4-digit year! */
158 x += 1900;
159 }
160 /* by definition - tm_year is year - 1900 */
161 //tmp->tm_year = x - 1900;
162 date.year = x;
163
164 /* MONTH */
165 szTemp[0] = *cp++;
166 szTemp[1] = *cp++;
167 szTemp[2] = '\0';
168 x = atoi( szTemp );
169 /* in the string, months are from 1 to 12 */
170 if((x > 12) || (x <= 0)) {
171 MacOSError::throwMe(paramErr);
172 }
173 /* in a tm, 0 to 11 */
174 //tmp->tm_mon = x - 1;
175 date.month = x;
176
177 /* DAY */
178 szTemp[0] = *cp++;
179 szTemp[1] = *cp++;
180 szTemp[2] = '\0';
181 x = atoi( szTemp );
182 /* 1..31 in both formats */
183 if((x > 31) || (x <= 0)) {
184 MacOSError::throwMe(paramErr);
185 }
186 //tmp->tm_mday = x;
187 date.day = x;
188
189 /* HOUR */
190 szTemp[0] = *cp++;
191 szTemp[1] = *cp++;
192 szTemp[2] = '\0';
193 x = atoi( szTemp );
194 if((x > 23) || (x < 0)) {
195 MacOSError::throwMe(paramErr);
196 }
197 //tmp->tm_hour = x;
198 date.hour = x;
199
200 /* MINUTE */
201 szTemp[0] = *cp++;
202 szTemp[1] = *cp++;
203 szTemp[2] = '\0';
204 x = atoi( szTemp );
205 if((x > 59) || (x < 0)) {
206 MacOSError::throwMe(paramErr);
207 }
208 //tmp->tm_min = x;
209 date.minute = x;
210
211 /* SECOND */
212 szTemp[0] = *cp++;
213 szTemp[1] = *cp++;
214 szTemp[2] = '\0';
215 x = atoi( szTemp );
216 if((x > 59) || (x < 0)) {
217 MacOSError::throwMe(paramErr);
218 }
219 //tmp->tm_sec = x;
220 date.second = x;
221
222 CFTimeZoneRef timeZone = CFTimeZoneCopyDefault();
223 CFAbsoluteTime absTime = CFGregorianDateGetAbsoluteTime(date, timeZone);
224 CFRelease(timeZone);
225 outMacDate = SInt64(double(absTime + kCFAbsoluteTimeIntervalSince1904));
226 }
227
228 void MacSecondsToTimeString(UInt32 inMacDate, UInt32 inLength, void *outData)
229 {
230 SInt64 ldt = SInt64(UInt64(inMacDate));
231 MacLongDateTimeToTimeString(ldt, inLength, outData);
232 }
233
234 void MacLongDateTimeToTimeString(const SInt64 &inMacDate,
235 UInt32 inLength, void *outData)
236 {
237 CFAbsoluteTime absTime = inMacDate - kCFAbsoluteTimeIntervalSince1904;
238 CFTimeZoneRef timeZone = CFTimeZoneCopyDefault();
239 CFGregorianDate date = CFAbsoluteTimeGetGregorianDate(absTime, timeZone);
240 CFRelease(timeZone);
241
242 if (inLength == 16)
243 {
244 sprintf((char *)(outData), "%04d%02d%02d%02d%02d%02dZ",
245 int(date.year % 10000), date.month, date.day,
246 date.hour, date.minute, int(date.second));
247 }
248 else if (inLength == 14)
249 {
250 /* UTC - 2 year digits - code which parses this assumes that
251 * (2-digit) years between 0 and 49 are in century 21 */
252 sprintf((char *)(outData), "%02d%02d%02d%02d%02d%02dZ",
253 int(date.year % 100), date.month, date.day,
254 date.hour, date.minute, int(date.second));
255 }
256 else
257 MacOSError::throwMe(paramErr);
258 }
259
260 }; // end namespace CSSMDateTimeUtils
261
262 } // end namespace Security