mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-03 12:11:33 +01:00
dirmngr: New libdns snapshot
This commit is contained in:
parent
f6acd04264
commit
f8ab2c4c70
213
dirmngr/dns.c
213
dirmngr/dns.c
@ -4585,10 +4585,11 @@ dns_error_t dns_trace_fput(const struct dns_trace_event *te, const void *data, s
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void dns_trace_setcname(struct dns_trace *trace, const char *host, const struct sockaddr *addr) {
|
static void dns_trace_setcname(struct dns_trace *trace, const char *host, const struct sockaddr *addr) {
|
||||||
|
struct dns_trace_cname *cname;
|
||||||
if (!trace || !trace->fp)
|
if (!trace || !trace->fp)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
struct dns_trace_cname *cname = &trace->cnames.base[trace->cnames.p];
|
cname = &trace->cnames.base[trace->cnames.p];
|
||||||
dns_strlcpy(cname->host, host, sizeof cname->host);
|
dns_strlcpy(cname->host, host, sizeof cname->host);
|
||||||
memcpy(&cname->addr, addr, DNS_PP_MIN(dns_sa_len(addr), sizeof cname->addr));
|
memcpy(&cname->addr, addr, DNS_PP_MIN(dns_sa_len(addr), sizeof cname->addr));
|
||||||
|
|
||||||
@ -4609,10 +4610,10 @@ static const char *dns_trace_cname(struct dns_trace *trace, const struct sockadd
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void dns_trace_res_submit(struct dns_trace *trace, const char *qname, enum dns_type qtype, enum dns_class qclass, int error) {
|
static void dns_trace_res_submit(struct dns_trace *trace, const char *qname, enum dns_type qtype, enum dns_class qclass, int error) {
|
||||||
|
struct dns_trace_event te;
|
||||||
if (!trace || !trace->fp)
|
if (!trace || !trace->fp)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
struct dns_trace_event te;
|
|
||||||
dns_te_init(&te, DNS_TE_RES_SUBMIT);
|
dns_te_init(&te, DNS_TE_RES_SUBMIT);
|
||||||
dns_strlcpy(te.res_submit.qname, qname, sizeof te.res_submit.qname);
|
dns_strlcpy(te.res_submit.qname, qname, sizeof te.res_submit.qname);
|
||||||
te.res_submit.qtype = qtype;
|
te.res_submit.qtype = qtype;
|
||||||
@ -4622,25 +4623,27 @@ static void dns_trace_res_submit(struct dns_trace *trace, const char *qname, enu
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void dns_trace_res_fetch(struct dns_trace *trace, const struct dns_packet *packet, int error) {
|
static void dns_trace_res_fetch(struct dns_trace *trace, const struct dns_packet *packet, int error) {
|
||||||
|
struct dns_trace_event te;
|
||||||
|
const void *data;
|
||||||
|
size_t datasize;
|
||||||
if (!trace || !trace->fp)
|
if (!trace || !trace->fp)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
struct dns_trace_event te;
|
|
||||||
dns_te_init(&te, DNS_TE_RES_FETCH);
|
dns_te_init(&te, DNS_TE_RES_FETCH);
|
||||||
const void *data = (packet)? packet->data : NULL;
|
data = (packet)? packet->data : NULL;
|
||||||
size_t datasize = (packet)? packet->end : 0;
|
datasize = (packet)? packet->end : 0;
|
||||||
te.res_fetch.error = error;
|
te.res_fetch.error = error;
|
||||||
dns_trace_tag_and_put(trace, &te, data, datasize);
|
dns_trace_tag_and_put(trace, &te, data, datasize);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dns_trace_so_submit(struct dns_trace *trace, const struct dns_packet *packet, const struct sockaddr *haddr, int error) {
|
static void dns_trace_so_submit(struct dns_trace *trace, const struct dns_packet *packet, const struct sockaddr *haddr, int error) {
|
||||||
|
struct dns_trace_event te;
|
||||||
|
const char *cname;
|
||||||
if (!trace || !trace->fp)
|
if (!trace || !trace->fp)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
struct dns_trace_event te;
|
|
||||||
dns_te_init(&te, DNS_TE_SO_SUBMIT);
|
dns_te_init(&te, DNS_TE_SO_SUBMIT);
|
||||||
memcpy(&te.so_submit.haddr, haddr, DNS_PP_MIN(dns_sa_len(haddr), sizeof te.so_submit.haddr));
|
memcpy(&te.so_submit.haddr, haddr, DNS_PP_MIN(dns_sa_len(haddr), sizeof te.so_submit.haddr));
|
||||||
const char *cname;
|
|
||||||
if ((cname = dns_trace_cname(trace, haddr)))
|
if ((cname = dns_trace_cname(trace, haddr)))
|
||||||
dns_strlcpy(te.so_submit.hname, cname, sizeof te.so_submit.hname);
|
dns_strlcpy(te.so_submit.hname, cname, sizeof te.so_submit.hname);
|
||||||
te.so_submit.error = error;
|
te.so_submit.error = error;
|
||||||
@ -4648,32 +4651,34 @@ static void dns_trace_so_submit(struct dns_trace *trace, const struct dns_packet
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void dns_trace_so_verify(struct dns_trace *trace, const struct dns_packet *packet, int error) {
|
static void dns_trace_so_verify(struct dns_trace *trace, const struct dns_packet *packet, int error) {
|
||||||
|
struct dns_trace_event te;
|
||||||
if (!trace || !trace->fp)
|
if (!trace || !trace->fp)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
struct dns_trace_event te;
|
|
||||||
dns_te_init(&te, DNS_TE_SO_VERIFY);
|
dns_te_init(&te, DNS_TE_SO_VERIFY);
|
||||||
te.so_verify.error = error;
|
te.so_verify.error = error;
|
||||||
dns_trace_tag_and_put(trace, &te, packet->data, packet->end);
|
dns_trace_tag_and_put(trace, &te, packet->data, packet->end);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dns_trace_so_fetch(struct dns_trace *trace, const struct dns_packet *packet, int error) {
|
static void dns_trace_so_fetch(struct dns_trace *trace, const struct dns_packet *packet, int error) {
|
||||||
|
struct dns_trace_event te;
|
||||||
|
const void *data;
|
||||||
|
size_t datasize;
|
||||||
if (!trace || !trace->fp)
|
if (!trace || !trace->fp)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
struct dns_trace_event te;
|
|
||||||
dns_te_init(&te, DNS_TE_SO_FETCH);
|
dns_te_init(&te, DNS_TE_SO_FETCH);
|
||||||
const void *data = (packet)? packet->data : NULL;
|
data = (packet)? packet->data : NULL;
|
||||||
size_t datasize = (packet)? packet->end : 0;
|
datasize = (packet)? packet->end : 0;
|
||||||
te.so_fetch.error = error;
|
te.so_fetch.error = error;
|
||||||
dns_trace_tag_and_put(trace, &te, data, datasize);
|
dns_trace_tag_and_put(trace, &te, data, datasize);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dns_trace_sys_connect(struct dns_trace *trace, int fd, int socktype, const struct sockaddr *dst, int error) {
|
static void dns_trace_sys_connect(struct dns_trace *trace, int fd, int socktype, const struct sockaddr *dst, int error) {
|
||||||
|
struct dns_trace_event te;
|
||||||
if (!trace || !trace->fp)
|
if (!trace || !trace->fp)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
struct dns_trace_event te;
|
|
||||||
dns_te_init(&te, DNS_TE_SYS_CONNECT);
|
dns_te_init(&te, DNS_TE_SYS_CONNECT);
|
||||||
dns_te_initname(&te.sys_connect.src, fd, &getsockname);
|
dns_te_initname(&te.sys_connect.src, fd, &getsockname);
|
||||||
memcpy(&te.sys_connect.dst, dst, DNS_PP_MIN(dns_sa_len(dst), sizeof te.sys_connect.dst));
|
memcpy(&te.sys_connect.dst, dst, DNS_PP_MIN(dns_sa_len(dst), sizeof te.sys_connect.dst));
|
||||||
@ -4683,10 +4688,10 @@ static void dns_trace_sys_connect(struct dns_trace *trace, int fd, int socktype,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void dns_trace_sys_send(struct dns_trace *trace, int fd, int socktype, const void *data, size_t datasize, int error) {
|
static void dns_trace_sys_send(struct dns_trace *trace, int fd, int socktype, const void *data, size_t datasize, int error) {
|
||||||
|
struct dns_trace_event te;
|
||||||
if (!trace || !trace->fp)
|
if (!trace || !trace->fp)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
struct dns_trace_event te;
|
|
||||||
dns_te_init(&te, DNS_TE_SYS_SEND);
|
dns_te_init(&te, DNS_TE_SYS_SEND);
|
||||||
dns_te_initnames(&te.sys_send.src, &te.sys_send.dst, fd);
|
dns_te_initnames(&te.sys_send.src, &te.sys_send.dst, fd);
|
||||||
te.sys_send.socktype = socktype;
|
te.sys_send.socktype = socktype;
|
||||||
@ -4695,10 +4700,10 @@ static void dns_trace_sys_send(struct dns_trace *trace, int fd, int socktype, co
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void dns_trace_sys_recv(struct dns_trace *trace, int fd, int socktype, const void *data, size_t datasize, int error) {
|
static void dns_trace_sys_recv(struct dns_trace *trace, int fd, int socktype, const void *data, size_t datasize, int error) {
|
||||||
|
struct dns_trace_event te;
|
||||||
if (!trace || !trace->fp)
|
if (!trace || !trace->fp)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
struct dns_trace_event te;
|
|
||||||
dns_te_init(&te, DNS_TE_SYS_RECV);
|
dns_te_init(&te, DNS_TE_SYS_RECV);
|
||||||
dns_te_initnames(&te.sys_recv.dst, &te.sys_recv.src, fd);
|
dns_te_initnames(&te.sys_recv.dst, &te.sys_recv.src, fd);
|
||||||
te.sys_recv.socktype = socktype;
|
te.sys_recv.socktype = socktype;
|
||||||
@ -4710,6 +4715,9 @@ static dns_error_t dns_trace_dump_packet(struct dns_trace *trace, const char *pr
|
|||||||
struct dns_packet *packet = NULL;
|
struct dns_packet *packet = NULL;
|
||||||
char *line = NULL, *p;
|
char *line = NULL, *p;
|
||||||
size_t size = 1, skip = 0;
|
size_t size = 1, skip = 0;
|
||||||
|
struct dns_rr_i records;
|
||||||
|
struct dns_p_lines_i lines;
|
||||||
|
size_t len, count;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if (!(packet = dns_p_make(datasize, &error)))
|
if (!(packet = dns_p_make(datasize, &error)))
|
||||||
@ -4724,9 +4732,9 @@ resize:
|
|||||||
line = p;
|
line = p;
|
||||||
size *= 2;
|
size *= 2;
|
||||||
|
|
||||||
struct dns_rr_i records = { 0 };
|
memset(&records, 0, sizeof records);
|
||||||
struct dns_p_lines_i lines = { 0 };
|
memset(&lines, 0, sizeof lines);
|
||||||
size_t len, count = 0;
|
count = 0;
|
||||||
|
|
||||||
while ((len = dns_p_lines(line, size, &error, packet, &records, &lines))) {
|
while ((len = dns_p_lines(line, size, &error, packet, &records, &lines))) {
|
||||||
if (!(len < size)) {
|
if (!(len < size)) {
|
||||||
@ -4899,22 +4907,22 @@ dns_error_t dns_trace_dump(struct dns_trace *trace, FILE *fp) {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case DNS_TE_SYS_CONNECT: {
|
case DNS_TE_SYS_CONNECT: {
|
||||||
|
int socktype = te->sys_connect.socktype;
|
||||||
fprintf(fp, "dns_sys_connect:\n");
|
fprintf(fp, "dns_sys_connect:\n");
|
||||||
dns_trace_dump_meta(trace, " ", te, state.elapsed, fp);
|
dns_trace_dump_meta(trace, " ", te, state.elapsed, fp);
|
||||||
dns_trace_dump_addr(trace, " src: ", &te->sys_connect.src, fp);
|
dns_trace_dump_addr(trace, " src: ", &te->sys_connect.src, fp);
|
||||||
dns_trace_dump_addr(trace, " dst: ", &te->sys_connect.dst, fp);
|
dns_trace_dump_addr(trace, " dst: ", &te->sys_connect.dst, fp);
|
||||||
int socktype = te->sys_connect.socktype;
|
|
||||||
fprintf(fp, " socktype: %d (%s)\n", socktype, ((socktype == SOCK_STREAM)? "SOCK_STREAM" : (socktype == SOCK_DGRAM)? "SOCK_DGRAM" : "?"));
|
fprintf(fp, " socktype: %d (%s)\n", socktype, ((socktype == SOCK_STREAM)? "SOCK_STREAM" : (socktype == SOCK_DGRAM)? "SOCK_DGRAM" : "?"));
|
||||||
dns_trace_dump_error(trace, " error: ", te->sys_connect.error, fp);
|
dns_trace_dump_error(trace, " error: ", te->sys_connect.error, fp);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DNS_TE_SYS_SEND: {
|
case DNS_TE_SYS_SEND: {
|
||||||
|
int socktype = te->sys_send.socktype;
|
||||||
fprintf(fp, "dns_sys_send:\n");
|
fprintf(fp, "dns_sys_send:\n");
|
||||||
dns_trace_dump_meta(trace, " ", te, state.elapsed, fp);
|
dns_trace_dump_meta(trace, " ", te, state.elapsed, fp);
|
||||||
dns_trace_dump_addr(trace, " src: ", &te->sys_send.src, fp);
|
dns_trace_dump_addr(trace, " src: ", &te->sys_send.src, fp);
|
||||||
dns_trace_dump_addr(trace, " dst: ", &te->sys_send.dst, fp);
|
dns_trace_dump_addr(trace, " dst: ", &te->sys_send.dst, fp);
|
||||||
int socktype = te->sys_send.socktype;
|
|
||||||
fprintf(fp, " socktype: %d (%s)\n", socktype, ((socktype == SOCK_STREAM)? "SOCK_STREAM" : (socktype == SOCK_DGRAM)? "SOCK_DGRAM" : "?"));
|
fprintf(fp, " socktype: %d (%s)\n", socktype, ((socktype == SOCK_STREAM)? "SOCK_STREAM" : (socktype == SOCK_DGRAM)? "SOCK_DGRAM" : "?"));
|
||||||
dns_trace_dump_error(trace, " error: ", te->sys_send.error, fp);
|
dns_trace_dump_error(trace, " error: ", te->sys_send.error, fp);
|
||||||
|
|
||||||
@ -4927,11 +4935,11 @@ dns_error_t dns_trace_dump(struct dns_trace *trace, FILE *fp) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DNS_TE_SYS_RECV: {
|
case DNS_TE_SYS_RECV: {
|
||||||
|
int socktype = te->sys_recv.socktype;
|
||||||
fprintf(fp, "dns_sys_recv:\n");
|
fprintf(fp, "dns_sys_recv:\n");
|
||||||
dns_trace_dump_meta(trace, " ", te, state.elapsed, fp);
|
dns_trace_dump_meta(trace, " ", te, state.elapsed, fp);
|
||||||
dns_trace_dump_addr(trace, " src: ", &te->sys_recv.src, fp);
|
dns_trace_dump_addr(trace, " src: ", &te->sys_recv.src, fp);
|
||||||
dns_trace_dump_addr(trace, " dst: ", &te->sys_recv.dst, fp);
|
dns_trace_dump_addr(trace, " dst: ", &te->sys_recv.dst, fp);
|
||||||
int socktype = te->sys_recv.socktype;
|
|
||||||
fprintf(fp, " socktype: %d (%s)\n", socktype, ((socktype == SOCK_STREAM)? "SOCK_STREAM" : (socktype == SOCK_DGRAM)? "SOCK_DGRAM" : "?"));
|
fprintf(fp, " socktype: %d (%s)\n", socktype, ((socktype == SOCK_STREAM)? "SOCK_STREAM" : (socktype == SOCK_DGRAM)? "SOCK_DGRAM" : "?"));
|
||||||
dns_trace_dump_error(trace, " error: ", te->sys_recv.error, fp);
|
dns_trace_dump_error(trace, " error: ", te->sys_recv.error, fp);
|
||||||
|
|
||||||
@ -7118,8 +7126,11 @@ enum {
|
|||||||
|
|
||||||
DNS_SO_SOCKS_INIT,
|
DNS_SO_SOCKS_INIT,
|
||||||
DNS_SO_SOCKS_CONN,
|
DNS_SO_SOCKS_CONN,
|
||||||
|
DNS_SO_SOCKS_HELLO_SEND,
|
||||||
|
DNS_SO_SOCKS_HELLO_RECV,
|
||||||
DNS_SO_SOCKS_AUTH_SEND,
|
DNS_SO_SOCKS_AUTH_SEND,
|
||||||
DNS_SO_SOCKS_AUTH_RECV,
|
DNS_SO_SOCKS_AUTH_RECV,
|
||||||
|
DNS_SO_SOCKS_REQUEST_PREPARE,
|
||||||
DNS_SO_SOCKS_REQUEST_SEND,
|
DNS_SO_SOCKS_REQUEST_SEND,
|
||||||
DNS_SO_SOCKS_REQUEST_RECV,
|
DNS_SO_SOCKS_REQUEST_RECV,
|
||||||
DNS_SO_SOCKS_REQUEST_RECV_V6,
|
DNS_SO_SOCKS_REQUEST_RECV_V6,
|
||||||
@ -7424,6 +7435,30 @@ static _Bool dns_so_tcp_keep(struct dns_socket *so) {
|
|||||||
} /* dns_so_tcp_keep() */
|
} /* dns_so_tcp_keep() */
|
||||||
|
|
||||||
|
|
||||||
|
/* Convenience functions for sending non-DNS data. */
|
||||||
|
|
||||||
|
/* Set up everything for sending LENGTH octets. Returns the buffer
|
||||||
|
for the data. */
|
||||||
|
static unsigned char *dns_so_tcp_send_buffer(struct dns_socket *so, size_t length) {
|
||||||
|
/* Skip the length octets, we are not doing DNS. */
|
||||||
|
so->qout = 2;
|
||||||
|
so->query->end = length;
|
||||||
|
return so->query->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up everything for receiving LENGTH octets. */
|
||||||
|
static void dns_so_tcp_recv_expect(struct dns_socket *so, size_t length) {
|
||||||
|
/* Skip the length octets, we are not doing DNS. */
|
||||||
|
so->apos = 2;
|
||||||
|
so->alen = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns the buffer containing the received data. */
|
||||||
|
static unsigned char *dns_so_tcp_recv_buffer(struct dns_socket *so) {
|
||||||
|
return so->answer->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if defined __clang__
|
#if defined __clang__
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
#pragma clang diagnostic ignored "-Warray-bounds"
|
#pragma clang diagnostic ignored "-Warray-bounds"
|
||||||
@ -7500,10 +7535,7 @@ static int dns_so_tcp_recv(struct dns_socket *so) {
|
|||||||
int dns_so_check(struct dns_socket *so) {
|
int dns_so_check(struct dns_socket *so) {
|
||||||
int error;
|
int error;
|
||||||
size_t n;
|
size_t n;
|
||||||
|
|
||||||
/* XXX */
|
|
||||||
unsigned char *buffer;
|
unsigned char *buffer;
|
||||||
int method;
|
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
switch (so->state) {
|
switch (so->state) {
|
||||||
@ -7595,7 +7627,9 @@ retry:
|
|||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
so->state++;
|
so->state++;
|
||||||
case DNS_SO_SOCKS_CONN:
|
case DNS_SO_SOCKS_CONN: {
|
||||||
|
unsigned char method;
|
||||||
|
|
||||||
error = dns_connect(so->tcp, (struct sockaddr *)so->opts.socks_host, dns_sa_len(so->opts.socks_host));
|
error = dns_connect(so->tcp, (struct sockaddr *)so->opts.socks_host, dns_sa_len(so->opts.socks_host));
|
||||||
dns_trace_sys_connect(so->trace, so->tcp, SOCK_STREAM, (struct sockaddr *)so->opts.socks_host, error);
|
dns_trace_sys_connect(so->trace, so->tcp, SOCK_STREAM, (struct sockaddr *)so->opts.socks_host, error);
|
||||||
if (error && error != DNS_EISCONN)
|
if (error && error != DNS_EISCONN)
|
||||||
@ -7609,37 +7643,32 @@ retry:
|
|||||||
/* Create a new buffer for the handshake. */
|
/* Create a new buffer for the handshake. */
|
||||||
dns_p_grow(&so->query);
|
dns_p_grow(&so->query);
|
||||||
|
|
||||||
/* Skip the two octets length field when
|
|
||||||
transmitting, send three octets. */
|
|
||||||
so->qout = 2;
|
|
||||||
so->query->end = 3;
|
|
||||||
buffer = so->query->data;
|
|
||||||
|
|
||||||
/* Negotiate method. */
|
/* Negotiate method. */
|
||||||
|
buffer = dns_so_tcp_send_buffer(so, 3);
|
||||||
buffer[0] = 5; /* RFC-1928 VER field. */
|
buffer[0] = 5; /* RFC-1928 VER field. */
|
||||||
buffer[1] = 1; /* NMETHODS */
|
buffer[1] = 1; /* NMETHODS */
|
||||||
if (0 /* XXX */)
|
if (so->opts.socks_user)
|
||||||
method = 2; /* Method: username/password authentication. */
|
method = 2; /* Method: username/password authentication. */
|
||||||
else
|
else
|
||||||
method = 0; /* Method: No authentication required. */
|
method = 0; /* Method: No authentication required. */
|
||||||
buffer[2] = method;
|
buffer[2] = method;
|
||||||
|
|
||||||
so->state++;
|
so->state++;
|
||||||
case DNS_SO_SOCKS_AUTH_SEND:
|
}
|
||||||
|
case DNS_SO_SOCKS_HELLO_SEND:
|
||||||
if ((error = dns_so_tcp_send(so)))
|
if ((error = dns_so_tcp_send(so)))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* Skip the two length octets, and receive two octets. */
|
dns_so_tcp_recv_expect(so, 2);
|
||||||
so->apos = 2;
|
|
||||||
so->alen = 2;
|
|
||||||
|
|
||||||
so->state++;
|
so->state++;
|
||||||
case DNS_SO_SOCKS_AUTH_RECV:
|
case DNS_SO_SOCKS_HELLO_RECV: {
|
||||||
|
unsigned char method;
|
||||||
|
|
||||||
if ((error = dns_so_tcp_recv(so)))
|
if ((error = dns_so_tcp_recv(so)))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
buffer = so->answer->data;
|
buffer = dns_so_tcp_recv_buffer(so);
|
||||||
method = 0; /* XXX authentication not yet supported */
|
method = so->opts.socks_user ? 2 : 0;
|
||||||
if (buffer[0] != 5 || buffer[1] != method) {
|
if (buffer[0] != 5 || buffer[1] != method) {
|
||||||
/* Socks server returned wrong version or does
|
/* Socks server returned wrong version or does
|
||||||
not support our requested method. */
|
not support our requested method. */
|
||||||
@ -7647,12 +7676,67 @@ retry:
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip the two octets length field when
|
if (method == 0) {
|
||||||
transmitting. */
|
/* No authentication, go ahead and send the
|
||||||
so->qout = 2;
|
request. */
|
||||||
buffer = so->query->data;
|
so->state = DNS_SO_SOCKS_REQUEST_PREPARE;
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prepare username/password sub-negotiation. */
|
||||||
|
if (! so->opts.socks_password) {
|
||||||
|
error = EINVAL; /* No password given. */
|
||||||
|
goto error;
|
||||||
|
} else {
|
||||||
|
size_t buflen, ulen, plen;
|
||||||
|
|
||||||
|
ulen = strlen(so->opts.socks_user);
|
||||||
|
plen = strlen(so->opts.socks_password);
|
||||||
|
if (!ulen || ulen > 255 || !plen || plen > 255) {
|
||||||
|
error = EINVAL; /* Credentials too long or too short. */
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = dns_so_tcp_send_buffer(so, 3 + ulen + plen);
|
||||||
|
buffer[0] = 1; /* VER of the sub-negotiation. */
|
||||||
|
buffer[1] = (unsigned char) ulen;
|
||||||
|
buflen = 2;
|
||||||
|
memcpy (buffer+buflen, so->opts.socks_user, ulen);
|
||||||
|
buflen += ulen;
|
||||||
|
buffer[buflen++] = (unsigned char) plen;
|
||||||
|
memcpy (buffer+buflen, so->opts.socks_password, plen);
|
||||||
|
}
|
||||||
|
|
||||||
|
so->state++;
|
||||||
|
}
|
||||||
|
case DNS_SO_SOCKS_AUTH_SEND:
|
||||||
|
if ((error = dns_so_tcp_send(so)))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
/* Skip the two length octets, and receive two octets. */
|
||||||
|
dns_so_tcp_recv_expect(so, 2);
|
||||||
|
|
||||||
|
so->state++;
|
||||||
|
case DNS_SO_SOCKS_AUTH_RECV:
|
||||||
|
if ((error = dns_so_tcp_recv(so)))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
buffer = dns_so_tcp_recv_buffer(so);
|
||||||
|
if (buffer[0] != 1) {
|
||||||
|
/* SOCKS server returned wrong version. */
|
||||||
|
error = EPROTO;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (buffer[1]) {
|
||||||
|
/* SOCKS server denied access. */
|
||||||
|
error = EACCES;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
so->state++;
|
||||||
|
case DNS_SO_SOCKS_REQUEST_PREPARE:
|
||||||
/* Send request details (rfc-1928, 4). */
|
/* Send request details (rfc-1928, 4). */
|
||||||
|
buffer = dns_so_tcp_send_buffer(so, so->remote.ss_family == AF_INET6 ? 22 : 10);
|
||||||
buffer[0] = 5; /* VER */
|
buffer[0] = 5; /* VER */
|
||||||
buffer[1] = 1; /* CMD = CONNECT */
|
buffer[1] = 1; /* CMD = CONNECT */
|
||||||
buffer[2] = 0; /* RSV */
|
buffer[2] = 0; /* RSV */
|
||||||
@ -7662,14 +7746,12 @@ retry:
|
|||||||
buffer[3] = 4; /* ATYP = IPv6 */
|
buffer[3] = 4; /* ATYP = IPv6 */
|
||||||
memcpy (buffer+ 4, &addr_in6->sin6_addr.s6_addr, 16); /* DST.ADDR */
|
memcpy (buffer+ 4, &addr_in6->sin6_addr.s6_addr, 16); /* DST.ADDR */
|
||||||
memcpy (buffer+20, &addr_in6->sin6_port, 2); /* DST.PORT */
|
memcpy (buffer+20, &addr_in6->sin6_port, 2); /* DST.PORT */
|
||||||
so->query->end = 22;
|
|
||||||
} else {
|
} else {
|
||||||
struct sockaddr_in *addr_in = (struct sockaddr_in *)&so->remote;
|
struct sockaddr_in *addr_in = (struct sockaddr_in *)&so->remote;
|
||||||
|
|
||||||
buffer[3] = 1; /* ATYP = IPv4 */
|
buffer[3] = 1; /* ATYP = IPv4 */
|
||||||
memcpy (buffer+4, &addr_in->sin_addr.s_addr, 4); /* DST.ADDR */
|
memcpy (buffer+4, &addr_in->sin_addr.s_addr, 4); /* DST.ADDR */
|
||||||
memcpy (buffer+8, &addr_in->sin_port, 2); /* DST.PORT */
|
memcpy (buffer+8, &addr_in->sin_port, 2); /* DST.PORT */
|
||||||
so->query->end = 10;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
so->state++;
|
so->state++;
|
||||||
@ -7677,18 +7759,15 @@ retry:
|
|||||||
if ((error = dns_so_tcp_send(so)))
|
if ((error = dns_so_tcp_send(so)))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* Skip the two length octets, and receive ten octets.
|
/* Expect ten octets. This is the length of the
|
||||||
* This is the length of the response assuming a IPv4
|
* response assuming a IPv4 address is used. */
|
||||||
* address is used. */
|
dns_so_tcp_recv_expect(so, 10);
|
||||||
so->apos = 2;
|
|
||||||
so->alen = 10;
|
|
||||||
|
|
||||||
so->state++;
|
so->state++;
|
||||||
case DNS_SO_SOCKS_REQUEST_RECV:
|
case DNS_SO_SOCKS_REQUEST_RECV:
|
||||||
if ((error = dns_so_tcp_recv(so)))
|
if ((error = dns_so_tcp_recv(so)))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
buffer = so->answer->data;
|
buffer = dns_so_tcp_recv_buffer(so);
|
||||||
if (buffer[0] != 5 || buffer[2] != 0) {
|
if (buffer[0] != 5 || buffer[2] != 0) {
|
||||||
/* Socks server returned wrong version or the
|
/* Socks server returned wrong version or the
|
||||||
reserved field is not zero. */
|
reserved field is not zero. */
|
||||||
@ -7737,13 +7816,10 @@ retry:
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ATYP indicates a v6 address. Skip the two length
|
/* Expect receive twelve octets. This accounts for
|
||||||
* octets, and receive twelve octets. This accounts
|
* the remaining bytes assuming an IPv6 address is
|
||||||
* for the remaining bytes assuming an IPv6 address is
|
|
||||||
* used. */
|
* used. */
|
||||||
so->apos = 2;
|
dns_so_tcp_recv_expect(so, 12);
|
||||||
so->alen = 12;
|
|
||||||
|
|
||||||
so->state++;
|
so->state++;
|
||||||
case DNS_SO_SOCKS_REQUEST_RECV_V6:
|
case DNS_SO_SOCKS_REQUEST_RECV_V6:
|
||||||
if ((error = dns_so_tcp_recv(so)))
|
if ((error = dns_so_tcp_recv(so)))
|
||||||
@ -9997,6 +10073,8 @@ struct {
|
|||||||
} memo;
|
} memo;
|
||||||
|
|
||||||
struct sockaddr_storage socks_host;
|
struct sockaddr_storage socks_host;
|
||||||
|
const char *socks_user;
|
||||||
|
const char *socks_password;
|
||||||
} MAIN = {
|
} MAIN = {
|
||||||
.sort = &dns_rr_i_packet,
|
.sort = &dns_rr_i_packet,
|
||||||
};
|
};
|
||||||
@ -10679,7 +10757,9 @@ static int resolve_query(int argc DNS_NOTUSED, char *argv[]) {
|
|||||||
resconf()->options.recurse = recurse;
|
resconf()->options.recurse = recurse;
|
||||||
|
|
||||||
if (!(R = dns_res_open(resconf(), hosts(), dns_hints_mortal(hints(resconf(), &error)), cache(),
|
if (!(R = dns_res_open(resconf(), hosts(), dns_hints_mortal(hints(resconf(), &error)), cache(),
|
||||||
dns_opts(.socks_host=&MAIN.socks_host), &error)))
|
dns_opts(.socks_host=&MAIN.socks_host,
|
||||||
|
.socks_user=MAIN.socks_user,
|
||||||
|
.socks_password=MAIN.socks_password), &error)))
|
||||||
panic("%s: %s", MAIN.qname, dns_strerror(error));
|
panic("%s: %s", MAIN.qname, dns_strerror(error));
|
||||||
|
|
||||||
dns_res_settrace(R, trace("w+b"));
|
dns_res_settrace(R, trace("w+b"));
|
||||||
@ -10966,6 +11046,7 @@ static void print_usage(const char *progname, FILE *fp) {
|
|||||||
" -s HOW Sort records\n"
|
" -s HOW Sort records\n"
|
||||||
" -S ADDR Address of SOCKS server to use\n"
|
" -S ADDR Address of SOCKS server to use\n"
|
||||||
" -P PORT Port of SOCKS server to use\n"
|
" -P PORT Port of SOCKS server to use\n"
|
||||||
|
" -A USER:PASSWORD Credentials for the SOCKS server\n"
|
||||||
" -f PATH Path to trace file\n"
|
" -f PATH Path to trace file\n"
|
||||||
" -v Be more verbose (-vv show packets; -vvv hexdump packets)\n"
|
" -v Be more verbose (-vv show packets; -vvv hexdump packets)\n"
|
||||||
" -V Print version info\n"
|
" -V Print version info\n"
|
||||||
@ -11022,7 +11103,7 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
atexit(&main_exit);
|
atexit(&main_exit);
|
||||||
|
|
||||||
while (-1 != (ch = getopt(argc, argv, "q:t:c:n:l:z:s:S:P:f:vVh"))) {
|
while (-1 != (ch = getopt(argc, argv, "q:t:c:n:l:z:s:S:P:A:f:vVh"))) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'c':
|
case 'c':
|
||||||
assert(MAIN.resconf.count < lengthof(MAIN.resconf.path));
|
assert(MAIN.resconf.count < lengthof(MAIN.resconf.path));
|
||||||
@ -11102,6 +11183,18 @@ int main(int argc, char **argv) {
|
|||||||
*dns_sa_port(MAIN.socks_host.ss_family, &MAIN.socks_host) = htons(atoi(optarg));
|
*dns_sa_port(MAIN.socks_host.ss_family, &MAIN.socks_host) = htons(atoi(optarg));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
case 'A': {
|
||||||
|
char *password;
|
||||||
|
if (! MAIN.socks_host.ss_family)
|
||||||
|
panic("-A without prior -S");
|
||||||
|
if (! (password = strchr(optarg, ':')))
|
||||||
|
panic("Usage: -A USER:PASSWORD");
|
||||||
|
*password = 0;
|
||||||
|
password += 1;
|
||||||
|
MAIN.socks_user = optarg;
|
||||||
|
MAIN.socks_password = password;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'f':
|
case 'f':
|
||||||
MAIN.trace = optarg;
|
MAIN.trace = optarg;
|
||||||
|
|
||||||
|
@ -533,7 +533,7 @@ struct dns_rr_i {
|
|||||||
|
|
||||||
int follow;
|
int follow;
|
||||||
|
|
||||||
int (*sort)();
|
int (*sort)(struct dns_rr *, struct dns_rr *, struct dns_rr_i *, struct dns_packet *);
|
||||||
unsigned args[2];
|
unsigned args[2];
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@ -1076,7 +1076,11 @@ struct dns_options {
|
|||||||
} events;
|
} events;
|
||||||
|
|
||||||
/* Use this SOCKS server. */
|
/* Use this SOCKS server. */
|
||||||
struct sockaddr_storage *socks_host;
|
const struct sockaddr_storage *socks_host;
|
||||||
|
|
||||||
|
/* Credentials for the SOCKS server (optional). */
|
||||||
|
const char *socks_user;
|
||||||
|
const char *socks_password;
|
||||||
}; /* struct dns_options */
|
}; /* struct dns_options */
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user