diff options
Diffstat (limited to 'pathologist/src/pathologist/mail_sender.c')
-rw-r--r-- | pathologist/src/pathologist/mail_sender.c | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/pathologist/src/pathologist/mail_sender.c b/pathologist/src/pathologist/mail_sender.c new file mode 100644 index 0000000..98edf84 --- /dev/null +++ b/pathologist/src/pathologist/mail_sender.c | |||
@@ -0,0 +1,231 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include <ctype.h> | ||
4 | #include <unistd.h> | ||
5 | #include <getopt.h> | ||
6 | #include <string.h> | ||
7 | #include <fcntl.h> | ||
8 | #include <signal.h> | ||
9 | #include <errno.h> | ||
10 | #include <stdarg.h> | ||
11 | |||
12 | #include <openssl/ssl.h> | ||
13 | #include <auth-client.h> | ||
14 | #include <libesmtp.h> | ||
15 | |||
16 | #if !defined (__GNUC__) || __GNUC__ < 2 | ||
17 | # define __attribute__(x) | ||
18 | #endif | ||
19 | |||
20 | |||
21 | int | ||
22 | handle_invalid_peer_certificate(long vfy_result) | ||
23 | { | ||
24 | const char *k ="rare error"; | ||
25 | switch(vfy_result) { | ||
26 | case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: | ||
27 | k="X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT"; break; | ||
28 | case X509_V_ERR_UNABLE_TO_GET_CRL: | ||
29 | k="X509_V_ERR_UNABLE_TO_GET_CRL"; break; | ||
30 | case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: | ||
31 | k="X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE"; break; | ||
32 | case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: | ||
33 | k="X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE"; break; | ||
34 | case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: | ||
35 | k="X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY"; break; | ||
36 | case X509_V_ERR_CERT_SIGNATURE_FAILURE: | ||
37 | k="X509_V_ERR_CERT_SIGNATURE_FAILURE"; break; | ||
38 | case X509_V_ERR_CRL_SIGNATURE_FAILURE: | ||
39 | k="X509_V_ERR_CRL_SIGNATURE_FAILURE"; break; | ||
40 | case X509_V_ERR_CERT_NOT_YET_VALID: | ||
41 | k="X509_V_ERR_CERT_NOT_YET_VALID"; break; | ||
42 | case X509_V_ERR_CERT_HAS_EXPIRED: | ||
43 | k="X509_V_ERR_CERT_HAS_EXPIRED"; break; | ||
44 | case X509_V_ERR_CRL_NOT_YET_VALID: | ||
45 | k="X509_V_ERR_CRL_NOT_YET_VALID"; break; | ||
46 | case X509_V_ERR_CRL_HAS_EXPIRED: | ||
47 | k="X509_V_ERR_CRL_HAS_EXPIRED"; break; | ||
48 | case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: | ||
49 | k="X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD"; break; | ||
50 | case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: | ||
51 | k="X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD"; break; | ||
52 | case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: | ||
53 | k="X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD"; break; | ||
54 | case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: | ||
55 | k="X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD"; break; | ||
56 | case X509_V_ERR_OUT_OF_MEM: | ||
57 | k="X509_V_ERR_OUT_OF_MEM"; break; | ||
58 | case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: | ||
59 | k="X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT"; break; | ||
60 | case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: | ||
61 | k="X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN"; break; | ||
62 | case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: | ||
63 | k="X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY"; break; | ||
64 | case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: | ||
65 | k="X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE"; break; | ||
66 | case X509_V_ERR_CERT_CHAIN_TOO_LONG: | ||
67 | k="X509_V_ERR_CERT_CHAIN_TOO_LONG"; break; | ||
68 | case X509_V_ERR_CERT_REVOKED: | ||
69 | k="X509_V_ERR_CERT_REVOKED"; break; | ||
70 | case X509_V_ERR_INVALID_CA: | ||
71 | k="X509_V_ERR_INVALID_CA"; break; | ||
72 | case X509_V_ERR_PATH_LENGTH_EXCEEDED: | ||
73 | k="X509_V_ERR_PATH_LENGTH_EXCEEDED"; break; | ||
74 | case X509_V_ERR_INVALID_PURPOSE: | ||
75 | k="X509_V_ERR_INVALID_PURPOSE"; break; | ||
76 | case X509_V_ERR_CERT_UNTRUSTED: | ||
77 | k="X509_V_ERR_CERT_UNTRUSTED"; break; | ||
78 | case X509_V_ERR_CERT_REJECTED: | ||
79 | k="X509_V_ERR_CERT_REJECTED"; break; | ||
80 | } | ||
81 | printf("SMTP_EV_INVALID_PEER_CERTIFICATE: %ld: %s\n", vfy_result, k); | ||
82 | return 1; /* Accept the problem */ | ||
83 | } | ||
84 | |||
85 | |||
86 | void event_cb (smtp_session_t session, int event_no, void *arg,...) | ||
87 | { | ||
88 | va_list alist; | ||
89 | int *ok; | ||
90 | |||
91 | va_start(alist, arg); | ||
92 | switch(event_no) { | ||
93 | case SMTP_EV_CONNECT: | ||
94 | case SMTP_EV_MAILSTATUS: | ||
95 | case SMTP_EV_RCPTSTATUS: | ||
96 | case SMTP_EV_MESSAGEDATA: | ||
97 | case SMTP_EV_MESSAGESENT: | ||
98 | case SMTP_EV_DISCONNECT: break; | ||
99 | case SMTP_EV_WEAK_CIPHER: { | ||
100 | int bits; | ||
101 | bits = va_arg(alist, long); ok = va_arg(alist, int*); | ||
102 | printf("SMTP_EV_WEAK_CIPHER, bits=%d - accepted.\n", bits); | ||
103 | *ok = 1; break; | ||
104 | } | ||
105 | case SMTP_EV_STARTTLS_OK: | ||
106 | puts("SMTP_EV_STARTTLS_OK - TLS started here."); break; | ||
107 | case SMTP_EV_INVALID_PEER_CERTIFICATE: { | ||
108 | long vfy_result; | ||
109 | vfy_result = va_arg(alist, long); ok = va_arg(alist, int*); | ||
110 | *ok = handle_invalid_peer_certificate(vfy_result); | ||
111 | break; | ||
112 | } | ||
113 | case SMTP_EV_NO_PEER_CERTIFICATE: { | ||
114 | ok = va_arg(alist, int*); | ||
115 | puts("SMTP_EV_NO_PEER_CERTIFICATE - accepted."); | ||
116 | *ok = 1; break; | ||
117 | } | ||
118 | case SMTP_EV_WRONG_PEER_CERTIFICATE: { | ||
119 | ok = va_arg(alist, int*); | ||
120 | puts("SMTP_EV_WRONG_PEER_CERTIFICATE - accepted."); | ||
121 | *ok = 1; break; | ||
122 | } | ||
123 | case SMTP_EV_NO_CLIENT_CERTIFICATE: { | ||
124 | ok = va_arg(alist, int*); | ||
125 | puts("SMTP_EV_NO_CLIENT_CERTIFICATE - accepted."); | ||
126 | *ok = 1; break; | ||
127 | } | ||
128 | default: | ||
129 | printf("Got event: %d - ignored.\n", event_no); | ||
130 | } | ||
131 | va_end(alist); | ||
132 | } | ||
133 | |||
134 | |||
135 | /* Callback to prnt the recipient status */ | ||
136 | void | ||
137 | print_recipient_status (smtp_recipient_t recipient, | ||
138 | const char *mailbox, void *arg) | ||
139 | { | ||
140 | const smtp_status_t *status; | ||
141 | |||
142 | status = smtp_recipient_status (recipient); | ||
143 | printf ("%s: %d %s", mailbox, status->code, status->text); | ||
144 | } | ||
145 | |||
146 | |||
147 | void sendMail(const char *messageContents, const char* reportFileName, const char *emailAddress) | ||
148 | { | ||
149 | smtp_session_t session; | ||
150 | smtp_message_t message; | ||
151 | smtp_recipient_t recipient; | ||
152 | const smtp_status_t *status; | ||
153 | struct sigaction sa; | ||
154 | char *host = "localhost:25"; | ||
155 | char *from = "monkey@gnunet.org"; | ||
156 | char *subject = "Monkey bug report"; | ||
157 | const char *recipient_address = emailAddress; | ||
158 | char tempFileName[1000]; | ||
159 | int tempFd; | ||
160 | FILE *fp; | ||
161 | enum notify_flags notify = Notify_SUCCESS | Notify_FAILURE; | ||
162 | |||
163 | auth_client_init(); | ||
164 | session = smtp_create_session(); | ||
165 | message = smtp_add_message(session); | ||
166 | |||
167 | /* Ignore sigpipe */ | ||
168 | sa.sa_handler = SIG_IGN; | ||
169 | sigemptyset(&sa.sa_mask); | ||
170 | sa.sa_flags = 0; | ||
171 | sigaction(SIGPIPE, &sa, NULL); | ||
172 | |||
173 | |||
174 | smtp_set_server(session, host); | ||
175 | smtp_set_eventcb(session, event_cb, NULL); | ||
176 | |||
177 | /* Set the reverse path for the mail envelope. (NULL is ok) | ||
178 | */ | ||
179 | smtp_set_reverse_path(message, from); | ||
180 | |||
181 | /* Set the Subject: header. For no reason, we want the supplied subject | ||
182 | to override any subject line in the message headers. */ | ||
183 | if (subject != NULL) { | ||
184 | smtp_set_header(message, "Subject", subject); | ||
185 | smtp_set_header_option(message, "Subject", Hdr_OVERRIDE, 1); | ||
186 | } | ||
187 | |||
188 | |||
189 | /* Prepare message */ | ||
190 | if (NULL == reportFileName) { | ||
191 | memset(tempFileName, 0, sizeof(tempFileName)); | ||
192 | sprintf(tempFileName, "/tmp/messageXXXXXX"); | ||
193 | tempFd = mkstemp(tempFileName); | ||
194 | fp = fdopen(tempFd, "w"); | ||
195 | fprintf(fp, "%s", messageContents); | ||
196 | fclose(fp); | ||
197 | fp = fopen(tempFileName, "r"); | ||
198 | smtp_set_message_fp(message, fp); | ||
199 | } else { | ||
200 | fp = fopen(reportFileName, "r"); | ||
201 | smtp_set_message_fp(message, fp); | ||
202 | } | ||
203 | |||
204 | |||
205 | recipient = smtp_add_recipient(message, recipient_address); | ||
206 | |||
207 | smtp_dsn_set_notify (recipient, notify); | ||
208 | |||
209 | /* Initiate a connection to the SMTP server and transfer the | ||
210 | message. */ | ||
211 | if (!smtp_start_session(session)) { | ||
212 | char buf[128]; | ||
213 | |||
214 | fprintf(stderr, "SMTP server problem %s\n", smtp_strerror(smtp_errno(), | ||
215 | buf, sizeof buf)); | ||
216 | } else { | ||
217 | /* Report on the success or otherwise of the mail transfer. | ||
218 | */ | ||
219 | status = smtp_message_transfer_status(message); | ||
220 | printf("%d %s", status->code, (status->text != NULL) ? status->text | ||
221 | : "\n"); | ||
222 | smtp_enumerate_recipients(message, print_recipient_status, NULL); | ||
223 | } | ||
224 | |||
225 | /* Free resources consumed by the program. | ||
226 | */ | ||
227 | smtp_destroy_session(session); | ||
228 | fclose(fp); | ||
229 | auth_client_exit(); | ||
230 | } | ||
231 | |||