s4-smbtorture: skip wbcChangeUserPassword test when no oldpass is set in environment.
[kamenim/samba.git] / nsswitch / libwbclient / tests / wbclient.c
index 7047e0905530dbf1ad0fe93e6c49ac405c215ad5..e2b3794d06f97381c49b1abccd2ddd894eb8b84d 100644 (file)
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#include "includes.h"
+#include "lib/replace/replace.h"
+#include "libcli/util/ntstatus.h"
+#include "libcli/util/werror.h"
+#include "lib/util/data_blob.h"
+#include "lib/util/time.h"
 #include "nsswitch/libwbclient/wbclient.h"
 #include "nsswitch/libwbclient/wbc_async.h"
 #include "torture/smbtorture.h"
 #include "torture/winbind/proto.h"
 #include "lib/util/util_net.h"
+#include "lib/util/charset/charset.h"
+#include "libcli/auth/libcli_auth.h"
+#include "source4/param/param.h"
+#include "lib/util/util.h"
+#include "lib/crypto/arcfour.h"
 
 #define WBC_ERROR_EQUAL(x,y) (x == y)
 
@@ -529,21 +538,22 @@ static bool test_wbc_get_sidaliases(struct torture_context *tctx)
        return true;
 }
 
-static bool test_wbc_authenticate_user(struct torture_context *tctx)
+static bool test_wbc_authenticate_user_int(struct torture_context *tctx,
+                                          const char *correct_password)
 {
        struct wbcAuthUserParams params;
        struct wbcAuthUserInfo *info = NULL;
        struct wbcAuthErrorInfo *error = NULL;
        wbcErr ret;
 
-       ret = wbcAuthenticateUser(getenv("USERNAME"), getenv("PASSWORD"));
+       ret = wbcAuthenticateUser(getenv("USERNAME"), correct_password);
        torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
                                 "wbcAuthenticateUser failed");
 
        ZERO_STRUCT(params);
        params.account_name             = getenv("USERNAME");
        params.level                    = WBC_AUTH_USER_LEVEL_PLAIN;
-       params.password.plaintext       = getenv("PASSWORD");
+       params.password.plaintext       = correct_password;
 
        ret = wbcAuthenticateUserEx(&params, &info, &error);
        torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
@@ -568,6 +578,98 @@ static bool test_wbc_authenticate_user(struct torture_context *tctx)
        return true;
 }
 
+static bool test_wbc_authenticate_user(struct torture_context *tctx)
+{
+       return test_wbc_authenticate_user_int(tctx, getenv("PASSWORD"));
+}
+
+static bool test_wbc_change_password(struct torture_context *tctx)
+{
+       wbcErr ret;
+       const char *oldpass = getenv("PASSWORD");
+       const char *newpass = "Koo8irei";
+
+       struct samr_CryptPassword new_nt_password;
+       struct samr_CryptPassword new_lm_password;
+       struct samr_Password old_nt_hash_enc;
+       struct samr_Password old_lanman_hash_enc;
+
+       uint8_t old_nt_hash[16];
+       uint8_t old_lanman_hash[16];
+       uint8_t new_nt_hash[16];
+       uint8_t new_lanman_hash[16];
+
+       struct wbcChangePasswordParams params;
+
+       if (oldpass == NULL) {
+               torture_skip(tctx,
+                       "skipping wbcChangeUserPassword test as old password cannot be retrieved\n");
+       }
+
+       ZERO_STRUCT(params);
+
+       E_md4hash(oldpass, old_nt_hash);
+       E_md4hash(newpass, new_nt_hash);
+
+       if (lp_client_lanman_auth(tctx->lp_ctx) &&
+           E_deshash(newpass, new_lanman_hash) &&
+           E_deshash(oldpass, old_lanman_hash)) {
+
+               /* E_deshash returns false for 'long' passwords (> 14
+                  DOS chars).  This allows us to match Win2k, which
+                  does not store a LM hash for these passwords (which
+                  would reduce the effective password length to 14) */
+
+               encode_pw_buffer(new_lm_password.data, newpass, STR_UNICODE);
+               arcfour_crypt(new_lm_password.data, old_nt_hash, 516);
+               E_old_pw_hash(new_nt_hash, old_lanman_hash,
+                             old_lanman_hash_enc.hash);
+
+               params.old_password.response.old_lm_hash_enc_length =
+                       sizeof(old_lanman_hash_enc.hash);
+               params.old_password.response.old_lm_hash_enc_data =
+                       old_lanman_hash_enc.hash;
+               params.new_password.response.lm_length =
+                       sizeof(new_lm_password.data);
+               params.new_password.response.lm_data =
+                       new_lm_password.data;
+       } else {
+               ZERO_STRUCT(new_lm_password);
+               ZERO_STRUCT(old_lanman_hash_enc);
+       }
+
+       encode_pw_buffer(new_nt_password.data, newpass, STR_UNICODE);
+
+       arcfour_crypt(new_nt_password.data, old_nt_hash, 516);
+       E_old_pw_hash(new_nt_hash, old_nt_hash, old_nt_hash_enc.hash);
+
+       params.old_password.response.old_nt_hash_enc_length =
+               sizeof(old_nt_hash_enc.hash);
+       params.old_password.response.old_nt_hash_enc_data =
+               old_nt_hash_enc.hash;
+       params.new_password.response.nt_length = sizeof(new_nt_password.data);
+       params.new_password.response.nt_data = new_nt_password.data;
+
+       params.level = WBC_CHANGE_PASSWORD_LEVEL_RESPONSE;
+       params.account_name = getenv("USERNAME");
+       params.domain_name = "SAMBA-TEST";
+
+       ret = wbcChangeUserPasswordEx(&params, NULL, NULL, NULL);
+       torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
+                                "wbcChangeUserPassword failed");
+
+       if (!test_wbc_authenticate_user_int(tctx, "Koo8irei")) {
+               return false;
+       }
+
+       ret = wbcChangeUserPassword(getenv("USERNAME"), "Koo8irei",
+                                   getenv("PASSWORD"));
+       torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
+                                "wbcChangeUserPassword failed");
+
+       return test_wbc_authenticate_user_int(tctx, getenv("PASSWORD"));
+}
+
 static bool test_wbc_logon_user(struct torture_context *tctx)
 {
        struct wbcLogonUserParams params;
@@ -662,6 +764,19 @@ static bool test_wbc_logon_user(struct torture_context *tctx)
        return true;
 }
 
+static bool test_wbc_getgroups(struct torture_context *tctx)
+{
+       wbcErr ret;
+       uint32_t num_groups;
+       gid_t *groups;
+
+       ret = wbcGetGroups(getenv("USERNAME"), &num_groups, &groups);
+       torture_assert_wbc_equal(tctx, ret, WBC_ERR_SUCCESS,
+                                "wbcGetGroups failed");
+       wbcFreeMemory(groups);
+       return true;
+}
+
 struct torture_suite *torture_wbclient(void)
 {
        struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "WBCLIENT");
@@ -691,6 +806,10 @@ struct torture_suite *torture_wbclient(void)
                                      test_wbc_authenticate_user);
        torture_suite_add_simple_test(suite, "wbcLogonUser",
                                      test_wbc_logon_user);
+       torture_suite_add_simple_test(suite, "wbcChangeUserPassword",
+                                     test_wbc_change_password);
+       torture_suite_add_simple_test(suite, "wbcGetGroups",
+                                     test_wbc_getgroups);
 
        return suite;
 }