mirror of
				https://github.com/samba-team/samba.git
				synced 2025-11-04 00:23:49 +03:00 
			
		
		
		
	r1952: change the _RPC levels into _SAMR
because we may have other rpc levels in future add more comments about what's going on check the rsult of samr_OpenUser metze
This commit is contained in:
		
				
					committed by
					
						
						Gerald (Jerry) Carter
					
				
			
			
				
	
			
			
			
						parent
						
							b660e5b9e6
						
					
				
				
					commit
					741f95909b
				
			@@ -79,7 +79,7 @@ union libnet_rpc_connect {
 | 
			
		||||
/* struct and enum for doing a remote password change */
 | 
			
		||||
enum libnet_ChangePassword_level {
 | 
			
		||||
	LIBNET_CHANGE_PASSWORD_GENERIC,
 | 
			
		||||
	LIBNET_CHANGE_PASSWORD_RPC,
 | 
			
		||||
	LIBNET_CHANGE_PASSWORD_SAMR,
 | 
			
		||||
	LIBNET_CHANGE_PASSWORD_KRB5,
 | 
			
		||||
	LIBNET_CHANGE_PASSWORD_LDAP,
 | 
			
		||||
	LIBNET_CHANGE_PASSWORD_RAP
 | 
			
		||||
@@ -105,7 +105,7 @@ union libnet_ChangePassword {
 | 
			
		||||
		enum libnet_ChangePassword_level level;
 | 
			
		||||
		struct _libnet_ChangePassword_in in;
 | 
			
		||||
		struct _libnet_ChangePassword_out out;
 | 
			
		||||
	} rpc;
 | 
			
		||||
	} samr;
 | 
			
		||||
 | 
			
		||||
	struct {
 | 
			
		||||
		enum libnet_ChangePassword_level level;
 | 
			
		||||
@@ -129,7 +129,7 @@ union libnet_ChangePassword {
 | 
			
		||||
/* struct and enum for doing a remote password set */
 | 
			
		||||
enum libnet_SetPassword_level {
 | 
			
		||||
	LIBNET_SET_PASSWORD_GENERIC,
 | 
			
		||||
	LIBNET_SET_PASSWORD_RPC,
 | 
			
		||||
	LIBNET_SET_PASSWORD_SAMR,
 | 
			
		||||
	LIBNET_SET_PASSWORD_KRB5,
 | 
			
		||||
	LIBNET_SET_PASSWORD_LDAP,
 | 
			
		||||
	LIBNET_SET_PASSWORD_RAP
 | 
			
		||||
@@ -154,7 +154,7 @@ union libnet_SetPassword {
 | 
			
		||||
		enum libnet_SetPassword_level level;
 | 
			
		||||
		struct _libnet_SetPassword_in in;
 | 
			
		||||
		struct _libnet_SetPassword_out out;
 | 
			
		||||
	} rpc;
 | 
			
		||||
	} samr;
 | 
			
		||||
 | 
			
		||||
	struct {
 | 
			
		||||
		enum libnet_SetPassword_level level;
 | 
			
		||||
 
 | 
			
		||||
@@ -23,9 +23,12 @@
 | 
			
		||||
/*
 | 
			
		||||
 * do a password change using DCERPC/SAMR calls
 | 
			
		||||
 * 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation)
 | 
			
		||||
 * 2. try samr_ChangePassword3
 | 
			
		||||
 * 2. try samr_ChangePasswordUser3
 | 
			
		||||
 * 3. try samr_ChangePasswordUser2
 | 
			
		||||
 * 4. try samr_OemChangePasswordUser2
 | 
			
		||||
 * (not yet: 5. try samr_ChangePasswordUser)
 | 
			
		||||
 */
 | 
			
		||||
static NTSTATUS libnet_ChangePassword_rpc(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_ChangePassword *r)
 | 
			
		||||
static NTSTATUS libnet_ChangePassword_samr(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_ChangePassword *r)
 | 
			
		||||
{
 | 
			
		||||
        NTSTATUS status;
 | 
			
		||||
	union libnet_rpc_connect c;
 | 
			
		||||
@@ -44,37 +47,38 @@ static NTSTATUS libnet_ChangePassword_rpc(struct libnet_context *ctx, TALLOC_CTX
 | 
			
		||||
	uint8_t old_nt_hash[16], new_nt_hash[16];
 | 
			
		||||
	uint8_t old_lm_hash[16], new_lm_hash[16];
 | 
			
		||||
 | 
			
		||||
	/* prepare connect to the SAMR pipe of the */
 | 
			
		||||
	/* prepare connect to the SAMR pipe of the users domain PDC */
 | 
			
		||||
	c.pdc.level			= LIBNET_RPC_CONNECT_PDC;
 | 
			
		||||
	c.pdc.in.domain_name		= r->rpc.in.domain_name;
 | 
			
		||||
	c.pdc.in.domain_name		= r->samr.in.domain_name;
 | 
			
		||||
	c.pdc.in.dcerpc_iface_name	= DCERPC_SAMR_NAME;
 | 
			
		||||
	c.pdc.in.dcerpc_iface_uuid	= DCERPC_SAMR_UUID;
 | 
			
		||||
	c.pdc.in.dcerpc_iface_version	= DCERPC_SAMR_VERSION;
 | 
			
		||||
 | 
			
		||||
	/* do connect to the SAMR pipe of the */
 | 
			
		||||
	/* 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation) */
 | 
			
		||||
	status = libnet_rpc_connect(ctx, mem_ctx, &c);
 | 
			
		||||
	if (!NT_STATUS_IS_OK(status)) {
 | 
			
		||||
		r->rpc.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
		r->samr.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
						"Connection to SAMR pipe of PDC of domain '%s' failed: %s\n",
 | 
			
		||||
						r->rpc.in.domain_name, nt_errstr(status));
 | 
			
		||||
						r->samr.in.domain_name, nt_errstr(status));
 | 
			
		||||
		return status;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* prepare password change for account */
 | 
			
		||||
	server.name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(c.pdc.out.dcerpc_pipe));
 | 
			
		||||
	account.name = r->rpc.in.account_name;
 | 
			
		||||
	account.name = r->samr.in.account_name;
 | 
			
		||||
 | 
			
		||||
	E_md4hash(r->rpc.in.oldpassword, old_nt_hash);
 | 
			
		||||
	E_md4hash(r->rpc.in.newpassword, new_nt_hash);
 | 
			
		||||
	E_md4hash(r->samr.in.oldpassword, old_nt_hash);
 | 
			
		||||
	E_md4hash(r->samr.in.newpassword, new_nt_hash);
 | 
			
		||||
 | 
			
		||||
	E_deshash(r->rpc.in.oldpassword, old_lm_hash);
 | 
			
		||||
	E_deshash(r->rpc.in.newpassword, new_lm_hash);
 | 
			
		||||
	E_deshash(r->samr.in.oldpassword, old_lm_hash);
 | 
			
		||||
	E_deshash(r->samr.in.newpassword, new_lm_hash);
 | 
			
		||||
 | 
			
		||||
	encode_pw_buffer(lm_pass.data, r->rpc.in.newpassword, STR_UNICODE);
 | 
			
		||||
	/* prepare samr_ChangePasswordUser3 */
 | 
			
		||||
	encode_pw_buffer(lm_pass.data, r->samr.in.newpassword, STR_UNICODE);
 | 
			
		||||
	arcfour_crypt(lm_pass.data, old_nt_hash, 516);
 | 
			
		||||
	E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
 | 
			
		||||
 | 
			
		||||
	encode_pw_buffer(nt_pass.data,  r->rpc.in.newpassword, STR_UNICODE);
 | 
			
		||||
	encode_pw_buffer(nt_pass.data,  r->samr.in.newpassword, STR_UNICODE);
 | 
			
		||||
	arcfour_crypt(nt_pass.data, old_nt_hash, 516);
 | 
			
		||||
	E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
 | 
			
		||||
 | 
			
		||||
@@ -87,20 +91,20 @@ static NTSTATUS libnet_ChangePassword_rpc(struct libnet_context *ctx, TALLOC_CTX
 | 
			
		||||
	pw3.in.lm_verifier = &lm_verifier;
 | 
			
		||||
	pw3.in.password3 = NULL;
 | 
			
		||||
 | 
			
		||||
	/* do password change for account */
 | 
			
		||||
	/* 2. try samr_ChangePasswordUser3 */
 | 
			
		||||
	status = dcerpc_samr_ChangePasswordUser3(c.pdc.out.dcerpc_pipe, mem_ctx, &pw3);
 | 
			
		||||
	if (!NT_STATUS_IS_OK(status)) {
 | 
			
		||||
		r->rpc.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
		r->samr.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
						"samr_ChangePasswordUser3 failed: %s\n",
 | 
			
		||||
						nt_errstr(status));
 | 
			
		||||
		goto ChangePasswordUser2;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* check result of password change */
 | 
			
		||||
	/* check result of samr_ChangePasswordUser3 */
 | 
			
		||||
	if (!NT_STATUS_IS_OK(pw3.out.result)) {
 | 
			
		||||
		r->rpc.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
		r->samr.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
						"samr_ChangePasswordUser3 for '%s\\%s' failed: %s\n",
 | 
			
		||||
						r->rpc.in.domain_name, r->rpc.in.account_name, 
 | 
			
		||||
						r->samr.in.domain_name, r->samr.in.account_name, 
 | 
			
		||||
						nt_errstr(pw3.out.result));
 | 
			
		||||
						/* TODO: give the reason of the reject */
 | 
			
		||||
		if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
 | 
			
		||||
@@ -112,12 +116,12 @@ static NTSTATUS libnet_ChangePassword_rpc(struct libnet_context *ctx, TALLOC_CTX
 | 
			
		||||
	goto disconnect;
 | 
			
		||||
 | 
			
		||||
ChangePasswordUser2:
 | 
			
		||||
 | 
			
		||||
	encode_pw_buffer(lm_pass.data, r->rpc.in.newpassword, STR_ASCII|STR_TERMINATE);
 | 
			
		||||
	/* prepare samr_ChangePasswordUser2 */
 | 
			
		||||
	encode_pw_buffer(lm_pass.data, r->samr.in.newpassword, STR_ASCII|STR_TERMINATE);
 | 
			
		||||
	arcfour_crypt(lm_pass.data, old_lm_hash, 516);
 | 
			
		||||
	E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
 | 
			
		||||
 | 
			
		||||
	encode_pw_buffer(nt_pass.data, r->rpc.in.newpassword, STR_UNICODE);
 | 
			
		||||
	encode_pw_buffer(nt_pass.data, r->samr.in.newpassword, STR_UNICODE);
 | 
			
		||||
	arcfour_crypt(nt_pass.data, old_nt_hash, 516);
 | 
			
		||||
	E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
 | 
			
		||||
 | 
			
		||||
@@ -129,19 +133,20 @@ ChangePasswordUser2:
 | 
			
		||||
	pw2.in.lm_password = &lm_pass;
 | 
			
		||||
	pw2.in.lm_verifier = &lm_verifier;
 | 
			
		||||
 | 
			
		||||
	/* 3. try samr_ChangePasswordUser2 */
 | 
			
		||||
	status = dcerpc_samr_ChangePasswordUser2(c.pdc.out.dcerpc_pipe, mem_ctx, &pw2);
 | 
			
		||||
	if (!NT_STATUS_IS_OK(status)) {
 | 
			
		||||
		r->rpc.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
		r->samr.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
						"samr_ChangePasswordUser2 failed: %s\n",
 | 
			
		||||
						nt_errstr(status));
 | 
			
		||||
		goto OemChangePasswordUser2;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* check result of password change */
 | 
			
		||||
	/* check result of samr_ChangePasswordUser2 */
 | 
			
		||||
	if (!NT_STATUS_IS_OK(pw2.out.result)) {
 | 
			
		||||
		r->rpc.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
		r->samr.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
						"samr_ChangePasswordUser2 for '%s\\%s' failed: %s\n",
 | 
			
		||||
						r->rpc.in.domain_name, r->rpc.in.account_name, 
 | 
			
		||||
						r->samr.in.domain_name, r->samr.in.account_name, 
 | 
			
		||||
						nt_errstr(pw2.out.result));
 | 
			
		||||
		goto OemChangePasswordUser2;
 | 
			
		||||
	}
 | 
			
		||||
@@ -149,11 +154,11 @@ ChangePasswordUser2:
 | 
			
		||||
	goto disconnect;
 | 
			
		||||
 | 
			
		||||
OemChangePasswordUser2:
 | 
			
		||||
 | 
			
		||||
	/* prepare samr_OemChangePasswordUser2 */
 | 
			
		||||
	a_server.name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(c.pdc.out.dcerpc_pipe));
 | 
			
		||||
	a_account.name = r->rpc.in.account_name;
 | 
			
		||||
	a_account.name = r->samr.in.account_name;
 | 
			
		||||
 | 
			
		||||
	encode_pw_buffer(lm_pass.data, r->rpc.in.newpassword, STR_ASCII);
 | 
			
		||||
	encode_pw_buffer(lm_pass.data, r->samr.in.newpassword, STR_ASCII);
 | 
			
		||||
	arcfour_crypt(lm_pass.data, old_lm_hash, 516);
 | 
			
		||||
	E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
 | 
			
		||||
 | 
			
		||||
@@ -162,19 +167,20 @@ OemChangePasswordUser2:
 | 
			
		||||
	oe2.in.password = &lm_pass;
 | 
			
		||||
	oe2.in.hash = &lm_verifier;
 | 
			
		||||
 | 
			
		||||
	/* 4. try samr_OemChangePasswordUser2 */
 | 
			
		||||
	status = dcerpc_samr_OemChangePasswordUser2(c.pdc.out.dcerpc_pipe, mem_ctx, &oe2);
 | 
			
		||||
	if (!NT_STATUS_IS_OK(status)) {
 | 
			
		||||
		r->rpc.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
		r->samr.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
						"samr_OemChangePasswordUser2 failed: %s\n",
 | 
			
		||||
						nt_errstr(status));
 | 
			
		||||
		goto ChangePasswordUser;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* check result of password change */
 | 
			
		||||
	/* check result of samr_OemChangePasswordUser2 */
 | 
			
		||||
	if (!NT_STATUS_IS_OK(oe2.out.result)) {
 | 
			
		||||
		r->rpc.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
		r->samr.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
						"samr_OemChangePasswordUser2 for '%s\\%s' failed: %s\n",
 | 
			
		||||
						r->rpc.in.domain_name, r->rpc.in.account_name, 
 | 
			
		||||
						r->samr.in.domain_name, r->samr.in.account_name, 
 | 
			
		||||
						nt_errstr(oe2.out.result));
 | 
			
		||||
		goto ChangePasswordUser;
 | 
			
		||||
	}
 | 
			
		||||
@@ -183,6 +189,7 @@ OemChangePasswordUser2:
 | 
			
		||||
 | 
			
		||||
ChangePasswordUser:
 | 
			
		||||
#if 0
 | 
			
		||||
	/* prepare samr_ChangePasswordUser */
 | 
			
		||||
	E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
 | 
			
		||||
	E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
 | 
			
		||||
	E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
 | 
			
		||||
@@ -203,19 +210,20 @@ ChangePasswordUser:
 | 
			
		||||
	pw.in.cross2_present = 1;
 | 
			
		||||
	pw.in.lm_cross = &hash6;
 | 
			
		||||
 | 
			
		||||
	/* 5. try samr_ChangePasswordUser */
 | 
			
		||||
	status = dcerpc_samr_ChangePasswordUser(c.pdc.out.dcerpc_pipe, mem_ctx, &pw);
 | 
			
		||||
	if (!NT_STATUS_IS_OK(status)) {
 | 
			
		||||
		r->rpc.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
		r->samr.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
						"samr_ChangePasswordUser failed: %s\n",
 | 
			
		||||
						nt_errstr(status));
 | 
			
		||||
		goto disconnect;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* check result of password change */
 | 
			
		||||
	/* check result of samr_ChangePasswordUser */
 | 
			
		||||
	if (!NT_STATUS_IS_OK(pw.out.result)) {
 | 
			
		||||
		r->rpc.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
		r->samr.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
						"samr_ChangePasswordUser for '%s\\%s' failed: %s\n",
 | 
			
		||||
						r->rpc.in.domain_name, r->rpc.in.account_name, 
 | 
			
		||||
						r->samr.in.domain_name, r->samr.in.account_name, 
 | 
			
		||||
						nt_errstr(pw.out.result));
 | 
			
		||||
		goto disconnect;
 | 
			
		||||
	}
 | 
			
		||||
@@ -232,15 +240,15 @@ static NTSTATUS libnet_ChangePassword_generic(struct libnet_context *ctx, TALLOC
 | 
			
		||||
	NTSTATUS status;
 | 
			
		||||
	union libnet_ChangePassword r2;
 | 
			
		||||
 | 
			
		||||
	r2.rpc.level		= LIBNET_CHANGE_PASSWORD_RPC;
 | 
			
		||||
	r2.rpc.in.account_name	= r->generic.in.account_name;
 | 
			
		||||
	r2.rpc.in.domain_name	= r->generic.in.domain_name;
 | 
			
		||||
	r2.rpc.in.oldpassword	= r->generic.in.oldpassword;
 | 
			
		||||
	r2.rpc.in.newpassword	= r->generic.in.newpassword;
 | 
			
		||||
	r2.samr.level		= LIBNET_CHANGE_PASSWORD_SAMR;
 | 
			
		||||
	r2.samr.in.account_name	= r->generic.in.account_name;
 | 
			
		||||
	r2.samr.in.domain_name	= r->generic.in.domain_name;
 | 
			
		||||
	r2.samr.in.oldpassword	= r->generic.in.oldpassword;
 | 
			
		||||
	r2.samr.in.newpassword	= r->generic.in.newpassword;
 | 
			
		||||
 | 
			
		||||
	status = libnet_ChangePassword(ctx, mem_ctx, &r2);
 | 
			
		||||
 | 
			
		||||
	r->generic.out.error_string = r2.rpc.out.error_string;
 | 
			
		||||
	r->generic.out.error_string = r2.samr.out.error_string;
 | 
			
		||||
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
@@ -250,8 +258,8 @@ NTSTATUS libnet_ChangePassword(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
 | 
			
		||||
	switch (r->generic.level) {
 | 
			
		||||
		case LIBNET_CHANGE_PASSWORD_GENERIC:
 | 
			
		||||
			return libnet_ChangePassword_generic(ctx, mem_ctx, r);
 | 
			
		||||
		case LIBNET_CHANGE_PASSWORD_RPC:
 | 
			
		||||
			return libnet_ChangePassword_rpc(ctx, mem_ctx, r);
 | 
			
		||||
		case LIBNET_CHANGE_PASSWORD_SAMR:
 | 
			
		||||
			return libnet_ChangePassword_samr(ctx, mem_ctx, r);
 | 
			
		||||
		case LIBNET_CHANGE_PASSWORD_KRB5:
 | 
			
		||||
			return NT_STATUS_NOT_IMPLEMENTED;
 | 
			
		||||
		case LIBNET_CHANGE_PASSWORD_LDAP:
 | 
			
		||||
@@ -265,10 +273,16 @@ NTSTATUS libnet_ChangePassword(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * set a password with DCERPC/SAMR calls
 | 
			
		||||
 *
 | 
			
		||||
 * is it correct to contact the the pdc of the domain of the user who's password should be set?
 | 
			
		||||
 * 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation)
 | 
			
		||||
 *    is it correct to contact the the pdc of the domain of the user who's password should be set?
 | 
			
		||||
 * 2. do a samr_Connect to get a policy handle
 | 
			
		||||
 * 3. do a samr_LookupDomain to get the domain sid
 | 
			
		||||
 * 4. do a samr_OpenDomain to get a domain handle
 | 
			
		||||
 * 5. do a samr_LookupNames to get the users rid
 | 
			
		||||
 * 6. do a samr_OpenUser to get a user handle
 | 
			
		||||
 * 7. try samr_SetUserInfo level 26 to set the password
 | 
			
		||||
 */
 | 
			
		||||
static NTSTATUS libnet_SetPassword_rpc(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
 | 
			
		||||
static NTSTATUS libnet_SetPassword_samr(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
 | 
			
		||||
{
 | 
			
		||||
	NTSTATUS status;
 | 
			
		||||
	union libnet_rpc_connect c;
 | 
			
		||||
@@ -288,138 +302,157 @@ static NTSTATUS libnet_SetPassword_rpc(struct libnet_context *ctx, TALLOC_CTX *m
 | 
			
		||||
	uint8_t confounder[16];	
 | 
			
		||||
	struct MD5Context md5;
 | 
			
		||||
 | 
			
		||||
	/* prepare connect to the SAMR pipe of the */
 | 
			
		||||
	/* prepare connect to the SAMR pipe of users domain PDC */
 | 
			
		||||
	c.pdc.level			= LIBNET_RPC_CONNECT_PDC;
 | 
			
		||||
	c.pdc.in.domain_name		= r->rpc.in.domain_name;
 | 
			
		||||
	c.pdc.in.domain_name		= r->samr.in.domain_name;
 | 
			
		||||
	c.pdc.in.dcerpc_iface_name	= DCERPC_SAMR_NAME;
 | 
			
		||||
	c.pdc.in.dcerpc_iface_uuid	= DCERPC_SAMR_UUID;
 | 
			
		||||
	c.pdc.in.dcerpc_iface_version	= DCERPC_SAMR_VERSION;
 | 
			
		||||
 | 
			
		||||
	/* do connect to the SAMR pipe of the */
 | 
			
		||||
	/* 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation) */
 | 
			
		||||
	status = libnet_rpc_connect(ctx, mem_ctx, &c);
 | 
			
		||||
	if (!NT_STATUS_IS_OK(status)) {
 | 
			
		||||
		r->rpc.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
		r->samr.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
						"Connection to SAMR pipe of PDC of domain '%s' failed: %s\n",
 | 
			
		||||
						r->rpc.in.domain_name, nt_errstr(status));
 | 
			
		||||
						r->samr.in.domain_name, nt_errstr(status));
 | 
			
		||||
		return status;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* do a samr_Connect to get a policy handle */
 | 
			
		||||
	/* prepare samr_Connect */
 | 
			
		||||
	ZERO_STRUCT(p_handle);
 | 
			
		||||
	sc.in.system_name = 0;
 | 
			
		||||
	sc.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
 | 
			
		||||
	sc.out.handle = &p_handle;
 | 
			
		||||
 | 
			
		||||
	/* 2. do a samr_Connect to get a policy handle */
 | 
			
		||||
	status = dcerpc_samr_Connect(c.pdc.out.dcerpc_pipe, mem_ctx, &sc);
 | 
			
		||||
	if (!NT_STATUS_IS_OK(status)) {
 | 
			
		||||
		r->rpc.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
		r->samr.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
						"samr_Connect failed: %s\n",
 | 
			
		||||
						nt_errstr(status));
 | 
			
		||||
		goto disconnect;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* check result of samr_connect */
 | 
			
		||||
	/* check result of samr_Connect */
 | 
			
		||||
	if (!NT_STATUS_IS_OK(sc.out.result)) {
 | 
			
		||||
		r->rpc.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
		r->samr.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
						"samr_Connect failed: %s\n", 
 | 
			
		||||
						nt_errstr(sc.out.result));
 | 
			
		||||
		goto disconnect;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* do a samr_LookupDomain */
 | 
			
		||||
	d_name.name = r->rpc.in.domain_name;
 | 
			
		||||
	/* prepare samr_LookupDomain */
 | 
			
		||||
	d_name.name = r->samr.in.domain_name;
 | 
			
		||||
	ld.in.handle = &p_handle;
 | 
			
		||||
	ld.in.domain = &d_name;
 | 
			
		||||
 | 
			
		||||
	/* 3. do a samr_LookupDomain to get the domain sid */
 | 
			
		||||
	status = dcerpc_samr_LookupDomain(c.pdc.out.dcerpc_pipe, mem_ctx, &ld);
 | 
			
		||||
	if (!NT_STATUS_IS_OK(status)) {
 | 
			
		||||
		r->rpc.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
		r->samr.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
						"samr_LookupDomain for [%s] failed: %s\n",
 | 
			
		||||
						r->rpc.in.domain_name, nt_errstr(status));
 | 
			
		||||
						r->samr.in.domain_name, nt_errstr(status));
 | 
			
		||||
		goto disconnect;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* check result of samr_LookupDomain */
 | 
			
		||||
	if (!NT_STATUS_IS_OK(ld.out.result)) {
 | 
			
		||||
		r->rpc.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
		r->samr.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
						"samr_LookupDomain for [%s] failed: %s\n",
 | 
			
		||||
						r->rpc.in.domain_name, nt_errstr(ld.out.result));
 | 
			
		||||
						r->samr.in.domain_name, nt_errstr(ld.out.result));
 | 
			
		||||
		goto disconnect;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* do a samr_OpenDomain to get a domain handle */
 | 
			
		||||
	/* prepare samr_OpenDomain */
 | 
			
		||||
	ZERO_STRUCT(d_handle);
 | 
			
		||||
	od.in.handle = &p_handle;
 | 
			
		||||
	od.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
 | 
			
		||||
	od.in.sid = ld.out.sid;
 | 
			
		||||
	od.out.domain_handle = &d_handle;
 | 
			
		||||
 | 
			
		||||
	/* 4. do a samr_OpenDomain to get a domain handle */
 | 
			
		||||
	status = dcerpc_samr_OpenDomain(c.pdc.out.dcerpc_pipe, mem_ctx, &od);
 | 
			
		||||
	if (!NT_STATUS_IS_OK(status)) {
 | 
			
		||||
		r->rpc.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
		r->samr.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
						"samr_OpenDomain for [%s] failed: %s\n",
 | 
			
		||||
						r->rpc.in.domain_name, nt_errstr(status));
 | 
			
		||||
						r->samr.in.domain_name, nt_errstr(status));
 | 
			
		||||
		goto disconnect;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* check result of samr_LookupDomain */
 | 
			
		||||
	/* check result of samr_OpenDomain */
 | 
			
		||||
	if (!NT_STATUS_IS_OK(od.out.result)) {
 | 
			
		||||
		r->rpc.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
		r->samr.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
						"samr_OpenDomain for [%s] failed: %s\n",
 | 
			
		||||
						r->rpc.in.domain_name, nt_errstr(od.out.result));
 | 
			
		||||
						r->samr.in.domain_name, nt_errstr(od.out.result));
 | 
			
		||||
		goto disconnect;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* do a samr_LookupNames for the account_name to get the RID */
 | 
			
		||||
	/* prepare samr_LookupNames */
 | 
			
		||||
	ln.in.handle = &d_handle;
 | 
			
		||||
	ln.in.num_names = 1;
 | 
			
		||||
	ln.in.names = talloc_array_p(mem_ctx, struct samr_Name, 1);
 | 
			
		||||
	if (!ln.in.names) {
 | 
			
		||||
		r->rpc.out.error_string = "Out of Memory";
 | 
			
		||||
		r->samr.out.error_string = "Out of Memory";
 | 
			
		||||
		return NT_STATUS_NO_MEMORY;
 | 
			
		||||
	}
 | 
			
		||||
	ln.in.names[0].name = r->rpc.in.account_name;
 | 
			
		||||
	ln.in.names[0].name = r->samr.in.account_name;
 | 
			
		||||
 | 
			
		||||
	/* 5. do a samr_LookupNames to get the users rid */
 | 
			
		||||
	status = dcerpc_samr_LookupNames(c.pdc.out.dcerpc_pipe, mem_ctx, &ln);
 | 
			
		||||
	if (!NT_STATUS_IS_OK(status)) {
 | 
			
		||||
		r->rpc.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
		r->samr.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
						"samr_LookupNames for [%s] failed: %s\n",
 | 
			
		||||
						r->rpc.in.account_name, nt_errstr(status));
 | 
			
		||||
						r->samr.in.account_name, nt_errstr(status));
 | 
			
		||||
		goto disconnect;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* check result of samr_LookupDomain */
 | 
			
		||||
	/* check result of samr_LookupNames */
 | 
			
		||||
	if (!NT_STATUS_IS_OK(ln.out.result)) {
 | 
			
		||||
		r->rpc.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
		r->samr.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
						"samr_LookupNames for [%s] failed: %s\n",
 | 
			
		||||
						r->rpc.in.account_name, nt_errstr(ln.out.result));
 | 
			
		||||
						r->samr.in.account_name, nt_errstr(ln.out.result));
 | 
			
		||||
		goto disconnect;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* check if we got one RID for the user */
 | 
			
		||||
	if (ln.out.rids.count != 1) {
 | 
			
		||||
		r->rpc.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
		r->samr.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
						"samr_LookupNames for [%s] returns %d RIDs\n",
 | 
			
		||||
						r->rpc.in.account_name, ln.out.rids.count);
 | 
			
		||||
						r->samr.in.account_name, ln.out.rids.count);
 | 
			
		||||
		goto disconnect;	
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* do samr_OpenUser to get the user handle */
 | 
			
		||||
	/* prepare samr_OpenUser */
 | 
			
		||||
	ZERO_STRUCT(u_handle);
 | 
			
		||||
	ou.in.handle = &d_handle;
 | 
			
		||||
	ou.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
 | 
			
		||||
	ou.in.rid = ln.out.rids.ids[0];
 | 
			
		||||
	ou.out.acct_handle = &u_handle;
 | 
			
		||||
 | 
			
		||||
	/* 6. do a samr_OpenUser to get a user handle */
 | 
			
		||||
	status = dcerpc_samr_OpenUser(c.pdc.out.dcerpc_pipe, mem_ctx, &ou);
 | 
			
		||||
	if (!NT_STATUS_IS_OK(status)) {
 | 
			
		||||
		r->samr.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
						"samr_OpenUser for [%s] failed: %s\n",
 | 
			
		||||
						r->samr.in.account_name, nt_errstr(status));
 | 
			
		||||
		goto disconnect;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* prepare password set with samr_UserInfo26 */
 | 
			
		||||
	encode_pw_buffer(u_info.info26.password.data, r->rpc.in.newpassword, STR_UNICODE);
 | 
			
		||||
	u_info.info26.pw_len = strlen(r->rpc.in.newpassword);
 | 
			
		||||
	/* check result of samr_OpenUser */
 | 
			
		||||
	if (!NT_STATUS_IS_OK(ou.out.result)) {
 | 
			
		||||
		r->samr.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
						"samr_OpenUser for [%s] failed: %s\n",
 | 
			
		||||
						r->samr.in.account_name, nt_errstr(ou.out.result));
 | 
			
		||||
		goto disconnect;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* prepare samr_SetUserInfo level 26 */
 | 
			
		||||
	encode_pw_buffer(u_info.info26.password.data, r->samr.in.newpassword, STR_UNICODE);
 | 
			
		||||
	u_info.info26.pw_len = strlen(r->samr.in.newpassword);
 | 
			
		||||
 | 
			
		||||
	status = dcerpc_fetch_session_key(c.pdc.out.dcerpc_pipe, &session_key);
 | 
			
		||||
	if (!NT_STATUS_IS_OK(status)) {
 | 
			
		||||
		r->rpc.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
		r->samr.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
						"dcerpc_fetch_session_key failed: %s\n",
 | 
			
		||||
						nt_errstr(status));
 | 
			
		||||
		goto disconnect;
 | 
			
		||||
@@ -439,19 +472,20 @@ static NTSTATUS libnet_SetPassword_rpc(struct libnet_context *ctx, TALLOC_CTX *m
 | 
			
		||||
	sui.in.info = &u_info;
 | 
			
		||||
	sui.in.level = 26;
 | 
			
		||||
 | 
			
		||||
	/* 7. try samr_SetUserInfo level 26 to set the password */
 | 
			
		||||
	status = dcerpc_samr_SetUserInfo(c.pdc.out.dcerpc_pipe, mem_ctx, &sui);
 | 
			
		||||
	if (!NT_STATUS_IS_OK(status)) {
 | 
			
		||||
		r->rpc.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
		r->samr.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
						"SetUserInfo level 26 for [%s] failed: %s\n",
 | 
			
		||||
						r->rpc.in.account_name, nt_errstr(status));
 | 
			
		||||
						r->samr.in.account_name, nt_errstr(status));
 | 
			
		||||
		goto UserInfo25;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* check result of samr_LookupDomain */
 | 
			
		||||
	/* check result of samr_SetUserInfo level 26 */
 | 
			
		||||
	if (!NT_STATUS_IS_OK(sui.out.result)) {
 | 
			
		||||
		r->rpc.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
		r->samr.out.error_string = talloc_asprintf(mem_ctx,
 | 
			
		||||
						"SetUserInfo level 26 for [%s] failed: %s\n",
 | 
			
		||||
						r->rpc.in.account_name, nt_errstr(sui.out.result));
 | 
			
		||||
						r->samr.in.account_name, nt_errstr(sui.out.result));
 | 
			
		||||
		goto UserInfo25;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -469,14 +503,14 @@ static NTSTATUS libnet_SetPassword_generic(struct libnet_context *ctx, TALLOC_CT
 | 
			
		||||
	NTSTATUS status;
 | 
			
		||||
	union libnet_SetPassword r2;
 | 
			
		||||
 | 
			
		||||
	r2.rpc.level		= LIBNET_SET_PASSWORD_RPC;
 | 
			
		||||
	r2.rpc.in.account_name	= r->generic.in.account_name;
 | 
			
		||||
	r2.rpc.in.domain_name	= r->generic.in.domain_name;
 | 
			
		||||
	r2.rpc.in.newpassword	= r->generic.in.newpassword;
 | 
			
		||||
	r2.samr.level		= LIBNET_SET_PASSWORD_SAMR;
 | 
			
		||||
	r2.samr.in.account_name	= r->generic.in.account_name;
 | 
			
		||||
	r2.samr.in.domain_name	= r->generic.in.domain_name;
 | 
			
		||||
	r2.samr.in.newpassword	= r->generic.in.newpassword;
 | 
			
		||||
 | 
			
		||||
	status = libnet_SetPassword(ctx, mem_ctx, &r2);
 | 
			
		||||
 | 
			
		||||
	r->generic.out.error_string = r2.rpc.out.error_string;
 | 
			
		||||
	r->generic.out.error_string = r2.samr.out.error_string;
 | 
			
		||||
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
@@ -486,8 +520,8 @@ NTSTATUS libnet_SetPassword(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, uni
 | 
			
		||||
	switch (r->generic.level) {
 | 
			
		||||
		case LIBNET_SET_PASSWORD_GENERIC:
 | 
			
		||||
			return libnet_SetPassword_generic(ctx, mem_ctx, r);
 | 
			
		||||
		case LIBNET_SET_PASSWORD_RPC:
 | 
			
		||||
			return libnet_SetPassword_rpc(ctx, mem_ctx, r);
 | 
			
		||||
		case LIBNET_SET_PASSWORD_SAMR:
 | 
			
		||||
			return libnet_SetPassword_samr(ctx, mem_ctx, r);
 | 
			
		||||
		case LIBNET_SET_PASSWORD_KRB5:
 | 
			
		||||
			return NT_STATUS_NOT_IMPLEMENTED;
 | 
			
		||||
		case LIBNET_SET_PASSWORD_LDAP:
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user