LCOV - code coverage report
Current view: top level - libgpo - gpo_ldap.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 184 395 46.6 %
Date: 2024-02-28 12:06:22 Functions: 9 12 75.0 %

          Line data    Source code
       1             : /*
       2             :  *  Unix SMB/CIFS implementation.
       3             :  *  Group Policy Object Support
       4             :  *  Copyright (C) Guenther Deschner 2005,2007
       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 "libgpo/gpo.h"
      22             : #include "auth.h"
      23             : #include "../libcli/security/security.h"
      24             : 
      25             : /****************************************************************
      26             :  parse the raw extension string into a GP_EXT structure
      27             : ****************************************************************/
      28             : 
      29           0 : bool ads_parse_gp_ext(TALLOC_CTX *mem_ctx,
      30             :                       const char *extension_raw,
      31             :                       struct GP_EXT **gp_ext)
      32             : {
      33           0 :         bool ret = false;
      34           0 :         struct GP_EXT *ext = NULL;
      35           0 :         char **ext_list = NULL;
      36           0 :         char **ext_strings = NULL;
      37           0 :         int i;
      38             : 
      39           0 :         if (!extension_raw) {
      40           0 :                 goto parse_error;
      41             :         }
      42             : 
      43           0 :         DEBUG(20,("ads_parse_gp_ext: %s\n", extension_raw));
      44             : 
      45           0 :         ext = talloc_zero(mem_ctx, struct GP_EXT);
      46           0 :         if (!ext) {
      47           0 :                 goto parse_error;
      48             :         }
      49             : 
      50           0 :         ext_list = str_list_make(mem_ctx, extension_raw, "]");
      51           0 :         if (!ext_list) {
      52           0 :                 goto parse_error;
      53             :         }
      54             : 
      55           0 :         for (i = 0; ext_list[i] != NULL; i++) {
      56             :                 /* no op */
      57           0 :         }
      58             : 
      59           0 :         ext->num_exts = i;
      60             : 
      61           0 :         if (ext->num_exts) {
      62           0 :                 ext->extensions      = talloc_zero_array(mem_ctx, char *,
      63             :                                                             ext->num_exts);
      64           0 :                 ext->extensions_guid = talloc_zero_array(mem_ctx, char *,
      65             :                                                             ext->num_exts);
      66           0 :                 ext->snapins         = talloc_zero_array(mem_ctx, char *,
      67             :                                                             ext->num_exts);
      68           0 :                 ext->snapins_guid    = talloc_zero_array(mem_ctx, char *,
      69             :                                                             ext->num_exts);
      70             :         }
      71             : 
      72           0 :         ext->gp_extension = talloc_strdup(mem_ctx, extension_raw);
      73             : 
      74           0 :         if (!ext->extensions || !ext->extensions_guid ||
      75           0 :             !ext->snapins || !ext->snapins_guid ||
      76           0 :             !ext->gp_extension) {
      77           0 :                 goto parse_error;
      78             :         }
      79             : 
      80           0 :         for (i = 0; ext_list[i] != NULL; i++) {
      81             : 
      82           0 :                 int k;
      83           0 :                 char *p, *q;
      84             : 
      85           0 :                 DEBUGADD(10,("extension #%d\n", i));
      86             : 
      87           0 :                 p = ext_list[i];
      88             : 
      89           0 :                 if (p[0] == '[') {
      90           0 :                         p++;
      91             :                 }
      92             : 
      93           0 :                 ext_strings = str_list_make(mem_ctx, p, "}");
      94           0 :                 if (ext_strings == NULL) {
      95           0 :                         goto parse_error;
      96             :                 }
      97             : 
      98           0 :                 for (k = 0; ext_strings[k] != NULL; k++) {
      99             :                         /* no op */
     100           0 :                 }
     101           0 :                 if (k == 0) {
     102           0 :                         goto parse_error;
     103             :                 }
     104           0 :                 q = ext_strings[0];
     105             : 
     106           0 :                 if (q[0] == '{') {
     107           0 :                         q++;
     108             :                 }
     109             : 
     110           0 :                 ext->extensions[i] = talloc_strdup(mem_ctx,
     111             :                                            cse_gpo_guid_string_to_name(q));
     112           0 :                 ext->extensions_guid[i] = talloc_strdup(mem_ctx, q);
     113             : 
     114             :                 /* we might have no name for the guid */
     115           0 :                 if (ext->extensions_guid[i] == NULL) {
     116           0 :                         goto parse_error;
     117             :                 }
     118             : 
     119           0 :                 for (k = 1; ext_strings[k] != NULL; k++) {
     120             : 
     121           0 :                         char *m = ext_strings[k];
     122             : 
     123           0 :                         if (m[0] == '{') {
     124           0 :                                 m++;
     125             :                         }
     126             : 
     127             :                         /* FIXME: theoretically there could be more than one
     128             :                          * snapin per extension */
     129           0 :                         ext->snapins[i] = talloc_strdup(mem_ctx,
     130             :                                 cse_snapin_gpo_guid_string_to_name(m));
     131           0 :                         ext->snapins_guid[i] = talloc_strdup(mem_ctx, m);
     132             : 
     133             :                         /* we might have no name for the guid */
     134           0 :                         if (ext->snapins_guid[i] == NULL) {
     135           0 :                                 goto parse_error;
     136             :                         }
     137             :                 }
     138             :         }
     139             : 
     140           0 :         *gp_ext = ext;
     141             : 
     142           0 :         ret = true;
     143             : 
     144           0 :  parse_error:
     145           0 :         talloc_free(ext_list);
     146           0 :         talloc_free(ext_strings);
     147             : 
     148           0 :         return ret;
     149             : }
     150             : 
     151             : #ifdef HAVE_LDAP
     152             : 
     153             : /****************************************************************
     154             :  parse the raw link string into a GP_LINK structure
     155             : ****************************************************************/
     156             : 
     157           4 : static ADS_STATUS gpo_parse_gplink(TALLOC_CTX *mem_ctx,
     158             :                                    const char *gp_link_raw,
     159             :                                    uint32_t options,
     160             :                                    struct GP_LINK *gp_link)
     161             : {
     162           4 :         ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
     163           0 :         char **link_list;
     164           0 :         int i;
     165             : 
     166           4 :         ZERO_STRUCTP(gp_link);
     167             : 
     168           4 :         DEBUG(10,("gpo_parse_gplink: gPLink: %s\n", gp_link_raw));
     169             : 
     170           4 :         link_list = str_list_make_v3(mem_ctx, gp_link_raw, "]");
     171           4 :         if (!link_list) {
     172           0 :                 goto parse_error;
     173             :         }
     174             : 
     175           8 :         for (i = 0; link_list[i] != NULL; i++) {
     176             :                 /* no op */
     177           0 :         }
     178             : 
     179           4 :         gp_link->gp_opts = options;
     180           4 :         gp_link->num_links = i;
     181             : 
     182           4 :         if (gp_link->num_links) {
     183           4 :                 gp_link->link_names = talloc_zero_array(mem_ctx, char *,
     184             :                                                         gp_link->num_links);
     185           4 :                 gp_link->link_opts = talloc_zero_array(mem_ctx, uint32_t,
     186             :                                                        gp_link->num_links);
     187             :         }
     188             : 
     189           4 :         gp_link->gp_link = talloc_strdup(mem_ctx, gp_link_raw);
     190             : 
     191           4 :         if (!gp_link->link_names || !gp_link->link_opts || !gp_link->gp_link) {
     192           0 :                 goto parse_error;
     193             :         }
     194             : 
     195           8 :         for (i = 0; link_list[i] != NULL; i++) {
     196             : 
     197           0 :                 char *p, *q;
     198             : 
     199           4 :                 DEBUGADD(10,("gpo_parse_gplink: processing link #%d\n", i));
     200             : 
     201           4 :                 q = link_list[i];
     202           4 :                 if (q[0] == '[') {
     203           4 :                         q++;
     204           0 :                 };
     205             : 
     206           4 :                 p = strchr(q, ';');
     207             : 
     208           4 :                 if (p == NULL) {
     209           0 :                         goto parse_error;
     210             :                 }
     211             : 
     212           4 :                 gp_link->link_names[i] = talloc_strdup(mem_ctx, q);
     213           4 :                 if (gp_link->link_names[i] == NULL) {
     214           0 :                         goto parse_error;
     215             :                 }
     216           4 :                 gp_link->link_names[i][PTR_DIFF(p, q)] = 0;
     217             : 
     218           4 :                 gp_link->link_opts[i] = atoi(p + 1);
     219             : 
     220           4 :                 DEBUGADD(10,("gpo_parse_gplink: link: %s\n",
     221             :                         gp_link->link_names[i]));
     222           4 :                 DEBUGADD(10,("gpo_parse_gplink: opt: %d\n",
     223             :                         gp_link->link_opts[i]));
     224             : 
     225             :         }
     226             : 
     227           4 :         status = ADS_SUCCESS;
     228             : 
     229           4 :  parse_error:
     230           4 :         talloc_free(link_list);
     231             : 
     232           4 :         return status;
     233             : }
     234             : 
     235             : /****************************************************************
     236             :  helper call to get a GP_LINK structure from a linkdn
     237             : ****************************************************************/
     238             : 
     239           6 : ADS_STATUS ads_get_gpo_link(ADS_STRUCT *ads,
     240             :                             TALLOC_CTX *mem_ctx,
     241             :                             const char *link_dn,
     242             :                             struct GP_LINK *gp_link_struct)
     243             : {
     244           0 :         ADS_STATUS status;
     245           6 :         const char *attrs[] = {"gPLink", "gPOptions", NULL};
     246           6 :         LDAPMessage *res = NULL;
     247           0 :         const char *gp_link;
     248           0 :         uint32_t gp_options;
     249             : 
     250           6 :         ZERO_STRUCTP(gp_link_struct);
     251             : 
     252           6 :         status = ads_search_dn(ads, &res, link_dn, attrs);
     253           6 :         if (!ADS_ERR_OK(status)) {
     254           0 :                 DEBUG(10,("ads_get_gpo_link: search failed with %s\n",
     255             :                         ads_errstr(status)));
     256           0 :                 return status;
     257             :         }
     258             : 
     259           6 :         if (ads_count_replies(ads, res) != 1) {
     260           0 :                 DEBUG(10,("ads_get_gpo_link: no result\n"));
     261           0 :                 ads_msgfree(ads, res);
     262           0 :                 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
     263             :         }
     264             : 
     265           6 :         gp_link = ads_pull_string(ads, mem_ctx, res, "gPLink");
     266           6 :         if (gp_link == NULL) {
     267           2 :                 DEBUG(10,("ads_get_gpo_link: no 'gPLink' attribute found\n"));
     268           2 :                 ads_msgfree(ads, res);
     269           2 :                 return ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE);
     270             :         }
     271             : 
     272             :         /* perfectly legal to have no options */
     273           4 :         if (!ads_pull_uint32(ads, res, "gPOptions", &gp_options)) {
     274           4 :                 DEBUG(10,("ads_get_gpo_link: "
     275             :                         "no 'gPOptions' attribute found\n"));
     276           4 :                 gp_options = 0;
     277             :         }
     278             : 
     279           4 :         ads_msgfree(ads, res);
     280             : 
     281           4 :         return gpo_parse_gplink(mem_ctx, gp_link, gp_options, gp_link_struct);
     282             : }
     283             : 
     284             : /****************************************************************
     285             :  helper call to add a gp link
     286             : ****************************************************************/
     287             : 
     288           0 : ADS_STATUS ads_add_gpo_link(ADS_STRUCT *ads,
     289             :                             TALLOC_CTX *mem_ctx,
     290             :                             const char *link_dn,
     291             :                             const char *gpo_dn,
     292             :                             uint32_t gpo_opt)
     293             : {
     294           0 :         ADS_STATUS status;
     295           0 :         const char *attrs[] = {"gPLink", NULL};
     296           0 :         LDAPMessage *res = NULL;
     297           0 :         const char *gp_link, *gp_link_new;
     298           0 :         ADS_MODLIST mods;
     299             : 
     300             :         /* although ADS allows one to set anything here, we better check here if
     301             :          * the gpo_dn is sane */
     302             : 
     303           0 :         if (!strnequal(gpo_dn, "LDAP://CN={", strlen("LDAP://CN={")) != 0) {
     304           0 :                 return ADS_ERROR(LDAP_INVALID_DN_SYNTAX);
     305             :         }
     306             : 
     307           0 :         status = ads_search_dn(ads, &res, link_dn, attrs);
     308           0 :         if (!ADS_ERR_OK(status)) {
     309           0 :                 DEBUG(10,("ads_add_gpo_link: search failed with %s\n",
     310             :                         ads_errstr(status)));
     311           0 :                 return status;
     312             :         }
     313             : 
     314           0 :         if (ads_count_replies(ads, res) != 1) {
     315           0 :                 DEBUG(10,("ads_add_gpo_link: no result\n"));
     316           0 :                 ads_msgfree(ads, res);
     317           0 :                 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
     318             :         }
     319             : 
     320           0 :         gp_link = ads_pull_string(ads, mem_ctx, res, "gPLink");
     321           0 :         if (gp_link == NULL) {
     322           0 :                 gp_link_new = talloc_asprintf(mem_ctx, "[%s;%d]",
     323             :                         gpo_dn, gpo_opt);
     324             :         } else {
     325           0 :                 gp_link_new = talloc_asprintf(mem_ctx, "%s[%s;%d]",
     326             :                         gp_link, gpo_dn, gpo_opt);
     327             :         }
     328             : 
     329           0 :         ads_msgfree(ads, res);
     330           0 :         ADS_ERROR_HAVE_NO_MEMORY(gp_link_new);
     331             : 
     332           0 :         mods = ads_init_mods(mem_ctx);
     333           0 :         ADS_ERROR_HAVE_NO_MEMORY(mods);
     334             : 
     335           0 :         status = ads_mod_str(mem_ctx, &mods, "gPLink", gp_link_new);
     336           0 :         if (!ADS_ERR_OK(status)) {
     337           0 :                 return status;
     338             :         }
     339             : 
     340           0 :         return ads_gen_mod(ads, link_dn, mods);
     341             : }
     342             : 
     343             : /****************************************************************
     344             :  helper call to delete add a gp link
     345             : ****************************************************************/
     346             : 
     347             : /* untested & broken */
     348           0 : ADS_STATUS ads_delete_gpo_link(ADS_STRUCT *ads,
     349             :                                TALLOC_CTX *mem_ctx,
     350             :                                const char *link_dn,
     351             :                                const char *gpo_dn)
     352             : {
     353           0 :         ADS_STATUS status;
     354           0 :         const char *attrs[] = {"gPLink", NULL};
     355           0 :         LDAPMessage *res = NULL;
     356           0 :         const char *gp_link, *gp_link_new = NULL;
     357           0 :         ADS_MODLIST mods;
     358             : 
     359             :         /* check for a sane gpo_dn */
     360           0 :         if (gpo_dn[0] != '[') {
     361           0 :                 DEBUG(10,("ads_delete_gpo_link: first char not: [\n"));
     362           0 :                 return ADS_ERROR(LDAP_INVALID_DN_SYNTAX);
     363             :         }
     364             : 
     365           0 :         if (gpo_dn[strlen(gpo_dn)] != ']') {
     366           0 :                 DEBUG(10,("ads_delete_gpo_link: last char not: ]\n"));
     367           0 :                 return ADS_ERROR(LDAP_INVALID_DN_SYNTAX);
     368             :         }
     369             : 
     370           0 :         status = ads_search_dn(ads, &res, link_dn, attrs);
     371           0 :         if (!ADS_ERR_OK(status)) {
     372           0 :                 DEBUG(10,("ads_delete_gpo_link: search failed with %s\n",
     373             :                         ads_errstr(status)));
     374           0 :                 return status;
     375             :         }
     376             : 
     377           0 :         if (ads_count_replies(ads, res) != 1) {
     378           0 :                 DEBUG(10,("ads_delete_gpo_link: no result\n"));
     379           0 :                 ads_msgfree(ads, res);
     380           0 :                 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
     381             :         }
     382             : 
     383           0 :         gp_link = ads_pull_string(ads, mem_ctx, res, "gPLink");
     384           0 :         if (gp_link == NULL) {
     385           0 :                 return ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE);
     386             :         }
     387             : 
     388             :         /* find link to delete */
     389             :         /* gp_link_new = talloc_asprintf(mem_ctx, "%s[%s;%d]", gp_link,
     390             :                                          gpo_dn, gpo_opt); */
     391             : 
     392           0 :         ads_msgfree(ads, res);
     393           0 :         ADS_ERROR_HAVE_NO_MEMORY(gp_link_new);
     394             : 
     395           0 :         mods = ads_init_mods(mem_ctx);
     396           0 :         ADS_ERROR_HAVE_NO_MEMORY(mods);
     397             : 
     398           0 :         status = ads_mod_str(mem_ctx, &mods, "gPLink", gp_link_new);
     399           0 :         if (!ADS_ERR_OK(status)) {
     400           0 :                 return status;
     401             :         }
     402             : 
     403           0 :         return ads_gen_mod(ads, link_dn, mods);
     404             : }
     405             : 
     406             : /****************************************************************
     407             :  parse a GROUP_POLICY_OBJECT structure from an LDAPMessage result
     408             : ****************************************************************/
     409             : 
     410           4 :  ADS_STATUS ads_parse_gpo(ADS_STRUCT *ads,
     411             :                           TALLOC_CTX *mem_ctx,
     412             :                           LDAPMessage *res,
     413             :                           const char *gpo_dn,
     414             :                           struct GROUP_POLICY_OBJECT *gpo)
     415             : {
     416           4 :         ZERO_STRUCTP(gpo);
     417             : 
     418           4 :         ADS_ERROR_HAVE_NO_MEMORY(res);
     419             : 
     420           4 :         if (gpo_dn) {
     421           4 :                 gpo->ds_path = talloc_strdup(mem_ctx, gpo_dn);
     422             :         } else {
     423           0 :                 gpo->ds_path = ads_get_dn(ads, mem_ctx, res);
     424             :         }
     425             : 
     426           4 :         ADS_ERROR_HAVE_NO_MEMORY(gpo->ds_path);
     427             : 
     428           4 :         if (!ads_pull_uint32(ads, res, "versionNumber", &gpo->version)) {
     429           0 :                 return ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE);
     430             :         }
     431             : 
     432           4 :         if (!ads_pull_uint32(ads, res, "flags", &gpo->options)) {
     433           0 :                 return ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE);
     434             :         }
     435             : 
     436           4 :         gpo->file_sys_path = ads_pull_string(ads, mem_ctx, res,
     437             :                 "gPCFileSysPath");
     438           4 :         if (gpo->file_sys_path == NULL) {
     439           0 :                 return ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE);
     440             :         }
     441             : 
     442           4 :         gpo->display_name = ads_pull_string(ads, mem_ctx, res,
     443             :                 "displayName");
     444           4 :         if (gpo->display_name == NULL) {
     445           0 :                 return ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE);
     446             :         }
     447             : 
     448           4 :         gpo->name = ads_pull_string(ads, mem_ctx, res,
     449             :                 "name");
     450           4 :         if (gpo->name == NULL) {
     451           0 :                 return ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE);
     452             :         }
     453             : 
     454           4 :         gpo->machine_extensions = ads_pull_string(ads, mem_ctx, res,
     455             :                 "gPCMachineExtensionNames");
     456           4 :         gpo->user_extensions = ads_pull_string(ads, mem_ctx, res,
     457             :                 "gPCUserExtensionNames");
     458             : 
     459           4 :         ads_pull_sd(ads, mem_ctx, res, "ntSecurityDescriptor",
     460             :                 &gpo->security_descriptor);
     461           4 :         if (gpo->security_descriptor == NULL) {
     462           0 :                 return ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE);
     463             :         }
     464             : 
     465           4 :         return ADS_ERROR(LDAP_SUCCESS);
     466             : }
     467             : 
     468             : /****************************************************************
     469             :  get a GROUP_POLICY_OBJECT structure based on different input parameters
     470             : ****************************************************************/
     471             : 
     472           4 : ADS_STATUS ads_get_gpo(ADS_STRUCT *ads,
     473             :                        TALLOC_CTX *mem_ctx,
     474             :                        const char *gpo_dn,
     475             :                        const char *display_name,
     476             :                        const char *guid_name,
     477             :                        struct GROUP_POLICY_OBJECT *gpo)
     478             : {
     479           4 :         ADS_STATUS status = ADS_ERROR(LDAP_NO_SUCH_OBJECT);
     480           4 :         LDAPMessage *res = NULL;
     481           0 :         char *dn;
     482           0 :         const char *filter;
     483           4 :         const char *attrs[] = {
     484             :                 "cn",
     485             :                 "displayName",
     486             :                 "flags",
     487             :                 "gPCFileSysPath",
     488             :                 "gPCFunctionalityVersion",
     489             :                 "gPCMachineExtensionNames",
     490             :                 "gPCUserExtensionNames",
     491             :                 "gPCWQLFilter",
     492             :                 "name",
     493             :                 "ntSecurityDescriptor",
     494             :                 "versionNumber",
     495             :                 NULL};
     496           4 :         uint32_t sd_flags = SECINFO_DACL;
     497             : 
     498           4 :         ZERO_STRUCTP(gpo);
     499             : 
     500           4 :         if (!gpo_dn && !display_name && !guid_name) {
     501           0 :                 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
     502             :         }
     503             : 
     504           4 :         if (gpo_dn) {
     505             : 
     506           4 :                 if (strnequal(gpo_dn, "LDAP://", strlen("LDAP://")) != 0) {
     507           4 :                         gpo_dn = gpo_dn + strlen("LDAP://");
     508             :                 }
     509             : 
     510           4 :                 status = ads_search_retry_dn_sd_flags(ads, &res,
     511             :                                                       sd_flags,
     512             :                                                       gpo_dn, attrs);
     513             : 
     514           0 :         } else if (display_name || guid_name) {
     515             : 
     516           0 :                 filter = talloc_asprintf(mem_ctx,
     517             :                                  "(&(objectclass=groupPolicyContainer)(%s=%s))",
     518             :                                  display_name ? "displayName" : "name",
     519             :                                  display_name ? display_name : guid_name);
     520           0 :                 ADS_ERROR_HAVE_NO_MEMORY(filter);
     521             : 
     522           0 :                 status = ads_do_search_all_sd_flags(ads, ads->config.bind_path,
     523             :                                                     LDAP_SCOPE_SUBTREE, filter,
     524             :                                                     attrs, sd_flags, &res);
     525             :         }
     526             : 
     527           4 :         if (!ADS_ERR_OK(status)) {
     528           0 :                 DEBUG(10,("ads_get_gpo: search failed with %s\n",
     529             :                         ads_errstr(status)));
     530           0 :                 return status;
     531             :         }
     532             : 
     533           4 :         if (ads_count_replies(ads, res) != 1) {
     534           0 :                 DEBUG(10,("ads_get_gpo: no result\n"));
     535           0 :                 ads_msgfree(ads, res);
     536           0 :                 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
     537             :         }
     538             : 
     539           4 :         dn = ads_get_dn(ads, mem_ctx, res);
     540           4 :         if (dn == NULL) {
     541           0 :                 ads_msgfree(ads, res);
     542           0 :                 return ADS_ERROR(LDAP_NO_MEMORY);
     543             :         }
     544             : 
     545           4 :         status = ads_parse_gpo(ads, mem_ctx, res, dn, gpo);
     546           4 :         ads_msgfree(ads, res);
     547           4 :         TALLOC_FREE(dn);
     548             : 
     549           4 :         return status;
     550             : }
     551             : 
     552             : /****************************************************************
     553             :  add a gplink to the GROUP_POLICY_OBJECT linked list
     554             : ****************************************************************/
     555             : 
     556           4 : static ADS_STATUS add_gplink_to_gpo_list(ADS_STRUCT *ads,
     557             :                                          TALLOC_CTX *mem_ctx,
     558             :                                          struct GROUP_POLICY_OBJECT **gpo_list,
     559             :                                          struct GROUP_POLICY_OBJECT **forced_gpo_list,
     560             :                                          const char *link_dn,
     561             :                                          struct GP_LINK *gp_link,
     562             :                                          enum GPO_LINK_TYPE link_type,
     563             :                                          bool only_add_forced_gpos,
     564             :                                          const struct security_token *token)
     565             : {
     566           0 :         ADS_STATUS status;
     567           0 :         uint32_t count;
     568             : 
     569             :         /*
     570             :          * Note: DLIST_ADD pushes to the front,
     571             :          * so loop from last to first to get the
     572             :          * order right.
     573             :          */
     574           8 :         for (count = gp_link->num_links; count > 0; count--) {
     575             :                 /* NB. Index into arrays is one less than counter. */
     576           4 :                 uint32_t i = count - 1;
     577           4 :                 struct GROUP_POLICY_OBJECT **target_list = NULL;
     578           4 :                 struct GROUP_POLICY_OBJECT *new_gpo = NULL;
     579           4 :                 bool is_forced =
     580           4 :                         (gp_link->link_opts[i] & GPO_LINK_OPT_ENFORCED) != 0;
     581             : 
     582           4 :                 if (gp_link->link_opts[i] & GPO_LINK_OPT_DISABLED) {
     583           0 :                         DEBUG(10,("skipping disabled GPO\n"));
     584           0 :                         continue;
     585             :                 }
     586             : 
     587           4 :                 if (only_add_forced_gpos) {
     588             : 
     589           0 :                         if (!is_forced) {
     590           0 :                                 DEBUG(10,("skipping nonenforced GPO link "
     591             :                                         "because GPOPTIONS_BLOCK_INHERITANCE "
     592             :                                         "has been set\n"));
     593           0 :                                 continue;
     594             :                         } else {
     595           0 :                                 DEBUG(10,("adding enforced GPO link although "
     596             :                                         "the GPOPTIONS_BLOCK_INHERITANCE "
     597             :                                         "has been set\n"));
     598             :                         }
     599             :                 }
     600             : 
     601           4 :                 new_gpo = talloc_zero(mem_ctx, struct GROUP_POLICY_OBJECT);
     602           4 :                 ADS_ERROR_HAVE_NO_MEMORY(new_gpo);
     603             : 
     604           4 :                 status = ads_get_gpo(ads, mem_ctx, gp_link->link_names[i],
     605             :                                      NULL, NULL, new_gpo);
     606           4 :                 if (!ADS_ERR_OK(status)) {
     607           0 :                         DEBUG(10,("failed to get gpo: %s\n",
     608             :                                 gp_link->link_names[i]));
     609           0 :                         if ((status.error_type == ENUM_ADS_ERROR_LDAP) &&
     610           0 :                             (status.err.rc == LDAP_NO_SUCH_ATTRIBUTE)) {
     611           0 :                                 DEBUG(10,("skipping empty gpo: %s\n",
     612             :                                         gp_link->link_names[i]));
     613           0 :                                 talloc_free(new_gpo);
     614           0 :                                 continue;
     615             :                         }
     616           0 :                         return status;
     617             :                 }
     618             : 
     619           4 :                 status = ADS_ERROR_NT(gpo_apply_security_filtering(new_gpo,
     620             :                                                                    token));
     621           4 :                 if (!ADS_ERR_OK(status)) {
     622           0 :                         DEBUG(10,("skipping GPO \"%s\" as object "
     623             :                                 "has no access to it\n",
     624             :                                 new_gpo->display_name));
     625           0 :                         talloc_free(new_gpo);
     626           0 :                         continue;
     627             :                 }
     628             : 
     629           4 :                 new_gpo->link = link_dn;
     630           4 :                 new_gpo->link_type = link_type;
     631             : 
     632           4 :                 target_list = is_forced ? forced_gpo_list : gpo_list;
     633           4 :                 DLIST_ADD(*target_list, new_gpo);
     634             : 
     635           4 :                 DEBUG(10,("add_gplink_to_gplist: added GPLINK #%d %s "
     636             :                         "to GPO list\n", i, gp_link->link_names[i]));
     637             :         }
     638             : 
     639           4 :         return ADS_ERROR(LDAP_SUCCESS);
     640             : }
     641             : 
     642             : /****************************************************************
     643             : ****************************************************************/
     644             : 
     645           2 : ADS_STATUS ads_get_sid_token(ADS_STRUCT *ads,
     646             :                              TALLOC_CTX *mem_ctx,
     647             :                              const char *dn,
     648             :                              struct security_token **token)
     649             : {
     650           0 :         ADS_STATUS status;
     651           0 :         struct dom_sid object_sid;
     652           0 :         struct dom_sid primary_group_sid;
     653           0 :         struct dom_sid *ad_token_sids;
     654           2 :         size_t num_ad_token_sids = 0;
     655           0 :         struct dom_sid *token_sids;
     656           2 :         uint32_t num_token_sids = 0;
     657           2 :         struct security_token *new_token = NULL;
     658           0 :         int i;
     659             : 
     660           2 :         status = ads_get_tokensids(ads, mem_ctx, dn,
     661             :                                    &object_sid, &primary_group_sid,
     662             :                                    &ad_token_sids, &num_ad_token_sids);
     663           2 :         if (!ADS_ERR_OK(status)) {
     664           0 :                 return status;
     665             :         }
     666             : 
     667           2 :         token_sids = talloc_array(mem_ctx, struct dom_sid, 1);
     668           2 :         ADS_ERROR_HAVE_NO_MEMORY(token_sids);
     669             : 
     670           2 :         status = ADS_ERROR_NT(add_sid_to_array_unique(mem_ctx,
     671             :                                                       &primary_group_sid,
     672             :                                                       &token_sids,
     673             :                                                       &num_token_sids));
     674           2 :         if (!ADS_ERR_OK(status)) {
     675           0 :                 return status;
     676             :         }
     677             : 
     678           6 :         for (i = 0; i < num_ad_token_sids; i++) {
     679             : 
     680           4 :                 if (sid_check_is_in_builtin(&ad_token_sids[i])) {
     681           0 :                         continue;
     682             :                 }
     683             : 
     684           4 :                 status = ADS_ERROR_NT(add_sid_to_array_unique(mem_ctx,
     685             :                                                               &ad_token_sids[i],
     686             :                                                               &token_sids,
     687             :                                                               &num_token_sids));
     688           4 :                 if (!ADS_ERR_OK(status)) {
     689           0 :                         return status;
     690             :                 }
     691             :         }
     692             : 
     693           2 :         status = ADS_ERROR_NT(create_local_nt_token(mem_ctx, 
     694             :                                           &object_sid, false,
     695             :                                           num_token_sids, token_sids, &new_token));
     696           2 :         if (!ADS_ERR_OK(status)) {
     697           0 :                 return status;
     698             :         }
     699             :         
     700           2 :         *token = new_token;
     701             : 
     702           2 :         security_token_debug(DBGC_CLASS, 5, *token);
     703             : 
     704           2 :         return ADS_ERROR_LDAP(LDAP_SUCCESS);
     705             : }
     706             : 
     707             : /****************************************************************
     708             : ****************************************************************/
     709             : 
     710           2 : static ADS_STATUS add_local_policy_to_gpo_list(TALLOC_CTX *mem_ctx,
     711             :                                                struct GROUP_POLICY_OBJECT **gpo_list,
     712             :                                                enum GPO_LINK_TYPE link_type)
     713             : {
     714           2 :         struct GROUP_POLICY_OBJECT *gpo = NULL;
     715             : 
     716           2 :         ADS_ERROR_HAVE_NO_MEMORY(gpo_list);
     717             : 
     718           2 :         gpo = talloc_zero(mem_ctx, struct GROUP_POLICY_OBJECT);
     719           2 :         ADS_ERROR_HAVE_NO_MEMORY(gpo);
     720             : 
     721           2 :         gpo->name = talloc_strdup(mem_ctx, "Local Policy");
     722           2 :         ADS_ERROR_HAVE_NO_MEMORY(gpo->name);
     723             : 
     724           2 :         gpo->display_name = talloc_strdup(mem_ctx, "Local Policy");
     725           2 :         ADS_ERROR_HAVE_NO_MEMORY(gpo->display_name);
     726             : 
     727           2 :         gpo->link_type = link_type;
     728             : 
     729           2 :         DLIST_ADD(*gpo_list, gpo);
     730             : 
     731           2 :         return ADS_ERROR_NT(NT_STATUS_OK);
     732             : }
     733             : 
     734             : /****************************************************************
     735             :  Get the full list of GROUP_POLICY_OBJECTs for a given dn.
     736             : ****************************************************************/
     737             : 
     738           2 : static ADS_STATUS ads_get_gpo_list_internal(ADS_STRUCT *ads,
     739             :                             TALLOC_CTX *mem_ctx,
     740             :                             const char *dn,
     741             :                             uint32_t flags,
     742             :                             const struct security_token *token,
     743             :                             struct GROUP_POLICY_OBJECT **gpo_list,
     744             :                             struct GROUP_POLICY_OBJECT **forced_gpo_list)
     745             : {
     746             :         /*
     747             :          * Push GPOs to gpo_list so that the traversal order of the list matches
     748             :          * the order of application:
     749             :          * (L)ocal (S)ite (D)omain (O)rganizational(U)nit
     750             :          * For different domains and OUs: parent-to-child.
     751             :          * Within same level of domains and OUs: Link order.
     752             :          * Since GPOs are pushed to the front of gpo_list, GPOs have to be
     753             :          * pushed in the opposite order of application (OUs first, local last,
     754             :          * child-to-parent).
     755             :          * Forced GPOs are appended in the end since they override all others.
     756             :          */
     757             : 
     758           0 :         ADS_STATUS status;
     759           0 :         struct GP_LINK gp_link;
     760           0 :         const char *parent_dn, *site_dn, *tmp_dn;
     761           2 :         bool add_only_forced_gpos = false;
     762             : 
     763           2 :         ZERO_STRUCTP(gpo_list);
     764           2 :         ZERO_STRUCTP(forced_gpo_list);
     765             : 
     766           2 :         if (!dn) {
     767           0 :                 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
     768             :         }
     769             : 
     770           2 :         if (!ads_set_sasl_wrap_flags(ads, ADS_AUTH_SASL_SIGN)) {
     771           0 :                 return ADS_ERROR(LDAP_INVALID_CREDENTIALS);
     772             :         }
     773             : 
     774           2 :         DEBUG(10,("ads_get_gpo_list: getting GPO list for [%s]\n", dn));
     775             : 
     776           2 :         tmp_dn = dn;
     777             : 
     778           6 :         while ((parent_dn = ads_parent_dn(tmp_dn)) &&
     779           6 :                (!strequal(parent_dn, ads_parent_dn(ads->config.bind_path)))) {
     780             : 
     781             : 
     782             :                 /* (O)rganizational(U)nit */
     783             : 
     784             :                 /* An account can be a member of more OUs */
     785           4 :                 if (strncmp(parent_dn, "OU=", strlen("OU=")) == 0) {
     786             : 
     787           2 :                         DEBUG(10,("ads_get_gpo_list: query OU: [%s] for GPOs\n",
     788             :                                 parent_dn));
     789             : 
     790           2 :                         status = ads_get_gpo_link(ads, mem_ctx, parent_dn,
     791             :                                                   &gp_link);
     792           2 :                         if (ADS_ERR_OK(status)) {
     793             : 
     794           2 :                                 if (DEBUGLEVEL >= 100) {
     795           0 :                                         dump_gplink(&gp_link);
     796             :                                 }
     797             : 
     798           2 :                                 status = add_gplink_to_gpo_list(ads,
     799             :                                                         mem_ctx,
     800             :                                                         gpo_list,
     801             :                                                         forced_gpo_list,
     802             :                                                         parent_dn,
     803             :                                                         &gp_link,
     804             :                                                         GP_LINK_OU,
     805             :                                                         add_only_forced_gpos,
     806             :                                                         token);
     807           2 :                                 if (!ADS_ERR_OK(status)) {
     808           0 :                                         return status;
     809             :                                 }
     810             : 
     811             :                                 /* block inheritance from now on */
     812           2 :                                 if (gp_link.gp_opts &
     813             :                                     GPOPTIONS_BLOCK_INHERITANCE) {
     814           0 :                                         add_only_forced_gpos = true;
     815             :                                 }
     816             :                         }
     817             :                 }
     818             : 
     819           4 :                 tmp_dn = parent_dn;
     820             : 
     821             :         }
     822             : 
     823             :         /* reset dn again */
     824           2 :         tmp_dn = dn;
     825             : 
     826           6 :         while ((parent_dn = ads_parent_dn(tmp_dn)) &&
     827           6 :                (!strequal(parent_dn, ads_parent_dn(ads->config.bind_path)))) {
     828             : 
     829             :                 /* (D)omain */
     830             : 
     831             :                 /* An account can just be a member of one domain */
     832           4 :                 if (strncmp(parent_dn, "DC=", strlen("DC=")) == 0) {
     833             : 
     834           2 :                         DEBUG(10,("ads_get_gpo_list: query DC: [%s] for GPOs\n",
     835             :                                 parent_dn));
     836             : 
     837           2 :                         status = ads_get_gpo_link(ads, mem_ctx, parent_dn,
     838             :                                                   &gp_link);
     839           2 :                         if (ADS_ERR_OK(status)) {
     840             : 
     841           2 :                                 if (DEBUGLEVEL >= 100) {
     842           0 :                                         dump_gplink(&gp_link);
     843             :                                 }
     844             : 
     845           2 :                                 status = add_gplink_to_gpo_list(ads,
     846             :                                                         mem_ctx,
     847             :                                                         gpo_list,
     848             :                                                         forced_gpo_list,
     849             :                                                         parent_dn,
     850             :                                                         &gp_link,
     851             :                                                         GP_LINK_DOMAIN,
     852             :                                                         add_only_forced_gpos,
     853             :                                                         token);
     854           2 :                                 if (!ADS_ERR_OK(status)) {
     855           0 :                                         return status;
     856             :                                 }
     857             : 
     858             :                                 /* block inheritance from now on */
     859           2 :                                 if (gp_link.gp_opts &
     860             :                                     GPOPTIONS_BLOCK_INHERITANCE) {
     861           0 :                                         add_only_forced_gpos = true;
     862             :                                 }
     863             :                         }
     864             :                 }
     865             : 
     866           4 :                 tmp_dn = parent_dn;
     867             :         }
     868             : 
     869             :         /* (S)ite */
     870             : 
     871             :         /* are site GPOs valid for users as well ??? */
     872           2 :         if (flags & GPO_LIST_FLAG_MACHINE) {
     873             : 
     874           2 :                 status = ads_site_dn_for_machine(ads, mem_ctx,
     875             :                                                  ads->config.ldap_server_name,
     876             :                                                  &site_dn);
     877           2 :                 if (!ADS_ERR_OK(status)) {
     878           0 :                         return status;
     879             :                 }
     880             : 
     881           2 :                 DEBUG(10,("ads_get_gpo_list: query SITE: [%s] for GPOs\n",
     882             :                         site_dn));
     883             : 
     884           2 :                 status = ads_get_gpo_link(ads, mem_ctx, site_dn, &gp_link);
     885           2 :                 if (ADS_ERR_OK(status)) {
     886             : 
     887           0 :                         if (DEBUGLEVEL >= 100) {
     888           0 :                                 dump_gplink(&gp_link);
     889             :                         }
     890             : 
     891           0 :                         status = add_gplink_to_gpo_list(ads,
     892             :                                                         mem_ctx,
     893             :                                                         gpo_list,
     894             :                                                         forced_gpo_list,
     895             :                                                         site_dn,
     896             :                                                         &gp_link,
     897             :                                                         GP_LINK_SITE,
     898             :                                                         add_only_forced_gpos,
     899             :                                                         token);
     900           0 :                         if (!ADS_ERR_OK(status)) {
     901           0 :                                 return status;
     902             :                         }
     903             : 
     904           0 :                         if (flags & GPO_LIST_FLAG_SITEONLY) {
     905           0 :                                 return ADS_ERROR(LDAP_SUCCESS);
     906             :                         }
     907             : 
     908             :                         /* inheritance can't be blocked at the site level */
     909             :                 }
     910             :         }
     911             : 
     912             :         /* (L)ocal */
     913           2 :         status = add_local_policy_to_gpo_list(mem_ctx, gpo_list,
     914             :                                               GP_LINK_LOCAL);
     915           2 :         if (!ADS_ERR_OK(status)) {
     916           0 :                 return status;
     917             :         }
     918             : 
     919           2 :         return ADS_ERROR(LDAP_SUCCESS);
     920             : }
     921             : 
     922             : /****************************************************************
     923             :  Get the full list of GROUP_POLICY_OBJECTs for a given dn, wrapper
     924             :  around ads_get_gpo_list_internal() that ensures correct ordering.
     925             : ****************************************************************/
     926             : 
     927           2 : ADS_STATUS ads_get_gpo_list(ADS_STRUCT *ads,
     928             :                             TALLOC_CTX *mem_ctx,
     929             :                             const char *dn,
     930             :                             uint32_t flags,
     931             :                             const struct security_token *token,
     932             :                             struct GROUP_POLICY_OBJECT **gpo_list)
     933             : {
     934           2 :         struct GROUP_POLICY_OBJECT *forced_gpo_list = NULL;
     935           0 :         ADS_STATUS status;
     936             : 
     937           2 :         status = ads_get_gpo_list_internal(ads,
     938             :                                            mem_ctx,
     939             :                                            dn,
     940             :                                            flags,
     941             :                                            token,
     942             :                                            gpo_list,
     943             :                                            &forced_gpo_list);
     944           2 :         if (!ADS_ERR_OK(status)) {
     945           0 :                 return status;
     946             :         }
     947             :         /*
     948             :          * Append |forced_gpo_list| at the end of |gpo_list|,
     949             :          * so that forced GPOs are applied on top of non enforced GPOs.
     950             :          */
     951           2 :         DLIST_CONCATENATE(*gpo_list, forced_gpo_list);
     952             : 
     953           2 :         return ADS_ERROR(LDAP_SUCCESS);
     954             : }
     955             : 
     956             : #endif /* HAVE_LDAP */

Generated by: LCOV version 1.14