LCOV - code coverage report
Current view: top level - source4/libnet - libnet_passwd.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 283 597 47.4 %
Date: 2024-04-21 15:09:00 Functions: 11 14 78.6 %

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

Generated by: LCOV version 1.14