summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Schneider <asn@samba.org>2015-07-30 14:46:48 +0200
committerAndrew Bartlett <abartlet@samba.org>2016-03-17 04:32:28 +0100
commit909e7f9ff609291064af4667271b5abe2aaeceb9 (patch)
treeccd6d6a57b7a264b588038cfe0d1c817309a0edb
parent77cec013c317b331e366ea9294c6fa7bad891226 (diff)
downloadsamba-909e7f9ff609291064af4667271b5abe2aaeceb9.tar.gz
mit_samba: Add function to change the password
Signed-off-by: Andreas Schneider <asn@samba.org> Reviewed-by: Sumit Bose <sbose@redhat.com> Reviewed-by: Guenther Deschner <gd@samba.org> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
-rw-r--r--source4/kdc/mit_samba.c164
-rw-r--r--source4/kdc/mit_samba.h4
-rwxr-xr-xsource4/kdc/wscript_build1
3 files changed, 169 insertions, 0 deletions
diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c
index 6abb7330a9a..0f5e1a68cd1 100644
--- a/source4/kdc/mit_samba.c
+++ b/source4/kdc/mit_samba.c
@@ -24,12 +24,15 @@
#include "dsdb/samdb/samdb.h"
#include "system/kerberos.h"
#include <kdb.h>
+#include <kadm5/kadm_err.h>
#include "kdc/sdb.h"
#include "kdc/sdb_kdb.h"
#include "auth/kerberos/kerberos.h"
#include "kdc/samba_kdc.h"
#include "kdc/pac-glue.h"
#include "kdc/db-glue.h"
+#include "auth/auth.h"
+#include "kdc/kpasswd_glue.h"
#include "mit_samba.h"
@@ -475,3 +478,164 @@ int mit_samba_check_s4u2proxy(struct mit_samba_context *ctx,
return ret;
#endif
}
+
+static krb5_error_code mit_samba_change_pwd_error(krb5_context context,
+ NTSTATUS result,
+ enum samPwdChangeReason reject_reason,
+ struct samr_DomInfo1 *dominfo)
+{
+ krb5_error_code code = KADM5_PASS_Q_GENERIC;
+
+ if (NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_USER)) {
+ code = KADM5_BAD_PRINCIPAL;
+ krb5_set_error_message(context,
+ code,
+ "No such user when changing password");
+ }
+ if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
+ code = KADM5_PASS_Q_GENERIC;
+ krb5_set_error_message(context,
+ code,
+ "Not permitted to change password");
+ }
+ if (NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_RESTRICTION) &&
+ dominfo != NULL) {
+ switch (reject_reason) {
+ case SAM_PWD_CHANGE_PASSWORD_TOO_SHORT:
+ code = KADM5_PASS_Q_TOOSHORT;
+ krb5_set_error_message(context,
+ code,
+ "Password too short, password "
+ "must be at least %d characters "
+ "long.",
+ dominfo->min_password_length);
+ break;
+ case SAM_PWD_CHANGE_NOT_COMPLEX:
+ code = KADM5_PASS_Q_DICT;
+ krb5_set_error_message(context,
+ code,
+ "Password does not meet "
+ "complexity requirements");
+ break;
+ case SAM_PWD_CHANGE_PWD_IN_HISTORY:
+ code = KADM5_PASS_TOOSOON;
+ krb5_set_error_message(context,
+ code,
+ "Password is already in password "
+ "history. New password must not "
+ "match any of your %d previous "
+ "passwords.",
+ dominfo->password_history_length);
+ break;
+ default:
+ code = KADM5_PASS_Q_GENERIC;
+ krb5_set_error_message(context,
+ code,
+ "Password change rejected, "
+ "password changes may not be "
+ "permitted on this account, or "
+ "the minimum password age may "
+ "not have elapsed.");
+ break;
+ }
+ }
+
+ return code;
+}
+
+int mit_samba_kpasswd_change_password(struct mit_samba_context *ctx,
+ char *pwd,
+ krb5_db_entry *db_entry)
+{
+ NTSTATUS status;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ TALLOC_CTX *tmp_ctx;
+ DATA_BLOB password;
+ enum samPwdChangeReason reject_reason;
+ struct samr_DomInfo1 *dominfo;
+ const char *error_string = NULL;
+ struct auth_user_info_dc *user_info_dc;
+ struct samba_kdc_entry *p;
+ krb5_error_code code = 0;
+
+#ifdef DEBUG_PASSWORD
+ DEBUG(1,("mit_samba_kpasswd_change_password called with: %s\n", pwd));
+#endif
+
+ tmp_ctx = talloc_named(ctx, 0, "mit_samba_kpasswd_change_password");
+ if (tmp_ctx == NULL) {
+ return ENOMEM;
+ }
+
+ p = (struct samba_kdc_entry *)db_entry->e_data;
+
+ status = authsam_make_user_info_dc(tmp_ctx,
+ ctx->db_ctx->samdb,
+ lpcfg_netbios_name(ctx->db_ctx->lp_ctx),
+ lpcfg_sam_name(ctx->db_ctx->lp_ctx),
+ p->realm_dn,
+ p->msg,
+ data_blob(NULL, 0),
+ data_blob(NULL, 0),
+ &user_info_dc);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1,("authsam_make_user_info_dc failed: %s\n",
+ nt_errstr(status)));
+ talloc_free(tmp_ctx);
+ return EINVAL;
+ }
+
+ status = auth_generate_session_info(tmp_ctx,
+ ctx->db_ctx->lp_ctx,
+ ctx->db_ctx->samdb,
+ user_info_dc,
+ 0, /* session_info_flags */
+ &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;
+ }
+
+ /* 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;
+ }
+
+ status = samdb_kpasswd_change_password(tmp_ctx,
+ ctx->db_ctx->lp_ctx,
+ ctx->db_ctx->ev_ctx,
+ ctx->db_ctx->samdb,
+ ctx->session_info,
+ &password,
+ &reject_reason,
+ &dominfo,
+ &error_string,
+ &result);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1,("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;
+ }
+
+ if (!NT_STATUS_IS_OK(result)) {
+ code = mit_samba_change_pwd_error(ctx->context,
+ result,
+ reject_reason,
+ dominfo);
+ }
+
+out:
+ talloc_free(tmp_ctx);
+
+ return code;
+}
diff --git a/source4/kdc/mit_samba.h b/source4/kdc/mit_samba.h
index 022d8c7364d..b7fd1606239 100644
--- a/source4/kdc/mit_samba.h
+++ b/source4/kdc/mit_samba.h
@@ -71,4 +71,8 @@ int mit_samba_check_s4u2proxy(struct mit_samba_context *ctx,
const char *target_name,
bool is_nt_enterprise_name);
+int mit_samba_kpasswd_change_password(struct mit_samba_context *ctx,
+ char *pwd,
+ krb5_db_entry *db_entry);
+
#endif /* _MIT_SAMBA_H */
diff --git a/source4/kdc/wscript_build b/source4/kdc/wscript_build
index f6779247bf6..89e4fd293d5 100755
--- a/source4/kdc/wscript_build
+++ b/source4/kdc/wscript_build
@@ -114,6 +114,7 @@ bld.SAMBA_SUBSYSTEM('MIT_SAMBA',
samba-credentials
db-glue
PAC_GLUE
+ KPASSWD_GLUE
samba-hostconfig
com_err
sdb_kdb