#include "kdc/kdc-glue.h"
#include "dsdb/common/util.h"
#include "kdc/kpasswd_glue.h"
-
-/* Return true if there is a valid error packet formed in the error_blob */
-static bool kpasswdd_make_error_reply(struct kdc_server *kdc,
- TALLOC_CTX *mem_ctx,
- uint16_t result_code,
- const char *error_string,
- DATA_BLOB *error_blob)
-{
- char *error_string_utf8;
- size_t len;
-
- DEBUG(result_code ? 3 : 10, ("kpasswdd: %s\n", error_string));
-
- if (!push_utf8_talloc(mem_ctx, &error_string_utf8, error_string, &len)) {
- return false;
- }
-
- *error_blob = data_blob_talloc(mem_ctx, NULL, 2 + len + 1);
- if (!error_blob->data) {
- return false;
- }
- RSSVAL(error_blob->data, 0, result_code);
- memcpy(error_blob->data + 2, error_string_utf8, len + 1);
- return true;
-}
+#include "kdc/kpasswd-helper.h"
/* Return true if there is a valid error packet formed in the error_blob */
static bool kpasswdd_make_unauth_error_reply(struct kdc_server *kdc,
int kret;
DATA_BLOB error_bytes;
krb5_data k5_error_bytes, k5_error_blob;
- ret = kpasswdd_make_error_reply(kdc, mem_ctx, result_code, error_string,
+ ret = kpasswd_make_error_reply(mem_ctx, result_code, error_string,
&error_bytes);
if (!ret) {
return false;
DATA_BLOB *error_blob)
{
if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
- return kpasswdd_make_error_reply(kdc, mem_ctx,
+ return kpasswd_make_error_reply(mem_ctx,
KRB5_KPASSWD_ACCESSDENIED,
"No such user when changing password",
error_blob);
}
if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
- return kpasswdd_make_error_reply(kdc, mem_ctx,
+ return kpasswd_make_error_reply(mem_ctx,
KRB5_KPASSWD_ACCESSDENIED,
"Not permitted to change password",
error_blob);
reject_string = "Password change rejected, password changes may not be permitted on this account, or the minimum password age may not have elapsed.";
break;
}
- return kpasswdd_make_error_reply(kdc, mem_ctx,
+ return kpasswd_make_error_reply(mem_ctx,
KRB5_KPASSWD_SOFTERROR,
reject_string,
error_blob);
}
if (!NT_STATUS_IS_OK(status)) {
- return kpasswdd_make_error_reply(kdc, mem_ctx,
+ return kpasswd_make_error_reply(mem_ctx,
KRB5_KPASSWD_HARDERROR,
talloc_asprintf(mem_ctx, "failed to set password: %s", nt_errstr(status)),
error_blob);
}
- return kpasswdd_make_error_reply(kdc, mem_ctx, KRB5_KPASSWD_SUCCESS,
+ return kpasswd_make_error_reply(mem_ctx, KRB5_KPASSWD_SUCCESS,
"Password changed",
error_blob);
}
&error_string,
&result);
if (!NT_STATUS_IS_OK(status)) {
- return kpasswdd_make_error_reply(kdc,
- mem_ctx,
+ return kpasswd_make_error_reply(mem_ctx,
KRB5_KPASSWD_ACCESSDENIED,
error_string,
reply);
if (!NT_STATUS_IS_OK(gensec_session_info(gensec_security,
mem_ctx,
&session_info))) {
- return kpasswdd_make_error_reply(kdc, mem_ctx,
+ return kpasswd_make_error_reply(mem_ctx,
KRB5_KPASSWD_HARDERROR,
"gensec_session_info failed!",
reply);
ret = decode_ChangePasswdDataMS(input->data, input->length,
&chpw, &len);
if (ret) {
- return kpasswdd_make_error_reply(kdc, mem_ctx,
+ return kpasswd_make_error_reply(mem_ctx,
KRB5_KPASSWD_MALFORMED,
"failed to decode password change structure",
reply);
if ((chpw.targname && !chpw.targrealm)
|| (!chpw.targname && chpw.targrealm)) {
free_ChangePasswdDataMS(&chpw);
- return kpasswdd_make_error_reply(kdc, mem_ctx,
+ return kpasswd_make_error_reply(mem_ctx,
KRB5_KPASSWD_MALFORMED,
"Realm and principal must be both present, or neither present",
reply);
*chpw.targrealm, 0);
if (ret) {
free_ChangePasswdDataMS(&chpw);
- return kpasswdd_make_error_reply(kdc, mem_ctx,
+ return kpasswd_make_error_reply(mem_ctx,
KRB5_KPASSWD_MALFORMED,
"failed to get principal",
reply);
if (copy_PrincipalName(chpw.targname, &principal->name)) {
free_ChangePasswdDataMS(&chpw);
krb5_free_principal(context, principal);
- return kpasswdd_make_error_reply(kdc, mem_ctx,
+ return kpasswd_make_error_reply(mem_ctx,
KRB5_KPASSWD_MALFORMED,
"failed to extract principal to set",
reply);
if (krb5_unparse_name_short(context, principal, &set_password_on_princ) != 0) {
krb5_free_principal(context, principal);
- return kpasswdd_make_error_reply(kdc, mem_ctx,
+ return kpasswd_make_error_reply(mem_ctx,
KRB5_KPASSWD_MALFORMED,
"krb5_unparse_name failed!",
reply);
} else {
if (krb5_unparse_name(context, principal, &set_password_on_princ) != 0) {
krb5_free_principal(context, principal);
- return kpasswdd_make_error_reply(kdc, mem_ctx,
+ return kpasswd_make_error_reply(mem_ctx,
KRB5_KPASSWD_MALFORMED,
"krb5_unparse_name failed!",
reply);
samdb = samdb_connect(mem_ctx, kdc->task->event_ctx, kdc->task->lp_ctx, session_info, 0);
if (!samdb) {
free(set_password_on_princ);
- return kpasswdd_make_error_reply(kdc, mem_ctx,
+ return kpasswd_make_error_reply(mem_ctx,
KRB5_KPASSWD_HARDERROR,
"Unable to open database!",
reply);
reply);
}
default:
- return kpasswdd_make_error_reply(kdc, mem_ctx,
+ return kpasswd_make_error_reply(mem_ctx,
KRB5_KPASSWD_BAD_VERSION,
talloc_asprintf(mem_ctx,
"Protocol version %u not supported",
--- /dev/null
+/*
+ Unix SMB/CIFS implementation.
+
+ Samba kpasswd implementation
+
+ Copyright (c) 2005 Andrew Bartlett <abartlet@samba.org>
+ Copyright (c) 2016 Andreas Schneider <asn@samba.org>
+
+ 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/>.
+*/
+
+#include "includes.h"
+#include "system/kerberos.h"
+#include "kdc/kpasswd-helper.h"
+
+bool kpasswd_make_error_reply(TALLOC_CTX *mem_ctx,
+ krb5_error_code error_code,
+ const char *error_string,
+ DATA_BLOB *error_data)
+{
+ bool ok;
+ char *s;
+ size_t slen;
+
+ if (error_code == 0) {
+ DBG_DEBUG("kpasswd reply - %s\n", error_string);
+ } else {
+ DBG_INFO("kpasswd reply - %s\n", error_string);
+ }
+
+ ok = push_utf8_talloc(mem_ctx, &s, error_string, &slen);
+ if (!ok) {
+ return false;
+ }
+
+ /*
+ * The string 's' has two terminating nul-bytes which are also
+ * reflected by 'slen'. Normally Kerberos doesn't expect that strings
+ * are nul-terminated, but Heimdal does!
+ */
+#ifndef SAMBA4_USES_HEIMDAL
+ if (slen < 2) {
+ return false;
+ }
+ slen -= 2;
+#endif
+ if (2 + slen < slen) {
+ return false;
+ }
+ error_data->length = 2 + slen;
+ error_data->data = talloc_size(mem_ctx, error_data->length);
+ if (error_data->data == NULL) {
+ talloc_free(s);
+ return false;
+ }
+
+ RSSVAL(error_data->data, 0, error_code);
+ memcpy(error_data->data + 2, s, slen);
+
+ talloc_free(s);
+
+ return true;
+}