1*8dbeaf78Seric /* $OpenBSD: queue_backend.c,v 1.21 2012/06/01 11:42:34 eric Exp $ */ 22a81c1f8Sgilles 32a81c1f8Sgilles /* 42a81c1f8Sgilles * Copyright (c) 2011 Gilles Chehade <gilles@openbsd.org> 52a81c1f8Sgilles * 62a81c1f8Sgilles * Permission to use, copy, modify, and distribute this software for any 72a81c1f8Sgilles * purpose with or without fee is hereby granted, provided that the above 82a81c1f8Sgilles * copyright notice and this permission notice appear in all copies. 92a81c1f8Sgilles * 102a81c1f8Sgilles * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 112a81c1f8Sgilles * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 122a81c1f8Sgilles * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 132a81c1f8Sgilles * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 142a81c1f8Sgilles * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 152a81c1f8Sgilles * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 162a81c1f8Sgilles * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 172a81c1f8Sgilles */ 182a81c1f8Sgilles 192a81c1f8Sgilles #include <sys/types.h> 202a81c1f8Sgilles #include <sys/queue.h> 212a81c1f8Sgilles #include <sys/tree.h> 222a81c1f8Sgilles #include <sys/param.h> 232a81c1f8Sgilles #include <sys/socket.h> 242a81c1f8Sgilles #include <sys/stat.h> 252a81c1f8Sgilles 26148c5951Sgilles #include <ctype.h> 272a81c1f8Sgilles #include <event.h> 282a81c1f8Sgilles #include <imsg.h> 29b5c4b6b5Schl #include <inttypes.h> 302a81c1f8Sgilles #include <libgen.h> 312a81c1f8Sgilles #include <pwd.h> 322a81c1f8Sgilles #include <stdio.h> 332a81c1f8Sgilles #include <stdlib.h> 342a81c1f8Sgilles #include <string.h> 352a81c1f8Sgilles #include <unistd.h> 362a81c1f8Sgilles 372a81c1f8Sgilles #include "smtpd.h" 382a81c1f8Sgilles #include "log.h" 392a81c1f8Sgilles 40d97aaa5bSeric static const char* envelope_validate(struct envelope *, uint64_t); 41148c5951Sgilles 423f522ce8Sgilles /* fsqueue backend */ 43c91bb5c0Seric extern struct queue_backend queue_backend_fs; 447b5d776dSgilles 452a81c1f8Sgilles 462a81c1f8Sgilles struct queue_backend * 472a81c1f8Sgilles queue_backend_lookup(enum queue_type type) 482a81c1f8Sgilles { 49c91bb5c0Seric switch (type) { 50c91bb5c0Seric case QT_FS: 51c91bb5c0Seric return &queue_backend_fs; 522a81c1f8Sgilles 53c91bb5c0Seric default: 542a81c1f8Sgilles fatalx("invalid queue type"); 55c91bb5c0Seric } 562a81c1f8Sgilles 57c91bb5c0Seric return (NULL); 582a81c1f8Sgilles } 592a81c1f8Sgilles 602a81c1f8Sgilles int 61e4d36f12Seric queue_message_create(enum queue_kind qkind, u_int32_t *msgid) 622a81c1f8Sgilles { 63e4d36f12Seric return env->sc_queue->message(qkind, QOP_CREATE, msgid); 642a81c1f8Sgilles } 652a81c1f8Sgilles 662a81c1f8Sgilles int 67e4d36f12Seric queue_message_delete(enum queue_kind qkind, u_int32_t msgid) 682a81c1f8Sgilles { 69e4d36f12Seric return env->sc_queue->message(qkind, QOP_DELETE, &msgid); 702a81c1f8Sgilles } 712a81c1f8Sgilles 722a81c1f8Sgilles int 73e4d36f12Seric queue_message_commit(enum queue_kind qkind, u_int32_t msgid) 742a81c1f8Sgilles { 75e4d36f12Seric return env->sc_queue->message(qkind, QOP_COMMIT, &msgid); 762a81c1f8Sgilles } 772a81c1f8Sgilles 782a81c1f8Sgilles int 79b31e1002Sgilles queue_message_corrupt(enum queue_kind qkind, u_int32_t msgid) 80b31e1002Sgilles { 81b31e1002Sgilles return env->sc_queue->message(qkind, QOP_CORRUPT, &msgid); 82b31e1002Sgilles } 83b31e1002Sgilles 84b31e1002Sgilles int 85e4d36f12Seric queue_message_fd_r(enum queue_kind qkind, u_int32_t msgid) 862a81c1f8Sgilles { 87e4d36f12Seric return env->sc_queue->message(qkind, QOP_FD_R, &msgid); 882a81c1f8Sgilles } 892a81c1f8Sgilles 902a81c1f8Sgilles int 91e4d36f12Seric queue_message_fd_rw(enum queue_kind qkind, u_int32_t msgid) 922a81c1f8Sgilles { 93e4d36f12Seric return env->sc_queue->message(qkind, QOP_FD_RW, &msgid); 942a81c1f8Sgilles } 952a81c1f8Sgilles 962a81c1f8Sgilles int 975ff81a3dSgilles queue_envelope_create(enum queue_kind qkind, struct envelope *ep) 982a81c1f8Sgilles { 99*8dbeaf78Seric int r; 100*8dbeaf78Seric 101*8dbeaf78Seric ep->creation = time(NULL); 102*8dbeaf78Seric r = env->sc_queue->envelope(qkind, QOP_CREATE, ep); 103*8dbeaf78Seric if (!r) { 104*8dbeaf78Seric ep->creation = 0; 105*8dbeaf78Seric ep->id = 0; 106*8dbeaf78Seric } 107*8dbeaf78Seric return (r); 1082a81c1f8Sgilles } 1092a81c1f8Sgilles 1102a81c1f8Sgilles int 1115ff81a3dSgilles queue_envelope_delete(enum queue_kind qkind, struct envelope *ep) 1122a81c1f8Sgilles { 1135ff81a3dSgilles return env->sc_queue->envelope(qkind, QOP_DELETE, ep); 1142a81c1f8Sgilles } 1152a81c1f8Sgilles 1162a81c1f8Sgilles int 1175ff81a3dSgilles queue_envelope_load(enum queue_kind qkind, u_int64_t evpid, struct envelope *ep) 1182a81c1f8Sgilles { 119d97aaa5bSeric const char *e; 120d97aaa5bSeric 121148c5951Sgilles ep->id = evpid; 122d97aaa5bSeric if (env->sc_queue->envelope(qkind, QOP_LOAD, ep)) { 123d97aaa5bSeric if ((e = envelope_validate(ep, evpid)) == NULL) 124d97aaa5bSeric return 1; 125d97aaa5bSeric log_debug("invalid envelope %016" PRIx64 ": %s", ep->id, e); 126d97aaa5bSeric } 127148c5951Sgilles return 0; 1282a81c1f8Sgilles } 1292a81c1f8Sgilles 1302a81c1f8Sgilles int 1315ff81a3dSgilles queue_envelope_update(enum queue_kind qkind, struct envelope *ep) 1322a81c1f8Sgilles { 1335ff81a3dSgilles return env->sc_queue->envelope(qkind, QOP_UPDATE, ep); 1342a81c1f8Sgilles } 135148c5951Sgilles 1367b5d776dSgilles void * 1377b5d776dSgilles qwalk_new(enum queue_kind kind, u_int32_t msgid) 1387b5d776dSgilles { 1397b5d776dSgilles return env->sc_queue->qwalk_new(kind, msgid); 1407b5d776dSgilles } 1417b5d776dSgilles 1427b5d776dSgilles int 1437b5d776dSgilles qwalk(void *hdl, u_int64_t *evpid) 1447b5d776dSgilles { 1457b5d776dSgilles return env->sc_queue->qwalk(hdl, evpid); 1467b5d776dSgilles } 1477b5d776dSgilles 1487b5d776dSgilles void 1497b5d776dSgilles qwalk_close(void *hdl) 1507b5d776dSgilles { 1517b5d776dSgilles return env->sc_queue->qwalk_close(hdl); 1527b5d776dSgilles } 1537b5d776dSgilles 1547b5d776dSgilles u_int32_t 1557b5d776dSgilles queue_generate_msgid(void) 1567b5d776dSgilles { 1577b5d776dSgilles u_int32_t msgid; 1587b5d776dSgilles 1599f0761fdSeric while((msgid = arc4random_uniform(0xffffffff)) == 0) 1609f0761fdSeric ; 1617b5d776dSgilles 1627b5d776dSgilles return msgid; 1637b5d776dSgilles } 1647b5d776dSgilles 1657b5d776dSgilles u_int64_t 1667b5d776dSgilles queue_generate_evpid(u_int32_t msgid) 1677b5d776dSgilles { 1687b5d776dSgilles u_int32_t rnd; 1697b5d776dSgilles u_int64_t evpid; 1707b5d776dSgilles 1719f0761fdSeric while((rnd = arc4random_uniform(0xffffffff)) == 0) 1729f0761fdSeric ; 1737b5d776dSgilles 1747b5d776dSgilles evpid = msgid; 1757b5d776dSgilles evpid <<= 32; 1767b5d776dSgilles evpid |= rnd; 1777b5d776dSgilles 1787b5d776dSgilles return evpid; 1797b5d776dSgilles } 1807b5d776dSgilles 1817b5d776dSgilles 1827b5d776dSgilles /**/ 183d97aaa5bSeric static const char* 184d97aaa5bSeric envelope_validate(struct envelope *ep, uint64_t id) 185148c5951Sgilles { 186148c5951Sgilles if (ep->version != SMTPD_ENVELOPE_VERSION) 187d97aaa5bSeric return "version mismatch"; 188148c5951Sgilles 189d97aaa5bSeric if ((ep->id & 0xffffffff) == 0 || ((ep->id >> 32) & 0xffffffff) == 0) 190d97aaa5bSeric return "invalid id"; 191148c5951Sgilles 192d97aaa5bSeric if (ep->id != id) 193d97aaa5bSeric return "id mismatch"; 194d97aaa5bSeric 195d97aaa5bSeric if (memchr(ep->helo, '\0', sizeof(ep->helo)) == NULL) 196d97aaa5bSeric return "invalid helo"; 197148c5951Sgilles if (ep->helo[0] == '\0') 198d97aaa5bSeric return "empty helo"; 199148c5951Sgilles 200d97aaa5bSeric if (memchr(ep->hostname, '\0', sizeof(ep->hostname)) == NULL) 201d97aaa5bSeric return "invalid hostname"; 202148c5951Sgilles if (ep->hostname[0] == '\0') 203d97aaa5bSeric return "empty hostname"; 204148c5951Sgilles 205d97aaa5bSeric if (memchr(ep->errorline, '\0', sizeof(ep->errorline)) == NULL) 206d97aaa5bSeric return "invalid error line"; 207148c5951Sgilles 208d97aaa5bSeric return NULL; 209148c5951Sgilles } 210