Re-implement GSASL support.
* libmu_auth/lbuf.c: Removed. * libmu_auth/lbuf.h: Removed. * libmu_auth/Makefile.am : Remove lbuf stuff. * include/mailutils/sys/gsasl-stream.h: New file. * include/mailutils/sys/Makefile.am: Add gsasl-stream.h. * include/mailutils/gsasl.h (mu_gsasl_stream_create): Remove. (gsasl_encoder_stream, gsasl_decoder_stream): New prototypes. * libmu_auth/gsasl.c: Rewrite. * imap4d/authenticate.c (auth_data): Remove. Use struct imap4d_auth instead. (_auth_try): Use new authentication API. (imap4d_authenticate): Likewise. * imap4d/imap4d.h (util_register_event, util_event_remove) (util_run_events): Remove. (imap4d_auth_handler_fp): Change prototype. (imap4d_auth): New struct. (imap4d_auth_result): New enum. * imap4d/io.c (io_format_completion_response) (io_stream_completion_response): New functions. (io_completion_response): Rewrite using io_format_completion_response. * imap4d/util.c (sc2string): Remove leftover prototype. (util_register_event, util_event_remove) (util_run_events): Remove. * imap4d/auth_gsasl.c: Revamp using new streams and the new authentication interface. * imap4d/auth_gss.c: Likewise (though yet untested). * mailbox/xscript-stream.c (_xscript_ctl): Remove unused variables.
Showing
14 changed files
with
376 additions
and
602 deletions
... | @@ -29,43 +29,6 @@ static Gsasl_session *sess_ctx; | ... | @@ -29,43 +29,6 @@ static Gsasl_session *sess_ctx; |
29 | 29 | ||
30 | static void auth_gsasl_capa_init (int disable); | 30 | static void auth_gsasl_capa_init (int disable); |
31 | 31 | ||
32 | static int | ||
33 | create_gsasl_stream (mu_stream_t *newstr, mu_stream_t transport, int flags) | ||
34 | { | ||
35 | int rc; | ||
36 | |||
37 | rc = mu_gsasl_stream_create (newstr, transport, sess_ctx, flags); | ||
38 | if (rc) | ||
39 | { | ||
40 | mu_diag_output (MU_DIAG_ERROR, _("cannot create SASL stream: %s"), | ||
41 | mu_strerror (rc)); | ||
42 | return RESP_NO; | ||
43 | } | ||
44 | |||
45 | if ((rc = mu_stream_open (*newstr)) != 0) | ||
46 | { | ||
47 | mu_diag_output (MU_DIAG_ERROR, | ||
48 | _("cannot open SASL input stream: %s"), | ||
49 | mu_stream_strerror (*newstr, rc)); | ||
50 | return RESP_NO; | ||
51 | } | ||
52 | |||
53 | return RESP_OK; | ||
54 | } | ||
55 | |||
56 | int | ||
57 | gsasl_replace_streams (void *self, void *data) | ||
58 | { | ||
59 | mu_stream_t *s = data; | ||
60 | |||
61 | util_set_input (s[0]); | ||
62 | util_set_output (s[1]); | ||
63 | free (s); | ||
64 | util_event_remove (self); | ||
65 | free (self); | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static void | 32 | static void |
70 | finish_session (void) | 33 | finish_session (void) |
71 | { | 34 | { |
... | @@ -73,7 +36,21 @@ finish_session (void) | ... | @@ -73,7 +36,21 @@ finish_session (void) |
73 | } | 36 | } |
74 | 37 | ||
75 | static int | 38 | static int |
76 | auth_gsasl (struct imap4d_command *command, char *auth_type, char **username) | 39 | restore_and_return (struct imap4d_auth *ap, mu_stream_t *str, int resp) |
40 | { | ||
41 | int rc = mu_stream_ioctl (iostream, MU_IOCTL_SWAP_STREAM, str); | ||
42 | if (rc) | ||
43 | { | ||
44 | mu_error (_("%s failed when it should not: %s"), "MU_IOCTL_SWAP_STREAM", | ||
45 | mu_stream_strerror (iostream, rc)); | ||
46 | abort (); | ||
47 | } | ||
48 | ap->response = resp; | ||
49 | return imap4d_auth_resp; | ||
50 | } | ||
51 | |||
52 | static enum imap4d_auth_result | ||
53 | auth_gsasl (struct imap4d_auth *ap) | ||
77 | { | 54 | { |
78 | char *input_str = NULL; | 55 | char *input_str = NULL; |
79 | size_t input_size = 0; | 56 | size_t input_size = 0; |
... | @@ -81,15 +58,15 @@ auth_gsasl (struct imap4d_command *command, char *auth_type, char **username) | ... | @@ -81,15 +58,15 @@ auth_gsasl (struct imap4d_command *command, char *auth_type, char **username) |
81 | char *output; | 58 | char *output; |
82 | int rc; | 59 | int rc; |
83 | 60 | ||
84 | rc = gsasl_server_start (ctx, auth_type, &sess_ctx); | 61 | rc = gsasl_server_start (ctx, ap->auth_type, &sess_ctx); |
85 | if (rc != GSASL_OK) | 62 | if (rc != GSASL_OK) |
86 | { | 63 | { |
87 | mu_diag_output (MU_DIAG_NOTICE, _("SASL gsasl_server_start: %s"), | 64 | mu_diag_output (MU_DIAG_NOTICE, _("SASL gsasl_server_start: %s"), |
88 | gsasl_strerror (rc)); | 65 | gsasl_strerror (rc)); |
89 | return 0; | 66 | return imap4d_auth_fail; |
90 | } | 67 | } |
91 | 68 | ||
92 | gsasl_callback_hook_set (ctx, username); | 69 | gsasl_callback_hook_set (ctx, &ap->username); |
93 | 70 | ||
94 | output = NULL; | 71 | output = NULL; |
95 | while ((rc = gsasl_step64 (sess_ctx, input_str, &output)) | 72 | while ((rc = gsasl_step64 (sess_ctx, input_str, &output)) |
... | @@ -105,7 +82,8 @@ auth_gsasl (struct imap4d_command *command, char *auth_type, char **username) | ... | @@ -105,7 +82,8 @@ auth_gsasl (struct imap4d_command *command, char *auth_type, char **username) |
105 | gsasl_strerror (rc)); | 82 | gsasl_strerror (rc)); |
106 | free (input_str); | 83 | free (input_str); |
107 | free (output); | 84 | free (output); |
108 | return RESP_NO; | 85 | ap->response = RESP_NO; |
86 | return imap4d_auth_resp; | ||
109 | } | 87 | } |
110 | 88 | ||
111 | /* Some SASL mechanisms output additional data when GSASL_OK is | 89 | /* Some SASL mechanisms output additional data when GSASL_OK is |
... | @@ -119,44 +97,81 @@ auth_gsasl (struct imap4d_command *command, char *auth_type, char **username) | ... | @@ -119,44 +97,81 @@ auth_gsasl (struct imap4d_command *command, char *auth_type, char **username) |
119 | mu_diag_output (MU_DIAG_NOTICE, _("non-empty client response")); | 97 | mu_diag_output (MU_DIAG_NOTICE, _("non-empty client response")); |
120 | free (input_str); | 98 | free (input_str); |
121 | free (output); | 99 | free (output); |
122 | return RESP_NO; | 100 | ap->response = RESP_NO; |
101 | return imap4d_auth_resp; | ||
123 | } | 102 | } |
124 | } | 103 | } |
125 | 104 | ||
126 | free (input_str); | 105 | free (input_str); |
127 | free (output); | 106 | free (output); |
128 | 107 | ||
129 | if (*username == NULL) | 108 | if (ap->username == NULL) |
130 | { | 109 | { |
131 | mu_diag_output (MU_DIAG_NOTICE, _("GSASL %s: cannot get username"), auth_type); | 110 | mu_diag_output (MU_DIAG_NOTICE, _("GSASL %s: cannot get username"), |
132 | return RESP_NO; | 111 | ap->auth_type); |
112 | ap->response = RESP_NO; | ||
113 | return imap4d_auth_resp; | ||
133 | } | 114 | } |
134 | 115 | ||
116 | auth_gsasl_capa_init (1); | ||
135 | if (sess_ctx) | 117 | if (sess_ctx) |
136 | { | 118 | { |
137 | mu_stream_t tmp, new_in, new_out; | 119 | mu_stream_t stream[2], newstream[2]; |
138 | mu_stream_t *s; | 120 | |
139 | 121 | stream[0] = stream[1] = NULL; | |
140 | util_get_input (&tmp); | 122 | rc = mu_stream_ioctl (iostream, MU_IOCTL_SWAP_STREAM, stream); |
141 | if (create_gsasl_stream (&new_in, tmp, MU_STREAM_READ)) | 123 | if (rc) |
142 | return RESP_NO; | 124 | { |
143 | util_get_output (&tmp); | 125 | mu_error (_("%s failed: %s"), "MU_IOCTL_SWAP_STREAM", |
144 | if (create_gsasl_stream (&new_out, tmp, MU_STREAM_WRITE)) | 126 | mu_stream_strerror (iostream, rc)); |
127 | ap->response = RESP_NO; | ||
128 | return imap4d_auth_resp; | ||
129 | } | ||
130 | rc = gsasl_encoder_stream (&newstream[0], stream[0], sess_ctx, | ||
131 | MU_STREAM_READ); | ||
132 | if (rc) | ||
133 | { | ||
134 | mu_error (_("%s failed: %s"), "gsasl_encoder_stream", | ||
135 | mu_strerror (rc)); | ||
136 | return restore_and_return (ap, stream, RESP_NO); | ||
137 | } | ||
138 | |||
139 | rc = gsasl_decoder_stream (&newstream[1], stream[1], sess_ctx, | ||
140 | MU_STREAM_WRITE); | ||
141 | if (rc) | ||
142 | { | ||
143 | mu_error (_("%s failed: %s"), "gsasl_decoder_stream", | ||
144 | mu_strerror (rc)); | ||
145 | mu_stream_destroy (&newstream[0]); | ||
146 | return restore_and_return (ap, stream, RESP_NO); | ||
147 | } | ||
148 | |||
149 | if (ap->username) | ||
145 | { | 150 | { |
146 | mu_stream_destroy (&new_in); | 151 | if (imap4d_session_setup (ap->username)) |
147 | return RESP_NO; | 152 | return restore_and_return (ap, stream, RESP_NO); |
148 | } | 153 | } |
149 | 154 | ||
150 | s = calloc (2, sizeof (mu_stream_t)); | 155 | /* FIXME: This is not reflected in the transcript. */ |
151 | s[0] = new_in; | 156 | io_stream_completion_response (stream[1], ap->command, RESP_OK, |
152 | s[1] = new_out; | 157 | "%s authentication successful", |
153 | util_register_event (STATE_NONAUTH, STATE_AUTH, | 158 | ap->auth_type); |
154 | gsasl_replace_streams, s); | 159 | mu_stream_flush (stream[1]); |
160 | |||
161 | rc = mu_stream_ioctl (iostream, MU_IOCTL_SWAP_STREAM, newstream); | ||
162 | if (rc) | ||
163 | { | ||
164 | mu_error (_("%s failed when it should not: %s"), | ||
165 | "MU_IOCTL_SWAP_STREAM", | ||
166 | mu_stream_strerror (iostream, rc)); | ||
167 | abort (); | ||
168 | } | ||
155 | util_atexit (finish_session); | 169 | util_atexit (finish_session); |
170 | return imap4d_auth_ok; | ||
156 | } | 171 | } |
157 | 172 | ||
158 | auth_gsasl_capa_init (1); | 173 | ap->response = RESP_OK; |
159 | return RESP_OK; | 174 | return imap4d_auth_resp; |
160 | } | 175 | } |
161 | 176 | ||
162 | static void | 177 | static void | ... | ... |
... | @@ -108,9 +108,8 @@ imap4d_gss_userok (gss_buffer_t client_name, char *name) | ... | @@ -108,9 +108,8 @@ imap4d_gss_userok (gss_buffer_t client_name, char *name) |
108 | } | 108 | } |
109 | #endif | 109 | #endif |
110 | 110 | ||
111 | static int | 111 | static enum imap4d_auth_result |
112 | auth_gssapi (struct imap4d_command *command, | 112 | auth_gssapi (struct imap4d_auth *ap) |
113 | char *auth_type_unused, char **username) | ||
114 | { | 113 | { |
115 | gss_buffer_desc tokbuf, outbuf; | 114 | gss_buffer_desc tokbuf, outbuf; |
116 | OM_uint32 maj_stat, min_stat, min_stat2; | 115 | OM_uint32 maj_stat, min_stat, min_stat2; |
... | @@ -147,7 +146,8 @@ auth_gssapi (struct imap4d_command *command, | ... | @@ -147,7 +146,8 @@ auth_gssapi (struct imap4d_command *command, |
147 | if (maj_stat != GSS_S_COMPLETE) | 146 | if (maj_stat != GSS_S_COMPLETE) |
148 | { | 147 | { |
149 | display_status ("import name", maj_stat, min_stat); | 148 | display_status ("import name", maj_stat, min_stat); |
150 | return RESP_NO; | 149 | ap->response = RESP_NO; |
150 | return imap4d_auth_resp; | ||
151 | } | 151 | } |
152 | 152 | ||
153 | maj_stat = gss_acquire_cred (&min_stat, server_name, 0, | 153 | maj_stat = gss_acquire_cred (&min_stat, server_name, 0, |
... | @@ -158,7 +158,8 @@ auth_gssapi (struct imap4d_command *command, | ... | @@ -158,7 +158,8 @@ auth_gssapi (struct imap4d_command *command, |
158 | if (maj_stat != GSS_S_COMPLETE) | 158 | if (maj_stat != GSS_S_COMPLETE) |
159 | { | 159 | { |
160 | display_status ("acquire credentials", maj_stat, min_stat); | 160 | display_status ("acquire credentials", maj_stat, min_stat); |
161 | return RESP_NO; | 161 | ap->response = RESP_NO; |
162 | return imap4d_auth_resp; | ||
162 | } | 163 | } |
163 | 164 | ||
164 | /* Start the dialogue */ | 165 | /* Start the dialogue */ |
... | @@ -206,7 +207,8 @@ auth_gssapi (struct imap4d_command *command, | ... | @@ -206,7 +207,8 @@ auth_gssapi (struct imap4d_command *command, |
206 | maj_stat = gss_delete_sec_context (&min_stat, &context, &outbuf); | 207 | maj_stat = gss_delete_sec_context (&min_stat, &context, &outbuf); |
207 | gss_release_buffer (&min_stat, &outbuf); | 208 | gss_release_buffer (&min_stat, &outbuf); |
208 | free (token_str); | 209 | free (token_str); |
209 | return RESP_NO; | 210 | ap->response = RESP_NO; |
211 | return imap4d_auth_resp; | ||
210 | } | 212 | } |
211 | 213 | ||
212 | if (outbuf.length) | 214 | if (outbuf.length) |
... | @@ -228,7 +230,8 @@ auth_gssapi (struct imap4d_command *command, | ... | @@ -228,7 +230,8 @@ auth_gssapi (struct imap4d_command *command, |
228 | { | 230 | { |
229 | display_status ("wrap", maj_stat, min_stat); | 231 | display_status ("wrap", maj_stat, min_stat); |
230 | free (token_str); | 232 | free (token_str); |
231 | return RESP_NO; | 233 | ap->response = RESP_NO; |
234 | return imap4d_auth_resp; | ||
232 | } | 235 | } |
233 | 236 | ||
234 | mu_base64_encode (outbuf.value, outbuf.length, &tmp, &size); | 237 | mu_base64_encode (outbuf.value, outbuf.length, &tmp, &size); |
... | @@ -246,7 +249,8 @@ auth_gssapi (struct imap4d_command *command, | ... | @@ -246,7 +249,8 @@ auth_gssapi (struct imap4d_command *command, |
246 | if (maj_stat != GSS_S_COMPLETE) | 249 | if (maj_stat != GSS_S_COMPLETE) |
247 | { | 250 | { |
248 | display_status ("unwrap", maj_stat, min_stat); | 251 | display_status ("unwrap", maj_stat, min_stat); |
249 | return RESP_NO; | 252 | ap->response = RESP_NO; |
253 | return imap4d_auth_resp; | ||
250 | } | 254 | } |
251 | 255 | ||
252 | sec_level = ntohl (*(OM_uint32 *) outbuf.value); | 256 | sec_level = ntohl (*(OM_uint32 *) outbuf.value); |
... | @@ -261,23 +265,25 @@ auth_gssapi (struct imap4d_command *command, | ... | @@ -261,23 +265,25 @@ auth_gssapi (struct imap4d_command *command, |
261 | gss_release_buffer (&min_stat, &outbuf); | 265 | gss_release_buffer (&min_stat, &outbuf); |
262 | maj_stat = gss_delete_sec_context (&min_stat, &context, &outbuf); | 266 | maj_stat = gss_delete_sec_context (&min_stat, &context, &outbuf); |
263 | gss_release_buffer (&min_stat, &outbuf); | 267 | gss_release_buffer (&min_stat, &outbuf); |
264 | return RESP_NO; | 268 | ap->response = RESP_NO; |
269 | return imap4d_auth_resp; | ||
265 | } | 270 | } |
266 | protection_mech = mech; | 271 | protection_mech = mech; |
267 | client_buffer_size = sec_level & 0x00ffffffff; | 272 | client_buffer_size = sec_level & 0x00ffffffff; |
268 | 273 | ||
269 | *username = malloc (outbuf.length - 4 + 1); | 274 | ap->username = malloc (outbuf.length - 4 + 1); |
270 | if (!*username) | 275 | if (!ap->username) |
271 | { | 276 | { |
272 | mu_diag_output (MU_DIAG_NOTICE, _("not enough memory")); | 277 | mu_diag_output (MU_DIAG_NOTICE, _("not enough memory")); |
273 | gss_release_buffer (&min_stat, &outbuf); | 278 | gss_release_buffer (&min_stat, &outbuf); |
274 | maj_stat = gss_delete_sec_context (&min_stat, &context, &outbuf); | 279 | maj_stat = gss_delete_sec_context (&min_stat, &context, &outbuf); |
275 | gss_release_buffer (&min_stat, &outbuf); | 280 | gss_release_buffer (&min_stat, &outbuf); |
276 | return RESP_NO; | 281 | ap->response = RESP_NO; |
282 | return imap4d_auth_resp; | ||
277 | } | 283 | } |
278 | 284 | ||
279 | memcpy (*username, (char *) outbuf.value + 4, outbuf.length - 4); | 285 | memcpy (ap->username, (char *) outbuf.value + 4, outbuf.length - 4); |
280 | (*username)[outbuf.length - 4] = '\0'; | 286 | ap->username[outbuf.length - 4] = '\0'; |
281 | gss_release_buffer (&min_stat, &outbuf); | 287 | gss_release_buffer (&min_stat, &outbuf); |
282 | 288 | ||
283 | maj_stat = gss_display_name (&min_stat, client, &client_name, &mech_type); | 289 | maj_stat = gss_display_name (&min_stat, client, &client_name, &mech_type); |
... | @@ -286,36 +292,40 @@ auth_gssapi (struct imap4d_command *command, | ... | @@ -286,36 +292,40 @@ auth_gssapi (struct imap4d_command *command, |
286 | display_status ("get client name", maj_stat, min_stat); | 292 | display_status ("get client name", maj_stat, min_stat); |
287 | maj_stat = gss_delete_sec_context (&min_stat, &context, &outbuf); | 293 | maj_stat = gss_delete_sec_context (&min_stat, &context, &outbuf); |
288 | gss_release_buffer (&min_stat, &outbuf); | 294 | gss_release_buffer (&min_stat, &outbuf); |
289 | free (*username); | 295 | free (ap->username); |
290 | return RESP_NO; | 296 | ap->response = RESP_NO; |
297 | return imap4d_auth_resp; | ||
291 | } | 298 | } |
292 | 299 | ||
293 | #ifdef WITH_GSS | 300 | #ifdef WITH_GSS |
294 | baduser = !gss_userok (client, *username); | 301 | baduser = !gss_userok (client, ap->username); |
295 | #else | 302 | #else |
296 | baduser = imap4d_gss_userok (&client_name, *username); | 303 | baduser = imap4d_gss_userok (&client_name, ap->username); |
297 | #endif | 304 | #endif |
298 | 305 | ||
299 | if (baduser) | 306 | if (baduser) |
300 | { | 307 | { |
301 | mu_diag_output (MU_DIAG_NOTICE, _("GSSAPI user %s is NOT authorized as %s"), | 308 | mu_diag_output (MU_DIAG_NOTICE, |
302 | (char *) client_name.value, *username); | 309 | _("GSSAPI user %s is NOT authorized as %s"), |
310 | (char *) client_name.value, ap->username); | ||
303 | maj_stat = gss_delete_sec_context (&min_stat, &context, &outbuf); | 311 | maj_stat = gss_delete_sec_context (&min_stat, &context, &outbuf); |
304 | gss_release_buffer (&min_stat, &outbuf); | 312 | gss_release_buffer (&min_stat, &outbuf); |
305 | gss_release_buffer (&min_stat, &client_name); | 313 | gss_release_buffer (&min_stat, &client_name); |
306 | free (*username); | 314 | free (ap->username); |
307 | return RESP_NO; | 315 | ap->response = RESP_NO; |
316 | return imap4d_auth_resp; | ||
308 | } | 317 | } |
309 | else | 318 | else |
310 | { | 319 | { |
311 | mu_diag_output (MU_DIAG_NOTICE, _("GSSAPI user %s is authorized as %s"), | 320 | mu_diag_output (MU_DIAG_NOTICE, _("GSSAPI user %s is authorized as %s"), |
312 | (char *) client_name.value, *username); | 321 | (char *) client_name.value, ap->username); |
313 | } | 322 | } |
314 | 323 | ||
315 | gss_release_buffer (&min_stat, &client_name); | 324 | gss_release_buffer (&min_stat, &client_name); |
316 | maj_stat = gss_delete_sec_context (&min_stat, &context, &outbuf); | 325 | maj_stat = gss_delete_sec_context (&min_stat, &context, &outbuf); |
317 | gss_release_buffer (&min_stat, &outbuf); | 326 | gss_release_buffer (&min_stat, &outbuf); |
318 | return RESP_OK; | 327 | ap->response = RESP_OK; |
328 | return imap4d_auth_resp; | ||
319 | } | 329 | } |
320 | 330 | ||
321 | void | 331 | void | ... | ... |
... | @@ -19,7 +19,8 @@ | ... | @@ -19,7 +19,8 @@ |
19 | 19 | ||
20 | #include "imap4d.h" | 20 | #include "imap4d.h" |
21 | 21 | ||
22 | struct imap_auth { | 22 | struct imap_auth |
23 | { | ||
23 | char *name; | 24 | char *name; |
24 | imap4d_auth_handler_fp handler; | 25 | imap4d_auth_handler_fp handler; |
25 | }; | 26 | }; |
... | @@ -66,24 +67,17 @@ _auth_capa (void *item, void *usused) | ... | @@ -66,24 +67,17 @@ _auth_capa (void *item, void *usused) |
66 | return 0; | 67 | return 0; |
67 | } | 68 | } |
68 | 69 | ||
69 | struct auth_data { | ||
70 | struct imap4d_command *command; | ||
71 | char *auth_type; | ||
72 | char *arg; | ||
73 | char *username; | ||
74 | int result; | ||
75 | }; | ||
76 | |||
77 | static int | 70 | static int |
78 | _auth_try (void *item, void *data) | 71 | _auth_try (void *item, void *data) |
79 | { | 72 | { |
80 | struct imap_auth *p = item; | 73 | struct imap_auth *p = item; |
81 | struct auth_data *ap = data; | 74 | struct imap4d_auth *ap = data; |
82 | 75 | ||
83 | if (strcmp (p->name, ap->auth_type) == 0) | 76 | if (strcmp (p->name, ap->auth_type) == 0) |
84 | { | 77 | { |
85 | ap->result = p->handler (ap->command, ap->auth_type, &ap->username); | 78 | int res = p->handler (ap); |
86 | return 1; | 79 | if (res) |
80 | return res; | ||
87 | } | 81 | } |
88 | return 0; | 82 | return 0; |
89 | } | 83 | } |
... | @@ -104,8 +98,9 @@ int | ... | @@ -104,8 +98,9 @@ int |
104 | imap4d_authenticate (struct imap4d_command *command, imap4d_tokbuf_t tok) | 98 | imap4d_authenticate (struct imap4d_command *command, imap4d_tokbuf_t tok) |
105 | { | 99 | { |
106 | char *auth_type; | 100 | char *auth_type; |
107 | struct auth_data adata; | 101 | struct imap4d_auth adata; |
108 | 102 | enum imap4d_auth_result res; | |
103 | |||
109 | if (imap4d_tokbuf_argc (tok) != 3) | 104 | if (imap4d_tokbuf_argc (tok) != 3) |
110 | return io_completion_response (command, RESP_BAD, "Invalid arguments"); | 105 | return io_completion_response (command, RESP_BAD, "Invalid arguments"); |
111 | 106 | ||
... | @@ -117,25 +112,35 @@ imap4d_authenticate (struct imap4d_command *command, imap4d_tokbuf_t tok) | ... | @@ -117,25 +112,35 @@ imap4d_authenticate (struct imap4d_command *command, imap4d_tokbuf_t tok) |
117 | 112 | ||
118 | adata.command = command; | 113 | adata.command = command; |
119 | adata.auth_type = auth_type; | 114 | adata.auth_type = auth_type; |
120 | adata.arg = NULL; | ||
121 | adata.username = NULL; | 115 | adata.username = NULL; |
122 | 116 | ||
123 | if (mu_list_do (imap_auth_list, _auth_try, &adata) == 0) | 117 | res = mu_list_do (imap_auth_list, _auth_try, &adata); |
124 | return io_completion_response (command, RESP_NO, | 118 | |
125 | "Authentication mechanism not supported"); | 119 | switch (res) |
126 | |||
127 | if (adata.result == RESP_OK && adata.username) | ||
128 | { | 120 | { |
129 | if (imap4d_session_setup (adata.username)) | 121 | case imap4d_auth_nosup: |
130 | return io_completion_response (command, RESP_NO, | 122 | return io_completion_response (command, RESP_NO, |
131 | "User name or passwd rejected"); | 123 | "Authentication mechanism not supported"); |
132 | else | 124 | case imap4d_auth_ok: |
133 | return io_completion_response (command, RESP_OK, | 125 | return 0; |
134 | "%s authentication successful", | 126 | |
135 | auth_type); | 127 | case imap4d_auth_resp: |
128 | if (adata.response == RESP_OK && adata.username) | ||
129 | { | ||
130 | if (imap4d_session_setup (adata.username)) | ||
131 | return io_completion_response (command, RESP_NO, | ||
132 | "User name or passwd rejected"); | ||
133 | else | ||
134 | return io_completion_response (command, RESP_OK, | ||
135 | "%s authentication successful", | ||
136 | auth_type); | ||
137 | } | ||
138 | /* fall through */ | ||
139 | case imap4d_auth_fail: | ||
140 | adata.response = RESP_NO; | ||
141 | break; | ||
136 | } | 142 | } |
137 | 143 | return io_completion_response (command, adata.response, | |
138 | return io_completion_response (command, adata.result, | 144 | "%s authentication failed", auth_type); |
139 | "%s authentication failed", auth_type); | ||
140 | } | 145 | } |
141 | 146 | ... | ... |
... | @@ -218,6 +218,11 @@ extern int io_send_literal (const char *); | ... | @@ -218,6 +218,11 @@ extern int io_send_literal (const char *); |
218 | extern int io_copy_out (mu_stream_t str, size_t size); | 218 | extern int io_copy_out (mu_stream_t str, size_t size); |
219 | extern int io_completion_response (struct imap4d_command *, int, | 219 | extern int io_completion_response (struct imap4d_command *, int, |
220 | const char *, ...) MU_PRINTFLIKE(3,4); | 220 | const char *, ...) MU_PRINTFLIKE(3,4); |
221 | extern int io_stream_completion_response (mu_stream_t str, | ||
222 | struct imap4d_command *command, | ||
223 | int rc, | ||
224 | const char *format, ...) | ||
225 | MU_PRINTFLIKE(4,5); | ||
221 | int io_getline (char **pbuf, size_t *psize, size_t *pnbytes); | 226 | int io_getline (char **pbuf, size_t *psize, size_t *pnbytes); |
222 | void io_setio (FILE*, FILE*); | 227 | void io_setio (FILE*, FILE*); |
223 | void io_flush (void); | 228 | void io_flush (void); |
... | @@ -368,10 +373,6 @@ int util_type_to_attribute (int type, char **attr_str); | ... | @@ -368,10 +373,6 @@ int util_type_to_attribute (int type, char **attr_str); |
368 | int util_attribute_matches_flag (mu_attribute_t attr, const char *item); | 373 | int util_attribute_matches_flag (mu_attribute_t attr, const char *item); |
369 | int util_uidvalidity (mu_mailbox_t smbox, unsigned long *uidvp); | 374 | int util_uidvalidity (mu_mailbox_t smbox, unsigned long *uidvp); |
370 | 375 | ||
371 | void util_register_event (int old_state, int new_state, | ||
372 | mu_list_action_t *action, void *data); | ||
373 | void util_event_remove (void *id); | ||
374 | void util_run_events (int old_state, int new_state); | ||
375 | 376 | ||
376 | int util_is_master (void); | 377 | int util_is_master (void); |
377 | void util_bye (void); | 378 | void util_bye (void); |
... | @@ -385,8 +386,26 @@ int util_trim_nl (char *s, size_t len); | ... | @@ -385,8 +386,26 @@ int util_trim_nl (char *s, size_t len); |
385 | int imap4d_init_tls_server (void); | 386 | int imap4d_init_tls_server (void); |
386 | #endif /* WITH_TLS */ | 387 | #endif /* WITH_TLS */ |
387 | 388 | ||
388 | typedef int (*imap4d_auth_handler_fp) (struct imap4d_command *, | 389 | struct imap4d_auth |
389 | char *, char **); | 390 | { |
391 | /* input */ | ||
392 | struct imap4d_command *command; | ||
393 | char *auth_type; | ||
394 | /* output */ | ||
395 | char *username; | ||
396 | int response; | ||
397 | }; | ||
398 | |||
399 | enum imap4d_auth_result | ||
400 | { | ||
401 | imap4d_auth_nosup, | ||
402 | imap4d_auth_ok, | ||
403 | imap4d_auth_resp, | ||
404 | imap4d_auth_fail | ||
405 | }; | ||
406 | |||
407 | typedef enum imap4d_auth_result | ||
408 | (*imap4d_auth_handler_fp) (struct imap4d_auth *); | ||
390 | 409 | ||
391 | extern void auth_add (char *name, imap4d_auth_handler_fp handler); | 410 | extern void auth_add (char *name, imap4d_auth_handler_fp handler); |
392 | extern void auth_remove (char *name); | 411 | extern void auth_remove (char *name); | ... | ... |
... | @@ -219,20 +219,18 @@ io_untagged_response (int rc, const char *format, ...) | ... | @@ -219,20 +219,18 @@ io_untagged_response (int rc, const char *format, ...) |
219 | 219 | ||
220 | /* Send the completion response and reset the state. */ | 220 | /* Send the completion response and reset the state. */ |
221 | int | 221 | int |
222 | io_completion_response (struct imap4d_command *command, int rc, | 222 | io_format_completion_response (mu_stream_t str, |
223 | const char *format, ...) | 223 | struct imap4d_command *command, int rc, |
224 | const char *format, va_list ap) | ||
224 | { | 225 | { |
225 | int new_state; | 226 | int new_state; |
226 | int status = 0; | 227 | int status = 0; |
227 | va_list ap; | ||
228 | const char *sc = sc2string (rc); | 228 | const char *sc = sc2string (rc); |
229 | 229 | ||
230 | mu_stream_printf (iostream, "%s %s%s ", | 230 | mu_stream_printf (str, "%s %s%s ", |
231 | command->tag, sc, command->name); | 231 | command->tag, sc, command->name); |
232 | va_start (ap, format); | 232 | mu_stream_vprintf (str, format, ap); |
233 | mu_stream_vprintf (iostream, format, ap); | 233 | mu_stream_write (str, "\n", 1, NULL); |
234 | va_end (ap); | ||
235 | mu_stream_write (iostream, "\n", 1, NULL); | ||
236 | 234 | ||
237 | /* Reset the state. */ | 235 | /* Reset the state. */ |
238 | if (rc == RESP_OK) | 236 | if (rc == RESP_OK) |
... | @@ -243,11 +241,35 @@ io_completion_response (struct imap4d_command *command, int rc, | ... | @@ -243,11 +241,35 @@ io_completion_response (struct imap4d_command *command, int rc, |
243 | new_state = STATE_NONE; | 241 | new_state = STATE_NONE; |
244 | 242 | ||
245 | if (new_state != STATE_NONE) | 243 | if (new_state != STATE_NONE) |
246 | { | 244 | state = new_state; |
247 | util_run_events (state, new_state); | 245 | |
248 | state = new_state; | 246 | return status; |
249 | } | 247 | } |
248 | |||
249 | int | ||
250 | io_completion_response (struct imap4d_command *command, int rc, | ||
251 | const char *format, ...) | ||
252 | { | ||
253 | va_list ap; | ||
254 | int status; | ||
255 | |||
256 | va_start (ap, format); | ||
257 | status = io_format_completion_response (iostream, command, rc, format, ap); | ||
258 | va_end (ap); | ||
259 | return status; | ||
260 | } | ||
261 | |||
262 | int | ||
263 | io_stream_completion_response (mu_stream_t str, | ||
264 | struct imap4d_command *command, int rc, | ||
265 | const char *format, ...) | ||
266 | { | ||
267 | va_list ap; | ||
268 | int status; | ||
250 | 269 | ||
270 | va_start (ap, format); | ||
271 | status = io_format_completion_response (str, command, rc, format, ap); | ||
272 | va_end (ap); | ||
251 | return status; | 273 | return status; |
252 | } | 274 | } |
253 | 275 | ... | ... |
... | @@ -20,7 +20,6 @@ | ... | @@ -20,7 +20,6 @@ |
20 | #include "imap4d.h" | 20 | #include "imap4d.h" |
21 | 21 | ||
22 | static int add2set (size_t **, int *, unsigned long); | 22 | static int add2set (size_t **, int *, unsigned long); |
23 | static const char *sc2string (int); | ||
24 | 23 | ||
25 | /* NOTE: Allocates Memory. */ | 24 | /* NOTE: Allocates Memory. */ |
26 | /* Expand: ~ --> /home/user and to ~guest --> /home/guest. */ | 25 | /* Expand: ~ --> /home/user and to ~guest --> /home/guest. */ |
... | @@ -651,74 +650,6 @@ util_bye () | ... | @@ -651,74 +650,6 @@ util_bye () |
651 | mu_list_do (atexit_list, atexit_run, 0); | 650 | mu_list_do (atexit_list, atexit_run, 0); |
652 | } | 651 | } |
653 | 652 | ||
654 | struct state_event | ||
655 | { | ||
656 | int old_state; | ||
657 | int new_state; | ||
658 | mu_list_action_t *action; | ||
659 | void *data; | ||
660 | }; | ||
661 | |||
662 | static mu_list_t event_list; | ||
663 | |||
664 | void | ||
665 | util_register_event (int old_state, int new_state, | ||
666 | mu_list_action_t *action, void *data) | ||
667 | { | ||
668 | struct state_event *evp = malloc (sizeof (*evp)); | ||
669 | if (!evp) | ||
670 | imap4d_bye (ERR_NO_MEM); | ||
671 | evp->old_state = old_state; | ||
672 | evp->new_state = new_state; | ||
673 | evp->action = action; | ||
674 | evp->data = data; | ||
675 | if (!event_list) | ||
676 | { | ||
677 | mu_list_create (&event_list); | ||
678 | mu_list_set_destroy_item (event_list, mu_list_free_item); | ||
679 | } | ||
680 | mu_list_append (event_list, (void*)evp); | ||
681 | } | ||
682 | |||
683 | void | ||
684 | util_event_remove (void *id) | ||
685 | { | ||
686 | mu_list_remove (event_list, id); | ||
687 | } | ||
688 | |||
689 | static int | ||
690 | event_exec (void *item, void *data) | ||
691 | { | ||
692 | struct state_event *ev = data, *elem = item; | ||
693 | |||
694 | if (ev->old_state == elem->old_state && ev->new_state == elem->new_state) | ||
695 | return elem->action (item, elem->data); | ||
696 | return 0; | ||
697 | } | ||
698 | |||
699 | void | ||
700 | util_run_events (int old_state, int new_state) | ||
701 | { | ||
702 | if (event_list) | ||
703 | { | ||
704 | struct state_event ev; | ||
705 | mu_iterator_t itr; | ||
706 | ev.old_state = old_state; | ||
707 | ev.new_state = new_state; | ||
708 | |||
709 | mu_list_get_iterator (event_list, &itr); | ||
710 | for (mu_iterator_first (itr); | ||
711 | !mu_iterator_is_done (itr); mu_iterator_next (itr)) | ||
712 | { | ||
713 | struct state_event *p; | ||
714 | mu_iterator_current (itr, (void **)&p); | ||
715 | if (event_exec (p, &ev)) | ||
716 | break; | ||
717 | } | ||
718 | mu_iterator_destroy (&itr); | ||
719 | } | ||
720 | } | ||
721 | |||
722 | void | 653 | void |
723 | util_chdir (const char *dir) | 654 | util_chdir (const char *dir) |
724 | { | 655 | { | ... | ... |
... | @@ -36,8 +36,10 @@ extern struct mu_gsasl_module_data mu_gsasl_module_data; | ... | @@ -36,8 +36,10 @@ extern struct mu_gsasl_module_data mu_gsasl_module_data; |
36 | #ifdef WITH_GSASL | 36 | #ifdef WITH_GSASL |
37 | #include <gsasl.h> | 37 | #include <gsasl.h> |
38 | 38 | ||
39 | int mu_gsasl_stream_create (mu_stream_t *stream, mu_stream_t transport, | 39 | int gsasl_encoder_stream (mu_stream_t *pstr, mu_stream_t transport, |
40 | Gsasl_session *ctx, int flags); | 40 | Gsasl_session *ctx, int flags); |
41 | int gsasl_decoder_stream (mu_stream_t *pstr, mu_stream_t transport, | ||
42 | Gsasl_session *ctx, int flags); | ||
41 | 43 | ||
42 | #endif | 44 | #endif |
43 | 45 | ... | ... |
... | @@ -22,6 +22,7 @@ sysinclude_HEADERS = \ | ... | @@ -22,6 +22,7 @@ sysinclude_HEADERS = \ |
22 | dbgstream.h\ | 22 | dbgstream.h\ |
23 | file_stream.h\ | 23 | file_stream.h\ |
24 | filter.h\ | 24 | filter.h\ |
25 | gsasl-stream.h\ | ||
25 | header_stream.h\ | 26 | header_stream.h\ |
26 | header.h\ | 27 | header.h\ |
27 | iostream.h\ | 28 | iostream.h\ | ... | ... |
include/mailutils/sys/gsasl-stream.h
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2010 Free Software Foundation, Inc. | ||
3 | |||
4 | This library is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU Lesser General Public License as published by | ||
6 | the Free Software Foundation; either version 3, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This library is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General Public License | ||
15 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ | ||
16 | |||
17 | #ifndef _MAILUTILS_SYS_TLS_STREAM_H | ||
18 | # define _MAILUTILS_SYS_GSASL_STREAM_H | ||
19 | |||
20 | # include <mailutils/types.h> | ||
21 | # include <mailutils/stream.h> | ||
22 | # include <mailutils/sys/stream.h> | ||
23 | |||
24 | struct _mu_gsasl_filter | ||
25 | { | ||
26 | Gsasl_session *sess_ctx; /* Context */ | ||
27 | int gsasl_err; /* Last Gsasl error code */ | ||
28 | char *bufptr; | ||
29 | size_t bufsize; | ||
30 | }; | ||
31 | |||
32 | struct _mu_gsasl_stream | ||
33 | { | ||
34 | struct _mu_stream stream; | ||
35 | mu_stream_t transport; | ||
36 | }; | ||
37 | |||
38 | #endif |
... | @@ -33,9 +33,10 @@ | ... | @@ -33,9 +33,10 @@ |
33 | #include <mailutils/nls.h> | 33 | #include <mailutils/nls.h> |
34 | #include <mailutils/stream.h> | 34 | #include <mailutils/stream.h> |
35 | #include <mailutils/gsasl.h> | 35 | #include <mailutils/gsasl.h> |
36 | #include <mailutils/sys/gsasl-stream.h> | ||
37 | #include <mailutils/filter.h> | ||
36 | 38 | ||
37 | #include <gsasl.h> | 39 | #include <gsasl.h> |
38 | #include <lbuf.h> | ||
39 | 40 | ||
40 | struct mu_gsasl_module_data mu_gsasl_module_data = { | 41 | struct mu_gsasl_module_data mu_gsasl_module_data = { |
41 | SITE_CRAM_MD5_PWD | 42 | SITE_CRAM_MD5_PWD |
... | @@ -49,235 +50,172 @@ mu_gsasl_module_init (enum mu_gocs_op op, void *data) | ... | @@ -49,235 +50,172 @@ mu_gsasl_module_init (enum mu_gocs_op op, void *data) |
49 | return 0; | 50 | return 0; |
50 | } | 51 | } |
51 | 52 | ||
52 | struct _gsasl_stream { | 53 | |
53 | Gsasl_session *sess_ctx; /* Context */ | 54 | static enum mu_filter_result |
54 | int last_err; /* Last Gsasl error code */ | 55 | _gsasl_encoder (void *xdata, |
55 | 56 | enum mu_filter_command cmd, | |
56 | mu_stream_t stream; /* I/O stream */ | 57 | struct mu_filter_io *iobuf) |
57 | struct _line_buffer *lb; | ||
58 | }; | ||
59 | |||
60 | static void | ||
61 | _gsasl_destroy (mu_stream_t stream) | ||
62 | { | ||
63 | int flags; | ||
64 | struct _gsasl_stream *s = mu_stream_get_owner (stream); | ||
65 | mu_stream_get_flags (stream, &flags); | ||
66 | if (!(flags & MU_STREAM_NO_CLOSE)) | ||
67 | mu_stream_destroy (&s->stream, mu_stream_get_owner (s->stream)); | ||
68 | _auth_lb_destroy (&s->lb); | ||
69 | } | ||
70 | |||
71 | static int | ||
72 | _gsasl_readline (mu_stream_t stream, char *optr, size_t osize, | ||
73 | off_t offset, size_t *nbytes) | ||
74 | { | 58 | { |
75 | struct _gsasl_stream *s = mu_stream_get_owner (stream); | 59 | struct _mu_gsasl_filter *flt = xdata; |
76 | int rc; | ||
77 | size_t len, sz; | ||
78 | char *bufp = NULL; | ||
79 | 60 | ||
80 | if (_auth_lb_level (s->lb)) | 61 | switch (cmd) |
81 | { | 62 | { |
82 | len = _auth_lb_readline (s->lb, optr, osize-1); | 63 | case mu_filter_init: |
83 | optr[len] = 0; | 64 | flt->bufptr = NULL; |
84 | if (nbytes) | 65 | flt->bufsize = 0; |
85 | *nbytes = len; | 66 | flt->gsasl_err = 0; |
86 | return 0; | 67 | return mu_filter_ok; |
68 | |||
69 | case mu_filter_done: | ||
70 | if (flt->bufptr) | ||
71 | free (flt->bufptr); | ||
72 | free (flt); | ||
73 | return mu_filter_ok; | ||
74 | |||
75 | default: | ||
76 | break; | ||
87 | } | 77 | } |
88 | 78 | ||
89 | do | 79 | if (flt->bufptr == NULL) |
90 | { | 80 | { |
91 | char c; | 81 | int status = gsasl_encode (flt->sess_ctx, iobuf->input, iobuf->isize, |
92 | size_t sz; | 82 | &flt->bufptr, &flt->bufsize); |
93 | int status; | 83 | /* FIXME: Can it require more input? */ |
94 | 84 | if (status) | |
95 | status = mu_stream_sequential_read (s->stream, &c, 1, &sz); | ||
96 | if (status == EINTR) | ||
97 | continue; | ||
98 | else if (status) | ||
99 | { | 85 | { |
100 | free (bufp); | 86 | flt->gsasl_err = status; |
101 | return status; | 87 | return mu_filter_falure; |
102 | } | 88 | } |
103 | rc = _auth_lb_grow (s->lb, &c, sz); | ||
104 | if (rc) | ||
105 | return rc; | ||
106 | |||
107 | rc = gsasl_decode (s->sess_ctx, | ||
108 | _auth_lb_data (s->lb), | ||
109 | _auth_lb_level (s->lb), | ||
110 | &bufp, &len); | ||
111 | } | 89 | } |
112 | while (rc == GSASL_NEEDS_MORE); | 90 | |
91 | iobuf->osize = flt->bufsize; | ||
113 | 92 | ||
114 | if (rc != GSASL_OK) | 93 | if (flt->bufsize > iobuf->osize) |
115 | { | 94 | return mu_filter_moreoutput; |
116 | s->last_err = rc; | ||
117 | free (bufp); | ||
118 | return EIO; | ||
119 | } | ||
120 | |||
121 | sz = len > osize ? osize : len; | ||
122 | |||
123 | if (len > osize) | ||
124 | { | ||
125 | memcpy (optr, bufp, osize); | ||
126 | _auth_lb_drop (s->lb); | ||
127 | _auth_lb_grow (s->lb, bufp + osize, len - osize); | ||
128 | len = osize; | ||
129 | } | ||
130 | else | ||
131 | { | ||
132 | _auth_lb_drop (s->lb); | ||
133 | memcpy (optr, bufp, len); | ||
134 | } | ||
135 | 95 | ||
136 | if (len < osize) | 96 | memcpy (iobuf->output, flt->bufptr, flt->bufsize); |
137 | optr[len] = 0; | ||
138 | |||
139 | if (nbytes) | ||
140 | *nbytes = len; | ||
141 | |||
142 | free (bufp); | ||
143 | 97 | ||
144 | return 0; | 98 | free (flt->bufptr); |
99 | flt->bufptr = NULL; | ||
100 | flt->bufsize = 0; | ||
101 | |||
102 | return mu_filter_ok; | ||
145 | } | 103 | } |
146 | 104 | ||
147 | int | 105 | |
148 | write_chunk (void *data, char *start, char *end) | 106 | static enum mu_filter_result |
107 | _gsasl_decoder (void *xdata, | ||
108 | enum mu_filter_command cmd, | ||
109 | struct mu_filter_io *iobuf) | ||
149 | { | 110 | { |
150 | struct _gsasl_stream *s = data; | 111 | struct _mu_gsasl_filter *flt = xdata; |
151 | size_t chunk_size = end - start + 1; | ||
152 | size_t len = 0; | ||
153 | char *buf = NULL; | ||
154 | int status; | 112 | int status; |
155 | |||
156 | gsasl_encode (s->sess_ctx, start, chunk_size, &buf, &len); | ||
157 | |||
158 | status = mu_stream_sequential_write (s->stream, buf, len); | ||
159 | 113 | ||
160 | free (buf); | 114 | switch (cmd) |
115 | { | ||
116 | case mu_filter_init: | ||
117 | flt->bufptr = NULL; | ||
118 | flt->bufsize = 0; | ||
119 | flt->gsasl_err = 0; | ||
120 | return mu_filter_ok; | ||
121 | |||
122 | case mu_filter_done: | ||
123 | if (flt->bufptr) | ||
124 | free (flt->bufptr); | ||
125 | free (flt); | ||
126 | return mu_filter_ok; | ||
127 | |||
128 | default: | ||
129 | break; | ||
130 | } | ||
161 | 131 | ||
162 | return status; | 132 | if (flt->bufptr == NULL) |
163 | } | 133 | { |
134 | status = gsasl_decode (flt->sess_ctx, iobuf->input, iobuf->isize, | ||
135 | &flt->bufptr, &flt->bufsize); | ||
136 | switch (status) | ||
137 | { | ||
138 | case GSASL_OK: | ||
139 | break; | ||
140 | |||
141 | case GSASL_NEEDS_MORE: | ||
142 | iobuf->isize++; | ||
143 | return mu_filter_moreinput; | ||
144 | |||
145 | default: | ||
146 | flt->gsasl_err = status; | ||
147 | return mu_filter_falure; | ||
148 | } | ||
149 | } | ||
164 | 150 | ||
151 | iobuf->osize = flt->bufsize; | ||
165 | 152 | ||
166 | static int | 153 | if (flt->bufsize > iobuf->osize) |
167 | _gsasl_write (mu_stream_t stream, const char *iptr, size_t isize, | 154 | return mu_filter_moreoutput; |
168 | off_t offset, size_t *nbytes) | ||
169 | { | ||
170 | int rc; | ||
171 | struct _gsasl_stream *s = mu_stream_get_owner (stream); | ||
172 | 155 | ||
173 | rc = _auth_lb_grow (s->lb, iptr, isize); | 156 | memcpy (iobuf->output, flt->bufptr, flt->bufsize); |
174 | if (rc) | ||
175 | return rc; | ||
176 | |||
177 | return _auth_lb_writelines (s->lb, iptr, isize, offset, | ||
178 | write_chunk, s, nbytes); | ||
179 | } | ||
180 | |||
181 | static int | ||
182 | _gsasl_flush (mu_stream_t stream) | ||
183 | { | ||
184 | struct _gsasl_stream *s = mu_stream_get_owner (stream); | ||
185 | return mu_stream_flush (s->stream); | ||
186 | } | ||
187 | 157 | ||
188 | static int | 158 | free (flt->bufptr); |
189 | _gsasl_close (mu_stream_t stream) | 159 | flt->bufptr = NULL; |
190 | { | 160 | flt->bufsize = 0; |
191 | int flags; | 161 | |
192 | struct _gsasl_stream *s = mu_stream_get_owner (stream); | 162 | return mu_filter_ok; |
193 | |||
194 | mu_stream_get_flags (stream, &flags); | ||
195 | if (!(flags & MU_STREAM_NO_CLOSE)) | ||
196 | mu_stream_close (s->stream); | ||
197 | return 0; | ||
198 | } | ||
199 | |||
200 | static int | ||
201 | _gsasl_open (mu_stream_t stream) | ||
202 | { | ||
203 | /* Nothing to do */ | ||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | int | ||
208 | _gsasl_strerror (mu_stream_t stream, const char **pstr) | ||
209 | { | ||
210 | struct _gsasl_stream *s = mu_stream_get_owner (stream); | ||
211 | *pstr = gsasl_strerror (s->last_err); | ||
212 | return 0; | ||
213 | } | 163 | } |
214 | 164 | ||
215 | int | 165 | int |
216 | _gsasl_get_transport2 (mu_stream_t stream, mu_transport_t *pt, mu_transport_t *pt2) | 166 | gsasl_encoder_stream (mu_stream_t *pstr, mu_stream_t transport, |
167 | Gsasl_session *ctx, int flags) | ||
217 | { | 168 | { |
218 | struct _gsasl_stream *s = mu_stream_get_owner (stream); | 169 | int rc; |
219 | *pt2 = NULL; /* FIXME 1 */ | 170 | struct _mu_gsasl_filter *flt = calloc (1, sizeof (*flt)); |
220 | *pt = (mu_transport_t) s->stream; | 171 | flt->sess_ctx = ctx; |
221 | return 0; | 172 | rc = mu_filter_stream_create (pstr, transport, |
173 | MU_FILTER_ENCODE, | ||
174 | _gsasl_encoder, | ||
175 | flt, flags); | ||
176 | if (rc == 0) | ||
177 | mu_stream_set_buffer (*pstr, mu_buffer_line, 1024); | ||
178 | return rc; | ||
222 | } | 179 | } |
223 | 180 | ||
224 | int | 181 | int |
225 | _gsasl_wait (mu_stream_t stream, int *pflags, struct timeval *tvp) | 182 | gsasl_decoder_stream (mu_stream_t *pstr, mu_stream_t transport, |
183 | Gsasl_session *ctx, int flags) | ||
226 | { | 184 | { |
227 | int flags; | 185 | int rc; |
228 | struct _gsasl_stream *s = mu_stream_get_owner (stream); | 186 | struct _mu_gsasl_filter *flt = calloc (1, sizeof (*flt)); |
229 | 187 | flt->sess_ctx = ctx; | |
230 | mu_stream_get_flags (stream, &flags); | 188 | rc = mu_filter_stream_create (pstr, transport, |
231 | if (((*pflags & MU_STREAM_READY_RD) && !(flags & MU_STREAM_READ)) | 189 | MU_FILTER_DECODE, |
232 | || ((*pflags & MU_STREAM_READY_WR) && !(flags & MU_STREAM_WRITE))) | 190 | _gsasl_decoder, |
233 | return EINVAL; | 191 | flt, flags); |
234 | return mu_stream_wait (s->stream, pflags, tvp); | 192 | if (rc == 0) |
193 | mu_stream_set_buffer (*pstr, mu_buffer_line, 1024); | ||
194 | return rc; | ||
235 | } | 195 | } |
236 | 196 | ||
237 | int | 197 | int |
238 | mu_gsasl_stream_create (mu_stream_t *stream, mu_stream_t transport, | 198 | mu_gsasl_stream_create (mu_stream_t *stream, mu_stream_t transport, |
239 | Gsasl_session *ctx, int flags) | 199 | Gsasl_session *ctx, int flags) |
240 | { | 200 | { |
241 | struct _gsasl_stream *s; | ||
242 | int rc; | 201 | int rc; |
243 | 202 | mu_stream_t in, out; | |
203 | |||
244 | if (stream == NULL) | 204 | if (stream == NULL) |
245 | return MU_ERR_OUT_PTR_NULL; | 205 | return MU_ERR_OUT_PTR_NULL; |
246 | 206 | rc = gsasl_encoder_stream (&in, transport, ctx, MU_STREAM_READ); | |
247 | if ((flags & ~(MU_STREAM_READ|MU_STREAM_WRITE)) | 207 | if (rc) |
248 | || (flags & (MU_STREAM_READ|MU_STREAM_WRITE)) == | 208 | return rc; |
249 | (MU_STREAM_READ|MU_STREAM_WRITE)) | 209 | rc = gsasl_encoder_stream (&out, transport, ctx, MU_STREAM_WRITE); |
250 | return EINVAL; | ||
251 | |||
252 | s = calloc (1, sizeof (*s)); | ||
253 | if (s == NULL) | ||
254 | return ENOMEM; | ||
255 | |||
256 | s->stream = transport; | ||
257 | s->sess_ctx = ctx; | ||
258 | |||
259 | rc = mu_stream_create (stream, flags, s); | ||
260 | if (rc) | 210 | if (rc) |
261 | { | 211 | { |
262 | free (s); | 212 | mu_stream_destroy (&in); |
263 | return rc; | 213 | return rc; |
264 | } | 214 | } |
265 | 215 | rc = mu_iostream_create (stream, in, out); | |
266 | mu_stream_set_open (*stream, _gsasl_open, s); | 216 | mu_stream_unref (in); |
267 | mu_stream_set_close (*stream, _gsasl_close, s); | 217 | mu_stream_unref (out); |
268 | mu_stream_set_flush (*stream, _gsasl_flush, s); | 218 | return rc; |
269 | mu_stream_set_destroy (*stream, _gsasl_destroy, s); | ||
270 | mu_stream_set_strerror (*stream, _gsasl_strerror, s); | ||
271 | mu_stream_set_wait (*stream, _gsasl_wait, s); | ||
272 | mu_stream_set_get_transport2 (*stream, _gsasl_get_transport2, s); | ||
273 | if (flags & MU_STREAM_READ) | ||
274 | mu_stream_set_readline (*stream, _gsasl_readline, s); | ||
275 | else | ||
276 | mu_stream_set_write (*stream, _gsasl_write, s); | ||
277 | |||
278 | _auth_lb_create (&s->lb); | ||
279 | |||
280 | return 0; | ||
281 | } | 219 | } |
282 | 220 | ||
283 | #endif | 221 | #endif | ... | ... |
libmu_auth/lbuf.c
deleted
100644 → 0
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2003, 2007, 2010 Free Software Foundation, Inc. | ||
3 | |||
4 | This library is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU Lesser General Public | ||
6 | License as published by the Free Software Foundation; either | ||
7 | version 3 of the License, or (at your option) any later version. | ||
8 | |||
9 | This library is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General | ||
15 | Public License along with this library; if not, write to the | ||
16 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
17 | Boston, MA 02110-1301 USA */ | ||
18 | |||
19 | #ifdef HAVE_CONFIG_H | ||
20 | # include <config.h> | ||
21 | #endif | ||
22 | #include <stdlib.h> | ||
23 | #include <string.h> | ||
24 | #include <errno.h> | ||
25 | #include <sys/types.h> | ||
26 | #include <lbuf.h> | ||
27 | |||
28 | struct _line_buffer { | ||
29 | char *buffer; /* Line buffer */ | ||
30 | size_t size; /* Allocated size */ | ||
31 | size_t level; /* Current filling level */ | ||
32 | }; | ||
33 | |||
34 | int | ||
35 | _auth_lb_create (struct _line_buffer **s) | ||
36 | { | ||
37 | *s = malloc (sizeof (**s)); | ||
38 | if (!*s) | ||
39 | return ENOMEM; | ||
40 | (*s)->buffer = NULL; | ||
41 | (*s)->size = 0; | ||
42 | (*s)->level = 0; | ||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | void | ||
47 | _auth_lb_destroy (struct _line_buffer **s) | ||
48 | { | ||
49 | if (s && *s) | ||
50 | { | ||
51 | free ((*s)->buffer); | ||
52 | free (*s); | ||
53 | *s = NULL; | ||
54 | } | ||
55 | } | ||
56 | |||
57 | void | ||
58 | _auth_lb_drop (struct _line_buffer *s) | ||
59 | { | ||
60 | s->level = 0; | ||
61 | } | ||
62 | |||
63 | int | ||
64 | _auth_lb_grow (struct _line_buffer *s, const char *ptr, size_t size) | ||
65 | { | ||
66 | if (!s->buffer) | ||
67 | { | ||
68 | s->buffer = malloc (size); | ||
69 | s->size = size; | ||
70 | s->level = 0; | ||
71 | } | ||
72 | else if (s->size - s->level < size) | ||
73 | { | ||
74 | size_t newsize = s->size + size; | ||
75 | s->buffer = realloc (s->buffer, newsize); | ||
76 | if (s->buffer) | ||
77 | s->size = newsize; | ||
78 | } | ||
79 | |||
80 | if (!s->buffer) | ||
81 | return ENOMEM; | ||
82 | |||
83 | memcpy (s->buffer + s->level, ptr, size); | ||
84 | s->level += size; | ||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | int | ||
89 | _auth_lb_read (struct _line_buffer *s, char *optr, size_t osize) | ||
90 | { | ||
91 | int len; | ||
92 | |||
93 | len = s->level > osize ? osize : s->level; | ||
94 | memcpy (optr, s->buffer, len); | ||
95 | if (s->level > len) | ||
96 | { | ||
97 | memmove (s->buffer, s->buffer + len, s->level - len); | ||
98 | s->level -= len; | ||
99 | } | ||
100 | else if (s->level == len) | ||
101 | s->level = 0; | ||
102 | |||
103 | return len; | ||
104 | } | ||
105 | |||
106 | int | ||
107 | _auth_lb_readline (struct _line_buffer *s, char *ptr, size_t size) | ||
108 | { | ||
109 | char *p = strchr (s->buffer, '\n'); | ||
110 | |||
111 | if (p && p - s->buffer + 1 < size) | ||
112 | size = p - s->buffer + 1; | ||
113 | return _auth_lb_read (s, ptr, size); | ||
114 | } | ||
115 | |||
116 | int | ||
117 | _auth_lb_writelines (struct _line_buffer *s, const char *iptr, size_t isize, | ||
118 | off_t offset, | ||
119 | int (*wr) (void *data, char *start, char *end), | ||
120 | void *data, | ||
121 | size_t *nbytes) | ||
122 | { | ||
123 | if (s->level > 2) | ||
124 | { | ||
125 | char *start, *end; | ||
126 | |||
127 | for (start = s->buffer, | ||
128 | end = memchr (start, '\n', s->buffer + s->level - start); | ||
129 | end && end < s->buffer + s->level; | ||
130 | start = end + 1, | ||
131 | end = memchr (start, '\n', s->buffer + s->level - start)) | ||
132 | if (end[-1] == '\r') | ||
133 | { | ||
134 | int rc = wr (data, start, end); | ||
135 | if (rc) | ||
136 | return rc; | ||
137 | } | ||
138 | |||
139 | if (start > s->buffer) | ||
140 | { | ||
141 | if (start < s->buffer + s->level) | ||
142 | { | ||
143 | int rest = s->buffer + s->level - start; | ||
144 | memmove (s->buffer, start, rest); | ||
145 | s->level = rest; | ||
146 | } | ||
147 | else | ||
148 | s->level = 0; | ||
149 | } | ||
150 | } | ||
151 | |||
152 | if (nbytes) | ||
153 | *nbytes = isize; | ||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | int | ||
158 | _auth_lb_level (struct _line_buffer *s) | ||
159 | { | ||
160 | return s->level; | ||
161 | } | ||
162 | |||
163 | char * | ||
164 | _auth_lb_data (struct _line_buffer *s) | ||
165 | { | ||
166 | return s->buffer; | ||
167 | } |
libmu_auth/lbuf.h
deleted
100644 → 0
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2003, 2005, 2007, 2010 Free Software Foundation, Inc. | ||
3 | |||
4 | This library is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU Lesser General Public | ||
6 | License as published by the Free Software Foundation; either | ||
7 | version 3 of the License, or (at your option) any later version. | ||
8 | |||
9 | This library is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General | ||
15 | Public License along with this library; if not, write to the | ||
16 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
17 | Boston, MA 02110-1301 USA */ | ||
18 | |||
19 | #include <mailutils/types.h> | ||
20 | |||
21 | struct _line_buffer; | ||
22 | |||
23 | int _auth_lb_create (struct _line_buffer **s); | ||
24 | void _auth_lb_destroy (struct _line_buffer **s); | ||
25 | void _auth_lb_drop (struct _line_buffer *s); | ||
26 | |||
27 | int _auth_lb_grow (struct _line_buffer *s, const char *ptr, size_t size); | ||
28 | int _auth_lb_read (struct _line_buffer *s, char *ptr, size_t size); | ||
29 | int _auth_lb_readline (struct _line_buffer *s, char *ptr, size_t size); | ||
30 | int _auth_lb_writelines (struct _line_buffer *s, const char *iptr, | ||
31 | size_t isize, off_t offset, | ||
32 | int (*wr) (void *data, char *start, char *end), | ||
33 | void *data, size_t *nbytes); | ||
34 | int _auth_lb_level (struct _line_buffer *s); | ||
35 | char *_auth_lb_data (struct _line_buffer *s); | ||
36 | |||
37 |
... | @@ -176,7 +176,6 @@ _xscript_ctl (struct _mu_stream *str, int op, void *arg) | ... | @@ -176,7 +176,6 @@ _xscript_ctl (struct _mu_stream *str, int op, void *arg) |
176 | { | 176 | { |
177 | struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str; | 177 | struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str; |
178 | mu_transport_t *ptrans; | 178 | mu_transport_t *ptrans; |
179 | mu_stream_t strtab[2]; | ||
180 | 179 | ||
181 | switch (op) | 180 | switch (op) |
182 | { | 181 | { | ... | ... |
-
Please register or sign in to post a comment