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