17 |
|
|
18 |
#include "imap4d.h" |
#include "imap4d.h" |
19 |
|
|
20 |
static FILE *ifile; |
static stream_t istream; |
21 |
static FILE *ofile; |
static stream_t ostream; |
|
#ifdef WITH_TLS |
|
|
static gnutls_session sfile; |
|
|
#endif /* WITH_TLS */ |
|
22 |
|
|
23 |
static int add2set __P ((size_t **, int *, unsigned long)); |
static int add2set __P ((size_t **, int *, unsigned long)); |
24 |
static const char *sc2string __P ((int)); |
static const char *sc2string __P ((int)); |
315 |
return 0; |
return 0; |
316 |
} |
} |
317 |
|
|
|
static int |
|
|
util_send_lowlevel (char *buf) |
|
|
{ |
|
|
int status; |
|
|
|
|
|
if (buf) |
|
|
{ |
|
|
#ifdef WITH_TLS |
|
|
if (tls_done) |
|
|
status = gnutls_record_send (sfile, buf, strlen (buf)); |
|
|
else |
|
|
#endif /* WITH_TLS */ |
|
|
status = fprintf (ofile, buf); |
|
|
} |
|
|
|
|
|
return status; |
|
|
} |
|
|
|
|
318 |
int |
int |
319 |
util_send (const char *format, ...) |
util_send (const char *format, ...) |
320 |
{ |
{ |
324 |
|
|
325 |
va_start (ap, format); |
va_start (ap, format); |
326 |
vasprintf (&buf, format, ap); |
vasprintf (&buf, format, ap); |
327 |
|
va_end (ap); |
328 |
|
if (!buf) |
329 |
|
imap4d_bye (ERR_NO_MEM); |
330 |
|
|
331 |
if (buf) |
if (daemon_param.transcript) |
332 |
{ |
syslog (LOG_DEBUG, "sent: %s", buf); |
|
if (daemon_param.transcript) |
|
|
syslog (LOG_DEBUG, "sent: %s", buf); |
|
333 |
|
|
334 |
status = util_send_lowlevel (buf); |
status = stream_sequential_write (ostream, buf, strlen (buf)); |
335 |
free (buf); |
free (buf); |
|
} |
|
336 |
|
|
|
va_end (ap); |
|
337 |
return status; |
return status; |
338 |
} |
} |
339 |
|
|
378 |
asprintf (&tempbuf, "* %s%s\r\n", sc2string (rc), format); |
asprintf (&tempbuf, "* %s%s\r\n", sc2string (rc), format); |
379 |
va_start (ap, format); |
va_start (ap, format); |
380 |
vasprintf (&buf, tempbuf, ap); |
vasprintf (&buf, tempbuf, ap); |
381 |
|
va_end (ap); |
382 |
|
if (!buf) |
383 |
|
imap4d_bye (ERR_NO_MEM); |
384 |
|
|
385 |
if (buf) |
if (daemon_param.transcript) |
386 |
{ |
syslog (LOG_DEBUG, "sent: %s", buf); |
|
if (daemon_param.transcript) |
|
|
syslog (LOG_DEBUG, "sent: %s", buf); |
|
|
|
|
|
status = util_send_lowlevel (buf); |
|
|
free (buf); |
|
|
} |
|
387 |
|
|
388 |
va_end (ap); |
status = stream_sequential_write (ostream, buf, strlen (buf)); |
389 |
|
free (buf); |
390 |
free (tempbuf); |
free (tempbuf); |
391 |
return status; |
return status; |
392 |
} |
} |
405 |
command->name, format); |
command->name, format); |
406 |
va_start (ap, format); |
va_start (ap, format); |
407 |
vasprintf (&buf, tempbuf, ap); |
vasprintf (&buf, tempbuf, ap); |
408 |
|
va_end (ap); |
409 |
|
if (!buf) |
410 |
|
imap4d_bye (ERR_NO_MEM); |
411 |
|
|
412 |
if (buf) |
if (daemon_param.transcript) |
413 |
{ |
syslog (LOG_DEBUG, "sent: %s", buf); |
|
if (daemon_param.transcript) |
|
|
syslog (LOG_DEBUG, "sent: %s", buf); |
|
|
|
|
|
status = util_send_lowlevel (buf); |
|
|
free (buf); |
|
|
} |
|
414 |
|
|
415 |
va_end (ap); |
status = stream_sequential_write (ostream, buf, strlen (buf)); |
416 |
|
free (buf); |
417 |
free (tempbuf); |
free (tempbuf); |
418 |
|
|
419 |
/* Reset the state. */ |
/* Reset the state. */ |
451 |
line[0] = '\0'; /* start with a empty string. */ |
line[0] = '\0'; /* start with a empty string. */ |
452 |
do |
do |
453 |
{ |
{ |
454 |
|
size_t sz; |
455 |
|
int rc; |
456 |
|
|
457 |
alarm (daemon_param.timeout); |
alarm (daemon_param.timeout); |
458 |
#ifdef WITH_TLS |
rc = stream_sequential_readline (istream, buffer, sizeof (buffer), &sz); |
459 |
if (tls_done) |
if (sz == 0) |
460 |
{ |
{ |
461 |
len = gnutls_record_recv (sfile, buffer, sizeof (buffer) - 1); |
syslog (LOG_INFO, _("unexpected eof on input")); |
462 |
if (len < 0) |
imap4d_bye (ERR_NO_OFILE); |
|
{ |
|
|
syslog (LOG_INFO, _("TLS error on read: %s"), |
|
|
gnutls_strerror (len)); |
|
|
imap4d_bye (ERR_TLS); |
|
|
} |
|
|
else |
|
|
buffer[len] = 0; |
|
463 |
} |
} |
464 |
else |
else if (rc) |
|
#endif /* WITH_TLS */ |
|
|
if (fgets (buffer, sizeof (buffer), ifile) == NULL) |
|
465 |
{ |
{ |
466 |
if (feof (ifile)) |
const char *p; |
467 |
syslog (LOG_INFO, _("unexpected eof on input")); |
if (stream_strerror (istream, &p)) |
468 |
else if (errno) |
p = strerror (errno); |
469 |
syslog (LOG_INFO, _("error reading from input file: %m")); |
|
470 |
else |
syslog (LOG_INFO, _("error reading from input file: %s"), p); |
|
continue; |
|
471 |
imap4d_bye (ERR_NO_OFILE); |
imap4d_bye (ERR_NO_OFILE); |
472 |
} |
} |
473 |
alarm (0); |
alarm (0); |
766 |
} |
} |
767 |
_imap4d_attrlist[] = |
_imap4d_attrlist[] = |
768 |
{ |
{ |
769 |
{ |
{ "\\Answered", MU_ATTRIBUTE_ANSWERED }, |
770 |
"\\Answered", MU_ATTRIBUTE_ANSWERED} |
{ "\\Flagged", MU_ATTRIBUTE_FLAGGED }, |
771 |
, |
{ "\\Deleted", MU_ATTRIBUTE_DELETED }, |
772 |
{ |
{ "\\Draft", MU_ATTRIBUTE_DRAFT }, |
773 |
"\\Flagged", MU_ATTRIBUTE_FLAGGED} |
{ "\\Seen", MU_ATTRIBUTE_READ }, |
774 |
, |
{ "\\Recent", MU_ATTRIBUTE_RECENT }, |
775 |
{ |
}; |
|
"\\Deleted", MU_ATTRIBUTE_DELETED} |
|
|
, |
|
|
{ |
|
|
"\\Draft", MU_ATTRIBUTE_DRAFT} |
|
|
, |
|
|
{ |
|
|
"\\Seen", MU_ATTRIBUTE_READ} |
|
|
, |
|
|
{ |
|
|
"\\Recent", MU_ATTRIBUTE_RECENT} |
|
|
,}; |
|
776 |
|
|
777 |
#define NATTR sizeof(_imap4d_attrlist)/sizeof(_imap4d_attrlist[0]) |
#define NATTR sizeof(_imap4d_attrlist)/sizeof(_imap4d_attrlist[0]) |
778 |
|
|
1094 |
|
|
1095 |
|
|
1096 |
void |
void |
1097 |
util_setio (int infile, int outfile) |
util_setio (FILE *in, FILE *out) |
1098 |
{ |
{ |
1099 |
ifile = fdopen (infile, "r"); |
if (!out || !in) |
|
ofile = fdopen (outfile, "w"); |
|
|
if (!ofile || !ifile) |
|
1100 |
imap4d_bye (ERR_NO_OFILE); |
imap4d_bye (ERR_NO_OFILE); |
1101 |
|
|
1102 |
setvbuf (ofile, NULL, _IOLBF, 0); |
if (stdio_stream_create (&istream, in, MU_STREAM_NO_CLOSE) |
1103 |
|
|| stdio_stream_create (&ostream, out, MU_STREAM_NO_CLOSE)) |
1104 |
|
imap4d_bye (ERR_NO_OFILE); |
1105 |
} |
} |
1106 |
|
|
1107 |
void |
void |
1108 |
util_flush_output () |
util_flush_output () |
1109 |
{ |
{ |
1110 |
if (!tls_done) |
stream_flush (ostream); |
|
fflush (ofile); |
|
1111 |
} |
} |
1112 |
|
|
1113 |
FILE * |
int |
1114 |
util_is_ofile () |
util_is_master () |
1115 |
{ |
{ |
1116 |
return ofile; |
return ostream == NULL; |
1117 |
} |
} |
1118 |
|
|
1119 |
#ifdef WITH_TLS |
#ifdef WITH_TLS |
|
|
|
1120 |
int |
int |
1121 |
imap4d_init_tls_server () |
imap4d_init_tls_server () |
1122 |
{ |
{ |
1123 |
sfile = |
stream_t stream; |
1124 |
(gnutls_session) mu_init_tls_server (fileno (ifile), fileno (ofile)); |
int in_fd; |
1125 |
if (!sfile) |
int out_fd; |
1126 |
|
int rc; |
1127 |
|
|
1128 |
|
if (stream_get_fd (istream, &in_fd) |
1129 |
|
|| stream_get_fd (ostream, &out_fd)) |
1130 |
|
return 0; |
1131 |
|
rc = tls_stream_create (&stream, in_fd, out_fd, 0); |
1132 |
|
if (rc) |
1133 |
return 0; |
return 0; |
1134 |
|
|
1135 |
|
if (stream_open (stream)) |
1136 |
|
{ |
1137 |
|
const char *p; |
1138 |
|
stream_strerror (stream, &p); |
1139 |
|
syslog (LOG_ERR, _("cannot open TLS stream: %s"), p); |
1140 |
|
return 0; |
1141 |
|
} |
1142 |
|
|
1143 |
|
stream_destroy (&istream, stream_get_owner (istream)); |
1144 |
|
stream_destroy (&ostream, stream_get_owner (ostream)); |
1145 |
|
istream = ostream = stream; |
1146 |
return 1; |
return 1; |
1147 |
} |
} |
1148 |
|
#endif /* WITH_TLS */ |
1149 |
|
|
1150 |
void |
void |
1151 |
imap4d_deinit_tls_server () |
util_bye () |
1152 |
{ |
{ |
1153 |
mu_deinit_tls_server (sfile); |
if (istream == ostream) |
1154 |
|
{ |
1155 |
|
stream_close (istream); |
1156 |
|
stream_destroy (&istream, stream_get_owner (istream)); |
1157 |
|
} |
1158 |
|
/* There's no reason closing in/out streams otherwise */ |
1159 |
|
#ifdef WITH_TLS |
1160 |
|
mu_deinit_tls_libs (); |
1161 |
|
#endif /* WITH_TLS */ |
1162 |
} |
} |
1163 |
|
|
1164 |
#endif /* WITH_TLS */ |
|
1165 |
|
|
1166 |
|
|