LCOV - code coverage report
Current view: top level - source4/torture/gpo - apply.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 107 117 91.5 %
Date: 2024-02-28 12:06:22 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Copyright (C) David Mulder 2017
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "param/param.h"
      22             : #include "param/loadparm.h"
      23             : #include "torture/smbtorture.h"
      24             : #include "lib/util/mkdir_p.h"
      25             : #include "dsdb/samdb/samdb.h"
      26             : #include "auth/session.h"
      27             : #include "lib/ldb/include/ldb.h"
      28             : #include "torture/gpo/proto.h"
      29             : #include <unistd.h>
      30             : #include "lib/util/samba_util.h"
      31             : #include "util/tevent_ntstatus.h"
      32             : 
      33             : #undef strncasecmp
      34             : 
      35        2379 : struct torture_suite *gpo_apply_suite(TALLOC_CTX *ctx)
      36             : {
      37        2379 :         struct torture_suite *suite = torture_suite_create(ctx, "apply");
      38             : 
      39        2379 :         torture_suite_add_simple_test(suite, "gpo_param_from_gpo",
      40             :                                       torture_gpo_system_access_policies);
      41             : 
      42        2379 :         suite->description = talloc_strdup(suite, "Group Policy apply tests");
      43             : 
      44        2379 :         return suite;
      45             : }
      46             : 
      47          12 : static int exec_wait(struct torture_context *tctx, const char **gpo_update_cmd)
      48             : {
      49           0 :         NTSTATUS status;
      50          12 :         int ret = 0;
      51           0 :         struct tevent_req *req;
      52             : 
      53          12 :         req = samba_runcmd_send(tctx,
      54             :                                 tctx->ev,
      55             :                                 timeval_current_ofs(100, 0),
      56             :                                 2, 0,
      57             :                                 gpo_update_cmd,
      58             :                                 "gpo_reload_cmd", NULL);
      59          12 :         if (req == NULL) {
      60           0 :                 return -1;
      61             :         }
      62             : 
      63          12 :         if (!tevent_req_poll_ntstatus(req, tctx->ev, &status)) {
      64           0 :                 return -1;
      65             :         }
      66          12 :         if (samba_runcmd_recv(req, &ret) != 0) {
      67           0 :                 return -1;
      68             :         }
      69          12 :         return ret;
      70             : }
      71             : 
      72          32 : static int unix2nttime(const char *sval)
      73             : {
      74          32 :         return (strtoll(sval, NULL, 10) * -1 / 60 / 60 / 24 / 10000000);
      75             : }
      76             : 
      77             : #define GPODIR "addom.samba.example.com/Policies/"\
      78             :                "{31B2F340-016D-11D2-945F-00C04FB984F9}/MACHINE/Microsoft/"\
      79             :                "Windows NT/SecEdit"
      80             : #define GPOFILE "GptTmpl.inf"
      81             : #define GPTTMPL "[System Access]\n\
      82             : MinimumPasswordAge = %d\n\
      83             : MaximumPasswordAge = %d\n\
      84             : MinimumPasswordLength = %d\n\
      85             : PasswordComplexity = %d\n\
      86             : "
      87             : #define GPTINI "addom.samba.example.com/Policies/"\
      88             :                "{31B2F340-016D-11D2-945F-00C04FB984F9}/GPT.INI"
      89             : 
      90           2 : bool torture_gpo_system_access_policies(struct torture_context *tctx)
      91             : {
      92           2 :         TALLOC_CTX *ctx = talloc_new(tctx);
      93           2 :         int ret, vers = 0, i;
      94           2 :         const char *sysvol_path = NULL, *gpo_dir = NULL;
      95           2 :         const char *gpo_file = NULL, *gpt_file = NULL;
      96           2 :         struct ldb_context *samdb = NULL;
      97           0 :         struct ldb_result *result;
      98           2 :         const char *attrs[] = {
      99             :                 "minPwdAge",
     100             :                 "maxPwdAge",
     101             :                 "minPwdLength",
     102             :                 "pwdProperties",
     103             :                 NULL
     104             :         };
     105           2 :         FILE *fp = NULL;
     106           0 :         const char **gpo_update_cmd;
     107           0 :         const char **gpo_unapply_cmd;
     108           0 :         const char **gpo_update_force_cmd;
     109           2 :         int minpwdcases[] = { 0, 1, 998 };
     110           2 :         int maxpwdcases[] = { 0, 1, 999 };
     111           2 :         int pwdlencases[] = { 0, 1, 14 };
     112           2 :         int pwdpropcases[] = { 0, 1, 1 };
     113           2 :         struct ldb_message *old_message = NULL;
     114           0 :         const char **itr;
     115           2 :         int gpo_update_len = 0;
     116             : 
     117           2 :         sysvol_path = lpcfg_path(lpcfg_service(tctx->lp_ctx, "sysvol"),
     118             :                                  lpcfg_default_service(tctx->lp_ctx), tctx);
     119           2 :         torture_assert(tctx, sysvol_path, "Failed to fetch the sysvol path");
     120             : 
     121             :         /* Ensure the sysvol path exists */
     122           2 :         gpo_dir = talloc_asprintf(ctx, "%s/%s", sysvol_path, GPODIR);
     123           2 :         mkdir_p(gpo_dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
     124           2 :         gpo_file = talloc_asprintf(ctx, "%s/%s", gpo_dir, GPOFILE);
     125             : 
     126             :         /* Get the gpo update command */
     127           2 :         gpo_update_cmd = lpcfg_gpo_update_command(tctx->lp_ctx);
     128           2 :         torture_assert(tctx, gpo_update_cmd && gpo_update_cmd[0],
     129             :                        "Failed to fetch the gpo update command");
     130             : 
     131             :         /* Open and read the samba db and store the initial password settings */
     132           2 :         samdb = samdb_connect(ctx,
     133             :                               tctx->ev,
     134             :                               tctx->lp_ctx,
     135             :                               system_session(tctx->lp_ctx),
     136             :                               NULL,
     137             :                               0);
     138           2 :         torture_assert(tctx, samdb, "Failed to connect to the samdb");
     139             : 
     140           2 :         ret = ldb_search(samdb, ctx, &result, ldb_get_default_basedn(samdb),
     141             :                          LDB_SCOPE_BASE, attrs, NULL);
     142           2 :         torture_assert(tctx, ret == LDB_SUCCESS && result->count == 1,
     143             :                        "Searching the samdb failed");
     144             : 
     145           2 :         old_message = result->msgs[0];
     146             : 
     147           8 :         for (i = 0; i < 3; i++) {
     148             :                 /* Write out the sysvol */
     149           6 :                 if ( (fp = fopen(gpo_file, "w")) ) {
     150           6 :                         fputs(talloc_asprintf(ctx, GPTTMPL, minpwdcases[i],
     151             :                                               maxpwdcases[i], pwdlencases[i],
     152             :                                               pwdpropcases[i]), fp);
     153           6 :                         fclose(fp);
     154             :                 }
     155             : 
     156             :                 /* Update the version in the GPT.INI */
     157           6 :                 gpt_file = talloc_asprintf(ctx, "%s/%s", sysvol_path, GPTINI);
     158           6 :                 if ( (fp = fopen(gpt_file, "r")) ) {
     159             :                         char line[256];
     160          12 :                         while (fgets(line, 256, fp)) {
     161          12 :                                 if (strncasecmp(line, "Version=", 8) == 0) {
     162           6 :                                         vers = atoi(line+8);
     163           6 :                                         break;
     164             :                                 }
     165             :                         }
     166           6 :                         fclose(fp);
     167             :                 }
     168           6 :                 if ( (fp = fopen(gpt_file, "w")) ) {
     169           6 :                         char *data = talloc_asprintf(ctx,
     170             :                                                      "[General]\nVersion=%d\n",
     171             :                                                      ++vers);
     172           6 :                         fputs(data, fp);
     173           6 :                         fclose(fp);
     174             :                 }
     175             : 
     176             :                 /* Run the gpo update command */
     177           6 :                 ret = exec_wait(tctx, gpo_update_cmd);
     178             : 
     179           6 :                 torture_assert(tctx, ret == 0,
     180             :                                "Failed to execute the gpo update command");
     181           6 :                 ret = ldb_search(samdb, ctx, &result,
     182             :                                  ldb_get_default_basedn(samdb),
     183             :                                  LDB_SCOPE_BASE, attrs, NULL);
     184           6 :                 torture_assert(tctx, ret == LDB_SUCCESS && result->count == 1,
     185             :                                "Searching the samdb failed");
     186             : 
     187             :                 /* minPwdAge */
     188           6 :                 torture_assert_int_equal(tctx, unix2nttime(
     189             :                                                 ldb_msg_find_attr_as_string(
     190             :                                                         result->msgs[0],
     191             :                                                         attrs[0],
     192             :                                                         "")), minpwdcases[i],
     193             :                                "The minPwdAge was not applied");
     194             : 
     195             :                 /* maxPwdAge */
     196           6 :                 torture_assert_int_equal(tctx, unix2nttime(
     197             :                                                 ldb_msg_find_attr_as_string(
     198             :                                                         result->msgs[0],
     199             :                                                         attrs[1],
     200             :                                                         "")), maxpwdcases[i],
     201             :                                "The maxPwdAge was not applied");
     202             : 
     203             :                 /* minPwdLength */
     204           6 :                 torture_assert_int_equal(tctx, ldb_msg_find_attr_as_int(
     205             :                                                         result->msgs[0],
     206             :                                                         attrs[2],
     207             :                                                         -1),
     208             :                                                pwdlencases[i],
     209             :                                 "The minPwdLength was not applied");
     210             : 
     211             :                 /* pwdProperties */
     212           6 :                 torture_assert_int_equal(tctx, ldb_msg_find_attr_as_int(
     213             :                                                         result->msgs[0],
     214             :                                                         attrs[3],
     215             :                                                         -1),
     216             :                                                pwdpropcases[i],
     217             :                                "The pwdProperties were not applied");
     218             :         }
     219             : 
     220             :         /* Reset settings, then verify a reapply doesn't force them back */
     221          10 :         for (i = 0; i < old_message->num_elements; i++) {
     222           8 :                 old_message->elements[i].flags = LDB_FLAG_MOD_REPLACE;
     223             :         }
     224           2 :         ret = ldb_modify(samdb, old_message);
     225           2 :         torture_assert(tctx, ret == 0, "Failed to reset password settings.");
     226             : 
     227           2 :         ret = exec_wait(tctx, gpo_update_cmd);
     228           2 :         torture_assert(tctx, ret == 0,
     229             :                        "Failed to execute the gpo update command");
     230             : 
     231             :         /* Validate that the apply did nothing (without --force param) */
     232           2 :         ret = ldb_search(samdb, ctx, &result, ldb_get_default_basedn(samdb),
     233             :                          LDB_SCOPE_BASE, attrs, NULL);
     234           2 :         torture_assert(tctx, ret == LDB_SUCCESS && result->count == 1,
     235             :                        "Searching the samdb failed");
     236             :         /* minPwdAge */
     237           2 :         torture_assert_int_equal(tctx, unix2nttime(ldb_msg_find_attr_as_string(
     238             :                                                 result->msgs[0],
     239             :                                                 attrs[0],
     240             :                                                 "")),
     241             :                        unix2nttime(ldb_msg_find_attr_as_string(old_message,
     242             :                                                                attrs[0],
     243             :                                                                "")
     244             :                                   ),
     245             :                        "The minPwdAge was re-applied");
     246             :         /* maxPwdAge */
     247           2 :         torture_assert_int_equal(tctx, unix2nttime(ldb_msg_find_attr_as_string(
     248             :                                                 result->msgs[0],
     249             :                                                 attrs[1],
     250             :                                                 "")),
     251             :                        unix2nttime(ldb_msg_find_attr_as_string(old_message,
     252             :                                                                attrs[1],
     253             :                                                                "")
     254             :                                   ),
     255             :                        "The maxPwdAge was re-applied");
     256             :         /* minPwdLength */
     257           2 :         torture_assert_int_equal(tctx, ldb_msg_find_attr_as_int(
     258             :                                                 result->msgs[0],
     259             :                                                 attrs[2],
     260             :                                                 -1),
     261             :                                        ldb_msg_find_attr_as_int(
     262             :                                                 old_message,
     263             :                                                 attrs[2],
     264             :                                                 -2),
     265             :                         "The minPwdLength was re-applied");
     266             :         /* pwdProperties */
     267           2 :         torture_assert_int_equal(tctx, ldb_msg_find_attr_as_int(
     268             :                                                 result->msgs[0],
     269             :                                                 attrs[3],
     270             :                                                 -1),
     271             :                                         ldb_msg_find_attr_as_int(
     272             :                                                 old_message,
     273             :                                                 attrs[3],
     274             :                                                 -2),
     275             :                         "The pwdProperties were re-applied");
     276             : 
     277          12 :         for (itr = gpo_update_cmd; *itr != NULL; itr++) {
     278          10 :                 gpo_update_len++;
     279             :         }
     280             : 
     281             :         /* Run gpupdate --force and verify settings are re-applied */
     282           2 :         gpo_update_force_cmd = talloc_array(ctx, const char*, gpo_update_len+2);
     283          12 :         for (i = 0; i < gpo_update_len; i++) {
     284          10 :                 gpo_update_force_cmd[i] = talloc_strdup(gpo_update_force_cmd,
     285          10 :                                                         gpo_update_cmd[i]);
     286             :         }
     287           2 :         gpo_update_force_cmd[i] = talloc_asprintf(gpo_update_force_cmd,
     288             :                                                   "--force");
     289           2 :         gpo_update_force_cmd[i+1] = NULL;
     290           2 :         ret = exec_wait(tctx, gpo_update_force_cmd);
     291           2 :         torture_assert(tctx, ret == 0,
     292             :                        "Failed to execute the gpupdate --force command");
     293             : 
     294           2 :         ret = ldb_search(samdb, ctx, &result,
     295             :                          ldb_get_default_basedn(samdb),
     296             :                          LDB_SCOPE_BASE, attrs, NULL);
     297           2 :         torture_assert(tctx, ret == LDB_SUCCESS && result->count == 1,
     298             :                        "Searching the samdb failed");
     299             : 
     300             :         /* minPwdAge */
     301           2 :         torture_assert_int_equal(tctx, unix2nttime(
     302             :                                         ldb_msg_find_attr_as_string(
     303             :                                                 result->msgs[0],
     304             :                                                 attrs[0],
     305             :                                                 "")), minpwdcases[2],
     306             :                        "The minPwdAge was not applied");
     307             : 
     308             :         /* maxPwdAge */
     309           2 :         torture_assert_int_equal(tctx, unix2nttime(
     310             :                                         ldb_msg_find_attr_as_string(
     311             :                                                 result->msgs[0],
     312             :                                                 attrs[1],
     313             :                                                 "")), maxpwdcases[2],
     314             :                        "The maxPwdAge was not applied");
     315             : 
     316             :         /* minPwdLength */
     317           2 :         torture_assert_int_equal(tctx, ldb_msg_find_attr_as_int(
     318             :                                                 result->msgs[0],
     319             :                                                 attrs[2],
     320             :                                                 -1),
     321             :                                        pwdlencases[2],
     322             :                         "The minPwdLength was not applied");
     323             : 
     324             :         /* pwdProperties */
     325           2 :         torture_assert_int_equal(tctx, ldb_msg_find_attr_as_int(
     326             :                                                 result->msgs[0],
     327             :                                                 attrs[3],
     328             :                                                 -1),
     329             :                                        pwdpropcases[2],
     330             :                        "The pwdProperties were not applied");
     331             : 
     332             :         /* Unapply the settings and verify they are removed */
     333           2 :         gpo_unapply_cmd = talloc_array(ctx, const char*, gpo_update_len+2);
     334          12 :         for (i = 0; i < gpo_update_len; i++) {
     335          10 :                 gpo_unapply_cmd[i] = talloc_strdup(gpo_unapply_cmd,
     336          10 :                                                    gpo_update_cmd[i]);
     337             :         }
     338           2 :         gpo_unapply_cmd[i] = talloc_asprintf(gpo_unapply_cmd, "--unapply");
     339           2 :         gpo_unapply_cmd[i+1] = NULL;
     340           2 :         ret = exec_wait(tctx, gpo_unapply_cmd);
     341           2 :         torture_assert(tctx, ret == 0,
     342             :                        "Failed to execute the gpo unapply command");
     343           2 :         ret = ldb_search(samdb, ctx, &result, ldb_get_default_basedn(samdb),
     344             :                          LDB_SCOPE_BASE, attrs, NULL);
     345           2 :         torture_assert(tctx, ret == LDB_SUCCESS && result->count == 1,
     346             :                        "Searching the samdb failed");
     347             :         /* minPwdAge */
     348           2 :         torture_assert_int_equal(tctx, unix2nttime(ldb_msg_find_attr_as_string(
     349             :                                                 result->msgs[0],
     350             :                                                 attrs[0],
     351             :                                                 "")),
     352             :                        unix2nttime(ldb_msg_find_attr_as_string(old_message,
     353             :                                                                attrs[0],
     354             :                                                                "")
     355             :                                   ),
     356             :                        "The minPwdAge was not unapplied");
     357             :         /* maxPwdAge */
     358           2 :         torture_assert_int_equal(tctx, unix2nttime(ldb_msg_find_attr_as_string(
     359             :                                                 result->msgs[0],
     360             :                                                 attrs[1],
     361             :                                                 "")),
     362             :                        unix2nttime(ldb_msg_find_attr_as_string(old_message,
     363             :                                                                attrs[1],
     364             :                                                                "")
     365             :                                   ),
     366             :                        "The maxPwdAge was not unapplied");
     367             :         /* minPwdLength */
     368           2 :         torture_assert_int_equal(tctx, ldb_msg_find_attr_as_int(
     369             :                                                 result->msgs[0],
     370             :                                                 attrs[2],
     371             :                                                 -1),
     372             :                                        ldb_msg_find_attr_as_int(
     373             :                                                 old_message,
     374             :                                                 attrs[2],
     375             :                                                 -2),
     376             :                         "The minPwdLength was not unapplied");
     377             :         /* pwdProperties */
     378           2 :         torture_assert_int_equal(tctx, ldb_msg_find_attr_as_int(
     379             :                                                 result->msgs[0],
     380             :                                                 attrs[3],
     381             :                                                 -1),
     382             :                                         ldb_msg_find_attr_as_int(
     383             :                                                 old_message,
     384             :                                                 attrs[3],
     385             :                                                 -2),
     386             :                         "The pwdProperties were not unapplied");
     387             : 
     388           2 :         talloc_free(ctx);
     389           2 :         return true;
     390             : }

Generated by: LCOV version 1.14