static int add_one_attribute(Attribute **attr, unsigned int *len, const heim_oid *oid, heim_octet_string *data) { void *d; int ret; d = realloc(*attr, sizeof((*attr)[0]) * (*len + 1)); if (d == NULL) return ENOMEM; (*attr) = d; ret = der_copy_oid(oid, &(*attr)[*len].type); if (ret) return ret; ALLOC_SEQ(&(*attr)[*len].value, 1); if ((*attr)[*len].value.val == NULL) { der_free_oid(&(*attr)[*len].type); return ENOMEM; } (*attr)[*len].value.val[0].data = data->data; (*attr)[*len].value.val[0].length = data->length; *len += 1; return 0; }
krb5_error_code KRB5_LIB_FUNCTION krb5_copy_addresses(krb5_context context, const krb5_addresses *inaddr, krb5_addresses *outaddr) { int i; ALLOC_SEQ(outaddr, inaddr->len); if(inaddr->len > 0 && outaddr->val == NULL) return ENOMEM; for(i = 0; i < inaddr->len; i++) krb5_copy_address(context, &inaddr->val[i], &outaddr->val[i]); return 0; }
static int set_ptypes(krb5_context context, KRB_ERROR *error, const krb5_preauthtype **ptypes, krb5_preauthdata **preauth) { static krb5_preauthdata preauth2; static krb5_preauthtype ptypes2[] = { KRB5_PADATA_ENC_TIMESTAMP, KRB5_PADATA_NONE }; if(error->e_data) { METHOD_DATA md; int i; decode_METHOD_DATA(error->e_data->data, error->e_data->length, &md, NULL); for(i = 0; i < md.len; i++){ switch(md.val[i].padata_type){ case KRB5_PADATA_ENC_TIMESTAMP: *ptypes = ptypes2; break; case KRB5_PADATA_ETYPE_INFO: *preauth = &preauth2; ALLOC_SEQ(*preauth, 1); (*preauth)->val[0].type = KRB5_PADATA_ENC_TIMESTAMP; krb5_decode_ETYPE_INFO(context, md.val[i].padata_value.data, md.val[i].padata_value.length, &(*preauth)->val[0].info, NULL); break; default: break; } } free_METHOD_DATA(&md); } else { *ptypes = ptypes2; } return(1); }
krb5_error_code KRB5_LIB_FUNCTION krb5_ret_authdata(krb5_storage *sp, krb5_authdata *auth) { krb5_error_code ret; int32_t tmp; int16_t tmp2; int i; ret = krb5_ret_int32(sp, &tmp); if(ret) return ret; ALLOC_SEQ(auth, tmp); if (auth->val == NULL && tmp != 0) return ENOMEM; for(i = 0; i < tmp; i++){ ret = krb5_ret_int16(sp, &tmp2); if(ret) break; auth->val[i].ad_type = tmp2; ret = krb5_ret_data(sp, &auth->val[i].ad_data); if(ret) break; } return ret; }
static krb5_error_code init_tgs_req (krb5_context context, krb5_ccache ccache, krb5_addresses *addresses, krb5_kdc_flags flags, Ticket *second_ticket, krb5_creds *in_creds, krb5_creds *krbtgt, unsigned nonce, const METHOD_DATA *padata, krb5_keyblock **subkey, TGS_REQ *t) { krb5_auth_context ac = NULL; krb5_error_code ret = 0; memset(t, 0, sizeof(*t)); t->pvno = 5; t->msg_type = krb_tgs_req; if (in_creds->session.keytype) { ALLOC_SEQ(&t->req_body.etype, 1); if(t->req_body.etype.val == NULL) { ret = ENOMEM; krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); goto fail; } t->req_body.etype.val[0] = in_creds->session.keytype; } else { ret = krb5_init_etype(context, &t->req_body.etype.len, &t->req_body.etype.val, NULL); } if (ret) goto fail; t->req_body.addresses = addresses; t->req_body.kdc_options = flags.b; ret = copy_Realm(&in_creds->server->realm, &t->req_body.realm); if (ret) goto fail; ALLOC(t->req_body.sname, 1); if (t->req_body.sname == NULL) { ret = ENOMEM; krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); goto fail; } /* some versions of some code might require that the client be present in TGS-REQs, but this is clearly against the spec */ ret = copy_PrincipalName(&in_creds->server->name, t->req_body.sname); if (ret) goto fail; /* req_body.till should be NULL if there is no endtime specified, but old MIT code (like DCE secd) doesn't like that */ ALLOC(t->req_body.till, 1); if(t->req_body.till == NULL){ ret = ENOMEM; krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); goto fail; } *t->req_body.till = in_creds->times.endtime; t->req_body.nonce = nonce; if(second_ticket){ ALLOC(t->req_body.additional_tickets, 1); if (t->req_body.additional_tickets == NULL) { ret = ENOMEM; krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); goto fail; } ALLOC_SEQ(t->req_body.additional_tickets, 1); if (t->req_body.additional_tickets->val == NULL) { ret = ENOMEM; krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); goto fail; } ret = copy_Ticket(second_ticket, t->req_body.additional_tickets->val); if (ret) goto fail; } ALLOC(t->padata, 1); if (t->padata == NULL) { ret = ENOMEM; krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); goto fail; } ALLOC_SEQ(t->padata, 1 + padata->len); if (t->padata->val == NULL) { ret = ENOMEM; krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); goto fail; } { int i; for (i = 0; i < padata->len; i++) { ret = copy_PA_DATA(&padata->val[i], &t->padata->val[i + 1]); if (ret) { krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); goto fail; } } } ret = krb5_auth_con_init(context, &ac); if(ret) goto fail; ret = krb5_auth_con_generatelocalsubkey(context, ac, &krbtgt->session); if (ret) goto fail; ret = set_auth_data (context, &t->req_body, &in_creds->authdata, ac->local_subkey); if (ret) goto fail; ret = make_pa_tgs_req(context, ac, &t->req_body, &t->padata->val[0], krbtgt); if(ret) goto fail; ret = krb5_auth_con_getlocalsubkey(context, ac, subkey); if (ret) goto fail; fail: if (ac) krb5_auth_con_free(context, ac); if (ret) { t->req_body.addresses = NULL; free_TGS_REQ (t); } return ret; }
krb5_error_code _krb5_init_tgs_req(krb5_context context, krb5_ccache ccache, krb5_addresses *addresses, krb5_kdc_flags flags, krb5_const_principal impersonate_principal, Ticket *second_ticket, krb5_creds *in_creds, krb5_creds *krbtgt, unsigned nonce, METHOD_DATA *padata, krb5_keyblock **subkey, TGS_REQ *t) { krb5_auth_context ac = NULL; krb5_error_code ret = 0; /* inherit the forwardable/proxyable flags from the krbtgt */ flags.b.forwardable = krbtgt->flags.b.forwardable; flags.b.proxiable = krbtgt->flags.b.proxiable; if (ccache->ops->tgt_req) { KERB_TGS_REQ_OUT out; KERB_TGS_REQ_IN in; memset(&in, 0, sizeof(in)); memset(&out, 0, sizeof(out)); ret = ccache->ops->tgt_req(context, ccache, &in, &out); if (ret) return ret; free_KERB_TGS_REQ_OUT(&out); return 0; } memset(t, 0, sizeof(*t)); if (impersonate_principal) { krb5_crypto crypto; PA_S4U2Self self; krb5_data data; void *buf; size_t size, len; self.name = impersonate_principal->name; self.realm = impersonate_principal->realm; self.auth = rk_UNCONST("Kerberos"); ret = _krb5_s4u2self_to_checksumdata(context, &self, &data); if (ret) goto fail; ret = krb5_crypto_init(context, &krbtgt->session, 0, &crypto); if (ret) { krb5_data_free(&data); goto fail; } ret = krb5_create_checksum(context, crypto, KRB5_KU_OTHER_CKSUM, 0, data.data, data.length, &self.cksum); krb5_crypto_destroy(context, crypto); krb5_data_free(&data); if (ret) goto fail; ASN1_MALLOC_ENCODE(PA_S4U2Self, buf, len, &self, &size, ret); free_Checksum(&self.cksum); if (ret) goto fail; if (len != size) krb5_abortx(context, "internal asn1 error"); ret = krb5_padata_add(context, padata, KRB5_PADATA_FOR_USER, buf, len); if (ret) goto fail; } t->pvno = 5; t->msg_type = krb_tgs_req; if (in_creds->session.keytype) { ALLOC_SEQ(&t->req_body.etype, 1); if(t->req_body.etype.val == NULL) { ret = ENOMEM; krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); goto fail; } t->req_body.etype.val[0] = in_creds->session.keytype; } else { ret = _krb5_init_etype(context, KRB5_PDU_TGS_REQUEST, &t->req_body.etype.len, &t->req_body.etype.val, NULL); } if (ret) goto fail; t->req_body.addresses = addresses; t->req_body.kdc_options = flags.b; ret = copy_Realm(&in_creds->server->realm, &t->req_body.realm); if (ret) goto fail; ALLOC(t->req_body.sname, 1); if (t->req_body.sname == NULL) { ret = ENOMEM; krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); goto fail; } /* some versions of some code might require that the client be present in TGS-REQs, but this is clearly against the spec */ ret = copy_PrincipalName(&in_creds->server->name, t->req_body.sname); if (ret) goto fail; /* req_body.till should be NULL if there is no endtime specified, but old MIT code (like DCE secd) doesn't like that */ ALLOC(t->req_body.till, 1); if(t->req_body.till == NULL){ ret = ENOMEM; krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); goto fail; } *t->req_body.till = in_creds->times.endtime; t->req_body.nonce = nonce; if(second_ticket){ ALLOC(t->req_body.additional_tickets, 1); if (t->req_body.additional_tickets == NULL) { ret = ENOMEM; krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); goto fail; } ALLOC_SEQ(t->req_body.additional_tickets, 1); if (t->req_body.additional_tickets->val == NULL) { ret = ENOMEM; krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); goto fail; } ret = copy_Ticket(second_ticket, t->req_body.additional_tickets->val); if (ret) goto fail; } ALLOC(t->padata, 1); if (t->padata == NULL) { ret = ENOMEM; krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); goto fail; } ALLOC_SEQ(t->padata, 1 + padata->len); if (t->padata->val == NULL) { ret = ENOMEM; krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); goto fail; } { size_t i; for (i = 0; i < padata->len; i++) { ret = copy_PA_DATA(&padata->val[i], &t->padata->val[i + 1]); if (ret) { krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); goto fail; } } } ret = krb5_auth_con_init(context, &ac); if(ret) goto fail; ret = krb5_auth_con_generatelocalsubkey(context, ac, &krbtgt->session); if (ret) goto fail; ret = set_auth_data (context, &t->req_body, &in_creds->authdata, ac->local_subkey); if (ret) goto fail; ret = make_pa_tgs_req(context, ac, &t->req_body, &t->padata->val[0], ccache, krbtgt); if(ret) goto fail; ret = krb5_auth_con_getlocalsubkey(context, ac, subkey); if (ret) goto fail; fail: if (ac) krb5_auth_con_free(context, ac); if (ret) { t->req_body.addresses = NULL; free_TGS_REQ (t); } return ret; }
int hx509_cms_envelope_1(hx509_context context, int flags, hx509_cert cert, const void *data, size_t length, const heim_oid *encryption_type, const heim_oid *contentType, heim_octet_string *content) { KeyTransRecipientInfo *ri; heim_octet_string ivec; heim_octet_string key; hx509_crypto crypto = NULL; int ret, cmsidflag; EnvelopedData ed; size_t size; memset(&ivec, 0, sizeof(ivec)); memset(&key, 0, sizeof(key)); memset(&ed, 0, sizeof(ed)); memset(content, 0, sizeof(*content)); if (encryption_type == NULL) encryption_type = &asn1_oid_id_aes_256_cbc; if ((flags & HX509_CMS_EV_NO_KU_CHECK) == 0) { ret = _hx509_check_key_usage(context, cert, 1 << 2, TRUE); if (ret) goto out; } ret = hx509_crypto_init(context, NULL, encryption_type, &crypto); if (ret) goto out; if (flags & HX509_CMS_EV_ALLOW_WEAK) hx509_crypto_allow_weak(crypto); ret = hx509_crypto_set_random_key(crypto, &key); if (ret) { hx509_set_error_string(context, 0, ret, "Create random key for EnvelopedData content"); goto out; } ret = hx509_crypto_random_iv(crypto, &ivec); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to create a random iv"); goto out; } ret = hx509_crypto_encrypt(crypto, data, length, &ivec, &ed.encryptedContentInfo.encryptedContent); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to encrypt EnvelopedData content"); goto out; } { AlgorithmIdentifier *enc_alg; enc_alg = &ed.encryptedContentInfo.contentEncryptionAlgorithm; ret = der_copy_oid(encryption_type, &enc_alg->algorithm); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to set crypto oid " "for EnvelopedData"); goto out; } ALLOC(enc_alg->parameters, 1); if (enc_alg->parameters == NULL) { ret = ENOMEM; hx509_set_error_string(context, 0, ret, "Failed to allocate crypto paramaters " "for EnvelopedData"); goto out; } ret = hx509_crypto_get_params(context, crypto, &ivec, enc_alg->parameters); if (ret) { goto out; } } ALLOC_SEQ(&ed.recipientInfos, 1); if (ed.recipientInfos.val == NULL) { ret = ENOMEM; hx509_set_error_string(context, 0, ret, "Failed to allocate recipients info " "for EnvelopedData"); goto out; } ri = &ed.recipientInfos.val[0]; if (flags & HX509_CMS_EV_ID_NAME) { ri->version = 0; cmsidflag = CMS_ID_NAME; } else { ri->version = 2; cmsidflag = CMS_ID_SKI; } ret = fill_CMSIdentifier(cert, cmsidflag, &ri->rid); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to set CMS identifier info " "for EnvelopedData"); goto out; } ret = hx509_cert_public_encrypt(context, &key, cert, &ri->keyEncryptionAlgorithm.algorithm, &ri->encryptedKey); if (ret) { hx509_set_error_string(context, HX509_ERROR_APPEND, ret, "Failed to encrypt transport key for " "EnvelopedData"); goto out; } /* * */ ed.version = 0; ed.originatorInfo = NULL; ret = der_copy_oid(contentType, &ed.encryptedContentInfo.contentType); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to copy content oid for " "EnvelopedData"); goto out; } ed.unprotectedAttrs = NULL; ASN1_MALLOC_ENCODE(EnvelopedData, content->data, content->length, &ed, &size, ret); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to encode EnvelopedData"); goto out; } if (size != content->length) _hx509_abort("internal ASN.1 encoder error"); out: if (crypto) hx509_crypto_destroy(crypto); if (ret) der_free_octet_string(content); der_free_octet_string(&key); der_free_octet_string(&ivec); free_EnvelopedData(&ed); return ret; }
static krb5_error_code make_etypelist(krb5_context context, krb5_authdata **auth_data) { EtypeList etypes; krb5_error_code ret; krb5_authdata ad; u_char *buf; size_t len = 0; size_t buf_size; ret = _krb5_init_etype(context, KRB5_PDU_NONE, &etypes.len, &etypes.val, NULL); if (ret) return ret; ASN1_MALLOC_ENCODE(EtypeList, buf, buf_size, &etypes, &len, ret); if (ret) { free_EtypeList(&etypes); return ret; } if(buf_size != len) krb5_abortx(context, "internal error in ASN.1 encoder"); free_EtypeList(&etypes); ALLOC_SEQ(&ad, 1); if (ad.val == NULL) { free(buf); krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); return ENOMEM; } ad.val[0].ad_type = KRB5_AUTHDATA_GSS_API_ETYPE_NEGOTIATION; ad.val[0].ad_data.length = len; ad.val[0].ad_data.data = buf; ASN1_MALLOC_ENCODE(AD_IF_RELEVANT, buf, buf_size, &ad, &len, ret); if (ret) { free_AuthorizationData(&ad); return ret; } if(buf_size != len) krb5_abortx(context, "internal error in ASN.1 encoder"); free_AuthorizationData(&ad); ALLOC(*auth_data, 1); if (*auth_data == NULL) { free(buf); krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); return ENOMEM; } ALLOC_SEQ(*auth_data, 1); if ((*auth_data)->val == NULL) { free(*auth_data); free(buf); krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); return ENOMEM; } (*auth_data)->val[0].ad_type = KRB5_AUTHDATA_IF_RELEVANT; (*auth_data)->val[0].ad_data.length = len; (*auth_data)->val[0].ad_data.data = buf; return 0; }
int mit_prop_dump(void *arg, const char *file) { krb5_error_code ret; char line [2048]; FILE *f; int lineno = 0; struct hdb_entry_ex ent; struct prop_data *pd = arg; f = fopen(file, "r"); if(f == NULL) return errno; while(fgets(line, sizeof(line), f)) { char *p = line, *q; int i; int num_tl_data; int num_key_data; int high_kvno; int attributes; int tmp; lineno++; memset(&ent, 0, sizeof(ent)); q = nexttoken(&p); if(strcmp(q, "kdb5_util") == 0) { int major; q = nexttoken(&p); /* load_dump */ if(strcmp(q, "load_dump")) errx(1, "line %d: unknown version", lineno); q = nexttoken(&p); /* load_dump */ if(strcmp(q, "version")) errx(1, "line %d: unknown version", lineno); q = nexttoken(&p); /* x.0 */ if(sscanf(q, "%d", &major) != 1) errx(1, "line %d: unknown version", lineno); if(major != 4 && major != 5 && major != 6) errx(1, "unknown dump file format, got %d, expected 4-6", major); continue; } else if(strcmp(q, "policy") == 0) { continue; } else if(strcmp(q, "princ") != 0) { warnx("line %d: not a principal", lineno); continue; } tmp = getint(&p); if(tmp != 38) { warnx("line %d: bad base length %d != 38", lineno, tmp); continue; } nexttoken(&p); /* length of principal */ num_tl_data = getint(&p); /* number of tl-data */ num_key_data = getint(&p); /* number of key-data */ getint(&p); /* length of extra data */ q = nexttoken(&p); /* principal name */ krb5_parse_name(pd->context, q, &ent.entry.principal); attributes = getint(&p); /* attributes */ attr_to_flags(attributes, &ent.entry.flags); tmp = getint(&p); /* max life */ if(tmp != 0) { ALLOC(ent.entry.max_life); *ent.entry.max_life = tmp; } tmp = getint(&p); /* max renewable life */ if(tmp != 0) { ALLOC(ent.entry.max_renew); *ent.entry.max_renew = tmp; } tmp = getint(&p); /* expiration */ if(tmp != 0 && tmp != 2145830400) { ALLOC(ent.entry.valid_end); *ent.entry.valid_end = tmp; } tmp = getint(&p); /* pw expiration */ if(tmp != 0) { ALLOC(ent.entry.pw_end); *ent.entry.pw_end = tmp; } nexttoken(&p); /* last auth */ nexttoken(&p); /* last failed auth */ nexttoken(&p); /* fail auth count */ for(i = 0; i < num_tl_data; i++) { unsigned long val; int tl_type, tl_length; unsigned char *buf; krb5_principal princ; tl_type = getint(&p); /* data type */ tl_length = getint(&p); /* data length */ #define mit_KRB5_TL_LAST_PWD_CHANGE 1 #define mit_KRB5_TL_MOD_PRINC 2 switch(tl_type) { case mit_KRB5_TL_LAST_PWD_CHANGE: buf = malloc(tl_length); if (buf == NULL) errx(ENOMEM, "malloc"); getdata(&p, buf, tl_length); /* data itself */ val = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); free(buf); ALLOC(ent.entry.extensions); ALLOC_SEQ(ent.entry.extensions, 1); ent.entry.extensions->val[0].mandatory = 0; ent.entry.extensions->val[0].data.element = choice_HDB_extension_data_last_pw_change; ent.entry.extensions->val[0].data.u.last_pw_change = val; break; case mit_KRB5_TL_MOD_PRINC: buf = malloc(tl_length); if (buf == NULL) errx(ENOMEM, "malloc"); getdata(&p, buf, tl_length); /* data itself */ val = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); ret = krb5_parse_name(pd->context, (char *)buf + 4, &princ); if (ret) krb5_err(pd->context, 1, ret, "parse_name: %s", (char *)buf + 4); free(buf); ALLOC(ent.entry.modified_by); ent.entry.modified_by->time = val; ent.entry.modified_by->principal = princ; break; default: nexttoken(&p); break; } } ALLOC_SEQ(&ent.entry.keys, num_key_data); high_kvno = -1; for(i = 0; i < num_key_data; i++) { int key_versions; int kvno; key_versions = getint(&p); /* key data version */ kvno = getint(&p); /* * An MIT dump file may contain multiple sets of keys with * different kvnos. Since the Heimdal database can only represent * one kvno per principal, we only want the highest set. Assume * that set will be given first, and discard all keys with lower * kvnos. */ if (kvno > high_kvno && high_kvno != -1) errx(1, "line %d: high kvno keys given after low kvno keys", lineno); else if (kvno < high_kvno) { nexttoken(&p); /* key type */ nexttoken(&p); /* key length */ nexttoken(&p); /* key */ if (key_versions > 1) { nexttoken(&p); /* salt type */ nexttoken(&p); /* salt length */ nexttoken(&p); /* salt */ } ent.entry.keys.len--; continue; } ent.entry.kvno = kvno; high_kvno = kvno; ALLOC(ent.entry.keys.val[i].mkvno); *ent.entry.keys.val[i].mkvno = 1; /* key version 0 -- actual key */ ent.entry.keys.val[i].key.keytype = getint(&p); /* key type */ tmp = getint(&p); /* key length */ /* the first two bytes of the key is the key length -- skip it */ krb5_data_alloc(&ent.entry.keys.val[i].key.keyvalue, tmp - 2); q = nexttoken(&p); /* key itself */ hex_to_octet_string(q + 4, &ent.entry.keys.val[i].key.keyvalue); if(key_versions > 1) { /* key version 1 -- optional salt */ ALLOC(ent.entry.keys.val[i].salt); ent.entry.keys.val[i].salt->type = getint(&p); /* salt type */ tmp = getint(&p); /* salt length */ if(tmp > 0) { krb5_data_alloc(&ent.entry.keys.val[i].salt->salt, tmp - 2); q = nexttoken(&p); /* salt itself */ hex_to_octet_string(q + 4, &ent.entry.keys.val[i].salt->salt); } else { ent.entry.keys.val[i].salt->salt.length = 0; ent.entry.keys.val[i].salt->salt.data = NULL; getint(&p); /* -1, if no data. */ } fix_salt(pd->context, &ent.entry, i); } } nexttoken(&p); /* extra data */ v5_prop(pd->context, NULL, &ent, arg); } fclose(f); return 0; }
krb5_error_code KRB5_LIB_FUNCTION krb5_get_forwarded_creds (krb5_context context, krb5_auth_context auth_context, krb5_ccache ccache, krb5_flags flags, const char *hostname, krb5_creds *in_creds, krb5_data *out_data) { krb5_error_code ret; krb5_creds *out_creds; krb5_addresses addrs, *paddrs; KRB_CRED cred; KrbCredInfo *krb_cred_info; EncKrbCredPart enc_krb_cred_part; size_t len; unsigned char *buf; size_t buf_size; krb5_kdc_flags kdc_flags; krb5_crypto crypto; struct addrinfo *ai; int save_errno; krb5_creds *ticket; char *realm; if (in_creds->client && in_creds->client->realm) realm = in_creds->client->realm; else realm = in_creds->server->realm; addrs.len = 0; addrs.val = NULL; paddrs = &addrs; /* * If tickets are address-less, forward address-less tickets. */ ret = _krb5_get_krbtgt (context, ccache, realm, &ticket); if(ret == 0) { if (ticket->addresses.len == 0) paddrs = NULL; krb5_free_creds (context, ticket); } if (paddrs != NULL) { ret = getaddrinfo (hostname, NULL, NULL, &ai); if (ret) { save_errno = errno; krb5_set_error_string(context, "resolving %s: %s", hostname, gai_strerror(ret)); return krb5_eai_to_heim_errno(ret, save_errno); } ret = add_addrs (context, &addrs, ai); freeaddrinfo (ai); if (ret) return ret; } kdc_flags.b = int2KDCOptions(flags); ret = krb5_get_kdc_cred (context, ccache, kdc_flags, paddrs, NULL, in_creds, &out_creds); krb5_free_addresses (context, &addrs); if (ret) { return ret; } memset (&cred, 0, sizeof(cred)); cred.pvno = 5; cred.msg_type = krb_cred; ALLOC_SEQ(&cred.tickets, 1); if (cred.tickets.val == NULL) { ret = ENOMEM; krb5_set_error_string(context, "malloc: out of memory"); goto out2; } ret = decode_Ticket(out_creds->ticket.data, out_creds->ticket.length, cred.tickets.val, &len); if (ret) goto out3; memset (&enc_krb_cred_part, 0, sizeof(enc_krb_cred_part)); ALLOC_SEQ(&enc_krb_cred_part.ticket_info, 1); if (enc_krb_cred_part.ticket_info.val == NULL) { ret = ENOMEM; krb5_set_error_string(context, "malloc: out of memory"); goto out4; } if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) { krb5_timestamp sec; int32_t usec; krb5_us_timeofday (context, &sec, &usec); ALLOC(enc_krb_cred_part.timestamp, 1); if (enc_krb_cred_part.timestamp == NULL) { ret = ENOMEM; krb5_set_error_string(context, "malloc: out of memory"); goto out4; } *enc_krb_cred_part.timestamp = sec; ALLOC(enc_krb_cred_part.usec, 1); if (enc_krb_cred_part.usec == NULL) { ret = ENOMEM; krb5_set_error_string(context, "malloc: out of memory"); goto out4; } *enc_krb_cred_part.usec = usec; } else { enc_krb_cred_part.timestamp = NULL; enc_krb_cred_part.usec = NULL; } if (auth_context->local_address && auth_context->local_port) { krb5_boolean noaddr; krb5_const_realm realm; realm = krb5_principal_get_realm(context, out_creds->server); krb5_appdefault_boolean(context, NULL, realm, "no-addresses", paddrs == NULL, &noaddr); if (!noaddr) { ret = krb5_make_addrport (context, &enc_krb_cred_part.s_address, auth_context->local_address, auth_context->local_port); if (ret) goto out4; } } if (auth_context->remote_address) { if (auth_context->remote_port) { krb5_boolean noaddr; krb5_const_realm realm; realm = krb5_principal_get_realm(context, out_creds->server); /* Is this correct, and should we use the paddrs == NULL trick here as well? Having an address-less ticket may indicate that we don't know our own global address, but it does not necessary mean that we don't know the server's. */ krb5_appdefault_boolean(context, NULL, realm, "no-addresses", FALSE, &noaddr); if (!noaddr) { ret = krb5_make_addrport (context, &enc_krb_cred_part.r_address, auth_context->remote_address, auth_context->remote_port); if (ret) goto out4; } } else { ALLOC(enc_krb_cred_part.r_address, 1); if (enc_krb_cred_part.r_address == NULL) { ret = ENOMEM; krb5_set_error_string(context, "malloc: out of memory"); goto out4; } ret = krb5_copy_address (context, auth_context->remote_address, enc_krb_cred_part.r_address); if (ret) goto out4; } } /* fill ticket_info.val[0] */ enc_krb_cred_part.ticket_info.len = 1; krb_cred_info = enc_krb_cred_part.ticket_info.val; copy_EncryptionKey (&out_creds->session, &krb_cred_info->key); ALLOC(krb_cred_info->prealm, 1); copy_Realm (&out_creds->client->realm, krb_cred_info->prealm); ALLOC(krb_cred_info->pname, 1); copy_PrincipalName(&out_creds->client->name, krb_cred_info->pname); ALLOC(krb_cred_info->flags, 1); *krb_cred_info->flags = out_creds->flags.b; ALLOC(krb_cred_info->authtime, 1); *krb_cred_info->authtime = out_creds->times.authtime; ALLOC(krb_cred_info->starttime, 1); *krb_cred_info->starttime = out_creds->times.starttime; ALLOC(krb_cred_info->endtime, 1); *krb_cred_info->endtime = out_creds->times.endtime; ALLOC(krb_cred_info->renew_till, 1); *krb_cred_info->renew_till = out_creds->times.renew_till; ALLOC(krb_cred_info->srealm, 1); copy_Realm (&out_creds->server->realm, krb_cred_info->srealm); ALLOC(krb_cred_info->sname, 1); copy_PrincipalName (&out_creds->server->name, krb_cred_info->sname); ALLOC(krb_cred_info->caddr, 1); copy_HostAddresses (&out_creds->addresses, krb_cred_info->caddr); krb5_free_creds (context, out_creds); /* encode EncKrbCredPart */ ASN1_MALLOC_ENCODE(EncKrbCredPart, buf, buf_size, &enc_krb_cred_part, &len, ret); free_EncKrbCredPart (&enc_krb_cred_part); if (ret) { free_KRB_CRED(&cred); return ret; } if(buf_size != len) krb5_abortx(context, "internal error in ASN.1 encoder"); if (auth_context->flags & KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED) { cred.enc_part.etype = ENCTYPE_NULL; cred.enc_part.kvno = NULL; cred.enc_part.cipher.data = buf; cred.enc_part.cipher.length = buf_size; } else { krb5_keyblock *key; if (auth_context->local_subkey) key = auth_context->local_subkey; else if (auth_context->remote_subkey) key = auth_context->remote_subkey; else key = auth_context->keyblock; ret = krb5_crypto_init(context, key, 0, &crypto); if (ret) { free(buf); free_KRB_CRED(&cred); return ret; } ret = krb5_encrypt_EncryptedData (context, crypto, KRB5_KU_KRB_CRED, buf, len, 0, &cred.enc_part); free(buf); krb5_crypto_destroy(context, crypto); if (ret) { free_KRB_CRED(&cred); return ret; } } ASN1_MALLOC_ENCODE(KRB_CRED, buf, buf_size, &cred, &len, ret); free_KRB_CRED (&cred); if (ret) return ret; if(buf_size != len) krb5_abortx(context, "internal error in ASN.1 encoder"); out_data->length = len; out_data->data = buf; return 0; out4: free_EncKrbCredPart(&enc_krb_cred_part); out3: free_KRB_CRED(&cred); out2: krb5_free_creds (context, out_creds); return ret; }
int mit_prop_dump(void *arg, const char *file) { krb5_error_code ret; char line [2048]; FILE *f; int lineno = 0; struct hdb_entry_ex ent; struct prop_data *pd = arg; f = fopen(file, "r"); if(f == NULL) return errno; while(fgets(line, sizeof(line), f)) { char *p = line, *q; int i; int num_tl_data; int num_key_data; int extra_data_length; int attributes; int tmp; lineno++; memset(&ent, 0, sizeof(ent)); q = nexttoken(&p); if(strcmp(q, "kdb5_util") == 0) { int major; q = nexttoken(&p); /* load_dump */ if(strcmp(q, "load_dump")) errx(1, "line %d: unknown version", lineno); q = nexttoken(&p); /* load_dump */ if(strcmp(q, "version")) errx(1, "line %d: unknown version", lineno); q = nexttoken(&p); /* x.0 */ if(sscanf(q, "%d", &major) != 1) errx(1, "line %d: unknown version", lineno); if(major != 4) errx(1, "unknown dump file format, got %d, expected 4", major); continue; } else if(strcmp(q, "princ") != 0) { warnx("line %d: not a principal", lineno); continue; } tmp = getint(&p); if(tmp != 38) { warnx("line %d: bad base length %d != 38", lineno, tmp); continue; } q = nexttoken(&p); /* length of principal */ num_tl_data = getint(&p); /* number of tl-data */ num_key_data = getint(&p); /* number of key-data */ extra_data_length = getint(&p); /* length of extra data */ q = nexttoken(&p); /* principal name */ krb5_parse_name(pd->context, q, &ent.entry.principal); attributes = getint(&p); /* attributes */ attr_to_flags(attributes, &ent.entry.flags); tmp = getint(&p); /* max life */ if(tmp != 0) { ALLOC(ent.entry.max_life); *ent.entry.max_life = tmp; } tmp = getint(&p); /* max renewable life */ if(tmp != 0) { ALLOC(ent.entry.max_renew); *ent.entry.max_renew = tmp; } tmp = getint(&p); /* expiration */ if(tmp != 0 && tmp != 2145830400) { ALLOC(ent.entry.valid_end); *ent.entry.valid_end = tmp; } tmp = getint(&p); /* pw expiration */ if(tmp != 0) { ALLOC(ent.entry.pw_end); *ent.entry.pw_end = tmp; } q = nexttoken(&p); /* last auth */ q = nexttoken(&p); /* last failed auth */ q = nexttoken(&p); /* fail auth count */ for(i = 0; i < num_tl_data; i++) { unsigned long val; int tl_type, tl_length; unsigned char *buf; krb5_principal princ; tl_type = getint(&p); /* data type */ tl_length = getint(&p); /* data length */ #define mit_KRB5_TL_LAST_PWD_CHANGE 1 #define mit_KRB5_TL_MOD_PRINC 2 switch(tl_type) { case mit_KRB5_TL_MOD_PRINC: buf = malloc(tl_length); if (buf == NULL) errx(ENOMEM, "malloc"); getdata(&p, buf, tl_length); /* data itself */ val = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); ret = krb5_parse_name(pd->context, (char *)buf + 4, &princ); free(buf); ALLOC(ent.entry.modified_by); ent.entry.modified_by->time = val; ent.entry.modified_by->principal = princ; break; default: nexttoken(&p); break; } } ALLOC_SEQ(&ent.entry.keys, num_key_data); for(i = 0; i < num_key_data; i++) { int key_versions; key_versions = getint(&p); /* key data version */ ent.entry.kvno = getint(&p); /* XXX kvno */ ALLOC(ent.entry.keys.val[i].mkvno); *ent.entry.keys.val[i].mkvno = 0; /* key version 0 -- actual key */ ent.entry.keys.val[i].key.keytype = getint(&p); /* key type */ tmp = getint(&p); /* key length */ /* the first two bytes of the key is the key length -- skip it */ krb5_data_alloc(&ent.entry.keys.val[i].key.keyvalue, tmp - 2); q = nexttoken(&p); /* key itself */ hex_to_octet_string(q + 4, &ent.entry.keys.val[i].key.keyvalue); if(key_versions > 1) { /* key version 1 -- optional salt */ ALLOC(ent.entry.keys.val[i].salt); ent.entry.keys.val[i].salt->type = getint(&p); /* salt type */ tmp = getint(&p); /* salt length */ if(tmp > 0) { krb5_data_alloc(&ent.entry.keys.val[i].salt->salt, tmp - 2); q = nexttoken(&p); /* salt itself */ hex_to_octet_string(q + 4, &ent.entry.keys.val[i].salt->salt); } else { ent.entry.keys.val[i].salt->salt.length = 0; ent.entry.keys.val[i].salt->salt.data = NULL; tmp = getint(&p); /* -1, if no data. */ } fix_salt(pd->context, &ent.entry, i); } } q = nexttoken(&p); /* extra data */ v5_prop(pd->context, NULL, &ent, arg); } fclose(f); return 0; }
static krb5_error_code init_tgs_req (krb5_context context, krb5_ccache ccache, krb5_addresses *addresses, krb5_kdc_flags flags, Ticket *second_ticket, krb5_creds *in_creds, krb5_creds *krbtgt, unsigned nonce, krb5_keyblock **subkey, TGS_REQ *t, krb5_key_usage usage) { krb5_error_code ret = 0; memset(t, 0, sizeof(*t)); t->pvno = 5; t->msg_type = krb_tgs_req; if (in_creds->session.keytype) { ALLOC_SEQ(&t->req_body.etype, 1); if(t->req_body.etype.val == NULL) { ret = ENOMEM; krb5_set_error_string(context, "malloc: out of memory"); goto fail; } t->req_body.etype.val[0] = in_creds->session.keytype; } else { ret = krb5_init_etype(context, &t->req_body.etype.len, &t->req_body.etype.val, NULL); } if (ret) goto fail; t->req_body.addresses = addresses; t->req_body.kdc_options = flags.b; ret = copy_Realm(&in_creds->server->realm, &t->req_body.realm); if (ret) goto fail; ALLOC(t->req_body.sname, 1); if (t->req_body.sname == NULL) { ret = ENOMEM; krb5_set_error_string(context, "malloc: out of memory"); goto fail; } /* some versions of some code might require that the client be present in TGS-REQs, but this is clearly against the spec */ ret = copy_PrincipalName(&in_creds->server->name, t->req_body.sname); if (ret) goto fail; /* req_body.till should be NULL if there is no endtime specified, but old MIT code (like DCE secd) doesn't like that */ ALLOC(t->req_body.till, 1); if(t->req_body.till == NULL){ ret = ENOMEM; krb5_set_error_string(context, "malloc: out of memory"); goto fail; } *t->req_body.till = in_creds->times.endtime; t->req_body.nonce = nonce; if(second_ticket){ ALLOC(t->req_body.additional_tickets, 1); if (t->req_body.additional_tickets == NULL) { ret = ENOMEM; krb5_set_error_string(context, "malloc: out of memory"); goto fail; } ALLOC_SEQ(t->req_body.additional_tickets, 1); if (t->req_body.additional_tickets->val == NULL) { ret = ENOMEM; krb5_set_error_string(context, "malloc: out of memory"); goto fail; } ret = copy_Ticket(second_ticket, t->req_body.additional_tickets->val); if (ret) goto fail; } ALLOC(t->padata, 1); if (t->padata == NULL) { ret = ENOMEM; krb5_set_error_string(context, "malloc: out of memory"); goto fail; } ALLOC_SEQ(t->padata, 1); if (t->padata->val == NULL) { ret = ENOMEM; krb5_set_error_string(context, "malloc: out of memory"); goto fail; } { krb5_auth_context ac; krb5_keyblock *key = NULL; ret = krb5_auth_con_init(context, &ac); if(ret) goto fail; if (krb5_config_get_bool_default(context, NULL, FALSE, "realms", krbtgt->server->realm, "tgs_require_subkey", NULL)) { ret = krb5_generate_subkey (context, &krbtgt->session, &key); if (ret) { krb5_auth_con_free (context, ac); goto fail; } ret = krb5_auth_con_setlocalsubkey(context, ac, key); if (ret) { if (key) krb5_free_keyblock (context, key); krb5_auth_con_free (context, ac); goto fail; } } ret = set_auth_data (context, &t->req_body, &in_creds->authdata, key ? key : &krbtgt->session); if (ret) { if (key) krb5_free_keyblock (context, key); krb5_auth_con_free (context, ac); goto fail; } ret = make_pa_tgs_req(context, ac, &t->req_body, t->padata->val, krbtgt, usage); if(ret) { if (key) krb5_free_keyblock (context, key); krb5_auth_con_free(context, ac); goto fail; } *subkey = key; krb5_auth_con_free(context, ac); } fail: if (ret) { t->req_body.addresses = NULL; free_TGS_REQ (t); } return ret; }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_get_forwarded_creds (krb5_context context, krb5_auth_context auth_context, krb5_ccache ccache, krb5_flags flags, const char *hostname, krb5_creds *in_creds, krb5_data *out_data) { krb5_error_code ret; krb5_creds *out_creds; krb5_addresses addrs, *paddrs; KRB_CRED cred; KrbCredInfo *krb_cred_info; EncKrbCredPart enc_krb_cred_part; size_t len; unsigned char *buf; size_t buf_size; krb5_kdc_flags kdc_flags; krb5_crypto crypto; struct addrinfo *ai; krb5_creds *ticket; paddrs = NULL; addrs.len = 0; addrs.val = NULL; ret = krb5_get_credentials(context, 0, ccache, in_creds, &ticket); if(ret == 0) { if (ticket->addresses.len) paddrs = &addrs; krb5_free_creds (context, ticket); } else { krb5_boolean noaddr; krb5_appdefault_boolean(context, NULL, krb5_principal_get_realm(context, in_creds->client), "no-addresses", KRB5_ADDRESSLESS_DEFAULT, &noaddr); if (!noaddr) paddrs = &addrs; } /* * If tickets have addresses, get the address of the remote host. */ if (paddrs != NULL) { ret = getaddrinfo (hostname, NULL, NULL, &ai); if (ret) { krb5_error_code ret2 = krb5_eai_to_heim_errno(ret, errno); krb5_set_error_message(context, ret2, N_("resolving host %s failed: %s", "hostname, error"), hostname, gai_strerror(ret)); return ret2; } ret = add_addrs (context, &addrs, ai); freeaddrinfo (ai); if (ret) return ret; } kdc_flags.b = int2KDCOptions(flags); ret = krb5_get_kdc_cred (context, ccache, kdc_flags, paddrs, NULL, in_creds, &out_creds); krb5_free_addresses (context, &addrs); if (ret) return ret; memset (&cred, 0, sizeof(cred)); cred.pvno = 5; cred.msg_type = krb_cred; ALLOC_SEQ(&cred.tickets, 1); if (cred.tickets.val == NULL) { ret = ENOMEM; krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); goto out2; } ret = decode_Ticket(out_creds->ticket.data, out_creds->ticket.length, cred.tickets.val, &len); if (ret) goto out3; memset (&enc_krb_cred_part, 0, sizeof(enc_krb_cred_part)); ALLOC_SEQ(&enc_krb_cred_part.ticket_info, 1); if (enc_krb_cred_part.ticket_info.val == NULL) { ret = ENOMEM; krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); goto out4; } if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) { krb5_timestamp sec; int32_t usec; krb5_us_timeofday (context, &sec, &usec); ALLOC(enc_krb_cred_part.timestamp, 1); if (enc_krb_cred_part.timestamp == NULL) { ret = ENOMEM; krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); goto out4; } *enc_krb_cred_part.timestamp = sec; ALLOC(enc_krb_cred_part.usec, 1); if (enc_krb_cred_part.usec == NULL) { ret = ENOMEM; krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); goto out4; } *enc_krb_cred_part.usec = usec; } else { enc_krb_cred_part.timestamp = NULL; enc_krb_cred_part.usec = NULL; } if (auth_context->local_address && auth_context->local_port && paddrs) { ret = krb5_make_addrport (context, &enc_krb_cred_part.s_address, auth_context->local_address, auth_context->local_port); if (ret) goto out4; } if (auth_context->remote_address) { if (auth_context->remote_port) { krb5_boolean noaddr; krb5_const_realm srealm; srealm = krb5_principal_get_realm(context, out_creds->server); /* Is this correct, and should we use the paddrs == NULL trick here as well? Having an address-less ticket may indicate that we don't know our own global address, but it does not necessary mean that we don't know the server's. */ krb5_appdefault_boolean(context, NULL, srealm, "no-addresses", FALSE, &noaddr); if (!noaddr) { ret = krb5_make_addrport (context, &enc_krb_cred_part.r_address, auth_context->remote_address, auth_context->remote_port); if (ret) goto out4; } } else { ALLOC(enc_krb_cred_part.r_address, 1); if (enc_krb_cred_part.r_address == NULL) { ret = ENOMEM; krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); goto out4; } ret = krb5_copy_address (context, auth_context->remote_address, enc_krb_cred_part.r_address); if (ret) goto out4; } } /* fill ticket_info.val[0] */ enc_krb_cred_part.ticket_info.len = 1; krb_cred_info = enc_krb_cred_part.ticket_info.val; copy_EncryptionKey (&out_creds->session, &krb_cred_info->key); ALLOC(krb_cred_info->prealm, 1); copy_Realm (&out_creds->client->realm, krb_cred_info->prealm); ALLOC(krb_cred_info->pname, 1); copy_PrincipalName(&out_creds->client->name, krb_cred_info->pname); ALLOC(krb_cred_info->flags, 1); *krb_cred_info->flags = out_creds->flags.b; ALLOC(krb_cred_info->authtime, 1); *krb_cred_info->authtime = out_creds->times.authtime; ALLOC(krb_cred_info->starttime, 1); *krb_cred_info->starttime = out_creds->times.starttime; ALLOC(krb_cred_info->endtime, 1); *krb_cred_info->endtime = out_creds->times.endtime; ALLOC(krb_cred_info->renew_till, 1); *krb_cred_info->renew_till = out_creds->times.renew_till; ALLOC(krb_cred_info->srealm, 1); copy_Realm (&out_creds->server->realm, krb_cred_info->srealm); ALLOC(krb_cred_info->sname, 1); copy_PrincipalName (&out_creds->server->name, krb_cred_info->sname); ALLOC(krb_cred_info->caddr, 1); copy_HostAddresses (&out_creds->addresses, krb_cred_info->caddr); krb5_free_creds (context, out_creds); /* encode EncKrbCredPart */ ASN1_MALLOC_ENCODE(EncKrbCredPart, buf, buf_size, &enc_krb_cred_part, &len, ret); free_EncKrbCredPart (&enc_krb_cred_part); if (ret) { free_KRB_CRED(&cred); return ret; } if(buf_size != len) krb5_abortx(context, "internal error in ASN.1 encoder"); /** * Some older of the MIT gssapi library used clear-text tickets * (warped inside AP-REQ encryption), use the krb5_auth_context * flag KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED to support those * tickets. The session key is used otherwise to encrypt the * forwarded ticket. */ if (auth_context->flags & KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED) { cred.enc_part.etype = KRB5_ENCTYPE_NULL; cred.enc_part.kvno = NULL; cred.enc_part.cipher.data = buf; cred.enc_part.cipher.length = buf_size; } else { /* * Here older versions then 0.7.2 of Heimdal used the local or * remote subkey. That is wrong, the session key should be * used. Heimdal 0.7.2 and newer have code to try both in the * receiving end. */ ret = krb5_crypto_init(context, auth_context->keyblock, 0, &crypto); if (ret) { free(buf); free_KRB_CRED(&cred); return ret; } ret = krb5_encrypt_EncryptedData (context, crypto, KRB5_KU_KRB_CRED, buf, len, 0, &cred.enc_part); free(buf); krb5_crypto_destroy(context, crypto); if (ret) { free_KRB_CRED(&cred); return ret; } } ASN1_MALLOC_ENCODE(KRB_CRED, buf, buf_size, &cred, &len, ret); free_KRB_CRED (&cred); if (ret) return ret; if(buf_size != len) krb5_abortx(context, "internal error in ASN.1 encoder"); out_data->length = len; out_data->data = buf; return 0; out4: free_EncKrbCredPart(&enc_krb_cred_part); out3: free_KRB_CRED(&cred); out2: krb5_free_creds (context, out_creds); return ret; }
int hx509_cms_create_signed(hx509_context context, int flags, const heim_oid *eContentType, const void *data, size_t length, const AlgorithmIdentifier *digest_alg, hx509_certs certs, hx509_peer_info peer, hx509_certs anchors, hx509_certs pool, heim_octet_string *signed_data) { unsigned int i; hx509_name name; int ret; size_t size; struct sigctx sigctx; memset(&sigctx, 0, sizeof(sigctx)); memset(&name, 0, sizeof(name)); if (eContentType == NULL) eContentType = &asn1_oid_id_pkcs7_data; sigctx.digest_alg = digest_alg; sigctx.content.data = rk_UNCONST(data); sigctx.content.length = length; sigctx.eContentType = eContentType; sigctx.peer = peer; /** * Use HX509_CMS_SIGNATURE_ID_NAME to preferred use of issuer name * and serial number if possible. Otherwise subject key identifier * will preferred. */ if (flags & HX509_CMS_SIGNATURE_ID_NAME) sigctx.cmsidflag = CMS_ID_NAME; else sigctx.cmsidflag = CMS_ID_SKI; ret = hx509_certs_init(context, "MEMORY:certs", 0, NULL, &sigctx.certs); if (ret) return ret; sigctx.anchors = anchors; sigctx.pool = pool; sigctx.sd.version = CMSVersion_v3; der_copy_oid(eContentType, &sigctx.sd.encapContentInfo.eContentType); /** * Use HX509_CMS_SIGNATURE_DETACHED to create detached signatures. */ if ((flags & HX509_CMS_SIGNATURE_DETACHED) == 0) { ALLOC(sigctx.sd.encapContentInfo.eContent, 1); if (sigctx.sd.encapContentInfo.eContent == NULL) { hx509_clear_error_string(context); ret = ENOMEM; goto out; } sigctx.sd.encapContentInfo.eContent->data = malloc(length); if (sigctx.sd.encapContentInfo.eContent->data == NULL) { hx509_clear_error_string(context); ret = ENOMEM; goto out; } memcpy(sigctx.sd.encapContentInfo.eContent->data, data, length); sigctx.sd.encapContentInfo.eContent->length = length; } /** * Use HX509_CMS_SIGNATURE_NO_SIGNER to create no sigInfo (no * signatures). */ if ((flags & HX509_CMS_SIGNATURE_NO_SIGNER) == 0) { ret = hx509_certs_iter(context, certs, sig_process, &sigctx); if (ret) goto out; } if (sigctx.sd.signerInfos.len) { ALLOC_SEQ(&sigctx.sd.digestAlgorithms, sigctx.sd.signerInfos.len); if (sigctx.sd.digestAlgorithms.val == NULL) { ret = ENOMEM; hx509_clear_error_string(context); goto out; } /* XXX remove dups */ for (i = 0; i < sigctx.sd.signerInfos.len; i++) { AlgorithmIdentifier *di = &sigctx.sd.signerInfos.val[i].digestAlgorithm; ret = copy_AlgorithmIdentifier(di, &sigctx.sd.digestAlgorithms.val[i]); if (ret) { hx509_clear_error_string(context); goto out; } } } if (sigctx.certs) { ALLOC(sigctx.sd.certificates, 1); if (sigctx.sd.certificates == NULL) { hx509_clear_error_string(context); ret = ENOMEM; goto out; } ret = hx509_certs_iter(context, sigctx.certs, cert_process, &sigctx); if (ret) goto out; } ASN1_MALLOC_ENCODE(SignedData, signed_data->data, signed_data->length, &sigctx.sd, &size, ret); if (ret) { hx509_clear_error_string(context); goto out; } if (signed_data->length != size) _hx509_abort("internal ASN.1 encoder error"); out: hx509_certs_free(&sigctx.certs); free_SignedData(&sigctx.sd); return ret; }
krb5_error_code KRB5_LIB_FUNCTION krb5_parse_address(krb5_context context, const char *string, krb5_addresses *addresses) { int i, n; struct addrinfo *ai, *a; int error; int save_errno; addresses->len = 0; addresses->val = NULL; for(i = 0; i < num_addrs; i++) { if(at[i].parse_addr) { krb5_address addr; if((*at[i].parse_addr)(context, string, &addr) == 0) { ALLOC_SEQ(addresses, 1); if (addresses->val == NULL) { krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); return ENOMEM; } addresses->val[0] = addr; return 0; } } } error = getaddrinfo (string, NULL, NULL, &ai); if (error) { krb5_error_code ret2; save_errno = errno; ret2 = krb5_eai_to_heim_errno(error, save_errno); krb5_set_error_message (context, ret2, "%s: %s", string, gai_strerror(error)); return ret2; } n = 0; for (a = ai; a != NULL; a = a->ai_next) ++n; ALLOC_SEQ(addresses, n); if (addresses->val == NULL) { krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); freeaddrinfo(ai); return ENOMEM; } addresses->len = 0; for (a = ai, i = 0; a != NULL; a = a->ai_next) { if (krb5_sockaddr2address (context, ai->ai_addr, &addresses->val[i])) continue; if(krb5_address_search(context, &addresses->val[i], addresses)) { krb5_free_address(context, &addresses->val[i]); continue; } i++; addresses->len = i; } freeaddrinfo (ai); return 0; }