drv_imap.c 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819
  1. /*
  2. * mbsync - mailbox synchronizer
  3. * Copyright (C) 2000-2002 Michael R. Elkins <me@mutt.org>
  4. * Copyright (C) 2002-2004 Oswald Buddenhagen <ossi@users.sf.net>
  5. * Copyright (C) 2004 Theodore Y. Ts'o <tytso@mit.edu>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. *
  21. * As a special exception, mbsync may be linked with the OpenSSL library,
  22. * despite that library's more restrictive license.
  23. */
  24. #include "isync.h"
  25. #include <assert.h>
  26. #include <unistd.h>
  27. #include <sys/mman.h>
  28. #include <sys/time.h>
  29. #include <stdlib.h>
  30. #include <stdio.h>
  31. #include <stddef.h>
  32. #include <errno.h>
  33. #include <string.h>
  34. #include <ctype.h>
  35. #include <sys/socket.h>
  36. #include <sys/ioctl.h>
  37. #include <netinet/in.h>
  38. #include <netinet/tcp.h>
  39. #include <arpa/inet.h>
  40. #include <netdb.h>
  41. #if HAVE_LIBSSL
  42. # include <openssl/ssl.h>
  43. # include <openssl/err.h>
  44. # include <openssl/hmac.h>
  45. #endif
  46. typedef struct imap_server_conf {
  47. struct imap_server_conf *next;
  48. char *name;
  49. char *tunnel;
  50. char *host;
  51. int port;
  52. char *user;
  53. char *pass;
  54. #if HAVE_LIBSSL
  55. char *cert_file;
  56. unsigned use_imaps:1;
  57. unsigned require_ssl:1;
  58. unsigned use_sslv2:1;
  59. unsigned use_sslv3:1;
  60. unsigned use_tlsv1:1;
  61. unsigned require_cram:1;
  62. #endif
  63. } imap_server_conf_t;
  64. typedef struct imap_store_conf {
  65. store_conf_t gen;
  66. imap_server_conf_t *server;
  67. unsigned use_namespace:1;
  68. } imap_store_conf_t;
  69. typedef struct imap_message {
  70. message_t gen;
  71. /* int seq; will be needed when expunges are tracked */
  72. } imap_message_t;
  73. #define NIL (void*)0x1
  74. #define LIST (void*)0x2
  75. typedef struct _list {
  76. struct _list *next, *child;
  77. char *val;
  78. int len;
  79. } list_t;
  80. typedef struct {
  81. int fd;
  82. #if HAVE_LIBSSL
  83. SSL *ssl;
  84. unsigned int use_ssl:1;
  85. #endif
  86. } Socket_t;
  87. typedef struct {
  88. Socket_t sock;
  89. int bytes;
  90. int offset;
  91. char buf[1024];
  92. } buffer_t;
  93. struct imap_cmd;
  94. #define max_in_progress 50 /* make this configurable? */
  95. typedef struct imap {
  96. int uidnext; /* from SELECT responses */
  97. list_t *ns_personal, *ns_other, *ns_shared; /* NAMESPACE info */
  98. string_list_t *boxes; /* LIST results */
  99. message_t **msgapp; /* FETCH results */
  100. unsigned caps, rcaps; /* CAPABILITY results */
  101. /* command queue */
  102. int nexttag, num_in_progress, literal_pending;
  103. struct imap_cmd *in_progress, **in_progress_append;
  104. #if HAVE_LIBSSL
  105. SSL_CTX *SSLContext;
  106. #endif
  107. buffer_t buf; /* this is BIG, so put it last */
  108. } imap_t;
  109. typedef struct imap_store {
  110. store_t gen;
  111. imap_t *imap;
  112. const char *prefix;
  113. unsigned /*currentnc:1,*/ trashnc:1;
  114. } imap_store_t;
  115. struct imap_cmd_cb {
  116. int (*cont)( imap_store_t *ctx, struct imap_cmd *cmd, const char *prompt );
  117. void (*done)( imap_store_t *ctx, struct imap_cmd *cmd, int response);
  118. void *ctx;
  119. char *data;
  120. int dlen;
  121. int uid;
  122. unsigned create:1, trycreate:1;
  123. };
  124. struct imap_cmd {
  125. struct imap_cmd *next;
  126. struct imap_cmd_cb cb;
  127. char *cmd;
  128. int tag;
  129. };
  130. #define CAP(cap) (imap->caps & (1 << (cap)))
  131. enum CAPABILITY {
  132. NOLOGIN = 0,
  133. UIDPLUS,
  134. LITERALPLUS,
  135. NAMESPACE,
  136. #if HAVE_LIBSSL
  137. CRAM,
  138. STARTTLS,
  139. #endif
  140. };
  141. static const char *cap_list[] = {
  142. "LOGINDISABLED",
  143. "UIDPLUS",
  144. "LITERAL+",
  145. "NAMESPACE",
  146. #if HAVE_LIBSSL
  147. "AUTH=CRAM-MD5",
  148. "STARTTLS",
  149. #endif
  150. };
  151. #define RESP_OK 0
  152. #define RESP_NO 1
  153. #define RESP_BAD 2
  154. static int get_cmd_result( imap_store_t *ctx, struct imap_cmd *tcmd );
  155. static const char *Flags[] = {
  156. "Draft",
  157. "Flagged",
  158. "Answered",
  159. "Seen",
  160. "Deleted",
  161. };
  162. #if HAVE_LIBSSL
  163. /* this gets called when a certificate is to be verified */
  164. static int
  165. verify_cert( SSL *ssl )
  166. {
  167. X509 *cert;
  168. int err;
  169. char buf[256];
  170. int ret = -1;
  171. BIO *bio;
  172. cert = SSL_get_peer_certificate( ssl );
  173. if (!cert) {
  174. fprintf( stderr, "Error, no server certificate\n" );
  175. return -1;
  176. }
  177. err = SSL_get_verify_result( ssl );
  178. if (err == X509_V_OK)
  179. return 0;
  180. fprintf( stderr, "Error, can't verify certificate: %s (%d)\n",
  181. X509_verify_cert_error_string(err), err );
  182. X509_NAME_oneline( X509_get_subject_name( cert ), buf, sizeof(buf) );
  183. info( "\nSubject: %s\n", buf );
  184. X509_NAME_oneline( X509_get_issuer_name( cert ), buf, sizeof(buf) );
  185. info( "Issuer: %s\n", buf );
  186. bio = BIO_new( BIO_s_mem() );
  187. ASN1_TIME_print( bio, X509_get_notBefore( cert ) );
  188. memset( buf, 0, sizeof(buf) );
  189. BIO_read( bio, buf, sizeof(buf) - 1 );
  190. info( "Valid from: %s\n", buf );
  191. ASN1_TIME_print( bio, X509_get_notAfter( cert ) );
  192. memset( buf, 0, sizeof(buf) );
  193. BIO_read( bio, buf, sizeof(buf) - 1 );
  194. BIO_free( bio );
  195. info( " to: %s\n", buf );
  196. fputs( "\n*** WARNING *** There is no way to verify this certificate. It is\n"
  197. " possible that a hostile attacker has replaced the\n"
  198. " server certificate. Continue at your own risk!\n"
  199. "\nAccept this certificate anyway? [no]: ", stderr );
  200. if (fgets( buf, sizeof(buf), stdin ) && (buf[0] == 'y' || buf[0] == 'Y')) {
  201. ret = 0;
  202. fprintf( stderr, "\n*** Fine, but don't say I didn't warn you!\n\n" );
  203. }
  204. return ret;
  205. }
  206. static int
  207. init_ssl_ctx( imap_store_t *ctx )
  208. {
  209. imap_t *imap = ctx->imap;
  210. imap_store_conf_t *conf = (imap_store_conf_t *)ctx->gen.conf;
  211. imap_server_conf_t *srvc = conf->server;
  212. SSL_METHOD *method;
  213. int options = 0;
  214. if (srvc->use_tlsv1 && !srvc->use_sslv2 && !srvc->use_sslv3)
  215. method = TLSv1_client_method();
  216. else
  217. method = SSLv23_client_method();
  218. imap->SSLContext = SSL_CTX_new( method );
  219. if (!srvc->cert_file) {
  220. fprintf( stderr, "Error, CertificateFile not defined\n" );
  221. return -1;
  222. } else if (access( srvc->cert_file, R_OK ))
  223. warn( "*** Warning: can't read CertificateFile, so can't verify server certificates\n" );
  224. else if (!SSL_CTX_load_verify_locations( imap->SSLContext, srvc->cert_file, NULL )) {
  225. fprintf( stderr, "Error, SSL_CTX_load_verify_locations: %s\n",
  226. ERR_error_string( ERR_get_error(), 0 ) );
  227. return -1;
  228. }
  229. if (!srvc->use_sslv2)
  230. options |= SSL_OP_NO_SSLv2;
  231. if (!srvc->use_sslv3)
  232. options |= SSL_OP_NO_SSLv3;
  233. if (!srvc->use_tlsv1)
  234. options |= SSL_OP_NO_TLSv1;
  235. SSL_CTX_set_options( imap->SSLContext, options );
  236. /* we check the result of the verification after SSL_connect() */
  237. SSL_CTX_set_verify( imap->SSLContext, SSL_VERIFY_NONE, 0 );
  238. return 0;
  239. }
  240. #endif /* HAVE_LIBSSL */
  241. static void
  242. socket_perror( const char *func, Socket_t *sock, int ret )
  243. {
  244. #if HAVE_LIBSSL
  245. int err;
  246. if (sock->use_ssl) {
  247. switch ((err = SSL_get_error( sock->ssl, ret ))) {
  248. case SSL_ERROR_SYSCALL:
  249. case SSL_ERROR_SSL:
  250. if ((err = ERR_get_error()) == 0) {
  251. if (ret == 0)
  252. fprintf( stderr, "SSL_%s:got EOF\n", func );
  253. else
  254. fprintf( stderr, "SSL_%s:%d:%s\n", func, errno, strerror(errno) );
  255. } else
  256. fprintf( stderr, "SSL_%s:%d:%s\n", func, err, ERR_error_string( err, 0 ) );
  257. return;
  258. default:
  259. fprintf( stderr, "SSL_%s:%d:unhandled SSL error\n", func, err );
  260. break;
  261. }
  262. return;
  263. }
  264. #else
  265. (void)sock;
  266. #endif
  267. if (ret < 0)
  268. perror( func );
  269. else
  270. fprintf( stderr, "%s: unexpected EOF\n", func );
  271. }
  272. static int
  273. socket_read( Socket_t *sock, char *buf, int len )
  274. {
  275. int n =
  276. #if HAVE_LIBSSL
  277. sock->use_ssl ? SSL_read( sock->ssl, buf, len ) :
  278. #endif
  279. read( sock->fd, buf, len );
  280. if (n <= 0) {
  281. socket_perror( "read", sock, n );
  282. close( sock->fd );
  283. sock->fd = -1;
  284. }
  285. return n;
  286. }
  287. static int
  288. socket_write( Socket_t *sock, char *buf, int len )
  289. {
  290. int n =
  291. #if HAVE_LIBSSL
  292. sock->use_ssl ? SSL_write( sock->ssl, buf, len ) :
  293. #endif
  294. write( sock->fd, buf, len );
  295. if (n != len) {
  296. socket_perror( "write", sock, n );
  297. close( sock->fd );
  298. sock->fd = -1;
  299. }
  300. return n;
  301. }
  302. static int
  303. socket_pending( Socket_t *sock )
  304. {
  305. int num = -1;
  306. if (ioctl( sock->fd, FIONREAD, &num ) < 0)
  307. return -1;
  308. if (num > 0)
  309. return num;
  310. #if HAVE_LIBSSL
  311. if (sock->use_ssl)
  312. return SSL_pending( sock->ssl );
  313. #endif
  314. return 0;
  315. }
  316. /* simple line buffering */
  317. static int
  318. buffer_gets( buffer_t * b, char **s )
  319. {
  320. int n;
  321. int start = b->offset;
  322. *s = b->buf + start;
  323. for (;;) {
  324. /* make sure we have enough data to read the \r\n sequence */
  325. if (b->offset + 1 >= b->bytes) {
  326. if (start) {
  327. /* shift down used bytes */
  328. *s = b->buf;
  329. assert( start <= b->bytes );
  330. n = b->bytes - start;
  331. if (n)
  332. memcpy( b->buf, b->buf + start, n );
  333. b->offset -= start;
  334. b->bytes = n;
  335. start = 0;
  336. }
  337. n = socket_read( &b->sock, b->buf + b->bytes,
  338. sizeof(b->buf) - b->bytes );
  339. if (n <= 0)
  340. return -1;
  341. b->bytes += n;
  342. }
  343. if (b->buf[b->offset] == '\r') {
  344. assert( b->offset + 1 < b->bytes );
  345. if (b->buf[b->offset + 1] == '\n') {
  346. b->buf[b->offset] = 0; /* terminate the string */
  347. b->offset += 2; /* next line */
  348. if (Verbose)
  349. puts( *s );
  350. return 0;
  351. }
  352. }
  353. b->offset++;
  354. }
  355. /* not reached */
  356. }
  357. static struct imap_cmd *
  358. v_issue_imap_cmd( imap_store_t *ctx, struct imap_cmd_cb *cb,
  359. const char *fmt, va_list ap )
  360. {
  361. imap_t *imap = ctx->imap;
  362. struct imap_cmd *cmd;
  363. int n, bufl;
  364. char buf[1024];
  365. cmd = nfmalloc( sizeof(struct imap_cmd) );
  366. nfvasprintf( &cmd->cmd, fmt, ap );
  367. cmd->tag = ++imap->nexttag;
  368. if (cb)
  369. cmd->cb = *cb;
  370. else
  371. memset( &cmd->cb, 0, sizeof(cmd->cb) );
  372. while (imap->literal_pending)
  373. get_cmd_result( ctx, 0 );
  374. bufl = nfsnprintf( buf, sizeof(buf), cmd->cb.data ? CAP(LITERALPLUS) ?
  375. "%d %s{%d+}\r\n" : "%d %s{%d}\r\n" : "%d %s\r\n",
  376. cmd->tag, cmd->cmd, cmd->cb.dlen );
  377. if (Verbose) {
  378. if (imap->num_in_progress)
  379. printf( "(%d in progress) ", imap->num_in_progress );
  380. if (memcmp( cmd->cmd, "LOGIN", 5 ))
  381. printf( ">>> %s", buf );
  382. else
  383. printf( ">>> %d LOGIN <user> <pass>\n", cmd->tag );
  384. }
  385. if (socket_write( &imap->buf.sock, buf, bufl ) != bufl) {
  386. free( cmd->cmd );
  387. free( cmd );
  388. if (cb && cb->data)
  389. free( cb->data );
  390. return NULL;
  391. }
  392. if (cmd->cb.data) {
  393. if (CAP(LITERALPLUS)) {
  394. n = socket_write( &imap->buf.sock, cmd->cb.data, cmd->cb.dlen );
  395. free( cmd->cb.data );
  396. if (n != cmd->cb.dlen ||
  397. (n = socket_write( &imap->buf.sock, "\r\n", 2 )) != 2)
  398. {
  399. free( cmd->cmd );
  400. free( cmd );
  401. return NULL;
  402. }
  403. cmd->cb.data = 0;
  404. } else
  405. imap->literal_pending = 1;
  406. } else if (cmd->cb.cont)
  407. imap->literal_pending = 1;
  408. cmd->next = 0;
  409. *imap->in_progress_append = cmd;
  410. imap->in_progress_append = &cmd->next;
  411. imap->num_in_progress++;
  412. return cmd;
  413. }
  414. static struct imap_cmd *
  415. issue_imap_cmd( imap_store_t *ctx, struct imap_cmd_cb *cb, const char *fmt, ... )
  416. {
  417. struct imap_cmd *ret;
  418. va_list ap;
  419. va_start( ap, fmt );
  420. ret = v_issue_imap_cmd( ctx, cb, fmt, ap );
  421. va_end( ap );
  422. return ret;
  423. }
  424. static struct imap_cmd *
  425. issue_imap_cmd_w( imap_store_t *ctx, struct imap_cmd_cb *cb, const char *fmt, ... )
  426. {
  427. imap_t *imap = ctx->imap;
  428. struct imap_cmd *ret;
  429. va_list ap;
  430. va_start( ap, fmt );
  431. ret = v_issue_imap_cmd( ctx, cb, fmt, ap );
  432. va_end( ap );
  433. while (imap->num_in_progress > max_in_progress ||
  434. socket_pending( &imap->buf.sock ))
  435. get_cmd_result( ctx, 0 );
  436. return ret;
  437. }
  438. static int
  439. imap_exec( imap_store_t *ctx, struct imap_cmd_cb *cb, const char *fmt, ... )
  440. {
  441. va_list ap;
  442. struct imap_cmd *cmdp;
  443. va_start( ap, fmt );
  444. cmdp = v_issue_imap_cmd( ctx, cb, fmt, ap );
  445. va_end( ap );
  446. if (!cmdp)
  447. return RESP_BAD;
  448. return get_cmd_result( ctx, cmdp );
  449. }
  450. static int
  451. imap_exec_b( imap_store_t *ctx, struct imap_cmd_cb *cb, const char *fmt, ... )
  452. {
  453. va_list ap;
  454. struct imap_cmd *cmdp;
  455. va_start( ap, fmt );
  456. cmdp = v_issue_imap_cmd( ctx, cb, fmt, ap );
  457. va_end( ap );
  458. if (!cmdp)
  459. return DRV_STORE_BAD;
  460. switch (get_cmd_result( ctx, cmdp )) {
  461. case RESP_BAD: return DRV_STORE_BAD;
  462. case RESP_NO: return DRV_BOX_BAD;
  463. default: return DRV_OK;
  464. }
  465. }
  466. static int
  467. imap_exec_m( imap_store_t *ctx, struct imap_cmd_cb *cb, const char *fmt, ... )
  468. {
  469. va_list ap;
  470. struct imap_cmd *cmdp;
  471. va_start( ap, fmt );
  472. cmdp = v_issue_imap_cmd( ctx, cb, fmt, ap );
  473. va_end( ap );
  474. if (!cmdp)
  475. return DRV_STORE_BAD;
  476. switch (get_cmd_result( ctx, cmdp )) {
  477. case RESP_BAD: return DRV_STORE_BAD;
  478. case RESP_NO: return DRV_MSG_BAD;
  479. default: return DRV_OK;
  480. }
  481. }
  482. /*
  483. static void
  484. drain_imap_replies( imap_t *imap )
  485. {
  486. while (imap->num_in_progress)
  487. get_cmd_result( imap, 0 );
  488. }
  489. */
  490. static int
  491. is_atom( list_t *list )
  492. {
  493. return list && list->val && list->val != NIL && list->val != LIST;
  494. }
  495. static int
  496. is_list( list_t *list )
  497. {
  498. return list && list->val == LIST;
  499. }
  500. static void
  501. free_list( list_t *list )
  502. {
  503. list_t *tmp;
  504. for (; list; list = tmp) {
  505. tmp = list->next;
  506. if (is_list( list ))
  507. free_list( list->child );
  508. else if (is_atom( list ))
  509. free( list->val );
  510. free( list );
  511. }
  512. }
  513. static int
  514. parse_imap_list_l( imap_t *imap, char **sp, list_t **curp, int level )
  515. {
  516. list_t *cur;
  517. char *s = *sp, *p;
  518. int n, bytes;
  519. for (;;) {
  520. while (isspace( (unsigned char)*s ))
  521. s++;
  522. if (level && *s == ')') {
  523. s++;
  524. break;
  525. }
  526. *curp = cur = nfmalloc( sizeof(*cur) );
  527. curp = &cur->next;
  528. cur->val = 0; /* for clean bail */
  529. if (*s == '(') {
  530. /* sublist */
  531. s++;
  532. cur->val = LIST;
  533. if (parse_imap_list_l( imap, &s, &cur->child, level + 1 ))
  534. goto bail;
  535. } else if (imap && *s == '{') {
  536. /* literal */
  537. bytes = cur->len = strtol( s + 1, &s, 10 );
  538. if (*s != '}')
  539. goto bail;
  540. s = cur->val = nfmalloc( cur->len );
  541. /* dump whats left over in the input buffer */
  542. n = imap->buf.bytes - imap->buf.offset;
  543. if (n > bytes)
  544. /* the entire message fit in the buffer */
  545. n = bytes;
  546. memcpy( s, imap->buf.buf + imap->buf.offset, n );
  547. s += n;
  548. bytes -= n;
  549. /* mark that we used part of the buffer */
  550. imap->buf.offset += n;
  551. /* now read the rest of the message */
  552. while (bytes > 0) {
  553. if ((n = socket_read (&imap->buf.sock, s, bytes)) <= 0)
  554. goto bail;
  555. s += n;
  556. bytes -= n;
  557. }
  558. if (buffer_gets( &imap->buf, &s ))
  559. goto bail;
  560. } else if (*s == '"') {
  561. /* quoted string */
  562. s++;
  563. p = s;
  564. for (; *s != '"'; s++)
  565. if (!*s)
  566. goto bail;
  567. cur->len = s - p;
  568. s++;
  569. cur->val = nfmalloc( cur->len + 1 );
  570. memcpy( cur->val, p, cur->len );
  571. cur->val[cur->len] = 0;
  572. } else {
  573. /* atom */
  574. p = s;
  575. for (; *s && !isspace( (unsigned char)*s ); s++)
  576. if (level && *s == ')')
  577. break;
  578. cur->len = s - p;
  579. if (cur->len == 3 && !memcmp ("NIL", p, 3))
  580. cur->val = NIL;
  581. else {
  582. cur->val = nfmalloc( cur->len + 1 );
  583. memcpy( cur->val, p, cur->len );
  584. cur->val[cur->len] = 0;
  585. }
  586. }
  587. if (!level)
  588. break;
  589. if (!*s)
  590. goto bail;
  591. }
  592. *sp = s;
  593. *curp = 0;
  594. return 0;
  595. bail:
  596. *curp = 0;
  597. return -1;
  598. }
  599. static list_t *
  600. parse_imap_list( imap_t *imap, char **sp )
  601. {
  602. list_t *head;
  603. if (!parse_imap_list_l( imap, sp, &head, 0 ))
  604. return head;
  605. free_list( head );
  606. return NULL;
  607. }
  608. static list_t *
  609. parse_list( char **sp )
  610. {
  611. return parse_imap_list( 0, sp );
  612. }
  613. static int
  614. parse_fetch( imap_t *imap, char *cmd ) /* move this down */
  615. {
  616. list_t *tmp, *list, *flags;
  617. char *body = 0;
  618. imap_message_t *cur;
  619. msg_data_t *msgdata;
  620. struct imap_cmd *cmdp;
  621. int uid = 0, mask = 0, status = 0, size = 0;
  622. unsigned i;
  623. list = parse_imap_list( imap, &cmd );
  624. if (!is_list( list )) {
  625. fprintf( stderr, "IMAP error: bogus FETCH response\n" );
  626. free_list( list );
  627. return -1;
  628. }
  629. for (tmp = list->child; tmp; tmp = tmp->next) {
  630. if (is_atom( tmp )) {
  631. if (!strcmp( "UID", tmp->val )) {
  632. tmp = tmp->next;
  633. if (is_atom( tmp ))
  634. uid = atoi( tmp->val );
  635. else
  636. fprintf( stderr, "IMAP error: unable to parse UID\n" );
  637. } else if (!strcmp( "FLAGS", tmp->val )) {
  638. tmp = tmp->next;
  639. if (is_list( tmp )) {
  640. for (flags = tmp->child; flags; flags = flags->next) {
  641. if (is_atom( flags )) {
  642. if (flags->val[0] == '\\') { /* ignore user-defined flags for now */
  643. if (!strcmp( "Recent", flags->val + 1)) {
  644. status |= M_RECENT;
  645. goto flagok;
  646. }
  647. for (i = 0; i < as(Flags); i++)
  648. if (!strcmp( Flags[i], flags->val + 1 )) {
  649. mask |= 1 << i;
  650. goto flagok;
  651. }
  652. fprintf( stderr, "IMAP warning: unknown system flag %s\n", flags->val );
  653. }
  654. flagok: ;
  655. } else
  656. fprintf( stderr, "IMAP error: unable to parse FLAGS list\n" );
  657. }
  658. status |= M_FLAGS;
  659. } else
  660. fprintf( stderr, "IMAP error: unable to parse FLAGS\n" );
  661. } else if (!strcmp( "RFC822.SIZE", tmp->val )) {
  662. tmp = tmp->next;
  663. if (is_atom( tmp ))
  664. size = atoi( tmp->val );
  665. else
  666. fprintf( stderr, "IMAP error: unable to parse SIZE\n" );
  667. } else if (!strcmp( "BODY[]", tmp->val )) {
  668. tmp = tmp->next;
  669. if (is_atom( tmp )) {
  670. body = tmp->val;
  671. tmp->val = 0; /* don't free together with list */
  672. size = tmp->len;
  673. } else
  674. fprintf( stderr, "IMAP error: unable to parse BODY[]\n" );
  675. }
  676. }
  677. }
  678. if (body) {
  679. for (cmdp = imap->in_progress; cmdp; cmdp = cmdp->next)
  680. if (cmdp->cb.uid == uid)
  681. goto gotuid;
  682. fprintf( stderr, "IMAP error: unexpected FETCH response (UID %d)\n", uid );
  683. free_list( list );
  684. return -1;
  685. gotuid:
  686. msgdata = (msg_data_t *)cmdp->cb.ctx;
  687. msgdata->data = body;
  688. msgdata->len = size;
  689. msgdata->crlf = 1;
  690. if (status & M_FLAGS)
  691. msgdata->flags = mask;
  692. } else if (uid) { /* ignore async flag updates for now */
  693. /* XXX this will need sorting for out-of-order (multiple queries) */
  694. cur = nfcalloc( sizeof(*cur) );
  695. *imap->msgapp = &cur->gen;
  696. imap->msgapp = &cur->gen.next;
  697. cur->gen.next = 0;
  698. cur->gen.uid = uid;
  699. cur->gen.flags = mask;
  700. cur->gen.status = status;
  701. cur->gen.size = size;
  702. }
  703. free_list( list );
  704. return 0;
  705. }
  706. static void
  707. parse_capability( imap_t *imap, char *cmd )
  708. {
  709. char *arg;
  710. unsigned i;
  711. imap->caps = 0x80000000;
  712. while ((arg = next_arg( &cmd )))
  713. for (i = 0; i < as(cap_list); i++)
  714. if (!strcmp( cap_list[i], arg ))
  715. imap->caps |= 1 << i;
  716. imap->rcaps = imap->caps;
  717. }
  718. static int
  719. parse_response_code( imap_store_t *ctx, struct imap_cmd_cb *cb, char *s )
  720. {
  721. imap_t *imap = ctx->imap;
  722. char *arg, *p;
  723. if (*s != '[')
  724. return RESP_OK; /* no response code */
  725. s++;
  726. if (!(p = strchr( s, ']' ))) {
  727. fprintf( stderr, "IMAP error: malformed response code\n" );
  728. return RESP_BAD;
  729. }
  730. *p++ = 0;
  731. arg = next_arg( &s );
  732. if (!strcmp( "UIDVALIDITY", arg )) {
  733. if (!(arg = next_arg( &s )) || !(ctx->gen.uidvalidity = atoi( arg ))) {
  734. fprintf( stderr, "IMAP error: malformed UIDVALIDITY status\n" );
  735. return RESP_BAD;
  736. }
  737. } else if (!strcmp( "UIDNEXT", arg )) {
  738. if (!(arg = next_arg( &s )) || !(imap->uidnext = atoi( arg ))) {
  739. fprintf( stderr, "IMAP error: malformed NEXTUID status\n" );
  740. return RESP_BAD;
  741. }
  742. } else if (!strcmp( "CAPABILITY", arg )) {
  743. parse_capability( imap, s );
  744. } else if (!strcmp( "ALERT", arg )) {
  745. /* RFC2060 says that these messages MUST be displayed
  746. * to the user
  747. */
  748. for (; isspace( (unsigned char)*p ); p++);
  749. fprintf( stderr, "*** IMAP ALERT *** %s\n", p );
  750. } else if (cb && cb->ctx && !strcmp( "APPENDUID", arg )) {
  751. if (!(arg = next_arg( &s )) || !(ctx->gen.uidvalidity = atoi( arg )) ||
  752. !(arg = next_arg( &s )) || !(*(int *)cb->ctx = atoi( arg )))
  753. {
  754. fprintf( stderr, "IMAP error: malformed APPENDUID status\n" );
  755. return RESP_BAD;
  756. }
  757. }
  758. return RESP_OK;
  759. }
  760. static void
  761. parse_search( imap_t *imap, char *cmd )
  762. {
  763. char *arg;
  764. struct imap_cmd *cmdp;
  765. int uid;
  766. arg = next_arg( &cmd );
  767. if (!arg || !(uid = atoi( arg ))) {
  768. fprintf( stderr, "IMAP error: malformed SEARCH response\n" );
  769. return;
  770. }
  771. /* Find the first command that expects a UID - this is guaranteed
  772. * to come in-order, as there are no other means to identify which
  773. * SEARCH response belongs to which request.
  774. */
  775. for (cmdp = imap->in_progress; cmdp; cmdp = cmdp->next)
  776. if (cmdp->cb.uid == -1) {
  777. *(int *)cmdp->cb.ctx = uid;
  778. return;
  779. }
  780. fprintf( stderr, "IMAP error: unexpected SEARCH response (UID %u)\n", uid );
  781. }
  782. static void
  783. parse_list_rsp( imap_store_t *ctx, char *cmd )
  784. {
  785. imap_t *imap = ctx->imap;
  786. char *arg;
  787. list_t *list, *lp;
  788. int l;
  789. list = parse_list( &cmd );
  790. if (list->val == LIST)
  791. for (lp = list->child; lp; lp = lp->next)
  792. if (is_atom( lp ) && !strcasecmp( lp->val, "\\NoSelect" )) {
  793. free_list( list );
  794. return;
  795. }
  796. free_list( list );
  797. (void) next_arg( &cmd ); /* skip delimiter */
  798. arg = next_arg( &cmd );
  799. l = strlen( ctx->gen.conf->path );
  800. if (memcmp( arg, ctx->gen.conf->path, l ))
  801. return;
  802. arg += l;
  803. if (!memcmp( arg + strlen( arg ) - 5, ".lock", 5 )) /* workaround broken servers */
  804. return;
  805. add_string_list( &imap->boxes, arg );
  806. }
  807. static int
  808. get_cmd_result( imap_store_t *ctx, struct imap_cmd *tcmd )
  809. {
  810. imap_t *imap = ctx->imap;
  811. struct imap_cmd *cmdp, **pcmdp, *ncmdp;
  812. char *cmd, *arg, *arg1, *p;
  813. int n, resp, resp2, tag;
  814. for (;;) {
  815. if (buffer_gets( &imap->buf, &cmd ))
  816. return RESP_BAD;
  817. arg = next_arg( &cmd );
  818. if (*arg == '*') {
  819. arg = next_arg( &cmd );
  820. if (!arg) {
  821. fprintf( stderr, "IMAP error: unable to parse untagged response\n" );
  822. return RESP_BAD;
  823. }
  824. if (!strcmp( "NAMESPACE", arg )) {
  825. imap->ns_personal = parse_list( &cmd );
  826. imap->ns_other = parse_list( &cmd );
  827. imap->ns_shared = parse_list( &cmd );
  828. } else if (!strcmp( "OK", arg ) || !strcmp( "BAD", arg ) ||
  829. !strcmp( "NO", arg ) || !strcmp( "BYE", arg )) {
  830. if ((resp = parse_response_code( ctx, 0, cmd )) != RESP_OK)
  831. return resp;
  832. } else if (!strcmp( "CAPABILITY", arg ))
  833. parse_capability( imap, cmd );
  834. else if (!strcmp( "LIST", arg ))
  835. parse_list_rsp( ctx, cmd );
  836. else if (!strcmp( "SEARCH", arg ))
  837. parse_search( imap, cmd );
  838. else if ((arg1 = next_arg( &cmd ))) {
  839. if (!strcmp( "EXISTS", arg1 ))
  840. ctx->gen.count = atoi( arg );
  841. else if (!strcmp( "RECENT", arg1 ))
  842. ctx->gen.recent = atoi( arg );
  843. else if(!strcmp ( "FETCH", arg1 )) {
  844. if (parse_fetch( imap, cmd ))
  845. return RESP_BAD;
  846. }
  847. } else {
  848. fprintf( stderr, "IMAP error: unable to parse untagged response\n" );
  849. return RESP_BAD;
  850. }
  851. } else if (!imap->in_progress) {
  852. fprintf( stderr, "IMAP error: unexpected reply: %s %s\n", arg, cmd ? cmd : "" );
  853. return RESP_BAD;
  854. } else if (*arg == '+') {
  855. /* This can happen only with the last command underway, as
  856. it enforces a round-trip. */
  857. cmdp = (struct imap_cmd *)((char *)imap->in_progress_append -
  858. offsetof(struct imap_cmd, next));
  859. if (cmdp->cb.data) {
  860. n = socket_write( &imap->buf.sock, cmdp->cb.data, cmdp->cb.dlen );
  861. free( cmdp->cb.data );
  862. cmdp->cb.data = 0;
  863. if (n != (int)cmdp->cb.dlen)
  864. return RESP_BAD;
  865. } else if (cmdp->cb.cont) {
  866. if (cmdp->cb.cont( ctx, cmdp, cmd ))
  867. return RESP_BAD;
  868. } else {
  869. fprintf( stderr, "IMAP error: unexpected command continuation request\n" );
  870. return RESP_BAD;
  871. }
  872. if (socket_write( &imap->buf.sock, "\r\n", 2 ) != 2)
  873. return RESP_BAD;
  874. if (!cmdp->cb.cont)
  875. imap->literal_pending = 0;
  876. if (!tcmd)
  877. return DRV_OK;
  878. } else {
  879. tag = atoi( arg );
  880. for (pcmdp = &imap->in_progress; (cmdp = *pcmdp); pcmdp = &cmdp->next)
  881. if (cmdp->tag == tag)
  882. goto gottag;
  883. fprintf( stderr, "IMAP error: unexpected tag %s\n", arg );
  884. return RESP_BAD;
  885. gottag:
  886. if (!(*pcmdp = cmdp->next))
  887. imap->in_progress_append = pcmdp;
  888. imap->num_in_progress--;
  889. if (cmdp->cb.cont || cmdp->cb.data)
  890. imap->literal_pending = 0;
  891. arg = next_arg( &cmd );
  892. if (!strcmp( "OK", arg ))
  893. resp = DRV_OK;
  894. else {
  895. if (!strcmp( "NO", arg )) {
  896. if (cmdp->cb.create && cmd && (cmdp->cb.trycreate || !memcmp( cmd, "[TRYCREATE]", 11 ))) { /* SELECT, APPEND or UID COPY */
  897. p = strchr( cmdp->cmd, '"' );
  898. if (!issue_imap_cmd( ctx, 0, "CREATE %.*s", strchr( p + 1, '"' ) - p + 1, p )) {
  899. resp = RESP_BAD;
  900. goto normal;
  901. }
  902. /* not waiting here violates the spec, but a server that does not
  903. grok this nonetheless violates it too. */
  904. cmdp->cb.create = 0;
  905. if (!(ncmdp = issue_imap_cmd( ctx, &cmdp->cb, "%s", cmdp->cmd ))) {
  906. resp = RESP_BAD;
  907. goto normal;
  908. }
  909. free( cmdp->cmd );
  910. free( cmdp );
  911. if (!tcmd)
  912. return 0; /* ignored */
  913. if (cmdp == tcmd)
  914. tcmd = ncmdp;
  915. continue;
  916. }
  917. resp = RESP_NO;
  918. } else /*if (!strcmp( "BAD", arg ))*/
  919. resp = RESP_BAD;
  920. fprintf( stderr, "IMAP command '%s' returned an error: %s %s\n",
  921. memcmp (cmdp->cmd, "LOGIN", 5) ?
  922. cmdp->cmd : "LOGIN <user> <pass>",
  923. arg, cmd ? cmd : "");
  924. }
  925. if ((resp2 = parse_response_code( ctx, &cmdp->cb, cmd )) > resp)
  926. resp = resp2;
  927. normal:
  928. if (cmdp->cb.done)
  929. cmdp->cb.done( ctx, cmdp, resp );
  930. if (cmdp->cb.data)
  931. free( cmdp->cb.data );
  932. free( cmdp->cmd );
  933. free( cmdp );
  934. if (!tcmd || tcmd == cmdp)
  935. return resp;
  936. }
  937. }
  938. /* not reached */
  939. }
  940. static void
  941. imap_close_server( imap_store_t *ictx )
  942. {
  943. imap_t *imap = ictx->imap;
  944. if (imap->buf.sock.fd != -1) {
  945. imap_exec( ictx, 0, "LOGOUT" );
  946. close( imap->buf.sock.fd );
  947. }
  948. #ifdef HAVE_LIBSSL
  949. if (imap->SSLContext)
  950. SSL_CTX_free( imap->SSLContext );
  951. #endif
  952. free_list( imap->ns_personal );
  953. free_list( imap->ns_other );
  954. free_list( imap->ns_shared );
  955. free( imap );
  956. }
  957. static void
  958. imap_close_store( store_t *ctx )
  959. {
  960. imap_close_server( (imap_store_t *)ctx );
  961. free_generic_messages( ctx->msgs );
  962. free( ctx );
  963. }
  964. #ifdef HAVE_LIBSSL
  965. static int
  966. start_tls( imap_store_t *ctx )
  967. {
  968. imap_t *imap = ctx->imap;
  969. int ret;
  970. static int ssl_inited;
  971. if (!ssl_inited) {
  972. SSL_library_init();
  973. SSL_load_error_strings();
  974. ssl_inited = 1;
  975. }
  976. if (init_ssl_ctx( ctx ))
  977. return 1;
  978. imap->buf.sock.ssl = SSL_new( imap->SSLContext );
  979. SSL_set_fd( imap->buf.sock.ssl, imap->buf.sock.fd );
  980. if ((ret = SSL_connect( imap->buf.sock.ssl )) <= 0) {
  981. socket_perror( "connect", &imap->buf.sock, ret );
  982. return 1;
  983. }
  984. /* verify the server certificate */
  985. if (verify_cert( imap->buf.sock.ssl ))
  986. return 1;
  987. imap->buf.sock.use_ssl = 1;
  988. info( "Connection is now encrypted\n" );
  989. return 0;
  990. }
  991. #define ENCODED_SIZE(n) (4*((n+2)/3))
  992. static char
  993. hexchar( unsigned int b )
  994. {
  995. if (b < 10)
  996. return '0' + b;
  997. return 'a' + (b - 10);
  998. }
  999. /* XXX merge into do_cram_auth? */
  1000. static char *
  1001. cram( const char *challenge, const char *user, const char *pass )
  1002. {
  1003. HMAC_CTX hmac;
  1004. char hash[16];
  1005. char hex[33];
  1006. int i;
  1007. unsigned int hashlen = sizeof(hash);
  1008. char buf[256];
  1009. int len = strlen( challenge );
  1010. char *response = nfcalloc( 1 + len );
  1011. char *final;
  1012. /* response will always be smaller than challenge because we are
  1013. * decoding.
  1014. */
  1015. len = EVP_DecodeBlock( (unsigned char *)response, (unsigned char *)challenge, strlen( challenge ) );
  1016. HMAC_Init( &hmac, (unsigned char *) pass, strlen( pass ), EVP_md5() );
  1017. HMAC_Update( &hmac, (unsigned char *)response, strlen( response ) );
  1018. HMAC_Final( &hmac, (unsigned char *)hash, &hashlen );
  1019. assert( hashlen == sizeof(hash) );
  1020. free( response );
  1021. hex[32] = 0;
  1022. for (i = 0; i < 16; i++) {
  1023. hex[2 * i] = hexchar( (hash[i] >> 4) & 0xf );
  1024. hex[2 * i + 1] = hexchar( hash[i] & 0xf );
  1025. }
  1026. nfsnprintf( buf, sizeof(buf), "%s %s", user, hex );
  1027. len = strlen( buf );
  1028. len = ENCODED_SIZE( len ) + 1;
  1029. final = nfmalloc( len );
  1030. final[len - 1] = 0;
  1031. assert( EVP_EncodeBlock( (unsigned char *)final, (unsigned char *)buf, strlen( buf ) ) == len - 1 );
  1032. return final;
  1033. }
  1034. static int
  1035. do_cram_auth (imap_store_t *ctx, struct imap_cmd *cmdp, const char *prompt)
  1036. {
  1037. imap_t *imap = ctx->imap;
  1038. imap_server_conf_t *srvc = ((imap_store_conf_t *)ctx->gen.conf)->server;
  1039. char *resp;
  1040. int n, l;
  1041. resp = cram( prompt, srvc->user, srvc->pass );
  1042. if (Verbose)
  1043. printf( ">+> %s\n", resp );
  1044. l = strlen( resp );
  1045. n = socket_write( &imap->buf.sock, resp, l );
  1046. free( resp );
  1047. if (n != l)
  1048. return -1;
  1049. cmdp->cb.cont = 0;
  1050. return 0;
  1051. }
  1052. #endif
  1053. static store_t *
  1054. imap_open_store( store_conf_t *conf, store_t *oldctx )
  1055. {
  1056. imap_store_conf_t *cfg = (imap_store_conf_t *)conf;
  1057. imap_server_conf_t *srvc = cfg->server;
  1058. imap_store_t *ctx = (imap_store_t *)oldctx;
  1059. imap_t *imap;
  1060. char *arg, *rsp;
  1061. struct hostent *he;
  1062. struct sockaddr_in addr;
  1063. int s, a[2], preauth;
  1064. #if HAVE_LIBSSL
  1065. int use_ssl;
  1066. #endif
  1067. if (ctx) {
  1068. if (((imap_store_conf_t *)(ctx->gen.conf))->server == cfg->server) {
  1069. ctx->gen.conf = conf;
  1070. imap = ctx->imap;
  1071. goto final;
  1072. }
  1073. imap_close_server( ctx );
  1074. } else
  1075. ctx = nfcalloc( sizeof(*ctx) );
  1076. ctx->gen.conf = conf;
  1077. ctx->imap = imap = nfcalloc( sizeof(*imap) );
  1078. imap->buf.sock.fd = -1;
  1079. imap->in_progress_append = &imap->in_progress;
  1080. /* open connection to IMAP server */
  1081. #if HAVE_LIBSSL
  1082. use_ssl = 0;
  1083. #endif
  1084. if (srvc->tunnel) {
  1085. info( "Starting tunnel '%s'... ", srvc->tunnel );
  1086. if (socketpair( PF_UNIX, SOCK_STREAM, 0, a )) {
  1087. perror( "socketpair" );
  1088. exit( 1 );
  1089. }
  1090. if (fork() == 0) {
  1091. if (dup2( a[0], 0 ) == -1 || dup2( a[0], 1 ) == -1)
  1092. _exit( 127 );
  1093. close( a[0] );
  1094. close( a[1] );
  1095. execl( "/bin/sh", "sh", "-c", srvc->tunnel, (char *)0 );
  1096. _exit( 127 );
  1097. }
  1098. close (a[0]);
  1099. imap->buf.sock.fd = a[1];
  1100. info( "ok\n" );
  1101. } else {
  1102. memset( &addr, 0, sizeof(addr) );
  1103. addr.sin_port = htons( srvc->port );
  1104. addr.sin_family = AF_INET;
  1105. info( "Resolving %s... ", srvc->host );
  1106. he = gethostbyname( srvc->host );
  1107. if (!he) {
  1108. perror( "gethostbyname" );
  1109. goto bail;
  1110. }
  1111. info( "ok\n" );
  1112. addr.sin_addr.s_addr = *((int *) he->h_addr_list[0]);
  1113. s = socket( PF_INET, SOCK_STREAM, 0 );
  1114. info( "Connecting to %s:%hu... ", inet_ntoa( addr.sin_addr ), ntohs( addr.sin_port ) );
  1115. if (connect( s, (struct sockaddr *)&addr, sizeof(addr) )) {
  1116. close( s );
  1117. perror( "connect" );
  1118. goto bail;
  1119. }
  1120. info( "ok\n" );
  1121. imap->buf.sock.fd = s;
  1122. #if HAVE_LIBSSL
  1123. if (srvc->use_imaps) {
  1124. if (start_tls( ctx ))
  1125. goto bail;
  1126. use_ssl = 1;
  1127. }
  1128. #endif
  1129. }
  1130. /* read the greeting string */
  1131. if (buffer_gets( &imap->buf, &rsp )) {
  1132. fprintf( stderr, "IMAP error: no greeting response\n" );
  1133. goto bail;
  1134. }
  1135. arg = next_arg( &rsp );
  1136. if (!arg || *arg != '*' || (arg = next_arg( &rsp )) == NULL) {
  1137. fprintf( stderr, "IMAP error: invalid greeting response\n" );
  1138. goto bail;
  1139. }
  1140. preauth = 0;
  1141. if (!strcmp( "PREAUTH", arg ))
  1142. preauth = 1;
  1143. else if (strcmp( "OK", arg ) != 0) {
  1144. fprintf( stderr, "IMAP error: unknown greeting response\n" );
  1145. goto bail;
  1146. }
  1147. parse_response_code( ctx, 0, rsp );
  1148. if (!imap->caps && imap_exec( ctx, 0, "CAPABILITY" ) != RESP_OK)
  1149. goto bail;
  1150. if (!preauth) {
  1151. #if HAVE_LIBSSL
  1152. if (!srvc->use_imaps && (srvc->use_sslv2 || srvc->use_sslv3 || srvc->use_tlsv1)) {
  1153. /* always try to select SSL support if available */
  1154. if (CAP(STARTTLS)) {
  1155. if (imap_exec( ctx, 0, "STARTTLS" ) != RESP_OK)
  1156. goto bail;
  1157. if (start_tls( ctx ))
  1158. goto bail;
  1159. use_ssl = 1;
  1160. if (imap_exec( ctx, 0, "CAPABILITY" ) != RESP_OK)
  1161. goto bail;
  1162. } else {
  1163. if (srvc->require_ssl) {
  1164. fprintf( stderr, "IMAP error: SSL support not available\n" );
  1165. goto bail;
  1166. } else
  1167. warn( "IMAP warning: SSL support not available\n" );
  1168. }
  1169. }
  1170. #endif
  1171. info ("Logging in...\n");
  1172. if (!srvc->user) {
  1173. fprintf( stderr, "Skipping server %s, no user\n", srvc->host );
  1174. goto bail;
  1175. }
  1176. if (!srvc->pass) {
  1177. char prompt[80];
  1178. sprintf( prompt, "Password (%s@%s): ", srvc->user, srvc->host );
  1179. arg = getpass( prompt );
  1180. if (!arg) {
  1181. perror( "getpass" );
  1182. exit( 1 );
  1183. }
  1184. if (!*arg) {
  1185. fprintf( stderr, "Skipping account %s@%s, no password\n", srvc->user, srvc->host );
  1186. goto bail;
  1187. }
  1188. /*
  1189. * getpass() returns a pointer to a static buffer. make a copy
  1190. * for long term storage.
  1191. */
  1192. srvc->pass = nfstrdup( arg );
  1193. }
  1194. #if HAVE_LIBSSL
  1195. if (CAP(CRAM)) {
  1196. struct imap_cmd_cb cb;
  1197. info( "Authenticating with CRAM-MD5\n" );
  1198. memset( &cb, 0, sizeof(cb) );
  1199. cb.cont = do_cram_auth;
  1200. if (imap_exec( ctx, &cb, "AUTHENTICATE CRAM-MD5" ) != RESP_OK)
  1201. goto bail;
  1202. } else if (srvc->require_cram) {
  1203. fprintf( stderr, "IMAP error: CRAM-MD5 authentication is not supported by server\n" );
  1204. goto bail;
  1205. } else
  1206. #endif
  1207. {
  1208. if (CAP(NOLOGIN)) {
  1209. fprintf( stderr, "Skipping account %s@%s, server forbids LOGIN\n", srvc->user, srvc->host );
  1210. goto bail;
  1211. }
  1212. #if HAVE_LIBSSL
  1213. if (!use_ssl)
  1214. #endif
  1215. warn( "*** IMAP Warning *** Password is being sent in the clear\n" );
  1216. if (imap_exec( ctx, 0, "LOGIN \"%s\" \"%s\"", srvc->user, srvc->pass ) != RESP_OK) {
  1217. fprintf( stderr, "IMAP error: LOGIN failed\n" );
  1218. goto bail;
  1219. }
  1220. }
  1221. } /* !preauth */
  1222. final:
  1223. ctx->prefix = "";
  1224. if (*conf->path)
  1225. ctx->prefix = conf->path;
  1226. else if (cfg->use_namespace && CAP(NAMESPACE)) {
  1227. /* get NAMESPACE info */
  1228. if (imap_exec( ctx, 0, "NAMESPACE" ) != RESP_OK)
  1229. goto bail;
  1230. /* XXX for now assume personal namespace */
  1231. if (is_list( imap->ns_personal ) &&
  1232. is_list( imap->ns_personal->child ) &&
  1233. is_atom( imap->ns_personal->child->child ))
  1234. ctx->prefix = imap->ns_personal->child->child->val;
  1235. }
  1236. ctx->trashnc = 1;
  1237. return (store_t *)ctx;
  1238. bail:
  1239. imap_close_store( &ctx->gen );
  1240. return 0;
  1241. }
  1242. static void
  1243. imap_prepare( store_t *gctx, int opts )
  1244. {
  1245. free_generic_messages( gctx->msgs );
  1246. gctx->msgs = 0;
  1247. gctx->opts = opts;
  1248. }
  1249. static int
  1250. imap_select( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs )
  1251. {
  1252. imap_store_t *ctx = (imap_store_t *)gctx;
  1253. imap_t *imap = ctx->imap;
  1254. const char *prefix;
  1255. int ret, i, j, bl;
  1256. struct imap_cmd_cb cb;
  1257. char buf[1000];
  1258. if (!strcmp( gctx->name, "INBOX" )) {
  1259. // imap->currentnc = 0;
  1260. prefix = "";
  1261. } else {
  1262. // imap->currentnc = 1; /* could use LIST results for that */
  1263. prefix = ctx->prefix;
  1264. }
  1265. memset( &cb, 0, sizeof(cb) );
  1266. cb.create = (gctx->opts & OPEN_CREATE) != 0;
  1267. cb.trycreate = 1;
  1268. if ((ret = imap_exec_b( ctx, &cb, "SELECT \"%s%s\"", prefix, gctx->name )) != DRV_OK)
  1269. goto bail;
  1270. if (gctx->count) {
  1271. imap->msgapp = &gctx->msgs;
  1272. sort_ints( excs, nexcs );
  1273. for (i = 0; i < nexcs; ) {
  1274. for (bl = 0; i < nexcs && bl < 960; i++) {
  1275. if (bl)
  1276. buf[bl++] = ',';
  1277. bl += sprintf( buf + bl, "%d", excs[i] );
  1278. j = i;
  1279. for (; i + 1 < nexcs && excs[i + 1] == excs[i] + 1; i++);
  1280. if (i != j)
  1281. bl += sprintf( buf + bl, ":%d", excs[i] );
  1282. }
  1283. if ((ret = imap_exec_b( ctx, 0, "UID FETCH %s (UID%s%s)", buf,
  1284. (gctx->opts & OPEN_FLAGS) ? " FLAGS" : "",
  1285. (gctx->opts & OPEN_SIZE) ? " RFC822.SIZE" : "" )) != DRV_OK)
  1286. goto bail;
  1287. }
  1288. if (maxuid == INT_MAX)
  1289. maxuid = imap->uidnext ? imap->uidnext - 1 : 1000000000;
  1290. if (maxuid >= minuid &&
  1291. (ret = imap_exec_b( ctx, 0, "UID FETCH %d:%d (UID%s%s)", minuid, maxuid,
  1292. (gctx->opts & OPEN_FLAGS) ? " FLAGS" : "",
  1293. (gctx->opts & OPEN_SIZE) ? " RFC822.SIZE" : "" )) != DRV_OK)
  1294. goto bail;
  1295. }
  1296. ret = DRV_OK;
  1297. bail:
  1298. if (excs)
  1299. free( excs );
  1300. return ret;
  1301. }
  1302. static int
  1303. imap_fetch_msg( store_t *ctx, message_t *msg, msg_data_t *data )
  1304. {
  1305. struct imap_cmd_cb cb;
  1306. memset( &cb, 0, sizeof(cb) );
  1307. cb.uid = msg->uid;
  1308. cb.ctx = data;
  1309. return imap_exec_m( (imap_store_t *)ctx, &cb, "UID FETCH %d (%sBODY.PEEK[])",
  1310. msg->uid, (msg->status & M_FLAGS) ? "" : "FLAGS " );
  1311. }
  1312. static int
  1313. imap_make_flags( int flags, char *buf )
  1314. {
  1315. const char *s;
  1316. unsigned i, d;
  1317. for (i = d = 0; i < as(Flags); i++)
  1318. if (flags & (1 << i)) {
  1319. buf[d++] = ' ';
  1320. buf[d++] = '\\';
  1321. for (s = Flags[i]; *s; s++)
  1322. buf[d++] = *s;
  1323. }
  1324. buf[0] = '(';
  1325. buf[d++] = ')';
  1326. return d;
  1327. }
  1328. static int
  1329. imap_flags_helper( imap_store_t *ctx, int uid, char what, int flags)
  1330. {
  1331. char buf[256];
  1332. buf[imap_make_flags( flags, buf )] = 0;
  1333. return issue_imap_cmd_w( ctx, 0, "UID STORE %d %cFLAGS.SILENT %s", uid, what, buf ) ? DRV_OK : DRV_STORE_BAD;
  1334. }
  1335. static int
  1336. imap_set_flags( store_t *gctx, message_t *msg, int uid, int add, int del )
  1337. {
  1338. imap_store_t *ctx = (imap_store_t *)gctx;
  1339. int ret;
  1340. if (msg) {
  1341. uid = msg->uid;
  1342. add &= ~msg->flags;
  1343. del &= msg->flags;
  1344. msg->flags |= add;
  1345. msg->flags &= ~del;
  1346. }
  1347. if ((!add || (ret = imap_flags_helper( ctx, uid, '+', add )) == DRV_OK) &&
  1348. (!del || (ret = imap_flags_helper( ctx, uid, '-', del )) == DRV_OK))
  1349. return DRV_OK;
  1350. return ret;
  1351. }
  1352. static int
  1353. imap_close( store_t *ctx )
  1354. {
  1355. return imap_exec_b( (imap_store_t *)ctx, 0, "CLOSE" );
  1356. }
  1357. static int
  1358. imap_trash_msg( store_t *gctx, message_t *msg )
  1359. {
  1360. imap_store_t *ctx = (imap_store_t *)gctx;
  1361. struct imap_cmd_cb cb;
  1362. memset( &cb, 0, sizeof(cb) );
  1363. cb.create = 1;
  1364. return imap_exec_m( ctx, &cb, "UID COPY %d \"%s%s\"",
  1365. msg->uid, ctx->prefix, gctx->conf->trash );
  1366. }
  1367. #define TUIDL 8
  1368. static int
  1369. imap_store_msg( store_t *gctx, msg_data_t *data, int *uid )
  1370. {
  1371. imap_store_t *ctx = (imap_store_t *)gctx;
  1372. imap_t *imap = ctx->imap;
  1373. struct imap_cmd_cb cb;
  1374. char *fmap, *buf;
  1375. const char *prefix, *box;
  1376. int ret, i, j, d, len, extra, nocr;
  1377. int start, sbreak = 0, ebreak = 0;
  1378. char flagstr[128], tuid[TUIDL * 2 + 1];
  1379. memset( &cb, 0, sizeof(cb) );
  1380. fmap = data->data;
  1381. len = data->len;
  1382. nocr = !data->crlf;
  1383. extra = 0, i = 0;
  1384. if (!CAP(UIDPLUS) && uid) {
  1385. nloop:
  1386. start = i;
  1387. while (i < len)
  1388. if (fmap[i++] == '\n') {
  1389. extra += nocr;
  1390. if (i - 2 + nocr == start) {
  1391. sbreak = ebreak = i - 2 + nocr;
  1392. goto mktid;
  1393. }
  1394. if (!memcmp( fmap + start, "X-TUID: ", 8 )) {
  1395. extra -= (ebreak = i) - (sbreak = start) + nocr;
  1396. goto mktid;
  1397. }
  1398. goto nloop;
  1399. }
  1400. /* invalid message */
  1401. free( fmap );
  1402. return DRV_MSG_BAD;
  1403. mktid:
  1404. for (j = 0; j < TUIDL; j++)
  1405. sprintf( tuid + j * 2, "%02x", arc4_getbyte() );
  1406. extra += 8 + TUIDL * 2 + 2;
  1407. }
  1408. if (nocr)
  1409. for (; i < len; i++)
  1410. if (fmap[i] == '\n')
  1411. extra++;
  1412. cb.dlen = len + extra;
  1413. buf = cb.data = nfmalloc( cb.dlen );
  1414. i = 0;
  1415. if (!CAP(UIDPLUS) && uid) {
  1416. if (nocr) {
  1417. for (; i < sbreak; i++)
  1418. if (fmap[i] == '\n') {
  1419. *buf++ = '\r';
  1420. *buf++ = '\n';
  1421. } else
  1422. *buf++ = fmap[i];
  1423. } else {
  1424. memcpy( buf, fmap, sbreak );
  1425. buf += sbreak;
  1426. }
  1427. memcpy( buf, "X-TUID: ", 8 );
  1428. buf += 8;
  1429. memcpy( buf, tuid, TUIDL * 2 );
  1430. buf += TUIDL * 2;
  1431. *buf++ = '\r';
  1432. *buf++ = '\n';
  1433. i = ebreak;
  1434. }
  1435. if (nocr) {
  1436. for (; i < len; i++)
  1437. if (fmap[i] == '\n') {
  1438. *buf++ = '\r';
  1439. *buf++ = '\n';
  1440. } else
  1441. *buf++ = fmap[i];
  1442. } else
  1443. memcpy( buf, fmap + i, len - i );
  1444. free( fmap );
  1445. d = 0;
  1446. if (data->flags) {
  1447. d = imap_make_flags( data->flags, flagstr );
  1448. flagstr[d++] = ' ';
  1449. }
  1450. flagstr[d] = 0;
  1451. if (!uid) {
  1452. box = gctx->conf->trash;
  1453. prefix = ctx->prefix;
  1454. cb.create = 1;
  1455. if (ctx->trashnc)
  1456. imap->caps = imap->rcaps & ~(1 << LITERALPLUS);
  1457. } else {
  1458. box = gctx->name;
  1459. prefix = !strcmp( box, "INBOX" ) ? "" : ctx->prefix;
  1460. cb.create = (gctx->opts & OPEN_CREATE) != 0;
  1461. /*if (ctx->currentnc)
  1462. imap->caps = imap->rcaps & ~(1 << LITERALPLUS);*/
  1463. }
  1464. cb.ctx = uid;
  1465. ret = imap_exec_m( ctx, &cb, "APPEND \"%s%s\" %s", prefix, box, flagstr );
  1466. imap->caps = imap->rcaps;
  1467. if (ret != DRV_OK)
  1468. return ret;
  1469. if (!uid)
  1470. ctx->trashnc = 0;
  1471. else {
  1472. /*ctx->currentnc = 0;*/
  1473. gctx->count++;
  1474. }
  1475. if (CAP(UIDPLUS) || !uid)
  1476. return DRV_OK;
  1477. /* Didn't receive an APPENDUID */
  1478. cb.uid = -1; /* we're looking for a UID */
  1479. cb.data = 0; /* reset; ctx still set */
  1480. return imap_exec_m( ctx, &cb, "UID SEARCH HEADER X-TUID %s", tuid );
  1481. }
  1482. static int
  1483. imap_list( store_t *gctx, string_list_t **retb )
  1484. {
  1485. imap_store_t *ctx = (imap_store_t *)gctx;
  1486. imap_t *imap = ctx->imap;
  1487. int ret;
  1488. imap->boxes = 0;
  1489. if ((ret = imap_exec_b( ctx, 0, "LIST \"\" \"%s%%\"", ctx->prefix )) != DRV_OK)
  1490. return ret;
  1491. *retb = imap->boxes;
  1492. return DRV_OK;
  1493. }
  1494. static int
  1495. imap_check( store_t *gctx )
  1496. {
  1497. (void) gctx;
  1498. /* flush queue here */
  1499. return DRV_OK;
  1500. }
  1501. imap_server_conf_t *servers, **serverapp = &servers;
  1502. static int
  1503. imap_parse_store( conffile_t *cfg, store_conf_t **storep, int *err )
  1504. {
  1505. imap_store_conf_t *store;
  1506. imap_server_conf_t *server, *srv, sserver;
  1507. if (!strcasecmp( "IMAPAccount", cfg->cmd )) {
  1508. server = nfcalloc( sizeof(*server) );
  1509. server->name = nfstrdup( cfg->val );
  1510. *serverapp = server;
  1511. serverapp = &server->next;
  1512. store = 0;
  1513. } else if (!strcasecmp( "IMAPStore", cfg->cmd )) {
  1514. store = nfcalloc( sizeof(*store) );
  1515. store->gen.driver = &imap_driver;
  1516. store->gen.name = nfstrdup( cfg->val );
  1517. store->use_namespace = 1;
  1518. memset( &sserver, 0, sizeof(sserver) );
  1519. server = &sserver;
  1520. } else
  1521. return 0;
  1522. #if HAVE_LIBSSL
  1523. /* this will probably annoy people, but its the best default just in
  1524. * case people forget to turn it on
  1525. */
  1526. server->require_ssl = 1;
  1527. server->use_tlsv1 = 1;
  1528. #endif
  1529. while (getcline( cfg ) && cfg->cmd) {
  1530. if (!strcasecmp( "Account", cfg->cmd )) {
  1531. for (srv = servers; srv; srv = srv->next)
  1532. if (srv->name && !strcmp( srv->name, cfg->val ))
  1533. goto gotsrv;
  1534. fprintf( stderr, "%s:%d: unknown IMAP account '%s'\n",
  1535. cfg->file, cfg->line, cfg->val );
  1536. *err = 1;
  1537. continue;
  1538. gotsrv:
  1539. store->server = srv;
  1540. } else if (!strcasecmp( "Host", cfg->cmd )) {
  1541. #if HAVE_LIBSSL
  1542. if (!memcmp( "imaps:", cfg->val, 6 )) {
  1543. cfg->val += 6;
  1544. server->use_imaps = 1;
  1545. server->use_sslv2 = 1;
  1546. server->use_sslv3 = 1;
  1547. if (!server->port)
  1548. server->port = 993;
  1549. } else
  1550. #endif
  1551. {
  1552. if (!memcmp( "imap:", cfg->val, 5 ))
  1553. cfg->val += 5;
  1554. if (!server->port)
  1555. server->port = 143;
  1556. }
  1557. if (!memcmp( "//", cfg->val, 2 ))
  1558. cfg->val += 2;
  1559. server->host = nfstrdup( cfg->val );
  1560. }
  1561. else if (!strcasecmp( "User", cfg->cmd ))
  1562. server->user = nfstrdup( cfg->val );
  1563. else if (!strcasecmp( "Pass", cfg->cmd ))
  1564. server->pass = nfstrdup( cfg->val );
  1565. else if (!strcasecmp( "Port", cfg->cmd ))
  1566. server->port = parse_int( cfg );
  1567. #if HAVE_LIBSSL
  1568. else if (!strcasecmp( "CertificateFile", cfg->cmd ))
  1569. server->cert_file = expand_strdup( cfg->val );
  1570. else if (!strcasecmp( "RequireSSL", cfg->cmd ))
  1571. server->require_ssl = parse_bool( cfg );
  1572. else if (!strcasecmp( "UseSSLv2", cfg->cmd ))
  1573. server->use_sslv2 = parse_bool( cfg );
  1574. else if (!strcasecmp( "UseSSLv3", cfg->cmd ))
  1575. server->use_sslv3 = parse_bool( cfg );
  1576. else if (!strcasecmp( "UseTLSv1", cfg->cmd ))
  1577. server->use_tlsv1 = parse_bool( cfg );
  1578. else if (!strcasecmp( "RequireCRAM", cfg->cmd ))
  1579. server->require_cram = parse_bool( cfg );
  1580. #endif
  1581. else if (!strcasecmp( "Tunnel", cfg->cmd ))
  1582. server->tunnel = nfstrdup( cfg->val );
  1583. else if (store) {
  1584. if (!strcasecmp( "UseNamespace", cfg->cmd ))
  1585. store->use_namespace = parse_bool( cfg );
  1586. else if (!strcasecmp( "Path", cfg->cmd ))
  1587. store->gen.path = nfstrdup( cfg->val );
  1588. else
  1589. parse_generic_store( &store->gen, cfg, err );
  1590. } else {
  1591. fprintf( stderr, "%s:%d: unknown keyword '%s'\n",
  1592. cfg->file, cfg->line, cfg->cmd );
  1593. *err = 1;
  1594. }
  1595. }
  1596. if (!store || !store->server) {
  1597. if (!server->tunnel && !server->host) {
  1598. if (store)
  1599. fprintf( stderr, "IMAP store '%s' has incomplete connection details\n", store->gen.name );
  1600. else
  1601. fprintf( stderr, "IMAP account '%s' has incomplete connection details\n", server->name );
  1602. *err = 1;
  1603. /* leaking server/store */
  1604. *storep = 0;
  1605. return 1;
  1606. }
  1607. }
  1608. *storep = &store->gen;
  1609. if (store && !store->server) {
  1610. store->server = nfmalloc( sizeof(sserver) );
  1611. memcpy( store->server, &sserver, sizeof(sserver) );
  1612. }
  1613. return 1;
  1614. }
  1615. struct driver imap_driver = {
  1616. imap_parse_store,
  1617. imap_open_store,
  1618. imap_close_store,
  1619. imap_list,
  1620. imap_prepare,
  1621. imap_select,
  1622. imap_fetch_msg,
  1623. imap_store_msg,
  1624. imap_set_flags,
  1625. imap_trash_msg,
  1626. imap_check,
  1627. imap_close
  1628. };