Commit 4d145b9023 for strongswan.org
commit 4d145b9023f489b7e3b03bd8ad864a25c379d37d
Author: Tobias Brunner <tobias@strongswan.org>
Date: Tue Oct 27 17:26:37 2026 +0100
asn1: Add checks to validate the basic structure of oid.txt
The checks make sure the file is well-formed and we don't loose any
values due to incorrect indentation (like the one fixed in the previous
commit). While a strict ordering of siblings is technically not
necessary, it makes editing the file easier and we can make sure the
values on the same level are unique. We also make sure we don't have
any invalid leaf nodes.
Lines that don't match the required syntax are now not just silently
skipped but cause a failure. Empty lines and comments (#) are explicitly
allowed. The parse/verification steps happen strictly before writing
any output to avoid creating incomplete files.
Also reformat the file slightly (only use tabs for indentation).
diff --git a/src/libstrongswan/asn1/oid.pl b/src/libstrongswan/asn1/oid.pl
index 479610a9d6..71ba292b7a 100644
--- a/src/libstrongswan/asn1/oid.pl
+++ b/src/libstrongswan/asn1/oid.pl
@@ -1,6 +1,7 @@
#!/usr/bin/perl
# Generates oid.h and oid.c out of oid.txt
#
+# Copyright (C) 2026 Tobias Brunner
# Copyright (C) 2003-2008 Andreas Steffen
#
# Copyright (C) secunet Security Networks AG
@@ -20,36 +21,10 @@ $copyright="Copyright (C) 2003-2008 Andreas Steffen";
$automatic="This file has been automatically generated by the script oid.pl";
$warning="Do not edit manually!";
-# Generate oid.h
-
-open(OID_H, ">oid.h")
- or die "could not open 'oid.h': $!";
-
-print OID_H "/* Object identifiers (OIDs) used by strongSwan\n",
- " * ", $copyright, "\n",
- " * \n",
- " * ", $automatic, "\n",
- " * ", $warning, "\n",
- " */\n\n",
- "#include <utils/utils.h>\n\n",
- "#ifndef OID_H_\n",
- "#define OID_H_\n\n",
- "typedef struct {\n",
- " u_char octet;\n",
- " u_int next;\n",
- " u_int down;\n",
- " u_int level;\n",
- " const u_char *name;\n",
- "} oid_t;\n",
- "\n",
- "extern const oid_t oid_names[];\n",
- "\n",
- "#define OID_UNKNOWN -1\n";
-
-# parse oid.txt
+# Parse oid.txt
open(SRC, "<oid.txt")
- or die "could not open 'oid.txt': $!";
+ or die "could not open 'oid.txt': $!";
$counter = 0;
$max_name = 0;
@@ -57,66 +32,180 @@ $max_order = 0;
while ($line = <SRC>)
{
- $line =~ m/( *?)(0x\w{2})\s+(".*?")[ \t]*?([\w_]*?)\Z/;
-
- @order[$counter] = length($1);
- @octet[$counter] = $2;
- @name[$counter] = $3;
-
- if (length($1) > $max_order)
- {
- $max_order = length($1);
- }
- if (length($3) > $max_name)
- {
- $max_name = length($3);
- }
- if (length($4) > 0)
- {
- printf OID_H "#define %s%s%d\n", $4, "\t" x ((39-length($4))/4), $counter;
- }
- $counter++;
+ next if $line =~ /^\s*(#.*)?$/;
+
+ if ($line !~ /^( *?)(0x\w{2})\s+(".*?")[ \t]*?([\w_]*?)\Z/)
+ {
+ die "oid.txt line $.: unable to parse entry: $line";
+ }
+
+ @order[$counter] = length($1);
+ if (@order[$counter] % 2)
+ {
+ die "oid.txt line $.: indentation not a multiple of 2 spaces\n"
+ }
+
+ @lineno[$counter] = $.;
+ @octet[$counter] = $2;
+ @name[$counter] = $3;
+
+ if (length($1) > $max_order)
+ {
+ $max_order = length($1);
+ }
+ if (length($3) > $max_name)
+ {
+ $max_name = length($3);
+ }
+ if (length($4) > 0)
+ {
+ @oid_name[$counter] = $4;
+ }
+ $counter++;
+}
+
+close SRC;
+
+die "oid.txt does not contain any OIDs\n"
+ if !$counter;
+
+# Validate the tree structure of oid.txt. The indentation by 2 spaces (already
+# checked above) defines the tree:
+#
+# - a child has to be indented exactly one level deeper than its parent
+# - the octets of siblings have to be unique and in strictly increasing order
+# - an octet with the most significant bit set is a base-128 continuation
+# octet and has to be followed by at least one child octet
+
+# stack of [order/indent, last sibling octet, last sibling line]
+@tree = ();
+
+for ($c = 0; $c < $counter; $c++)
+{
+ $lineno = @lineno[$c];
+ $oct = hex(@octet[$c]);
+
+ while (@tree && @order[$c] < $tree[$#tree][0])
+ {
+ pop(@tree);
+ }
+
+ if (@tree)
+ {
+ $top = $tree[$#tree][0];
+ if (@order[$c] == $top + 2)
+ {
+ # child, indented one level deeper
+ push(@tree, [@order[$c], $oct, $lineno]);
+ }
+ elsif (@order[$c] == $top)
+ {
+ # sibling of the previous entry at this level
+ $prev_line = $tree[$#tree][2];
+ if ($oct <= $tree[$#tree][1])
+ {
+ die "oid.txt lines $prev_line/$lineno: sibling octets must be ",
+ "unique and in strictly increasing order\n";
+ }
+ $tree[$#tree][1] = $oct;
+ $tree[$#tree][2] = $lineno;
+ }
+ else
+ {
+ die "oid.txt line $lineno: indentation does not continue a ",
+ "previous level\n";
+ }
+ }
+ elsif (@order[$c])
+ {
+ die "oid.txt line $lineno: top level OIDs must not be indented\n";
+ }
+ else
+ {
+ push(@tree, [0, $oct, $lineno]);
+ }
+
+ if ($oct >= 0x80 && ($c >= $counter || @order[$c+1] != @order[$c] + 2))
+ {
+ # a continuation octet has to be followed by a child
+ die "oid.txt line $lineno: octet @octet[$c] (continuation byte) must ",
+ "have children\n"
+ }
+}
+
+# Generate oid.h
+
+open(OID_H, ">oid.h")
+ or die "could not open 'oid.h': $!";
+
+print OID_H "/* Object identifiers (OIDs) used by strongSwan\n",
+ " * ", $copyright, "\n",
+ " * \n",
+ " * ", $automatic, "\n",
+ " * ", $warning, "\n",
+ " */\n\n",
+ "#include <utils/utils.h>\n\n",
+ "#ifndef OID_H_\n",
+ "#define OID_H_\n\n",
+ "typedef struct {\n",
+ " u_char octet;\n",
+ " u_int next;\n",
+ " u_int down;\n",
+ " u_int level;\n",
+ " const u_char *name;\n",
+ "} oid_t;\n",
+ "\n",
+ "extern const oid_t oid_names[];\n",
+ "\n",
+ "#define OID_UNKNOWN -1\n";
+
+for ($c = 0; $c < $counter; $c++)
+{
+ if (defined(@oid_name[$c]))
+ {
+ printf OID_H "#define %s%s%d\n", @oid_name[$c],
+ "\t" x ((39-length(@oid_name[$c]))/4), $c
+ }
}
printf OID_H "\n#define OID_MAX%s%d\n", "\t" x 8, $counter;
print OID_H "\n#endif /* OID_H_ */\n";
-close SRC;
close OID_H;
# Generate oid.c
open(OID_C, ">oid.c")
- or die "could not open 'oid.c': $!";
+ or die "could not open 'oid.c': $!";
print OID_C "/* List of some useful object identifiers (OIDs)\n",
- " * ", $copyright, "\n",
- " * \n",
- " * ", $automatic, "\n",
- " * ", $warning, "\n",
- " */\n",
- "\n",
- "#include <stdlib.h>\n",
- "\n",
- "#include \"oid.h\"\n",
- "\n",
- "const oid_t oid_names[] = {\n";
+ " * ", $copyright, "\n",
+ " * \n",
+ " * ", $automatic, "\n",
+ " * ", $warning, "\n",
+ " */\n",
+ "\n",
+ "#include <stdlib.h>\n",
+ "\n",
+ "#include \"oid.h\"\n",
+ "\n",
+ "const oid_t oid_names[] = {\n";
for ($c = 0; $c < $counter; $c++)
{
- $next = 0;
+ $next = 0;
- for ($d = $c+1; $d < $counter && @order[$d] >= @order[$c]; $d++)
- {
- if (@order[$d] == @order[$c])
+ for ($d = $c+1; $d < $counter && @order[$d] >= @order[$c]; $d++)
{
- @next[$c] = $d;
- last;
+ if (@order[$d] == @order[$c])
+ {
+ @next[$c] = $d;
+ last;
+ }
}
- }
- printf OID_C " {%s%s,%s%3d, %d, %2d, %s%s}%s /* %3d */\n"
+ printf OID_C " {%s%s,%s%3d, %d, %2d, %s%s}%s /* %3d */\n"
,' ' x @order[$c]
, @octet[$c]
, ' ' x (1 + $max_order - @order[$c])