Exemplo n.º 1
0
krb5_error_code
_kdc_add_inital_verified_cas(krb5_context context,
			     krb5_kdc_configuration *config,
			     pk_client_params *params,
			     EncTicketPart *tkt)
{
    AD_INITIAL_VERIFIED_CAS cas;
    krb5_error_code ret;
    krb5_data data;
    size_t size;

    memset(&cas, 0, sizeof(cas));

    /* XXX add CAs to cas here */

    ASN1_MALLOC_ENCODE(AD_INITIAL_VERIFIED_CAS, data.data, data.length,
		       &cas, &size, ret);
    if (ret)
	return ret;
    if (data.length != size)
	krb5_abortx(context, "internal asn.1 encoder error");

    ret = _kdc_tkt_add_if_relevant_ad(context, tkt,
				      KRB5_AUTHDATA_INITIAL_VERIFIED_CAS,
				      &data);
    krb5_data_free(&data);
    return ret;
}
Exemplo n.º 2
0
KRB5_LIB_FUNCTION void KRB5_LIB_CALL
krb5_generate_random_block(void *buf, size_t len)
{
    int ret = krb5_generate_random(buf, len);
    if (ret)
	krb5_abortx(NULL, "Failed to generate random block");
}
Exemplo n.º 3
0
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_setivector(krb5_context context,
			 krb5_auth_context auth_context,
			 krb5_pointer ivector)
{
    krb5_abortx(context, "unimplemented krb5_auth_con_setivector called");
}
Exemplo n.º 4
0
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_getenctype(krb5_context context,
			 krb5_auth_context auth_context,
			 krb5_enctype *etype)
{
    krb5_abortx(context, "unimplemented krb5_auth_getenctype called");
}
Exemplo n.º 5
0
static krb5_error_code KRB5_CALLCONV
mkt_close(krb5_context context, krb5_keytab id)
{
    struct mkt_data *d = id->data, **dp;
    int i;

    HEIMDAL_MUTEX_lock(&mkt_mutex);
    if (d->refcount < 1)
	krb5_abortx(context,
		    "krb5 internal error, memory keytab refcount < 1 on close");

    if (--d->refcount > 0) {
	HEIMDAL_MUTEX_unlock(&mkt_mutex);
	return 0;
    }
    for (dp = &mkt_head; *dp != NULL; dp = &(*dp)->next) {
	if (*dp == d) {
	    *dp = d->next;
	    break;
	}
    }
    HEIMDAL_MUTEX_unlock(&mkt_mutex);

    free(d->name);
    for(i = 0; i < d->num_entries; i++)
	krb5_kt_free_entry(context, &d->entries[i]);
    free(d->entries);
    free(d);
    return 0;
}
Exemplo n.º 6
0
static krb5_error_code
pa_data_add_pac_request(krb5_context context,
			krb5_get_init_creds_ctx *ctx,
			METHOD_DATA *md)
{
    size_t len, length;
    krb5_error_code ret;
    PA_PAC_REQUEST req;
    void *buf;

    switch (ctx->req_pac) {
    case KRB5_INIT_CREDS_TRISTATE_UNSET:
	return 0; /* don't bother */
    case KRB5_INIT_CREDS_TRISTATE_TRUE:
	req.include_pac = 1;
	break;
    case KRB5_INIT_CREDS_TRISTATE_FALSE:
	req.include_pac = 0;
    }

    ASN1_MALLOC_ENCODE(PA_PAC_REQUEST, buf, length,
		       &req, &len, ret);
    if (ret)
	return ret;
    if(len != length)
	krb5_abortx(context, "internal error in ASN.1 encoder");

    ret = krb5_padata_add(context, md, KRB5_PADATA_PA_PAC_REQUEST, buf, len);
    if (ret)
	free(buf);

    return 0;
}
Exemplo n.º 7
0
static krb5_error_code
verify_req_hash(krb5_context context,
		const Kx509Request *req,
		krb5_keyblock *key)
{
    unsigned char digest[SHA_DIGEST_LENGTH];
    HMAC_CTX ctx;

    if (req->pk_hash.length != sizeof(digest)) {
	krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
			       "pk-hash have wrong length: %lu",
			       (unsigned long)req->pk_hash.length);
	return KRB5KDC_ERR_PREAUTH_FAILED;
    }

    HMAC_CTX_init(&ctx);
    HMAC_Init_ex(&ctx,
		 key->keyvalue.data, key->keyvalue.length,
		 EVP_sha1(), NULL);
    if (sizeof(digest) != HMAC_size(&ctx))
	krb5_abortx(context, "runtime error, hmac buffer wrong size in kx509");
    HMAC_Update(&ctx, version_2_0, sizeof(version_2_0));
    HMAC_Update(&ctx, req->pk_key.data, req->pk_key.length);
    HMAC_Final(&ctx, digest, 0);
    HMAC_CTX_cleanup(&ctx);

    if (memcmp(req->pk_hash.data, digest, sizeof(digest)) != 0) {
	krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
			       "pk-hash is not correct");
	return KRB5KDC_ERR_PREAUTH_FAILED;
    }
    return 0;
}
Exemplo n.º 8
0
static krb5_error_code
make_pa_tgs_req(krb5_context context,
		krb5_auth_context ac,
		KDC_REQ_BODY *body,
		PA_DATA *padata,
		krb5_creds *creds)
{
    u_char *buf;
    size_t buf_size;
    size_t len = 0;
    krb5_data in_data;
    krb5_error_code ret;

    ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, body, &len, ret);
    if (ret)
	goto out;
    if(buf_size != len)
	krb5_abortx(context, "internal error in ASN.1 encoder");

    in_data.length = len;
    in_data.data   = buf;
    ret = _krb5_mk_req_internal(context, &ac, 0, &in_data, creds,
				&padata->padata_value,
				KRB5_KU_TGS_REQ_AUTH_CKSUM,
				KRB5_KU_TGS_REQ_AUTH);
 out:
    free (buf);
    if(ret)
	return ret;
    padata->padata_type = KRB5_PADATA_TGS_REQ;
    return 0;
}
Exemplo n.º 9
0
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
_krb5_config_copy(krb5_context context,
		  krb5_config_section *c,
		  krb5_config_section **head)
{
    krb5_config_binding *d, *previous = NULL;

    *head = NULL;

    while (c) {
	d = calloc(1, sizeof(*d));

	if (*head == NULL)
	    *head = d;

	d->name = strdup(c->name);
	d->type = c->type;
	if (d->type == krb5_config_string)
	    d->u.string = strdup(c->u.string);
	else if (d->type == krb5_config_list)
	    _krb5_config_copy (context, c->u.list, &d->u.list);
	else
	    krb5_abortx(context,
			"unknown binding type (%d) in krb5_config_copy",
			d->type);
	if (previous)
	    previous->next = d;

	previous = d;
	c = c->next;
    }
    return 0;
}
Exemplo n.º 10
0
KRB5_LIB_FUNCTION void KRB5_LIB_CALL
krb5_generate_random_block(void *buf, size_t len)
{
    static int rng_initialized = 0;

    HEIMDAL_MUTEX_lock(&crypto_mutex);
    if (!rng_initialized) {
	if (seed_something())
	    krb5_abortx(NULL, "Fatal: could not seed the "
			"random number generator");

	rng_initialized = 1;
    }
    HEIMDAL_MUTEX_unlock(&crypto_mutex);
    if (RAND_bytes(buf, len) <= 0)
	krb5_abortx(NULL, "Failed to generate random block");
}
Exemplo n.º 11
0
krb5_error_code KRB5_LIB_FUNCTION
krb5_unparse_name_ext(krb5_context context,
		      krb5_const_principal principal,
		      char **name,
		      size_t *size)
{
    krb5_abortx(context, "unimplemented krb5_unparse_name_ext called");
}
Exemplo n.º 12
0
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_mk_error_ext(krb5_context context,
		  krb5_error_code error_code,
		  const char *e_text,
		  const krb5_data *e_data,
		  const krb5_principal server,
		  const PrincipalName *client_name,
		  const Realm *client_realm,
		  time_t *client_time,
		  int *client_usec,
		  krb5_data *reply)
{
    const char *e_text2 = NULL;
    KRB_ERROR msg;
    krb5_timestamp sec;
    int32_t usec;
    size_t len = 0;
    krb5_error_code ret = 0;

    krb5_us_timeofday (context, &sec, &usec);

    memset(&msg, 0, sizeof(msg));
    msg.pvno     = 5;
    msg.msg_type = krb_error;
    msg.stime    = sec;
    msg.susec    = usec;
    msg.ctime    = client_time;
    msg.cusec    = client_usec;
    /* Make sure we only send `protocol' error codes */
    if(error_code < KRB5KDC_ERR_NONE || error_code >= KRB5_ERR_RCSID) {
	if(e_text == NULL)
	    e_text = e_text2 = krb5_get_error_message(context, error_code);
	error_code = KRB5KRB_ERR_GENERIC;
    }
    msg.error_code = error_code - KRB5KDC_ERR_NONE;
    if (e_text)
	msg.e_text = rk_UNCONST(&e_text);
    if (e_data)
	msg.e_data = rk_UNCONST(e_data);
    if(server){
	msg.realm = server->realm;
	msg.sname = server->name;
    }else{
	static char unspec[] = "<unspecified realm>";
	msg.realm = unspec;
    }
    msg.crealm = rk_UNCONST(client_realm);
    msg.cname = rk_UNCONST(client_name);

    ASN1_MALLOC_ENCODE(KRB_ERROR, reply->data, reply->length, &msg, &len, ret);
    if (e_text2)
	krb5_free_error_message(context, e_text2);
    if (ret)
	return ret;
    if(reply->length != len)
	krb5_abortx(context, "internal error in ASN.1 encoder");
    return 0;
}
Exemplo n.º 13
0
static krb5_error_code
pk_check_pkauthenticator(krb5_context context,
			 PKAuthenticator *a,
			 const KDC_REQ *req)
{
    u_char *buf = NULL;
    size_t buf_size;
    krb5_error_code ret;
    size_t len = 0;
    krb5_timestamp now;
    Checksum checksum;

    krb5_timeofday (context, &now);

    /* XXX cusec */
    if (a->ctime == 0 || labs(a->ctime - now) > context->max_skew) {
	krb5_clear_error_message(context);
	return KRB5KRB_AP_ERR_SKEW;
    }

    ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, &req->req_body, &len, ret);
    if (ret) {
	krb5_clear_error_message(context);
	return ret;
    }
    if (buf_size != len)
	krb5_abortx(context, "Internal error in ASN.1 encoder");

    ret = krb5_create_checksum(context,
			       NULL,
			       0,
			       CKSUMTYPE_SHA1,
			       buf,
			       len,
			       &checksum);
    free(buf);
    if (ret) {
	krb5_clear_error_message(context);
	return ret;
    }

    if (a->paChecksum == NULL) {
	krb5_clear_error_message(context);
	ret = KRB5_KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED;
	goto out;
    }

    if (der_heim_octet_string_cmp(a->paChecksum, &checksum.checksum) != 0) {
	krb5_clear_error_message(context);
	ret = KRB5KRB_ERR_GENERIC;
    }

out:
    free_Checksum(&checksum);

    return ret;
}
Exemplo n.º 14
0
krb5_error_code
_kdc_tkt_add_if_relevant_ad(krb5_context context,
			    EncTicketPart *tkt,
			    int type,
			    const krb5_data *data)
{
    krb5_error_code ret;
    size_t size = 0;

    if (tkt->authorization_data == NULL) {
	tkt->authorization_data = calloc(1, sizeof(*tkt->authorization_data));
	if (tkt->authorization_data == NULL) {
	    krb5_set_error_message(context, ENOMEM, "out of memory");
	    return ENOMEM;
	}
    }

    /* add the entry to the last element */
    {
	AuthorizationData ad = { 0, NULL };
	AuthorizationDataElement ade;

	ade.ad_type = type;
	ade.ad_data = *data;

	ret = add_AuthorizationData(&ad, &ade);
	if (ret) {
	    krb5_set_error_message(context, ret, "add AuthorizationData failed");
	    return ret;
	}

	ade.ad_type = KRB5_AUTHDATA_IF_RELEVANT;

	ASN1_MALLOC_ENCODE(AuthorizationData,
			   ade.ad_data.data, ade.ad_data.length,
			   &ad, &size, ret);
	free_AuthorizationData(&ad);
	if (ret) {
	    krb5_set_error_message(context, ret, "ASN.1 encode of "
				   "AuthorizationData failed");
	    return ret;
	}
	if (ade.ad_data.length != size)
	    krb5_abortx(context, "internal asn.1 encoder error");

	ret = add_AuthorizationData(tkt->authorization_data, &ade);
	der_free_octet_string(&ade.ad_data);
	if (ret) {
	    krb5_set_error_message(context, ret, "add AuthorizationData failed");
	    return ret;
	}
    }

    return 0;
}
static krb5_error_code
RSA_MD5_checksum(krb5_context context,
		 struct _krb5_key_data *key,
		 const void *data,
		 size_t len,
		 unsigned usage,
		 Checksum *C)
{
    if (CCDigest(kCCDigestMD5, data, len, C->checksum.data) != 0)
	krb5_abortx(context, "md5 checksum failed");
    return 0;
}
Exemplo n.º 16
0
static krb5_error_code
RSA_MD5_checksum(krb5_context context,
		 struct _krb5_key_data *key,
		 const void *data,
		 size_t len,
		 unsigned usage,
		 Checksum *C)
{
    if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_md5(), NULL) != 1)
	krb5_abortx(context, "md5 checksum failed");
    return 0;
}
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_generate_seq_number(krb5_context context,
			 const krb5_keyblock *key,
			 uint32_t *seqno)
{
    if (CCRandomCopyBytes(kCCRandomDefault, seqno, sizeof(*seqno)) != 0)
	krb5_abortx(context, "Failed to generate random block");
    /* MIT used signed numbers, lets not stomp into that space directly */
    *seqno &= 0x3fffffff;
    if (*seqno == 0)
	*seqno = 1;
    return 0;
}
Exemplo n.º 18
0
static krb5_error_code
set_auth_data (krb5_context context,
	       KDC_REQ_BODY *req_body,
	       krb5_authdata *authdata,
	       krb5_keyblock *subkey)
{
    if(authdata->len) {
	size_t len, buf_size;
	unsigned char *buf;
	krb5_crypto crypto;
	krb5_error_code ret;

	ASN1_MALLOC_ENCODE(AuthorizationData, buf, buf_size, authdata,
			   &len, ret);
	if (ret)
	    return ret;
	if (buf_size != len)
	    krb5_abortx(context, "internal error in ASN.1 encoder");

	ALLOC(req_body->enc_authorization_data, 1);
	if (req_body->enc_authorization_data == NULL) {
	    free (buf);
	    krb5_set_error_message(context, ENOMEM,
				   N_("malloc: out of memory", ""));
	    return ENOMEM;
	}
	ret = krb5_crypto_init(context, subkey, 0, &crypto);
	if (ret) {
	    free (buf);
	    free (req_body->enc_authorization_data);
	    req_body->enc_authorization_data = NULL;
	    return ret;
	}
	krb5_encrypt_EncryptedData(context,
				   crypto,
				   KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY,
				   buf,
				   len,
				   0,
				   req_body->enc_authorization_data);
	free (buf);
	krb5_crypto_destroy(context, crypto);
    } else {
	req_body->enc_authorization_data = NULL;
    }
    return 0;
}
Exemplo n.º 19
0
static krb5_error_code
verify_checksum(krb5_context context,
		krb5_auth_context auth_context,
		KRB_SAFE *safe)
{
    krb5_error_code ret;
    u_char *buf;
    size_t buf_size;
    size_t len;
    Checksum c;
    krb5_crypto crypto;
    krb5_keyblock *key;

    c = safe->cksum;
    safe->cksum.cksumtype       = 0;
    safe->cksum.checksum.data   = NULL;
    safe->cksum.checksum.length = 0;

    ASN1_MALLOC_ENCODE(KRB_SAFE, buf, buf_size, safe, &len, ret);
    if(ret)
	return ret;
    if(buf_size != len)
	krb5_abortx(context, "internal error in ASN.1 encoder");

    if (auth_context->remote_subkey)
	key = auth_context->remote_subkey;
    else if (auth_context->local_subkey)
	key = auth_context->local_subkey;
    else
	key = auth_context->keyblock;

    ret = krb5_crypto_init(context, key, 0, &crypto);
    if (ret)
	goto out;
    ret = krb5_verify_checksum (context,
				crypto,
				KRB5_KU_KRB_SAFE_CKSUM,
				buf + buf_size - len,
				len,
				&c);
    krb5_crypto_destroy(context, crypto);
out:
    safe->cksum = c;
    free (buf);
    return ret;
}
Exemplo n.º 20
0
static krb5_error_code
mkt_resolve(krb5_context context, const char *name, krb5_keytab id)
{
    struct mkt_data *d;

    HEIMDAL_MUTEX_lock(&mkt_mutex);

    for (d = mkt_head; d != NULL; d = d->next)
	if (strcmp(d->name, name) == 0)
	    break;
    if (d) {
	if (d->refcount < 1)
	    krb5_abortx(context, "Double close on memory keytab, "
			"refcount < 1 %d", d->refcount);
	d->refcount++;
	id->data = d;
	HEIMDAL_MUTEX_unlock(&mkt_mutex);
	return 0;
    }

    d = calloc(1, sizeof(*d));
    if(d == NULL) {
	HEIMDAL_MUTEX_unlock(&mkt_mutex);
	krb5_set_error_message(context, ENOMEM,
			       N_("malloc: out of memory", ""));
	return ENOMEM;
    }
    d->name = strdup(name);
    if (d->name == NULL) {
	HEIMDAL_MUTEX_unlock(&mkt_mutex);
	free(d);
	krb5_set_error_message(context, ENOMEM,
			       N_("malloc: out of memory", ""));
	return ENOMEM;
    }
    d->entries = NULL;
    d->num_entries = 0;
    d->refcount = 1;
    d->next = mkt_head;
    mkt_head = d;
    HEIMDAL_MUTEX_unlock(&mkt_mutex);
    id->data = d;
    return 0;
}
Exemplo n.º 21
0
static void
free_binding (krb5_context context, krb5_config_binding *b)
{
    krb5_config_binding *next_b;

    while (b) {
	free (b->name);
	if (b->type == krb5_config_string)
	    free (b->u.string);
	else if (b->type == krb5_config_list)
	    free_binding (context, b->u.list);
	else
	    krb5_abortx(context, "unknown binding type (%d) in free_binding", 
			b->type);
	next_b = b->next;
	free (b);
	b = next_b;
    }
}
Exemplo n.º 22
0
static krb5_error_code
mcc_destroy(krb5_context context,
	    krb5_ccache id)
{
    krb5_mcache **n, *m = MCACHE(id);
    struct link *l;

    if (m->refcnt == 0)
	krb5_abortx(context, "mcc_destroy: refcnt already 0");

    if (!MISDEAD(m)) {
	/* if this is an active mcache, remove it from the linked
           list, and free all data */
	HEIMDAL_MUTEX_lock(&mcc_mutex);
	for(n = &mcc_head; n && *n; n = &(*n)->next) {
	    if(m == *n) {
		*n = m->next;
		break;
	    }
	}
	HEIMDAL_MUTEX_unlock(&mcc_mutex);
	if (m->primary_principal != NULL) {
	    krb5_free_principal (context, m->primary_principal);
	    m->primary_principal = NULL;
	}
	m->dead = 1;

	l = m->creds;
	while (l != NULL) {
	    struct link *old;
	    
	    krb5_free_cred_contents (context, &l->cred);
	    old = l;
	    l = l->next;
	    free (old);
	}
	m->creds = NULL;
    }
    return 0;
}
Exemplo n.º 23
0
krb5_error_code KRB5_LIB_FUNCTION
krb5_build_ap_req (krb5_context context,
		   krb5_enctype enctype,
		   krb5_creds *cred,
		   krb5_flags ap_options,
		   krb5_data authenticator,
		   krb5_data *retdata)
{
  krb5_error_code ret = 0;
  AP_REQ ap;
  Ticket t;
  size_t len;
  
  ap.pvno = 5;
  ap.msg_type = krb_ap_req;
  memset(&ap.ap_options, 0, sizeof(ap.ap_options));
  ap.ap_options.use_session_key = (ap_options & AP_OPTS_USE_SESSION_KEY) > 0;
  ap.ap_options.mutual_required = (ap_options & AP_OPTS_MUTUAL_REQUIRED) > 0;
  
  ap.ticket.tkt_vno = 5;
  copy_Realm(&cred->server->realm, &ap.ticket.realm);
  copy_PrincipalName(&cred->server->name, &ap.ticket.sname);

  decode_Ticket(cred->ticket.data, cred->ticket.length, &t, &len);
  copy_EncryptedData(&t.enc_part, &ap.ticket.enc_part);
  free_Ticket(&t);

  ap.authenticator.etype = enctype;
  ap.authenticator.kvno  = NULL;
  ap.authenticator.cipher = authenticator;

  ASN1_MALLOC_ENCODE(AP_REQ, retdata->data, retdata->length,
		     &ap, &len, ret);
  if(ret == 0 && retdata->length != len)
      krb5_abortx(context, "internal error in ASN.1 encoder");
  free_AP_REQ(&ap);
  return ret;

}
Exemplo n.º 24
0
static krb5_error_code
encode_uvinfo(krb5_context context, krb5_const_principal p, krb5_data *data)
{
    KRB5PrincipalName pn;
    krb5_error_code ret;
    size_t size = 0;

    pn.principalName = p->name;
    pn.realm = p->realm;

    ASN1_MALLOC_ENCODE(KRB5PrincipalName, data->data, data->length,
		       &pn, &size, ret);
    if (ret) {
	krb5_data_zero(data);
	krb5_set_error_message(context, ret,
			       N_("Failed to encode KRB5PrincipalName", ""));
	return ret;
    }
    if (data->length != size)
	krb5_abortx(context, "asn1 compiler internal error");
    return 0;
}
Exemplo n.º 25
0
static void
storage_set_flags(krb5_context context, krb5_storage *sp, int vno)
{
    int flags = 0;
    switch(vno) {
    case KRB5_FCC_FVNO_1:
	flags |= KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS;
	flags |= KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE;
	flags |= KRB5_STORAGE_HOST_BYTEORDER;
	break;
    case KRB5_FCC_FVNO_2:
	flags |= KRB5_STORAGE_HOST_BYTEORDER;
	break;
    case KRB5_FCC_FVNO_3:
	flags |= KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE;
	break;
    case KRB5_FCC_FVNO_4:
	break;
    default:
	krb5_abortx(context,
		    "storage_set_flags called with bad vno (%x)", vno);
    }
    krb5_storage_set_flags(sp, flags);
}
Exemplo n.º 26
0
static krb5_error_code
get_cred_kdc(krb5_context context,
	     krb5_ccache id,
	     krb5_kdc_flags flags,
	     krb5_addresses *addresses,
	     krb5_creds *in_creds,
	     krb5_creds *krbtgt,
	     krb5_principal impersonate_principal,
	     Ticket *second_ticket,
	     krb5_creds *out_creds)
{
    TGS_REQ req;
    krb5_data enc;
    krb5_data resp;
    krb5_kdc_rep rep;
    KRB_ERROR error;
    krb5_error_code ret;
    unsigned nonce;
    krb5_keyblock *subkey = NULL;
    size_t len;
    Ticket second_ticket_data;
    METHOD_DATA padata;

    krb5_data_zero(&resp);
    krb5_data_zero(&enc);
    padata.val = NULL;
    padata.len = 0;

    krb5_generate_random_block(&nonce, sizeof(nonce));
    nonce &= 0xffffffff;

    if(flags.b.enc_tkt_in_skey && second_ticket == NULL){
	ret = decode_Ticket(in_creds->second_ticket.data,
			    in_creds->second_ticket.length,
			    &second_ticket_data, &len);
	if(ret)
	    return ret;
	second_ticket = &second_ticket_data;
    }


    if (impersonate_principal) {
	krb5_crypto crypto;
	PA_S4U2Self self;
	krb5_data data;
	void *buf;
	size_t size;

	self.name = impersonate_principal->name;
	self.realm = impersonate_principal->realm;
	self.auth = estrdup("Kerberos");
	
	ret = _krb5_s4u2self_to_checksumdata(context, &self, &data);
	if (ret) {
	    free(self.auth);
	    goto out;
	}

	ret = krb5_crypto_init(context, &krbtgt->session, 0, &crypto);
	if (ret) {
	    free(self.auth);
	    krb5_data_free(&data);
	    goto out;
	}

	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) {
	    free(self.auth);
	    goto out;
	}

	ASN1_MALLOC_ENCODE(PA_S4U2Self, buf, len, &self, &size, ret);
	free(self.auth);
	free_Checksum(&self.cksum);
	if (ret)
	    goto out;
	if (len != size)
	    krb5_abortx(context, "internal asn1 error");
	
	ret = krb5_padata_add(context, &padata, KRB5_PADATA_FOR_USER, buf, len);
	if (ret)
	    goto out;
    }

    ret = init_tgs_req (context,
			id,
			addresses,
			flags,
			second_ticket,
			in_creds,
			krbtgt,
			nonce,
			&padata,
			&subkey,
			&req);
    if (ret)
	goto out;

    ASN1_MALLOC_ENCODE(TGS_REQ, enc.data, enc.length, &req, &len, ret);
    if (ret)
	goto out;
    if(enc.length != len)
	krb5_abortx(context, "internal error in ASN.1 encoder");

    /* don't free addresses */
    req.req_body.addresses = NULL;
    free_TGS_REQ(&req);

    /*
     * Send and receive
     */
    {
	krb5_sendto_ctx stctx;
	ret = krb5_sendto_ctx_alloc(context, &stctx);
	if (ret)
	    return ret;
	krb5_sendto_ctx_set_func(stctx, _krb5_kdc_retry, NULL);

	ret = krb5_sendto_context (context, stctx, &enc,
				   krbtgt->server->name.name_string.val[1],
				   &resp);
	krb5_sendto_ctx_free(context, stctx);
    }
    if(ret)
	goto out;

    memset(&rep, 0, sizeof(rep));
    if(decode_TGS_REP(resp.data, resp.length, &rep.kdc_rep, &len) == 0) {
	unsigned eflags = 0;

	ret = krb5_copy_principal(context,
				  in_creds->client,
				  &out_creds->client);
	if(ret)
	    goto out2;
	ret = krb5_copy_principal(context,
				  in_creds->server,
				  &out_creds->server);
	if(ret)
	    goto out2;
	/* this should go someplace else */
	out_creds->times.endtime = in_creds->times.endtime;

	/* XXX should do better testing */
	if (flags.b.constrained_delegation || impersonate_principal)
	    eflags |= EXTRACT_TICKET_ALLOW_CNAME_MISMATCH;

	ret = _krb5_extract_ticket(context,
				   &rep,
				   out_creds,
				   &krbtgt->session,
				   NULL,
				   0,
				   &krbtgt->addresses,
				   nonce,
				   eflags,
				   decrypt_tkt_with_subkey,
				   subkey);
    out2:
	krb5_free_kdc_rep(context, &rep);
    } else if(krb5_rd_error(context, &resp, &error) == 0) {
	ret = krb5_error_from_rd_error(context, &error, in_creds);
	krb5_free_error_contents(context, &error);
    } else if(resp.length > 0 && ((char*)resp.data)[0] == 4) {
	ret = KRB5KRB_AP_ERR_V4_REPLY;
	krb5_clear_error_message(context);
    } else {
	ret = KRB5KRB_AP_ERR_MSG_TYPE;
	krb5_clear_error_message(context);
    }

out:
    if (second_ticket == &second_ticket_data)
	free_Ticket(&second_ticket_data);
    free_METHOD_DATA(&padata);
    krb5_data_free(&resp);
    krb5_data_free(&enc);
    if(subkey)
	krb5_free_keyblock(context, subkey);
    return ret;

}
Exemplo n.º 27
0
kadm5_ret_t
kadm5_s_get_principal(void *server_handle,
		      krb5_principal princ,
		      kadm5_principal_ent_t out,
		      uint32_t mask)
{
    kadm5_server_context *context = server_handle;
    kadm5_ret_t ret;
    hdb_entry_ex ent;

    memset(&ent, 0, sizeof(ent));

    if (!context->keep_open) {
	ret = context->db->hdb_open(context->context, context->db, O_RDONLY, 0);
	if(ret)
	    return ret;
    }
    ret = context->db->hdb_fetch_kvno(context->context, context->db, princ,
				      HDB_F_DECRYPT|HDB_F_ALL_KVNOS|
				      HDB_F_GET_ANY|HDB_F_ADMIN_DATA, 0, &ent);
    if (!context->keep_open)
	context->db->hdb_close(context->context, context->db);
    if(ret)
	return _kadm5_error_code(ret);

    memset(out, 0, sizeof(*out));
    if(mask & KADM5_PRINCIPAL)
	ret  = krb5_copy_principal(context->context, ent.entry.principal,
				   &out->principal);
    if(ret)
	goto out;
    if(mask & KADM5_PRINC_EXPIRE_TIME && ent.entry.valid_end)
	out->princ_expire_time = *ent.entry.valid_end;
    if(mask & KADM5_PW_EXPIRATION && ent.entry.pw_end)
	out->pw_expiration = *ent.entry.pw_end;
    if(mask & KADM5_LAST_PWD_CHANGE)
	hdb_entry_get_pw_change_time(&ent.entry, &out->last_pwd_change);
    if(mask & KADM5_ATTRIBUTES){
	out->attributes |= ent.entry.flags.postdate ? 0 : KRB5_KDB_DISALLOW_POSTDATED;
	out->attributes |= ent.entry.flags.forwardable ? 0 : KRB5_KDB_DISALLOW_FORWARDABLE;
	out->attributes |= ent.entry.flags.initial ? KRB5_KDB_DISALLOW_TGT_BASED : 0;
	out->attributes |= ent.entry.flags.renewable ? 0 : KRB5_KDB_DISALLOW_RENEWABLE;
	out->attributes |= ent.entry.flags.proxiable ? 0 : KRB5_KDB_DISALLOW_PROXIABLE;
	out->attributes |= ent.entry.flags.invalid ? KRB5_KDB_DISALLOW_ALL_TIX : 0;
	out->attributes |= ent.entry.flags.require_preauth ? KRB5_KDB_REQUIRES_PRE_AUTH : 0;
	out->attributes |= ent.entry.flags.server ? 0 : KRB5_KDB_DISALLOW_SVR;
	out->attributes |= ent.entry.flags.change_pw ? KRB5_KDB_PWCHANGE_SERVICE : 0;
	out->attributes |= ent.entry.flags.ok_as_delegate ? KRB5_KDB_OK_AS_DELEGATE : 0;
	out->attributes |= ent.entry.flags.trusted_for_delegation ? KRB5_KDB_TRUSTED_FOR_DELEGATION : 0;
	out->attributes |= ent.entry.flags.allow_kerberos4 ? KRB5_KDB_ALLOW_KERBEROS4 : 0;
	out->attributes |= ent.entry.flags.allow_digest ? KRB5_KDB_ALLOW_DIGEST : 0;
    }
    if(mask & KADM5_MAX_LIFE) {
	if(ent.entry.max_life)
	    out->max_life = *ent.entry.max_life;
	else
	    out->max_life = INT_MAX;
    }
    if(mask & KADM5_MOD_TIME) {
	if(ent.entry.modified_by)
	    out->mod_date = ent.entry.modified_by->time;
	else
	    out->mod_date = ent.entry.created_by.time;
    }
    if(mask & KADM5_MOD_NAME) {
	if(ent.entry.modified_by) {
	    if (ent.entry.modified_by->principal != NULL)
		ret = krb5_copy_principal(context->context,
					  ent.entry.modified_by->principal,
					  &out->mod_name);
	} else if(ent.entry.created_by.principal != NULL)
	    ret = krb5_copy_principal(context->context,
				      ent.entry.created_by.principal,
				      &out->mod_name);
	else
	    out->mod_name = NULL;
    }
    if(ret)
	goto out;

    if(mask & KADM5_KVNO)
	out->kvno = ent.entry.kvno;
    if(mask & KADM5_MKVNO) {
	size_t n;
	out->mkvno = 0; /* XXX */
	for(n = 0; n < ent.entry.keys.len; n++)
	    if(ent.entry.keys.val[n].mkvno) {
		out->mkvno = *ent.entry.keys.val[n].mkvno; /* XXX this isn't right */
		break;
	    }
    }
#if 0 /* XXX implement */
    if(mask & KADM5_AUX_ATTRIBUTES)
	;
    if(mask & KADM5_LAST_SUCCESS)
	;
    if(mask & KADM5_LAST_FAILED)
	;
    if(mask & KADM5_FAIL_AUTH_COUNT)
	;
#endif
    if(mask & KADM5_POLICY) {
	HDB_extension *ext;

	ext = hdb_find_extension(&ent.entry, choice_HDB_extension_data_policy);
	if (ext == NULL) {
	    out->policy = strdup("default");
	    /* It's OK if we retun NULL instead of "default" */
	} else {
	    out->policy = strdup(ext->data.u.policy);
	    if (out->policy == NULL) {
		ret = ENOMEM;
		goto out;
	    }
	}
    }
    if(mask & KADM5_MAX_RLIFE) {
	if(ent.entry.max_renew)
	    out->max_renewable_life = *ent.entry.max_renew;
	else
	    out->max_renewable_life = INT_MAX;
    }
    if(mask & KADM5_KEY_DATA){
	size_t i;
	size_t n_keys = ent.entry.keys.len;
	krb5_salt salt;
	HDB_extension *ext;
	HDB_Ext_KeySet *hist_keys = NULL;

	ext = hdb_find_extension(&ent.entry, choice_HDB_extension_data_hist_keys);
	if (ext != NULL)
	    hist_keys = &ext->data.u.hist_keys;

	krb5_get_pw_salt(context->context, ent.entry.principal, &salt);
	for (i = 0; hist_keys != NULL && i < hist_keys->len; i++)
	    n_keys += hist_keys->val[i].keys.len;
	out->key_data = malloc(n_keys * sizeof(*out->key_data));
	if (out->key_data == NULL && n_keys != 0) {
	    ret = ENOMEM;
	    goto out;
	}
	out->n_key_data = 0;
	ret = copy_keyset_to_kadm5(context, ent.entry.kvno, ent.entry.keys.len,
				   ent.entry.keys.val, &salt, out);
	if (ret)
	    goto out;
	for (i = 0; hist_keys != NULL && i < hist_keys->len; i++) {
	    ret = copy_keyset_to_kadm5(context, hist_keys->val[i].kvno,
				       hist_keys->val[i].keys.len,
				       hist_keys->val[i].keys.val,
				       &salt, out);
	    if (ret)
		goto out;
	}
	krb5_free_salt(context->context, salt);
	assert( out->n_key_data == n_keys );
    }
    if(ret){
	kadm5_free_principal_ent(context, out);
	goto out;
    }
    if(mask & KADM5_TL_DATA) {
	time_t last_pw_expire;
	const HDB_Ext_PKINIT_acl *acl;
	const HDB_Ext_Aliases *aliases;

	ret = hdb_entry_get_pw_change_time(&ent.entry, &last_pw_expire);
	if (ret == 0 && last_pw_expire) {
	    unsigned char buf[4];
	    _krb5_put_int(buf, last_pw_expire, sizeof(buf));
	    ret = add_tl_data(out, KRB5_TL_LAST_PWD_CHANGE, buf, sizeof(buf));
	}
	if(ret){
	    kadm5_free_principal_ent(context, out);
	    goto out;
	}
	/*
	 * If the client was allowed to get key data, let it have the
	 * password too.
	 */
	if(mask & KADM5_KEY_DATA) {
	    heim_utf8_string pw;

	    ret = hdb_entry_get_password(context->context,
					 context->db, &ent.entry, &pw);
	    if (ret == 0) {
		ret = add_tl_data(out, KRB5_TL_PASSWORD, pw, strlen(pw) + 1);
		free(pw);
	    }
	    krb5_clear_error_message(context->context);
	}

	ret = hdb_entry_get_pkinit_acl(&ent.entry, &acl);
	if (ret == 0 && acl) {
	    krb5_data buf;
	    size_t len;

	    ASN1_MALLOC_ENCODE(HDB_Ext_PKINIT_acl, buf.data, buf.length,
				acl, &len, ret);
	    if (ret) {
		kadm5_free_principal_ent(context, out);
		goto out;
	    }
	    if (len != buf.length)
		krb5_abortx(context->context,
			    "internal ASN.1 encoder error");
	    ret = add_tl_data(out, KRB5_TL_PKINIT_ACL, buf.data, buf.length);
	    free(buf.data);
	    if (ret) {
		kadm5_free_principal_ent(context, out);
		goto out;
	    }
	}
	if(ret){
	    kadm5_free_principal_ent(context, out);
	    goto out;
	}

	ret = hdb_entry_get_aliases(&ent.entry, &aliases);
	if (ret == 0 && aliases) {
	    krb5_data buf;
	    size_t len;

	    ASN1_MALLOC_ENCODE(HDB_Ext_Aliases, buf.data, buf.length,
			       aliases, &len, ret);
	    if (ret) {
		kadm5_free_principal_ent(context, out);
		goto out;
	    }
	    if (len != buf.length)
		krb5_abortx(context->context,
			    "internal ASN.1 encoder error");
	    ret = add_tl_data(out, KRB5_TL_ALIASES, buf.data, buf.length);
	    free(buf.data);
	    if (ret) {
		kadm5_free_principal_ent(context, out);
		goto out;
	    }
	}
	if(ret){
	    kadm5_free_principal_ent(context, out);
	    goto out;
	}

    }
out:
    hdb_free_entry(context->context, &ent);

    return _kadm5_error_code(ret);
}
Exemplo n.º 28
0
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_mk_rep(krb5_context context,
	    krb5_auth_context auth_context,
	    krb5_data *outbuf)
{
    krb5_error_code ret;
    AP_REP ap;
    EncAPRepPart body;
    u_char *buf = NULL;
    size_t buf_size;
    size_t len = 0;
    krb5_crypto crypto;

    ap.pvno = 5;
    ap.msg_type = krb_ap_rep;

    memset (&body, 0, sizeof(body));

    body.ctime = auth_context->authenticator->ctime;
    body.cusec = auth_context->authenticator->cusec;
    if (auth_context->flags & KRB5_AUTH_CONTEXT_USE_SUBKEY) {
	if (auth_context->local_subkey == NULL) {
	    ret = krb5_auth_con_generatelocalsubkey(context,
						    auth_context,
						    auth_context->keyblock);
	    if(ret) {
		free_EncAPRepPart(&body);
		return ret;
	    }
	}
	ret = krb5_copy_keyblock(context, auth_context->local_subkey,
				 &body.subkey);
	if (ret) {
	    free_EncAPRepPart(&body);
	    return krb5_enomem(context);
	}
    } else
	body.subkey = NULL;
    if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
	if(auth_context->local_seqnumber == 0)
	    krb5_generate_seq_number (context,
				      auth_context->keyblock,
				      &auth_context->local_seqnumber);
	ALLOC(body.seq_number, 1);
	if (body.seq_number == NULL) {
	    free_EncAPRepPart(&body);
	    return krb5_enomem(context);
	}
	*(body.seq_number) = auth_context->local_seqnumber;
    } else
	body.seq_number = NULL;

    ap.enc_part.etype = auth_context->keyblock->keytype;
    ap.enc_part.kvno  = NULL;

    ASN1_MALLOC_ENCODE(EncAPRepPart, buf, buf_size, &body, &len, ret);
    free_EncAPRepPart (&body);
    if(ret)
	return ret;
    if (buf_size != len)
	krb5_abortx(context, "internal error in ASN.1 encoder");
    ret = krb5_crypto_init(context, auth_context->keyblock,
			   0 /* ap.enc_part.etype */, &crypto);
    if (ret) {
	free (buf);
	return ret;
    }
    ret = krb5_encrypt (context,
			crypto,
			KRB5_KU_AP_REQ_ENC_PART,
			buf + buf_size - len,
			len,
			&ap.enc_part.cipher);
    krb5_crypto_destroy(context, crypto);
    free(buf);
    if (ret)
	return ret;

    ASN1_MALLOC_ENCODE(AP_REP, outbuf->data, outbuf->length, &ap, &len, ret);
    if (ret == 0 && outbuf->length != len)
	krb5_abortx(context, "internal error in ASN.1 encoder");
    free_AP_REP (&ap);
    return ret;
}
Exemplo n.º 29
0
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_rd_cred(krb5_context context,
	     krb5_auth_context auth_context,
	     krb5_data *in_data,
	     krb5_creds ***ret_creds,
	     krb5_replay_data *outdata)
{
    krb5_error_code ret;
    size_t len;
    KRB_CRED cred;
    EncKrbCredPart enc_krb_cred_part;
    krb5_data enc_krb_cred_part_data;
    krb5_crypto crypto;
    int i;

    memset(&enc_krb_cred_part, 0, sizeof(enc_krb_cred_part));

    if ((auth_context->flags &
	 (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
	outdata == NULL)
	return KRB5_RC_REQUIRED; /* XXX better error, MIT returns this */

    *ret_creds = NULL;

    ret = decode_KRB_CRED(in_data->data, in_data->length,
			  &cred, &len);
    if(ret) {
	krb5_clear_error_message(context);
	return ret;
    }

    if (cred.pvno != 5) {
	ret = KRB5KRB_AP_ERR_BADVERSION;
	krb5_clear_error_message (context);
	goto out;
    }

    if (cred.msg_type != krb_cred) {
	ret = KRB5KRB_AP_ERR_MSG_TYPE;
	krb5_clear_error_message (context);
	goto out;
    }

    if (cred.enc_part.etype == ETYPE_NULL) {
	/* DK: MIT GSS-API Compatibility */
	enc_krb_cred_part_data.length = cred.enc_part.cipher.length;
	enc_krb_cred_part_data.data   = cred.enc_part.cipher.data;
    } else {
	/* Try both subkey and session key.
	 *
	 * RFC4120 claims we should use the session key, but Heimdal
	 * before 0.8 used the remote subkey if it was send in the
	 * auth_context.
	 */

	if (auth_context->remote_subkey) {
	    ret = krb5_crypto_init(context, auth_context->remote_subkey,
				   0, &crypto);
	    if (ret)
		goto out;

	    ret = krb5_decrypt_EncryptedData(context,
					     crypto,
					     KRB5_KU_KRB_CRED,
					     &cred.enc_part,
					     &enc_krb_cred_part_data);
	
	    krb5_crypto_destroy(context, crypto);
	}

	/*
	 * If there was not subkey, or we failed using subkey,
	 * retry using the session key
	 */
	if (auth_context->remote_subkey == NULL || ret == KRB5KRB_AP_ERR_BAD_INTEGRITY)
	{

	    ret = krb5_crypto_init(context, auth_context->keyblock,
				   0, &crypto);

	    if (ret)
		goto out;
	
	    ret = krb5_decrypt_EncryptedData(context,
					     crypto,
					     KRB5_KU_KRB_CRED,
					     &cred.enc_part,
					     &enc_krb_cred_part_data);
	
	    krb5_crypto_destroy(context, crypto);
	}
	if (ret)
	    goto out;
    }

    ret = decode_EncKrbCredPart(enc_krb_cred_part_data.data,
				enc_krb_cred_part_data.length,
				&enc_krb_cred_part,
				&len);
    if (enc_krb_cred_part_data.data != cred.enc_part.cipher.data)
	krb5_data_free(&enc_krb_cred_part_data);
    if (ret) {
	krb5_set_error_message(context, ret,
			       N_("Failed to decode "
				  "encrypte credential part", ""));
	goto out;
    }

    /* check sender address */

    if (enc_krb_cred_part.s_address
	&& auth_context->remote_address
	&& auth_context->remote_port) {
	krb5_address *a;

	ret = krb5_make_addrport (context, &a,
				  auth_context->remote_address,
				  auth_context->remote_port);
	if (ret)
	    goto out;


	ret = compare_addrs(context, a, enc_krb_cred_part.s_address,
			    N_("sender address is wrong "
			       "in received creds", ""));
	krb5_free_address(context, a);
	free(a);
	if(ret)
	    goto out;
    }

    /* check receiver address */

    if (enc_krb_cred_part.r_address
	&& auth_context->local_address) {
	if(auth_context->local_port &&
	   enc_krb_cred_part.r_address->addr_type == KRB5_ADDRESS_ADDRPORT) {
	    krb5_address *a;
	    ret = krb5_make_addrport (context, &a,
				      auth_context->local_address,
				      auth_context->local_port);
	    if (ret)
		goto out;
	
	    ret = compare_addrs(context, a, enc_krb_cred_part.r_address,
				N_("receiver address is wrong "
				   "in received creds", ""));
	    krb5_free_address(context, a);
	    free(a);
	    if(ret)
		goto out;
	} else {
	    ret = compare_addrs(context, auth_context->local_address,
				enc_krb_cred_part.r_address,
				N_("receiver address is wrong "
				   "in received creds", ""));
	    if(ret)
		goto out;
	}
    }

    /* check timestamp */
    if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) {
	krb5_timestamp sec;

	krb5_timeofday (context, &sec);

	if (enc_krb_cred_part.timestamp == NULL ||
	    enc_krb_cred_part.usec      == NULL ||
	    abs(*enc_krb_cred_part.timestamp - sec)
	    > context->max_skew) {
	    krb5_clear_error_message (context);
	    ret = KRB5KRB_AP_ERR_SKEW;
	    goto out;
	}
    }

    if ((auth_context->flags &
	 (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE))) {
	/* if these fields are not present in the cred-part, silently
           return zero */
	memset(outdata, 0, sizeof(*outdata));
	if(enc_krb_cred_part.timestamp)
	    outdata->timestamp = *enc_krb_cred_part.timestamp;
	if(enc_krb_cred_part.usec)
	    outdata->usec = *enc_krb_cred_part.usec;
	if(enc_krb_cred_part.nonce)
	    outdata->seq = *enc_krb_cred_part.nonce;
    }

    /* Convert to NULL terminated list of creds */

    *ret_creds = calloc(enc_krb_cred_part.ticket_info.len + 1,
			sizeof(**ret_creds));

    if (*ret_creds == NULL) {
	ret = ENOMEM;
	krb5_set_error_message(context, ret,
			       N_("malloc: out of memory", ""));
	goto out;
    }

    for (i = 0; i < enc_krb_cred_part.ticket_info.len; ++i) {
	KrbCredInfo *kci = &enc_krb_cred_part.ticket_info.val[i];
	krb5_creds *creds;

	creds = calloc(1, sizeof(*creds));
	if(creds == NULL) {
	    ret = ENOMEM;
	    krb5_set_error_message(context, ret,
				   N_("malloc: out of memory", ""));
	    goto out;
	}

	ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length,
			   &cred.tickets.val[i], &len, ret);
	if (ret) {
	    free(creds);
	    goto out;
	}
	if(creds->ticket.length != len)
	    krb5_abortx(context, "internal error in ASN.1 encoder");
	copy_EncryptionKey (&kci->key, &creds->session);
	if (kci->prealm && kci->pname)
	    _krb5_principalname2krb5_principal (context,
						&creds->client,
						*kci->pname,
						*kci->prealm);
	if (kci->flags)
	    creds->flags.b = *kci->flags;
	if (kci->authtime)
	    creds->times.authtime = *kci->authtime;
	if (kci->starttime)
	    creds->times.starttime = *kci->starttime;
	if (kci->endtime)
	    creds->times.endtime = *kci->endtime;
	if (kci->renew_till)
	    creds->times.renew_till = *kci->renew_till;
	if (kci->srealm && kci->sname)
	    _krb5_principalname2krb5_principal (context,
						&creds->server,
						*kci->sname,
						*kci->srealm);
	if (kci->caddr)
	    krb5_copy_addresses (context,
				 kci->caddr,
				 &creds->addresses);
	
	(*ret_creds)[i] = creds;
	
    }
    (*ret_creds)[i] = NULL;

    free_KRB_CRED (&cred);
    free_EncKrbCredPart(&enc_krb_cred_part);

    return 0;

  out:
    free_EncKrbCredPart(&enc_krb_cred_part);
    free_KRB_CRED (&cred);
    if(*ret_creds) {
	for(i = 0; (*ret_creds)[i]; i++)
	    krb5_free_creds(context, (*ret_creds)[i]);
	free(*ret_creds);
	*ret_creds = NULL;
    }
    return ret;
}
Exemplo n.º 30
0
static krb5_error_code
check_KRB5SignedPath(krb5_context context,
		     krb5_kdc_configuration *config,
		     hdb_entry_ex *krbtgt,
		     EncTicketPart *tkt,
		     KRB5SignedPathPrincipals **delegated,
		     int require_signedpath)
{
    krb5_error_code ret;
    krb5_data data;
    krb5_crypto crypto = NULL;

    *delegated = NULL;

    ret = find_KRB5SignedPath(context, tkt->authorization_data, &data);
    if (ret == 0) {
	KRB5SignedPathData spd;
	KRB5SignedPath sp;
	AuthorizationData *ad;
	size_t size;

	ret = decode_KRB5SignedPath(data.data, data.length, &sp, NULL);
	krb5_data_free(&data);
	if (ret)
	    return ret;

	spd.encticket = *tkt;
	/* the KRB5SignedPath is the last entry */
	ad = spd.encticket.authorization_data;
	if (--ad->len == 0)
	    spd.encticket.authorization_data = NULL;
	spd.delegated = sp.delegated;

	ASN1_MALLOC_ENCODE(KRB5SignedPathData, data.data, data.length,
			   &spd, &size, ret);
	ad->len++;
	spd.encticket.authorization_data = ad;
	if (ret) {
	    free_KRB5SignedPath(&sp);
	    return ret;
	}
	if (data.length != size)
	    krb5_abortx(context, "internal asn.1 encoder error");

	{
	    Key *key;
	    ret = hdb_enctype2key(context, &krbtgt->entry, sp.etype, &key);
	    if (ret == 0)
		ret = krb5_crypto_init(context, &key->key, 0, &crypto);
	    if (ret) {
		free(data.data);
		free_KRB5SignedPath(&sp);
		return ret;
	    }
	}
	ret = krb5_verify_checksum(context, crypto, KRB5_KU_KRB5SIGNEDPATH, 
				   data.data, data.length, 
				   &sp.cksum);
	krb5_crypto_destroy(context, crypto);
	free(data.data);
	if (ret) {
	    free_KRB5SignedPath(&sp);
	    return ret;
	}

	if (sp.delegated) {

	    *delegated = malloc(sizeof(*sp.delegated));
	    if (*delegated == NULL) {
		free_KRB5SignedPath(&sp);
		return ENOMEM;
	    }

	    ret = copy_KRB5SignedPathPrincipals(*delegated, sp.delegated);
	    if (ret) {
		free_KRB5SignedPath(&sp);
		free(*delegated);
		*delegated = NULL;
		return ret;
	    }
	}
	free_KRB5SignedPath(&sp);
	
    } else {
	if (require_signedpath)
	    return KRB5KDC_ERR_BADOPTION;
    }

    return 0;
}