29 |
#define obstack_chunk_free free |
#define obstack_chunk_free free |
30 |
#include <obstack.h> |
#include <obstack.h> |
31 |
|
|
32 |
static int transfer_command(void *, void *, char *); |
static int transfer_command(void *, void *, MESSAGE *msg, char *); |
33 |
static void process_command(void *, void *, char *, int); |
static void process_command(void *, void *, MESSAGE *msg, char *, int); |
34 |
static void transfer_header(void *, void *, struct list *list); |
static void transfer_header(void *, void *, struct list *list); |
35 |
static void transfer_body(void *, void *); |
static void transfer_body(void *, void *, MESSAGE *msg); |
36 |
static void process_data(void *sd_client, void *sd_server); |
static void process_data(void *sd_client, void *sd_server, MESSAGE *msg); |
37 |
|
|
38 |
|
|
39 |
/* Collect and send headers */ |
/* Collect and send headers */ |
43 |
snd sent in multiline lines. */ |
snd sent in multiline lines. */ |
44 |
|
|
45 |
static void |
static void |
46 |
get_boundary(char *line) |
get_boundary(MESSAGE *msg, char *line) |
47 |
{ |
{ |
48 |
char boundary_buf[LINEBUFFER+1], *p; |
char boundary_buf[LINEBUFFER+1], *p; |
49 |
|
|
61 |
if (*q) |
if (*q) |
62 |
*q = 0; |
*q = 0; |
63 |
} |
} |
64 |
message.boundary = xmalloc(strlen(p) + 3); |
msg->boundary = xmalloc(strlen(p) + 3); |
65 |
sprintf(message.boundary, "--%s", p); |
sprintf(msg->boundary, "--%s", p); |
|
topt |= T_BOUNDARY; |
|
66 |
} |
} |
67 |
|
|
68 |
static void |
static void |
86 |
} |
} |
87 |
|
|
88 |
static void |
static void |
89 |
collect_headers(void *sd_client, struct list **listp) |
collect_headers(void *sd_client, MESSAGE *msg) |
90 |
{ |
{ |
91 |
char buf[LINEBUFFER+1]; |
char buf[LINEBUFFER+1]; |
92 |
char *line = NULL; |
char *line = NULL; |
93 |
|
|
94 |
*listp = list_create(); |
msg->header = list_create(); |
95 |
while (recvline(SERVER, sd_client, buf, LINEBUFFER)) { |
while (recvline(SERVER, sd_client, buf, LINEBUFFER)) { |
96 |
remcrlf(buf); |
remcrlf(buf); |
97 |
if (isspace(buf[0])) { |
if (isspace(buf[0])) { |
105 |
strcat(line, buf); |
strcat(line, buf); |
106 |
} else { |
} else { |
107 |
if (line) { |
if (line) { |
108 |
if (!(topt & (T_BOUNDARY|T_ENTIRE_BODY))) |
if (!(topt & T_ENTIRE_BODY) |
109 |
get_boundary(line); |
&& msg->boundary == NULL) |
110 |
add_header(*listp, line); |
get_boundary(msg, line); |
111 |
|
add_header(msg->header, line); |
112 |
line = NULL; |
line = NULL; |
113 |
} |
} |
114 |
if (buf[0] == 0) |
if (buf[0] == 0) |
137 |
if (strcmp(entry->key, X_ANUBIS_RULE_HEADER) == 0) |
if (strcmp(entry->key, X_ANUBIS_RULE_HEADER) == 0) |
138 |
return; |
return; |
139 |
swrite(CLIENT, sd_server, entry->key); |
swrite(CLIENT, sd_server, entry->key); |
140 |
swrite(CLIENT, sd_server, ":"); |
swrite(CLIENT, sd_server, ": "); |
141 |
} |
} |
142 |
write_header_line(sd_server, entry->value); |
write_header_line(sd_server, entry->value); |
143 |
} |
} |
178 |
#define ST_DONE 3 |
#define ST_DONE 3 |
179 |
|
|
180 |
static void |
static void |
181 |
collect_body(void *sd_client, char **retptr) |
collect_body(void *sd_client, MESSAGE *msg) |
182 |
{ |
{ |
183 |
int nread; |
int nread; |
184 |
char buf[LINEBUFFER+1]; |
char buf[LINEBUFFER+1]; |
186 |
int state = 0; |
int state = 0; |
187 |
int len; |
int len; |
188 |
|
|
189 |
if (topt & T_BOUNDARY) { |
if (msg->boundary) { |
190 |
len = strlen(message.boundary); |
len = strlen(msg->boundary); |
191 |
message.mime_hdr = list_create(); |
msg->mime_hdr = list_create(); |
192 |
} |
} |
193 |
|
|
194 |
obstack_init (&stk); |
obstack_init (&stk); |
199 |
|
|
200 |
remcrlf(buf); |
remcrlf(buf); |
201 |
|
|
202 |
if (topt & T_BOUNDARY) { |
if (msg->boundary) { |
203 |
switch (state) { |
switch (state) { |
204 |
case ST_INIT: |
case ST_INIT: |
205 |
if (strcmp(buf, message.boundary) == 0) |
if (strcmp(buf, msg->boundary) == 0) |
206 |
state = ST_HDR; |
state = ST_HDR; |
207 |
break; |
break; |
208 |
|
|
210 |
if (buf[0] == 0) |
if (buf[0] == 0) |
211 |
state = ST_BODY; |
state = ST_BODY; |
212 |
else |
else |
213 |
list_append(message.mime_hdr, |
list_append(msg->mime_hdr, |
214 |
strdup(buf)); |
strdup(buf)); |
215 |
break; |
break; |
216 |
|
|
217 |
case ST_BODY: |
case ST_BODY: |
218 |
if (strncmp(buf, message.boundary, len) == 0) |
if (strncmp(buf, msg->boundary, len) == 0) |
219 |
state = ST_DONE; |
state = ST_DONE; |
220 |
else { |
else { |
221 |
obstack_grow(&stk, buf, strlen(buf)); |
obstack_grow(&stk, buf, strlen(buf)); |
228 |
} |
} |
229 |
} |
} |
230 |
obstack_1grow(&stk, 0); |
obstack_1grow(&stk, 0); |
231 |
*retptr = strdup(obstack_finish(&stk)); |
msg->body = strdup(obstack_finish(&stk)); |
232 |
obstack_free(&stk, NULL); |
obstack_free(&stk, NULL); |
233 |
} |
} |
234 |
|
|
235 |
void |
void |
236 |
send_body(void *sd_server) |
send_body(MESSAGE *msg, void *sd_server) |
237 |
{ |
{ |
238 |
char *p; |
char *p; |
239 |
|
|
240 |
if (topt & T_BOUNDARY) { |
if (msg->boundary) { |
241 |
swrite(CLIENT, sd_server, message.boundary); |
swrite(CLIENT, sd_server, msg->boundary); |
242 |
swrite(CLIENT, sd_server, CRLF); |
swrite(CLIENT, sd_server, CRLF); |
243 |
send_string_list(sd_server, message.mime_hdr); |
send_string_list(sd_server, msg->mime_hdr); |
244 |
swrite(CLIENT, sd_server, CRLF); |
swrite(CLIENT, sd_server, CRLF); |
245 |
} |
} |
246 |
|
|
247 |
for (p = message.body; *p; ) { |
for (p = msg->body; *p; ) { |
248 |
char *q = strchr(p, '\n'); |
char *q = strchr(p, '\n'); |
249 |
if (q) |
if (q) |
250 |
*q++ = 0; |
*q++ = 0; |
256 |
p = q; |
p = q; |
257 |
} |
} |
258 |
|
|
259 |
if (topt & T_BOUNDARY) { |
if (msg->boundary) { |
260 |
swrite(CLIENT, sd_server, message.boundary); |
swrite(CLIENT, sd_server, msg->boundary); |
261 |
swrite(CLIENT, sd_server, CRLF); |
swrite(CLIENT, sd_server, CRLF); |
262 |
} |
} |
263 |
} |
} |
271 |
smtp_session(void *sd_client, void *sd_server) |
smtp_session(void *sd_client, void *sd_server) |
272 |
{ |
{ |
273 |
char command[LINEBUFFER+1]; |
char command[LINEBUFFER+1]; |
274 |
|
MESSAGE msg; |
275 |
|
|
276 |
/* |
/* |
277 |
First of all, transfer a welcome message. |
First of all, transfer a welcome message. |
307 |
Then process the commands... |
Then process the commands... |
308 |
*/ |
*/ |
309 |
|
|
310 |
|
message_init(&msg); |
311 |
while (recvline(SERVER, sd_client, command, LINEBUFFER)) |
while (recvline(SERVER, sd_client, command, LINEBUFFER)) |
312 |
{ |
{ |
313 |
process_command(sd_client, sd_server, command, LINEBUFFER); |
process_command(sd_client, sd_server, &msg, |
314 |
|
command, LINEBUFFER); |
315 |
sd_client = remote_client; |
sd_client = remote_client; |
316 |
sd_server = remote_server; |
sd_server = remote_server; |
317 |
|
|
320 |
if (strlen(command) == 0) |
if (strlen(command) == 0) |
321 |
continue; |
continue; |
322 |
|
|
323 |
if (transfer_command(sd_client, sd_server, command) == 0) |
if (transfer_command(sd_client, sd_server, &msg, command) == 0) |
324 |
break; |
break; |
325 |
} |
} |
326 |
return; |
return; |
331 |
*********************/ |
*********************/ |
332 |
|
|
333 |
static void |
static void |
334 |
save_command(char *line) |
save_command(MESSAGE *msg, char *line) |
335 |
{ |
{ |
336 |
int i; |
int i; |
337 |
ASSOC *asc = xmalloc(sizeof(*asc)); |
ASSOC *asc = xmalloc(sizeof(*asc)); |
348 |
asc->value = strdup(&line[i]); |
asc->value = strdup(&line[i]); |
349 |
else |
else |
350 |
asc->value = NULL; |
asc->value = NULL; |
351 |
list_append(message.commands, asc); |
list_append(msg->commands, asc); |
352 |
} |
} |
353 |
|
|
354 |
static void |
static void |
355 |
process_command(void *sd_client, void *sd_server, char *command, int size) |
process_command(void *sd_client, void *sd_server, MESSAGE *msg, |
356 |
|
char *command, int size) |
357 |
{ |
{ |
358 |
char buf[LINEBUFFER+1]; |
char buf[LINEBUFFER+1]; |
359 |
safe_strcpy(buf, command); /* make a back-up */ |
safe_strcpy(buf, command); /* make a back-up */ |
360 |
save_command(buf); |
save_command(msg, buf); |
361 |
|
|
362 |
change_to_lower(buf); |
change_to_lower(buf); |
363 |
|
|
472 |
} |
} |
473 |
|
|
474 |
static int |
static int |
475 |
transfer_command(void *sd_client, void *sd_server, char *command) |
transfer_command(void *sd_client, void *sd_server, MESSAGE *msg, char *command) |
476 |
{ |
{ |
477 |
char reply[2 * LINEBUFFER+1]; |
char reply[2 * LINEBUFFER+1]; |
478 |
char buf[LINEBUFFER+1]; |
char buf[LINEBUFFER+1]; |
594 |
if (topt & T_ERROR) |
if (topt & T_ERROR) |
595 |
return 0; |
return 0; |
596 |
|
|
597 |
if (isdigit((unsigned char)reply[0]) && (unsigned char)reply[0] < '4') { |
if (isdigit((unsigned char)reply[0]) |
598 |
|
&& (unsigned char)reply[0] < '4') { |
599 |
if (strncmp(buf, "quit", 4) == 0) |
if (strncmp(buf, "quit", 4) == 0) |
600 |
return 0; /* The QUIT command */ |
return 0; /* The QUIT command */ |
601 |
else if (strncmp(buf, "rset", 4) == 0) { |
else if (strncmp(buf, "rset", 4) == 0) { |
602 |
destroy_assoc_list(&message.commands); |
message_free(msg); |
|
destroy_assoc_list(&message.header); |
|
|
destroy_string_list(&message.mime_hdr); |
|
|
xfree(message.body); |
|
|
xfree(message.boundary); |
|
|
topt &= ~T_BOUNDARY; |
|
603 |
topt &= ~T_ERROR; |
topt &= ~T_ERROR; |
604 |
} |
} |
605 |
else if (strncmp(buf, "data", 4) == 0) { |
else if (strncmp(buf, "data", 4) == 0) { |
606 |
process_data(sd_client, sd_server); |
process_data(sd_client, sd_server, msg); |
|
xfree(message.body); |
|
|
xfree(message.boundary); |
|
|
topt &= ~T_BOUNDARY; |
|
607 |
topt &= ~T_ERROR; |
topt &= ~T_ERROR; |
608 |
} |
} |
609 |
} |
} |
611 |
} |
} |
612 |
|
|
613 |
void |
void |
614 |
process_data(void *sd_client, void *sd_server) |
process_data(void *sd_client, void *sd_server, MESSAGE *msg) |
615 |
{ |
{ |
616 |
char buf[LINEBUFFER+1]; |
char buf[LINEBUFFER+1]; |
617 |
|
|
618 |
alarm(1800); |
alarm(1800); |
619 |
|
|
620 |
collect_headers(sd_client, &message.header); |
collect_headers(sd_client, msg); |
621 |
collect_body(sd_client, &message.body); |
collect_body(sd_client, msg); |
622 |
|
|
623 |
rcfile_process_section(CF_CLIENT, "RULE", NULL, &message); |
rcfile_process_section(CF_CLIENT, "RULE", NULL, msg); |
624 |
|
|
625 |
transfer_header(sd_client, sd_server, message.header); |
transfer_header(sd_client, sd_server, msg->header); |
626 |
transfer_body(sd_client, sd_server); |
transfer_body(sd_client, sd_server, msg); |
627 |
|
|
628 |
recvline(CLIENT, sd_server, buf, LINEBUFFER); |
recvline(CLIENT, sd_server, buf, LINEBUFFER); |
629 |
swrite(SERVER, sd_client, buf); |
swrite(SERVER, sd_client, buf); |
630 |
|
|
631 |
/* FIXME: xfree(message_body); */ |
message_free(msg); |
632 |
|
|
633 |
alarm(0); |
alarm(0); |
634 |
} |
} |
659 |
} |
} |
660 |
|
|
661 |
void |
void |
662 |
transfer_body(void *sd_client, void *sd_server) |
transfer_body(void *sd_client, void *sd_server, MESSAGE *msg) |
663 |
{ |
{ |
664 |
if (topt & T_BOUNDARY) { |
if (msg->boundary) { |
665 |
send_body(sd_server); |
send_body(msg, sd_server); |
666 |
|
|
667 |
/* Transfer everything else */ |
/* Transfer everything else */ |
668 |
raw_transfer(sd_client, sd_server); |
raw_transfer(sd_client, sd_server); |
669 |
} else |
} else |
670 |
send_body(sd_server); |
send_body(msg, sd_server); |
671 |
swrite(CLIENT, sd_server, "."CRLF); |
swrite(CLIENT, sd_server, "."CRLF); |
672 |
} |
} |
673 |
|
|
|
void |
|
|
message_add_header(MESSAGE *msg, char *hdr) |
|
|
{ |
|
|
list_append(msg->header, header_assoc(hdr)); |
|
|
} |
|
|
|
|
|
void |
|
|
message_remove_headers(MESSAGE *msg, char *arg) |
|
|
{ |
|
|
ASSOC *asc; |
|
|
RC_REGEX *regex = anubis_regex_compile(arg, 0); |
|
|
|
|
|
for (asc = list_first(msg->header); asc; |
|
|
asc = list_next(msg->header)) { |
|
|
char **rv; |
|
|
int rc; |
|
|
char *h = assoc_to_header(asc); |
|
|
|
|
|
if (anubis_regex_match(regex, h, &rc, &rv)) { |
|
|
list_remove_current(msg->header); |
|
|
assoc_free(asc); |
|
|
} |
|
|
free(h); |
|
|
if (rc) |
|
|
free_pptr(rv); |
|
|
} |
|
|
anubis_regex_free(regex); |
|
|
} |
|
|
|
|
|
void |
|
|
message_modify_headers(MESSAGE *msg, char *arg, char *modify) |
|
|
{ |
|
|
ASSOC *asc; |
|
|
RC_REGEX *regex = anubis_regex_compile(arg, 0); |
|
|
|
|
|
for (asc = list_first(msg->header); asc; |
|
|
asc = list_next(msg->header)) { |
|
|
char **rv; |
|
|
int rc; |
|
|
char *h = assoc_to_header(asc); |
|
|
|
|
|
if (anubis_regex_match(regex, h, &rc, &rv)) { |
|
|
free(asc->value); |
|
|
asc->value = substitute(modify, rv); |
|
|
if (!asc->value) |
|
|
asc->value = strdup(modify); |
|
|
} |
|
|
free(h); |
|
|
free_pptr(rv); |
|
|
} |
|
|
anubis_regex_free(regex); |
|
|
} |
|
|
|
|
|
void |
|
|
message_external_proc(MESSAGE *msg, char *name) |
|
|
{ |
|
|
int rc = 0; |
|
|
char *extbuf = 0; |
|
|
extbuf = external_program(&rc, name, message.body, 0, 0); |
|
|
if (rc != -1 && extbuf) { |
|
|
xfree(message.body); |
|
|
message.body = extbuf; |
|
|
} |
|
|
} |
|
674 |
|
|
675 |
/* EOF */ |
/* EOF */ |
676 |
|
|