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

          Line data    Source code
       1             : /*
       2             :     Authors:
       3             :         Pavel Březina <pbrezina@redhat.com>
       4             : 
       5             :     Copyright (C) 2011 Red Hat
       6             : 
       7             :     This program is free software; you can redistribute it and/or modify
       8             :     it under the terms of the GNU General Public License as published by
       9             :     the Free Software Foundation; either version 3 of the License, or
      10             :     (at your option) any later version.
      11             : 
      12             :     This program is distributed in the hope that it will be useful,
      13             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :     GNU General Public License for more details.
      16             : 
      17             :     You should have received a copy of the GNU General Public License
      18             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include <stdint.h>
      22             : #include <errno.h>
      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/sudo/sudosrv_private.h"
      29             : #include "db/sysdb_sudo.h"
      30             : #include "sss_client/sss_cli.h"
      31             : #include "responder/common/negcache.h"
      32             : 
      33           0 : static errno_t sudosrv_cmd_send_reply(struct sudo_cmd_ctx *cmd_ctx,
      34             :                                       uint8_t *response_body,
      35             :                                       size_t response_len)
      36             : {
      37             :     errno_t ret;
      38           0 :     uint8_t *packet_body = NULL;
      39           0 :     size_t packet_len = 0;
      40           0 :     struct cli_ctx *cli_ctx = cmd_ctx->cli_ctx;
      41             :     TALLOC_CTX *tmp_ctx;
      42             : 
      43           0 :     tmp_ctx = talloc_new(NULL);
      44           0 :     if (!tmp_ctx) return ENOMEM;
      45             : 
      46           0 :     ret = sss_packet_new(cli_ctx->creq, 0,
      47           0 :                          sss_packet_get_cmd(cli_ctx->creq->in),
      48           0 :                          &cli_ctx->creq->out);
      49           0 :     if (ret != EOK) {
      50           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
      51             :               "Unable to create a new packet [%d]; %s\n",
      52             :                ret, strerror(ret));
      53           0 :         goto done;
      54             :     }
      55             : 
      56           0 :     ret = sss_packet_grow(cli_ctx->creq->out, response_len);
      57           0 :     if (ret != EOK) {
      58           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
      59             :               "Unable to create response: %s\n", strerror(ret));
      60           0 :         goto done;
      61             :     }
      62           0 :     sss_packet_get_body(cli_ctx->creq->out, &packet_body, &packet_len);
      63           0 :     memcpy(packet_body, response_body, response_len);
      64             : 
      65           0 :     sss_packet_set_error(cli_ctx->creq->out, EOK);
      66           0 :     sss_cmd_done(cmd_ctx->cli_ctx, cmd_ctx);
      67             : 
      68           0 :     ret = EOK;
      69             : 
      70             : done:
      71           0 :     talloc_zfree(tmp_ctx);
      72           0 :     return ret;
      73             : }
      74             : 
      75           0 : static errno_t sudosrv_cmd_send_error(TALLOC_CTX *mem_ctx,
      76             :                                       struct sudo_cmd_ctx *cmd_ctx,
      77             :                                       uint32_t error)
      78             : {
      79           0 :     uint8_t *response_body = NULL;
      80           0 :     size_t response_len = 0;
      81           0 :     int ret = EOK;
      82             : 
      83           0 :     if (error == EOK) {
      84           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "Everything is fine but we are "
      85             :               "returning error?\n");
      86           0 :         return EFAULT;
      87             :     }
      88             : 
      89           0 :     ret = sudosrv_build_response(mem_ctx, error, 0, NULL,
      90             :                                  &response_body, &response_len);
      91           0 :     if (ret != EOK) {
      92           0 :         return ret;
      93             :     }
      94             : 
      95           0 :     return sudosrv_cmd_send_reply(cmd_ctx, response_body, response_len);
      96             : }
      97             : 
      98           0 : errno_t sudosrv_cmd_done(struct sudo_cmd_ctx *cmd_ctx, int ret)
      99             : {
     100           0 :     uint8_t *response_body = NULL;
     101           0 :     size_t response_len = 0;
     102           0 :     uint32_t num_rules = cmd_ctx->num_rules;
     103           0 :     struct sysdb_attrs **rules = cmd_ctx->rules;
     104             : 
     105           0 :     switch (ret) {
     106             :     case EOK:
     107             :         /*
     108             :          * Parent of cmd_ctx->rules is in-memory cache, we must not talloc_free it!
     109             :          */
     110           0 :         if (cmd_ctx->sudo_ctx->timed) {
     111             :             /* filter rules by time */
     112             : 
     113           0 :             DEBUG(SSSDBG_TRACE_FUNC, "Applying time restrictions on"
     114             :                                       "%u rules\n", cmd_ctx->num_rules);
     115             : 
     116           0 :             ret = sysdb_sudo_filter_rules_by_time(cmd_ctx, cmd_ctx->num_rules,
     117             :                                                   cmd_ctx->rules, 0,
     118             :                                                   &num_rules, &rules);
     119           0 :             if (ret != EOK) {
     120           0 :                 return EFAULT;
     121             :             }
     122             : 
     123           0 :             DEBUG(SSSDBG_TRACE_FUNC, "Got %u rules after time filter\n",
     124             :                                       num_rules);
     125             :         }
     126             : 
     127             :         /* send result */
     128           0 :         ret = sudosrv_build_response(cmd_ctx, SSS_SUDO_ERROR_OK,
     129             :                                      num_rules, rules,
     130             :                                      &response_body, &response_len);
     131           0 :         if (ret != EOK) {
     132           0 :             return EFAULT;
     133             :         }
     134             : 
     135           0 :         ret = sudosrv_cmd_send_reply(cmd_ctx, response_body, response_len);
     136           0 :         break;
     137             : 
     138             :     case EAGAIN:
     139             :         /* async processing, just return here */
     140           0 :         return EOK;
     141             : 
     142             :     case EFAULT:
     143             :         /* very bad error */
     144           0 :         return EFAULT;
     145             : 
     146             : 
     147             :     /* case ENOENT:
     148             :      * - means user not found
     149             :      * - send error ENOENT
     150             :      */
     151             : 
     152             :     default:
     153             :         /* send error */
     154           0 :         ret = sudosrv_cmd_send_error(cmd_ctx, cmd_ctx, ret);
     155           0 :         break;
     156             :     }
     157             : 
     158           0 :     if (ret != EOK) {
     159           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Fatal error, killing connection!\n");
     160           0 :         talloc_free(cmd_ctx->cli_ctx);
     161           0 :         return EFAULT;
     162             :     }
     163             : 
     164           0 :     return EOK;
     165             : }
     166             : 
     167             : static void sudosrv_cmd_parse_query_done(struct tevent_req *req);
     168             : 
     169           0 : static int sudosrv_cmd(enum sss_sudo_type type, struct cli_ctx *cli_ctx)
     170             : {
     171           0 :     struct tevent_req *req = NULL;
     172           0 :     struct sudo_cmd_ctx *cmd_ctx = NULL;
     173           0 :     uint8_t *query_body = NULL;
     174           0 :     size_t query_len = 0;
     175           0 :     uint32_t protocol = cli_ctx->cli_protocol_version->version;
     176             :     errno_t ret;
     177             : 
     178             :     /* create cmd_ctx */
     179             : 
     180           0 :     cmd_ctx = talloc_zero(cli_ctx, struct sudo_cmd_ctx);
     181           0 :     if (cmd_ctx == NULL) {
     182             :         /* kill the connection here as we have no context for reply */
     183           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory?\n");
     184           0 :         return ENOMEM;
     185             :     }
     186             : 
     187           0 :     cmd_ctx->domain = NULL;
     188           0 :     cmd_ctx->cli_ctx = cli_ctx;
     189           0 :     cmd_ctx->type = type;
     190           0 :     cmd_ctx->sudo_ctx = talloc_get_type(cli_ctx->rctx->pvt_ctx, struct sudo_ctx);
     191           0 :     if (cmd_ctx->sudo_ctx == NULL) {
     192           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "sudo_ctx not set, killing connection!\n");
     193           0 :         return EFAULT;
     194             :     }
     195             : 
     196             :     /* if protocol is invalid return */
     197           0 :     switch (protocol) {
     198             :     case 0:
     199           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Protocol [%d] is not secure. "
     200             :               "SSSD does not allow to use this protocol.\n", protocol);
     201           0 :         ret = EFAULT;
     202           0 :         goto done;
     203             :         break;
     204             :     case SSS_SUDO_PROTOCOL_VERSION:
     205           0 :         DEBUG(SSSDBG_TRACE_INTERNAL, "Using protocol version [%d]\n",
     206             :                                       protocol);
     207           0 :         break;
     208             :     default:
     209           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Invalid protocol version [%d]!\n",
     210             :                                      protocol);
     211           0 :         ret = EFAULT;
     212           0 :         goto done;
     213             :     }
     214             : 
     215             :     /* parse query */
     216             : 
     217           0 :     sss_packet_get_body(cli_ctx->creq->in, &query_body, &query_len);
     218           0 :     if (query_len <= 0 || query_body == NULL) {
     219           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Query is empty\n");
     220           0 :         ret = EINVAL;
     221           0 :         goto done;
     222             :     }
     223             : 
     224           0 :     req = sudosrv_parse_query_send(cmd_ctx, cli_ctx->rctx,
     225             :                                    query_body, query_len);
     226           0 :     if (req == NULL) {
     227           0 :         ret = ENOMEM;
     228           0 :         goto done;
     229             :     }
     230             : 
     231           0 :     tevent_req_set_callback(req, sudosrv_cmd_parse_query_done, cmd_ctx);
     232             : 
     233           0 :     ret = EAGAIN;
     234             : 
     235             : done:
     236           0 :     return sudosrv_cmd_done(cmd_ctx, ret);
     237             : }
     238             : 
     239           0 : static void sudosrv_cmd_parse_query_done(struct tevent_req *req)
     240             : {
     241           0 :     struct sudo_cmd_ctx *cmd_ctx = NULL;
     242           0 :     struct sudo_dom_ctx *dom_ctx = NULL;
     243           0 :     struct sudo_ctx *sudo_ctx = NULL;
     244             :     errno_t ret;
     245             : 
     246           0 :     cmd_ctx = tevent_req_callback_data(req, struct sudo_cmd_ctx);
     247             : 
     248           0 :     ret = sudosrv_parse_query_recv(cmd_ctx, req, &cmd_ctx->uid,
     249             :                                    &cmd_ctx->username, &cmd_ctx->domain);
     250           0 :     talloc_zfree(req);
     251           0 :     if (ret != EOK) {
     252           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Invalid query [%d]: %s\n",
     253             :                                     ret, strerror(ret));
     254           0 :         goto done;
     255             :     }
     256             : 
     257           0 :     cmd_ctx->check_next = cmd_ctx->domain == NULL;
     258             : 
     259           0 :     switch (cmd_ctx->type) {
     260             :         case SSS_SUDO_DEFAULTS:
     261           0 :             DEBUG(SSSDBG_FUNC_DATA, "Requesting default options "
     262             :                   "for [%s] from [%s]\n", cmd_ctx->username,
     263             :                   cmd_ctx->domain ? cmd_ctx->domain->name : "<ALL>");
     264           0 :             break;
     265             :         case SSS_SUDO_USER:
     266           0 :             DEBUG(SSSDBG_FUNC_DATA, "Requesting rules "
     267             :                   "for [%s] from [%s]\n", cmd_ctx->username,
     268             :                   cmd_ctx->domain ? cmd_ctx->domain->name : "<ALL>");
     269           0 :             break;
     270             :     }
     271             : 
     272             :     /* create domain ctx */
     273             : 
     274           0 :     dom_ctx = talloc_zero(cmd_ctx, struct sudo_dom_ctx);
     275           0 :     if (dom_ctx == NULL) {
     276           0 :         ret = ENOMEM;
     277           0 :         goto done;
     278             :     }
     279           0 :     dom_ctx->cmd_ctx = cmd_ctx;
     280           0 :     dom_ctx->domain = cmd_ctx->domain != NULL ? cmd_ctx->domain
     281           0 :                                               : cmd_ctx->cli_ctx->rctx->domains;
     282             : 
     283           0 :     sudo_ctx = talloc_get_type(cmd_ctx->cli_ctx->rctx->pvt_ctx, struct sudo_ctx);
     284           0 :     ret = sss_ncache_check_user(sudo_ctx->ncache, sudo_ctx->neg_timeout,
     285           0 :                                 dom_ctx->domain, cmd_ctx->username);
     286           0 :     if (ret == EEXIST) {
     287           0 :         DEBUG(SSSDBG_TRACE_FUNC, "User [%s@%s] filtered out (ncache)\n",
     288             :               cmd_ctx->username, dom_ctx->domain->name);
     289           0 :         ret = ENOENT;
     290           0 :         goto done;
     291             :     }
     292             : 
     293           0 :     ret = sudosrv_get_sudorules(dom_ctx);
     294             : 
     295             : done:
     296           0 :     sudosrv_cmd_done(cmd_ctx, ret);
     297           0 : }
     298             : 
     299           0 : static int sudosrv_cmd_get_sudorules(struct cli_ctx *cli_ctx)
     300             : {
     301           0 :     return sudosrv_cmd(SSS_SUDO_USER, cli_ctx);
     302             : }
     303             : 
     304           0 : static int sudosrv_cmd_get_defaults(struct cli_ctx *cli_ctx)
     305             : {
     306           0 :     return sudosrv_cmd(SSS_SUDO_DEFAULTS, cli_ctx);
     307             : }
     308             : 
     309           0 : struct cli_protocol_version *register_cli_protocol_version(void)
     310             : {
     311             :     static struct cli_protocol_version sudo_cli_protocol_version[] = {
     312             :                 {1, "2012-05-14", "require uid and domain"},
     313             :         {0, NULL, NULL}
     314             :     };
     315             : 
     316           0 :     return sudo_cli_protocol_version;
     317             : }
     318             : 
     319           0 : struct sss_cmd_table *get_sudo_cmds(void) {
     320             :     static struct sss_cmd_table sudo_cmds[] = {
     321             :         {SSS_GET_VERSION, sss_cmd_get_version},
     322             :         {SSS_SUDO_GET_SUDORULES, sudosrv_cmd_get_sudorules},
     323             :         {SSS_SUDO_GET_DEFAULTS, sudosrv_cmd_get_defaults},
     324             :         {SSS_CLI_NULL, NULL}
     325             :     };
     326             : 
     327           0 :     return sudo_cmds;
     328             : }

Generated by: LCOV version 1.10