From 7ee75c95481f0d13598577361d18e96cb8394b9c Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 6 Jan 2011 14:53:04 +0100 Subject: lib/addns: move DNS client library to the main directory. Guenther --- lib/addns/addns.h | 30 +++ lib/addns/dns.h | 540 +++++++++++++++++++++++++++++++++++++++++ lib/addns/dnserr.h | 87 +++++++ lib/addns/dnsgss.c | 334 +++++++++++++++++++++++++ lib/addns/dnsmarshall.c | 530 ++++++++++++++++++++++++++++++++++++++++ lib/addns/dnsrecord.c | 422 ++++++++++++++++++++++++++++++++ lib/addns/dnssock.c | 377 ++++++++++++++++++++++++++++ lib/addns/dnsutils.c | 151 ++++++++++++ lib/addns/error.c | 59 +++++ lib/addns/wscript_build | 7 + source3/Makefile.in | 6 +- source3/configure.in | 2 +- source3/libaddns/addns.h | 30 --- source3/libaddns/dns.h | 540 ----------------------------------------- source3/libaddns/dnserr.h | 87 ------- source3/libaddns/dnsgss.c | 334 ------------------------- source3/libaddns/dnsmarshall.c | 530 ---------------------------------------- source3/libaddns/dnsrecord.c | 422 -------------------------------- source3/libaddns/dnssock.c | 377 ---------------------------- source3/libaddns/dnsutils.c | 151 ------------ source3/libaddns/error.c | 59 ----- source3/libaddns/wscript_build | 7 - source3/wscript_build | 2 +- 23 files changed, 2542 insertions(+), 2542 deletions(-) create mode 100644 lib/addns/addns.h create mode 100644 lib/addns/dns.h create mode 100644 lib/addns/dnserr.h create mode 100644 lib/addns/dnsgss.c create mode 100644 lib/addns/dnsmarshall.c create mode 100644 lib/addns/dnsrecord.c create mode 100644 lib/addns/dnssock.c create mode 100644 lib/addns/dnsutils.c create mode 100644 lib/addns/error.c create mode 100644 lib/addns/wscript_build delete mode 100644 source3/libaddns/addns.h delete mode 100644 source3/libaddns/dns.h delete mode 100644 source3/libaddns/dnserr.h delete mode 100644 source3/libaddns/dnsgss.c delete mode 100644 source3/libaddns/dnsmarshall.c delete mode 100644 source3/libaddns/dnsrecord.c delete mode 100644 source3/libaddns/dnssock.c delete mode 100644 source3/libaddns/dnsutils.c delete mode 100644 source3/libaddns/error.c delete mode 100644 source3/libaddns/wscript_build diff --git a/lib/addns/addns.h b/lib/addns/addns.h new file mode 100644 index 0000000000..6ef9329df8 --- /dev/null +++ b/lib/addns/addns.h @@ -0,0 +1,30 @@ +/* + Public Interface file for Linux DNS client library implementation + + Copyright (C) 2006 Krishna Ganugapati + Copyright (C) 2006 Gerald Carter + + ** NOTE! The following LGPL license applies to the libaddns + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifndef _ADDNS_H +#define _ADDNS_H + + +#endif /* _ADDNS_H */ + diff --git a/lib/addns/dns.h b/lib/addns/dns.h new file mode 100644 index 0000000000..29f1ed3e99 --- /dev/null +++ b/lib/addns/dns.h @@ -0,0 +1,540 @@ +/* + Linux DNS client library implementation + + Copyright (C) 2006 Krishna Ganugapati + Copyright (C) 2006 Gerald Carter + + ** NOTE! The following LGPL license applies to the libaddns + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifndef _DNS_H +#define _DNS_H + +#include "../replace/replace.h" +#include "system/network.h" + +/* make sure we have included the correct config.h */ +#ifndef NO_CONFIG_H /* for some tests */ +#ifndef CONFIG_H_IS_FROM_SAMBA +#error "make sure you have removed all config.h files from standalone builds!" +#error "the included config.h isn't from samba!" +#endif +#endif /* NO_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_UUID_UUID_H +#include +#endif + +#ifdef HAVE_KRB5_H +#include +#endif + +#ifdef HAVE_INTTYPES_H +#include + +#ifndef int16 +#define int16 int16_t +#endif + +#ifndef uint16 +#define uint16 uint16_t +#endif + +#ifndef int32 +#define int32 int32_t +#endif + +#ifndef uint32 +#define uint32 uint32_t +#endif +#endif + +#ifdef HAVE_KRB5_H +#include +#endif + +#if HAVE_GSSAPI_GSSAPI_H +#include +#elif HAVE_GSSAPI_GSSAPI_GENERIC_H +#include +#elif HAVE_GSSAPI_H +#include +#endif + +#if defined(HAVE_GSSAPI_H) || defined(HAVE_GSSAPI_GSSAPI_H) || defined(HAVE_GSSAPI_GSSAPI_GENERIC_H) +#define HAVE_GSSAPI_SUPPORT 1 +#endif + +#include + +#if 0 + +Disable these now we have checked all code paths and ensured +NULL returns on zero request. JRA. + +void *_talloc_zero_zeronull(const void *ctx, size_t size, const char *name); +void *_talloc_memdup_zeronull(const void *t, const void *p, size_t size, const char *name); +void *_talloc_array_zeronull(const void *ctx, size_t el_size, unsigned count, const char *name); +void *_talloc_zero_array_zeronull(const void *ctx, size_t el_size, unsigned count, const char *name); +void *talloc_zeronull(const void *context, size_t size, const char *name); + +#define TALLOC(ctx, size) talloc_zeronull(ctx, size, __location__) +#define TALLOC_P(ctx, type) (type *)talloc_zeronull(ctx, sizeof(type), #type) +#define TALLOC_ARRAY(ctx, type, count) (type *)_talloc_array_zeronull(ctx, sizeof(type), count, #type) +#define TALLOC_MEMDUP(ctx, ptr, size) _talloc_memdup_zeronull(ctx, ptr, size, __location__) +#define TALLOC_ZERO(ctx, size) _talloc_zero_zeronull(ctx, size, __location__) +#define TALLOC_ZERO_P(ctx, type) (type *)_talloc_zero_zeronull(ctx, sizeof(type), #type) +#define TALLOC_ZERO_ARRAY(ctx, type, count) (type *)_talloc_zero_array_zeronull(ctx, sizeof(type), count, #type) +#define TALLOC_SIZE(ctx, size) talloc_zeronull(ctx, size, __location__) +#define TALLOC_ZERO_SIZE(ctx, size) _talloc_zero_zeronull(ctx, size, __location__) + +#else + +#define TALLOC(ctx, size) talloc_named_const(ctx, size, __location__) +#define TALLOC_P(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type) +#define TALLOC_ARRAY(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type) +#define TALLOC_MEMDUP(ctx, ptr, size) _talloc_memdup(ctx, ptr, size, __location__) +#define TALLOC_ZERO(ctx, size) _talloc_zero(ctx, size, __location__) +#define TALLOC_ZERO_P(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type) +#define TALLOC_ZERO_ARRAY(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type) +#define TALLOC_SIZE(ctx, size) talloc_named_const(ctx, size, __location__) +#define TALLOC_ZERO_SIZE(ctx, size) _talloc_zero(ctx, size, __location__) + +#endif + +#define TALLOC_REALLOC(ctx, ptr, count) _talloc_realloc(ctx, ptr, count, __location__) +#define TALLOC_REALLOC_ARRAY(ctx, ptr, type, count) (type *)_talloc_realloc_array(ctx, ptr, sizeof(type), count, #type) +#define talloc_destroy(ctx) talloc_free(ctx) +#ifndef TALLOC_FREE +#define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0) +#endif + +/******************************************************************* + Type definitions for int16, int32, uint16 and uint32. Needed + for Samba coding style +*******************************************************************/ + +#ifndef uint8 +# define uint8 unsigned char +#endif + +#if !defined(int16) && !defined(HAVE_INT16_FROM_RPC_RPC_H) +# if (SIZEOF_SHORT == 4) +# define int16 __ERROR___CANNOT_DETERMINE_TYPE_FOR_INT16; +# else /* SIZEOF_SHORT != 4 */ +# define int16 short +# endif /* SIZEOF_SHORT != 4 */ + /* needed to work around compile issue on HP-UX 11.x */ +# define _INT16 1 +#endif + +/* + * Note we duplicate the size tests in the unsigned + * case as int16 may be a typedef from rpc/rpc.h + */ + +#if !defined(uint16) && !defined(HAVE_UINT16_FROM_RPC_RPC_H) +# if (SIZEOF_SHORT == 4) +# define uint16 __ERROR___CANNOT_DETERMINE_TYPE_FOR_INT16; +# else /* SIZEOF_SHORT != 4 */ +# define uint16 unsigned short +# endif /* SIZEOF_SHORT != 4 */ +#endif + +#if !defined(int32) && !defined(HAVE_INT32_FROM_RPC_RPC_H) +# if (SIZEOF_INT == 4) +# define int32 int +# elif (SIZEOF_LONG == 4) +# define int32 long +# elif (SIZEOF_SHORT == 4) +# define int32 short +# else + /* uggh - no 32 bit type?? probably a CRAY. just hope this works ... */ +# define int32 int +# endif +# ifndef _INT32 + /* needed to work around compile issue on HP-UX 11.x */ +# define _INT32 1 +# endif +#endif + +/* + * Note we duplicate the size tests in the unsigned + * case as int32 may be a typedef from rpc/rpc.h + */ + +#if !defined(uint32) && !defined(HAVE_UINT32_FROM_RPC_RPC_H) +# if (SIZEOF_INT == 4) +# define uint32 unsigned int +# elif (SIZEOF_LONG == 4) +# define uint32 unsigned long +# elif (SIZEOF_SHORT == 4) +# define uint32 unsigned short +# else + /* uggh - no 32 bit type?? probably a CRAY. just hope this works ... */ +# define uint32 unsigned +# endif +#endif + +/* + * check for 8 byte long long + */ + +#if !defined(uint64) +# if (SIZEOF_LONG == 8) +# define uint64 unsigned long +# elif (SIZEOF_LONG_LONG == 8) +# define uint64 unsigned long long +# endif /* don't lie. If we don't have it, then don't use it */ +#endif + +/* needed on Sun boxes */ +#ifndef INADDR_NONE +#define INADDR_NONE 0xFFFFFFFF +#endif + +#include "dnserr.h" + + +#define DNS_TCP 1 +#define DNS_UDP 2 + +#define DNS_OPCODE_UPDATE 1 + +/* DNS Class Types */ + +#define DNS_CLASS_IN 1 +#define DNS_CLASS_ANY 255 +#define DNS_CLASS_NONE 254 + +/* DNS RR Types */ + +#define DNS_RR_A 1 + +#define DNS_TCP_PORT 53 +#define DNS_UDP_PORT 53 + +#define QTYPE_A 1 +#define QTYPE_NS 2 +#define QTYPE_MD 3 +#define QTYPE_CNAME 5 +#define QTYPE_SOA 6 +#define QTYPE_ANY 255 +#define QTYPE_TKEY 249 +#define QTYPE_TSIG 250 + +/* +MF 4 a mail forwarder (Obsolete - use MX) +CNAME 5 the canonical name for an alias +SOA 6 marks the start of a zone of authority +MB 7 a mailbox domain name (EXPERIMENTAL) +MG 8 a mail group member (EXPERIMENTAL) +MR 9 a mail rename domain name (EXPERIMENTAL) +NULL 10 a null RR (EXPERIMENTAL) +WKS 11 a well known service description +PTR 12 a domain name pointer +HINFO 13 host information +MINFO 14 mailbox or mail list information +MX 15 mail exchange +TXT 16 text strings +*/ + +#define QR_QUERY 0x0000 +#define QR_RESPONSE 0x0001 + +#define OPCODE_QUERY 0x00 +#define OPCODE_IQUERY 0x01 +#define OPCODE_STATUS 0x02 + +#define AA 1 + +#define RECURSION_DESIRED 0x01 + +#define RCODE_NOERROR 0 +#define RCODE_FORMATERROR 1 +#define RCODE_SERVER_FAILURE 2 +#define RCODE_NAME_ERROR 3 +#define RCODE_NOTIMPLEMENTED 4 +#define RCODE_REFUSED 5 + +#define SENDBUFFER_SIZE 65536 +#define RECVBUFFER_SIZE 65536 + +/* + * TKEY Modes from rfc2930 + */ + +#define DNS_TKEY_MODE_SERVER 1 +#define DNS_TKEY_MODE_DH 2 +#define DNS_TKEY_MODE_GSSAPI 3 +#define DNS_TKEY_MODE_RESOLVER 4 +#define DNS_TKEY_MODE_DELETE 5 + + +#define DNS_ONE_DAY_IN_SECS 86400 +#define DNS_TEN_HOURS_IN_SECS 36000 + +#define SOCKET_ERROR -1 +#define INVALID_SOCKET -1 + +#define DNS_NO_ERROR 0 +#define DNS_FORMAT_ERROR 1 +#define DNS_SERVER_FAILURE 2 +#define DNS_NAME_ERROR 3 +#define DNS_NOT_IMPLEMENTED 4 +#define DNS_REFUSED 5 + +typedef long HANDLE; + +enum dns_ServerType { DNS_SRV_ANY, DNS_SRV_WIN2000, DNS_SRV_WIN2003 }; + +struct dns_domain_label { + struct dns_domain_label *next; + char *label; + size_t len; +}; + +struct dns_domain_name { + struct dns_domain_label *pLabelList; +}; + +struct dns_question { + struct dns_domain_name *name; + uint16 q_type; + uint16 q_class; +}; + +/* + * Before changing the definition of dns_zone, look + * dns_marshall_update_request(), we rely on this being the same as + * dns_question right now. + */ + +struct dns_zone { + struct dns_domain_name *name; + uint16 z_type; + uint16 z_class; +}; + +struct dns_rrec { + struct dns_domain_name *name; + uint16 type; + uint16 r_class; + uint32 ttl; + uint16 data_length; + uint8 *data; +}; + +struct dns_tkey_record { + struct dns_domain_name *algorithm; + time_t inception; + time_t expiration; + uint16 mode; + uint16 error; + uint16 key_length; + uint8 *key; +}; + +struct dns_request { + uint16 id; + uint16 flags; + uint16 num_questions; + uint16 num_answers; + uint16 num_auths; + uint16 num_additionals; + struct dns_question **questions; + struct dns_rrec **answers; + struct dns_rrec **auths; + struct dns_rrec **additionals; +}; + +/* + * Before changing the definition of dns_update_request, look + * dns_marshall_update_request(), we rely on this being the same as + * dns_request right now. + */ + +struct dns_update_request { + uint16 id; + uint16 flags; + uint16 num_zones; + uint16 num_preqs; + uint16 num_updates; + uint16 num_additionals; + struct dns_zone **zones; + struct dns_rrec **preqs; + struct dns_rrec **updates; + struct dns_rrec **additionals; +}; + +struct dns_connection { + int32 hType; + int s; + struct sockaddr RecvAddr; +}; + +struct dns_buffer { + uint8 *data; + size_t size; + size_t offset; + DNS_ERROR error; +}; + +/* from dnsutils.c */ + +DNS_ERROR dns_domain_name_from_string( TALLOC_CTX *mem_ctx, + const char *pszDomainName, + struct dns_domain_name **presult ); +char *dns_generate_keyname( TALLOC_CTX *mem_ctx ); + +/* from dnsrecord.c */ + +DNS_ERROR dns_create_query( TALLOC_CTX *mem_ctx, const char *name, + uint16 q_type, uint16 q_class, + struct dns_request **preq ); +DNS_ERROR dns_create_update( TALLOC_CTX *mem_ctx, const char *name, + struct dns_update_request **preq ); +DNS_ERROR dns_create_probe(TALLOC_CTX *mem_ctx, const char *zone, + const char *host, int num_ips, + const struct sockaddr_storage *sslist, + struct dns_update_request **preq); +DNS_ERROR dns_create_rrec(TALLOC_CTX *mem_ctx, const char *name, + uint16 type, uint16 r_class, uint32 ttl, + uint16 data_length, uint8 *data, + struct dns_rrec **prec); +DNS_ERROR dns_add_rrec(TALLOC_CTX *mem_ctx, struct dns_rrec *rec, + uint16 *num_records, struct dns_rrec ***records); +DNS_ERROR dns_create_tkey_record(TALLOC_CTX *mem_ctx, const char *keyname, + const char *algorithm_name, time_t inception, + time_t expiration, uint16 mode, uint16 error, + uint16 key_length, const uint8 *key, + struct dns_rrec **prec); +DNS_ERROR dns_create_name_in_use_record(TALLOC_CTX *mem_ctx, + const char *name, + const struct sockaddr_storage *ip, + struct dns_rrec **prec); +DNS_ERROR dns_create_delete_record(TALLOC_CTX *mem_ctx, const char *name, + uint16 type, uint16 r_class, + struct dns_rrec **prec); +DNS_ERROR dns_create_name_not_in_use_record(TALLOC_CTX *mem_ctx, + const char *name, uint32 type, + struct dns_rrec **prec); +DNS_ERROR dns_create_a_record(TALLOC_CTX *mem_ctx, const char *host, + uint32 ttl, const struct sockaddr_storage *pss, + struct dns_rrec **prec); +DNS_ERROR dns_unmarshall_tkey_record(TALLOC_CTX *mem_ctx, struct dns_rrec *rec, + struct dns_tkey_record **ptkey); +DNS_ERROR dns_create_tsig_record(TALLOC_CTX *mem_ctx, const char *keyname, + const char *algorithm_name, + time_t time_signed, uint16 fudge, + uint16 mac_length, const uint8 *mac, + uint16 original_id, uint16 error, + struct dns_rrec **prec); +DNS_ERROR dns_add_rrec(TALLOC_CTX *mem_ctx, struct dns_rrec *rec, + uint16 *num_records, struct dns_rrec ***records); +DNS_ERROR dns_create_update_request(TALLOC_CTX *mem_ctx, + const char *domainname, + const char *hostname, + const struct sockaddr_storage *ip_addr, + size_t num_adds, + struct dns_update_request **preq); + +/* from dnssock.c */ + +DNS_ERROR dns_open_connection( const char *nameserver, int32 dwType, + TALLOC_CTX *mem_ctx, + struct dns_connection **conn ); +DNS_ERROR dns_send(struct dns_connection *conn, const struct dns_buffer *buf); +DNS_ERROR dns_receive(TALLOC_CTX *mem_ctx, struct dns_connection *conn, + struct dns_buffer **presult); +DNS_ERROR dns_transaction(TALLOC_CTX *mem_ctx, struct dns_connection *conn, + const struct dns_request *req, + struct dns_request **resp); +DNS_ERROR dns_update_transaction(TALLOC_CTX *mem_ctx, + struct dns_connection *conn, + struct dns_update_request *up_req, + struct dns_update_request **up_resp); + +/* from dnsmarshall.c */ + +struct dns_buffer *dns_create_buffer(TALLOC_CTX *mem_ctx); +void dns_marshall_buffer(struct dns_buffer *buf, const uint8 *data, + size_t len); +void dns_marshall_uint16(struct dns_buffer *buf, uint16 val); +void dns_marshall_uint32(struct dns_buffer *buf, uint32 val); +void dns_unmarshall_buffer(struct dns_buffer *buf, uint8 *data, + size_t len); +void dns_unmarshall_uint16(struct dns_buffer *buf, uint16 *val); +void dns_unmarshall_uint32(struct dns_buffer *buf, uint32 *val); +void dns_unmarshall_domain_name(TALLOC_CTX *mem_ctx, + struct dns_buffer *buf, + struct dns_domain_name **pname); +void dns_marshall_domain_name(struct dns_buffer *buf, + const struct dns_domain_name *name); +void dns_unmarshall_domain_name(TALLOC_CTX *mem_ctx, + struct dns_buffer *buf, + struct dns_domain_name **pname); +DNS_ERROR dns_marshall_request(TALLOC_CTX *mem_ctx, + const struct dns_request *req, + struct dns_buffer **pbuf); +DNS_ERROR dns_unmarshall_request(TALLOC_CTX *mem_ctx, + struct dns_buffer *buf, + struct dns_request **preq); +DNS_ERROR dns_marshall_update_request(TALLOC_CTX *mem_ctx, + struct dns_update_request *update, + struct dns_buffer **pbuf); +DNS_ERROR dns_unmarshall_update_request(TALLOC_CTX *mem_ctx, + struct dns_buffer *buf, + struct dns_update_request **pupreq); +struct dns_request *dns_update2request(struct dns_update_request *update); +struct dns_update_request *dns_request2update(struct dns_request *request); +uint16 dns_response_code(uint16 flags); +const char *dns_errstr(DNS_ERROR err); + +/* from dnsgss.c */ + +#ifdef HAVE_GSSAPI_SUPPORT + +void display_status( const char *msg, OM_uint32 maj_stat, OM_uint32 min_stat ); +DNS_ERROR dns_negotiate_sec_ctx( const char *target_realm, + const char *servername, + const char *keyname, + gss_ctx_id_t *gss_ctx, + enum dns_ServerType srv_type ); +DNS_ERROR dns_sign_update(struct dns_update_request *req, + gss_ctx_id_t gss_ctx, + const char *keyname, + const char *algorithmname, + time_t time_signed, uint16 fudge); + +#endif /* HAVE_GSSAPI_SUPPORT */ + +#endif /* _DNS_H */ diff --git a/lib/addns/dnserr.h b/lib/addns/dnserr.h new file mode 100644 index 0000000000..9e049ac3a9 --- /dev/null +++ b/lib/addns/dnserr.h @@ -0,0 +1,87 @@ +/* + Error codes for Linux DNS client library implementation + + Copyright (C) 2006 Krishna Ganugapati + Copyright (C) 2006 Gerald Carter + + ** NOTE! The following LGPL license applies to the libaddns + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifndef _DNSERR_H +#define _DNSERR_H + + +/* The Splint code analysis tool (http://www.splint.org.) doesn't + like immediate structures. */ + +#ifdef _SPLINT_ +#undef HAVE_IMMEDIATE_STRUCTURES +#endif + +/* Setup the DNS_ERROR typedef. Technique takes from nt_status.h */ + +#if defined(HAVE_IMMEDIATE_STRUCTURES) +typedef struct {uint32 v;} DNS_ERROR; +#define ERROR_DNS(x) ((DNS_ERROR) { x }) +#define ERROR_DNS_V(x) ((x).v) +#else +typedef uint32 DNS_ERROR; +#define ERROR_DNS(x) (x) +#define ERROR_DNS_V(x) (x) +#endif + +#define ERR_DNS_IS_OK(x) (ERROR_DNS_V(x) == 0) +#define ERR_DNS_EQUAL(x,y) (ERROR_DNS_V(x) == ERROR_DNS_V(y)) + +/************************************************* + * Define the error codes here + *************************************************/ + +#define ERROR_DNS_SUCCESS ERROR_DNS(0) +#define ERROR_DNS_RECORD_NOT_FOUND ERROR_DNS(1) +#define ERROR_DNS_BAD_RESPONSE ERROR_DNS(2) +#define ERROR_DNS_INVALID_PARAMETER ERROR_DNS(3) +#define ERROR_DNS_NO_MEMORY ERROR_DNS(4) +#define ERROR_DNS_INVALID_NAME_SERVER ERROR_DNS(5) +#define ERROR_DNS_CONNECTION_FAILED ERROR_DNS(6) +#define ERROR_DNS_GSS_ERROR ERROR_DNS(7) +#define ERROR_DNS_INVALID_NAME ERROR_DNS(8) +#define ERROR_DNS_INVALID_MESSAGE ERROR_DNS(9) +#define ERROR_DNS_SOCKET_ERROR ERROR_DNS(10) +#define ERROR_DNS_UPDATE_FAILED ERROR_DNS(11) + +/* + * About to be removed, transitional error + */ +#define ERROR_DNS_UNSUCCESSFUL ERROR_DNS(999) + + +#define ERROR_BAD_RESPONSE 1 +#define ERROR_RECORD_NOT_FOUND 2 +#define ERROR_OUTOFMEMORY 8 +#if !defined(ERROR_INVALID_PARAMETER) +#define ERROR_INVALID_PARAMETER 87 +#endif + +/* + * About to be removed, transitional error + */ +#define ERROR_UNSUCCESSFUL 999 + +#endif /* _DNSERR_H */ + diff --git a/lib/addns/dnsgss.c b/lib/addns/dnsgss.c new file mode 100644 index 0000000000..c9037417da --- /dev/null +++ b/lib/addns/dnsgss.c @@ -0,0 +1,334 @@ +/* + Public Interface file for Linux DNS client library implementation + + Copyright (C) 2006 Krishna Ganugapati + Copyright (C) 2006 Gerald Carter + + ** NOTE! The following LGPL license applies to the libaddns + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#include "dns.h" +#include + + +#ifdef HAVE_GSSAPI_SUPPORT + +/********************************************************************* +*********************************************************************/ + +#ifndef HAVE_STRUPR +static int strupr( char *szDomainName ) +{ + if ( !szDomainName ) { + return ( 0 ); + } + while ( *szDomainName != '\0' ) { + *szDomainName = toupper( *szDomainName ); + szDomainName++; + } + return ( 0 ); +} +#endif + +#if 0 +/********************************************************************* +*********************************************************************/ + +static void display_status_1( const char *m, OM_uint32 code, int type ) +{ + OM_uint32 maj_stat, min_stat; + gss_buffer_desc msg; + OM_uint32 msg_ctx; + + msg_ctx = 0; + while ( 1 ) { + maj_stat = gss_display_status( &min_stat, code, + type, GSS_C_NULL_OID, + &msg_ctx, &msg ); + fprintf( stdout, "GSS-API error %s: %s\n", m, + ( char * ) msg.value ); + ( void ) gss_release_buffer( &min_stat, &msg ); + + if ( !msg_ctx ) + break; + } +} + +/********************************************************************* +*********************************************************************/ + +void display_status( const char *msg, OM_uint32 maj_stat, OM_uint32 min_stat ) +{ + display_status_1( msg, maj_stat, GSS_C_GSS_CODE ); + display_status_1( msg, min_stat, GSS_C_MECH_CODE ); +} +#endif + +static DNS_ERROR dns_negotiate_gss_ctx_int( TALLOC_CTX *mem_ctx, + struct dns_connection *conn, + const char *keyname, + const gss_name_t target_name, + gss_ctx_id_t *ctx, + enum dns_ServerType srv_type ) +{ + struct gss_buffer_desc_struct input_desc, *input_ptr, output_desc; + OM_uint32 major, minor; + OM_uint32 ret_flags; + DNS_ERROR err; + + gss_OID_desc krb5_oid_desc = + { 9, (char *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" }; + + *ctx = GSS_C_NO_CONTEXT; + input_ptr = NULL; + + do { + major = gss_init_sec_context( + &minor, NULL, ctx, target_name, &krb5_oid_desc, + GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | + GSS_C_CONF_FLAG | + GSS_C_INTEG_FLAG, + 0, NULL, input_ptr, NULL, &output_desc, + &ret_flags, NULL ); + + if (input_ptr != NULL) { + TALLOC_FREE(input_desc.value); + } + + if (output_desc.length != 0) { + + struct dns_request *req; + struct dns_rrec *rec; + struct dns_buffer *buf; + + time_t t = time(NULL); + + err = dns_create_query(mem_ctx, keyname, QTYPE_TKEY, + DNS_CLASS_IN, &req); + if (!ERR_DNS_IS_OK(err)) goto error; + + err = dns_create_tkey_record( + req, keyname, "gss.microsoft.com", t, + t + 86400, DNS_TKEY_MODE_GSSAPI, 0, + output_desc.length, (uint8 *)output_desc.value, + &rec ); + if (!ERR_DNS_IS_OK(err)) goto error; + + /* Windows 2000 DNS is broken and requires the + TKEY payload in the Answer section instead + of the Additional seciton like Windows 2003 */ + + if ( srv_type == DNS_SRV_WIN2000 ) { + err = dns_add_rrec(req, rec, &req->num_answers, + &req->answers); + } else { + err = dns_add_rrec(req, rec, &req->num_additionals, + &req->additionals); + } + + if (!ERR_DNS_IS_OK(err)) goto error; + + err = dns_marshall_request(req, req, &buf); + if (!ERR_DNS_IS_OK(err)) goto error; + + err = dns_send(conn, buf); + if (!ERR_DNS_IS_OK(err)) goto error; + + TALLOC_FREE(req); + } + + gss_release_buffer(&minor, &output_desc); + + if ((major != GSS_S_COMPLETE) && + (major != GSS_S_CONTINUE_NEEDED)) { + return ERROR_DNS_GSS_ERROR; + } + + if (major == GSS_S_CONTINUE_NEEDED) { + + struct dns_request *resp; + struct dns_buffer *buf; + struct dns_tkey_record *tkey; + + err = dns_receive(mem_ctx, conn, &buf); + if (!ERR_DNS_IS_OK(err)) goto error; + + err = dns_unmarshall_request(buf, buf, &resp); + if (!ERR_DNS_IS_OK(err)) goto error; + + /* + * TODO: Compare id and keyname + */ + + if ((resp->num_additionals != 1) || + (resp->num_answers == 0) || + (resp->answers[0]->type != QTYPE_TKEY)) { + err = ERROR_DNS_INVALID_MESSAGE; + goto error; + } + + err = dns_unmarshall_tkey_record( + mem_ctx, resp->answers[0], &tkey); + if (!ERR_DNS_IS_OK(err)) goto error; + + input_desc.length = tkey->key_length; + input_desc.value = talloc_move(mem_ctx, &tkey->key); + + input_ptr = &input_desc; + + TALLOC_FREE(buf); + } + + } while ( major == GSS_S_CONTINUE_NEEDED ); + + /* If we arrive here, we have a valid security context */ + + err = ERROR_DNS_SUCCESS; + + error: + + return err; +} + +DNS_ERROR dns_negotiate_sec_ctx( const char *target_realm, + const char *servername, + const char *keyname, + gss_ctx_id_t *gss_ctx, + enum dns_ServerType srv_type ) +{ + OM_uint32 major, minor; + + char *upcaserealm, *targetname; + DNS_ERROR err; + + gss_buffer_desc input_name; + struct dns_connection *conn; + + gss_name_t targ_name; + + gss_OID_desc nt_host_oid_desc = + {10, (char *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01"}; + + TALLOC_CTX *mem_ctx; + + if (!(mem_ctx = talloc_init("dns_negotiate_sec_ctx"))) { + return ERROR_DNS_NO_MEMORY; + } + + err = dns_open_connection( servername, DNS_TCP, mem_ctx, &conn ); + if (!ERR_DNS_IS_OK(err)) goto error; + + if (!(upcaserealm = talloc_strdup(mem_ctx, target_realm))) { + err = ERROR_DNS_NO_MEMORY; + goto error; + } + + strupr(upcaserealm); + + if (!(targetname = talloc_asprintf(mem_ctx, "dns/%s@%s", + servername, upcaserealm))) { + err = ERROR_DNS_NO_MEMORY; + goto error; + } + + input_name.value = targetname; + input_name.length = strlen(targetname); + + major = gss_import_name( &minor, &input_name, + &nt_host_oid_desc, &targ_name ); + + if (major) { + err = ERROR_DNS_GSS_ERROR; + goto error; + } + + err = dns_negotiate_gss_ctx_int(mem_ctx, conn, keyname, + targ_name, gss_ctx, srv_type ); + + gss_release_name( &minor, &targ_name ); + + error: + TALLOC_FREE(mem_ctx); + + return err; +} + +DNS_ERROR dns_sign_update(struct dns_update_request *req, + gss_ctx_id_t gss_ctx, + const char *keyname, + const char *algorithmname, + time_t time_signed, uint16 fudge) +{ + struct dns_buffer *buf; + DNS_ERROR err; + struct dns_domain_name *key, *algorithm; + struct gss_buffer_desc_struct msg, mic; + OM_uint32 major, minor; + struct dns_rrec *rec; + + err = dns_marshall_update_request(req, req, &buf); + if (!ERR_DNS_IS_OK(err)) return err; + + err = dns_domain_name_from_string(buf, keyname, &key); + if (!ERR_DNS_IS_OK(err)) goto error; + + err = dns_domain_name_from_string(buf, algorithmname, &algorithm); + if (!ERR_DNS_IS_OK(err)) goto error; + + dns_marshall_domain_name(buf, key); + dns_marshall_uint16(buf, DNS_CLASS_ANY); + dns_marshall_uint32(buf, 0); /* TTL */ + dns_marshall_domain_name(buf, algorithm); + dns_marshall_uint16(buf, 0); /* Time prefix for 48-bit time_t */ + dns_marshall_uint32(buf, time_signed); + dns_marshall_uint16(buf, fudge); + dns_marshall_uint16(buf, 0); /* error */ + dns_marshall_uint16(buf, 0); /* other len */ + + err = buf->error; + if (!ERR_DNS_IS_OK(buf->error)) goto error; + + msg.value = (void *)buf->data; + msg.length = buf->offset; + + major = gss_get_mic(&minor, gss_ctx, 0, &msg, &mic); + if (major != 0) { + err = ERROR_DNS_GSS_ERROR; + goto error; + } + + if (mic.length > 0xffff) { + gss_release_buffer(&minor, &mic); + err = ERROR_DNS_GSS_ERROR; + goto error; + } + + err = dns_create_tsig_record(buf, keyname, algorithmname, time_signed, + fudge, mic.length, (uint8 *)mic.value, + req->id, 0, &rec); + gss_release_buffer(&minor, &mic); + if (!ERR_DNS_IS_OK(err)) goto error; + + err = dns_add_rrec(req, rec, &req->num_additionals, &req->additionals); + + error: + TALLOC_FREE(buf); + return err; +} + +#endif /* HAVE_GSSAPI_SUPPORT */ diff --git a/lib/addns/dnsmarshall.c b/lib/addns/dnsmarshall.c new file mode 100644 index 0000000000..5530290c57 --- /dev/null +++ b/lib/addns/dnsmarshall.c @@ -0,0 +1,530 @@ +/* + Linux DNS client library implementation + Copyright (C) 2006 Gerald Carter + + ** NOTE! The following LGPL license applies to the libaddns + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#include "dns.h" +#include "assert.h" + +struct dns_buffer *dns_create_buffer(TALLOC_CTX *mem_ctx) +{ + struct dns_buffer *result; + + if (!(result = talloc(mem_ctx, struct dns_buffer))) { + return NULL; + } + + result->offset = 0; + result->error = ERROR_DNS_SUCCESS; + + /* + * Small inital size to excercise the realloc code + */ + result->size = 2; + + if (!(result->data = TALLOC_ARRAY(result, uint8, result->size))) { + TALLOC_FREE(result); + return NULL; + } + + return result; +} + +void dns_marshall_buffer(struct dns_buffer *buf, const uint8 *data, + size_t len) +{ + if (!ERR_DNS_IS_OK(buf->error)) return; + + if (buf->offset + len < buf->offset) { + /* + * Wraparound! + */ + buf->error = ERROR_DNS_INVALID_PARAMETER; + return; + } + + if ((buf->offset + len) > 0xffff) { + /* + * Only 64k possible + */ + buf->error = ERROR_DNS_INVALID_PARAMETER; + return; + } + + if (buf->offset + len > buf->size) { + size_t new_size = buf->offset + len; + uint8 *new_data; + + /* + * Don't do too many reallocs, round up to some multiple + */ + + new_size += (64 - (new_size % 64)); + + if (!(new_data = TALLOC_REALLOC_ARRAY(buf, buf->data, uint8, + new_size))) { + buf->error = ERROR_DNS_NO_MEMORY; + return; + } + + buf->size = new_size; + buf->data = new_data; + } + + memcpy(buf->data + buf->offset, data, len); + buf->offset += len; + return; +} + +void dns_marshall_uint16(struct dns_buffer *buf, uint16 val) +{ + uint16 n_val = htons(val); + dns_marshall_buffer(buf, (uint8 *)&n_val, sizeof(n_val)); +} + +void dns_marshall_uint32(struct dns_buffer *buf, uint32 val) +{ + uint32 n_val = htonl(val); + dns_marshall_buffer(buf, (uint8 *)&n_val, sizeof(n_val)); +} + +void dns_unmarshall_buffer(struct dns_buffer *buf, uint8 *data, + size_t len) +{ + if (!(ERR_DNS_IS_OK(buf->error))) return; + + if ((len > buf->size) || (buf->offset + len > buf->size)) { + buf->error = ERROR_DNS_INVALID_MESSAGE; + return; + } + + memcpy((void *)data, (const void *)(buf->data + buf->offset), len); + buf->offset += len; + + return; +} + +void dns_unmarshall_uint16(struct dns_buffer *buf, uint16 *val) +{ + uint16 n_val; + + dns_unmarshall_buffer(buf, (uint8 *)&n_val, sizeof(n_val)); + if (!(ERR_DNS_IS_OK(buf->error))) return; + + *val = ntohs(n_val); +} + +void dns_unmarshall_uint32(struct dns_buffer *buf, uint32 *val) +{ + uint32 n_val; + + dns_unmarshall_buffer(buf, (uint8 *)&n_val, sizeof(n_val)); + if (!(ERR_DNS_IS_OK(buf->error))) return; + + *val = ntohl(n_val); +} + +void dns_marshall_domain_name(struct dns_buffer *buf, + const struct dns_domain_name *name) +{ + struct dns_domain_label *label; + char end_char = '\0'; + + /* + * TODO: Implement DNS compression + */ + + for (label = name->pLabelList; label != NULL; label = label->next) { + uint8 len = label->len; + + dns_marshall_buffer(buf, (uint8 *)&len, sizeof(len)); + if (!ERR_DNS_IS_OK(buf->error)) return; + + dns_marshall_buffer(buf, (uint8 *)label->label, len); + if (!ERR_DNS_IS_OK(buf->error)) return; + } + + dns_marshall_buffer(buf, (uint8 *)&end_char, 1); +} + +static void dns_unmarshall_label(TALLOC_CTX *mem_ctx, + int level, + struct dns_buffer *buf, + struct dns_domain_label **plabel) +{ + struct dns_domain_label *label; + uint8 len; + + if (!ERR_DNS_IS_OK(buf->error)) return; + + if (level > 128) { + /* + * Protect against recursion + */ + buf->error = ERROR_DNS_INVALID_MESSAGE; + return; + } + + dns_unmarshall_buffer(buf, &len, sizeof(len)); + if (!ERR_DNS_IS_OK(buf->error)) return; + + if (len == 0) { + *plabel = NULL; + return; + } + + if ((len & 0xc0) == 0xc0) { + /* + * We've got a compressed name. Build up a new "fake" buffer + * and using the calculated offset. + */ + struct dns_buffer new_buf; + uint8 low; + + dns_unmarshall_buffer(buf, &low, sizeof(low)); + if (!ERR_DNS_IS_OK(buf->error)) return; + + new_buf = *buf; + new_buf.offset = len & 0x3f; + new_buf.offset <<= 8; + new_buf.offset |= low; + + dns_unmarshall_label(mem_ctx, level+1, &new_buf, plabel); + buf->error = new_buf.error; + return; + } + + if ((len & 0xc0) != 0) { + buf->error = ERROR_DNS_INVALID_NAME; + return; + } + + if (!(label = talloc(mem_ctx, struct dns_domain_label))) { + buf->error = ERROR_DNS_NO_MEMORY; + return; + } + + label->len = len; + + if (!(label->label = TALLOC_ARRAY(label, char, len+1))) { + buf->error = ERROR_DNS_NO_MEMORY; + goto error; + } + + dns_unmarshall_buffer(buf, (uint8 *)label->label, len); + if (!ERR_DNS_IS_OK(buf->error)) goto error; + + dns_unmarshall_label(label, level+1, buf, &label->next); + if (!ERR_DNS_IS_OK(buf->error)) goto error; + + *plabel = label; + return; + + error: + TALLOC_FREE(label); + return; +} + +void dns_unmarshall_domain_name(TALLOC_CTX *mem_ctx, + struct dns_buffer *buf, + struct dns_domain_name **pname) +{ + struct dns_domain_name *name; + + if (!ERR_DNS_IS_OK(buf->error)) return; + + if (!(name = talloc(mem_ctx, struct dns_domain_name))) { + buf->error = ERROR_DNS_NO_MEMORY; + return; + } + + dns_unmarshall_label(name, 0, buf, &name->pLabelList); + + if (!ERR_DNS_IS_OK(buf->error)) { + return; + } + + *pname = name; + return; +} + +static void dns_marshall_question(struct dns_buffer *buf, + const struct dns_question *q) +{ + dns_marshall_domain_name(buf, q->name); + dns_marshall_uint16(buf, q->q_type); + dns_marshall_uint16(buf, q->q_class); +} + +static void dns_unmarshall_question(TALLOC_CTX *mem_ctx, + struct dns_buffer *buf, + struct dns_question **pq) +{ + struct dns_question *q; + + if (!(ERR_DNS_IS_OK(buf->error))) return; + + if (!(q = talloc(mem_ctx, struct dns_question))) { + buf->error = ERROR_DNS_NO_MEMORY; + return; + } + + dns_unmarshall_domain_name(q, buf, &q->name); + dns_unmarshall_uint16(buf, &q->q_type); + dns_unmarshall_uint16(buf, &q->q_class); + + if (!(ERR_DNS_IS_OK(buf->error))) return; + + *pq = q; +} + +static void dns_marshall_rr(struct dns_buffer *buf, + const struct dns_rrec *r) +{ + dns_marshall_domain_name(buf, r->name); + dns_marshall_uint16(buf, r->type); + dns_marshall_uint16(buf, r->r_class); + dns_marshall_uint32(buf, r->ttl); + dns_marshall_uint16(buf, r->data_length); + dns_marshall_buffer(buf, r->data, r->data_length); +} + +static void dns_unmarshall_rr(TALLOC_CTX *mem_ctx, + struct dns_buffer *buf, + struct dns_rrec **pr) +{ + struct dns_rrec *r; + + if (!(ERR_DNS_IS_OK(buf->error))) return; + + if (!(r = talloc(mem_ctx, struct dns_rrec))) { + buf->error = ERROR_DNS_NO_MEMORY; + return; + } + + dns_unmarshall_domain_name(r, buf, &r->name); + dns_unmarshall_uint16(buf, &r->type); + dns_unmarshall_uint16(buf, &r->r_class); + dns_unmarshall_uint32(buf, &r->ttl); + dns_unmarshall_uint16(buf, &r->data_length); + r->data = NULL; + + if (!(ERR_DNS_IS_OK(buf->error))) return; + + if (r->data_length != 0) { + if (!(r->data = TALLOC_ARRAY(r, uint8, r->data_length))) { + buf->error = ERROR_DNS_NO_MEMORY; + return; + } + dns_unmarshall_buffer(buf, r->data, r->data_length); + } + + if (!(ERR_DNS_IS_OK(buf->error))) return; + + *pr = r; +} + +DNS_ERROR dns_marshall_request(TALLOC_CTX *mem_ctx, + const struct dns_request *req, + struct dns_buffer **pbuf) +{ + struct dns_buffer *buf; + uint16 i; + + if (!(buf = dns_create_buffer(mem_ctx))) { + return ERROR_DNS_NO_MEMORY; + } + + dns_marshall_uint16(buf, req->id); + dns_marshall_uint16(buf, req->flags); + dns_marshall_uint16(buf, req->num_questions); + dns_marshall_uint16(buf, req->num_answers); + dns_marshall_uint16(buf, req->num_auths); + dns_marshall_uint16(buf, req->num_additionals); + + for (i=0; inum_questions; i++) { + dns_marshall_question(buf, req->questions[i]); + } + for (i=0; inum_answers; i++) { + dns_marshall_rr(buf, req->answers[i]); + } + for (i=0; inum_auths; i++) { + dns_marshall_rr(buf, req->auths[i]); + } + for (i=0; inum_additionals; i++) { + dns_marshall_rr(buf, req->additionals[i]); + } + + if (!ERR_DNS_IS_OK(buf->error)) { + DNS_ERROR err = buf->error; + TALLOC_FREE(buf); + return err; + } + + *pbuf = buf; + return ERROR_DNS_SUCCESS; +} + +DNS_ERROR dns_unmarshall_request(TALLOC_CTX *mem_ctx, + struct dns_buffer *buf, + struct dns_request **preq) +{ + struct dns_request *req; + uint16 i; + DNS_ERROR err; + + if (!(req = TALLOC_ZERO_P(mem_ctx, struct dns_request))) { + return ERROR_DNS_NO_MEMORY; + } + + dns_unmarshall_uint16(buf, &req->id); + dns_unmarshall_uint16(buf, &req->flags); + dns_unmarshall_uint16(buf, &req->num_questions); + dns_unmarshall_uint16(buf, &req->num_answers); + dns_unmarshall_uint16(buf, &req->num_auths); + dns_unmarshall_uint16(buf, &req->num_additionals); + + if (!ERR_DNS_IS_OK(buf->error)) goto error; + + err = ERROR_DNS_NO_MEMORY; + + if ((req->num_questions != 0) && + !(req->questions = TALLOC_ARRAY(req, struct dns_question *, + req->num_questions))) { + goto error; + } + if ((req->num_answers != 0) && + !(req->answers = TALLOC_ARRAY(req, struct dns_rrec *, + req->num_answers))) { + goto error; + } + if ((req->num_auths != 0) && + !(req->auths = TALLOC_ARRAY(req, struct dns_rrec *, + req->num_auths))) { + goto error; + } + if ((req->num_additionals != 0) && + !(req->additionals = TALLOC_ARRAY(req, struct dns_rrec *, + req->num_additionals))) { + goto error; + } + + for (i=0; inum_questions; i++) { + dns_unmarshall_question(req->questions, buf, + &req->questions[i]); + } + for (i=0; inum_answers; i++) { + dns_unmarshall_rr(req->answers, buf, + &req->answers[i]); + } + for (i=0; inum_auths; i++) { + dns_unmarshall_rr(req->auths, buf, + &req->auths[i]); + } + for (i=0; inum_additionals; i++) { + dns_unmarshall_rr(req->additionals, buf, + &req->additionals[i]); + } + + if (!ERR_DNS_IS_OK(buf->error)) { + err = buf->error; + goto error; + } + + *preq = req; + return ERROR_DNS_SUCCESS; + + error: + err = buf->error; + TALLOC_FREE(req); + return err; +} + +struct dns_request *dns_update2request(struct dns_update_request *update) +{ + struct dns_request *req; + + /* + * This is a non-specified construct that happens to work on Linux/gcc + * and I would expect it to work everywhere else. dns_request and + * dns_update_request are essentially the same structures with + * different names, so any difference would mean that the compiler + * applied two different variations of padding given the same types in + * the structures. + */ + + req = (struct dns_request *)(void *)update; + + /* + * The assert statement here looks like we could do the equivalent + * assignments to get portable, but it would mean that we have to + * allocate the dns_question record for the dns_zone records. We + * assume that if this assert works then the same holds true for + * dns_zone<>dns_question as well. + */ + +#ifdef DEVELOPER + assert((req->id == update->id) && (req->flags == update->flags) && + (req->num_questions == update->num_zones) && + (req->num_answers == update->num_preqs) && + (req->num_auths == update->num_updates) && + (req->num_additionals == update->num_additionals) && + (req->questions == + (struct dns_question **)(void *)update->zones) && + (req->answers == update->preqs) && + (req->auths == update->updates) && + (req->additionals == update->additionals)); +#endif + + return req; +} + +struct dns_update_request *dns_request2update(struct dns_request *request) +{ + /* + * For portability concerns see dns_update2request; + */ + return (struct dns_update_request *)(void *)request; +} + +DNS_ERROR dns_marshall_update_request(TALLOC_CTX *mem_ctx, + struct dns_update_request *update, + struct dns_buffer **pbuf) +{ + return dns_marshall_request(mem_ctx, dns_update2request(update), pbuf); +} + +DNS_ERROR dns_unmarshall_update_request(TALLOC_CTX *mem_ctx, + struct dns_buffer *buf, + struct dns_update_request **pupreq) +{ + /* + * See comments above about portability. If the above works, this will + * as well. + */ + + return dns_unmarshall_request(mem_ctx, buf, + (struct dns_request **)(void *)pupreq); +} + +uint16 dns_response_code(uint16 flags) +{ + return flags & 0xF; +} diff --git a/lib/addns/dnsrecord.c b/lib/addns/dnsrecord.c new file mode 100644 index 0000000000..559c2644d4 --- /dev/null +++ b/lib/addns/dnsrecord.c @@ -0,0 +1,422 @@ +/* + Linux DNS client library implementation + Copyright (C) 2006 Krishna Ganugapati + Copyright (C) 2006 Gerald Carter + + ** NOTE! The following LGPL license applies to the libaddns + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#include "dns.h" + +DNS_ERROR dns_create_query( TALLOC_CTX *mem_ctx, const char *name, + uint16 q_type, uint16 q_class, + struct dns_request **preq ) +{ + struct dns_request *req; + struct dns_question *q; + DNS_ERROR err; + + if (!(req = TALLOC_ZERO_P(mem_ctx, struct dns_request)) || + !(req->questions = TALLOC_ARRAY(req, struct dns_question *, 1)) || + !(req->questions[0] = talloc(req->questions, + struct dns_question))) { + TALLOC_FREE(req); + return ERROR_DNS_NO_MEMORY; + } + + req->id = random(); + + req->num_questions = 1; + q = req->questions[0]; + + err = dns_domain_name_from_string(q, name, &q->name); + if (!ERR_DNS_IS_OK(err)) { + TALLOC_FREE(req); + return err; + } + + q->q_type = q_type; + q->q_class = q_class; + + *preq = req; + return ERROR_DNS_SUCCESS; +} + +DNS_ERROR dns_create_update( TALLOC_CTX *mem_ctx, const char *name, + struct dns_update_request **preq ) +{ + struct dns_update_request *req; + struct dns_zone *z; + DNS_ERROR err; + + if (!(req = TALLOC_ZERO_P(mem_ctx, struct dns_update_request)) || + !(req->zones = TALLOC_ARRAY(req, struct dns_zone *, 1)) || + !(req->zones[0] = talloc(req->zones, struct dns_zone))) { + TALLOC_FREE(req); + return ERROR_DNS_NO_MEMORY; + } + + req->id = random(); + req->flags = 0x2800; /* Dynamic update */ + + req->num_zones = 1; + z = req->zones[0]; + + err = dns_domain_name_from_string(z, name, &z->name); + if (!ERR_DNS_IS_OK(err)) { + TALLOC_FREE(req); + return err; + } + + z->z_type = QTYPE_SOA; + z->z_class = DNS_CLASS_IN; + + *preq = req; + return ERROR_DNS_SUCCESS; +} + +DNS_ERROR dns_create_rrec(TALLOC_CTX *mem_ctx, const char *name, + uint16 type, uint16 r_class, uint32 ttl, + uint16 data_length, uint8 *data, + struct dns_rrec **prec) +{ + struct dns_rrec *rec; + DNS_ERROR err; + + if (!(rec = talloc(mem_ctx, struct dns_rrec))) { + return ERROR_DNS_NO_MEMORY; + } + + err = dns_domain_name_from_string(rec, name, &rec->name); + if (!(ERR_DNS_IS_OK(err))) { + TALLOC_FREE(rec); + return err; + } + + rec->type = type; + rec->r_class = r_class; + rec->ttl = ttl; + rec->data_length = data_length; + rec->data = talloc_move(rec, &data); + + *prec = rec; + return ERROR_DNS_SUCCESS; +} + +DNS_ERROR dns_create_a_record(TALLOC_CTX *mem_ctx, const char *host, + uint32 ttl, const struct sockaddr_storage *pss, + struct dns_rrec **prec) +{ + uint8 *data; + DNS_ERROR err; + struct in_addr ip; + + if (pss->ss_family != AF_INET) { + /* Silently ignore this. */ + return ERROR_DNS_SUCCESS; + } + + ip = ((struct sockaddr_in *)pss)->sin_addr; + if (!(data = (uint8 *)TALLOC_MEMDUP(mem_ctx, (const void *)&ip.s_addr, + sizeof(ip.s_addr)))) { + return ERROR_DNS_NO_MEMORY; + } + + err = dns_create_rrec(mem_ctx, host, QTYPE_A, DNS_CLASS_IN, ttl, + sizeof(ip.s_addr), data, prec); + + if (!ERR_DNS_IS_OK(err)) { + TALLOC_FREE(data); + } + + return err; +} + +DNS_ERROR dns_create_name_in_use_record(TALLOC_CTX *mem_ctx, + const char *name, + const struct sockaddr_storage *ss, + struct dns_rrec **prec) +{ + if (ss != NULL) { + return dns_create_a_record(mem_ctx, name, 0, ss, prec); + } + + return dns_create_rrec(mem_ctx, name, QTYPE_ANY, DNS_CLASS_IN, 0, 0, + NULL, prec); +} + +DNS_ERROR dns_create_name_not_in_use_record(TALLOC_CTX *mem_ctx, + const char *name, uint32 type, + struct dns_rrec **prec) +{ + return dns_create_rrec(mem_ctx, name, type, DNS_CLASS_NONE, 0, + 0, NULL, prec); +} + +DNS_ERROR dns_create_delete_record(TALLOC_CTX *mem_ctx, const char *name, + uint16 type, uint16 r_class, + struct dns_rrec **prec) +{ + return dns_create_rrec(mem_ctx, name, type, r_class, 0, 0, NULL, prec); +} + +DNS_ERROR dns_create_tkey_record(TALLOC_CTX *mem_ctx, const char *keyname, + const char *algorithm_name, time_t inception, + time_t expiration, uint16 mode, uint16 error, + uint16 key_length, const uint8 *key, + struct dns_rrec **prec) +{ + struct dns_buffer *buf; + struct dns_domain_name *algorithm; + DNS_ERROR err; + + if (!(buf = dns_create_buffer(mem_ctx))) { + return ERROR_DNS_NO_MEMORY; + } + + err = dns_domain_name_from_string(buf, algorithm_name, &algorithm); + if (!ERR_DNS_IS_OK(err)) goto error; + + dns_marshall_domain_name(buf, algorithm); + dns_marshall_uint32(buf, inception); + dns_marshall_uint32(buf, expiration); + dns_marshall_uint16(buf, mode); + dns_marshall_uint16(buf, error); + dns_marshall_uint16(buf, key_length); + dns_marshall_buffer(buf, key, key_length); + dns_marshall_uint16(buf, 0); /* Other Size */ + + if (!ERR_DNS_IS_OK(buf->error)) { + err = buf->error; + goto error; + } + + err = dns_create_rrec(mem_ctx, keyname, QTYPE_TKEY, DNS_CLASS_ANY, 0, + buf->offset, buf->data, prec); + + error: + TALLOC_FREE(buf); + return err; +} + +DNS_ERROR dns_unmarshall_tkey_record(TALLOC_CTX *mem_ctx, struct dns_rrec *rec, + struct dns_tkey_record **ptkey) +{ + struct dns_tkey_record *tkey; + struct dns_buffer buf; + uint32 tmp_inception, tmp_expiration; + + if (!(tkey = talloc(mem_ctx, struct dns_tkey_record))) { + return ERROR_DNS_NO_MEMORY; + } + + buf.data = rec->data; + buf.size = rec->data_length; + buf.offset = 0; + buf.error = ERROR_DNS_SUCCESS; + + dns_unmarshall_domain_name(tkey, &buf, &tkey->algorithm); + dns_unmarshall_uint32(&buf, &tmp_inception); + dns_unmarshall_uint32(&buf, &tmp_expiration); + dns_unmarshall_uint16(&buf, &tkey->mode); + dns_unmarshall_uint16(&buf, &tkey->error); + dns_unmarshall_uint16(&buf, &tkey->key_length); + + if (!ERR_DNS_IS_OK(buf.error)) goto error; + + if (tkey->key_length) { + if (!(tkey->key = TALLOC_ARRAY(tkey, uint8, tkey->key_length))) { + buf.error = ERROR_DNS_NO_MEMORY; + goto error; + } + } else { + tkey->key = NULL; + } + + dns_unmarshall_buffer(&buf, tkey->key, tkey->key_length); + if (!ERR_DNS_IS_OK(buf.error)) goto error; + + tkey->inception = (time_t)tmp_inception; + tkey->expiration = (time_t)tmp_expiration; + + *ptkey = tkey; + return ERROR_DNS_SUCCESS; + + error: + TALLOC_FREE(tkey); + return buf.error; +} + +DNS_ERROR dns_create_tsig_record(TALLOC_CTX *mem_ctx, const char *keyname, + const char *algorithm_name, + time_t time_signed, uint16 fudge, + uint16 mac_length, const uint8 *mac, + uint16 original_id, uint16 error, + struct dns_rrec **prec) +{ + struct dns_buffer *buf; + struct dns_domain_name *algorithm; + DNS_ERROR err; + + if (!(buf = dns_create_buffer(mem_ctx))) { + return ERROR_DNS_NO_MEMORY; + } + + err = dns_domain_name_from_string(buf, algorithm_name, &algorithm); + if (!ERR_DNS_IS_OK(err)) goto error; + + dns_marshall_domain_name(buf, algorithm); + dns_marshall_uint16(buf, 0); /* time prefix */ + dns_marshall_uint32(buf, time_signed); + dns_marshall_uint16(buf, fudge); + dns_marshall_uint16(buf, mac_length); + dns_marshall_buffer(buf, mac, mac_length); + dns_marshall_uint16(buf, original_id); + dns_marshall_uint16(buf, error); + dns_marshall_uint16(buf, 0); /* Other Size */ + + if (!ERR_DNS_IS_OK(buf->error)) { + err = buf->error; + goto error; + } + + err = dns_create_rrec(mem_ctx, keyname, QTYPE_TSIG, DNS_CLASS_ANY, 0, + buf->offset, buf->data, prec); + + error: + TALLOC_FREE(buf); + return err; +} + +DNS_ERROR dns_add_rrec(TALLOC_CTX *mem_ctx, struct dns_rrec *rec, + uint16 *num_records, struct dns_rrec ***records) +{ + struct dns_rrec **new_records; + + if (!(new_records = TALLOC_REALLOC_ARRAY(mem_ctx, *records, + struct dns_rrec *, + (*num_records)+1))) { + return ERROR_DNS_NO_MEMORY; + } + + new_records[*num_records] = talloc_move(new_records, &rec); + + *num_records += 1; + *records = new_records; + return ERROR_DNS_SUCCESS; +} + +/* + * Create a request that probes a server whether the list of IP addresses + * provides meets our expectations + */ + +DNS_ERROR dns_create_probe(TALLOC_CTX *mem_ctx, const char *zone, + const char *host, int num_ips, + const struct sockaddr_storage *sslist, + struct dns_update_request **preq) +{ + struct dns_update_request *req; + struct dns_rrec *rec; + DNS_ERROR err; + uint16 i; + + err = dns_create_update(mem_ctx, zone, &req); + if (!ERR_DNS_IS_OK(err)) goto error; + + err = dns_create_name_not_in_use_record(req, host, QTYPE_CNAME, &rec); + if (!ERR_DNS_IS_OK(err)) goto error; + + err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs); + if (!ERR_DNS_IS_OK(err)) goto error; + + for (i=0; inum_preqs, &req->preqs); + if (!ERR_DNS_IS_OK(err)) goto error; + } + + *preq = req; + return ERROR_DNS_SUCCESS; + + error: + TALLOC_FREE(req); + return err; +} + +DNS_ERROR dns_create_update_request(TALLOC_CTX *mem_ctx, + const char *domainname, + const char *hostname, + const struct sockaddr_storage *ss_addrs, + size_t num_addrs, + struct dns_update_request **preq) +{ + struct dns_update_request *req; + struct dns_rrec *rec; + DNS_ERROR err; + size_t i; + + err = dns_create_update(mem_ctx, domainname, &req); + if (!ERR_DNS_IS_OK(err)) return err; + + /* + * Use the same prereq as WinXP -- No CNAME records for this host. + */ + + err = dns_create_rrec(req, hostname, QTYPE_CNAME, DNS_CLASS_NONE, + 0, 0, NULL, &rec); + if (!ERR_DNS_IS_OK(err)) goto error; + + err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs); + if (!ERR_DNS_IS_OK(err)) goto error; + + /* + * Delete any existing A records + */ + + err = dns_create_delete_record(req, hostname, QTYPE_A, DNS_CLASS_ANY, + &rec); + if (!ERR_DNS_IS_OK(err)) goto error; + + err = dns_add_rrec(req, rec, &req->num_updates, &req->updates); + if (!ERR_DNS_IS_OK(err)) goto error; + + /* + * .. and add our IPs + */ + + for ( i=0; inum_updates, &req->updates); + if (!ERR_DNS_IS_OK(err)) + goto error; + } + + *preq = req; + return ERROR_DNS_SUCCESS; + + error: + TALLOC_FREE(req); + return err; +} diff --git a/lib/addns/dnssock.c b/lib/addns/dnssock.c new file mode 100644 index 0000000000..7c8bd418e5 --- /dev/null +++ b/lib/addns/dnssock.c @@ -0,0 +1,377 @@ +/* + Linux DNS client library implementation + + Copyright (C) 2006 Krishna Ganugapati + Copyright (C) 2006 Gerald Carter + + ** NOTE! The following LGPL license applies to the libaddns + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#include "dns.h" +#include +#include + +static int destroy_dns_connection(struct dns_connection *conn) +{ + return close(conn->s); +} + +/******************************************************************** +********************************************************************/ + +static DNS_ERROR dns_tcp_open( const char *nameserver, + TALLOC_CTX *mem_ctx, + struct dns_connection **result ) +{ + uint32_t ulAddress; + struct hostent *pHost; + struct sockaddr_in s_in; + struct dns_connection *conn; + int res; + + if (!(conn = talloc(mem_ctx, struct dns_connection))) { + return ERROR_DNS_NO_MEMORY; + } + + if ( (ulAddress = inet_addr( nameserver )) == INADDR_NONE ) { + if ( (pHost = gethostbyname( nameserver )) == NULL ) { + TALLOC_FREE(conn); + return ERROR_DNS_INVALID_NAME_SERVER; + } + memcpy( &ulAddress, pHost->h_addr, pHost->h_length ); + } + + conn->s = socket( PF_INET, SOCK_STREAM, 0 ); + if (conn->s == -1) { + TALLOC_FREE(conn); + return ERROR_DNS_CONNECTION_FAILED; + } + + talloc_set_destructor(conn, destroy_dns_connection); + + s_in.sin_family = AF_INET; + s_in.sin_addr.s_addr = ulAddress; + s_in.sin_port = htons( DNS_TCP_PORT ); + + res = connect(conn->s, (struct sockaddr*)&s_in, sizeof( s_in )); + if (res == -1) { + TALLOC_FREE(conn); + return ERROR_DNS_CONNECTION_FAILED; + } + + conn->hType = DNS_TCP; + + *result = conn; + return ERROR_DNS_SUCCESS; +} + +/******************************************************************** +********************************************************************/ + +static DNS_ERROR dns_udp_open( const char *nameserver, + TALLOC_CTX *mem_ctx, + struct dns_connection **result ) +{ + unsigned long ulAddress; + struct hostent *pHost; + struct sockaddr_in RecvAddr; + struct dns_connection *conn; + + if (!(conn = talloc(NULL, struct dns_connection))) { + return ERROR_DNS_NO_MEMORY; + } + + if ( (ulAddress = inet_addr( nameserver )) == INADDR_NONE ) { + if ( (pHost = gethostbyname( nameserver )) == NULL ) { + TALLOC_FREE(conn); + return ERROR_DNS_INVALID_NAME_SERVER; + } + memcpy( &ulAddress, pHost->h_addr, pHost->h_length ); + } + + /* Create a socket for sending data */ + + conn->s = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); + if (conn->s == -1) { + TALLOC_FREE(conn); + return ERROR_DNS_CONNECTION_FAILED; + } + + talloc_set_destructor(conn, destroy_dns_connection); + + /* Set up the RecvAddr structure with the IP address of + the receiver (in this example case "123.456.789.1") + and the specified port number. */ + + ZERO_STRUCT(RecvAddr); + RecvAddr.sin_family = AF_INET; + RecvAddr.sin_port = htons( DNS_UDP_PORT ); + RecvAddr.sin_addr.s_addr = ulAddress; + + conn->hType = DNS_UDP; + memcpy( &conn->RecvAddr, &RecvAddr, sizeof( struct sockaddr_in ) ); + + *result = conn; + return ERROR_DNS_SUCCESS; +} + +/******************************************************************** +********************************************************************/ + +DNS_ERROR dns_open_connection( const char *nameserver, int32 dwType, + TALLOC_CTX *mem_ctx, + struct dns_connection **conn ) +{ + switch ( dwType ) { + case DNS_TCP: + return dns_tcp_open( nameserver, mem_ctx, conn ); + case DNS_UDP: + return dns_udp_open( nameserver, mem_ctx, conn ); + } + + return ERROR_DNS_INVALID_PARAMETER; +} + +static DNS_ERROR write_all(int fd, uint8 *data, size_t len) +{ + size_t total = 0; + + while (total < len) { + + ssize_t ret = write(fd, data + total, len - total); + + if (ret <= 0) { + /* + * EOF or error + */ + return ERROR_DNS_SOCKET_ERROR; + } + + total += ret; + } + + return ERROR_DNS_SUCCESS; +} + +static DNS_ERROR dns_send_tcp(struct dns_connection *conn, + const struct dns_buffer *buf) +{ + uint16 len = htons(buf->offset); + DNS_ERROR err; + + err = write_all(conn->s, (uint8 *)&len, sizeof(len)); + if (!ERR_DNS_IS_OK(err)) return err; + + return write_all(conn->s, buf->data, buf->offset); +} + +static DNS_ERROR dns_send_udp(struct dns_connection *conn, + const struct dns_buffer *buf) +{ + ssize_t ret; + + ret = sendto(conn->s, buf->data, buf->offset, 0, + (struct sockaddr *)&conn->RecvAddr, + sizeof(conn->RecvAddr)); + + if (ret != buf->offset) { + return ERROR_DNS_SOCKET_ERROR; + } + + return ERROR_DNS_SUCCESS; +} + +DNS_ERROR dns_send(struct dns_connection *conn, const struct dns_buffer *buf) +{ + if (conn->hType == DNS_TCP) { + return dns_send_tcp(conn, buf); + } + + if (conn->hType == DNS_UDP) { + return dns_send_udp(conn, buf); + } + + return ERROR_DNS_INVALID_PARAMETER; +} + +static DNS_ERROR read_all(int fd, uint8 *data, size_t len) +{ + size_t total = 0; + fd_set rfds; + struct timeval tv; + + while (total < len) { + ssize_t ret; + int fd_ready; + + FD_ZERO( &rfds ); + FD_SET( fd, &rfds ); + + /* 10 second timeout */ + tv.tv_sec = 10; + tv.tv_usec = 0; + + fd_ready = select( fd+1, &rfds, NULL, NULL, &tv ); + if ( fd_ready == 0 ) { + /* read timeout */ + return ERROR_DNS_SOCKET_ERROR; + } + + ret = read(fd, data + total, len - total); + if (ret <= 0) { + /* EOF or error */ + return ERROR_DNS_SOCKET_ERROR; + } + + total += ret; + } + + return ERROR_DNS_SUCCESS; +} + +static DNS_ERROR dns_receive_tcp(TALLOC_CTX *mem_ctx, + struct dns_connection *conn, + struct dns_buffer **presult) +{ + struct dns_buffer *buf; + DNS_ERROR err; + uint16 len; + + if (!(buf = TALLOC_ZERO_P(mem_ctx, struct dns_buffer))) { + return ERROR_DNS_NO_MEMORY; + } + + err = read_all(conn->s, (uint8 *)&len, sizeof(len)); + if (!ERR_DNS_IS_OK(err)) { + return err; + } + + buf->size = ntohs(len); + + if (buf->size) { + if (!(buf->data = TALLOC_ARRAY(buf, uint8, buf->size))) { + TALLOC_FREE(buf); + return ERROR_DNS_NO_MEMORY; + } + } else { + buf->data = NULL; + } + + err = read_all(conn->s, buf->data, buf->size); + if (!ERR_DNS_IS_OK(err)) { + TALLOC_FREE(buf); + return err; + } + + *presult = buf; + return ERROR_DNS_SUCCESS; +} + +static DNS_ERROR dns_receive_udp(TALLOC_CTX *mem_ctx, + struct dns_connection *conn, + struct dns_buffer **presult) +{ + struct dns_buffer *buf; + ssize_t received; + + if (!(buf = TALLOC_ZERO_P(mem_ctx, struct dns_buffer))) { + return ERROR_DNS_NO_MEMORY; + } + + /* + * UDP based DNS can only be 512 bytes + */ + + if (!(buf->data = TALLOC_ARRAY(buf, uint8, 512))) { + TALLOC_FREE(buf); + return ERROR_DNS_NO_MEMORY; + } + + received = recv(conn->s, (void *)buf->data, 512, 0); + + if (received == -1) { + TALLOC_FREE(buf); + return ERROR_DNS_SOCKET_ERROR; + } + + if (received > 512) { + TALLOC_FREE(buf); + return ERROR_DNS_BAD_RESPONSE; + } + + buf->size = received; + buf->offset = 0; + + *presult = buf; + return ERROR_DNS_SUCCESS; +} + +DNS_ERROR dns_receive(TALLOC_CTX *mem_ctx, struct dns_connection *conn, + struct dns_buffer **presult) +{ + if (conn->hType == DNS_TCP) { + return dns_receive_tcp(mem_ctx, conn, presult); + } + + if (conn->hType == DNS_UDP) { + return dns_receive_udp(mem_ctx, conn, presult); + } + + return ERROR_DNS_INVALID_PARAMETER; +} + +DNS_ERROR dns_transaction(TALLOC_CTX *mem_ctx, struct dns_connection *conn, + const struct dns_request *req, + struct dns_request **resp) +{ + struct dns_buffer *buf = NULL; + DNS_ERROR err; + + err = dns_marshall_request(conn, req, &buf); + if (!ERR_DNS_IS_OK(err)) goto error; + + err = dns_send(conn, buf); + if (!ERR_DNS_IS_OK(err)) goto error; + TALLOC_FREE(buf); + + err = dns_receive(mem_ctx, conn, &buf); + if (!ERR_DNS_IS_OK(err)) goto error; + + err = dns_unmarshall_request(mem_ctx, buf, resp); + + error: + TALLOC_FREE(buf); + return err; +} + +DNS_ERROR dns_update_transaction(TALLOC_CTX *mem_ctx, + struct dns_connection *conn, + struct dns_update_request *up_req, + struct dns_update_request **up_resp) +{ + struct dns_request *resp; + DNS_ERROR err; + + err = dns_transaction(mem_ctx, conn, dns_update2request(up_req), + &resp); + + if (!ERR_DNS_IS_OK(err)) return err; + + *up_resp = dns_request2update(resp); + return ERROR_DNS_SUCCESS; +} diff --git a/lib/addns/dnsutils.c b/lib/addns/dnsutils.c new file mode 100644 index 0000000000..37b862c7f0 --- /dev/null +++ b/lib/addns/dnsutils.c @@ -0,0 +1,151 @@ +/* + Linux DNS client library implementation + + Copyright (C) 2006 Krishna Ganugapati + Copyright (C) 2006 Gerald Carter + + ** NOTE! The following LGPL license applies to the libaddns + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#include "dns.h" +#include + +static DNS_ERROR LabelList( TALLOC_CTX *mem_ctx, + const char *name, + struct dns_domain_label **presult ) +{ + struct dns_domain_label *result; + const char *dot; + + for (dot = name; *dot != '\0'; dot += 1) { + char c = *dot; + + if (c == '.') + break; + + if (c == '-') continue; + if ((c >= 'a') && (c <= 'z')) continue; + if ((c >= 'A') && (c <= 'Z')) continue; + if ((c >= '0') && (c <= '9')) continue; + + return ERROR_DNS_INVALID_NAME; + } + + if ((dot - name) > 63) { + /* + * DNS labels can only be 63 chars long + */ + return ERROR_DNS_INVALID_NAME; + } + + if (!(result = TALLOC_ZERO_P(mem_ctx, struct dns_domain_label))) { + return ERROR_DNS_NO_MEMORY; + } + + if (*dot == '\0') { + /* + * No dot around, so this is the last component + */ + + if (!(result->label = talloc_strdup(result, name))) { + TALLOC_FREE(result); + return ERROR_DNS_NO_MEMORY; + } + result->len = strlen(result->label); + *presult = result; + return ERROR_DNS_SUCCESS; + } + + if (dot[1] == '.') { + /* + * Two dots in a row, reject + */ + + TALLOC_FREE(result); + return ERROR_DNS_INVALID_NAME; + } + + if (dot[1] != '\0') { + /* + * Something follows, get the rest + */ + + DNS_ERROR err = LabelList(result, dot+1, &result->next); + + if (!ERR_DNS_IS_OK(err)) { + TALLOC_FREE(result); + return err; + } + } + + result->len = (dot - name); + + if (!(result->label = talloc_strndup(result, name, result->len))) { + TALLOC_FREE(result); + return ERROR_DNS_NO_MEMORY; + } + + *presult = result; + return ERROR_DNS_SUCCESS; +} + +DNS_ERROR dns_domain_name_from_string( TALLOC_CTX *mem_ctx, + const char *pszDomainName, + struct dns_domain_name **presult ) +{ + struct dns_domain_name *result; + DNS_ERROR err; + + if (!(result = talloc(mem_ctx, struct dns_domain_name))) { + return ERROR_DNS_NO_MEMORY; + } + + err = LabelList( result, pszDomainName, &result->pLabelList ); + if (!ERR_DNS_IS_OK(err)) { + TALLOC_FREE(result); + return err; + } + + *presult = result; + return ERROR_DNS_SUCCESS; +} + +/********************************************************************* +*********************************************************************/ + +char *dns_generate_keyname( TALLOC_CTX *mem_ctx ) +{ + char *result = NULL; +#if defined(WITH_DNS_UPDATES) + + uuid_t uuid; + + /* + * uuid_unparse gives 36 bytes plus '\0' + */ + if (!(result = TALLOC_ARRAY(mem_ctx, char, 37))) { + return NULL; + } + + uuid_generate( uuid ); + uuid_unparse( uuid, result ); + +#endif + + return result; +} diff --git a/lib/addns/error.c b/lib/addns/error.c new file mode 100644 index 0000000000..361388cea3 --- /dev/null +++ b/lib/addns/error.c @@ -0,0 +1,59 @@ +/* + Linux DNS client library implementation + Copyright (C) 2010 Guenther Deschner + + ** NOTE! The following LGPL license applies to the libaddns + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#include "dns.h" +#include "dnserr.h" + +typedef struct { + const char *dns_errstr; + DNS_ERROR dns_errcode; +} dns_err_code_struct; + +static const dns_err_code_struct dns_errs[] = +{ + { "ERROR_DNS_SUCCESS", ERROR_DNS_SUCCESS }, + { "ERROR_DNS_RECORD_NOT_FOUND", ERROR_DNS_RECORD_NOT_FOUND }, + { "ERROR_DNS_BAD_RESPONSE", ERROR_DNS_BAD_RESPONSE }, + { "ERROR_DNS_INVALID_PARAMETER", ERROR_DNS_INVALID_PARAMETER }, + { "ERROR_DNS_NO_MEMORY", ERROR_DNS_NO_MEMORY }, + { "ERROR_DNS_INVALID_NAME_SERVER", ERROR_DNS_INVALID_NAME_SERVER }, + { "ERROR_DNS_CONNECTION_FAILED", ERROR_DNS_CONNECTION_FAILED }, + { "ERROR_DNS_GSS_ERROR", ERROR_DNS_GSS_ERROR }, + { "ERROR_DNS_INVALID_NAME", ERROR_DNS_INVALID_NAME }, + { "ERROR_DNS_INVALID_MESSAGE", ERROR_DNS_INVALID_MESSAGE }, + { "ERROR_DNS_SOCKET_ERROR", ERROR_DNS_SOCKET_ERROR }, + { "ERROR_DNS_UPDATE_FAILED", ERROR_DNS_UPDATE_FAILED }, + { NULL, ERROR_DNS_SUCCESS }, +}; + +const char *dns_errstr(DNS_ERROR err) +{ + int i; + + for (i=0; dns_errs[i].dns_errstr != NULL; i++) { + if (ERR_DNS_EQUAL(err, dns_errs[i].dns_errcode)) { + return dns_errs[i].dns_errstr; + } + } + + return NULL; +} diff --git a/lib/addns/wscript_build b/lib/addns/wscript_build new file mode 100644 index 0000000000..69a4716245 --- /dev/null +++ b/lib/addns/wscript_build @@ -0,0 +1,7 @@ +#!/usr/bin/env python + +bld.SAMBA_LIBRARY('addns', + source='dnsrecord.c dnsutils.c dnssock.c dnsgss.c dnsmarshall.c error.c', + public_deps='talloc krb5 k5crypto com_err gssapi gssapi_krb5 uuid', + private_library=True, + vars=locals()) diff --git a/source3/Makefile.in b/source3/Makefile.in index 50046cc2b4..7151df90f2 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -491,8 +491,8 @@ PARAM_OBJ = $(PARAM_WITHOUT_REG_OBJ) $(PARAM_REG_ADD_OBJ) KRBCLIENT_OBJ = libads/kerberos.o libads/ads_status.o -LIBADDNS_OBJ0 = libaddns/dnsrecord.o libaddns/dnsutils.o libaddns/dnssock.o \ - libaddns/dnsgss.o libaddns/dnsmarshall.o libaddns/error.o +LIBADDNS_OBJ0 = ../lib/addns/dnsrecord.o ../lib/addns/dnsutils.o ../lib/addns/dnssock.o \ + ../lib/addns/dnsgss.o ../lib/addns/dnsmarshall.o ../lib/addns/error.o LIBADDNS_OBJ = $(LIBADDNS_OBJ0) $(SOCKET_WRAPPER_OBJ) GPEXT_OBJ = ../libgpo/gpext/gpext.o @GPEXT_STATIC@ @@ -2245,7 +2245,7 @@ LIBADDNS_SHARED_TARGET_SONAME=$(LIBADDNS_SHARED_TARGET).$(LIBADDNS_SOVER) LIBADDNS_STATIC_TARGET=@LIBADDNS_STATIC_TARGET@ LIBADDNS=@LIBADDNS_STATIC@ @LIBADDNS_SHARED@ #LIBADDNS_SYMS=$(srcdir)/exports/libaddns.@SYMSEXT@ -LIBADDNS_HEADERS=$(srcdir)/libaddns/addns.h +LIBADDNS_HEADERS=$(srcdir)/../lib/addns/addns.h $(LIBADDNS_SHARED_TARGET_SONAME): $(BINARY_PREREQS) $(LIBADDNS_OBJ) $(LIBTALLOC) @echo Linking shared library $@ diff --git a/source3/configure.in b/source3/configure.in index ac43308c1c..f565fdb992 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -37,7 +37,7 @@ LIBS="${LIBS} ${TEVENT_LIBS}" SAMBA_CPPFLAGS="-Iinclude -I${srcdir-.}/include -I. -I${srcdir-.}" SAMBA_CPPFLAGS="${SAMBA_CPPFLAGS} -I${srcdir-.}/../lib/replace" SAMBA_CPPFLAGS="${SAMBA_CPPFLAGS} ${TEVENT_CFLAGS}" -SAMBA_CPPFLAGS="${SAMBA_CPPFLAGS} -I${srcdir-.}/libaddns" +SAMBA_CPPFLAGS="${SAMBA_CPPFLAGS} -I${srcdir-.}/../lib/addns" SAMBA_CPPFLAGS="${SAMBA_CPPFLAGS} -I${srcdir-.}/librpc" SAMBA_CPPFLAGS="${SAMBA_CPPFLAGS} -I${srcdir-.}/.." diff --git a/source3/libaddns/addns.h b/source3/libaddns/addns.h deleted file mode 100644 index 6ef9329df8..0000000000 --- a/source3/libaddns/addns.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - Public Interface file for Linux DNS client library implementation - - Copyright (C) 2006 Krishna Ganugapati - Copyright (C) 2006 Gerald Carter - - ** NOTE! The following LGPL license applies to the libaddns - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see . -*/ - -#ifndef _ADDNS_H -#define _ADDNS_H - - -#endif /* _ADDNS_H */ - diff --git a/source3/libaddns/dns.h b/source3/libaddns/dns.h deleted file mode 100644 index 29f1ed3e99..0000000000 --- a/source3/libaddns/dns.h +++ /dev/null @@ -1,540 +0,0 @@ -/* - Linux DNS client library implementation - - Copyright (C) 2006 Krishna Ganugapati - Copyright (C) 2006 Gerald Carter - - ** NOTE! The following LGPL license applies to the libaddns - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see . -*/ - -#ifndef _DNS_H -#define _DNS_H - -#include "../replace/replace.h" -#include "system/network.h" - -/* make sure we have included the correct config.h */ -#ifndef NO_CONFIG_H /* for some tests */ -#ifndef CONFIG_H_IS_FROM_SAMBA -#error "make sure you have removed all config.h files from standalone builds!" -#error "the included config.h isn't from samba!" -#endif -#endif /* NO_CONFIG_H */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_UUID_UUID_H -#include -#endif - -#ifdef HAVE_KRB5_H -#include -#endif - -#ifdef HAVE_INTTYPES_H -#include - -#ifndef int16 -#define int16 int16_t -#endif - -#ifndef uint16 -#define uint16 uint16_t -#endif - -#ifndef int32 -#define int32 int32_t -#endif - -#ifndef uint32 -#define uint32 uint32_t -#endif -#endif - -#ifdef HAVE_KRB5_H -#include -#endif - -#if HAVE_GSSAPI_GSSAPI_H -#include -#elif HAVE_GSSAPI_GSSAPI_GENERIC_H -#include -#elif HAVE_GSSAPI_H -#include -#endif - -#if defined(HAVE_GSSAPI_H) || defined(HAVE_GSSAPI_GSSAPI_H) || defined(HAVE_GSSAPI_GSSAPI_GENERIC_H) -#define HAVE_GSSAPI_SUPPORT 1 -#endif - -#include - -#if 0 - -Disable these now we have checked all code paths and ensured -NULL returns on zero request. JRA. - -void *_talloc_zero_zeronull(const void *ctx, size_t size, const char *name); -void *_talloc_memdup_zeronull(const void *t, const void *p, size_t size, const char *name); -void *_talloc_array_zeronull(const void *ctx, size_t el_size, unsigned count, const char *name); -void *_talloc_zero_array_zeronull(const void *ctx, size_t el_size, unsigned count, const char *name); -void *talloc_zeronull(const void *context, size_t size, const char *name); - -#define TALLOC(ctx, size) talloc_zeronull(ctx, size, __location__) -#define TALLOC_P(ctx, type) (type *)talloc_zeronull(ctx, sizeof(type), #type) -#define TALLOC_ARRAY(ctx, type, count) (type *)_talloc_array_zeronull(ctx, sizeof(type), count, #type) -#define TALLOC_MEMDUP(ctx, ptr, size) _talloc_memdup_zeronull(ctx, ptr, size, __location__) -#define TALLOC_ZERO(ctx, size) _talloc_zero_zeronull(ctx, size, __location__) -#define TALLOC_ZERO_P(ctx, type) (type *)_talloc_zero_zeronull(ctx, sizeof(type), #type) -#define TALLOC_ZERO_ARRAY(ctx, type, count) (type *)_talloc_zero_array_zeronull(ctx, sizeof(type), count, #type) -#define TALLOC_SIZE(ctx, size) talloc_zeronull(ctx, size, __location__) -#define TALLOC_ZERO_SIZE(ctx, size) _talloc_zero_zeronull(ctx, size, __location__) - -#else - -#define TALLOC(ctx, size) talloc_named_const(ctx, size, __location__) -#define TALLOC_P(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type) -#define TALLOC_ARRAY(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type) -#define TALLOC_MEMDUP(ctx, ptr, size) _talloc_memdup(ctx, ptr, size, __location__) -#define TALLOC_ZERO(ctx, size) _talloc_zero(ctx, size, __location__) -#define TALLOC_ZERO_P(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type) -#define TALLOC_ZERO_ARRAY(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type) -#define TALLOC_SIZE(ctx, size) talloc_named_const(ctx, size, __location__) -#define TALLOC_ZERO_SIZE(ctx, size) _talloc_zero(ctx, size, __location__) - -#endif - -#define TALLOC_REALLOC(ctx, ptr, count) _talloc_realloc(ctx, ptr, count, __location__) -#define TALLOC_REALLOC_ARRAY(ctx, ptr, type, count) (type *)_talloc_realloc_array(ctx, ptr, sizeof(type), count, #type) -#define talloc_destroy(ctx) talloc_free(ctx) -#ifndef TALLOC_FREE -#define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0) -#endif - -/******************************************************************* - Type definitions for int16, int32, uint16 and uint32. Needed - for Samba coding style -*******************************************************************/ - -#ifndef uint8 -# define uint8 unsigned char -#endif - -#if !defined(int16) && !defined(HAVE_INT16_FROM_RPC_RPC_H) -# if (SIZEOF_SHORT == 4) -# define int16 __ERROR___CANNOT_DETERMINE_TYPE_FOR_INT16; -# else /* SIZEOF_SHORT != 4 */ -# define int16 short -# endif /* SIZEOF_SHORT != 4 */ - /* needed to work around compile issue on HP-UX 11.x */ -# define _INT16 1 -#endif - -/* - * Note we duplicate the size tests in the unsigned - * case as int16 may be a typedef from rpc/rpc.h - */ - -#if !defined(uint16) && !defined(HAVE_UINT16_FROM_RPC_RPC_H) -# if (SIZEOF_SHORT == 4) -# define uint16 __ERROR___CANNOT_DETERMINE_TYPE_FOR_INT16; -# else /* SIZEOF_SHORT != 4 */ -# define uint16 unsigned short -# endif /* SIZEOF_SHORT != 4 */ -#endif - -#if !defined(int32) && !defined(HAVE_INT32_FROM_RPC_RPC_H) -# if (SIZEOF_INT == 4) -# define int32 int -# elif (SIZEOF_LONG == 4) -# define int32 long -# elif (SIZEOF_SHORT == 4) -# define int32 short -# else - /* uggh - no 32 bit type?? probably a CRAY. just hope this works ... */ -# define int32 int -# endif -# ifndef _INT32 - /* needed to work around compile issue on HP-UX 11.x */ -# define _INT32 1 -# endif -#endif - -/* - * Note we duplicate the size tests in the unsigned - * case as int32 may be a typedef from rpc/rpc.h - */ - -#if !defined(uint32) && !defined(HAVE_UINT32_FROM_RPC_RPC_H) -# if (SIZEOF_INT == 4) -# define uint32 unsigned int -# elif (SIZEOF_LONG == 4) -# define uint32 unsigned long -# elif (SIZEOF_SHORT == 4) -# define uint32 unsigned short -# else - /* uggh - no 32 bit type?? probably a CRAY. just hope this works ... */ -# define uint32 unsigned -# endif -#endif - -/* - * check for 8 byte long long - */ - -#if !defined(uint64) -# if (SIZEOF_LONG == 8) -# define uint64 unsigned long -# elif (SIZEOF_LONG_LONG == 8) -# define uint64 unsigned long long -# endif /* don't lie. If we don't have it, then don't use it */ -#endif - -/* needed on Sun boxes */ -#ifndef INADDR_NONE -#define INADDR_NONE 0xFFFFFFFF -#endif - -#include "dnserr.h" - - -#define DNS_TCP 1 -#define DNS_UDP 2 - -#define DNS_OPCODE_UPDATE 1 - -/* DNS Class Types */ - -#define DNS_CLASS_IN 1 -#define DNS_CLASS_ANY 255 -#define DNS_CLASS_NONE 254 - -/* DNS RR Types */ - -#define DNS_RR_A 1 - -#define DNS_TCP_PORT 53 -#define DNS_UDP_PORT 53 - -#define QTYPE_A 1 -#define QTYPE_NS 2 -#define QTYPE_MD 3 -#define QTYPE_CNAME 5 -#define QTYPE_SOA 6 -#define QTYPE_ANY 255 -#define QTYPE_TKEY 249 -#define QTYPE_TSIG 250 - -/* -MF 4 a mail forwarder (Obsolete - use MX) -CNAME 5 the canonical name for an alias -SOA 6 marks the start of a zone of authority -MB 7 a mailbox domain name (EXPERIMENTAL) -MG 8 a mail group member (EXPERIMENTAL) -MR 9 a mail rename domain name (EXPERIMENTAL) -NULL 10 a null RR (EXPERIMENTAL) -WKS 11 a well known service description -PTR 12 a domain name pointer -HINFO 13 host information -MINFO 14 mailbox or mail list information -MX 15 mail exchange -TXT 16 text strings -*/ - -#define QR_QUERY 0x0000 -#define QR_RESPONSE 0x0001 - -#define OPCODE_QUERY 0x00 -#define OPCODE_IQUERY 0x01 -#define OPCODE_STATUS 0x02 - -#define AA 1 - -#define RECURSION_DESIRED 0x01 - -#define RCODE_NOERROR 0 -#define RCODE_FORMATERROR 1 -#define RCODE_SERVER_FAILURE 2 -#define RCODE_NAME_ERROR 3 -#define RCODE_NOTIMPLEMENTED 4 -#define RCODE_REFUSED 5 - -#define SENDBUFFER_SIZE 65536 -#define RECVBUFFER_SIZE 65536 - -/* - * TKEY Modes from rfc2930 - */ - -#define DNS_TKEY_MODE_SERVER 1 -#define DNS_TKEY_MODE_DH 2 -#define DNS_TKEY_MODE_GSSAPI 3 -#define DNS_TKEY_MODE_RESOLVER 4 -#define DNS_TKEY_MODE_DELETE 5 - - -#define DNS_ONE_DAY_IN_SECS 86400 -#define DNS_TEN_HOURS_IN_SECS 36000 - -#define SOCKET_ERROR -1 -#define INVALID_SOCKET -1 - -#define DNS_NO_ERROR 0 -#define DNS_FORMAT_ERROR 1 -#define DNS_SERVER_FAILURE 2 -#define DNS_NAME_ERROR 3 -#define DNS_NOT_IMPLEMENTED 4 -#define DNS_REFUSED 5 - -typedef long HANDLE; - -enum dns_ServerType { DNS_SRV_ANY, DNS_SRV_WIN2000, DNS_SRV_WIN2003 }; - -struct dns_domain_label { - struct dns_domain_label *next; - char *label; - size_t len; -}; - -struct dns_domain_name { - struct dns_domain_label *pLabelList; -}; - -struct dns_question { - struct dns_domain_name *name; - uint16 q_type; - uint16 q_class; -}; - -/* - * Before changing the definition of dns_zone, look - * dns_marshall_update_request(), we rely on this being the same as - * dns_question right now. - */ - -struct dns_zone { - struct dns_domain_name *name; - uint16 z_type; - uint16 z_class; -}; - -struct dns_rrec { - struct dns_domain_name *name; - uint16 type; - uint16 r_class; - uint32 ttl; - uint16 data_length; - uint8 *data; -}; - -struct dns_tkey_record { - struct dns_domain_name *algorithm; - time_t inception; - time_t expiration; - uint16 mode; - uint16 error; - uint16 key_length; - uint8 *key; -}; - -struct dns_request { - uint16 id; - uint16 flags; - uint16 num_questions; - uint16 num_answers; - uint16 num_auths; - uint16 num_additionals; - struct dns_question **questions; - struct dns_rrec **answers; - struct dns_rrec **auths; - struct dns_rrec **additionals; -}; - -/* - * Before changing the definition of dns_update_request, look - * dns_marshall_update_request(), we rely on this being the same as - * dns_request right now. - */ - -struct dns_update_request { - uint16 id; - uint16 flags; - uint16 num_zones; - uint16 num_preqs; - uint16 num_updates; - uint16 num_additionals; - struct dns_zone **zones; - struct dns_rrec **preqs; - struct dns_rrec **updates; - struct dns_rrec **additionals; -}; - -struct dns_connection { - int32 hType; - int s; - struct sockaddr RecvAddr; -}; - -struct dns_buffer { - uint8 *data; - size_t size; - size_t offset; - DNS_ERROR error; -}; - -/* from dnsutils.c */ - -DNS_ERROR dns_domain_name_from_string( TALLOC_CTX *mem_ctx, - const char *pszDomainName, - struct dns_domain_name **presult ); -char *dns_generate_keyname( TALLOC_CTX *mem_ctx ); - -/* from dnsrecord.c */ - -DNS_ERROR dns_create_query( TALLOC_CTX *mem_ctx, const char *name, - uint16 q_type, uint16 q_class, - struct dns_request **preq ); -DNS_ERROR dns_create_update( TALLOC_CTX *mem_ctx, const char *name, - struct dns_update_request **preq ); -DNS_ERROR dns_create_probe(TALLOC_CTX *mem_ctx, const char *zone, - const char *host, int num_ips, - const struct sockaddr_storage *sslist, - struct dns_update_request **preq); -DNS_ERROR dns_create_rrec(TALLOC_CTX *mem_ctx, const char *name, - uint16 type, uint16 r_class, uint32 ttl, - uint16 data_length, uint8 *data, - struct dns_rrec **prec); -DNS_ERROR dns_add_rrec(TALLOC_CTX *mem_ctx, struct dns_rrec *rec, - uint16 *num_records, struct dns_rrec ***records); -DNS_ERROR dns_create_tkey_record(TALLOC_CTX *mem_ctx, const char *keyname, - const char *algorithm_name, time_t inception, - time_t expiration, uint16 mode, uint16 error, - uint16 key_length, const uint8 *key, - struct dns_rrec **prec); -DNS_ERROR dns_create_name_in_use_record(TALLOC_CTX *mem_ctx, - const char *name, - const struct sockaddr_storage *ip, - struct dns_rrec **prec); -DNS_ERROR dns_create_delete_record(TALLOC_CTX *mem_ctx, const char *name, - uint16 type, uint16 r_class, - struct dns_rrec **prec); -DNS_ERROR dns_create_name_not_in_use_record(TALLOC_CTX *mem_ctx, - const char *name, uint32 type, - struct dns_rrec **prec); -DNS_ERROR dns_create_a_record(TALLOC_CTX *mem_ctx, const char *host, - uint32 ttl, const struct sockaddr_storage *pss, - struct dns_rrec **prec); -DNS_ERROR dns_unmarshall_tkey_record(TALLOC_CTX *mem_ctx, struct dns_rrec *rec, - struct dns_tkey_record **ptkey); -DNS_ERROR dns_create_tsig_record(TALLOC_CTX *mem_ctx, const char *keyname, - const char *algorithm_name, - time_t time_signed, uint16 fudge, - uint16 mac_length, const uint8 *mac, - uint16 original_id, uint16 error, - struct dns_rrec **prec); -DNS_ERROR dns_add_rrec(TALLOC_CTX *mem_ctx, struct dns_rrec *rec, - uint16 *num_records, struct dns_rrec ***records); -DNS_ERROR dns_create_update_request(TALLOC_CTX *mem_ctx, - const char *domainname, - const char *hostname, - const struct sockaddr_storage *ip_addr, - size_t num_adds, - struct dns_update_request **preq); - -/* from dnssock.c */ - -DNS_ERROR dns_open_connection( const char *nameserver, int32 dwType, - TALLOC_CTX *mem_ctx, - struct dns_connection **conn ); -DNS_ERROR dns_send(struct dns_connection *conn, const struct dns_buffer *buf); -DNS_ERROR dns_receive(TALLOC_CTX *mem_ctx, struct dns_connection *conn, - struct dns_buffer **presult); -DNS_ERROR dns_transaction(TALLOC_CTX *mem_ctx, struct dns_connection *conn, - const struct dns_request *req, - struct dns_request **resp); -DNS_ERROR dns_update_transaction(TALLOC_CTX *mem_ctx, - struct dns_connection *conn, - struct dns_update_request *up_req, - struct dns_update_request **up_resp); - -/* from dnsmarshall.c */ - -struct dns_buffer *dns_create_buffer(TALLOC_CTX *mem_ctx); -void dns_marshall_buffer(struct dns_buffer *buf, const uint8 *data, - size_t len); -void dns_marshall_uint16(struct dns_buffer *buf, uint16 val); -void dns_marshall_uint32(struct dns_buffer *buf, uint32 val); -void dns_unmarshall_buffer(struct dns_buffer *buf, uint8 *data, - size_t len); -void dns_unmarshall_uint16(struct dns_buffer *buf, uint16 *val); -void dns_unmarshall_uint32(struct dns_buffer *buf, uint32 *val); -void dns_unmarshall_domain_name(TALLOC_CTX *mem_ctx, - struct dns_buffer *buf, - struct dns_domain_name **pname); -void dns_marshall_domain_name(struct dns_buffer *buf, - const struct dns_domain_name *name); -void dns_unmarshall_domain_name(TALLOC_CTX *mem_ctx, - struct dns_buffer *buf, - struct dns_domain_name **pname); -DNS_ERROR dns_marshall_request(TALLOC_CTX *mem_ctx, - const struct dns_request *req, - struct dns_buffer **pbuf); -DNS_ERROR dns_unmarshall_request(TALLOC_CTX *mem_ctx, - struct dns_buffer *buf, - struct dns_request **preq); -DNS_ERROR dns_marshall_update_request(TALLOC_CTX *mem_ctx, - struct dns_update_request *update, - struct dns_buffer **pbuf); -DNS_ERROR dns_unmarshall_update_request(TALLOC_CTX *mem_ctx, - struct dns_buffer *buf, - struct dns_update_request **pupreq); -struct dns_request *dns_update2request(struct dns_update_request *update); -struct dns_update_request *dns_request2update(struct dns_request *request); -uint16 dns_response_code(uint16 flags); -const char *dns_errstr(DNS_ERROR err); - -/* from dnsgss.c */ - -#ifdef HAVE_GSSAPI_SUPPORT - -void display_status( const char *msg, OM_uint32 maj_stat, OM_uint32 min_stat ); -DNS_ERROR dns_negotiate_sec_ctx( const char *target_realm, - const char *servername, - const char *keyname, - gss_ctx_id_t *gss_ctx, - enum dns_ServerType srv_type ); -DNS_ERROR dns_sign_update(struct dns_update_request *req, - gss_ctx_id_t gss_ctx, - const char *keyname, - const char *algorithmname, - time_t time_signed, uint16 fudge); - -#endif /* HAVE_GSSAPI_SUPPORT */ - -#endif /* _DNS_H */ diff --git a/source3/libaddns/dnserr.h b/source3/libaddns/dnserr.h deleted file mode 100644 index 9e049ac3a9..0000000000 --- a/source3/libaddns/dnserr.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - Error codes for Linux DNS client library implementation - - Copyright (C) 2006 Krishna Ganugapati - Copyright (C) 2006 Gerald Carter - - ** NOTE! The following LGPL license applies to the libaddns - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see . -*/ - -#ifndef _DNSERR_H -#define _DNSERR_H - - -/* The Splint code analysis tool (http://www.splint.org.) doesn't - like immediate structures. */ - -#ifdef _SPLINT_ -#undef HAVE_IMMEDIATE_STRUCTURES -#endif - -/* Setup the DNS_ERROR typedef. Technique takes from nt_status.h */ - -#if defined(HAVE_IMMEDIATE_STRUCTURES) -typedef struct {uint32 v;} DNS_ERROR; -#define ERROR_DNS(x) ((DNS_ERROR) { x }) -#define ERROR_DNS_V(x) ((x).v) -#else -typedef uint32 DNS_ERROR; -#define ERROR_DNS(x) (x) -#define ERROR_DNS_V(x) (x) -#endif - -#define ERR_DNS_IS_OK(x) (ERROR_DNS_V(x) == 0) -#define ERR_DNS_EQUAL(x,y) (ERROR_DNS_V(x) == ERROR_DNS_V(y)) - -/************************************************* - * Define the error codes here - *************************************************/ - -#define ERROR_DNS_SUCCESS ERROR_DNS(0) -#define ERROR_DNS_RECORD_NOT_FOUND ERROR_DNS(1) -#define ERROR_DNS_BAD_RESPONSE ERROR_DNS(2) -#define ERROR_DNS_INVALID_PARAMETER ERROR_DNS(3) -#define ERROR_DNS_NO_MEMORY ERROR_DNS(4) -#define ERROR_DNS_INVALID_NAME_SERVER ERROR_DNS(5) -#define ERROR_DNS_CONNECTION_FAILED ERROR_DNS(6) -#define ERROR_DNS_GSS_ERROR ERROR_DNS(7) -#define ERROR_DNS_INVALID_NAME ERROR_DNS(8) -#define ERROR_DNS_INVALID_MESSAGE ERROR_DNS(9) -#define ERROR_DNS_SOCKET_ERROR ERROR_DNS(10) -#define ERROR_DNS_UPDATE_FAILED ERROR_DNS(11) - -/* - * About to be removed, transitional error - */ -#define ERROR_DNS_UNSUCCESSFUL ERROR_DNS(999) - - -#define ERROR_BAD_RESPONSE 1 -#define ERROR_RECORD_NOT_FOUND 2 -#define ERROR_OUTOFMEMORY 8 -#if !defined(ERROR_INVALID_PARAMETER) -#define ERROR_INVALID_PARAMETER 87 -#endif - -/* - * About to be removed, transitional error - */ -#define ERROR_UNSUCCESSFUL 999 - -#endif /* _DNSERR_H */ - diff --git a/source3/libaddns/dnsgss.c b/source3/libaddns/dnsgss.c deleted file mode 100644 index c9037417da..0000000000 --- a/source3/libaddns/dnsgss.c +++ /dev/null @@ -1,334 +0,0 @@ -/* - Public Interface file for Linux DNS client library implementation - - Copyright (C) 2006 Krishna Ganugapati - Copyright (C) 2006 Gerald Carter - - ** NOTE! The following LGPL license applies to the libaddns - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see . -*/ - -#include "dns.h" -#include - - -#ifdef HAVE_GSSAPI_SUPPORT - -/********************************************************************* -*********************************************************************/ - -#ifndef HAVE_STRUPR -static int strupr( char *szDomainName ) -{ - if ( !szDomainName ) { - return ( 0 ); - } - while ( *szDomainName != '\0' ) { - *szDomainName = toupper( *szDomainName ); - szDomainName++; - } - return ( 0 ); -} -#endif - -#if 0 -/********************************************************************* -*********************************************************************/ - -static void display_status_1( const char *m, OM_uint32 code, int type ) -{ - OM_uint32 maj_stat, min_stat; - gss_buffer_desc msg; - OM_uint32 msg_ctx; - - msg_ctx = 0; - while ( 1 ) { - maj_stat = gss_display_status( &min_stat, code, - type, GSS_C_NULL_OID, - &msg_ctx, &msg ); - fprintf( stdout, "GSS-API error %s: %s\n", m, - ( char * ) msg.value ); - ( void ) gss_release_buffer( &min_stat, &msg ); - - if ( !msg_ctx ) - break; - } -} - -/********************************************************************* -*********************************************************************/ - -void display_status( const char *msg, OM_uint32 maj_stat, OM_uint32 min_stat ) -{ - display_status_1( msg, maj_stat, GSS_C_GSS_CODE ); - display_status_1( msg, min_stat, GSS_C_MECH_CODE ); -} -#endif - -static DNS_ERROR dns_negotiate_gss_ctx_int( TALLOC_CTX *mem_ctx, - struct dns_connection *conn, - const char *keyname, - const gss_name_t target_name, - gss_ctx_id_t *ctx, - enum dns_ServerType srv_type ) -{ - struct gss_buffer_desc_struct input_desc, *input_ptr, output_desc; - OM_uint32 major, minor; - OM_uint32 ret_flags; - DNS_ERROR err; - - gss_OID_desc krb5_oid_desc = - { 9, (char *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" }; - - *ctx = GSS_C_NO_CONTEXT; - input_ptr = NULL; - - do { - major = gss_init_sec_context( - &minor, NULL, ctx, target_name, &krb5_oid_desc, - GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | - GSS_C_CONF_FLAG | - GSS_C_INTEG_FLAG, - 0, NULL, input_ptr, NULL, &output_desc, - &ret_flags, NULL ); - - if (input_ptr != NULL) { - TALLOC_FREE(input_desc.value); - } - - if (output_desc.length != 0) { - - struct dns_request *req; - struct dns_rrec *rec; - struct dns_buffer *buf; - - time_t t = time(NULL); - - err = dns_create_query(mem_ctx, keyname, QTYPE_TKEY, - DNS_CLASS_IN, &req); - if (!ERR_DNS_IS_OK(err)) goto error; - - err = dns_create_tkey_record( - req, keyname, "gss.microsoft.com", t, - t + 86400, DNS_TKEY_MODE_GSSAPI, 0, - output_desc.length, (uint8 *)output_desc.value, - &rec ); - if (!ERR_DNS_IS_OK(err)) goto error; - - /* Windows 2000 DNS is broken and requires the - TKEY payload in the Answer section instead - of the Additional seciton like Windows 2003 */ - - if ( srv_type == DNS_SRV_WIN2000 ) { - err = dns_add_rrec(req, rec, &req->num_answers, - &req->answers); - } else { - err = dns_add_rrec(req, rec, &req->num_additionals, - &req->additionals); - } - - if (!ERR_DNS_IS_OK(err)) goto error; - - err = dns_marshall_request(req, req, &buf); - if (!ERR_DNS_IS_OK(err)) goto error; - - err = dns_send(conn, buf); - if (!ERR_DNS_IS_OK(err)) goto error; - - TALLOC_FREE(req); - } - - gss_release_buffer(&minor, &output_desc); - - if ((major != GSS_S_COMPLETE) && - (major != GSS_S_CONTINUE_NEEDED)) { - return ERROR_DNS_GSS_ERROR; - } - - if (major == GSS_S_CONTINUE_NEEDED) { - - struct dns_request *resp; - struct dns_buffer *buf; - struct dns_tkey_record *tkey; - - err = dns_receive(mem_ctx, conn, &buf); - if (!ERR_DNS_IS_OK(err)) goto error; - - err = dns_unmarshall_request(buf, buf, &resp); - if (!ERR_DNS_IS_OK(err)) goto error; - - /* - * TODO: Compare id and keyname - */ - - if ((resp->num_additionals != 1) || - (resp->num_answers == 0) || - (resp->answers[0]->type != QTYPE_TKEY)) { - err = ERROR_DNS_INVALID_MESSAGE; - goto error; - } - - err = dns_unmarshall_tkey_record( - mem_ctx, resp->answers[0], &tkey); - if (!ERR_DNS_IS_OK(err)) goto error; - - input_desc.length = tkey->key_length; - input_desc.value = talloc_move(mem_ctx, &tkey->key); - - input_ptr = &input_desc; - - TALLOC_FREE(buf); - } - - } while ( major == GSS_S_CONTINUE_NEEDED ); - - /* If we arrive here, we have a valid security context */ - - err = ERROR_DNS_SUCCESS; - - error: - - return err; -} - -DNS_ERROR dns_negotiate_sec_ctx( const char *target_realm, - const char *servername, - const char *keyname, - gss_ctx_id_t *gss_ctx, - enum dns_ServerType srv_type ) -{ - OM_uint32 major, minor; - - char *upcaserealm, *targetname; - DNS_ERROR err; - - gss_buffer_desc input_name; - struct dns_connection *conn; - - gss_name_t targ_name; - - gss_OID_desc nt_host_oid_desc = - {10, (char *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01"}; - - TALLOC_CTX *mem_ctx; - - if (!(mem_ctx = talloc_init("dns_negotiate_sec_ctx"))) { - return ERROR_DNS_NO_MEMORY; - } - - err = dns_open_connection( servername, DNS_TCP, mem_ctx, &conn ); - if (!ERR_DNS_IS_OK(err)) goto error; - - if (!(upcaserealm = talloc_strdup(mem_ctx, target_realm))) { - err = ERROR_DNS_NO_MEMORY; - goto error; - } - - strupr(upcaserealm); - - if (!(targetname = talloc_asprintf(mem_ctx, "dns/%s@%s", - servername, upcaserealm))) { - err = ERROR_DNS_NO_MEMORY; - goto error; - } - - input_name.value = targetname; - input_name.length = strlen(targetname); - - major = gss_import_name( &minor, &input_name, - &nt_host_oid_desc, &targ_name ); - - if (major) { - err = ERROR_DNS_GSS_ERROR; - goto error; - } - - err = dns_negotiate_gss_ctx_int(mem_ctx, conn, keyname, - targ_name, gss_ctx, srv_type ); - - gss_release_name( &minor, &targ_name ); - - error: - TALLOC_FREE(mem_ctx); - - return err; -} - -DNS_ERROR dns_sign_update(struct dns_update_request *req, - gss_ctx_id_t gss_ctx, - const char *keyname, - const char *algorithmname, - time_t time_signed, uint16 fudge) -{ - struct dns_buffer *buf; - DNS_ERROR err; - struct dns_domain_name *key, *algorithm; - struct gss_buffer_desc_struct msg, mic; - OM_uint32 major, minor; - struct dns_rrec *rec; - - err = dns_marshall_update_request(req, req, &buf); - if (!ERR_DNS_IS_OK(err)) return err; - - err = dns_domain_name_from_string(buf, keyname, &key); - if (!ERR_DNS_IS_OK(err)) goto error; - - err = dns_domain_name_from_string(buf, algorithmname, &algorithm); - if (!ERR_DNS_IS_OK(err)) goto error; - - dns_marshall_domain_name(buf, key); - dns_marshall_uint16(buf, DNS_CLASS_ANY); - dns_marshall_uint32(buf, 0); /* TTL */ - dns_marshall_domain_name(buf, algorithm); - dns_marshall_uint16(buf, 0); /* Time prefix for 48-bit time_t */ - dns_marshall_uint32(buf, time_signed); - dns_marshall_uint16(buf, fudge); - dns_marshall_uint16(buf, 0); /* error */ - dns_marshall_uint16(buf, 0); /* other len */ - - err = buf->error; - if (!ERR_DNS_IS_OK(buf->error)) goto error; - - msg.value = (void *)buf->data; - msg.length = buf->offset; - - major = gss_get_mic(&minor, gss_ctx, 0, &msg, &mic); - if (major != 0) { - err = ERROR_DNS_GSS_ERROR; - goto error; - } - - if (mic.length > 0xffff) { - gss_release_buffer(&minor, &mic); - err = ERROR_DNS_GSS_ERROR; - goto error; - } - - err = dns_create_tsig_record(buf, keyname, algorithmname, time_signed, - fudge, mic.length, (uint8 *)mic.value, - req->id, 0, &rec); - gss_release_buffer(&minor, &mic); - if (!ERR_DNS_IS_OK(err)) goto error; - - err = dns_add_rrec(req, rec, &req->num_additionals, &req->additionals); - - error: - TALLOC_FREE(buf); - return err; -} - -#endif /* HAVE_GSSAPI_SUPPORT */ diff --git a/source3/libaddns/dnsmarshall.c b/source3/libaddns/dnsmarshall.c deleted file mode 100644 index 5530290c57..0000000000 --- a/source3/libaddns/dnsmarshall.c +++ /dev/null @@ -1,530 +0,0 @@ -/* - Linux DNS client library implementation - Copyright (C) 2006 Gerald Carter - - ** NOTE! The following LGPL license applies to the libaddns - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see . -*/ - -#include "dns.h" -#include "assert.h" - -struct dns_buffer *dns_create_buffer(TALLOC_CTX *mem_ctx) -{ - struct dns_buffer *result; - - if (!(result = talloc(mem_ctx, struct dns_buffer))) { - return NULL; - } - - result->offset = 0; - result->error = ERROR_DNS_SUCCESS; - - /* - * Small inital size to excercise the realloc code - */ - result->size = 2; - - if (!(result->data = TALLOC_ARRAY(result, uint8, result->size))) { - TALLOC_FREE(result); - return NULL; - } - - return result; -} - -void dns_marshall_buffer(struct dns_buffer *buf, const uint8 *data, - size_t len) -{ - if (!ERR_DNS_IS_OK(buf->error)) return; - - if (buf->offset + len < buf->offset) { - /* - * Wraparound! - */ - buf->error = ERROR_DNS_INVALID_PARAMETER; - return; - } - - if ((buf->offset + len) > 0xffff) { - /* - * Only 64k possible - */ - buf->error = ERROR_DNS_INVALID_PARAMETER; - return; - } - - if (buf->offset + len > buf->size) { - size_t new_size = buf->offset + len; - uint8 *new_data; - - /* - * Don't do too many reallocs, round up to some multiple - */ - - new_size += (64 - (new_size % 64)); - - if (!(new_data = TALLOC_REALLOC_ARRAY(buf, buf->data, uint8, - new_size))) { - buf->error = ERROR_DNS_NO_MEMORY; - return; - } - - buf->size = new_size; - buf->data = new_data; - } - - memcpy(buf->data + buf->offset, data, len); - buf->offset += len; - return; -} - -void dns_marshall_uint16(struct dns_buffer *buf, uint16 val) -{ - uint16 n_val = htons(val); - dns_marshall_buffer(buf, (uint8 *)&n_val, sizeof(n_val)); -} - -void dns_marshall_uint32(struct dns_buffer *buf, uint32 val) -{ - uint32 n_val = htonl(val); - dns_marshall_buffer(buf, (uint8 *)&n_val, sizeof(n_val)); -} - -void dns_unmarshall_buffer(struct dns_buffer *buf, uint8 *data, - size_t len) -{ - if (!(ERR_DNS_IS_OK(buf->error))) return; - - if ((len > buf->size) || (buf->offset + len > buf->size)) { - buf->error = ERROR_DNS_INVALID_MESSAGE; - return; - } - - memcpy((void *)data, (const void *)(buf->data + buf->offset), len); - buf->offset += len; - - return; -} - -void dns_unmarshall_uint16(struct dns_buffer *buf, uint16 *val) -{ - uint16 n_val; - - dns_unmarshall_buffer(buf, (uint8 *)&n_val, sizeof(n_val)); - if (!(ERR_DNS_IS_OK(buf->error))) return; - - *val = ntohs(n_val); -} - -void dns_unmarshall_uint32(struct dns_buffer *buf, uint32 *val) -{ - uint32 n_val; - - dns_unmarshall_buffer(buf, (uint8 *)&n_val, sizeof(n_val)); - if (!(ERR_DNS_IS_OK(buf->error))) return; - - *val = ntohl(n_val); -} - -void dns_marshall_domain_name(struct dns_buffer *buf, - const struct dns_domain_name *name) -{ - struct dns_domain_label *label; - char end_char = '\0'; - - /* - * TODO: Implement DNS compression - */ - - for (label = name->pLabelList; label != NULL; label = label->next) { - uint8 len = label->len; - - dns_marshall_buffer(buf, (uint8 *)&len, sizeof(len)); - if (!ERR_DNS_IS_OK(buf->error)) return; - - dns_marshall_buffer(buf, (uint8 *)label->label, len); - if (!ERR_DNS_IS_OK(buf->error)) return; - } - - dns_marshall_buffer(buf, (uint8 *)&end_char, 1); -} - -static void dns_unmarshall_label(TALLOC_CTX *mem_ctx, - int level, - struct dns_buffer *buf, - struct dns_domain_label **plabel) -{ - struct dns_domain_label *label; - uint8 len; - - if (!ERR_DNS_IS_OK(buf->error)) return; - - if (level > 128) { - /* - * Protect against recursion - */ - buf->error = ERROR_DNS_INVALID_MESSAGE; - return; - } - - dns_unmarshall_buffer(buf, &len, sizeof(len)); - if (!ERR_DNS_IS_OK(buf->error)) return; - - if (len == 0) { - *plabel = NULL; - return; - } - - if ((len & 0xc0) == 0xc0) { - /* - * We've got a compressed name. Build up a new "fake" buffer - * and using the calculated offset. - */ - struct dns_buffer new_buf; - uint8 low; - - dns_unmarshall_buffer(buf, &low, sizeof(low)); - if (!ERR_DNS_IS_OK(buf->error)) return; - - new_buf = *buf; - new_buf.offset = len & 0x3f; - new_buf.offset <<= 8; - new_buf.offset |= low; - - dns_unmarshall_label(mem_ctx, level+1, &new_buf, plabel); - buf->error = new_buf.error; - return; - } - - if ((len & 0xc0) != 0) { - buf->error = ERROR_DNS_INVALID_NAME; - return; - } - - if (!(label = talloc(mem_ctx, struct dns_domain_label))) { - buf->error = ERROR_DNS_NO_MEMORY; - return; - } - - label->len = len; - - if (!(label->label = TALLOC_ARRAY(label, char, len+1))) { - buf->error = ERROR_DNS_NO_MEMORY; - goto error; - } - - dns_unmarshall_buffer(buf, (uint8 *)label->label, len); - if (!ERR_DNS_IS_OK(buf->error)) goto error; - - dns_unmarshall_label(label, level+1, buf, &label->next); - if (!ERR_DNS_IS_OK(buf->error)) goto error; - - *plabel = label; - return; - - error: - TALLOC_FREE(label); - return; -} - -void dns_unmarshall_domain_name(TALLOC_CTX *mem_ctx, - struct dns_buffer *buf, - struct dns_domain_name **pname) -{ - struct dns_domain_name *name; - - if (!ERR_DNS_IS_OK(buf->error)) return; - - if (!(name = talloc(mem_ctx, struct dns_domain_name))) { - buf->error = ERROR_DNS_NO_MEMORY; - return; - } - - dns_unmarshall_label(name, 0, buf, &name->pLabelList); - - if (!ERR_DNS_IS_OK(buf->error)) { - return; - } - - *pname = name; - return; -} - -static void dns_marshall_question(struct dns_buffer *buf, - const struct dns_question *q) -{ - dns_marshall_domain_name(buf, q->name); - dns_marshall_uint16(buf, q->q_type); - dns_marshall_uint16(buf, q->q_class); -} - -static void dns_unmarshall_question(TALLOC_CTX *mem_ctx, - struct dns_buffer *buf, - struct dns_question **pq) -{ - struct dns_question *q; - - if (!(ERR_DNS_IS_OK(buf->error))) return; - - if (!(q = talloc(mem_ctx, struct dns_question))) { - buf->error = ERROR_DNS_NO_MEMORY; - return; - } - - dns_unmarshall_domain_name(q, buf, &q->name); - dns_unmarshall_uint16(buf, &q->q_type); - dns_unmarshall_uint16(buf, &q->q_class); - - if (!(ERR_DNS_IS_OK(buf->error))) return; - - *pq = q; -} - -static void dns_marshall_rr(struct dns_buffer *buf, - const struct dns_rrec *r) -{ - dns_marshall_domain_name(buf, r->name); - dns_marshall_uint16(buf, r->type); - dns_marshall_uint16(buf, r->r_class); - dns_marshall_uint32(buf, r->ttl); - dns_marshall_uint16(buf, r->data_length); - dns_marshall_buffer(buf, r->data, r->data_length); -} - -static void dns_unmarshall_rr(TALLOC_CTX *mem_ctx, - struct dns_buffer *buf, - struct dns_rrec **pr) -{ - struct dns_rrec *r; - - if (!(ERR_DNS_IS_OK(buf->error))) return; - - if (!(r = talloc(mem_ctx, struct dns_rrec))) { - buf->error = ERROR_DNS_NO_MEMORY; - return; - } - - dns_unmarshall_domain_name(r, buf, &r->name); - dns_unmarshall_uint16(buf, &r->type); - dns_unmarshall_uint16(buf, &r->r_class); - dns_unmarshall_uint32(buf, &r->ttl); - dns_unmarshall_uint16(buf, &r->data_length); - r->data = NULL; - - if (!(ERR_DNS_IS_OK(buf->error))) return; - - if (r->data_length != 0) { - if (!(r->data = TALLOC_ARRAY(r, uint8, r->data_length))) { - buf->error = ERROR_DNS_NO_MEMORY; - return; - } - dns_unmarshall_buffer(buf, r->data, r->data_length); - } - - if (!(ERR_DNS_IS_OK(buf->error))) return; - - *pr = r; -} - -DNS_ERROR dns_marshall_request(TALLOC_CTX *mem_ctx, - const struct dns_request *req, - struct dns_buffer **pbuf) -{ - struct dns_buffer *buf; - uint16 i; - - if (!(buf = dns_create_buffer(mem_ctx))) { - return ERROR_DNS_NO_MEMORY; - } - - dns_marshall_uint16(buf, req->id); - dns_marshall_uint16(buf, req->flags); - dns_marshall_uint16(buf, req->num_questions); - dns_marshall_uint16(buf, req->num_answers); - dns_marshall_uint16(buf, req->num_auths); - dns_marshall_uint16(buf, req->num_additionals); - - for (i=0; inum_questions; i++) { - dns_marshall_question(buf, req->questions[i]); - } - for (i=0; inum_answers; i++) { - dns_marshall_rr(buf, req->answers[i]); - } - for (i=0; inum_auths; i++) { - dns_marshall_rr(buf, req->auths[i]); - } - for (i=0; inum_additionals; i++) { - dns_marshall_rr(buf, req->additionals[i]); - } - - if (!ERR_DNS_IS_OK(buf->error)) { - DNS_ERROR err = buf->error; - TALLOC_FREE(buf); - return err; - } - - *pbuf = buf; - return ERROR_DNS_SUCCESS; -} - -DNS_ERROR dns_unmarshall_request(TALLOC_CTX *mem_ctx, - struct dns_buffer *buf, - struct dns_request **preq) -{ - struct dns_request *req; - uint16 i; - DNS_ERROR err; - - if (!(req = TALLOC_ZERO_P(mem_ctx, struct dns_request))) { - return ERROR_DNS_NO_MEMORY; - } - - dns_unmarshall_uint16(buf, &req->id); - dns_unmarshall_uint16(buf, &req->flags); - dns_unmarshall_uint16(buf, &req->num_questions); - dns_unmarshall_uint16(buf, &req->num_answers); - dns_unmarshall_uint16(buf, &req->num_auths); - dns_unmarshall_uint16(buf, &req->num_additionals); - - if (!ERR_DNS_IS_OK(buf->error)) goto error; - - err = ERROR_DNS_NO_MEMORY; - - if ((req->num_questions != 0) && - !(req->questions = TALLOC_ARRAY(req, struct dns_question *, - req->num_questions))) { - goto error; - } - if ((req->num_answers != 0) && - !(req->answers = TALLOC_ARRAY(req, struct dns_rrec *, - req->num_answers))) { - goto error; - } - if ((req->num_auths != 0) && - !(req->auths = TALLOC_ARRAY(req, struct dns_rrec *, - req->num_auths))) { - goto error; - } - if ((req->num_additionals != 0) && - !(req->additionals = TALLOC_ARRAY(req, struct dns_rrec *, - req->num_additionals))) { - goto error; - } - - for (i=0; inum_questions; i++) { - dns_unmarshall_question(req->questions, buf, - &req->questions[i]); - } - for (i=0; inum_answers; i++) { - dns_unmarshall_rr(req->answers, buf, - &req->answers[i]); - } - for (i=0; inum_auths; i++) { - dns_unmarshall_rr(req->auths, buf, - &req->auths[i]); - } - for (i=0; inum_additionals; i++) { - dns_unmarshall_rr(req->additionals, buf, - &req->additionals[i]); - } - - if (!ERR_DNS_IS_OK(buf->error)) { - err = buf->error; - goto error; - } - - *preq = req; - return ERROR_DNS_SUCCESS; - - error: - err = buf->error; - TALLOC_FREE(req); - return err; -} - -struct dns_request *dns_update2request(struct dns_update_request *update) -{ - struct dns_request *req; - - /* - * This is a non-specified construct that happens to work on Linux/gcc - * and I would expect it to work everywhere else. dns_request and - * dns_update_request are essentially the same structures with - * different names, so any difference would mean that the compiler - * applied two different variations of padding given the same types in - * the structures. - */ - - req = (struct dns_request *)(void *)update; - - /* - * The assert statement here looks like we could do the equivalent - * assignments to get portable, but it would mean that we have to - * allocate the dns_question record for the dns_zone records. We - * assume that if this assert works then the same holds true for - * dns_zone<>dns_question as well. - */ - -#ifdef DEVELOPER - assert((req->id == update->id) && (req->flags == update->flags) && - (req->num_questions == update->num_zones) && - (req->num_answers == update->num_preqs) && - (req->num_auths == update->num_updates) && - (req->num_additionals == update->num_additionals) && - (req->questions == - (struct dns_question **)(void *)update->zones) && - (req->answers == update->preqs) && - (req->auths == update->updates) && - (req->additionals == update->additionals)); -#endif - - return req; -} - -struct dns_update_request *dns_request2update(struct dns_request *request) -{ - /* - * For portability concerns see dns_update2request; - */ - return (struct dns_update_request *)(void *)request; -} - -DNS_ERROR dns_marshall_update_request(TALLOC_CTX *mem_ctx, - struct dns_update_request *update, - struct dns_buffer **pbuf) -{ - return dns_marshall_request(mem_ctx, dns_update2request(update), pbuf); -} - -DNS_ERROR dns_unmarshall_update_request(TALLOC_CTX *mem_ctx, - struct dns_buffer *buf, - struct dns_update_request **pupreq) -{ - /* - * See comments above about portability. If the above works, this will - * as well. - */ - - return dns_unmarshall_request(mem_ctx, buf, - (struct dns_request **)(void *)pupreq); -} - -uint16 dns_response_code(uint16 flags) -{ - return flags & 0xF; -} diff --git a/source3/libaddns/dnsrecord.c b/source3/libaddns/dnsrecord.c deleted file mode 100644 index 559c2644d4..0000000000 --- a/source3/libaddns/dnsrecord.c +++ /dev/null @@ -1,422 +0,0 @@ -/* - Linux DNS client library implementation - Copyright (C) 2006 Krishna Ganugapati - Copyright (C) 2006 Gerald Carter - - ** NOTE! The following LGPL license applies to the libaddns - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see . -*/ - -#include "dns.h" - -DNS_ERROR dns_create_query( TALLOC_CTX *mem_ctx, const char *name, - uint16 q_type, uint16 q_class, - struct dns_request **preq ) -{ - struct dns_request *req; - struct dns_question *q; - DNS_ERROR err; - - if (!(req = TALLOC_ZERO_P(mem_ctx, struct dns_request)) || - !(req->questions = TALLOC_ARRAY(req, struct dns_question *, 1)) || - !(req->questions[0] = talloc(req->questions, - struct dns_question))) { - TALLOC_FREE(req); - return ERROR_DNS_NO_MEMORY; - } - - req->id = random(); - - req->num_questions = 1; - q = req->questions[0]; - - err = dns_domain_name_from_string(q, name, &q->name); - if (!ERR_DNS_IS_OK(err)) { - TALLOC_FREE(req); - return err; - } - - q->q_type = q_type; - q->q_class = q_class; - - *preq = req; - return ERROR_DNS_SUCCESS; -} - -DNS_ERROR dns_create_update( TALLOC_CTX *mem_ctx, const char *name, - struct dns_update_request **preq ) -{ - struct dns_update_request *req; - struct dns_zone *z; - DNS_ERROR err; - - if (!(req = TALLOC_ZERO_P(mem_ctx, struct dns_update_request)) || - !(req->zones = TALLOC_ARRAY(req, struct dns_zone *, 1)) || - !(req->zones[0] = talloc(req->zones, struct dns_zone))) { - TALLOC_FREE(req); - return ERROR_DNS_NO_MEMORY; - } - - req->id = random(); - req->flags = 0x2800; /* Dynamic update */ - - req->num_zones = 1; - z = req->zones[0]; - - err = dns_domain_name_from_string(z, name, &z->name); - if (!ERR_DNS_IS_OK(err)) { - TALLOC_FREE(req); - return err; - } - - z->z_type = QTYPE_SOA; - z->z_class = DNS_CLASS_IN; - - *preq = req; - return ERROR_DNS_SUCCESS; -} - -DNS_ERROR dns_create_rrec(TALLOC_CTX *mem_ctx, const char *name, - uint16 type, uint16 r_class, uint32 ttl, - uint16 data_length, uint8 *data, - struct dns_rrec **prec) -{ - struct dns_rrec *rec; - DNS_ERROR err; - - if (!(rec = talloc(mem_ctx, struct dns_rrec))) { - return ERROR_DNS_NO_MEMORY; - } - - err = dns_domain_name_from_string(rec, name, &rec->name); - if (!(ERR_DNS_IS_OK(err))) { - TALLOC_FREE(rec); - return err; - } - - rec->type = type; - rec->r_class = r_class; - rec->ttl = ttl; - rec->data_length = data_length; - rec->data = talloc_move(rec, &data); - - *prec = rec; - return ERROR_DNS_SUCCESS; -} - -DNS_ERROR dns_create_a_record(TALLOC_CTX *mem_ctx, const char *host, - uint32 ttl, const struct sockaddr_storage *pss, - struct dns_rrec **prec) -{ - uint8 *data; - DNS_ERROR err; - struct in_addr ip; - - if (pss->ss_family != AF_INET) { - /* Silently ignore this. */ - return ERROR_DNS_SUCCESS; - } - - ip = ((struct sockaddr_in *)pss)->sin_addr; - if (!(data = (uint8 *)TALLOC_MEMDUP(mem_ctx, (const void *)&ip.s_addr, - sizeof(ip.s_addr)))) { - return ERROR_DNS_NO_MEMORY; - } - - err = dns_create_rrec(mem_ctx, host, QTYPE_A, DNS_CLASS_IN, ttl, - sizeof(ip.s_addr), data, prec); - - if (!ERR_DNS_IS_OK(err)) { - TALLOC_FREE(data); - } - - return err; -} - -DNS_ERROR dns_create_name_in_use_record(TALLOC_CTX *mem_ctx, - const char *name, - const struct sockaddr_storage *ss, - struct dns_rrec **prec) -{ - if (ss != NULL) { - return dns_create_a_record(mem_ctx, name, 0, ss, prec); - } - - return dns_create_rrec(mem_ctx, name, QTYPE_ANY, DNS_CLASS_IN, 0, 0, - NULL, prec); -} - -DNS_ERROR dns_create_name_not_in_use_record(TALLOC_CTX *mem_ctx, - const char *name, uint32 type, - struct dns_rrec **prec) -{ - return dns_create_rrec(mem_ctx, name, type, DNS_CLASS_NONE, 0, - 0, NULL, prec); -} - -DNS_ERROR dns_create_delete_record(TALLOC_CTX *mem_ctx, const char *name, - uint16 type, uint16 r_class, - struct dns_rrec **prec) -{ - return dns_create_rrec(mem_ctx, name, type, r_class, 0, 0, NULL, prec); -} - -DNS_ERROR dns_create_tkey_record(TALLOC_CTX *mem_ctx, const char *keyname, - const char *algorithm_name, time_t inception, - time_t expiration, uint16 mode, uint16 error, - uint16 key_length, const uint8 *key, - struct dns_rrec **prec) -{ - struct dns_buffer *buf; - struct dns_domain_name *algorithm; - DNS_ERROR err; - - if (!(buf = dns_create_buffer(mem_ctx))) { - return ERROR_DNS_NO_MEMORY; - } - - err = dns_domain_name_from_string(buf, algorithm_name, &algorithm); - if (!ERR_DNS_IS_OK(err)) goto error; - - dns_marshall_domain_name(buf, algorithm); - dns_marshall_uint32(buf, inception); - dns_marshall_uint32(buf, expiration); - dns_marshall_uint16(buf, mode); - dns_marshall_uint16(buf, error); - dns_marshall_uint16(buf, key_length); - dns_marshall_buffer(buf, key, key_length); - dns_marshall_uint16(buf, 0); /* Other Size */ - - if (!ERR_DNS_IS_OK(buf->error)) { - err = buf->error; - goto error; - } - - err = dns_create_rrec(mem_ctx, keyname, QTYPE_TKEY, DNS_CLASS_ANY, 0, - buf->offset, buf->data, prec); - - error: - TALLOC_FREE(buf); - return err; -} - -DNS_ERROR dns_unmarshall_tkey_record(TALLOC_CTX *mem_ctx, struct dns_rrec *rec, - struct dns_tkey_record **ptkey) -{ - struct dns_tkey_record *tkey; - struct dns_buffer buf; - uint32 tmp_inception, tmp_expiration; - - if (!(tkey = talloc(mem_ctx, struct dns_tkey_record))) { - return ERROR_DNS_NO_MEMORY; - } - - buf.data = rec->data; - buf.size = rec->data_length; - buf.offset = 0; - buf.error = ERROR_DNS_SUCCESS; - - dns_unmarshall_domain_name(tkey, &buf, &tkey->algorithm); - dns_unmarshall_uint32(&buf, &tmp_inception); - dns_unmarshall_uint32(&buf, &tmp_expiration); - dns_unmarshall_uint16(&buf, &tkey->mode); - dns_unmarshall_uint16(&buf, &tkey->error); - dns_unmarshall_uint16(&buf, &tkey->key_length); - - if (!ERR_DNS_IS_OK(buf.error)) goto error; - - if (tkey->key_length) { - if (!(tkey->key = TALLOC_ARRAY(tkey, uint8, tkey->key_length))) { - buf.error = ERROR_DNS_NO_MEMORY; - goto error; - } - } else { - tkey->key = NULL; - } - - dns_unmarshall_buffer(&buf, tkey->key, tkey->key_length); - if (!ERR_DNS_IS_OK(buf.error)) goto error; - - tkey->inception = (time_t)tmp_inception; - tkey->expiration = (time_t)tmp_expiration; - - *ptkey = tkey; - return ERROR_DNS_SUCCESS; - - error: - TALLOC_FREE(tkey); - return buf.error; -} - -DNS_ERROR dns_create_tsig_record(TALLOC_CTX *mem_ctx, const char *keyname, - const char *algorithm_name, - time_t time_signed, uint16 fudge, - uint16 mac_length, const uint8 *mac, - uint16 original_id, uint16 error, - struct dns_rrec **prec) -{ - struct dns_buffer *buf; - struct dns_domain_name *algorithm; - DNS_ERROR err; - - if (!(buf = dns_create_buffer(mem_ctx))) { - return ERROR_DNS_NO_MEMORY; - } - - err = dns_domain_name_from_string(buf, algorithm_name, &algorithm); - if (!ERR_DNS_IS_OK(err)) goto error; - - dns_marshall_domain_name(buf, algorithm); - dns_marshall_uint16(buf, 0); /* time prefix */ - dns_marshall_uint32(buf, time_signed); - dns_marshall_uint16(buf, fudge); - dns_marshall_uint16(buf, mac_length); - dns_marshall_buffer(buf, mac, mac_length); - dns_marshall_uint16(buf, original_id); - dns_marshall_uint16(buf, error); - dns_marshall_uint16(buf, 0); /* Other Size */ - - if (!ERR_DNS_IS_OK(buf->error)) { - err = buf->error; - goto error; - } - - err = dns_create_rrec(mem_ctx, keyname, QTYPE_TSIG, DNS_CLASS_ANY, 0, - buf->offset, buf->data, prec); - - error: - TALLOC_FREE(buf); - return err; -} - -DNS_ERROR dns_add_rrec(TALLOC_CTX *mem_ctx, struct dns_rrec *rec, - uint16 *num_records, struct dns_rrec ***records) -{ - struct dns_rrec **new_records; - - if (!(new_records = TALLOC_REALLOC_ARRAY(mem_ctx, *records, - struct dns_rrec *, - (*num_records)+1))) { - return ERROR_DNS_NO_MEMORY; - } - - new_records[*num_records] = talloc_move(new_records, &rec); - - *num_records += 1; - *records = new_records; - return ERROR_DNS_SUCCESS; -} - -/* - * Create a request that probes a server whether the list of IP addresses - * provides meets our expectations - */ - -DNS_ERROR dns_create_probe(TALLOC_CTX *mem_ctx, const char *zone, - const char *host, int num_ips, - const struct sockaddr_storage *sslist, - struct dns_update_request **preq) -{ - struct dns_update_request *req; - struct dns_rrec *rec; - DNS_ERROR err; - uint16 i; - - err = dns_create_update(mem_ctx, zone, &req); - if (!ERR_DNS_IS_OK(err)) goto error; - - err = dns_create_name_not_in_use_record(req, host, QTYPE_CNAME, &rec); - if (!ERR_DNS_IS_OK(err)) goto error; - - err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs); - if (!ERR_DNS_IS_OK(err)) goto error; - - for (i=0; inum_preqs, &req->preqs); - if (!ERR_DNS_IS_OK(err)) goto error; - } - - *preq = req; - return ERROR_DNS_SUCCESS; - - error: - TALLOC_FREE(req); - return err; -} - -DNS_ERROR dns_create_update_request(TALLOC_CTX *mem_ctx, - const char *domainname, - const char *hostname, - const struct sockaddr_storage *ss_addrs, - size_t num_addrs, - struct dns_update_request **preq) -{ - struct dns_update_request *req; - struct dns_rrec *rec; - DNS_ERROR err; - size_t i; - - err = dns_create_update(mem_ctx, domainname, &req); - if (!ERR_DNS_IS_OK(err)) return err; - - /* - * Use the same prereq as WinXP -- No CNAME records for this host. - */ - - err = dns_create_rrec(req, hostname, QTYPE_CNAME, DNS_CLASS_NONE, - 0, 0, NULL, &rec); - if (!ERR_DNS_IS_OK(err)) goto error; - - err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs); - if (!ERR_DNS_IS_OK(err)) goto error; - - /* - * Delete any existing A records - */ - - err = dns_create_delete_record(req, hostname, QTYPE_A, DNS_CLASS_ANY, - &rec); - if (!ERR_DNS_IS_OK(err)) goto error; - - err = dns_add_rrec(req, rec, &req->num_updates, &req->updates); - if (!ERR_DNS_IS_OK(err)) goto error; - - /* - * .. and add our IPs - */ - - for ( i=0; inum_updates, &req->updates); - if (!ERR_DNS_IS_OK(err)) - goto error; - } - - *preq = req; - return ERROR_DNS_SUCCESS; - - error: - TALLOC_FREE(req); - return err; -} diff --git a/source3/libaddns/dnssock.c b/source3/libaddns/dnssock.c deleted file mode 100644 index 7c8bd418e5..0000000000 --- a/source3/libaddns/dnssock.c +++ /dev/null @@ -1,377 +0,0 @@ -/* - Linux DNS client library implementation - - Copyright (C) 2006 Krishna Ganugapati - Copyright (C) 2006 Gerald Carter - - ** NOTE! The following LGPL license applies to the libaddns - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see . -*/ - -#include "dns.h" -#include -#include - -static int destroy_dns_connection(struct dns_connection *conn) -{ - return close(conn->s); -} - -/******************************************************************** -********************************************************************/ - -static DNS_ERROR dns_tcp_open( const char *nameserver, - TALLOC_CTX *mem_ctx, - struct dns_connection **result ) -{ - uint32_t ulAddress; - struct hostent *pHost; - struct sockaddr_in s_in; - struct dns_connection *conn; - int res; - - if (!(conn = talloc(mem_ctx, struct dns_connection))) { - return ERROR_DNS_NO_MEMORY; - } - - if ( (ulAddress = inet_addr( nameserver )) == INADDR_NONE ) { - if ( (pHost = gethostbyname( nameserver )) == NULL ) { - TALLOC_FREE(conn); - return ERROR_DNS_INVALID_NAME_SERVER; - } - memcpy( &ulAddress, pHost->h_addr, pHost->h_length ); - } - - conn->s = socket( PF_INET, SOCK_STREAM, 0 ); - if (conn->s == -1) { - TALLOC_FREE(conn); - return ERROR_DNS_CONNECTION_FAILED; - } - - talloc_set_destructor(conn, destroy_dns_connection); - - s_in.sin_family = AF_INET; - s_in.sin_addr.s_addr = ulAddress; - s_in.sin_port = htons( DNS_TCP_PORT ); - - res = connect(conn->s, (struct sockaddr*)&s_in, sizeof( s_in )); - if (res == -1) { - TALLOC_FREE(conn); - return ERROR_DNS_CONNECTION_FAILED; - } - - conn->hType = DNS_TCP; - - *result = conn; - return ERROR_DNS_SUCCESS; -} - -/******************************************************************** -********************************************************************/ - -static DNS_ERROR dns_udp_open( const char *nameserver, - TALLOC_CTX *mem_ctx, - struct dns_connection **result ) -{ - unsigned long ulAddress; - struct hostent *pHost; - struct sockaddr_in RecvAddr; - struct dns_connection *conn; - - if (!(conn = talloc(NULL, struct dns_connection))) { - return ERROR_DNS_NO_MEMORY; - } - - if ( (ulAddress = inet_addr( nameserver )) == INADDR_NONE ) { - if ( (pHost = gethostbyname( nameserver )) == NULL ) { - TALLOC_FREE(conn); - return ERROR_DNS_INVALID_NAME_SERVER; - } - memcpy( &ulAddress, pHost->h_addr, pHost->h_length ); - } - - /* Create a socket for sending data */ - - conn->s = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); - if (conn->s == -1) { - TALLOC_FREE(conn); - return ERROR_DNS_CONNECTION_FAILED; - } - - talloc_set_destructor(conn, destroy_dns_connection); - - /* Set up the RecvAddr structure with the IP address of - the receiver (in this example case "123.456.789.1") - and the specified port number. */ - - ZERO_STRUCT(RecvAddr); - RecvAddr.sin_family = AF_INET; - RecvAddr.sin_port = htons( DNS_UDP_PORT ); - RecvAddr.sin_addr.s_addr = ulAddress; - - conn->hType = DNS_UDP; - memcpy( &conn->RecvAddr, &RecvAddr, sizeof( struct sockaddr_in ) ); - - *result = conn; - return ERROR_DNS_SUCCESS; -} - -/******************************************************************** -********************************************************************/ - -DNS_ERROR dns_open_connection( const char *nameserver, int32 dwType, - TALLOC_CTX *mem_ctx, - struct dns_connection **conn ) -{ - switch ( dwType ) { - case DNS_TCP: - return dns_tcp_open( nameserver, mem_ctx, conn ); - case DNS_UDP: - return dns_udp_open( nameserver, mem_ctx, conn ); - } - - return ERROR_DNS_INVALID_PARAMETER; -} - -static DNS_ERROR write_all(int fd, uint8 *data, size_t len) -{ - size_t total = 0; - - while (total < len) { - - ssize_t ret = write(fd, data + total, len - total); - - if (ret <= 0) { - /* - * EOF or error - */ - return ERROR_DNS_SOCKET_ERROR; - } - - total += ret; - } - - return ERROR_DNS_SUCCESS; -} - -static DNS_ERROR dns_send_tcp(struct dns_connection *conn, - const struct dns_buffer *buf) -{ - uint16 len = htons(buf->offset); - DNS_ERROR err; - - err = write_all(conn->s, (uint8 *)&len, sizeof(len)); - if (!ERR_DNS_IS_OK(err)) return err; - - return write_all(conn->s, buf->data, buf->offset); -} - -static DNS_ERROR dns_send_udp(struct dns_connection *conn, - const struct dns_buffer *buf) -{ - ssize_t ret; - - ret = sendto(conn->s, buf->data, buf->offset, 0, - (struct sockaddr *)&conn->RecvAddr, - sizeof(conn->RecvAddr)); - - if (ret != buf->offset) { - return ERROR_DNS_SOCKET_ERROR; - } - - return ERROR_DNS_SUCCESS; -} - -DNS_ERROR dns_send(struct dns_connection *conn, const struct dns_buffer *buf) -{ - if (conn->hType == DNS_TCP) { - return dns_send_tcp(conn, buf); - } - - if (conn->hType == DNS_UDP) { - return dns_send_udp(conn, buf); - } - - return ERROR_DNS_INVALID_PARAMETER; -} - -static DNS_ERROR read_all(int fd, uint8 *data, size_t len) -{ - size_t total = 0; - fd_set rfds; - struct timeval tv; - - while (total < len) { - ssize_t ret; - int fd_ready; - - FD_ZERO( &rfds ); - FD_SET( fd, &rfds ); - - /* 10 second timeout */ - tv.tv_sec = 10; - tv.tv_usec = 0; - - fd_ready = select( fd+1, &rfds, NULL, NULL, &tv ); - if ( fd_ready == 0 ) { - /* read timeout */ - return ERROR_DNS_SOCKET_ERROR; - } - - ret = read(fd, data + total, len - total); - if (ret <= 0) { - /* EOF or error */ - return ERROR_DNS_SOCKET_ERROR; - } - - total += ret; - } - - return ERROR_DNS_SUCCESS; -} - -static DNS_ERROR dns_receive_tcp(TALLOC_CTX *mem_ctx, - struct dns_connection *conn, - struct dns_buffer **presult) -{ - struct dns_buffer *buf; - DNS_ERROR err; - uint16 len; - - if (!(buf = TALLOC_ZERO_P(mem_ctx, struct dns_buffer))) { - return ERROR_DNS_NO_MEMORY; - } - - err = read_all(conn->s, (uint8 *)&len, sizeof(len)); - if (!ERR_DNS_IS_OK(err)) { - return err; - } - - buf->size = ntohs(len); - - if (buf->size) { - if (!(buf->data = TALLOC_ARRAY(buf, uint8, buf->size))) { - TALLOC_FREE(buf); - return ERROR_DNS_NO_MEMORY; - } - } else { - buf->data = NULL; - } - - err = read_all(conn->s, buf->data, buf->size); - if (!ERR_DNS_IS_OK(err)) { - TALLOC_FREE(buf); - return err; - } - - *presult = buf; - return ERROR_DNS_SUCCESS; -} - -static DNS_ERROR dns_receive_udp(TALLOC_CTX *mem_ctx, - struct dns_connection *conn, - struct dns_buffer **presult) -{ - struct dns_buffer *buf; - ssize_t received; - - if (!(buf = TALLOC_ZERO_P(mem_ctx, struct dns_buffer))) { - return ERROR_DNS_NO_MEMORY; - } - - /* - * UDP based DNS can only be 512 bytes - */ - - if (!(buf->data = TALLOC_ARRAY(buf, uint8, 512))) { - TALLOC_FREE(buf); - return ERROR_DNS_NO_MEMORY; - } - - received = recv(conn->s, (void *)buf->data, 512, 0); - - if (received == -1) { - TALLOC_FREE(buf); - return ERROR_DNS_SOCKET_ERROR; - } - - if (received > 512) { - TALLOC_FREE(buf); - return ERROR_DNS_BAD_RESPONSE; - } - - buf->size = received; - buf->offset = 0; - - *presult = buf; - return ERROR_DNS_SUCCESS; -} - -DNS_ERROR dns_receive(TALLOC_CTX *mem_ctx, struct dns_connection *conn, - struct dns_buffer **presult) -{ - if (conn->hType == DNS_TCP) { - return dns_receive_tcp(mem_ctx, conn, presult); - } - - if (conn->hType == DNS_UDP) { - return dns_receive_udp(mem_ctx, conn, presult); - } - - return ERROR_DNS_INVALID_PARAMETER; -} - -DNS_ERROR dns_transaction(TALLOC_CTX *mem_ctx, struct dns_connection *conn, - const struct dns_request *req, - struct dns_request **resp) -{ - struct dns_buffer *buf = NULL; - DNS_ERROR err; - - err = dns_marshall_request(conn, req, &buf); - if (!ERR_DNS_IS_OK(err)) goto error; - - err = dns_send(conn, buf); - if (!ERR_DNS_IS_OK(err)) goto error; - TALLOC_FREE(buf); - - err = dns_receive(mem_ctx, conn, &buf); - if (!ERR_DNS_IS_OK(err)) goto error; - - err = dns_unmarshall_request(mem_ctx, buf, resp); - - error: - TALLOC_FREE(buf); - return err; -} - -DNS_ERROR dns_update_transaction(TALLOC_CTX *mem_ctx, - struct dns_connection *conn, - struct dns_update_request *up_req, - struct dns_update_request **up_resp) -{ - struct dns_request *resp; - DNS_ERROR err; - - err = dns_transaction(mem_ctx, conn, dns_update2request(up_req), - &resp); - - if (!ERR_DNS_IS_OK(err)) return err; - - *up_resp = dns_request2update(resp); - return ERROR_DNS_SUCCESS; -} diff --git a/source3/libaddns/dnsutils.c b/source3/libaddns/dnsutils.c deleted file mode 100644 index 37b862c7f0..0000000000 --- a/source3/libaddns/dnsutils.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - Linux DNS client library implementation - - Copyright (C) 2006 Krishna Ganugapati - Copyright (C) 2006 Gerald Carter - - ** NOTE! The following LGPL license applies to the libaddns - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see . -*/ - -#include "dns.h" -#include - -static DNS_ERROR LabelList( TALLOC_CTX *mem_ctx, - const char *name, - struct dns_domain_label **presult ) -{ - struct dns_domain_label *result; - const char *dot; - - for (dot = name; *dot != '\0'; dot += 1) { - char c = *dot; - - if (c == '.') - break; - - if (c == '-') continue; - if ((c >= 'a') && (c <= 'z')) continue; - if ((c >= 'A') && (c <= 'Z')) continue; - if ((c >= '0') && (c <= '9')) continue; - - return ERROR_DNS_INVALID_NAME; - } - - if ((dot - name) > 63) { - /* - * DNS labels can only be 63 chars long - */ - return ERROR_DNS_INVALID_NAME; - } - - if (!(result = TALLOC_ZERO_P(mem_ctx, struct dns_domain_label))) { - return ERROR_DNS_NO_MEMORY; - } - - if (*dot == '\0') { - /* - * No dot around, so this is the last component - */ - - if (!(result->label = talloc_strdup(result, name))) { - TALLOC_FREE(result); - return ERROR_DNS_NO_MEMORY; - } - result->len = strlen(result->label); - *presult = result; - return ERROR_DNS_SUCCESS; - } - - if (dot[1] == '.') { - /* - * Two dots in a row, reject - */ - - TALLOC_FREE(result); - return ERROR_DNS_INVALID_NAME; - } - - if (dot[1] != '\0') { - /* - * Something follows, get the rest - */ - - DNS_ERROR err = LabelList(result, dot+1, &result->next); - - if (!ERR_DNS_IS_OK(err)) { - TALLOC_FREE(result); - return err; - } - } - - result->len = (dot - name); - - if (!(result->label = talloc_strndup(result, name, result->len))) { - TALLOC_FREE(result); - return ERROR_DNS_NO_MEMORY; - } - - *presult = result; - return ERROR_DNS_SUCCESS; -} - -DNS_ERROR dns_domain_name_from_string( TALLOC_CTX *mem_ctx, - const char *pszDomainName, - struct dns_domain_name **presult ) -{ - struct dns_domain_name *result; - DNS_ERROR err; - - if (!(result = talloc(mem_ctx, struct dns_domain_name))) { - return ERROR_DNS_NO_MEMORY; - } - - err = LabelList( result, pszDomainName, &result->pLabelList ); - if (!ERR_DNS_IS_OK(err)) { - TALLOC_FREE(result); - return err; - } - - *presult = result; - return ERROR_DNS_SUCCESS; -} - -/********************************************************************* -*********************************************************************/ - -char *dns_generate_keyname( TALLOC_CTX *mem_ctx ) -{ - char *result = NULL; -#if defined(WITH_DNS_UPDATES) - - uuid_t uuid; - - /* - * uuid_unparse gives 36 bytes plus '\0' - */ - if (!(result = TALLOC_ARRAY(mem_ctx, char, 37))) { - return NULL; - } - - uuid_generate( uuid ); - uuid_unparse( uuid, result ); - -#endif - - return result; -} diff --git a/source3/libaddns/error.c b/source3/libaddns/error.c deleted file mode 100644 index 361388cea3..0000000000 --- a/source3/libaddns/error.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - Linux DNS client library implementation - Copyright (C) 2010 Guenther Deschner - - ** NOTE! The following LGPL license applies to the libaddns - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see . -*/ - -#include "dns.h" -#include "dnserr.h" - -typedef struct { - const char *dns_errstr; - DNS_ERROR dns_errcode; -} dns_err_code_struct; - -static const dns_err_code_struct dns_errs[] = -{ - { "ERROR_DNS_SUCCESS", ERROR_DNS_SUCCESS }, - { "ERROR_DNS_RECORD_NOT_FOUND", ERROR_DNS_RECORD_NOT_FOUND }, - { "ERROR_DNS_BAD_RESPONSE", ERROR_DNS_BAD_RESPONSE }, - { "ERROR_DNS_INVALID_PARAMETER", ERROR_DNS_INVALID_PARAMETER }, - { "ERROR_DNS_NO_MEMORY", ERROR_DNS_NO_MEMORY }, - { "ERROR_DNS_INVALID_NAME_SERVER", ERROR_DNS_INVALID_NAME_SERVER }, - { "ERROR_DNS_CONNECTION_FAILED", ERROR_DNS_CONNECTION_FAILED }, - { "ERROR_DNS_GSS_ERROR", ERROR_DNS_GSS_ERROR }, - { "ERROR_DNS_INVALID_NAME", ERROR_DNS_INVALID_NAME }, - { "ERROR_DNS_INVALID_MESSAGE", ERROR_DNS_INVALID_MESSAGE }, - { "ERROR_DNS_SOCKET_ERROR", ERROR_DNS_SOCKET_ERROR }, - { "ERROR_DNS_UPDATE_FAILED", ERROR_DNS_UPDATE_FAILED }, - { NULL, ERROR_DNS_SUCCESS }, -}; - -const char *dns_errstr(DNS_ERROR err) -{ - int i; - - for (i=0; dns_errs[i].dns_errstr != NULL; i++) { - if (ERR_DNS_EQUAL(err, dns_errs[i].dns_errcode)) { - return dns_errs[i].dns_errstr; - } - } - - return NULL; -} diff --git a/source3/libaddns/wscript_build b/source3/libaddns/wscript_build deleted file mode 100644 index 69a4716245..0000000000 --- a/source3/libaddns/wscript_build +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env python - -bld.SAMBA_LIBRARY('addns', - source='dnsrecord.c dnsutils.c dnssock.c dnsgss.c dnsmarshall.c error.c', - public_deps='talloc krb5 k5crypto com_err gssapi gssapi_krb5 uuid', - private_library=True, - vars=locals()) diff --git a/source3/wscript_build b/source3/wscript_build index db4b48e2e2..a9e2e245cd 100644 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -1489,6 +1489,7 @@ bld.RECURSE('../lib/tsocket') bld.RECURSE('../lib/iniparser/src') bld.RECURSE('../lib/crypto') bld.RECURSE('../lib/async_req') +bld.RECURSE('../lib/addns') bld.RECURSE('../libcli/auth') bld.RECURSE('../libcli/drsuapi') bld.RECURSE('../libcli/samsync') @@ -1503,7 +1504,6 @@ bld.RECURSE('winbindd') bld.RECURSE('libgpo/gpext') bld.RECURSE('pam_smbpass') bld.RECURSE('rpc_server') -bld.RECURSE('libaddns') bld.ENFORCE_GROUP_ORDERING() bld.CHECK_PROJECT_RULES() -- cgit