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