Esempio n. 1
0
static krb5_error_code
decode_creds(krb5_context context, const void *data, size_t length,
	     krb5_creds *creds)
{
    krb5_error_code ret;
    krb5_storage *sp;

    sp = krb5_storage_from_readonly_mem(data, length);
    if (sp == NULL)
	return krb5_enomem(context);

    ret = krb5_ret_creds(sp, creds);
    krb5_storage_free(sp);
    if (ret) {
	krb5_set_error_message(context, ret,
			       N_("Failed to read credential in scache", ""));
	return ret;
    }
    return 0;
}
Esempio n. 2
0
static krb5_error_code KRB5_CALLCONV
xcc_get_next (krb5_context context,
	      krb5_ccache id,
	      krb5_cc_cursor *cursor,
	      krb5_creds *creds)
{
    struct xcc_cursor *c = *cursor;
    krb5_error_code ret;
    krb5_storage *sp;
    HeimCredRef cred;
    CFDataRef data;

    if (c->array == NULL)
	return KRB5_CC_END;

 next:
    if (c->offset >= CFArrayGetCount(c->array))
	return KRB5_CC_END;
    
    cred = (HeimCredRef)CFArrayGetValueAtIndex(c->array, c->offset++);
    if (cred == NULL)
	return KRB5_CC_END;
    
    data = HeimCredCopyAttribute(cred, kHEIMAttrData);
    if (data == NULL) {
	goto next;
    }
    
    sp = krb5_storage_from_readonly_mem(CFDataGetBytePtr(data), CFDataGetLength(data));
    if (sp == NULL) {
	CFRELEASE_NULL(data);
	return KRB5_CC_END;
    }
    
    ret = krb5_ret_creds(sp, creds);
    krb5_storage_free(sp);
    CFRELEASE_NULL(data);
    
    return ret;
}
Esempio n. 3
0
static krb5_error_code
verify_logonname(krb5_context context,
		 const struct PAC_INFO_BUFFER *logon_name,
		 const krb5_data *data,
		 time_t authtime,
		 krb5_const_principal principal)
{
    krb5_error_code ret;
    krb5_principal p2;
    uint32_t time1, time2;
    krb5_storage *sp;
    uint16_t len;
    char *s;

    sp = krb5_storage_from_readonly_mem((const char *)data->data + logon_name->offset_lo,
					logon_name->buffersize);
    if (sp == NULL)
	return krb5_enomem(context);

    krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE);

    CHECK(ret, krb5_ret_uint32(sp, &time1), out);
    CHECK(ret, krb5_ret_uint32(sp, &time2), out);

    {
	uint64_t t1, t2;
	t1 = unix2nttime(authtime);
	t2 = ((uint64_t)time2 << 32) | time1;
	if (t1 != t2) {
	    krb5_storage_free(sp);
	    krb5_set_error_message(context, EINVAL, "PAC timestamp mismatch");
	    return EINVAL;
	}
    }
    CHECK(ret, krb5_ret_uint16(sp, &len), out);
    if (len == 0) {
	krb5_storage_free(sp);
	krb5_set_error_message(context, EINVAL, "PAC logon name length missing");
	return EINVAL;
    }

    s = malloc(len);
    if (s == NULL) {
	krb5_storage_free(sp);
	return krb5_enomem(context);
    }
    ret = krb5_storage_read(sp, s, len);
    if (ret != len) {
	krb5_storage_free(sp);
	krb5_set_error_message(context, EINVAL, "Failed to read PAC logon name");
	return EINVAL;
    }
    krb5_storage_free(sp);
    {
	size_t ucs2len = len / 2;
	uint16_t *ucs2;
	size_t u8len;
	unsigned int flags = WIND_RW_LE;

	ucs2 = malloc(sizeof(ucs2[0]) * ucs2len);
	if (ucs2 == NULL)
	    return krb5_enomem(context);

	ret = wind_ucs2read(s, len, &flags, ucs2, &ucs2len);
	free(s);
	if (ret) {
	    free(ucs2);
	    krb5_set_error_message(context, ret, "Failed to convert string to UCS-2");
	    return ret;
	}
	ret = wind_ucs2utf8_length(ucs2, ucs2len, &u8len);
	if (ret) {
	    free(ucs2);
	    krb5_set_error_message(context, ret, "Failed to count length of UCS-2 string");
	    return ret;
	}
	u8len += 1; /* Add space for NUL */
	s = malloc(u8len);
	if (s == NULL) {
	    free(ucs2);
	    return krb5_enomem(context);
	}
	ret = wind_ucs2utf8(ucs2, ucs2len, s, &u8len);
	free(ucs2);
	if (ret) {
	    free(s);
	    krb5_set_error_message(context, ret, "Failed to convert to UTF-8");
	    return ret;
	}
    }
    ret = krb5_parse_name_flags(context, s, KRB5_PRINCIPAL_PARSE_NO_REALM, &p2);
    free(s);
    if (ret)
	return ret;

    if (krb5_principal_compare_any_realm(context, principal, p2) != TRUE) {
	ret = EINVAL;
	krb5_set_error_message(context, ret, "PAC logon name mismatch");
    }
    krb5_free_principal(context, p2);
    return ret;
out:
    return ret;
}
Esempio n. 4
0
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_pac_parse(krb5_context context, const void *ptr, size_t len,
	       krb5_pac *pac)
{
    krb5_error_code ret;
    krb5_pac p;
    krb5_storage *sp = NULL;
    uint32_t i, tmp, tmp2, header_end;

    p = calloc(1, sizeof(*p));
    if (p == NULL) {
	ret = krb5_enomem(context);
	goto out;
    }

    sp = krb5_storage_from_readonly_mem(ptr, len);
    if (sp == NULL) {
	ret = krb5_enomem(context);
	goto out;
    }
    krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE);

    CHECK(ret, krb5_ret_uint32(sp, &tmp), out);
    CHECK(ret, krb5_ret_uint32(sp, &tmp2), out);
    if (tmp < 1) {
	ret = EINVAL; /* Too few buffers */
	krb5_set_error_message(context, ret, N_("PAC have too few buffer", ""));
	goto out;
    }
    if (tmp2 != 0) {
	ret = EINVAL; /* Wrong version */
	krb5_set_error_message(context, ret,
			       N_("PAC have wrong version %d", ""),
			       (int)tmp2);
	goto out;
    }

    p->pac = calloc(1,
		    sizeof(*p->pac) + (sizeof(p->pac->buffers[0]) * (tmp - 1)));
    if (p->pac == NULL) {
	ret = krb5_enomem(context);
	goto out;
    }

    p->pac->numbuffers = tmp;
    p->pac->version = tmp2;

    header_end = PACTYPE_SIZE + (PAC_INFO_BUFFER_SIZE * p->pac->numbuffers);
    if (header_end > len) {
	ret = EINVAL;
	goto out;
    }

    for (i = 0; i < p->pac->numbuffers; i++) {
	CHECK(ret, krb5_ret_uint32(sp, &p->pac->buffers[i].type), out);
	CHECK(ret, krb5_ret_uint32(sp, &p->pac->buffers[i].buffersize), out);
	CHECK(ret, krb5_ret_uint32(sp, &p->pac->buffers[i].offset_lo), out);
	CHECK(ret, krb5_ret_uint32(sp, &p->pac->buffers[i].offset_hi), out);

	/* consistency checks */
	if (p->pac->buffers[i].offset_lo & (PAC_ALIGNMENT - 1)) {
	    ret = EINVAL;
	    krb5_set_error_message(context, ret,
				   N_("PAC out of allignment", ""));
	    goto out;
	}
	if (p->pac->buffers[i].offset_hi) {
	    ret = EINVAL;
	    krb5_set_error_message(context, ret,
				   N_("PAC high offset set", ""));
	    goto out;
	}
	if (p->pac->buffers[i].offset_lo > len) {
	    ret = EINVAL;
	    krb5_set_error_message(context, ret,
				   N_("PAC offset off end", ""));
	    goto out;
	}
	if (p->pac->buffers[i].offset_lo < header_end) {
	    ret = EINVAL;
	    krb5_set_error_message(context, ret,
				   N_("PAC offset inside header: %lu %lu", ""),
				   (unsigned long)p->pac->buffers[i].offset_lo,
				   (unsigned long)header_end);
	    goto out;
	}
	if (p->pac->buffers[i].buffersize > len - p->pac->buffers[i].offset_lo){
	    ret = EINVAL;
	    krb5_set_error_message(context, ret, N_("PAC length off end", ""));
	    goto out;
	}

	/* let save pointer to data we need later */
	if (p->pac->buffers[i].type == PAC_SERVER_CHECKSUM) {
	    if (p->server_checksum) {
		ret = EINVAL;
		krb5_set_error_message(context, ret,
				       N_("PAC have two server checksums", ""));
		goto out;
	    }
	    p->server_checksum = &p->pac->buffers[i];
	} else if (p->pac->buffers[i].type == PAC_PRIVSVR_CHECKSUM) {
	    if (p->privsvr_checksum) {
		ret = EINVAL;
		krb5_set_error_message(context, ret,
				       N_("PAC have two KDC checksums", ""));
		goto out;
	    }
	    p->privsvr_checksum = &p->pac->buffers[i];
	} else if (p->pac->buffers[i].type == PAC_LOGON_NAME) {
	    if (p->logon_name) {
		ret = EINVAL;
		krb5_set_error_message(context, ret,
				       N_("PAC have two logon names", ""));
		goto out;
	    }
	    p->logon_name = &p->pac->buffers[i];
	}
    }

    ret = krb5_data_copy(&p->data, ptr, len);
    if (ret)
	goto out;

    krb5_storage_free(sp);

    *pac = p;
    return 0;

out:
    if (sp)
	krb5_storage_free(sp);
    if (p) {
	if (p->pac)
	    free(p->pac);
	free(p);
    }
    *pac = NULL;

    return ret;
}
Esempio n. 5
0
File: pac.c Progetto: InvLim/heimdal
static krb5_error_code
verify_logonname(krb5_context context,
		 const struct PAC_INFO_BUFFER *logon_name,
		 const krb5_data *data,
		 time_t authtime,
		 krb5_const_principal principal)
{
    krb5_error_code ret;
    uint32_t time1, time2;
    krb5_storage *sp;
    uint16_t len;
    char *s = NULL;
    char *principal_string = NULL;
    char *logon_string = NULL;

    sp = krb5_storage_from_readonly_mem((const char *)data->data + logon_name->offset_lo,
					logon_name->buffersize);
    if (sp == NULL)
	return krb5_enomem(context);

    krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE);

    CHECK(ret, krb5_ret_uint32(sp, &time1), out);
    CHECK(ret, krb5_ret_uint32(sp, &time2), out);

    {
	uint64_t t1, t2;
	t1 = unix2nttime(authtime);
	t2 = ((uint64_t)time2 << 32) | time1;
	/*
	 * When neither the ticket nor the PAC set an explicit authtime,
	 * both times are zero, but relative to different time scales.
	 * So we must compare "not set" values without converting to a
	 * common time reference.
         */
	if (t1 != t2 && (t2 != 0 && authtime != 0)) {
	    krb5_storage_free(sp);
	    krb5_set_error_message(context, EINVAL, "PAC timestamp mismatch");
	    return EINVAL;
	}
    }
    CHECK(ret, krb5_ret_uint16(sp, &len), out);
    if (len == 0) {
	krb5_storage_free(sp);
	krb5_set_error_message(context, EINVAL, "PAC logon name length missing");
	return EINVAL;
    }

    s = malloc(len);
    if (s == NULL) {
	krb5_storage_free(sp);
	return krb5_enomem(context);
    }
    ret = krb5_storage_read(sp, s, len);
    if (ret != len) {
	krb5_storage_free(sp);
	krb5_set_error_message(context, EINVAL, "Failed to read PAC logon name");
	return EINVAL;
    }
    krb5_storage_free(sp);
    {
	size_t ucs2len = len / 2;
	uint16_t *ucs2;
	size_t u8len;
	unsigned int flags = WIND_RW_LE;

	ucs2 = malloc(sizeof(ucs2[0]) * ucs2len);
	if (ucs2 == NULL)
	    return krb5_enomem(context);

	ret = wind_ucs2read(s, len, &flags, ucs2, &ucs2len);
	free(s);
	if (ret) {
	    free(ucs2);
	    krb5_set_error_message(context, ret, "Failed to convert string to UCS-2");
	    return ret;
	}
	ret = wind_ucs2utf8_length(ucs2, ucs2len, &u8len);
	if (ret) {
	    free(ucs2);
	    krb5_set_error_message(context, ret, "Failed to count length of UCS-2 string");
	    return ret;
	}
	u8len += 1; /* Add space for NUL */
	logon_string = malloc(u8len);
	if (logon_string == NULL) {
	    free(ucs2);
	    return krb5_enomem(context);
	}
	ret = wind_ucs2utf8(ucs2, ucs2len, logon_string, &u8len);
	free(ucs2);
	if (ret) {
	    free(logon_string);
	    krb5_set_error_message(context, ret, "Failed to convert to UTF-8");
	    return ret;
	}
    }
    ret = krb5_unparse_name_flags(context, principal,
				  KRB5_PRINCIPAL_UNPARSE_NO_REALM |
				  KRB5_PRINCIPAL_UNPARSE_DISPLAY,
				  &principal_string);
    if (ret) {
	free(logon_string);
	return ret;
    }

    ret = strcmp(logon_string, principal_string);
    if (ret != 0) {
	ret = EINVAL;
	krb5_set_error_message(context, ret, "PAC logon name [%s] mismatch principal name [%s]",
			       logon_string, principal_string);
    }
    free(logon_string);
    free(principal_string);
    return ret;
out:
    return ret;
}