LCOV - code coverage report
Current view: top level - providers/ad - ad_gpo_child.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 0 372 0.0 %
Date: 2015-10-19 Functions: 0 11 0.0 %

          Line data    Source code
       1             : /*
       2             :     SSSD
       3             : 
       4             :     AD GPO Backend Module -- perform SMB and CSE processing in a child process
       5             : 
       6             :     Authors:
       7             :         Yassir Elley <yelley@redhat.com>
       8             : 
       9             :     Copyright (C) 2013 Red Hat
      10             : 
      11             :     This program is free software; you can redistribute it and/or modify
      12             :     it under the terms of the GNU General Public License as published by
      13             :     the Free Software Foundation; either version 3 of the License, or
      14             :     (at your option) any later version.
      15             : 
      16             :     This program is distributed in the hope that it will be useful,
      17             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      18             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19             :     GNU General Public License for more details.
      20             : 
      21             :     You should have received a copy of the GNU General Public License
      22             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      23             : */
      24             : 
      25             : #include <sys/types.h>
      26             : #include <unistd.h>
      27             : #include <sys/stat.h>
      28             : #include <popt.h>
      29             : #include <libsmbclient.h>
      30             : #include <ini_configobj.h>
      31             : #include <security/pam_modules.h>
      32             : 
      33             : #include "util/util.h"
      34             : #include "util/child_common.h"
      35             : #include "providers/dp_backend.h"
      36             : #include "providers/ad/ad_gpo.h"
      37             : #include "sss_cli.h"
      38             : 
      39             : #define SMB_BUFFER_SIZE 65536
      40             : #define GPT_INI "/GPT.INI"
      41             : #define INI_GENERAL_SECTION "General"
      42             : #define GPT_INI_VERSION "Version"
      43             : 
      44             : struct input_buffer {
      45             :     int cached_gpt_version;
      46             :     const char *smb_server;
      47             :     const char *smb_share;
      48             :     const char *smb_path;
      49             :     const char *smb_cse_suffix;
      50             : };
      51             : 
      52             : static errno_t
      53           0 : unpack_buffer(uint8_t *buf,
      54             :               size_t size,
      55             :               struct input_buffer *ibuf)
      56             : {
      57           0 :     size_t p = 0;
      58             :     uint32_t len;
      59             :     uint32_t cached_gpt_version;
      60             : 
      61             :     /* cached_gpt_version */
      62           0 :     SAFEALIGN_COPY_UINT32_CHECK(&cached_gpt_version, buf + p, size, &p);
      63           0 :     DEBUG(SSSDBG_TRACE_FUNC, "cached_gpt_version: %d\n", cached_gpt_version);
      64           0 :     ibuf->cached_gpt_version = cached_gpt_version;
      65             : 
      66             :     /* smb_server */
      67           0 :     SAFEALIGN_COPY_UINT32_CHECK(&len, buf + p, size, &p);
      68           0 :     DEBUG(SSSDBG_TRACE_ALL, "smb_server length: %d\n", len);
      69           0 :     if (len == 0) {
      70           0 :         return EINVAL;
      71             :     } else {
      72           0 :         if (len > size - p) return EINVAL;
      73           0 :         ibuf->smb_server = talloc_strndup(ibuf, (char *)(buf + p), len);
      74           0 :         if (ibuf->smb_server == NULL) return ENOMEM;
      75           0 :         DEBUG(SSSDBG_TRACE_ALL, "smb_server: %s\n", ibuf->smb_server);
      76           0 :         p += len;
      77             :     }
      78             : 
      79             :     /* smb_share */
      80           0 :     SAFEALIGN_COPY_UINT32_CHECK(&len, buf + p, size, &p);
      81           0 :     DEBUG(SSSDBG_TRACE_ALL, "smb_share length: %d\n", len);
      82           0 :     if (len == 0) {
      83           0 :         return EINVAL;
      84             :     } else {
      85           0 :         if (len > size - p) return EINVAL;
      86           0 :         ibuf->smb_share = talloc_strndup(ibuf, (char *)(buf + p), len);
      87           0 :         if (ibuf->smb_share == NULL) return ENOMEM;
      88           0 :         DEBUG(SSSDBG_TRACE_ALL, "smb_share: %s\n", ibuf->smb_share);
      89           0 :         p += len;
      90             :     }
      91             : 
      92             :     /* smb_path */
      93           0 :     SAFEALIGN_COPY_UINT32_CHECK(&len, buf + p, size, &p);
      94           0 :     DEBUG(SSSDBG_TRACE_ALL, "smb_path length: %d\n", len);
      95           0 :     if (len == 0) {
      96           0 :         return EINVAL;
      97             :     } else {
      98           0 :         if (len > size - p) return EINVAL;
      99           0 :         ibuf->smb_path = talloc_strndup(ibuf, (char *)(buf + p), len);
     100           0 :         if (ibuf->smb_path == NULL) return ENOMEM;
     101           0 :         DEBUG(SSSDBG_TRACE_ALL, "smb_path: %s\n", ibuf->smb_path);
     102           0 :         p += len;
     103             :     }
     104             : 
     105             :     /* smb_cse_suffix */
     106           0 :     SAFEALIGN_COPY_UINT32_CHECK(&len, buf + p, size, &p);
     107           0 :     DEBUG(SSSDBG_TRACE_ALL, "smb_cse_suffix length: %d\n", len);
     108           0 :     if (len == 0) {
     109           0 :         return EINVAL;
     110             :     } else {
     111           0 :         if (len > size - p) return EINVAL;
     112           0 :         ibuf->smb_cse_suffix = talloc_strndup(ibuf, (char *)(buf + p), len);
     113           0 :         if (ibuf->smb_cse_suffix == NULL) return ENOMEM;
     114           0 :         DEBUG(SSSDBG_TRACE_ALL, "smb_cse_suffix: %s\n", ibuf->smb_cse_suffix);
     115           0 :         p += len;
     116             :     }
     117             : 
     118           0 :     return EOK;
     119             : }
     120             : 
     121             : 
     122             : static errno_t
     123           0 : pack_buffer(struct response *r,
     124             :             int sysvol_gpt_version,
     125             :             int result)
     126             : {
     127           0 :     size_t p = 0;
     128             : 
     129             :     /* A buffer with the following structure must be created:
     130             :      *   uint32_t sysvol_gpt_version (required)
     131             :      *   uint32_t status of the request (required)
     132             :      */
     133           0 :     r->size = 2 * sizeof(uint32_t);
     134             : 
     135           0 :     r->buf = talloc_array(r, uint8_t, r->size);
     136           0 :     if(r->buf == NULL) {
     137           0 :         return ENOMEM;
     138             :     }
     139             : 
     140           0 :     DEBUG(SSSDBG_TRACE_FUNC, "result [%d]\n", result);
     141             : 
     142             :     /* sysvol_gpt_version */
     143           0 :     SAFEALIGN_SET_UINT32(&r->buf[p], sysvol_gpt_version, &p);
     144             : 
     145             :     /* result */
     146           0 :     SAFEALIGN_SET_UINT32(&r->buf[p], result, &p);
     147             : 
     148           0 :     return EOK;
     149             : }
     150             : 
     151             : static errno_t
     152           0 : prepare_response(TALLOC_CTX *mem_ctx,
     153             :                  int sysvol_gpt_version,
     154             :                  int result,
     155             :                  struct response **rsp)
     156             : {
     157             :     int ret;
     158           0 :     struct response *r = NULL;
     159             : 
     160           0 :     r = talloc_zero(mem_ctx, struct response);
     161           0 :     if (r == NULL) {
     162           0 :         return ENOMEM;
     163             :     }
     164             : 
     165           0 :     r->buf = NULL;
     166           0 :     r->size = 0;
     167             : 
     168           0 :     ret = pack_buffer(r, sysvol_gpt_version, result);
     169           0 :     if (ret != EOK) {
     170           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "pack_buffer failed\n");
     171           0 :         return ret;
     172             :     }
     173             : 
     174           0 :     *rsp = r;
     175           0 :     DEBUG(SSSDBG_TRACE_ALL, "r->size: %zu\n", r->size);
     176           0 :     return EOK;
     177             : }
     178             : 
     179             : static void
     180           0 : sssd_krb_get_auth_data_fn(const char * pServer,
     181             :                           const char * pShare,
     182             :                           char * pWorkgroup,
     183             :                           int maxLenWorkgroup,
     184             :                           char * pUsername,
     185             :                           int maxLenUsername,
     186             :                           char * pPassword,
     187             :                           int maxLenPassword)
     188             : {
     189             :     /* since we are using kerberos for authentication, we simply return */
     190           0 :     return;
     191             : }
     192             : 
     193             : /*
     194             :  * This function prepares the gpo_cache by:
     195             :  * - parsing the input_smb_path into its component directories
     196             :  * - creating each component directory (if it doesn't already exist)
     197             :  */
     198           0 : static errno_t prepare_gpo_cache(TALLOC_CTX *mem_ctx,
     199             :                                  const char *cache_dir,
     200             :                                  const char *input_smb_path_with_suffix)
     201             : {
     202             :     char *current_dir;
     203             :     char *ptr;
     204           0 :     const char delim = '/';
     205           0 :     int num_dirs = 0;
     206             :     int i;
     207           0 :     char *first = NULL;
     208           0 :     char *last = NULL;
     209           0 :     char *smb_path_with_suffix = NULL;
     210             :     errno_t ret;
     211             : 
     212           0 :     smb_path_with_suffix = talloc_strdup(mem_ctx, input_smb_path_with_suffix);
     213           0 :     if (smb_path_with_suffix == NULL) {
     214           0 :         return ENOMEM;
     215             :     }
     216             : 
     217           0 :     DEBUG(SSSDBG_TRACE_ALL, "smb_path_with_suffix: %s\n", smb_path_with_suffix);
     218             : 
     219           0 :     current_dir = talloc_strdup(mem_ctx, cache_dir);
     220           0 :     if (current_dir == NULL) {
     221           0 :         return ENOMEM;
     222             :     }
     223             : 
     224           0 :     ptr = smb_path_with_suffix + 1;
     225           0 :     while ((ptr = strchr(ptr, delim))) {
     226           0 :         ptr++;
     227           0 :         num_dirs++;
     228             :     }
     229             : 
     230           0 :     ptr = smb_path_with_suffix + 1;
     231             : 
     232           0 :     for (i = 0; i < num_dirs; i++) {
     233           0 :         first = ptr;
     234           0 :         last = strchr(first, delim);
     235           0 :         if (last == NULL) {
     236           0 :             return EINVAL;
     237             :         }
     238           0 :         *last = '\0';
     239           0 :         last++;
     240             : 
     241           0 :         current_dir = talloc_asprintf(mem_ctx, "%s/%s", current_dir, first);
     242           0 :         if (current_dir == NULL) {
     243           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf failed.\n");
     244           0 :             return ENOMEM;
     245             :         }
     246           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Storing GPOs in %s\n", current_dir);
     247             : 
     248           0 :         if ((mkdir(current_dir, 0644)) < 0 && errno != EEXIST) {
     249           0 :             ret = errno;
     250           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     251             :                   "mkdir(%s) failed: %d\n", current_dir, ret);
     252           0 :             return ret;
     253             :         }
     254             : 
     255           0 :         ptr = last;
     256             :     }
     257             : 
     258           0 :     return EOK;
     259             : 
     260             : }
     261             : 
     262             : /*
     263             :  * This function stores the input buf to a local file, whose file path
     264             :  * is constructed by concatenating:
     265             :  *   GPO_CACHE_PATH,
     266             :  *   input smb_path,
     267             :  *   input smb_cse_suffix
     268             :  * Note that the backend will later read the file from the same file path.
     269             :  */
     270           0 : static errno_t gpo_cache_store_file(const char *smb_path,
     271             :                                     const char *smb_cse_suffix,
     272             :                                     uint8_t *buf,
     273             :                                     int buflen)
     274             : {
     275             :     int ret;
     276             :     int fret;
     277           0 :     int fd = -1;
     278           0 :     char *tmp_name = NULL;
     279             :     ssize_t written;
     280           0 :     char *filename = NULL;
     281           0 :     char *smb_path_with_suffix = NULL;
     282           0 :     TALLOC_CTX *tmp_ctx = NULL;
     283             : 
     284           0 :     tmp_ctx = talloc_new(NULL);
     285           0 :     if (tmp_ctx == NULL) {
     286           0 :         ret = ENOMEM;
     287           0 :         goto done;
     288             :     }
     289             : 
     290           0 :     smb_path_with_suffix =
     291             :         talloc_asprintf(tmp_ctx, "%s%s", smb_path, smb_cse_suffix);
     292           0 :     if (smb_path_with_suffix == NULL) {
     293           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf failed.\n");
     294           0 :         ret = ENOMEM;
     295           0 :         goto done;
     296             :     }
     297             : 
     298             :     /* create component directories of smb_path, if needed */
     299           0 :     ret = prepare_gpo_cache(tmp_ctx, GPO_CACHE_PATH, smb_path_with_suffix);
     300           0 :     if (ret != EOK) {
     301           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     302             :               "prepare_gpo_cache failed [%d][%s]\n",
     303             :               ret, strerror(ret));
     304           0 :         goto done;
     305             :     }
     306             : 
     307           0 :     filename = talloc_asprintf(tmp_ctx, GPO_CACHE_PATH"%s", smb_path_with_suffix);
     308           0 :     if (filename == NULL) {
     309           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf failed.\n");
     310           0 :         ret = ENOMEM;
     311           0 :         goto done;
     312             :     }
     313             : 
     314           0 :     tmp_name = talloc_asprintf(tmp_ctx, "%sXXXXXX", filename);
     315           0 :     if (tmp_name == NULL) {
     316           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf failed.\n");
     317           0 :         ret = ENOMEM;
     318           0 :         goto done;
     319             :     }
     320             : 
     321           0 :     fd = sss_unique_file(tmp_ctx, tmp_name, &ret);
     322           0 :     if (fd == -1) {
     323           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     324             :               "sss_unique_file failed [%d][%s].\n", ret, strerror(ret));
     325           0 :         goto done;
     326             :     }
     327             : 
     328           0 :     errno = 0;
     329           0 :     written = sss_atomic_write_s(fd, buf, buflen);
     330           0 :     if (written == -1) {
     331           0 :         ret = errno;
     332           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     333             :               "write failed [%d][%s].\n", ret, strerror(ret));
     334           0 :         goto done;
     335             :     }
     336             : 
     337           0 :     if (written != buflen) {
     338           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     339             :               "Write error, wrote [%zd] bytes, expected [%d]\n",
     340             :                written, buflen);
     341           0 :         ret = EIO;
     342           0 :         goto done;
     343             :     }
     344             : 
     345           0 :     ret = fchmod(fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
     346           0 :     if (ret == -1) {
     347           0 :         ret = errno;
     348           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     349             :               "fchmod failed [%d][%s].\n", ret, strerror(ret));
     350           0 :         goto done;
     351             :     }
     352             : 
     353           0 :     ret = rename(tmp_name, filename);
     354           0 :     if (ret == -1) {
     355           0 :         ret = errno;
     356           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     357             :               "rename failed [%d][%s].\n", ret, strerror(ret));
     358           0 :         goto done;
     359             :     }
     360             : 
     361           0 :     ret = EOK;
     362             :  done:
     363           0 :     if (ret != EOK) {
     364           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Error encountered: %d.\n", ret);
     365             :     }
     366             : 
     367           0 :     if (fd != -1) {
     368           0 :         fret = close(fd);
     369           0 :         if (fret == -1) {
     370           0 :             fret = errno;
     371           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     372             :                   "close failed [%d][%s].\n", fret, strerror(fret));
     373             :         }
     374             :     }
     375             : 
     376           0 :     talloc_free(tmp_ctx);
     377           0 :     return ret;
     378             : }
     379             : 
     380             : static errno_t
     381           0 : parse_ini_file_with_libini(struct ini_cfgobj *ini_config,
     382             :                            int *_gpt_version)
     383             : {
     384             :     int ret;
     385           0 :     struct value_obj *vobj = NULL;
     386             :     int gpt_version;
     387             : 
     388           0 :     ret = ini_get_config_valueobj(INI_GENERAL_SECTION, GPT_INI_VERSION,
     389             :                                   ini_config, INI_GET_FIRST_VALUE, &vobj);
     390           0 :     if (ret != 0) {
     391           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     392             :               "ini_get_config_valueobj failed [%d][%s]\n", ret, strerror(ret));
     393           0 :         goto done;
     394             :     }
     395           0 :     if (vobj == NULL) {
     396           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "section/name not found: [%s][%s]\n",
     397             :               INI_GENERAL_SECTION, GPT_INI_VERSION);
     398           0 :         ret = EINVAL;
     399           0 :         goto done;
     400             :     }
     401             : 
     402           0 :     gpt_version = ini_get_int32_config_value(vobj, 0, -1, &ret);
     403           0 :     if (ret != 0) {
     404           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     405             :               "ini_get_int32_config_value failed [%d][%s]\n",
     406             :               ret, strerror(ret));
     407           0 :         goto done;
     408             :     }
     409             : 
     410           0 :     *_gpt_version = gpt_version;
     411             : 
     412           0 :     ret = EOK;
     413             : 
     414             :  done:
     415             : 
     416           0 :     return ret;
     417             : }
     418             : 
     419             : /*
     420             :  * This function parses the GPT_INI file stored in the gpo_cache, and uses the
     421             :  * results to populate the output parameters ...
     422             :  */
     423             : static errno_t
     424           0 : ad_gpo_parse_ini_file(const char *smb_path,
     425             :                       int *_gpt_version)
     426             : {
     427           0 :     struct ini_cfgfile *file_ctx = NULL;
     428           0 :     struct ini_cfgobj *ini_config = NULL;
     429             :     const char *ini_filename;
     430             :     int ret;
     431           0 :     int gpt_version = -1;
     432           0 :     TALLOC_CTX *tmp_ctx = NULL;
     433             : 
     434           0 :     tmp_ctx = talloc_new(NULL);
     435           0 :     if (tmp_ctx == NULL) {
     436           0 :         ret = ENOMEM;
     437           0 :         goto done;
     438             :     }
     439             : 
     440           0 :     ini_filename = talloc_asprintf(tmp_ctx, GPO_CACHE_PATH"%s%s",
     441             :                                    smb_path, GPT_INI);
     442           0 :     if (ini_filename == NULL) {
     443           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf failed.\n");
     444           0 :         ret = ENOMEM;
     445           0 :         goto done;
     446             :     }
     447             : 
     448           0 :     DEBUG(SSSDBG_TRACE_FUNC, "ini_filename:%s\n", ini_filename);
     449             : 
     450           0 :     ret = ini_config_create(&ini_config);
     451           0 :     if (ret != 0) {
     452           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     453             :               "ini_config_create failed [%d][%s]\n", ret, strerror(ret));
     454           0 :         goto done;
     455             :     }
     456             : 
     457           0 :     ret = ini_config_file_open(ini_filename, 0, &file_ctx);
     458           0 :     if (ret != 0) {
     459           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     460             :               "ini_config_file_open failed [%d][%s]\n", ret, strerror(ret));
     461           0 :         goto done;
     462             :     }
     463             : 
     464           0 :     ret = ini_config_parse(file_ctx, INI_STOP_ON_NONE, 0, 0, ini_config);
     465           0 :     if (ret != 0) {
     466           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     467             :               "ini_config_parse failed [%d][%s]\n", ret, strerror(ret));
     468           0 :         goto done;
     469             :     }
     470             : 
     471           0 :     ret = parse_ini_file_with_libini(ini_config, &gpt_version);
     472           0 :     if (ret != 0) {
     473           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     474             :               "parse_ini_file_with_libini failed [%d][%s]\n",
     475             :               ret, strerror(ret));
     476           0 :         goto done;
     477             :     }
     478             : 
     479           0 :     *_gpt_version = gpt_version;
     480             : 
     481             :  done:
     482             : 
     483           0 :     if (ret != EOK) {
     484           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Error encountered: %d.\n", ret);
     485             :     }
     486             : 
     487           0 :     ini_config_file_destroy(file_ctx);
     488           0 :     ini_config_destroy(ini_config);
     489           0 :     talloc_free(tmp_ctx);
     490           0 :     return ret;
     491             : }
     492             : 
     493             : /*
     494             :  * This function uses the input smb uri components to download a sysvol file
     495             :  * (e.g. INI file, policy file, etc) and store it to the GPO_CACHE directory.
     496             :  */
     497             : static errno_t
     498           0 : copy_smb_file_to_gpo_cache(SMBCCTX *smbc_ctx,
     499             :                            const char *smb_server,
     500             :                            const char *smb_share,
     501             :                            const char *smb_path,
     502             :                            const char *smb_cse_suffix)
     503             : {
     504           0 :     char *smb_uri = NULL;
     505             :     SMBCFILE *file;
     506             :     int ret;
     507           0 :     uint8_t *buf = NULL;
     508           0 :     int buflen = 0;
     509             : 
     510           0 :     TALLOC_CTX *tmp_ctx = NULL;
     511             : 
     512           0 :     tmp_ctx = talloc_new(NULL);
     513           0 :     if (tmp_ctx == NULL) {
     514           0 :         return ENOMEM;
     515             :     }
     516             : 
     517           0 :     smb_uri = talloc_asprintf(tmp_ctx, "%s%s%s%s", smb_server,
     518             :                               smb_share, smb_path, smb_cse_suffix);
     519           0 :     if (smb_uri == NULL) {
     520           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf failed.\n");
     521           0 :         ret = ENOMEM;
     522           0 :         goto done;
     523             :     }
     524             : 
     525           0 :     DEBUG(SSSDBG_TRACE_FUNC, "smb_uri: %s\n", smb_uri);
     526             : 
     527           0 :     errno = 0;
     528           0 :     file = smbc_getFunctionOpen(smbc_ctx)(smbc_ctx, smb_uri, O_RDONLY, 0755);
     529           0 :     if (file == NULL) {
     530           0 :         ret = errno;
     531           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "smbc_getFunctionOpen failed [%d][%s]\n",
     532             :               ret, strerror(ret));
     533           0 :         goto done;
     534             :     }
     535             : 
     536           0 :     buf = talloc_array(tmp_ctx, uint8_t, SMB_BUFFER_SIZE);
     537           0 :     if (buf == NULL) {
     538           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_array failed.\n");
     539           0 :         ret = ENOMEM;
     540           0 :         goto done;
     541             :     }
     542             : 
     543           0 :     errno = 0;
     544           0 :     buflen = smbc_getFunctionRead(smbc_ctx)(smbc_ctx, file, buf, SMB_BUFFER_SIZE);
     545           0 :     if (buflen < 0) {
     546           0 :         ret = errno;
     547           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "smbc_getFunctionRead failed [%d][%s]\n",
     548             :               ret, strerror(ret));
     549           0 :         goto done;
     550             :     }
     551             : 
     552           0 :     DEBUG(SSSDBG_TRACE_ALL, "smb_buflen: %d\n", buflen);
     553             : 
     554           0 :     ret = gpo_cache_store_file(smb_path, smb_cse_suffix, buf, buflen);
     555           0 :     if (ret != EOK) {
     556           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     557             :               "gpo_cache_store_file failed [%d][%s]\n",
     558             :               ret, strerror(ret));
     559           0 :         goto done;
     560             :     }
     561             : 
     562             :  done:
     563           0 :     talloc_free(tmp_ctx);
     564           0 :     return ret;
     565             : }
     566             : 
     567             : 
     568             : /*
     569             :  * Using its smb_uri components and cached_gpt_version inputs, this function
     570             :  * does several things:
     571             :  * - it downloads the GPT_INI file to GPO_CACHE
     572             :  * - it parses the sysvol_gpt_version field from the GPT_INI file
     573             :  * - if the sysvol_gpt_version is greater than the cached_gpt_version
     574             :  *   - it downloads the policy file to GPO_CACHE
     575             :  * - else
     576             :  *   - it doesn't retrieve the policy file
     577             :  *   - in this case, the backend will use the existing policy file in GPO_CACHE
     578             :  * - it returns the sysvol_gpt_version in the _sysvol_gpt_version output param
     579             :  *
     580             :  * Note that if the cached_gpt_version sent by the backend is -1 (to indicate
     581             :  * that no gpt_version has been set in the cache for the corresponding gpo_guid),
     582             :  * then the parsed sysvol_gpt_version (which must be at least 0) will be greater
     583             :  * than the cached_gpt_version, thereby triggering a fresh download.
     584             :  *
     585             :  * Note that the backend will later do the following:
     586             :  * - backend will save the sysvol_gpt_version to sysdb cache
     587             :  * - backend will read the policy file from the GPO_CACHE
     588             :  */
     589             : static errno_t
     590           0 : perform_smb_operations(int cached_gpt_version,
     591             :                        const char *smb_server,
     592             :                        const char *smb_share,
     593             :                        const char *smb_path,
     594             :                        const char *smb_cse_suffix,
     595             :                        int *_sysvol_gpt_version)
     596             : {
     597             :     SMBCCTX *smbc_ctx;
     598             :     int ret;
     599             :     int sysvol_gpt_version;
     600             : 
     601           0 :     smbc_ctx = smbc_new_context();
     602           0 :     if (smbc_ctx == NULL) {
     603           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Could not allocate new smbc context\n");
     604           0 :         ret = ENOMEM;
     605           0 :         goto done;
     606             :     }
     607             : 
     608           0 :     smbc_setOptionDebugToStderr(smbc_ctx, 1);
     609           0 :     smbc_setFunctionAuthData(smbc_ctx, sssd_krb_get_auth_data_fn);
     610           0 :     smbc_setOptionUseKerberos(smbc_ctx, 1);
     611             : 
     612             :     /* Initialize the context using the previously specified options */
     613           0 :     if (smbc_init_context(smbc_ctx) == NULL) {
     614           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Could not initialize smbc context\n");
     615           0 :         ret = ENOMEM;
     616           0 :         goto done;
     617             :     }
     618             : 
     619             :     /* download ini file */
     620           0 :     ret = copy_smb_file_to_gpo_cache(smbc_ctx, smb_server, smb_share, smb_path,
     621             :                                      GPT_INI);
     622           0 :     if (ret != EOK) {
     623           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     624             :               "copy_smb_file_to_gpo_cache failed [%d][%s]\n",
     625             :               ret, strerror(ret));
     626           0 :         goto done;
     627             :     }
     628             : 
     629           0 :     ret = ad_gpo_parse_ini_file(smb_path, &sysvol_gpt_version);
     630           0 :     if (ret != EOK) {
     631           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     632             :               "Cannot parse ini file: [%d][%s]\n", ret, strerror(ret));
     633           0 :         goto done;
     634             :     }
     635             : 
     636           0 :     DEBUG(SSSDBG_TRACE_FUNC, "sysvol_gpt_version: %d\n", sysvol_gpt_version);
     637             : 
     638           0 :     if (sysvol_gpt_version > cached_gpt_version) {
     639             :         /* download policy file */
     640           0 :         ret = copy_smb_file_to_gpo_cache(smbc_ctx, smb_server, smb_share,
     641             :                                          smb_path, smb_cse_suffix);
     642           0 :         if (ret != EOK) {
     643           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     644             :                   "copy_smb_file_to_gpo_cache failed [%d][%s]\n",
     645             :                   ret, strerror(ret));
     646           0 :             goto done;
     647             :         }
     648             :     }
     649             : 
     650           0 :     *_sysvol_gpt_version = sysvol_gpt_version;
     651             : 
     652             :  done:
     653           0 :     smbc_free_context(smbc_ctx, 0);
     654           0 :     return ret;
     655             : }
     656             : 
     657             : int
     658           0 : main(int argc, const char *argv[])
     659             : {
     660             :     int opt;
     661             :     poptContext pc;
     662           0 :     int debug_fd = -1;
     663             :     errno_t ret;
     664             :     int sysvol_gpt_version;
     665             :     int result;
     666           0 :     TALLOC_CTX *main_ctx = NULL;
     667           0 :     uint8_t *buf = NULL;
     668           0 :     ssize_t len = 0;
     669           0 :     struct input_buffer *ibuf = NULL;
     670           0 :     struct response *resp = NULL;
     671             :     ssize_t written;
     672             : 
     673           0 :     struct poptOption long_options[] = {
     674             :         POPT_AUTOHELP
     675             :         {"debug-level", 'd', POPT_ARG_INT, &debug_level, 0,
     676           0 :          _("Debug level"), NULL},
     677             :         {"debug-timestamps", 0, POPT_ARG_INT, &debug_timestamps, 0,
     678           0 :          _("Add debug timestamps"), NULL},
     679             :         {"debug-microseconds", 0, POPT_ARG_INT, &debug_microseconds, 0,
     680           0 :          _("Show timestamps with microseconds"), NULL},
     681             :         {"debug-fd", 0, POPT_ARG_INT, &debug_fd, 0,
     682           0 :          _("An open file descriptor for the debug logs"), NULL},
     683             :         {"debug-to-stderr", 0, POPT_ARG_NONE | POPT_ARGFLAG_DOC_HIDDEN,
     684             :          &debug_to_stderr, 0,
     685           0 :          _("Send the debug output to stderr directly."), NULL },
     686             :         POPT_TABLEEND
     687             :     };
     688             : 
     689             :     /* Set debug level to invalid value so we can decide if -d 0 was used. */
     690           0 :     debug_level = SSSDBG_INVALID;
     691             : 
     692           0 :     pc = poptGetContext(argv[0], argc, argv, long_options, 0);
     693           0 :     while((opt = poptGetNextOpt(pc)) != -1) {
     694             :         switch(opt) {
     695             :         default:
     696           0 :         fprintf(stderr, "\nInvalid option %s: %s\n\n",
     697             :                   poptBadOption(pc, 0), poptStrerror(opt));
     698           0 :             poptPrintUsage(pc, stderr, 0);
     699           0 :             _exit(-1);
     700             :         }
     701             :     }
     702             : 
     703           0 :     poptFreeContext(pc);
     704             : 
     705           0 :     DEBUG_INIT(debug_level);
     706             : 
     707           0 :     debug_prg_name = talloc_asprintf(NULL, "[sssd[gpo_child[%d]]]", getpid());
     708           0 :     if (debug_prg_name == NULL) {
     709           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf failed.\n");
     710           0 :         goto fail;
     711             :     }
     712             : 
     713           0 :     if (debug_fd != -1) {
     714           0 :         ret = set_debug_file_from_fd(debug_fd);
     715           0 :         if (ret != EOK) {
     716           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "set_debug_file_from_fd failed.\n");
     717             :         }
     718             :     }
     719             : 
     720           0 :     DEBUG(SSSDBG_TRACE_FUNC, "gpo_child started.\n");
     721             : 
     722           0 :     main_ctx = talloc_new(NULL);
     723           0 :     if (main_ctx == NULL) {
     724           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new failed.\n");
     725           0 :         talloc_free(discard_const(debug_prg_name));
     726           0 :         goto fail;
     727             :     }
     728           0 :     talloc_steal(main_ctx, debug_prg_name);
     729             : 
     730           0 :     buf = talloc_size(main_ctx, sizeof(uint8_t)*IN_BUF_SIZE);
     731           0 :     if (buf == NULL) {
     732           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_size failed.\n");
     733           0 :         goto fail;
     734             :     }
     735             : 
     736           0 :     ibuf = talloc_zero(main_ctx, struct input_buffer);
     737           0 :     if (ibuf == NULL) {
     738           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
     739           0 :         goto fail;
     740             :     }
     741             : 
     742           0 :     DEBUG(SSSDBG_TRACE_FUNC, "context initialized\n");
     743             : 
     744           0 :     errno = 0;
     745           0 :     len = sss_atomic_read_s(STDIN_FILENO, buf, IN_BUF_SIZE);
     746           0 :     if (len == -1) {
     747           0 :         ret = errno;
     748           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "read failed [%d][%s].\n", ret, strerror(ret));
     749           0 :         goto fail;
     750             :     }
     751             : 
     752           0 :     close(STDIN_FILENO);
     753             : 
     754           0 :     ret = unpack_buffer(buf, len, ibuf);
     755           0 :     if (ret != EOK) {
     756           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     757             :               "unpack_buffer failed.[%d][%s].\n", ret, strerror(ret));
     758           0 :         goto fail;
     759             :     }
     760             : 
     761           0 :     DEBUG(SSSDBG_TRACE_FUNC, "performing smb operations\n");
     762             : 
     763           0 :     result = perform_smb_operations(ibuf->cached_gpt_version,
     764             :                                     ibuf->smb_server,
     765             :                                     ibuf->smb_share,
     766             :                                     ibuf->smb_path,
     767             :                                     ibuf->smb_cse_suffix,
     768             :                                     &sysvol_gpt_version);
     769           0 :     if (result != EOK) {
     770           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     771             :               "perform_smb_operations failed.[%d][%s].\n",
     772             :               result, strerror(result));
     773           0 :         goto fail;
     774             :     }
     775             : 
     776           0 :     ret = prepare_response(main_ctx, sysvol_gpt_version, result, &resp);
     777           0 :     if (ret != EOK) {
     778           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "prepare_response failed. [%d][%s].\n",
     779             :                     ret, strerror(ret));
     780           0 :         goto fail;
     781             :     }
     782             : 
     783           0 :     errno = 0;
     784             : 
     785           0 :     written = sss_atomic_write_s(AD_GPO_CHILD_OUT_FILENO, resp->buf, resp->size);
     786           0 :     if (written == -1) {
     787           0 :         ret = errno;
     788           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "write failed [%d][%s].\n", ret,
     789             :                     strerror(ret));
     790           0 :         goto fail;
     791             :     }
     792             : 
     793           0 :     if (written != resp->size) {
     794           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Expected to write %zu bytes, wrote %zu\n",
     795             :               resp->size, written);
     796           0 :         goto fail;
     797             :     }
     798             : 
     799           0 :     DEBUG(SSSDBG_TRACE_FUNC, "gpo_child completed successfully\n");
     800           0 :     close(AD_GPO_CHILD_OUT_FILENO);
     801           0 :     talloc_free(main_ctx);
     802           0 :     return EXIT_SUCCESS;
     803             : 
     804             : fail:
     805           0 :     DEBUG(SSSDBG_CRIT_FAILURE, "gpo_child failed!\n");
     806           0 :     close(AD_GPO_CHILD_OUT_FILENO);
     807           0 :     talloc_free(main_ctx);
     808           0 :     return EXIT_FAILURE;
     809             : }

Generated by: LCOV version 1.10