[Pdns-users] PostgreSQL schema for DNSSEC signing
ktm at rice.edu
ktm at rice.edu
Thu Jan 9 22:47:46 UTC 2014
On Thu, Jan 09, 2014 at 10:26:07AM -0600, ktm at rice.edu wrote:
> Hi,
>
> I am working on porting your auto-signing schema proof-of-concept for Oracle:
>
> http://wiki.powerdns.com/trac/browser/trunk/pdns/modules/oraclebackend/schema.sql
>
> to PostgreSQL. I have found something that looks like a bug in the following
> function dnsname_to_raw():
>
> ------------------------------------------------
> CREATE OR REPLACE FUNCTION dnsname_to_raw (in_dnsname IN VARCHAR2) RETURN RAW AS
> dnsname VARCHAR2(512) := LOWER(in_dnsname);
> rawname RAW(512);
>
> lpos BINARY_INTEGER := 1;
> rpos BINARY_INTEGER;
> label VARCHAR2(63);
>
> TYPE convarray IS VARRAY(64) OF RAW(1);
> byteval convarray := convarray(
> '00', '01', '02', '03', '04', '05', '06', '07',
> '08', '09', '0A', '0B', '0C', '0D', '0E', '0F',
> '10', '11', '12', '13', '14', '15', '16', '17',
> '18', '19', '1A', '1B', '1C', '1D', '1E', '1F',
> '20', '21', '22', '23', '24', '25', '26', '27',
> '28', '29', '2A', '2B', '2C', '2D', '2E', '2F',
> '30', '31', '32', '33', '34', '35', '36', '37',
> '38', '39', '3A', '3B', '3C', '3D', '3E', '3F'
> );
> BEGIN
> IF dnsname IS NULL THEN
> RETURN('00');
> END IF;
>
> WHILE lpos <= LENGTH(dnsname) LOOP
> rpos := INSTR(dnsname, '.', lpos);
> IF rpos = 0 THEN
> rpos := LENGTH(dnsname) + 1;
> END IF;
> label := SUBSTR(dnsname, lpos, rpos - lpos);
> rawname := UTL_RAW.CONCAT(
> rawname,
> byteval(LENGTH(label) + 1),
> UTL_I18N.STRING_TO_RAW(label, 'US7ASCII')
> );
> lpos := rpos + 1;
> END LOOP;
>
> IF rpos = LENGTH(dnsname) THEN
> rawname := UTL_RAW.CONCAT(rawname, '00');
> END IF;
>
> RETURN(rawname);
> END;
> ------------------------------------------------
>
> At the end of the function, it has a test to see if "rpos = LENGTH(dnsname)"
> and if so, appends a 00 byte to the end, but the only place that sets rpos
> earlier:
>
> IF rpos = 0 THEN
> rpos := LENGTH(dnsname) + 1;
> END IF;
>
> specifically sets rpos to the length of the string + 1, which would mean
> that the trailing nul would never be added. This looks like a bug, but I
> am working from the "code-as-documentation" instead of a spec for what
> the dnsname_to_raw output definition. Once the PostgreSQL schema has been
> tested, I will post/submit our final version for inclusion in the dist.
> Any assistance would be appreciated.
>
> Regards,
> Ken
Okay, using the assumption that the code has a bug, here is the PostgreSQL
version:
------------------------------------------------
CREATE OR REPLACE FUNCTION dnsname_to_raw (
in_dnsname VARCHAR
) RETURNS BYTEA AS $$
DECLARE
dnsname VARCHAR := LOWER(in_dnsname);
rawname BYTEA;
i INTEGER;
label VARCHAR[];
byteval VARCHAR[64] := ARRAY[
'00', '01', '02', '03', '04', '05', '06', '07',
'08', '09', '0A', '0B', '0C', '0D', '0E', '0F',
'10', '11', '12', '13', '14', '15', '16', '17',
'18', '19', '1A', '1B', '1C', '1D', '1E', '1F',
'20', '21', '22', '23', '24', '25', '26', '27',
'28', '29', '2A', '2B', '2C', '2D', '2E', '2F',
'30', '31', '32', '33', '34', '35', '36', '37',
'38', '39', '3A', '3B', '3C', '3D', '3E', '3F'
];
BEGIN
IF dnsname IS NULL THEN
RETURN('00');
END IF;
label := string_to_array(dnsname, '.');
FOR i IN 1 .. ARRAY_UPPER(label, 1)
LOOP
IF rawname IS NULL THEN
rawname := decode(byteval[LENGTH(label[i]) + 1], 'hex')
|| convert_to(label[i], 'SQL_ASCII');
ELSE
rawname := rawname || decode(byteval[LENGTH(label[i]) + 1], 'hex')
|| convert_to(label[i], 'SQL_ASCII');
END IF;
END LOOP;
rawname := rawname || decode('00', 'hex');
RETURN rawname;
END;
$$ LANGUAGE plpgsql STRICT IMMUTABLE;
------------------------------------------------
Here is a sample of the results for a test case:
test=> select dnsname_to_raw('moe.rice.edu');
dnsname_to_raw
--------------------------------
\x036d6f6504726963650365647500
(1 row)
This seems like it should be the correct result, but I would appreciate
it if someone who knew would corroborate this. Thank you.
Regards,
Ken
More information about the Pdns-users
mailing list