Skip to content

Commit

Permalink
Add set_real_time(), timeofday(), us_timeofday() and get_time_offsets()
Browse files Browse the repository at this point in the history
  • Loading branch information
steffen-kiess committed Mar 12, 2024
1 parent 0339512 commit 1d772b0
Show file tree
Hide file tree
Showing 6 changed files with 203 additions and 1 deletion.
20 changes: 19 additions & 1 deletion src/krb5/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,15 @@
cc_switch,
)
from krb5._cccol import cccol_iter
from krb5._context import Context, get_default_realm, init_context, set_default_realm
from krb5._context import (
Context,
get_default_realm,
init_context,
set_default_realm,
set_real_time,
timeofday,
us_timeofday,
)
from krb5._creds import (
Creds,
InitCredsContext,
Expand Down Expand Up @@ -135,8 +143,11 @@
"kt_resolve",
"parse_name_flags",
"set_default_realm",
"set_real_time",
"string_to_enctype",
"timeofday",
"unparse_name_flags",
"us_timeofday",
]

# Provider or version specific APIs
Expand Down Expand Up @@ -169,6 +180,13 @@
else:
__all__.append("init_secure_context")

try:
from krb5._context_mit import get_time_offsets
except ImportError:
pass
else:
__all__.append("get_time_offsets")


try:
from krb5._creds_opt_heimdal import get_init_creds_opt_set_default_flags
Expand Down
44 changes: 44 additions & 0 deletions src/krb5/_context.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,47 @@ def set_default_realm(
context: Krb5 context.
realm: The realm to set as the default realm.
"""

def timeofday(
context: Context,
) -> int:
"""Return the adjusted time.
Return the adjusted time.
Args:
context: Krb5 context.
Returns:
The current time as seen by the KDC in seconds.
"""

def us_timeofday(
context: Context,
) -> typing.Tuple[int, int]:
"""Return the adjusted time with microseconds.
Return the adjusted time with microseconds.
Args:
context: Krb5 context.
Returns:
The current time as seen by the KDC in seconds and microseconds.
"""

def set_real_time(
context: Context,
seconds: int,
microseconds: int,
) -> None:
"""Set the time offset to the difference between the system time and the specified time.
Set the time offset of the context to the difference between the system time
and the specified time.
Args:
context: Krb5 context.
seconds: The seconds of the current time as seen by the KDC.
microseconds: The microseconds of the current time as seen by the KDC or -1.
"""
58 changes: 58 additions & 0 deletions src/krb5/_context.pyx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Copyright: (c) 2021 Jordan Borean (@jborean93) <jborean93@gmail.com>
# MIT License (see LICENSE or https://opensource.org/licenses/MIT)

import typing

from krb5._exceptions import Krb5Error

from krb5._krb5_types cimport *
Expand Down Expand Up @@ -43,6 +45,23 @@ cdef extern from "python_krb5.h":
const char *realm
) nogil

krb5_error_code krb5_timeofday(
krb5_context context,
krb5_timestamp *seconds
) nogil

krb5_error_code krb5_us_timeofday(
krb5_context context,
krb5_timestamp *seconds,
int32_t *microseconds
) nogil

krb5_error_code krb5_set_real_time(
krb5_context context,
krb5_timestamp seconds,
int32_t microseconds
) nogil


cdef class Context:
# cdef krb5_context raw
Expand Down Expand Up @@ -98,3 +117,42 @@ def set_default_realm(
err = krb5_set_default_realm(context.raw, realm_ptr)
if err:
raise Krb5Error(context, err)


def timeofday(
Context context not None,
) -> int:
cdef krb5_error_code = 0

cdef krb5_timestamp seconds
err = krb5_timeofday(context.raw, &seconds)
if err:
raise Krb5Error(context, err)

return seconds


def us_timeofday(
Context context not None,
) -> typing.Tuple[int, int]:
cdef krb5_error_code = 0

cdef krb5_timestamp seconds
cdef int32_t microseconds
err = krb5_us_timeofday(context.raw, &seconds, &microseconds)
if err:
raise Krb5Error(context, err)

return seconds, microseconds


def set_real_time(
Context context not None,
int seconds,
int microseconds,
) -> None:
cdef krb5_error_code = 0

err = krb5_set_real_time(context.raw, seconds, microseconds)
if err:
raise Krb5Error(context, err)
16 changes: 16 additions & 0 deletions src/krb5/_context_mit.pyi
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Copyright: (c) 2021 Jordan Borean (@jborean93) <jborean93@gmail.com>
# MIT License (see LICENSE or https://opensource.org/licenses/MIT)

import typing

from krb5._context import Context

def init_secure_context() -> Context:
Expand All @@ -12,3 +14,17 @@ def init_secure_context() -> Context:
Returns:
Context: The opened krb5 library context.
"""

def get_time_offsets(
context: Context,
) -> typing.Tuple[int, int]:
"""Return the time offset of the specified context.
Returns the time offset of the specified context.
Args:
context: Krb5 context.
Returns:
The seconds and microseconds of the time offset.
"""
23 changes: 23 additions & 0 deletions src/krb5/_context_mit.pyx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
# Copyright: (c) 2021 Jordan Borean (@jborean93) <jborean93@gmail.com>
# MIT License (see LICENSE or https://opensource.org/licenses/MIT)

import typing

from krb5._context cimport Context
from krb5._exceptions import Krb5Error
from krb5._krb5_types cimport *


Expand All @@ -10,9 +13,29 @@ cdef extern from "python_krb5.h":
krb5_context *context,
) nogil

krb5_error_code krb5_get_time_offsets(
krb5_context context,
krb5_timestamp *seconds,
int32_t *microseconds
) nogil


def init_secure_context() -> Context:
context = Context()
krb5_init_secure_context(&context.raw)

return context


def get_time_offsets(
Context context not None,
) -> typing.Tuple[int, int]:
cdef krb5_error_code = 0

cdef krb5_timestamp seconds
cdef int32_t microseconds
err = krb5_get_time_offsets(context.raw, &seconds, &microseconds)
if err:
raise Krb5Error(context, err)

return seconds, microseconds
43 changes: 43 additions & 0 deletions tests/test_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# MIT License (see LICENSE or https://opensource.org/licenses/MIT)

import os
import time

import k5test
import pytest
Expand Down Expand Up @@ -31,6 +32,48 @@ def test_set_default_realm(realm: k5test.K5Realm) -> None:
assert default == realm.realm.encode()


def test_set_real_time() -> None:
ctx = krb5.init_context()

diff = krb5.timeofday(ctx) - time.time()
assert diff > -5
assert diff < 5

now = krb5.us_timeofday(ctx)
diff = now[0] * 1000000 + now[1] - int(time.time() * 1e6)
assert diff > -5000000
assert diff < 5000000

krb5.set_real_time(ctx, int(time.time()) + 100, 0)
diff = krb5.timeofday(ctx) - time.time()
assert diff > 95
assert diff < 105

krb5.set_real_time(ctx, int(time.time()), -1)
diff = krb5.timeofday(ctx) - time.time()
assert diff > -5
assert diff < 5


@pytest.mark.requires_api("get_time_offsets")
def test_get_time_offsets() -> None:
ctx = krb5.init_context()

sec, usec = krb5.get_time_offsets(ctx)
assert sec == 0
assert usec == 0

krb5.set_real_time(ctx, int(time.time()) + 100, 0)
sec, usec = krb5.get_time_offsets(ctx)
assert sec > 95
assert sec < 105

krb5.set_real_time(ctx, int(time.time()), -1)
sec, usec = krb5.get_time_offsets(ctx)
assert sec > -5
assert sec < 5


@pytest.mark.requires_api("init_secure_context")
def test_init_secure_context() -> None:
context = krb5.init_secure_context()
Expand Down

0 comments on commit 1d772b0

Please sign in to comment.