summaryrefslogtreecommitdiff
path: root/src/mail-wrapper.c
blob: 5989ae16236a605d158a5197a5c9d966ee55da6b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
** generic wrapper that will take info from a environment 
** variable, and pass it to two commands.
**
** 10-17-96 : Hal Schechner
** 12-14-96 : John Viega -- changed to work on 1 command, 
**                          take a list of valid commands,
**                          just pass on argv, and use execvp()
**                          Also threw in some useful feedback for when there's
**                          a failure, mainly for future debugging.
**                          Made it a root script so we could call setuid()
**
** Chmod this bitch 4755.
**
*/
#include <stdio.h>

const char *COMMAND_LOCATION = "/home/mailman/mailman/scripts";

extern int errno;
FILE *f;

const char *VALID_COMMANDS[] = {
  "post", 
  "mailcmd",
  "mailowner",
  NULL /* Sentinal, don't remove */
};


/* Might want to make this full path.  
   I can write whatever program named sendmail,
   so this isn't much for security.
*/
const char *LEGAL_PARENT_NAMES[] = {
  "sendmail",
  NULL /* Sentinal, don't remove */
};

/* Should make these arrays too... */
const int  LEGAL_PARENT_UID = 1;  /* mail's UID */
const int  LEGAL_PARENT_GID = 1; /* mail's GID */


/*
** what is the name of the process with pid of 'pid'
*/
char *get_process_name(int pid) {
    FILE *proc;
    char fname[30];
    char tmp[255];
    static char procname[255];
    sprintf(fname, "/proc/%d/status", pid);
    proc = fopen(fname, "r");
    fgets(tmp, 256, proc);
    sscanf(tmp, "Name:   %s\n", procname);
    fclose(proc);
    return procname;
}


int valid_parent(char *parent){
  int i = 0;

  while(LEGAL_PARENT_NAMES[i] != NULL)
    {
      if(!strcmp(parent, LEGAL_PARENT_NAMES[i]))
	{
	  return 1;
	}
      i++;
    }
  return 0;
}

/* 
** is the parent process allowed to call us?
*/
int legal_caller() {
    /* compare to our parent's uid */
    if(LEGAL_PARENT_UID != getuid()) 
      {
	fprintf(f,"GOT UID %d.\n", getuid());
        return 0;
      }
    if(LEGAL_PARENT_GID != getgid())
      {
	fprintf(f,"GOT GID %d.\n", getgid());
        return 0;
      }
    return 1;
}

int valid_command(char *command){
  int i = 0;

  while(VALID_COMMANDS[i] != NULL)
    {
      if(!strcmp(command, VALID_COMMANDS[i]))
	{
	  return 1;
	}
      i++;
    }
  return 0;
}

void main(int argc, char **argv) {
  char  *command;
  int   i;
  
  f = fopen("/tmp/fart", "w+");
  if(argc < 2)
    {
      fprintf(f,"Usage: %s program [args...]\n", argv[0]);
      fflush(stdout);
      exit(0);
    }
  i = strlen(argv[1]) + strlen(COMMAND_LOCATION) + 2;
  command = (char *)malloc(sizeof(char) * i);
  sprintf(command, "%s/%s", COMMAND_LOCATION, argv[1]);

  if(!valid_command(argv[1])){
      fprintf(f,"Illegal command.\n");
    }
  else{
    if(legal_caller()) {
      setuid(geteuid());
      execv(command, &argv[1]);
    }
    else {
      fprintf(f,"Illegal caller!\n");
    }
  }
}