mirror of
https://github.com/samba-team/samba.git
synced 2025-02-02 09:47:23 +03:00
pydns: expose dns timestamp utils to python, and test
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz> Reviewed-by: Jeremy Allison <jra@samba.org>
This commit is contained in:
parent
2b9279bd31
commit
146c23fb7d
86
python/samba/tests/dsdb_dns.py
Normal file
86
python/samba/tests/dsdb_dns.py
Normal file
@ -0,0 +1,86 @@
|
||||
# Unix SMB/CIFS implementation. Tests for dsdb_dns module
|
||||
# Copyright © Catalyst IT 2021
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
from samba.tests import TestCase
|
||||
from samba import dsdb_dns
|
||||
import time
|
||||
|
||||
|
||||
def unix2nttime(t):
|
||||
# here we reimplement unix_to_nt_time from lib/util/time.c
|
||||
if t == -1:
|
||||
return t
|
||||
if t == (1 << 63) - 1:
|
||||
return (1 << 63) - 1
|
||||
if t == 0:
|
||||
return 0
|
||||
t += 11644473600
|
||||
t *= 1e7
|
||||
return int(t)
|
||||
|
||||
|
||||
def unix2dns_timestamp(t):
|
||||
nt = unix2nttime(t)
|
||||
if nt < 0:
|
||||
# because NTTIME is a uint64_t.
|
||||
nt += 1 << 64
|
||||
return nt // int(3.6e10)
|
||||
|
||||
|
||||
def timestamp2nttime(ts):
|
||||
nt = ts * int(3.6e10)
|
||||
if nt >= 1 << 63:
|
||||
raise OverflowError("nt time won't fit this")
|
||||
return nt
|
||||
|
||||
|
||||
class DsdbDnsTestCase(TestCase):
|
||||
def test_unix_to_dns_timestamp(self):
|
||||
unixtimes = [1616829393,
|
||||
1,
|
||||
0,
|
||||
-1,
|
||||
1 << 31 - 1]
|
||||
|
||||
for t in unixtimes:
|
||||
expected = unix2dns_timestamp(t)
|
||||
result = dsdb_dns.unix_to_dns_timestamp(t)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_dns_timestamp_to_nt_time(self):
|
||||
timestamps = [16168393,
|
||||
1,
|
||||
0,
|
||||
(1 << 32) - 1,
|
||||
(1 << 63) - 1,
|
||||
int((1 << 63) / 3.6e10),
|
||||
int((1 << 63) / 3.6e10) + 1, # overflows
|
||||
]
|
||||
|
||||
for t in timestamps:
|
||||
overflows = False
|
||||
try:
|
||||
expected = timestamp2nttime(t)
|
||||
except OverflowError:
|
||||
overflows = True
|
||||
try:
|
||||
result = dsdb_dns.dns_timestamp_to_nt_time(t)
|
||||
except ValueError:
|
||||
self.assertTrue(overflows, f"timestamp {t} should not overflow")
|
||||
continue
|
||||
self.assertFalse(overflows, f"timestamp {t} should overflow")
|
||||
|
||||
self.assertEqual(result, expected)
|
@ -325,6 +325,48 @@ static PyObject *py_dsdb_dns_replace_by_dn(PyObject *self, PyObject *args)
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *py_dsdb_dns_unix_to_dns_timestamp(PyObject *self, PyObject *args)
|
||||
{
|
||||
uint32_t timestamp;
|
||||
time_t t;
|
||||
long long lt;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "L", <)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
t = lt;
|
||||
if (t != lt) {
|
||||
/* time_t is presumably 32 bit here */
|
||||
PyErr_SetString(PyExc_ValueError, "Time out of range");
|
||||
return NULL;
|
||||
}
|
||||
timestamp = unix_to_dns_timestamp(t);
|
||||
return Py_BuildValue("k", (unsigned long) timestamp);
|
||||
}
|
||||
|
||||
static PyObject *py_dsdb_dns_timestamp_to_nt_time(PyObject *self, PyObject *args)
|
||||
{
|
||||
unsigned long long timestamp;
|
||||
NTSTATUS status;
|
||||
NTTIME nt;
|
||||
if (!PyArg_ParseTuple(args, "K", ×tamp)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (timestamp > UINT32_MAX || timestamp < 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "Time out of range");
|
||||
return NULL;
|
||||
}
|
||||
status = dns_timestamp_to_nt_time(&nt, (uint32_t)timestamp);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
PyErr_SetString(PyExc_ValueError, "Time out of range");
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("L", (long long) nt);
|
||||
}
|
||||
|
||||
|
||||
static PyMethodDef py_dsdb_dns_methods[] = {
|
||||
|
||||
{ "lookup", PY_DISCARD_FUNC_SIG(PyCFunction, py_dsdb_dns_lookup),
|
||||
@ -336,6 +378,12 @@ static PyMethodDef py_dsdb_dns_methods[] = {
|
||||
METH_VARARGS, "Replace the DNS database entries for a LDB DN"},
|
||||
{ "extract", (PyCFunction)py_dsdb_dns_extract,
|
||||
METH_VARARGS, "Return the DNS database entry as a python structure from an Ldb.MessageElement of type dnsRecord"},
|
||||
{ "unix_to_dns_timestamp", (PyCFunction)py_dsdb_dns_unix_to_dns_timestamp,
|
||||
METH_VARARGS,
|
||||
"Convert a time.time() value to a dns timestamp (hours since 1601)"},
|
||||
{ "dns_timestamp_to_nt_time", (PyCFunction)py_dsdb_dns_timestamp_to_nt_time,
|
||||
METH_VARARGS,
|
||||
"Convert a dns timestamp to an NTTIME value"},
|
||||
{0}
|
||||
};
|
||||
|
||||
|
@ -823,6 +823,8 @@ planoldpythontestsuite("ad_dc_default:local", "samba.tests.krb5.s4u_tests",
|
||||
'SERVICE_PASSWORD':'$PASSWORD',
|
||||
'FOR_USER':'$USERNAME'})
|
||||
|
||||
planoldpythontestsuite("ad_dc_default", "samba.tests.dsdb_dns")
|
||||
|
||||
planoldpythontestsuite("fl2008r2dc:local", "samba.tests.krb5.xrealm_tests")
|
||||
|
||||
for env in ["ad_dc", smbv1_disabled_testenv]:
|
||||
|
Loading…
x
Reference in New Issue
Block a user