1 -- Regano database type definitions
3 -- Uses PostgreSQL extensions.
5 -- Regano is a domain registration system for OpenNIC TLDs written in
6 -- Perl. This file is part of Regano.
8 -- Regano may be distributed under the same terms as Perl itself. Of
9 -- particular importance, note that while regano is distributed in the
10 -- hope that it will be useful, there is NO WARRANTY OF ANY KIND
11 -- WHATSOEVER WHETHER EXPLICIT OR IMPLIED.
14 -- The role 'regano' must already exist.
16 CREATE EXTENSION IF NOT EXISTS pgcrypto WITH SCHEMA public;
18 CREATE SCHEMA IF NOT EXISTS regano AUTHORIZATION regano;
19 CREATE SCHEMA IF NOT EXISTS regano_api AUTHORIZATION regano;
21 -- This is an unsigned 8 bit integer.
22 CREATE DOMAIN regano.uint8bit AS smallint
23 CHECK(VALUE >= 0 AND VALUE < 256);
24 -- This is an unsigned 16 bit integer.
25 CREATE DOMAIN regano.uint16bit AS integer
26 CHECK(VALUE >= 0 AND VALUE < 65536);
27 -- This is an unsigned 32 bit integer.
28 CREATE DOMAIN regano.uint32bit AS bigint
29 CHECK(VALUE >= 0 AND VALUE < 4294967296);
30 -- This is an interval, less than 2^31 seconds long.
31 CREATE DOMAIN regano.dns_interval AS interval
32 CHECK(EXTRACT(EPOCH FROM VALUE)::bigint < 2147483648);
33 -- This is binary data, as hexadecimal digits.
34 CREATE DOMAIN regano.hexstring AS text
35 CHECK(VALUE SIMILAR TO '([0123456789ABCDEF]{2})+');
36 -- This is binary data, in Base64.
37 CREATE DOMAIN regano.base64string AS text
38 CHECK(VALUE ~ '^[[:alnum:]+/-_]+=*$');
39 -- This is a single label in the DNS.
40 CREATE DOMAIN regano.dns_label AS text
41 CHECK(octet_length(VALUE) <= 63) -- per RFC 1035 2.3.4
42 CHECK(octet_length(VALUE) >= 1)
43 CHECK(VALUE NOT LIKE '%.%');
44 -- This is a name in the DNS.
45 CREATE DOMAIN regano.dns_name AS text
46 CHECK(octet_length(VALUE) <= 255) -- per RFC 1035 2.3.4
47 CHECK(octet_length(VALUE) >= 1)
48 CHECK(VALUE NOT LIKE '%..%');
49 -- This is a Fully Qualified Domain Name.
50 CREATE DOMAIN regano.dns_fqdn AS regano.dns_name
51 CHECK(VALUE LIKE '%.');
52 -- This is an email address, encoded into a DNS name.
53 CREATE DOMAIN regano.dns_email AS regano.dns_fqdn
54 CHECK(VALUE LIKE '%.%.%.');
56 ALTER DOMAIN regano.uint8bit OWNER TO regano;
57 ALTER DOMAIN regano.uint16bit OWNER TO regano;
58 ALTER DOMAIN regano.uint32bit OWNER TO regano;
59 ALTER DOMAIN regano.dns_interval OWNER TO regano;
60 ALTER DOMAIN regano.hexstring OWNER TO regano;
61 ALTER DOMAIN regano.base64string OWNER TO regano;
62 ALTER DOMAIN regano.dns_name OWNER TO regano;
63 ALTER DOMAIN regano.dns_fqdn OWNER TO regano;
64 ALTER DOMAIN regano.dns_email OWNER TO regano;
66 -- This bundles together type information, two salts, and a password hash.
67 CREATE TYPE regano.password AS (
70 -- salt for external digest
72 -- hashed password (with internal salt)
75 -- The password type is used both for storing passwords in the DB and for
76 -- communications between the DB and frontend. In the DB, the "digest"
77 -- field stores a digest value from crypt(). When reading salts, the
78 -- "xdigest" and "xsalt" fields contain the external digest algorithm and
79 -- external salt, while "digest" is null. When attempting a login, the
80 -- "digest" field contains the password, salted and hashed according to
81 -- "xdigest" and "xsalt", which the DB will run through crypt() and then
82 -- compare with the stored password. If they match, a session is opened.
84 -- These are the types of contact verifications implemented.
85 CREATE TYPE regano.contact_verification_type AS ENUM (
89 ALTER TYPE regano.contact_verification_type OWNER TO regano;
91 -- These are the DNS record classes defined in RFC 1035.
92 CREATE TYPE regano.dns_record_class AS ENUM (
94 'CS', -- CSNET (obsolete even before RFC 1035)
99 -- The allowed record types are a subset of those supported in BIND.
100 CREATE TYPE regano.dns_record_type AS ENUM (
101 'SOA', -- RFC 1035: start of authority record
102 'A', -- RFC 1035: IPv4 address
103 'AAAA', -- RFC 1886: IPv6 address
104 'CERT', -- RFC 2538: certificate, including PGP key
105 'CNAME', -- RFC 1035: canonical name of alias
106 'DNAME', -- RFC 2672: delegation alias
107 -- TODO: are DNSSEC records other than DS needed?
108 'DS', -- RFC 4034: delegation signer
109 'IPSECKEY', -- RFC 4025: IPsec public key
110 'LOC', -- RFC 1876: physical location ("ICBM address")
111 'MX', -- RFC 1035: mail exchange
112 'NAPTR', -- RFC 2915: regex URI rewrite
113 'NS', -- RFC 1035: authoritative name server
114 'PTR', -- RFC 1035: domain name pointer
115 'RP', -- RFC 1183: responsible person
116 'SPF', -- RFC 4408: Sender Policy Framework record
117 'SRV', -- RFC 2782: service location
118 'SSHFP', -- RFC 4255: SSH host key fingerprint
119 'TLSA', -- RFC 6698: DANE TLSA
120 'TXT' -- RFC 1035: general descriptive text
123 ALTER TYPE regano.dns_record_class OWNER TO regano;
124 ALTER TYPE regano.dns_record_type OWNER TO regano;
126 -- SOA RDATA per RFC 1035 3.3.13
127 CREATE TYPE regano.dns_RR_SOA AS (
128 -- MNAME: zone master nameserver
129 master regano.dns_name,
130 -- RNAME: email address for zone admin
131 mbox regano.dns_email,
132 -- NOTE: The database does not store zone serial numbers. The export
133 -- process assigns a serial number based on the domain's timestamp.
134 -- -- SERIAL: zone data revision
135 -- serial regano.uint32bit,
136 -- REFRESH: refresh interval
137 refresh regano.dns_interval,
138 -- RETRY: retry interval if refresh fails
139 retry regano.dns_interval,
140 -- EXPIRE: lifespan of zone data if refresh continues to fail
141 expire regano.dns_interval,
142 -- MINIMUM: minimum TTL of any record in this zone
143 minimum regano.dns_interval
145 ALTER TYPE regano.dns_RR_SOA OWNER TO regano;
147 -- A RDATA per RFC 1035 3.4.1
148 CREATE DOMAIN regano.dns_RR_A AS inet
149 CONSTRAINT "an A record must hold an IPv4 address"
150 CHECK(family(VALUE) = 4 AND masklen(VALUE) = 32);
151 ALTER DOMAIN regano.dns_RR_A OWNER TO regano;
153 -- AAAA RDATA per RFC 1886
154 CREATE DOMAIN regano.dns_RR_AAAA AS inet
155 CONSTRAINT "an AAAA record must hold an IPv6 address"
156 CHECK(family(VALUE) = 6 AND masklen(VALUE) = 128);
157 ALTER DOMAIN regano.dns_RR_AAAA OWNER TO regano;
159 -- CERT RDATA per RFC 2538
160 CREATE TYPE regano.dns_RR_CERT AS (
161 type regano.uint16bit,
162 key_tag regano.uint16bit,
163 algorithm regano.uint8bit,
164 certificate regano.base64string
166 ALTER TYPE regano.dns_RR_CERT OWNER TO regano;
168 -- CNAME RDATA per RFC 1035 3.3.1
169 -- use common "data_name" field
171 -- DNAME RDATA per RFC 2672
172 -- use common "data_name" field
174 -- DS RDATA per RFC 4034
175 CREATE TYPE regano.dns_RR_DS AS (
176 key_tag regano.uint16bit,
177 algorithm regano.uint8bit,
178 digest_type regano.uint8bit,
179 digest regano.hexstring
181 ALTER TYPE regano.dns_RR_DS OWNER TO regano;
183 -- IPSECKEY RDATA per RFC 4025
184 CREATE TYPE regano.dns_RR_IPSECKEY_gateway_type AS ENUM (
185 '0:None', '1:IPv4', '2:IPv6', '3:DNS'
187 CREATE TYPE regano.dns_RR_IPSECKEY AS (
188 precedence regano.uint8bit,
189 gateway_type regano.dns_RR_IPSECKEY_gateway_type,
190 algorithm regano.uint8bit,
191 gateway_dns regano.dns_fqdn,
193 public_key regano.base64string
195 ALTER TYPE regano.dns_RR_IPSECKEY_gateway_type OWNER TO regano;
196 ALTER TYPE regano.dns_RR_IPSECKEY OWNER TO regano;
198 -- LOC RDATA per RFC 1876
199 CREATE DOMAIN regano.dns_RR_LOC AS text
200 CHECK(VALUE SIMILAR TO
201 ( '(90|[0-8]?[0-9])( [0-5]?[0-9]( [0-5]?[0-9.]+)?)? [NS] '
202 ||'(180|1[0-7][0-9]|0?[0-9]{1,2})'
203 ||'( [0-5]?[0-9]( [0-5]?[0-9.]+)?)? [EW] '
204 ||'(-1?[0-9]{1,5}|[0-3]?[0-9]{1,7})([.][0-9]{0,2})?m?'
205 ||'( (90000000|[0-8]?[0-9]{1,7})([.][0-9]{0,2})?){0,3}'));
206 ALTER DOMAIN regano.dns_RR_LOC OWNER TO regano;
208 -- MX RDATA per RFC 1035 3.3.9
209 CREATE TYPE regano.dns_RR_MX AS (
210 preference regano.uint16bit,
211 exchange regano.dns_name
213 ALTER TYPE regano.dns_RR_MX OWNER TO regano;
215 -- NAPTR RDATA per RFC 2915
216 CREATE TYPE regano.dns_RR_NAPTR AS (
217 naptr_order regano.uint16bit,
218 naptr_preference regano.uint16bit,
222 replacement regano.dns_fqdn
224 ALTER TYPE regano.dns_RR_NAPTR OWNER TO regano;
226 -- NS RDATA per RFC 1035 3.3.11
227 -- use common "data_name" field
229 -- PTR RDATA per RFC 1035 3.3.12
230 -- use common "data_name" field
232 -- RP RDATA per RFC 1183 2
233 CREATE TYPE regano.dns_RR_RP AS (
234 mbox regano.dns_fqdn, -- should be dns_email, but may be "."
235 txt_ref regano.dns_fqdn
237 ALTER TYPE regano.dns_RR_RP OWNER TO regano;
239 -- SPF RDATA per RFC 4408
240 -- use common "data_text" field
242 -- SRV RDATA per RFC 2782
243 CREATE TYPE regano.dns_RR_SRV AS (
244 priority regano.uint16bit,
245 weight regano.uint16bit,
246 port regano.uint16bit,
247 target regano.dns_fqdn
249 ALTER TYPE regano.dns_RR_SRV OWNER TO regano;
251 -- SSHFP RDATA per RFC 4255
252 CREATE TYPE regano.dns_RR_SSHFP AS (
253 algorithm regano.uint8bit,
254 fp_type regano.uint8bit,
255 fingerprint regano.hexstring
257 ALTER TYPE regano.dns_RR_SSHFP OWNER TO regano;
259 -- TLSA RDATA per RFC 6698
260 CREATE TYPE regano.dns_RR_TLSA AS (
261 cert_usage regano.uint8bit,
262 selector regano.uint8bit,
263 match_type regano.uint8bit,
264 cert_data regano.hexstring
266 ALTER TYPE regano.dns_RR_TLSA OWNER TO regano;
268 -- TXT RDATA per RFC 1035 3.3.14
269 -- use common "data_text" field
273 -- Any domain is in one of 7 states:
276 -- Not available for registration.
278 -- Not in a TLD managed by this server.
280 -- Is itself a TLD managed by this server.
282 -- May be registered.
284 -- Pre-registered but owning account not yet validated.
286 -- Currently registered and active.
288 -- Registration has expired, but has not yet been released.
290 CREATE TYPE regano.domain_status AS ENUM (
299 ALTER TYPE regano.domain_status OWNER TO regano;
302 -- Each registered domain is in one of 3 modes:
305 -- All records for this domain are in the main TLD zone.
307 -- This domain has its own zone on the main TLD server.
309 -- This domain has its own authoritative server(s).
311 CREATE TYPE regano.domain_mode AS ENUM ('INLINE', 'HOSTED', 'DELEGATED');
312 ALTER TYPE regano.domain_mode OWNER TO regano;
314 -- This is summary information for a pending domain.
315 CREATE TYPE regano.pending_domain AS (
317 start timestamp with time zone,
318 expire timestamp with time zone
321 -- This is summary information for a registered domain.
322 CREATE TYPE regano.domain AS (
324 registered timestamp with time zone,
325 expiration timestamp with time zone,
326 last_update timestamp with time zone,
327 -- status will be either REGISTERED or EXPIRED
328 status regano.domain_status