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