LCOV - code coverage report
Current view: top level - responder/autofs - autofssrv_cmd.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 0 696 0.0 %
Date: 2015-10-19 Functions: 0 31 0.0 %

          Line data    Source code
       1             : /*
       2             :     Authors:
       3             :         Jakub Hrozek <jhrozek@redhat.com>
       4             : 
       5             :     Copyright (C) 2012 Red Hat
       6             : 
       7             :     Autofs responder: commands
       8             : 
       9             :     This program is free software; you can redistribute it and/or modify
      10             :     it under the terms of the GNU General Public License as published by
      11             :     the Free Software Foundation; either version 3 of the License, or
      12             :     (at your option) any later version.
      13             : 
      14             :     This program is distributed in the hope that it will be useful,
      15             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :     GNU General Public License for more details.
      18             : 
      19             :     You should have received a copy of the GNU General Public License
      20             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include <talloc.h>
      24             : 
      25             : #include "util/util.h"
      26             : #include "responder/common/responder.h"
      27             : #include "responder/common/responder_packet.h"
      28             : #include "responder/autofs/autofs_private.h"
      29             : #include "db/sysdb.h"
      30             : #include "db/sysdb_autofs.h"
      31             : #include "confdb/confdb.h"
      32             : 
      33           0 : static int autofs_cmd_send_error(struct autofs_cmd_ctx *cmdctx, int err)
      34             : {
      35           0 :     return sss_cmd_send_error(cmdctx->cctx, err);
      36             : }
      37             : 
      38             : static int
      39           0 : autofs_cmd_send_empty(struct autofs_cmd_ctx *cmdctx)
      40             : {
      41           0 :     return sss_cmd_send_empty(cmdctx->cctx, cmdctx);
      42             : }
      43             : 
      44             : static int
      45           0 : autofs_cmd_done(struct autofs_cmd_ctx *cmdctx, int ret)
      46             : {
      47           0 :     switch (ret) {
      48             :     case EOK:
      49             :         /* all fine, just return here */
      50           0 :         break;
      51             : 
      52             :     case ENOENT:
      53           0 :         ret = autofs_cmd_send_empty(cmdctx);
      54           0 :         if (ret) {
      55           0 :             return EFAULT;
      56             :         }
      57           0 :         break;
      58             : 
      59             :     case EAGAIN:
      60             :         /* async processing, just return here */
      61           0 :         break;
      62             : 
      63             :     case EFAULT:
      64             :         /* very bad error */
      65           0 :         return EFAULT;
      66             : 
      67             :     default:
      68           0 :         ret = autofs_cmd_send_error(cmdctx, ret);
      69           0 :         if (ret) {
      70           0 :             return EFAULT;
      71             :         }
      72           0 :         sss_cmd_done(cmdctx->cctx, cmdctx);
      73           0 :         break;
      74             :     }
      75             : 
      76           0 :     return EOK;
      77             : }
      78             : 
      79             : static errno_t
      80           0 : autofs_setent_add_ref(TALLOC_CTX *memctx,
      81             :                       struct autofs_map_ctx *map_ctx,
      82             :                       struct tevent_req *req)
      83             : {
      84           0 :     return setent_add_ref(memctx, map_ctx, &map_ctx->reqs, req);
      85             : }
      86             : 
      87             : static void
      88           0 : autofs_setent_notify(struct autofs_map_ctx *map_ctx, errno_t ret)
      89             : {
      90           0 :     setent_notify(&map_ctx->reqs, ret);
      91           0 : }
      92             : 
      93             : errno_t
      94           0 : autofs_orphan_maps(struct autofs_ctx *actx)
      95             : {
      96             :     int hret;
      97             :     unsigned long mcount;
      98             :     unsigned long i;
      99             :     hash_key_t *maps;
     100             : 
     101           0 :     if (!actx || !actx->maps) {
     102           0 :         return EINVAL;
     103             :     }
     104             : 
     105           0 :     hret = hash_keys(actx->maps, &mcount, &maps);
     106           0 :     if (hret != HASH_SUCCESS) {
     107           0 :         return EIO;
     108             :     }
     109             : 
     110           0 :     for (i = 0; i < mcount; i++) {
     111           0 :         hret = hash_delete(actx->maps, &maps[i]);
     112           0 :         if (hret != HASH_SUCCESS) {
     113           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "Could not delete key from hash\n");
     114           0 :             continue;
     115             :         }
     116             :     }
     117             : 
     118           0 :     return EOK;
     119             : }
     120             : 
     121             : static errno_t
     122           0 : get_autofs_map(struct autofs_ctx *actx,
     123             :                char *mapname,
     124             :                struct autofs_map_ctx **map)
     125             : {
     126             :     hash_key_t key;
     127             :     hash_value_t value;
     128             :     int hret;
     129             : 
     130           0 :     key.type = HASH_KEY_STRING;
     131           0 :     key.str = mapname;
     132             : 
     133           0 :     hret = hash_lookup(actx->maps, &key, &value);
     134           0 :     if (hret == HASH_SUCCESS) {
     135           0 :         *map = talloc_get_type(value.ptr, struct autofs_map_ctx);
     136           0 :         return EOK;
     137           0 :     } else if (hret == HASH_ERROR_KEY_NOT_FOUND) {
     138           0 :         return ENOENT;
     139             :     }
     140             : 
     141           0 :     DEBUG(SSSDBG_CRIT_FAILURE,
     142             :           "Unexpected error reading from autofs map hash [%d][%s]\n",
     143             :           hret, hash_error_string(hret));
     144           0 :     return EIO;
     145             : }
     146             : 
     147             : static int autofs_map_hash_remove (TALLOC_CTX *ctx);
     148             : 
     149             : void
     150           0 : autofs_map_hash_delete_cb(hash_entry_t *item,
     151             :                           hash_destroy_enum deltype, void *pvt)
     152             : {
     153             :     struct autofs_map_ctx *map;
     154             : 
     155           0 :     if (deltype != HASH_ENTRY_DESTROY) {
     156           0 :         return;
     157             :     }
     158             : 
     159           0 :     map = talloc_get_type(item->value.ptr, struct autofs_map_ctx);
     160           0 :     if (!map) {
     161           0 :         DEBUG(SSSDBG_OP_FAILURE, "Invalid autofs map\n");
     162           0 :         return;
     163             :     }
     164             : 
     165             :     /* So that the destructor wouldn't attempt to remove the map from hash
     166             :      * table */
     167           0 :     map->map_table = NULL;
     168             : }
     169             : 
     170             : static errno_t
     171           0 : set_autofs_map(struct autofs_ctx *actx,
     172             :                struct autofs_map_ctx *map)
     173             : {
     174             :     hash_key_t key;
     175             :     hash_value_t value;
     176             :     int hret;
     177             : 
     178           0 :     if (map->mapname == NULL) {
     179           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Missing autofs map name.\n");
     180           0 :         return EINVAL;
     181             :     }
     182             : 
     183             :     /* Add this entry to the hash table */
     184           0 :     key.type = HASH_KEY_STRING;
     185           0 :     key.str = map->mapname;
     186           0 :     value.type = HASH_VALUE_PTR;
     187           0 :     value.ptr = map;
     188           0 :     hret = hash_enter(actx->maps, &key, &value);
     189           0 :     if (hret != EOK) {
     190           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     191             :               "Unable to add hash table entry for [%s]\n", key.str);
     192           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     193             :               "Hash error [%d][%s]\n", hret, hash_error_string(hret));
     194           0 :         return EIO;
     195             :     }
     196           0 :     talloc_steal(actx->maps, map);
     197           0 :     talloc_set_destructor((TALLOC_CTX *) map, autofs_map_hash_remove);
     198             : 
     199           0 :     return EOK;
     200             : }
     201             : 
     202             : static int
     203           0 : autofs_map_hash_remove(TALLOC_CTX *ctx)
     204             : {
     205             :     int hret;
     206             :     hash_key_t key;
     207           0 :     struct autofs_map_ctx *map =
     208             :             talloc_get_type(ctx, struct autofs_map_ctx);
     209             : 
     210           0 :     if (map->map_table == NULL) {
     211           0 :         DEBUG(SSSDBG_TRACE_LIBS, "autofs map [%s] was already removed\n",
     212             :               map->mapname);
     213           0 :         return 0;
     214             :     }
     215             : 
     216           0 :     key.type = HASH_KEY_STRING;
     217           0 :     key.str = map->mapname;
     218             : 
     219             :     /* Remove the autofs map result object from the lookup table */
     220           0 :     hret = hash_delete(map->map_table, &key);
     221           0 :     if (hret != HASH_SUCCESS) {
     222           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     223             :               "Could not remove key from table! [%d][%s]\n",
     224             :               hret, hash_error_string(hret));
     225           0 :         return -1;
     226             :     }
     227           0 :     return 0;
     228             : }
     229             : 
     230             : static struct tevent_req *
     231             : setautomntent_send(TALLOC_CTX *mem_ctx,
     232             :                    const char *rawname,
     233             :                    struct autofs_cmd_ctx *cmdctx);
     234             : static errno_t setautomntent_recv(struct tevent_req *req);
     235             : static void sss_autofs_cmd_setautomntent_done(struct tevent_req *req);
     236             : 
     237             : /* FIXME - file a ticket to have per-responder private
     238             :  * data instead of growing the cli_ctx structure */
     239             : static int
     240           0 : sss_autofs_cmd_setautomntent(struct cli_ctx *client)
     241             : {
     242             :     struct autofs_cmd_ctx *cmdctx;
     243             :     uint8_t *body;
     244             :     size_t blen;
     245           0 :     errno_t ret = EOK;
     246             :     const char *rawname;
     247             :     struct tevent_req *req;
     248             : 
     249           0 :     DEBUG(SSSDBG_TRACE_INTERNAL, "sss_autofs_cmd_setautomntent\n");
     250             : 
     251           0 :     cmdctx = talloc_zero(client, struct autofs_cmd_ctx);
     252           0 :     if (!cmdctx) {
     253           0 :         return ENOMEM;
     254             :     }
     255           0 :     cmdctx->cctx = client;
     256             : 
     257           0 :     sss_packet_get_body(client->creq->in, &body, &blen);
     258             : 
     259             :     /* if not terminated fail */
     260           0 :     if (body[blen -1] != '\0') {
     261           0 :         ret = EINVAL;
     262           0 :         goto done;
     263             :     }
     264             : 
     265             :     /* If the body isn't valid UTF-8, fail */
     266           0 :     if (!sss_utf8_check(body, blen -1)) {
     267           0 :         ret = EINVAL;
     268           0 :         goto done;
     269             :     }
     270             : 
     271           0 :     rawname = (const char *)body;
     272           0 :     DEBUG(SSSDBG_TRACE_FUNC,
     273             :           "Got request for automount map named %s\n", rawname);
     274             : 
     275           0 :     req = setautomntent_send(cmdctx, rawname, cmdctx);
     276           0 :     if (!req) {
     277           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     278             :               "Fatal error calling setautomntent_send\n");
     279           0 :         ret = EIO;
     280           0 :         goto done;
     281             :     }
     282           0 :     tevent_req_set_callback(req, sss_autofs_cmd_setautomntent_done, cmdctx);
     283             : 
     284           0 :     ret = EOK;
     285             : done:
     286           0 :     return autofs_cmd_done(cmdctx, ret);
     287             : }
     288             : 
     289           0 : static void sss_autofs_cmd_setautomntent_done(struct tevent_req *req)
     290             : {
     291           0 :     struct autofs_cmd_ctx *cmdctx =
     292           0 :         tevent_req_callback_data(req, struct autofs_cmd_ctx);
     293             :     errno_t ret;
     294             :     errno_t reqret;
     295             :     struct sss_packet *packet;
     296             :     uint8_t *body;
     297             :     size_t blen;
     298             : 
     299           0 :     DEBUG(SSSDBG_TRACE_INTERNAL, "setautomntent done\n");
     300             : 
     301           0 :     reqret = setautomntent_recv(req);
     302           0 :     talloc_zfree(req);
     303           0 :     if (reqret != EOK && reqret != ENOENT) {
     304           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "setautomntent_recv failed\n");
     305           0 :         autofs_cmd_done(cmdctx, reqret);
     306           0 :         return;
     307             :     }
     308             : 
     309             :     /* Either we succeeded or no domains were eligible */
     310           0 :     ret = sss_packet_new(cmdctx->cctx->creq, 0,
     311           0 :                          sss_packet_get_cmd(cmdctx->cctx->creq->in),
     312           0 :                          &cmdctx->cctx->creq->out);
     313           0 :     if (ret == EOK) {
     314           0 :         if (reqret == ENOENT) {
     315           0 :             DEBUG(SSSDBG_TRACE_FUNC, "setautomntent did not find requested map\n");
     316             :             /* Notify the caller that this entry wasn't found */
     317           0 :             sss_cmd_empty_packet(cmdctx->cctx->creq->out);
     318             :         } else {
     319           0 :             DEBUG(SSSDBG_TRACE_FUNC, "setautomntent found data\n");
     320           0 :             packet = cmdctx->cctx->creq->out;
     321           0 :             ret = sss_packet_grow(packet, 2*sizeof(uint32_t));
     322           0 :             if (ret != EOK) {
     323           0 :                 DEBUG(SSSDBG_CRIT_FAILURE, "Couldn't grow the packet\n");
     324           0 :                 talloc_free(cmdctx);
     325           0 :                 return;
     326             :             }
     327             : 
     328           0 :             sss_packet_get_body(packet, &body, &blen);
     329             : 
     330             :             /* Got some results */
     331           0 :             SAFEALIGN_SETMEM_UINT32(body, 1, NULL);
     332             : 
     333             :             /* Reserved padding */
     334           0 :             SAFEALIGN_SETMEM_UINT32(body + sizeof(uint32_t), 0, NULL);
     335             :         }
     336             : 
     337           0 :         sss_cmd_done(cmdctx->cctx, NULL);
     338           0 :         return;
     339             :     }
     340             : 
     341           0 :     DEBUG(SSSDBG_CRIT_FAILURE, "Error creating packet\n");
     342           0 :     return;
     343             : }
     344             : 
     345             : struct setautomntent_state {
     346             :     struct autofs_cmd_ctx *cmdctx;
     347             :     struct autofs_dom_ctx *dctx;
     348             : 
     349             :     char *mapname;
     350             :     struct autofs_map_ctx *map;
     351             : };
     352             : 
     353             : struct setautomntent_lookup_ctx {
     354             :     struct autofs_ctx *actx;
     355             :     struct autofs_dom_ctx *dctx;
     356             :     struct resp_ctx *rctx;
     357             :     struct cli_ctx *cctx;
     358             : 
     359             :     bool returned_to_mainloop;
     360             : 
     361             :     char *mapname;
     362             :     struct autofs_map_ctx *map;
     363             : };
     364             : 
     365             : static errno_t
     366             : lookup_automntmap_step(struct setautomntent_lookup_ctx *lookup_ctx);
     367             : 
     368             : static void
     369           0 : autofs_map_result_timeout(struct tevent_context *ev,
     370             :                           struct tevent_timer *te,
     371             :                           struct timeval current_time,
     372             :                           void *pvt)
     373             : {
     374           0 :     struct autofs_map_ctx *map =
     375             :             talloc_get_type(pvt, struct autofs_map_ctx);
     376             : 
     377             :     /* Free the autofs map result context
     378             :      * The destructor for the autofs map will remove itself
     379             :      * from the hash table
     380             :      */
     381           0 :     talloc_free(map);
     382           0 : }
     383             : 
     384             : static void
     385           0 : set_autofs_map_lifetime(uint32_t lifetime,
     386             :                         struct setautomntent_lookup_ctx *lookup_ctx,
     387             :                         struct autofs_map_ctx *map)
     388             : {
     389             :     struct timeval tv;
     390             :     struct tevent_timer *te;
     391             : 
     392           0 :     tv = tevent_timeval_current_ofs(lifetime, 0);
     393           0 :     te = tevent_add_timer(lookup_ctx->rctx->ev,
     394             :                           lookup_ctx->rctx, tv,
     395             :                           autofs_map_result_timeout,
     396             :                           map);
     397           0 :     if (!te) {
     398           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     399             :               "Could not set up life timer for autofs maps. "
     400             :                "Entries may become stale.\n");
     401             :     }
     402           0 : }
     403             : 
     404             : static errno_t
     405             : setautomntent_get_autofs_map(struct autofs_ctx *actx,
     406             :                              char *mapname,
     407             :                              struct autofs_map_ctx **map);
     408             : 
     409             : static struct tevent_req *
     410           0 : setautomntent_send(TALLOC_CTX *mem_ctx,
     411             :                    const char *rawname,
     412             :                    struct autofs_cmd_ctx *cmdctx)
     413             : {
     414             :     char *domname;
     415             :     errno_t ret;
     416             :     struct tevent_req *req;
     417             :     struct setautomntent_state *state;
     418           0 :     struct cli_ctx *client = cmdctx->cctx;
     419             :     struct autofs_dom_ctx *dctx;
     420           0 :     struct autofs_ctx *actx =
     421           0 :             talloc_get_type(client->rctx->pvt_ctx, struct autofs_ctx);
     422             :     struct setautomntent_lookup_ctx *lookup_ctx;
     423             : 
     424           0 :     req = tevent_req_create(mem_ctx, &state, struct setautomntent_state);
     425           0 :     if (!req) {
     426           0 :         DEBUG(SSSDBG_FATAL_FAILURE,
     427             :               "Could not create tevent request for setautomntent\n");
     428           0 :         return NULL;
     429             :     }
     430           0 :     state->cmdctx = cmdctx;
     431             : 
     432           0 :     dctx = talloc_zero(state, struct autofs_dom_ctx);
     433           0 :     if (!dctx) {
     434           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory\n");
     435           0 :         ret = ENOMEM;
     436           0 :         goto fail;
     437             :     }
     438           0 :     dctx->cmd_ctx = state->cmdctx;
     439           0 :     state->dctx = dctx;
     440             : 
     441           0 :     ret = sss_parse_name_for_domains(state, client->rctx->domains,
     442             :                                      NULL, rawname,
     443           0 :                                      &domname, &state->mapname);
     444           0 :     if (ret != EOK) {
     445           0 :         DEBUG(SSSDBG_FATAL_FAILURE,
     446             :               "Invalid name received [%s]\n", rawname);
     447           0 :         goto fail;
     448             :     }
     449             : 
     450           0 :     DEBUG(SSSDBG_TRACE_FUNC,
     451             :          "Requesting info for automount map [%s] from [%s]\n",
     452             :          state->mapname, domname?domname:"<ALL>");
     453             : 
     454           0 :     if (domname) {
     455           0 :         dctx->domain = responder_get_domain(client->rctx, domname);
     456           0 :         if (!dctx->domain) {
     457           0 :             ret = EINVAL;
     458           0 :             goto fail;
     459             :         }
     460             : 
     461           0 :         client->automntmap_name = talloc_strdup(client, rawname);
     462           0 :         if (!client->automntmap_name) {
     463           0 :             ret = ENOMEM;
     464           0 :             goto fail;
     465             :         }
     466             :     } else {
     467             :         /* this is a multidomain search */
     468           0 :         dctx->domain = client->rctx->domains;
     469           0 :         cmdctx->check_next = true;
     470             : 
     471           0 :         client->automntmap_name = talloc_strdup(client, state->mapname);
     472           0 :         if (!client->automntmap_name) {
     473           0 :             ret = ENOMEM;
     474           0 :             goto fail;
     475             :         }
     476             :     }
     477             : 
     478           0 :     dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
     479             :     /* Is the result context already available?
     480             :      * Check for existing lookups for this map
     481             :      */
     482           0 :     ret = setautomntent_get_autofs_map(actx, state->mapname, &state->map);
     483           0 :     if (ret == EOK) {
     484             :         /* Another process already requested this map
     485             :          * Check whether it's ready for processing.
     486             :          */
     487           0 :         if (state->map->ready) {
     488           0 :             if (state->map->found) {
     489           0 :                 DEBUG(SSSDBG_TRACE_LIBS,
     490             :                       "Map %s is ready to be processed\n", state->mapname);
     491           0 :                 tevent_req_done(req);
     492           0 :                 tevent_req_post(req, actx->rctx->ev);
     493           0 :                 return req;
     494             :             } else {
     495           0 :                 DEBUG(SSSDBG_TRACE_LIBS,
     496             :                       "Map %s was marked as nonexistent\n", state->mapname);
     497           0 :                 tevent_req_error(req, ENOENT);
     498           0 :                 tevent_req_post(req, actx->rctx->ev);
     499           0 :                 return req;
     500             :             }
     501             :         }
     502             : 
     503             :         /* Result object is still being constructed
     504             :          * Register for notification when it's ready
     505             :          */
     506           0 :         DEBUG(SSSDBG_TRACE_LIBS,
     507             :               "Map %s is being looked up, registering for notification\n",
     508             :                state->mapname);
     509           0 :         ret = autofs_setent_add_ref(state, state->map, req);
     510           0 :         if (ret != EOK) {
     511           0 :             goto fail;
     512             :         }
     513             :         /* Will return control below */
     514           0 :     } else if (ret == ENOENT) {
     515           0 :         DEBUG(SSSDBG_TRACE_LIBS,
     516             :               "Map %s needs to be looked up\n", state->mapname);
     517             : 
     518           0 :         state->map = talloc_zero(actx, struct autofs_map_ctx);
     519           0 :         if (!state->map) {
     520           0 :             ret = ENOMEM;
     521           0 :             goto fail;
     522             :         }
     523           0 :         dctx->map_ctx = state->map;
     524             : 
     525           0 :         state->map->mapname = talloc_strdup(state->map, state->mapname);
     526           0 :         if (!state->map->mapname) {
     527           0 :             talloc_free(state->map);
     528           0 :             ret = ENOMEM;
     529           0 :             goto fail;
     530             :         }
     531           0 :         state->map->map_table = actx->maps;
     532             : 
     533           0 :         ret = autofs_setent_add_ref(state, state->map, req);
     534           0 :         if (ret != EOK) {
     535           0 :             talloc_free(state->map);
     536           0 :             goto fail;
     537             :         }
     538             : 
     539           0 :         ret = set_autofs_map(actx, state->map);
     540           0 :         if (ret != EOK) {
     541           0 :             talloc_free(state->map);
     542           0 :             goto fail;
     543             :         }
     544             : 
     545             :         /* Perform lookup */
     546           0 :         lookup_ctx = talloc_zero(state->map, struct setautomntent_lookup_ctx);
     547           0 :         if (!lookup_ctx) {
     548           0 :             talloc_free(state->map);
     549           0 :             ret = ENOMEM;
     550           0 :             goto fail;
     551             :         }
     552             : 
     553             :         /* Steal the dom_ctx onto the lookup_ctx so it doesn't go out of scope if
     554             :         * this request is canceled while other requests are in-progress.
     555             :         */
     556           0 :         lookup_ctx->dctx = talloc_steal(lookup_ctx, state->dctx);
     557           0 :         lookup_ctx->actx = actx;
     558           0 :         lookup_ctx->map = state->map;
     559           0 :         lookup_ctx->rctx = client->rctx;
     560           0 :         lookup_ctx->mapname =
     561           0 :                     talloc_strdup(lookup_ctx, state->mapname);
     562           0 :         if (!lookup_ctx->mapname) {
     563           0 :             talloc_free(state->map);
     564           0 :             ret = ENOMEM;
     565           0 :             goto fail;
     566             :         }
     567             : 
     568           0 :         ret = lookup_automntmap_step(lookup_ctx);
     569           0 :         if (ret == EAGAIN) {
     570           0 :             DEBUG(SSSDBG_TRACE_INTERNAL, "lookup_automntmap_step "
     571             :                   "is refreshing the cache, re-entering the mainloop\n");
     572           0 :             return req;
     573           0 :         } else if (ret != EOK) {
     574           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Could not get data from cache\n");
     575           0 :             talloc_free(state->map);
     576           0 :             ret = ENOMEM;
     577           0 :             goto fail;
     578             :         }
     579             : 
     580           0 :         tevent_req_done(req);
     581           0 :         tevent_req_post(req, cmdctx->cctx->ev);
     582           0 :         return req;
     583             :     } else {
     584           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     585             :               "Unexpected error from get_autofs_map [%d]: %s\n",
     586             :                ret, strerror(ret));
     587           0 :         goto fail;
     588             :     }
     589             : 
     590           0 :     return req;
     591             : 
     592             : fail:
     593           0 :     tevent_req_error(req, ret);
     594           0 :     tevent_req_post(req, actx->rctx->ev);
     595           0 :     return req;
     596             : }
     597             : 
     598             : static errno_t
     599           0 : setautomntent_get_autofs_map(struct autofs_ctx *actx,
     600             :                              char *mapname,
     601             :                              struct autofs_map_ctx **map)
     602             : {
     603             :     errno_t ret;
     604             : 
     605           0 :     if (strcmp(mapname, "auto.master") == 0) {
     606             :         /* Iterate over the hash and remove all maps */
     607           0 :         ret = autofs_orphan_maps(actx);
     608           0 :         if (ret != EOK) {
     609           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "Could not remove existing maps from hash\n");
     610             :         }
     611           0 :         return ENOENT;
     612             :     }
     613             : 
     614           0 :     return get_autofs_map(actx, mapname, map);
     615             : }
     616             : 
     617             : static errno_t
     618             : lookup_automntmap_update_cache(struct setautomntent_lookup_ctx *lookup_ctx);
     619             : 
     620             : static errno_t
     621           0 : lookup_automntmap_step(struct setautomntent_lookup_ctx *lookup_ctx)
     622             : {
     623             :     errno_t ret;
     624           0 :     struct sss_domain_info *dom = lookup_ctx->dctx->domain;
     625           0 :     struct autofs_dom_ctx *dctx = lookup_ctx->dctx;
     626             :     struct sysdb_ctx *sysdb;
     627             :     struct autofs_map_ctx *map;
     628             : 
     629             :     /* Check each domain for this map name */
     630           0 :     while (dom) {
     631           0 :         if (dom != dctx->domain) {
     632             :             /* make sure we reset the check_provider flag when we check
     633             :              * a new domain */
     634           0 :             dctx->check_provider =
     635           0 :                     NEED_CHECK_PROVIDER(dom->provider);
     636             :         }
     637             : 
     638             :         /* make sure to update the dctx if we changed domain */
     639           0 :         dctx->domain = dom;
     640             : 
     641           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Requesting info for [%s@%s]\n",
     642             :               lookup_ctx->mapname, dom->name);
     643           0 :         sysdb = dom->sysdb;
     644           0 :         if (sysdb == NULL) {
     645           0 :             DEBUG(SSSDBG_FATAL_FAILURE,
     646             :                   "Fatal: Sysdb CTX not found for this domain!\n");
     647           0 :             return EIO;
     648             :         }
     649             : 
     650             :         /* Look into the cache */
     651           0 :         talloc_free(dctx->map);
     652           0 :         ret = sysdb_get_map_byname(dctx, dom, lookup_ctx->mapname,
     653             :                                    &dctx->map);
     654           0 :         if (ret != EOK && ret != ENOENT) {
     655           0 :             DEBUG(SSSDBG_OP_FAILURE, "Could not check cache\n");
     656           0 :             return ret;
     657           0 :         } else if (ret == ENOENT) {
     658           0 :             DEBUG(SSSDBG_MINOR_FAILURE,
     659             :                   "No automount map [%s] in cache for domain [%s]\n",
     660             :                    lookup_ctx->mapname, dom->name);
     661           0 :             if (!dctx->check_provider) {
     662           0 :                 if (dctx->cmd_ctx->check_next) {
     663           0 :                     DEBUG(SSSDBG_TRACE_INTERNAL, "Moving on to next domain\n");
     664           0 :                     dom = get_next_domain(dom, false);
     665           0 :                     continue;
     666             :                 }
     667           0 :                 else break;
     668             :             }
     669             :         }
     670             : 
     671           0 :         ret = get_autofs_map(lookup_ctx->actx, lookup_ctx->mapname, &map);
     672           0 :         if (ret != EOK) {
     673             :             /* Something really bad happened! */
     674           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Autofs map entry was lost!\n");
     675           0 :             return ret;
     676             :         }
     677             : 
     678           0 :         if (dctx->map == NULL && !dctx->check_provider) {
     679           0 :             DEBUG(SSSDBG_MINOR_FAILURE,
     680             :                   "Autofs map not found, setting negative cache\n");
     681           0 :             map->ready = true;
     682           0 :             map->found = false;
     683           0 :             set_autofs_map_lifetime(lookup_ctx->actx->neg_timeout, lookup_ctx, map);
     684           0 :             return ENOENT;
     685             :         }
     686             : 
     687           0 :         if (dctx->check_provider) {
     688           0 :             ret = lookup_automntmap_update_cache(lookup_ctx);
     689           0 :             if (ret == EAGAIN) {
     690           0 :                 DEBUG(SSSDBG_TRACE_INTERNAL,
     691             :                       "Looking up automount maps from the DP\n");
     692           0 :                 return EAGAIN;
     693           0 :             } else if (ret != EOK) {
     694           0 :                 DEBUG(SSSDBG_OP_FAILURE,
     695             :                       "Error looking up automount maps [%d]: %s\n",
     696             :                        ret, strerror(ret));
     697           0 :                 return ret;
     698             :             }
     699             :         }
     700             : 
     701             :         /* OK, the map is in cache and valid.
     702             :          * Let's get all members and return it
     703             :          */
     704           0 :         ret = sysdb_autofs_entries_by_map(map, dom, map->mapname,
     705           0 :                                           &map->entry_count,
     706           0 :                                           &map->entries);
     707           0 :         if (ret != EOK && ret != ENOENT) {
     708           0 :             DEBUG(SSSDBG_OP_FAILURE,
     709             :                   "Error looking automount map entries [%d]: %s\n",
     710             :                   ret, strerror(ret));
     711           0 :             map->ready = true;
     712           0 :             map->found = false;
     713           0 :             set_autofs_map_lifetime(lookup_ctx->actx->neg_timeout, lookup_ctx, map);
     714           0 :             return EIO;
     715             :         }
     716             : 
     717           0 :         map->map = talloc_steal(map, dctx->map);
     718             : 
     719           0 :         DEBUG(SSSDBG_TRACE_FUNC,
     720             :               "setautomntent done for map %s\n", lookup_ctx->mapname);
     721           0 :         map->ready = true;
     722           0 :         map->found = true;
     723           0 :         set_autofs_map_lifetime(dom->autofsmap_timeout, lookup_ctx, map);
     724           0 :         return EOK;
     725             :     }
     726             : 
     727           0 :     map = talloc_zero(lookup_ctx->actx, struct autofs_map_ctx);
     728           0 :     if (!map) {
     729           0 :         return ENOMEM;
     730             :     }
     731             : 
     732           0 :     map->ready = true;
     733           0 :     map->found = false;
     734           0 :     map->map_table = lookup_ctx->actx->maps;
     735             : 
     736           0 :     map->mapname = talloc_strdup(map, lookup_ctx->mapname);
     737           0 :     if (!map->mapname) {
     738           0 :         talloc_free(map);
     739           0 :         return ENOMEM;
     740             :     }
     741             : 
     742           0 :     ret = set_autofs_map(lookup_ctx->actx, map);
     743           0 :     if (ret != EOK) {
     744           0 :         talloc_free(map);
     745           0 :         return ENOMEM;
     746             :     }
     747             : 
     748           0 :     set_autofs_map_lifetime(lookup_ctx->actx->neg_timeout, lookup_ctx, map);
     749             : 
     750             :     /* If we've gotten here, then no domain contained this map */
     751           0 :     return ENOENT;
     752             : }
     753             : 
     754             : static void lookup_automntmap_cache_updated(uint16_t err_maj, uint32_t err_min,
     755             :                                             const char *err_msg, void *ptr);
     756             : static void autofs_dp_send_map_req_done(struct tevent_req *req);
     757             : 
     758             : static errno_t
     759           0 : lookup_automntmap_update_cache(struct setautomntent_lookup_ctx *lookup_ctx)
     760             : {
     761             :     errno_t ret;
     762           0 :     uint64_t cache_expire = 0;
     763           0 :     struct autofs_dom_ctx *dctx = lookup_ctx->dctx;
     764           0 :     struct tevent_req *req = NULL;
     765           0 :     struct dp_callback_ctx *cb_ctx = NULL;
     766             : 
     767           0 :     if (dctx->map != NULL) {
     768           0 :         if (strcmp(lookup_ctx->mapname, "auto.master") != 0) {
     769           0 :             cache_expire = ldb_msg_find_attr_as_uint64(dctx->map,
     770             :                                                        SYSDB_CACHE_EXPIRE, 0);
     771             :         }
     772             : 
     773             :         /* if we have any reply let's check cache validity */
     774           0 :         ret = sss_cmd_check_cache(dctx->map, 0, cache_expire);
     775           0 :         if (ret == EOK) {
     776           0 :             DEBUG(SSSDBG_TRACE_FUNC, "Cached entry is valid, returning..\n");
     777           0 :             return EOK;
     778           0 :         } else if (ret != EAGAIN && ret != ENOENT) {
     779           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Error checking cache: %d\n", ret);
     780           0 :             goto error;
     781             :         }
     782             :     }
     783             : 
     784             :     /* dont loop forever :-) */
     785           0 :     dctx->check_provider = false;
     786             : 
     787             :     /* keep around current data in case backend is offline */
     788             :     /* FIXME - do this by default */
     789             : #if 0
     790             :     if (dctx->res->count) {
     791             :         dctx->res = talloc_steal(dctx, dctx->res);
     792             :     }
     793             : #endif
     794             : 
     795           0 :     req = sss_dp_get_autofs_send(lookup_ctx->cctx, lookup_ctx->rctx,
     796           0 :                                  lookup_ctx->dctx->domain, true,
     797           0 :                                  SSS_DP_AUTOFS, lookup_ctx->mapname);
     798           0 :     if (!req) {
     799           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     800             :               "Out of memory sending data provider request\n");
     801           0 :         ret = ENOMEM;
     802           0 :         goto error;
     803             :     }
     804             : 
     805           0 :     cb_ctx = talloc_zero(lookup_ctx->dctx, struct dp_callback_ctx);
     806           0 :     if(!cb_ctx) {
     807           0 :         talloc_zfree(req);
     808           0 :         ret = ENOMEM;
     809           0 :         goto error;
     810             :     }
     811           0 :     cb_ctx->callback = lookup_automntmap_cache_updated;
     812           0 :     cb_ctx->ptr = lookup_ctx;
     813           0 :     cb_ctx->cctx = lookup_ctx->dctx->cmd_ctx->cctx;
     814           0 :     cb_ctx->mem_ctx = lookup_ctx->dctx;
     815             : 
     816           0 :     tevent_req_set_callback(req, autofs_dp_send_map_req_done, cb_ctx);
     817             : 
     818           0 :     return EAGAIN;
     819             : 
     820             : error:
     821           0 :     ret = autofs_cmd_send_error(lookup_ctx->dctx->cmd_ctx, ret);
     822           0 :     if (ret != EOK) {
     823           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Fatal error, killing connection!\n");
     824           0 :         talloc_free(lookup_ctx->cctx);
     825           0 :         return ret;
     826             :     }
     827           0 :     autofs_cmd_done(lookup_ctx->dctx->cmd_ctx, ret);
     828           0 :     return EOK;
     829             : }
     830             : 
     831           0 : static void autofs_dp_send_map_req_done(struct tevent_req *req)
     832             : {
     833           0 :     struct dp_callback_ctx *cb_ctx =
     834           0 :             tevent_req_callback_data(req, struct dp_callback_ctx);
     835           0 :     struct setautomntent_lookup_ctx *lookup_ctx =
     836           0 :             talloc_get_type(cb_ctx->ptr, struct setautomntent_lookup_ctx);
     837             : 
     838             :     errno_t ret;
     839             :     dbus_uint16_t err_maj;
     840             :     dbus_uint32_t err_min;
     841             :     char *err_msg;
     842             : 
     843           0 :     ret = sss_dp_get_autofs_recv(cb_ctx->mem_ctx, req,
     844             :                                  &err_maj, &err_min,
     845             :                                  &err_msg);
     846           0 :     talloc_free(req);
     847           0 :     if (ret != EOK) {
     848           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Fatal error, killing connection!\n");
     849           0 :         talloc_free(lookup_ctx->cctx);
     850           0 :         return;
     851             :     }
     852             : 
     853           0 :     cb_ctx->callback(err_maj, err_min, err_msg, cb_ctx->ptr);
     854             : }
     855             : 
     856           0 : static void lookup_automntmap_cache_updated(uint16_t err_maj, uint32_t err_min,
     857             :                                             const char *err_msg, void *ptr)
     858             : {
     859           0 :     struct setautomntent_lookup_ctx *lookup_ctx =
     860             :             talloc_get_type(ptr, struct setautomntent_lookup_ctx);
     861           0 :     struct autofs_dom_ctx *dctx = lookup_ctx->dctx;
     862             :     errno_t ret;
     863             : 
     864           0 :     if (err_maj) {
     865           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     866             :               "Unable to get information from Data Provider\n"
     867             :                "Error: %u, %u, %s\n"
     868             :                "Will try to return what we have in cache\n",
     869             :                (unsigned int)err_maj, (unsigned int)err_min, err_msg);
     870             :         /* Loop to the next domain if possible */
     871           0 :         if (dctx->cmd_ctx->check_next && get_next_domain(dctx->domain, false)) {
     872           0 :             dctx->domain = get_next_domain(dctx->domain, false);
     873           0 :             dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
     874             :         }
     875             :     }
     876             : 
     877             :     /* ok the backend returned, search to see if we have updated results */
     878           0 :     ret = lookup_automntmap_step(lookup_ctx);
     879           0 :     if (ret != EOK) {
     880           0 :         if (ret == EAGAIN) {
     881           0 :             return;
     882             :         }
     883             :     }
     884             : 
     885             :     /* We have results to return */
     886           0 :     autofs_setent_notify(lookup_ctx->map, ret);
     887             : }
     888             : 
     889             : static errno_t
     890           0 : setautomntent_recv(struct tevent_req *req)
     891             : {
     892           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     893           0 :     return EOK;
     894             : }
     895             : 
     896             : static errno_t
     897             : getautomntent_process(struct autofs_cmd_ctx *cmdctx,
     898             :                       struct autofs_map_ctx *map,
     899             :                       uint32_t cursor, uint32_t max_entries);
     900             : static void
     901             : getautomntent_implicit_done(struct tevent_req *req);
     902             : static errno_t
     903             : fill_autofs_entry(struct ldb_message *entry, struct sss_packet *packet, size_t *rp);
     904             : 
     905             : 
     906             : static int
     907           0 : sss_autofs_cmd_getautomntent(struct cli_ctx *client)
     908             : {
     909             :     struct autofs_cmd_ctx *cmdctx;
     910             :     struct autofs_map_ctx *map;
     911             :     struct autofs_ctx *actx;
     912             :     uint8_t *body;
     913             :     size_t blen;
     914             :     errno_t ret;
     915             :     uint32_t namelen;
     916           0 :     size_t c = 0;
     917             :     struct tevent_req *req;
     918             : 
     919           0 :     DEBUG(SSSDBG_TRACE_INTERNAL, "sss_autofs_cmd_getautomntent\n");
     920             : 
     921           0 :     cmdctx = talloc_zero(client, struct autofs_cmd_ctx);
     922           0 :     if (!cmdctx) {
     923           0 :         return ENOMEM;
     924             :     }
     925           0 :     cmdctx->cctx = client;
     926             : 
     927           0 :     actx = talloc_get_type(client->rctx->pvt_ctx, struct autofs_ctx);
     928           0 :     if (!actx) {
     929           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Missing autofs context\n");
     930           0 :         return EIO;
     931             :     }
     932             : 
     933             :     /* get autofs map name and index to query */
     934           0 :     sss_packet_get_body(client->creq->in, &body, &blen);
     935             : 
     936           0 :     SAFEALIGN_COPY_UINT32_CHECK(&namelen, body+c, blen, &c);
     937             : 
     938           0 :     if (namelen == 0 || namelen > blen - c) {
     939           0 :         ret = EINVAL;
     940           0 :         goto done;
     941             :     }
     942             : 
     943           0 :     cmdctx->mapname = (char *) body+c;
     944             : 
     945             :     /* if not null-terminated fail */
     946           0 :     if (cmdctx->mapname[namelen] != '\0') {
     947           0 :         ret = EINVAL;
     948           0 :         goto done;
     949             :     }
     950             : 
     951             :     /* If the name isn't valid UTF-8, fail */
     952           0 :     if (!sss_utf8_check((const uint8_t *) cmdctx->mapname, namelen -1)) {
     953           0 :         ret = EINVAL;
     954           0 :         goto done;
     955             :     }
     956             : 
     957           0 :     SAFEALIGN_COPY_UINT32_CHECK(&cmdctx->cursor, body+c+namelen+1, blen, &c);
     958           0 :     SAFEALIGN_COPY_UINT32_CHECK(&cmdctx->max_entries, body+c+namelen+1, blen, &c);
     959             : 
     960           0 :     DEBUG(SSSDBG_TRACE_FUNC,
     961             :           "Requested data of map %s cursor %d max entries %d\n",
     962             :            cmdctx->mapname, cmdctx->cursor, cmdctx->max_entries);
     963             : 
     964           0 :     ret = get_autofs_map(actx, cmdctx->mapname, &map);
     965           0 :     if (ret == ENOENT) {
     966           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Performing implicit setautomntent\n");
     967           0 :         req = setautomntent_send(cmdctx, cmdctx->mapname, cmdctx);
     968           0 :         if (req == NULL) {
     969           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "setautomntent_send failed\n");
     970           0 :             ret = EIO;
     971           0 :             goto done;
     972             :         }
     973             : 
     974           0 :         tevent_req_set_callback(req, getautomntent_implicit_done, cmdctx);
     975           0 :         ret = EOK;
     976           0 :         goto done;
     977           0 :     } else if (ret != EOK) {
     978           0 :         DEBUG(SSSDBG_OP_FAILURE,
     979             :               "An unexpected error occurred: [%d][%s]\n",
     980             :               ret, strerror(ret));
     981           0 :         goto done;
     982             :     }
     983             : 
     984           0 :     if (map->ready == false) {
     985           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Performing implicit setautomntent\n");
     986           0 :         req = setautomntent_send(cmdctx, cmdctx->mapname, cmdctx);
     987           0 :         if (req == NULL) {
     988           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "setautomntent_send failed\n");
     989           0 :             ret = EIO;
     990           0 :             goto done;
     991             :         }
     992             : 
     993           0 :         tevent_req_set_callback(req, getautomntent_implicit_done, cmdctx);
     994           0 :         ret = EOK;
     995           0 :         goto done;
     996           0 :     } else if (map->found == false) {
     997           0 :         DEBUG(SSSDBG_TRACE_FUNC, "negative cache hit\n");
     998           0 :         ret = ENOENT;
     999           0 :         goto done;
    1000             :     }
    1001             : 
    1002           0 :     DEBUG(SSSDBG_TRACE_INTERNAL,
    1003             :           "returning entries for [%s]\n", map->mapname);
    1004             : 
    1005           0 :     ret = getautomntent_process(cmdctx, map, cmdctx->cursor, cmdctx->max_entries);
    1006             : 
    1007             : done:
    1008           0 :     return autofs_cmd_done(cmdctx, ret);
    1009             : }
    1010             : 
    1011             : static void
    1012           0 : getautomntent_implicit_done(struct tevent_req *req)
    1013             : {
    1014             :     errno_t ret;
    1015             :     struct autofs_map_ctx *map;
    1016           0 :     struct autofs_cmd_ctx *cmdctx =
    1017           0 :         tevent_req_callback_data(req, struct autofs_cmd_ctx);
    1018           0 :     struct autofs_ctx *actx =
    1019           0 :         talloc_get_type(cmdctx->cctx->rctx->pvt_ctx, struct autofs_ctx);
    1020             : 
    1021           0 :     ret = setautomntent_recv(req);
    1022           0 :     talloc_zfree(req);
    1023           0 :     if (ret != EOK) {
    1024           0 :         if (ret != ENOENT) {
    1025           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "setautomntent_recv failed\n");
    1026             :         } else {
    1027           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "No such map\n");
    1028             :         }
    1029           0 :         goto done;
    1030             :     }
    1031             : 
    1032           0 :     ret = get_autofs_map(actx, cmdctx->mapname, &map);
    1033           0 :     if (ret != EOK) {
    1034           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
    1035             :               "Cannot get map after setautomntent succeeded?\n");
    1036           0 :         goto done;
    1037             :     }
    1038             : 
    1039           0 :     if (map->ready == false) {
    1040           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
    1041             :               "Map not ready after setautomntent succeeded\n");
    1042           0 :         goto done;
    1043             :     }
    1044             : 
    1045           0 :     ret = getautomntent_process(cmdctx, map,
    1046             :                                 cmdctx->cursor, cmdctx->max_entries);
    1047             : done:
    1048           0 :     autofs_cmd_done(cmdctx, ret);
    1049           0 :     return;
    1050             : }
    1051             : 
    1052             : static errno_t
    1053           0 : getautomntent_process(struct autofs_cmd_ctx *cmdctx,
    1054             :                       struct autofs_map_ctx *map,
    1055             :                       uint32_t cursor, uint32_t max_entries)
    1056             : {
    1057           0 :     struct cli_ctx *client = cmdctx->cctx;
    1058             :     errno_t ret;
    1059             :     struct ldb_message *entry;
    1060             :     size_t rp;
    1061             :     uint32_t i, stop, left, nentries;
    1062             :     uint8_t *body;
    1063             :     size_t blen;
    1064             : 
    1065             :     /* create response packet */
    1066           0 :     ret = sss_packet_new(client->creq, 0,
    1067           0 :                          sss_packet_get_cmd(client->creq->in),
    1068           0 :                          &client->creq->out);
    1069           0 :     if (ret != EOK) {
    1070           0 :         return ret;
    1071             :     }
    1072             : 
    1073           0 :     if (!map->map || !map->entries || !map->entries[0] ||
    1074           0 :         cursor >= map->entry_count) {
    1075           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "No entries found\n");
    1076           0 :         ret = sss_cmd_empty_packet(client->creq->out);
    1077           0 :         if (ret != EOK) {
    1078           0 :             return autofs_cmd_done(cmdctx, ret);
    1079             :         }
    1080           0 :         goto done;
    1081             :     }
    1082             : 
    1083             :     /* allocate memory for number of entries in the packet */
    1084           0 :     ret = sss_packet_grow(client->creq->out, sizeof(uint32_t));
    1085           0 :     if (ret != EOK) {
    1086           0 :         DEBUG(SSSDBG_OP_FAILURE, "Cannot grow packet\n");
    1087           0 :         goto done;
    1088             :     }
    1089             : 
    1090           0 :     rp = sizeof(uint32_t);  /* We'll write the number of entries here */
    1091             : 
    1092           0 :     left = map->entry_count - cursor;
    1093           0 :     stop = max_entries < left ? max_entries : left;
    1094             : 
    1095           0 :     nentries = 0;
    1096           0 :     for (i=0; i < stop; i++) {
    1097           0 :         entry = map->entries[cursor];
    1098           0 :         cursor++;
    1099             : 
    1100           0 :         ret = fill_autofs_entry(entry, client->creq->out, &rp);
    1101           0 :         if (ret != EOK) {
    1102           0 :             DEBUG(SSSDBG_MINOR_FAILURE,
    1103             :                   "Cannot fill entry %d/%d, skipping\n", i, stop);
    1104           0 :             continue;
    1105             :         }
    1106           0 :         nentries++;
    1107             :     }
    1108             : 
    1109             :     /* packet grows in fill_autofs_entry, body pointer may change,
    1110             :      * thus we have to obtain it here */
    1111           0 :     sss_packet_get_body(client->creq->out, &body, &blen);
    1112             : 
    1113           0 :     rp = 0;
    1114           0 :     SAFEALIGN_SET_UINT32(&body[rp], nentries, &rp);
    1115             : 
    1116           0 :     ret = EOK;
    1117             : done:
    1118           0 :     sss_packet_set_error(client->creq->out, ret);
    1119           0 :     sss_cmd_done(client, cmdctx);
    1120             : 
    1121           0 :     return EOK;
    1122             : }
    1123             : 
    1124             : static errno_t
    1125           0 : fill_autofs_entry(struct ldb_message *entry, struct sss_packet *packet, size_t *rp)
    1126             : {
    1127             :     errno_t ret;
    1128             :     const char *key;
    1129             :     size_t keylen;
    1130             :     const char *value;
    1131             :     size_t valuelen;
    1132             :     uint8_t *body;
    1133             :     size_t blen;
    1134             :     size_t len;
    1135             : 
    1136           0 :     key = ldb_msg_find_attr_as_string(entry, SYSDB_AUTOFS_ENTRY_KEY, NULL);
    1137           0 :     value = ldb_msg_find_attr_as_string(entry, SYSDB_AUTOFS_ENTRY_VALUE, NULL);
    1138           0 :     if (!key || !value) {
    1139           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "Incomplete entry\n");
    1140           0 :         return EINVAL;
    1141             :     }
    1142             : 
    1143           0 :     keylen = 1 + strlen(key);
    1144           0 :     valuelen = 1 + strlen(value);
    1145           0 :     len = sizeof(uint32_t) + sizeof(uint32_t) + keylen + sizeof(uint32_t) + valuelen;
    1146             : 
    1147           0 :     ret = sss_packet_grow(packet, len);
    1148           0 :     if (ret != EOK) {
    1149           0 :         DEBUG(SSSDBG_OP_FAILURE, "Cannot grow packet\n");
    1150           0 :         return ret;
    1151             :     }
    1152             : 
    1153           0 :     sss_packet_get_body(packet, &body, &blen);
    1154             : 
    1155           0 :     SAFEALIGN_SET_UINT32(&body[*rp], len, rp);
    1156           0 :     SAFEALIGN_SET_UINT32(&body[*rp], keylen, rp);
    1157             : 
    1158           0 :     if (keylen == 1) {
    1159           0 :         body[*rp] = '\0';
    1160             :     } else {
    1161           0 :         memcpy(&body[*rp], key, keylen);
    1162             :     }
    1163           0 :     *rp += keylen;
    1164             : 
    1165           0 :     SAFEALIGN_SET_UINT32(&body[*rp], valuelen, rp);
    1166           0 :     if (valuelen == 1) {
    1167           0 :         body[*rp] = '\0';
    1168             :     } else {
    1169           0 :         memcpy(&body[*rp], value, valuelen);
    1170             :     }
    1171           0 :     *rp += valuelen;
    1172             : 
    1173           0 :     return EOK;
    1174             : }
    1175             : 
    1176             : static errno_t
    1177             : getautomntbyname_process(struct autofs_cmd_ctx *cmdctx,
    1178             :                          struct autofs_map_ctx *map,
    1179             :                          const char *key);
    1180             : static void
    1181             : getautomntbyname_implicit_done(struct tevent_req *req);
    1182             : 
    1183             : static int
    1184           0 : sss_autofs_cmd_getautomntbyname(struct cli_ctx *client)
    1185             : {
    1186             :     errno_t ret;
    1187             :     struct autofs_cmd_ctx *cmdctx;
    1188             :     struct autofs_map_ctx *map;
    1189             :     struct autofs_ctx *actx;
    1190             :     uint8_t *body;
    1191             :     size_t blen;
    1192             :     uint32_t namelen;
    1193             :     uint32_t keylen;
    1194           0 :     size_t c = 0;
    1195             :     struct tevent_req *req;
    1196             : 
    1197           0 :     DEBUG(SSSDBG_TRACE_INTERNAL, "sss_autofs_cmd_getautomntbyname\n");
    1198             : 
    1199           0 :     cmdctx = talloc_zero(client, struct autofs_cmd_ctx);
    1200           0 :     if (!cmdctx) {
    1201           0 :         return ENOMEM;
    1202             :     }
    1203           0 :     cmdctx->cctx = client;
    1204             : 
    1205           0 :     actx = talloc_get_type(client->rctx->pvt_ctx, struct autofs_ctx);
    1206           0 :     if (!actx) {
    1207           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Missing autofs context\n");
    1208           0 :         return EIO;
    1209             :     }
    1210             : 
    1211             :     /* get autofs map name and index to query */
    1212           0 :     sss_packet_get_body(client->creq->in, &body, &blen);
    1213             : 
    1214             :     /* FIXME - split out a function to get string from <len><str>\0 */
    1215           0 :     SAFEALIGN_COPY_UINT32_CHECK(&namelen, body+c, blen, &c);
    1216             : 
    1217           0 :     if (namelen == 0 || namelen > blen - c) {
    1218           0 :         ret = EINVAL;
    1219           0 :         goto done;
    1220             :     }
    1221             : 
    1222           0 :     cmdctx->mapname = (char *) body+c;
    1223             : 
    1224             :     /* if not null-terminated fail */
    1225           0 :     if (cmdctx->mapname[namelen] != '\0') {
    1226           0 :         ret = EINVAL;
    1227           0 :         goto done;
    1228             :     }
    1229             : 
    1230             :     /* If the name isn't valid UTF-8, fail */
    1231           0 :     if (!sss_utf8_check((const uint8_t *) cmdctx->mapname, namelen -1)) {
    1232           0 :         ret = EINVAL;
    1233           0 :         goto done;
    1234             :     }
    1235             : 
    1236           0 :     c += namelen + 1;
    1237             : 
    1238             :     /* FIXME - split out a function to get string from <len><str>\0 */
    1239           0 :     SAFEALIGN_COPY_UINT32_CHECK(&keylen, body+c, blen, &c);
    1240             : 
    1241           0 :     if (keylen == 0 || keylen > blen - c) {
    1242           0 :         ret = EINVAL;
    1243           0 :         goto done;
    1244             :     }
    1245             : 
    1246           0 :     cmdctx->key = (char *) body+c;
    1247             : 
    1248             :     /* if not null-terminated fail */
    1249           0 :     if (cmdctx->key[keylen] != '\0') {
    1250           0 :         ret = EINVAL;
    1251           0 :         goto done;
    1252             :     }
    1253             : 
    1254             :     /* If the key isn't valid UTF-8, fail */
    1255           0 :     if (!sss_utf8_check((const uint8_t *) cmdctx->key, keylen -1)) {
    1256           0 :         ret = EINVAL;
    1257           0 :         goto done;
    1258             :     }
    1259             : 
    1260           0 :     DEBUG(SSSDBG_TRACE_FUNC,
    1261             :           "Requested data of map %s key %s\n", cmdctx->mapname, cmdctx->key);
    1262             : 
    1263           0 :     ret = get_autofs_map(actx, cmdctx->mapname, &map);
    1264           0 :     if (ret == ENOENT) {
    1265           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Performing implicit setautomntent\n");
    1266           0 :         req = setautomntent_send(cmdctx, cmdctx->mapname, cmdctx);
    1267           0 :         if (req == NULL) {
    1268           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "setautomntent_send failed\n");
    1269           0 :             ret = EIO;
    1270           0 :             goto done;
    1271             :         }
    1272             : 
    1273           0 :         tevent_req_set_callback(req, getautomntbyname_implicit_done, cmdctx);
    1274           0 :         ret = EOK;
    1275           0 :         goto done;
    1276           0 :     } else if (ret != EOK) {
    1277           0 :         DEBUG(SSSDBG_OP_FAILURE,
    1278             :               "An unexpected error occurred: [%d][%s]\n",
    1279             :               ret, strerror(ret));
    1280           0 :         goto done;
    1281             :     }
    1282             : 
    1283           0 :     if (map->ready == false) {
    1284           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Performing implicit setautomntent\n");
    1285           0 :         req = setautomntent_send(cmdctx, cmdctx->mapname, cmdctx);
    1286           0 :         if (req == NULL) {
    1287           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "setautomntent_send failed\n");
    1288           0 :             ret = EIO;
    1289           0 :             goto done;
    1290             :         }
    1291             : 
    1292           0 :         tevent_req_set_callback(req, getautomntbyname_implicit_done, cmdctx);
    1293           0 :         ret = EOK;
    1294           0 :         goto done;
    1295           0 :     } else if (map->found == false) {
    1296           0 :         DEBUG(SSSDBG_TRACE_FUNC, "negative cache hit\n");
    1297           0 :         ret = ENOENT;
    1298           0 :         goto done;
    1299             :     }
    1300             : 
    1301           0 :     DEBUG(SSSDBG_TRACE_INTERNAL,
    1302             :           "Looking up value for [%s] in [%s]\n", cmdctx->key, map->mapname);
    1303             : 
    1304           0 :     ret = getautomntbyname_process(cmdctx, map, cmdctx->key);
    1305             : 
    1306             : done:
    1307           0 :     return autofs_cmd_done(cmdctx, ret);
    1308             : }
    1309             : 
    1310             : static void
    1311           0 : getautomntbyname_implicit_done(struct tevent_req *req)
    1312             : {
    1313             :     errno_t ret;
    1314             :     struct autofs_map_ctx *map;
    1315           0 :     struct autofs_cmd_ctx *cmdctx =
    1316           0 :         tevent_req_callback_data(req, struct autofs_cmd_ctx);
    1317           0 :     struct autofs_ctx *actx =
    1318           0 :         talloc_get_type(cmdctx->cctx->rctx->pvt_ctx, struct autofs_ctx);
    1319             : 
    1320           0 :     ret = setautomntent_recv(req);
    1321           0 :     talloc_zfree(req);
    1322           0 :     if (ret != EOK) {
    1323           0 :         if (ret != ENOENT) {
    1324           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "setautomntent_recv failed\n");
    1325             :         } else {
    1326           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "No such map\n");
    1327             :         }
    1328           0 :         goto done;
    1329             :     }
    1330             : 
    1331           0 :     ret = get_autofs_map(actx, cmdctx->mapname, &map);
    1332           0 :     if (ret != EOK) {
    1333           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
    1334             :               "Cannot get map after setautomntent succeeded?\n");
    1335           0 :         goto done;
    1336             :     }
    1337             : 
    1338           0 :     if (map->ready == false) {
    1339           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
    1340             :               "Map not ready after setautomntent succeeded\n");
    1341           0 :         goto done;
    1342             :     }
    1343             : 
    1344           0 :     ret = getautomntbyname_process(cmdctx, map, cmdctx->key);
    1345             : done:
    1346           0 :     autofs_cmd_done(cmdctx, ret);
    1347           0 :     return;
    1348             : }
    1349             : 
    1350             : static errno_t
    1351           0 : getautomntbyname_process(struct autofs_cmd_ctx *cmdctx,
    1352             :                          struct autofs_map_ctx *map,
    1353             :                          const char *key)
    1354             : {
    1355           0 :     struct cli_ctx *client = cmdctx->cctx;
    1356             :     errno_t ret;
    1357             :     size_t i;
    1358             :     const char *k;
    1359             :     const char *value;
    1360             :     size_t valuelen;
    1361             :     size_t len;
    1362             :     uint8_t *body;
    1363             :     size_t blen, rp;
    1364             : 
    1365             :     /* create response packet */
    1366           0 :     ret = sss_packet_new(client->creq, 0,
    1367           0 :                          sss_packet_get_cmd(client->creq->in),
    1368           0 :                          &client->creq->out);
    1369           0 :     if (ret != EOK) {
    1370           0 :         return ret;
    1371             :     }
    1372             : 
    1373           0 :     if (!map->map || !map->entries || !map->entries[0]) {
    1374           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "No entries found\n");
    1375           0 :         ret = sss_cmd_empty_packet(client->creq->out);
    1376           0 :         if (ret != EOK) {
    1377           0 :             return autofs_cmd_done(cmdctx, ret);
    1378             :         }
    1379           0 :         goto done;
    1380             :     }
    1381             : 
    1382           0 :     for (i=0; i < map->entry_count; i++) {
    1383           0 :         k = ldb_msg_find_attr_as_string(map->entries[i],
    1384             :                                         SYSDB_AUTOFS_ENTRY_KEY, NULL);
    1385           0 :         if (!k) {
    1386           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "Skipping incomplete entry\n");
    1387           0 :             continue;
    1388             :         }
    1389             : 
    1390           0 :         if (strcmp(k, key) == 0) {
    1391           0 :             DEBUG(SSSDBG_TRACE_INTERNAL, "Found key [%s]\n", key);
    1392           0 :             break;
    1393             :         }
    1394             :     }
    1395             : 
    1396           0 :     if (i >= map->entry_count) {
    1397           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "No key named [%s] found\n", key);
    1398           0 :         ret = sss_cmd_empty_packet(client->creq->out);
    1399           0 :         if (ret != EOK) {
    1400           0 :             return autofs_cmd_done(cmdctx, ret);
    1401             :         }
    1402           0 :         goto done;
    1403             :     }
    1404             : 
    1405           0 :     value = ldb_msg_find_attr_as_string(map->entries[i],
    1406             :                                         SYSDB_AUTOFS_ENTRY_VALUE, NULL);
    1407             : 
    1408           0 :     valuelen = 1 + strlen(value);
    1409           0 :     len = sizeof(uint32_t) + sizeof(uint32_t) + valuelen;
    1410             : 
    1411           0 :     ret = sss_packet_grow(client->creq->out, len);
    1412           0 :     if (ret != EOK) {
    1413           0 :         goto done;
    1414             :     }
    1415             : 
    1416           0 :     sss_packet_get_body(client->creq->out, &body, &blen);
    1417             : 
    1418           0 :     rp = 0;
    1419           0 :     SAFEALIGN_SET_UINT32(&body[rp], len, &rp);
    1420             : 
    1421           0 :     SAFEALIGN_SET_UINT32(&body[rp], valuelen, &rp);
    1422           0 :     if (valuelen == 1) {
    1423           0 :         body[rp] = '\0';
    1424             :     } else {
    1425           0 :         memcpy(&body[rp], value, valuelen);
    1426             :     }
    1427           0 :     rp += valuelen;
    1428             : 
    1429           0 :     ret = EOK;
    1430             : done:
    1431           0 :     sss_packet_set_error(client->creq->out, ret);
    1432           0 :     sss_cmd_done(client, cmdctx);
    1433             : 
    1434           0 :     return EOK;
    1435             : }
    1436             : 
    1437             : static int
    1438           0 : sss_autofs_cmd_endautomntent(struct cli_ctx *client)
    1439             : {
    1440             :     errno_t ret;
    1441             : 
    1442           0 :     DEBUG(SSSDBG_TRACE_FUNC, "endautomntent called\n");
    1443             : 
    1444             :     /* create response packet */
    1445           0 :     ret = sss_packet_new(client->creq, 0,
    1446           0 :                          sss_packet_get_cmd(client->creq->in),
    1447           0 :                          &client->creq->out);
    1448             : 
    1449           0 :     if (ret != EOK) {
    1450           0 :         return ret;
    1451             :     }
    1452             : 
    1453           0 :     sss_cmd_done(client, NULL);
    1454           0 :     return EOK;
    1455             : }
    1456             : 
    1457           0 : struct cli_protocol_version *register_cli_protocol_version(void)
    1458             : {
    1459             :     static struct cli_protocol_version autofs_cli_protocol_version[] = {
    1460             :         { SSS_AUTOFS_PROTO_VERSION, NULL, NULL }
    1461             :     };
    1462             : 
    1463           0 :     return autofs_cli_protocol_version;
    1464             : }
    1465             : 
    1466           0 : struct sss_cmd_table *get_autofs_cmds(void)
    1467             : {
    1468             :     static struct sss_cmd_table autofs_cmds[] = {
    1469             :         { SSS_GET_VERSION, sss_cmd_get_version },
    1470             :         { SSS_AUTOFS_SETAUTOMNTENT, sss_autofs_cmd_setautomntent },
    1471             :         { SSS_AUTOFS_GETAUTOMNTENT, sss_autofs_cmd_getautomntent },
    1472             :         { SSS_AUTOFS_GETAUTOMNTBYNAME, sss_autofs_cmd_getautomntbyname },
    1473             :         { SSS_AUTOFS_ENDAUTOMNTENT, sss_autofs_cmd_endautomntent },
    1474             :         { SSS_CLI_NULL, NULL}
    1475             :     };
    1476             : 
    1477           0 :     return autofs_cmds;
    1478             : }

Generated by: LCOV version 1.10