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/nsswitch/wb_common.c

    r860 r988  
    77   Copyright (C) Andrew Tridgell 2000
    88   Copyright (C) Andrew Bartlett 2002
     9   Copyright (C) Matthew Newton 2015
    910
    1011
     
    2728#include "winbind_client.h"
    2829
    29 /* Global variables.  These are effectively the client state information */
    30 
    31 int winbindd_fd = -1;           /* fd for winbindd socket */
    32 static int is_privileged = 0;
     30/* Global context */
     31
     32struct winbindd_context {
     33        int winbindd_fd;        /* winbind file descriptor */
     34        bool is_privileged;     /* using the privileged socket? */
     35        pid_t our_pid;          /* calling process pid */
     36};
     37
     38static struct winbindd_context wb_global_ctx = {
     39        .winbindd_fd = -1,
     40        .is_privileged = 0,
     41        .our_pid = 0
     42};
    3343
    3444/* Free a response structure */
     
    6575/* Close established socket */
    6676
    67 #if HAVE_FUNCTION_ATTRIBUTE_DESTRUCTOR
     77static void winbind_close_sock(struct winbindd_context *ctx)
     78{
     79        if (!ctx) {
     80                return;
     81        }
     82
     83        if (ctx->winbindd_fd != -1) {
     84                close(ctx->winbindd_fd);
     85                ctx->winbindd_fd = -1;
     86        }
     87}
     88
     89/* Destructor for global context to ensure fd is closed */
     90
     91#if HAVE_DESTRUCTOR_ATTRIBUTE
    6892__attribute__((destructor))
    6993#endif
    70 static void winbind_close_sock(void)
    71 {
    72         if (winbindd_fd != -1) {
    73                 close(winbindd_fd);
    74                 winbindd_fd = -1;
    75         }
     94static void winbind_destructor(void)
     95{
     96        winbind_close_sock(&wb_global_ctx);
    7697}
    7798
     
    169190}
    170191
     192/**
     193 * @internal
     194 *
     195 * @brief Check if we talk to the priviliged pipe which should be owned by root.
     196 *
     197 * This checks if we have uid_wrapper running and if this is the case it will
     198 * allow one to connect to the winbind privileged pipe even it is not owned by root.
     199 *
     200 * @param[in]  uid      The uid to check if we can safely talk to the pipe.
     201 *
     202 * @return              If we have access it returns true, else false.
     203 */
     204static bool winbind_privileged_pipe_is_root(uid_t uid)
     205{
     206        if (uid == 0) {
     207                return true;
     208        }
     209
     210        if (uid_wrapper_enabled()) {
     211                return true;
     212        }
     213
     214        return false;
     215}
     216
    171217/* Connect to winbindd socket */
    172218
     
    175221        struct sockaddr_un sunaddr;
    176222        struct stat st;
    177         char *path = NULL;
    178223        int fd;
    179224        int wait_time;
    180225        int slept;
     226        int ret;
    181227
    182228        /* Check permissions on unix socket directory */
     
    187233        }
    188234
     235        /*
     236         * This tells us that the pipe is owned by a privileged
     237         * process, as we will be sending passwords to it.
     238         */
    189239        if (!S_ISDIR(st.st_mode) ||
    190             (st.st_uid != 0 && st.st_uid != geteuid())) {
     240            !winbind_privileged_pipe_is_root(st.st_uid)) {
    191241                errno = ENOENT;
    192242                return -1;
     
    195245        /* Connect to socket */
    196246
    197         if (asprintf(&path, "%s/%s", dir, WINBINDD_SOCKET_NAME) < 0) {
    198                 return -1;
    199         }
    200 
    201         ZERO_STRUCT(sunaddr);
    202         sunaddr.sun_family = AF_UNIX;
    203         strncpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path) - 1);
     247        sunaddr = (struct sockaddr_un) { .sun_family = AF_UNIX };
     248
     249        ret = snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path),
     250                       "%s/%s", dir, WINBINDD_SOCKET_NAME);
     251        if ((ret == -1) || (ret >= sizeof(sunaddr.sun_path))) {
     252                errno = ENAMETOOLONG;
     253                return -1;
     254        }
    204255
    205256        /* If socket file doesn't exist, don't bother trying to connect
     
    207258           the winbindd daemon is not running. */
    208259
    209         if (lstat(path, &st) == -1) {
     260        if (lstat(sunaddr.sun_path, &st) == -1) {
    210261                errno = ENOENT;
    211                 SAFE_FREE(path);
    212                 return -1;
    213         }
    214 
    215         SAFE_FREE(path);
     262                return -1;
     263        }
     264
    216265        /* Check permissions on unix socket file */
    217266
     267        /*
     268         * This tells us that the pipe is owned by a privileged
     269         * process, as we will be sending passwords to it.
     270         */
    218271        if (!S_ISSOCK(st.st_mode) ||
    219             (st.st_uid != 0 && st.st_uid != geteuid())) {
     272            !winbind_privileged_pipe_is_root(st.st_uid)) {
    220273                errno = ENOENT;
    221274                return -1;
     
    237290                        wait_time += slept) {
    238291                struct pollfd pfd;
    239                 int ret;
    240292                int connect_errno = 0;
    241293                socklen_t errnosize;
     
    287339static const char *winbindd_socket_dir(void)
    288340{
    289 #ifdef SOCKET_WRAPPER
    290         const char *env_dir;
    291 
    292         env_dir = getenv(WINBINDD_SOCKET_DIR_ENVVAR);
    293         if (env_dir) {
    294                 return env_dir;
    295         }
    296 #endif
     341        if (nss_wrapper_enabled()) {
     342                const char *env_dir;
     343
     344                env_dir = getenv("SELFTEST_WINBINDD_SOCKET_DIR");
     345                if (env_dir != NULL) {
     346                        return env_dir;
     347                }
     348        }
    297349
    298350        return WINBINDD_SOCKET_DIR;
     
    301353/* Connect to winbindd socket */
    302354
    303 static int winbind_open_pipe_sock(int recursing, int need_priv)
     355static int winbind_open_pipe_sock(struct winbindd_context *ctx,
     356                                  int recursing, int need_priv)
    304357{
    305358#ifdef HAVE_UNIXSOCKET
    306         static pid_t our_pid;
    307359        struct winbindd_request request;
    308360        struct winbindd_response response;
     361
    309362        ZERO_STRUCT(request);
    310363        ZERO_STRUCT(response);
    311364
    312         if (our_pid != getpid()) {
    313                 winbind_close_sock();
    314                 our_pid = getpid();
    315         }
    316 
    317         if ((need_priv != 0) && (is_privileged == 0)) {
    318                 winbind_close_sock();
    319         }
    320 
    321         if (winbindd_fd != -1) {
    322                 return winbindd_fd;
     365        if (!ctx) {
     366                return -1;
     367        }
     368
     369        if (ctx->our_pid != getpid()) {
     370                winbind_close_sock(ctx);
     371                ctx->our_pid = getpid();
     372        }
     373
     374        if ((need_priv != 0) && (ctx->is_privileged == 0)) {
     375                winbind_close_sock(ctx);
     376        }
     377
     378        if (ctx->winbindd_fd != -1) {
     379                return ctx->winbindd_fd;
    323380        }
    324381
     
    327384        }
    328385
    329         if ((winbindd_fd = winbind_named_pipe_sock(winbindd_socket_dir())) == -1) {
    330                 return -1;
    331         }
    332 
    333         is_privileged = 0;
     386        ctx->winbindd_fd = winbind_named_pipe_sock(winbindd_socket_dir());
     387
     388        if (ctx->winbindd_fd == -1) {
     389                return -1;
     390        }
     391
     392        ctx->is_privileged = 0;
    334393
    335394        /* version-check the socket */
    336395
    337396        request.wb_flags = WBFLAG_RECURSE;
    338         if ((winbindd_request_response(WINBINDD_INTERFACE_VERSION, &request, &response) != NSS_STATUS_SUCCESS) || (response.data.interface_version != WINBIND_INTERFACE_VERSION)) {
    339                 winbind_close_sock();
     397        if ((winbindd_request_response(ctx, WINBINDD_INTERFACE_VERSION, &request,
     398                                       &response) != NSS_STATUS_SUCCESS) ||
     399            (response.data.interface_version != WINBIND_INTERFACE_VERSION)) {
     400                winbind_close_sock(ctx);
    340401                return -1;
    341402        }
     
    344405
    345406        request.wb_flags = WBFLAG_RECURSE;
    346         if (winbindd_request_response(WINBINDD_PRIV_PIPE_DIR, &request, &response) == NSS_STATUS_SUCCESS) {
     407
     408        /* Note that response needs to be initialized to avoid
     409         * crashing on clean up after WINBINDD_PRIV_PIPE_DIR call failed
     410         * as interface version (from the first request) returned as a fstring,
     411         * thus response.extra_data.data will not be NULL even though
     412         * winbindd response did not write over it due to a failure */
     413        ZERO_STRUCT(response);
     414        if (winbindd_request_response(ctx, WINBINDD_PRIV_PIPE_DIR, &request,
     415                                      &response) == NSS_STATUS_SUCCESS) {
    347416                int fd;
    348                 if ((fd = winbind_named_pipe_sock((char *)response.extra_data.data)) != -1) {
    349                         close(winbindd_fd);
    350                         winbindd_fd = fd;
    351                         is_privileged = 1;
    352                 }
    353         }
    354 
    355         if ((need_priv != 0) && (is_privileged == 0)) {
     417                fd = winbind_named_pipe_sock((char *)response.extra_data.data);
     418                if (fd != -1) {
     419                        close(ctx->winbindd_fd);
     420                        ctx->winbindd_fd = fd;
     421                        ctx->is_privileged = 1;
     422                }
     423        }
     424
     425        if ((need_priv != 0) && (ctx->is_privileged == 0)) {
    356426                return -1;
    357427        }
     
    359429        SAFE_FREE(response.extra_data.data);
    360430
    361         return winbindd_fd;
     431        return ctx->winbindd_fd;
    362432#else
    363433        return -1;
     
    367437/* Write data to winbindd socket */
    368438
    369 static int winbind_write_sock(void *buffer, int count, int recursing,
    370                               int need_priv)
    371 {
    372         int result, nwritten;
     439static int winbind_write_sock(struct winbindd_context *ctx, void *buffer,
     440                              int count, int recursing, int need_priv)
     441{
     442        int fd, result, nwritten;
    373443
    374444        /* Open connection to winbind daemon */
     
    376446 restart:
    377447
    378         if (winbind_open_pipe_sock(recursing, need_priv) == -1) {
     448        fd = winbind_open_pipe_sock(ctx, recursing, need_priv);
     449        if (fd == -1) {
    379450                errno = ENOENT;
    380451                return -1;
     
    392463                   call would not block by calling poll(). */
    393464
    394                 pfd.fd = winbindd_fd;
     465                pfd.fd = fd;
    395466                pfd.events = POLLIN|POLLOUT|POLLHUP;
    396467
    397468                ret = poll(&pfd, 1, -1);
    398469                if (ret == -1) {
    399                         winbind_close_sock();
     470                        winbind_close_sock(ctx);
    400471                        return -1;                   /* poll error */
    401472                }
     
    407478                        /* Pipe has closed on remote end */
    408479
    409                         winbind_close_sock();
     480                        winbind_close_sock(ctx);
    410481                        goto restart;
    411482                }
     
    413484                /* Do the write */
    414485
    415                 result = write(winbindd_fd,
    416                                (char *)buffer + nwritten,
     486                result = write(fd, (char *)buffer + nwritten,
    417487                               count - nwritten);
    418488
     
    421491                        /* Write failed */
    422492
    423                         winbind_close_sock();
     493                        winbind_close_sock(ctx);
    424494                        return -1;
    425495                }
     
    433503/* Read data from winbindd socket */
    434504
    435 static int winbind_read_sock(void *buffer, int count)
    436 {
     505static int winbind_read_sock(struct winbindd_context *ctx,
     506                             void *buffer, int count)
     507{
     508        int fd;
    437509        int nread = 0;
    438510        int total_time = 0;
    439511
    440         if (winbindd_fd == -1) {
     512        fd = winbind_open_pipe_sock(ctx, false, false);
     513        if (fd == -1) {
    441514                return -1;
    442515        }
     
    450523                   call would not block by calling poll(). */
    451524
    452                 pfd.fd = winbindd_fd;
     525                pfd.fd = fd;
    453526                pfd.events = POLLIN|POLLHUP;
    454527
     
    457530                ret = poll(&pfd, 1, 5000);
    458531                if (ret == -1) {
    459                         winbind_close_sock();
     532                        winbind_close_sock(ctx);
    460533                        return -1;                   /* poll error */
    461534                }
     
    463536                if (ret == 0) {
    464537                        /* Not ready for read yet... */
    465                         if (total_time >= 30) {
     538                        if (total_time >= 300) {
    466539                                /* Timeout */
    467                                 winbind_close_sock();
     540                                winbind_close_sock(ctx);
    468541                                return -1;
    469542                        }
     
    476549                        /* Do the Read */
    477550
    478                         int result = read(winbindd_fd, (char *)buffer + nread,
     551                        int result = read(fd, (char *)buffer + nread,
    479552                              count - nread);
    480553
     
    485558                                   transaction has failed half way through. */
    486559
    487                                 winbind_close_sock();
     560                                winbind_close_sock(ctx);
    488561                                return -1;
    489562                        }
     
    499572/* Read reply */
    500573
    501 static int winbindd_read_reply(struct winbindd_response *response)
     574static int winbindd_read_reply(struct winbindd_context *ctx,
     575                               struct winbindd_response *response)
    502576{
    503577        int result1, result2 = 0;
     
    509583        /* Read fixed length response */
    510584
    511         result1 = winbind_read_sock(response,
     585        result1 = winbind_read_sock(ctx, response,
    512586                                    sizeof(struct winbindd_response));
    513         if (result1 == -1) {
    514                 return -1;
    515         }
    516 
    517         if (response->length < sizeof(struct winbindd_response)) {
    518                 return -1;
    519         }
    520587
    521588        /* We actually send the pointer value of the extra_data field from
     
    525592        response->extra_data.data = NULL;
    526593
     594        if (result1 == -1) {
     595                return -1;
     596        }
     597
     598        if (response->length < sizeof(struct winbindd_response)) {
     599                return -1;
     600        }
     601
    527602        /* Read variable length response */
    528603
     
    537612                }
    538613
    539                 result2 = winbind_read_sock(response->extra_data.data,
     614                result2 = winbind_read_sock(ctx, response->extra_data.data,
    540615                                            extra_data_len);
    541616                if (result2 == -1) {
     
    554629 */
    555630
    556 NSS_STATUS winbindd_send_request(int req_type, int need_priv,
     631NSS_STATUS winbindd_send_request(struct winbindd_context *ctx,
     632                                 int req_type, int need_priv,
    557633                                 struct winbindd_request *request)
    558634{
     
    574650        winbindd_init_request(request, req_type);
    575651
    576         if (winbind_write_sock(request, sizeof(*request),
     652        if (winbind_write_sock(ctx, request, sizeof(*request),
    577653                               request->wb_flags & WBFLAG_RECURSE,
    578654                               need_priv) == -1)
     
    585661
    586662        if ((request->extra_len != 0) &&
    587             (winbind_write_sock(request->extra_data.data,
     663            (winbind_write_sock(ctx, request->extra_data.data,
    588664                                request->extra_len,
    589665                                request->wb_flags & WBFLAG_RECURSE,
     
    603679 */
    604680
    605 NSS_STATUS winbindd_get_response(struct winbindd_response *response)
     681NSS_STATUS winbindd_get_response(struct winbindd_context *ctx,
     682                                 struct winbindd_response *response)
    606683{
    607684        struct winbindd_response lresponse;
     
    615692
    616693        /* Wait for reply */
    617         if (winbindd_read_reply(response) == -1) {
     694        if (winbindd_read_reply(ctx, response) == -1) {
    618695                /* Set ENOENT for consistency.  Required by some apps */
    619696                errno = ENOENT;
     
    637714/* Handle simple types of requests */
    638715
    639 NSS_STATUS winbindd_request_response(int req_type,
    640                             struct winbindd_request *request,
    641                             struct winbindd_response *response)
     716NSS_STATUS winbindd_request_response(struct winbindd_context *ctx,
     717                                     int req_type,
     718                                     struct winbindd_request *request,
     719                                     struct winbindd_response *response)
    642720{
    643721        NSS_STATUS status = NSS_STATUS_UNAVAIL;
    644         int count = 0;
    645 
    646         while ((status == NSS_STATUS_UNAVAIL) && (count < 10)) {
    647                 status = winbindd_send_request(req_type, 0, request);
    648                 if (status != NSS_STATUS_SUCCESS)
    649                         return(status);
    650                 status = winbindd_get_response(response);
    651                 count += 1;
    652         }
     722        struct winbindd_context *wb_ctx = ctx;
     723
     724        if (ctx == NULL) {
     725                wb_ctx = &wb_global_ctx;
     726        }
     727
     728        status = winbindd_send_request(wb_ctx, req_type, 0, request);
     729        if (status != NSS_STATUS_SUCCESS)
     730                return (status);
     731        status = winbindd_get_response(wb_ctx, response);
    653732
    654733        return status;
    655734}
    656735
    657 NSS_STATUS winbindd_priv_request_response(int req_type,
     736NSS_STATUS winbindd_priv_request_response(struct winbindd_context *ctx,
     737                                          int req_type,
    658738                                          struct winbindd_request *request,
    659739                                          struct winbindd_response *response)
    660740{
    661741        NSS_STATUS status = NSS_STATUS_UNAVAIL;
    662         int count = 0;
    663 
    664         while ((status == NSS_STATUS_UNAVAIL) && (count < 10)) {
    665                 status = winbindd_send_request(req_type, 1, request);
    666                 if (status != NSS_STATUS_SUCCESS)
    667                         return(status);
    668                 status = winbindd_get_response(response);
    669                 count += 1;
    670         }
     742        struct winbindd_context *wb_ctx = ctx;
     743
     744        if (ctx == NULL) {
     745                wb_ctx = &wb_global_ctx;
     746        }
     747
     748        status = winbindd_send_request(wb_ctx, req_type, 1, request);
     749        if (status != NSS_STATUS_SUCCESS)
     750                return (status);
     751        status = winbindd_get_response(wb_ctx, response);
    671752
    672753        return status;
    673754}
     755
     756/* Create and free winbindd context */
     757
     758struct winbindd_context *winbindd_ctx_create(void)
     759{
     760        struct winbindd_context *ctx;
     761
     762        ctx = calloc(1, sizeof(struct winbindd_context));
     763
     764        if (!ctx) {
     765                return NULL;
     766        }
     767
     768        ctx->winbindd_fd = -1;
     769
     770        return ctx;
     771}
     772
     773void winbindd_ctx_free(struct winbindd_context *ctx)
     774{
     775        winbind_close_sock(ctx);
     776        free(ctx);
     777}
Note: See TracChangeset for help on using the changeset viewer.