mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
ndr dns: Add simple parser
This commit is contained in:
parent
96195b2c0c
commit
719a6bbfed
@ -10,7 +10,7 @@
|
||||
|
||||
import "misc.idl";
|
||||
[
|
||||
helper("librpc/ndr/ndr_dnsp.h"),
|
||||
helper("librpc/ndr/ndr_dns.h"),
|
||||
helpstring("DNS records"),
|
||||
version(0.0),
|
||||
uuid("a047c001-5f22-40b0-9d52-7042c43f711a")
|
||||
@ -109,7 +109,7 @@ interface dns
|
||||
} dns_qtype;
|
||||
|
||||
typedef [public] struct {
|
||||
dnsp_name name;
|
||||
dns_string name;
|
||||
dns_qtype question_type;
|
||||
dns_qclass question_class;
|
||||
} dns_name_question;
|
||||
@ -120,12 +120,13 @@ interface dns
|
||||
} dns_rdata_data;
|
||||
|
||||
typedef [nodiscriminant,public] union {
|
||||
[case(DNS_QTYPE_A)] ipv4address ipv4_address;
|
||||
[case(DNS_QTYPE_A),subcontext(2)] ipv4address ipv4_address;
|
||||
[case(DNS_QTYPE_AAAA),subcontext(2)] ipv6address ipv6_address;
|
||||
[default] dns_rdata_data data;
|
||||
} dns_rdata;
|
||||
|
||||
typedef [flag(LIBNDR_PRINT_ARRAY_HEX),public] struct {
|
||||
dnsp_name name;
|
||||
dns_string name;
|
||||
dns_qtype rr_type;
|
||||
dns_qclass rr_class;
|
||||
uint32 ttl;
|
||||
|
@ -92,6 +92,7 @@ struct ndr_push {
|
||||
struct ndr_token_list *relative_list;
|
||||
struct ndr_token_list *relative_begin_list;
|
||||
struct ndr_token_list *nbt_string_list;
|
||||
struct ndr_token_list *dns_string_list;
|
||||
struct ndr_token_list *full_ptr_list;
|
||||
|
||||
/* this is used to ensure we generate unique reference IDs */
|
||||
|
210
librpc/ndr/ndr_dns.c
Normal file
210
librpc/ndr/ndr_dns.c
Normal file
@ -0,0 +1,210 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
manipulate dns name structures
|
||||
|
||||
Copyright (C) 2010 Kai Blin <kai@samba.org>
|
||||
|
||||
Heavily based on nbtname.c which is:
|
||||
|
||||
Copyright (C) Andrew Tridgell 2005
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
see rfc1002 for the detailed format of compressed names
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "librpc/gen_ndr/ndr_dns.h"
|
||||
#include "librpc/gen_ndr/ndr_misc.h"
|
||||
#include "system/locale.h"
|
||||
#include "lib/util/util_net.h"
|
||||
|
||||
/* don't allow an unlimited number of name components */
|
||||
#define MAX_COMPONENTS 10
|
||||
|
||||
/**
|
||||
print a dns string
|
||||
*/
|
||||
_PUBLIC_ void ndr_print_dns_string(struct ndr_print *ndr, const char *name, const char *s)
|
||||
{
|
||||
ndr_print_string(ndr, name, s);
|
||||
}
|
||||
|
||||
/*
|
||||
pull one component of a dns_string
|
||||
*/
|
||||
static enum ndr_err_code ndr_pull_component(struct ndr_pull *ndr,
|
||||
uint8_t **component,
|
||||
uint32_t *offset,
|
||||
uint32_t *max_offset)
|
||||
{
|
||||
uint8_t len;
|
||||
unsigned int loops = 0;
|
||||
while (loops < 5) {
|
||||
if (*offset >= ndr->data_size) {
|
||||
return ndr_pull_error(ndr, NDR_ERR_STRING,
|
||||
"BAD DNS NAME component");
|
||||
}
|
||||
len = ndr->data[*offset];
|
||||
if (len == 0) {
|
||||
*offset += 1;
|
||||
*max_offset = MAX(*max_offset, *offset);
|
||||
*component = NULL;
|
||||
return NDR_ERR_SUCCESS;
|
||||
}
|
||||
if ((len & 0xC0) == 0xC0) {
|
||||
/* its a label pointer */
|
||||
if (1 + *offset >= ndr->data_size) {
|
||||
return ndr_pull_error(ndr, NDR_ERR_STRING,
|
||||
"BAD DNS NAME component");
|
||||
}
|
||||
*max_offset = MAX(*max_offset, *offset + 2);
|
||||
*offset = ((len&0x3F)<<8) | ndr->data[1 + *offset];
|
||||
*max_offset = MAX(*max_offset, *offset);
|
||||
loops++;
|
||||
continue;
|
||||
}
|
||||
if ((len & 0xC0) != 0) {
|
||||
/* its a reserved length field */
|
||||
return ndr_pull_error(ndr, NDR_ERR_STRING,
|
||||
"BAD DNS NAME component");
|
||||
}
|
||||
if (*offset + len + 2 > ndr->data_size) {
|
||||
return ndr_pull_error(ndr, NDR_ERR_STRING,
|
||||
"BAD DNS NAME component");
|
||||
}
|
||||
*component = (uint8_t*)talloc_strndup(ndr, (const char *)&ndr->data[1 + *offset], len);
|
||||
NDR_ERR_HAVE_NO_MEMORY(*component);
|
||||
*offset += len + 1;
|
||||
*max_offset = MAX(*max_offset, *offset);
|
||||
return NDR_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
/* too many pointers */
|
||||
return ndr_pull_error(ndr, NDR_ERR_STRING, "BAD DNS NAME component");
|
||||
}
|
||||
|
||||
/**
|
||||
pull a dns_string from the wire
|
||||
*/
|
||||
_PUBLIC_ enum ndr_err_code ndr_pull_dns_string(struct ndr_pull *ndr, int ndr_flags, const char **s)
|
||||
{
|
||||
uint32_t offset = ndr->offset;
|
||||
uint32_t max_offset = offset;
|
||||
unsigned num_components;
|
||||
char *name;
|
||||
|
||||
if (!(ndr_flags & NDR_SCALARS)) {
|
||||
return NDR_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
name = NULL;
|
||||
|
||||
/* break up name into a list of components */
|
||||
for (num_components=0;num_components<MAX_COMPONENTS;num_components++) {
|
||||
uint8_t *component = NULL;
|
||||
NDR_CHECK(ndr_pull_component(ndr, &component, &offset, &max_offset));
|
||||
if (component == NULL) break;
|
||||
if (name) {
|
||||
name = talloc_asprintf_append_buffer(name, ".%s", component);
|
||||
NDR_ERR_HAVE_NO_MEMORY(name);
|
||||
} else {
|
||||
name = (char *)component;
|
||||
}
|
||||
}
|
||||
if (num_components == MAX_COMPONENTS) {
|
||||
return ndr_pull_error(ndr, NDR_ERR_STRING,
|
||||
"BAD DNS NAME too many components");
|
||||
}
|
||||
if (num_components == 0) {
|
||||
name = talloc_strdup(ndr, "");
|
||||
NDR_ERR_HAVE_NO_MEMORY(name);
|
||||
}
|
||||
|
||||
(*s) = name;
|
||||
ndr->offset = max_offset;
|
||||
|
||||
return NDR_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
push a dns string to the wire
|
||||
*/
|
||||
_PUBLIC_ enum ndr_err_code ndr_push_dns_string(struct ndr_push *ndr, int ndr_flags, const char *s)
|
||||
{
|
||||
if (!(ndr_flags & NDR_SCALARS)) {
|
||||
return NDR_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
while (s && *s) {
|
||||
enum ndr_err_code ndr_err;
|
||||
char *compname;
|
||||
size_t complen;
|
||||
uint32_t offset;
|
||||
|
||||
/* see if we have pushed the remaing string allready,
|
||||
* if so we use a label pointer to this string
|
||||
*/
|
||||
ndr_err = ndr_token_retrieve_cmp_fn(&ndr->dns_string_list, s, &offset, (comparison_fn_t)strcmp, false);
|
||||
if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
||||
uint8_t b[2];
|
||||
|
||||
if (offset > 0x3FFF) {
|
||||
return ndr_push_error(ndr, NDR_ERR_STRING,
|
||||
"offset for dns string label pointer %u[%08X] > 0x00003FFF",
|
||||
offset, offset);
|
||||
}
|
||||
|
||||
b[0] = 0xC0 | (offset>>8);
|
||||
b[1] = (offset & 0xFF);
|
||||
|
||||
return ndr_push_bytes(ndr, b, 2);
|
||||
}
|
||||
|
||||
complen = strcspn(s, ".");
|
||||
|
||||
/* we need to make sure the length fits into 6 bytes */
|
||||
if (complen > 0x3F) {
|
||||
return ndr_push_error(ndr, NDR_ERR_STRING,
|
||||
"component length %u[%08X] > 0x0000003F",
|
||||
(unsigned)complen, (unsigned)complen);
|
||||
}
|
||||
|
||||
compname = talloc_asprintf(ndr, "%c%*.*s",
|
||||
(unsigned char)complen,
|
||||
(unsigned char)complen,
|
||||
(unsigned char)complen, s);
|
||||
NDR_ERR_HAVE_NO_MEMORY(compname);
|
||||
|
||||
/* remember the current componemt + the rest of the string
|
||||
* so it can be reused later
|
||||
*/
|
||||
NDR_CHECK(ndr_token_store(ndr, &ndr->dns_string_list, s, ndr->offset));
|
||||
|
||||
/* push just this component into the blob */
|
||||
NDR_CHECK(ndr_push_bytes(ndr, (const uint8_t *)compname, complen+1));
|
||||
talloc_free(compname);
|
||||
|
||||
s += complen;
|
||||
if (*s == '.') s++;
|
||||
}
|
||||
|
||||
/* if we reach the end of the string and have pushed the last component
|
||||
* without using a label pointer, we need to terminate the string
|
||||
*/
|
||||
return ndr_push_bytes(ndr, (const uint8_t *)"", 1);
|
||||
}
|
3
librpc/ndr/ndr_dns.h
Normal file
3
librpc/ndr/ndr_dns.h
Normal file
@ -0,0 +1,3 @@
|
||||
_PUBLIC_ void ndr_print_dns_string(struct ndr_print *ndr, const char *name, const char *s);
|
||||
_PUBLIC_ enum ndr_err_code ndr_pull_dns_string(struct ndr_pull *ndr, int ndr_flags, const char **s);
|
||||
_PUBLIC_ enum ndr_err_code ndr_push_dns_string(struct ndr_push *ndr, int ndr_flags, const char *s);
|
@ -18,8 +18,8 @@ bld.SAMBA_SUBSYSTEM('NDR_DNSSERVER',
|
||||
)
|
||||
|
||||
bld.SAMBA_SUBSYSTEM('NDR_DNS',
|
||||
source='../librpc/gen_ndr/ndr_dns.c',
|
||||
public_deps='LIBNDR NDR_DNSP'
|
||||
source='../librpc/gen_ndr/ndr_dns.c ../librpc/ndr/ndr_dns.c',
|
||||
public_deps='LIBNDR'
|
||||
)
|
||||
|
||||
bld.SAMBA_SUBSYSTEM('NDR_DSBACKUP',
|
||||
|
@ -72,6 +72,7 @@ my $scalar_alignment = {
|
||||
'WERROR' => 4,
|
||||
'NTSTATUS' => 4,
|
||||
'COMRESULT' => 4,
|
||||
'dns_string' => 4,
|
||||
'nbt_string' => 4,
|
||||
'wrepl_nbt_name' => 4,
|
||||
'ipv4address' => 4,
|
||||
|
@ -916,6 +916,11 @@ sub ConvertObjectFromPythonData($$$$$$;$)
|
||||
return;
|
||||
}
|
||||
|
||||
if ($actual_ctype->{TYPE} eq "SCALAR" and ($actual_ctype->{NAME} eq "dns_string" or $actual_ctype->{NAME} eq "dns_name")) {
|
||||
$self->pidl("$target = talloc_strdup($mem_ctx, PyString_AS_STRING($cvar));");
|
||||
return;
|
||||
}
|
||||
|
||||
if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "ipv4address") {
|
||||
$self->pidl("$target = PyString_AS_STRING($cvar);");
|
||||
return;
|
||||
@ -1094,6 +1099,10 @@ sub ConvertScalarToPython($$$)
|
||||
return "PyString_FromString_check_null($cvar)";
|
||||
}
|
||||
|
||||
if (($ctypename eq "dns_string" or $ctypename eq "dns_name")) {
|
||||
return "PyString_FromString_check_null($cvar)";
|
||||
}
|
||||
|
||||
# Not yet supported
|
||||
if ($ctypename eq "string_array") { return "PyCObject_FromTallocPtr($cvar)"; }
|
||||
if ($ctypename eq "ipv4address") { return "PyString_FromString_check_null($cvar)"; }
|
||||
|
@ -20,7 +20,7 @@ use strict;
|
||||
my %types = ();
|
||||
|
||||
my @reference_scalars = (
|
||||
"string", "string_array", "nbt_string",
|
||||
"string", "string_array", "nbt_string", "dns_string",
|
||||
"wrepl_nbt_name", "ipv4address", "ipv6address"
|
||||
);
|
||||
|
||||
@ -54,6 +54,7 @@ my %scalars = (
|
||||
"WERROR" => "WERROR",
|
||||
"NTSTATUS" => "NTSTATUS",
|
||||
"COMRESULT" => "COMRESULT",
|
||||
"dns_string" => "const char *",
|
||||
"nbt_string" => "const char *",
|
||||
"wrepl_nbt_name"=> "struct nbt_name *",
|
||||
"ipv4address" => "const char *",
|
||||
|
@ -33,6 +33,8 @@
|
||||
#include "lib/socket/netif.h"
|
||||
#include "dns_server/dns_server.h"
|
||||
#include "param/param.h"
|
||||
#include "librpc/ndr/libndr.h"
|
||||
#include "librpc/gen_ndr/ndr_dns.h"
|
||||
|
||||
/* hold information about one dns socket */
|
||||
struct dns_socket {
|
||||
@ -87,7 +89,21 @@ bool dns_process(struct dns_server *dns,
|
||||
DATA_BLOB *in,
|
||||
DATA_BLOB *out)
|
||||
{
|
||||
DEBUG(0, ("FIXME: actually process DNS packet here\n"));
|
||||
enum ndr_err_code ndr_err;
|
||||
struct dns_name_packet *packet = talloc(mem_ctx, struct dns_name_packet);
|
||||
if (packet == NULL) return false;
|
||||
|
||||
dump_data(0, in->data, in->length);
|
||||
|
||||
ndr_err = ndr_pull_struct_blob(in, packet, packet,
|
||||
(ndr_pull_flags_fn_t)ndr_pull_dns_name_packet);
|
||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
||||
TALLOC_FREE(packet);
|
||||
DEBUG(0, ("Failed to parse packet %d!\n", ndr_err));
|
||||
return false;
|
||||
}
|
||||
|
||||
NDR_PRINT_DEBUG(dns_name_packet, packet);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -96,7 +96,9 @@ bld.SAMBA_LIBRARY('NDR_STANDARD',
|
||||
source='../../librpc/gen_ndr/ndr_atsvc.c ../../librpc/gen_ndr/ndr_eventlog6.c',
|
||||
vnum='0.0.1',
|
||||
pc_files='../../librpc/ndr_standard.pc',
|
||||
deps='NDR_SECURITY NDR_LSA NDR_SAMR NDR_NETLOGON NDR_EVENTLOG NDR_DFS NDR_NTSVCS NDR_SVCCTL NDR_INITSHUTDOWN NDR_WKSSVC NDR_SRVSVC NDR_WINREG NDR_ECHO LIBSECURITY',
|
||||
deps='''NDR_SECURITY NDR_LSA NDR_SAMR NDR_NETLOGON NDR_EVENTLOG NDR_DFS
|
||||
NDR_NTSVCS NDR_SVCCTL NDR_INITSHUTDOWN NDR_WKSSVC NDR_SRVSVC NDR_WINREG
|
||||
NDR_ECHO LIBSECURITY NDR_DNS''',
|
||||
public_deps='LIBNDR',
|
||||
public_headers='../../librpc/gen_ndr/samr.h ../../librpc/gen_ndr/ndr_samr.h ../../librpc/gen_ndr/lsa.h ../../librpc/gen_ndr/netlogon.h ../../librpc/gen_ndr/atsvc.h ../../librpc/gen_ndr/ndr_atsvc.h ../../librpc/gen_ndr/ndr_svcctl.h ../../librpc/gen_ndr/svcctl.h',
|
||||
header_path='gen_ndr'
|
||||
|
Loading…
Reference in New Issue
Block a user