1/*
2 * Copyright (c) 2003 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
7 * obtain a copy of the License at http://www.apple.com/publicsource and
8 * read it before 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
12 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
13 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
14 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
15 * Please see the License for the specific language governing rights and
16 * limitations under the License.
17 */
18
19/*
20 * crlrefresh: command line access to ocspd's CRL cache refresh mechanism
21 */
22
23#include <stdlib.h>
24#include <stdio.h>
25#include <security_ocspd/ocspdClient.h>
26#include <security_utilities/alloc.h>
27#include <security_cdsa_utils/cuTimeStr.h>
28#include <security_cdsa_utils/cuCdsaUtils.h>
29#include <security_cdsa_utils/cuFileIo.h>
30#include <Security/cssmtype.h>
31#include <Security/cssmapple.h>
32
33#define DEFAULT_STALE_DAYS				10
34#define DEFAULT_EXPIRE_OVERLAP_SECONDS	3600
35
36#ifdef	NDEBUG
37#define DEBUG_PRINT		0
38#else
39#define DEBUG_PRINT		1
40#endif
41
42#if		DEBUG_PRINT
43#define dprintf(args...)	fprintf(stderr, args)
44#else
45#define dprintf(args...)
46#endif
47
48static void usage(char **argv)
49{
50	printf("Usage\n");
51	printf("Refresh    : %s r [options]\n", argv[0]);
52	printf("Fetch CRL  : %s f URI [options]\n", argv[0]);
53	printf("Fetch cert : %s F URI [options]\n", argv[0]);
54	printf("Refresh options:\n");
55	printf("   s=stale_period in DAYS; default=%d\n", DEFAULT_STALE_DAYS);
56	printf("   o=expire_overlap in SECONDS; default=%d\n",
57					DEFAULT_EXPIRE_OVERLAP_SECONDS);
58	printf("   p (Purge all entries, ensuring refresh with fresh CRLs)\n");
59	printf("   f (Full crypto CRL verification)\n");
60	printf("Fetch options:\n");
61	printf("   F=outFileName (default is stdout)\n");
62	printf("   n (no write to cache after fetch)\n");
63	exit(1);
64}
65
66/*
67 * Fetch a CRL or Cert from net; write it to a file.
68 */
69int fetchItemFromNet(
70	bool fetchCrl,
71	const char *URI,
72	char *outFileName,		// NULL indicates write to stdout
73	bool writeToCache)
74{
75	const CSSM_DATA uriData = {strlen(URI) + 1, (uint8 *)URI};
76	CSSM_DATA item;
77	CSSM_RETURN crtn;
78	int irtn;
79	Allocator &alloc = Allocator::standard();
80	char *op = "";
81
82	dprintf("fetchItemFromNet %s outFile %s\n",
83		URI, outFileName ? outFileName : "stdout");
84
85	if(fetchCrl) {
86		char *cssmTime = cuTimeAtNowPlus(0, TIME_CSSM);
87		op = "ocspdCRLFetch";
88		crtn = ocspdCRLFetch(alloc, uriData, NULL,
89			true,		// cacheRead
90			writeToCache,
91			cssmTime,
92			item);
93		APP_FREE(cssmTime);
94	}
95	else {
96		op = "ocspdCertFetch";
97		crtn = ocspdCertFetch(alloc, uriData, item);
98	}
99
100	if(crtn) {
101		cssmPerror(op, crtn);
102		return 1;
103	}
104	dprintf("fetchItemFromNet %s complete, %lu bytes read\n",
105		op, item.Length);
106	if(outFileName == NULL) {
107		irtn = write(STDOUT_FILENO, item.Data, item.Length);
108		if(irtn != (int)item.Length) {
109			irtn = errno;
110			perror("write");
111		}
112		else {
113			irtn = 0;
114		}
115	}
116	else {
117		irtn = writeFile(outFileName, item.Data, item.Length);
118		if(irtn) {
119			perror(outFileName);
120		}
121	}
122	alloc.free(item.Data);
123	dprintf("fetchItemFromNet returning %d\n", irtn);
124	return irtn;
125}
126
127int main(int argc, char **argv)
128{
129	CSSM_RETURN crtn;
130	char		*argp;
131	int			arg;
132	int 		optArg = 1;
133
134	/* user-specified variables */
135	bool		verbose = false;
136	bool		purgeAll = false;
137	bool		fullCryptoValidation = false;
138	int 		staleDays = DEFAULT_STALE_DAYS;
139	int			expireOverlapSeconds = DEFAULT_EXPIRE_OVERLAP_SECONDS;
140
141	/* fetch options */
142	bool		fetchCrl = true;
143	char		*outFileName = NULL;
144	bool		writeToCache = true;
145	char		*uri = NULL;
146
147	if(argc < 2) {
148		usage(argv);
149	}
150	switch(argv[1][0]) {
151		case 'F':
152			fetchCrl = false;
153			/* and drop thru */
154		case 'f':
155			if(argc < 3) {
156				usage(argv);
157			}
158			uri = argv[2];
159			optArg = 3;
160			break;
161		case 'r':
162			optArg = 2;
163			break;
164		default:
165			usage(argv);
166	}
167	/* refresh options */
168	for(arg=optArg; arg<argc; arg++) {
169		argp = argv[arg];
170		switch(argp[0]) {
171			case 's':
172				if(argp[1] != '=') {
173					usage(argv);
174				}
175				staleDays = atoi(&argp[2]);
176				break;
177			case 'o':
178				if(argp[1] != '=') {
179					usage(argv);
180				}
181				expireOverlapSeconds = atoi(&argp[2]);
182				break;
183			case 'p':
184				purgeAll = true;
185				break;
186			case 'f':
187				fullCryptoValidation = true;
188				break;
189			case 'k':
190				/* keychain argument no longer used but we'll allow/ignore it */
191				fprintf(stderr, "Warning: keychain specification no longer used\n");
192				break;
193			case 'n':
194				writeToCache = false;
195				break;
196			case 'F':
197				if(argp[1] != '=') {
198					usage(argv);
199				}
200				outFileName = &argp[2];
201				break;
202			case 'v':
203				verbose = true;
204				break;
205			default:
206				usage(argv);
207		}
208	}
209	if(argv[1][0] != 'r') {
210		return fetchItemFromNet(fetchCrl, uri, outFileName, writeToCache);
211	}
212
213	dprintf("...staleDays %d  expireOverlapSeconds %d\n",
214		staleDays, expireOverlapSeconds);
215
216	crtn = ocspdCRLRefresh(staleDays, expireOverlapSeconds, purgeAll,
217		fullCryptoValidation);
218	if(crtn) {
219		cssmPerror("ocspdCRLRefresh", crtn);
220		return -1;
221	}
222	return 0;
223}
224