]>
git.ipfire.org Git - people/ms/strongswan.git/blob - programs/openac/openac.c
1 /* Generation of X.509 attribute certificates
2 * Copyright (C) 2002 Ueli Galizzi, Ariane Seiler
3 * Copyright (C) 2004 Andreas Steffen
4 * Zuercher Hochschule Winterthur, Switzerland
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * RCSID $Id: openac.c,v 1.18 2006/01/04 21:12:33 as Exp $
30 #include "../pluto/constants.h"
31 #include "../pluto/defs.h"
32 #include "../pluto/mp_defs.h"
33 #include "../pluto/log.h"
34 #include "../pluto/asn1.h"
35 #include "../pluto/certs.h"
36 #include "../pluto/x509.h"
37 #include "../pluto/crl.h"
38 #include "../pluto/keys.h"
39 #include "../pluto/ac.h"
43 #define OPENAC_PATH "/etc/openac"
44 #define OPENAC_SERIAL "/etc/openac/serial"
46 const char openac_version
[] = "openac 0.3";
48 /* by default the CRL policy is lenient */
49 bool strict_crl_policy
= FALSE
;
51 /* by default pluto does not check crls dynamically */
52 long crl_check_interval
= 0;
54 /* by default pluto logs out after every smartcard use */
55 bool pkcs11_keep_state
= FALSE
;
58 usage(const char *mess
)
60 if (mess
!= NULL
&& *mess
!= '\0')
61 fprintf(stderr
, "%s\n", mess
);
66 " [--optionsfrom <filename>]"
79 " [--startdate <YYYYMMDDHHMMSSZ>]"
80 " [--enddate <YYYYMMDDHHMMSSZ>]"
84 " [--password <password>]"
86 " --usercert <certfile>"
87 " --groups <attr1,attr2,..>"
91 exit(mess
== NULL
? 0 : 1);
95 * read the last serial number from file
105 FILE *fd
= fopen(OPENAC_SERIAL
, "r");
107 /* serial number defaults to 0 */
113 if (fscanf(fd
, "%s", buf
))
115 err_t ugh
= ttodata(buf
, 0, 16, bytes
, BUF_LEN
, &len
);
118 plog(" error reading serial number from %s: %s"
119 , OPENAC_SERIAL
, ugh
);
124 plog(" file '%s' does not exist yet - serial number set to 01"
127 /* conversion of read serial number to a multiprecision integer
128 * and incrementing it by one
129 * and representing it as a two's complement octet string
131 n_to_mpz(&number
, bytes
, len
);
132 mpz_add_ui(&number
, &number
, 0x01);
133 serial
= mpz_to_n(&number
, 1 + mpz_sizeinbase(&number
, 2)/BITS_PER_BYTE
);
140 * write back the last serial number to file
143 write_serial(chunk_t serial
)
147 FILE *fd
= fopen(OPENAC_SERIAL
, "w");
151 datatot(serial
.ptr
, serial
.len
, 16, buf
, BUF_LEN
);
152 plog(" serial number is %s", buf
);
153 fprintf(fd
, "%s\n", buf
);
157 plog(" could not open file '%s' for writing", OPENAC_SERIAL
);
161 * global variables accessible by both main() and build.c
163 x509cert_t
*user
= NULL
;
164 x509cert_t
*signer
= NULL
;
166 ietfAttrList_t
*groups
= NULL
;
167 struct RSA_private_key
*signerkey
= NULL
;
169 time_t notBefore
= 0;
176 main(int argc
, char **argv
)
178 char *keyfile
= NULL
;
179 char *certfile
= NULL
;
180 char *usercertfile
= NULL
;
181 char *outfile
= NULL
;
183 cert_t signercert
= empty_cert
;
184 cert_t usercert
= empty_cert
;
186 chunk_t attr_cert
= empty_chunk
;
187 x509acert_t
*ac
= NULL
;
189 const time_t default_validity
= 24*3600; /* 24 hours */
194 pass
.secret
[0] = '\0';
196 pass
.fd
= STDIN_FILENO
;
198 log_to_stderr
= TRUE
;
200 /* handle arguments */
203 # define DBG_OFFSET 256
204 static const struct option long_opts
[] = {
205 /* name, has_arg, flag, val */
206 { "help", no_argument
, NULL
, 'h' },
207 { "version", no_argument
, NULL
, 'v' },
208 { "optionsfrom", required_argument
, NULL
, '+' },
209 { "quiet", no_argument
, NULL
, 'q' },
210 { "cert", required_argument
, NULL
, 'c' },
211 { "key", required_argument
, NULL
, 'k' },
212 { "password", required_argument
, NULL
, 'p' },
213 { "usercert", required_argument
, NULL
, 'u' },
214 { "groups", required_argument
, NULL
, 'g' },
215 { "days", required_argument
, NULL
, 'D' },
216 { "hours", required_argument
, NULL
, 'H' },
217 { "startdate", required_argument
, NULL
, 'S' },
218 { "enddate", required_argument
, NULL
, 'E' },
219 { "out", required_argument
, NULL
, 'o' },
221 { "debug-all", no_argument
, NULL
, 'A' },
222 { "debug-raw", no_argument
, NULL
, DBG_RAW
+ DBG_OFFSET
},
223 { "debug-parsing", no_argument
, NULL
, DBG_PARSING
+ DBG_OFFSET
},
224 { "debug-private", no_argument
, NULL
, DBG_PRIVATE
+ DBG_OFFSET
},
229 int c
= getopt_long(argc
, argv
, "hv+:qc:k:p;u:g:D:H:S:E:o:", long_opts
, NULL
);
231 /* Note: "breaking" from case terminates loop */
234 case EOF
: /* end of flags */
237 case 0: /* long option already handled */
240 case ':': /* diagnostic already printed by getopt_long */
241 case '?': /* diagnostic already printed by getopt_long */
243 break; /* not actually reached */
245 case 'h': /* --help */
247 break; /* not actually reached */
249 case 'v': /* --version */
250 printf("%s\n", openac_version
);
252 break; /* not actually reached */
254 case '+': /* --optionsfrom <filename> */
258 if (*optarg
== '/') /* absolute pathname */
259 strncpy(path
, optarg
, BUF_LEN
);
260 else /* relative pathname */
261 snprintf(path
, BUF_LEN
, "%s/%s", OPENAC_PATH
, optarg
);
262 optionsfrom(path
, &argc
, &argv
, optind
, stderr
);
263 /* does not return on error */
267 case 'q': /* --quiet */
268 log_to_stderr
= TRUE
;
271 case 'c': /* --cert */
275 case 'k': /* --key */
279 case 'p': /* --key */
281 strncpy(pass
.secret
, optarg
, sizeof(pass
.secret
));
284 case 'u': /* --usercert */
285 usercertfile
= optarg
;
288 case 'g': /* --groups */
289 decode_groups(optarg
, &groups
);
292 case 'D': /* --days */
293 if (optarg
== NULL
|| !isdigit(optarg
[0]))
294 usage("missing number of days");
297 long days
= strtol(optarg
, &endptr
, 0);
299 if (*endptr
!= '\0' || endptr
== optarg
301 usage("<days> must be a positive number");
302 validity
+= 24*3600*days
;
306 case 'H': /* --hours */
307 if (optarg
== NULL
|| !isdigit(optarg
[0]))
308 usage("missing number of hours");
311 long hours
= strtol(optarg
, &endptr
, 0);
313 if (*endptr
!= '\0' || endptr
== optarg
315 usage("<hours> must be a positive number");
316 validity
+= 3600*hours
;
320 case 'S': /* --startdate */
321 if (optarg
== NULL
|| strlen(optarg
) != 15 || optarg
[14] != 'Z')
322 usage("date format must be YYYYMMDDHHMMSSZ");
324 chunk_t date
= { optarg
, 15 };
325 notBefore
= asn1totime(&date
, ASN1_GENERALIZEDTIME
);
329 case 'E': /* --enddate */
330 if (optarg
== NULL
|| strlen(optarg
) != 15 || optarg
[14] != 'Z')
331 usage("date format must be YYYYMMDDHHMMSSZ");
333 chunk_t date
= { optarg
, 15 };
334 notAfter
= asn1totime(&date
, ASN1_GENERALIZEDTIME
);
338 case 'o': /* --outt */
343 case 'A': /* --debug-all */
344 base_debugging
= DBG_ALL
;
351 base_debugging
|= c
- DBG_OFFSET
;
362 cur_debugging
= base_debugging
;
365 usage("unexpected argument");
367 /* load the signer's RSA private key */
372 signerkey
= alloc_thing(RSA_private_key_t
, "RSA private key");
373 ugh
= load_rsa_private_key(keyfile
, &pass
, signerkey
);
377 free_RSA_private_content(signerkey
);
384 /* load the signer's X.509 certificate */
385 if (certfile
!= NULL
)
387 if (!load_cert(certfile
, "signer cert", &signercert
))
389 signer
= signercert
.u
.x509
;
392 /* load the users's X.509 certificate */
393 if (usercertfile
!= NULL
)
395 if (!load_cert(usercertfile
, "user cert", &usercert
))
397 user
= usercert
.u
.x509
;
400 /* compute validity interval */
401 validity
= (validity
)? validity
: default_validity
;
402 notBefore
= (notBefore
) ? notBefore
: time(NULL
);
403 notAfter
= (notAfter
) ? notAfter
: notBefore
+ validity
;
405 /* build and parse attribute certificate */
406 if (user
!= NULL
&& signer
!= NULL
&& signerkey
!= NULL
)
408 /* read the serial number and increment it by one */
409 serial
= read_serial();
411 attr_cert
= build_attr_cert();
412 ac
= alloc_thing(x509acert_t
, "x509acert");
414 parse_ac(attr_cert
, ac
);
416 /* write the attribute certificate to file */
417 if (write_chunk(outfile
, "attribute cert", attr_cert
, 0022, TRUE
))
418 write_serial(serial
);
421 /* delete all dynamic objects */
422 if (signerkey
!= NULL
)
424 free_RSA_private_content(signerkey
);
427 free_x509cert(signercert
.u
.x509
);
428 free_x509cert(usercert
.u
.x509
);
429 free_ietfAttrList(groups
);
433 #ifdef LEAK_DETECTIVE
435 #endif /* LEAK_DETECTIVE */