Mercurial > masqmail
comparison src/masqmail.c @ 10:26e34ae9a3e3
changed indention and line wrapping to a more consistent style
author | meillo@marmaro.de |
---|---|
date | Mon, 27 Oct 2008 16:23:10 +0100 |
parents | 08114f7dcc23 |
children | 9fb7ddbaf129 |
comparison
equal
deleted
inserted
replaced
9:31cc8a89cb74 | 10:26e34ae9a3e3 |
---|---|
35 | 35 |
36 /* mutually exclusive modes. Note that there is neither a 'get' mode | 36 /* mutually exclusive modes. Note that there is neither a 'get' mode |
37 nor a 'queue daemon' mode. These, as well as the distinction beween | 37 nor a 'queue daemon' mode. These, as well as the distinction beween |
38 the two (non exclusive) daemon (queue and listen) modes are handled | 38 the two (non exclusive) daemon (queue and listen) modes are handled |
39 by flags.*/ | 39 by flags.*/ |
40 typedef enum _mta_mode | 40 typedef enum _mta_mode { |
41 { | 41 MODE_ACCEPT = 0, /* accept message on stdin */ |
42 MODE_ACCEPT = 0, /* accept message on stdin */ | 42 MODE_DAEMON, /* run as daemon */ |
43 MODE_DAEMON, /* run as daemon */ | 43 MODE_RUNQUEUE, /* single queue run, online or offline */ |
44 MODE_RUNQUEUE, /* single queue run, online or offline */ | 44 MODE_GET_DAEMON, /* run as get (retrieve) daemon */ |
45 MODE_GET_DAEMON, /* run as get (retrieve) daemon */ | 45 MODE_SMTP, /* accept SMTP on stdin */ |
46 MODE_SMTP, /* accept SMTP on stdin */ | 46 MODE_LIST, /* list queue */ |
47 MODE_LIST, /* list queue */ | 47 MODE_MCMD, /* do queue manipulation */ |
48 MODE_MCMD, /* do queue manipulation */ | 48 MODE_VERSION, /* show version */ |
49 MODE_VERSION, /* show version */ | 49 MODE_BI, /* fake ;-) */ |
50 MODE_BI, /* fake ;-) */ | 50 MODE_NONE /* to prevent default MODE_ACCEPT */ |
51 MODE_NONE /* to prevent default MODE_ACCEPT */ | 51 } mta_mode; |
52 }mta_mode; | |
53 | 52 |
54 char *pidfile = NULL; | 53 char *pidfile = NULL; |
55 volatile int sigterm_in_progress = 0; | 54 volatile int sigterm_in_progress = 0; |
56 | 55 |
57 static | 56 static void |
58 void sigterm_handler(int sig) | 57 sigterm_handler(int sig) |
59 { | 58 { |
60 if(sigterm_in_progress) | 59 if (sigterm_in_progress) |
61 raise(sig); | 60 raise(sig); |
62 sigterm_in_progress = 1; | 61 sigterm_in_progress = 1; |
63 | 62 |
64 if(pidfile){ | 63 if (pidfile) { |
65 uid_t uid; | 64 uid_t uid; |
66 uid = seteuid(0); | 65 uid = seteuid(0); |
67 if(unlink(pidfile) != 0) | 66 if (unlink(pidfile) != 0) |
68 logwrite(LOG_WARNING, "could not delete pid file %s: %s\n", | 67 logwrite(LOG_WARNING, "could not delete pid file %s: %s\n", pidfile, strerror(errno)); |
69 pidfile, strerror(errno)); | 68 seteuid(uid); /* we exit anyway after this, just to be sure */ |
70 seteuid(uid); /* we exit anyway after this, just to be sure */ | 69 } |
71 } | 70 |
72 | 71 signal(sig, SIG_DFL); |
73 signal(sig, SIG_DFL); | 72 raise(sig); |
74 raise(sig); | 73 } |
75 } | 74 |
76 | 75 #ifdef ENABLE_IDENT /* so far used for that only */ |
77 #ifdef ENABLE_IDENT /* so far used for that only */ | 76 static gboolean |
78 static | 77 is_in_netlist(gchar * host, GList * netlist) |
79 gboolean is_in_netlist(gchar *host, GList *netlist) | 78 { |
80 { | 79 guint hostip = inet_addr(host); |
81 guint hostip = inet_addr(host); | 80 struct in_addr addr; |
82 struct in_addr addr; | 81 |
83 | 82 addr.s_addr = hostip; |
84 addr.s_addr = hostip; | 83 if (addr.s_addr != INADDR_NONE) { |
85 if(addr.s_addr != INADDR_NONE){ | 84 GList *node; |
86 GList *node; | 85 foreach(netlist, node) { |
87 foreach(netlist, node){ | 86 struct in_addr *net = (struct in_addr *) (node->data); |
88 struct in_addr *net = (struct in_addr *)(node->data); | 87 if ((addr.s_addr & net->s_addr) == net->s_addr) |
89 if((addr.s_addr & net->s_addr) == net->s_addr) | 88 return TRUE; |
90 return TRUE; | 89 } |
91 } | 90 } |
92 } | 91 return FALSE; |
93 return FALSE; | 92 } |
94 } | 93 #endif |
95 #endif | 94 |
96 | 95 gchar* |
97 gchar *get_optarg(char *argv[], gint argc, gint *argp, gint *pos) | 96 get_optarg(char *argv[], gint argc, gint * argp, gint * pos) |
98 { | 97 { |
99 if(argv[*argp][*pos]) | 98 if (argv[*argp][*pos]) |
100 return &(argv[*argp][*pos]); | 99 return &(argv[*argp][*pos]); |
101 else{ | 100 else { |
102 if(*argp+1 < argc){ | 101 if (*argp + 1 < argc) { |
103 if(argv[(*argp)+1][0] != '-'){ | 102 if (argv[(*argp) + 1][0] != '-') { |
104 (*argp)++; | 103 (*argp)++; |
105 *pos = 0; | 104 *pos = 0; |
106 return &(argv[*argp][*pos]); | 105 return &(argv[*argp][*pos]); |
107 } | 106 } |
108 } | 107 } |
109 } | 108 } |
110 return NULL; | 109 return NULL; |
111 } | 110 } |
112 | 111 |
113 gchar *get_progname(gchar *arg0) | 112 gchar* |
114 { | 113 get_progname(gchar * arg0) |
115 gchar *p = arg0 + strlen(arg0) - 1; | 114 { |
116 while(p > arg0){ | 115 gchar *p = arg0 + strlen(arg0) - 1; |
117 if(*p == '/') | 116 while (p > arg0) { |
118 return p+1; | 117 if (*p == '/') |
119 p--; | 118 return p + 1; |
120 } | 119 p--; |
121 return p; | 120 } |
122 } | 121 return p; |
123 | 122 } |
124 gboolean write_pidfile(gchar *name) | 123 |
125 { | 124 gboolean |
126 FILE *fptr; | 125 write_pidfile(gchar * name) |
127 | 126 { |
128 if((fptr = fopen(name, "wt"))){ | 127 FILE *fptr; |
129 fprintf(fptr, "%d\n", getpid()); | 128 |
130 fclose(fptr); | 129 if ((fptr = fopen(name, "wt"))) { |
131 pidfile = strdup(name); | 130 fprintf(fptr, "%d\n", getpid()); |
132 return TRUE; | 131 fclose(fptr); |
133 } | 132 pidfile = strdup(name); |
134 logwrite(LOG_WARNING, "could not write pid file: %s\n", strerror(errno)); | 133 return TRUE; |
135 return FALSE; | 134 } |
136 } | 135 logwrite(LOG_WARNING, "could not write pid file: %s\n", strerror(errno)); |
137 | 136 return FALSE; |
138 static | 137 } |
139 void mode_daemon(gboolean do_listen, gint queue_interval, char *argv[]) | 138 |
140 { | 139 static void |
141 guint pid; | 140 mode_daemon(gboolean do_listen, gint queue_interval, char *argv[]) |
142 | 141 { |
143 /* daemon */ | 142 guint pid; |
144 if(!conf.run_as_user){ | 143 |
145 if((conf.orig_uid != 0) && (conf.orig_uid != conf.mail_uid)){ | 144 /* daemon */ |
146 fprintf(stderr, "must be root or %s for daemon.\n", DEF_MAIL_USER); | 145 if (!conf.run_as_user) { |
147 exit(EXIT_FAILURE); | 146 if ((conf.orig_uid != 0) && (conf.orig_uid != conf.mail_uid)) { |
148 } | 147 fprintf(stderr, "must be root or %s for daemon.\n", DEF_MAIL_USER); |
149 } | 148 exit(EXIT_FAILURE); |
150 | 149 } |
151 if((pid = fork()) > 0){ | 150 } |
152 exit(EXIT_SUCCESS); | 151 |
153 }else if(pid < 0){ | 152 if ((pid = fork()) > 0) { |
154 logwrite(LOG_ALERT, "could not fork!"); | 153 exit(EXIT_SUCCESS); |
155 exit(EXIT_FAILURE); | 154 } else if (pid < 0) { |
156 } | 155 logwrite(LOG_ALERT, "could not fork!"); |
157 | 156 exit(EXIT_FAILURE); |
158 signal(SIGTERM, sigterm_handler); | 157 } |
159 write_pidfile(PIDFILEDIR"/masqmail.pid"); | 158 |
160 | 159 signal(SIGTERM, sigterm_handler); |
161 conf.do_verbose = FALSE; | 160 write_pidfile(PIDFILEDIR "/masqmail.pid"); |
162 | 161 |
163 fclose(stdin); | 162 conf.do_verbose = FALSE; |
164 fclose(stdout); | 163 |
165 fclose(stderr); | 164 fclose(stdin); |
166 | 165 fclose(stdout); |
167 listen_port(do_listen ? conf.listen_addresses : NULL, | 166 fclose(stderr); |
168 queue_interval, argv); | 167 |
168 listen_port(do_listen ? conf.listen_addresses : NULL, queue_interval, argv); | |
169 } | 169 } |
170 | 170 |
171 #ifdef ENABLE_POP3 | 171 #ifdef ENABLE_POP3 |
172 static | 172 static void |
173 void mode_get_daemon(gint get_interval, char *argv[]) | 173 mode_get_daemon(gint get_interval, char *argv[]) |
174 { | 174 { |
175 guint pid; | 175 guint pid; |
176 | 176 |
177 /* daemon */ | 177 /* daemon */ |
178 if(!conf.run_as_user){ | 178 if (!conf.run_as_user) { |
179 if((conf.orig_uid != 0) && (conf.orig_uid != conf.mail_uid)){ | 179 if ((conf.orig_uid != 0) && (conf.orig_uid != conf.mail_uid)) { |
180 fprintf(stderr, "must be root or %s for daemon.\n", DEF_MAIL_USER); | 180 fprintf(stderr, "must be root or %s for daemon.\n", DEF_MAIL_USER); |
181 exit(EXIT_FAILURE); | 181 exit(EXIT_FAILURE); |
182 } | 182 } |
183 } | 183 } |
184 | 184 |
185 if((pid = fork()) > 0){ | 185 if ((pid = fork()) > 0) { |
186 exit(EXIT_SUCCESS); | 186 exit(EXIT_SUCCESS); |
187 }else if(pid < 0){ | 187 } else if (pid < 0) { |
188 logwrite(LOG_ALERT, "could not fork!"); | 188 logwrite(LOG_ALERT, "could not fork!"); |
189 exit(EXIT_FAILURE); | 189 exit(EXIT_FAILURE); |
190 } | 190 } |
191 | 191 |
192 signal(SIGTERM, sigterm_handler); | 192 signal(SIGTERM, sigterm_handler); |
193 write_pidfile(PIDFILEDIR"/masqmail-get.pid"); | 193 write_pidfile(PIDFILEDIR "/masqmail-get.pid"); |
194 | 194 |
195 conf.do_verbose = FALSE; | 195 conf.do_verbose = FALSE; |
196 | 196 |
197 fclose(stdin); | 197 fclose(stdin); |
198 fclose(stdout); | 198 fclose(stdout); |
199 fclose(stderr); | 199 fclose(stderr); |
200 | 200 |
201 get_daemon(get_interval, argv); | 201 get_daemon(get_interval, argv); |
202 } | 202 } |
203 #endif | 203 #endif |
204 | 204 |
205 #ifdef ENABLE_SMTP_SERVER | 205 #ifdef ENABLE_SMTP_SERVER |
206 static void mode_smtp() | 206 static void |
207 { | 207 mode_smtp() |
208 /* accept smtp message on stdin */ | 208 { |
209 /* write responses to stderr. */ | 209 /* accept smtp message on stdin */ |
210 | 210 /* write responses to stderr. */ |
211 struct sockaddr_in saddr; | 211 |
212 gchar *peername = NULL; | 212 struct sockaddr_in saddr; |
213 int dummy = sizeof(saddr); | 213 gchar *peername = NULL; |
214 int dummy = sizeof(saddr); | |
214 #ifdef ENABLE_IDENT | 215 #ifdef ENABLE_IDENT |
215 gchar *ident = NULL; | 216 gchar *ident = NULL; |
216 #endif | 217 #endif |
217 | 218 |
218 conf.do_verbose = FALSE; | 219 conf.do_verbose = FALSE; |
219 | 220 |
220 if(!conf.run_as_user){ | 221 if (!conf.run_as_user) { |
221 seteuid(conf.orig_uid); | 222 seteuid(conf.orig_uid); |
222 setegid(conf.orig_gid); | 223 setegid(conf.orig_gid); |
223 } | 224 } |
224 | 225 |
225 DEBUG(5) debugf("accepting smtp message on stdin\n"); | 226 DEBUG(5) debugf("accepting smtp message on stdin\n"); |
226 | 227 |
227 if(getpeername(0, (struct sockaddr *)(&saddr), &dummy) == 0){ | 228 if (getpeername(0, (struct sockaddr *) (&saddr), &dummy) == 0) { |
228 peername = g_strdup(inet_ntoa(saddr.sin_addr)); | 229 peername = g_strdup(inet_ntoa(saddr.sin_addr)); |
229 #ifdef ENABLE_IDENT | 230 #ifdef ENABLE_IDENT |
230 { | 231 { |
231 gchar *id = NULL; | 232 gchar *id = NULL; |
232 if((id = (gchar *)ident_id(0, 60))){ | 233 if ((id = (gchar *) ident_id(0, 60))) { |
233 ident = g_strdup(id); | 234 ident = g_strdup(id); |
234 } | 235 } |
235 } | 236 } |
236 #endif | 237 #endif |
237 }else if(errno != ENOTSOCK) | 238 } else if (errno != ENOTSOCK) |
238 exit(EXIT_FAILURE); | 239 exit(EXIT_FAILURE); |
239 | 240 |
240 //smtp_in(stdin, stdout, peername); | 241 //smtp_in(stdin, stdout, peername); |
241 smtp_in(stdin, stderr, peername, NULL); | 242 smtp_in(stdin, stderr, peername, NULL); |
242 | 243 |
243 #ifdef ENABLE_IDENT | 244 #ifdef ENABLE_IDENT |
244 if(ident) g_free(ident); | 245 if (ident) |
245 #endif | 246 g_free(ident); |
246 } | 247 #endif |
247 #endif | 248 } |
248 | 249 #endif |
249 static void mode_accept(address *return_path, gchar *full_sender_name, | 250 |
250 guint accept_flags, char **addresses, int addr_cnt) | 251 static void |
251 { | 252 mode_accept(address * return_path, gchar * full_sender_name, guint accept_flags, char **addresses, int addr_cnt) |
252 /* accept message on stdin */ | 253 { |
253 accept_error err; | 254 /* accept message on stdin */ |
254 message *msg = create_message(); | 255 accept_error err; |
255 gint i; | 256 message *msg = create_message(); |
256 | 257 gint i; |
257 if(return_path != NULL){ | 258 |
258 if((conf.orig_uid != 0) && | 259 if (return_path != NULL) { |
259 (conf.orig_uid != conf.mail_uid) && | 260 if ((conf.orig_uid != 0) |
260 (!is_ingroup(conf.orig_uid, conf.mail_gid))){ | 261 && (conf.orig_uid != conf.mail_uid) |
261 fprintf(stderr, | 262 && (!is_ingroup(conf.orig_uid, conf.mail_gid))) { |
262 "must be in root, %s or in group %s for setting return path.\n", | 263 fprintf(stderr, "must be in root, %s or in group %s for setting return path.\n", DEF_MAIL_USER, DEF_MAIL_GROUP); |
263 DEF_MAIL_USER, DEF_MAIL_GROUP); | 264 exit(EXIT_FAILURE); |
264 exit(EXIT_FAILURE); | 265 } |
265 } | 266 } |
266 } | 267 |
267 | 268 if (!conf.run_as_user) { |
268 if(!conf.run_as_user){ | 269 seteuid(conf.orig_uid); |
269 seteuid(conf.orig_uid); | 270 setegid(conf.orig_gid); |
270 setegid(conf.orig_gid); | 271 } |
271 } | 272 |
272 | 273 DEBUG(5) debugf("accepting message on stdin\n"); |
273 DEBUG(5) debugf("accepting message on stdin\n"); | 274 |
274 | 275 msg->received_prot = PROT_LOCAL; |
275 msg->received_prot = PROT_LOCAL; | 276 for (i = 0; i < addr_cnt; i++) { |
276 for(i = 0; i < addr_cnt; i++){ | 277 if (addresses[i][0] != '|') |
277 if(addresses[i][0] != '|') | 278 msg->rcpt_list = g_list_append(msg->rcpt_list, create_address_qualified(addresses[i], TRUE, conf.host_name)); |
278 msg->rcpt_list = | 279 else { |
279 g_list_append(msg->rcpt_list, | 280 logwrite(LOG_ALERT, "no pipe allowed as recipient address: %s\n", addresses[i]); |
280 create_address_qualified(addresses[i], TRUE, conf.host_name)); | 281 exit(EXIT_FAILURE); |
281 else{ | 282 } |
282 logwrite(LOG_ALERT, "no pipe allowed as recipient address: %s\n", addresses[i]); | 283 } |
283 exit(EXIT_FAILURE); | 284 |
284 } | 285 /* -f option */ |
285 } | 286 msg->return_path = return_path; |
286 | 287 |
287 /* -f option */ | 288 /* -F option */ |
288 msg->return_path = return_path; | 289 msg->full_sender_name = full_sender_name; |
289 | 290 |
290 /* -F option */ | 291 if ((err = accept_message(stdin, msg, accept_flags)) == AERR_OK) { |
291 msg->full_sender_name = full_sender_name; | 292 if (spool_write(msg, TRUE)) { |
292 | 293 pid_t pid; |
293 if((err = accept_message(stdin, msg, accept_flags)) == AERR_OK){ | 294 logwrite(LOG_NOTICE, "%s <= %s with %s\n", msg->uid, addr_string(msg->return_path), prot_names[PROT_LOCAL]); |
294 if(spool_write(msg, TRUE)){ | 295 |
295 pid_t pid; | 296 if (!conf.do_queue) { |
296 logwrite(LOG_NOTICE, "%s <= %s with %s\n", | 297 if ((pid = fork()) == 0) { |
297 msg->uid, addr_string(msg->return_path), | 298 conf.do_verbose = FALSE; |
298 prot_names[PROT_LOCAL]); | 299 fclose(stdin); |
299 | 300 fclose(stdout); |
300 if(!conf.do_queue){ | 301 fclose(stderr); |
301 | 302 if (deliver(msg)) { |
302 if((pid = fork()) == 0){ | 303 exit(EXIT_SUCCESS); |
303 | 304 } else |
304 conf.do_verbose = FALSE; | 305 exit(EXIT_FAILURE); |
305 | 306 } else if (pid < 0) { |
306 fclose(stdin); | 307 logwrite(LOG_ALERT, "could not fork for delivery, id = %s", msg->uid); |
307 fclose(stdout); | 308 } |
308 fclose(stderr); | 309 } |
309 | 310 } else { |
310 if(deliver(msg)){ | 311 fprintf(stderr, "Could not write spool file\n"); |
311 exit(EXIT_SUCCESS); | 312 exit(EXIT_FAILURE); |
312 }else | 313 } |
313 exit(EXIT_FAILURE); | 314 } else { |
314 }else if(pid < 0){ | 315 switch (err) { |
315 logwrite(LOG_ALERT, "could not fork for delivery, id = %s", | 316 case AERR_EOF: |
316 msg->uid); | 317 fprintf(stderr, "unexpected EOF.\n"); |
317 } | 318 exit(EXIT_FAILURE); |
318 } | 319 case AERR_NORCPT: |
319 }else{ | 320 fprintf(stderr, "no recipients.\n"); |
320 fprintf(stderr, "Could not write spool file\n"); | 321 exit(EXIT_FAILURE); |
321 exit(EXIT_FAILURE); | 322 default: |
322 } | 323 /* should never happen: */ |
323 }else{ | 324 fprintf(stderr, "Unknown error (%d)\r\n", err); |
324 switch(err){ | 325 exit(EXIT_FAILURE); |
325 case AERR_EOF: | 326 } |
326 fprintf(stderr, "unexpected EOF.\n"); | 327 exit(EXIT_FAILURE); |
327 exit(EXIT_FAILURE); | 328 } |
328 case AERR_NORCPT: | |
329 fprintf(stderr, "no recipients.\n"); | |
330 exit(EXIT_FAILURE); | |
331 default: | |
332 /* should never happen: */ | |
333 fprintf(stderr, "Unknown error (%d)\r\n", err); | |
334 exit(EXIT_FAILURE); | |
335 } | |
336 exit(EXIT_FAILURE); | |
337 } | |
338 } | 329 } |
339 | 330 |
340 int | 331 int |
341 main(int argc, char *argv[]) | 332 main(int argc, char *argv[]) |
342 { | 333 { |
343 /* cmd line flags */ | 334 /* cmd line flags */ |
344 gchar *conf_file = CONF_FILE; | 335 gchar *conf_file = CONF_FILE; |
345 gint arg = 1; | 336 gint arg = 1; |
346 gboolean do_get = FALSE; | 337 gboolean do_get = FALSE; |
347 gboolean do_get_online = FALSE; | 338 gboolean do_get_online = FALSE; |
348 | 339 |
349 gboolean do_listen = FALSE; | 340 gboolean do_listen = FALSE; |
350 gboolean do_runq = FALSE; | 341 gboolean do_runq = FALSE; |
351 gboolean do_runq_online = FALSE; | 342 gboolean do_runq_online = FALSE; |
352 | 343 |
353 gboolean do_queue = FALSE; | 344 gboolean do_queue = FALSE; |
354 | 345 |
355 gboolean do_verbose = FALSE; | 346 gboolean do_verbose = FALSE; |
356 gint debug_level = -1; | 347 gint debug_level = -1; |
357 | 348 |
358 mta_mode mta_mode = MODE_ACCEPT; | 349 mta_mode mta_mode = MODE_ACCEPT; |
359 | 350 |
360 gint queue_interval = 0; | 351 gint queue_interval = 0; |
361 gint get_interval = 0; | 352 gint get_interval = 0; |
362 gboolean opt_t = FALSE; | 353 gboolean opt_t = FALSE; |
363 gboolean opt_i = FALSE; | 354 gboolean opt_i = FALSE; |
364 gboolean opt_odb = FALSE; | 355 gboolean opt_odb = FALSE; |
365 gboolean opt_oem = FALSE; | 356 gboolean opt_oem = FALSE; |
366 gboolean exit_failure = FALSE; | 357 gboolean exit_failure = FALSE; |
367 | 358 |
368 gchar *M_cmd = NULL; | 359 gchar *M_cmd = NULL; |
369 | 360 |
370 gint exit_code = EXIT_SUCCESS; | 361 gint exit_code = EXIT_SUCCESS; |
371 gchar *route_name = NULL; | 362 gchar *route_name = NULL; |
372 gchar *get_name = NULL; | 363 gchar *get_name = NULL; |
373 gchar *progname; | 364 gchar *progname; |
374 gchar *f_address = NULL; | 365 gchar *f_address = NULL; |
375 gchar *full_sender_name = NULL; | 366 gchar *full_sender_name = NULL; |
376 address *return_path = NULL; /* may be changed by -f option */ | 367 address *return_path = NULL; /* may be changed by -f option */ |
377 | 368 |
378 progname = get_progname(argv[0]); | 369 progname = get_progname(argv[0]); |
379 | 370 |
380 if(strcmp(progname, "mailq") == 0) | 371 if (strcmp(progname, "mailq") == 0) { |
381 { mta_mode = MODE_LIST; } | 372 mta_mode = MODE_LIST; |
382 else if(strcmp(progname, "mailrm") == 0) | 373 } else if (strcmp(progname, "mailrm") == 0) { |
383 { mta_mode = MODE_MCMD; M_cmd = "rm"; } | 374 mta_mode = MODE_MCMD; |
384 else if(strcmp(progname, "runq") == 0) | 375 M_cmd = "rm"; |
385 { mta_mode = MODE_RUNQUEUE; do_runq = TRUE; } | 376 } else if (strcmp(progname, "runq") == 0) { |
386 else if(strcmp(progname, "rmail") == 0) | 377 mta_mode = MODE_RUNQUEUE; |
387 { mta_mode = MODE_ACCEPT; opt_i = TRUE; } | 378 do_runq = TRUE; |
388 else if(strcmp(progname, "smtpd") == 0 || strcmp(progname, "in.smtpd") == 0) | 379 } else if (strcmp(progname, "rmail") == 0) { |
389 { mta_mode = MODE_SMTP; } | 380 mta_mode = MODE_ACCEPT; |
390 | 381 opt_i = TRUE; |
391 /* parse cmd line */ | 382 } else if (strcmp(progname, "smtpd") == 0 || strcmp(progname, "in.smtpd") == 0) { |
392 while(arg < argc){ | 383 mta_mode = MODE_SMTP; |
393 gint pos = 0; | 384 } |
394 if((argv[arg][pos] == '-') && (argv[arg][pos+1] != '-')){ | 385 |
395 pos++; | 386 /* parse cmd line */ |
396 switch(argv[arg][pos++]){ | 387 while (arg < argc) { |
397 case 'b': | 388 gint pos = 0; |
398 switch(argv[arg][pos++]){ | 389 if ((argv[arg][pos] == '-') && (argv[arg][pos + 1] != '-')) { |
399 case 'd': | 390 pos++; |
400 do_listen = TRUE; | 391 switch (argv[arg][pos++]) { |
401 mta_mode = MODE_DAEMON; | 392 case 'b': |
402 break; | 393 switch (argv[arg][pos++]) { |
403 case 'i': | 394 case 'd': |
404 /* ignored */ | 395 do_listen = TRUE; |
405 mta_mode = MODE_BI; | 396 mta_mode = MODE_DAEMON; |
406 break; | 397 break; |
407 case 's': | 398 case 'i': |
408 mta_mode = MODE_SMTP; | 399 /* ignored */ |
409 break; | 400 mta_mode = MODE_BI; |
410 case 'p': | 401 break; |
411 mta_mode = MODE_LIST; | 402 case 's': |
412 break; | 403 mta_mode = MODE_SMTP; |
413 case 'V': | 404 break; |
414 mta_mode = MODE_VERSION; | 405 case 'p': |
415 break; | 406 mta_mode = MODE_LIST; |
407 break; | |
408 case 'V': | |
409 mta_mode = MODE_VERSION; | |
410 break; | |
411 default: | |
412 fprintf(stderr, "unrecognized option '%s'\n", argv[arg]); | |
413 exit(EXIT_FAILURE); | |
414 } | |
415 break; | |
416 case 'B': | |
417 /* we ignore this and throw the argument away */ | |
418 get_optarg(argv, argc, &arg, &pos); | |
419 break; | |
420 case 'C': | |
421 if (!(conf_file = get_optarg(argv, argc, &arg, &pos))) { | |
422 fprintf(stderr, "-C requires a filename as argument.\n"); | |
423 exit(EXIT_FAILURE); | |
424 } | |
425 break; | |
426 case 'F': | |
427 { | |
428 full_sender_name = get_optarg(argv, argc, &arg, &pos); | |
429 if (!full_sender_name) { | |
430 fprintf(stderr, "-F requires a name as an argument\n"); | |
431 exit(EXIT_FAILURE); | |
432 } | |
433 } | |
434 break; | |
435 case 'd': | |
436 if (getuid() == 0) { | |
437 char *lvl = get_optarg(argv, argc, &arg, &pos); | |
438 if (lvl) | |
439 debug_level = atoi(lvl); | |
440 else { | |
441 fprintf(stderr, "-d requires a number as an argument.\n"); | |
442 exit(EXIT_FAILURE); | |
443 } | |
444 } else { | |
445 fprintf(stderr, "only root may set the debug level.\n"); | |
446 exit(EXIT_FAILURE); | |
447 } | |
448 break; | |
449 case 'f': | |
450 /* set return path */ | |
451 { | |
452 gchar *address; | |
453 address = get_optarg(argv, argc, &arg, &pos); | |
454 if (address) { | |
455 f_address = g_strdup(address); | |
456 } else { | |
457 fprintf(stderr, "-f requires an address as an argument\n"); | |
458 exit(EXIT_FAILURE); | |
459 } | |
460 } | |
461 break; | |
462 case 'g': | |
463 do_get = TRUE; | |
464 if (!mta_mode) | |
465 mta_mode = MODE_NONE; /* to prevent default MODE_ACCEPT */ | |
466 if (argv[arg][pos] == 'o') { | |
467 pos++; | |
468 do_get_online = TRUE; | |
469 /* can be NULL, then we use online detection method */ | |
470 route_name = get_optarg(argv, argc, &arg, &pos); | |
471 | |
472 if (route_name != NULL) { | |
473 if (isdigit(route_name[0])) { | |
474 get_interval = time_interval(route_name, &pos); | |
475 route_name = get_optarg(argv, argc, &arg, &pos); | |
476 mta_mode = MODE_GET_DAEMON; | |
477 do_get = FALSE; | |
478 } | |
479 } | |
480 } else { | |
481 if ((optarg = get_optarg(argv, argc, &arg, &pos))) { | |
482 get_name = get_optarg(argv, argc, &arg, &pos); | |
483 } | |
484 } | |
485 break; | |
486 case 'i': | |
487 if (argv[arg][pos] == 0) { | |
488 opt_i = TRUE; | |
489 exit_failure = FALSE; /* may override -oem */ | |
490 } else { | |
491 fprintf(stderr, "unrecognized option '%s'\n", argv[arg]); | |
492 exit(EXIT_FAILURE); | |
493 } | |
494 break; | |
495 case 'M': | |
496 { | |
497 mta_mode = MODE_MCMD; | |
498 M_cmd = g_strdup(&(argv[arg][pos])); | |
499 } | |
500 break; | |
501 case 'o': | |
502 switch (argv[arg][pos++]) { | |
503 case 'e': | |
504 if (argv[arg][pos++] == 'm') /* -oem */ | |
505 if (!opt_i) | |
506 exit_failure = TRUE; | |
507 opt_oem = TRUE; | |
508 break; | |
509 case 'd': | |
510 if (argv[arg][pos] == 'b') /* -odb */ | |
511 opt_odb = TRUE; | |
512 else if (argv[arg][pos] == 'q') /* -odq */ | |
513 do_queue = TRUE; | |
514 break; | |
515 case 'i': | |
516 opt_i = TRUE; | |
517 exit_failure = FALSE; /* may override -oem */ | |
518 break; | |
519 } | |
520 break; | |
521 | |
522 case 'q': | |
523 { | |
524 gchar *optarg; | |
525 | |
526 do_runq = TRUE; | |
527 mta_mode = MODE_RUNQUEUE; | |
528 if (argv[arg][pos] == 'o') { | |
529 pos++; | |
530 do_runq = FALSE; | |
531 do_runq_online = TRUE; | |
532 /* can be NULL, then we use online detection method */ | |
533 route_name = get_optarg(argv, argc, &arg, &pos); | |
534 } else | |
535 if ((optarg = get_optarg(argv, argc, &arg, &pos))) { | |
536 mta_mode = MODE_DAEMON; | |
537 queue_interval = time_interval(optarg, &pos); | |
538 } | |
539 } | |
540 break; | |
541 case 't': | |
542 if (argv[arg][pos] == 0) { | |
543 opt_t = TRUE; | |
544 } else { | |
545 fprintf(stderr, "unrecognized option '%s'\n", argv[arg]); | |
546 exit(EXIT_FAILURE); | |
547 } | |
548 break; | |
549 case 'v': | |
550 do_verbose = TRUE; | |
551 break; | |
552 default: | |
553 fprintf(stderr, "unrecognized option '%s'\n", argv[arg]); | |
554 exit(EXIT_FAILURE); | |
555 } | |
556 } else { | |
557 if (argv[arg][pos + 1] == '-') { | |
558 if (argv[arg][pos + 2] != '\0') { | |
559 fprintf(stderr, "unrecognized option '%s'\n", argv[arg]); | |
560 exit(EXIT_FAILURE); | |
561 } | |
562 arg++; | |
563 } | |
564 break; | |
565 } | |
566 arg++; | |
567 } | |
568 | |
569 if (mta_mode == MODE_VERSION) { | |
570 gchar *with_resolver = "", *with_smtp_server = "", *with_pop3 = "", | |
571 *with_auth = "", *with_maildir = "", *with_ident = "", *with_mserver = ""; | |
572 | |
573 #ifdef ENABLE_RESOLVER | |
574 with_resolver = " +resolver"; | |
575 #endif | |
576 #ifdef ENABLE_SMTP_SERVER | |
577 with_smtp_server = " +smtp-server"; | |
578 #endif | |
579 #ifdef ENABLE_POP3 | |
580 with_pop3 = " +pop3"; | |
581 #endif | |
582 #ifdef ENABLE_AUTH | |
583 with_auth = " +auth"; | |
584 #endif | |
585 #ifdef ENABLE_MAILDIR | |
586 with_maildir = " +maildir"; | |
587 #endif | |
588 #ifdef ENABLE_IDENT | |
589 with_ident = " +ident"; | |
590 #endif | |
591 #ifdef ENABLE_MSERVER | |
592 with_mserver = " +mserver"; | |
593 #endif | |
594 | |
595 printf("%s %s%s%s%s%s%s%s%s\n", PACKAGE, VERSION, with_resolver, with_smtp_server, | |
596 with_pop3, with_auth, with_maildir, with_ident, with_mserver); | |
597 | |
598 exit(EXIT_SUCCESS); | |
599 } | |
600 | |
601 /* initialize random generator */ | |
602 srand(time(NULL)); | |
603 /* ignore SIGPIPE signal */ | |
604 signal(SIGPIPE, SIG_IGN); | |
605 | |
606 /* close all possibly open file descriptors */ | |
607 { | |
608 int i, max_fd = sysconf(_SC_OPEN_MAX); | |
609 | |
610 if (max_fd <= 0) | |
611 max_fd = 64; | |
612 for (i = 3; i < max_fd; i++) | |
613 close(i); | |
614 } | |
615 | |
616 init_conf(); | |
617 | |
618 /* if we are not privileged, and the config file was changed we | |
619 implicetely set the the run_as_user flag and give up all | |
620 privileges. | |
621 | |
622 So it is possible for a user to run his own daemon without | |
623 breaking security. | |
624 */ | |
625 if (strcmp(conf_file, CONF_FILE) != 0) { | |
626 if (conf.orig_uid != 0) { | |
627 conf.run_as_user = TRUE; | |
628 seteuid(conf.orig_uid); | |
629 setegid(conf.orig_gid); | |
630 setuid(conf.orig_uid); | |
631 setgid(conf.orig_gid); | |
632 } | |
633 } | |
634 | |
635 read_conf(conf_file); | |
636 | |
637 if (do_queue) | |
638 conf.do_queue = TRUE; | |
639 if (do_verbose) | |
640 conf.do_verbose = TRUE; | |
641 if (debug_level >= 0) /* if >= 0, it was given by argument */ | |
642 conf.debug_level = debug_level; | |
643 | |
644 chdir("/"); | |
645 | |
646 if (!conf.run_as_user) { | |
647 if (setgid(0) != 0) { | |
648 fprintf(stderr, "could not set gid to 0. Is the setuid bit set? : %s\n", strerror(errno)); | |
649 exit(EXIT_FAILURE); | |
650 } | |
651 if (setuid(0) != 0) { | |
652 fprintf(stderr, "could not gain root privileges. Is the setuid bit set? : %s\n", strerror(errno)); | |
653 exit(EXIT_FAILURE); | |
654 } | |
655 } | |
656 | |
657 if (!logopen()) { | |
658 fprintf(stderr, "could not open log file\n"); | |
659 exit(EXIT_FAILURE); | |
660 } | |
661 | |
662 DEBUG(1) debugf("masqmail %s starting\n", VERSION); | |
663 | |
664 DEBUG(5) { | |
665 gchar **str = argv; | |
666 debugf("args: \n"); | |
667 while (*str) { | |
668 debugf("%s \n", *str); | |
669 str++; | |
670 } | |
671 } | |
672 DEBUG(5) debugf("queue_interval = %d\n", queue_interval); | |
673 | |
674 if (f_address) { | |
675 return_path = create_address_qualified(f_address, TRUE, conf.host_name); | |
676 g_free(f_address); | |
677 if (!return_path) { | |
678 fprintf(stderr, "invalid RFC821 address: %s\n", f_address); | |
679 exit(EXIT_FAILURE); | |
680 } | |
681 } | |
682 | |
683 if (do_get) { | |
684 #ifdef ENABLE_POP3 | |
685 if ((mta_mode == MODE_NONE) || (mta_mode == MODE_RUNQUEUE)) { | |
686 set_identity(conf.orig_uid, "getting mail"); | |
687 if (do_get_online) { | |
688 if (route_name != NULL) { | |
689 conf.online_detect = g_strdup("argument"); | |
690 set_online_name(route_name); | |
691 } | |
692 get_online(); | |
693 } else { | |
694 if (get_name) | |
695 get_from_name(get_name); | |
696 else | |
697 get_all(); | |
698 } | |
699 } else { | |
700 logwrite(LOG_ALERT, "get (-g) only allowed alone or together with queue run (-q)\n"); | |
701 } | |
702 #else | |
703 fprintf(stderr, "get (pop) support not compiled in\n"); | |
704 #endif | |
705 } | |
706 | |
707 switch (mta_mode) { | |
708 case MODE_DAEMON: | |
709 mode_daemon(do_listen, queue_interval, argv); | |
710 break; | |
711 case MODE_RUNQUEUE: | |
712 { | |
713 /* queue runs */ | |
714 set_identity(conf.orig_uid, "queue run"); | |
715 | |
716 if (do_runq) | |
717 exit_code = queue_run() ? EXIT_SUCCESS : EXIT_FAILURE; | |
718 | |
719 if (do_runq_online) { | |
720 if (route_name != NULL) { | |
721 conf.online_detect = g_strdup("argument"); | |
722 set_online_name(route_name); | |
723 } | |
724 exit_code = | |
725 queue_run_online() ? EXIT_SUCCESS : EXIT_FAILURE; | |
726 } | |
727 } | |
728 break; | |
729 case MODE_GET_DAEMON: | |
730 #ifdef ENABLE_POP3 | |
731 if (route_name != NULL) { | |
732 conf.online_detect = g_strdup("argument"); | |
733 set_online_name(route_name); | |
734 } | |
735 mode_get_daemon(get_interval, argv); | |
736 #endif | |
737 break; | |
738 | |
739 case MODE_SMTP: | |
740 #ifdef ENABLE_SMTP_SERVER | |
741 mode_smtp(); | |
742 #else | |
743 fprintf(stderr, "smtp server support not compiled in\n"); | |
744 #endif | |
745 break; | |
746 | |
747 case MODE_LIST: | |
748 queue_list(); | |
749 break; | |
750 | |
751 case MODE_BI: | |
752 exit(EXIT_SUCCESS); | |
753 break; /* well... */ | |
754 | |
755 case MODE_MCMD: | |
756 if (strcmp(M_cmd, "rm") == 0) { | |
757 gboolean ok = FALSE; | |
758 | |
759 set_euidgid(conf.mail_uid, conf.mail_gid, NULL, NULL); | |
760 | |
761 if (is_privileged_user(conf.orig_uid)) { | |
762 for (; arg < argc; arg++) { | |
763 if (queue_delete(argv[arg])) | |
764 ok = TRUE; | |
765 } | |
766 } else { | |
767 struct passwd *pw = getpwuid(conf.orig_uid); | |
768 if (pw) { | |
769 for (; arg < argc; arg++) { | |
770 message *msg = msg_spool_read(argv[arg], FALSE); | |
771 #ifdef ENABLE_IDENT | |
772 if (((msg->received_host == NULL) && (msg->received_prot == PROT_LOCAL)) | |
773 || is_in_netlist(msg->received_host, conf.ident_trusted_nets)) { | |
774 #else | |
775 if ((msg->received_host == NULL) && (msg->received_prot == PROT_LOCAL)) { | |
776 #endif | |
777 if (msg->ident) { | |
778 if (strcmp(pw->pw_name, msg->ident) == 0) { | |
779 if (queue_delete(argv[arg])) | |
780 ok = TRUE; | |
781 } else { | |
782 fprintf(stderr, "you do not own message id %s\n", argv[arg]); | |
783 } | |
784 } else | |
785 fprintf(stderr, "message %s does not have an ident.\n", argv[arg]); | |
786 } else { | |
787 fprintf(stderr, "message %s was not received locally or from a trusted network.\n", argv[arg]); | |
788 } | |
789 } | |
790 } else { | |
791 fprintf(stderr, "could not find a passwd entry for uid %d: %s\n", conf.orig_uid, strerror(errno)); | |
792 } | |
793 } | |
794 exit(ok ? EXIT_SUCCESS : EXIT_FAILURE); | |
795 } else { | |
796 fprintf(stderr, "unknown command %s\n", M_cmd); | |
797 exit(EXIT_FAILURE); | |
798 } | |
799 break; | |
800 | |
801 case MODE_ACCEPT: | |
802 { | |
803 guint accept_flags = (opt_t ? ACC_DEL_RCPTS | ACC_DEL_BCC | ACC_RCPT_FROM_HEAD : ACC_HEAD_FROM_RCPT) | |
804 | (opt_i ? ACC_NODOT_TERM : ACC_NODOT_RELAX); | |
805 mode_accept(return_path, full_sender_name, accept_flags, &(argv[arg]), argc - arg); | |
806 exit(exit_failure ? EXIT_FAILURE : EXIT_SUCCESS); | |
807 } | |
808 break; | |
809 case MODE_NONE: | |
810 break; | |
416 default: | 811 default: |
417 fprintf(stderr, "unrecognized option '%s'\n", argv[arg]); | 812 fprintf(stderr, "unknown mode: %d\n", mta_mode); |
418 exit(EXIT_FAILURE); | 813 break; |
419 } | 814 } |
420 break; | 815 |
421 case 'B': | 816 logclose(); |
422 /* we ignore this and throw the argument away */ | 817 |
423 get_optarg(argv, argc, &arg, &pos); | 818 exit(exit_code); |
424 break; | 819 } |
425 case 'C': | |
426 if(!(conf_file = get_optarg(argv, argc, &arg, &pos))){ | |
427 fprintf(stderr, "-C requires a filename as argument.\n"); | |
428 exit(EXIT_FAILURE); | |
429 } | |
430 break; | |
431 case 'F': | |
432 { | |
433 full_sender_name = get_optarg(argv, argc, &arg, &pos); | |
434 if(!full_sender_name){ | |
435 fprintf(stderr, "-F requires a name as an argument\n"); | |
436 exit(EXIT_FAILURE); | |
437 } | |
438 } | |
439 break; | |
440 case 'd': | |
441 if(getuid() == 0){ | |
442 char *lvl = get_optarg(argv, argc, &arg, &pos); | |
443 if(lvl) | |
444 debug_level = atoi(lvl); | |
445 else{ | |
446 fprintf(stderr, "-d requires a number as an argument.\n"); | |
447 exit(EXIT_FAILURE); | |
448 } | |
449 }else{ | |
450 fprintf(stderr, "only root may set the debug level.\n"); | |
451 exit(EXIT_FAILURE); | |
452 } | |
453 break; | |
454 case 'f': | |
455 /* set return path */ | |
456 { | |
457 gchar *address; | |
458 address = get_optarg(argv, argc, &arg, &pos); | |
459 if(address){ | |
460 f_address = g_strdup(address); | |
461 }else{ | |
462 fprintf(stderr, "-f requires an address as an argument\n"); | |
463 exit(EXIT_FAILURE); | |
464 } | |
465 } | |
466 break; | |
467 case 'g': | |
468 do_get = TRUE; | |
469 if(!mta_mode) mta_mode = MODE_NONE; /* to prevent default MODE_ACCEPT */ | |
470 if(argv[arg][pos] == 'o'){ | |
471 pos++; | |
472 do_get_online = TRUE; | |
473 /* can be NULL, then we use online detection method */ | |
474 route_name = get_optarg(argv, argc, &arg, &pos); | |
475 | |
476 if(route_name != NULL){ | |
477 if(isdigit(route_name[0])){ | |
478 get_interval = time_interval(route_name, &pos); | |
479 route_name = get_optarg(argv, argc, &arg, &pos); | |
480 mta_mode = MODE_GET_DAEMON; | |
481 do_get = FALSE; | |
482 } | |
483 } | |
484 }else{ | |
485 if((optarg = get_optarg(argv, argc, &arg, &pos))){ | |
486 get_name = get_optarg(argv, argc, &arg, &pos); | |
487 } | |
488 } | |
489 break; | |
490 case 'i': | |
491 if(argv[arg][pos] == 0){ | |
492 opt_i = TRUE; | |
493 exit_failure = FALSE; /* may override -oem */ | |
494 }else{ | |
495 fprintf(stderr, "unrecognized option '%s'\n", argv[arg]); | |
496 exit(EXIT_FAILURE); | |
497 } | |
498 break; | |
499 case 'M': | |
500 { | |
501 mta_mode = MODE_MCMD; | |
502 M_cmd = g_strdup(&(argv[arg][pos])); | |
503 } | |
504 break; | |
505 case 'o': | |
506 switch(argv[arg][pos++]){ | |
507 case 'e': | |
508 if(argv[arg][pos++] == 'm') /* -oem */ | |
509 if(!opt_i) exit_failure = TRUE; | |
510 opt_oem = TRUE; | |
511 break; | |
512 case 'd': | |
513 if(argv[arg][pos] == 'b') /* -odb */ | |
514 opt_odb = TRUE; | |
515 else if(argv[arg][pos] == 'q') /* -odq */ | |
516 do_queue = TRUE; | |
517 break; | |
518 case 'i': | |
519 opt_i = TRUE; | |
520 exit_failure = FALSE; /* may override -oem */ | |
521 break; | |
522 } | |
523 break; | |
524 | |
525 case 'q': | |
526 { | |
527 gchar *optarg; | |
528 | |
529 do_runq = TRUE; | |
530 mta_mode = MODE_RUNQUEUE; | |
531 if(argv[arg][pos] == 'o'){ | |
532 pos++; | |
533 do_runq = FALSE; | |
534 do_runq_online = TRUE; | |
535 /* can be NULL, then we use online detection method */ | |
536 route_name = get_optarg(argv, argc, &arg, &pos); | |
537 }else if((optarg = get_optarg(argv, argc, &arg, &pos))){ | |
538 mta_mode = MODE_DAEMON; | |
539 queue_interval = time_interval(optarg, &pos); | |
540 } | |
541 } | |
542 break; | |
543 case 't': | |
544 if(argv[arg][pos] == 0){ | |
545 opt_t = TRUE; | |
546 }else{ | |
547 fprintf(stderr, "unrecognized option '%s'\n", argv[arg]); | |
548 exit(EXIT_FAILURE); | |
549 } | |
550 break; | |
551 case 'v': | |
552 do_verbose = TRUE; | |
553 break; | |
554 default: | |
555 fprintf(stderr, "unrecognized option '%s'\n", argv[arg]); | |
556 exit(EXIT_FAILURE); | |
557 } | |
558 }else{ | |
559 if(argv[arg][pos+1] == '-'){ | |
560 if(argv[arg][pos+2] != '\0'){ | |
561 fprintf(stderr, "unrecognized option '%s'\n", argv[arg]); | |
562 exit(EXIT_FAILURE); | |
563 } | |
564 arg++; | |
565 } | |
566 break; | |
567 } | |
568 arg++; | |
569 } | |
570 | |
571 if(mta_mode == MODE_VERSION){ | |
572 gchar *with_resolver = "", *with_smtp_server = "", *with_pop3 = "", *with_auth = "", | |
573 *with_maildir = "", *with_ident = "", *with_mserver = ""; | |
574 | |
575 #ifdef ENABLE_RESOLVER | |
576 with_resolver = " +resolver"; | |
577 #endif | |
578 #ifdef ENABLE_SMTP_SERVER | |
579 with_smtp_server = " +smtp-server"; | |
580 #endif | |
581 #ifdef ENABLE_POP3 | |
582 with_pop3 = " +pop3"; | |
583 #endif | |
584 #ifdef ENABLE_AUTH | |
585 with_auth = " +auth"; | |
586 #endif | |
587 #ifdef ENABLE_MAILDIR | |
588 with_maildir = " +maildir"; | |
589 #endif | |
590 #ifdef ENABLE_IDENT | |
591 with_ident = " +ident"; | |
592 #endif | |
593 #ifdef ENABLE_MSERVER | |
594 with_mserver = " +mserver"; | |
595 #endif | |
596 | |
597 printf("%s %s%s%s%s%s%s%s%s\n", PACKAGE, VERSION, | |
598 with_resolver, with_smtp_server, with_pop3, with_auth, | |
599 with_maildir, with_ident, with_mserver); | |
600 | |
601 exit(EXIT_SUCCESS); | |
602 } | |
603 | |
604 /* initialize random generator */ | |
605 srand(time(NULL)); | |
606 /* ignore SIGPIPE signal */ | |
607 signal(SIGPIPE, SIG_IGN); | |
608 | |
609 /* close all possibly open file descriptors */ | |
610 { | |
611 int i, max_fd = sysconf(_SC_OPEN_MAX); | |
612 | |
613 if(max_fd <= 0) max_fd = 64; | |
614 for(i = 3; i < max_fd; i++) | |
615 close(i); | |
616 } | |
617 | |
618 init_conf(); | |
619 | |
620 /* if we are not privileged, and the config file was changed we | |
621 implicetely set the the run_as_user flag and give up all | |
622 privileges. | |
623 | |
624 So it is possible for a user to run his own daemon without | |
625 breaking security. | |
626 */ | |
627 if(strcmp(conf_file, CONF_FILE) != 0){ | |
628 if(conf.orig_uid != 0){ | |
629 conf.run_as_user = TRUE; | |
630 seteuid(conf.orig_uid); | |
631 setegid(conf.orig_gid); | |
632 setuid(conf.orig_uid); | |
633 setgid(conf.orig_gid); | |
634 } | |
635 } | |
636 | |
637 read_conf(conf_file); | |
638 | |
639 if(do_queue) conf.do_queue = TRUE; | |
640 if(do_verbose) conf.do_verbose = TRUE; | |
641 if(debug_level >= 0) /* if >= 0, it was given by argument */ | |
642 conf.debug_level = debug_level; | |
643 | |
644 chdir("/"); | |
645 | |
646 if(!conf.run_as_user){ | |
647 if(setgid(0) != 0){ | |
648 fprintf(stderr, | |
649 "could not set gid to 0. Is the setuid bit set? : %s\n", | |
650 strerror(errno)); | |
651 exit(EXIT_FAILURE); | |
652 } | |
653 if(setuid(0) != 0){ | |
654 fprintf(stderr, | |
655 "could not gain root privileges. Is the setuid bit set? : %s\n", | |
656 strerror(errno)); | |
657 exit(EXIT_FAILURE); | |
658 } | |
659 } | |
660 | |
661 if(!logopen()){ | |
662 fprintf(stderr, "could not open log file\n"); | |
663 exit(EXIT_FAILURE); | |
664 } | |
665 | |
666 DEBUG(1) debugf("masqmail %s starting\n", VERSION); | |
667 | |
668 DEBUG(5){ | |
669 gchar **str = argv; | |
670 debugf("args: \n"); | |
671 while(*str){ | |
672 debugf("%s \n", *str); | |
673 str++; | |
674 } | |
675 } | |
676 DEBUG(5) debugf("queue_interval = %d\n", queue_interval); | |
677 | |
678 if(f_address){ | |
679 return_path = create_address_qualified(f_address, TRUE, conf.host_name); | |
680 g_free(f_address); | |
681 if(!return_path){ | |
682 fprintf(stderr, "invalid RFC821 address: %s\n", f_address); | |
683 exit(EXIT_FAILURE); | |
684 } | |
685 } | |
686 | |
687 if(do_get){ | |
688 #ifdef ENABLE_POP3 | |
689 if((mta_mode == MODE_NONE) || (mta_mode == MODE_RUNQUEUE)){ | |
690 | |
691 set_identity(conf.orig_uid, "getting mail"); | |
692 | |
693 if(do_get_online){ | |
694 if(route_name != NULL){ | |
695 conf.online_detect = g_strdup("argument"); | |
696 set_online_name(route_name); | |
697 } | |
698 get_online(); | |
699 }else{ | |
700 if(get_name) | |
701 get_from_name(get_name); | |
702 else | |
703 get_all(); | |
704 } | |
705 }else{ | |
706 logwrite(LOG_ALERT, "get (-g) only allowed alone or together with queue run (-q)\n"); | |
707 } | |
708 #else | |
709 fprintf(stderr, "get (pop) support not compiled in\n"); | |
710 #endif | |
711 } | |
712 | |
713 switch(mta_mode){ | |
714 case MODE_DAEMON: | |
715 mode_daemon(do_listen, queue_interval, argv); | |
716 break; | |
717 case MODE_RUNQUEUE: | |
718 { | |
719 /* queue runs */ | |
720 set_identity(conf.orig_uid, "queue run"); | |
721 | |
722 if(do_runq) | |
723 exit_code = queue_run() ? EXIT_SUCCESS : EXIT_FAILURE; | |
724 | |
725 if(do_runq_online){ | |
726 if(route_name != NULL){ | |
727 conf.online_detect = g_strdup("argument"); | |
728 set_online_name(route_name); | |
729 } | |
730 exit_code = queue_run_online() ? EXIT_SUCCESS : EXIT_FAILURE; | |
731 } | |
732 } | |
733 break; | |
734 case MODE_GET_DAEMON: | |
735 #ifdef ENABLE_POP3 | |
736 if(route_name != NULL){ | |
737 conf.online_detect = g_strdup("argument"); | |
738 set_online_name(route_name); | |
739 } | |
740 mode_get_daemon(get_interval, argv); | |
741 #endif | |
742 break; | |
743 | |
744 case MODE_SMTP: | |
745 #ifdef ENABLE_SMTP_SERVER | |
746 mode_smtp(); | |
747 #else | |
748 fprintf(stderr, "smtp server support not compiled in\n"); | |
749 #endif | |
750 break; | |
751 case MODE_LIST: | |
752 | |
753 queue_list(); | |
754 break; | |
755 | |
756 case MODE_BI: | |
757 | |
758 exit(EXIT_SUCCESS); | |
759 break; /* well... */ | |
760 | |
761 case MODE_MCMD: | |
762 if(strcmp(M_cmd, "rm") == 0){ | |
763 gboolean ok = FALSE; | |
764 | |
765 set_euidgid(conf.mail_uid, conf.mail_gid, NULL, NULL); | |
766 | |
767 if(is_privileged_user(conf.orig_uid)){ | |
768 for(; arg < argc; arg++){ | |
769 if(queue_delete(argv[arg])) | |
770 ok = TRUE; | |
771 } | |
772 }else{ | |
773 struct passwd *pw = getpwuid(conf.orig_uid); | |
774 if(pw){ | |
775 for(; arg < argc; arg++){ | |
776 message *msg = msg_spool_read(argv[arg], FALSE); | |
777 #ifdef ENABLE_IDENT | |
778 if(((msg->received_host == NULL) && (msg->received_prot == PROT_LOCAL)) || | |
779 is_in_netlist(msg->received_host, conf.ident_trusted_nets)){ | |
780 #else | |
781 if((msg->received_host == NULL) && (msg->received_prot == PROT_LOCAL)){ | |
782 #endif | |
783 if(msg->ident){ | |
784 if(strcmp(pw->pw_name, msg->ident) == 0){ | |
785 if(queue_delete(argv[arg])) | |
786 ok = TRUE; | |
787 }else{ | |
788 fprintf(stderr, "you do not own message id %s\n", argv[arg]); | |
789 } | |
790 }else | |
791 fprintf(stderr, "message %s does not have an ident.\n", argv[arg]); | |
792 }else{ | |
793 fprintf(stderr, "message %s was not received locally or from a trusted network.\n", argv[arg]); | |
794 } | |
795 } | |
796 }else{ | |
797 fprintf(stderr, "could not find a passwd entry for uid %d: %s\n", conf.orig_uid, strerror(errno)); | |
798 } | |
799 } | |
800 exit(ok ? EXIT_SUCCESS : EXIT_FAILURE); | |
801 }else{ | |
802 fprintf(stderr, "unknown command %s\n", M_cmd); | |
803 exit(EXIT_FAILURE); | |
804 } | |
805 break; | |
806 | |
807 case MODE_ACCEPT: | |
808 { | |
809 guint accept_flags = | |
810 (opt_t ? ACC_DEL_RCPTS|ACC_DEL_BCC|ACC_RCPT_FROM_HEAD : ACC_HEAD_FROM_RCPT) | | |
811 (opt_i ? ACC_NODOT_TERM : ACC_NODOT_RELAX); | |
812 | |
813 mode_accept(return_path, full_sender_name, accept_flags, &(argv[arg]), argc - arg); | |
814 | |
815 exit(exit_failure ? EXIT_FAILURE : EXIT_SUCCESS); | |
816 } | |
817 break; | |
818 case MODE_NONE: | |
819 break; | |
820 default: | |
821 fprintf(stderr, "unknown mode: %d\n", mta_mode); | |
822 break; | |
823 } | |
824 | |
825 logclose(); | |
826 | |
827 exit(exit_code); | |
828 } |