1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-23 09:57:40 +03:00

dns_server: Add a python module directly accessing DNS records in sam.ldb

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
This commit is contained in:
Andrew Bartlett 2015-09-22 12:11:04 +12:00
parent 0504065948
commit 87cd68c1dc
3 changed files with 240 additions and 1 deletions

View File

@ -27,7 +27,7 @@ import ldb
import time
import base64
import os
from samba import dsdb
from samba import dsdb, dsdb_dns
from samba.ndr import ndr_unpack, ndr_pack
from samba.dcerpc import drsblobs, misc
from samba.common import normalise_int32
@ -921,3 +921,11 @@ accountExpires: %u
'''get the server DN from the rootDSE'''
res = self.search(base="", scope=ldb.SCOPE_BASE, attrs=["serverName"])
return res[0]["serverName"][0]
def dns_lookup(self, dns_name):
'''Do a DNS lookup in the database, returns the NDR database structures'''
return dsdb_dns.lookup(self, dns_name)
def dns_replace(self, dns_name, new_records):
'''Do a DNS modification on the database, sets the NDR database structures'''
return dsdb_dns.replace(self, dns_name, new_records)

225
source4/dns_server/pydns.c Normal file
View File

@ -0,0 +1,225 @@
/*
Unix SMB/CIFS implementation.
Python DNS server wrapper
Copyright (C) 2015 Andrew Bartlett
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Python.h>
#include "includes.h"
#include <pyldb.h>
#include <pytalloc.h>
#include "dns_server/dnsserver_common.h"
#include "dsdb/samdb/samdb.h"
#include "dsdb/common/util.h"
#include "librpc/gen_ndr/ndr_dnsp.h"
#include "librpc/rpc/pyrpc_util.h"
/* FIXME: These should be in a header file somewhere */
#define PyErr_LDB_OR_RAISE(py_ldb, ldb) \
if (!py_check_dcerpc_type(py_ldb, "ldb", "Ldb")) { \
PyErr_SetString(py_ldb_get_exception(), "Ldb connection object required"); \
return NULL; \
} \
ldb = pyldb_Ldb_AsLdbContext(py_ldb);
static PyObject *py_ldb_get_exception(void)
{
PyObject *mod = PyImport_ImportModule("ldb");
if (mod == NULL)
return NULL;
return PyObject_GetAttrString(mod, "LdbError");
}
static PyObject *py_dnsp_DnssrvRpcRecord_get_list(struct dnsp_DnssrvRpcRecord *records,
uint16_t num_records)
{
PyObject *py_dns_list;
int i;
py_dns_list = PyList_New(num_records);
if (py_dns_list == NULL) {
return NULL;
}
for (i = 0; i < num_records; i++) {
PyObject *py_dns_record;
py_dns_record = py_return_ndr_struct("samba.dcerpc.dnsp", "DnssrvRpcRecord", records, &records[i]);
PyList_SetItem(py_dns_list, i, py_dns_record);
}
return py_dns_list;
}
static int py_dnsp_DnssrvRpcRecord_get_array(PyObject *value,
TALLOC_CTX *mem_ctx,
struct dnsp_DnssrvRpcRecord **records,
uint16_t *num_records)
{
int i;
struct dnsp_DnssrvRpcRecord *recs;
PY_CHECK_TYPE(&PyList_Type, value, return -1;);
recs = talloc_array(mem_ctx, struct dnsp_DnssrvRpcRecord,
PyList_GET_SIZE(value));
if (recs == NULL) {
PyErr_NoMemory();
return -1;
}
for (i = 0; i < PyList_GET_SIZE(value); i++) {
bool type_correct;
PyObject *item = PyList_GET_ITEM(value, i);
type_correct = py_check_dcerpc_type(item, "samba.dcerpc.dnsp", "DnssrvRpcRecord");
if (type_correct == false) {
return -1;
}
if (talloc_reference(mem_ctx, pytalloc_get_mem_ctx(item)) == NULL) {
PyErr_NoMemory();
return -1;
}
recs[i] = *(struct dnsp_DnssrvRpcRecord *)pytalloc_get_ptr(item);
}
*records = recs;
*num_records = PyList_GET_SIZE(value);
return 0;
}
static PyObject *py_dsdb_dns_lookup(PyObject *self, PyObject *args)
{
struct ldb_context *samdb;
PyObject *py_ldb;
char *dns_name;
TALLOC_CTX *frame;
NTSTATUS status;
WERROR werr;
struct dns_server_zone *zones_list;
struct ldb_dn *dn;
struct dnsp_DnssrvRpcRecord *records;
uint16_t num_records;
if (!PyArg_ParseTuple(args, "Os", &py_ldb, &dns_name)) {
return NULL;
}
PyErr_LDB_OR_RAISE(py_ldb, samdb);
frame = talloc_stackframe();
status = dns_common_zones(samdb, frame, &zones_list);
if (!NT_STATUS_IS_OK(status)) {
PyErr_SetNTSTATUS(status);
return NULL;
}
werr = dns_common_name2dn(samdb, zones_list, frame, dns_name, &dn);
if (!W_ERROR_IS_OK(werr)) {
PyErr_SetWERROR(werr);
return NULL;
}
werr = dns_common_lookup(samdb,
frame,
dn,
&records,
&num_records,
NULL);
if (!W_ERROR_IS_OK(werr)) {
PyErr_SetWERROR(werr);
return NULL;
}
return py_dnsp_DnssrvRpcRecord_get_list(records, num_records);
}
static PyObject *py_dsdb_dns_replace(PyObject *self, PyObject *args)
{
struct ldb_context *samdb;
PyObject *py_ldb, *py_dns_records;
char *dns_name;
TALLOC_CTX *frame;
NTSTATUS status;
WERROR werr;
int ret;
struct dns_server_zone *zones_list;
struct ldb_dn *dn;
struct dnsp_DnssrvRpcRecord *records;
uint16_t num_records;
/*
* TODO: This is a shocking abuse, but matches what the
* internal DNS server does, it should be pushed into
* dns_common_replace()
*/
static const int serial = 110;
if (!PyArg_ParseTuple(args, "OsO", &py_ldb, &dns_name, &py_dns_records)) {
return NULL;
}
PyErr_LDB_OR_RAISE(py_ldb, samdb);
frame = talloc_stackframe();
status = dns_common_zones(samdb, frame, &zones_list);
if (!NT_STATUS_IS_OK(status)) {
PyErr_SetNTSTATUS(status);
return NULL;
}
werr = dns_common_name2dn(samdb, zones_list, frame, dns_name, &dn);
if (!W_ERROR_IS_OK(werr)) {
PyErr_SetWERROR(werr);
return NULL;
}
ret = py_dnsp_DnssrvRpcRecord_get_array(py_dns_records,
frame,
&records, &num_records);
if (ret != 0) {
return NULL;
}
werr = dns_common_replace(samdb,
frame,
dn,
false, /* Not adding a record */
serial,
records,
num_records);
if (!W_ERROR_IS_OK(werr)) {
PyErr_SetWERROR(werr);
return NULL;
}
Py_RETURN_NONE;
}
static PyMethodDef py_dsdb_dns_methods[] = {
{ "lookup", (PyCFunction)py_dsdb_dns_lookup,
METH_VARARGS, "Get the DNS database entries for a DNS name"},
{ "replace", (PyCFunction)py_dsdb_dns_replace,
METH_VARARGS, "Replace the DNS database entries for a DNS name"},
{ NULL }
};
void initdsdb_dns(void);
void initdsdb_dns(void)
{
PyObject *m;
m = Py_InitModule3("dsdb_dns", py_dsdb_dns_methods,
"Python bindings for the DNS objects in the directory service databases.");
if (m == NULL)
return;
}

View File

@ -53,3 +53,9 @@ bld.SAMBA_LIBRARY('dlz_bind9_for_torture',
private_library=True,
deps='samba-hostconfig samdb-common gensec popt dnsserver_common',
enabled=bld.AD_DC_BUILD_IS_ENABLED())
bld.SAMBA_PYTHON('python_dsdb_dns',
source='pydns.c',
deps='samdb pyldb-util pyrpc_util dnsserver_common',
realname='samba/dsdb_dns.so')