root/source4/libnet/libnet_passwd.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. libnet_ChangePassword_samr
  2. libnet_ChangePassword_generic
  3. libnet_ChangePassword
  4. libnet_SetPassword_samr_handle_26
  5. libnet_SetPassword_samr_handle_25
  6. libnet_SetPassword_samr_handle_24
  7. libnet_SetPassword_samr_handle_23
  8. libnet_SetPassword_samr_handle
  9. libnet_SetPassword_samr
  10. libnet_SetPassword_generic
  11. libnet_SetPassword

   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 "../lib/crypto/crypto.h"
  24 #include "libcli/auth/libcli_auth.h"
  25 #include "librpc/gen_ndr/ndr_samr_c.h"
  26 
  27 /*
  28  * do a password change using DCERPC/SAMR calls
  29  * 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation)
  30  * 2. try samr_ChangePasswordUser3
  31  * 3. try samr_ChangePasswordUser2
  32  * 4. try samr_OemChangePasswordUser2
  33  * (not yet: 5. try samr_ChangePasswordUser)
  34  */
  35 static NTSTATUS libnet_ChangePassword_samr(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_ChangePassword *r)
     /* [<][>][^][v][top][bottom][index][help] */
  36 {
  37         NTSTATUS status;
  38         struct libnet_RpcConnect c;
  39 #if 0
  40         struct policy_handle user_handle;
  41         struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
  42         struct samr_ChangePasswordUser pw;
  43 #endif
  44         struct samr_OemChangePasswordUser2 oe2;
  45         struct samr_ChangePasswordUser2 pw2;
  46         struct samr_ChangePasswordUser3 pw3;
  47         struct lsa_String server, account;
  48         struct lsa_AsciiString a_server, a_account;
  49         struct samr_CryptPassword nt_pass, lm_pass;
  50         struct samr_Password nt_verifier, lm_verifier;
  51         uint8_t old_nt_hash[16], new_nt_hash[16];
  52         uint8_t old_lm_hash[16], new_lm_hash[16];
  53         struct samr_DomInfo1 *dominfo = NULL;
  54         struct samr_ChangeReject *reject = NULL;
  55 
  56         /* prepare connect to the SAMR pipe of the users domain PDC */
  57         c.level                    = LIBNET_RPC_CONNECT_PDC;
  58         c.in.name                  = r->samr.in.domain_name;
  59         c.in.dcerpc_iface          = &ndr_table_samr;
  60 
  61         /* 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation) */
  62         status = libnet_RpcConnect(ctx, mem_ctx, &c);
  63         if (!NT_STATUS_IS_OK(status)) {
  64                 r->samr.out.error_string = talloc_asprintf(mem_ctx,
  65                                                 "Connection to SAMR pipe of PDC of domain '%s' failed: %s",
  66                                                 r->samr.in.domain_name, nt_errstr(status));
  67                 return status;
  68         }
  69 
  70         /* prepare password change for account */
  71         server.string = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(c.out.dcerpc_pipe));
  72         account.string = r->samr.in.account_name;
  73 
  74         E_md4hash(r->samr.in.oldpassword, old_nt_hash);
  75         E_md4hash(r->samr.in.newpassword, new_nt_hash);
  76 
  77         E_deshash(r->samr.in.oldpassword, old_lm_hash);
  78         E_deshash(r->samr.in.newpassword, new_lm_hash);
  79 
  80         /* prepare samr_ChangePasswordUser3 */
  81         encode_pw_buffer(lm_pass.data, r->samr.in.newpassword, STR_UNICODE);
  82         arcfour_crypt(lm_pass.data, old_nt_hash, 516);
  83         E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
  84 
  85         encode_pw_buffer(nt_pass.data,  r->samr.in.newpassword, STR_UNICODE);
  86         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
  87         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
  88 
  89         pw3.in.server = &server;
  90         pw3.in.account = &account;
  91         pw3.in.nt_password = &nt_pass;
  92         pw3.in.nt_verifier = &nt_verifier;
  93         pw3.in.lm_change = 1;
  94         pw3.in.lm_password = &lm_pass;
  95         pw3.in.lm_verifier = &lm_verifier;
  96         pw3.in.password3 = NULL;
  97         pw3.out.dominfo = &dominfo;
  98         pw3.out.reject = &reject;
  99 
 100         /* 2. try samr_ChangePasswordUser3 */
 101         status = dcerpc_samr_ChangePasswordUser3(c.out.dcerpc_pipe, mem_ctx, &pw3);
 102         if (!NT_STATUS_IS_OK(status)) {
 103                 r->samr.out.error_string = talloc_asprintf(mem_ctx,
 104                                                 "samr_ChangePasswordUser3 failed: %s",
 105                                                 nt_errstr(status));
 106                 goto ChangePasswordUser2;
 107         }
 108 
 109         /* check result of samr_ChangePasswordUser3 */
 110         if (!NT_STATUS_IS_OK(pw3.out.result)) {
 111                 r->samr.out.error_string = talloc_asprintf(mem_ctx,
 112                                                 "samr_ChangePasswordUser3 for '%s\\%s' failed: %s",
 113                                                 r->samr.in.domain_name, r->samr.in.account_name, 
 114                                                 nt_errstr(pw3.out.result));
 115                                                 /* TODO: give the reason of the reject */
 116                 if (NT_STATUS_EQUAL(pw3.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
 117                         status = pw3.out.result;
 118                         goto disconnect;
 119                 }
 120                 goto ChangePasswordUser2;
 121         }
 122 
 123         goto disconnect;
 124 
 125 ChangePasswordUser2:
 126         /* prepare samr_ChangePasswordUser2 */
 127         encode_pw_buffer(lm_pass.data, r->samr.in.newpassword, STR_ASCII|STR_TERMINATE);
 128         arcfour_crypt(lm_pass.data, old_lm_hash, 516);
 129         E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
 130 
 131         encode_pw_buffer(nt_pass.data, r->samr.in.newpassword, STR_UNICODE);
 132         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
 133         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
 134 
 135         pw2.in.server = &server;
 136         pw2.in.account = &account;
 137         pw2.in.nt_password = &nt_pass;
 138         pw2.in.nt_verifier = &nt_verifier;
 139         pw2.in.lm_change = 1;
 140         pw2.in.lm_password = &lm_pass;
 141         pw2.in.lm_verifier = &lm_verifier;
 142 
 143         /* 3. try samr_ChangePasswordUser2 */
 144         status = dcerpc_samr_ChangePasswordUser2(c.out.dcerpc_pipe, mem_ctx, &pw2);
 145         if (!NT_STATUS_IS_OK(status)) {
 146                 r->samr.out.error_string = talloc_asprintf(mem_ctx,
 147                                                 "samr_ChangePasswordUser2 failed: %s",
 148                                                 nt_errstr(status));
 149                 goto OemChangePasswordUser2;
 150         }
 151 
 152         /* check result of samr_ChangePasswordUser2 */
 153         if (!NT_STATUS_IS_OK(pw2.out.result)) {
 154                 r->samr.out.error_string = talloc_asprintf(mem_ctx,
 155                                                 "samr_ChangePasswordUser2 for '%s\\%s' failed: %s",
 156                                                 r->samr.in.domain_name, r->samr.in.account_name, 
 157                                                 nt_errstr(pw2.out.result));
 158                 if (NT_STATUS_EQUAL(pw2.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
 159                         status = pw2.out.result;
 160                         goto disconnect;
 161                 }
 162                 goto OemChangePasswordUser2;
 163         }
 164 
 165         goto disconnect;
 166 
 167 OemChangePasswordUser2:
 168         /* prepare samr_OemChangePasswordUser2 */
 169         a_server.string = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(c.out.dcerpc_pipe));
 170         a_account.string = r->samr.in.account_name;
 171 
 172         encode_pw_buffer(lm_pass.data, r->samr.in.newpassword, STR_ASCII);
 173         arcfour_crypt(lm_pass.data, old_lm_hash, 516);
 174         E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
 175 
 176         oe2.in.server = &a_server;
 177         oe2.in.account = &a_account;
 178         oe2.in.password = &lm_pass;
 179         oe2.in.hash = &lm_verifier;
 180 
 181         /* 4. try samr_OemChangePasswordUser2 */
 182         status = dcerpc_samr_OemChangePasswordUser2(c.out.dcerpc_pipe, mem_ctx, &oe2);
 183         if (!NT_STATUS_IS_OK(status)) {
 184                 r->samr.out.error_string = talloc_asprintf(mem_ctx,
 185                                                 "samr_OemChangePasswordUser2 failed: %s",
 186                                                 nt_errstr(status));
 187                 goto ChangePasswordUser;
 188         }
 189 
 190         /* check result of samr_OemChangePasswordUser2 */
 191         if (!NT_STATUS_IS_OK(oe2.out.result)) {
 192                 r->samr.out.error_string = talloc_asprintf(mem_ctx,
 193                                                 "samr_OemChangePasswordUser2 for '%s\\%s' failed: %s",
 194                                                 r->samr.in.domain_name, r->samr.in.account_name, 
 195                                                 nt_errstr(oe2.out.result));
 196                 if (NT_STATUS_EQUAL(oe2.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
 197                         status = oe2.out.result;
 198                         goto disconnect;
 199                 }
 200                 goto ChangePasswordUser;
 201         }
 202 
 203         goto disconnect;
 204 
 205 ChangePasswordUser:
 206 #if 0
 207         /* prepare samr_ChangePasswordUser */
 208         E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
 209         E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
 210         E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
 211         E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
 212         E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
 213         E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
 214 
 215         /* TODO: ask for a user_handle */
 216         pw.in.handle = &user_handle;
 217         pw.in.lm_present = 1;
 218         pw.in.old_lm_crypted = &hash1;
 219         pw.in.new_lm_crypted = &hash2;
 220         pw.in.nt_present = 1;
 221         pw.in.old_nt_crypted = &hash3;
 222         pw.in.new_nt_crypted = &hash4;
 223         pw.in.cross1_present = 1;
 224         pw.in.nt_cross = &hash5;
 225         pw.in.cross2_present = 1;
 226         pw.in.lm_cross = &hash6;
 227 
 228         /* 5. try samr_ChangePasswordUser */
 229         status = dcerpc_samr_ChangePasswordUser(c.pdc.out.dcerpc_pipe, mem_ctx, &pw);
 230         if (!NT_STATUS_IS_OK(status)) {
 231                 r->samr.out.error_string = talloc_asprintf(mem_ctx,
 232                                                 "samr_ChangePasswordUser failed: %s",
 233                                                 nt_errstr(status));
 234                 goto disconnect;
 235         }
 236 
 237         /* check result of samr_ChangePasswordUser */
 238         if (!NT_STATUS_IS_OK(pw.out.result)) {
 239                 r->samr.out.error_string = talloc_asprintf(mem_ctx,
 240                                                 "samr_ChangePasswordUser for '%s\\%s' failed: %s",
 241                                                 r->samr.in.domain_name, r->samr.in.account_name, 
 242                                                 nt_errstr(pw.out.result));
 243                 if (NT_STATUS_EQUAL(pw.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
 244                         status = pw.out.result;
 245                         goto disconnect;
 246                 }
 247                 goto disconnect;
 248         }
 249 #endif
 250 disconnect:
 251         /* close connection */
 252         talloc_free(c.out.dcerpc_pipe);
 253 
 254         return status;
 255 }
 256 
 257 static NTSTATUS libnet_ChangePassword_generic(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_ChangePassword *r)
     /* [<][>][^][v][top][bottom][index][help] */
 258 {
 259         NTSTATUS status;
 260         union libnet_ChangePassword r2;
 261 
 262         r2.samr.level           = LIBNET_CHANGE_PASSWORD_SAMR;
 263         r2.samr.in.account_name = r->generic.in.account_name;
 264         r2.samr.in.domain_name  = r->generic.in.domain_name;
 265         r2.samr.in.oldpassword  = r->generic.in.oldpassword;
 266         r2.samr.in.newpassword  = r->generic.in.newpassword;
 267 
 268         status = libnet_ChangePassword(ctx, mem_ctx, &r2);
 269 
 270         r->generic.out.error_string = r2.samr.out.error_string;
 271 
 272         return status;
 273 }
 274 
 275 NTSTATUS libnet_ChangePassword(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_ChangePassword *r)
     /* [<][>][^][v][top][bottom][index][help] */
 276 {
 277         switch (r->generic.level) {
 278                 case LIBNET_CHANGE_PASSWORD_GENERIC:
 279                         return libnet_ChangePassword_generic(ctx, mem_ctx, r);
 280                 case LIBNET_CHANGE_PASSWORD_SAMR:
 281                         return libnet_ChangePassword_samr(ctx, mem_ctx, r);
 282                 case LIBNET_CHANGE_PASSWORD_KRB5:
 283                         return NT_STATUS_NOT_IMPLEMENTED;
 284                 case LIBNET_CHANGE_PASSWORD_LDAP:
 285                         return NT_STATUS_NOT_IMPLEMENTED;
 286                 case LIBNET_CHANGE_PASSWORD_RAP:
 287                         return NT_STATUS_NOT_IMPLEMENTED;
 288         }
 289 
 290         return NT_STATUS_INVALID_LEVEL;
 291 }
 292 
 293 static NTSTATUS libnet_SetPassword_samr_handle_26(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
     /* [<][>][^][v][top][bottom][index][help] */
 294 {
 295         NTSTATUS status;
 296         struct samr_SetUserInfo2 sui;
 297         union samr_UserInfo u_info;
 298         DATA_BLOB session_key;
 299         DATA_BLOB confounded_session_key = data_blob_talloc(mem_ctx, NULL, 16);
 300         uint8_t confounder[16]; 
 301         struct MD5Context md5;
 302 
 303         if (r->samr_handle.in.info21) {
 304                 return NT_STATUS_INVALID_PARAMETER_MIX;
 305         }
 306 
 307         /* prepare samr_SetUserInfo2 level 26 */
 308         ZERO_STRUCT(u_info);
 309         encode_pw_buffer(u_info.info26.password.data, r->samr_handle.in.newpassword, STR_UNICODE);
 310         u_info.info26.password_expired = 0;
 311         
 312         status = dcerpc_fetch_session_key(r->samr_handle.in.dcerpc_pipe, &session_key);
 313         if (!NT_STATUS_IS_OK(status)) {
 314                 r->samr_handle.out.error_string = talloc_asprintf(mem_ctx,
 315                                                                   "dcerpc_fetch_session_key failed: %s",
 316                                                                   nt_errstr(status));
 317                 return status;
 318         }
 319         
 320         generate_random_buffer((uint8_t *)confounder, 16);
 321         
 322         MD5Init(&md5);
 323         MD5Update(&md5, confounder, 16);
 324         MD5Update(&md5, session_key.data, session_key.length);
 325         MD5Final(confounded_session_key.data, &md5);
 326         
 327         arcfour_crypt_blob(u_info.info26.password.data, 516, &confounded_session_key);
 328         memcpy(&u_info.info26.password.data[516], confounder, 16);
 329         
 330         sui.in.user_handle = r->samr_handle.in.user_handle;
 331         sui.in.info = &u_info;
 332         sui.in.level = 26;
 333         
 334         /* 7. try samr_SetUserInfo2 level 26 to set the password */
 335         status = dcerpc_samr_SetUserInfo2(r->samr_handle.in.dcerpc_pipe, mem_ctx, &sui);
 336         /* check result of samr_SetUserInfo2 level 26 */
 337         if (!NT_STATUS_IS_OK(status)) {
 338                 r->samr_handle.out.error_string
 339                         = talloc_asprintf(mem_ctx,
 340                                           "SetUserInfo2 level 26 for [%s] failed: %s",
 341                                           r->samr_handle.in.account_name, nt_errstr(status));
 342         }
 343         return status;
 344 }
 345 
 346 static NTSTATUS libnet_SetPassword_samr_handle_25(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
     /* [<][>][^][v][top][bottom][index][help] */
 347 {
 348         NTSTATUS status;
 349         struct samr_SetUserInfo2 sui;
 350         union samr_UserInfo u_info;
 351         DATA_BLOB session_key;
 352         DATA_BLOB confounded_session_key = data_blob_talloc(mem_ctx, NULL, 16);
 353         uint8_t confounder[16]; 
 354         struct MD5Context md5;
 355 
 356         if (!r->samr_handle.in.info21) {
 357                 return NT_STATUS_INVALID_PARAMETER_MIX;
 358         }
 359 
 360         /* prepare samr_SetUserInfo2 level 25 */
 361         ZERO_STRUCT(u_info);
 362         u_info.info25.info = *r->samr_handle.in.info21;
 363         u_info.info25.info.fields_present |= SAMR_FIELD_NT_PASSWORD_PRESENT;
 364         encode_pw_buffer(u_info.info25.password.data, r->samr_handle.in.newpassword, STR_UNICODE);
 365 
 366         status = dcerpc_fetch_session_key(r->samr_handle.in.dcerpc_pipe, &session_key);
 367         if (!NT_STATUS_IS_OK(status)) {
 368                 r->samr_handle.out.error_string = talloc_asprintf(mem_ctx,
 369                                                 "dcerpc_fetch_session_key failed: %s",
 370                                                 nt_errstr(status));
 371                 return status;
 372         }
 373 
 374         generate_random_buffer((uint8_t *)confounder, 16);
 375 
 376         MD5Init(&md5);
 377         MD5Update(&md5, confounder, 16);
 378         MD5Update(&md5, session_key.data, session_key.length);
 379         MD5Final(confounded_session_key.data, &md5);
 380 
 381         arcfour_crypt_blob(u_info.info25.password.data, 516, &confounded_session_key);
 382         memcpy(&u_info.info25.password.data[516], confounder, 16);
 383 
 384         sui.in.user_handle = r->samr_handle.in.user_handle;
 385         sui.in.info = &u_info;
 386         sui.in.level = 25;
 387 
 388         /* 8. try samr_SetUserInfo2 level 25 to set the password */
 389         status = dcerpc_samr_SetUserInfo2(r->samr_handle.in.dcerpc_pipe, mem_ctx, &sui);
 390         if (!NT_STATUS_IS_OK(status)) {
 391                 r->samr_handle.out.error_string
 392                         = talloc_asprintf(mem_ctx,
 393                                           "SetUserInfo2 level 25 for [%s] failed: %s",
 394                                           r->samr_handle.in.account_name, nt_errstr(status));
 395         }
 396         return status;
 397 }
 398 
 399 static NTSTATUS libnet_SetPassword_samr_handle_24(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
     /* [<][>][^][v][top][bottom][index][help] */
 400 {
 401         NTSTATUS status;
 402         struct samr_SetUserInfo2 sui;
 403         union samr_UserInfo u_info;
 404         DATA_BLOB session_key;
 405 
 406         if (r->samr_handle.in.info21) {
 407                 return NT_STATUS_INVALID_PARAMETER_MIX;
 408         }
 409 
 410         /* prepare samr_SetUserInfo2 level 24 */
 411         ZERO_STRUCT(u_info);
 412         encode_pw_buffer(u_info.info24.password.data, r->samr_handle.in.newpassword, STR_UNICODE);
 413         u_info.info24.password_expired = 0;
 414 
 415         status = dcerpc_fetch_session_key(r->samr_handle.in.dcerpc_pipe, &session_key);
 416         if (!NT_STATUS_IS_OK(status)) {
 417                 r->samr_handle.out.error_string = talloc_asprintf(mem_ctx,
 418                                                 "dcerpc_fetch_session_key failed: %s",
 419                                                 nt_errstr(status));
 420                 return status;
 421         }
 422 
 423         arcfour_crypt_blob(u_info.info24.password.data, 516, &session_key);
 424 
 425         sui.in.user_handle = r->samr_handle.in.user_handle;
 426         sui.in.info = &u_info;
 427         sui.in.level = 24;
 428 
 429         /* 9. try samr_SetUserInfo2 level 24 to set the password */
 430         status = dcerpc_samr_SetUserInfo2(r->samr_handle.in.dcerpc_pipe, mem_ctx, &sui);
 431         if (!NT_STATUS_IS_OK(status)) {
 432                 r->samr_handle.out.error_string
 433                         = talloc_asprintf(mem_ctx,
 434                                           "SetUserInfo2 level 24 for [%s] failed: %s",
 435                                           r->samr_handle.in.account_name, nt_errstr(status));
 436         }
 437         return status;
 438 }
 439 
 440 static NTSTATUS libnet_SetPassword_samr_handle_23(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
     /* [<][>][^][v][top][bottom][index][help] */
 441 {
 442         NTSTATUS status;
 443         struct samr_SetUserInfo2 sui;
 444         union samr_UserInfo u_info;
 445         DATA_BLOB session_key;
 446 
 447         if (!r->samr_handle.in.info21) {
 448                 return NT_STATUS_INVALID_PARAMETER_MIX;
 449         }
 450 
 451         /* prepare samr_SetUserInfo2 level 23 */
 452         ZERO_STRUCT(u_info);
 453         u_info.info23.info = *r->samr_handle.in.info21;
 454         u_info.info23.info.fields_present |= SAMR_FIELD_NT_PASSWORD_PRESENT;
 455         encode_pw_buffer(u_info.info23.password.data, r->samr_handle.in.newpassword, STR_UNICODE);
 456 
 457         status = dcerpc_fetch_session_key(r->samr_handle.in.dcerpc_pipe, &session_key);
 458         if (!NT_STATUS_IS_OK(status)) {
 459                 r->samr_handle.out.error_string
 460                         = talloc_asprintf(mem_ctx,
 461                                           "dcerpc_fetch_session_key failed: %s",
 462                                           nt_errstr(status));
 463                 return status;
 464         }
 465 
 466         arcfour_crypt_blob(u_info.info23.password.data, 516, &session_key);
 467 
 468         sui.in.user_handle = r->samr_handle.in.user_handle;
 469         sui.in.info = &u_info;
 470         sui.in.level = 23;
 471 
 472         /* 10. try samr_SetUserInfo2 level 23 to set the password */
 473         status = dcerpc_samr_SetUserInfo2(r->samr_handle.in.dcerpc_pipe, mem_ctx, &sui);
 474         if (!NT_STATUS_IS_OK(status)) {
 475                 r->samr_handle.out.error_string
 476                         = talloc_asprintf(mem_ctx,
 477                                           "SetUserInfo2 level 23 for [%s] failed: %s",
 478                                           r->samr_handle.in.account_name, nt_errstr(status));
 479         }
 480         return status;
 481 }
 482 
 483 /*
 484  * 1. try samr_SetUserInfo2 level 26 to set the password
 485  * 2. try samr_SetUserInfo2 level 25 to set the password
 486  * 3. try samr_SetUserInfo2 level 24 to set the password
 487  * 4. try samr_SetUserInfo2 level 23 to set the password
 488 */
 489 static NTSTATUS libnet_SetPassword_samr_handle(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
     /* [<][>][^][v][top][bottom][index][help] */
 490 {
 491 
 492         NTSTATUS status;
 493         enum libnet_SetPassword_level levels[] = {
 494                 LIBNET_SET_PASSWORD_SAMR_HANDLE_26,
 495                 LIBNET_SET_PASSWORD_SAMR_HANDLE_25,
 496                 LIBNET_SET_PASSWORD_SAMR_HANDLE_24,
 497                 LIBNET_SET_PASSWORD_SAMR_HANDLE_23,
 498         };
 499         int i;
 500 
 501         for (i=0; i < ARRAY_SIZE(levels); i++) {
 502                 r->generic.level = levels[i];
 503                 status = libnet_SetPassword(ctx, mem_ctx, r);
 504                 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)
 505                     || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER_MIX)
 506                     || NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
 507                         /* Try another password set mechanism */
 508                         continue;
 509                 }
 510                 break;
 511         }
 512         
 513         return status;
 514 }
 515 /*
 516  * set a password with DCERPC/SAMR calls
 517  * 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation)
 518  *    is it correct to contact the the pdc of the domain of the user who's password should be set?
 519  * 2. do a samr_Connect to get a policy handle
 520  * 3. do a samr_LookupDomain to get the domain sid
 521  * 4. do a samr_OpenDomain to get a domain handle
 522  * 5. do a samr_LookupNames to get the users rid
 523  * 6. do a samr_OpenUser to get a user handle
 524  * 7  call libnet_SetPassword_samr_handle to set the password
 525  */
 526 static NTSTATUS libnet_SetPassword_samr(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
     /* [<][>][^][v][top][bottom][index][help] */
 527 {
 528         NTSTATUS status;
 529         struct libnet_RpcConnect c;
 530         struct samr_Connect sc;
 531         struct policy_handle p_handle;
 532         struct samr_LookupDomain ld;
 533         struct dom_sid2 *sid = NULL;
 534         struct lsa_String d_name;
 535         struct samr_OpenDomain od;
 536         struct policy_handle d_handle;
 537         struct samr_LookupNames ln;
 538         struct samr_Ids rids, types;
 539         struct samr_OpenUser ou;
 540         struct policy_handle u_handle;
 541         union libnet_SetPassword r2;
 542 
 543         /* prepare connect to the SAMR pipe of users domain PDC */
 544         c.level               = LIBNET_RPC_CONNECT_PDC;
 545         c.in.name             = r->samr.in.domain_name;
 546         c.in.dcerpc_iface     = &ndr_table_samr;
 547 
 548         /* 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation) */
 549         status = libnet_RpcConnect(ctx, mem_ctx, &c);
 550         if (!NT_STATUS_IS_OK(status)) {
 551                 r->samr.out.error_string = talloc_asprintf(mem_ctx,
 552                                                            "Connection to SAMR pipe of PDC of domain '%s' failed: %s",
 553                                                            r->samr.in.domain_name, nt_errstr(status));
 554                 return status;
 555         }
 556 
 557         /* prepare samr_Connect */
 558         ZERO_STRUCT(p_handle);
 559         sc.in.system_name = NULL;
 560         sc.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
 561         sc.out.connect_handle = &p_handle;
 562 
 563         /* 2. do a samr_Connect to get a policy handle */
 564         status = dcerpc_samr_Connect(c.out.dcerpc_pipe, mem_ctx, &sc);
 565         if (!NT_STATUS_IS_OK(status)) {
 566                 r->samr.out.error_string = talloc_asprintf(mem_ctx,
 567                                                 "samr_Connect failed: %s",
 568                                                 nt_errstr(status));
 569                 goto disconnect;
 570         }
 571 
 572         /* prepare samr_LookupDomain */
 573         d_name.string = r->samr.in.domain_name;
 574         ld.in.connect_handle = &p_handle;
 575         ld.in.domain_name = &d_name;
 576         ld.out.sid = &sid;
 577 
 578         /* 3. do a samr_LookupDomain to get the domain sid */
 579         status = dcerpc_samr_LookupDomain(c.out.dcerpc_pipe, mem_ctx, &ld);
 580         if (!NT_STATUS_IS_OK(status)) {
 581                 r->samr.out.error_string = talloc_asprintf(mem_ctx,
 582                                                 "samr_LookupDomain for [%s] failed: %s",
 583                                                 r->samr.in.domain_name, nt_errstr(status));
 584                 goto disconnect;
 585         }
 586 
 587         /* prepare samr_OpenDomain */
 588         ZERO_STRUCT(d_handle);
 589         od.in.connect_handle = &p_handle;
 590         od.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
 591         od.in.sid = *ld.out.sid;
 592         od.out.domain_handle = &d_handle;
 593 
 594         /* 4. do a samr_OpenDomain to get a domain handle */
 595         status = dcerpc_samr_OpenDomain(c.out.dcerpc_pipe, mem_ctx, &od);
 596         if (!NT_STATUS_IS_OK(status)) {
 597                 r->samr.out.error_string = talloc_asprintf(mem_ctx,
 598                                                 "samr_OpenDomain for [%s] failed: %s",
 599                                                 r->samr.in.domain_name, nt_errstr(status));
 600                 goto disconnect;
 601         }
 602 
 603         /* prepare samr_LookupNames */
 604         ln.in.domain_handle = &d_handle;
 605         ln.in.num_names = 1;
 606         ln.in.names = talloc_array(mem_ctx, struct lsa_String, 1);
 607         ln.out.rids = &rids;
 608         ln.out.types = &types;
 609         if (!ln.in.names) {
 610                 r->samr.out.error_string = "Out of Memory";
 611                 return NT_STATUS_NO_MEMORY;
 612         }
 613         ln.in.names[0].string = r->samr.in.account_name;
 614 
 615         /* 5. do a samr_LookupNames to get the users rid */
 616         status = dcerpc_samr_LookupNames(c.out.dcerpc_pipe, mem_ctx, &ln);
 617         if (!NT_STATUS_IS_OK(status)) {
 618                 r->samr.out.error_string = talloc_asprintf(mem_ctx,
 619                                                 "samr_LookupNames for [%s] failed: %s",
 620                                                 r->samr.in.account_name, nt_errstr(status));
 621                 goto disconnect;
 622         }
 623 
 624         /* check if we got one RID for the user */
 625         if (ln.out.rids->count != 1) {
 626                 r->samr.out.error_string = talloc_asprintf(mem_ctx,
 627                                                 "samr_LookupNames for [%s] returns %d RIDs",
 628                                                 r->samr.in.account_name, ln.out.rids->count);
 629                 status = NT_STATUS_INVALID_PARAMETER;
 630                 goto disconnect;        
 631         }
 632 
 633         /* prepare samr_OpenUser */
 634         ZERO_STRUCT(u_handle);
 635         ou.in.domain_handle = &d_handle;
 636         ou.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
 637         ou.in.rid = ln.out.rids->ids[0];
 638         ou.out.user_handle = &u_handle;
 639 
 640         /* 6. do a samr_OpenUser to get a user handle */
 641         status = dcerpc_samr_OpenUser(c.out.dcerpc_pipe, mem_ctx, &ou);
 642         if (!NT_STATUS_IS_OK(status)) {
 643                 r->samr.out.error_string = talloc_asprintf(mem_ctx,
 644                                                 "samr_OpenUser for [%s] failed: %s",
 645                                                 r->samr.in.account_name, nt_errstr(status));
 646                 goto disconnect;
 647         }
 648 
 649         r2.samr_handle.level            = LIBNET_SET_PASSWORD_SAMR_HANDLE;
 650         r2.samr_handle.in.account_name  = r->samr.in.account_name;
 651         r2.samr_handle.in.newpassword   = r->samr.in.newpassword;
 652         r2.samr_handle.in.user_handle   = &u_handle;
 653         r2.samr_handle.in.dcerpc_pipe   = c.out.dcerpc_pipe;
 654         r2.samr_handle.in.info21        = NULL;
 655 
 656         status = libnet_SetPassword(ctx, mem_ctx, &r2);
 657 
 658         r->generic.out.error_string = r2.samr_handle.out.error_string;
 659 
 660 disconnect:
 661         /* close connection */
 662         talloc_free(c.out.dcerpc_pipe);
 663 
 664         return status;
 665 }
 666 
 667 static NTSTATUS libnet_SetPassword_generic(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
     /* [<][>][^][v][top][bottom][index][help] */
 668 {
 669         NTSTATUS status;
 670         union libnet_SetPassword r2;
 671 
 672         r2.samr.level           = LIBNET_SET_PASSWORD_SAMR;
 673         r2.samr.in.account_name = r->generic.in.account_name;
 674         r2.samr.in.domain_name  = r->generic.in.domain_name;
 675         r2.samr.in.newpassword  = r->generic.in.newpassword;
 676 
 677         r->generic.out.error_string = "Unknown Error";
 678         status = libnet_SetPassword(ctx, mem_ctx, &r2);
 679 
 680         r->generic.out.error_string = r2.samr.out.error_string;
 681 
 682         return status;
 683 }
 684 
 685 NTSTATUS libnet_SetPassword(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
     /* [<][>][^][v][top][bottom][index][help] */
 686 {
 687         switch (r->generic.level) {
 688                 case LIBNET_SET_PASSWORD_GENERIC:
 689                         return libnet_SetPassword_generic(ctx, mem_ctx, r);
 690                 case LIBNET_SET_PASSWORD_SAMR:
 691                         return libnet_SetPassword_samr(ctx, mem_ctx, r);
 692                 case LIBNET_SET_PASSWORD_SAMR_HANDLE:
 693                         return libnet_SetPassword_samr_handle(ctx, mem_ctx, r);
 694                 case LIBNET_SET_PASSWORD_SAMR_HANDLE_26:
 695                         return libnet_SetPassword_samr_handle_26(ctx, mem_ctx, r);
 696                 case LIBNET_SET_PASSWORD_SAMR_HANDLE_25:
 697                         return libnet_SetPassword_samr_handle_25(ctx, mem_ctx, r);
 698                 case LIBNET_SET_PASSWORD_SAMR_HANDLE_24:
 699                         return libnet_SetPassword_samr_handle_24(ctx, mem_ctx, r);
 700                 case LIBNET_SET_PASSWORD_SAMR_HANDLE_23:
 701                         return libnet_SetPassword_samr_handle_23(ctx, mem_ctx, r);
 702                 case LIBNET_SET_PASSWORD_KRB5:
 703                         return NT_STATUS_NOT_IMPLEMENTED;
 704                 case LIBNET_SET_PASSWORD_LDAP:
 705                         return NT_STATUS_NOT_IMPLEMENTED;
 706                 case LIBNET_SET_PASSWORD_RAP:
 707                         return NT_STATUS_NOT_IMPLEMENTED;
 708         }
 709 
 710         return NT_STATUS_INVALID_LEVEL;
 711 }

/* [<][>][^][v][top][bottom][index][help] */