diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-12-08 22:08:36 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-12-08 22:11:04 +0200 |
commit | 67ca2ef061a73bc90e4399471ee0cb3ce6f0ee41 (patch) | |
tree | d45493df75f3f613ca6b3d13a7f5d7a0280650a6 | |
parent | e1afd42340c0b2c22660744e0f88258a44617e88 (diff) | |
download | wydawca-67ca2ef061a73bc90e4399471ee0cb3ce6f0ee41.tar.gz wydawca-67ca2ef061a73bc90e4399471ee0cb3ce6f0ee41.tar.bz2 |
Implement GPG signing of the outgoing notifications.
* src/config.c (mail_statistics_kw): New keyword gpg-sign.
(notify_event_kw): Likewise.
(wydawca_kw): New keyword gpg-homedir.
* src/gpg.c (wydawca_gpg_homedir): Rename to
create_gpg_homedir. Make static.
All uses updated.
* src/mail.c (admin_stat_sign_key): New global.
(mu_stream_data_read_cb)
(gpg_sign, sign_message): New functions.
(mail_send_message): Take 3rd argument: ID of
the PGP key to sign the message with.
All callers updated.
(do_notify): Rewrite.
* src/wydawca.c (wydawca_gpg_homedir): New variable.
* src/wydawca.h (struct notification): New member
sign_keys.
(admin_stat_sign_key): New extern.
(wydawca_gpg_homedir): New extern.
-rw-r--r-- | doc/Makefile.am | 9 | ||||
-rw-r--r-- | src/config.c | 9 | ||||
-rw-r--r-- | src/gpg.c | 9 | ||||
-rw-r--r-- | src/mail.c | 222 | ||||
-rw-r--r-- | src/wydawca.c | 1 | ||||
-rw-r--r-- | src/wydawca.h | 4 |
6 files changed, 238 insertions, 16 deletions
diff --git a/doc/Makefile.am b/doc/Makefile.am index f53e47c..721ea29 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am | |||
@@ -99,6 +99,15 @@ check-unrevised: | |||
99 | rm $@-t; \ | 99 | rm $@-t; \ |
100 | fi | 100 | fi |
101 | 101 | ||
102 | check-config: | ||
103 | @check-docs.sh 'configuration statements' \ | ||
104 | '/wydawca_keywords\[\] *= *{/,/^}/s/[ \t]*{ *"\([^,"]*\)".*/\1/pg' \ | ||
105 | 's/@deffnx\{0,1\} {Config} *\([^@,]*\).*/\1/p' \ | ||
106 | $(top_srcdir)/src/config.c -- \ | ||
107 | $(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) -E - \ | ||
108 | $(info_TEXINFOS) | ||
109 | |||
110 | |||
102 | all-check-docs: check-format check-options check-refs check-fixmes check-unrevised check-writeme | 111 | all-check-docs: check-format check-options check-refs check-fixmes check-unrevised check-writeme |
103 | 112 | ||
104 | check-docs: | 113 | check-docs: |
diff --git a/src/config.c b/src/config.c index 559f766..f0a7042 100644 --- a/src/config.c +++ b/src/config.c | |||
@@ -863,6 +863,9 @@ static struct grecs_keyword mail_statistics_kw[] = { | |||
863 | { "statistics", | 863 | { "statistics", |
864 | N_("items"), N_("Send mail if one or more of these items are set"), | 864 | N_("items"), N_("Send mail if one or more of these items are set"), |
865 | grecs_type_string, &mail_admin_mask, 0, cb_statistics }, | 865 | grecs_type_string, &mail_admin_mask, 0, cb_statistics }, |
866 | { "gpg-sign", | ||
867 | N_("key"), N_("Sign message with this key"), | ||
868 | grecs_type_string, &admin_stat_sign_key }, | ||
866 | { NULL } | 869 | { NULL } |
867 | }; | 870 | }; |
868 | 871 | ||
@@ -907,6 +910,9 @@ static struct grecs_keyword notify_event_kw[] = { | |||
907 | { "message", N_("text-or-id"), | 910 | { "message", N_("text-or-id"), |
908 | N_("Text of the notification or identifier of a defined message template"), | 911 | N_("Text of the notification or identifier of a defined message template"), |
909 | grecs_type_string, NULL, offsetof(struct notification, msg) }, | 912 | grecs_type_string, NULL, offsetof(struct notification, msg) }, |
913 | { "gpg-sign", N_("key"), | ||
914 | N_("Sign message with this key"), | ||
915 | grecs_type_string, NULL, offsetof(struct notification, sign_keys) }, | ||
910 | { NULL } | 916 | { NULL } |
911 | }; | 917 | }; |
912 | 918 | ||
@@ -1457,6 +1463,9 @@ static struct grecs_keyword wydawca_kw[] = { | |||
1457 | { "all-spools", NULL, N_("Service names that request scanning all spools"), | 1463 | { "all-spools", NULL, N_("Service names that request scanning all spools"), |
1458 | grecs_type_string|GRECS_LIST, &all_spool_aliases }, | 1464 | grecs_type_string|GRECS_LIST, &all_spool_aliases }, |
1459 | 1465 | ||
1466 | { "gpg-homedir", NULL, N_("GPG home directory"), | ||
1467 | grecs_type_string, &wydawca_gpg_homedir }, | ||
1468 | |||
1460 | { NULL } | 1469 | { NULL } |
1461 | }; | 1470 | }; |
1462 | 1471 | ||
@@ -128,8 +128,8 @@ remove_homedir () | |||
128 | } | 128 | } |
129 | 129 | ||
130 | /* Create a temporary GPG home directory */ | 130 | /* Create a temporary GPG home directory */ |
131 | int | 131 | static int |
132 | wydawca_gpg_homedir () | 132 | create_gpg_homedir () |
133 | { | 133 | { |
134 | if (homedir) | 134 | if (homedir) |
135 | return 0; | 135 | return 0; |
@@ -222,12 +222,11 @@ verify_directive_signature (struct file_triplet *trp, | |||
222 | { | 222 | { |
223 | gpgme_ctx_t ctx; | 223 | gpgme_ctx_t ctx; |
224 | gpgme_data_t key_data, directive_data, plain; | 224 | gpgme_data_t key_data, directive_data, plain; |
225 | off_t size; | ||
226 | gpgme_error_t ec; | 225 | gpgme_error_t ec; |
227 | int rc; | 226 | int rc; |
228 | struct uploader_info *uptr; | 227 | struct uploader_info *uptr; |
229 | 228 | ||
230 | wydawca_gpg_homedir (); | 229 | create_gpg_homedir (); |
231 | fail_if_err (gpgme_new (&ctx)); | 230 | fail_if_err (gpgme_new (&ctx)); |
232 | 231 | ||
233 | for (uptr = trp->uploader_list; uptr; uptr = uptr->next) | 232 | for (uptr = trp->uploader_list; uptr; uptr = uptr->next) |
@@ -301,7 +300,7 @@ verify_detached_signature (struct file_triplet *trp, | |||
301 | return 1; | 300 | return 1; |
302 | } | 301 | } |
303 | 302 | ||
304 | wydawca_gpg_homedir (); | 303 | create_gpg_homedir (); |
305 | argv[0] = info->file_name; | 304 | argv[0] = info->file_name; |
306 | argv[1] = "--verify"; | 305 | argv[1] = "--verify"; |
307 | argv[2] = trp->file[file_signature].name; | 306 | argv[2] = trp->file[file_signature].name; |
@@ -17,6 +17,7 @@ | |||
17 | #include "wydawca.h" | 17 | #include "wydawca.h" |
18 | #include <mail.h> | 18 | #include <mail.h> |
19 | #include <hash.h> | 19 | #include <hash.h> |
20 | #include <gpgme.h> | ||
20 | 21 | ||
21 | int mailer_opened; | 22 | int mailer_opened; |
22 | mu_mailer_t mailer; | 23 | mu_mailer_t mailer; |
@@ -27,6 +28,7 @@ unsigned long owner_notification_flags; | |||
27 | char *user_message_template[MAX_EVENT]; | 28 | char *user_message_template[MAX_EVENT]; |
28 | 29 | ||
29 | char *admin_stat_message; | 30 | char *admin_stat_message; |
31 | char *admin_stat_sign_key; | ||
30 | 32 | ||
31 | void | 33 | void |
32 | mail_init () | 34 | mail_init () |
@@ -44,8 +46,203 @@ mail_init () | |||
44 | } | 46 | } |
45 | } | 47 | } |
46 | 48 | ||
49 | struct mu_stream_handle | ||
50 | { | ||
51 | mu_stream_t str; | ||
52 | mu_off_t off; | ||
53 | }; | ||
54 | |||
55 | static ssize_t | ||
56 | mu_stream_data_read_cb (void *handle, void *buffer, size_t size) | ||
57 | { | ||
58 | struct mu_stream_handle *mhp = handle; | ||
59 | size_t nread; | ||
60 | int rc; | ||
61 | |||
62 | rc = mu_stream_read (mhp->str, buffer, size, mhp->off, &nread); | ||
63 | if (rc) | ||
64 | { | ||
65 | logmsg (LOG_ERR, "mu_stream_read: %s", mu_strerror (rc)); | ||
66 | errno = EIO; | ||
67 | return -1; | ||
68 | } | ||
69 | |||
70 | mhp->off += nread; | ||
71 | return nread; | ||
72 | } | ||
73 | |||
74 | static int | ||
75 | gpg_sign (gpgme_data_t *output, gpgme_data_t input, const char *sign_keys) | ||
76 | { | ||
77 | gpgme_ctx_t ctx; | ||
78 | gpgme_error_t err = 0; | ||
79 | gpgme_key_t key; | ||
80 | |||
81 | err = gpgme_new (&ctx); | ||
82 | if (err) | ||
83 | { | ||
84 | logmsg (LOG_ERR, _("GPGME: cannot create context: %s"), | ||
85 | gpgme_strerror (err)); | ||
86 | return 1; | ||
87 | } | ||
88 | |||
89 | err = gpgme_op_keylist_start (ctx, sign_keys, 0); | ||
90 | if (!err) | ||
91 | { | ||
92 | while ((err = gpgme_op_keylist_next (ctx, &key)) == 0) | ||
93 | { | ||
94 | err = gpgme_signers_add (ctx, key); | ||
95 | gpgme_key_release (key); | ||
96 | } | ||
97 | } | ||
98 | |||
99 | if (err && gpg_err_code (err) != GPG_ERR_EOF) | ||
100 | { | ||
101 | logmsg (LOG_ERR, _("GPGME: cannot list keys: %s"), | ||
102 | gpgme_strerror (err)); | ||
103 | gpgme_release (ctx); | ||
104 | return 1; | ||
105 | } | ||
106 | |||
107 | err = gpgme_data_new (output); | ||
108 | if (err) | ||
109 | { | ||
110 | logmsg (LOG_ERR, _("%s: GPGME error: %s"), | ||
111 | "gpgme_data_new", | ||
112 | gpgme_strerror (err)); | ||
113 | gpgme_release (ctx); | ||
114 | return 1; | ||
115 | } | ||
116 | |||
117 | /* FIXME: Passphrase */ | ||
118 | gpgme_set_textmode (ctx, 1); | ||
119 | gpgme_set_armor (ctx, 1); | ||
120 | |||
121 | err = gpgme_op_sign (ctx, input, *output, GPGME_SIG_MODE_CLEAR); | ||
122 | if (err) | ||
123 | logmsg (LOG_ERR, _("%s: GPGME error: %s"), | ||
124 | "gpgme_op_sign", | ||
125 | gpgme_strerror (err)); | ||
126 | #if 0 | ||
127 | /* FIXME: */ | ||
128 | else if (debug_level > 1) | ||
129 | gpgme_debug_info (ctx); | ||
130 | #endif | ||
131 | |||
132 | gpgme_release (ctx); | ||
133 | return err != 0; | ||
134 | } | ||
135 | |||
136 | static int | ||
137 | sign_message (mu_message_t *pmsg, const char *key) | ||
138 | { | ||
139 | mu_message_t msg = *pmsg; | ||
140 | mu_message_t newmsg; | ||
141 | mu_body_t body; | ||
142 | mu_header_t hdr; | ||
143 | struct mu_stream_handle mhn; | ||
144 | mu_stream_t istr, ostr; | ||
145 | int rc; | ||
146 | struct gpgme_data_cbs cbs; | ||
147 | gpgme_data_t input, output; | ||
148 | gpgme_error_t err; | ||
149 | char *buf = NULL; | ||
150 | size_t size = 0; | ||
151 | size_t nread; | ||
152 | |||
153 | if (debug_level) | ||
154 | logmsg (LOG_DEBUG, _("signing message as %s"), key); | ||
155 | |||
156 | if (wydawca_gpg_homedir) | ||
157 | { | ||
158 | if (debug_level > 1) | ||