Ignore:
Timestamp:
Nov 24, 2016, 1:14:11 PM (9 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: update vendor to version 4.4.3

File:
1 edited

Legend:

Unmodified
Added
Removed
  • vendor/current/source3/libads/cldap.c

    r740 r988  
    2424#include "../libcli/cldap/cldap.h"
    2525#include "../lib/tsocket/tsocket.h"
     26#include "../lib/util/tevent_ntstatus.h"
    2627#include "libads/cldap.h"
     28
     29struct cldap_multi_netlogon_state {
     30        struct tevent_context *ev;
     31        const struct tsocket_address * const *servers;
     32        int num_servers;
     33        const char *domain;
     34        const char *hostname;
     35        unsigned ntversion;
     36        int min_servers;
     37
     38        struct cldap_socket **cldap;
     39        struct tevent_req **subreqs;
     40        int num_sent;
     41        int num_received;
     42        int num_good_received;
     43        struct cldap_netlogon *ios;
     44        struct netlogon_samlogon_response **responses;
     45};
     46
     47static void cldap_multi_netlogon_done(struct tevent_req *subreq);
     48static void cldap_multi_netlogon_next(struct tevent_req *subreq);
     49
     50/*
     51 * Do a parallel cldap ping to the servers. The first "min_servers"
     52 * are fired directly, the remaining ones in 100msec intervals. If
     53 * "min_servers" responses came in successfully, we immediately reply,
     54 * not waiting for the remaining ones.
     55 */
     56
     57struct tevent_req *cldap_multi_netlogon_send(
     58        TALLOC_CTX *mem_ctx, struct tevent_context *ev,
     59        const struct tsocket_address * const *servers, int num_servers,
     60        const char *domain, const char *hostname, unsigned ntversion,
     61        int min_servers)
     62{
     63        struct tevent_req *req, *subreq;
     64        struct cldap_multi_netlogon_state *state;
     65        int i;
     66
     67        req = tevent_req_create(mem_ctx, &state,
     68                                struct cldap_multi_netlogon_state);
     69        if (req == NULL) {
     70                return NULL;
     71        }
     72        state->ev = ev;
     73        state->servers = servers;
     74        state->num_servers = num_servers;
     75        state->domain = domain;
     76        state->hostname = hostname;
     77        state->ntversion = ntversion;
     78        state->min_servers = min_servers;
     79
     80        if (min_servers > num_servers) {
     81                tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     82                return tevent_req_post(req, ev);
     83        }
     84
     85        state->subreqs = talloc_zero_array(state,
     86                                           struct tevent_req *,
     87                                           num_servers);
     88        if (tevent_req_nomem(state->subreqs, req)) {
     89                return tevent_req_post(req, ev);
     90        }
     91
     92        state->cldap = talloc_zero_array(state,
     93                                         struct cldap_socket *,
     94                                         num_servers);
     95        if (tevent_req_nomem(state->cldap, req)) {
     96                return tevent_req_post(req, ev);
     97        }
     98
     99        state->responses = talloc_zero_array(state,
     100                                struct netlogon_samlogon_response *,
     101                                num_servers);
     102        if (tevent_req_nomem(state->responses, req)) {
     103                return tevent_req_post(req, ev);
     104        }
     105
     106        state->ios = talloc_zero_array(state->responses,
     107                                       struct cldap_netlogon,
     108                                       num_servers);
     109        if (tevent_req_nomem(state->ios, req)) {
     110                return tevent_req_post(req, ev);
     111        }
     112
     113        for (i=0; i<num_servers; i++) {
     114                NTSTATUS status;
     115
     116                status = cldap_socket_init(state->cldap,
     117                                           NULL, /* local_addr */
     118                                           state->servers[i],
     119                                           &state->cldap[i]);
     120                if (tevent_req_nterror(req, status)) {
     121                        return tevent_req_post(req, ev);
     122                }
     123
     124                state->ios[i].in.dest_address   = NULL;
     125                state->ios[i].in.dest_port      = 0;
     126                state->ios[i].in.realm          = domain;
     127                state->ios[i].in.host           = NULL;
     128                state->ios[i].in.user           = NULL;
     129                state->ios[i].in.domain_guid    = NULL;
     130                state->ios[i].in.domain_sid     = NULL;
     131                state->ios[i].in.acct_control   = 0;
     132                state->ios[i].in.version        = ntversion;
     133                state->ios[i].in.map_response   = false;
     134        }
     135
     136        for (i=0; i<min_servers; i++) {
     137                state->subreqs[i] = cldap_netlogon_send(state->subreqs,
     138                                                        state->ev,
     139                                                        state->cldap[i],
     140                                                        &state->ios[i]);
     141                if (tevent_req_nomem(state->subreqs[i], req)) {
     142                        return tevent_req_post(req, ev);
     143                }
     144                tevent_req_set_callback(
     145                        state->subreqs[i], cldap_multi_netlogon_done, req);
     146        }
     147        state->num_sent = min_servers;
     148
     149        if (state->num_sent < state->num_servers) {
     150                /*
     151                 * After 100 milliseconds fire the next one
     152                 */
     153                subreq = tevent_wakeup_send(state, state->ev,
     154                                            timeval_current_ofs(0, 100000));
     155                if (tevent_req_nomem(subreq, req)) {
     156                        return tevent_req_post(req, ev);
     157                }
     158                tevent_req_set_callback(subreq, cldap_multi_netlogon_next,
     159                                        req);
     160        }
     161
     162        return req;
     163}
     164
     165static void cldap_multi_netlogon_done(struct tevent_req *subreq)
     166{
     167        struct tevent_req *req = tevent_req_callback_data(
     168                subreq, struct tevent_req);
     169        struct cldap_multi_netlogon_state *state = tevent_req_data(
     170                req, struct cldap_multi_netlogon_state);
     171        NTSTATUS status;
     172        struct netlogon_samlogon_response *response;
     173        int i;
     174
     175        for (i=0; i<state->num_sent; i++) {
     176                if (state->subreqs[i] == subreq) {
     177                        break;
     178                }
     179        }
     180        if (i == state->num_sent) {
     181                /*
     182                 * Got a response we did not fire...
     183                 */
     184                tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
     185                return;
     186        }
     187        state->subreqs[i] = NULL;
     188
     189        response = talloc_zero(state, struct netlogon_samlogon_response);
     190        if (tevent_req_nomem(response, req)) {
     191                return;
     192        }
     193
     194        status = cldap_netlogon_recv(subreq, response,
     195                                     &state->ios[i]);
     196        TALLOC_FREE(subreq);
     197        state->num_received += 1;
     198
     199        if (NT_STATUS_IS_OK(status)) {
     200                *response = state->ios[i].out.netlogon;
     201                state->responses[i] = talloc_move(state->responses,
     202                                                  &response);
     203                state->num_good_received += 1;
     204        }
     205
     206        if ((state->num_received == state->num_servers) ||
     207            (state->num_good_received >= state->min_servers)) {
     208                tevent_req_done(req);
     209                return;
     210        }
     211}
     212
     213static void cldap_multi_netlogon_next(struct tevent_req *subreq)
     214{
     215        struct tevent_req *req = tevent_req_callback_data(
     216                subreq, struct tevent_req);
     217        struct cldap_multi_netlogon_state *state = tevent_req_data(
     218                req, struct cldap_multi_netlogon_state);
     219        bool ret;
     220
     221        ret = tevent_wakeup_recv(subreq);
     222        TALLOC_FREE(subreq);
     223        if (!ret) {
     224                tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
     225                return;
     226        }
     227
     228        subreq = cldap_netlogon_send(state->subreqs,
     229                                     state->ev,
     230                                     state->cldap[state->num_sent],
     231                                     &state->ios[state->num_sent]);
     232        if (tevent_req_nomem(subreq, req)) {
     233                return;
     234        }
     235        tevent_req_set_callback(subreq, cldap_multi_netlogon_done, req);
     236        state->subreqs[state->num_sent] = subreq;
     237        state->num_sent += 1;
     238
     239        if (state->num_sent < state->num_servers) {
     240                /*
     241                 * After 100 milliseconds fire the next one
     242                 */
     243                subreq = tevent_wakeup_send(state, state->ev,
     244                                            timeval_current_ofs(0, 100000));
     245                if (tevent_req_nomem(subreq, req)) {
     246                        return;
     247                }
     248                tevent_req_set_callback(subreq, cldap_multi_netlogon_next,
     249                                        req);
     250        }
     251}
     252
     253NTSTATUS cldap_multi_netlogon_recv(
     254        struct tevent_req *req, TALLOC_CTX *mem_ctx,
     255        struct netlogon_samlogon_response ***responses)
     256{
     257        struct cldap_multi_netlogon_state *state = tevent_req_data(
     258                req, struct cldap_multi_netlogon_state);
     259        NTSTATUS status;
     260
     261        if (tevent_req_is_nterror(req, &status) &&
     262            !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
     263                return status;
     264        }
     265        /*
     266         * If we timeout, give back what we have so far
     267         */
     268        *responses = talloc_move(mem_ctx, &state->responses);
     269        return NT_STATUS_OK;
     270}
     271
     272NTSTATUS cldap_multi_netlogon(
     273        TALLOC_CTX *mem_ctx,
     274        const struct tsocket_address * const *servers,
     275        int num_servers,
     276        const char *domain, const char *hostname, unsigned ntversion,
     277        int min_servers, struct timeval timeout,
     278        struct netlogon_samlogon_response ***responses)
     279{
     280        struct tevent_context *ev;
     281        struct tevent_req *req;
     282        NTSTATUS status = NT_STATUS_NO_MEMORY;
     283
     284        ev = samba_tevent_context_init(talloc_tos());
     285        if (ev == NULL) {
     286                goto fail;
     287        }
     288        req = cldap_multi_netlogon_send(
     289                ev, ev, servers, num_servers, domain, hostname, ntversion,
     290                min_servers);
     291        if (req == NULL) {
     292                goto fail;
     293        }
     294        if (!tevent_req_set_endtime(req, ev, timeout)) {
     295                goto fail;
     296        }
     297        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     298                goto fail;
     299        }
     300        status = cldap_multi_netlogon_recv(req, mem_ctx, responses);
     301fail:
     302        TALLOC_FREE(ev);
     303        return status;
     304}
    27305
    28306/*******************************************************************
     
    31309
    32310bool ads_cldap_netlogon(TALLOC_CTX *mem_ctx,
    33                         const char *server,
     311                        struct sockaddr_storage *ss,
    34312                        const char *realm,
    35313                        uint32_t nt_version,
    36314                        struct netlogon_samlogon_response **_reply)
    37315{
    38         struct cldap_socket *cldap;
    39         struct cldap_netlogon io;
    40         struct netlogon_samlogon_response *reply;
    41316        NTSTATUS status;
    42         struct sockaddr_storage ss;
    43317        char addrstr[INET6_ADDRSTRLEN];
    44318        const char *dest_str;
     319        struct tsocket_address *dest_addr;
     320        const struct tsocket_address * const *dest_addrs;
     321        struct netlogon_samlogon_response **responses = NULL;
    45322        int ret;
    46         struct tsocket_address *dest_addr;
    47 
    48         if (!interpret_string_addr_prefer_ipv4(&ss, server, 0)) {
    49                 DEBUG(2,("Failed to resolve[%s] into an address for cldap\n",
    50                         server));
    51                 return false;
    52         }
    53         dest_str = print_sockaddr(addrstr, sizeof(addrstr), &ss);
     323
     324        dest_str = print_sockaddr(addrstr, sizeof(addrstr), ss);
    54325
    55326        ret = tsocket_address_inet_from_strings(mem_ctx, "ip",
     
    63334        }
    64335
    65         /*
    66          * as we use a connected udp socket
    67          */
    68         status = cldap_socket_init(mem_ctx, NULL, NULL, dest_addr, &cldap);
    69         TALLOC_FREE(dest_addr);
     336        dest_addrs = (const struct tsocket_address * const *)&dest_addr;
     337
     338        status = cldap_multi_netlogon(talloc_tos(),
     339                                dest_addrs, 1,
     340                                realm, NULL,
     341                                nt_version, 1,
     342                                timeval_current_ofs(MAX(3,lp_ldap_timeout()/2), 0),
     343                                &responses);
    70344        if (!NT_STATUS_IS_OK(status)) {
    71                 DEBUG(2,("Failed to create cldap socket to %s: %s\n",
    72                          dest_str, nt_errstr(status)));
    73                 return false;
    74         }
    75 
    76         reply = talloc(cldap, struct netlogon_samlogon_response);
    77         if (!reply) {
    78                 goto failed;
    79         }
    80 
    81         /*
    82          * as we use a connected socket, so we don't need to specify the
    83          * destination
    84          */
    85         io.in.dest_address      = NULL;
    86         io.in.dest_port         = 0;
    87         io.in.realm             = realm;
    88         io.in.host              = NULL;
    89         io.in.user              = NULL;
    90         io.in.domain_guid       = NULL;
    91         io.in.domain_sid        = NULL;
    92         io.in.acct_control      = 0;
    93         io.in.version           = nt_version;
    94         io.in.map_response      = false;
    95 
    96         status = cldap_netlogon(cldap, reply, &io);
    97         if (!NT_STATUS_IS_OK(status)) {
    98                 DEBUG(2,("cldap_netlogon() failed: %s\n", nt_errstr(status)));
    99                 goto failed;
    100         }
    101 
    102         *reply = io.out.netlogon;
    103         *_reply = talloc_move(mem_ctx, &reply);
    104         TALLOC_FREE(cldap);
     345                DEBUG(2, ("ads_cldap_netlogon: cldap_multi_netlogon "
     346                          "failed: %s\n", nt_errstr(status)));
     347                return false;
     348        }
     349        if (responses[0] == NULL) {
     350                DEBUG(2, ("ads_cldap_netlogon: did not get a reply\n"));
     351                TALLOC_FREE(responses);
     352                return false;
     353        }
     354        *_reply = talloc_move(mem_ctx, &responses[0]);
     355
    105356        return true;
    106 failed:
    107         TALLOC_FREE(cldap);
    108         return false;
    109357}
    110358
     
    114362
    115363bool ads_cldap_netlogon_5(TALLOC_CTX *mem_ctx,
    116                           const char *server,
     364                          struct sockaddr_storage *ss,
    117365                          const char *realm,
    118366                          struct NETLOGON_SAM_LOGON_RESPONSE_EX *reply5)
     
    122370        bool ret;
    123371
    124         ret = ads_cldap_netlogon(mem_ctx, server, realm, nt_version, &reply);
     372        ret = ads_cldap_netlogon(mem_ctx, ss, realm, nt_version, &reply);
    125373        if (!ret) {
    126374                return false;
Note: See TracChangeset for help on using the changeset viewer.