source: trunk/run_email2trac.c

Last change on this file was 654, checked in by bas, 10 years ago

fixed format-security problem, closes #341
fixed Typo in variable assignment, closes #342

  • Property svn:keywords set to Id
File size: 4.8 KB
Line 
1/*
2    run_email2trac.c
3    Authors: Bas van der Vlies, Walter de Jong and Michel Jouvin
4    SVN Info:
5        $Id: run_email2trac.c 654 2014-04-24 20:01:07Z bas $
6
7    Only nobody can become the user www-data. Postfix uses this
8    user to start an program
9
10    Copyright 2002 SURFsara
11
12    Licensed under the Apache License, Version 2.0 (the "License");
13    you may not use this file except in compliance with the License.
14    You may obtain a copy of the License at
15
16    http://www.apache.org/licenses/LICENSE-2.0
17
18    Unless required by applicable law or agreed to in writing, software
19    distributed under the License is distributed on an "AS IS" BASIS,
20    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21    See the License for the specific language governing permissions and
22    limitations under the License.
23*/
24#include "config.h"
25
26#include <sys/types.h>
27#include <stdlib.h>
28#include <unistd.h>
29#include <pwd.h>
30#include <sys/stat.h>
31#include <string.h>
32#include <stdio.h>
33#include <limits.h>
34#include <syslog.h>
35
36#ifdef HAVE_INITGROUPS
37#include <grp.h>
38#endif
39
40#include "run_email2trac.h"
41
42#ifndef DEBUG
43#define DEBUG 0
44#endif
45
46void check_username(char *name)
47{
48  if ( strlen(name) > 30 ) {
49    openlog("run_email2trac", LOG_PID, LOG_MAIL); 
50    syslog(LOG_ERR, "MTA_USERNAME is to large; %s\n", name);
51    closelog();
52    exit(-1);
53  }
54}
55
56void email2trac_log(char *message)
57{
58    openlog("run_email2trac", LOG_PID, LOG_MAIL); 
59    syslog(LOG_ERR, "%s", message);
60    closelog();
61}
62
63int main(int argc, char** argv) {
64
65    int i,j;
66    int caller = getuid();
67    int status; 
68   
69    char   **trac_script_args;
70    char   *python_egg_cache = NULL; 
71    struct passwd *TRAC; 
72    struct passwd *MTA;
73    struct stat script_attrs;
74    const char *trac_script = TRAC_SCRIPT_PATH "/" TRAC_SCRIPT_NAME;
75
76    char    error_msg[1024];
77 
78    /*
79    printf("trac_script = %s\n", trac_script);
80    */
81
82    /*
83    First copy arguments passed to the wrapper as scripts arguments
84    aft er filtering out some of the possible script options
85    */
86
87    trac_script_args = (char**) malloc((argc+1)*sizeof(char*));
88    if (trac_script_args == NULL) {
89        snprintf(error_msg, sizeof(error_msg), "malloc failed");
90        email2trac_log(error_msg);
91        return 1; 
92    } 
93   
94    trac_script_args[0] = TRAC_SCRIPT_NAME;
95    for (i=j=1; i<argc; i++) {
96
97        if ( (strcmp(argv[i],"--file") == 0) || 
98             (strcmp(argv[i],"-f") == 0) ) {
99            i++;
100            continue;
101        }
102        else if ( (strcmp(argv[i],"--eggcache") == 0) ||
103                  (strcmp(argv[i],"-e") == 0) ) {
104            i++;
105            python_egg_cache = argv[i];
106            continue;
107        }
108   
109        trac_script_args[j] = argv[i];
110        j++;
111    }
112
113    trac_script_args[j] = NULL;
114
115    /* check caller */
116    check_username(MTA_USER);
117    MTA = getpwnam(MTA_USER); 
118   
119    if ( MTA == NULL ) {
120        snprintf(error_msg, sizeof(error_msg), "Invalid MTA user (%s)", MTA_USER);
121        email2trac_log(error_msg);
122        return -3;     /* 253 : MTA user not found */
123    }
124
125    if ( caller !=  MTA->pw_uid ) {
126        snprintf(error_msg, sizeof(error_msg), "Invalid caller UID (%d)", caller);
127        email2trac_log(error_msg);
128        return -2;     /* 254 : Invalid caller */
129    }
130 
131    /* set UID/GID and supplementary groups to be Trac (or apache) user */
132    check_username(TRAC_USER);
133    if ( TRAC = getpwnam(TRAC_USER) ) {
134#ifdef HAVE_INITGROUPS
135        if (initgroups(TRAC_USER, TRAC->pw_gid)) {
136            snprintf(error_msg, sizeof(error_msg), "initgroups failed");
137            email2trac_log(error_msg);
138            return -7;    /* 249 : Can't set supplementary groups */
139        }
140#endif
141        if (setgid(TRAC->pw_gid) || setuid(TRAC->pw_uid)) {
142            snprintf(error_msg, sizeof(error_msg), "setgid or setuid failed");
143            email2trac_log(error_msg);
144            return -5;   /* 251: Can't set gid or uid */
145        }
146    } 
147    else {
148            snprintf(error_msg, sizeof(error_msg), "Invalid Trac user (%s)", TRAC_USER);
149            email2trac_log(error_msg);
150            return -6;     /* 250 : Trac user not found */
151    }
152   
153    /* Check that script exists */
154    if ( stat(trac_script,&script_attrs) ) {
155        snprintf(error_msg, sizeof(error_msg), "Script not found (%s)", trac_script);
156        email2trac_log(error_msg);
157        return -4;    /* 252 : script not found */
158    }
159 
160    /* Set PYTHON_EGG_CACHE env variable if we have been told to do so */
161    if ( python_egg_cache != NULL ) {
162        setenv("PYTHON_EGG_CACHE",python_egg_cache ,1);
163    }
164
165    /* Execute script */
166    status = execv(trac_script, trac_script_args);
167 
168    /* should never reach this point */
169    snprintf(error_msg, sizeof(error_msg), 
170        "Script %s execution failure (error=%d). Check permission and interpreter path.", 
171        trac_script, status);
172    email2trac_log(error_msg);
173    return -1; 
174}
175
176/* EOB */
Note: See TracBrowser for help on using the repository browser.