home *** CD-ROM | disk | FTP | other *** search
- /* +-------------------------------------------------------------------+ */
- /* | Copyright 1991, David Koblas. | */
- /* | Permission to use, copy, modify, and distribute this software | */
- /* | and its documentation for any purpose and without fee is hereby | */
- /* | granted, provided that the above copyright notice appear in all | */
- /* | copies and that both that copyright notice and this permission | */
- /* | notice appear in supporting documentation. This software is | */
- /* | provided "as is" without express or implied warranty. | */
- /* +-------------------------------------------------------------------+ */
-
- #include <stdio.h>
- #include <varargs.h>
- #include <syslog.h>
- #include <pwd.h>
- #include <grp.h>
- #include <ctype.h>
- #include "defs.h"
- #include "regexp.h"
-
- #ifndef LOG_AUTH
- /*
- ** Pmax's don't have LOG_AUTH
- */
- #define LOG_AUTH LOG_WARNING
- #endif
-
- #define MAXARG 1024
- #define MAXENV MAXARG
-
- extern char *index();
- extern char *savestr();
- extern char *getpass(), *crypt();
-
- char *Progname;
- cmd_t *Find();
- cmd_t *First = NULL;
-
- Usage()
- {
- fatal("Usage: %s mnemonic [args]\n %s -h [-u username] mnemonic",
- Progname, Progname);
- }
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- int num, argStart = 1;
- char user[MAXSTRLEN];
- cmd_t *cmd, *def, *new;
- struct passwd *pw;
- int hflag = 0;
- char *uptr = NULL;
-
- Progname = argv[0];
-
- while (1) {
- if (argStart >= argc)
- break;
-
- if (strcmp("-h", argv[argStart]) == 0) {
- hflag++;
- argStart++;
- } else if (strcmp("-u", argv[argStart]) == 0) {
- if (strlen(argv[argStart]) == 2) {
- if (argStart+1 >= argc)
- Usage();
- argStart++;
- uptr = argv[argStart];
- }
- argStart++;
- } else if (strcmp("-uh", argv[argStart]) == 0) {
- hflag++;
- if (strlen(argv[argStart]) == 3) {
- if (argStart+1 >= argc)
- Usage();
- argStart++;
- uptr = argv[argStart];
- }
- argStart++;
- } else if (strcmp("-hu", argv[argStart]) == 0) {
- hflag++;
- if (strlen(argv[argStart]) == 3) {
- if (argStart+1 >= argc)
- Usage();
- argStart++;
- uptr = argv[argStart];
- }
- argStart++;
- } else {
- break;
- }
- }
-
- if (openlog("op", 0, LOG_AUTH) < 0)
- fatal("openlog failed");
-
- ReadFile("/etc/op.access");
-
- if (hflag) {
- if (uptr != NULL) {
- if (getuid() != 0)
- fatal("Permission denied for -u option");
- }
- }
- if (uptr != NULL)
- Usage();
-
- if (argStart >= argc)
- Usage();
-
- def = Find("DEFAULT");
- cmd = Find(argv[argStart]);
-
- if (cmd == NULL)
- fatal("No such command %s", argv[1]);
-
- argc -= argStart;
- argv += argStart;
-
- new = Build(def, cmd);
- num = CountArgs(new);
-
- if ((num < 0) && ((argc-1) < -num))
- fatal("Improper number of arguments");
- if ((num > 0) && ((argc-1) != num))
- fatal("Improper number of arguments");
- if (num <0)
- num = -num;
-
- if ((pw = getpwuid(getuid())) == NULL)
- exit(1);
- strcpy(user, pw->pw_name);
- if (Verify(new, num, argc, argv) < 0) {
- syslog(LOG_NOTICE, "user %s FAILED to execute '%s'",
- user, argv[0]);
- fatal("Permission denied");
- } else {
- syslog(LOG_NOTICE, "user %s SUCCEDED to execute '%s'",
- user, argv[0]);
- }
-
- return Go(new, num, argc, argv);
- }
-
- fatal(va_alist)
- va_dcl
- {
- va_list ap;
- char *s;
-
- va_start(ap);
- s = va_arg(ap, char *);
- vfprintf(stderr, s, ap);
- fputc('\n', stderr);
- va_end(ap);
-
- exit(1);
- }
-
- cmd_t *Find(name)
- char *name;
- {
- cmd_t *cmd;
-
- for (cmd = First; cmd != NULL; cmd = cmd ->next) {
- if (strcmp(cmd->name, name) == 0)
- break;
- }
-
- return cmd;
- }
-
- char *FindOpt(cmd, str)
- cmd_t *cmd;
- char *str;
- {
- static char nul[2] = "";
- int i;
- char *cp;
-
- for (i = 0; i < cmd->nopts; i++) {
- if ((cp = index(cmd->opts[i], '=')) == NULL) {
- if (strcmp(cmd->opts[i], str) == 0)
- return nul;
- } else {
- int l = cp - cmd->opts[i];
- if (strncmp(cmd->opts[i], str, l) == 0)
- return cp+1;
- }
- }
-
- return NULL;
- }
-
- char *GetField(cp, str)
- char *cp, *str;
- {
- if (*cp == '\0')
- return NULL;
-
- while ((*cp != '\0') && (*cp != ',')) {
- if (*cp == '\\')
- if (*(cp+1) == ',') {
- *str++ = ',';
- cp++;
- } else
- *str++ = '\\';
- else
- *str++ = *cp;
- cp++;
- }
-
- *str = '\0';
-
- return (*cp == '\0') ? cp : (cp+1);
- }
-
- Verify(cmd, num, argc, argv)
- cmd_t *cmd;
- int argc;
- int num;
- char **argv;
- {
- int gr_fail = 1, uid_fail = 1;
- int i, j, val;
- char *np, *cp, str[MAXSTRLEN], buf[MAXSTRLEN];
- regexp *reg = NULL;
- struct passwd *pw, spw;
- struct group *gr;
-
- if ((pw = getpwuid(getuid())) == NULL)
- return -1;
-
- if ((cp=FindOpt(cmd, "password")) != NULL) {
- if ((np = getpass("Password:")) == NULL)
- return -1;
- if (((cp = GetField(cp, str)) != NULL) &&
- ((pw = getpwnam(str)) == NULL))
- return -1;
- if (strcmp(crypt(np, pw->pw_passwd), pw->pw_passwd) != 0)
- return -1;
- }
-
- if ((pw = getpwuid(getuid())) == NULL)
- return -1;
-
- if ((cp = FindOpt(cmd, "groups")) != NULL) {
- for (cp=GetField(cp, str); cp!=NULL; cp=GetField(cp, str)) {
- if (re_comp(str) != 0)
- return -1;
- if ((gr = getgrgid(pw->pw_gid)) != NULL) {
- if (re_exec(gr->gr_name) == 1) {
- gr_fail = 0;
- break;
- }
- }
- setgrent();
- while ((gr = getgrent()) != NULL) {
- i = 0;
- while (gr->gr_mem[i] != NULL) {
- if (strcmp(gr->gr_mem[i],
- pw->pw_name)==0)
- break;
- i++;
- }
- if ((gr->gr_mem[i] != NULL) &&
- (re_exec(gr->gr_name) == 1)) {
- gr_fail = 0;
- break;
- }
- }
- }
- }
- if (gr_fail && ((cp = FindOpt(cmd, "users")) != NULL)) {
- for (cp=GetField(cp, str); cp!=NULL; cp=GetField(cp, str)) {
- if (re_comp(str) != 0)
- return -1;
- if (re_exec(pw->pw_name) == 1) {
- uid_fail = 0;
- break;
- }
- }
- }
-
- if (gr_fail && uid_fail)
- return -1;
-
- for (i = 0; i < cmd->nopts; i++) {
- if ((cmd->opts[i][0] != '$') ||
- ((cp = index(cmd->opts[i], '=')) == NULL))
- continue;
- if (cmd->opts[i][1] != '*') {
- for (np = cmd->opts[i] + 1; np != cp; np++)
- if (!isdigit(*np))
- break;
- if (np != cp)
- continue;
- } else {
- if (cmd->opts[i][2] != '=')
- continue;
- np = cmd->opts[i] + 3;
- for (j = num+1; j < argc; j++) {
- cp = np;
- for (cp=GetField(cp, str); cp!=NULL;
- cp=GetField(cp, str)) {
- if (re_comp(str) != 0)
- return -1;
- if (re_exec(argv[j]) == 1)
- break;
- }
- if (cp == NULL)
- return -1;
- }
- }
-
- strncpy(str, cmd->opts[i] + 1, cp - cmd->opts[i] - 1);
- str[cp - cmd->opts[i] - 1] = '\0';
- val = atoi(str);
-
- if (val >= argc)
- continue;
- cp++;
- np = cp;
- if (reg != NULL) {
- for (cp=GetField(cp, str); cp!=NULL;
- cp=GetField(cp, str)) {
- regsub(reg, str, buf);
- if (strcmp(buf, argv[val]) == 0)
- break;
- }
-
- if (cp != NULL)
- continue;
-
- free(reg);
- reg = NULL;
- }
-
- if ((reg == NULL) || (cp == NULL)) {
- cp = np;
- for (cp=GetField(cp, str); cp!=NULL;
- cp=GetField(cp, str)) {
- if ((reg = regcomp(str)) == NULL)
- return -1;
- if (regexec(reg, argv[val]) == 1)
- break;
-
- free(reg);
- reg = NULL;
- }
- }
-
- if (cp == NULL)
- return -1;
- }
- }
-
- Go(cmd, num, argc, argv)
- cmd_t *cmd;
- int argc;
- int num;
- char **argv;
- {
- extern char **environ;
- int i, j, flag, val, len = 0;
- char *cp, *np;
- struct passwd *pw;
- struct group *gr;
- int ngroups, gidset[256];
- int curenv = 0, curarg = 0;
- char *new_envp[MAXENV];
- char *new_argv[MAXARG];
- char str[MAXSTRLEN], buf[4*MAXSTRLEN];
-
- if ((cp = FindOpt(cmd, "uid")) == NULL) {
- if (setuid(0) < 0)
- fatal("Unable to set uid to default", cp);
- } else {
- if ((pw = getpwnam(cp)) == NULL) {
- if (setuid(atoi(cp)) < 0)
- fatal("Unable to set uid to %s", cp);
- }
- if (setuid(pw->pw_uid) < 0)
- fatal("Unable to set uid to %s", cp);
- }
-
- if ((cp = FindOpt(cmd, "gid")) == NULL) {
- ; /* don't have a default */
- } else {
- for (cp=GetField(cp, str); cp!=NULL; cp=GetField(cp, str)) {
- if ((gr = getgrnam(cp)) != NULL)
- gidset[ngroups++] = gr->gr_gid;
- }
- if (ngroups == 0)
- fatal("Unable to setgid to any group");
- if (setgroups(ngroups, gidset) < 0)
- fatal("Set group failed");
- }
-
- if ((cp = FindOpt(cmd, "umask")) == NULL) {
- if (umask(0022) < 0)
- fatal("Unable to set umask to default");
- } else {
- if (umask(atov(cp, 8)) < 0)
- fatal("Unable to set umask to %s", cp);
- }
-
- if ((cp = FindOpt(cmd, "chroot")) == NULL) {
- ; /* don't have a default */
- } else {
- if (chroot(cp) < 0)
- fatal("Unable to chroot to %s", cp);
- }
-
- if ((cp = FindOpt(cmd, "dir")) == NULL) {
- ; /* don't have a default */
- } else {
- if (chdir(cp) < 0)
- fatal("Unable to chdir to %s", cp);
- }
-
- if (FindOpt(cmd, "environment") == NULL) {
- for (i = 0; i < cmd->nopts; i++) {
- if (cmd->opts[i][0] != '$')
- continue;
- cp = cmd->opts[i] + 1;
- flag = 0;
- while ((*cp != '\0') && (*cp != '=')) {
- if (! isdigit(*cp))
- flag = 1;
- cp++;
- }
- if (! flag)
- continue;
- if (index(cmd->opts[i], '=') != NULL) {
- new_envp[curenv++] = cmd->opts[i] + 1;
- continue;
- }
- for (j = 0; environ[j] != NULL ; j++) {
- if ((cp = index(environ[j], '=')) == NULL)
- continue;
- if (strncmp(cmd->opts[i] + 1, environ[j],
- cp - environ[j]) == 0) {
- new_envp[curenv++] = environ[j];
- break;
- }
- }
- }
- } else {
- for (i = 0; environ[i] != NULL; i++)
- new_envp[curenv++] = environ[i];
- }
- new_envp[curenv] = NULL;
-
- if (strcmp("MAGIC_SHELL", cmd->args[0]) == 0) {
- for (i = 0; environ[i] != NULL; i++)
- if (strncmp("SHELL=", environ[i], 6) == 0)
- break;
-
- if (environ[i] != NULL)
- new_argv[curarg++] = environ[i] + 6;
- else {
- fprintf(stderr,"No shell\n");
- exit(1);
- }
-
- if (argc != 1) {
- new_argv[curarg++] = "-c";
-
- for (i = 1; i < argc; i++)
- len += strlen(argv[i]) + 1;
-
- if ((cp = (char *)malloc(len + 10)) == NULL) {
- fprintf(stderr, "Unable to create buffer");
- exit(1);
- }
-
- len = 0;
- *cp = '\0';
-
- for (i = 1; i < argc; i++) {
- strcat(cp, argv[i]);
- strcat(cp, " ");
- }
- new_argv[curarg++] = cp;
- }
- } else {
- for (i = 0; i < cmd->nargs; i++) {
- np = cmd->args[i];
-
- while ((cp = index(np, '$')) != NULL) {
- if ((cp != cmd->args[i]) && (*(cp-1) == '\\'))
- np = cp + 1;
- else
- break;
- }
-
- if (cp == NULL) {
- new_argv[curarg++] = cmd->args[i];
- continue;
- }
- if (*(cp+1) == '*') {
- for (j = num + 1; j < argc; j++) {
- new_argv[curarg++] = argv[j];
- }
- continue;
- }
-
- cp++;
- np = cp;
- while (isdigit(*cp))
- cp++;
- if ((cp - np) == 0) {
- new_argv[curarg++] = cmd->args[i];
- continue;
- }
- strncpy(str, np, cp - np);
- str[cp - np] = '\0';
- val = atoi(str);
- buf[0] = '\0';
- strncpy(buf, cmd->args[i], np - cmd->args[i] - 1);
- strcat(buf, argv[val]);
- strcat(buf, cp);
- new_argv[curarg++] = savestr(buf);
- }
- }
- new_argv[curarg] = NULL;
-
- if (execve(new_argv[0], new_argv, new_envp) < 0)
- perror("execve");
- }
-
- output(cmd)
- cmd_t *cmd;
- {
- int i;
-
- printf("cmd '%s'\n",cmd->name);
- printf("\n args\t");
- for (i = 0; i < cmd->nargs; i++)
- printf("'%s' ",cmd->args[i]);
- printf("\n opts\t");
- for (i = 0; i < cmd->nopts; i++)
- printf("'%s' ",cmd->opts[i]);
- printf("\n");
- }
-