LCOV - code coverage report
Current view: top level - providers/proxy - proxy_services.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 165 0.0 %
Date: 2016-06-29 Functions: 0 4 0.0 %

          Line data    Source code
       1             : /*
       2             :     SSSD
       3             : 
       4             :     Authors:
       5             :         Stephen Gallagher <sgallagh@redhat.com>
       6             : 
       7             :     Copyright (C) 2012 Red Hat
       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 "providers/proxy/proxy.h"
      24             : #include "util/util.h"
      25             : #include "util/strtonum.h"
      26             : #include "db/sysdb_services.h"
      27             : 
      28             : #define BUFLEN  1024
      29             : 
      30             : errno_t
      31           0 : proxy_save_service(struct sss_domain_info *domain,
      32             :                    struct servent *svc,
      33             :                    bool lowercase,
      34             :                    uint64_t cache_timeout)
      35             : {
      36             :     errno_t ret;
      37             :     char *cased_name;
      38             :     const char **protocols;
      39             :     const char **cased_aliases;
      40             :     TALLOC_CTX *tmp_ctx;
      41           0 :     char *lc_alias = NULL;
      42           0 :     time_t now = time(NULL);
      43             : 
      44           0 :     tmp_ctx = talloc_new(NULL);
      45           0 :     if (!tmp_ctx) return ENOMEM;
      46             : 
      47           0 :     cased_name = sss_get_cased_name(tmp_ctx, svc->s_name,
      48           0 :                                     domain->case_preserve);
      49           0 :     if (!cased_name) {
      50           0 :         ret = ENOMEM;
      51           0 :         goto done;
      52             :     }
      53             : 
      54           0 :     protocols = talloc_array(tmp_ctx, const char *, 2);
      55           0 :     if (!protocols) {
      56           0 :         ret = ENOMEM;
      57           0 :         goto done;
      58             :     }
      59             : 
      60           0 :     protocols[0] = sss_get_cased_name(protocols, svc->s_proto,
      61           0 :                                       !lowercase);
      62           0 :     if (!protocols[0]) {
      63           0 :         ret = ENOMEM;
      64           0 :         goto done;
      65             :     }
      66           0 :     protocols[1] = NULL;
      67             : 
      68             :     /* Count the aliases */
      69           0 :     ret = sss_get_cased_name_list(tmp_ctx,
      70           0 :                                   (const char * const *) svc->s_aliases,
      71           0 :                                   !lowercase, &cased_aliases);
      72           0 :     if (ret != EOK) {
      73           0 :         goto done;
      74             :     }
      75             : 
      76           0 :     if (domain->case_preserve) {
      77             :         /* Add lowercased alias to allow case-insensitive lookup */
      78           0 :         lc_alias = sss_tc_utf8_str_tolower(tmp_ctx, svc->s_name);
      79           0 :         if (lc_alias == NULL) {
      80           0 :             DEBUG(SSSDBG_OP_FAILURE, "Cannot convert name to lowercase.\n");
      81           0 :             ret = ENOMEM;
      82           0 :             goto done;
      83             :         }
      84             : 
      85           0 :         ret = add_string_to_list(tmp_ctx, lc_alias,
      86             :                                  discard_const_p(char **, &cased_aliases));
      87           0 :         if (ret != EOK) {
      88           0 :             DEBUG(SSSDBG_OP_FAILURE,
      89             :                   "Failed to add lowercased name alias.\n");
      90           0 :             goto done;
      91             :         }
      92             :     }
      93             : 
      94           0 :     ret = sysdb_store_service(domain,
      95             :                               cased_name,
      96           0 :                               ntohs(svc->s_port),
      97             :                               cased_aliases,
      98             :                               protocols,
      99             :                               NULL, NULL,
     100             :                               cache_timeout,
     101             :                               now);
     102             : done:
     103           0 :     talloc_free(tmp_ctx);
     104           0 :     return ret;
     105             : }
     106             : 
     107             : errno_t
     108           0 : get_serv_byname(struct proxy_id_ctx *ctx,
     109             :                 struct sss_domain_info *dom,
     110             :                 const char *name,
     111             :                 const char *protocol)
     112             : {
     113             :     errno_t ret;
     114             :     enum nss_status status;
     115             :     struct servent *result;
     116             :     TALLOC_CTX *tmp_ctx;
     117             :     char buffer[BUFLEN];
     118             : 
     119           0 :     tmp_ctx = talloc_new(NULL);
     120           0 :     if (!tmp_ctx) return ENOMEM;
     121             : 
     122           0 :     result = talloc_zero(tmp_ctx, struct servent);
     123           0 :     if (!result) {
     124           0 :         ret = ENOMEM;
     125           0 :         goto done;
     126             :     }
     127             : 
     128           0 :     status = ctx->ops.getservbyname_r(name, protocol, result,
     129             :                                       buffer, BUFLEN, &ret);
     130           0 :     if (status != NSS_STATUS_SUCCESS && status != NSS_STATUS_NOTFOUND) {
     131           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     132             :               "getservbyname_r failed for service [%s].\n", name);
     133           0 :         goto done;
     134             :     }
     135             : 
     136           0 :     if (status == NSS_STATUS_NOTFOUND) {
     137             :         /* Make sure we remove it from the cache */
     138           0 :         ret = sysdb_svc_delete(dom, name, 0, protocol);
     139             :     } else {
     140             : 
     141             :         /* Results found. Save them into the cache */
     142           0 :         ret = proxy_save_service(dom, result,
     143           0 :                                  !dom->case_sensitive,
     144           0 :                                  dom->service_timeout);
     145             :     }
     146             : 
     147             : done:
     148           0 :     talloc_free(tmp_ctx);
     149           0 :     return ret;
     150             : }
     151             : 
     152             : errno_t
     153           0 : get_serv_byport(struct proxy_id_ctx *ctx,
     154             :                 struct sss_domain_info *dom,
     155             :                 const char *be_filter,
     156             :                 const char *protocol)
     157             : {
     158             :     errno_t ret;
     159             :     enum nss_status status;
     160             :     struct servent *result;
     161             :     TALLOC_CTX *tmp_ctx;
     162             :     uint16_t port;
     163             :     char buffer[BUFLEN];
     164             : 
     165           0 :     tmp_ctx = talloc_new(NULL);
     166           0 :     if (!tmp_ctx) return ENOMEM;
     167             : 
     168           0 :     result = talloc_zero(tmp_ctx, struct servent);
     169           0 :     if (!result) {
     170           0 :         ret = ENOMEM;
     171           0 :         goto done;
     172             :     }
     173             : 
     174           0 :     errno = 0;
     175           0 :     port = htons(strtouint16(be_filter, NULL, 0));
     176           0 :     if (errno) {
     177           0 :         ret = errno;
     178           0 :         goto done;
     179             :     }
     180             : 
     181           0 :     status = ctx->ops.getservbyport_r(port, protocol, result,
     182             :                                       buffer, BUFLEN, &ret);
     183           0 :     if (status != NSS_STATUS_SUCCESS && status != NSS_STATUS_NOTFOUND) {
     184           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     185             :               "getservbyport_r failed for service [%s].\n", be_filter);
     186           0 :         goto done;
     187             :     }
     188             : 
     189           0 :     if (status == NSS_STATUS_NOTFOUND) {
     190             :         /* Make sure we remove it from the cache */
     191           0 :         ret = sysdb_svc_delete(dom, NULL, port, protocol);
     192             :     } else {
     193             :         /* Results found. Save them into the cache */
     194           0 :         ret = proxy_save_service(dom, result,
     195           0 :                                  !dom->case_sensitive,
     196           0 :                                  dom->service_timeout);
     197             :     }
     198             : 
     199             : done:
     200           0 :     talloc_free(tmp_ctx);
     201           0 :     return ret;
     202             : }
     203             : 
     204             : errno_t
     205           0 : enum_services(struct proxy_id_ctx *ctx,
     206             :               struct sysdb_ctx *sysdb,
     207             :               struct sss_domain_info *dom)
     208             : {
     209             :     TALLOC_CTX *tmpctx;
     210           0 :     bool in_transaction = false;
     211             :     struct servent *svc;
     212             :     enum nss_status status;
     213             :     size_t buflen;
     214             :     char *buffer;
     215             :     char *newbuf;
     216             :     errno_t ret, sret;
     217           0 :     time_t now = time(NULL);
     218             :     const char **protocols;
     219             :     const char **cased_aliases;
     220             :     bool again;
     221             : 
     222           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Enumerating services\n");
     223             : 
     224           0 :     tmpctx = talloc_new(NULL);
     225           0 :     if (!tmpctx) {
     226           0 :         return ENOMEM;
     227             :     }
     228             : 
     229           0 :     svc = talloc(tmpctx, struct servent);
     230           0 :     if (!svc) {
     231           0 :         ret = ENOMEM;
     232           0 :         goto done;
     233             :     }
     234             : 
     235           0 :     buflen = DEFAULT_BUFSIZE;
     236           0 :     buffer = talloc_size(tmpctx, buflen);
     237           0 :     if (!buffer) {
     238           0 :         ret = ENOMEM;
     239           0 :         goto done;
     240             :     }
     241             : 
     242           0 :     protocols = talloc_zero_array(tmpctx, const char *, 2);
     243           0 :     if (protocols == NULL) {
     244           0 :         ret = ENOMEM;
     245           0 :         goto done;
     246             :     }
     247             : 
     248           0 :     ret = sysdb_transaction_start(sysdb);
     249           0 :     if (ret) {
     250           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n");
     251           0 :         goto done;
     252             :     }
     253           0 :     in_transaction = true;
     254             : 
     255           0 :     status = ctx->ops.setservent();
     256           0 :     if (status != NSS_STATUS_SUCCESS) {
     257           0 :         ret = EIO;
     258           0 :         goto done;
     259             :     }
     260             : 
     261             :     do {
     262           0 :         again = false;
     263             : 
     264             :         /* always zero out the svc structure */
     265           0 :         memset(svc, 0, sizeof(struct servent));
     266             : 
     267             :         /* get entry */
     268           0 :         status = ctx->ops.getservent_r(svc, buffer, buflen, &ret);
     269             : 
     270           0 :         switch (status) {
     271             :             case NSS_STATUS_TRYAGAIN:
     272             :                 /* buffer too small ? */
     273           0 :                 if (buflen < MAX_BUF_SIZE) {
     274           0 :                     buflen *= 2;
     275             :                 }
     276           0 :                 if (buflen > MAX_BUF_SIZE) {
     277           0 :                     buflen = MAX_BUF_SIZE;
     278             :                 }
     279           0 :                 newbuf = talloc_realloc_size(tmpctx, buffer, buflen);
     280           0 :                 if (!newbuf) {
     281           0 :                     ret = ENOMEM;
     282           0 :                     goto done;
     283             :                 }
     284           0 :                 buffer = newbuf;
     285           0 :                 again = true;
     286           0 :                 break;
     287             : 
     288             :             case NSS_STATUS_NOTFOUND:
     289             : 
     290             :                 /* we are done here */
     291           0 :                 DEBUG(SSSDBG_TRACE_FUNC, "Enumeration completed.\n");
     292             : 
     293           0 :                 ret = sysdb_transaction_commit(sysdb);
     294           0 :                 if (ret != EOK) {
     295           0 :                     DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction\n");
     296           0 :                     goto done;
     297             :                 }
     298             : 
     299           0 :                 in_transaction = false;
     300           0 :                 break;
     301             : 
     302             :             case NSS_STATUS_SUCCESS:
     303             : 
     304           0 :                 DEBUG(SSSDBG_TRACE_INTERNAL,
     305             :                         "Service found (%s, %d/%s)\n",
     306             :                          svc->s_name, svc->s_port, svc->s_proto);
     307             : 
     308           0 :                 protocols[0] = sss_get_cased_name(protocols, svc->s_proto,
     309           0 :                         dom->case_sensitive);
     310           0 :                 if (!protocols[0]) {
     311           0 :                     ret = ENOMEM;
     312           0 :                     goto done;
     313             :                 }
     314           0 :                 protocols[1] = NULL;
     315             : 
     316           0 :                 ret = sss_get_cased_name_list(tmpctx,
     317           0 :                         (const char * const *) svc->s_aliases,
     318           0 :                         dom->case_sensitive, &cased_aliases);
     319           0 :                 if (ret != EOK) {
     320             :                     /* Do not fail completely on errors.
     321             :                      * Just report the failure to save and go on */
     322           0 :                     DEBUG(SSSDBG_OP_FAILURE,
     323             :                             "Failed to store service [%s]. Ignoring.\n",
     324             :                              strerror(ret));
     325           0 :                     again = true;
     326           0 :                     break;
     327             :                 }
     328             : 
     329           0 :                 ret = sysdb_store_service(dom,
     330           0 :                                           svc->s_name,
     331             :                                           svc->s_port,
     332             :                                           cased_aliases,
     333             :                                           protocols,
     334             :                                           NULL, NULL,
     335           0 :                                           dom->service_timeout,
     336             :                                           now);
     337           0 :                 if (ret) {
     338             :                     /* Do not fail completely on errors.
     339             :                      * Just report the failure to save and go on */
     340           0 :                     DEBUG(SSSDBG_OP_FAILURE,
     341             :                             "Failed to store service [%s]. Ignoring.\n",
     342             :                              strerror(ret));
     343             :                 }
     344           0 :                 again = true;
     345           0 :                 break;
     346             : 
     347             :             case NSS_STATUS_UNAVAIL:
     348             :                 /* "remote" backend unavailable. Enter offline mode */
     349           0 :                 ret = ENXIO;
     350           0 :                 break;
     351             : 
     352             :             default:
     353           0 :                 ret = EIO;
     354           0 :                 DEBUG(SSSDBG_CRIT_FAILURE,
     355             :                         "proxy -> getservent_r failed (%d)[%s]\n",
     356             :                          ret, strerror(ret));
     357           0 :                 break;
     358             :         }
     359           0 :     } while (again);
     360             : 
     361             : done:
     362           0 :     talloc_zfree(tmpctx);
     363           0 :     if (in_transaction) {
     364           0 :         sret = sysdb_transaction_cancel(sysdb);
     365           0 :         if (sret != EOK) {
     366           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     367             :                   "Could not cancel transaction! [%s]\n",
     368             :                    strerror(sret));
     369             :         }
     370             :     }
     371           0 :     ctx->ops.endservent();
     372           0 :     return ret;
     373             : }

Generated by: LCOV version 1.10