LCOV - code coverage report
Current view: top level - libgpo - gpo_ini.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 49 218 22.5 %
Date: 2024-04-21 15:09:00 Functions: 5 10 50.0 %

          Line data    Source code
       1             : /*
       2             :  *  Unix SMB/CIFS implementation.
       3             :  *  Group Policy Support
       4             :  *  Copyright (C) Guenther Deschner 2007
       5             :  *  Copyright (C) Wilco Baan Hofman 2009
       6             :  *
       7             :  *  This program is free software; you can redistribute it and/or modify
       8             :  *  it under the terms of the GNU General Public License as published by
       9             :  *  the Free Software Foundation; either version 3 of the License, or
      10             :  *  (at your option) any later version.
      11             :  *
      12             :  *  This program is distributed in the hope that it will be useful,
      13             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  *  GNU General Public License for more details.
      16             :  *
      17             :  *  You should have received a copy of the GNU General Public License
      18             :  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : #include "includes.h"
      22             : #include "lib/util/util_file.h"
      23             : #include "gpo.h"
      24             : #include "gpo_ini.h"
      25             : #include "system/filesys.h"
      26             : 
      27             : 
      28          46 : static bool change_section(const char *section, void *ctx_ptr)
      29             : {
      30          46 :         struct gp_inifile_context *ctx = (struct gp_inifile_context *) ctx_ptr;
      31             : 
      32          46 :         if (ctx->current_section) {
      33           0 :                 talloc_free(ctx->current_section);
      34             :         }
      35          46 :         ctx->current_section = talloc_strdup(ctx, section);
      36          46 :         if (!ctx->current_section) {
      37           0 :                 return false;
      38             :         }
      39          46 :         return true;
      40             : }
      41             : 
      42             : /****************************************************************
      43             : ****************************************************************/
      44             : 
      45          46 : static bool store_keyval_pair(const char *key, const char *value, void *ctx_ptr)
      46             : {
      47          46 :         struct gp_inifile_context *ctx = (struct gp_inifile_context *) ctx_ptr;
      48             : 
      49          46 :         ctx->data = talloc_realloc(ctx, ctx->data, struct keyval_pair *, ctx->keyval_count+1);
      50          46 :         if (!ctx->data) {
      51           0 :                 return false;
      52             :         }
      53             : 
      54          46 :         ctx->data[ctx->keyval_count] = talloc_zero(ctx, struct keyval_pair);
      55          46 :         if (!ctx->data[ctx->keyval_count]) {
      56           0 :                 return false;
      57             :         }
      58             : 
      59          46 :         ctx->data[ctx->keyval_count]->key = talloc_asprintf(ctx, "%s:%s", ctx->current_section, key);
      60          46 :         ctx->data[ctx->keyval_count]->val = talloc_strdup(ctx, value ? value : "");
      61             : 
      62          46 :         if (!ctx->data[ctx->keyval_count]->key ||
      63          46 :             !ctx->data[ctx->keyval_count]->val) {
      64           0 :                 return false;
      65             :         }
      66             : 
      67          46 :         ctx->keyval_count++;
      68          46 :         return true;
      69             : }
      70             : 
      71             : /****************************************************************
      72             : ****************************************************************/
      73             : 
      74           0 : static NTSTATUS convert_file_from_ucs2(TALLOC_CTX *mem_ctx,
      75             :                                        const char *filename_in,
      76             :                                        char **filename_out)
      77             : {
      78           0 :         int tmp_fd = -1;
      79           0 :         uint8_t *data_in = NULL;
      80           0 :         uint8_t *data_out = NULL;
      81           0 :         char *tmp_name = NULL;
      82           0 :         NTSTATUS status;
      83           0 :         size_t n = 0;
      84           0 :         size_t converted_size;
      85           0 :         mode_t mask;
      86             : 
      87           0 :         if (!filename_out) {
      88           0 :                 return NT_STATUS_INVALID_PARAMETER;
      89             :         }
      90             : 
      91           0 :         data_in = (uint8_t *)file_load(filename_in, &n, 0, mem_ctx);
      92           0 :         if (!data_in) {
      93           0 :                 status = NT_STATUS_NO_SUCH_FILE;
      94           0 :                 goto out;
      95             :         }
      96             : 
      97           0 :         DEBUG(11,("convert_file_from_ucs2: "
      98             :                "data_in[0]: 0x%x, data_in[1]: 0x%x, data_in[2]: 0x%x\n",
      99             :                 data_in[0], data_in[1], data_in[2]));
     100             : 
     101           0 :         if ((data_in[0] != 0xff) || (data_in[1] != 0xfe) || (data_in[2] != 0x0d)) {
     102           0 :                 *filename_out = NULL;
     103           0 :                 status = NT_STATUS_OK;
     104           0 :                 goto out;
     105             :         }
     106             : 
     107           0 :         tmp_name = talloc_asprintf(mem_ctx, "%s/convert_file_from_ucs2.XXXXXX",
     108             :                 tmpdir());
     109           0 :         if (!tmp_name) {
     110           0 :                 status = NT_STATUS_NO_MEMORY;
     111           0 :                 goto out;
     112             :         }
     113             : 
     114           0 :         mask = umask(S_IRWXO | S_IRWXG);
     115           0 :         tmp_fd = mkstemp(tmp_name);
     116           0 :         umask(mask);
     117           0 :         if (tmp_fd == -1) {
     118           0 :                 status = NT_STATUS_ACCESS_DENIED;
     119           0 :                 goto out;
     120             :         }
     121             : 
     122           0 :         if (!convert_string_talloc(mem_ctx, CH_UTF16LE, CH_UNIX, data_in, n,
     123             :                                    &data_out, &converted_size))
     124             :         {
     125           0 :                 status = NT_STATUS_INVALID_BUFFER_SIZE;
     126           0 :                 goto out;
     127             :         }
     128             : 
     129           0 :         DEBUG(11,("convert_file_from_ucs2: "
     130             :                  "%s skipping utf16-le BOM\n", tmp_name));
     131             : 
     132           0 :         converted_size -= 3;
     133             : 
     134           0 :         if (write(tmp_fd, data_out + 3, converted_size) != converted_size) {
     135           0 :                 status = map_nt_error_from_unix_common(errno);
     136           0 :                 goto out;
     137             :         }
     138             : 
     139           0 :         *filename_out = tmp_name;
     140             : 
     141           0 :         status = NT_STATUS_OK;
     142             : 
     143           0 :  out:
     144           0 :         if (tmp_fd != -1) {
     145           0 :                 close(tmp_fd);
     146             :         }
     147             : 
     148           0 :         talloc_free(data_in);
     149           0 :         talloc_free(data_out);
     150             : 
     151           0 :         return status;
     152             : }
     153             : 
     154             : /****************************************************************
     155             : ****************************************************************/
     156             : 
     157          92 : NTSTATUS gp_inifile_getstring(struct gp_inifile_context *ctx, const char *key, const char **ret)
     158             : {
     159           0 :         int i;
     160             : 
     161         138 :         for (i = 0; i < ctx->keyval_count; i++) {
     162          92 :                 if (strcmp(ctx->data[i]->key, key) == 0) {
     163          46 :                         if (ret) {
     164          46 :                                 *ret = ctx->data[i]->val;
     165             :                         }
     166          46 :                         return NT_STATUS_OK;
     167             :                 }
     168             :         }
     169          46 :         return NT_STATUS_NOT_FOUND;
     170             : }
     171             : 
     172             : /****************************************************************
     173             : ****************************************************************/
     174             : 
     175          46 : NTSTATUS gp_inifile_getint(struct gp_inifile_context *ctx, const char *key, int *ret)
     176             : {
     177           0 :         const char *value;
     178           0 :         NTSTATUS result;
     179             : 
     180          46 :         result = gp_inifile_getstring(ctx,key, &value);
     181          46 :         if (!NT_STATUS_IS_OK(result)) {
     182           0 :                 return result;
     183             :         }
     184             : 
     185          46 :         if (ret) {
     186          46 :                 *ret = (int)strtol(value, NULL, 10);
     187             :         }
     188          46 :         return NT_STATUS_OK;
     189             : }
     190             : 
     191             : /****************************************************************
     192             : ****************************************************************/
     193             : 
     194           0 : NTSTATUS gp_inifile_getbool(struct gp_inifile_context *ctx, const char *key, bool *ret)
     195             : {
     196           0 :         const char *value;
     197           0 :         NTSTATUS result;
     198             : 
     199           0 :         result = gp_inifile_getstring(ctx,key, &value);
     200           0 :         if (!NT_STATUS_IS_OK(result)) {
     201           0 :                 return result;
     202             :         }
     203             : 
     204           0 :         if (strequal(value, "Yes") ||
     205           0 :             strequal(value, "True")) {
     206           0 :                 if (ret) {
     207           0 :                         *ret = true;
     208             :                 }
     209           0 :                 return NT_STATUS_OK;
     210           0 :         } else if (strequal(value, "No") ||
     211           0 :                    strequal(value, "False")) {
     212           0 :                 if (ret) {
     213           0 :                         *ret = false;
     214             :                 }
     215           0 :                 return NT_STATUS_OK;
     216             :         }
     217             : 
     218           0 :         return NT_STATUS_NOT_FOUND;
     219             : }
     220             : 
     221             : /****************************************************************
     222             : ****************************************************************/
     223             : 
     224           0 : NTSTATUS gp_inifile_enum_section(struct gp_inifile_context *ctx,
     225             :                                  const char *section,
     226             :                                  size_t *num_ini_keys,
     227             :                                  const char ***ini_keys,
     228             :                                  const char ***ini_values)
     229             : {
     230           0 :         NTSTATUS status;
     231           0 :         int i;
     232           0 :         size_t num_keys = 0, num_vals = 0;
     233           0 :         const char **keys = NULL;
     234           0 :         const char **values = NULL;
     235             : 
     236           0 :         if (section == NULL || num_ini_keys == NULL ||
     237           0 :             ini_keys == NULL || ini_values == NULL) {
     238           0 :                 return NT_STATUS_INVALID_PARAMETER;
     239             :         }
     240             : 
     241           0 :         for (i = 0; i < ctx->keyval_count; i++) {
     242             : 
     243           0 :                 bool ok;
     244             : 
     245             :                 /*
     246             :                  * section: KEYNAME
     247             :                  * KEYNAME:value matches
     248             :                  * KEYNAME_OEM:value not
     249             :                  */
     250             : 
     251           0 :                 if (strlen(section)+1 > strlen(ctx->data[i]->key)) {
     252           0 :                         continue;
     253             :                 }
     254             : 
     255           0 :                 if (!strnequal(section, ctx->data[i]->key, strlen(section))) {
     256           0 :                         continue;
     257             :                 }
     258             : 
     259           0 :                 if (ctx->data[i]->key[strlen(section)] != ':') {
     260           0 :                         continue;
     261             :                 }
     262             : 
     263           0 :                 ok = add_string_to_array(ctx, ctx->data[i]->key, &keys, &num_keys);
     264           0 :                 if (!ok) {
     265           0 :                         status = NT_STATUS_NO_MEMORY;
     266           0 :                         goto failed;
     267             :                 }
     268             : 
     269           0 :                 ok = add_string_to_array(ctx, ctx->data[i]->val, &values, &num_vals);
     270           0 :                 if (!ok) {
     271           0 :                         status = NT_STATUS_NO_MEMORY;
     272           0 :                         goto failed;
     273             :                 }
     274             : 
     275           0 :                 if (num_keys != num_vals) {
     276           0 :                         status = NT_STATUS_INTERNAL_DB_CORRUPTION;
     277           0 :                         goto failed;
     278             :                 }
     279             :         }
     280             : 
     281           0 :         *num_ini_keys = num_keys;
     282           0 :         *ini_keys = keys;
     283           0 :         *ini_values = values;
     284             : 
     285           0 :         return NT_STATUS_OK;
     286             : 
     287           0 :  failed:
     288           0 :         talloc_free(keys);
     289           0 :         talloc_free(values);
     290             : 
     291           0 :         return status;
     292             : }
     293             : 
     294             : 
     295             : /****************************************************************
     296             : ****************************************************************/
     297             : 
     298           0 : NTSTATUS gp_inifile_init_context(TALLOC_CTX *mem_ctx,
     299             :                                  uint32_t flags,
     300             :                                  const char *unix_path,
     301             :                                  const char *suffix,
     302             :                                  struct gp_inifile_context **ctx_ret)
     303             : {
     304           0 :         struct gp_inifile_context *ctx = NULL;
     305           0 :         NTSTATUS status;
     306           0 :         int rv;
     307           0 :         char *tmp_filename = NULL;
     308           0 :         const char *ini_filename = NULL;
     309             : 
     310           0 :         if (!unix_path || !ctx_ret) {
     311           0 :                 return NT_STATUS_INVALID_PARAMETER;
     312             :         }
     313             : 
     314           0 :         ctx = talloc_zero(mem_ctx, struct gp_inifile_context);
     315           0 :         NT_STATUS_HAVE_NO_MEMORY(ctx);
     316             : 
     317           0 :         status = gp_find_file(mem_ctx, flags, unix_path, suffix,
     318             :                               &ini_filename);
     319             : 
     320           0 :         if (!NT_STATUS_IS_OK(status)) {
     321           0 :                 goto failed;
     322             :         }
     323             : 
     324           0 :         status = convert_file_from_ucs2(mem_ctx, ini_filename,
     325             :                                         &tmp_filename);
     326           0 :         if (!NT_STATUS_IS_OK(status)) {
     327           0 :                 goto failed;
     328             :         }
     329             : 
     330           0 :         rv = pm_process(tmp_filename != NULL ? tmp_filename : ini_filename,
     331             :                         change_section, store_keyval_pair, ctx);
     332           0 :         if (!rv) {
     333           0 :                 return NT_STATUS_NO_SUCH_FILE;
     334             :         }
     335             : 
     336             : 
     337           0 :         ctx->generated_filename = tmp_filename;
     338           0 :         ctx->mem_ctx = mem_ctx;
     339             : 
     340           0 :         *ctx_ret = ctx;
     341             : 
     342           0 :         return NT_STATUS_OK;
     343             : 
     344           0 :  failed:
     345             : 
     346           0 :         DEBUG(1,("gp_inifile_init_context failed: %s\n",
     347             :                 nt_errstr(status)));
     348             : 
     349           0 :         talloc_free(ctx);
     350             : 
     351           0 :         return status;
     352             : }
     353             : 
     354             : /****************************************************************
     355             : ****************************************************************/
     356             : 
     357           0 : NTSTATUS gp_inifile_init_context_direct(TALLOC_CTX *mem_ctx,
     358             :                                         const char *unix_path,
     359             :                                         struct gp_inifile_context **pgp_ctx)
     360             : {
     361           0 :         struct gp_inifile_context *gp_ctx = NULL;
     362           0 :         NTSTATUS status;
     363           0 :         bool rv;
     364           0 :         char *tmp_filename = NULL;
     365             : 
     366           0 :         if (unix_path == NULL || pgp_ctx == NULL) {
     367           0 :                 return NT_STATUS_INVALID_PARAMETER;
     368             :         }
     369             : 
     370           0 :         gp_ctx = talloc_zero(mem_ctx, struct gp_inifile_context);
     371           0 :         if (gp_ctx == NULL) {
     372           0 :                 return NT_STATUS_NO_MEMORY;
     373             :         }
     374             : 
     375           0 :         status = convert_file_from_ucs2(mem_ctx, unix_path,
     376             :                                         &tmp_filename);
     377           0 :         if (!NT_STATUS_IS_OK(status)) {
     378           0 :                 goto failed;
     379             :         }
     380             : 
     381           0 :         rv = pm_process_with_flags(tmp_filename != NULL ? tmp_filename : unix_path,
     382             :                                    true,
     383             :                                    change_section,
     384             :                                    store_keyval_pair,
     385             :                                    gp_ctx);
     386           0 :         if (!rv) {
     387           0 :                 return NT_STATUS_NO_SUCH_FILE;
     388             :         }
     389             : 
     390           0 :         gp_ctx->generated_filename = tmp_filename;
     391           0 :         gp_ctx->mem_ctx = mem_ctx;
     392             : 
     393           0 :         *pgp_ctx = gp_ctx;
     394             : 
     395           0 :         return NT_STATUS_OK;
     396             : 
     397           0 :  failed:
     398             : 
     399           0 :         DEBUG(1,("gp_inifile_init_context_direct failed: %s\n",
     400             :                 nt_errstr(status)));
     401             : 
     402           0 :         talloc_free(gp_ctx);
     403             : 
     404           0 :         return status;
     405             : }
     406             : 
     407             : 
     408             : /****************************************************************
     409             :  parse the local gpt.ini file
     410             : ****************************************************************/
     411             : 
     412             : #define GPT_INI_SECTION_GENERAL "General"
     413             : #define GPT_INI_PARAMETER_VERSION "Version"
     414             : #define GPT_INI_PARAMETER_DISPLAYNAME "displayName"
     415             : 
     416          46 : NTSTATUS parse_gpt_ini(TALLOC_CTX *mem_ctx,
     417             :                        const char *filename,
     418             :                        uint32_t *version,
     419             :                        char **display_name)
     420             : {
     421           0 :         NTSTATUS result;
     422           0 :         int rv;
     423          46 :         int v = 0;
     424          46 :         const char *name = NULL;
     425           0 :         struct gp_inifile_context *ctx;
     426             : 
     427          46 :         if (!filename) {
     428           0 :                 return NT_STATUS_INVALID_PARAMETER;
     429             :         }
     430             : 
     431          46 :         ctx = talloc_zero(mem_ctx, struct gp_inifile_context);
     432          46 :         NT_STATUS_HAVE_NO_MEMORY(ctx);
     433             : 
     434          46 :         rv = pm_process(filename, change_section, store_keyval_pair, ctx);
     435          46 :         if (!rv) {
     436           0 :                 return NT_STATUS_NO_SUCH_FILE;
     437             :         }
     438             : 
     439             : 
     440          46 :         result = gp_inifile_getstring(ctx, GPT_INI_SECTION_GENERAL
     441             :                         ":"GPT_INI_PARAMETER_DISPLAYNAME, &name);
     442          46 :         if (!NT_STATUS_IS_OK(result)) {
     443             :                 /* the default domain policy and the default domain controller
     444             :                  * policy never have a displayname in their gpt.ini file */
     445          46 :                 DEBUG(10,("parse_gpt_ini: no name in %s\n", filename));
     446             :         }
     447             : 
     448          46 :         if (name && display_name) {
     449           0 :                 *display_name = talloc_strdup(ctx, name);
     450           0 :                 if (*display_name == NULL) {
     451           0 :                         return NT_STATUS_NO_MEMORY;
     452             :                 }
     453             :         }
     454             : 
     455          46 :         result = gp_inifile_getint(ctx, GPT_INI_SECTION_GENERAL
     456             :                         ":"GPT_INI_PARAMETER_VERSION, &v);
     457          46 :         if (!NT_STATUS_IS_OK(result)) {
     458           0 :                 DEBUG(10,("parse_gpt_ini: no version\n"));
     459           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
     460             :         }
     461             : 
     462          46 :         if (version) {
     463          46 :                 *version = v;
     464             :         }
     465             : 
     466          46 :         talloc_free(ctx);
     467             : 
     468          46 :         return NT_STATUS_OK;
     469             : }

Generated by: LCOV version 1.14