static int load_all(vici_conn_t *conn) { bool clear = FALSE, noprompt = FALSE; command_format_options_t format = COMMAND_FORMAT_NONE; settings_t *cfg; int ret = 0; char *arg; while (TRUE) { switch (command_getopt(&arg)) { case 'h': return command_usage(NULL); case 'c': clear = TRUE; continue; case 'n': noprompt = TRUE; continue; case 'P': format |= COMMAND_FORMAT_PRETTY; /* fall through to raw */ case 'r': format |= COMMAND_FORMAT_RAW; continue; case EOF: break; default: return command_usage("invalid --load-all option"); } break; } cfg = settings_create(SWANCTL_CONF); if (!cfg) { fprintf(stderr, "parsing '%s' failed\n", SWANCTL_CONF); return EINVAL; } if (ret == 0) { ret = load_creds_cfg(conn, format, cfg, clear, noprompt); } if (ret == 0) { ret = load_pools_cfg(conn, format, cfg); } if (ret == 0) { ret = load_conns_cfg(conn, format, cfg); } cfg->destroy(cfg); return ret; }
static int list_pools(vici_conn_t *conn) { vici_req_t *req; vici_res_t *res; bool raw = FALSE; char *arg; int ret = 0; while (TRUE) { switch (command_getopt(&arg)) { case 'h': return command_usage(NULL); case 'r': raw = TRUE; continue; case EOF: break; default: return command_usage("invalid --list-pools option"); } break; } req = vici_begin("get-pools"); res = vici_submit(req, conn); if (!res) { fprintf(stderr, "get-pools request failed: %s\n", strerror(errno)); return errno; } if (raw) { vici_dump(res, "get-pools reply", stdout); } else { ret = vici_parse_cb(res, list_pool, NULL, NULL, NULL); } vici_free_res(res); return ret; }
static int load_authorities(vici_conn_t *conn) { command_format_options_t format = COMMAND_FORMAT_NONE; settings_t *cfg; char *arg, *file = NULL; int ret; while (TRUE) { switch (command_getopt(&arg)) { case 'h': return command_usage(NULL); case 'P': format |= COMMAND_FORMAT_PRETTY; /* fall through to raw */ case 'r': format |= COMMAND_FORMAT_RAW; continue; case 'f': file = arg; continue; case EOF: break; default: return command_usage("invalid --load-authorities option"); } break; } cfg = load_swanctl_conf(file); if (!cfg) { return EINVAL; } ret = load_authorities_cfg(conn, format, cfg); cfg->destroy(cfg); return ret; }
static int load_authorities(vici_conn_t *conn) { command_format_options_t format = COMMAND_FORMAT_NONE; settings_t *cfg; char *arg; int ret; while (TRUE) { switch (command_getopt(&arg)) { case 'h': return command_usage(NULL); case 'P': format |= COMMAND_FORMAT_PRETTY; /* fall through to raw */ case 'r': format |= COMMAND_FORMAT_RAW; continue; case EOF: break; default: return command_usage("invalid --load-authorities option"); } break; } cfg = settings_create(SWANCTL_CONF); if (!cfg) { fprintf(stderr, "parsing '%s' failed\n", SWANCTL_CONF); return EINVAL; } ret = load_authorities_cfg(conn, format, cfg); cfg->destroy(cfg); return ret; }
static int logcmd(vici_conn_t *conn) { command_format_options_t format = COMMAND_FORMAT_NONE; char *arg; while (TRUE) { switch (command_getopt(&arg)) { case 'h': return command_usage(NULL); case 'P': format |= COMMAND_FORMAT_PRETTY; /* fall through to raw */ case 'r': format |= COMMAND_FORMAT_RAW; continue; case EOF: break; default: return command_usage("invalid --log option"); } break; } if (vici_register(conn, "log", log_cb, &format) != 0) { fprintf(stderr, "registering for log failed: %s\n", strerror(errno)); return errno; } wait_sigint(); fprintf(stderr, "disconnecting...\n"); return 0; }
/** * Verify a certificate signature */ static int verify() { bool trusted = FALSE, valid = FALSE, revoked = FALSE; bool has_ca = FALSE, online = FALSE; certificate_t *cert; enumerator_t *enumerator; auth_cfg_t *auth; mem_cred_t *creds; char *arg, *file = NULL; creds = mem_cred_create(); lib->credmgr->add_set(lib->credmgr, &creds->set); while (TRUE) { switch (command_getopt(&arg)) { case 'h': creds->destroy(creds); return command_usage(NULL); case 'i': file = arg; continue; case 'c': if (load_certs(creds, arg, CERT_X509)) { has_ca = TRUE; } continue; case 'l': if (load_certs(creds, arg, CERT_X509_CRL)) { online = TRUE; } continue; case 'o': online = TRUE; continue; case EOF: break; default: creds->destroy(creds); return command_usage("invalid --verify option"); } break; } if (file) { cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, BUILD_FROM_FILE, file, BUILD_END); } else { chunk_t chunk; set_file_mode(stdin, CERT_ASN1_DER); if (!chunk_from_fd(0, &chunk)) { fprintf(stderr, "reading certificate failed: %s\n", strerror(errno)); goto end; } cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, BUILD_BLOB, chunk, BUILD_END); free(chunk.ptr); } if (!cert) { fprintf(stderr, "parsing certificate failed\n"); goto end; } cert = creds->add_cert_ref(creds, !has_ca, cert); enumerator = lib->credmgr->create_trusted_enumerator(lib->credmgr, KEY_ANY, cert->get_subject(cert), online); if (enumerator->enumerate(enumerator, &cert, &auth)) { trusted = TRUE; if (cert->get_validity(cert, NULL, NULL, NULL)) { printf("certificate trusted, lifetimes valid"); valid = TRUE; } else { printf("certificate trusted, but no valid lifetime"); } if (online) { switch ((uintptr_t)auth->get(auth, AUTH_RULE_CRL_VALIDATION)) { case VALIDATION_GOOD: printf(", certificate not revoked"); break; case VALIDATION_SKIPPED: printf(", no revocation information"); break; case VALIDATION_STALE: printf(", revocation information stale"); break; case VALIDATION_FAILED: printf(", revocation checking failed"); break; case VALIDATION_ON_HOLD: printf(", certificate revocation on hold"); revoked = TRUE; break; case VALIDATION_REVOKED: printf(", certificate revoked"); revoked = TRUE; break; } } printf("\n"); } enumerator->destroy(enumerator); cert->destroy(cert); if (!trusted) { printf("certificate untrusted\n"); } end: lib->credmgr->remove_set(lib->credmgr, &creds->set); creds->destroy(creds); if (!trusted) { return 1; } if (!valid) { return 2; } if (revoked) { return 3; } return 0; }
static int load_pools(vici_conn_t *conn) { command_format_options_t format = COMMAND_FORMAT_NONE; u_int found = 0, loaded = 0, unloaded = 0; char *arg, *section; enumerator_t *enumerator; linked_list_t *pools; settings_t *cfg; while (TRUE) { switch (command_getopt(&arg)) { case 'h': return command_usage(NULL); case 'P': format |= COMMAND_FORMAT_PRETTY; /* fall through to raw */ case 'r': format |= COMMAND_FORMAT_RAW; continue; case EOF: break; default: return command_usage("invalid --load-pools option"); } break; } cfg = settings_create(SWANCTL_CONF); if (!cfg) { fprintf(stderr, "parsing '%s' failed\n", SWANCTL_CONF); return EINVAL; } pools = list_pools(conn, format); enumerator = cfg->create_section_enumerator(cfg, "pools"); while (enumerator->enumerate(enumerator, §ion)) { remove_from_list(pools, section); found++; if (load_pool(conn, cfg, section, format)) { loaded++; } } enumerator->destroy(enumerator); cfg->destroy(cfg); /* unload all pools in daemon, but not in file */ while (pools->remove_first(pools, (void**)§ion) == SUCCESS) { if (unload_pool(conn, section, format)) { unloaded++; } free(section); } pools->destroy(pools); if (format & COMMAND_FORMAT_RAW) { return 0; } if (found == 0) { printf("no pools found, %u unloaded\n", unloaded); return 0; } if (loaded == found) { printf("successfully loaded %u pools, %u unloaded\n", loaded, unloaded); return 0; } fprintf(stderr, "loaded %u of %u pools, %u failed to load, " "%u unloaded\n", loaded, found, found - loaded, unloaded); return EINVAL; }
/** * Extract subject DN */ static int dn() { identification_t *id; certificate_t *cert; chunk_t chunk; enum { FORMAT_CONFIG, FORMAT_HEX, FORMAT_BASE64, FORMAT_BINARY, } format = FORMAT_CONFIG; char *arg, *file = NULL, *fmt; while (TRUE) { switch (command_getopt(&arg)) { case 'h': return command_usage(NULL); case 'f': if (streq(arg, "hex")) { format = FORMAT_HEX; } else if (streq(arg, "base64")) { format = FORMAT_BASE64; } else if (streq(arg, "bin")) { format = FORMAT_BINARY; } else if (!streq(arg, "config")) { return command_usage( "invalid output format"); } continue; case 'i': file = arg; continue; case EOF: break; default: return command_usage("invalid --print option"); } break; } if (file) { cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, BUILD_FROM_FILE, file, BUILD_END); } else { chunk_t chunk; set_file_mode(stdin, CERT_ASN1_DER); if (!chunk_from_fd(0, &chunk)) { fprintf(stderr, "reading input failed: %s\n", strerror(errno)); return 1; } cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, BUILD_BLOB, chunk, BUILD_END); free(chunk.ptr); } if (!cert) { fprintf(stderr, "parsing input failed\n"); return 1; } id = cert->get_subject(cert); if (!id) { fprintf(stderr, "failed to get certificate's subject DN\n"); cert->destroy(cert); return 1; } fmt = "%.*s\n"; switch (format) { case FORMAT_CONFIG: fmt = "\"asn1dn:#%.*s\"\n"; /* fall-through */ case FORMAT_HEX: chunk = chunk_to_hex(id->get_encoding(id), NULL, FALSE); printf(fmt, (int)chunk.len, chunk.ptr); chunk_free(&chunk); break; case FORMAT_BASE64: chunk = chunk_to_base64(id->get_encoding(id), NULL); printf(fmt, (int)chunk.len, chunk.ptr); chunk_free(&chunk); break; case FORMAT_BINARY: chunk = id->get_encoding(id); if (fwrite(chunk.ptr, chunk.len, 1, stdout) != 1) { fprintf(stderr, "writing subject DN failed\n"); } break; } cert->destroy(cert); return 0; }
/** * Issue an attribute certificate */ static int acert() { cred_encoding_type_t form = CERT_ASN1_DER; hash_algorithm_t digest = HASH_SHA1; certificate_t *ac = NULL, *cert = NULL, *issuer =NULL; private_key_t *private = NULL; public_key_t *public = NULL; char *file = NULL, *hex = NULL, *issuercert = NULL, *issuerkey = NULL; char *error = NULL, *keyid = NULL; linked_list_t *groups; chunk_t serial = chunk_empty, encoding = chunk_empty; time_t not_before, not_after, lifetime = 24 * 60 * 60; char *datenb = NULL, *datena = NULL, *dateform = NULL; rng_t *rng; char *arg; groups = linked_list_create(); while (TRUE) { switch (command_getopt(&arg)) { case 'h': goto usage; case 'g': if (!enum_from_name(hash_algorithm_short_names, arg, &digest)) { error = "invalid --digest type"; goto usage; } continue; case 'i': file = arg; continue; case 'm': groups->insert_last(groups, arg); continue; case 'c': issuercert = arg; continue; case 'k': issuerkey = arg; continue; case 'x': keyid = arg; continue; case 'l': lifetime = atoi(arg) * 60 * 60; if (!lifetime) { error = "invalid --lifetime value"; goto usage; } continue; case 'D': dateform = arg; continue; case 'F': datenb = arg; continue; case 'T': datena = arg; continue; case 's': hex = arg; continue; case 'f': if (!get_form(arg, &form, CRED_CERTIFICATE)) { error = "invalid output format"; goto usage; } continue; case EOF: break; default: error = "invalid --acert option"; goto usage; } break; } if (!calculate_lifetime(dateform, datenb, datena, lifetime, ¬_before, ¬_after)) { error = "invalid --not-before/after datetime"; goto usage; } if (!issuercert) { error = "--issuercert is required"; goto usage; } if (!issuerkey && !keyid) { error = "--issuerkey or --issuerkeyid is required"; goto usage; } issuer = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, BUILD_FROM_FILE, issuercert, BUILD_END); if (!issuer) { error = "parsing issuer certificate failed"; goto end; } public = issuer->get_public_key(issuer);
/** * Create a self-signed PKCS#10 certificate requesst. */ static int req() { cred_encoding_type_t form = CERT_ASN1_DER; key_type_t type = KEY_RSA; hash_algorithm_t digest = HASH_SHA1; certificate_t *cert = NULL; private_key_t *private = NULL; char *file = NULL, *dn = NULL, *error = NULL; identification_t *id = NULL; linked_list_t *san; chunk_t encoding = chunk_empty; chunk_t challenge_password = chunk_empty; char *arg; san = linked_list_create(); while (TRUE) { switch (command_getopt(&arg)) { case 'h': goto usage; case 't': if (streq(arg, "rsa")) { type = KEY_RSA; } else if (streq(arg, "ecdsa")) { type = KEY_ECDSA; } else if (streq(arg, "bliss")) { type = KEY_BLISS; } else { error = "invalid input type"; goto usage; } continue; case 'g': if (!enum_from_name(hash_algorithm_short_names, arg, &digest)) { error = "invalid --digest type"; goto usage; } continue; case 'i': file = arg; continue; case 'd': dn = arg; continue; case 'a': san->insert_last(san, identification_create_from_string(arg)); continue; case 'p': challenge_password = chunk_create(arg, strlen(arg)); continue; case 'f': if (!get_form(arg, &form, CRED_CERTIFICATE)) { error = "invalid output format"; goto usage; } continue; case EOF: break; default: error = "invalid --req option"; goto usage; } break; } if (type == KEY_BLISS) { /* currently only SHA-512 is supported */ digest = HASH_SHA512; } if (!dn) { error = "--dn is required"; goto usage; } id = identification_create_from_string(dn); if (id->get_type(id) != ID_DER_ASN1_DN) { error = "supplied --dn is not a distinguished name"; goto end; } if (file) { private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type, BUILD_FROM_FILE, file, BUILD_END); }
static int stats(vici_conn_t *conn) { vici_req_t *req; vici_res_t *res; char *arg; command_format_options_t format = COMMAND_FORMAT_NONE; while (TRUE) { switch (command_getopt(&arg)) { case 'h': return command_usage(NULL); case 'P': format |= COMMAND_FORMAT_PRETTY; /* fall through to raw */ case 'r': format |= COMMAND_FORMAT_RAW; continue; case EOF: break; default: return command_usage("invalid --stats option"); } break; } req = vici_begin("stats"); res = vici_submit(req, conn); if (!res) { fprintf(stderr, "stats request failed: %s\n", strerror(errno)); return errno; } if (format & COMMAND_FORMAT_RAW) { vici_dump(res, "stats reply", format & COMMAND_FORMAT_PRETTY, stdout); } else { printf("uptime: %s, since %s\n", vici_find_str(res, "", "uptime.running"), vici_find_str(res, "", "uptime.since")); printf("worker threads: %s total, %s idle, working: %s/%s/%s/%s\n", vici_find_str(res, "", "workers.total"), vici_find_str(res, "", "workers.idle"), vici_find_str(res, "", "workers.active.critical"), vici_find_str(res, "", "workers.active.high"), vici_find_str(res, "", "workers.active.medium"), vici_find_str(res, "", "workers.active.low")); printf("job queues: %s/%s/%s/%s\n", vici_find_str(res, "", "queues.critical"), vici_find_str(res, "", "queues.high"), vici_find_str(res, "", "queues.medium"), vici_find_str(res, "", "queues.low")); printf("jobs scheduled: %s\n", vici_find_str(res, "", "scheduled")); printf("IKE_SAs: %s total, %s half-open\n", vici_find_str(res, "", "ikesas.total"), vici_find_str(res, "", "ikesas.half-open")); if (vici_find_str(res, NULL, "mem.total")) { printf("memory usage: %s bytes, %s allocations\n", vici_find_str(res, "", "mem.total"), vici_find_str(res, "", "mem.allocs")); } if (vici_find_str(res, NULL, "mallinfo.sbrk")) { printf("mallinfo: sbrk %s, mmap %s, used %s, free %s\n", vici_find_str(res, "", "mallinfo.sbrk"), vici_find_str(res, "", "mallinfo.mmap"), vici_find_str(res, "", "mallinfo.used"), vici_find_str(res, "", "mallinfo.free")); } } vici_free_res(res); return 0; }
static int manage_policy(vici_conn_t *conn, char *label) { vici_req_t *req; vici_res_t *res; command_format_options_t format = COMMAND_FORMAT_NONE; char *arg, *child = NULL, *ike = NULL; int ret = 0; while (TRUE) { switch (command_getopt(&arg)) { case 'h': return command_usage(NULL); case 'P': format |= COMMAND_FORMAT_RAW; /* fall through to raw */ case 'r': format |= COMMAND_FORMAT_PRETTY; continue; case 'c': child = arg; continue; case 'i': ike = arg; continue; case EOF: break; default: return command_usage("invalid --%s option", label); } break; } req = vici_begin(label); if (child) { vici_add_key_valuef(req, "child", "%s", child); } if (ike) { vici_add_key_valuef(req, "ike", "%s", ike); } res = vici_submit(req, conn); if (!res) { ret = errno; fprintf(stderr, "%s request failed: %s\n", label, strerror(errno)); return ret; } if (format & COMMAND_FORMAT_RAW) { puts(label); vici_dump(res, " reply", format & COMMAND_FORMAT_PRETTY, stdout); } else { if (streq(vici_find_str(res, "no", "success"), "yes")) { printf("%s completed successfully\n", label); } else { fprintf(stderr, "%s failed: %s\n", label, vici_find_str(res, "", "errmsg")); ret = 1; } } vici_free_res(res); return ret; }
static int initiate(vici_conn_t *conn) { vici_req_t *req; vici_res_t *res; command_format_options_t format = COMMAND_FORMAT_NONE; char *arg, *child = NULL; int ret = 0, timeout = 0, level = 1; while (TRUE) { switch (command_getopt(&arg)) { case 'h': return command_usage(NULL); case 'P': format |= COMMAND_FORMAT_PRETTY; /* fall through to raw */ case 'r': format |= COMMAND_FORMAT_RAW; continue; case 'c': child = arg; continue; case 't': timeout = atoi(arg); continue; case 'l': level = atoi(arg); continue; case EOF: break; default: return command_usage("invalid --initiate option"); } break; } if (vici_register(conn, "control-log", log_cb, &format) != 0) { fprintf(stderr, "registering for log failed: %s\n", strerror(errno)); return errno; } req = vici_begin("initiate"); if (child) { vici_add_key_valuef(req, "child", "%s", child); } if (timeout) { vici_add_key_valuef(req, "timeout", "%d", timeout * 1000); } vici_add_key_valuef(req, "loglevel", "%d", level); res = vici_submit(req, conn); if (!res) { fprintf(stderr, "initiate request failed: %s\n", strerror(errno)); return errno; } if (format & COMMAND_FORMAT_RAW) { vici_dump(res, "initiate reply", format & COMMAND_FORMAT_PRETTY, stdout); } else { if (streq(vici_find_str(res, "no", "success"), "yes")) { printf("initiate completed successfully\n"); } else { fprintf(stderr, "initiate failed: %s\n", vici_find_str(res, "", "errmsg")); ret = 1; } } vici_free_res(res); return ret; }
/** * Create a self-signed PKCS#10 certificate requesst. */ static int req() { cred_encoding_type_t form = CERT_ASN1_DER; key_type_t type = KEY_ANY; hash_algorithm_t digest = HASH_UNKNOWN; signature_params_t *scheme = NULL; certificate_t *cert = NULL; private_key_t *private = NULL; char *file = NULL, *keyid = NULL, *dn = NULL, *error = NULL; identification_t *id = NULL; linked_list_t *san; chunk_t encoding = chunk_empty; chunk_t challenge_password = chunk_empty; char *arg; bool pss = lib->settings->get_bool(lib->settings, "%s.rsa_pss", FALSE, lib->ns); san = linked_list_create(); while (TRUE) { switch (command_getopt(&arg)) { case 'h': goto usage; case 't': if (streq(arg, "rsa")) { type = KEY_RSA; } else if (streq(arg, "ecdsa")) { type = KEY_ECDSA; } else if (streq(arg, "bliss")) { type = KEY_BLISS; } else if (streq(arg, "priv")) { type = KEY_ANY; } else { error = "invalid input type"; goto usage; } continue; case 'g': if (!enum_from_name(hash_algorithm_short_names, arg, &digest)) { error = "invalid --digest type"; goto usage; } continue; case 'R': if (streq(arg, "pss")) { pss = TRUE; } else if (!streq(arg, "pkcs1")) { error = "invalid RSA padding"; goto usage; } continue; case 'i': file = arg; continue; case 'd': dn = arg; continue; case 'a': san->insert_last(san, identification_create_from_string(arg)); continue; case 'p': challenge_password = chunk_create(arg, strlen(arg)); continue; case 'f': if (!get_form(arg, &form, CRED_CERTIFICATE)) { error = "invalid output format"; goto usage; } continue; case 'x': keyid = arg; continue; case EOF: break; default: error = "invalid --req option"; goto usage; } break; } if (!dn) { error = "--dn is required"; goto usage; } id = identification_create_from_string(dn); if (id->get_type(id) != ID_DER_ASN1_DN) { error = "supplied --dn is not a distinguished name"; goto end; } if (file) { private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type, BUILD_FROM_FILE, file, BUILD_END); }
/** * Wrap/Unwrap PKCs#7 containers */ static int pkcs7() { char *arg, *file = NULL; private_key_t *key = NULL; certificate_t *cert = NULL; chunk_t data = chunk_empty; mem_cred_t *creds; int res = 1; FILE *in; enum { OP_NONE, OP_SIGN, OP_VERIFY, OP_ENCRYPT, OP_DECRYPT, OP_SHOW, } op = OP_NONE; creds = mem_cred_create(); while (TRUE) { switch (command_getopt(&arg)) { case 'h': creds->destroy(creds); return command_usage(NULL); case 'i': file = arg; continue; case 's': if (op != OP_NONE) { goto invalid; } op = OP_SIGN; continue; case 'u': if (op != OP_NONE) { goto invalid; } op = OP_VERIFY; continue; case 'e': if (op != OP_NONE) { goto invalid; } op = OP_ENCRYPT; continue; case 'd': if (op != OP_NONE) { goto invalid; } op = OP_DECRYPT; continue; case 'p': if (op != OP_NONE) { goto invalid; } op = OP_SHOW; continue; case 'k': key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA, BUILD_FROM_FILE, arg, BUILD_END); if (!key) { fprintf(stderr, "parsing private key failed\n"); goto end; } creds->add_key(creds, key); continue; case 'c': cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, BUILD_FROM_FILE, arg, BUILD_END); if (!cert) { fprintf(stderr, "parsing certificate failed\n"); goto end; } creds->add_cert(creds, TRUE, cert); continue; case EOF: break; default: invalid: creds->destroy(creds); return command_usage("invalid --pkcs7 option"); } break; } if (file) { in = fopen(file, "r"); if (in) { data = read_from_stream(in); fclose(in); } } else { data = read_from_stream(stdin); } if (!data.len) { fprintf(stderr, "reading input failed!\n"); goto end; } if (op != OP_SHOW && !cert) { fprintf(stderr, "requiring a certificate!\n"); goto end; } lib->credmgr->add_local_set(lib->credmgr, &creds->set, FALSE); switch (op) { case OP_SIGN: if (!key) { fprintf(stderr, "signing requires a private key\n"); res = 1; break; } res = sign(data, cert, key); break; case OP_VERIFY: res = verify(data); break; case OP_ENCRYPT: res = encrypt(data, cert); break; case OP_DECRYPT: if (!key) { fprintf(stderr, "decryption requires a private key\n"); res = 1; break; } res = decrypt(data); break; case OP_SHOW: res = show(data); break; default: res = 1; break; } lib->credmgr->remove_local_set(lib->credmgr, &creds->set); end: creds->destroy(creds); free(data.ptr); return res; }
/** * Sign a CRL */ static int sign_crl() { cred_encoding_type_t form = CERT_ASN1_DER; private_key_t *private = NULL; public_key_t *public = NULL; certificate_t *ca = NULL, *crl = NULL; crl_t *lastcrl = NULL; x509_t *x509; hash_algorithm_t digest = HASH_UNKNOWN; signature_params_t *scheme = NULL; char *arg, *cacert = NULL, *cakey = NULL, *lastupdate = NULL, *error = NULL; char *basecrl = NULL; char serial[512], *keyid = NULL; int serial_len; crl_reason_t reason = CRL_REASON_UNSPECIFIED; time_t thisUpdate, nextUpdate, date = time(NULL); time_t lifetime = 15 * 24 * 60 * 60; char *datetu = NULL, *datenu = NULL, *dateform = NULL; linked_list_t *list, *cdps; enumerator_t *enumerator, *lastenum = NULL; x509_cdp_t *cdp; chunk_t crl_serial = chunk_empty, baseCrlNumber = chunk_empty; chunk_t encoding = chunk_empty; bool pss = lib->settings->get_bool(lib->settings, "%s.rsa_pss", FALSE, lib->ns); list = linked_list_create(); cdps = linked_list_create(); while (TRUE) { switch (command_getopt(&arg)) { case 'h': goto usage; case 'g': if (!enum_from_name(hash_algorithm_short_names, arg, &digest)) { error = "invalid --digest type"; goto usage; } continue; case 'R': if (streq(arg, "pss")) { pss = TRUE; } else if (!streq(arg, "pkcs1")) { error = "invalid RSA padding"; goto usage; } continue; case 'c': cacert = arg; continue; case 'k': cakey = arg; continue; case 'x': keyid = arg; continue; case 'a': lastupdate = arg; continue; case 'l': lifetime = atoi(arg) * 24 * 60 * 60; if (!lifetime) { error = "invalid --lifetime value"; goto usage; } continue; case 'D': dateform = arg; continue; case 'F': datetu = arg; continue; case 'T': datenu = arg; continue; case 'z': serial_len = read_serial(arg, serial, sizeof(serial)); if (serial_len < 0) { snprintf(serial, sizeof(serial), "parsing certificate '%s' failed", arg); error = serial; goto error; } add_revoked(list, chunk_create(serial, serial_len), reason, date); date = time(NULL); reason = CRL_REASON_UNSPECIFIED; continue; case 's': { chunk_t chunk; int hex_len; hex_len = strlen(arg); if ((hex_len / 2) + (hex_len % 2) > sizeof(serial)) { error = "invalid serial"; goto usage; } chunk = chunk_from_hex(chunk_create(arg, hex_len), serial); serial_len = chunk.len; add_revoked(list, chunk_create(serial, serial_len), reason, date); date = time(NULL); reason = CRL_REASON_UNSPECIFIED; continue; } case 'b': basecrl = arg; continue; case 'u': INIT(cdp, .uri = strdup(arg), ); cdps->insert_last(cdps, cdp); continue; case 'r': if (streq(arg, "key-compromise")) { reason = CRL_REASON_KEY_COMPROMISE; } else if (streq(arg, "ca-compromise")) { reason = CRL_REASON_CA_COMPROMISE; } else if (streq(arg, "affiliation-changed")) { reason = CRL_REASON_AFFILIATION_CHANGED; } else if (streq(arg, "superseded")) { reason = CRL_REASON_SUPERSEDED; } else if (streq(arg, "cessation-of-operation")) { reason = CRL_REASON_CESSATION_OF_OPERATON; } else if (streq(arg, "certificate-hold")) { reason = CRL_REASON_CERTIFICATE_HOLD; } else { error = "invalid revocation reason"; goto usage; } continue; case 'd': date = atol(arg); if (!date) { error = "invalid date"; goto usage; } continue; case 'f': if (!get_form(arg, &form, CRED_CERTIFICATE)) { error = "invalid output format"; goto usage; } continue; case EOF: break; default: error = "invalid --signcrl option"; goto usage; } break; } if (!cacert) { error = "--cacert is required"; goto usage; } if (!cakey && !keyid) { error = "--cakey or --keyid is required"; goto usage; } if (!calculate_lifetime(dateform, datetu, datenu, lifetime, &thisUpdate, &nextUpdate)) { error = "invalid --this/next-update datetime"; goto usage; } ca = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, BUILD_FROM_FILE, cacert, BUILD_END); if (!ca) { error = "parsing CA certificate failed"; goto error; } x509 = (x509_t*)ca; if (!(x509->get_flags(x509) & (X509_CA | X509_CRL_SIGN))) { error = "CA certificate misses CA basicConstraint / CRLSign keyUsage"; goto error; } public = ca->get_public_key(ca);
/** * Generate a private key */ static int gen() { key_encoding_type_t form = KEY_PRIV_ASN1_DER; key_type_t type = KEY_RSA; u_int size = 0; private_key_t *key; chunk_t encoding; char *arg; while (TRUE) { switch (command_getopt(&arg)) { case 'h': return command_usage(NULL); case 't': if (streq(arg, "rsa")) { type = KEY_RSA; } else if (streq(arg, "ecdsa")) { type = KEY_ECDSA; } else { return command_usage("invalid key type"); } continue; case 'f': if (!get_form(arg, &form, FALSE)) { return command_usage("invalid key output format"); } continue; case 's': size = atoi(arg); if (!size) { return command_usage("invalid key size"); } continue; case EOF: break; default: return command_usage("invalid --gen option"); } break; } /* default key sizes */ if (!size) { switch (type) { case KEY_RSA: size = 2048; break; case KEY_ECDSA: size = 384; break; default: break; } } key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type, BUILD_KEY_SIZE, size, BUILD_END); if (!key) { fprintf(stderr, "private key generation failed\n"); return 1; } if (!key->get_encoding(key, form, &encoding)) { fprintf(stderr, "private key encoding failed\n"); key->destroy(key); return 1; } key->destroy(key); if (fwrite(encoding.ptr, encoding.len, 1, stdout) != 1) { fprintf(stderr, "writing private key failed\n"); free(encoding.ptr); return 1; } free(encoding.ptr); return 0; }
/** * Calculate the keyid of a key/certificate */ static int keyid() { credential_type_t type = CRED_PRIVATE_KEY; int subtype = KEY_ANY; certificate_t *cert; private_key_t *private; public_key_t *public; char *file = NULL; void *cred; chunk_t id; char *arg; while (TRUE) { switch (command_getopt(&arg)) { case 'h': return command_usage(NULL); case 't': if (streq(arg, "rsa") || streq(arg, "rsa-priv")) { type = CRED_PRIVATE_KEY; subtype = KEY_RSA; } else if (streq(arg, "ecdsa") || streq(arg, "ecdsa-priv")) { type = CRED_PRIVATE_KEY; subtype = KEY_ECDSA; } else if (streq(arg, "bliss") || streq(arg, "bliss-priv")) { type = CRED_PRIVATE_KEY; subtype = KEY_BLISS; } else if (streq(arg, "priv")) { type = CRED_PRIVATE_KEY; subtype = KEY_ANY; } else if (streq(arg, "pub")) { type = CRED_PUBLIC_KEY; subtype = KEY_ANY; } else if (streq(arg, "pkcs10")) { type = CRED_CERTIFICATE; subtype = CERT_PKCS10_REQUEST; } else if (streq(arg, "x509")) { type = CRED_CERTIFICATE; subtype = CERT_X509; } else { return command_usage( "invalid input type"); } continue; case 'i': file = arg; continue; case EOF: break; default: return command_usage("invalid --keyid option"); } break; } if (file) { cred = lib->creds->create(lib->creds, type, subtype, BUILD_FROM_FILE, file, BUILD_END); } else { chunk_t chunk; set_file_mode(stdin, CERT_ASN1_DER); if (!chunk_from_fd(0, &chunk)) { fprintf(stderr, "reading input failed: %s\n", strerror(errno)); return 1; } cred = lib->creds->create(lib->creds, type, subtype, BUILD_BLOB, chunk, BUILD_END); free(chunk.ptr); } if (!cred) { fprintf(stderr, "parsing input failed\n"); return 1; } if (type == CRED_PRIVATE_KEY) { private = cred; if (private->get_fingerprint(private, KEYID_PUBKEY_SHA1, &id)) { printf("subjectKeyIdentifier: %#B\n", &id); } if (private->get_fingerprint(private, KEYID_PUBKEY_INFO_SHA1, &id)) { printf("subjectPublicKeyInfo hash: %#B\n", &id); } private->destroy(private);
/** * Create a self signed certificate. */ static int self() { cred_encoding_type_t form = CERT_ASN1_DER; key_type_t type = KEY_RSA; hash_algorithm_t digest = HASH_SHA1; certificate_t *cert = NULL; private_key_t *private = NULL; public_key_t *public = NULL; char *file = NULL, *dn = NULL, *hex = NULL, *error = NULL, *keyid = NULL; identification_t *id = NULL; linked_list_t *san, *ocsp, *permitted, *excluded, *policies, *mappings; int pathlen = X509_NO_CONSTRAINT, inhibit_any = X509_NO_CONSTRAINT; int inhibit_mapping = X509_NO_CONSTRAINT, require_explicit = X509_NO_CONSTRAINT; chunk_t serial = chunk_empty; chunk_t encoding = chunk_empty; time_t lifetime = 1095; time_t not_before, not_after; x509_flag_t flags = 0; x509_cert_policy_t *policy = NULL; char *arg; san = linked_list_create(); ocsp = linked_list_create(); permitted = linked_list_create(); excluded = linked_list_create(); policies = linked_list_create(); mappings = linked_list_create(); while (TRUE) { switch (command_getopt(&arg)) { case 'h': goto usage; case 't': if (streq(arg, "rsa")) { type = KEY_RSA; } else if (streq(arg, "ecdsa")) { type = KEY_ECDSA; } else { error = "invalid input type"; goto usage; } continue; case 'g': digest = enum_from_name(hash_algorithm_short_names, arg); if (digest == -1) { error = "invalid --digest type"; goto usage; } continue; case 'i': file = arg; continue; case 'x': keyid = arg; continue; case 'd': dn = arg; continue; case 'a': san->insert_last(san, identification_create_from_string(arg)); continue; case 'l': lifetime = atoi(arg); if (!lifetime) { error = "invalid --lifetime value"; goto usage; } continue; case 's': hex = arg; continue; case 'b': flags |= X509_CA; continue; case 'p': pathlen = atoi(arg); continue; case 'n': permitted->insert_last(permitted, identification_create_from_string(arg)); continue; case 'N': excluded->insert_last(excluded, identification_create_from_string(arg)); continue; case 'P': { chunk_t oid; oid = asn1_oid_from_string(arg); if (!oid.len) { error = "--cert-policy OID invalid"; goto usage; } INIT(policy, .oid = oid, ); policies->insert_last(policies, policy); continue; } case 'C': if (!policy) { error = "--cps-uri must follow a --cert-policy"; goto usage; } policy->cps_uri = arg; continue; case 'U': if (!policy) { error = "--user-notice must follow a --cert-policy"; goto usage; } policy->unotice_text = arg; continue; case 'M': { char *pos = strchr(arg, ':'); x509_policy_mapping_t *mapping; chunk_t subject_oid, issuer_oid; if (pos) { *pos++ = '\0'; issuer_oid = asn1_oid_from_string(arg); subject_oid = asn1_oid_from_string(pos); } if (!pos || !issuer_oid.len || !subject_oid.len) { error = "--policy-map OIDs invalid"; goto usage; } INIT(mapping, .issuer = issuer_oid, .subject = subject_oid, ); mappings->insert_last(mappings, mapping); continue; } case 'E': require_explicit = atoi(arg); continue; case 'H': inhibit_mapping = atoi(arg); continue; case 'A': inhibit_any = atoi(arg); continue; case 'e': if (streq(arg, "serverAuth")) { flags |= X509_SERVER_AUTH; } else if (streq(arg, "clientAuth")) { flags |= X509_CLIENT_AUTH; } else if (streq(arg, "ikeIntermediate")) { flags |= X509_IKE_INTERMEDIATE; } else if (streq(arg, "crlSign")) { flags |= X509_CRL_SIGN; } else if (streq(arg, "ocspSigning")) { flags |= X509_OCSP_SIGNER; } continue; case 'f': if (!get_form(arg, &form, CRED_CERTIFICATE)) { error = "invalid output format"; goto usage; } continue; case 'o': ocsp->insert_last(ocsp, arg); continue; case EOF: break; default: error = "invalid --self option"; goto usage; } break; } if (!dn) { error = "--dn is required"; goto usage; } id = identification_create_from_string(dn); if (id->get_type(id) != ID_DER_ASN1_DN) { error = "supplied --dn is not a distinguished name"; goto end; } if (file) { private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type, BUILD_FROM_FILE, file, BUILD_END); }
/** * Verify a certificate signature */ static int verify() { certificate_t *cert, *ca; char *file = NULL, *cafile = NULL; bool good = FALSE; char *arg; while (TRUE) { switch (command_getopt(&arg)) { case 'h': return command_usage(NULL); case 'i': file = arg; continue; case 'c': cafile = arg; continue; case EOF: break; default: return command_usage("invalid --verify option"); } break; } if (file) { cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, BUILD_FROM_FILE, file, BUILD_END); } else { cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, BUILD_FROM_FD, 0, BUILD_END); } if (!cert) { fprintf(stderr, "parsing certificate failed\n"); return 1; } if (cafile) { ca = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, BUILD_FROM_FILE, cafile, BUILD_END); if (!ca) { fprintf(stderr, "parsing CA certificate failed\n"); return 1; } } else { ca = cert; } if (cert->issued_by(cert, ca, NULL)) { if (cert->get_validity(cert, NULL, NULL, NULL)) { if (cafile) { if (ca->get_validity(ca, NULL, NULL, NULL)) { printf("signature good, certificates valid\n"); good = TRUE; } else { printf("signature good, CA certificates not valid now\n"); } } else { printf("signature good, certificate valid\n"); good = TRUE; } } else { printf("certificate not valid now\n"); } } else { printf("signature invalid\n"); } if (cafile) { ca->destroy(ca); } cert->destroy(cert); return good ? 0 : 2; }