1c2aa98e2SPeter Wemm /*
25dd76dd0SGregory Neil Shapiro * Copyright (c) 1998-2004 Proofpoint, Inc. and its suppliers.
33299c2f1SGregory Neil Shapiro * All rights reserved.
4c2aa98e2SPeter Wemm * Copyright (c) 1993 Eric P. Allman. All rights reserved.
5c2aa98e2SPeter Wemm * Copyright (c) 1993
6c2aa98e2SPeter Wemm * The Regents of the University of California. All rights reserved.
7c2aa98e2SPeter Wemm *
8c2aa98e2SPeter Wemm * By using this file, you agree to the terms and conditions set
9c2aa98e2SPeter Wemm * forth in the LICENSE file which can be found at the top level of
10c2aa98e2SPeter Wemm * the sendmail distribution.
11c2aa98e2SPeter Wemm *
12c2aa98e2SPeter Wemm */
13c2aa98e2SPeter Wemm
1412ed1c7cSGregory Neil Shapiro #include <sm/gen.h>
1512ed1c7cSGregory Neil Shapiro
1612ed1c7cSGregory Neil Shapiro SM_IDSTR(copyright,
175dd76dd0SGregory Neil Shapiro "@(#) Copyright (c) 1998-2004 Proofpoint, Inc. and its suppliers.\n\
183299c2f1SGregory Neil Shapiro All rights reserved.\n\
193299c2f1SGregory Neil Shapiro Copyright (c) 1993 Eric P. Allman. All rights reserved.\n\
203299c2f1SGregory Neil Shapiro Copyright (c) 1993\n\
2112ed1c7cSGregory Neil Shapiro The Regents of the University of California. All rights reserved.\n")
223299c2f1SGregory Neil Shapiro
234313cc83SGregory Neil Shapiro SM_IDSTR(id, "@(#)$Id: smrsh.c,v 8.66 2013-11-22 20:52:00 ca Exp $")
243299c2f1SGregory Neil Shapiro
25c2aa98e2SPeter Wemm /*
26c2aa98e2SPeter Wemm ** SMRSH -- sendmail restricted shell
27c2aa98e2SPeter Wemm **
28c2aa98e2SPeter Wemm ** This is a patch to get around the prog mailer bugs in most
29c2aa98e2SPeter Wemm ** versions of sendmail.
30c2aa98e2SPeter Wemm **
31c2aa98e2SPeter Wemm ** Use this in place of /bin/sh in the "prog" mailer definition
32c2aa98e2SPeter Wemm ** in your sendmail.cf file. You then create CMDDIR (owned by
33c2aa98e2SPeter Wemm ** root, mode 755) and put links to any programs you want
34c2aa98e2SPeter Wemm ** available to prog mailers in that directory. This should
35c2aa98e2SPeter Wemm ** include things like "vacation" and "procmail", but not "sed"
36c2aa98e2SPeter Wemm ** or "sh".
37c2aa98e2SPeter Wemm **
38c2aa98e2SPeter Wemm ** Leading pathnames are stripped from program names so that
39c2aa98e2SPeter Wemm ** existing .forward files that reference things like
401bceb5b2SPeter Wemm ** "/usr/bin/vacation" will continue to work.
41c2aa98e2SPeter Wemm **
42c2aa98e2SPeter Wemm ** The following characters are completely illegal:
433299c2f1SGregory Neil Shapiro ** < > ^ & ` ( ) \n \r
443299c2f1SGregory Neil Shapiro ** The following characters are sometimes illegal:
453299c2f1SGregory Neil Shapiro ** | &
46c2aa98e2SPeter Wemm ** This is more restrictive than strictly necessary.
47c2aa98e2SPeter Wemm **
483299c2f1SGregory Neil Shapiro ** To use this, add FEATURE(`smrsh') to your .mc file.
49c2aa98e2SPeter Wemm **
50c2aa98e2SPeter Wemm ** This can be used on any version of sendmail.
51c2aa98e2SPeter Wemm **
52c2aa98e2SPeter Wemm ** In loving memory of RTM. 11/02/93.
53c2aa98e2SPeter Wemm */
54c2aa98e2SPeter Wemm
55c2aa98e2SPeter Wemm #include <unistd.h>
5612ed1c7cSGregory Neil Shapiro #include <sm/io.h>
5788ad41d4SGregory Neil Shapiro #include <sm/limits.h>
5812ed1c7cSGregory Neil Shapiro #include <sm/string.h>
59c2aa98e2SPeter Wemm #include <sys/file.h>
60509cae37SGregory Neil Shapiro #include <sys/types.h>
61509cae37SGregory Neil Shapiro #include <sys/stat.h>
62c2aa98e2SPeter Wemm #include <string.h>
63c2aa98e2SPeter Wemm #include <ctype.h>
643299c2f1SGregory Neil Shapiro #include <errno.h>
65c2aa98e2SPeter Wemm #ifdef EX_OK
66c2aa98e2SPeter Wemm # undef EX_OK
67*5b0945b5SGregory Neil Shapiro #endif
68c2aa98e2SPeter Wemm #include <sysexits.h>
69c2aa98e2SPeter Wemm #include <syslog.h>
70c2aa98e2SPeter Wemm #include <stdlib.h>
71c2aa98e2SPeter Wemm
7212ed1c7cSGregory Neil Shapiro #include <sm/conf.h>
7312ed1c7cSGregory Neil Shapiro #include <sm/errstring.h>
743299c2f1SGregory Neil Shapiro
75c2aa98e2SPeter Wemm /* directory in which all commands must reside */
76c2aa98e2SPeter Wemm #ifndef CMDDIR
7712ed1c7cSGregory Neil Shapiro # ifdef SMRSH_CMDDIR
7812ed1c7cSGregory Neil Shapiro # define CMDDIR SMRSH_CMDDIR
79*5b0945b5SGregory Neil Shapiro # else
8012ed1c7cSGregory Neil Shapiro # define CMDDIR "/usr/adm/sm.bin"
81*5b0945b5SGregory Neil Shapiro # endif
823299c2f1SGregory Neil Shapiro #endif /* ! CMDDIR */
83c2aa98e2SPeter Wemm
84c2aa98e2SPeter Wemm /* characters disallowed in the shell "-c" argument */
85c2aa98e2SPeter Wemm #define SPECIALS "<|>^();&`$\r\n"
86c2aa98e2SPeter Wemm
87c2aa98e2SPeter Wemm /* default search path */
88c2aa98e2SPeter Wemm #ifndef PATH
8912ed1c7cSGregory Neil Shapiro # ifdef SMRSH_PATH
9012ed1c7cSGregory Neil Shapiro # define PATH SMRSH_PATH
91*5b0945b5SGregory Neil Shapiro # else
9212ed1c7cSGregory Neil Shapiro # define PATH "/bin:/usr/bin:/usr/ucb"
93*5b0945b5SGregory Neil Shapiro # endif
943299c2f1SGregory Neil Shapiro #endif /* ! PATH */
953299c2f1SGregory Neil Shapiro
963299c2f1SGregory Neil Shapiro char newcmdbuf[1000];
973299c2f1SGregory Neil Shapiro char *prg, *par;
983299c2f1SGregory Neil Shapiro
99684b2a5fSGregory Neil Shapiro static void addcmd __P((char *, bool, size_t));
100684b2a5fSGregory Neil Shapiro
1013299c2f1SGregory Neil Shapiro /*
1023299c2f1SGregory Neil Shapiro ** ADDCMD -- add a string to newcmdbuf, check for overflow
1033299c2f1SGregory Neil Shapiro **
1043299c2f1SGregory Neil Shapiro ** Parameters:
1053299c2f1SGregory Neil Shapiro ** s -- string to add
1063299c2f1SGregory Neil Shapiro ** cmd -- it's a command: prepend CMDDIR/
1073299c2f1SGregory Neil Shapiro ** len -- length of string to add
1083299c2f1SGregory Neil Shapiro **
1093299c2f1SGregory Neil Shapiro ** Side Effects:
1103299c2f1SGregory Neil Shapiro ** changes newcmdbuf or exits with a failure.
1113299c2f1SGregory Neil Shapiro **
1123299c2f1SGregory Neil Shapiro */
1133299c2f1SGregory Neil Shapiro
114684b2a5fSGregory Neil Shapiro static void
addcmd(s,cmd,len)1153299c2f1SGregory Neil Shapiro addcmd(s, cmd, len)
1163299c2f1SGregory Neil Shapiro char *s;
11712ed1c7cSGregory Neil Shapiro bool cmd;
11812ed1c7cSGregory Neil Shapiro size_t len;
1193299c2f1SGregory Neil Shapiro {
1203299c2f1SGregory Neil Shapiro if (s == NULL || *s == '\0')
1213299c2f1SGregory Neil Shapiro return;
1223299c2f1SGregory Neil Shapiro
1231ae5b8d4SGregory Neil Shapiro /* enough space for s (len) and CMDDIR + "/" and '\0'? */
1243299c2f1SGregory Neil Shapiro if (sizeof newcmdbuf - strlen(newcmdbuf) <=
1251ae5b8d4SGregory Neil Shapiro len + 1 + (cmd ? (strlen(CMDDIR) + 1) : 0))
1263299c2f1SGregory Neil Shapiro {
12712ed1c7cSGregory Neil Shapiro (void)sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
12812ed1c7cSGregory Neil Shapiro "%s: command too long: %s\n", prg, par);
1293299c2f1SGregory Neil Shapiro #ifndef DEBUG
1303299c2f1SGregory Neil Shapiro syslog(LOG_WARNING, "command too long: %.40s", par);
131*5b0945b5SGregory Neil Shapiro #endif
1323299c2f1SGregory Neil Shapiro exit(EX_UNAVAILABLE);
1333299c2f1SGregory Neil Shapiro }
1343299c2f1SGregory Neil Shapiro if (cmd)
13588ad41d4SGregory Neil Shapiro (void) sm_strlcat2(newcmdbuf, CMDDIR, "/", sizeof newcmdbuf);
1361ae5b8d4SGregory Neil Shapiro (void) strncat(newcmdbuf, s, len);
1373299c2f1SGregory Neil Shapiro }
138c2aa98e2SPeter Wemm
139c2aa98e2SPeter Wemm int
main(argc,argv)140c2aa98e2SPeter Wemm main(argc, argv)
141c2aa98e2SPeter Wemm int argc;
142c2aa98e2SPeter Wemm char **argv;
143c2aa98e2SPeter Wemm {
144c2aa98e2SPeter Wemm register char *p;
145c2aa98e2SPeter Wemm register char *q;
1463299c2f1SGregory Neil Shapiro register char *r;
147c2aa98e2SPeter Wemm register char *cmd;
1483299c2f1SGregory Neil Shapiro int isexec;
1493299c2f1SGregory Neil Shapiro int save_errno;
150c2aa98e2SPeter Wemm char *newenv[2];
151c2aa98e2SPeter Wemm char pathbuf[1000];
1523299c2f1SGregory Neil Shapiro char specialbuf[32];
153509cae37SGregory Neil Shapiro struct stat st;
154c2aa98e2SPeter Wemm
1553299c2f1SGregory Neil Shapiro #ifndef DEBUG
156c2aa98e2SPeter Wemm # ifndef LOG_MAIL
157c2aa98e2SPeter Wemm openlog("smrsh", 0);
158*5b0945b5SGregory Neil Shapiro # else
159c2aa98e2SPeter Wemm openlog("smrsh", LOG_ODELAY|LOG_CONS, LOG_MAIL);
160*5b0945b5SGregory Neil Shapiro # endif
1613299c2f1SGregory Neil Shapiro #endif /* ! DEBUG */
162c2aa98e2SPeter Wemm
16388ad41d4SGregory Neil Shapiro (void) sm_strlcpyn(pathbuf, sizeof pathbuf, 2, "PATH=", PATH);
164c2aa98e2SPeter Wemm newenv[0] = pathbuf;
165c2aa98e2SPeter Wemm newenv[1] = NULL;
166c2aa98e2SPeter Wemm
167c2aa98e2SPeter Wemm /*
168c2aa98e2SPeter Wemm ** Do basic argv usage checking
169c2aa98e2SPeter Wemm */
170c2aa98e2SPeter Wemm
1713299c2f1SGregory Neil Shapiro prg = argv[0];
1723299c2f1SGregory Neil Shapiro
173c2aa98e2SPeter Wemm if (argc != 3 || strcmp(argv[1], "-c") != 0)
174c2aa98e2SPeter Wemm {
17512ed1c7cSGregory Neil Shapiro (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
17612ed1c7cSGregory Neil Shapiro "Usage: %s -c command\n", prg);
1773299c2f1SGregory Neil Shapiro #ifndef DEBUG
178c2aa98e2SPeter Wemm syslog(LOG_ERR, "usage");
179*5b0945b5SGregory Neil Shapiro #endif
180c2aa98e2SPeter Wemm exit(EX_USAGE);
181c2aa98e2SPeter Wemm }
182c2aa98e2SPeter Wemm
183c0c4794dSGregory Neil Shapiro par = argv[2];
184c0c4794dSGregory Neil Shapiro
185c2aa98e2SPeter Wemm /*
186c2aa98e2SPeter Wemm ** Disallow special shell syntax. This is overly restrictive,
187c2aa98e2SPeter Wemm ** but it should shut down all attacks.
188c2aa98e2SPeter Wemm ** Be sure to include 8-bit versions, since many shells strip
189c2aa98e2SPeter Wemm ** the address to 7 bits before checking.
190c2aa98e2SPeter Wemm */
191c2aa98e2SPeter Wemm
1923299c2f1SGregory Neil Shapiro if (strlen(SPECIALS) * 2 >= sizeof specialbuf)
193c2aa98e2SPeter Wemm {
1943299c2f1SGregory Neil Shapiro #ifndef DEBUG
1953299c2f1SGregory Neil Shapiro syslog(LOG_ERR, "too many specials: %.40s", SPECIALS);
196*5b0945b5SGregory Neil Shapiro #endif
197c2aa98e2SPeter Wemm exit(EX_UNAVAILABLE);
198c2aa98e2SPeter Wemm }
19912ed1c7cSGregory Neil Shapiro (void) sm_strlcpy(specialbuf, SPECIALS, sizeof specialbuf);
2003299c2f1SGregory Neil Shapiro for (p = specialbuf; *p != '\0'; p++)
2013299c2f1SGregory Neil Shapiro *p |= '\200';
20212ed1c7cSGregory Neil Shapiro (void) sm_strlcat(specialbuf, SPECIALS, sizeof specialbuf);
203c2aa98e2SPeter Wemm
204c2aa98e2SPeter Wemm /*
205c2aa98e2SPeter Wemm ** Do a quick sanity check on command line length.
206c2aa98e2SPeter Wemm */
207c2aa98e2SPeter Wemm
20812ed1c7cSGregory Neil Shapiro if (strlen(par) > (sizeof newcmdbuf - sizeof CMDDIR - 2))
209c2aa98e2SPeter Wemm {
21012ed1c7cSGregory Neil Shapiro (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
21112ed1c7cSGregory Neil Shapiro "%s: command too long: %s\n", prg, par);
2123299c2f1SGregory Neil Shapiro #ifndef DEBUG
2133299c2f1SGregory Neil Shapiro syslog(LOG_WARNING, "command too long: %.40s", par);
214*5b0945b5SGregory Neil Shapiro #endif
215c2aa98e2SPeter Wemm exit(EX_UNAVAILABLE);
216c2aa98e2SPeter Wemm }
217c2aa98e2SPeter Wemm
2183299c2f1SGregory Neil Shapiro q = par;
2193299c2f1SGregory Neil Shapiro newcmdbuf[0] = '\0';
22012ed1c7cSGregory Neil Shapiro isexec = false;
2213299c2f1SGregory Neil Shapiro
22288ad41d4SGregory Neil Shapiro while (*q != '\0')
2233299c2f1SGregory Neil Shapiro {
224c2aa98e2SPeter Wemm /*
225c2aa98e2SPeter Wemm ** Strip off a leading pathname on the command name. For
226c2aa98e2SPeter Wemm ** example, change /usr/ucb/vacation to vacation.
227c2aa98e2SPeter Wemm */
228c2aa98e2SPeter Wemm
229c2aa98e2SPeter Wemm /* strip leading spaces */
2303299c2f1SGregory Neil Shapiro while (*q != '\0' && isascii(*q) && isspace(*q))
231c2aa98e2SPeter Wemm q++;
2323299c2f1SGregory Neil Shapiro if (*q == '\0')
2333299c2f1SGregory Neil Shapiro {
2343299c2f1SGregory Neil Shapiro if (isexec)
2353299c2f1SGregory Neil Shapiro {
23612ed1c7cSGregory Neil Shapiro (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
23712ed1c7cSGregory Neil Shapiro "%s: missing command to exec\n",
2383299c2f1SGregory Neil Shapiro prg);
2393299c2f1SGregory Neil Shapiro #ifndef DEBUG
24012ed1c7cSGregory Neil Shapiro syslog(LOG_CRIT, "uid %d: missing command to exec", (int) getuid());
241*5b0945b5SGregory Neil Shapiro #endif
2423299c2f1SGregory Neil Shapiro exit(EX_UNAVAILABLE);
2433299c2f1SGregory Neil Shapiro }
2443299c2f1SGregory Neil Shapiro break;
2453299c2f1SGregory Neil Shapiro }
246c2aa98e2SPeter Wemm
247c2aa98e2SPeter Wemm /* find the end of the command name */
248c2aa98e2SPeter Wemm p = strpbrk(q, " \t");
249c2aa98e2SPeter Wemm if (p == NULL)
250c2aa98e2SPeter Wemm cmd = &q[strlen(q)];
251c2aa98e2SPeter Wemm else
252c2aa98e2SPeter Wemm {
253c2aa98e2SPeter Wemm *p = '\0';
254c2aa98e2SPeter Wemm cmd = p;
255c2aa98e2SPeter Wemm }
256c2aa98e2SPeter Wemm /* search backwards for last / (allow for 0200 bit) */
257c2aa98e2SPeter Wemm while (cmd > q)
258c2aa98e2SPeter Wemm {
259c2aa98e2SPeter Wemm if ((*--cmd & 0177) == '/')
260c2aa98e2SPeter Wemm {
261c2aa98e2SPeter Wemm cmd++;
262c2aa98e2SPeter Wemm break;
263c2aa98e2SPeter Wemm }
264c2aa98e2SPeter Wemm }
265c2aa98e2SPeter Wemm /* cmd now points at final component of path name */
266c2aa98e2SPeter Wemm
2673299c2f1SGregory Neil Shapiro /* allow a few shell builtins */
2683299c2f1SGregory Neil Shapiro if (strcmp(q, "exec") == 0 && p != NULL)
2693299c2f1SGregory Neil Shapiro {
27012ed1c7cSGregory Neil Shapiro addcmd("exec ", false, strlen("exec "));
27188ad41d4SGregory Neil Shapiro
2723299c2f1SGregory Neil Shapiro /* test _next_ arg */
2733299c2f1SGregory Neil Shapiro q = ++p;
27412ed1c7cSGregory Neil Shapiro isexec = true;
2753299c2f1SGregory Neil Shapiro continue;
2763299c2f1SGregory Neil Shapiro }
2773299c2f1SGregory Neil Shapiro else if (strcmp(q, "exit") == 0 || strcmp(q, "echo") == 0)
2783299c2f1SGregory Neil Shapiro {
27912ed1c7cSGregory Neil Shapiro addcmd(cmd, false, strlen(cmd));
28088ad41d4SGregory Neil Shapiro
2813299c2f1SGregory Neil Shapiro /* test following chars */
2823299c2f1SGregory Neil Shapiro }
2833299c2f1SGregory Neil Shapiro else
2843299c2f1SGregory Neil Shapiro {
28588ad41d4SGregory Neil Shapiro char cmdbuf[MAXPATHLEN];
28688ad41d4SGregory Neil Shapiro
287c2aa98e2SPeter Wemm /*
288c2aa98e2SPeter Wemm ** Check to see if the command name is legal.
289c2aa98e2SPeter Wemm */
29088ad41d4SGregory Neil Shapiro
29188ad41d4SGregory Neil Shapiro if (sm_strlcpyn(cmdbuf, sizeof cmdbuf, 3, CMDDIR,
29288ad41d4SGregory Neil Shapiro "/", cmd) >= sizeof cmdbuf)
29388ad41d4SGregory Neil Shapiro {
29488ad41d4SGregory Neil Shapiro /* too long */
29588ad41d4SGregory Neil Shapiro (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
2962ef40764SGregory Neil Shapiro "%s: \"%s\" not available for sendmail programs (filename too long)\n",
29788ad41d4SGregory Neil Shapiro prg, cmd);
29888ad41d4SGregory Neil Shapiro if (p != NULL)
29988ad41d4SGregory Neil Shapiro *p = ' ';
30088ad41d4SGregory Neil Shapiro #ifndef DEBUG
3012ef40764SGregory Neil Shapiro syslog(LOG_CRIT, "uid %d: attempt to use \"%s\" (filename too long)",
30288ad41d4SGregory Neil Shapiro (int) getuid(), cmd);
303*5b0945b5SGregory Neil Shapiro #endif
30488ad41d4SGregory Neil Shapiro exit(EX_UNAVAILABLE);
30588ad41d4SGregory Neil Shapiro }
30688ad41d4SGregory Neil Shapiro
307c2aa98e2SPeter Wemm #ifdef DEBUG
30812ed1c7cSGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
30912ed1c7cSGregory Neil Shapiro "Trying %s\n", cmdbuf);
310*5b0945b5SGregory Neil Shapiro #endif
311509cae37SGregory Neil Shapiro if (stat(cmdbuf, &st) < 0)
312509cae37SGregory Neil Shapiro {
313509cae37SGregory Neil Shapiro /* can't stat it */
314509cae37SGregory Neil Shapiro (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
3152ef40764SGregory Neil Shapiro "%s: \"%s\" not available for sendmail programs (stat failed)\n",
316509cae37SGregory Neil Shapiro prg, cmd);
317509cae37SGregory Neil Shapiro if (p != NULL)
318509cae37SGregory Neil Shapiro *p = ' ';
319509cae37SGregory Neil Shapiro #ifndef DEBUG
3202ef40764SGregory Neil Shapiro syslog(LOG_CRIT, "uid %d: attempt to use \"%s\" (stat failed)",
321509cae37SGregory Neil Shapiro (int) getuid(), cmd);
322*5b0945b5SGregory Neil Shapiro #endif
323509cae37SGregory Neil Shapiro exit(EX_UNAVAILABLE);
324509cae37SGregory Neil Shapiro }
325509cae37SGregory Neil Shapiro if (!S_ISREG(st.st_mode)
326509cae37SGregory Neil Shapiro #ifdef S_ISLNK
327509cae37SGregory Neil Shapiro && !S_ISLNK(st.st_mode)
328*5b0945b5SGregory Neil Shapiro #endif
329509cae37SGregory Neil Shapiro )
330509cae37SGregory Neil Shapiro {
331509cae37SGregory Neil Shapiro /* can't stat it */
332509cae37SGregory Neil Shapiro (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
3332ef40764SGregory Neil Shapiro "%s: \"%s\" not available for sendmail programs (not a file)\n",
334509cae37SGregory Neil Shapiro prg, cmd);
335509cae37SGregory Neil Shapiro if (p != NULL)
336509cae37SGregory Neil Shapiro *p = ' ';
337509cae37SGregory Neil Shapiro #ifndef DEBUG
3382ef40764SGregory Neil Shapiro syslog(LOG_CRIT, "uid %d: attempt to use \"%s\" (not a file)",
339509cae37SGregory Neil Shapiro (int) getuid(), cmd);
340*5b0945b5SGregory Neil Shapiro #endif
341509cae37SGregory Neil Shapiro exit(EX_UNAVAILABLE);
342509cae37SGregory Neil Shapiro }
343c2aa98e2SPeter Wemm if (access(cmdbuf, X_OK) < 0)
344c2aa98e2SPeter Wemm {
345*5b0945b5SGregory Neil Shapiro /* oops.... crack attack possibility */
34612ed1c7cSGregory Neil Shapiro (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
3472ef40764SGregory Neil Shapiro "%s: \"%s\" not available for sendmail programs\n",
3483299c2f1SGregory Neil Shapiro prg, cmd);
349c2aa98e2SPeter Wemm if (p != NULL)
350c2aa98e2SPeter Wemm *p = ' ';
3513299c2f1SGregory Neil Shapiro #ifndef DEBUG
3522ef40764SGregory Neil Shapiro syslog(LOG_CRIT, "uid %d: attempt to use \"%s\"",
35312ed1c7cSGregory Neil Shapiro (int) getuid(), cmd);
354*5b0945b5SGregory Neil Shapiro #endif
355c2aa98e2SPeter Wemm exit(EX_UNAVAILABLE);
356c2aa98e2SPeter Wemm }
357c2aa98e2SPeter Wemm
358c2aa98e2SPeter Wemm /*
359c2aa98e2SPeter Wemm ** Create the actual shell input.
360c2aa98e2SPeter Wemm */
361c2aa98e2SPeter Wemm
36212ed1c7cSGregory Neil Shapiro addcmd(cmd, true, strlen(cmd));
3633299c2f1SGregory Neil Shapiro }
36412ed1c7cSGregory Neil Shapiro isexec = false;
3653299c2f1SGregory Neil Shapiro
3663299c2f1SGregory Neil Shapiro if (p != NULL)
3673299c2f1SGregory Neil Shapiro *p = ' ';
3683299c2f1SGregory Neil Shapiro else
3693299c2f1SGregory Neil Shapiro break;
3703299c2f1SGregory Neil Shapiro
3713299c2f1SGregory Neil Shapiro r = strpbrk(p, specialbuf);
37212ed1c7cSGregory Neil Shapiro if (r == NULL)
37312ed1c7cSGregory Neil Shapiro {
37412ed1c7cSGregory Neil Shapiro addcmd(p, false, strlen(p));
3753299c2f1SGregory Neil Shapiro break;
3763299c2f1SGregory Neil Shapiro }
3773299c2f1SGregory Neil Shapiro #if ALLOWSEMI
37812ed1c7cSGregory Neil Shapiro if (*r == ';')
37912ed1c7cSGregory Neil Shapiro {
38012ed1c7cSGregory Neil Shapiro addcmd(p, false, r - p + 1);
3813299c2f1SGregory Neil Shapiro q = r + 1;
3823299c2f1SGregory Neil Shapiro continue;
3833299c2f1SGregory Neil Shapiro }
3843299c2f1SGregory Neil Shapiro #endif /* ALLOWSEMI */
3853299c2f1SGregory Neil Shapiro if ((*r == '&' && *(r + 1) == '&') ||
3863299c2f1SGregory Neil Shapiro (*r == '|' && *(r + 1) == '|'))
3873299c2f1SGregory Neil Shapiro {
38812ed1c7cSGregory Neil Shapiro addcmd(p, false, r - p + 2);
3893299c2f1SGregory Neil Shapiro q = r + 2;
3903299c2f1SGregory Neil Shapiro continue;
3913299c2f1SGregory Neil Shapiro }
3923299c2f1SGregory Neil Shapiro
39312ed1c7cSGregory Neil Shapiro (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
39412ed1c7cSGregory Neil Shapiro "%s: cannot use %c in command\n", prg, *r);
3953299c2f1SGregory Neil Shapiro #ifndef DEBUG
3963299c2f1SGregory Neil Shapiro syslog(LOG_CRIT, "uid %d: attempt to use %c in command: %s",
39712ed1c7cSGregory Neil Shapiro (int) getuid(), *r, par);
398*5b0945b5SGregory Neil Shapiro #endif
3993299c2f1SGregory Neil Shapiro exit(EX_UNAVAILABLE);
40088ad41d4SGregory Neil Shapiro }
4013299c2f1SGregory Neil Shapiro if (isexec)
4023299c2f1SGregory Neil Shapiro {
40312ed1c7cSGregory Neil Shapiro (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
40412ed1c7cSGregory Neil Shapiro "%s: missing command to exec\n", prg);
4053299c2f1SGregory Neil Shapiro #ifndef DEBUG
40612ed1c7cSGregory Neil Shapiro syslog(LOG_CRIT, "uid %d: missing command to exec",
40712ed1c7cSGregory Neil Shapiro (int) getuid());
408*5b0945b5SGregory Neil Shapiro #endif
4093299c2f1SGregory Neil Shapiro exit(EX_UNAVAILABLE);
4103299c2f1SGregory Neil Shapiro }
4113299c2f1SGregory Neil Shapiro /* make sure we created something */
4123299c2f1SGregory Neil Shapiro if (newcmdbuf[0] == '\0')
4133299c2f1SGregory Neil Shapiro {
41412ed1c7cSGregory Neil Shapiro (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
41512ed1c7cSGregory Neil Shapiro "Usage: %s -c command\n", prg);
4163299c2f1SGregory Neil Shapiro #ifndef DEBUG
4173299c2f1SGregory Neil Shapiro syslog(LOG_ERR, "usage");
418*5b0945b5SGregory Neil Shapiro #endif
4193299c2f1SGregory Neil Shapiro exit(EX_USAGE);
4203299c2f1SGregory Neil Shapiro }
421c2aa98e2SPeter Wemm
422c2aa98e2SPeter Wemm /*
423c2aa98e2SPeter Wemm ** Now invoke the shell
424c2aa98e2SPeter Wemm */
425c2aa98e2SPeter Wemm
426c2aa98e2SPeter Wemm #ifdef DEBUG
42712ed1c7cSGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s\n", newcmdbuf);
428*5b0945b5SGregory Neil Shapiro #endif
4293fdb3903SGregory Neil Shapiro (void) execle("/bin/sh", "/bin/sh", "-c", newcmdbuf,
4303fdb3903SGregory Neil Shapiro (char *)NULL, newenv);
4313299c2f1SGregory Neil Shapiro save_errno = errno;
4323299c2f1SGregory Neil Shapiro #ifndef DEBUG
43312ed1c7cSGregory Neil Shapiro syslog(LOG_CRIT, "Cannot exec /bin/sh: %s", sm_errstring(errno));
434*5b0945b5SGregory Neil Shapiro #endif
4353299c2f1SGregory Neil Shapiro errno = save_errno;
43612ed1c7cSGregory Neil Shapiro sm_perror("/bin/sh");
437c2aa98e2SPeter Wemm exit(EX_OSFILE);
4383299c2f1SGregory Neil Shapiro /* NOTREACHED */
4393299c2f1SGregory Neil Shapiro return EX_OSFILE;
440c2aa98e2SPeter Wemm }
441