Revision 47, 2022-12-16 11:26:53 +0100 (Fri, 16 Dec 2022)
This commit is contained in:
commit
7df7cb0b6d
42
Makefile
Normal file
42
Makefile
Normal file
@ -0,0 +1,42 @@
|
||||
LOCALBASE?= /usr/local/
|
||||
|
||||
PROG= filter-dkimverify
|
||||
MAN= filter-dkimverify.8
|
||||
BINDIR= ${LOCALBASE}/libexec/smtpd/
|
||||
MANDIR= ${LOCALBASE}/man/man
|
||||
|
||||
SRCS+= main.c ltok.c unpack_dns.c
|
||||
|
||||
.ifdef HAVE_ED25519
|
||||
CFLAGS+= -DHAVE_ED25519
|
||||
.endif
|
||||
.ifdef LIBCRYPTOPC
|
||||
CRYPT_CFLAGS!= pkg-config --cflags ${LIBCRYPTOPC}
|
||||
CRYPT_LDFLAGS_L!=pkg-config --libs-only-L ${LIBCRYPTOPC}
|
||||
CRYPT_LDFLAGS_libdir!=pkg-config --variable libdir ${LIBCRYPTOPC}
|
||||
CRYPT_LDFLAGS= ${CRYPT_LDFLAGS_L}
|
||||
CRYPT_LDFLAGS+= -Wl,-rpath,${CRYPT_LDFLAGS_libdir}
|
||||
CRYPT_LDADD!= pkg-config --libs-only-l ${LIBCRYPTOPC}
|
||||
.else
|
||||
CRYPT_CFLAGS=
|
||||
CRYPT_LDFLAGS=
|
||||
CRYPT_LDADD= -lcrypto
|
||||
.endif
|
||||
|
||||
CFLAGS+= -I${LOCALBASE}/include -I${.CURDIR}/openbsd-compat
|
||||
CFLAGS+= -Wall -I${.CURDIR}
|
||||
CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes
|
||||
CFLAGS+= -Wmissing-declarations
|
||||
CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual
|
||||
CFLAGS+= -Wsign-compare
|
||||
CFLAGS+= ${CRYPT_CFLAGS}
|
||||
|
||||
LDFLAGS+= -L${LOCALBASE}/lib
|
||||
LDFLAGS+= ${CRYPT_LDFLAGS}
|
||||
LDADD+= ${CRYPT_LDADD} -lopensmtpd -levent
|
||||
DPADD= ${LIBCRYPTO}
|
||||
|
||||
bindir:
|
||||
${INSTALL} -d ${DESTDIR}${BINDIR}
|
||||
|
||||
.include <bsd.prog.mk>
|
32
filter-dkimverify.8
Normal file
32
filter-dkimverify.8
Normal file
@ -0,0 +1,32 @@
|
||||
.\" $OpenBSD$
|
||||
.\"
|
||||
.\" Copyright (c) 2019 Martijn van Duren <martijn@openbsd.org>
|
||||
.\"
|
||||
.\" Permission to use, copy, modify, and distribute this software for any
|
||||
.\" purpose with or without fee is hereby granted, provided that the above
|
||||
.\" copyright notice and this permission notice appear in all copies.
|
||||
.\"
|
||||
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate$
|
||||
.Dt FILTER-DKIMVERIFY 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm filter-dkimverify
|
||||
.Nd verifies dkim signature of messages
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
verifies the dkim signatures of messages and adds an Authentication-Results
|
||||
header to the message.
|
||||
.Sh SEE ALSO
|
||||
.Xr filter-admdscrub 8
|
||||
.Xr filter-dkimsign 8
|
||||
.Xr smtpd 8
|
175
ltok.h
Normal file
175
ltok.h
Normal file
@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2022 Martijn van Duren <martijn@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* RFC 5234 - Augmented BNF for Syntax Specifications: ABNF */
|
||||
const char *osmtpd_ltok_skip_alpha(const char *, int);
|
||||
const char *osmtpd_ltok_skip_bit(const char *, int);
|
||||
const char *osmtpd_ltok_skip_char(const char *, int);
|
||||
const char *osmtpd_ltok_skip_cr(const char *, int);
|
||||
const char *osmtpd_ltok_skip_crlf(const char *, int);
|
||||
const char *osmtpd_ltok_skip_ctl(const char *, int);
|
||||
const char *osmtpd_ltok_skip_digit(const char *, int);
|
||||
const char *osmtpd_ltok_skip_dquote(const char *, int);
|
||||
const char *osmtpd_ltok_skip_hexdig(const char *, int);
|
||||
const char *osmtpd_ltok_skip_htab(const char *, int);
|
||||
const char *osmtpd_ltok_skip_lf(const char *, int);
|
||||
const char *osmtpd_ltok_skip_octet(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sp(const char *, int);
|
||||
const char *osmtpd_ltok_skip_vchar(const char *, int);
|
||||
const char *osmtpd_ltok_skip_wsp(const char *, int);
|
||||
|
||||
/* RFC 5321 - Simple Mail Transfer Protocol */
|
||||
const char *osmtpd_ltok_skip_keyword(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sub_domain(const char *, int);
|
||||
const char *osmtpd_ltok_skip_let_dig(const char *, int);
|
||||
const char *osmtpd_ltok_skip_ldh_string(const char *, int);
|
||||
|
||||
/* RFC 5322 - Internet Message Format */
|
||||
const char *osmtpd_ltok_skip_quoted_pair(const char *, int);
|
||||
const char *osmtpd_ltok_skip_fws(const char *, int);
|
||||
const char *osmtpd_ltok_skip_ctext(const char *, int);
|
||||
const char *osmtpd_ltok_skip_ccontent(const char *, int);
|
||||
const char *osmtpd_ltok_skip_comment(const char *, int);
|
||||
const char *osmtpd_ltok_skip_cfws(const char *, int);
|
||||
const char *osmtpd_ltok_skip_atext(const char *, int);
|
||||
const char *osmtpd_ltok_skip_atom(const char *, int);
|
||||
const char *osmtpd_ltok_skip_dot_atom_text(const char *, int);
|
||||
const char *osmtpd_ltok_skip_dot_atom(const char *, int);
|
||||
const char *osmtpd_ltok_skip_qtext(const char *, int);
|
||||
const char *osmtpd_ltok_skip_qcontent(const char *, int);
|
||||
const char *osmtpd_ltok_skip_quoted_string(const char *, int);
|
||||
const char *osmtpd_ltok_skip_word(const char *, int);
|
||||
const char *osmtpd_ltok_skip_phrase(const char *, int);
|
||||
const char *osmtpd_ltok_skip_name_addr(const char *, int);
|
||||
const char *osmtpd_ltok_skip_angle_addr(const char *, int);
|
||||
const char *osmtpd_ltok_skip_display_name(const char *, int);
|
||||
const char *osmtpd_ltok_skip_addr_spec(const char *, int);
|
||||
const char *osmtpd_ltok_skip_local_part(const char *, int);
|
||||
const char *osmtpd_ltok_skip_domain(const char *, int);
|
||||
const char *osmtpd_ltok_skip_domain_literal(const char *, int);
|
||||
const char *osmtpd_ltok_skip_dtext(const char *, int);
|
||||
const char *osmtpd_ltok_skip_field_name(const char *, int);
|
||||
const char *osmtpd_ltok_skip_ftext(const char *, int);
|
||||
const char *osmtpd_ltok_skip_obs_no_ws_ctl(const char *, int);
|
||||
const char *osmtpd_ltok_skip_obs_ctext(const char *, int);
|
||||
const char *osmtpd_ltok_skip_obs_qtext(const char *, int);
|
||||
const char *osmtpd_ltok_skip_obs_qp(const char *, int);
|
||||
const char *osmtpd_ltok_skip_obs_phrase(const char *, int);
|
||||
const char *osmtpd_ltok_skip_obs_fws(const char *, int);
|
||||
const char *osmtpd_ltok_skip_obs_angle_addr(const char *, int);
|
||||
const char *osmtpd_ltok_skip_obs_route(const char *, int);
|
||||
const char *osmtpd_ltok_skip_obs_domain_list(const char *, int);
|
||||
const char *osmtpd_ltok_skip_obs_local_part(const char *, int);
|
||||
const char *osmtpd_ltok_skip_obs_domain(const char *, int);
|
||||
const char *osmtpd_ltok_skip_obs_dtext(const char *, int);
|
||||
|
||||
/* RFC 2045 - Multipurpose Internet Mail Extensions */
|
||||
const char *osmtpd_ltok_skip_value(const char *, int);
|
||||
const char *osmtpd_ltok_skip_token(const char *, int);
|
||||
const char *osmtpd_ltok_skip_tspecials(const char *, int);
|
||||
const char *osmtpd_ltok_skip_qp_section(const char *, int);
|
||||
const char *osmtpd_ltok_skip_ptext(const char *, int);
|
||||
const char *osmtpd_ltok_skip_safe_char(const char *, int);
|
||||
const char *osmtpd_ltok_skip_hex_octet(const char *, int);
|
||||
|
||||
/* RFC 6376 - DomainKeys Identified Mail (DKIM) Signatures */
|
||||
const char *osmtpd_ltok_skip_hyphenated_word(const char *, int);
|
||||
const char *osmtpd_ltok_skip_alphadigitps(const char *, int);
|
||||
const char *osmtpd_ltok_skip_base64string(const char *, int);
|
||||
const char *osmtpd_ltok_skip_hdr_name(const char *, int);
|
||||
const char *osmtpd_ltok_skip_qp_hdr_value(const char *, int);
|
||||
const char *osmtpd_ltok_skip_dkim_quoted_printable(const char *, int);
|
||||
const char *osmtpd_ltok_skip_dkim_safe_char(const char *, int);
|
||||
const char *osmtpd_ltok_skip_selector(const char *, int);
|
||||
const char *osmtpd_ltok_skip_tag_list(const char *, int);
|
||||
const char *osmtpd_ltok_skip_tag_spec(const char *, int);
|
||||
const char *osmtpd_ltok_skip_tag_name(const char *, int);
|
||||
const char *osmtpd_ltok_skip_tag_value(const char *, int);
|
||||
const char *osmtpd_ltok_skip_tval(const char *, int);
|
||||
const char *osmtpd_ltok_skip_valchar(const char *, int);
|
||||
const char *osmtpd_ltok_skip_alnumpunc(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_v_tag(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_v_tag_value(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_a_tag(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_a_tag_value(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_a_tag_alg(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_a_tag_k(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_a_tag_h(const char *, int);
|
||||
const char *osmtpd_ltok_skip_x_sig_a_tag_k(const char *, int);
|
||||
const char *osmtpd_ltok_skip_x_sig_a_tag_h(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_b_tag(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_b_tag_value(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_b_tag_data(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_bh_tag(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_bh_tag_value(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_bh_tag_data(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_c_tag(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_c_tag_value(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_c_tag_alg(const char *, int);
|
||||
const char *osmtpd_ltok_skip_x_sig_c_tag_alg(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_d_tag(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_d_tag_value(const char *, int);
|
||||
const char *osmtpd_ltok_skip_domain_name(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_h_tag(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_h_tag_value(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_i_tag(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_i_tag_value(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_l_tag(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_l_tag_value(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_q_tag(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_q_tag_value(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_q_tag_method(const char *, int);
|
||||
const char *osmtpd_ltok_skip_x_sig_q_tag_type(const char *, int);
|
||||
const char *osmtpd_ltok_skip_x_sig_q_tag_args(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_s_tag(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_s_tag_value(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_t_tag(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_t_tag_value(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_x_tag(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_x_tag_value(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_z_tag(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_z_tag_value(const char *, int);
|
||||
const char *osmtpd_ltok_skip_sig_z_tag_copy(const char *, int);
|
||||
const char *osmtpd_ltok_skip_key_v_tag(const char *, int);
|
||||
const char *osmtpd_ltok_skip_key_v_tag_value(const char *, int);
|
||||
const char *osmtpd_ltok_skip_key_h_tag(const char *, int);
|
||||
const char *osmtpd_ltok_skip_key_h_tag_value(const char *, int);
|
||||
const char *osmtpd_ltok_skip_key_h_tag_alg(const char *, int);
|
||||
const char *osmtpd_ltok_skip_x_key_h_tag_alg(const char *, int);
|
||||
const char *osmtpd_ltok_skip_key_k_tag(const char *, int);
|
||||
const char *osmtpd_ltok_skip_key_k_tag_value(const char *, int);
|
||||
const char *osmtpd_ltok_skip_key_k_tag_type(const char *, int);
|
||||
const char *osmtpd_ltok_skip_x_key_k_tag_type(const char *, int);
|
||||
const char *osmtpd_ltok_skip_key_n_tag(const char *, int);
|
||||
const char *osmtpd_ltok_skip_key_n_tag_value(const char *, int);
|
||||
const char *osmtpd_ltok_skip_key_p_tag(const char *, int);
|
||||
const char *osmtpd_ltok_skip_key_p_tag_value(const char *, int);
|
||||
const char *osmtpd_ltok_skip_key_s_tag(const char *, int);
|
||||
const char *osmtpd_ltok_skip_key_s_tag_value(const char *, int);
|
||||
const char *osmtpd_ltok_skip_key_s_tag_type(const char *, int);
|
||||
const char *osmtpd_ltok_skip_x_key_s_tag_type(const char *, int);
|
||||
const char *osmtpd_ltok_skip_key_t_tag(const char *, int);
|
||||
const char *osmtpd_ltok_skip_key_t_tag_value(const char *, int);
|
||||
const char *osmtpd_ltok_skip_key_t_tag_flag(const char *, int);
|
||||
const char *osmtpd_ltok_skip_x_key_t_tag_flag(const char *, int);
|
||||
|
||||
/* Authentication-Results */
|
||||
const char *osmtpd_ltok_skip_ar_pvalue(const char *, int);
|
||||
|
||||
const char *osmtpd_ltok_domain_uncomment(const char *);
|
||||
const char *osmtpd_ltok_from_domain(const char *);
|
||||
|
||||
const char *osmtpd_ltok_quoted_string_normalize(const char *);
|
295
unpack_dns.c
Normal file
295
unpack_dns.c
Normal file
@ -0,0 +1,295 @@
|
||||
/* $OpenBSD: unpack_dns.c,v 1.1 2018/01/06 07:57:53 sunil Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2011-2014 Eric Faurot <eric@faurot.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "unpack_dns.h"
|
||||
|
||||
static int unpack_data(struct unpack *, void *, size_t);
|
||||
static int unpack_u16(struct unpack *, uint16_t *);
|
||||
static int unpack_u32(struct unpack *, uint32_t *);
|
||||
static int unpack_inaddr(struct unpack *, struct in_addr *);
|
||||
static int unpack_in6addr(struct unpack *, struct in6_addr *);
|
||||
static int unpack_dname(struct unpack *, char *, size_t);
|
||||
|
||||
void
|
||||
unpack_init(struct unpack *unpack, const char *buf, size_t len)
|
||||
{
|
||||
unpack->buf = buf;
|
||||
unpack->len = len;
|
||||
unpack->offset = 0;
|
||||
unpack->err = NULL;
|
||||
}
|
||||
|
||||
int
|
||||
unpack_header(struct unpack *p, struct dns_header *h)
|
||||
{
|
||||
if (unpack_data(p, h, HFIXEDSZ) == -1)
|
||||
return (-1);
|
||||
|
||||
h->flags = ntohs(h->flags);
|
||||
h->qdcount = ntohs(h->qdcount);
|
||||
h->ancount = ntohs(h->ancount);
|
||||
h->nscount = ntohs(h->nscount);
|
||||
h->arcount = ntohs(h->arcount);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
unpack_query(struct unpack *p, struct dns_query *q)
|
||||
{
|
||||
unpack_dname(p, q->q_dname, sizeof(q->q_dname));
|
||||
unpack_u16(p, &q->q_type);
|
||||
unpack_u16(p, &q->q_class);
|
||||
|
||||
return (p->err) ? (-1) : (0);
|
||||
}
|
||||
|
||||
int
|
||||
unpack_rr(struct unpack *p, struct dns_rr *rr)
|
||||
{
|
||||
uint16_t rdlen;
|
||||
size_t save_offset;
|
||||
|
||||
unpack_dname(p, rr->rr_dname, sizeof(rr->rr_dname));
|
||||
unpack_u16(p, &rr->rr_type);
|
||||
unpack_u16(p, &rr->rr_class);
|
||||
unpack_u32(p, &rr->rr_ttl);
|
||||
unpack_u16(p, &rdlen);
|
||||
|
||||
if (p->err)
|
||||
return (-1);
|
||||
|
||||
if (p->len - p->offset < rdlen) {
|
||||
p->err = "too short";
|
||||
return (-1);
|
||||
}
|
||||
|
||||
save_offset = p->offset;
|
||||
|
||||
switch (rr->rr_type) {
|
||||
|
||||
case T_CNAME:
|
||||
unpack_dname(p, rr->rr.cname.cname, sizeof(rr->rr.cname.cname));
|
||||
break;
|
||||
|
||||
case T_MX:
|
||||
unpack_u16(p, &rr->rr.mx.preference);
|
||||
unpack_dname(p, rr->rr.mx.exchange, sizeof(rr->rr.mx.exchange));
|
||||
break;
|
||||
|
||||
case T_NS:
|
||||
unpack_dname(p, rr->rr.ns.nsname, sizeof(rr->rr.ns.nsname));
|
||||
break;
|
||||
|
||||
case T_PTR:
|
||||
unpack_dname(p, rr->rr.ptr.ptrname, sizeof(rr->rr.ptr.ptrname));
|
||||
break;
|
||||
|
||||
case T_SOA:
|
||||
unpack_dname(p, rr->rr.soa.mname, sizeof(rr->rr.soa.mname));
|
||||
unpack_dname(p, rr->rr.soa.rname, sizeof(rr->rr.soa.rname));
|
||||
unpack_u32(p, &rr->rr.soa.serial);
|
||||
unpack_u32(p, &rr->rr.soa.refresh);
|
||||
unpack_u32(p, &rr->rr.soa.retry);
|
||||
unpack_u32(p, &rr->rr.soa.expire);
|
||||
unpack_u32(p, &rr->rr.soa.minimum);
|
||||
break;
|
||||
|
||||
case T_A:
|
||||
if (rr->rr_class != C_IN)
|
||||
goto other;
|
||||
unpack_inaddr(p, &rr->rr.in_a.addr);
|
||||
break;
|
||||
|
||||
case T_AAAA:
|
||||
if (rr->rr_class != C_IN)
|
||||
goto other;
|
||||
unpack_in6addr(p, &rr->rr.in_aaaa.addr6);
|
||||
break;
|
||||
default:
|
||||
other:
|
||||
rr->rr.other.rdata = p->buf + p->offset;
|
||||
rr->rr.other.rdlen = rdlen;
|
||||
p->offset += rdlen;
|
||||
}
|
||||
|
||||
if (p->err)
|
||||
return (-1);
|
||||
|
||||
/* make sure that the advertised rdlen is really ok */
|
||||
if (p->offset - save_offset != rdlen)
|
||||
p->err = "bad dlen";
|
||||
|
||||
return (p->err) ? (-1) : (0);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
dname_expand(const unsigned char *data, size_t len, size_t offset,
|
||||
size_t *newoffset, char *dst, size_t max)
|
||||
{
|
||||
size_t n, count, end, ptr, start;
|
||||
ssize_t res;
|
||||
|
||||
if (offset >= len)
|
||||
return (-1);
|
||||
|
||||
res = 0;
|
||||
end = start = offset;
|
||||
|
||||
for (; (n = data[offset]); ) {
|
||||
if ((n & 0xc0) == 0xc0) {
|
||||
if (offset + 2 > len)
|
||||
return (-1);
|
||||
ptr = 256 * (n & ~0xc0) + data[offset + 1];
|
||||
if (ptr >= start)
|
||||
return (-1);
|
||||
if (end < offset + 2)
|
||||
end = offset + 2;
|
||||
offset = start = ptr;
|
||||
continue;
|
||||
}
|
||||
if (offset + n + 1 > len)
|
||||
return (-1);
|
||||
|
||||
/* copy n + at offset+1 */
|
||||
if (dst != NULL && max != 0) {
|
||||
count = (max < n + 1) ? (max) : (n + 1);
|
||||
memmove(dst, data + offset, count);
|
||||
dst += count;
|
||||
max -= count;
|
||||
}
|
||||
res += n + 1;
|
||||
offset += n + 1;
|
||||
if (end < offset)
|
||||
end = offset;
|
||||
}
|
||||
if (end < offset + 1)
|
||||
end = offset + 1;
|
||||
|
||||
if (dst != NULL && max != 0)
|
||||
dst[0] = 0;
|
||||
if (newoffset)
|
||||
*newoffset = end;
|
||||
return (res + 1);
|
||||
}
|
||||
|
||||
char *
|
||||
print_dname(const char *_dname, char *buf, size_t max)
|
||||
{
|
||||
const unsigned char *dname = _dname;
|
||||
char *res;
|
||||
size_t left, count;
|
||||
|
||||
if (_dname[0] == 0) {
|
||||
(void)strlcpy(buf, ".", max);
|
||||
return buf;
|
||||
}
|
||||
|
||||
res = buf;
|
||||
left = max - 1;
|
||||
for (; dname[0] && left;) {
|
||||
count = (dname[0] < (left - 1)) ? dname[0] : (left - 1);
|
||||
memmove(buf, dname + 1, count);
|
||||
dname += dname[0] + 1;
|
||||
left -= count;
|
||||
buf += count;
|
||||
if (left) {
|
||||
left -= 1;
|
||||
*buf++ = '.';
|
||||
}
|
||||
}
|
||||
buf[0] = 0;
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
||||
static int
|
||||
unpack_data(struct unpack *p, void *data, size_t len)
|
||||
{
|
||||
if (p->err)
|
||||
return (-1);
|
||||
|
||||
if (p->len - p->offset < len) {
|
||||
p->err = "too short";
|
||||
return (-1);
|
||||
}
|
||||
|
||||
memmove(data, p->buf + p->offset, len);
|
||||
p->offset += len;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
unpack_u16(struct unpack *p, uint16_t *u16)
|
||||
{
|
||||
if (unpack_data(p, u16, 2) == -1)
|
||||
return (-1);
|
||||
|
||||
*u16 = ntohs(*u16);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
unpack_u32(struct unpack *p, uint32_t *u32)
|
||||
{
|
||||
if (unpack_data(p, u32, 4) == -1)
|
||||
return (-1);
|
||||
|
||||
*u32 = ntohl(*u32);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
unpack_inaddr(struct unpack *p, struct in_addr *a)
|
||||
{
|
||||
return (unpack_data(p, a, 4));
|
||||
}
|
||||
|
||||
static int
|
||||
unpack_in6addr(struct unpack *p, struct in6_addr *a6)
|
||||
{
|
||||
return (unpack_data(p, a6, 16));
|
||||
}
|
||||
|
||||
static int
|
||||
unpack_dname(struct unpack *p, char *dst, size_t max)
|
||||
{
|
||||
ssize_t e;
|
||||
|
||||
if (p->err)
|
||||
return (-1);
|
||||
|
||||
e = dname_expand(p->buf, p->len, p->offset, &p->offset, dst, max);
|
||||
if (e == -1) {
|
||||
p->err = "bad domain name";
|
||||
return (-1);
|
||||
}
|
||||
if (e < 0 || e > MAXDNAME) {
|
||||
p->err = "domain name too long";
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
96
unpack_dns.h
Normal file
96
unpack_dns.h
Normal file
@ -0,0 +1,96 @@
|
||||
/* $OpenBSD: unpack_dns.h,v 1.1 2018/01/06 07:57:53 sunil Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2011-2014 Eric Faurot <eric@faurot.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <arpa/nameser.h>
|
||||
|
||||
struct unpack {
|
||||
const char *buf;
|
||||
size_t len;
|
||||
size_t offset;
|
||||
const char *err;
|
||||
};
|
||||
|
||||
struct dns_header {
|
||||
uint16_t id;
|
||||
uint16_t flags;
|
||||
uint16_t qdcount;
|
||||
uint16_t ancount;
|
||||
uint16_t nscount;
|
||||
uint16_t arcount;
|
||||
};
|
||||
|
||||
struct dns_query {
|
||||
char q_dname[MAXDNAME];
|
||||
uint16_t q_type;
|
||||
uint16_t q_class;
|
||||
};
|
||||
|
||||
struct dns_rr {
|
||||
char rr_dname[MAXDNAME];
|
||||
uint16_t rr_type;
|
||||
uint16_t rr_class;
|
||||
uint32_t rr_ttl;
|
||||
union {
|
||||
struct {
|
||||
char cname[MAXDNAME];
|
||||
} cname;
|
||||
struct {
|
||||
uint16_t preference;
|
||||
char exchange[MAXDNAME];
|
||||
} mx;
|
||||
struct {
|
||||
char nsname[MAXDNAME];
|
||||
} ns;
|
||||
struct {
|
||||
char ptrname[MAXDNAME];
|
||||
} ptr;
|
||||
struct {
|
||||
char mname[MAXDNAME];
|
||||
char rname[MAXDNAME];
|
||||
uint32_t serial;
|
||||
uint32_t refresh;
|
||||
uint32_t retry;
|
||||
uint32_t expire;
|
||||
uint32_t minimum;
|
||||
} soa;
|
||||
struct {
|
||||
struct in_addr addr;
|
||||
} in_a;
|
||||
struct {
|
||||
struct in6_addr addr6;
|
||||
} in_aaaa;
|
||||
struct {
|
||||
uint16_t rdlen;
|
||||
const void *rdata;
|
||||
} other;
|
||||
} rr;
|
||||
};
|
||||
|
||||
void unpack_init(struct unpack *, const char *, size_t);
|
||||
int unpack_header(struct unpack *, struct dns_header *);
|
||||
int unpack_rr(struct unpack *, struct dns_rr *);
|
||||
int unpack_query(struct unpack *, struct dns_query *);
|
||||
char *print_dname(const char *, char *, size_t);
|
||||
ssize_t dname_expand(const unsigned char *, size_t, size_t, size_t *,
|
||||
char *, size_t);
|
||||
|
Loading…
Reference in New Issue
Block a user