Пример #1
0
static struct pa_info_data *
pa_etype_info(krb5_context context,
	      const krb5_principal client,
	      const AS_REQ *asreq,
	      struct pa_info_data *paid,
	      heim_octet_string *data)
{
    krb5_error_code ret;
    ETYPE_INFO e;
    size_t sz;
    int i, j;

    memset(&e, 0, sizeof(e));
    ret = decode_ETYPE_INFO(data->data, data->length, &e, &sz);
    if (ret)
	goto out;
    if (e.len == 0)
	goto out;
    for (j = 0; j < asreq->req_body.etype.len; j++) {
	for (i = 0; i < e.len; i++) {
	    if (asreq->req_body.etype.val[j] == e.val[i].etype) {
		krb5_salt salt;
		salt.salttype = KRB5_PW_SALT;
		if (e.val[i].salt == NULL)
		    ret = krb5_get_pw_salt(context, client, &salt);
		else {
		    salt.saltvalue = *e.val[i].salt;
		    ret = 0;
		}
		if (e.val[i].salttype)
		    salt.salttype = *e.val[i].salttype;
		if (ret == 0) {
		    ret = set_paid(paid, context, e.val[i].etype,
				   salt.salttype,
				   salt.saltvalue.data,
				   salt.saltvalue.length,
				   NULL);
		    if (e.val[i].salt == NULL)
			krb5_free_salt(context, salt);
		}
		if (ret == 0) {
		    free_ETYPE_INFO(&e);
		    return paid;
		}
	    }
	}
    }
 out:
    free_ETYPE_INFO(&e);
    return NULL;
}
Пример #2
0
int
decode_ETYPE_INFO(const unsigned char *p, size_t len, ETYPE_INFO *data, size_t *size)
{
size_t ret = 0, reallen;
size_t l;
int e;

memset(data, 0, sizeof(*data));
reallen = 0;
e = der_match_tag_and_length (p, len, ASN1_C_UNIV, CONS, UT_Sequence,&reallen, &l);
FORW;
if(len < reallen)
return ASN1_OVERRUN;
len = reallen;
{
size_t origlen = len;
int oldret = ret;
ret = 0;
(data)->len = 0;
(data)->val = NULL;
while(ret < origlen) {
(data)->len++;
(data)->val = realloc((data)->val, sizeof(*((data)->val)) * (data)->len);
e = decode_ETYPE_INFO_ENTRY(p, len, &(data)->val[(data)->len-1], &l);
FORW;
len = origlen - ret;
}
ret += oldret;
}
if(size) *size = ret;
return 0;
fail:
free_ETYPE_INFO(data);
return e;
}
Пример #3
0
static krb5_error_code
get_pa_etype_info(krb5_context context,
		  krb5_kdc_configuration *config,
		  METHOD_DATA *md, Key *ckey)
{
    krb5_error_code ret = 0;
    ETYPE_INFO pa;
    unsigned char *buf;
    size_t len;


    pa.len = 1;
    pa.val = calloc(1, sizeof(pa.val[0]));
    if(pa.val == NULL)
	return ENOMEM;

    ret = make_etype_info_entry(context, &pa.val[0], ckey);
    if (ret) {
	free_ETYPE_INFO(&pa);
	return ret;
    }

    ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret);
    free_ETYPE_INFO(&pa);
    if(ret)
	return ret;
    ret = realloc_method_data(md);
    if(ret) {
	free(buf);
	return ret;
    }
    md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO;
    md->val[md->len - 1].padata_value.length = len;
    md->val[md->len - 1].padata_value.data = buf;
    return 0;
}
Пример #4
0
static krb5_error_code
get_pa_etype_info(krb5_context context, 
		  krb5_kdc_configuration *config,
		  METHOD_DATA *md, hdb_entry *client, 
		  ENCTYPE *etypes, unsigned int etypes_len)
{
    krb5_error_code ret = 0;
    int i, j;
    unsigned int n = 0;
    ETYPE_INFO pa;
    unsigned char *buf;
    size_t len;
    

    pa.len = client->keys.len;
    if(pa.len > UINT_MAX/sizeof(*pa.val))
	return ERANGE;
    pa.val = malloc(pa.len * sizeof(*pa.val));
    if(pa.val == NULL)
	return ENOMEM;
    memset(pa.val, 0, pa.len * sizeof(*pa.val));

    for(i = 0; i < client->keys.len; i++) {
	for (j = 0; j < n; j++)
	    if (pa.val[j].etype == client->keys.val[i].key.keytype)
		goto skip1;
	for(j = 0; j < etypes_len; j++) {
	    if(client->keys.val[i].key.keytype == etypes[j]) {
 		if (krb5_enctype_valid(context, etypes[j]) != 0)
 		    continue;
		if (!older_enctype(etypes[j]))
 		    continue;
		if (n >= pa.len)
		    krb5_abortx(context, "internal error: n >= p.len");
		if((ret = make_etype_info_entry(context, 
						&pa.val[n++], 
						&client->keys.val[i])) != 0) {
		    free_ETYPE_INFO(&pa);
		    return ret;
		}
		break;
	    }
	}
    skip1:;
    }
    for(i = 0; i < client->keys.len; i++) {
	/* already added? */
	for(j = 0; j < etypes_len; j++) {
	    if(client->keys.val[i].key.keytype == etypes[j])
		goto skip2;
	}
	if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0)
	    continue;
	if (!older_enctype(etypes[j]))
	    continue;
	if (n >= pa.len)
	    krb5_abortx(context, "internal error: n >= p.len");
	if((ret = make_etype_info_entry(context, 
					&pa.val[n++], 
					&client->keys.val[i])) != 0) {
	    free_ETYPE_INFO(&pa);
	    return ret;
	}
    skip2:;
    }
    
    if(n < pa.len) {
	/* stripped out dups, newer enctypes, and not valid enctypes */
 	pa.len = n;
    }

    ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret);
    free_ETYPE_INFO(&pa);
    if(ret)
	return ret;
    ret = realloc_method_data(md);
    if(ret) {
	free(buf);
	return ret;
    }
    md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO;
    md->val[md->len - 1].padata_value.length = len;
    md->val[md->len - 1].padata_value.data = buf;
    return 0;
}
Пример #5
0
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_in_cred(krb5_context context,
		 krb5_flags options,
		 const krb5_addresses *addrs,
		 const krb5_enctype *etypes,
		 const krb5_preauthtype *ptypes,
		 const krb5_preauthdata *preauth,
		 krb5_key_proc key_proc,
		 krb5_const_pointer keyseed,
		 krb5_decrypt_proc decrypt_proc,
		 krb5_const_pointer decryptarg,
		 krb5_creds *creds,
		 krb5_kdc_rep *ret_as_reply)
{
    krb5_error_code ret;
    AS_REQ a;
    krb5_kdc_rep rep;
    krb5_data req, resp;
    size_t len;
    krb5_salt salt;
    krb5_keyblock *key;
    size_t size;
    KDCOptions opts;
    PA_DATA *pa;
    krb5_enctype etype;
    krb5_preauthdata *my_preauth = NULL;
    unsigned nonce;
    int done;

    opts = int2KDCOptions(options);

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

    do {
	done = 1;
	ret = init_as_req (context,
			   opts,
			   creds,
			   addrs,
			   etypes,
			   ptypes,
			   preauth,
			   key_proc,
			   keyseed,
			   nonce,
			   &a);
	if (my_preauth) {
	    free_ETYPE_INFO(&my_preauth->val[0].info);
	    free (my_preauth->val);
	    my_preauth = NULL;
	}
	if (ret)
	    return ret;

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

	ret = krb5_sendto_kdc (context, &req, &creds->client->realm, &resp);
	krb5_data_free(&req);
	if (ret)
	    return ret;

	memset (&rep, 0, sizeof(rep));
	ret = decode_AS_REP(resp.data, resp.length, &rep.kdc_rep, &size);
	if(ret) {
	    /* let's try to parse it as a KRB-ERROR */
	    KRB_ERROR error;
	    int ret2;

	    ret2 = krb5_rd_error(context, &resp, &error);
	    if(ret2 && resp.data && ((char*)resp.data)[0] == 4)
		ret = KRB5KRB_AP_ERR_V4_REPLY;
	    krb5_data_free(&resp);
	    if (ret2 == 0) {
		ret = krb5_error_from_rd_error(context, &error, creds);
		/* if no preauth was set and KDC requires it, give it
                   one more try */
		if (!ptypes && !preauth
		    && ret == KRB5KDC_ERR_PREAUTH_REQUIRED
#if 0
			|| ret == KRB5KDC_ERR_BADOPTION
#endif
		    && set_ptypes(context, &error, &ptypes, &my_preauth)) {
		    done = 0;
		    preauth = my_preauth;
		    krb5_free_error_contents(context, &error);
		    krb5_clear_error_string(context);
		    continue;
		}
		if(ret_as_reply)
		    ret_as_reply->error = error;
		else
		    free_KRB_ERROR (&error);
		return ret;
	    }
	    return ret;
	}
	krb5_data_free(&resp);
    } while(!done);
    
    pa = NULL;
    etype = rep.kdc_rep.enc_part.etype;
    if(rep.kdc_rep.padata){
	int i = 0;
	pa = krb5_find_padata(rep.kdc_rep.padata->val, rep.kdc_rep.padata->len, 
			      KRB5_PADATA_PW_SALT, &i);
	if(pa == NULL) {
	    i = 0;
	    pa = krb5_find_padata(rep.kdc_rep.padata->val, 
				  rep.kdc_rep.padata->len, 
				  KRB5_PADATA_AFS3_SALT, &i);
	}
    }
    if(pa) {
	salt.salttype = pa->padata_type;
	salt.saltvalue = pa->padata_value;
	
	ret = (*key_proc)(context, etype, salt, keyseed, &key);
    } else {
	/* make a v5 salted pa-data */
	ret = krb5_get_pw_salt (context, creds->client, &salt);
	
	if (ret)
	    goto out;
	ret = (*key_proc)(context, etype, salt, keyseed, &key);
	krb5_free_salt(context, salt);
    }
    if (ret)
	goto out;
	
    {
	unsigned flags = 0;
	if (opts.request_anonymous)
	    flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH;

	ret = _krb5_extract_ticket(context, 
				   &rep, 
				   creds, 
				   key, 
				   keyseed, 
				   KRB5_KU_AS_REP_ENC_PART,
				   NULL, 
				   nonce, 
				   flags,
				   decrypt_proc, 
				   decryptarg);
    }
    memset (key->keyvalue.data, 0, key->keyvalue.length);
    krb5_free_keyblock_contents (context, key);
    free (key);

out:
    if (ret == 0 && ret_as_reply)
	*ret_as_reply = rep;
    else
	krb5_free_kdc_rep (context, &rep);
    return ret;
}