1efee5fca4677c550febec8f97a36a27e10f84a7
[freeradius.git] / src / main / exec.c
1 /*
2  * exec.c       Execute external programs.
3  *
4  * Version:     $Id$
5  *
6  *   This program is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU General Public License as published by
8  *   the Free Software Foundation; either version 2 of the License, or
9  *   (at your option) any later version.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License
17  *   along with this program; if not, write to the Free Software
18  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2000-2004,2006  The FreeRADIUS server project
21  */
22
23 #include <freeradius-devel/ident.h>
24 RCSID("$Id$")
25
26 #include <freeradius-devel/radiusd.h>
27 #include <freeradius-devel/rad_assert.h>
28
29 #include <sys/file.h>
30
31 #include <fcntl.h>
32 #include <ctype.h>
33 #include <signal.h>
34
35 #ifdef HAVE_SYS_WAIT_H
36 #       include <sys/wait.h>
37 #endif
38 #ifndef WEXITSTATUS
39 #       define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
40 #endif
41 #ifndef WIFEXITED
42 #       define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
43 #endif
44
45 #define MAX_ARGV (256)
46
47 #define USEC 1000000
48 static void tv_sub(struct timeval *end, struct timeval *start,
49                    struct timeval *elapsed)
50 {
51         elapsed->tv_sec = end->tv_sec - start->tv_sec;
52         if (elapsed->tv_sec > 0) {
53                 elapsed->tv_sec--;
54                 elapsed->tv_usec = USEC;
55         } else {
56                 elapsed->tv_usec = 0;
57         }
58         elapsed->tv_usec += end->tv_usec;
59         elapsed->tv_usec -= start->tv_usec;
60         
61         if (elapsed->tv_usec >= USEC) {
62                 elapsed->tv_usec -= USEC;
63                 elapsed->tv_sec++;
64         }
65 }
66
67
68 /*
69  *      Execute a program on successful authentication.
70  *      Return 0 if exec_wait == 0.
71  *      Return the exit code of the called program if exec_wait != 0.
72  *      Return -1 on fork/other errors in the parent process.
73  */
74 int radius_exec_program(const char *cmd, REQUEST *request,
75                         int exec_wait,
76                         char *user_msg, int msg_len,
77                         VALUE_PAIR *input_pairs,
78                         VALUE_PAIR **output_pairs,
79                         int shell_escape)
80 {
81         VALUE_PAIR *vp;
82         char mycmd[1024];
83         const char *from;
84         char *p, *to;
85         int pd[2];
86         pid_t pid, child_pid;
87         int argc = -1;
88         int comma = 0;
89         int status;
90         int i;
91         int n, left, done;
92         char *argv[MAX_ARGV];
93         char answer[4096];
94         char argv_buf[4096];
95 #define MAX_ENVP 1024
96         char *envp[MAX_ENVP];
97         struct timeval start;
98 #ifdef O_NONBLOCK
99         int nonblock = TRUE;
100 #endif
101
102         if (user_msg) *user_msg = '\0';
103         if (output_pairs) *output_pairs = NULL;
104
105         if (strlen(cmd) > (sizeof(mycmd) - 1)) {
106                 radlog(L_ERR|L_CONS, "Command line is too long");
107                 return -1;
108         }
109
110         /*
111          *      Check for bad escapes.
112          */
113         if (cmd[strlen(cmd) - 1] == '\\') {
114                 radlog(L_ERR|L_CONS, "Command line has final backslash, without a following character");
115                 return -1;
116         }
117
118         strlcpy(mycmd, cmd, sizeof(mycmd));
119
120         /*
121          *      Split the string into argv's BEFORE doing radius_xlat...
122          */
123         from = cmd;
124         to = mycmd;
125         argc = 0;
126         while (*from) {
127                 int length;
128
129                 /*
130                  *      Skip spaces.
131                  */
132                 if ((*from == ' ') || (*from == '\t')) {
133                         from++;
134                         continue;
135                 }
136
137                 argv[argc] = to;
138                 argc++;
139
140                 if (argc >= (MAX_ARGV - 1)) break;
141
142                 /*
143                  *      Copy the argv over to our buffer.
144                  */
145                 while (*from && (*from != ' ') && (*from != '\t')) {
146                         if (to >= mycmd + sizeof(mycmd) - 1) {
147                                 return -1; /* ran out of space */
148                         }
149
150                         switch (*from) {
151                         case '"':
152                         case '\'':
153                                 length = rad_copy_string(to, from);
154                                 if (length < 0) {
155                                         radlog(L_ERR|L_CONS, "Invalid string passed as argument for external program");
156                                         return -1;
157                                 }
158                                 from += length;
159                                 to += length;
160                                 break;
161
162                         case '%':
163                                 if (from[1] == '{') {
164                                         *(to++) = *(from++);
165
166                                         length = rad_copy_variable(to, from);
167                                         if (length < 0) {
168                                                 radlog(L_ERR|L_CONS, "Invalid variable expansion passed as argument for external program");
169                                                 return -1;
170                                         }
171                                         from += length;
172                                         to += length;
173                                 } else { /* FIXME: catch %%{ ? */
174                                         *(to++) = *(from++);
175                                 }
176                                 break;
177
178                         default:
179                                 *(to++) = *(from++);
180                         }
181                 } /* end of string, or found a space */
182
183                 *(to++) = '\0'; /* terminate the string */
184         }
185
186         /*
187          *      We have to have SOMETHING, at least.
188          */
189         if (argc <= 0) {
190                 radlog(L_ERR, "Exec-Program: empty command line.");
191                 return -1;
192         }
193
194         /*
195          *      Expand each string, as appropriate.
196          */
197         to = argv_buf;
198         left = sizeof(argv_buf);
199         for (i = 0; i < argc; i++) {
200                 int sublen;
201
202                 /*
203                  *      Don't touch argv's which won't be translated.
204                  */
205                 if (strchr(argv[i], '%') == NULL) continue;
206
207                 if (!request) continue;
208
209                 sublen = radius_xlat(to, left - 1, argv[i], request, NULL);
210                 if (sublen <= 0) {
211                         /*
212                          *      Fail to be backwards compatible.
213                          *
214                          *      It's yucky, but it won't break anything,
215                          *      and it won't cause security problems.
216                          */
217                         sublen = 0;
218                 }
219
220                 argv[i] = to;
221                 to += sublen;
222                 *(to++) = '\0';
223                 left -= sublen;
224                 left--;
225
226                 if (left <= 0) {
227                         radlog(L_ERR, "Exec-Program: Ran out of space while expanding arguments.");
228                         return -1;
229                 }
230         }
231         argv[argc] = NULL;
232
233 #ifndef __MINGW32__
234         /*
235          *      Open a pipe for child/parent communication, if necessary.
236          */
237         if (exec_wait) {
238                 if (pipe(pd) != 0) {
239                         radlog(L_ERR|L_CONS, "Couldn't open pipe: %s",
240                                strerror(errno));
241                         return -1;
242                 }
243         } else {
244                 /*
245                  *      We're not waiting, so we don't look for a
246                  *      message, or VP's.
247                  */
248                 user_msg = NULL;
249                 output_pairs = NULL;
250         }
251
252         envp[0] = NULL;
253
254         if (input_pairs) {
255                 int envlen;
256                 char buffer[1024];
257
258                 /*
259                  *      Set up the environment variables in the
260                  *      parent, so we don't call libc functions that
261                  *      hold mutexes.  They might be locked when we fork,
262                  *      and will remain locked in the child.
263                  */
264                 envlen = 0;
265
266                 for (vp = input_pairs; vp != NULL; vp = vp->next) {
267                         /*
268                          *      Hmm... maybe we shouldn't pass the
269                          *      user's password in an environment
270                          *      variable...
271                          */
272                         snprintf(buffer, sizeof(buffer), "%s=", vp->name);
273                         if (shell_escape) {
274                                 for (p = buffer; *p != '='; p++) {
275                                         if (*p == '-') {
276                                                 *p = '_';
277                                         } else if (isalpha((int) *p)) {
278                                                 *p = toupper(*p);
279                                         }
280                                 }
281                         }
282
283                         n = strlen(buffer);
284                         vp_prints_value(buffer+n, sizeof(buffer) - n, vp, shell_escape);
285
286                         envp[envlen++] = strdup(buffer);
287
288                         /*
289                          *      Don't add too many attributes.
290                          */
291                         if (envlen == (MAX_ENVP - 1)) break;
292                 }
293                 envp[envlen] = NULL;
294         }
295
296         if (exec_wait) {
297                 pid = rad_fork();       /* remember PID */
298         } else {
299                 pid = fork();           /* don't wait */
300         }
301
302         if (pid == 0) {
303                 int devnull;
304
305                 /*
306                  *      Child process.
307                  *
308                  *      We try to be fail-safe here. So if ANYTHING
309                  *      goes wrong, we exit with status 1.
310                  */
311
312                 /*
313                  *      Open STDIN to /dev/null
314                  */
315                 devnull = open("/dev/null", O_RDWR);
316                 if (devnull < 0) {
317                         radlog(L_ERR|L_CONS, "Failed opening /dev/null: %s\n",
318                                strerror(errno));
319                         exit(1);
320                 }
321                 dup2(devnull, STDIN_FILENO);
322
323                 /*
324                  *      Only massage the pipe handles if the parent
325                  *      has created them.
326                  */
327                 if (exec_wait) {
328                         /*
329                          *      pd[0] is the FD the child will read from,
330                          *      which we don't want.
331                          */
332                         if (close(pd[0]) != 0) {
333                                 radlog(L_ERR|L_CONS, "Can't close pipe: %s",
334                                        strerror(errno));
335                                 exit(1);
336                         }
337
338                         /*
339                          *      pd[1] is the FD that the child will write to,
340                          *      so we make it STDOUT.
341                          */
342                         if (dup2(pd[1], STDOUT_FILENO) != 1) {
343                                 radlog(L_ERR|L_CONS, "Can't dup stdout: %s",
344                                        strerror(errno));
345                                 exit(1);
346                         }
347
348                 } else {        /* no pipe, STDOUT should be /dev/null */
349                         dup2(devnull, STDOUT_FILENO);
350                 }
351
352                 /*
353                  *      If we're not debugging, then we can't do
354                  *      anything with the error messages, so we throw
355                  *      them away.
356                  *
357                  *      If we are debugging, then we want the error
358                  *      messages to go to the STDERR of the server.
359                  */
360                 if (debug_flag == 0) {
361                         dup2(devnull, STDERR_FILENO);
362                 }
363                 close(devnull);
364
365                 /*
366                  *      The server may have MANY FD's open.  We don't
367                  *      want to leave dangling FD's for the child process
368                  *      to play funky games with, so we close them.
369                  */
370                 closefrom(3);
371
372                 execve(argv[0], argv, envp);
373                 radlog(L_ERR, "Exec-Program: FAILED to execute %s: %s",
374                        argv[0], strerror(errno));
375                 exit(1);
376         }
377
378         /*
379          *      Free child environment variables
380          */
381         for (i = 0; envp[i] != NULL; i++) {
382                 free(envp[i]);
383         }
384
385         /*
386          *      Parent process.
387          */
388         if (pid < 0) {
389                 radlog(L_ERR|L_CONS, "Couldn't fork %s: %s",
390                        argv[0], strerror(errno));
391                 if (exec_wait) {
392                         close(pd[0]);
393                         close(pd[1]);
394                 }
395                 return -1;
396         }
397
398         /*
399          *      We're not waiting, exit, and ignore any child's status.
400          */
401         if (!exec_wait) {
402                 return 0;
403         }
404
405         /*
406          *      Close the FD to which the child writes it's data.
407          *
408          *      If we can't close it, then we close pd[0], and return an
409          *      error.
410          */
411         if (close(pd[1]) != 0) {
412                 radlog(L_ERR|L_CONS, "Can't close pipe: %s", strerror(errno));
413                 close(pd[0]);
414                 return -1;
415         }
416
417 #ifdef O_NONBLOCK
418         /*
419          *      Try to set it non-blocking.
420          */
421         do {
422                 int flags;
423                 
424                 if ((flags = fcntl(pd[0], F_GETFL, NULL)) < 0)  {
425                         nonblock = FALSE;
426                         break;
427                 }
428                 
429                 flags |= O_NONBLOCK;
430                 if( fcntl(pd[0], F_SETFL, flags) < 0) {
431                         nonblock = FALSE;
432                         break;
433                 }
434         } while (0);
435 #endif
436
437
438         /*
439          *      Read from the pipe until we doesn't get any more or
440          *      until the message is full.
441          */
442         done = 0;
443         left = sizeof(answer) - 1;
444         gettimeofday(&start, NULL);
445         while (1) {
446                 int rcode;
447                 fd_set fds;
448                 struct timeval when, elapsed, wake;
449
450                 FD_ZERO(&fds);
451                 FD_SET(pd[0], &fds);
452
453                 gettimeofday(&when, NULL);
454                 tv_sub(&when, &start, &elapsed);
455                 if (elapsed.tv_sec >= 10) goto too_long;
456                 
457                 when.tv_sec = 10;
458                 when.tv_usec = 0;
459                 tv_sub(&when, &elapsed, &wake);
460
461                 rcode = select(pd[0] + 1, &fds, NULL, NULL, &wake);
462                 if (rcode == 0) {
463                 too_long:
464                         radlog(L_ERR, "Child PID %u is taking too much time: forcing failure and killing child.", pid);
465                         kill(pid, SIGTERM);
466                         close(pd[0]); /* should give SIGPIPE to child, too */
467
468                         /*
469                          *      Clean up the child entry.
470                          */
471                         rad_waitpid(pid, &status);
472                         return 1;                       
473                 }
474                 if (rcode < 0) {
475                         if (errno == EINTR) continue;
476                         break;
477                 }
478
479 #ifdef O_NONBLOCK
480                 /*
481                  *      Read as many bytes as possible.  The kernel
482                  *      will return the number of bytes available.
483                  */
484                 if (nonblock) {
485                         status = read(pd[0], answer + done, left);
486                 } else 
487 #endif
488                         /*
489                          *      There's at least 1 byte ready: read it.
490                          */
491                         status = read(pd[0], answer + done, 1);
492
493                 /*
494                  *      Nothing more to read: stop.
495                  */
496                 if (status == 0) {
497                         break;
498                 }
499
500                 /*
501                  *      Error: See if we have to continue.
502                  */
503                 if (status < 0) {
504                         /*
505                          *      We were interrupted: continue reading.
506                          */
507                         if (errno == EINTR) {
508                                 continue;
509                         }
510
511                         /*
512                          *      There was another error.  Most likely
513                          *      The child process has finished, and
514                          *      exited.
515                          */
516                         break;
517                 }
518
519                 done += status;
520                 left -= status;
521                 if (left <= 0) break;
522         }
523         answer[done] = 0;
524
525         /*
526          *      Make sure that the writer can't block while writing to
527          *      a pipe that no one is reading from anymore.
528          */
529         close(pd[0]);
530
531         DEBUG2("Exec-Program output: %s", answer);
532
533         /*
534          *      Parse the output, if any.
535          */
536         if (done) {
537                 n = T_OP_INVALID;
538                 if (output_pairs) {
539                         /*
540                          *      For backwards compatibility, first check
541                          *      for plain text (user_msg).
542                          */
543                         vp = NULL;
544                         n = userparse(answer, &vp);
545                         if (vp) {
546                                 pairfree(&vp);
547                         }
548                 }
549
550                 if (n == T_OP_INVALID) {
551                         DEBUG("Exec-Program-Wait: plaintext: %s", answer);
552                         if (user_msg) {
553                                 strlcpy(user_msg, answer, msg_len);
554                         }
555                 } else {
556                         /*
557                          *      HACK: Replace '\n' with ',' so that
558                          *      userparse() can parse the buffer in
559                          *      one go (the proper way would be to
560                          *      fix userparse(), but oh well).
561                          */
562                         for (p = answer; *p; p++) {
563                                 if (*p == '\n') {
564                                         *p = comma ? ' ' : ',';
565                                         p++;
566                                         comma = 0;
567                                 }
568                                 if (*p == ',') comma++;
569                         }
570
571                         /*
572                          *      Replace any trailing comma by a NUL.
573                          */
574                         if (answer[strlen(answer) - 1] == ',') {
575                                 answer[strlen(answer) - 1] = '\0';
576                         }
577
578                         radlog(L_DBG,"Exec-Program-Wait: value-pairs: %s", answer);
579                         if (userparse(answer, &vp) == T_OP_INVALID) {
580                                 radlog(L_ERR, "Exec-Program-Wait: %s: unparsable reply", cmd);
581
582                         } else {
583                                 /*
584                                  *      Tell the caller about the value
585                                  *      pairs.
586                                  */
587                                 *output_pairs = vp;
588                         }
589                 } /* else the answer was a set of VP's, not a text message */
590         } /* else we didn't read anything from the child */
591
592         /*
593          *      Call rad_waitpid (should map to waitpid on non-threaded
594          *      or single-server systems).
595          */
596         child_pid = rad_waitpid(pid, &status);
597         if (child_pid == 0) {
598                 radlog(L_DBG, "Exec-Program: Timeout waiting for child");
599                 return 2;
600         }
601
602         if (child_pid == pid) {
603                 if (WIFEXITED(status)) {
604                         status = WEXITSTATUS(status);
605                         radlog(L_DBG, "Exec-Program: returned: %d", status);
606                         return status;
607                 }
608         }
609
610         radlog(L_ERR|L_CONS, "Exec-Program: Abnormal child exit: %s",
611                strerror(errno));
612         return 1;
613 #else
614         msg_len = msg_len;      /* -Wunused */
615
616         if (exec_wait) {
617                 radlog(L_ERR, "Exec-Program-Wait is not supported");
618                 return -1;
619         }
620         
621         /*
622          *      We're not waiting, so we don't look for a
623          *      message, or VP's.
624          */
625         user_msg = NULL;
626         output_pairs = NULL;
627
628         {
629                 /*
630                  *      The _spawn and _exec families of functions are
631                  *      found in Windows compiler libraries for
632                  *      portability from UNIX. There is a variety of
633                  *      functions, including the ability to pass
634                  *      either a list or array of parameters, to
635                  *      search in the PATH or otherwise, and whether
636                  *      or not to pass an environment (a set of
637                  *      environment variables). Using _spawn, you can
638                  *      also specify whether you want the new process
639                  *      to close your program (_P_OVERLAY), to wait
640                  *      until the new process is finished (_P_WAIT) or
641                  *      for the two to run concurrently (_P_NOWAIT).
642                  
643                  *      _spawn and _exec are useful for instances in
644                  *      which you have simple requirements for running
645                  *      the program, don't want the overhead of the
646                  *      Windows header file, or are interested
647                  *      primarily in portability.
648                  */
649
650                 /*
651                  *      FIXME: check return code... what is it?
652                  */
653                 _spawnve(_P_NOWAIT, argv[0], argv, envp);
654         }
655
656         return 0;
657 #endif
658 }