s4-kdc: Move kpasswd_make_error_reply() to a helper file
authorAndreas Schneider <asn@samba.org>
Wed, 7 Sep 2016 12:47:31 +0000 (14:47 +0200)
committerJeremy Allison <jra@samba.org>
Sun, 11 Sep 2016 00:58:22 +0000 (02:58 +0200)
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source4/kdc/kpasswd-heimdal.c
source4/kdc/kpasswd-helper.c [new file with mode: 0644]
source4/kdc/kpasswd-helper.h [new file with mode: 0644]
source4/kdc/wscript_build

index 85d173008c0eedf91894406334d61b9739a22d06..af8187b4765607e58c71508f54b148aa1c3727d6 100644 (file)
 #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,
@@ -70,7 +46,7 @@ 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;
@@ -104,13 +80,13 @@ static bool kpasswd_make_pwchange_reply(struct kdc_server *kdc,
                                        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);
@@ -133,19 +109,19 @@ static bool kpasswd_make_pwchange_reply(struct kdc_server *kdc,
                        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);
 }
@@ -179,8 +155,7 @@ static bool kpasswdd_change_password(struct kdc_server *kdc,
                                               &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);
@@ -207,7 +182,7 @@ static bool kpasswd_process_request(struct kdc_server *kdc,
        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);
@@ -251,7 +226,7 @@ static bool kpasswd_process_request(struct kdc_server *kdc,
                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);
@@ -271,7 +246,7 @@ static bool kpasswd_process_request(struct kdc_server *kdc,
                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);
@@ -283,7 +258,7 @@ static bool kpasswd_process_request(struct kdc_server *kdc,
                                                       *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);
@@ -291,7 +266,7 @@ static bool kpasswd_process_request(struct kdc_server *kdc,
                        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);
@@ -312,7 +287,7 @@ static bool kpasswd_process_request(struct kdc_server *kdc,
 
                        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);
@@ -320,7 +295,7 @@ static bool kpasswd_process_request(struct kdc_server *kdc,
                } 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);
@@ -331,7 +306,7 @@ static bool kpasswd_process_request(struct kdc_server *kdc,
                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);
@@ -399,7 +374,7 @@ static bool kpasswd_process_request(struct kdc_server *kdc,
                                                   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",
diff --git a/source4/kdc/kpasswd-helper.c b/source4/kdc/kpasswd-helper.c
new file mode 100644 (file)
index 0000000..31195d9
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+   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;
+}
diff --git a/source4/kdc/kpasswd-helper.h b/source4/kdc/kpasswd-helper.h
new file mode 100644 (file)
index 0000000..74a508c
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Samba kpasswd implementation
+
+   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/>.
+*/
+
+#ifndef _KPASSWD_HELPER_H
+#define _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);
+
+#endif /* _KPASSWD_HELPER_H */
index 230118cdd600bbac78c26c52c3e1f6372d0ee6bd..170cc349927200167c26d14aebed61f06bff4b2e 100755 (executable)
@@ -7,7 +7,7 @@ else:
     kdc_include = getattr(bld.env, "CPPPATH_KDC")
 
 bld.SAMBA_MODULE('service_kdc',
-                 source='kdc-heimdal.c kpasswd-heimdal.c',
+                 source='kdc-heimdal.c kpasswd-helper.c kpasswd-heimdal.c',
                  subsystem='service',
                  init_function='server_service_kdc_init',
                  deps='''