"Fossies" - the Fresh Open Source Software Archive

Member "sssd-2.2.2/src/providers/ad/ad_dyndns.c" (12 Sep 2019, 9289 Bytes) of package /linux/misc/sssd-2.2.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ad_dyndns.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 2.2.0_vs_2.2.1.

    1 /*
    2     SSSD
    3 
    4     ad_dyndns.c
    5 
    6     Authors:
    7         Jakub Hrozek <jhrozek@redhat.com>
    8 
    9     Copyright (C) 2013 Red Hat
   10 
   11     This program is free software; you can redistribute it and/or modify
   12     it under the terms of the GNU General Public License as published by
   13     the Free Software Foundation; either version 3 of the License, or
   14     (at your option) any later version.
   15 
   16     This program is distributed in the hope that it will be useful,
   17     but WITHOUT ANY WARRANTY; without even the implied warranty of
   18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   19     GNU General Public License for more details.
   20 
   21     You should have received a copy of the GNU General Public License
   22     along with this program.  If not, see <http://www.gnu.org/licenses/>.
   23 */
   24 
   25 #include <ctype.h>
   26 #include "util/util.h"
   27 #include "providers/ldap/sdap_dyndns.h"
   28 #include "providers/data_provider.h"
   29 #include "providers/be_dyndns.h"
   30 #include "providers/ad/ad_common.h"
   31 
   32 struct ad_dyndns_update_state {
   33     struct ad_options *ad_ctx;
   34     struct sdap_id_op *sdap_op;
   35 };
   36 
   37 static void
   38 ad_dyndns_sdap_update_done(struct tevent_req *subreq);
   39 
   40 static struct tevent_req *
   41 ad_dyndns_update_send(TALLOC_CTX *mem_ctx,
   42                       struct tevent_context *ev,
   43                       struct be_ctx *be_ctx,
   44                       struct be_ptask *be_ptask,
   45                       void *pvt);
   46 
   47 static errno_t
   48 ad_dyndns_update_recv(struct tevent_req *req);
   49 
   50 static void
   51 ad_dyndns_update_connect_done(struct tevent_req *subreq);
   52 
   53 errno_t ad_dyndns_init(struct be_ctx *be_ctx,
   54                        struct ad_options *ad_opts)
   55 {
   56     errno_t ret;
   57     const time_t ptask_first_delay = 10;
   58     int period;
   59     uint32_t extraflags = 0;
   60 
   61     /* nsupdate is available. Dynamic updates
   62      * are supported
   63      */
   64     ret = ad_get_dyndns_options(be_ctx, ad_opts);
   65     if (ret != EOK) {
   66         DEBUG(SSSDBG_CRIT_FAILURE, "Could not set AD options\n");
   67         return ret;
   68     }
   69 
   70     if (dp_opt_get_bool(ad_opts->dyndns_ctx->opts,
   71                         DP_OPT_DYNDNS_UPDATE) == false) {
   72         DEBUG(SSSDBG_CONF_SETTINGS, "Dynamic DNS updates are off.\n");
   73         return EOK;
   74     }
   75 
   76     DEBUG(SSSDBG_CONF_SETTINGS,
   77           "Dynamic DNS updates are on. Checking for nsupdate..\n");
   78     ret = be_nsupdate_check();
   79     if (ret == ENOENT) {
   80         DEBUG(SSSDBG_MINOR_FAILURE,
   81               "DNS updates requested but nsupdate not available\n");
   82         return EOK;
   83     } else if (ret != EOK) {
   84         DEBUG(SSSDBG_OP_FAILURE, "Could not check for nsupdate\n");
   85         return ret;
   86     }
   87 
   88     ad_opts->be_res = be_ctx->be_res;
   89     if (ad_opts->be_res == NULL) {
   90         DEBUG(SSSDBG_OP_FAILURE, "Resolver must be initialized in order "
   91               "to use the AD dynamic DNS updates\n");
   92         return EINVAL;
   93     }
   94 
   95     period = dp_opt_get_int(ad_opts->dyndns_ctx->opts, DP_OPT_DYNDNS_REFRESH_INTERVAL);
   96     if (period == 0) {
   97         DEBUG(SSSDBG_TRACE_FUNC, "DNS will not be updated periodically, "
   98               "dyndns_refresh_interval is 0\n");
   99         extraflags |= BE_PTASK_NO_PERIODIC;
  100     }
  101 
  102     ret = be_ptask_create(ad_opts, be_ctx, period, ptask_first_delay, 0, 0,
  103                           period, 0,
  104                           ad_dyndns_update_send, ad_dyndns_update_recv, ad_opts,
  105                           "Dyndns update",
  106                           extraflags |
  107                           BE_PTASK_OFFLINE_DISABLE |
  108                           BE_PTASK_SCHEDULE_FROM_LAST,
  109                           NULL);
  110 
  111     if (ret != EOK) {
  112         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to setup ptask "
  113               "[%d]: %s\n", ret, sss_strerror(ret));
  114     }
  115     return ret;
  116 }
  117 
  118 static struct tevent_req *
  119 ad_dyndns_update_send(TALLOC_CTX *mem_ctx,
  120                       struct tevent_context *ev,
  121                       struct be_ctx *be_ctx,
  122                       struct be_ptask *be_ptask,
  123                       void *pvt)
  124 {
  125     int ret;
  126     struct ad_options *ctx;
  127     struct ad_dyndns_update_state *state;
  128     struct tevent_req *req, *subreq;
  129     struct sdap_id_ctx *sdap_ctx;
  130 
  131     DEBUG(SSSDBG_TRACE_FUNC, "Performing update\n");
  132 
  133     ctx = talloc_get_type(pvt, struct ad_options);
  134     sdap_ctx = ctx->id_ctx->sdap_id_ctx;
  135 
  136     req = tevent_req_create(ctx, &state, struct ad_dyndns_update_state);
  137     if (req == NULL) {
  138         return NULL;
  139     }
  140     state->ad_ctx = ctx;
  141 
  142     if (ctx->dyndns_ctx->last_refresh + 60 > time(NULL) ||
  143         ctx->dyndns_ctx->timer_in_progress) {
  144         DEBUG(SSSDBG_FUNC_DATA, "Last periodic update ran recently or timer "
  145               "in progress, not scheduling another update\n");
  146         tevent_req_done(req);
  147         tevent_req_post(req, sdap_ctx->be->ev);
  148         return req;
  149     }
  150     state->ad_ctx->dyndns_ctx->last_refresh = time(NULL);
  151 
  152     /* Make sure to have a valid LDAP connection */
  153     state->sdap_op = sdap_id_op_create(state, sdap_ctx->conn->conn_cache);
  154     if (state->sdap_op == NULL) {
  155         DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
  156         ret = ENOMEM;
  157         goto done;
  158     }
  159 
  160     subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret);
  161     if (!subreq) {
  162         DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed: [%d](%s)\n",
  163               ret, sss_strerror(ret));
  164         ret = ENOMEM;
  165         goto done;
  166     }
  167     tevent_req_set_callback(subreq, ad_dyndns_update_connect_done, req);
  168     ret = EOK;
  169 done:
  170     if (ret != EOK) {
  171         tevent_req_error(req, ret);
  172         tevent_req_post(req, sdap_ctx->be->ev);
  173     }
  174     return req;
  175 }
  176 
  177 static void ad_dyndns_update_connect_done(struct tevent_req *subreq)
  178 {
  179     int dp_error;
  180     int ret;
  181     struct tevent_req *req;
  182     struct ad_dyndns_update_state *state;
  183     struct sdap_id_ctx *sdap_ctx;
  184     struct ad_options *ctx;
  185     LDAPURLDesc *lud;
  186 
  187     req = tevent_req_callback_data(subreq, struct tevent_req);
  188     state = tevent_req_data(req, struct ad_dyndns_update_state);
  189 
  190     ret = sdap_id_op_connect_recv(subreq, &dp_error);
  191     talloc_zfree(subreq);
  192 
  193     if (ret != EOK) {
  194         if (dp_error == DP_ERR_OFFLINE) {
  195             DEBUG(SSSDBG_MINOR_FAILURE, "No server is available, "
  196                   "dynamic DNS update is skipped in offline mode.\n");
  197             tevent_req_error(req, ERR_DYNDNS_OFFLINE);
  198         } else {
  199             DEBUG(SSSDBG_OP_FAILURE,
  200                   "Failed to connect to LDAP server: [%d](%s)\n",
  201                   ret, sss_strerror(ret));
  202             tevent_req_error(req, ERR_NETWORK_IO);
  203         }
  204         return;
  205     }
  206 
  207     ctx = state->ad_ctx;
  208     sdap_ctx = ctx->id_ctx->sdap_id_ctx;
  209 
  210     ret = ldap_url_parse(ctx->service->sdap->uri, &lud);
  211     if (ret != LDAP_SUCCESS) {
  212         DEBUG(SSSDBG_CRIT_FAILURE,
  213               "Failed to parse ldap URI (%s)!\n", ctx->service->sdap->uri);
  214         ret = EINVAL;
  215         goto done;
  216     }
  217 
  218     if (lud->lud_scheme != NULL &&
  219         strcasecmp(lud->lud_scheme, "ldapi") == 0) {
  220         DEBUG(SSSDBG_CRIT_FAILURE,
  221               "The LDAP scheme is ldapi://, cannot proceed with update\n");
  222         ldap_free_urldesc(lud);
  223         ret = EINVAL;
  224         goto done;
  225     }
  226 
  227     if (lud->lud_host == NULL) {
  228         DEBUG(SSSDBG_CRIT_FAILURE,
  229               "The LDAP URI (%s) did not contain a host name\n",
  230               ctx->service->sdap->uri);
  231         ldap_free_urldesc(lud);
  232         ret = EINVAL;
  233         goto done;
  234     }
  235 
  236     subreq = sdap_dyndns_update_send(state, sdap_ctx->be->ev,
  237                                      sdap_ctx->be,
  238                                      ctx->dyndns_ctx->opts,
  239                                      sdap_ctx,
  240                                      ctx->dyndns_ctx->auth_type,
  241                                      dp_opt_get_string(ctx->dyndns_ctx->opts,
  242                                                        DP_OPT_DYNDNS_IFACE),
  243                                      dp_opt_get_string(ctx->basic,
  244                                                        AD_HOSTNAME),
  245                                      dp_opt_get_string(ctx->basic,
  246                                                        AD_KRB5_REALM),
  247                                      dp_opt_get_int(ctx->dyndns_ctx->opts,
  248                                                     DP_OPT_DYNDNS_TTL),
  249                                      false);
  250     if (!subreq) {
  251         ret = EIO;
  252         DEBUG(SSSDBG_OP_FAILURE,
  253               "sdap_dyndns_update_send failed: [%d](%s)\n",
  254                ret, sss_strerror(ret));
  255         goto done;
  256     }
  257     tevent_req_set_callback(subreq, ad_dyndns_sdap_update_done, req);
  258     ret = EOK;
  259 done:
  260     if (ret != EOK) {
  261         tevent_req_error(req, ret);
  262         tevent_req_post(req, sdap_ctx->be->ev);
  263     }
  264 }
  265 
  266 static void ad_dyndns_sdap_update_done(struct tevent_req *subreq)
  267 {
  268     struct tevent_req *req = tevent_req_callback_data(subreq,
  269                                                       struct tevent_req);
  270     errno_t ret;
  271 
  272     ret = sdap_dyndns_update_recv(subreq);
  273     talloc_zfree(subreq);
  274     if (ret != EOK) {
  275         DEBUG(SSSDBG_OP_FAILURE,
  276               "Dynamic DNS update failed [%d]: %s\n",
  277               ret, sss_strerror(ret));
  278         tevent_req_error(req, ret);
  279         return;
  280     }
  281 
  282     tevent_req_done(req);
  283 }
  284 
  285 static errno_t ad_dyndns_update_recv(struct tevent_req *req)
  286 {
  287     TEVENT_REQ_RETURN_ON_ERROR(req);
  288 
  289     return EOK;
  290 }