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