Commit ea8b0398 ea8b03988a4717c9ed6323755a625e4921812218 by Sergey Poznyakoff

(create_gsasl_stream,gsasl_replace_streams): Fixed declarations.

(auth_step_base64): New function. A wrapper around
gsasl_server_step_base64 to cope with GSASL_TOO_SMALL_BUFFER
error code.
(auth_gsasl): Use auth_step_base64(). Output any surplus
data returned with GSASL_OK code (proposed by Simon Josefsson
<jas@extundo.com>)
1 parent e64792a0
...@@ -22,12 +22,14 @@ ...@@ -22,12 +22,14 @@
22 static Gsasl_ctx *ctx; 22 static Gsasl_ctx *ctx;
23 static Gsasl_session_ctx *sess_ctx; 23 static Gsasl_session_ctx *sess_ctx;
24 24
25 static void auth_gsasl_capa_init __P((int disable));
26
25 static int 27 static int
26 create_gsasl_stream (stream_t *newstr, stream_t str, int flags) 28 create_gsasl_stream (stream_t *newstr, int fd, int flags)
27 { 29 {
28 int rc; 30 int rc;
29 31
30 rc = gsasl_stream_create (newstr, str, sess_ctx, flags); 32 rc = gsasl_stream_create (newstr, fd, sess_ctx, flags);
31 if (rc) 33 if (rc)
32 { 34 {
33 syslog (LOG_ERR, _("cannot create SASL stream: %s"), 35 syslog (LOG_ERR, _("cannot create SASL stream: %s"),
...@@ -47,7 +49,7 @@ create_gsasl_stream (stream_t *newstr, stream_t str, int flags) ...@@ -47,7 +49,7 @@ create_gsasl_stream (stream_t *newstr, stream_t str, int flags)
47 return RESP_OK; 49 return RESP_OK;
48 } 50 }
49 51
50 void 52 int
51 gsasl_replace_streams (void *self, void *data) 53 gsasl_replace_streams (void *self, void *data)
52 { 54 {
53 stream_t *s = data; 55 stream_t *s = data;
...@@ -60,13 +62,36 @@ gsasl_replace_streams (void *self, void *data) ...@@ -60,13 +62,36 @@ gsasl_replace_streams (void *self, void *data)
60 return 0; 62 return 0;
61 } 63 }
62 64
65 #define AUTHBUFSIZE 512
66
67 static int
68 auth_step_base64(Gsasl_session_ctx *sess_ctx, char *input,
69 char **output, size_t *output_len)
70 {
71 int rc;
72
73 while (1)
74 {
75 rc = gsasl_server_step_base64 (sess_ctx, input, *output, *output_len);
76
77 if (rc == GSASL_TOO_SMALL_BUFFER)
78 {
79 *output_len += AUTHBUFSIZE;
80 *output = realloc(*output, *output_len);
81 if (output)
82 continue;
83 }
84 break;
85 }
86 return rc;
87 }
63 88
64 static int 89 static int
65 auth_gsasl (struct imap4d_command *command, 90 auth_gsasl (struct imap4d_command *command,
66 char *auth_type, char *arg, char **username) 91 char *auth_type, char *arg, char **username)
67 { 92 {
68 char *input = NULL; 93 char *input = NULL;
69 char output[512]; 94 char *output;
70 size_t output_len; 95 size_t output_len;
71 char *s; 96 char *s;
72 int rc; 97 int rc;
...@@ -84,22 +109,33 @@ auth_gsasl (struct imap4d_command *command, ...@@ -84,22 +109,33 @@ auth_gsasl (struct imap4d_command *command,
84 109
85 gsasl_server_application_data_set (sess_ctx, username); 110 gsasl_server_application_data_set (sess_ctx, username);
86 111
112 output_len = AUTHBUFSIZE;
113 output = malloc (output_len);
114 if (!output)
115 imap4d_bye (ERR_NO_MEM);
116
87 output[0] = '\0'; 117 output[0] = '\0';
88 output_len = sizeof (output);
89 118
90 while ((rc = gsasl_server_step_base64 (sess_ctx, input, output, output_len)) 119 while ((rc = auth_step_base64 (sess_ctx, input, &output, &output_len))
91 == GSASL_NEEDS_MORE) 120 == GSASL_NEEDS_MORE)
92 { 121 {
93 util_send ("+ %s\r\n", output); 122 util_send ("+ %s\r\n", output);
94 input = imap4d_readline_ex (); 123 input = imap4d_readline_ex ();
95 } 124 }
96 125
97 if (rc != GSASL_OK) 126 if (rc != GSASL_OK)
98 { 127 {
99 syslog (LOG_NOTICE, _("GSASL error: %s"), gsasl_strerror (rc)); 128 syslog (LOG_NOTICE, _("GSASL error: %s"), gsasl_strerror (rc));
129 free (output);
100 return RESP_NO; 130 return RESP_NO;
101 } 131 }
102 132
133 /* Some SASL mechanisms output data when GSASL_OK is returned */
134 if (output[0])
135 util_send ("+ %s\r\n", output);
136
137 free (output);
138
103 if (*username == NULL) 139 if (*username == NULL)
104 { 140 {
105 syslog (LOG_NOTICE, _("GSASL %s: cannot get username"), auth_type); 141 syslog (LOG_NOTICE, _("GSASL %s: cannot get username"), auth_type);
......