djbdnscurve6 45
djbdnscurve6
Loading...
Searching...
No Matches
server.c
Go to the documentation of this file.
1/* 'server.c' supports currently only UDP */
2#include <sys/stat.h>
3#include <unistd.h>
4#include "byte.h"
5#include "case.h"
6#include "env.h"
7#include "buffer.h"
8#include "ip.h"
9#include "uint_t.h"
10#include "ndelay.h"
11#include "socket_if.h"
12#include "droproot.h"
13#include "qlog.h"
14#include "response.h"
15#include "dns.h"
16#include "alloc.h"
17#include "str.h"
18#include "open.h"
19#include "logmsg.h"
20#include "curve.h"
21
22uint16 dnsport = 53;
23extern char *fatal;
24extern char *starting;
25extern int respond(char *,char *,char *);
26extern void init_server(void);
29extern int flagcurved;
30
31static char ip[16];
32static uint16 port;
33unsigned char curvekey[32];
34
35static char buf[MAXMSGSIZE];
36static int len;
37
38static char *q;
39
40void nomem()
41{
42 logmsg(fatal,111,FATAL,"out of memory");
43}
44
45static int doit(void)
46{
47 unsigned int pos, zone;
48 char header[12];
49 char qtype[2];
50 char qclass[2];
51 char tid[2];
52 uint8 secret[32];
53 uint8 pubkey[32];
54 uint8 nonce[24];
55 uint8 sandbox[MAXMSGSIZE];
56 uint8 qname[MAXMSGSIZE];
57 unsigned int boxlen = 0;
58 unsigned int qnamelen = 0;
59 int rd;
60 int r;
61
62 if (len >= sizeof(buf)) goto NOQ;
63 if (!flagcurved) goto NOC;
64
65 /* Parse potential DNSCurve message and read query */
66
67 pos = dns_curve_query(buf,len,0); if (!pos) goto TXT;
68 pos = dns_curve_pubkey(pubkey,buf,pos); if (!pos) goto NOC;
69 pos = dns_curve_nonce(nonce,buf,pos); if (!pos) goto NOC;
70 boxlen = dns_curve_cryptobox(sandbox + 16,buf,len,pos); if (!boxlen) goto NOC;
71
72 byte_zero(sandbox,16);
73 byte_zero(nonce + 12,12);
74
75 if (crypto_box_beforenm(secret,pubkey,curvekey)) {
76 logmsg(fatal,99,WARN,"can't compute shared secret");
77 goto NOC;
78 }
79 if (crypto_box_open_afternm(sandbox,sandbox,boxlen + 16,nonce,secret)) {
80 logmsg(fatal,99,WARN,"can't open cryptobox");
81 goto NOC;
82 }
83 if (!dns_packet_copy(sandbox + 32,boxlen,0,buf,boxlen)) goto NOC;
84 flagcurved = 2;
85 goto NOC;
86
87
88 TXT:
89
90 pos = dns_curve_txtquery(buf,len,2); if (!pos) goto NOC; // pos of '\x36x1a'
91 boxlen = dns_curve_txtqname(sandbox + 4,buf,len); if (!boxlen) goto NOC; // length of base32box incl. nonce
92 if (!dns_curve_txtnonce(nonce,sandbox + 4)) goto NOC; // length of nonce (= 12)
93 zone = dns_curve_txtpubkey(pubkey,buf,pos + 4);
94 if (buf[2] & 1) rd = 1;
95 else rd = 0;
96
97 byte_zero(sandbox,16); // BOXZERO bytes
98 byte_zero(nonce + 12,12); // fullnonce
99
100 if (crypto_box_beforenm(secret,pubkey,curvekey)) {
101 logmsg(fatal,99,WARN,"can't compute shared secret");
102 goto NOC;
103 }
104 if (crypto_box_open_afternm(sandbox,sandbox,boxlen + 4,nonce,secret)) {
105 logmsg(fatal,99,WARN,"can't open cryptobox");
106 goto NOC;
107 }
108 pos = dns_packet_getname(buf,len,pos,&q); if (!pos) goto NOQ; // orig q
109 qnamelen = pos - 12;
110 byte_copy(qname,qnamelen,buf + 12);
111 byte_copy(tid,2,buf);
112 if (!dns_packet_copy(sandbox + 32,len,0,buf,len)) goto NOC;
113 flagcurved = 3;
114
115
116 NOC:
117
118 pos = dns_packet_copy(buf,len,0,header,12); if (!pos) goto NOQ;
119 if (header[2] & 128) goto NOQ;
120 if (header[4]) goto NOQ;
121 if (header[5] != 1) goto NOQ;
122
123 pos = dns_packet_getname(buf,len,pos,&q); if (!pos) goto NOQ; // name -> q
124 pos = dns_packet_copy(buf,len,pos,qtype,2); if (!pos) goto NOQ; // -> qtype
125 pos = dns_packet_copy(buf,len,pos,qclass,2); if (!pos) goto NOQ; // -> qclass
126
127 if (!response_query(q,qtype,qclass)) goto NOQ; // generate response, copy q add answers
128
129 response_id(header);
130 if (byte_equal(qclass,2,DNS_C_IN))
131 response[2] |= 4;
132 else
133 if (byte_diff(qclass,2,DNS_C_ANY)) goto WEIRDCLASS;
134 response[3] &= ~128;
135 if (!(header[2] & 1)) response[2] &= ~1;
136
137 if (header[2] & 126) goto NOTIMP;
138 if (byte_equal(qtype,2,DNS_T_AXFR)) goto NOTIMP;
139
141 case_lowerb(q,len);
142 r = respond(q,qtype,ip);
143
144 if (flagcurved == 2) response_stream(secret,nonce);
145 if (flagcurved == 3) response_alttxt(secret,nonce,tid,qname,qnamelen,rd);
146
147 // Logging & return
148
149 if (flagcurved > 1) {
150 flagcurved = 1; // reset state
151 if (r) { qlog(ip,port,header,q,qtype," * "); return 1; }
152 else { qlog(ip,port,header,q,qtype," ~ "); return 0; }
153 } else {
154 if (r) { qlog(ip,port,header,q,qtype," + "); return 1; }
155 else { qlog(ip,port,header,q,qtype," - "); return 0; }
156 }
157
158
159 NOTIMP:
160 response[3] &= ~15;
161 response[3] |= 4;
162 qlog(ip,port,header,q,qtype," I ");
163 return 1;
164
165 WEIRDCLASS:
166 response[3] &= ~15;
167 response[3] |= 1;
168 qlog(ip,port,header,q,qtype," C ");
169 return 1;
170
171 NOQ:
172 qlog(ip,port,"\0\0","","\0\0"," / ");
173 return 0;
174}
175
176int main()
177{
178 char *x;
179 int udp53;
180 int fd;
181 stralloc ifname = {0};
182 uint32 ifidx = 0;
183 struct stat st;
184
185 x = env_get("IP");
186 if (!x)
187 logmsg(fatal,111,ERROR,"IP not set");
188 if (case_equals(x,"::")) {
189 flagipv6anycast = 1;
190 } else if (case_equals(x,":0")) {
191 flagdualstack = 1;
192 byte_copy(x,2,"::");
193 }
194 if (!ip6_ifscan(x,ip,&ifname))
195 logmsg(fatal,111,FATAL,B("unable to parse IPv6 address: ",x));
196
197 if (ifname.len > 1) ifidx = socket_getifidx(ifname.s);
198
199 if (ip6_isv4mapped(ip))
200 udp53 = socket_udp4();
201 else
202 udp53 = socket_udp();
203 if (udp53 == -1)
204 logmsg(fatal,111,FATAL,"unable to create UDP socket");
205
206 if (flagdualstack) socket_dualstack(udp53);
207 if (flagipv6anycast) socket_ip6anycast(udp53);
208 if (socket_bind_reuse(udp53,ip,dnsport,ifidx) == -1)
209 logmsg(fatal,111,FATAL,"unable to bind to UDP socket");
210
211 /* If no CURVEDNS_PRIVATE_KEY is supplied, go for normal mode */
212
213 if (!stat("env/CURVEDNS_PRIVATE_KEY",&st)) {
214 fd = open_read("env/CURVEDNS_PRIVATE_KEY");
215 if (fd == -1) logmsg(fatal,111,FATAL,"unable read CURVEDNS_PRIVATE_KEY");
216 len = read(fd,&curvekey,32);
217 close(fd);
218 if (len != 32) logmsg(fatal,111,FATAL,"error reading CURVEDNS_PRIVATE_KEY");
219 logmsg(fatal,0,INFO,"DNSCurve support enabled");
220 flagcurved = 1;
221 } else {
222 flagcurved = 0;
223 }
224
226
227 init_server();
228
229 ndelay_off(udp53);
230 socket_tryreservein(udp53,65536);
231
233
234 for (;;) {
235 len = socket_recv(udp53,buf,sizeof(buf),ip,&port,&ifidx);
236 if (len < 0) continue;
237 if (!doit()) continue;
238 if (ip6_isv4mapped(ip))
239 socket_send4(udp53,response,response_len,ip + 12,port);
240 else
241 socket_send(udp53,response,response_len,ip,port,ifidx);
242 /* may block for buffer space; if it fails, too bad */
243 }
244}
int fd
Definition: axfr-get.c:103
unsigned int doit(char *buf, unsigned int len, unsigned int pos)
Definition: axfr-get.c:131
unsigned long port
Definition: axfrdns.c:126
char ip[16]
Definition: axfrdns.c:125
uint16 len
Definition: axfrdns.c:319
char buf[MSGSIZE]
Definition: axfrdns.c:318
int dns_curve_txtquery(const char *buf, const unsigned int len, const unsigned int pos)
Definition: curve.c:78
int dns_curve_txtpubkey(uint8 *pubkey, const char *buf, const unsigned int pos)
Definition: curve.c:128
int dns_curve_cryptobox(uint8 *cryptobox, const char *buf, const unsigned int len, const unsigned int pos)
Definition: curve.c:53
int dns_curve_pubkey(uint8 *pubkey, const char *buf, const unsigned int pos)
Definition: curve.c:41
int dns_curve_query(const char *buf, const unsigned int len, const unsigned int pos)
Definition: curve.c:33
int response_alttxt(const uint8 *secret, const uint8 *nonce, const char id[2], const unsigned char *query, const unsigned int len, const int rd)
Definition: curve.c:195
int dns_curve_nonce(uint8 *nonce, const char *buf, const unsigned int pos)
Definition: curve.c:47
int dns_curve_txtqname(uint8 *base32box, const char *buf, const unsigned int len)
Definition: curve.c:101
int dns_curve_txtnonce(uint8 *nonce, const uint8 *base32box)
Definition: curve.c:135
int response_stream(const uint8 *secret, const uint8 *nonce)
Definition: curve.c:152
#define crypto_box_beforenm
Definition: curve.h:12
#define crypto_box_open_afternm
Definition: curve.h:15
#define DNS_T_AXFR
Definition: dns.h:84
#define DNS_C_IN
Definition: dns.h:53
#define DNS_C_ANY
Definition: dns.h:54
#define MAXMSGSIZE
Definition: dns.h:40
unsigned int dns_domain_length(const char *dn)
Definition: dns_domain.c:6
unsigned int dns_packet_getname(const char *buf, unsigned int len, unsigned int pos, char **d)
Definition: dns_packet.c:35
unsigned int dns_packet_copy(const char *buf, unsigned int len, unsigned int pos, char *out, unsigned int outlen)
Definition: dns_packet.c:8
uint32 ifidx
Definition: dnscache.c:32
stralloc ifname
Definition: dnscache.c:31
struct line * x
void droproot(const char *fatal)
Definition: droproot.c:8
void qlog(const char *, uint16, const char *, const char *, const char *, const char *)
void log_start(const char *, const char *, uint32)
void response_id(const char *)
char response[]
Definition: response.c:6
unsigned int response_len
Definition: response.c:7
int response_query(const char *, const char *, const char *)
int flagipv6anycast
Definition: server.c:28
int flagcurved
Definition: rbldns.c:17
void init_server(void)
Definition: rbldns.c:162
int respond(char *, char *, char *)
char * fatal
Definition: rbldns.c:16
unsigned char curvekey[32]
Definition: server.c:33
void nomem()
Definition: server.c:40
char * starting
Definition: rbldns.c:160
uint16 dnsport
Definition: server.c:22
int main()
Definition: server.c:176
int flagdualstack
Definition: server.c:27