LCOV - code coverage report
Current view: top level - db - sysdb_ssh.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 67 160 41.9 %
Date: 2015-10-19 Functions: 5 9 55.6 %

          Line data    Source code
       1             : /*
       2             :     Authors:
       3             :         Jan Cholasta <jcholast@redhat.com>
       4             : 
       5             :     Copyright (C) 2012 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 <talloc.h>
      22             : 
      23             : #include "db/sysdb_ssh.h"
      24             : #include "db/sysdb_private.h"
      25             : 
      26             : static struct ldb_dn *
      27           0 : sysdb_ssh_host_dn(TALLOC_CTX *mem_ctx,
      28             :                   struct sss_domain_info *domain,
      29             :                   const char *name)
      30             : {
      31           0 :     return sysdb_custom_dn(mem_ctx, domain, name, SSH_HOSTS_SUBDIR);
      32             : }
      33             : 
      34             : static errno_t
      35           2 : sysdb_update_ssh_host(struct sss_domain_info *domain,
      36             :                       const char *name,
      37             :                       struct sysdb_attrs *attrs)
      38             : {
      39             :     errno_t ret;
      40             : 
      41           2 :     ret = sysdb_store_custom(domain, name, SSH_HOSTS_SUBDIR,
      42             :                              attrs);
      43           2 :     if (ret != EOK) {
      44           0 :         DEBUG(SSSDBG_OP_FAILURE,
      45             :               "Error storing host %s [%d]: %s\n", name, ret, strerror(ret));
      46           0 :         return ret;
      47             :     }
      48             : 
      49           2 :     return EOK;
      50             : }
      51             : 
      52             : errno_t
      53           2 : sysdb_store_ssh_host(struct sss_domain_info *domain,
      54             :                      const char *name,
      55             :                      const char *alias,
      56             :                      int cache_timeout,
      57             :                      time_t now,
      58             :                      struct sysdb_attrs *attrs)
      59             : {
      60             :     TALLOC_CTX *tmp_ctx;
      61             :     errno_t ret, sret;
      62           2 :     bool in_transaction = false;
      63           2 :     const char *search_attrs[] = { SYSDB_NAME_ALIAS, NULL };
      64             :     bool new_alias;
      65           2 :     struct ldb_message *host = NULL;
      66             :     struct ldb_message_element *el;
      67             :     unsigned int i;
      68             : 
      69           2 :     DEBUG(SSSDBG_TRACE_FUNC, "Storing host %s\n", name);
      70             : 
      71           2 :     tmp_ctx = talloc_new(NULL);
      72           2 :     if (!tmp_ctx) {
      73           0 :         return ENOMEM;
      74             :     }
      75             : 
      76           2 :     ret = sysdb_transaction_start(domain->sysdb);
      77           2 :     if (ret != EOK) {
      78           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n");
      79           0 :         goto done;
      80             :     }
      81             : 
      82           2 :     in_transaction = true;
      83             : 
      84           2 :     ret = sysdb_get_ssh_host(tmp_ctx, domain, name, search_attrs, &host);
      85           2 :     if (ret != EOK && ret != ENOENT) {
      86           0 :         goto done;
      87             :     }
      88             : 
      89           2 :     ret = sysdb_attrs_add_string(attrs, SYSDB_OBJECTCLASS, SYSDB_SSH_HOST_OC);
      90           2 :     if (ret != EOK) {
      91           0 :         DEBUG(SSSDBG_OP_FAILURE,
      92             :               "Could not set object class [%d]: %s\n", ret, strerror(ret));
      93           0 :         goto done;
      94             :     }
      95             : 
      96           2 :     ret = sysdb_attrs_add_string(attrs, SYSDB_NAME, name);
      97           2 :     if (ret != EOK) {
      98           0 :         DEBUG(SSSDBG_OP_FAILURE,
      99             :               "Could not set name attribute [%d]: %s\n", ret, strerror(ret));
     100           0 :         goto done;
     101             :     }
     102             : 
     103           2 :     if (alias) {
     104           0 :         new_alias = true;
     105             : 
     106             :         /* copy aliases from the existing entry */
     107           0 :         if (host) {
     108           0 :             el = ldb_msg_find_element(host, SYSDB_NAME_ALIAS);
     109             : 
     110           0 :             if (el) {
     111           0 :                 for (i = 0; i < el->num_values; i++) {
     112           0 :                     if (strcmp((char *)el->values[i].data, alias) == 0) {
     113           0 :                         new_alias = false;
     114             :                     }
     115             : 
     116           0 :                     ret = sysdb_attrs_add_val(attrs,
     117           0 :                                               SYSDB_NAME_ALIAS, &el->values[i]);
     118           0 :                     if (ret != EOK) {
     119           0 :                         DEBUG(SSSDBG_OP_FAILURE,
     120             :                               "Could not add name alias %s [%d]: %s\n",
     121             :                                el->values[i].data, ret, strerror(ret));
     122           0 :                         goto done;
     123             :                     }
     124             :                 }
     125             :             }
     126             :         }
     127             : 
     128             :         /* add alias only if it is not already present */
     129           0 :         if (new_alias) {
     130           0 :             ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, alias);
     131           0 :             if (ret != EOK) {
     132           0 :                 DEBUG(SSSDBG_OP_FAILURE,
     133             :                       "Could not add name alias %s [%d]: %s\n",
     134             :                        alias, ret, strerror(ret));
     135           0 :                 goto done;
     136             :             }
     137             :         }
     138             :     }
     139             : 
     140             :     /* make sure sshPublicKey is present when modifying an existing host */
     141           2 :     if (host) {
     142           0 :         ret = sysdb_attrs_get_el(attrs, SYSDB_SSH_PUBKEY, &el);
     143           0 :         if (ret != EOK) {
     144           0 :             DEBUG(SSSDBG_OP_FAILURE,
     145             :                   "Could not get sysdb sshPublicKey [%d]: %s\n",
     146             :                    ret, strerror(ret));
     147           0 :             goto done;
     148             :         }
     149             :     }
     150             : 
     151           2 :     ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now);
     152           2 :     if (ret != EOK) {
     153           0 :         DEBUG(SSSDBG_OP_FAILURE,
     154             :               "Could not set sysdb lastUpdate [%d]: %s\n",
     155             :                ret, strerror(ret));
     156           0 :         goto done;
     157             :     }
     158             : 
     159           4 :     ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE,
     160           2 :                                  cache_timeout ? (now + cache_timeout) : 0);
     161           2 :     if (ret != EOK) {
     162           0 :         DEBUG(SSSDBG_OP_FAILURE, "Could not set sysdb cache expire [%d]: %s\n",
     163             :               ret, strerror(ret));
     164           0 :         goto done;
     165             :     }
     166             : 
     167           2 :     ret = sysdb_update_ssh_host(domain, name, attrs);
     168           2 :     if (ret != EOK) {
     169           0 :         goto done;
     170             :     }
     171             : 
     172           2 :     ret = sysdb_transaction_commit(domain->sysdb);
     173           2 :     if (ret != EOK) {
     174           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction\n");
     175           0 :         goto done;
     176             :     }
     177             : 
     178           2 :     in_transaction = false;
     179             : 
     180           2 :     ret = EOK;
     181             : 
     182             : done:
     183           2 :     if (in_transaction) {
     184           0 :         sret = sysdb_transaction_cancel(domain->sysdb);
     185           0 :         if (sret != EOK) {
     186           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Could not cancel transaction\n");
     187             :         }
     188             :     }
     189             : 
     190           2 :     talloc_free(tmp_ctx);
     191             : 
     192           2 :     return ret;
     193             : }
     194             : 
     195             : errno_t
     196           0 : sysdb_set_ssh_host_attr(struct sss_domain_info *domain,
     197             :                         const char *name,
     198             :                         struct sysdb_attrs *attrs,
     199             :                         int mod_op)
     200             : {
     201             :     errno_t ret;
     202             :     struct ldb_dn *dn;
     203             :     TALLOC_CTX *tmp_ctx;
     204             : 
     205           0 :     tmp_ctx = talloc_new(NULL);
     206           0 :     if (!tmp_ctx) {
     207           0 :         return ENOMEM;
     208             :     }
     209             : 
     210           0 :     dn = sysdb_ssh_host_dn(tmp_ctx, domain, name);
     211           0 :     if (!dn) {
     212           0 :         ret = ENOMEM;
     213           0 :         goto done;
     214             :     }
     215             : 
     216           0 :     ret = sysdb_set_entry_attr(domain->sysdb, dn, attrs, mod_op);
     217             : 
     218             : done:
     219           0 :     talloc_free(tmp_ctx);
     220           0 :     return ret;
     221             : }
     222             : 
     223             : errno_t
     224           0 : sysdb_update_ssh_known_host_expire(struct sss_domain_info *domain,
     225             :                                    const char *name,
     226             :                                    time_t now,
     227             :                                    int known_hosts_timeout)
     228             : {
     229             :     TALLOC_CTX *tmp_ctx;
     230             :     errno_t ret;
     231             :     struct sysdb_attrs *attrs;
     232             : 
     233           0 :     DEBUG(SSSDBG_TRACE_FUNC,
     234             :           "Updating known_hosts expire time of host %s\n", name);
     235             : 
     236           0 :     tmp_ctx = talloc_new(NULL);
     237           0 :     if (!tmp_ctx) {
     238           0 :         return ENOMEM;
     239             :     }
     240             : 
     241           0 :     attrs = sysdb_new_attrs(tmp_ctx);
     242           0 :     if (!attrs) {
     243           0 :         ret = ENOMEM;
     244           0 :         goto done;
     245             :     }
     246             : 
     247           0 :     ret = sysdb_attrs_add_time_t(attrs, SYSDB_SSH_KNOWN_HOSTS_EXPIRE,
     248             :                                  now + known_hosts_timeout);
     249           0 :     if (ret != EOK) {
     250           0 :         DEBUG(SSSDBG_OP_FAILURE,
     251             :               "Could not set known_hosts expire time [%d]: %s\n",
     252             :                ret, strerror(ret));
     253           0 :         goto done;
     254             :     }
     255             : 
     256           0 :     ret = sysdb_update_ssh_host(domain, name, attrs);
     257           0 :     if (ret != EOK) {
     258           0 :         goto done;
     259             :     }
     260             : 
     261           0 :     ret = EOK;
     262             : 
     263             : done:
     264           0 :     talloc_free(tmp_ctx);
     265             : 
     266           0 :     return ret;
     267             : }
     268             : 
     269             : errno_t
     270           2 : sysdb_delete_ssh_host(struct sss_domain_info *domain,
     271             :                       const char *name)
     272             : {
     273           2 :     DEBUG(SSSDBG_TRACE_FUNC, "Deleting host %s\n", name);
     274           2 :     return sysdb_delete_custom(domain, name, SSH_HOSTS_SUBDIR);
     275             : }
     276             : 
     277             : errno_t
     278           3 : sysdb_search_ssh_hosts(TALLOC_CTX *mem_ctx,
     279             :                        struct sss_domain_info *domain,
     280             :                        const char *filter,
     281             :                        const char **attrs,
     282             :                        size_t *num_hosts,
     283             :                        struct ldb_message ***hosts)
     284             : {
     285             :     errno_t ret;
     286             :     TALLOC_CTX *tmp_ctx;
     287             :     struct ldb_message **results;
     288             :     size_t num_results;
     289             : 
     290           3 :     tmp_ctx = talloc_new(NULL);
     291           3 :     if (!tmp_ctx) {
     292           0 :         return ENOMEM;
     293             :     }
     294             : 
     295           3 :     ret = sysdb_search_custom(tmp_ctx, domain, filter,
     296             :                               SSH_HOSTS_SUBDIR, attrs,
     297             :                               &num_results, &results);
     298           3 :     if (ret != EOK && ret != ENOENT) {
     299           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     300             :               "Error looking up host [%d]: %s\n",
     301             :                ret, strerror(ret));
     302           0 :         goto done;
     303           3 :     } if (ret == ENOENT) {
     304           2 :         DEBUG(SSSDBG_TRACE_FUNC, "No such host\n");
     305           2 :         *hosts = NULL;
     306           2 :         *num_hosts = 0;
     307           2 :         goto done;
     308             :     }
     309             : 
     310           1 :     *hosts = talloc_steal(mem_ctx, results);
     311           1 :     *num_hosts = num_results;
     312           1 :     ret = EOK;
     313             : 
     314             : done:
     315           3 :     talloc_free(tmp_ctx);
     316             : 
     317           3 :     return ret;
     318             : }
     319             : 
     320             : errno_t
     321           3 : sysdb_get_ssh_host(TALLOC_CTX *mem_ctx,
     322             :                    struct sss_domain_info *domain,
     323             :                    const char *name,
     324             :                    const char **attrs,
     325             :                    struct ldb_message **host)
     326             : {
     327             :     TALLOC_CTX *tmp_ctx;
     328             :     errno_t ret;
     329             :     const char *filter;
     330             :     struct ldb_message **hosts;
     331             :     size_t num_hosts;
     332             : 
     333           3 :     tmp_ctx = talloc_new(NULL);
     334           3 :     if (!tmp_ctx) {
     335           0 :         return ENOMEM;
     336             :     }
     337             : 
     338           3 :     filter = talloc_asprintf(tmp_ctx, "(%s=%s)", SYSDB_NAME, name);
     339           3 :     if (!filter) {
     340           0 :         ret = ENOMEM;
     341           0 :         goto done;
     342             :     }
     343             : 
     344           3 :     ret = sysdb_search_ssh_hosts(tmp_ctx, domain, filter, attrs,
     345             :                                  &num_hosts, &hosts);
     346           3 :     if (ret != EOK) {
     347           2 :         goto done;
     348             :     }
     349             : 
     350           1 :     if (num_hosts > 1) {
     351           0 :         ret = EINVAL;
     352           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     353             :               "Found more than one host with name %s\n", name);
     354           0 :         goto done;
     355             :     }
     356             : 
     357           1 :     *host = talloc_steal(mem_ctx, hosts[0]);
     358           1 :     ret = EOK;
     359             : 
     360             : done:
     361           3 :     talloc_free(tmp_ctx);
     362             : 
     363           3 :     return ret;
     364             : }
     365             : 
     366             : errno_t
     367           0 : sysdb_get_ssh_known_hosts(TALLOC_CTX *mem_ctx,
     368             :                           struct sss_domain_info *domain,
     369             :                           time_t now,
     370             :                           const char **attrs,
     371             :                           struct ldb_message ***hosts,
     372             :                           size_t *num_hosts)
     373             : {
     374             :     TALLOC_CTX *tmp_ctx;
     375             :     errno_t ret;
     376             :     const char *filter;
     377             : 
     378           0 :     tmp_ctx = talloc_new(NULL);
     379           0 :     if (!tmp_ctx) {
     380           0 :         return ENOMEM;
     381             :     }
     382             : 
     383           0 :     filter = talloc_asprintf(tmp_ctx,
     384             :                              "(&(|(!(%s=*))(%s=0)(%s>=%lld))(%s>=%lld))",
     385             :                              SYSDB_CACHE_EXPIRE,
     386             :                              SYSDB_CACHE_EXPIRE,
     387             :                              SYSDB_CACHE_EXPIRE, (long long)now + 1,
     388             :                              SYSDB_SSH_KNOWN_HOSTS_EXPIRE, (long long)now + 1);
     389           0 :     if (!filter) {
     390           0 :         ret = ENOMEM;
     391           0 :         goto done;
     392             :     }
     393             : 
     394           0 :     ret = sysdb_search_ssh_hosts(mem_ctx, domain, filter, attrs,
     395             :                                  num_hosts, hosts);
     396             : 
     397             : done:
     398           0 :     talloc_free(tmp_ctx);
     399             : 
     400           0 :     return ret;
     401             : }

Generated by: LCOV version 1.10