#include "param/param.h"
#include "dsdb/samdb/samdb.h"
#include "system/kerberos.h"
+#include "lib/replace/system/filesys.h"
#include <com_err.h>
#include <kdb.h>
#include <kadm5/kadm_err.h>
void mit_samba_context_free(struct mit_samba_context *ctx)
{
- /* free heimdal's krb5_context */
+ /* free MIT's krb5_context */
if (ctx->context) {
krb5_free_context(ctx->context);
}
}
/*
- * Implemant a callback to log to the MIT KDC log facility
+ * Implement a callback to log to the MIT KDC log facility
*
* http://web.mit.edu/kerberos/krb5-devel/doc/plugindev/general.html#logging-from-kdc-and-kadmind-plugin-modules
*/
is_error = 0;
}
- com_err("", is_error, "%s", msg);
+ com_err("mitkdc", is_error, "%s", msg);
}
-int mit_samba_context_init(struct mit_samba_context **_ctx)
+krb5_error_code mit_samba_context_init(struct mit_samba_context **_ctx)
{
NTSTATUS status;
struct mit_samba_context *ctx;
const char *s4_conf_file;
- int ret;
- struct samba_kdc_base_context base_ctx;
+ krb5_error_code ret;
+ struct samba_kdc_base_context base_ctx = {};
ctx = talloc_zero(NULL, struct mit_samba_context);
if (!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;
goto done;
}
- /* init heimdal's krb_context and log facilities */
+ /* init MIT's krb_context and log facilities */
ret = smb_krb5_init_context_basic(ctx,
ctx->db_ctx->lp_ctx,
&ctx->context);
return ret;
}
-static krb5_error_code ks_is_tgs_principal(struct mit_samba_context *ctx,
- krb5_const_principal principal)
-{
- char *p;
- int eq = -1;
-
- p = smb_krb5_principal_get_comp_string(ctx, ctx->context, principal, 0);
-
- eq = krb5_princ_size(ctx->context, principal) == 2 &&
- (strcmp(p, KRB5_TGS_NAME) == 0);
-
- talloc_free(p);
-
- return eq;
-}
-
int mit_samba_generate_salt(krb5_data *salt)
{
if (salt == NULL) {
{
TALLOC_CTX *tmp_ctx;
char *password;
+ char *data = NULL;
+ const unsigned length = 24;
if (pwd == NULL) {
return EINVAL;
}
- pwd->length = 24;
tmp_ctx = talloc_named(NULL,
0,
- "mit_samba_create_principal_password context");
+ "mit_samba_generate_random_password context");
if (tmp_ctx == NULL) {
return ENOMEM;
}
- password = generate_random_password(tmp_ctx, pwd->length, pwd->length);
+ password = generate_random_password(tmp_ctx, length, length);
if (password == NULL) {
talloc_free(tmp_ctx);
return ENOMEM;
}
- pwd->data = strdup(password);
+ data = strdup(password);
talloc_free(tmp_ctx);
- if (pwd->data == NULL) {
+ if (data == NULL) {
return ENOMEM;
}
+ *pwd = smb_krb5_make_data(data, length);
+
return 0;
}
-int mit_samba_get_principal(struct mit_samba_context *ctx,
- krb5_const_principal principal,
- unsigned int kflags,
- krb5_db_entry **_kentry)
+krb5_error_code mit_samba_get_principal(struct mit_samba_context *ctx,
+ krb5_const_principal principal,
+ unsigned int kflags,
+ krb5_db_entry **_kentry)
{
struct sdb_entry sentry = {};
krb5_db_entry *kentry;
- int ret;
+ 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) {
return ENOMEM;
}
-#if KRB5_KDB_API_VERSION >= 10
/*
* The MIT KDC code that wants the canonical name in all lookups, and
* takes care to canonicalize only when appropriate.
*/
sflags |= SDB_F_FORCE_CANON;
-#endif
-#if KRB5_KDB_DAL_MAJOR_VERSION >= 9
if (kflags & KRB5_KDB_FLAG_REFERRAL_OK) {
sflags |= SDB_F_CANON;
}
sflags |= SDB_F_FOR_TGS_REQ;
}
}
-#else /* KRB5_KDB_DAL_MAJOR_VERSION < 9 */
- if (kflags & KRB5_KDB_FLAG_CANONICALIZE) {
- sflags |= SDB_F_CANON;
- }
- if (kflags & (KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY |
- KRB5_KDB_FLAG_INCLUDE_PAC)) {
- /*
- * KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY is equal to
- * SDB_F_FOR_AS_REQ
- *
- * We use ANY to also allow AS_REQ for service principal names
- * This is supported by Windows.
- */
- sflags |= SDB_F_GET_ANY|SDB_F_FOR_AS_REQ;
- } else {
- int equal = smb_krb5_principal_is_tgs(ctx->context, principal);
- if (equal == -1) {
- return ENOMEM;
- }
-
- if (equal) {
- sflags |= SDB_F_GET_KRBTGT;
- } else {
- sflags |= SDB_F_GET_SERVER|SDB_F_FOR_TGS_REQ;
- }
- }
-#endif /* KRB5_KDB_DAL_MAJOR_VERSION */
/* always set this or the created_by data will not be populated by samba's
* backend and we will fail to parse the entry later */
*
* ADDOM.SAMBA.EXAMPLE.COM
*
- * We look up if we have and entry in the database and get an
- * entry with the pricipal:
+ * We look up if we have an entry in the database and get an
+ * entry with the principal:
*
* cifs/dc7.SAMBA2008R2.EXAMPLE.COM@SAMBA2008R2.EXAMPLE.COM
*
* and the error: SDB_ERR_WRONG_REALM.
*
* In the case of a TGS-REQ we need to return a referral ticket
- * fo the next trust hop to the client. This ticket will have
+ * for the next trust hop to the client. This ticket will have
* the following principal:
*
* krbtgt/SAMBA2008R2.EXAMPLE.COM@ADDOM.SAMBA.EXAMPLE.COM
return ret;
}
-int mit_samba_get_firstkey(struct mit_samba_context *ctx,
- krb5_db_entry **_kentry)
+krb5_error_code mit_samba_get_firstkey(struct mit_samba_context *ctx,
+ krb5_db_entry **_kentry)
{
struct sdb_entry sentry = {};
krb5_db_entry *kentry;
- int ret;
+ 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;
}
- ret = samba_kdc_firstkey(ctx->context, ctx->db_ctx, &sentry);
+ ret = samba_kdc_firstkey(ctx->context, ctx->db_ctx, SDB_F_ADMIN_DATA, &sentry);
switch (ret) {
case 0:
break;
return ret;
}
-int mit_samba_get_nextkey(struct mit_samba_context *ctx,
- krb5_db_entry **_kentry)
+krb5_error_code mit_samba_get_nextkey(struct mit_samba_context *ctx,
+ krb5_db_entry **_kentry)
{
struct sdb_entry sentry = {};
krb5_db_entry *kentry;
- int ret;
+ 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;
}
- ret = samba_kdc_nextkey(ctx->context, ctx->db_ctx, &sentry);
+ ret = samba_kdc_nextkey(ctx->context, ctx->db_ctx, SDB_F_ADMIN_DATA, &sentry);
switch (ret) {
case 0:
break;
return ret;
}
-int mit_samba_get_pac(struct mit_samba_context *smb_ctx,
- krb5_context context,
- uint32_t flags,
- krb5_db_entry *client,
- krb5_db_entry *server,
- krb5_keyblock *replaced_reply_key,
- krb5_pac *pac)
+krb5_error_code mit_samba_get_pac(struct mit_samba_context *smb_ctx,
+ krb5_context context,
+ uint32_t flags,
+ krb5_db_entry *client,
+ krb5_db_entry *server,
+ krb5_keyblock *replaced_reply_key,
+ krb5_pac *pac)
{
TALLOC_CTX *tmp_ctx;
+ const struct auth_user_info_dc *user_info_dc = NULL;
+ struct auth_user_info_dc *user_info_dc_shallow_copy = NULL;
DATA_BLOB *logon_info_blob = NULL;
DATA_BLOB *upn_dns_info_blob = NULL;
DATA_BLOB *cred_ndr = NULL;
DATA_BLOB *pcred_blob = NULL;
DATA_BLOB *pac_attrs_blob = NULL;
DATA_BLOB *requester_sid_blob = NULL;
+ const DATA_BLOB *client_claims_blob = NULL;
NTSTATUS nt_status;
krb5_error_code code;
struct samba_kdc_entry *skdc_entry;
+ struct samba_kdc_entry *server_entry = NULL;
bool is_krbtgt;
+ /* Only include resource groups in a service ticket. */
+ enum auth_group_inclusion group_inclusion;
enum samba_asserted_identity asserted_identity =
(flags & KRB5_KDB_FLAG_PROTOCOL_TRANSITION) ?
SAMBA_ASSERTED_IDENTITY_SERVICE :
SAMBA_ASSERTED_IDENTITY_AUTHENTICATION_AUTHORITY;
+ if (client == NULL) {
+ return EINVAL;
+ }
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;
+ }
+ {
+ int result = smb_krb5_principal_is_tgs(smb_ctx->context, server->princ);
+ if (result == -1) {
+ return ENOMEM;
+ }
+
+ is_krbtgt = result;
+ }
+ server_entry = talloc_get_type_abort(server->e_data,
+ struct samba_kdc_entry);
+
+ /* Only include resource groups in a service ticket. */
+ if (is_krbtgt) {
+ group_inclusion = AUTH_EXCLUDE_RESOURCE_GROUPS;
+ } else if (server_entry->supported_enctypes & KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED) {
+ group_inclusion = AUTH_INCLUDE_RESOURCE_GROUPS;
+ } else {
+ group_inclusion = AUTH_INCLUDE_RESOURCE_GROUPS_COMPRESSED;
+ }
+
tmp_ctx = talloc_named(smb_ctx,
0,
- "mit_samba_get_pac_data_blobs context");
+ "mit_samba_get_pac context");
if (tmp_ctx == NULL) {
return ENOMEM;
}
cred_ndr_ptr = &cred_ndr;
}
- is_krbtgt = ks_is_tgs_principal(smb_ctx, server->princ);
+ code = samba_kdc_get_user_info_from_db(tmp_ctx,
+ server_entry->kdc_db_ctx->samdb,
+ skdc_entry,
+ skdc_entry->msg,
+ &user_info_dc);
+ if (code) {
+ talloc_free(tmp_ctx);
+ return code;
+ }
+
+ /* Make a shallow copy of the user_info_dc structure. */
+ nt_status = authsam_shallow_copy_user_info_dc(tmp_ctx,
+ user_info_dc,
+ &user_info_dc_shallow_copy);
+ user_info_dc = NULL;
- nt_status = samba_kdc_get_pac_blobs(tmp_ctx,
- skdc_entry,
- asserted_identity,
- &logon_info_blob,
- cred_ndr_ptr,
- &upn_dns_info_blob,
- is_krbtgt ? &pac_attrs_blob : NULL,
- PAC_ATTRIBUTE_FLAG_PAC_WAS_GIVEN_IMPLICITLY,
- is_krbtgt ? &requester_sid_blob : NULL);
if (!NT_STATUS_IS_OK(nt_status)) {
+ DBG_ERR("Failed to allocate shallow copy of user_info_dc: %s\n",
+ nt_errstr(nt_status));
talloc_free(tmp_ctx);
- if (NT_STATUS_EQUAL(nt_status,
- NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
- return ENOENT;
+ return map_errno_from_nt_status(nt_status);
+ }
+
+
+ nt_status = samba_kdc_add_asserted_identity(asserted_identity,
+ user_info_dc_shallow_copy);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DBG_ERR("Failed to add asserted identity: %s\n",
+ nt_errstr(nt_status));
+ talloc_free(tmp_ctx);
+ return EINVAL;
+ }
+
+ nt_status = samba_kdc_add_claims_valid(user_info_dc_shallow_copy);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DBG_ERR("Failed to add Claims Valid: %s\n",
+ nt_errstr(nt_status));
+ talloc_free(tmp_ctx);
+ return EINVAL;
+ }
+
+ /* We no longer need to modify this, so assign to const variable */
+ user_info_dc = user_info_dc_shallow_copy;
+
+ nt_status = samba_kdc_get_logon_info_blob(tmp_ctx,
+ user_info_dc,
+ group_inclusion,
+ &logon_info_blob);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ talloc_free(tmp_ctx);
+ return EINVAL;
+ }
+
+ if (cred_ndr_ptr != NULL) {
+ nt_status = samba_kdc_get_cred_ndr_blob(tmp_ctx,
+ skdc_entry,
+ cred_ndr_ptr);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ talloc_free(tmp_ctx);
+ return EINVAL;
}
+ }
+
+ nt_status = samba_kdc_get_upn_info_blob(tmp_ctx,
+ user_info_dc,
+ &upn_dns_info_blob);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ talloc_free(tmp_ctx);
+ return EINVAL;
+ }
+
+ if (is_krbtgt) {
+ nt_status = samba_kdc_get_pac_attrs_blob(tmp_ctx,
+ PAC_ATTRIBUTE_FLAG_PAC_WAS_GIVEN_IMPLICITLY,
+ &pac_attrs_blob);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ talloc_free(tmp_ctx);
+ return EINVAL;
+ }
+
+ nt_status = samba_kdc_get_requester_sid_blob(tmp_ctx,
+ user_info_dc,
+ &requester_sid_blob);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ talloc_free(tmp_ctx);
+ return EINVAL;
+ }
+ }
+
+ nt_status = samba_kdc_get_claims_blob(tmp_ctx,
+ skdc_entry,
+ &client_claims_blob);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ talloc_free(tmp_ctx);
return EINVAL;
}
upn_dns_info_blob,
pac_attrs_blob,
requester_sid_blob,
- NULL,
+ NULL /* deleg_blob */,
+ client_claims_blob,
+ NULL /* device_info_blob */,
+ NULL /* device_claims_blob */,
*pac);
talloc_free(tmp_ctx);
return code;
}
-#if KRB5_KDB_DAL_MAJOR_VERSION < 9
-krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx,
- krb5_context context,
- int kdc_flags,
- krb5_const_principal client_principal,
- krb5_db_entry *client,
- krb5_db_entry *server,
- krb5_db_entry *krbtgt,
- krb5_keyblock *krbtgt_keyblock,
- krb5_pac *pac)
-{
- TALLOC_CTX *tmp_ctx;
- krb5_error_code code;
- struct samba_kdc_entry *client_skdc_entry = NULL;
- struct samba_kdc_entry *krbtgt_skdc_entry = NULL;
- struct samba_kdc_entry *server_skdc_entry = NULL;
- krb5_principal delegated_proxy_principal = NULL;
- krb5_pac new_pac = NULL;
- bool is_in_db = false;
- bool is_untrusted = false;
- uint32_t flags = SAMBA_KDC_FLAG_SKIP_PAC_BUFFER;
-
- /* Create a memory context early so code can use talloc_stackframe() */
- tmp_ctx = talloc_named(ctx, 0, "mit_samba_reget_pac context");
- if (tmp_ctx == NULL) {
- return ENOMEM;
- }
-
- if (client != NULL) {
- client_skdc_entry =
- talloc_get_type_abort(client->e_data,
- struct samba_kdc_entry);
- }
-
- if (server == NULL) {
- code = EINVAL;
- goto done;
- }
-
- server_skdc_entry =
- talloc_get_type_abort(server->e_data,
- struct samba_kdc_entry);
-
- if (krbtgt == NULL) {
- code = EINVAL;
- goto done;
- }
- krbtgt_skdc_entry =
- talloc_get_type_abort(krbtgt->e_data,
- struct samba_kdc_entry);
-
- code = samba_krbtgt_is_in_db(krbtgt_skdc_entry,
- &is_in_db,
- &is_untrusted);
- if (code != 0) {
- goto done;
- }
-
- if (is_untrusted) {
- flags |= SAMBA_KDC_FLAG_KRBTGT_IS_UNTRUSTED;
- }
-
- if (is_in_db) {
- flags |= SAMBA_KDC_FLAG_KRBTGT_IN_DB;
-
- }
-
- if (kdc_flags & KRB5_KDB_FLAG_PROTOCOL_TRANSITION) {
- flags |= SAMBA_KDC_FLAG_PROTOCOL_TRANSITION;
- }
-
- if (kdc_flags & KRB5_KDB_FLAG_CONSTRAINED_DELEGATION) {
- flags |= SAMBA_KDC_FLAG_CONSTRAINED_DELEGATION;
- delegated_proxy_principal = discard_const(client_principal);
- }
-
- /* Build an updated PAC */
- code = krb5_pac_init(context, &new_pac);
- if (code != 0) {
- goto done;
- }
-
- code = samba_kdc_update_pac(tmp_ctx,
- context,
- krbtgt_skdc_entry->kdc_db_ctx->samdb,
- flags,
- client_skdc_entry,
- server->princ,
- server_skdc_entry,
- krbtgt_skdc_entry,
- delegated_proxy_principal,
- *pac,
- new_pac);
- if (code != 0) {
- krb5_pac_free(context, new_pac);
- if (code == ENODATA) {
- krb5_pac_free(context, *pac);
- *pac = NULL;
- code = 0;
- }
- goto done;
- }
-
- /* We now replace the pac */
- krb5_pac_free(context, *pac);
- *pac = new_pac;
-
-done:
- talloc_free(tmp_ctx);
- return code;
-}
-#else
krb5_error_code mit_samba_update_pac(struct mit_samba_context *ctx,
krb5_context context,
int kdc_flags,
struct samba_kdc_entry *client_skdc_entry = NULL;
struct samba_kdc_entry *server_skdc_entry = NULL;
struct samba_kdc_entry *krbtgt_skdc_entry = NULL;
+ struct samba_kdc_entry_pac client_pac_entry = {};
bool is_in_db = false;
- bool is_untrusted = false;
- uint32_t flags = SAMBA_KDC_FLAG_SKIP_PAC_BUFFER;
+ bool is_trusted = false;
+ uint32_t flags = 0;
/* Create a memory context early so code can use talloc_stackframe() */
tmp_ctx = talloc_named(ctx, 0, "mit_samba_update_pac context");
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;
+ }
server_skdc_entry =
talloc_get_type_abort(server->e_data,
struct samba_kdc_entry);
*/
code = samba_krbtgt_is_in_db(krbtgt_skdc_entry,
&is_in_db,
- &is_untrusted);
+ &is_trusted);
if (code != 0) {
goto done;
}
- if (is_untrusted) {
- flags |= SAMBA_KDC_FLAG_KRBTGT_IS_UNTRUSTED;
- }
-
- if (is_in_db) {
- flags |= SAMBA_KDC_FLAG_KRBTGT_IN_DB;
-
+ if (kdc_flags & KRB5_KDB_FLAG_PROTOCOL_TRANSITION) {
+ flags |= SAMBA_KDC_FLAG_PROTOCOL_TRANSITION;
}
if (kdc_flags & KRB5_KDB_FLAG_CONSTRAINED_DELEGATION) {
flags |= SAMBA_KDC_FLAG_CONSTRAINED_DELEGATION;
}
+ client_pac_entry = samba_kdc_entry_pac_from_trusted(old_pac,
+ client_skdc_entry,
+ samba_kdc_entry_is_trust(krbtgt_skdc_entry),
+ is_trusted);
+
+ code = samba_kdc_verify_pac(tmp_ctx,
+ context,
+ krbtgt_skdc_entry->kdc_db_ctx->samdb,
+ flags,
+ client_pac_entry,
+ krbtgt_skdc_entry);
+ if (code != 0) {
+ goto done;
+ }
+
code = samba_kdc_update_pac(tmp_ctx,
context,
krbtgt_skdc_entry->kdc_db_ctx->samdb,
+ krbtgt_skdc_entry->kdc_db_ctx->lp_ctx,
flags,
- client_skdc_entry,
+ client_pac_entry,
server->princ,
server_skdc_entry,
- krbtgt_skdc_entry,
- NULL,
- old_pac,
- new_pac);
+ NULL /* delegated_proxy_principal */,
+ (struct samba_kdc_entry_pac) {} /* delegated_proxy */,
+ (struct samba_kdc_entry_pac) {} /* device */,
+ new_pac,
+ NULL /* server_audit_info_out */,
+ NULL /* status_out */);
if (code != 0) {
- if (code == ENODATA) {
+ if (code == ENOATTR) {
/*
* We can't tell the KDC to not issue a PAC. It will
* just return the newly allocated empty PAC.
talloc_free(tmp_ctx);
return code;
}
-#endif
/* provide header, function is exported but there are no public headers */
e_data->length = 0;
pa.magic = KV5M_PA_DATA;
- pa.pa_type = KRB5_PADATA_PW_SALT;
+ pa.pa_type = KRB5_PADATA_PW_SALT /* KERB_ERR_TYPE_EXTENDED */;
pa.length = 12;
pa.contents = malloc(pa.length);
if (!pa.contents) {
return;
}
-int mit_samba_check_client_access(struct mit_samba_context *ctx,
- krb5_db_entry *client,
- const char *client_name,
- krb5_db_entry *server,
- const char *server_name,
- const char *netbios_name,
- bool password_change,
- DATA_BLOB *e_data)
+krb5_error_code mit_samba_check_client_access(struct mit_samba_context *ctx,
+ krb5_db_entry *client,
+ const char *client_name,
+ krb5_db_entry *server,
+ const char *server_name,
+ const char *netbios_name,
+ bool password_change,
+ DATA_BLOB *e_data)
{
struct samba_kdc_entry *skdc_entry;
NTSTATUS nt_status;
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,
return 0;
}
-int mit_samba_check_s4u2proxy(struct mit_samba_context *ctx,
- const krb5_db_entry *server,
- krb5_const_principal target_principal)
+krb5_error_code mit_samba_check_s4u2proxy(struct mit_samba_context *ctx,
+ const krb5_db_entry *server,
+ krb5_const_principal target_principal)
{
-#if KRB5_KDB_DAL_MAJOR_VERSION < 9
- return KRB5KDC_ERR_BADOPTION;
-#else
struct samba_kdc_entry *server_skdc_entry =
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,
target_principal);
return code;
-#endif
}
krb5_error_code mit_samba_check_allowed_to_delegate_from(
krb5_pac header_pac,
const krb5_db_entry *proxy)
{
-#if KRB5_KDB_DAL_MAJOR_VERSION < 8
- return KRB5KDC_ERR_POLICY;
-#else
struct samba_kdc_entry *proxy_skdc_entry =
talloc_get_type_abort(proxy->e_data, struct samba_kdc_entry);
+ struct auth_user_info_dc *user_info_dc = NULL;
+ 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;
+ }
+
+ /*
+ * FIXME: If ever we support RODCs, we must check that the PAC has not
+ * been issued by an RODC (other than ourselves) — otherwise the PAC
+ * cannot be trusted. Because the plugin interface does not give us the
+ * client entry, we cannot look up its groups in the database.
+ */
+ code = kerberos_pac_to_user_info_dc(mem_ctx,
+ header_pac,
+ ctx->context,
+ &user_info_dc,
+ AUTH_INCLUDE_RESOURCE_GROUPS,
+ NULL,
+ NULL,
+ NULL);
+ if (code != 0) {
+ goto out;
+ }
+
code = samba_kdc_check_s4u2proxy_rbcd(ctx->context,
ctx->db_ctx,
client_principal,
server_principal,
- header_pac,
+ user_info_dc,
+ NULL /* device_info_dc */,
+ (struct auth_claims) {},
proxy_skdc_entry);
-
+out:
+ talloc_free(mem_ctx);
return code;
-#endif
}
static krb5_error_code mit_samba_change_pwd_error(krb5_context context,
return code;
}
-int mit_samba_kpasswd_change_password(struct mit_samba_context *ctx,
- char *pwd,
- krb5_db_entry *db_entry)
+krb5_error_code mit_samba_kpasswd_change_password(struct mit_samba_context *ctx,
+ char *pwd,
+ krb5_db_entry *db_entry)
{
NTSTATUS status;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
enum samPwdChangeReason reject_reason;
struct samr_DomInfo1 *dominfo;
const char *error_string = NULL;
- struct auth_user_info_dc *user_info_dc;
+ const struct auth_user_info_dc *user_info_dc = NULL;
struct samba_kdc_entry *p =
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
- DEBUG(1,("mit_samba_kpasswd_change_password called with: %s\n", pwd));
+ DBG_WARNING("mit_samba_kpasswd_change_password called with: %s\n", pwd);
#endif
tmp_ctx = talloc_named(ctx, 0, "mit_samba_kpasswd_change_password");
return ENOMEM;
}
- status = samba_kdc_get_user_info_from_db(p,
- p->msg,
- &user_info_dc);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1,("samba_kdc_get_user_info_from_db failed: %s\n",
- nt_errstr(status)));
- talloc_free(tmp_ctx);
- return EINVAL;
+ code = samba_kdc_get_user_info_from_db(tmp_ctx,
+ ctx->db_ctx->samdb,
+ p,
+ p->msg,
+ &user_info_dc);
+ if (code) {
+ const char *krb5err = krb5_get_error_message(ctx->context, code);
+ DBG_WARNING("samba_kdc_get_user_info_from_db failed: %s\n",
+ krb5err != NULL ? krb5err : "<unknown>");
+ krb5_free_error_message(ctx->context, krb5err);
+
+ goto out;
}
status = auth_generate_session_info(tmp_ctx,
&ctx->session_info);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1,("auth_generate_session_info failed: %s\n",
- nt_errstr(status)));
- talloc_free(tmp_ctx);
- return EINVAL;
+ DBG_WARNING("auth_generate_session_info failed: %s\n",
+ nt_errstr(status));
+ code = EINVAL;
+ goto out;
}
/* password is expected as UTF16 */
if (!convert_string_talloc(tmp_ctx, CH_UTF8, CH_UTF16,
pwd, strlen(pwd),
&password.data, &password.length)) {
- DEBUG(1,("convert_string_talloc failed\n"));
- talloc_free(tmp_ctx);
- return EINVAL;
+ DBG_WARNING("convert_string_talloc failed\n");
+ code = EINVAL;
+ goto out;
}
status = samdb_kpasswd_change_password(tmp_ctx,
&error_string,
&result);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1,("samdb_kpasswd_change_password failed: %s\n",
- nt_errstr(status)));
+ DBG_WARNING("samdb_kpasswd_change_password failed: %s\n",
+ nt_errstr(status));
code = KADM5_PASS_Q_GENERIC;
krb5_set_error_message(ctx->context, code, "%s", error_string);
goto out;
void mit_samba_zero_bad_password_count(krb5_db_entry *db_entry)
{
- struct netr_SendToSamBase *send_to_sam = NULL;
+ /* struct netr_SendToSamBase *send_to_sam = NULL; */
struct samba_kdc_entry *p =
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,
p->msg,
domain_dn,
true,
- &send_to_sam);
+ NULL, NULL);
/* TODO: RODC support */
}
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);
}