2017-03-03 22:54:30 +03:00
/*
Unix SMB / CIFS implementation .
Copyright ( C ) David Mulder 2017
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
the Free Software Foundation ; either version 3 of the License , or
( 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
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
# include "param/param.h"
# include "param/loadparm.h"
# include "torture/smbtorture.h"
# include "lib/util/mkdir_p.h"
# include "dsdb/samdb/samdb.h"
# include "auth/session.h"
# include "lib/ldb/include/ldb.h"
# include "torture/gpo/proto.h"
# include <unistd.h>
2018-11-06 22:50:00 +03:00
# include "lib/util/samba_util.h"
# include "util/tevent_ntstatus.h"
2017-03-03 22:54:30 +03:00
2020-08-07 23:27:39 +03:00
# undef strncasecmp
2017-03-03 22:54:30 +03:00
struct torture_suite * gpo_apply_suite ( TALLOC_CTX * ctx )
{
struct torture_suite * suite = torture_suite_create ( ctx , " apply " ) ;
2017-11-20 00:28:33 +03:00
torture_suite_add_simple_test ( suite , " gpo_param_from_gpo " ,
torture_gpo_system_access_policies ) ;
2017-03-03 22:54:30 +03:00
suite - > description = talloc_strdup ( suite , " Group Policy apply tests " ) ;
return suite ;
}
2018-11-06 22:50:00 +03:00
static int exec_wait ( struct torture_context * tctx , const char * * gpo_update_cmd )
2017-03-03 22:54:30 +03:00
{
2018-11-06 22:50:00 +03:00
NTSTATUS status ;
int ret = 0 ;
struct tevent_req * req ;
req = samba_runcmd_send ( tctx ,
tctx - > ev ,
timeval_current_ofs ( 100 , 0 ) ,
2 , 0 ,
gpo_update_cmd ,
" gpo_reload_cmd " , NULL ) ;
if ( req = = NULL ) {
return - 1 ;
}
if ( ! tevent_req_poll_ntstatus ( req , tctx - > ev , & status ) ) {
return - 1 ;
}
2020-05-01 02:17:04 +03:00
if ( samba_runcmd_recv ( req , & ret ) ! = 0 ) {
2018-11-06 22:50:00 +03:00
return - 1 ;
2017-03-03 22:54:30 +03:00
}
return ret ;
}
2017-12-06 20:16:11 +03:00
static int unix2nttime ( const char * sval )
2017-03-03 22:54:30 +03:00
{
return ( strtoll ( sval , NULL , 10 ) * - 1 / 60 / 60 / 24 / 10000000 ) ;
}
2017-11-20 00:28:33 +03:00
# define GPODIR "addom.samba.example.com / Policies / "\
" {31B2F340-016D-11D2-945F-00C04FB984F9}/MACHINE/Microsoft/ " \
" Windows NT/SecEdit "
2017-03-03 22:54:30 +03:00
# define GPOFILE "GptTmpl.inf"
# define GPTTMPL "[System Access]\n\
MinimumPasswordAge = % d \ n \
MaximumPasswordAge = % d \ n \
MinimumPasswordLength = % d \ n \
PasswordComplexity = % d \ n \
"
2017-11-20 00:28:33 +03:00
# define GPTINI "addom.samba.example.com / Policies / "\
" {31B2F340-016D-11D2-945F-00C04FB984F9}/GPT.INI "
2017-03-03 22:54:30 +03:00
bool torture_gpo_system_access_policies ( struct torture_context * tctx )
{
2017-12-06 20:16:11 +03:00
TALLOC_CTX * ctx = talloc_new ( tctx ) ;
2017-03-03 22:54:30 +03:00
int ret , vers = 0 , i ;
2017-11-20 00:28:33 +03:00
const char * sysvol_path = NULL , * gpo_dir = NULL ;
const char * gpo_file = NULL , * gpt_file = NULL ;
2017-03-03 22:54:30 +03:00
struct ldb_context * samdb = NULL ;
struct ldb_result * result ;
const char * attrs [ ] = {
" minPwdAge " ,
" maxPwdAge " ,
" minPwdLength " ,
" pwdProperties " ,
NULL
} ;
FILE * fp = NULL ;
const char * * gpo_update_cmd ;
2018-11-06 22:50:00 +03:00
const char * * gpo_unapply_cmd ;
const char * * gpo_update_force_cmd ;
2017-03-03 22:54:30 +03:00
int minpwdcases [ ] = { 0 , 1 , 998 } ;
int maxpwdcases [ ] = { 0 , 1 , 999 } ;
int pwdlencases [ ] = { 0 , 1 , 14 } ;
int pwdpropcases [ ] = { 0 , 1 , 1 } ;
struct ldb_message * old_message = NULL ;
2017-12-06 20:16:11 +03:00
const char * * itr ;
int gpo_update_len = 0 ;
2017-03-03 22:54:30 +03:00
2017-11-20 00:28:33 +03:00
sysvol_path = lpcfg_path ( lpcfg_service ( tctx - > lp_ctx , " sysvol " ) ,
lpcfg_default_service ( tctx - > lp_ctx ) , tctx ) ;
2017-03-03 22:54:30 +03:00
torture_assert ( tctx , sysvol_path , " Failed to fetch the sysvol path " ) ;
/* Ensure the sysvol path exists */
2017-12-06 20:16:11 +03:00
gpo_dir = talloc_asprintf ( ctx , " %s/%s " , sysvol_path , GPODIR ) ;
2017-03-03 22:54:30 +03:00
mkdir_p ( gpo_dir , S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH ) ;
2017-12-06 20:16:11 +03:00
gpo_file = talloc_asprintf ( ctx , " %s/%s " , gpo_dir , GPOFILE ) ;
2017-03-03 22:54:30 +03:00
/* Get the gpo update command */
gpo_update_cmd = lpcfg_gpo_update_command ( tctx - > lp_ctx ) ;
2017-11-20 00:28:33 +03:00
torture_assert ( tctx , gpo_update_cmd & & gpo_update_cmd [ 0 ] ,
" Failed to fetch the gpo update command " ) ;
2017-03-03 22:54:30 +03:00
/* Open and read the samba db and store the initial password settings */
2018-04-11 21:41:30 +03:00
samdb = samdb_connect ( ctx ,
tctx - > ev ,
tctx - > lp_ctx ,
system_session ( tctx - > lp_ctx ) ,
NULL ,
0 ) ;
2017-03-03 22:54:30 +03:00
torture_assert ( tctx , samdb , " Failed to connect to the samdb " ) ;
2017-12-06 20:16:11 +03:00
ret = ldb_search ( samdb , ctx , & result , ldb_get_default_basedn ( samdb ) ,
2017-11-20 00:28:33 +03:00
LDB_SCOPE_BASE , attrs , NULL ) ;
torture_assert ( tctx , ret = = LDB_SUCCESS & & result - > count = = 1 ,
" Searching the samdb failed " ) ;
2017-03-03 22:54:30 +03:00
old_message = result - > msgs [ 0 ] ;
for ( i = 0 ; i < 3 ; i + + ) {
/* Write out the sysvol */
if ( ( fp = fopen ( gpo_file , " w " ) ) ) {
2017-12-06 20:16:11 +03:00
fputs ( talloc_asprintf ( ctx , GPTTMPL , minpwdcases [ i ] ,
2017-11-20 00:28:33 +03:00
maxpwdcases [ i ] , pwdlencases [ i ] ,
pwdpropcases [ i ] ) , fp ) ;
2017-03-03 22:54:30 +03:00
fclose ( fp ) ;
}
/* Update the version in the GPT.INI */
2017-12-06 20:16:11 +03:00
gpt_file = talloc_asprintf ( ctx , " %s/%s " , sysvol_path , GPTINI ) ;
2017-03-03 22:54:30 +03:00
if ( ( fp = fopen ( gpt_file , " r " ) ) ) {
char line [ 256 ] ;
while ( fgets ( line , 256 , fp ) ) {
if ( strncasecmp ( line , " Version= " , 8 ) = = 0 ) {
vers = atoi ( line + 8 ) ;
break ;
}
}
fclose ( fp ) ;
}
if ( ( fp = fopen ( gpt_file , " w " ) ) ) {
2017-12-06 20:16:11 +03:00
char * data = talloc_asprintf ( ctx ,
" [General] \n Version=%d \n " ,
2017-11-20 00:28:33 +03:00
+ + vers ) ;
2017-03-03 22:54:30 +03:00
fputs ( data , fp ) ;
fclose ( fp ) ;
}
/* Run the gpo update command */
2018-11-06 22:50:00 +03:00
ret = exec_wait ( tctx , gpo_update_cmd ) ;
2017-11-20 00:28:33 +03:00
torture_assert ( tctx , ret = = 0 ,
" Failed to execute the gpo update command " ) ;
2017-12-06 20:16:11 +03:00
ret = ldb_search ( samdb , ctx , & result ,
ldb_get_default_basedn ( samdb ) ,
2017-11-20 00:28:33 +03:00
LDB_SCOPE_BASE , attrs , NULL ) ;
torture_assert ( tctx , ret = = LDB_SUCCESS & & result - > count = = 1 ,
" Searching the samdb failed " ) ;
2017-03-03 22:54:30 +03:00
/* minPwdAge */
2017-12-06 20:16:11 +03:00
torture_assert_int_equal ( tctx , unix2nttime (
ldb_msg_find_attr_as_string (
result - > msgs [ 0 ] ,
attrs [ 0 ] ,
" " ) ) , minpwdcases [ i ] ,
2017-11-20 00:28:33 +03:00
" The minPwdAge was not applied " ) ;
2017-03-03 22:54:30 +03:00
/* maxPwdAge */
2017-12-06 20:16:11 +03:00
torture_assert_int_equal ( tctx , unix2nttime (
ldb_msg_find_attr_as_string (
result - > msgs [ 0 ] ,
attrs [ 1 ] ,
" " ) ) , maxpwdcases [ i ] ,
2017-11-20 00:28:33 +03:00
" The maxPwdAge was not applied " ) ;
2017-03-03 22:54:30 +03:00
/* minPwdLength */
2017-12-06 20:16:11 +03:00
torture_assert_int_equal ( tctx , ldb_msg_find_attr_as_int (
result - > msgs [ 0 ] ,
attrs [ 2 ] ,
- 1 ) ,
pwdlencases [ i ] ,
" The minPwdLength was not applied " ) ;
2017-03-03 22:54:30 +03:00
/* pwdProperties */
2017-12-06 20:16:11 +03:00
torture_assert_int_equal ( tctx , ldb_msg_find_attr_as_int (
result - > msgs [ 0 ] ,
attrs [ 3 ] ,
- 1 ) ,
pwdpropcases [ i ] ,
2017-11-20 00:28:33 +03:00
" The pwdProperties were not applied " ) ;
2017-03-03 22:54:30 +03:00
}
2018-07-23 22:27:31 +03:00
/* Reset settings, then verify a reapply doesn't force them back */
for ( i = 0 ; i < old_message - > num_elements ; i + + ) {
old_message - > elements [ i ] . flags = LDB_FLAG_MOD_REPLACE ;
}
ret = ldb_modify ( samdb , old_message ) ;
torture_assert ( tctx , ret = = 0 , " Failed to reset password settings. " ) ;
2018-11-06 22:50:00 +03:00
ret = exec_wait ( tctx , gpo_update_cmd ) ;
2018-07-23 22:27:31 +03:00
torture_assert ( tctx , ret = = 0 ,
" Failed to execute the gpo update command " ) ;
/* Validate that the apply did nothing (without --force param) */
ret = ldb_search ( samdb , ctx , & result , ldb_get_default_basedn ( samdb ) ,
LDB_SCOPE_BASE , attrs , NULL ) ;
torture_assert ( tctx , ret = = LDB_SUCCESS & & result - > count = = 1 ,
" Searching the samdb failed " ) ;
/* minPwdAge */
torture_assert_int_equal ( tctx , unix2nttime ( ldb_msg_find_attr_as_string (
result - > msgs [ 0 ] ,
attrs [ 0 ] ,
" " ) ) ,
unix2nttime ( ldb_msg_find_attr_as_string ( old_message ,
attrs [ 0 ] ,
" " )
) ,
" The minPwdAge was re-applied " ) ;
/* maxPwdAge */
torture_assert_int_equal ( tctx , unix2nttime ( ldb_msg_find_attr_as_string (
result - > msgs [ 0 ] ,
attrs [ 1 ] ,
" " ) ) ,
unix2nttime ( ldb_msg_find_attr_as_string ( old_message ,
attrs [ 1 ] ,
" " )
) ,
" The maxPwdAge was re-applied " ) ;
/* minPwdLength */
torture_assert_int_equal ( tctx , ldb_msg_find_attr_as_int (
result - > msgs [ 0 ] ,
attrs [ 2 ] ,
- 1 ) ,
ldb_msg_find_attr_as_int (
old_message ,
attrs [ 2 ] ,
- 2 ) ,
" The minPwdLength was re-applied " ) ;
/* pwdProperties */
torture_assert_int_equal ( tctx , ldb_msg_find_attr_as_int (
result - > msgs [ 0 ] ,
attrs [ 3 ] ,
- 1 ) ,
ldb_msg_find_attr_as_int (
old_message ,
attrs [ 3 ] ,
- 2 ) ,
" The pwdProperties were re-applied " ) ;
2017-12-06 20:16:11 +03:00
for ( itr = gpo_update_cmd ; * itr ! = NULL ; itr + + ) {
gpo_update_len + + ;
2017-03-03 22:54:30 +03:00
}
2018-07-23 22:27:31 +03:00
/* Run gpupdate --force and verify settings are re-applied */
2018-11-06 22:50:00 +03:00
gpo_update_force_cmd = talloc_array ( ctx , const char * , gpo_update_len + 2 ) ;
2018-07-23 22:27:31 +03:00
for ( i = 0 ; i < gpo_update_len ; i + + ) {
gpo_update_force_cmd [ i ] = talloc_strdup ( gpo_update_force_cmd ,
gpo_update_cmd [ i ] ) ;
}
gpo_update_force_cmd [ i ] = talloc_asprintf ( gpo_update_force_cmd ,
" --force " ) ;
gpo_update_force_cmd [ i + 1 ] = NULL ;
2018-11-06 22:50:00 +03:00
ret = exec_wait ( tctx , gpo_update_force_cmd ) ;
2018-07-23 22:27:31 +03:00
torture_assert ( tctx , ret = = 0 ,
" Failed to execute the gpupdate --force command " ) ;
ret = ldb_search ( samdb , ctx , & result ,
ldb_get_default_basedn ( samdb ) ,
LDB_SCOPE_BASE , attrs , NULL ) ;
torture_assert ( tctx , ret = = LDB_SUCCESS & & result - > count = = 1 ,
" Searching the samdb failed " ) ;
/* minPwdAge */
torture_assert_int_equal ( tctx , unix2nttime (
ldb_msg_find_attr_as_string (
result - > msgs [ 0 ] ,
attrs [ 0 ] ,
" " ) ) , minpwdcases [ 2 ] ,
" The minPwdAge was not applied " ) ;
/* maxPwdAge */
torture_assert_int_equal ( tctx , unix2nttime (
ldb_msg_find_attr_as_string (
result - > msgs [ 0 ] ,
attrs [ 1 ] ,
" " ) ) , maxpwdcases [ 2 ] ,
" The maxPwdAge was not applied " ) ;
/* minPwdLength */
torture_assert_int_equal ( tctx , ldb_msg_find_attr_as_int (
result - > msgs [ 0 ] ,
attrs [ 2 ] ,
- 1 ) ,
pwdlencases [ 2 ] ,
" The minPwdLength was not applied " ) ;
/* pwdProperties */
torture_assert_int_equal ( tctx , ldb_msg_find_attr_as_int (
result - > msgs [ 0 ] ,
attrs [ 3 ] ,
- 1 ) ,
pwdpropcases [ 2 ] ,
" The pwdProperties were not applied " ) ;
/* Unapply the settings and verify they are removed */
2018-11-06 22:50:00 +03:00
gpo_unapply_cmd = talloc_array ( ctx , const char * , gpo_update_len + 2 ) ;
2017-12-06 20:16:11 +03:00
for ( i = 0 ; i < gpo_update_len ; i + + ) {
gpo_unapply_cmd [ i ] = talloc_strdup ( gpo_unapply_cmd ,
gpo_update_cmd [ i ] ) ;
}
gpo_unapply_cmd [ i ] = talloc_asprintf ( gpo_unapply_cmd , " --unapply " ) ;
gpo_unapply_cmd [ i + 1 ] = NULL ;
2018-11-06 22:50:00 +03:00
ret = exec_wait ( tctx , gpo_unapply_cmd ) ;
2017-12-06 20:16:11 +03:00
torture_assert ( tctx , ret = = 0 ,
" Failed to execute the gpo unapply command " ) ;
ret = ldb_search ( samdb , ctx , & result , ldb_get_default_basedn ( samdb ) ,
LDB_SCOPE_BASE , attrs , NULL ) ;
torture_assert ( tctx , ret = = LDB_SUCCESS & & result - > count = = 1 ,
" Searching the samdb failed " ) ;
/* minPwdAge */
torture_assert_int_equal ( tctx , unix2nttime ( ldb_msg_find_attr_as_string (
result - > msgs [ 0 ] ,
attrs [ 0 ] ,
" " ) ) ,
unix2nttime ( ldb_msg_find_attr_as_string ( old_message ,
attrs [ 0 ] ,
" " )
) ,
" The minPwdAge was not unapplied " ) ;
/* maxPwdAge */
torture_assert_int_equal ( tctx , unix2nttime ( ldb_msg_find_attr_as_string (
result - > msgs [ 0 ] ,
attrs [ 1 ] ,
" " ) ) ,
unix2nttime ( ldb_msg_find_attr_as_string ( old_message ,
attrs [ 1 ] ,
" " )
) ,
" The maxPwdAge was not unapplied " ) ;
/* minPwdLength */
torture_assert_int_equal ( tctx , ldb_msg_find_attr_as_int (
result - > msgs [ 0 ] ,
attrs [ 2 ] ,
- 1 ) ,
ldb_msg_find_attr_as_int (
old_message ,
attrs [ 2 ] ,
- 2 ) ,
" The minPwdLength was not unapplied " ) ;
/* pwdProperties */
torture_assert_int_equal ( tctx , ldb_msg_find_attr_as_int (
result - > msgs [ 0 ] ,
attrs [ 3 ] ,
- 1 ) ,
ldb_msg_find_attr_as_int (
old_message ,
attrs [ 3 ] ,
- 2 ) ,
" The pwdProperties were not unapplied " ) ;
2017-03-03 22:54:30 +03:00
2017-12-06 20:16:11 +03:00
talloc_free ( ctx ) ;
2017-03-03 22:54:30 +03:00
return true ;
}