return gmsa_current_time(current_time_out);
}
+
+/* Set the current time. Caller to supply valid unsigned long long talloc pointer and manage lifetime */
+bool dsdb_gmsa_set_current_time(struct ldb_context *ldb, unsigned long long *current_time_talloc)
+{
+ int ret = ldb_set_opaque(ldb, DSDB_GMSA_TIME_OPAQUE, current_time_talloc);
+ if (ret != LDB_SUCCESS) {
+
+ return false;
+ }
+ return true;
+}
ret = ENOMEM;
goto out;
}
+ p->current_nttime = *kdc_db_ctx->current_nttime_ull;
talloc_set_destructor(p, samba_kdc_entry_destructor);
enum ndr_err_code ndr_err;
int ret;
unsigned int i;
- struct timeval tv;
- NTTIME an_hour_ago;
+ NTTIME now = *kdc_db_ctx->current_nttime_ull;
+ NTTIME an_hour_ago, an_hour;
bool prefer_current = false;
bool force_rc4 = lpcfg_kdc_force_enable_rc4_weak_session_keys(lp_ctx);
uint32_t supported_enctypes = ENC_RC4_HMAC_MD5;
p->kdc_db_ctx = kdc_db_ctx;
p->realm_dn = realm_dn;
p->supported_enctypes = pa_supported_enctypes;
+ p->current_nttime = *kdc_db_ctx->current_nttime_ull;
talloc_set_destructor(p, samba_kdc_entry_destructor);
/*
* Windows prefers the previous key for one hour.
*/
- tv = timeval_current();
- if (tv.tv_sec > 3600) {
- tv.tv_sec -= 3600;
+
+ an_hour = INT64_C(1000) * 1000 * 10 * 3600;
+
+ /*
+ * While a 'now' value of 0 is implausible, avoid this being a
+ * silly value in that case
+ */
+ if (now > an_hour) {
+ an_hour_ago = now - an_hour;
+ } else {
+ an_hour_ago = now;
}
- an_hour_ago = timeval_to_nttime(&tv);
/* first work out the current kvno */
current_kvno = 0;
int ldb_ret;
struct ldb_message *msg = NULL;
struct samba_kdc_db_context *kdc_db_ctx = NULL;
+ bool time_ok;
+
/* The idea here is very simple. Using Kerberos to
* authenticate the KDC to the LDAP server is highly likely to
* be circular.
kdc_db_ctx->lp_ctx = base_ctx->lp_ctx;
kdc_db_ctx->msg_ctx = base_ctx->msg_ctx;
+ /* Copy over the pointer that will be updated with the time */
+ kdc_db_ctx->current_nttime_ull = base_ctx->current_nttime_ull;
+
/* get default kdc policy */
lpcfg_default_kdc_policy(mem_ctx,
base_ctx->lp_ctx,
}
}
+ /*
+ * Set the current time pointer, which will be updated before
+ * each packet (Heimdal) or fetch call (MIT)
+ */
+ time_ok = dsdb_gmsa_set_current_time(kdc_db_ctx->samdb, kdc_db_ctx->current_nttime_ull);
+ if (!time_ok) {
+ talloc_free(kdc_db_ctx);
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
/* Find out our own krbtgt kvno */
ldb_ret = samdb_rodc(kdc_db_ctx->samdb, &kdc_db_ctx->rodc);
if (ldb_ret != LDB_SUCCESS) {
struct sockaddr_storage ss;
krb5_data k5_reply;
krb5_kdc_configuration *kdc_config = kdc->private_data;
+ struct timespec now_timespec = timespec_current();
+ struct timeval now_timeval = convert_timespec_to_timeval(now_timespec);
krb5_data_zero(&k5_reply);
- krb5_kdc_update_time(NULL);
+ krb5_kdc_update_time(&now_timeval);
+
+ /* This sets the time into the DSDB opaque */
+ *kdc->base_ctx->current_nttime_ull = full_timespec_to_nt_time(&now_timespec);
ret = tsocket_address_bsd_sockaddr(peer_addr, (struct sockaddr *) &ss,
sizeof(struct sockaddr_storage));
kdc->base_ctx->lp_ctx = task->lp_ctx;
kdc->base_ctx->msg_ctx = task->msg_ctx;
+ kdc->base_ctx->current_nttime_ull = talloc_zero(kdc, unsigned long long);
+ if (kdc->base_ctx->current_nttime_ull == NULL) {
+ task_server_terminate(task, "kdc: out of memory creating time variable", true);
+ return;
+ }
+
status = hdb_samba4_create_kdc(kdc->base_ctx,
kdc->smb_krb5_context->krb5_context,
&kdc_config->db[0],
#include "db-glue.h"
#include "sdb.h"
#include "mit_kdc_irpc.h"
+#include "lib/crypto/gmsa.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_KERBEROS
struct sdb_keys skeys;
unsigned int i;
const uint8_t *d = NULL;
+ NTTIME now;
+ bool time_ok;
+
+ time_ok = gmsa_current_time(&now);
+ if (!time_ok) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ *mki_ctx->db_ctx->current_nttime_ull = now;
/* There is no reply to this request */
r->out.generic_reply = data_blob(NULL, 0);
base_ctx.ev_ctx = task->event_ctx;
base_ctx.lp_ctx = task->lp_ctx;
+ base_ctx.current_nttime_ull = talloc_zero(mki_ctx, unsigned long long);
+ if (base_ctx.current_nttime_ull == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
/* db-glue.h */
status = samba_kdc_setup_db_ctx(mki_ctx,
&base_ctx,
lpcfg_load_default(base_ctx.lp_ctx);
}
+ base_ctx.current_nttime_ull = talloc_zero(ctx, unsigned long long);
+ if (base_ctx.current_nttime_ull == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
status = samba_kdc_setup_db_ctx(ctx, &base_ctx, &ctx->db_ctx);
if (!NT_STATUS_IS_OK(status)) {
ret = EINVAL;
krb5_error_code ret;
uint32_t sflags = 0;
krb5_principal referral_principal = NULL;
+ NTTIME now;
+ bool time_ok;
+
+ time_ok = gmsa_current_time(&now);
+ if (!time_ok) {
+ return EINVAL;
+ }
+
+ *ctx->db_ctx->current_nttime_ull = now;
kentry = calloc(1, sizeof(krb5_db_entry));
if (kentry == NULL) {
krb5_db_entry *kentry;
krb5_error_code ret;
+ NTTIME now;
+ bool time_ok;
+
+ time_ok = gmsa_current_time(&now);
+ if (!time_ok) {
+ return EINVAL;
+ }
+
+ *ctx->db_ctx->current_nttime_ull = now;
+
kentry = malloc(sizeof(krb5_db_entry));
if (kentry == NULL) {
return ENOMEM;
krb5_db_entry *kentry;
krb5_error_code ret;
+ /* Not updating time, keep the same for the whole operation */
+
kentry = malloc(sizeof(krb5_db_entry));
if (kentry == NULL) {
return ENOMEM;
skdc_entry = talloc_get_type_abort(client->e_data,
struct samba_kdc_entry);
+ /* This sets the time into the DSDB opaque */
+ *smb_ctx->db_ctx->current_nttime_ull = skdc_entry->current_nttime;
+
if (server == NULL) {
return EINVAL;
}
talloc_get_type_abort(krbtgt->e_data,
struct samba_kdc_entry);
+ /* This sets the time into the DSDB opaque */
+ *ctx->db_ctx->current_nttime_ull = krbtgt_skdc_entry->current_nttime;
+
if (server == NULL) {
code = EINVAL;
goto done;
skdc_entry = talloc_get_type(client->e_data, struct samba_kdc_entry);
+ /* This sets the time into the DSDB opaque */
+ *ctx->db_ctx->current_nttime_ull = skdc_entry->current_nttime;
+
nt_status = samba_kdc_check_client_access(skdc_entry,
client_name,
netbios_name,
talloc_get_type_abort(server->e_data, struct samba_kdc_entry);
krb5_error_code code;
+ /* This sets the time into the DSDB opaque */
+ *ctx->db_ctx->current_nttime_ull = server_skdc_entry->current_nttime;
+
code = samba_kdc_check_s4u2proxy(ctx->context,
ctx->db_ctx,
server_skdc_entry,
TALLOC_CTX *mem_ctx = NULL;
krb5_error_code code;
+ /* This sets the time into the DSDB opaque */
+ *ctx->db_ctx->current_nttime_ull = proxy_skdc_entry->current_nttime;
+
mem_ctx = talloc_new(NULL);
if (mem_ctx == NULL) {
return ENOMEM;
talloc_get_type_abort(db_entry->e_data, struct samba_kdc_entry);
krb5_error_code code = 0;
+ /* This sets the time into the DSDB opaque */
+ *ctx->db_ctx->current_nttime_ull = p->current_nttime;
+
#ifdef DEBUG_PASSWORD
DBG_WARNING("mit_samba_kpasswd_change_password called with: %s\n", pwd);
#endif
talloc_get_type_abort(db_entry->e_data, struct samba_kdc_entry);
struct ldb_dn *domain_dn;
+ /* This sets the time into the DSDB opaque */
+ *p->kdc_db_ctx->current_nttime_ull = p->current_nttime;
+
domain_dn = ldb_get_default_basedn(p->kdc_db_ctx->samdb);
authsam_logon_success_accounting(p->kdc_db_ctx->samdb,
struct samba_kdc_entry *p =
talloc_get_type_abort(db_entry->e_data, struct samba_kdc_entry);
+ /* This sets the time into the DSDB opaque */
+ *p->kdc_db_ctx->current_nttime_ull = p->current_nttime;
+
authsam_update_bad_pwd_count(p->kdc_db_ctx->samdb,
p->msg,
ldb_get_default_basedn(p->kdc_db_ctx->samdb));
struct samba_kdc_entry *skdc_entry =
talloc_get_type_abort(db_entry->e_data, struct samba_kdc_entry);
+ /* This sets the time into the DSDB opaque */
+ *skdc_entry->kdc_db_ctx->current_nttime_ull = skdc_entry->current_nttime;
+
return samba_princ_needs_pac(skdc_entry);
}
struct loadparm_context *lp_ctx;
struct imessaging_context *msg_ctx;
struct ldb_context *samdb;
+
+ /*
+ * If we are under Heimdal, this will be updated at each
+ * packet to be the same time as the KDC process uses and will
+ * be set into dsdb_gmsa_set_current_time() (otherwise NULL)
+ */
+ unsigned long long *current_nttime_ull;
};
struct samba_kdc_seq;
unsigned int my_krbtgt_number;
struct ldb_dn *krbtgt_dn;
struct samba_kdc_policy policy;
+ /*
+ * Copied from the base_context when this is created
+ */
+ unsigned long long *current_nttime_ull;
};
struct samba_kdc_entry {
bool claims_from_pac_are_initialized : 1;
bool claims_from_db_are_initialized : 1;
bool group_managed_service_account : 1;
+ NTTIME current_nttime;
};
extern struct hdb_method hdb_samba4_interface;
#include "libnet/libnet_export_keytab.h"
#include "kdc/db-glue.h"
#include "kdc/sdb.h"
+#include "dsdb/gmsa/util.h"
static NTSTATUS sdb_kt_copy(TALLOC_CTX *mem_ctx,
struct smb_krb5_context *smb_krb5_context,
base_ctx->ev_ctx = ctx->event_ctx;
base_ctx->lp_ctx = ctx->lp_ctx;
base_ctx->samdb = r->in.samdb;
+ if (base_ctx->samdb != NULL) {
+ base_ctx->current_nttime_ull = talloc_get_type(
+ ldb_get_opaque(base_ctx->samdb, DSDB_GMSA_TIME_OPAQUE), unsigned long long);
+ }
+
+ /*
+ * If the caller hasn't set a fixed time, or a samdb, set up
+ * the pointer for the opaque and set to the current time
+ */
+ if (base_ctx->current_nttime_ull == NULL) {
+ bool time_ok;
+ NTTIME current_nttime;
+
+ base_ctx->current_nttime_ull = talloc_zero(base_ctx, unsigned long long);
+ if (base_ctx->current_nttime_ull == NULL) {
+ r->out.error_string = NULL;
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ time_ok = gmsa_current_time(¤t_nttime);
+
+ if (!time_ok) {
+ /* This is really quite unlikely */
+ r->out.error_string
+ = talloc_asprintf(mem_ctx,
+ "Failed to get current time to check "
+ "time-dependent keys against for export");
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ *base_ctx->current_nttime_ull = current_nttime;
+ }
status = samba_kdc_setup_db_ctx(mem_ctx, base_ctx, &db_ctx);
if (!NT_STATUS_IS_OK(status)) {