Commit 02abfc44 02abfc4419cc651df0005a065f0db781dc884594 by Sergey Poznyakoff

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.
1 parent b5986a2d
...@@ -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\
......
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
...@@ -26,8 +26,6 @@ lib_LTLIBRARIES = libmu_auth.la ...@@ -26,8 +26,6 @@ lib_LTLIBRARIES = libmu_auth.la
26 26
27 libmu_auth_la_SOURCES = \ 27 libmu_auth_la_SOURCES = \
28 gsasl.c\ 28 gsasl.c\
29 lbuf.c\
30 lbuf.h\
31 ldap.c\ 29 ldap.c\
32 pam.c\ 30 pam.c\
33 radius.c\ 31 radius.c\
......
...@@ -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
......
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 }
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 {
......