LCOV - code coverage report
Current view: top level - source4/libnet - libnet_passwd.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 294 591 49.7 %
Date: 2024-06-13 04:01:37 Functions: 14 19 73.7 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Copyright (C) Stefan Metzmacher      2004
       5             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
       6             : 
       7             :    This program is free software; you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation; either version 3 of the License, or
      10             :    (at your option) any later version.
      11             : 
      12             :    This program is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include "includes.h"
      22             : #include "libnet/libnet.h"
      23             : #include "libcli/auth/libcli_auth.h"
      24             : #include "librpc/gen_ndr/ndr_samr_c.h"
      25             : #include "source4/librpc/rpc/dcerpc.h"
      26             : #include "auth/credentials/credentials.h"
      27             : #include "libcli/smb/smb_constants.h"
      28             : #include "librpc/rpc/dcerpc_samr.h"
      29             : #include "source3/rpc_client/init_samr.h"
      30             : #include "lib/param/loadparm.h"
      31             : #include "lib/param/param.h"
      32             : 
      33             : #include "lib/crypto/gnutls_helpers.h"
      34             : #include <gnutls/gnutls.h>
      35             : #include <gnutls/crypto.h>
      36             : 
      37           2 : static NTSTATUS libnet_ChangePassword_samr_aes(TALLOC_CTX *mem_ctx,
      38             :                                                struct dcerpc_binding_handle *h,
      39             :                                                struct lsa_String *server,
      40             :                                                struct lsa_String *account,
      41             :                                                const char *old_password,
      42             :                                                const char *new_password,
      43             :                                                const char **error_string)
      44             : {
      45             : #ifdef HAVE_GNUTLS_PBKDF2
      46           2 :         struct samr_ChangePasswordUser4 r;
      47           2 :         uint8_t old_nt_key_data[16] = {0};
      48           2 :         gnutls_datum_t old_nt_key = {
      49             :                 .data = old_nt_key_data,
      50             :                 .size = sizeof(old_nt_key_data),
      51             :         };
      52           2 :         uint8_t cek_data[16] = {0};
      53           2 :         DATA_BLOB cek = {
      54             :                 .data = cek_data,
      55             :                 .length = sizeof(cek_data),
      56             :         };
      57           2 :         struct samr_EncryptedPasswordAES pwd_buf = {
      58             :                 .cipher_len = 0
      59             :         };
      60           2 :         DATA_BLOB salt = {
      61             :                 .data = pwd_buf.salt,
      62             :                 .length = sizeof(pwd_buf.salt),
      63             :         };
      64           2 :         gnutls_datum_t salt_datum = {
      65             :                 .data = pwd_buf.salt,
      66             :                 .size = sizeof(pwd_buf.salt),
      67             :         };
      68           2 :         uint64_t pbkdf2_iterations = generate_random_u64_range(5000, 1000000);
      69           2 :         NTSTATUS status;
      70           2 :         int rc;
      71             : 
      72           2 :         E_md4hash(old_password, old_nt_key_data);
      73             : 
      74           2 :         generate_nonce_buffer(salt.data, salt.length);
      75             : 
      76           4 :         rc = gnutls_pbkdf2(GNUTLS_MAC_SHA512,
      77             :                            &old_nt_key,
      78             :                            &salt_datum,
      79             :                            pbkdf2_iterations,
      80           2 :                            cek.data,
      81             :                            cek.length);
      82           2 :         BURN_DATA(old_nt_key_data);
      83           2 :         if (rc < 0) {
      84           0 :                 status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
      85           0 :                 if (!NT_STATUS_IS_OK(status)) {
      86           0 :                         goto done;
      87             :                 }
      88             :         }
      89             : 
      90           2 :         status = init_samr_CryptPasswordAES(mem_ctx,
      91             :                                             new_password,
      92             :                                             &salt,
      93             :                                             &cek,
      94             :                                             &pwd_buf);
      95           2 :         data_blob_clear(&cek);
      96           2 :         if (!NT_STATUS_IS_OK(status)) {
      97           0 :                 goto done;
      98             :         }
      99             : 
     100           2 :         pwd_buf.PBKDF2Iterations = pbkdf2_iterations;
     101             : 
     102           2 :         r.in.server = server;
     103           2 :         r.in.account = account;
     104           2 :         r.in.password = &pwd_buf;
     105             : 
     106           2 :         status = dcerpc_samr_ChangePasswordUser4_r(h, mem_ctx, &r);
     107           2 :         if (!NT_STATUS_IS_OK(status)) {
     108           0 :                 goto done;
     109             :         }
     110           2 :         if (!NT_STATUS_IS_OK(r.out.result)) {
     111           0 :                 status = r.out.result;
     112           0 :                 *error_string = talloc_asprintf(mem_ctx,
     113             :                                                 "samr_ChangePasswordUser4 for "
     114             :                                                 "'%s\\%s' failed: %s",
     115             :                                                 server->string,
     116             :                                                 account->string,
     117             :                                                 nt_errstr(status));
     118           0 :                 goto done;
     119             :         }
     120             : 
     121           2 : done:
     122           2 :         BURN_DATA(pwd_buf);
     123             : 
     124           2 :         return status;
     125             : #else /* HAVE_GNUTLS_PBKDF2 */
     126             :         return NT_STATUS_NOT_IMPLEMENTED;
     127             : #endif /* HAVE_GNUTLS_PBKDF2 */
     128             : }
     129             : 
     130          36 : static NTSTATUS libnet_ChangePassword_samr_rc4(TALLOC_CTX *mem_ctx,
     131             :                                                struct dcerpc_binding_handle *h,
     132             :                                                struct lsa_String *server,
     133             :                                                struct lsa_String *account,
     134             :                                                const char *old_password,
     135             :                                                const char *new_password,
     136             :                                                const char **error_string)
     137             : {
     138           0 :         struct samr_OemChangePasswordUser2 oe2;
     139           0 :         struct samr_ChangePasswordUser2 pw2;
     140           0 :         struct samr_ChangePasswordUser3 pw3;
     141           0 :         struct samr_CryptPassword nt_pass, lm_pass;
     142           0 :         uint8_t old_nt_hash[16], new_nt_hash[16];
     143           0 :         uint8_t old_lm_hash[16], new_lm_hash[16];
     144           0 :         struct samr_Password nt_verifier, lm_verifier;
     145           0 :         struct lsa_AsciiString a_server, a_account;
     146          36 :         gnutls_cipher_hd_t cipher_hnd = NULL;
     147          36 :         gnutls_datum_t nt_session_key = {
     148             :                 .data = old_nt_hash,
     149             :                 .size = sizeof(old_nt_hash),
     150             :         };
     151          36 :         gnutls_datum_t lm_session_key = {
     152             :                 .data = old_lm_hash,
     153             :                 .size = sizeof(old_lm_hash),
     154             :         };
     155          36 :         struct samr_DomInfo1 *dominfo = NULL;
     156          36 :         struct userPwdChangeFailureInformation *reject = NULL;
     157           0 :         NTSTATUS status;
     158           0 :         int rc;
     159             : 
     160          36 :         E_md4hash(old_password, old_nt_hash);
     161          36 :         E_md4hash(new_password, new_nt_hash);
     162             : 
     163          36 :         E_deshash(old_password, old_lm_hash);
     164          36 :         E_deshash(new_password, new_lm_hash);
     165             : 
     166             :         /* prepare samr_ChangePasswordUser3 */
     167          36 :         encode_pw_buffer(lm_pass.data, new_password, STR_UNICODE);
     168             : 
     169          36 :         rc = gnutls_cipher_init(&cipher_hnd,
     170             :                                 GNUTLS_CIPHER_ARCFOUR_128,
     171             :                                 &nt_session_key,
     172             :                                 NULL);
     173          36 :         if (rc < 0) {
     174           0 :                 status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     175           0 :                 goto done;
     176             :         }
     177             : 
     178          36 :         rc = gnutls_cipher_encrypt(cipher_hnd,
     179             :                                    lm_pass.data,
     180             :                                    516);
     181          36 :         gnutls_cipher_deinit(cipher_hnd);
     182          36 :         if (rc < 0) {
     183           0 :                 status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     184           0 :                 goto done;
     185             :         }
     186             : 
     187          36 :         rc = E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
     188          36 :         if (rc != 0) {
     189           0 :                 status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
     190           0 :                 goto done;
     191             :         }
     192             : 
     193          36 :         encode_pw_buffer(nt_pass.data, new_password, STR_UNICODE);
     194             : 
     195          36 :         rc = gnutls_cipher_init(&cipher_hnd,
     196             :                                 GNUTLS_CIPHER_ARCFOUR_128,
     197             :                                 &nt_session_key,
     198             :                                 NULL);
     199          36 :         if (rc < 0) {
     200           0 :                 status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     201           0 :                 goto done;
     202             :         }
     203             : 
     204          36 :         rc = gnutls_cipher_encrypt(cipher_hnd,
     205             :                                    nt_pass.data,
     206             :                                    516);
     207          36 :         gnutls_cipher_deinit(cipher_hnd);
     208          36 :         if (rc < 0) {
     209           0 :                 status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     210           0 :                 goto done;
     211             :         }
     212             : 
     213          36 :         rc = E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
     214          36 :         if (rc != 0) {
     215           0 :                 status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
     216           0 :                 goto done;
     217             :         }
     218             : 
     219          36 :         pw3.in.server = server;
     220          36 :         pw3.in.account = account;
     221          36 :         pw3.in.nt_password = &nt_pass;
     222          36 :         pw3.in.nt_verifier = &nt_verifier;
     223          36 :         pw3.in.lm_change = 1;
     224          36 :         pw3.in.lm_password = &lm_pass;
     225          36 :         pw3.in.lm_verifier = &lm_verifier;
     226          36 :         pw3.in.password3 = NULL;
     227          36 :         pw3.out.dominfo = &dominfo;
     228          36 :         pw3.out.reject = &reject;
     229             : 
     230             :         /* 2. try samr_ChangePasswordUser3 */
     231          36 :         status = dcerpc_samr_ChangePasswordUser3_r(h, mem_ctx, &pw3);
     232          36 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
     233          36 :                 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(pw3.out.result)) {
     234          18 :                         status = pw3.out.result;
     235             :                 }
     236          36 :                 if (!NT_STATUS_IS_OK(status)) {
     237          18 :                         *error_string = talloc_asprintf(
     238             :                                 mem_ctx,
     239             :                                 "samr_ChangePasswordUser3 failed: %s",
     240             :                                 nt_errstr(status));
     241          18 :                         *error_string =
     242          18 :                                 talloc_asprintf(mem_ctx,
     243             :                                                 "samr_ChangePasswordUser3 for "
     244             :                                                 "'%s\\%s' failed: %s",
     245             :                                                 server->string,
     246             :                                                 account->string,
     247             :                                                 nt_errstr(status));
     248             :                 }
     249           0 :                 goto done;
     250             :         }
     251             : 
     252             :         /* prepare samr_ChangePasswordUser2 */
     253           0 :         encode_pw_buffer(lm_pass.data, new_password, STR_ASCII | STR_TERMINATE);
     254             : 
     255           0 :         rc = gnutls_cipher_init(&cipher_hnd,
     256             :                                 GNUTLS_CIPHER_ARCFOUR_128,
     257             :                                 &lm_session_key,
     258             :                                 NULL);
     259           0 :         if (rc < 0) {
     260           0 :                 status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     261           0 :                 goto done;
     262             :         }
     263             : 
     264           0 :         rc = gnutls_cipher_encrypt(cipher_hnd,
     265             :                                    lm_pass.data,
     266             :                                    516);
     267           0 :         gnutls_cipher_deinit(cipher_hnd);
     268           0 :         if (rc < 0) {
     269           0 :                 status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     270           0 :                 goto done;
     271             :         }
     272             : 
     273           0 :         rc = E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
     274           0 :         if (rc != 0) {
     275           0 :                 status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
     276           0 :                 goto done;
     277             :         }
     278             : 
     279           0 :         encode_pw_buffer(nt_pass.data, new_password, STR_UNICODE);
     280             : 
     281           0 :         rc = gnutls_cipher_init(&cipher_hnd,
     282             :                                 GNUTLS_CIPHER_ARCFOUR_128,
     283             :                                 &nt_session_key,
     284             :                                 NULL);
     285           0 :         if (rc < 0) {
     286           0 :                 status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     287           0 :                 goto done;
     288             :         }
     289           0 :         rc = gnutls_cipher_encrypt(cipher_hnd,
     290             :                                    nt_pass.data,
     291             :                                    516);
     292           0 :         gnutls_cipher_deinit(cipher_hnd);
     293           0 :         if (rc < 0) {
     294           0 :                 status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     295           0 :                 goto done;
     296             :         }
     297             : 
     298           0 :         rc = E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
     299           0 :         if (rc != 0) {
     300           0 :                 status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
     301           0 :                 goto done;
     302             :         }
     303             : 
     304           0 :         pw2.in.server = server;
     305           0 :         pw2.in.account = account;
     306           0 :         pw2.in.nt_password = &nt_pass;
     307           0 :         pw2.in.nt_verifier = &nt_verifier;
     308           0 :         pw2.in.lm_change = 1;
     309           0 :         pw2.in.lm_password = &lm_pass;
     310           0 :         pw2.in.lm_verifier = &lm_verifier;
     311             : 
     312             :         /* 3. try samr_ChangePasswordUser2 */
     313           0 :         status = dcerpc_samr_ChangePasswordUser2_r(h, mem_ctx, &pw2);
     314           0 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
     315           0 :                 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(pw2.out.result)) {
     316           0 :                         status = pw2.out.result;
     317             :                 }
     318           0 :                 if (!NT_STATUS_IS_OK(status)) {
     319           0 :                         *error_string =
     320           0 :                                 talloc_asprintf(mem_ctx,
     321             :                                                 "samr_ChangePasswordUser2 for "
     322             :                                                 "'%s\\%s' failed: %s",
     323             :                                                 server->string,
     324             :                                                 account->string,
     325             :                                                 nt_errstr(status));
     326             :                 }
     327           0 :                 goto done;
     328             :         }
     329             : 
     330             : 
     331             :         /* prepare samr_OemChangePasswordUser2 */
     332           0 :         a_server.string = server->string;
     333           0 :         a_account.string = account->string;
     334             : 
     335           0 :         encode_pw_buffer(lm_pass.data, new_password, STR_ASCII);
     336             : 
     337           0 :         rc = gnutls_cipher_init(&cipher_hnd,
     338             :                                 GNUTLS_CIPHER_ARCFOUR_128,
     339             :                                 &lm_session_key,
     340             :                                 NULL);
     341           0 :         if (rc < 0) {
     342           0 :                 status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     343           0 :                 goto done;
     344             :         }
     345             : 
     346           0 :         rc = gnutls_cipher_encrypt(cipher_hnd,
     347             :                                    lm_pass.data,
     348             :                                    516);
     349           0 :         gnutls_cipher_deinit(cipher_hnd);
     350           0 :         if (rc < 0) {
     351           0 :                 status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     352           0 :                 goto done;
     353             :         }
     354             : 
     355           0 :         rc = E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
     356           0 :         if (rc != 0) {
     357           0 :                 status = gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
     358           0 :                 goto done;
     359             :         }
     360             : 
     361           0 :         oe2.in.server = &a_server;
     362           0 :         oe2.in.account = &a_account;
     363           0 :         oe2.in.password = &lm_pass;
     364           0 :         oe2.in.hash = &lm_verifier;
     365             : 
     366             :         /* 4. try samr_OemChangePasswordUser2 */
     367           0 :         status = dcerpc_samr_OemChangePasswordUser2_r(h, mem_ctx, &oe2);
     368           0 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
     369           0 :                 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(oe2.out.result)) {
     370           0 :                         status = oe2.out.result;
     371             :                 }
     372           0 :                 if (!NT_STATUS_IS_OK(oe2.out.result)) {
     373           0 :                         *error_string =
     374           0 :                                 talloc_asprintf(mem_ctx,
     375             :                                                 "samr_OemChangePasswordUser2 "
     376             :                                                 "for '%s\\%s' failed: %s",
     377             :                                                 server->string,
     378             :                                                 account->string,
     379             :                                                 nt_errstr(status));
     380             :                 }
     381           0 :                 goto done;
     382             :         }
     383             : 
     384             :         status = NT_STATUS_OK;
     385          36 : done:
     386          36 :         return status;
     387             : }
     388             : 
     389             : /*
     390             :  * do a password change using DCERPC/SAMR calls
     391             :  * 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation)
     392             :  * 2. try samr_ChangePasswordUser3
     393             :  * 3. try samr_ChangePasswordUser2
     394             :  * 4. try samr_OemChangePasswordUser2
     395             :  */
     396          38 : static NTSTATUS libnet_ChangePassword_samr(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_ChangePassword *r)
     397             : {
     398           2 :         NTSTATUS status;
     399           2 :         struct libnet_RpcConnect c;
     400           2 :         struct lsa_String server, account;
     401             : 
     402          38 :         ZERO_STRUCT(c);
     403             : 
     404             :         /* prepare connect to the SAMR pipe of the users domain PDC */
     405          38 :         c.level                    = LIBNET_RPC_CONNECT_PDC;
     406          38 :         c.in.name                  = r->samr.in.domain_name;
     407          38 :         c.in.dcerpc_iface          = &ndr_table_samr;
     408          38 :         c.in.dcerpc_flags          = DCERPC_ANON_FALLBACK;
     409             : 
     410             :         /* 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation) */
     411          38 :         status = libnet_RpcConnect(ctx, mem_ctx, &c);
     412          38 :         if (!NT_STATUS_IS_OK(status)) {
     413           0 :                 r->samr.out.error_string = talloc_asprintf(mem_ctx,
     414             :                                                 "Connection to SAMR pipe of PDC of domain '%s' failed: %s",
     415             :                                                 r->samr.in.domain_name, nt_errstr(status));
     416           0 :                 return status;
     417             :         }
     418             : 
     419             :         /* prepare password change for account */
     420          38 :         server.string = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(c.out.dcerpc_pipe));
     421          38 :         account.string = r->samr.in.account_name;
     422             : 
     423          76 :         status = libnet_ChangePassword_samr_aes(
     424             :                 mem_ctx,
     425          38 :                 c.out.dcerpc_pipe->binding_handle,
     426             :                 &server,
     427             :                 &account,
     428             :                 r->samr.in.oldpassword,
     429             :                 r->samr.in.newpassword,
     430             :                 &(r->samr.out.error_string));
     431           2 :         if (NT_STATUS_IS_OK(status)) {
     432           2 :                 goto disconnect;
     433           0 :         } else if (NT_STATUS_EQUAL(status,
     434           0 :                                    NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE) ||
     435           0 :                    NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED) ||
     436             :                    NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
     437             :                 /*
     438             :                  * Don't fallback to RC4 based SAMR if weak crypto is not
     439             :                  * allowed.
     440             :                  */
     441          36 :                 if (lpcfg_weak_crypto(ctx->lp_ctx) ==
     442             :                     SAMBA_WEAK_CRYPTO_DISALLOWED) {
     443           0 :                         goto disconnect;
     444             :                 }
     445             :         } else {
     446             :                 /* libnet_ChangePassword_samr_aes is implemented and failed */
     447           0 :                 goto disconnect;
     448             :         }
     449             : 
     450          72 :         status = libnet_ChangePassword_samr_rc4(
     451             :                 mem_ctx,
     452          36 :                 c.out.dcerpc_pipe->binding_handle,
     453             :                 &server,
     454             :                 &account,
     455             :                 r->samr.in.oldpassword,
     456             :                 r->samr.in.newpassword,
     457             :                 &(r->samr.out.error_string));
     458           0 :         if (!NT_STATUS_IS_OK(status)) {
     459             :                 goto disconnect;
     460             :         }
     461             : 
     462          38 : disconnect:
     463             :         /* close connection */
     464          38 :         talloc_unlink(ctx, c.out.dcerpc_pipe);
     465             : 
     466          38 :         return status;
     467             : }
     468             : 
     469          38 : static NTSTATUS libnet_ChangePassword_generic(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_ChangePassword *r)
     470             : {
     471           2 :         NTSTATUS status;
     472           2 :         union libnet_ChangePassword r2;
     473             : 
     474          38 :         r2.samr.level           = LIBNET_CHANGE_PASSWORD_SAMR;
     475          38 :         r2.samr.in.account_name = r->generic.in.account_name;
     476          38 :         r2.samr.in.domain_name  = r->generic.in.domain_name;
     477          38 :         r2.samr.in.oldpassword  = r->generic.in.oldpassword;
     478          38 :         r2.samr.in.newpassword  = r->generic.in.newpassword;
     479             : 
     480          38 :         status = libnet_ChangePassword(ctx, mem_ctx, &r2);
     481             : 
     482          38 :         r->generic.out.error_string = r2.samr.out.error_string;
     483             : 
     484          38 :         return status;
     485             : }
     486             : 
     487          76 : NTSTATUS libnet_ChangePassword(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_ChangePassword *r)
     488             : {
     489          76 :         switch (r->generic.level) {
     490          38 :                 case LIBNET_CHANGE_PASSWORD_GENERIC:
     491          38 :                         return libnet_ChangePassword_generic(ctx, mem_ctx, r);
     492          38 :                 case LIBNET_CHANGE_PASSWORD_SAMR:
     493          38 :                         return libnet_ChangePassword_samr(ctx, mem_ctx, r);
     494           0 :                 case LIBNET_CHANGE_PASSWORD_KRB5:
     495           0 :                         return NT_STATUS_NOT_IMPLEMENTED;
     496           0 :                 case LIBNET_CHANGE_PASSWORD_LDAP:
     497           0 :                         return NT_STATUS_NOT_IMPLEMENTED;
     498           0 :                 case LIBNET_CHANGE_PASSWORD_RAP:
     499           0 :                         return NT_STATUS_NOT_IMPLEMENTED;
     500             :         }
     501             : 
     502           0 :         return NT_STATUS_INVALID_LEVEL;
     503             : }
     504             : 
     505         265 : static NTSTATUS libnet_SetPassword_samr_handle_26(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
     506             : {
     507          21 :         NTSTATUS status;
     508          21 :         struct samr_SetUserInfo2 sui;
     509          21 :         union samr_UserInfo u_info;
     510          21 :         DATA_BLOB session_key;
     511             : 
     512         265 :         if (r->samr_handle.in.info21) {
     513         263 :                 return NT_STATUS_INVALID_PARAMETER_MIX;
     514             :         }
     515             : 
     516             :         /* prepare samr_SetUserInfo2 level 26 */
     517           2 :         ZERO_STRUCT(u_info);
     518           2 :         u_info.info26.password_expired = 0;
     519             : 
     520           2 :         status = dcerpc_fetch_session_key(r->samr_handle.in.dcerpc_pipe, &session_key);
     521           2 :         if (!NT_STATUS_IS_OK(status)) {
     522           0 :                 r->samr_handle.out.error_string = talloc_asprintf(mem_ctx,
     523             :                                                                   "dcerpc_fetch_session_key failed: %s",
     524             :                                                                   nt_errstr(status));
     525           0 :                 return status;
     526             :         }
     527             : 
     528           2 :         status = encode_rc4_passwd_buffer(r->samr_handle.in.newpassword,
     529             :                                           &session_key,
     530             :                                           &u_info.info26.password);
     531           2 :         if (!NT_STATUS_IS_OK(status)) {
     532           0 :                 r->samr_handle.out.error_string =
     533           0 :                         talloc_asprintf(mem_ctx,
     534             :                                         "encode_rc4_passwd_buffer failed: %s",
     535             :                                         nt_errstr(status));
     536           0 :                 return status;
     537             :         }
     538             : 
     539           2 :         sui.in.user_handle = r->samr_handle.in.user_handle;
     540           2 :         sui.in.info = &u_info;
     541           2 :         sui.in.level = 26;
     542             : 
     543             :         /* 7. try samr_SetUserInfo2 level 26 to set the password */
     544           2 :         status = dcerpc_samr_SetUserInfo2_r(r->samr_handle.in.dcerpc_pipe->binding_handle, mem_ctx, &sui);
     545             :         /* check result of samr_SetUserInfo2 level 26 */
     546           2 :         if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(sui.out.result)) {
     547           0 :                 status = sui.out.result;
     548             :         }
     549           2 :         if (!NT_STATUS_IS_OK(status)) {
     550           0 :                 r->samr_handle.out.error_string
     551           0 :                         = talloc_asprintf(mem_ctx,
     552             :                                           "SetUserInfo2 level 26 for [%s] failed: %s",
     553             :                                           r->samr_handle.in.account_name, nt_errstr(status));
     554             :         }
     555             : 
     556           2 :         return status;
     557             : }
     558             : 
     559         263 : static NTSTATUS libnet_SetPassword_samr_handle_25(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
     560             : {
     561          21 :         NTSTATUS status;
     562          21 :         struct samr_SetUserInfo2 sui;
     563          21 :         union samr_UserInfo u_info;
     564          21 :         DATA_BLOB session_key;
     565             : 
     566         263 :         if (!r->samr_handle.in.info21) {
     567           0 :                 return NT_STATUS_INVALID_PARAMETER_MIX;
     568             :         }
     569             : 
     570             :         /* prepare samr_SetUserInfo2 level 25 */
     571         263 :         ZERO_STRUCT(u_info);
     572         263 :         u_info.info25.info = *r->samr_handle.in.info21;
     573         263 :         u_info.info25.info.fields_present |= SAMR_FIELD_NT_PASSWORD_PRESENT;
     574             : 
     575         263 :         status = dcerpc_fetch_session_key(r->samr_handle.in.dcerpc_pipe, &session_key);
     576         263 :         if (!NT_STATUS_IS_OK(status)) {
     577           0 :                 r->samr_handle.out.error_string = talloc_asprintf(mem_ctx,
     578             :                                                 "dcerpc_fetch_session_key failed: %s",
     579             :                                                 nt_errstr(status));
     580           0 :                 return status;
     581             :         }
     582             : 
     583         263 :         status = encode_rc4_passwd_buffer(r->samr_handle.in.newpassword,
     584             :                                           &session_key,
     585             :                                           &u_info.info25.password);
     586         263 :         if (!NT_STATUS_IS_OK(status)) {
     587           0 :                 r->samr_handle.out.error_string =
     588           0 :                         talloc_asprintf(mem_ctx,
     589             :                                         "encode_rc4_passwd_buffer failed: %s",
     590             :                                         nt_errstr(status));
     591           0 :                 return status;
     592             :         }
     593             : 
     594             : 
     595         263 :         sui.in.user_handle = r->samr_handle.in.user_handle;
     596         263 :         sui.in.info = &u_info;
     597         263 :         sui.in.level = 25;
     598             : 
     599             :         /* 8. try samr_SetUserInfo2 level 25 to set the password */
     600         263 :         status = dcerpc_samr_SetUserInfo2_r(r->samr_handle.in.dcerpc_pipe->binding_handle, mem_ctx, &sui);
     601         263 :         if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(sui.out.result)) {
     602          21 :                 status = sui.out.result;
     603             :         }
     604         263 :         if (!NT_STATUS_IS_OK(status)) {
     605           0 :                 r->samr_handle.out.error_string
     606           0 :                         = talloc_asprintf(mem_ctx,
     607             :                                           "SetUserInfo2 level 25 for [%s] failed: %s",
     608             :                                           r->samr_handle.in.account_name, nt_errstr(status));
     609             :         }
     610             : 
     611         263 :         return status;
     612             : }
     613             : 
     614           0 : static NTSTATUS libnet_SetPassword_samr_handle_24(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
     615             : {
     616           0 :         NTSTATUS status;
     617           0 :         struct samr_SetUserInfo2 sui;
     618           0 :         union samr_UserInfo u_info;
     619           0 :         DATA_BLOB session_key;
     620           0 :         gnutls_cipher_hd_t cipher_hnd = NULL;
     621           0 :         gnutls_datum_t enc_session_key;
     622           0 :         int rc;
     623             : 
     624           0 :         if (r->samr_handle.in.info21) {
     625           0 :                 return NT_STATUS_INVALID_PARAMETER_MIX;
     626             :         }
     627             : 
     628             :         /* prepare samr_SetUserInfo2 level 24 */
     629           0 :         ZERO_STRUCT(u_info);
     630           0 :         encode_pw_buffer(u_info.info24.password.data, r->samr_handle.in.newpassword, STR_UNICODE);
     631           0 :         u_info.info24.password_expired = 0;
     632             : 
     633           0 :         status = dcerpc_fetch_session_key(r->samr_handle.in.dcerpc_pipe, &session_key);
     634           0 :         if (!NT_STATUS_IS_OK(status)) {
     635           0 :                 r->samr_handle.out.error_string = talloc_asprintf(mem_ctx,
     636             :                                                 "dcerpc_fetch_session_key failed: %s",
     637             :                                                 nt_errstr(status));
     638           0 :                 return status;
     639             :         }
     640             : 
     641           0 :         enc_session_key = (gnutls_datum_t) {
     642           0 :                 .data = session_key.data,
     643           0 :                 .size = session_key.length,
     644             :         };
     645             : 
     646           0 :         rc = gnutls_cipher_init(&cipher_hnd,
     647             :                                 GNUTLS_CIPHER_ARCFOUR_128,
     648             :                                 &enc_session_key,
     649             :                                 NULL);
     650           0 :         if (rc < 0) {
     651           0 :                 status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     652           0 :                 goto out;
     653             :         }
     654             : 
     655           0 :         rc = gnutls_cipher_encrypt(cipher_hnd,
     656             :                                    u_info.info24.password.data,
     657             :                                    516);
     658           0 :         gnutls_cipher_deinit(cipher_hnd);
     659           0 :         if (rc < 0) {
     660           0 :                 status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     661           0 :                 goto out;
     662             :         }
     663             : 
     664           0 :         sui.in.user_handle = r->samr_handle.in.user_handle;
     665           0 :         sui.in.info = &u_info;
     666           0 :         sui.in.level = 24;
     667             : 
     668             :         /* 9. try samr_SetUserInfo2 level 24 to set the password */
     669           0 :         status = dcerpc_samr_SetUserInfo2_r(r->samr_handle.in.dcerpc_pipe->binding_handle, mem_ctx, &sui);
     670           0 :         if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(sui.out.result)) {
     671           0 :                 status = sui.out.result;
     672             :         }
     673           0 :         if (!NT_STATUS_IS_OK(status)) {
     674           0 :                 r->samr_handle.out.error_string
     675           0 :                         = talloc_asprintf(mem_ctx,
     676             :                                           "SetUserInfo2 level 24 for [%s] failed: %s",
     677             :                                           r->samr_handle.in.account_name, nt_errstr(status));
     678             :         }
     679             : 
     680           0 : out:
     681           0 :         data_blob_clear(&session_key);
     682           0 :         return status;
     683             : }
     684             : 
     685           0 : static NTSTATUS libnet_SetPassword_samr_handle_23(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
     686             : {
     687           0 :         NTSTATUS status;
     688           0 :         struct samr_SetUserInfo2 sui;
     689           0 :         union samr_UserInfo u_info;
     690           0 :         DATA_BLOB session_key;
     691           0 :         gnutls_cipher_hd_t cipher_hnd = NULL;
     692           0 :         gnutls_datum_t _session_key;
     693           0 :         int rc;
     694             : 
     695           0 :         if (!r->samr_handle.in.info21) {
     696           0 :                 return NT_STATUS_INVALID_PARAMETER_MIX;
     697             :         }
     698             : 
     699             :         /* prepare samr_SetUserInfo2 level 23 */
     700           0 :         ZERO_STRUCT(u_info);
     701           0 :         u_info.info23.info = *r->samr_handle.in.info21;
     702           0 :         u_info.info23.info.fields_present |= SAMR_FIELD_NT_PASSWORD_PRESENT;
     703           0 :         encode_pw_buffer(u_info.info23.password.data, r->samr_handle.in.newpassword, STR_UNICODE);
     704             : 
     705           0 :         status = dcerpc_fetch_session_key(r->samr_handle.in.dcerpc_pipe, &session_key);
     706           0 :         if (!NT_STATUS_IS_OK(status)) {
     707           0 :                 r->samr_handle.out.error_string
     708           0 :                         = talloc_asprintf(mem_ctx,
     709             :                                           "dcerpc_fetch_session_key failed: %s",
     710             :                                           nt_errstr(status));
     711           0 :                 return status;
     712             :         }
     713             : 
     714           0 :         _session_key = (gnutls_datum_t) {
     715           0 :                 .data = session_key.data,
     716           0 :                 .size = session_key.length,
     717             :         };
     718             : 
     719           0 :         rc = gnutls_cipher_init(&cipher_hnd,
     720             :                                 GNUTLS_CIPHER_ARCFOUR_128,
     721             :                                 &_session_key,
     722             :                                 NULL);
     723           0 :         if (rc < 0) {
     724           0 :                 status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     725           0 :                 goto out;
     726             :         }
     727             : 
     728           0 :         rc = gnutls_cipher_encrypt(cipher_hnd,
     729             :                                    u_info.info23.password.data,
     730             :                                    516);
     731           0 :         data_blob_clear_free(&session_key);
     732           0 :         gnutls_cipher_deinit(cipher_hnd);
     733           0 :         if (rc < 0) {
     734           0 :                 status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     735           0 :                 goto out;
     736             :         }
     737             : 
     738           0 :         sui.in.user_handle = r->samr_handle.in.user_handle;
     739           0 :         sui.in.info = &u_info;
     740           0 :         sui.in.level = 23;
     741             : 
     742             :         /* 10. try samr_SetUserInfo2 level 23 to set the password */
     743           0 :         status = dcerpc_samr_SetUserInfo2_r(r->samr_handle.in.dcerpc_pipe->binding_handle, mem_ctx, &sui);
     744           0 :         if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(sui.out.result)) {
     745           0 :                 status = sui.out.result;
     746             :         }
     747           0 :         if (!NT_STATUS_IS_OK(status)) {
     748           0 :                 r->samr_handle.out.error_string
     749           0 :                         = talloc_asprintf(mem_ctx,
     750             :                                           "SetUserInfo2 level 23 for [%s] failed: %s",
     751             :                                           r->samr_handle.in.account_name, nt_errstr(status));
     752             :         }
     753             : 
     754           0 : out:
     755           0 :         return status;
     756             : }
     757             : 
     758          38 : static NTSTATUS libnet_SetPassword_samr_handle_18(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
     759             : {
     760           0 :         NTSTATUS status;
     761           0 :         struct samr_SetUserInfo2 sui;
     762           0 :         union samr_UserInfo u_info;
     763           0 :         struct samr_Password ntpwd;
     764           0 :         DATA_BLOB ntpwd_in;
     765           0 :         DATA_BLOB ntpwd_out;
     766           0 :         DATA_BLOB session_key;
     767           0 :         int rc;
     768             : 
     769          38 :         if (r->samr_handle.in.info21) {
     770           0 :                 return NT_STATUS_INVALID_PARAMETER_MIX;
     771             :         }
     772             : 
     773             :         /* prepare samr_SetUserInfo2 level 18 (nt_hash) */
     774          38 :         ZERO_STRUCT(u_info);
     775          38 :         E_md4hash(r->samr_handle.in.newpassword, ntpwd.hash);
     776          38 :         ntpwd_in = data_blob_const(ntpwd.hash, sizeof(ntpwd.hash));
     777          38 :         ntpwd_out = data_blob_const(u_info.info18.nt_pwd.hash,
     778             :                                     sizeof(u_info.info18.nt_pwd.hash));
     779          38 :         u_info.info18.nt_pwd_active = 1;
     780          38 :         u_info.info18.password_expired = 0;
     781             : 
     782          38 :         status = dcerpc_fetch_session_key(r->samr_handle.in.dcerpc_pipe, &session_key);
     783          38 :         if (!NT_STATUS_IS_OK(status)) {
     784           0 :                 r->samr_handle.out.error_string = talloc_asprintf(mem_ctx,
     785             :                                                 "dcerpc_fetch_session_key failed: %s",
     786             :                                                 nt_errstr(status));
     787           0 :                 return status;
     788             :         }
     789             : 
     790          38 :         rc = sess_crypt_blob(&ntpwd_out, &ntpwd_in,
     791             :                              &session_key, SAMBA_GNUTLS_ENCRYPT);
     792          38 :         if (rc < 0) {
     793           0 :                 status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     794           0 :                 goto out;
     795             :         }
     796             : 
     797          38 :         sui.in.user_handle = r->samr_handle.in.user_handle;
     798          38 :         sui.in.info = &u_info;
     799          38 :         sui.in.level = 18;
     800             : 
     801             :         /* 9. try samr_SetUserInfo2 level 18 to set the password */
     802          38 :         status = dcerpc_samr_SetUserInfo2_r(r->samr_handle.in.dcerpc_pipe->binding_handle, mem_ctx, &sui);
     803          38 :         if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(sui.out.result)) {
     804           0 :                 status = sui.out.result;
     805             :         }
     806          38 :         if (!NT_STATUS_IS_OK(status)) {
     807           0 :                 r->samr_handle.out.error_string
     808           0 :                         = talloc_asprintf(mem_ctx,
     809             :                                           "SetUserInfo2 level 18 for [%s] failed: %s",
     810             :                                           r->samr_handle.in.account_name, nt_errstr(status));
     811             :         }
     812             : 
     813          38 : out:
     814          38 :         data_blob_clear(&session_key);
     815          38 :         return status;
     816             : }
     817             : 
     818             : /*
     819             :  * 1. try samr_SetUserInfo2 level 26 to set the password
     820             :  * 2. try samr_SetUserInfo2 level 25 to set the password
     821             :  * 3. try samr_SetUserInfo2 level 24 to set the password
     822             :  * 4. try samr_SetUserInfo2 level 23 to set the password
     823             : */
     824         303 : static NTSTATUS libnet_SetPassword_samr_handle(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
     825             : {
     826             : 
     827          21 :         NTSTATUS status;
     828         303 :         enum libnet_SetPassword_level levels[] = {
     829             :                 LIBNET_SET_PASSWORD_SAMR_HANDLE_26,
     830             :                 LIBNET_SET_PASSWORD_SAMR_HANDLE_25,
     831             :                 LIBNET_SET_PASSWORD_SAMR_HANDLE_24,
     832             :                 LIBNET_SET_PASSWORD_SAMR_HANDLE_23,
     833             :         };
     834          21 :         unsigned int i;
     835             : 
     836         303 :         if (r->samr_handle.samr_level != 0) {
     837          38 :                 r->generic.level = r->samr_handle.samr_level;
     838          38 :                 return libnet_SetPassword(ctx, mem_ctx, r);
     839             :         }
     840             : 
     841         284 :         for (i=0; i < ARRAY_SIZE(levels); i++) {
     842         528 :                 r->generic.level = levels[i];
     843         528 :                 status = libnet_SetPassword(ctx, mem_ctx, r);
     844         528 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)
     845         528 :                     || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER_MIX)
     846         265 :                     || NT_STATUS_EQUAL(status, NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE)) {
     847             :                         /* Try another password set mechanism */
     848         263 :                         continue;
     849             :                 }
     850             :                 break;
     851             :         }
     852             : 
     853         265 :         return status;
     854             : }
     855             : /*
     856             :  * set a password with DCERPC/SAMR calls
     857             :  * 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation)
     858             :  *    is it correct to contact the the pdc of the domain of the user who's password should be set?
     859             :  * 2. do a samr_Connect to get a policy handle
     860             :  * 3. do a samr_LookupDomain to get the domain sid
     861             :  * 4. do a samr_OpenDomain to get a domain handle
     862             :  * 5. do a samr_LookupNames to get the users rid
     863             :  * 6. do a samr_OpenUser to get a user handle
     864             :  * 7  call libnet_SetPassword_samr_handle to set the password
     865             :  */
     866          40 : static NTSTATUS libnet_SetPassword_samr(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
     867             : {
     868           0 :         NTSTATUS status;
     869           0 :         struct libnet_RpcConnect c;
     870           0 :         struct samr_Connect sc;
     871           0 :         struct policy_handle p_handle;
     872           0 :         struct samr_LookupDomain ld;
     873          40 :         struct dom_sid2 *sid = NULL;
     874           0 :         struct lsa_String d_name;
     875           0 :         struct samr_OpenDomain od;
     876           0 :         struct policy_handle d_handle;
     877           0 :         struct samr_LookupNames ln;
     878           0 :         struct samr_Ids rids, types;
     879           0 :         struct samr_OpenUser ou;
     880           0 :         struct policy_handle u_handle;
     881           0 :         union libnet_SetPassword r2;
     882             : 
     883          40 :         ZERO_STRUCT(c);
     884             :         /* prepare connect to the SAMR pipe of users domain PDC */
     885          40 :         c.level               = LIBNET_RPC_CONNECT_PDC;
     886          40 :         c.in.name             = r->samr.in.domain_name;
     887          40 :         c.in.dcerpc_iface     = &ndr_table_samr;
     888             : 
     889             :         /* 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation) */
     890          40 :         status = libnet_RpcConnect(ctx, mem_ctx, &c);
     891          40 :         if (!NT_STATUS_IS_OK(status)) {
     892           0 :                 r->samr.out.error_string = talloc_asprintf(mem_ctx,
     893             :                                                            "Connection to SAMR pipe of PDC of domain '%s' failed: %s",
     894             :                                                            r->samr.in.domain_name, nt_errstr(status));
     895           0 :                 return status;
     896             :         }
     897             : 
     898             :         /* prepare samr_Connect */
     899          40 :         ZERO_STRUCT(p_handle);
     900          40 :         sc.in.system_name = NULL;
     901          40 :         sc.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
     902          40 :         sc.out.connect_handle = &p_handle;
     903             : 
     904             :         /* 2. do a samr_Connect to get a policy handle */
     905          40 :         status = dcerpc_samr_Connect_r(c.out.dcerpc_pipe->binding_handle, mem_ctx, &sc);
     906          40 :         if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(sc.out.result)) {
     907           0 :                 status = sc.out.result;
     908             :         }
     909          40 :         if (!NT_STATUS_IS_OK(status)) {
     910           0 :                 r->samr.out.error_string = talloc_asprintf(mem_ctx,
     911             :                                                 "samr_Connect failed: %s",
     912             :                                                 nt_errstr(status));
     913           0 :                 goto disconnect;
     914             :         }
     915             : 
     916             :         /* prepare samr_LookupDomain */
     917          40 :         d_name.string = r->samr.in.domain_name;
     918          40 :         ld.in.connect_handle = &p_handle;
     919          40 :         ld.in.domain_name = &d_name;
     920          40 :         ld.out.sid = &sid;
     921             : 
     922             :         /* 3. do a samr_LookupDomain to get the domain sid */
     923          40 :         status = dcerpc_samr_LookupDomain_r(c.out.dcerpc_pipe->binding_handle, mem_ctx, &ld);
     924          40 :         if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(ld.out.result)) {
     925           0 :                 status = ld.out.result;
     926             :         }
     927          40 :         if (!NT_STATUS_IS_OK(status)) {
     928           0 :                 r->samr.out.error_string = talloc_asprintf(mem_ctx,
     929             :                                                 "samr_LookupDomain for [%s] failed: %s",
     930             :                                                 r->samr.in.domain_name, nt_errstr(status));
     931           0 :                 goto disconnect;
     932             :         }
     933             : 
     934             :         /* prepare samr_OpenDomain */
     935          40 :         ZERO_STRUCT(d_handle);
     936          40 :         od.in.connect_handle = &p_handle;
     937          40 :         od.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
     938          40 :         od.in.sid = *ld.out.sid;
     939          40 :         od.out.domain_handle = &d_handle;
     940             : 
     941             :         /* 4. do a samr_OpenDomain to get a domain handle */
     942          40 :         status = dcerpc_samr_OpenDomain_r(c.out.dcerpc_pipe->binding_handle, mem_ctx, &od);
     943          40 :         if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(od.out.result)) {
     944           0 :                 status = od.out.result;
     945             :         }
     946          40 :         if (!NT_STATUS_IS_OK(status)) {
     947           0 :                 r->samr.out.error_string = talloc_asprintf(mem_ctx,
     948             :                                                 "samr_OpenDomain for [%s] failed: %s",
     949             :                                                 r->samr.in.domain_name, nt_errstr(status));
     950           0 :                 goto disconnect;
     951             :         }
     952             : 
     953             :         /* prepare samr_LookupNames */
     954          40 :         ln.in.domain_handle = &d_handle;
     955          40 :         ln.in.num_names = 1;
     956          40 :         ln.in.names = talloc_array(mem_ctx, struct lsa_String, 1);
     957          40 :         ln.out.rids = &rids;
     958          40 :         ln.out.types = &types;
     959          40 :         if (!ln.in.names) {
     960           0 :                 r->samr.out.error_string = "Out of Memory";
     961           0 :                 return NT_STATUS_NO_MEMORY;
     962             :         }
     963          40 :         ln.in.names[0].string = r->samr.in.account_name;
     964             : 
     965             :         /* 5. do a samr_LookupNames to get the users rid */
     966          40 :         status = dcerpc_samr_LookupNames_r(c.out.dcerpc_pipe->binding_handle, mem_ctx, &ln);
     967          40 :         if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(ln.out.result)) {
     968           0 :                 status = ln.out.result;
     969             :         }
     970          40 :         if (!NT_STATUS_IS_OK(status)) {
     971           0 :                 r->samr.out.error_string = talloc_asprintf(mem_ctx,
     972             :                                                 "samr_LookupNames for [%s] failed: %s",
     973             :                                                 r->samr.in.account_name, nt_errstr(status));
     974           0 :                 goto disconnect;
     975             :         }
     976             : 
     977             :         /* check if we got one RID for the user */
     978          40 :         if (ln.out.rids->count != 1) {
     979           0 :                 r->samr.out.error_string = talloc_asprintf(mem_ctx,
     980             :                                                 "samr_LookupNames for [%s] returns %d RIDs",
     981             :                                                 r->samr.in.account_name, ln.out.rids->count);
     982           0 :                 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
     983           0 :                 goto disconnect;
     984             :         }
     985             : 
     986          40 :         if (ln.out.types->count != 1) {
     987           0 :                 r->samr.out.error_string = talloc_asprintf(mem_ctx,
     988             :                                                 "samr_LookupNames for [%s] returns %d RID TYPEs",
     989             :                                                 r->samr.in.account_name, ln.out.types->count);
     990           0 :                 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
     991           0 :                 goto disconnect;
     992             :         }
     993             : 
     994             :         /* prepare samr_OpenUser */
     995          40 :         ZERO_STRUCT(u_handle);
     996          40 :         ou.in.domain_handle = &d_handle;
     997          40 :         ou.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
     998          40 :         ou.in.rid = ln.out.rids->ids[0];
     999          40 :         ou.out.user_handle = &u_handle;
    1000             : 
    1001             :         /* 6. do a samr_OpenUser to get a user handle */
    1002          40 :         status = dcerpc_samr_OpenUser_r(c.out.dcerpc_pipe->binding_handle, mem_ctx, &ou);
    1003          40 :         if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(ou.out.result)) {
    1004           0 :                 status = ou.out.result;
    1005             :         }
    1006          40 :         if (!NT_STATUS_IS_OK(status)) {
    1007           0 :                 r->samr.out.error_string = talloc_asprintf(mem_ctx,
    1008             :                                                 "samr_OpenUser for [%s] failed: %s",
    1009             :                                                 r->samr.in.account_name, nt_errstr(status));
    1010           0 :                 goto disconnect;
    1011             :         }
    1012             : 
    1013          40 :         ZERO_STRUCT(r2);
    1014          40 :         r2.samr_handle.level            = LIBNET_SET_PASSWORD_SAMR_HANDLE;
    1015          40 :         r2.samr_handle.samr_level       = r->samr.samr_level;
    1016          40 :         r2.samr_handle.in.account_name  = r->samr.in.account_name;
    1017          40 :         r2.samr_handle.in.newpassword   = r->samr.in.newpassword;
    1018          40 :         r2.samr_handle.in.user_handle   = &u_handle;
    1019          40 :         r2.samr_handle.in.dcerpc_pipe   = c.out.dcerpc_pipe;
    1020          40 :         r2.samr_handle.in.info21        = NULL;
    1021             : 
    1022          40 :         status = libnet_SetPassword(ctx, mem_ctx, &r2);
    1023             : 
    1024          40 :         r->generic.out.error_string = r2.samr_handle.out.error_string;
    1025             : 
    1026          40 : disconnect:
    1027             :         /* close connection */
    1028          40 :         talloc_unlink(ctx, c.out.dcerpc_pipe);
    1029             : 
    1030          40 :         return status;
    1031             : }
    1032             : 
    1033          40 : static NTSTATUS libnet_SetPassword_generic(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
    1034             : {
    1035           0 :         NTSTATUS status;
    1036           0 :         union libnet_SetPassword r2;
    1037             : 
    1038          40 :         ZERO_STRUCT(r2);
    1039          40 :         r2.samr.level           = LIBNET_SET_PASSWORD_SAMR;
    1040          40 :         r2.samr.samr_level      = r->generic.samr_level;
    1041          40 :         r2.samr.in.account_name = r->generic.in.account_name;
    1042          40 :         r2.samr.in.domain_name  = r->generic.in.domain_name;
    1043          40 :         r2.samr.in.newpassword  = r->generic.in.newpassword;
    1044             : 
    1045          40 :         r->generic.out.error_string = "Unknown Error";
    1046          40 :         status = libnet_SetPassword(ctx, mem_ctx, &r2);
    1047             : 
    1048          40 :         r->generic.out.error_string = r2.samr.out.error_string;
    1049             : 
    1050          40 :         return status;
    1051             : }
    1052             : 
    1053         949 : NTSTATUS libnet_SetPassword(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
    1054             : {
    1055         949 :         enum smb_encryption_setting encryption_state =
    1056         949 :                 cli_credentials_get_smb_encryption(ctx->cred);
    1057         949 :         NTSTATUS status =  NT_STATUS_INVALID_LEVEL;
    1058             : 
    1059         949 :         switch (r->generic.level) {
    1060          40 :                 case LIBNET_SET_PASSWORD_GENERIC:
    1061          40 :                         status = libnet_SetPassword_generic(ctx, mem_ctx, r);
    1062          40 :                         break;
    1063          40 :                 case LIBNET_SET_PASSWORD_SAMR:
    1064          40 :                         status = libnet_SetPassword_samr(ctx, mem_ctx, r);
    1065          40 :                         break;
    1066         303 :                 case LIBNET_SET_PASSWORD_SAMR_HANDLE:
    1067         303 :                         status = libnet_SetPassword_samr_handle(ctx, mem_ctx, r);
    1068         282 :                         break;
    1069          21 :                 case LIBNET_SET_PASSWORD_SAMR_HANDLE_26:
    1070          21 :                         if (encryption_state == SMB_ENCRYPTION_REQUIRED) {
    1071           0 :                                 GNUTLS_FIPS140_SET_LAX_MODE();
    1072             :                         }
    1073         265 :                         status = libnet_SetPassword_samr_handle_26(ctx, mem_ctx, r);
    1074         244 :                         break;
    1075          21 :                 case LIBNET_SET_PASSWORD_SAMR_HANDLE_25:
    1076          21 :                         if (encryption_state == SMB_ENCRYPTION_REQUIRED) {
    1077           0 :                                 GNUTLS_FIPS140_SET_LAX_MODE();
    1078             :                         }
    1079         263 :                         status = libnet_SetPassword_samr_handle_25(ctx, mem_ctx, r);
    1080         242 :                         break;
    1081           0 :                 case LIBNET_SET_PASSWORD_SAMR_HANDLE_24:
    1082           0 :                         if (encryption_state == SMB_ENCRYPTION_REQUIRED) {
    1083           0 :                                 GNUTLS_FIPS140_SET_LAX_MODE();
    1084             :                         }
    1085           0 :                         status = libnet_SetPassword_samr_handle_24(ctx, mem_ctx, r);
    1086           0 :                         break;
    1087           0 :                 case LIBNET_SET_PASSWORD_SAMR_HANDLE_23:
    1088           0 :                         if (encryption_state == SMB_ENCRYPTION_REQUIRED) {
    1089           0 :                                 GNUTLS_FIPS140_SET_LAX_MODE();
    1090             :                         }
    1091           0 :                         status = libnet_SetPassword_samr_handle_23(ctx, mem_ctx, r);
    1092           0 :                         break;
    1093           0 :                 case LIBNET_SET_PASSWORD_SAMR_HANDLE_18:
    1094           0 :                         if (encryption_state == SMB_ENCRYPTION_REQUIRED) {
    1095           0 :                                 GNUTLS_FIPS140_SET_LAX_MODE();
    1096             :                         }
    1097          38 :                         status = libnet_SetPassword_samr_handle_18(ctx, mem_ctx, r);
    1098          38 :                         break;
    1099           0 :                 case LIBNET_SET_PASSWORD_KRB5:
    1100           0 :                         status = NT_STATUS_NOT_IMPLEMENTED;
    1101           0 :                         break;
    1102           0 :                 case LIBNET_SET_PASSWORD_LDAP:
    1103           0 :                         status = NT_STATUS_NOT_IMPLEMENTED;
    1104           0 :                         break;
    1105           0 :                 case LIBNET_SET_PASSWORD_RAP:
    1106           0 :                         status = NT_STATUS_NOT_IMPLEMENTED;
    1107           0 :                         break;
    1108             :         }
    1109             : 
    1110          63 :         GNUTLS_FIPS140_SET_STRICT_MODE();
    1111         949 :         return status;
    1112             : }

Generated by: LCOV version 1.13