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