home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3571 / main.c < prev    next >
C/C++ Source or Header  |  1991-07-02  |  11KB  |  548 lines

  1. /* +-------------------------------------------------------------------+ */
  2. /* | Copyright 1991, David Koblas.                                     | */
  3. /* |   Permission to use, copy, modify, and distribute this software   | */
  4. /* |   and its documentation for any purpose and without fee is hereby | */
  5. /* |   granted, provided that the above copyright notice appear in all | */
  6. /* |   copies and that both that copyright notice and this permission  | */
  7. /* |   notice appear in supporting documentation.  This software is    | */
  8. /* |   provided "as is" without express or implied warranty.           | */
  9. /* +-------------------------------------------------------------------+ */
  10.  
  11. #include <stdio.h>
  12. #include <varargs.h>
  13. #include <syslog.h>
  14. #include <pwd.h>
  15. #include <grp.h>
  16. #include <ctype.h>
  17. #include "defs.h"
  18. #include "regexp.h"
  19.  
  20. #ifndef LOG_AUTH
  21. /*
  22. **  Pmax's don't have LOG_AUTH
  23. */
  24. #define LOG_AUTH LOG_WARNING
  25. #endif
  26.  
  27. #define    MAXARG    1024
  28. #define    MAXENV    MAXARG
  29.  
  30. extern char    *index();
  31. extern char    *savestr();
  32. extern char    *getpass(), *crypt();
  33.  
  34. char    *Progname;
  35. cmd_t    *Find();
  36. cmd_t    *First = NULL;
  37.  
  38. Usage()
  39. {
  40.     fatal("Usage: %s mnemonic [args]\n       %s -h [-u username] mnemonic",
  41.             Progname, Progname);
  42. }
  43.  
  44. main(argc, argv)
  45. int    argc;
  46. char    **argv;
  47. {
  48.     int        num, argStart = 1;
  49.     char        user[MAXSTRLEN];
  50.     cmd_t        *cmd, *def, *new;
  51.     struct passwd    *pw;
  52.     int        hflag = 0;
  53.     char        *uptr = NULL;
  54.  
  55.     Progname = argv[0];
  56.  
  57.     while (1) {
  58.         if (argStart >= argc)
  59.             break;
  60.  
  61.         if (strcmp("-h", argv[argStart]) == 0) {
  62.             hflag++;
  63.             argStart++;
  64.         } else if (strcmp("-u", argv[argStart]) == 0) {
  65.             if (strlen(argv[argStart]) == 2) {
  66.                 if (argStart+1 >= argc)
  67.                     Usage();
  68.                 argStart++;
  69.                 uptr = argv[argStart];
  70.             }
  71.             argStart++;
  72.         } else if (strcmp("-uh", argv[argStart]) == 0) {
  73.             hflag++;
  74.             if (strlen(argv[argStart]) == 3) {
  75.                 if (argStart+1 >= argc)
  76.                     Usage();
  77.                 argStart++;
  78.                 uptr = argv[argStart];
  79.             }
  80.             argStart++;
  81.         } else if (strcmp("-hu", argv[argStart]) == 0) {
  82.             hflag++;
  83.             if (strlen(argv[argStart]) == 3) {
  84.                 if (argStart+1 >= argc)
  85.                     Usage();
  86.                 argStart++;
  87.                 uptr = argv[argStart];
  88.             }
  89.             argStart++;
  90.         } else {
  91.             break;
  92.         }
  93.     }
  94.  
  95.     if (openlog("op", 0, LOG_AUTH) < 0) 
  96.         fatal("openlog failed");
  97.  
  98.     ReadFile("/etc/op.access");
  99.  
  100.     if (hflag) {
  101.         if (uptr != NULL) {
  102.             if (getuid() != 0) 
  103.                 fatal("Permission denied for -u option");
  104.         }
  105.     }
  106.     if (uptr != NULL) 
  107.         Usage();
  108.  
  109.     if (argStart >= argc)
  110.         Usage();
  111.  
  112.     def = Find("DEFAULT");
  113.     cmd = Find(argv[argStart]);
  114.  
  115.     if (cmd == NULL) 
  116.         fatal("No such command %s", argv[1]);
  117.  
  118.     argc -= argStart;
  119.     argv += argStart;
  120.  
  121.     new = Build(def, cmd);
  122.     num = CountArgs(new);
  123.  
  124.     if ((num < 0) && ((argc-1) < -num))
  125.         fatal("Improper number of arguments");
  126.     if ((num > 0) && ((argc-1) != num)) 
  127.         fatal("Improper number of arguments");
  128.     if (num <0)
  129.         num = -num;
  130.  
  131.     if ((pw = getpwuid(getuid())) == NULL) 
  132.         exit(1);
  133.     strcpy(user, pw->pw_name);
  134.     if (Verify(new, num, argc, argv) < 0) {
  135.         syslog(LOG_NOTICE, "user %s FAILED to execute '%s'", 
  136.                 user, argv[0]);
  137.         fatal("Permission denied");
  138.     } else {
  139.         syslog(LOG_NOTICE, "user %s SUCCEDED to execute '%s'",
  140.                 user, argv[0]);
  141.     }
  142.  
  143.     return Go(new, num, argc, argv);
  144. }
  145.  
  146. fatal(va_alist)
  147.  va_dcl
  148. {
  149.     va_list    ap;
  150.     char    *s;
  151.  
  152.     va_start(ap);
  153.     s = va_arg(ap, char *);
  154.     vfprintf(stderr, s, ap);
  155.     fputc('\n', stderr);
  156.     va_end(ap);
  157.  
  158.     exit(1);
  159. }
  160.  
  161. cmd_t    *Find(name)
  162. char    *name;
  163. {
  164.     cmd_t    *cmd;
  165.  
  166.     for (cmd = First; cmd != NULL; cmd = cmd ->next) {
  167.         if (strcmp(cmd->name, name) == 0)
  168.             break;
  169.     }
  170.  
  171.     return cmd;
  172. }
  173.  
  174. char    *FindOpt(cmd, str)
  175. cmd_t    *cmd;
  176. char    *str;
  177. {
  178.     static char    nul[2] = "";
  179.     int        i;
  180.     char        *cp;
  181.  
  182.     for (i = 0; i < cmd->nopts; i++) {
  183.         if ((cp = index(cmd->opts[i], '=')) == NULL) {
  184.             if (strcmp(cmd->opts[i], str) == 0)
  185.                 return nul;
  186.         } else {
  187.             int    l = cp - cmd->opts[i];
  188.             if (strncmp(cmd->opts[i], str, l) == 0)
  189.                 return cp+1;
  190.         }
  191.     }
  192.  
  193.     return NULL;
  194. }
  195.  
  196. char    *GetField(cp, str)
  197. char    *cp, *str;
  198. {
  199.     if (*cp == '\0')
  200.         return NULL;
  201.  
  202.     while ((*cp != '\0') && (*cp != ',')) {
  203.         if (*cp == '\\')
  204.             if (*(cp+1) == ',') {
  205.                 *str++ = ',';
  206.                 cp++;
  207.             } else
  208.                 *str++ = '\\';
  209.         else
  210.             *str++ = *cp;
  211.         cp++;
  212.     }
  213.  
  214.     *str = '\0';
  215.  
  216.     return (*cp == '\0') ? cp : (cp+1);
  217. }
  218.  
  219. Verify(cmd, num, argc, argv)
  220. cmd_t    *cmd;
  221. int    argc;
  222. int    num;
  223. char    **argv;
  224. {
  225.     int        gr_fail = 1, uid_fail = 1;
  226.     int        i, j, val;
  227.     char        *np, *cp, str[MAXSTRLEN], buf[MAXSTRLEN];
  228.     regexp        *reg = NULL;
  229.     struct passwd    *pw, spw;
  230.     struct group    *gr;
  231.  
  232.     if ((pw = getpwuid(getuid())) == NULL) 
  233.         return -1;
  234.  
  235.     if ((cp=FindOpt(cmd, "password")) != NULL) {
  236.         if ((np = getpass("Password:")) == NULL)
  237.             return -1;
  238.         if (((cp = GetField(cp, str)) != NULL) && 
  239.             ((pw = getpwnam(str)) == NULL))
  240.             return -1;
  241.         if (strcmp(crypt(np, pw->pw_passwd), pw->pw_passwd) != 0)
  242.             return -1;
  243.     }
  244.  
  245.     if ((pw = getpwuid(getuid())) == NULL) 
  246.         return -1;
  247.  
  248.     if ((cp = FindOpt(cmd, "groups")) != NULL) {
  249.         for (cp=GetField(cp, str); cp!=NULL; cp=GetField(cp, str)) {
  250.             if (re_comp(str) != 0)
  251.                 return -1;
  252.             if ((gr = getgrgid(pw->pw_gid)) != NULL) {
  253.                 if (re_exec(gr->gr_name) == 1) {
  254.                     gr_fail = 0;
  255.                     break;
  256.                 }
  257.             }
  258.             setgrent();
  259.             while ((gr = getgrent()) != NULL) {
  260.                 i = 0;
  261.                 while (gr->gr_mem[i] != NULL) {
  262.                     if (strcmp(gr->gr_mem[i],
  263.                             pw->pw_name)==0)
  264.                         break;
  265.                     i++;
  266.                 }
  267.                 if ((gr->gr_mem[i] != NULL) && 
  268.                     (re_exec(gr->gr_name) == 1)) {
  269.                         gr_fail = 0;
  270.                         break;
  271.                 }
  272.             }
  273.         }
  274.     }
  275.     if (gr_fail && ((cp = FindOpt(cmd, "users")) != NULL)) {
  276.         for (cp=GetField(cp, str); cp!=NULL; cp=GetField(cp, str)) {
  277.             if (re_comp(str) != 0)
  278.                 return -1;
  279.             if (re_exec(pw->pw_name) == 1) {
  280.                 uid_fail = 0;
  281.                 break;
  282.             }
  283.         }
  284.     }
  285.  
  286.     if (gr_fail && uid_fail)
  287.         return -1;
  288.     
  289.     for (i = 0; i < cmd->nopts; i++) {
  290.         if ((cmd->opts[i][0] != '$') || 
  291.             ((cp = index(cmd->opts[i], '=')) == NULL))
  292.             continue;
  293.         if (cmd->opts[i][1] != '*') {
  294.             for (np = cmd->opts[i] + 1; np != cp; np++) 
  295.                 if (!isdigit(*np))
  296.                     break;
  297.             if (np != cp)
  298.                 continue;
  299.         } else {
  300.             if (cmd->opts[i][2] != '=')
  301.                 continue;
  302.             np = cmd->opts[i] + 3;
  303.             for (j = num+1; j < argc; j++) {
  304.                 cp = np;
  305.                 for (cp=GetField(cp, str); cp!=NULL; 
  306.                         cp=GetField(cp, str)) {
  307.                     if (re_comp(str) != 0)
  308.                         return -1;
  309.                     if (re_exec(argv[j]) == 1)
  310.                         break;
  311.                 }
  312.                 if (cp == NULL)
  313.                     return -1;
  314.             }
  315.         }
  316.         
  317.         strncpy(str, cmd->opts[i] + 1, cp - cmd->opts[i] - 1);
  318.         str[cp - cmd->opts[i] - 1] = '\0';
  319.         val = atoi(str);
  320.  
  321.         if (val >= argc)
  322.             continue;
  323.         cp++;
  324.         np = cp;
  325.         if (reg != NULL) {
  326.             for (cp=GetField(cp, str); cp!=NULL; 
  327.                     cp=GetField(cp, str)) {
  328.                 regsub(reg, str, buf);
  329.                 if (strcmp(buf, argv[val]) == 0)
  330.                     break;
  331.             }
  332.  
  333.             if (cp != NULL)
  334.                 continue;
  335.  
  336.             free(reg);
  337.             reg = NULL;
  338.         }
  339.  
  340.         if ((reg == NULL) || (cp == NULL)) {
  341.             cp = np;
  342.             for (cp=GetField(cp, str); cp!=NULL; 
  343.                     cp=GetField(cp, str)) {
  344.                 if ((reg = regcomp(str)) == NULL) 
  345.                     return -1;
  346.                 if (regexec(reg, argv[val]) == 1)
  347.                     break;
  348.  
  349.                 free(reg);
  350.                 reg = NULL;
  351.             }
  352.         }
  353.  
  354.         if (cp == NULL)
  355.             return -1;
  356.     }
  357. }
  358.  
  359. Go(cmd, num, argc, argv)
  360. cmd_t    *cmd;
  361. int    argc;
  362. int    num;
  363. char    **argv;
  364. {
  365.     extern char    **environ;
  366.     int        i, j, flag, val, len = 0;
  367.     char        *cp, *np;
  368.     struct passwd    *pw;
  369.     struct group    *gr;
  370.     int        ngroups, gidset[256];
  371.     int        curenv = 0, curarg = 0;
  372.     char        *new_envp[MAXENV];
  373.     char        *new_argv[MAXARG];
  374.     char        str[MAXSTRLEN], buf[4*MAXSTRLEN];
  375.  
  376.     if ((cp = FindOpt(cmd, "uid")) == NULL) {
  377.         if (setuid(0) < 0)
  378.             fatal("Unable to set uid to default", cp);
  379.     } else {
  380.         if ((pw = getpwnam(cp)) == NULL) {
  381.             if (setuid(atoi(cp)) < 0)
  382.                 fatal("Unable to set uid to %s", cp);
  383.         }
  384.         if (setuid(pw->pw_uid) < 0)
  385.             fatal("Unable to set uid to %s", cp);
  386.     }
  387.  
  388.     if ((cp = FindOpt(cmd, "gid")) == NULL) {
  389.         ;        /* don't have a default */
  390.     } else {
  391.         for (cp=GetField(cp, str); cp!=NULL; cp=GetField(cp, str)) {
  392.             if ((gr = getgrnam(cp)) != NULL)
  393.                 gidset[ngroups++] = gr->gr_gid;
  394.         }
  395.         if (ngroups == 0) 
  396.             fatal("Unable to setgid to any group");
  397.         if (setgroups(ngroups, gidset) < 0)
  398.             fatal("Set group failed");
  399.     }
  400.  
  401.     if ((cp = FindOpt(cmd, "umask")) == NULL) {
  402.         if (umask(0022) < 0)
  403.             fatal("Unable to set umask to default");
  404.     } else {
  405.         if (umask(atov(cp, 8)) < 0)
  406.             fatal("Unable to set umask to %s", cp);
  407.     }
  408.  
  409.     if ((cp = FindOpt(cmd, "chroot")) == NULL) {
  410.         ;        /* don't have a default */
  411.     } else {
  412.         if (chroot(cp) < 0)
  413.             fatal("Unable to chroot to %s", cp);
  414.     }
  415.  
  416.     if ((cp = FindOpt(cmd, "dir")) == NULL) {
  417.         ;        /* don't have a default */
  418.     } else {
  419.         if (chdir(cp) < 0) 
  420.             fatal("Unable to chdir to %s", cp);
  421.     }
  422.  
  423.     if (FindOpt(cmd, "environment") == NULL) {
  424.         for (i = 0; i < cmd->nopts; i++) {
  425.             if (cmd->opts[i][0] != '$')
  426.                 continue;
  427.             cp = cmd->opts[i] + 1;
  428.             flag = 0;
  429.             while ((*cp != '\0') && (*cp != '=')) {
  430.                 if (! isdigit(*cp))
  431.                     flag = 1;
  432.                 cp++;
  433.             }
  434.             if (! flag)
  435.                 continue;
  436.             if (index(cmd->opts[i], '=') != NULL) {
  437.                 new_envp[curenv++] = cmd->opts[i] + 1;
  438.                 continue;
  439.             }
  440.             for (j = 0; environ[j] != NULL ; j++) {
  441.                 if ((cp = index(environ[j], '=')) == NULL)
  442.                     continue;
  443.                 if (strncmp(cmd->opts[i] + 1, environ[j],
  444.                         cp - environ[j]) == 0) {
  445.                     new_envp[curenv++] = environ[j];
  446.                     break;
  447.                 }
  448.             }
  449.         }
  450.     } else {
  451.         for (i = 0; environ[i] != NULL; i++)
  452.             new_envp[curenv++] = environ[i];
  453.     }
  454.     new_envp[curenv] = NULL;
  455.  
  456.     if (strcmp("MAGIC_SHELL", cmd->args[0]) == 0) {
  457.         for (i = 0; environ[i] != NULL; i++) 
  458.             if (strncmp("SHELL=", environ[i], 6) == 0)
  459.                 break;
  460.  
  461.         if (environ[i] != NULL)
  462.             new_argv[curarg++] = environ[i] + 6;
  463.         else {
  464.             fprintf(stderr,"No shell\n");
  465.             exit(1);
  466.         }
  467.  
  468.         if (argc != 1) {
  469.             new_argv[curarg++] = "-c";
  470.  
  471.             for (i = 1; i < argc; i++)
  472.                 len += strlen(argv[i]) + 1;
  473.  
  474.             if ((cp = (char *)malloc(len + 10)) == NULL) {
  475.                 fprintf(stderr, "Unable to create buffer");
  476.                 exit(1);
  477.             }
  478.  
  479.             len = 0;
  480.             *cp = '\0';
  481.  
  482.             for (i = 1; i < argc; i++) {
  483.                 strcat(cp, argv[i]);
  484.                 strcat(cp, " ");
  485.             }
  486.             new_argv[curarg++] = cp;
  487.         }
  488.     } else {
  489.         for (i = 0; i < cmd->nargs; i++) {
  490.             np = cmd->args[i];
  491.  
  492.             while ((cp = index(np, '$')) != NULL) {
  493.                 if ((cp != cmd->args[i]) && (*(cp-1) == '\\'))
  494.                     np = cp + 1;
  495.                 else
  496.                     break;
  497.             }
  498.  
  499.             if (cp == NULL) {
  500.                 new_argv[curarg++] = cmd->args[i];
  501.                 continue;
  502.             }
  503.             if (*(cp+1) == '*') {
  504.                 for (j = num + 1; j < argc; j++) {
  505.                     new_argv[curarg++] = argv[j];
  506.                 }
  507.                 continue;
  508.             }
  509.  
  510.             cp++;
  511.             np = cp;
  512.             while (isdigit(*cp))
  513.                 cp++;
  514.             if ((cp - np) == 0) {
  515.                 new_argv[curarg++] = cmd->args[i];
  516.                 continue;
  517.             }
  518.             strncpy(str, np, cp - np);
  519.             str[cp - np] = '\0';
  520.             val = atoi(str);
  521.             buf[0] = '\0';
  522.             strncpy(buf, cmd->args[i], np - cmd->args[i] - 1);
  523.             strcat(buf, argv[val]);
  524.             strcat(buf, cp);
  525.             new_argv[curarg++] = savestr(buf);
  526.         }
  527.     }
  528.     new_argv[curarg] = NULL;
  529.  
  530.     if (execve(new_argv[0], new_argv, new_envp) < 0)
  531.         perror("execve");
  532. }
  533.  
  534. output(cmd)
  535. cmd_t    *cmd;
  536. {
  537.     int    i;
  538.  
  539.     printf("cmd '%s'\n",cmd->name);
  540.     printf("\n  args\t");
  541.     for (i = 0; i < cmd->nargs; i++)
  542.         printf("'%s' ",cmd->args[i]);
  543.     printf("\n  opts\t");
  544.     for (i = 0; i < cmd->nopts; i++)
  545.         printf("'%s' ",cmd->opts[i]);
  546.     printf("\n");
  547. }
  548.