Skip to content

Commit 84fb8e1

Browse files
committed
add encoder, decoder, and tests for combo-ip
1 parent 4c7bb78 commit 84fb8e1

File tree

6 files changed

+118
-2
lines changed

6 files changed

+118
-2
lines changed

share/dictionary/der/dictionary.common

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ END RDNSequence
3838
END directoryName
3939

4040
ATTRIBUTE uniformResourceIdentifier 6 ia5string option
41+
ATTRIBUTE iPAddress 7 combo-ip option
4142

4243
END GeneralName
4344

src/protocols/der/base.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ static const bool *fr_type_to_der_tags[FR_DER_TAG_MAX] = {
120120
[FR_DER_TAG_BITSTRING] = true,
121121
},
122122

123+
[FR_TYPE_COMBO_IP_ADDR] = (bool [FR_DER_TAG_MAX]) {
124+
[FR_DER_TAG_OCTETSTRING] = true,
125+
},
126+
123127
[FR_TYPE_BOOL] = (bool [FR_DER_TAG_MAX]) {
124128
[FR_DER_TAG_BOOLEAN] = true,
125129
[FR_DER_TAG_INTEGER] = true,
@@ -618,7 +622,6 @@ static bool type_parse(fr_type_t *type_p,fr_dict_attr_t **da_p, char const *name
618622
return false;
619623

620624
case FR_TYPE_IFID:
621-
case FR_TYPE_COMBO_IP_ADDR:
622625
case FR_TYPE_COMBO_IP_PREFIX:
623626
case FR_TYPE_ETHERNET:
624627
case FR_TYPE_FLOAT32:
@@ -714,6 +717,8 @@ static const fr_der_tag_t fr_type_to_der_tag_defaults[FR_TYPE_MAX + 1] = {
714717
[FR_TYPE_IPV6_ADDR] = FR_DER_TAG_BITSTRING,
715718
[FR_TYPE_IPV6_PREFIX] = FR_DER_TAG_BITSTRING,
716719

720+
[FR_TYPE_COMBO_IP_ADDR] = FR_DER_TAG_OCTETSTRING,
721+
717722
[FR_TYPE_BOOL] = FR_DER_TAG_BOOLEAN,
718723

719724
[FR_TYPE_UINT8] = FR_DER_TAG_INTEGER,

src/protocols/der/decode.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -857,6 +857,14 @@ static ssize_t fr_der_decode_sequence(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_d
857857
child = fr_dict_attr_unknown_raw_afrom_num(decode_ctx->tmp_ctx, parent, current_tag);
858858
if (!child) return -1;
859859
}
860+
861+
/*
862+
* Options always have to have the context field set.
863+
*/
864+
if ((tag_byte & DER_TAG_CLASS_MASK) != FR_DER_CLASS_CONTEXT) {
865+
fr_strerror_printf("Tag has unexpected class %20x", tag_byte & DER_TAG_CLASS_MASK);
866+
return -1;
867+
}
860868
}
861869

862870
FR_PROTO_TRACE("decode context %s -> %s", parent->name, child->name);
@@ -1644,6 +1652,53 @@ static ssize_t fr_der_decode_ipv6_prefix(TALLOC_CTX *ctx, fr_pair_list_t *out, f
16441652
return fr_dbuff_set(in, &our_in);
16451653
}
16461654

1655+
static ssize_t fr_der_decode_combo_ip_addr(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent,
1656+
fr_dbuff_t *in, UNUSED fr_der_decode_ctx_t *decode_ctx)
1657+
{
1658+
fr_pair_t *vp;
1659+
fr_dbuff_t our_in = FR_DBUFF(in);
1660+
size_t len = fr_dbuff_remaining(&our_in);
1661+
1662+
/*
1663+
* RFC5280 Section 4.2.1.6
1664+
*
1665+
* When the subjectAltName extension contains an iPAddress, the address
1666+
* MUST be stored in the octet string in "network byte order", as
1667+
* specified in [RFC791]. The least significant bit (LSB) of each octet
1668+
* is the LSB of the corresponding byte in the network address. For IP
1669+
* version 4, as specified in [RFC791], the octet string MUST contain
1670+
* exactly four octets. For IP version 6, as specified in
1671+
* [RFC2460], the octet string MUST contain exactly sixteen octets.
1672+
*/
1673+
if ((len != 4) && (len != 16)) {
1674+
fr_strerror_printf("Invalid combo_ip_addr size. Expected 4 or 16, got %zu",
1675+
len);
1676+
return -1;
1677+
}
1678+
1679+
vp = fr_pair_afrom_da(ctx, parent);
1680+
if (unlikely(!vp)) {
1681+
fr_strerror_const("Out of memory");
1682+
return -1;
1683+
}
1684+
1685+
if (len == 4) {
1686+
vp->vp_ip.af = AF_INET;
1687+
vp->vp_ip.prefix = 32;
1688+
FR_DBUFF_OUT_MEMCPY_RETURN((uint8_t *) &vp->vp_ipv4addr, &our_in, sizeof(vp->vp_ipv4addr));
1689+
1690+
} else {
1691+
vp->vp_ip.af = AF_INET6;
1692+
vp->vp_ip.prefix = 128;
1693+
FR_DBUFF_OUT_MEMCPY_RETURN((uint8_t *) &vp->vp_ipv6addr, &our_in, sizeof(vp->vp_ipv6addr));
1694+
}
1695+
1696+
fr_pair_append(out, vp);
1697+
1698+
return fr_dbuff_set(in, &our_in);
1699+
}
1700+
1701+
16471702
static const fr_der_tag_decode_t tag_funcs[FR_DER_TAG_MAX] = {
16481703
[FR_DER_TAG_BOOLEAN] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_boolean },
16491704
[FR_DER_TAG_INTEGER] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_integer },
@@ -1672,6 +1727,8 @@ static const fr_der_tag_decode_t type_funcs[FR_TYPE_MAX] = {
16721727
[FR_TYPE_IPV4_PREFIX] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_ipv4_prefix },
16731728
[FR_TYPE_IPV6_ADDR] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_ipv6_addr },
16741729
[FR_TYPE_IPV6_PREFIX] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_ipv6_prefix },
1730+
1731+
[FR_TYPE_COMBO_IP_ADDR] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_combo_ip_addr },
16751732
};
16761733

16771734
/** Decode the tag and length fields of a DER encoded structure

src/protocols/der/encode.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,36 @@ static ssize_t fr_der_encode_ipv6_prefix(fr_dbuff_t *dbuff, fr_dcursor_t *cursor
501501
}
502502

503503

504+
static ssize_t fr_der_encode_combo_ip(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, UNUSED fr_der_encode_ctx_t *encode_ctx)
505+
{
506+
fr_dbuff_t our_dbuff = FR_DBUFF(dbuff);
507+
fr_pair_t const *vp;
508+
509+
vp = fr_dcursor_current(cursor);
510+
PAIR_VERIFY(vp);
511+
fr_assert(!vp->da->flags.is_raw);
512+
513+
/*
514+
* RFC5280 Section 4.2.1.6
515+
*
516+
* When the subjectAltName extension contains an iPAddress, the address
517+
* MUST be stored in the octet string in "network byte order", as
518+
* specified in [RFC791]. The least significant bit (LSB) of each octet
519+
* is the LSB of the corresponding byte in the network address. For IP
520+
* version 4, as specified in [RFC791], the octet string MUST contain
521+
* exactly four octets. For IP version 6, as specified in
522+
* [RFC2460], the octet string MUST contain exactly sixteen octets.
523+
*/
524+
if (vp->vp_ip.af == AF_INET) {
525+
FR_DBUFF_IN_MEMCPY_RETURN(&our_dbuff, (uint8_t const *) &vp->vp_ipv4addr, sizeof(vp->vp_ipv4addr));
526+
} else {
527+
FR_DBUFF_IN_MEMCPY_RETURN(&our_dbuff, (uint8_t const *) &vp->vp_ipv6addr, sizeof(vp->vp_ipv6addr));
528+
}
529+
530+
return fr_dbuff_set(dbuff, &our_dbuff);
531+
}
532+
533+
504534
static ssize_t fr_der_encode_octetstring(fr_dbuff_t *dbuff, fr_dcursor_t *cursor,
505535
UNUSED fr_der_encode_ctx_t *encode_ctx)
506536
{
@@ -1637,6 +1667,8 @@ static const fr_der_tag_encode_t type_funcs[FR_TYPE_MAX] = {
16371667
[FR_TYPE_IPV4_PREFIX] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_ipv4_prefix },
16381668
[FR_TYPE_IPV6_ADDR] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_ipv6_addr },
16391669
[FR_TYPE_IPV6_PREFIX] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_ipv6_prefix },
1670+
1671+
[FR_TYPE_COMBO_IP_ADDR] = { .constructed = FR_DER_TAG_PRIMITIVE, .encode = fr_der_encode_combo_ip },
16401672
};
16411673

16421674

src/tests/unit/protocols/der/base.txt

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -900,5 +900,24 @@ match Test-IPv4-Prefix = 10.5.0.4/32
900900
decode-pair 03 01 00
901901
match Test-IPv4-Prefix = 0.0.0.0/0
902902

903+
proto-dictionary der
904+
905+
#
906+
# IP address as fixed-size octets i.e. GeneralName.iPAddress
907+
#
908+
encode-pair Test-GeneralNames = { dNSName = "foo.bar" }
909+
match 30 09 82 07 66 6f 6f 2e 62 61 72
910+
911+
encode-pair Test-GeneralNames = { iPAddress = 10.0.5.4 }
912+
match 30 06 87 04 0a 00 05 04
913+
914+
proto-dictionary-root Test-GeneralNames
915+
916+
decode-pair 30 09 82 07 66 6f 6f 2e 62 61 72
917+
match Test-GeneralNames = { dNSName = "foo.bar" }
918+
919+
decode-pair 30 06 87 04 0a 00 05 04
920+
match Test-GeneralNames = { iPAddress = 10.0.5.4 }
921+
903922
count
904-
match 543
923+
match 553

src/tests/unit/protocols/der/dictionary.test

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
# Version $Id$
55
DEFINE Certificate-Extensions x509_extensions ref=@.OID-Tree
66

7+
DEFINE Test-GeneralNames group sequence_of=choice,ref=@.GeneralName
8+
79
DEFINE Issuer sequence sequence_of=set
810
BEGIN Issuer
911
DEFINE RelativeDistinguishedName set clone=@.RelativeDistinguishedName

0 commit comments

Comments
 (0)