nsswitch: protect access to wb_global_ctx by a mutex
[samba.git] / nsswitch / wb_common.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    winbind client common code
5
6    Copyright (C) Tim Potter 2000
7    Copyright (C) Andrew Tridgell 2000
8    Copyright (C) Andrew Bartlett 2002
9    Copyright (C) Matthew Newton 2015
10
11
12    This library is free software; you can redistribute it and/or
13    modify it under the terms of the GNU Lesser General Public
14    License as published by the Free Software Foundation; either
15    version 3 of the License, or (at your option) any later version.
16
17    This library is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20    Library General Public License for more details.
21
22    You should have received a copy of the GNU Lesser General Public License
23    along with this program.  If not, see <http://www.gnu.org/licenses/>.
24 */
25
26 #include "replace.h"
27 #include "system/select.h"
28 #include "winbind_client.h"
29
30 #if HAVE_PTHREAD_H
31 #include <pthread.h>
32 #endif
33
34 /* Global context */
35
36 struct winbindd_context {
37         int winbindd_fd;        /* winbind file descriptor */
38         bool is_privileged;     /* using the privileged socket? */
39         pid_t our_pid;          /* calling process pid */
40 };
41
42 #if HAVE_PTHREAD
43 static pthread_mutex_t wb_global_ctx_mutex = PTHREAD_MUTEX_INITIALIZER;
44 #endif
45
46 static struct winbindd_context *get_wb_global_ctx(void)
47 {
48         static struct winbindd_context wb_global_ctx = {
49                 .winbindd_fd = -1,
50                 .is_privileged = false,
51                 .our_pid = 0
52         };
53
54 #if HAVE_PTHREAD
55         pthread_mutex_lock(&wb_global_ctx_mutex);
56 #endif
57         return &wb_global_ctx;
58 }
59
60 static void put_wb_global_ctx(void)
61 {
62 #if HAVE_PTHREAD
63         pthread_mutex_unlock(&wb_global_ctx_mutex);
64 #endif
65         return;
66 }
67
68 /* Free a response structure */
69
70 void winbindd_free_response(struct winbindd_response *response)
71 {
72         /* Free any allocated extra_data */
73
74         if (response)
75                 SAFE_FREE(response->extra_data.data);
76 }
77
78 /* Initialise a request structure */
79
80 static void winbindd_init_request(struct winbindd_request *request,
81                                   int request_type)
82 {
83         request->length = sizeof(struct winbindd_request);
84
85         request->cmd = (enum winbindd_cmd)request_type;
86         request->pid = getpid();
87
88 }
89
90 /* Initialise a response structure */
91
92 static void init_response(struct winbindd_response *response)
93 {
94         /* Initialise return value */
95
96         response->result = WINBINDD_ERROR;
97 }
98
99 /* Close established socket */
100
101 static void winbind_close_sock(struct winbindd_context *ctx)
102 {
103         if (!ctx) {
104                 return;
105         }
106
107         if (ctx->winbindd_fd != -1) {
108                 close(ctx->winbindd_fd);
109                 ctx->winbindd_fd = -1;
110         }
111 }
112
113 /* Destructor for global context to ensure fd is closed */
114
115 #if HAVE_DESTRUCTOR_ATTRIBUTE
116 __attribute__((destructor))
117 #endif
118 static void winbind_destructor(void)
119 {
120         struct winbindd_context *ctx;
121
122         ctx = get_wb_global_ctx();
123         winbind_close_sock(ctx);
124         put_wb_global_ctx();
125 }
126
127 #define CONNECT_TIMEOUT 30
128
129 /* Make sure socket handle isn't stdin, stdout or stderr */
130 #define RECURSION_LIMIT 3
131
132 static int make_nonstd_fd_internals(int fd, int limit /* Recursion limiter */)
133 {
134         int new_fd;
135         if (fd >= 0 && fd <= 2) {
136 #ifdef F_DUPFD
137                 if ((new_fd = fcntl(fd, F_DUPFD, 3)) == -1) {
138                         return -1;
139                 }
140                 /* Paranoia */
141                 if (new_fd < 3) {
142                         close(new_fd);
143                         return -1;
144                 }
145                 close(fd);
146                 return new_fd;
147 #else
148                 if (limit <= 0)
149                         return -1;
150
151                 new_fd = dup(fd);
152                 if (new_fd == -1)
153                         return -1;
154
155                 /* use the program stack to hold our list of FDs to close */
156                 new_fd = make_nonstd_fd_internals(new_fd, limit - 1);
157                 close(fd);
158                 return new_fd;
159 #endif
160         }
161         return fd;
162 }
163
164 /****************************************************************************
165  Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
166  else
167  if SYSV use O_NDELAY
168  if BSD use FNDELAY
169  Set close on exec also.
170 ****************************************************************************/
171
172 static int make_safe_fd(int fd)
173 {
174         int result, flags;
175         int new_fd = make_nonstd_fd_internals(fd, RECURSION_LIMIT);
176         if (new_fd == -1) {
177                 close(fd);
178                 return -1;
179         }
180
181         /* Socket should be nonblocking. */
182 #ifdef O_NONBLOCK
183 #define FLAG_TO_SET O_NONBLOCK
184 #else
185 #ifdef SYSV
186 #define FLAG_TO_SET O_NDELAY
187 #else /* BSD */
188 #define FLAG_TO_SET FNDELAY
189 #endif
190 #endif
191
192         if ((flags = fcntl(new_fd, F_GETFL)) == -1) {
193                 close(new_fd);
194                 return -1;
195         }
196
197         flags |= FLAG_TO_SET;
198         if (fcntl(new_fd, F_SETFL, flags) == -1) {
199                 close(new_fd);
200                 return -1;
201         }
202
203 #undef FLAG_TO_SET
204
205         /* Socket should be closed on exec() */
206 #ifdef FD_CLOEXEC
207         result = flags = fcntl(new_fd, F_GETFD, 0);
208         if (flags >= 0) {
209                 flags |= FD_CLOEXEC;
210                 result = fcntl( new_fd, F_SETFD, flags );
211         }
212         if (result < 0) {
213                 close(new_fd);
214                 return -1;
215         }
216 #endif
217         return new_fd;
218 }
219
220 /**
221  * @internal
222  *
223  * @brief Check if we talk to the priviliged pipe which should be owned by root.
224  *
225  * This checks if we have uid_wrapper running and if this is the case it will
226  * allow one to connect to the winbind privileged pipe even it is not owned by root.
227  *
228  * @param[in]  uid      The uid to check if we can safely talk to the pipe.
229  *
230  * @return              If we have access it returns true, else false.
231  */
232 static bool winbind_privileged_pipe_is_root(uid_t uid)
233 {
234         if (uid == 0) {
235                 return true;
236         }
237
238         if (uid_wrapper_enabled()) {
239                 return true;
240         }
241
242         return false;
243 }
244
245 /* Connect to winbindd socket */
246
247 static int winbind_named_pipe_sock(const char *dir)
248 {
249         struct sockaddr_un sunaddr;
250         struct stat st;
251         int fd;
252         int wait_time;
253         int slept;
254         int ret;
255
256         /* Check permissions on unix socket directory */
257
258         if (lstat(dir, &st) == -1) {
259                 errno = ENOENT;
260                 return -1;
261         }
262
263         /*
264          * This tells us that the pipe is owned by a privileged
265          * process, as we will be sending passwords to it.
266          */
267         if (!S_ISDIR(st.st_mode) ||
268             !winbind_privileged_pipe_is_root(st.st_uid)) {
269                 errno = ENOENT;
270                 return -1;
271         }
272
273         /* Connect to socket */
274
275         sunaddr = (struct sockaddr_un) { .sun_family = AF_UNIX };
276
277         ret = snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path),
278                        "%s/%s", dir, WINBINDD_SOCKET_NAME);
279         if ((ret == -1) || (ret >= sizeof(sunaddr.sun_path))) {
280                 errno = ENAMETOOLONG;
281                 return -1;
282         }
283
284         /* If socket file doesn't exist, don't bother trying to connect
285            with retry.  This is an attempt to make the system usable when
286            the winbindd daemon is not running. */
287
288         if (lstat(sunaddr.sun_path, &st) == -1) {
289                 errno = ENOENT;
290                 return -1;
291         }
292
293         /* Check permissions on unix socket file */
294
295         /*
296          * This tells us that the pipe is owned by a privileged
297          * process, as we will be sending passwords to it.
298          */
299         if (!S_ISSOCK(st.st_mode) ||
300             !winbind_privileged_pipe_is_root(st.st_uid)) {
301                 errno = ENOENT;
302                 return -1;
303         }
304
305         /* Connect to socket */
306
307         if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
308                 return -1;
309         }
310
311         /* Set socket non-blocking and close on exec. */
312
313         if ((fd = make_safe_fd( fd)) == -1) {
314                 return fd;
315         }
316
317         for (wait_time = 0; connect(fd, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1;
318                         wait_time += slept) {
319                 struct pollfd pfd;
320                 int connect_errno = 0;
321                 socklen_t errnosize;
322
323                 if (wait_time >= CONNECT_TIMEOUT)
324                         goto error_out;
325
326                 switch (errno) {
327                         case EINPROGRESS:
328                                 pfd.fd = fd;
329                                 pfd.events = POLLOUT;
330
331                                 ret = poll(&pfd, 1, (CONNECT_TIMEOUT - wait_time) * 1000);
332
333                                 if (ret > 0) {
334                                         errnosize = sizeof(connect_errno);
335
336                                         ret = getsockopt(fd, SOL_SOCKET,
337                                                         SO_ERROR, &connect_errno, &errnosize);
338
339                                         if (ret >= 0 && connect_errno == 0) {
340                                                 /* Connect succeed */
341                                                 goto out;
342                                         }
343                                 }
344
345                                 slept = CONNECT_TIMEOUT;
346                                 break;
347                         case EAGAIN:
348                                 slept = rand() % 3 + 1;
349                                 sleep(slept);
350                                 break;
351                         default:
352                                 goto error_out;
353                 }
354
355         }
356
357   out:
358
359         return fd;
360
361   error_out:
362
363         close(fd);
364         return -1;
365 }
366
367 static const char *winbindd_socket_dir(void)
368 {
369         if (nss_wrapper_enabled()) {
370                 const char *env_dir;
371
372                 env_dir = getenv("SELFTEST_WINBINDD_SOCKET_DIR");
373                 if (env_dir != NULL) {
374                         return env_dir;
375                 }
376         }
377
378         return WINBINDD_SOCKET_DIR;
379 }
380
381 /* Connect to winbindd socket */
382
383 static int winbind_open_pipe_sock(struct winbindd_context *ctx,
384                                   int recursing, int need_priv)
385 {
386 #ifdef HAVE_UNIXSOCKET
387         struct winbindd_request request;
388         struct winbindd_response response;
389
390         ZERO_STRUCT(request);
391         ZERO_STRUCT(response);
392
393         if (!ctx) {
394                 return -1;
395         }
396
397         if (ctx->our_pid != getpid()) {
398                 winbind_close_sock(ctx);
399                 ctx->our_pid = getpid();
400         }
401
402         if ((need_priv != 0) && !ctx->is_privileged) {
403                 winbind_close_sock(ctx);
404         }
405
406         if (ctx->winbindd_fd != -1) {
407                 return ctx->winbindd_fd;
408         }
409
410         if (recursing) {
411                 return -1;
412         }
413
414         ctx->winbindd_fd = winbind_named_pipe_sock(winbindd_socket_dir());
415
416         if (ctx->winbindd_fd == -1) {
417                 return -1;
418         }
419
420         ctx->is_privileged = false;
421
422         /* version-check the socket */
423
424         request.wb_flags = WBFLAG_RECURSE;
425         if ((winbindd_request_response(ctx, WINBINDD_INTERFACE_VERSION, &request,
426                                        &response) != NSS_STATUS_SUCCESS) ||
427             (response.data.interface_version != WINBIND_INTERFACE_VERSION)) {
428                 winbind_close_sock(ctx);
429                 return -1;
430         }
431
432         if (need_priv == 0) {
433                 return ctx->winbindd_fd;
434         }
435
436         /* try and get priv pipe */
437
438         request.wb_flags = WBFLAG_RECURSE;
439
440         /* Note that response needs to be initialized to avoid
441          * crashing on clean up after WINBINDD_PRIV_PIPE_DIR call failed
442          * as interface version (from the first request) returned as a fstring,
443          * thus response.extra_data.data will not be NULL even though
444          * winbindd response did not write over it due to a failure */
445         ZERO_STRUCT(response);
446         if (winbindd_request_response(ctx, WINBINDD_PRIV_PIPE_DIR, &request,
447                                       &response) == NSS_STATUS_SUCCESS) {
448                 int fd;
449                 fd = winbind_named_pipe_sock((char *)response.extra_data.data);
450                 if (fd != -1) {
451                         close(ctx->winbindd_fd);
452                         ctx->winbindd_fd = fd;
453                         ctx->is_privileged = true;
454                 }
455
456                 SAFE_FREE(response.extra_data.data);
457         }
458
459         if (!ctx->is_privileged) {
460                 return -1;
461         }
462
463         return ctx->winbindd_fd;
464 #else
465         return -1;
466 #endif /* HAVE_UNIXSOCKET */
467 }
468
469 /* Write data to winbindd socket */
470
471 static int winbind_write_sock(struct winbindd_context *ctx, void *buffer,
472                               int count, int recursing, int need_priv)
473 {
474         int fd, result, nwritten;
475
476         /* Open connection to winbind daemon */
477
478  restart:
479
480         fd = winbind_open_pipe_sock(ctx, recursing, need_priv);
481         if (fd == -1) {
482                 errno = ENOENT;
483                 return -1;
484         }
485
486         /* Write data to socket */
487
488         nwritten = 0;
489
490         while(nwritten < count) {
491                 struct pollfd pfd;
492                 int ret;
493
494                 /* Catch pipe close on other end by checking if a read()
495                    call would not block by calling poll(). */
496
497                 pfd.fd = fd;
498                 pfd.events = POLLIN|POLLOUT|POLLHUP;
499
500                 ret = poll(&pfd, 1, -1);
501                 if (ret == -1) {
502                         winbind_close_sock(ctx);
503                         return -1;                   /* poll error */
504                 }
505
506                 /* Write should be OK if fd not available for reading */
507
508                 if ((ret == 1) && (pfd.revents & (POLLIN|POLLHUP|POLLERR))) {
509
510                         /* Pipe has closed on remote end */
511
512                         winbind_close_sock(ctx);
513                         goto restart;
514                 }
515
516                 /* Do the write */
517
518                 result = write(fd, (char *)buffer + nwritten,
519                                count - nwritten);
520
521                 if ((result == -1) || (result == 0)) {
522
523                         /* Write failed */
524
525                         winbind_close_sock(ctx);
526                         return -1;
527                 }
528
529                 nwritten += result;
530         }
531
532         return nwritten;
533 }
534
535 /* Read data from winbindd socket */
536
537 static int winbind_read_sock(struct winbindd_context *ctx,
538                              void *buffer, int count)
539 {
540         int fd;
541         int nread = 0;
542         int total_time = 0;
543
544         fd = winbind_open_pipe_sock(ctx, false, false);
545         if (fd == -1) {
546                 return -1;
547         }
548
549         /* Read data from socket */
550         while(nread < count) {
551                 struct pollfd pfd;
552                 int ret;
553
554                 /* Catch pipe close on other end by checking if a read()
555                    call would not block by calling poll(). */
556
557                 pfd.fd = fd;
558                 pfd.events = POLLIN|POLLHUP;
559
560                 /* Wait for 5 seconds for a reply. May need to parameterise this... */
561
562                 ret = poll(&pfd, 1, 5000);
563                 if (ret == -1) {
564                         winbind_close_sock(ctx);
565                         return -1;                   /* poll error */
566                 }
567
568                 if (ret == 0) {
569                         /* Not ready for read yet... */
570                         if (total_time >= 300) {
571                                 /* Timeout */
572                                 winbind_close_sock(ctx);
573                                 return -1;
574                         }
575                         total_time += 5;
576                         continue;
577                 }
578
579                 if ((ret == 1) && (pfd.revents & (POLLIN|POLLHUP|POLLERR))) {
580
581                         /* Do the Read */
582
583                         int result = read(fd, (char *)buffer + nread,
584                               count - nread);
585
586                         if ((result == -1) || (result == 0)) {
587
588                                 /* Read failed.  I think the only useful thing we
589                                    can do here is just return -1 and fail since the
590                                    transaction has failed half way through. */
591
592                                 winbind_close_sock(ctx);
593                                 return -1;
594                         }
595
596                         nread += result;
597
598                 }
599         }
600
601         return nread;
602 }
603
604 /* Read reply */
605
606 static int winbindd_read_reply(struct winbindd_context *ctx,
607                                struct winbindd_response *response)
608 {
609         int result1, result2 = 0;
610
611         if (!response) {
612                 return -1;
613         }
614
615         /* Read fixed length response */
616
617         result1 = winbind_read_sock(ctx, response,
618                                     sizeof(struct winbindd_response));
619
620         /* We actually send the pointer value of the extra_data field from
621            the server.  This has no meaning in the client's address space
622            so we clear it out. */
623
624         response->extra_data.data = NULL;
625
626         if (result1 == -1) {
627                 return -1;
628         }
629
630         if (response->length < sizeof(struct winbindd_response)) {
631                 return -1;
632         }
633
634         /* Read variable length response */
635
636         if (response->length > sizeof(struct winbindd_response)) {
637                 int extra_data_len = response->length -
638                         sizeof(struct winbindd_response);
639
640                 /* Mallocate memory for extra data */
641
642                 if (!(response->extra_data.data = malloc(extra_data_len))) {
643                         return -1;
644                 }
645
646                 result2 = winbind_read_sock(ctx, response->extra_data.data,
647                                             extra_data_len);
648                 if (result2 == -1) {
649                         winbindd_free_response(response);
650                         return -1;
651                 }
652         }
653
654         /* Return total amount of data read */
655
656         return result1 + result2;
657 }
658
659 /*
660  * send simple types of requests
661  */
662
663 static NSS_STATUS winbindd_send_request(
664         struct winbindd_context *ctx,
665         int req_type,
666         int need_priv,
667         struct winbindd_request *request)
668 {
669         struct winbindd_request lrequest;
670
671         /* Check for our tricky environment variable */
672
673         if (winbind_env_set()) {
674                 return NSS_STATUS_NOTFOUND;
675         }
676
677         if (!request) {
678                 ZERO_STRUCT(lrequest);
679                 request = &lrequest;
680         }
681
682         /* Fill in request and send down pipe */
683
684         winbindd_init_request(request, req_type);
685
686         if (winbind_write_sock(ctx, request, sizeof(*request),
687                                request->wb_flags & WBFLAG_RECURSE,
688                                need_priv) == -1)
689         {
690                 /* Set ENOENT for consistency.  Required by some apps */
691                 errno = ENOENT;
692
693                 return NSS_STATUS_UNAVAIL;
694         }
695
696         if ((request->extra_len != 0) &&
697             (winbind_write_sock(ctx, request->extra_data.data,
698                                 request->extra_len,
699                                 request->wb_flags & WBFLAG_RECURSE,
700                                 need_priv) == -1))
701         {
702                 /* Set ENOENT for consistency.  Required by some apps */
703                 errno = ENOENT;
704
705                 return NSS_STATUS_UNAVAIL;
706         }
707
708         return NSS_STATUS_SUCCESS;
709 }
710
711 /*
712  * Get results from winbindd request
713  */
714
715 static NSS_STATUS winbindd_get_response(struct winbindd_context *ctx,
716                                         struct winbindd_response *response)
717 {
718         struct winbindd_response lresponse;
719
720         if (!response) {
721                 ZERO_STRUCT(lresponse);
722                 response = &lresponse;
723         }
724
725         init_response(response);
726
727         /* Wait for reply */
728         if (winbindd_read_reply(ctx, response) == -1) {
729                 /* Set ENOENT for consistency.  Required by some apps */
730                 errno = ENOENT;
731
732                 return NSS_STATUS_UNAVAIL;
733         }
734
735         /* Throw away extra data if client didn't request it */
736         if (response == &lresponse) {
737                 winbindd_free_response(response);
738         }
739
740         /* Copy reply data from socket */
741         if (response->result != WINBINDD_OK) {
742                 return NSS_STATUS_NOTFOUND;
743         }
744
745         return NSS_STATUS_SUCCESS;
746 }
747
748 /* Handle simple types of requests */
749
750 NSS_STATUS winbindd_request_response(struct winbindd_context *ctx,
751                                      int req_type,
752                                      struct winbindd_request *request,
753                                      struct winbindd_response *response)
754 {
755         NSS_STATUS status = NSS_STATUS_UNAVAIL;
756         bool release_global_ctx = false;
757
758         if (ctx == NULL) {
759                 ctx = get_wb_global_ctx();
760                 release_global_ctx = true;
761         }
762
763         status = winbindd_send_request(ctx, req_type, 0, request);
764         if (status != NSS_STATUS_SUCCESS) {
765                 goto out;
766         }
767         status = winbindd_get_response(ctx, response);
768
769 out:
770         if (release_global_ctx) {
771                 put_wb_global_ctx();
772         }
773         return status;
774 }
775
776 NSS_STATUS winbindd_priv_request_response(struct winbindd_context *ctx,
777                                           int req_type,
778                                           struct winbindd_request *request,
779                                           struct winbindd_response *response)
780 {
781         NSS_STATUS status = NSS_STATUS_UNAVAIL;
782         bool release_global_ctx = false;
783
784         if (ctx == NULL) {
785                 ctx = get_wb_global_ctx();
786                 release_global_ctx = true;
787         }
788
789         status = winbindd_send_request(ctx, req_type, 1, request);
790         if (status != NSS_STATUS_SUCCESS) {
791                 goto out;
792         }
793         status = winbindd_get_response(ctx, response);
794
795 out:
796         if (release_global_ctx) {
797                 put_wb_global_ctx();
798         }
799         return status;
800 }
801
802 /* Create and free winbindd context */
803
804 struct winbindd_context *winbindd_ctx_create(void)
805 {
806         struct winbindd_context *ctx;
807
808         ctx = calloc(1, sizeof(struct winbindd_context));
809
810         if (!ctx) {
811                 return NULL;
812         }
813
814         ctx->winbindd_fd = -1;
815
816         return ctx;
817 }
818
819 void winbindd_ctx_free(struct winbindd_context *ctx)
820 {
821         winbind_close_sock(ctx);
822         free(ctx);
823 }