changed tab spacing from 8 to 4

This commit is contained in:
Andreas Steffen 2007-04-10 19:31:42 +00:00
parent 00ccb87671
commit 241ab32c10
2 changed files with 432 additions and 441 deletions

View File

@ -31,212 +31,201 @@
#include "build.h" #include "build.h"
static u_char ASN1_group_oid_str[] = { static u_char ASN1_group_oid_str[] = {
0x06, 0x08, 0x06, 0x08,
0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x0a ,0x04 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x0a ,0x04
}; };
static const chunk_t ASN1_group_oid = strchunk(ASN1_group_oid_str); static const chunk_t ASN1_group_oid = strchunk(ASN1_group_oid_str);
static u_char ASN1_authorityKeyIdentifier_oid_str[] = { static u_char ASN1_authorityKeyIdentifier_oid_str[] = {
0x06, 0x03, 0x06, 0x03,
0x55, 0x1d, 0x23 0x55, 0x1d, 0x23
}; };
static const chunk_t ASN1_authorityKeyIdentifier_oid static const chunk_t ASN1_authorityKeyIdentifier_oid
= strchunk(ASN1_authorityKeyIdentifier_oid_str); = strchunk(ASN1_authorityKeyIdentifier_oid_str);
static u_char ASN1_noRevAvail_ext_str[] = { static u_char ASN1_noRevAvail_ext_str[] = {
0x30, 0x09, 0x30, 0x09,
0x06, 0x03, 0x06, 0x03,
0x55, 0x1d, 0x38, 0x55, 0x1d, 0x38,
0x04, 0x02, 0x04, 0x02,
0x05, 0x00 0x05, 0x00
}; };
static const chunk_t ASN1_noRevAvail_ext = strchunk(ASN1_noRevAvail_ext_str); static const chunk_t ASN1_noRevAvail_ext = strchunk(ASN1_noRevAvail_ext_str);
/* /**
* build directoryName * build directoryName
*/ */
static chunk_t static chunk_t build_directoryName(asn1_t tag, chunk_t name)
build_directoryName(asn1_t tag, chunk_t name)
{ {
return asn1_wrap(tag, "m" return asn1_wrap(tag, "m",
, asn1_simple_object(ASN1_CONTEXT_C_4, name)); asn1_simple_object(ASN1_CONTEXT_C_4, name));
} }
/* /**
* build holder * build holder
*/ */
static chunk_t static chunk_t build_holder(void)
build_holder(void)
{ {
return asn1_wrap(ASN1_SEQUENCE, "mm" return asn1_wrap(ASN1_SEQUENCE, "mm",
, asn1_wrap(ASN1_CONTEXT_C_0, "mm" asn1_wrap(ASN1_CONTEXT_C_0, "mm",
, build_directoryName(ASN1_SEQUENCE, user->issuer) build_directoryName(ASN1_SEQUENCE, user->issuer),
, asn1_simple_object(ASN1_INTEGER, user->serialNumber) asn1_simple_object(ASN1_INTEGER, user->serialNumber)
) ),
, build_directoryName(ASN1_CONTEXT_C_1, user->subject)); build_directoryName(ASN1_CONTEXT_C_1, user->subject));
} }
/* /**
* build v2Form * build v2Form
*/ */
static chunk_t static chunk_t build_v2_form(void)
build_v2_form(void)
{ {
return asn1_wrap(ASN1_CONTEXT_C_0, "m" return asn1_wrap(ASN1_CONTEXT_C_0, "m",
, build_directoryName(ASN1_SEQUENCE, signer->subject)); build_directoryName(ASN1_SEQUENCE, signer->subject));
} }
/* /**
* build attrCertValidityPeriod * build attrCertValidityPeriod
*/ */
static chunk_t static chunk_t build_attr_cert_validity(void)
build_attr_cert_validity(void)
{ {
return asn1_wrap(ASN1_SEQUENCE, "mm" return asn1_wrap(ASN1_SEQUENCE, "mm",
, timetoasn1(&notBefore, ASN1_GENERALIZEDTIME) timetoasn1(&notBefore, ASN1_GENERALIZEDTIME),
, timetoasn1(&notAfter, ASN1_GENERALIZEDTIME)); timetoasn1(&notAfter, ASN1_GENERALIZEDTIME));
} }
/* /**
* build attributes * build attributes
*/ */
static chunk_t static chunk_t build_ietfAttributes(ietfAttrList_t *list)
build_ietfAttributes(ietfAttrList_t *list)
{ {
chunk_t ietfAttributes; chunk_t ietfAttributes;
ietfAttrList_t *item = list; ietfAttrList_t *item = list;
size_t size = 0; size_t size = 0;
u_char *pos; u_char *pos;
/* precalculate the total size of all values */ /* precalculate the total size of all values */
while (item != NULL) while (item != NULL)
{
size_t len = item->attr->value.len;
size += 1 + (len > 0) + (len >= 128) + (len >= 256) + (len >= 65536) + len;
item = item->next;
}
pos = build_asn1_object(&ietfAttributes, ASN1_SEQUENCE, size);
while (list != NULL)
{
ietfAttr_t *attr = list->attr;
asn1_t type = ASN1_NULL;
switch (attr->kind)
{ {
case IETF_ATTRIBUTE_OCTETS: size_t len = item->attr->value.len;
type = ASN1_OCTET_STRING;
break; size += 1 + (len > 0) + (len >= 128) + (len >= 256) + (len >= 65536) + len;
case IETF_ATTRIBUTE_STRING: item = item->next;
type = ASN1_UTF8STRING;
break;
case IETF_ATTRIBUTE_OID:
type = ASN1_OID;
break;
} }
mv_chunk(&pos, asn1_simple_object(type, attr->value)); pos = build_asn1_object(&ietfAttributes, ASN1_SEQUENCE, size);
list = list->next; while (list != NULL)
} {
ietfAttr_t *attr = list->attr;
asn1_t type = ASN1_NULL;
return asn1_wrap(ASN1_SEQUENCE, "m", ietfAttributes); switch (attr->kind)
{
case IETF_ATTRIBUTE_OCTETS:
type = ASN1_OCTET_STRING;
break;
case IETF_ATTRIBUTE_STRING:
type = ASN1_UTF8STRING;
break;
case IETF_ATTRIBUTE_OID:
type = ASN1_OID;
break;
}
mv_chunk(&pos, asn1_simple_object(type, attr->value));
list = list->next;
}
return asn1_wrap(ASN1_SEQUENCE, "m", ietfAttributes);
} }
/* /**
* build attribute type * build attribute type
*/ */
static chunk_t static chunk_t build_attribute_type(const chunk_t type, chunk_t content)
build_attribute_type(const chunk_t type, chunk_t content)
{ {
return asn1_wrap(ASN1_SEQUENCE, "cm" return asn1_wrap(ASN1_SEQUENCE, "cm",
, type type,
, asn1_wrap(ASN1_SET, "m", content)); asn1_wrap(ASN1_SET, "m", content));
} }
/* /**
* build attributes * build attributes
*/ */
static chunk_t static chunk_t build_attributes(void)
build_attributes(void)
{ {
return asn1_wrap(ASN1_SEQUENCE, "m" return asn1_wrap(ASN1_SEQUENCE, "m",
, build_attribute_type(ASN1_group_oid build_attribute_type(ASN1_group_oid,
, build_ietfAttributes(groups))); build_ietfAttributes(groups)));
} }
/* /**
* build authorityKeyIdentifier * build authorityKeyIdentifier
*/ */
static chunk_t static chunk_t build_authorityKeyID(x509cert_t *signer)
build_authorityKeyID(x509cert_t *signer)
{ {
chunk_t keyIdentifier = (signer->subjectKeyID.ptr == NULL) chunk_t keyIdentifier = (signer->subjectKeyID.ptr == NULL)
? empty_chunk ? empty_chunk
: asn1_simple_object(ASN1_CONTEXT_S_0 : asn1_simple_object(ASN1_CONTEXT_S_0,
, signer->subjectKeyID); signer->subjectKeyID);
chunk_t authorityCertIssuer = build_directoryName(ASN1_CONTEXT_C_1 chunk_t authorityCertIssuer = build_directoryName(ASN1_CONTEXT_C_1,
, signer->issuer); signer->issuer);
chunk_t authorityCertSerialNumber = asn1_simple_object(ASN1_CONTEXT_S_2 chunk_t authorityCertSerialNumber = asn1_simple_object(ASN1_CONTEXT_S_2,
, signer->serialNumber); signer->serialNumber);
return asn1_wrap(ASN1_SEQUENCE, "cm" return asn1_wrap(ASN1_SEQUENCE, "cm",
, ASN1_authorityKeyIdentifier_oid ASN1_authorityKeyIdentifier_oid,
, asn1_wrap(ASN1_OCTET_STRING, "m" asn1_wrap(ASN1_OCTET_STRING, "m",
, asn1_wrap(ASN1_SEQUENCE, "mmm" asn1_wrap(ASN1_SEQUENCE, "mmm",
, keyIdentifier keyIdentifier,
, authorityCertIssuer authorityCertIssuer,
, authorityCertSerialNumber authorityCertSerialNumber
) )
) )
); );
} }
/* /**
* build extensions * build extensions
*/ */
static chunk_t static chunk_t build_extensions(void)
build_extensions(void)
{ {
return asn1_wrap(ASN1_SEQUENCE, "mc" return asn1_wrap(ASN1_SEQUENCE, "mc",
, build_authorityKeyID(signer) build_authorityKeyID(signer),
, ASN1_noRevAvail_ext); ASN1_noRevAvail_ext);
} }
/* /**
* build attributeCertificateInfo * build attributeCertificateInfo
*/ */
static chunk_t static chunk_t build_attr_cert_info(void)
build_attr_cert_info(void)
{ {
return asn1_wrap(ASN1_SEQUENCE, "cmmcmmmm" return asn1_wrap(ASN1_SEQUENCE, "cmmcmmmm",
, ASN1_INTEGER_1 ASN1_INTEGER_1,
, build_holder() build_holder(),
, build_v2_form() build_v2_form(),
, ASN1_sha1WithRSA_id ASN1_sha1WithRSA_id,
, asn1_simple_object(ASN1_INTEGER, serial) asn1_simple_object(ASN1_INTEGER, serial),
, build_attr_cert_validity() build_attr_cert_validity(),
, build_attributes() build_attributes(),
, build_extensions()); build_extensions());
} }
/* /**
* build an X.509 attribute certificate * build an X.509 attribute certificate
*/ */
chunk_t chunk_t build_attr_cert(void)
build_attr_cert(void)
{ {
chunk_t attributeCertificateInfo = build_attr_cert_info(); chunk_t attributeCertificateInfo = build_attr_cert_info();
chunk_t signatureValue = pkcs1_build_signature(attributeCertificateInfo chunk_t signatureValue = pkcs1_build_signature(attributeCertificateInfo,
, OID_SHA1, signerkey, TRUE); OID_SHA1, signerkey, TRUE);
return asn1_wrap(ASN1_SEQUENCE, "mcm" return asn1_wrap(ASN1_SEQUENCE, "mcm",
, attributeCertificateInfo attributeCertificateInfo,
, ASN1_sha1WithRSA_id ASN1_sha1WithRSA_id,
, signatureValue); signatureValue);
} }

View File

@ -57,107 +57,113 @@ bool pkcs11_keep_state = FALSE;
static void static void
usage(const char *mess) usage(const char *mess)
{ {
if (mess != NULL && *mess != '\0') if (mess != NULL && *mess != '\0')
fprintf(stderr, "%s\n", mess); {
fprintf(stderr fprintf(stderr, "%s\n", mess);
, "Usage: openac" }
" [--help]" fprintf(stderr, "Usage: openac"
" [--version]" " [--help]"
" [--optionsfrom <filename>]" " [--version]"
" [--quiet]" " [--optionsfrom <filename>]"
" [--quiet]"
#ifdef DEBUG #ifdef DEBUG
" \\\n\t" " \\\n\t"
" [--debug-all]" " [--debug-all]"
" [--debug-parsing]" " [--debug-parsing]"
" [--debug-raw]" " [--debug-raw]"
" [--debug-private]" " [--debug-private]"
#endif #endif
" \\\n\t" " \\\n\t"
" [--days <days>]" " [--days <days>]"
" [--hours <hours>]" " [--hours <hours>]"
" \\\n\t" " \\\n\t"
" [--startdate <YYYYMMDDHHMMSSZ>]" " [--startdate <YYYYMMDDHHMMSSZ>]"
" [--enddate <YYYYMMDDHHMMSSZ>]" " [--enddate <YYYYMMDDHHMMSSZ>]"
" \\\n\t" " \\\n\t"
" --cert <certfile>" " --cert <certfile>"
" --key <keyfile>" " --key <keyfile>"
" [--password <password>]" " [--password <password>]"
" \\\n\t" " \\\n\t"
" --usercert <certfile>" " --usercert <certfile>"
" --groups <attr1,attr2,..>" " --groups <attr1,attr2,..>"
" --out <filename>" " --out <filename>"
"\n" "\n"
); );
exit(mess == NULL? 0 : 1); exit(mess == NULL? 0 : 1);
} }
/* /**
* read the last serial number from file * read the last serial number from file
*/ */
static chunk_t static chunk_t read_serial(void)
read_serial(void)
{ {
MP_INT number; MP_INT number;
char buf[BUF_LEN]; char buf[BUF_LEN];
char bytes[BUF_LEN]; char bytes[BUF_LEN];
FILE *fd = fopen(OPENAC_SERIAL, "r"); FILE *fd = fopen(OPENAC_SERIAL, "r");
/* serial number defaults to 0 */ /* serial number defaults to 0 */
size_t len = 1; size_t len = 1;
bytes[0] = 0x00; bytes[0] = 0x00;
if (fd) if (fd)
{
if (fscanf(fd, "%s", buf))
{ {
err_t ugh = ttodata(buf, 0, 16, bytes, BUF_LEN, &len); if (fscanf(fd, "%s", buf))
{
err_t ugh = ttodata(buf, 0, 16, bytes, BUF_LEN, &len);
if (ugh != NULL) if (ugh != NULL)
plog(" error reading serial number from %s: %s" {
, OPENAC_SERIAL, ugh); plog(" error reading serial number from %s: %s"
, OPENAC_SERIAL, ugh);
}
}
fclose(fd);
} }
fclose(fd); else
} {
else plog(" file '%s' does not exist yet - serial number set to 01"
plog(" file '%s' does not exist yet - serial number set to 01"
, OPENAC_SERIAL); , OPENAC_SERIAL);
}
/* conversion of read serial number to a multiprecision integer /**
* and incrementing it by one * conversion of read serial number to a multiprecision integer
* and representing it as a two's complement octet string * and incrementing it by one
*/ * and representing it as a two's complement octet string
n_to_mpz(&number, bytes, len); */
mpz_add_ui(&number, &number, 0x01); n_to_mpz(&number, bytes, len);
serial = mpz_to_n(&number, 1 + mpz_sizeinbase(&number, 2)/BITS_PER_BYTE); mpz_add_ui(&number, &number, 0x01);
mpz_clear(&number); serial = mpz_to_n(&number, 1 + mpz_sizeinbase(&number, 2)/BITS_PER_BYTE);
mpz_clear(&number);
return serial; return serial;
} }
/* /**
* write back the last serial number to file * write back the last serial number to file
*/ */
static void static void write_serial(chunk_t serial)
write_serial(chunk_t serial)
{ {
char buf[BUF_LEN]; char buf[BUF_LEN];
FILE *fd = fopen(OPENAC_SERIAL, "w"); FILE *fd = fopen(OPENAC_SERIAL, "w");
if (fd) if (fd)
{ {
datatot(serial.ptr, serial.len, 16, buf, BUF_LEN); datatot(serial.ptr, serial.len, 16, buf, BUF_LEN);
plog(" serial number is %s", buf); plog(" serial number is %s", buf);
fprintf(fd, "%s\n", buf); fprintf(fd, "%s\n", buf);
fclose(fd); fclose(fd);
} }
else else
plog(" could not open file '%s' for writing", OPENAC_SERIAL); {
plog(" could not open file '%s' for writing", OPENAC_SERIAL);
}
} }
/* /**
* global variables accessible by both main() and build.c * global variables accessible by both main() and build.c
*/ */
x509cert_t *user = NULL; x509cert_t *user = NULL;
@ -171,268 +177,264 @@ time_t notAfter = 0;
chunk_t serial; chunk_t serial;
int main(int argc, char **argv)
int
main(int argc, char **argv)
{ {
char *keyfile = NULL; char *keyfile = NULL;
char *certfile = NULL; char *certfile = NULL;
char *usercertfile = NULL; char *usercertfile = NULL;
char *outfile = NULL; char *outfile = NULL;
cert_t signercert = empty_cert; cert_t signercert = empty_cert;
cert_t usercert = empty_cert; cert_t usercert = empty_cert;
chunk_t attr_cert = empty_chunk; chunk_t attr_cert = empty_chunk;
x509acert_t *ac = NULL; x509acert_t *ac = NULL;
const time_t default_validity = 24*3600; /* 24 hours */ const time_t default_validity = 24*3600; /* 24 hours */
time_t validity = 0; time_t validity = 0;
prompt_pass_t pass; prompt_pass_t pass;
pass.secret[0] = '\0'; pass.secret[0] = '\0';
pass.prompt = TRUE; pass.prompt = TRUE;
pass.fd = STDIN_FILENO; pass.fd = STDIN_FILENO;
log_to_stderr = TRUE; log_to_stderr = TRUE;
/* handle arguments */ /* handle arguments */
for (;;) for (;;)
{
# define DBG_OFFSET 256
static const struct option long_opts[] = {
/* name, has_arg, flag, val */
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'v' },
{ "optionsfrom", required_argument, NULL, '+' },
{ "quiet", no_argument, NULL, 'q' },
{ "cert", required_argument, NULL, 'c' },
{ "key", required_argument, NULL, 'k' },
{ "password", required_argument, NULL, 'p' },
{ "usercert", required_argument, NULL, 'u' },
{ "groups", required_argument, NULL, 'g' },
{ "days", required_argument, NULL, 'D' },
{ "hours", required_argument, NULL, 'H' },
{ "startdate", required_argument, NULL, 'S' },
{ "enddate", required_argument, NULL, 'E' },
{ "out", required_argument, NULL, 'o' },
#ifdef DEBUG
{ "debug-all", no_argument, NULL, 'A' },
{ "debug-raw", no_argument, NULL, DBG_RAW + DBG_OFFSET },
{ "debug-parsing", no_argument, NULL, DBG_PARSING + DBG_OFFSET },
{ "debug-private", no_argument, NULL, DBG_PRIVATE + DBG_OFFSET },
#endif
{ 0,0,0,0 }
};
int c = getopt_long(argc, argv, "hv+:qc:k:p;u:g:D:H:S:E:o:", long_opts, NULL);
/* Note: "breaking" from case terminates loop */
switch (c)
{ {
case EOF: /* end of flags */ # define DBG_OFFSET 256
break; static const struct option long_opts[] = {
/* name, has_arg, flag, val */
case 0: /* long option already handled */ { "help", no_argument, NULL, 'h' },
continue; { "version", no_argument, NULL, 'v' },
{ "optionsfrom", required_argument, NULL, '+' },
case ':': /* diagnostic already printed by getopt_long */ { "quiet", no_argument, NULL, 'q' },
case '?': /* diagnostic already printed by getopt_long */ { "cert", required_argument, NULL, 'c' },
usage(NULL); { "key", required_argument, NULL, 'k' },
break; /* not actually reached */ { "password", required_argument, NULL, 'p' },
{ "usercert", required_argument, NULL, 'u' },
case 'h': /* --help */ { "groups", required_argument, NULL, 'g' },
usage(NULL); { "days", required_argument, NULL, 'D' },
break; /* not actually reached */ { "hours", required_argument, NULL, 'H' },
{ "startdate", required_argument, NULL, 'S' },
case 'v': /* --version */ { "enddate", required_argument, NULL, 'E' },
printf("%s\n", openac_version); { "out", required_argument, NULL, 'o' },
exit(0);
break; /* not actually reached */
case '+': /* --optionsfrom <filename> */
{
char path[BUF_LEN];
if (*optarg == '/') /* absolute pathname */
strncpy(path, optarg, BUF_LEN);
else /* relative pathname */
snprintf(path, BUF_LEN, "%s/%s", OPENAC_PATH, optarg);
optionsfrom(path, &argc, &argv, optind, stderr);
/* does not return on error */
}
continue;
case 'q': /* --quiet */
log_to_stderr = TRUE;
continue;
case 'c': /* --cert */
certfile = optarg;
continue;
case 'k': /* --key */
keyfile = optarg;
continue;
case 'p': /* --key */
pass.prompt = FALSE;
strncpy(pass.secret, optarg, sizeof(pass.secret));
continue;
case 'u': /* --usercert */
usercertfile = optarg;
continue;
case 'g': /* --groups */
decode_groups(optarg, &groups);
continue;
case 'D': /* --days */
if (optarg == NULL || !isdigit(optarg[0]))
usage("missing number of days");
{
char *endptr;
long days = strtol(optarg, &endptr, 0);
if (*endptr != '\0' || endptr == optarg
|| days <= 0)
usage("<days> must be a positive number");
validity += 24*3600*days;
}
continue;
case 'H': /* --hours */
if (optarg == NULL || !isdigit(optarg[0]))
usage("missing number of hours");
{
char *endptr;
long hours = strtol(optarg, &endptr, 0);
if (*endptr != '\0' || endptr == optarg
|| hours <= 0)
usage("<hours> must be a positive number");
validity += 3600*hours;
}
continue;
case 'S': /* --startdate */
if (optarg == NULL || strlen(optarg) != 15 || optarg[14] != 'Z')
usage("date format must be YYYYMMDDHHMMSSZ");
{
chunk_t date = { optarg, 15 };
notBefore = asn1totime(&date, ASN1_GENERALIZEDTIME);
}
continue;
case 'E': /* --enddate */
if (optarg == NULL || strlen(optarg) != 15 || optarg[14] != 'Z')
usage("date format must be YYYYMMDDHHMMSSZ");
{
chunk_t date = { optarg, 15 };
notAfter = asn1totime(&date, ASN1_GENERALIZEDTIME);
}
continue;
case 'o': /* --outt */
outfile = optarg;
continue ;
#ifdef DEBUG #ifdef DEBUG
case 'A': /* --debug-all */ { "debug-all", no_argument, NULL, 'A' },
base_debugging = DBG_ALL; { "debug-raw", no_argument, NULL, DBG_RAW + DBG_OFFSET },
continue; { "debug-parsing", no_argument, NULL, DBG_PARSING + DBG_OFFSET },
{ "debug-private", no_argument, NULL, DBG_PRIVATE + DBG_OFFSET },
#endif #endif
default: { 0,0,0,0 }
};
int c = getopt_long(argc, argv, "hv+:qc:k:p;u:g:D:H:S:E:o:", long_opts, NULL);
/* Note: "breaking" from case terminates loop */
switch (c)
{
case EOF: /* end of flags */
break;
case 0: /* long option already handled */
continue;
case ':': /* diagnostic already printed by getopt_long */
case '?': /* diagnostic already printed by getopt_long */
usage(NULL);
break; /* not actually reached */
case 'h': /* --help */
usage(NULL);
break; /* not actually reached */
case 'v': /* --version */
printf("%s\n", openac_version);
exit(0);
break; /* not actually reached */
case '+': /* --optionsfrom <filename> */
{
char path[BUF_LEN];
if (*optarg == '/') /* absolute pathname */
strncpy(path, optarg, BUF_LEN);
else /* relative pathname */
snprintf(path, BUF_LEN, "%s/%s", OPENAC_PATH, optarg);
optionsfrom(path, &argc, &argv, optind, stderr);
/* does not return on error */
}
continue;
case 'q': /* --quiet */
log_to_stderr = TRUE;
continue;
case 'c': /* --cert */
certfile = optarg;
continue;
case 'k': /* --key */
keyfile = optarg;
continue;
case 'p': /* --key */
pass.prompt = FALSE;
strncpy(pass.secret, optarg, sizeof(pass.secret));
continue;
case 'u': /* --usercert */
usercertfile = optarg;
continue;
case 'g': /* --groups */
decode_groups(optarg, &groups);
continue;
case 'D': /* --days */
if (optarg == NULL || !isdigit(optarg[0]))
usage("missing number of days");
{
char *endptr;
long days = strtol(optarg, &endptr, 0);
if (*endptr != '\0' || endptr == optarg || days <= 0)
usage("<days> must be a positive number");
validity += 24*3600*days;
}
continue;
case 'H': /* --hours */
if (optarg == NULL || !isdigit(optarg[0]))
usage("missing number of hours");
{
char *endptr;
long hours = strtol(optarg, &endptr, 0);
if (*endptr != '\0' || endptr == optarg || hours <= 0)
usage("<hours> must be a positive number");
validity += 3600*hours;
}
continue;
case 'S': /* --startdate */
if (optarg == NULL || strlen(optarg) != 15 || optarg[14] != 'Z')
usage("date format must be YYYYMMDDHHMMSSZ");
{
chunk_t date = { optarg, 15 };
notBefore = asn1totime(&date, ASN1_GENERALIZEDTIME);
}
continue;
case 'E': /* --enddate */
if (optarg == NULL || strlen(optarg) != 15 || optarg[14] != 'Z')
usage("date format must be YYYYMMDDHHMMSSZ");
{
chunk_t date = { optarg, 15 };
notAfter = asn1totime(&date, ASN1_GENERALIZEDTIME);
}
continue;
case 'o': /* --outt */
outfile = optarg;
continue;
#ifdef DEBUG #ifdef DEBUG
if (c >= DBG_OFFSET) case 'A': /* --debug-all */
{ base_debugging = DBG_ALL;
base_debugging |= c - DBG_OFFSET; continue;
continue; #endif
} default:
#ifdef DEBUG
if (c >= DBG_OFFSET)
{
base_debugging |= c - DBG_OFFSET;
continue;
}
#undef DBG_OFFSET #undef DBG_OFFSET
#endif #endif
bad_case(c); bad_case(c);
}
break;
} }
break;
}
init_log("openac"); init_log("openac");
cur_debugging = base_debugging; cur_debugging = base_debugging;
if (optind != argc) if (optind != argc)
usage("unexpected argument"); usage("unexpected argument");
/* load the signer's RSA private key */ /* load the signer's RSA private key */
if (keyfile != NULL) if (keyfile != NULL)
{
err_t ugh = NULL;
signerkey = alloc_thing(RSA_private_key_t, "RSA private key");
ugh = load_rsa_private_key(keyfile, &pass, signerkey);
if (ugh != NULL)
{ {
free_RSA_private_content(signerkey); err_t ugh = NULL;
pfree(signerkey);
plog("%s", ugh); signerkey = alloc_thing(RSA_private_key_t, "RSA private key");
exit(1); ugh = load_rsa_private_key(keyfile, &pass, signerkey);
if (ugh != NULL)
{
free_RSA_private_content(signerkey);
pfree(signerkey);
plog("%s", ugh);
exit(1);
}
} }
}
/* load the signer's X.509 certificate */ /* load the signer's X.509 certificate */
if (certfile != NULL) if (certfile != NULL)
{ {
if (!load_cert(certfile, "signer cert", &signercert)) if (!load_cert(certfile, "signer cert", &signercert))
exit(1); exit(1);
signer = signercert.u.x509; signer = signercert.u.x509;
} }
/* load the users's X.509 certificate */ /* load the users's X.509 certificate */
if (usercertfile != NULL) if (usercertfile != NULL)
{ {
if (!load_cert(usercertfile, "user cert", &usercert)) if (!load_cert(usercertfile, "user cert", &usercert))
exit(1); exit(1);
user = usercert.u.x509; user = usercert.u.x509;
} }
/* compute validity interval */
validity = (validity)? validity : default_validity;
notBefore = (notBefore) ? notBefore : time(NULL);
notAfter = (notAfter) ? notAfter : notBefore + validity;
/* build and parse attribute certificate */ /* compute validity interval */
if (user != NULL && signer != NULL && signerkey != NULL) validity = (validity)? validity : default_validity;
{ notBefore = (notBefore) ? notBefore : time(NULL);
/* read the serial number and increment it by one */ notAfter = (notAfter) ? notAfter : notBefore + validity;
serial = read_serial();
attr_cert = build_attr_cert(); /* build and parse attribute certificate */
ac = alloc_thing(x509acert_t, "x509acert"); if (user != NULL && signer != NULL && signerkey != NULL)
*ac = empty_ac; {
parse_ac(attr_cert, ac); /* read the serial number and increment it by one */
serial = read_serial();
attr_cert = build_attr_cert();
ac = alloc_thing(x509acert_t, "x509acert");
*ac = empty_ac;
parse_ac(attr_cert, ac);
/* write the attribute certificate to file */ /* write the attribute certificate to file */
if (write_chunk(outfile, "attribute cert", attr_cert, 0022, TRUE)) if (write_chunk(outfile, "attribute cert", attr_cert, 0022, TRUE))
write_serial(serial); write_serial(serial);
} }
/* delete all dynamic objects */ /* delete all dynamic objects */
if (signerkey != NULL) if (signerkey != NULL)
{ {
free_RSA_private_content(signerkey); free_RSA_private_content(signerkey);
pfree(signerkey); pfree(signerkey);
} }
free_x509cert(signercert.u.x509); free_x509cert(signercert.u.x509);
free_x509cert(usercert.u.x509); free_x509cert(usercert.u.x509);
free_ietfAttrList(groups); free_ietfAttrList(groups);
free_acert(ac); free_acert(ac);
pfree(serial.ptr); pfree(serial.ptr);
#ifdef LEAK_DETECTIVE #ifdef LEAK_DETECTIVE
report_leaks(); report_leaks();
#endif /* LEAK_DETECTIVE */ #endif /* LEAK_DETECTIVE */
close_log(); close_log();
exit(0); exit(0);
} }