zxid
view release on metacpan or search on metacpan
*e = 0;
return p;
}
/*() Extract a certificate as base64 textr from PEM encoded file. */
char* zxid_read_cert_pem(zxid_conf* cf, char* name, int siz, char* buf)
{
int got = read_all(siz, buf, "read_cert", 1, "%s" ZXID_PEM_DIR "%s", cf->cpath, name);
if (!got && cf->auto_cert)
zxid_mk_self_sig_cert(cf, siz, buf, "read_cert", name);
return zxid_extract_cert_pem(buf, name);
}
/*() Extract a certificate from PEM encoded string. */
/* Called by: opt, test_mode, zxid_read_cert */
X509* zxid_extract_cert(char* buf, char* name)
{
X509* x = 0; /* Forces d2i_X509() to alloc the memory. */
char* p;
char* e;
p = zxid_extract_cert_pem(buf, name);
if (!p)
return 0;
e = unbase64_raw(p, p+strlen(p), p, zx_std_index_64);
OpenSSL_add_all_algorithms();
if (!d2i_X509(&x, (const unsigned char**)&p /* *** compile warning */, e-p) || !x) {
ERR("DER decoding of X509 certificate failed.\n%d", 0);
return 0;
}
return x;
}
/*() Extract a certificate from PEM encoded file. */
/* Called by: hi_new_shuffler, zxid_idp_sso_desc x2, zxid_init_conf x3, zxid_lazy_load_sign_cert_and_pkey, zxid_sp_sso_desc x2, zxlog_write_line */
X509* zxid_read_cert(zxid_conf* cf, char* name)
{
X509* x = 0; /* Forces d2i_X509() to alloc the memory. */
char buf[8192];
char* p;
char* e;
p = zxid_read_cert_pem(cf, name, sizeof(buf), buf);
if (!p)
return 0;
OpenSSL_add_all_algorithms();
e = unbase64_raw(p, p+strlen(p), p, zx_std_index_64);
if (!d2i_X509(&x, (const unsigned char**)&p /* *** compile warning */, e-p) || !x) {
ERR("DER decoding of X509 certificate failed.\n%d", 0);
return 0;
}
return x;
}
/*() Extract a private key from PEM encoded string.
* *** This function needs to expand to handle DSA and EC */
/* Called by: */
EVP_PKEY* zxid_extract_private_key(char* buf, char* name)
{
char* p;
char* e;
int typ;
EVP_PKEY* pk = 0; /* Forces d2i_PrivateKey() to alloc the memory. */
OpenSSL_add_all_algorithms();
if (p = strstr(buf, PEM_RSA_PRIV_KEY_START)) {
typ = EVP_PKEY_RSA;
e = PEM_RSA_PRIV_KEY_END;
p += sizeof(PEM_RSA_PRIV_KEY_START) - 1;
} else if (p = strstr(buf, PEM_DSA_PRIV_KEY_START)) {
typ = EVP_PKEY_DSA;
e = PEM_DSA_PRIV_KEY_END;
p += sizeof(PEM_DSA_PRIV_KEY_START) - 1;
} else if (p = strstr(buf, PEM_PRIV_KEY_START)) { /* Not official format, but sometimes seen. */
typ = EVP_PKEY_RSA;
e = PEM_PRIV_KEY_END;
p += sizeof(PEM_PRIV_KEY_START) - 1;
} else {
ERR("No private key found in file(%s). Looking for separator (%s) or (%s).\npem data(%s)", name, PEM_RSA_PRIV_KEY_START, PEM_DSA_PRIV_KEY_START, buf);
return 0;
}
if (*p == 0xd) ++p;
if (*p != 0xa) {
ERR("Bad privkey missing newline ch(0x%x) at %ld (%.*s) of buf(%s)", *p, (long)(p-buf), 5, p-2, buf);
return 0;
}
++p;
e = strstr(buf, e);
if (!e) {
ERR("End marker not found, typ=%d", typ);
return 0;
}
zx_report_openssl_err("extract_private_key0"); /* *** seems something leaves errors on stack */
p = unbase64_raw(p, e, buf, zx_std_index_64);
if (!d2i_PrivateKey(typ, &pk, (const unsigned char**)&buf, p-buf) || !pk) {
zx_report_openssl_err("extract_private_key"); /* *** seems d2i can leave errors on stack */
ERR("DER decoding of private key failed.\n%d", 0);
return 0;
}
zx_report_openssl_err("extract_private_key2"); /* *** seems d2i can leave errors on stack */
return pk; /* RSA* rsa = EVP_PKEY_get1_RSA(pk); */
}
/*() Extract a private key from PEM encoded file. */
/* Called by: hi_new_shuffler, test_ibm_cert_problem x2, test_ibm_cert_problem_enc_dec x2, zxbus_mint_receipt x2, zxenc_privkey_dec, zxid_init_conf x3, zxid_lazy_load_sign_cert_and_pkey, zxlog_write_line x2 */
EVP_PKEY* zxid_read_private_key(zxid_conf* cf, char* name)
{
char buf[8192];
int got = read_all(sizeof(buf),buf,"read_private_key",1, "%s" ZXID_PEM_DIR "%s", cf->cpath, name);
if (!got && cf->auto_cert)
zxid_mk_self_sig_cert(cf, sizeof(buf), buf, "read_private_key", name);
return zxid_extract_private_key(buf, name);
}
/*() Lazy load signing certificate and private key. This reads them from disk
* if needed. If they do not exist and auto_cert is enabled, they will be
* generated on disk and then read. Once read from disk, they will be cached in
* memory.
*
* > N.B. If the cert does not yet exist, write access to disk will be needed.
* > If it already exists, read access is sufficient. Thus it is more secure
* > to pregenerate the certificate and then set the permissions so that
* > the process can read it, but can not alter it.
*
* cf:: Configuration object
* cert:: result parameter. If non null, the certificate will be extracted
* from file and pointer to the X509 data structure will be deposited
* to place pointed by this parameter. If null, certificate is neither
* extracted nor returned. The data structure should be freed by the
* caller.
* pkey:: result parameter. Must be specified. The private key data structure
* is extracted from the file and returned using this parameter. The
* data structure should be freed by the caller.
* logkey:: Free form string describing why the cert and private key are
* being requested. Used for logging and debugging.
* return:: Returns 1 on success and 0 on failure.
*/
/* Called by: zxid_anoint_a7n, zxid_anoint_sso_resp, zxid_az_soap x3, zxid_idp_soap_dispatch x2, zxid_idp_sso, zxid_mk_art_deref, zxid_mk_at_cert, zxid_saml2_post_enc, zxid_saml2_redir_enc, zxid_sp_mni_soap, zxid_sp_slo_soap, zxid_sp_soap_dispatch x...
int zxid_lazy_load_sign_cert_and_pkey(zxid_conf* cf, X509** cert, EVP_PKEY** pkey, const char* logkey)
{
LOCK(cf->mx, logkey);
if (cert) {
if (!(*cert = cf->sign_cert)) // Lazy load cert and private key
*cert = cf->sign_cert = zxid_read_cert(cf, "sign-nopw-cert.pem");
}
if (!(*pkey = cf->sign_pkey))
*pkey = cf->sign_pkey = zxid_read_private_key(cf, "sign-nopw-cert.pem");
UNLOCK(cf->mx, logkey);
if (cert && !*cert || !*pkey)
return 0;
return 1;
}
#endif /* USE_OPENSSL */
/*() Set obscure options of ZX and ZXID layers. Used to set debug options.
* Generally setting these options is not supported, but this function
* exists to avoid uncontrolled access to global variables. At least this
* way the unsupported activity will happen in one controlled place where
* it can be ignored, if need to be. You have been warned. */
/* Called by: main, zxid_fed_mgmt_cf, zxid_idp_list_cf_cgi, zxid_simple_cf_ses */
int zxid_set_opt(zxid_conf* cf, int which, int val)
{
switch (which) {
case 1: errmac_debug = val; INFO("errmac_debug=%d",val); return val;
case 5: exit(val); /* This is typically used to force __gcov_flush() */
case 6: zxid_set_opt_cstr(cf, 6, "/var/zxid/log/log.dbg"); return 0;
#ifdef M_CHECK_ACTION /* glibc specific */
case 7: mallopt(M_CHECK_ACTION, val); return 0; /* val==3 enables cores on bad free() */
#endif
default: ERR("zxid_set_opt: this version " ZXID_REL " does not support which=%d val=%d (ignored)", which, val);
}
return -1;
}
/*() Set obscure options of ZX and ZXID layers. Used to set debug options.
* Generally setting these options is not supported, but this function
* exists to avoid uncontrolled access to global variables. At least this
* way the unsupported activity will happen in one controlled place where
* it can be ignored, if need to be. You have been warned. */
/* Called by: zxid_parse_conf_raw, zxid_set_opt */
char* zxid_set_opt_cstr(zxid_conf* cf, int which, char* val)
{
char buf[PATH_MAX];
switch (which) {
case 2: strncpy(errmac_instance, val, sizeof(errmac_instance)); return errmac_instance;
case 3: D_INDENT(val); return errmac_indent;
case 4: D_DEDENT(val); return errmac_indent;
case 6:
D("Forwarding debug output to file(%s) cwd(%s)", STRNULLCHK(val), getcwd(buf, sizeof(buf)));
errmac_debug_log = fopen(val, "a");
if (!errmac_debug_log) {
perror("zxid_set_opt_cstr: failed to open new log file");
fprintf(stderr, "zxid_set_opt_cstr: failed to open new log file(%s), euid=%d egid=%d cwd(%s)", STRNULLCHK(val), geteuid(), getegid(), getcwd(buf, sizeof(buf)));
exit(1);
}
INFO("zxid_set_opt_cstr: opened new log file(%s), rel=" ZXID_REL " euid=%d egid=%d cwd(%s)", STRNULLCHK(val), geteuid(), getegid(), getcwd(buf, sizeof(buf)));
return "";
default: ERR("zxid_set_opt_cstr: this version " ZXID_REL " does not support which=%d val(%s) (ignored)", which, STRNULLCHK(val));
}
return 0;
}
/*() Set the BURL configuration variable. Special accessor function to
* manipulate BURL config option. Manipulating this option is common in
{
DD("Initconf with path(%s)", zxid_path);
cf->magic = ZXID_CONF_MAGIC;
cf->cpath_len = zxid_path ? strlen(zxid_path) : 0;
cf->cpath = ZX_ALLOC(cf->ctx, cf->cpath_len+1);
memcpy(cf->cpath, zxid_path, cf->cpath_len);
cf->cpath[cf->cpath_len] = 0;
cf->nice_name = ZXID_NICE_NAME;
cf->button_url = ZXID_BUTTON_URL;
cf->pref_button_size = ZXID_PREF_BUTTON_SIZE;
cf->org_name = ZXID_ORG_NAME;
cf->locality = ZXID_LOCALITY;
cf->state = ZXID_STATE;
cf->country = ZXID_COUNTRY;
cf->contact_org = ZXID_CONTACT_ORG;
cf->contact_name = ZXID_CONTACT_NAME;
cf->contact_email = ZXID_CONTACT_EMAIL;
cf->contact_tel = ZXID_CONTACT_TEL;
/* NB: Typically allocated by zxid_grab_domain_name(). */
COPYVAL(cf->fedusername_suffix, ZXID_FEDUSERNAME_SUFFIX,
ZXID_FEDUSERNAME_SUFFIX + strlen(ZXID_FEDUSERNAME_SUFFIX));
cf->burl = ZXID_BURL;
cf->non_standard_entityid = ZXID_NON_STANDARD_ENTITYID;
cf->redirect_hack_imposed_url = ZXID_REDIRECT_HACK_IMPOSED_URL;
cf->redirect_hack_zxid_url = ZXID_REDIRECT_HACK_ZXID_URL;
cf->defaultqs = ZXID_DEFAULTQS;
cf->wsp_pat = ZXID_WSP_PAT;
cf->uma_pat = ZXID_UMA_PAT;
cf->sso_pat = ZXID_SSO_PAT;
cf->cdc_url = ZXID_CDC_URL;
cf->cdc_choice = ZXID_CDC_CHOICE;
cf->authn_req_sign = ZXID_AUTHN_REQ_SIGN;
cf->want_sso_a7n_signed = ZXID_WANT_SSO_A7N_SIGNED;
cf->want_authn_req_signed = ZXID_WANT_AUTHN_REQ_SIGNED;
cf->sso_soap_sign = ZXID_SSO_SOAP_SIGN;
cf->sso_soap_resp_sign = ZXID_SSO_SOAP_RESP_SIGN;
cf->sso_sign = ZXID_SSO_SIGN;
cf->wsc_sign = ZXID_WSC_SIGN;
cf->wsp_sign = ZXID_WSP_SIGN;
cf->oaz_jwt_sigenc_alg = ZXID_OAZ_JWT_SIGENC_ALG;
cf->wspcgicmd = ZXID_WSPCGICMD;
cf->nameid_enc = ZXID_NAMEID_ENC;
cf->post_a7n_enc = ZXID_POST_A7N_ENC;
cf->canon_inopt = ZXID_CANON_INOPT;
if (cf->ctx) cf->ctx->canon_inopt = cf->canon_inopt;
cf->enc_tail_opt = ZXID_ENC_TAIL_OPT;
cf->enckey_opt = ZXID_ENCKEY_OPT;
cf->valid_opt = ZXID_VALID_OPT;
cf->idpatopt = ZXID_IDPATOPT;
cf->idp_list_meth = ZXID_IDP_LIST_METH;
cf->di_allow_create = ZXID_DI_ALLOW_CREATE;
cf->di_nid_fmt = ZXID_DI_NID_FMT;
cf->di_a7n_enc = ZXID_DI_A7N_ENC;
cf->bootstrap_level = ZXID_BOOTSTRAP_LEVEL;
cf->show_conf = ZXID_SHOW_CONF;
#ifdef USE_OPENSSL
if (zxid_path) {
#if 0
/* DO NOT ENABLE! The certificates and keys are read "just in time" if and when needed. */
cf->sign_cert = zxid_read_cert(cf, "sign-nopw-cert.pem");
cf->sign_pkey = zxid_read_private_key(cf, "sign-nopw-cert.pem");
cf->enc_cert = zxid_read_cert(cf, "enc-nopw-cert.pem");
cf->enc_pkey = zxid_read_private_key(cf, "enc-nopw-cert.pem");
cf->log_sign_pkey = zxid_read_private_key(cf, "logsign-nopw-cert.pem");
cf->log_enc_cert = zxid_read_cert(cf, "logenc-nopw-cert.pem");
zxid_sha1_file(cf, "pem/logenc.key", cf->log_symkey);
#endif
}
#else
ERR("This copy of zxid was compiled to NOT use OpenSSL. Reading certificate and private key is not supported. Signing and signature verification are not supported either. Add -DUSE_OPENSSL and recompile. %d", 0);
#endif
cf->md_fetch = ZXID_MD_FETCH;
cf->md_populate_cache = ZXID_MD_POPULATE_CACHE;
cf->md_cache_first = ZXID_MD_CACHE_FIRST;
cf->md_cache_last = ZXID_MD_CACHE_LAST;
cf->md_authority = ZXID_MD_AUTHORITY;
cf->load_cot_cache = ZXID_LOAD_COT_CACHE;
cf->auto_cert = ZXID_AUTO_CERT;
cf->ses_arch_dir = ZXID_SES_ARCH_DIR;
cf->ses_cookie_name = ZXID_SES_COOKIE_NAME;
cf->ptm_cookie_name = ZXID_PTM_COOKIE_NAME;
cf->user_local = ZXID_USER_LOCAL;
cf->idp_ena = ZXID_IDP_ENA;
cf->idp_pxy_ena = ZXID_IDP_PXY_ENA;
cf->imps_ena = ZXID_IMPS_ENA;
cf->as_ena = ZXID_AS_ENA;
cf->md_authority_ena = ZXID_MD_AUTHORITY_ENA;
cf->backwards_compat_ena = ZXID_BACKWARDS_COMPAT_ENA;
cf->pdp_ena = ZXID_PDP_ENA;
cf->cpn_ena = ZXID_CPN_ENA;
cf->az_opt = ZXID_AZ_OPT;
cf->az_fail_mode = ZXID_AZ_FAIL_MODE;
cf->loguser = ZXID_LOGUSER;
cf->log_level = ZXLOG_LEVEL;
cf->log_err = ZXLOG_ERR; /* Log enables and signing and encryption flags (if USE_OPENSSL) */
cf->log_act = ZXLOG_ACT;
cf->log_issue_a7n = ZXLOG_ISSUE_A7N;
cf->log_issue_msg = ZXLOG_ISSUE_MSG;
cf->log_rely_a7n = ZXLOG_RELY_A7N;
cf->log_rely_msg = ZXLOG_RELY_MSG;
cf->log_err_in_act = ZXLOG_ERR_IN_ACT;
cf->log_act_in_err = ZXLOG_ACT_IN_ERR;
cf->log_sigfail_is_err = ZXLOG_SIGFAIL_IS_ERR;
cf->bus_rcpt = ZXBUS_RCPT;
cf->bus_url = zxid_load_bus_url(cf, 0, ZXID_BUS_URL);
cf->bus_pw = ZXID_BUS_PW;
cf->sig_fatal = ZXID_SIG_FATAL;
cf->nosig_fatal = ZXID_NOSIG_FATAL;
cf->msg_sig_ok = ZXID_MSG_SIG_OK;
cf->timeout_fatal = ZXID_TIMEOUT_FATAL;
cf->audience_fatal = ZXID_AUDIENCE_FATAL;
cf->dup_a7n_fatal = ZXID_DUP_A7N_FATAL;
cf->dup_msg_fatal = ZXID_DUP_MSG_FATAL;
cf->relto_fatal = ZXID_RELTO_FATAL;
cf->wsp_nosig_fatal = ZXID_WSP_NOSIG_FATAL;
cf->notimestamp_fatal = ZXID_NOTIMESTAMP_FATAL;
cf->anon_ok = ZXID_ANON_OK;
cf->optional_login_pat = ZXID_OPTIONAL_LOGIN_PAT;
cf->required_authnctx = ZXID_REQUIRED_AUTHNCTX; /* NB: NULL. */
cf->issue_authnctx = zxid_load_cstr_list(cf, 0, ZXID_ISSUE_AUTHNCTX);
cf->idp_pref_acs_binding = ZXID_IDP_PREF_ACS_BINDING;
cf->mandatory_attr = ZXID_MANDATORY_ATTR;
( run in 4.235 seconds using v1.01-cache-2.11-cpan-a49fcb8fa48 )