djbdnscurve6 51
djbdnscurve6
Loading...
Searching...
No Matches
curvedns.c
Go to the documentation of this file.
1/* cns_transmit_start returns DNS_COM */
2
3#include <stdio.h>
4#include "alloc.h"
5#include "byte.h"
6#include "uint_t.h"
7#include "case.h"
8#include "dns.h"
9#include "curvedns.h"
10#include "base32.h"
11#include "query.h"
12#include "socket_if.h"
13#include "ip.h"
14#include "error.h"
15#include "serverok.h"
16#include "log.h"
17
18unsigned int flagedserver;
19unsigned int fallback;
20int flagdnsoptrr = 0; // extern
21
22char optrr[11] = { '\0', // root = 0
23 '\0','\51', // DNS_T_OPT
24 '\5', '\0', // max payload size (1280)
25 '\0', '\0', '\0', '\0', // could include D0 flag
26 '\0', '\0' };
27
28void cns_nonce(char nonce[12])
29{
30 int i;
31
32 for (i = 0; i < 12; i++)
33 nonce[i] = dns_random(256);
34}
35
36/* Generate standard DNS query message with EDNS(0) */
37
38void dns_basequery(struct dns_transmit *d,char *query)
39{
40 unsigned int len;
41
42 len = dns_domain_length(d->name);
43
44 byte_copy(query,2,d->nonce + 8); /* 2 byte Identification */
45 /* Parameter Mapping: 1: Query; 1: #Queries; 1: #AddSec = 1*/
46 if (flagdnsoptrr)
47 byte_copy(query + 2,10,d->flagrecursive ? "\1\0\0\1\0\0\0\0\0\1" : \
48 "\0\0\0\1\0\0\0\0\0\1");
49 else
50 byte_copy(query + 2,10,d->flagrecursive ? "\1\0\0\1\0\0\0\0\0\0" : \
51 "\0\0\0\1\0\0\0\0\0\0");
52 byte_copy(query + 12,len,d->name);
53 byte_copy(query + 12 + len,2,d->qtype);
54 byte_copy(query + 14 + len,2,DNS_C_IN);
55
56 /* EDNS(0) Pseudo RR: name(1) + type(2) + class(2) + ttl(4) + rdlen(2) => +11 octetts*/
57
58 if (flagdnsoptrr) {
59 byte_copy(query + 16 + len,3,optrr); // name = 0 + DNS_OPT
60 uint16_pack_big(query + 19 + len,MSGSIZE); // msg size
61 byte_copy(query + 21 + len,6,optrr + 5); // rest 0
62 }
63}
64
65/* Generate DNSCurve format query message */
66
67void cns_query(struct dns_transmit *d)
68{
69 unsigned int len;
70 char nonce[24];
71 const char *key;
72 unsigned int m;
73 unsigned int suffixlen;
74
75 cns_nonce(d->nonce);
76
77 if (!d->keys) {
78 byte_copy(d->query + 2,2,d->nonce + 8);
79 return;
80 }
81
82 len = dns_domain_length(d->name);
83
84 byte_copy(nonce,12,d->nonce);
85 byte_zero(nonce + 12,12);
86 key = d->keys + 32 * d->curserver;
87
88 byte_zero(d->query,32);
89 dns_basequery(d,d->query + 32);
90
91 crypto_box_afternm((unsigned char *) d->query,(const unsigned char *) d->query,len + 48, \
92 (const unsigned char *) nonce,(const unsigned char *) key);
93
94 if (!d->suffix) {
95 byte_copyr(d->query + 54,len + 32,d->query + 16);
96 uint16_pack_big(d->query,len + 84);
97 byte_copy(d->query + 2,8,"Q6fnvWj8");
98 byte_copy(d->query + 10,32,d->pubkey);
99 byte_copy(d->query + 42,12,nonce);
100 return;
101 }
102
103 byte_copyr(d->query + d->querylen - len - 32,len + 32,d->query + 16);
104 byte_copy(d->query + d->querylen - len - 44,12,nonce);
105
106 suffixlen = dns_domain_length(d->suffix);
107 m = base32_bytessize(len + 44);
108
109 uint16_pack_big(d->query,d->querylen - 2);
110 d->query[2] = dns_random(256);
111 d->query[3] = dns_random(256);
112 byte_copy(d->query + 4,10,"\0\0\0\1\0\0\0\0\0\0");
113 base32_encode(d->query + 14,d->query + d->querylen - len - 44,len + 44);
114 base32_clientkey(d->query + 14 + m,d->pubkey);
115 byte_copy(d->query + 69 + m,suffixlen,d->suffix);
116 byte_copy(d->query + 69 + m + suffixlen,4,DNS_T_TXT DNS_C_IN);
117}
118
119int cns_uncurve(const struct dns_transmit *d,char *buf,unsigned int *lenp)
120{
121 const char *key;
122 char nonce[24];
123 unsigned int len;
124 char out[16];
125 unsigned int pos;
126 uint16 datalen;
127 unsigned int i;
128 unsigned int j;
129 char ch;
130 unsigned int txtlen;
131 unsigned int namelen;
132
133 if (!d->keys) return 0;
134
135 key = d->keys + 32 * d->curserver;
136 len = *lenp;
137
138 if (!d->suffix) {
139 if (len < 48) return 1;
140 if (byte_diff(buf,8,"R6fnvWJ8")) return 1;
141 if (byte_diff(buf + 8,12,d->nonce)) return 1;
142 byte_copy(nonce,24,buf + 8);
143 byte_zero(buf + 16,16);
144
145 if (crypto_box_open_afternm((uint8 *) buf + 16,(const uint8 *) buf + 16,len - 16, \
146 (const uint8 *) nonce,(const uint8 *) key)) return 1;
147 byte_copy(buf,len - 48,buf + 48);
148 *lenp = len - 48;
149 return 0;
150 }
151
152 /* XXX: be more leniant? */
153
154 pos = dns_packet_copy(buf,len,0,out,12); if (!pos) return 1;
155 if (byte_diff(out,2,d->query + 2)) return 1;
156 if (byte_diff(out + 2,10,"\204\0\0\1\0\1\0\0\0\0")) return 1;
157
158 /* query name might be >255 bytes, so can't use dns_packet_getname */
159 namelen = dns_domain_length(d->query + 14);
160 pos += namelen;
161
162 pos = dns_packet_copy(buf,len,pos,out,16); if (!pos) return 1;
163 if (byte_diff(out,14,"\0\20\0\1\300\14\0\20\0\1\0\0\0\0")) return 1;
164 uint16_unpack_big(out + 14,&datalen);
165 if (datalen > len - pos) return 1;
166
167 j = 4;
168 txtlen = 0;
169 for (i = 0; i < datalen; ++i) {
170 ch = buf[pos + i];
171 if (!txtlen)
172 txtlen = (unsigned char) ch;
173 else {
174 --txtlen;
175 buf[j++] = ch;
176 }
177 }
178 if (txtlen) return 1;
179
180 if (j < 32) return 1;
181 byte_copy(nonce,12,d->nonce);
182 byte_copy(nonce + 12,12,buf + 4);
183 byte_zero(buf,16);
184
185 if (crypto_box_open_afternm((unsigned char *) buf,(const unsigned char *) buf,j, \
186 (const unsigned char *) nonce,(const unsigned char *) key)) return 1;
187 byte_copy(buf,j - 32,buf + 32);
188 *lenp = j - 32;
189
190 return 0;
191}
192
193int cns_pubkey(const char *dn,char *key)
194{
195 unsigned char c;
196
197 while ((c = *dn++)) {
198 if (c == 54)
199 if (!case_diffb(dn,3,"uz5"))
200 if (base32_decode(key,dn + 3,51,1) == 32)
201 return 1;
202 dn += (unsigned int) c;
203 }
204 return 0;
205}
206
207void cns_sortns(char *s,char *t,unsigned int n)
208{
209 unsigned int i;
210 char tmp[32];
211
212 /* s = ipaddres, t = pubkey, n = #NS */
213
214 while (n > 1) {
215 i = dns_random(n);
216 --n;
217 byte_copy(tmp,16,s + (i << 4));
218 byte_copy(s + (i << 4),16,s + (n << 4));
219 byte_copy(s + (n << 4),16,tmp);
220
221 byte_copy(tmp,32,t + (i << 5));
222 byte_copy(t + (i << 5),32,t + (n << 5));
223 byte_copy(t + (n << 5),32,tmp);
224 }
225}
226
227int cns_addns(struct query *z,const char *addr,int flagnskey,const char *key)
228{
229 int k;
230 int flagns = 0;
231
232 if (flagedserver) {
233 flagns = serverok(addr);
234 if (flagns == 1) return 1;
235 if (flagns == -1) flagnskey = 0;
236 }
237
238 if (z->flagnskeys[z->level - 1]) {
239 if (!flagnskey) goto IPONLY;
240 } else if (flagnskey) {
241 byte_zero(z->servers[z->level - 1],QUERY_MAXIPLEN);
242 byte_zero(z->keys[z->level - 1],1024);
243 z->flagnskeys[z->level - 1] = 1;
244 }
245
246 IPONLY:
247
248 for (k = 0; k < QUERY_MAXIPLEN; k += 16) {
249 if (byte_equal(z->servers[z->level - 1] + k,16,addr)) return flagns;
250 if (byte_equal(z->servers[z->level - 1] + k,16,V6localnet)) {
251 byte_copy(z->servers[z->level - 1] + k,16,addr);
252 if (flagnskey) byte_copy(z->keys[z->level - 1] + 2 * k,32,key);
253
254 break;
255 }
256 }
257
258 return flagns;
259}
260
262 int flagrecursive,const char *q,const char qtype[2], \
263 const char localip[16],\
264 const char keys[1024],const char pubkey[32],const char *suffix)
265{
266 unsigned int len;
267 unsigned int suffixlen;
268 unsigned int m;
269
271 errno = EIO;
273
274 if (!keys) {
275 d->querylen = len + 18;
276 if (flagdnsoptrr) d->querylen += 11; // +OPT-RR
277 } else if (!suffix)
278 d->querylen = len + 86;
279 else {
280 suffixlen = dns_domain_length(suffix);
281 m = base32_bytessize(len + 44);
282 d->querylen = m + suffixlen + 73;
283 }
284
285 d->query = alloc(d->querylen);
286 if (!d->query) return DNS_MEM;
287
288 d->name = q;
289 byte_copy(d->qtype,2,qtype);
290 d->servers = servers;
291 byte_copy(d->localip,16,localip);
292 d->flagrecursive = flagrecursive;
293 d->keys = keys;
294 d->pubkey = pubkey;
295 d->suffix = suffix;
296
297 if (!d->keys) {
298 uint16_pack_big(d->query,len + 16);
299 dns_basequery(d,d->query + 2);
300 d->name = d->query + 14; /* keeps dns_transmit_start backwards compatible */
301 }
302 d->udploop = flagrecursive ? 1 : 0;
303
304 if (len > MSGSIZE - 16) return firsttcp(d);
305
306 return firstudp(d);
307}
uint16 len
Definition: axfrdns.c:319
char buf[MSGSIZE]
Definition: axfrdns.c:318
unsigned int base32_bytessize(unsigned int len)
Definition: base32.c:40
void base32_clientkey(uint8 *out, const char *key)
Definition: base32.c:106
unsigned int base32_decode(uint8 *out, const char *in, unsigned int len, int mode)
Definition: base32.c:46
void base32_encode(uint8 *out, const char *in, unsigned int len)
Definition: base32.c:77
#define crypto_box_afternm
Definition: curve.h:14
#define crypto_box_open_afternm
Definition: curve.h:15
int cns_transmit_start(struct dns_transmit *d, const char servers[QUERY_MAXIPLEN], int flagrecursive, const char *q, const char qtype[2], const char localip[16], const char keys[1024], const char pubkey[32], const char *suffix)
Definition: curvedns.c:261
void dns_basequery(struct dns_transmit *d, char *query)
Definition: curvedns.c:38
void cns_sortns(char *s, char *t, unsigned int n)
Definition: curvedns.c:207
void cns_query(struct dns_transmit *d)
Definition: curvedns.c:67
void cns_nonce(char nonce[12])
Definition: curvedns.c:28
int cns_uncurve(const struct dns_transmit *d, char *buf, unsigned int *lenp)
Definition: curvedns.c:119
int cns_pubkey(const char *dn, char *key)
Definition: curvedns.c:193
int cns_addns(struct query *z, const char *addr, int flagnskey, const char *key)
Definition: curvedns.c:227
unsigned int fallback
Definition: curvedns.c:19
char optrr[11]
Definition: curvedns.c:22
unsigned int flagedserver
Definition: curvedns.c:18
int flagdnsoptrr
Definition: curvedns.c:20
#define QUERY_MAXIPLEN
Definition: dns.h:47
#define DNS_C_IN
Definition: dns.h:53
#define MSGSIZE
Definition: dns.h:40
#define DNS_T_TXT
Definition: dns.h:63
#define DNS_MEM
Definition: dns.h:33
unsigned int dns_domain_length(const char *dn)
Definition: dns_domain.c:6
unsigned int dns_packet_copy(const char *buf, unsigned int len, unsigned int pos, char *out, unsigned int outlen)
Definition: dns_packet.c:8
unsigned int dns_random(unsigned int n)
Definition: dns_random.c:56
void dns_transmit_free(struct dns_transmit *d)
Definition: dns_transmit.c:95
int firstudp(struct dns_transmit *d)
Definition: dns_transmit.c:193
int firsttcp(struct dns_transmit *d)
Definition: dns_transmit.c:250
struct tcpclient t[QUERY_MAXTCP]
char servers[QUERY_MAXIPLEN]
Definition: dnsfilter.c:48
struct line tmp
Definition: dnsfilter.c:32
void out(const char *s, unsigned int len)
Definition: generic-conf.c:54
void c(const char *home, const char *subdir, const char *file, int uid, int gid, int mode)
void d(const char *home, const char *subdir, int uid, int gid, int mode)
void z(char *home, char *subdir, char *file, int len, int uid, int gid, int mode)
Definition: install.c:88
int serverok(char[16])
Definition: serverok.c:17
Definition: query.h:59