1 #line 982 "../../src/builtin/snarf.m4"
2 /* -*- buffer-read-only: t -*- vi: set ro:
3    THIS FILE IS GENERATED AUTOMATICALLY.  PLEASE DO NOT EDIT.
4 */
5 #line 982
6 #ifdef HAVE_CONFIG_H
7 #line 982
8 # include <config.h>
9 #line 982
10 #endif
11 #line 982
12 #include <sys/types.h>
13 #line 982
14 
15 #line 982
16 #include "mailfromd.h"
17 #line 982
18 #include "prog.h"
19 #line 982
20 #include "builtin.h"
21 #line 982
22 
23 #line 65 "dkim.bi"
24 static mu_debug_handle_t debug_handle;
25 #line 982 "../../src/builtin/snarf.m4"
26 
27 #line 1022 "../../src/builtin/snarf.m4"
28 
29 /* End of snarf.m4 */
30 #line 1 "dkim.bi"
31 /* This file is part of Mailfromd.             -*- c -*-
32    Copyright (C) 2020-2021 Sergey Poznyakoff
33 
34    This program is free software; you can redistribute it and/or modify
35    it under the terms of the GNU General Public License as published by
36    the Free Software Foundation; either version 3, or (at your option)
37    any later version.
38 
39    This program is distributed in the hope that it will be useful,
40    but WITHOUT ANY WARRANTY; without even the implied warranty of
41    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
42    GNU General Public License for more details.
43 
44    You should have received a copy of the GNU General Public License
45    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
46 
47 
48 #ifdef WITH_DKIM
49 #line 18
50 
51 
52 #include "dkim.h"
53 #include "msg.h"
54 
55 struct msgmod_data {
56 	mu_message_t msg;
57 	char const *h_list;
58 	struct msgmod_closure *e_msgmod;
59 };
60 
61 static int
message_replace_body(mu_message_t msg,mu_stream_t stream)62 message_replace_body(mu_message_t msg, mu_stream_t stream)
63 {
64 	mu_body_t body;
65 	int rc;
66 
67 	rc = mu_body_create(&body, msg);
68 	if (rc) {
69 		mu_diag_funcall(MU_DIAG_ERROR, "mu_body_create", NULL, rc);
70 		return rc;
71 	}
72 
73 	rc = mu_body_set_stream(body, stream, msg);
74 	if (rc) {
75 		mu_body_destroy(&body, msg);
76 		mu_diag_funcall(MU_DIAG_ERROR, "mu_body_set_stream", NULL, rc);
77 		return rc;
78 	}
79 
80 	rc = mu_message_set_body(msg, body, mu_message_get_owner(msg));
81 	if (rc) {
82 		mu_body_destroy(&body, msg);
83 		mu_diag_funcall(MU_DIAG_ERROR, "mu_message_set_body", NULL, rc);
84 	}
85 	return rc;
86 }
87 
88 static int
do_msgmod(void * item,void * data)89 do_msgmod(void *item, void *data)
90 {
91 	struct msgmod_closure *msgmod = item;
92 	struct msgmod_data *md = data;
93 	mu_header_t hdr;
94 	mu_stream_t stream;
95 	int rc;
96 
97 
98 #line 65 "dkim.bi"
99 
100 #line 65
101 mu_debug(debug_handle, MU_DEBUG_TRACE6,("%s %s: %s %u",
102 		  msgmod_opcode_str(msgmod->opcode),
103 		  SP(msgmod->name), SP(msgmod->value), msgmod->idx));
104 #line 69
105 
106 	mu_message_get_header(md->msg, &hdr);
107 
108 	switch (msgmod->opcode) {
109 	case header_replace:
110 		if (!dkim_header_list_match(md->h_list, msgmod->name))
111 			break;
112 		if (mu_header_sget_value(hdr, msgmod->name, NULL) == 0) {
113 			rc = mu_header_insert(hdr, msgmod->name, msgmod->value,
114 					      NULL,
115 					      msgmod->idx, MU_HEADER_REPLACE);
116 			if (rc == MU_ERR_NOENT) {
117 				rc = mu_header_append(hdr, msgmod->name, msgmod->value);
118 				if (rc)
119 					mu_diag_funcall(MU_DIAG_ERROR,
120 							"mu_header_insert",
121 							msgmod->name,
122 							rc);
123 			} else if (rc) {
124 				mu_diag_funcall(MU_DIAG_ERROR,
125 						"mu_header_insert",
126 						msgmod->name,
127 						rc);
128 			}
129 		} else {
130 			rc = mu_header_append(hdr, msgmod->name, msgmod->value);
131 			if (rc)
132 				mu_diag_funcall(MU_DIAG_ERROR,
133 						"mu_header_append",
134 						msgmod->name,
135 						rc);
136 		}
137 		if (rc) {
138 			md->e_msgmod = msgmod;
139 			return rc;
140 		}
141 		break;
142 
143 	case header_delete:
144 		if (!dkim_header_list_match(md->h_list, msgmod->name))
145 		    break;
146 		rc = mu_header_remove(hdr, msgmod->name, msgmod->idx);
147 		if (rc && rc != MU_ERR_NOENT) {
148 			mu_diag_funcall(MU_DIAG_ERROR,
149 					"mu_header_remove",
150 					msgmod->name,
151 					rc);
152 			md->e_msgmod = msgmod;
153 			return rc;
154 		}
155 		break;
156 
157 	case body_repl:
158 		rc = mu_static_memory_stream_create(&stream, msgmod->value,
159 						    strlen(msgmod->value));
160 		if (rc) {
161 			md->e_msgmod = msgmod;
162 			return rc;
163 		}
164 		rc = message_replace_body(md->msg, stream);
165 		if (rc) {
166 			mu_stream_destroy(&stream);
167 			md->e_msgmod = msgmod;
168 			return rc;
169 		}
170 		break;
171 
172 	case body_repl_fd:
173 		rc = mu_fd_stream_create (&stream, "<body_repl_fd>",
174 					  msgmod->idx,
175 					  MU_STREAM_READ);
176 		if (rc) {
177 			md->e_msgmod = msgmod;
178 			return rc;
179 		}
180 		rc = message_replace_body(md->msg, stream);
181 		if (rc) {
182 			mu_stream_destroy(&stream);
183 			md->e_msgmod = msgmod;
184 			return rc;
185 		}
186 		break;
187 
188 	case header_add:
189 	case header_insert:
190 		if (!dkim_header_list_match(md->h_list, msgmod->name))
191 		    break;
192 		md->e_msgmod = msgmod;
193 		return MU_ERR_USER0;
194 
195 	case rcpt_add:
196 	case rcpt_delete:
197 	case quarantine:
198 	case set_from:
199 		break;
200 	}
201 	return 0;
202 }
203 
204 
205 
206 void
207 #line 170
bi_dkim_sign(eval_environ_t env)208 bi_dkim_sign(eval_environ_t env)
209 #line 170
210 
211 #line 170
212 
213 #line 170 "dkim.bi"
214 {
215 #line 170
216 
217 #line 170
218 
219 #line 170
220 long __bi_argcnt;
221 #line 170
222 char *  d;
223 #line 170
224         char *  s;
225 #line 170
226         char *  keyfile;
227 #line 170
228         char *  canon_h;
229 #line 170
230         char *  canon_b;
231 #line 170
232         char *  headers;
233 #line 170
234 
235 #line 170
236 get_string_arg(env, 1, &d);
237 #line 170
238         get_string_arg(env, 2, &s);
239 #line 170
240         get_string_arg(env, 3, &keyfile);
241 #line 170
242         get_string_arg(env, 4, &canon_h);
243 #line 170
244         get_string_arg(env, 5, &canon_b);
245 #line 170
246         get_string_arg(env, 6, &headers);
247 #line 170
248 
249 #line 170
250 get_numeric_arg(env, 0, &__bi_argcnt);
251 #line 170
252         adjust_stack(env, __bi_argcnt + 1);
253 #line 170
254 
255 #line 170
256 
257 #line 170
258 	if (builtin_module_trace(BUILTIN_IDX_dkim))
259 #line 170
260 		prog_trace(env, "dkim_sign %s %s %s %s %s %s",d, s, keyfile, ((__bi_argcnt > 3) ? canon_h : ""), ((__bi_argcnt > 4) ? canon_b : ""), ((__bi_argcnt > 5) ? headers : ""));;
261 #line 172
262 
263 {
264 	struct dkim_signature sig = {
265 		.v = DKIM_VERSION,
266 		.a = DKIM_ALGORITHM,
267 		.d = d,
268 		.s = s,
269 		.canon = { DKIM_CANON_SIMPLE, DKIM_CANON_SIMPLE },
270 		.q = DKIM_QUERY_METHOD,
271 		.l = DKIM_LENGTH_ALL
272 	};
273 	static char default_headers[] =
274 		"From:From:"
275 		"Reply-To:Reply-To:"
276 		"Subject:Subject:"
277 		"Date:Date:"
278 		"To:"
279 		"Cc:"
280 		"Resent-Date:"
281 		"Resent-From:"
282 		"Resent-To:"
283 		"Resent-Cc:"
284 		"In-Reply-To:"
285 		"References:"
286 		"List-Id:"
287 		"List-Help:"
288 		"List-Unsubscribe:"
289 		"List-Subscribe:"
290 		"List-Post:"
291 		"List-Owner:"
292 		"List-Archive";
293 	mu_message_t msg;
294 	int rc;
295 	char *sighdr, *p;
296 	struct mu_locus_range locus;
297 
298 	env_get_locus(env, &locus);
299 
300 	if ((__bi_argcnt > 3)) {
301 		sig.canon[0] = dkim_str_to_canon_type(canon_h, NULL);
302 		if (sig.canon[0] == DKIM_CANON_ERR)
303 			(
304 #line 213
305 	env_throw_bi(env, mfe_failure, "dkim_sign", _("bad canonicalization type: %s"),canon_h)
306 #line 213
307 );
308 #line 215
309 	}
310 	if ((__bi_argcnt > 4)) {
311 		sig.canon[1] = dkim_str_to_canon_type(canon_b, NULL);
312 		if (sig.canon[1] == DKIM_CANON_ERR)
313 			(
314 #line 219
315 	env_throw_bi(env, mfe_failure, "dkim_sign", _("bad canonicalization type: %s"),canon_b)
316 #line 219
317 );
318 #line 221
319 	}
320 
321 	sig.h = ((__bi_argcnt > 5) ? headers : default_headers);
322 	bi_get_current_message(env, &msg);
323 	if (env_msgmod_count(env)) {
324 		struct msgmod_data mdat;
325 
326 		rc = mu_message_create_copy(&mdat.msg, msg);
327 		if (rc) {
328 			mu_diag_funcall(MU_DIAG_ERROR,
329 					"mu_message_create_copy",
330 					NULL, rc);
331 			(
332 #line 233
333 	env_throw_bi(env, mfe_failure, "dkim_sign", "mu_message_create_copy: %s",mu_strerror(rc))
334 #line 233
335 );
336 #line 236
337 		}
338 		mdat.h_list = sig.h;
339 		mdat.e_msgmod = 0;
340 		rc = env_msgmod_apply(env, do_msgmod, &mdat);
341 		if (rc) {
342 			mu_message_unref(mdat.msg);
343 			if (rc == MU_ERR_USER0) {
344 				(
345 #line 243
346 	env_throw_bi(env, mfe_badmmq, "dkim_sign", _("MMQ incompatible with dkim_sign: %s on %s, value %s"),msgmod_opcode_str(mdat.e_msgmod->opcode),mdat.e_msgmod->name,SP(mdat.e_msgmod->value))
347 #line 243
348 );
349 #line 248
350 			} else if (mdat.e_msgmod) {
351 				(
352 #line 249
353 	env_throw_bi(env, mfe_failure, "dkim_sign", _("%s failed on %s, value %s: %s"),msgmod_opcode_str(mdat.e_msgmod->opcode),mdat.e_msgmod->name,SP(mdat.e_msgmod->value),mu_strerror(rc))
354 #line 249
355 );
356 #line 255
357 			} else
358 				(
359 #line 256
360 	env_throw_bi(env, mfe_failure, "dkim_sign", _("error: %s"),mu_strerror(rc))
361 #line 256
362 );
363 #line 259
364 		}
365 		msg = mdat.msg;
366 	} else
367 		mu_message_ref(msg);
368 
369 	rc = mfd_dkim_sign(msg, &sig, keyfile, &sighdr);
370 	mu_message_unref(msg);
371 		if (!(rc == 0))
372 #line 266
373 		(
374 #line 266
375 	env_throw_bi(env, mfe_failure, "dkim_sign", _("DKIM failed"))
376 #line 266
377 )
378 #line 266
379 ;
380 
381 	p = strchr(sighdr, ':');
382 	*p++ = 0;
383 	while (mu_isblank(*p))
384 		p++;
385 
386 	trace("%s%s:%u: %s %d \"%s: %s\"",
387 	      mailfromd_msgid(env_get_context(env)),
388 	      locus.beg.mu_file, locus.beg.mu_line,
389 	      msgmod_opcode_str(header_insert),
390 	      0,
391 	      sighdr, p);
392 	env_msgmod_append(env, header_insert, sighdr, p, 0);
393 	free(sighdr);
394 }
395 
396 #line 282
397         env_function_cleanup_flush(env, NULL);
398 #line 282
399 	return;
400 #line 282
401 }
402 
403 static size_t dkim_explanation_code_loc
404 #line 284 "dkim.bi"
405 ;
406 static size_t dkim_explanation_loc
407 #line 285 "dkim.bi"
408 ;
409 static size_t dkim_verified_signature_loc
410 #line 286 "dkim.bi"
411 ;
412 
413 
414 void
415 #line 289
bi_dkim_verify(eval_environ_t env)416 bi_dkim_verify(eval_environ_t env)
417 #line 289
418 
419 #line 289
420 
421 #line 289 "dkim.bi"
422 {
423 #line 289
424 
425 #line 289
426 
427 #line 289
428 
429 #line 289
430 long  nmsg;
431 #line 289
432 
433 #line 289
434 get_numeric_arg(env, 0, &nmsg);
435 #line 289
436 
437 #line 289
438 
439 #line 289
440         adjust_stack(env, 1);
441 #line 289
442 
443 #line 289
444 
445 #line 289
446 	if (builtin_module_trace(BUILTIN_IDX_dkim))
447 #line 289
448 		prog_trace(env, "dkim_verify %lu",nmsg);;
449 #line 289
450 
451 {
452 	mu_message_t msg = bi_message_from_descr(env, nmsg);
453 	char *sig;
454 	int result = mfd_dkim_verify(msg, &sig);
455 	mf_c_val(*env_data_ref(env, dkim_explanation_code_loc),long) = (result);
456 
457 #line 295
458 { size_t __off;
459 #line 295
460   const char *__s = dkim_explanation_str[result];
461 #line 295
462   if (__s)
463 #line 295
464      strcpy((char*)env_data_ref(env, __off = heap_reserve(env, strlen(__s) + 1)), __s);
465 #line 295
466   else
467 #line 295
468      __off = 0;
469 #line 295
470   mf_c_val(*env_data_ref(env, dkim_explanation_loc),size) = (__off); }
471 #line 295
472 ;
473 	if (dkim_result_trans[result] == DKIM_VERIFY_OK) {
474 
475 #line 297
476 { size_t __off;
477 #line 297
478   const char *__s = sig;
479 #line 297
480   if (__s)
481 #line 297
482      strcpy((char*)env_data_ref(env, __off = heap_reserve(env, strlen(__s) + 1)), __s);
483 #line 297
484   else
485 #line 297
486      __off = 0;
487 #line 297
488   mf_c_val(*env_data_ref(env, dkim_verified_signature_loc),size) = (__off); }
489 #line 297
490 ;
491 	} else {
492 
493 #line 299
494 { size_t __off;
495 #line 299
496   const char *__s = "";
497 #line 299
498   if (__s)
499 #line 299
500      strcpy((char*)env_data_ref(env, __off = heap_reserve(env, strlen(__s) + 1)), __s);
501 #line 299
502   else
503 #line 299
504      __off = 0;
505 #line 299
506   mf_c_val(*env_data_ref(env, dkim_verified_signature_loc),size) = (__off); }
507 #line 299
508 ;
509 	}
510 
511 #line 301
512 do {
513 #line 301
514   push(env, (STKVAL)(mft_number)(dkim_result_trans[result]));
515 #line 301
516   goto endlab;
517 #line 301
518 } while (0);
519 }
520 endlab:
521 #line 303
522         env_function_cleanup_flush(env, NULL);
523 #line 303
524 	return;
525 #line 303
526 }
527 #line 982 "../../src/builtin/snarf.m4"
528 
529 #line 982
530 
531 #line 982
532 #endif /* WITH_DKIM */
533 #line 982
534 
535 #line 982
536 void
537 #line 982
dkim_init_builtin(void)538 dkim_init_builtin(void)
539 #line 982
540 {
541 #line 982
542 		debug_handle = mu_debug_register_category("bi_dkim");
543 #line 982
544 
545 #line 982
546 #ifdef WITH_DKIM
547 #line 982
548 	pp_define("WITH_DKIM");
549 #line 982
550 	#line 170 "dkim.bi"
551 va_builtin_install_ex("dkim_sign", bi_dkim_sign, STATMASK(smtp_state_eom), dtype_unspecified, 6, 3, MFD_BUILTIN_CAPTURE|0, dtype_string, dtype_string, dtype_string, dtype_string, dtype_string, dtype_string);
552 #line 284 "dkim.bi"
553 	builtin_variable_install("dkim_explanation_code", dtype_number, SYM_VOLATILE, &dkim_explanation_code_loc);
554 #line 285 "dkim.bi"
555 	builtin_variable_install("dkim_explanation", dtype_string, SYM_VOLATILE, &dkim_explanation_loc);
556 #line 286 "dkim.bi"
557 	builtin_variable_install("dkim_verified_signature", dtype_string, SYM_VOLATILE, &dkim_verified_signature_loc);
558 #line 289 "dkim.bi"
559 va_builtin_install_ex("dkim_verify", bi_dkim_verify, 0, dtype_number, 1, 0, 0|0, dtype_number);
560 
561 #line 982 "../../src/builtin/snarf.m4"
562 
563 #line 982
564 #endif /* WITH_DKIM */
565 #line 982
566 }
567 #line 982 "../../src/builtin/snarf.m4"
568 
569