1998-03-12 00:11:04 +03:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
2002-08-17 20:05:44 +04:00
RPC pipe client
Copyright ( C ) Tim Potter 2000 - 2001 ,
Copyright ( C ) Andrew Tridgell 1992 - 1997 , 2000 ,
Copyright ( C ) Rafal Szczesniak 2002.
2005-09-30 21:13:37 +04:00
Copyright ( C ) Jeremy Allison 2005.
2008-02-27 21:38:48 +03:00
Copyright ( C ) Guenther Deschner 2008.
1998-03-12 00:11:04 +03:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
1998-03-12 00:11:04 +03:00
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
1998-03-12 00:11:04 +03:00
*/
# include "includes.h"
2011-04-13 16:32:16 +04:00
# include "rpc_client/rpc_client.h"
2009-03-16 13:27:58 +03:00
# include "../libcli/auth/libcli_auth.h"
2011-01-21 18:00:31 +03:00
# include "../librpc/gen_ndr/ndr_samr_c.h"
2010-05-18 20:25:50 +04:00
# include "rpc_client/cli_samr.h"
2010-05-18 02:16:40 +04:00
# include "../lib/crypto/arcfour.h"
2010-08-20 01:15:22 +04:00
# include "rpc_client/init_lsa.h"
1998-03-12 00:11:04 +03:00
2008-06-25 13:50:17 +04:00
/* User change password */
2011-01-11 15:07:02 +03:00
NTSTATUS dcerpc_samr_chgpasswd_user ( struct dcerpc_binding_handle * h ,
2008-06-25 13:50:17 +04:00
TALLOC_CTX * mem_ctx ,
struct policy_handle * user_handle ,
const char * newpassword ,
2011-01-11 15:07:02 +03:00
const char * oldpassword ,
NTSTATUS * presult )
2008-06-25 13:50:17 +04:00
{
2011-01-11 15:07:02 +03:00
NTSTATUS status ;
2008-06-25 13:50:17 +04:00
struct samr_Password hash1 , hash2 , hash3 , hash4 , hash5 , hash6 ;
uchar old_nt_hash [ 16 ] ;
uchar old_lm_hash [ 16 ] ;
uchar new_nt_hash [ 16 ] ;
uchar new_lm_hash [ 16 ] ;
ZERO_STRUCT ( old_nt_hash ) ;
ZERO_STRUCT ( old_lm_hash ) ;
ZERO_STRUCT ( new_nt_hash ) ;
ZERO_STRUCT ( new_lm_hash ) ;
DEBUG ( 10 , ( " rpccli_samr_chgpasswd_user \n " ) ) ;
E_md4hash ( oldpassword , old_nt_hash ) ;
E_md4hash ( newpassword , new_nt_hash ) ;
E_deshash ( oldpassword , old_lm_hash ) ;
E_deshash ( newpassword , new_lm_hash ) ;
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 ) ;
E_old_pw_hash ( old_nt_hash , new_nt_hash , hash4 . hash ) ;
E_old_pw_hash ( old_lm_hash , new_nt_hash , hash5 . hash ) ;
E_old_pw_hash ( old_nt_hash , new_lm_hash , hash6 . hash ) ;
2011-01-11 15:07:02 +03:00
status = dcerpc_samr_ChangePasswordUser ( h ,
mem_ctx ,
2008-06-25 13:50:17 +04:00
user_handle ,
true ,
& hash1 ,
& hash2 ,
true ,
& hash3 ,
& hash4 ,
true ,
& hash5 ,
true ,
2011-01-11 15:07:02 +03:00
& hash6 ,
presult ) ;
2008-06-25 13:50:17 +04:00
2011-01-11 15:07:02 +03:00
return status ;
2008-06-25 13:50:17 +04:00
}
2011-01-11 15:07:02 +03:00
NTSTATUS rpccli_samr_chgpasswd_user ( struct rpc_pipe_client * cli ,
TALLOC_CTX * mem_ctx ,
struct policy_handle * user_handle ,
const char * newpassword ,
const char * oldpassword )
{
NTSTATUS status ;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL ;
status = dcerpc_samr_chgpasswd_user ( cli - > binding_handle ,
mem_ctx ,
user_handle ,
newpassword ,
oldpassword ,
& result ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
return result ;
}
2008-06-25 13:50:17 +04:00
2004-01-26 11:45:02 +03:00
/* User change password */
2011-01-12 10:46:28 +03:00
NTSTATUS dcerpc_samr_chgpasswd_user2 ( struct dcerpc_binding_handle * h ,
2008-06-25 12:35:59 +04:00
TALLOC_CTX * mem_ctx ,
2011-01-12 10:46:28 +03:00
const char * srv_name_slash ,
2008-06-25 12:35:59 +04:00
const char * username ,
const char * newpassword ,
2011-01-12 10:46:28 +03:00
const char * oldpassword ,
NTSTATUS * presult )
2004-01-26 11:45:02 +03:00
{
2011-01-12 10:46:28 +03:00
NTSTATUS status ;
2008-02-06 03:50:01 +03:00
struct samr_CryptPassword new_nt_password ;
struct samr_CryptPassword new_lm_password ;
struct samr_Password old_nt_hash_enc ;
struct samr_Password old_lanman_hash_enc ;
2007-10-11 00:34:30 +04:00
2011-01-12 10:46:28 +03:00
uint8_t old_nt_hash [ 16 ] ;
uint8_t old_lanman_hash [ 16 ] ;
uint8_t new_nt_hash [ 16 ] ;
uint8_t new_lanman_hash [ 16 ] ;
2008-02-06 03:50:01 +03:00
struct lsa_String server , account ;
2007-10-11 00:34:30 +04:00
2008-06-25 12:35:59 +04:00
DEBUG ( 10 , ( " rpccli_samr_chgpasswd_user2 \n " ) ) ;
2004-01-26 11:45:02 +03:00
2011-01-12 10:46:28 +03:00
init_lsa_String ( & server , srv_name_slash ) ;
2008-02-06 03:50:01 +03:00
init_lsa_String ( & account , username ) ;
2004-01-26 11:45:02 +03:00
/* Calculate the MD4 hash (NT compatible) of the password */
E_md4hash ( oldpassword , old_nt_hash ) ;
E_md4hash ( newpassword , new_nt_hash ) ;
2008-02-06 03:50:01 +03:00
if ( lp_client_lanman_auth ( ) & &
E_deshash ( newpassword , new_lanman_hash ) & &
E_deshash ( oldpassword , old_lanman_hash ) ) {
2004-01-26 11:45:02 +03:00
/* E_deshash returns false for 'long' passwords (> 14
DOS chars ) . This allows us to match Win2k , which
does not store a LM hash for these passwords ( which
would reduce the effective password length to 14 ) */
2008-02-06 03:50:01 +03:00
encode_pw_buffer ( new_lm_password . data , newpassword , STR_UNICODE ) ;
2004-01-26 11:45:02 +03:00
2009-03-16 13:27:58 +03:00
arcfour_crypt ( new_lm_password . data , old_nt_hash , 516 ) ;
2008-02-06 03:50:01 +03:00
E_old_pw_hash ( new_nt_hash , old_lanman_hash , old_lanman_hash_enc . hash ) ;
2004-01-26 11:45:02 +03:00
} else {
ZERO_STRUCT ( new_lm_password ) ;
ZERO_STRUCT ( old_lanman_hash_enc ) ;
}
2008-02-06 03:50:01 +03:00
encode_pw_buffer ( new_nt_password . data , newpassword , STR_UNICODE ) ;
2007-10-11 00:34:30 +04:00
2009-03-16 13:27:58 +03:00
arcfour_crypt ( new_nt_password . data , old_nt_hash , 516 ) ;
2008-02-06 03:50:01 +03:00
E_old_pw_hash ( new_nt_hash , old_nt_hash , old_nt_hash_enc . hash ) ;
2007-10-11 00:34:30 +04:00
2011-01-12 10:46:28 +03:00
status = dcerpc_samr_ChangePasswordUser2 ( h ,
mem_ctx ,
2008-02-06 03:50:01 +03:00
& server ,
& account ,
& new_nt_password ,
& old_nt_hash_enc ,
true ,
& new_lm_password ,
2011-01-12 10:46:28 +03:00
& old_lanman_hash_enc ,
presult ) ;
return status ;
}
NTSTATUS rpccli_samr_chgpasswd_user2 ( struct rpc_pipe_client * cli ,
TALLOC_CTX * mem_ctx ,
const char * username ,
const char * newpassword ,
const char * oldpassword )
{
NTSTATUS status ;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL ;
status = dcerpc_samr_chgpasswd_user2 ( cli - > binding_handle ,
mem_ctx ,
cli - > srv_name_slash ,
username ,
newpassword ,
oldpassword ,
& result ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2007-10-11 00:34:30 +04:00
return result ;
2004-01-26 11:45:02 +03:00
}
2007-10-11 00:34:30 +04:00
/* User change password given blobs */
2006-07-13 13:29:25 +04:00
2011-01-12 11:04:19 +03:00
NTSTATUS dcerpc_samr_chng_pswd_auth_crap ( struct dcerpc_binding_handle * h ,
2008-02-06 03:50:01 +03:00
TALLOC_CTX * mem_ctx ,
2011-01-12 11:04:19 +03:00
const char * srv_name_slash ,
2008-02-06 03:50:01 +03:00
const char * username ,
DATA_BLOB new_nt_password_blob ,
DATA_BLOB old_nt_hash_enc_blob ,
DATA_BLOB new_lm_password_blob ,
2011-01-12 11:04:19 +03:00
DATA_BLOB old_lm_hash_enc_blob ,
NTSTATUS * presult )
2006-07-13 13:29:25 +04:00
{
2011-01-12 11:04:19 +03:00
NTSTATUS status ;
2008-02-06 03:50:01 +03:00
struct samr_CryptPassword new_nt_password ;
struct samr_CryptPassword new_lm_password ;
struct samr_Password old_nt_hash_enc ;
struct samr_Password old_lm_hash_enc ;
struct lsa_String server , account ;
2006-07-13 13:29:25 +04:00
2007-10-11 00:34:30 +04:00
DEBUG ( 10 , ( " rpccli_samr_chng_pswd_auth_crap \n " ) ) ;
2006-07-13 13:29:25 +04:00
2011-04-19 01:32:11 +04:00
ZERO_STRUCT ( new_nt_password ) ;
ZERO_STRUCT ( new_lm_password ) ;
ZERO_STRUCT ( old_nt_hash_enc ) ;
ZERO_STRUCT ( old_lm_hash_enc ) ;
2011-01-12 11:04:19 +03:00
init_lsa_String ( & server , srv_name_slash ) ;
2008-02-06 03:50:01 +03:00
init_lsa_String ( & account , username ) ;
2011-04-19 01:32:11 +04:00
if ( new_nt_password_blob . data & & new_nt_password_blob . length > = 516 ) {
2010-07-18 17:04:20 +04:00
memcpy ( & new_nt_password . data , new_nt_password_blob . data , 516 ) ;
}
2011-04-19 01:32:11 +04:00
if ( new_lm_password_blob . data & & new_lm_password_blob . length > = 516 ) {
2010-07-18 17:04:20 +04:00
memcpy ( & new_lm_password . data , new_lm_password_blob . data , 516 ) ;
}
2011-04-19 01:32:11 +04:00
if ( old_nt_hash_enc_blob . data & & old_nt_hash_enc_blob . length > = 16 ) {
2010-07-18 17:04:20 +04:00
memcpy ( & old_nt_hash_enc . hash , old_nt_hash_enc_blob . data , 16 ) ;
}
2011-04-19 01:32:11 +04:00
if ( old_lm_hash_enc_blob . data & & old_lm_hash_enc_blob . length > = 16 ) {
2010-07-18 17:04:20 +04:00
memcpy ( & old_lm_hash_enc . hash , old_lm_hash_enc_blob . data , 16 ) ;
}
2008-02-06 03:50:01 +03:00
2011-01-12 11:04:19 +03:00
status = dcerpc_samr_ChangePasswordUser2 ( h ,
mem_ctx ,
2008-02-06 03:50:01 +03:00
& server ,
& account ,
& new_nt_password ,
& old_nt_hash_enc ,
true ,
& new_lm_password ,
2011-01-12 11:04:19 +03:00
& old_lm_hash_enc ,
presult ) ;
return status ;
2006-07-13 13:29:25 +04:00
}
2011-01-12 11:04:19 +03:00
NTSTATUS rpccli_samr_chng_pswd_auth_crap ( struct rpc_pipe_client * cli ,
TALLOC_CTX * mem_ctx ,
const char * username ,
DATA_BLOB new_nt_password_blob ,
DATA_BLOB old_nt_hash_enc_blob ,
DATA_BLOB new_lm_password_blob ,
DATA_BLOB old_lm_hash_enc_blob )
{
NTSTATUS status ;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL ;
status = dcerpc_samr_chng_pswd_auth_crap ( cli - > binding_handle ,
mem_ctx ,
cli - > srv_name_slash ,
username ,
new_nt_password_blob ,
old_nt_hash_enc_blob ,
new_lm_password_blob ,
old_lm_hash_enc_blob ,
& result ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
return result ;
}
2007-10-11 00:34:30 +04:00
2005-11-30 02:23:02 +03:00
/* change password 3 */
2011-01-12 17:14:35 +03:00
NTSTATUS dcerpc_samr_chgpasswd_user3 ( struct dcerpc_binding_handle * h ,
2008-06-25 23:49:57 +04:00
TALLOC_CTX * mem_ctx ,
2011-01-12 17:14:35 +03:00
const char * srv_name_slash ,
2008-06-25 23:49:57 +04:00
const char * username ,
const char * newpassword ,
const char * oldpassword ,
struct samr_DomInfo1 * * dominfo1 ,
2011-01-12 17:14:35 +03:00
struct userPwdChangeFailureInformation * * reject ,
NTSTATUS * presult )
2005-11-30 02:23:02 +03:00
{
2008-02-05 22:14:54 +03:00
NTSTATUS status ;
struct samr_CryptPassword new_nt_password ;
struct samr_CryptPassword new_lm_password ;
struct samr_Password old_nt_hash_enc ;
struct samr_Password old_lanman_hash_enc ;
2005-11-30 02:23:02 +03:00
2011-01-12 17:14:35 +03:00
uint8_t old_nt_hash [ 16 ] ;
uint8_t old_lanman_hash [ 16 ] ;
uint8_t new_nt_hash [ 16 ] ;
uint8_t new_lanman_hash [ 16 ] ;
2005-11-30 02:23:02 +03:00
2008-02-05 22:14:54 +03:00
struct lsa_String server , account ;
2005-11-30 02:23:02 +03:00
2008-06-25 23:49:57 +04:00
DEBUG ( 10 , ( " rpccli_samr_chgpasswd_user3 \n " ) ) ;
2005-11-30 02:23:02 +03:00
2011-01-12 17:14:35 +03:00
init_lsa_String ( & server , srv_name_slash ) ;
2008-02-05 22:14:54 +03:00
init_lsa_String ( & account , username ) ;
2005-11-30 02:23:02 +03:00
/* Calculate the MD4 hash (NT compatible) of the password */
E_md4hash ( oldpassword , old_nt_hash ) ;
E_md4hash ( newpassword , new_nt_hash ) ;
2008-02-05 22:14:54 +03:00
if ( lp_client_lanman_auth ( ) & &
E_deshash ( newpassword , new_lanman_hash ) & &
E_deshash ( oldpassword , old_lanman_hash ) ) {
2005-11-30 02:23:02 +03:00
/* E_deshash returns false for 'long' passwords (> 14
DOS chars ) . This allows us to match Win2k , which
does not store a LM hash for these passwords ( which
would reduce the effective password length to 14 ) */
2008-02-05 22:14:54 +03:00
encode_pw_buffer ( new_lm_password . data , newpassword , STR_UNICODE ) ;
2005-11-30 02:23:02 +03:00
2009-03-16 13:27:58 +03:00
arcfour_crypt ( new_lm_password . data , old_nt_hash , 516 ) ;
2008-02-05 22:14:54 +03:00
E_old_pw_hash ( new_nt_hash , old_lanman_hash , old_lanman_hash_enc . hash ) ;
2005-11-30 02:23:02 +03:00
} else {
ZERO_STRUCT ( new_lm_password ) ;
ZERO_STRUCT ( old_lanman_hash_enc ) ;
}
2008-02-05 22:14:54 +03:00
encode_pw_buffer ( new_nt_password . data , newpassword , STR_UNICODE ) ;
2009-03-16 13:27:58 +03:00
arcfour_crypt ( new_nt_password . data , old_nt_hash , 516 ) ;
2008-02-05 22:14:54 +03:00
E_old_pw_hash ( new_nt_hash , old_nt_hash , old_nt_hash_enc . hash ) ;
2011-01-12 17:14:35 +03:00
status = dcerpc_samr_ChangePasswordUser3 ( h ,
mem_ctx ,
2008-02-05 22:14:54 +03:00
& server ,
& account ,
& new_nt_password ,
& old_nt_hash_enc ,
true ,
& new_lm_password ,
& old_lanman_hash_enc ,
NULL ,
dominfo1 ,
2011-01-12 17:14:35 +03:00
reject ,
presult ) ;
2008-02-05 22:14:54 +03:00
return status ;
2005-11-30 02:23:02 +03:00
}
2011-01-12 17:14:35 +03:00
NTSTATUS rpccli_samr_chgpasswd_user3 ( struct rpc_pipe_client * cli ,
TALLOC_CTX * mem_ctx ,
const char * username ,
const char * newpassword ,
const char * oldpassword ,
struct samr_DomInfo1 * * dominfo1 ,
struct userPwdChangeFailureInformation * * reject )
{
NTSTATUS status ;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL ;
status = dcerpc_samr_chgpasswd_user3 ( cli - > binding_handle ,
mem_ctx ,
cli - > srv_name_slash ,
username ,
newpassword ,
oldpassword ,
dominfo1 ,
reject ,
& result ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
return result ;
}
2003-01-29 23:15:35 +03:00
/* This function returns the bizzare set of (max_entries, max_size) required
for the QueryDisplayInfo RPC to actually work against a domain controller
with large ( 10 k and higher ) numbers of users . These values were
obtained by inspection using ethereal and NT4 running User Manager . */
2011-01-12 17:36:19 +03:00
void dcerpc_get_query_dispinfo_params ( int loop_count ,
uint32_t * max_entries ,
uint32_t * max_size )
2003-01-29 23:15:35 +03:00
{
switch ( loop_count ) {
case 0 :
* max_entries = 512 ;
* max_size = 16383 ;
break ;
case 1 :
* max_entries = 1024 ;
* max_size = 32766 ;
break ;
case 2 :
* max_entries = 2048 ;
* max_size = 65532 ;
break ;
case 3 :
* max_entries = 4096 ;
* max_size = 131064 ;
break ;
default : /* loop_count >= 4 */
* max_entries = 4096 ;
* max_size = 131071 ;
break ;
}
2006-09-18 23:18:29 +04:00
}
2008-04-04 03:40:29 +04:00
2011-01-12 17:51:49 +03:00
NTSTATUS dcerpc_try_samr_connects ( struct dcerpc_binding_handle * h ,
2008-04-04 03:40:29 +04:00
TALLOC_CTX * mem_ctx ,
2011-01-12 17:51:49 +03:00
const char * srv_name_slash ,
2008-04-04 03:40:29 +04:00
uint32_t access_mask ,
2011-01-12 17:51:49 +03:00
struct policy_handle * connect_pol ,
NTSTATUS * presult )
2008-04-04 03:40:29 +04:00
{
NTSTATUS status ;
union samr_ConnectInfo info_in , info_out ;
struct samr_ConnectInfo1 info1 ;
uint32_t lvl_out = 0 ;
ZERO_STRUCT ( info1 ) ;
info1 . client_version = SAMR_CONNECT_W2K ;
info_in . info1 = info1 ;
2011-01-12 17:51:49 +03:00
status = dcerpc_samr_Connect5 ( h ,
mem_ctx ,
srv_name_slash ,
2008-04-04 03:40:29 +04:00
access_mask ,
1 ,
& info_in ,
& lvl_out ,
& info_out ,
2011-01-12 17:51:49 +03:00
connect_pol ,
presult ) ;
2011-01-21 18:02:18 +03:00
if ( NT_STATUS_IS_OK ( status ) & & NT_STATUS_IS_OK ( * presult ) ) {
2008-04-04 03:40:29 +04:00
return status ;
}
2011-01-12 17:51:49 +03:00
status = dcerpc_samr_Connect4 ( h ,
mem_ctx ,
srv_name_slash ,
2008-04-04 03:40:29 +04:00
SAMR_CONNECT_W2K ,
access_mask ,
2011-01-12 17:51:49 +03:00
connect_pol ,
presult ) ;
2011-01-21 18:02:18 +03:00
if ( NT_STATUS_IS_OK ( status ) & & NT_STATUS_IS_OK ( * presult ) ) {
2008-04-04 03:40:29 +04:00
return status ;
}
2011-01-12 17:51:49 +03:00
status = dcerpc_samr_Connect2 ( h ,
mem_ctx ,
srv_name_slash ,
2008-04-04 03:40:29 +04:00
access_mask ,
2011-01-12 17:51:49 +03:00
connect_pol ,
presult ) ;
2008-04-04 03:40:29 +04:00
return status ;
}
2011-01-12 17:51:49 +03:00
NTSTATUS rpccli_try_samr_connects ( struct rpc_pipe_client * cli ,
TALLOC_CTX * mem_ctx ,
uint32_t access_mask ,
struct policy_handle * connect_pol )
{
NTSTATUS status ;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL ;
status = dcerpc_try_samr_connects ( cli - > binding_handle ,
mem_ctx ,
cli - > srv_name_slash ,
access_mask ,
connect_pol ,
& result ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
return result ;
}
/* vim: set ts=8 sw=8 noet cindent: */