version 1.83, 2010/02/26 20:29:54 |
version 1.84, 2010/03/03 01:44:36 |
|
|
cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen) |
cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen) |
{ |
{ |
u_char *principals, *constraints, *sig_key, *sig; |
u_char *principals, *constraints, *sig_key, *sig; |
u_int signed_len, plen, clen, sklen, slen; |
u_int signed_len, plen, clen, sklen, slen, kidlen; |
Buffer tmp; |
Buffer tmp; |
char *principal; |
char *principal; |
int ret = -1; |
int ret = -1; |
|
|
|
|
principals = constraints = sig_key = sig = NULL; |
principals = constraints = sig_key = sig = NULL; |
if (buffer_get_int_ret(&key->cert->type, b) != 0 || |
if (buffer_get_int_ret(&key->cert->type, b) != 0 || |
(key->cert->key_id = buffer_get_string_ret(b, NULL)) == NULL || |
(key->cert->key_id = buffer_get_string_ret(b, &kidlen)) == NULL || |
(principals = buffer_get_string_ret(b, &plen)) == NULL || |
(principals = buffer_get_string_ret(b, &plen)) == NULL || |
buffer_get_int64_ret(&key->cert->valid_after, b) != 0 || |
buffer_get_int64_ret(&key->cert->valid_after, b) != 0 || |
buffer_get_int64_ret(&key->cert->valid_before, b) != 0 || |
buffer_get_int64_ret(&key->cert->valid_before, b) != 0 || |
|
|
goto out; |
goto out; |
} |
} |
|
|
|
if (kidlen != strlen(key->cert->key_id)) { |
|
error("%s: key ID contains \\0 character", __func__); |
|
goto out; |
|
} |
|
|
/* Signature is left in the buffer so we can calculate this length */ |
/* Signature is left in the buffer so we can calculate this length */ |
signed_len = buffer_len(&key->cert->certblob) - buffer_len(b); |
signed_len = buffer_len(&key->cert->certblob) - buffer_len(b); |
|
|
|
|
buffer_append(&tmp, principals, plen); |
buffer_append(&tmp, principals, plen); |
while (buffer_len(&tmp) > 0) { |
while (buffer_len(&tmp) > 0) { |
if (key->cert->nprincipals >= CERT_MAX_PRINCIPALS) { |
if (key->cert->nprincipals >= CERT_MAX_PRINCIPALS) { |
error("Too many principals"); |
error("%s: Too many principals", __func__); |
goto out; |
goto out; |
} |
} |
if ((principal = buffer_get_string_ret(&tmp, NULL)) == NULL) { |
if ((principal = buffer_get_string_ret(&tmp, &plen)) == NULL) { |
error("Principals data invalid"); |
error("%s: Principals data invalid", __func__); |
goto out; |
goto out; |
} |
} |
|
if (strlen(principal) != plen) { |
|
error("%s: Principal contains \\0 character", |
|
__func__); |
|
goto out; |
|
} |
key->cert->principals = xrealloc(key->cert->principals, |
key->cert->principals = xrealloc(key->cert->principals, |
key->cert->nprincipals + 1, sizeof(*key->cert->principals)); |
key->cert->nprincipals + 1, sizeof(*key->cert->principals)); |
key->cert->principals[key->cert->nprincipals++] = principal; |
key->cert->principals[key->cert->nprincipals++] = principal; |
|
|
while (buffer_len(&tmp) != 0) { |
while (buffer_len(&tmp) != 0) { |
if (buffer_get_string_ptr(&tmp, NULL) == NULL || |
if (buffer_get_string_ptr(&tmp, NULL) == NULL || |
buffer_get_string_ptr(&tmp, NULL) == NULL) { |
buffer_get_string_ptr(&tmp, NULL) == NULL) { |
error("Constraints data invalid"); |
error("%s: Constraints data invalid", __func__); |
goto out; |
goto out; |
} |
} |
} |
} |
|
|
|
|
if ((key->cert->signature_key = key_from_blob(sig_key, |
if ((key->cert->signature_key = key_from_blob(sig_key, |
sklen)) == NULL) { |
sklen)) == NULL) { |
error("Signature key invalid"); |
error("%s: Signature key invalid", __func__); |
goto out; |
goto out; |
} |
} |
if (key->cert->signature_key->type != KEY_RSA && |
if (key->cert->signature_key->type != KEY_RSA && |
key->cert->signature_key->type != KEY_DSA) { |
key->cert->signature_key->type != KEY_DSA) { |
error("Invalid signature key type %s (%d)", |
error("%s: Invalid signature key type %s (%d)", __func__, |
key_type(key->cert->signature_key), |
key_type(key->cert->signature_key), |
key->cert->signature_key->type); |
key->cert->signature_key->type); |
goto out; |
goto out; |
|
|
switch (key_verify(key->cert->signature_key, sig, slen, |
switch (key_verify(key->cert->signature_key, sig, slen, |
buffer_ptr(&key->cert->certblob), signed_len)) { |
buffer_ptr(&key->cert->certblob), signed_len)) { |
case 1: |
case 1: |
|
ret = 0; |
break; /* Good signature */ |
break; /* Good signature */ |
case 0: |
case 0: |
error("Invalid signature on certificate"); |
error("%s: Invalid signature on certificate", __func__); |
goto out; |
goto out; |
case -1: |
case -1: |
error("Certificate signature verification failed"); |
error("%s: Certificate signature verification failed", |
|
__func__); |
goto out; |
goto out; |
} |
} |
|
|
ret = 0; |
|
|
|
out: |
out: |
buffer_free(&tmp); |
buffer_free(&tmp); |