示例#1
0
文件: rd_req.c 项目: Sp1l/heimdal
static krb5_error_code
check_transited(krb5_context context, Ticket *ticket, EncTicketPart *enc)
{
    char **realms;
    unsigned int num_realms, n;
    krb5_error_code ret;

    /*
     * Windows 2000 and 2003 uses this inside their TGT so it's normaly
     * not seen by others, however, samba4 joined with a Windows AD as
     * a Domain Controller gets exposed to this.
     */
    if(enc->transited.tr_type == 0 && enc->transited.contents.length == 0)
	return 0;

    if(enc->transited.tr_type != DOMAIN_X500_COMPRESS)
	return KRB5KDC_ERR_TRTYPE_NOSUPP;

    if(enc->transited.contents.length == 0)
	return 0;

    ret = krb5_domain_x500_decode(context, enc->transited.contents,
				  &realms, &num_realms,
				  enc->crealm,
				  ticket->realm);
    if(ret)
	return ret;
    ret = krb5_check_transited(context, enc->crealm,
			       ticket->realm,
			       realms, num_realms, NULL);
    for (n = 0; n < num_realms; n++)
	free(realms[n]);
    free(realms);
    return ret;
}
示例#2
0
static krb5_error_code
fix_transited_encoding(krb5_context context, 
		       krb5_kdc_configuration *config,
		       krb5_boolean check_policy,
		       const TransitedEncoding *tr, 
		       EncTicketPart *et, 
		       const char *client_realm, 
		       const char *server_realm, 
		       const char *tgt_realm)
{
    krb5_error_code ret = 0;
    char **realms, **tmp;
    int num_realms;
    int i;

    switch (tr->tr_type) {
    case DOMAIN_X500_COMPRESS:
	break;
    case 0:
	/*
	 * Allow empty content of type 0 because that is was Microsoft
	 * generates in their TGT.
	 */
	if (tr->contents.length == 0)
	    break;
	kdc_log(context, config, 0,
		"Transited type 0 with non empty content");
	return KRB5KDC_ERR_TRTYPE_NOSUPP;
    default:
	kdc_log(context, config, 0,
		"Unknown transited type: %u", tr->tr_type);
	return KRB5KDC_ERR_TRTYPE_NOSUPP;
    }

    ret = krb5_domain_x500_decode(context, 
				  tr->contents,
				  &realms, 
				  &num_realms,
				  client_realm,
				  server_realm);
    if(ret){
	krb5_warn(context, ret,
		  "Decoding transited encoding");
	return ret;
    }
    if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)) {
	/* not us, so add the previous realm to transited set */
	if (num_realms < 0 || num_realms + 1 > UINT_MAX/sizeof(*realms)) {
	    ret = ERANGE;
	    goto free_realms;
	}
	tmp = realloc(realms, (num_realms + 1) * sizeof(*realms));
	if(tmp == NULL){
	    ret = ENOMEM;
	    goto free_realms;
	}
	realms = tmp;
	realms[num_realms] = strdup(tgt_realm);
	if(realms[num_realms] == NULL){
	    ret = ENOMEM;
	    goto free_realms;
	}
	num_realms++;
    }
    if(num_realms == 0) {
	if(strcmp(client_realm, server_realm)) 
	    kdc_log(context, config, 0,
		    "cross-realm %s -> %s", client_realm, server_realm);
    } else {
	size_t l = 0;
	char *rs;
	for(i = 0; i < num_realms; i++)
	    l += strlen(realms[i]) + 2;
	rs = malloc(l);
	if(rs != NULL) {
	    *rs = '\0';
	    for(i = 0; i < num_realms; i++) {
		if(i > 0)
		    strlcat(rs, ", ", l);
		strlcat(rs, realms[i], l);
	    }
	    kdc_log(context, config, 0,
		    "cross-realm %s -> %s via [%s]",
		    client_realm, server_realm, rs);
	    free(rs);
	}
    }
    if(check_policy) {
	ret = krb5_check_transited(context, client_realm, 
				   server_realm, 
				   realms, num_realms, NULL);
	if(ret) {
	    krb5_warn(context, ret, "cross-realm %s -> %s", 
		      client_realm, server_realm);
	    goto free_realms;
	}
	et->flags.transited_policy_checked = 1;
    }
    et->transited.tr_type = DOMAIN_X500_COMPRESS;
    ret = krb5_domain_x500_encode(realms, num_realms, &et->transited.contents);
    if(ret)
	krb5_warn(context, ret, "Encoding transited encoding");
  free_realms:
    for(i = 0; i < num_realms; i++)
	free(realms[i]);
    free(realms);
    return ret;
}