/**************************************************************************** * * Copyright (c) 2001 Novell, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, contact Novell, Inc. * * To contact Novell about this file by physical or electronic mail, you * may find current contact information at www.novell.com. * ****************************************************************************/ #include #include #include #include #include #include #include #include #include #include "pluspack.h" #if defined(RELEASE_BUILD) #define PlusPackClientAlloc() MemPrivatePoolGetEntry(PlusPack.nmap.pool) #else #define PlusPackClientAlloc() MemPrivatePoolGetEntryDebug(PlusPack.nmap.pool, __FILE__, __LINE__) #endif static void SignalHandler(int sigtype); #define QUEUE_WORK_TO_DO(c, id, r) \ { \ XplWaitOnLocalSemaphore(PlusPack.nmap.semaphore); \ if (XplSafeRead(PlusPack.nmap.queue.idle)) { \ (c)->queue.previous = NULL; \ if (((c)->queue.next = PlusPack.nmap.queue.head) != NULL) { \ (c)->queue.next->queue.previous = (c); \ } else { \ PlusPack.nmap.queue.tail = (c); \ } \ PlusPack.nmap.queue.head = (c); \ (r) = 0; \ } else { \ XplSafeIncrement(PlusPack.nmap.queue.active); \ XplSignalBlock(); \ XplBeginThread(&(id), HandleConnection, 24 * 1024, XPL_INT_TO_PTR(XplSafeRead(PlusPack.nmap.queue.active)), (r)); \ XplSignalHandler(SignalHandler); \ if (!(r)) { \ (c)->queue.previous = NULL; \ if (((c)->queue.next = PlusPack.nmap.queue.head) != NULL) { \ (c)->queue.next->queue.previous = (c); \ } else { \ PlusPack.nmap.queue.tail = (c); \ } \ PlusPack.nmap.queue.head = (c); \ } else { \ XplSafeDecrement(PlusPack.nmap.queue.active); \ (r) = -1; \ } \ } \ XplSignalLocalSemaphore(PlusPack.nmap.semaphore); \ } PlusPackGlobals PlusPack; static BOOL PlusPackClientAllocCB(void *buffer, void *data) { register PlusPackClient *c = (PlusPackClient *)buffer; memset(c, 0, sizeof(PlusPackClient)); return(TRUE); } static void PlusPackClientFree(PlusPackClient *client) { register PlusPackClient *c = client; if (c->conn) { ConnClose(c->conn, 1); ConnFree(c->conn); c->conn = NULL; } MemPrivatePoolReturnEntry(c); return; } static void FreeClientData(PlusPackClient *client) { if (client && !(client->flags & PLUSPACK_CLIENT_FLAG_EXITING)) { client->flags |= PLUSPACK_CLIENT_FLAG_EXITING; if (client->conn) { ConnClose(client->conn, 1); ConnFree(client->conn); client->conn = NULL; } if (client->vs) { MDBDestroyValueStruct(client->vs); client->vs = NULL; } if (client->envelope.data) { MemFree(client->envelope.data); client->envelope.data = NULL; client->envelope.length = 0; } } return; } static int ProcessConnection(PlusPackClient *client) { int ccode; unsigned char preserve; unsigned char *cur; unsigned char *ptr; unsigned char *eol; unsigned char *line; MDBValueStruct *vs; preserve = '\0'; if (((ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE)) != -1) && (ccode == 6020) && ((ptr = strchr(client->line, ' ')) != NULL) && (client->line[3] == '-')) { *ptr++ = '\0'; strcpy(client->entry.name, client->line); client->line[3] = '\0'; client->entry.queue = atol(client->line); client->entry.id = atol(client->line + 4); client->envelope.length = atoi(ptr); client->envelope.data = MemMalloc(client->envelope.length + 3); vs = MDBCreateValueStruct(PlusPack.handle.directory, NULL); } else { NMAPSendCommand(client->conn, "QDONE\r\n", 7); NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, FALSE); return(-1); } if (client->envelope.data && vs) { sprintf(client->line, "PlusPack: %s", client->entry.name); XplRenameThread(XplGetThreadID(), client->line); ccode = NMAPReadCount(client->conn, client->envelope.data, client->envelope.length); } else { if (client->envelope.data) { MemFree(client->envelope.data); } NMAPSendCommand(client->conn, "QDONE\r\n", 7); NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, FALSE); return(-1); } if ((ccode != -1) && ((ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE)) == 6021)) { client->envelope.data[client->envelope.length] = '\0'; cur = client->envelope.data; } else { MemFree(client->envelope.data); client->envelope.data = NULL; NMAPSendCommand(client->conn, "QDONE\r\n", 7); NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, FALSE); return(-1); } eol = NULL; while (*cur) { if (eol) { *eol = preserve; } line = strchr(cur, 0x0A); if (line) { if (line[-1] == 0x0D) { eol = line - 1; } else { eol = line; } preserve = *eol; *eol = '\0'; line++; } else { eol = NULL; line = cur + strlen(cur); } switch (cur[0]) { case QUEUE_CALENDAR_LOCAL: { client->recipients.calendar++; break; } case QUEUE_FROM: { unsigned char *auth; auth = strchr(cur + 1, ' '); if (auth) { *auth = '\0'; strcpy(client->sender.claim, cur + 1); *auth++ = ' '; ptr = strchr(auth, ' '); if (ptr) { *ptr = '\0'; strcpy(client->sender.auth, auth); *ptr = ' '; } else { strcpy(client->sender.auth, auth); } } else { strcpy(client->sender.claim, cur + 1); client->sender.auth[0] = '-'; client->sender.auth[0] = '\0'; } break; } case QUEUE_RECIP_LOCAL: case QUEUE_RECIP_MBOX_LOCAL: { client->recipients.local++; break; } case QUEUE_RECIP_REMOTE: { client->recipients.remote++; break; } case QUEUE_FLAGS: { client->entry.flags = atol(cur + 1); break; } case QUEUE_ADDRESS: case QUEUE_BOUNCE: case QUEUE_DATE: case QUEUE_ID: case QUEUE_THIRD_PARTY: default: { break; } } cur = line; } if (eol) { *eol = preserve; } return(ccode); } static void ProcessACL(PlusPackClient *client) { unsigned long used; unsigned char *ptr; unsigned char *delim; client->dn[0] = '\0'; client->flags &= ~(PLUSPACK_CLIENT_FLAG_FOUND | PLUSPACK_CLIENT_FLAG_ALLOWED); if ((client->sender.auth[0] != '-') && (client->sender.auth[0] != '\0')) { ptr = client->sender.auth; } else if (!(PlusPack.flags & PLUSPACK_FLAG_ACL_AUTH_REQUIRED)) { ptr = client->sender.claim; } else { return; } delim = strchr(ptr, '@'); if (delim) { *delim = '\0'; } if (MsgFindObject(ptr, client->dn, NULL, NULL, client->vs)) { client->flags |= PLUSPACK_CLIENT_FLAG_FOUND; if (delim) { *delim = '@'; } } else if (delim) { *delim = '@'; delim = strchr(ptr, ' '); if (delim) { *delim = '\0'; } if (MsgFindObject(ptr, client->dn, NULL, NULL, client->vs)) { client->flags |= PLUSPACK_CLIENT_FLAG_FOUND; } if (delim) { *delim = ' '; } } if (client->dn[0]) { MDBFreeValues(client->vs); MDBReadDN(client->dn, A_GROUP_MEMBERSHIP, client->vs); for (used = 0; used < client->vs->Used; used++) { if (XplStrCaseCmp(PlusPack.allowedGroup, client->vs->Value[used]) != 0) { continue; } client->flags |= PLUSPACK_CLIENT_FLAG_ALLOWED; break; } } if (client->flags & PLUSPACK_CLIENT_FLAG_FOUND) { if (client->flags & PLUSPACK_CLIENT_FLAG_ALLOWED) { if (PlusPack.flags & PLUSPACK_FLAG_ACL_SENDNOMEMBERONLY) { client->flags &= ~PLUSPACK_CLIENT_FLAG_ALLOWED; } } else if (PlusPack.flags & PLUSPACK_FLAG_ACL_SENDNOMEMBERONLY) { client->flags |= PLUSPACK_CLIENT_FLAG_ALLOWED; } } MDBFreeValues(client->vs); return; } static int ProcessCopy(PlusPackClient *client) { int count; int length; unsigned char *cur; unsigned char *line; unsigned char *envelope; if (!(client->entry.flags & MSG_FLAG_PLUSPACK_COPIED) && (((client->entry.queue == Q_FIVE) && (client->recipients.local)) || ((client->entry.queue == Q_DELIVER) && (client->recipients.remote)))) { count = client->envelope.length + 39; count += (strlen(PlusPack.copy.user) * 2); count += strlen(PlusPack.copy.inbox); envelope = (unsigned char *)MemMalloc(count); if (envelope) { client->entry.flags |= MSG_FLAG_PLUSPACK_COPIED; count = 0; length = client->envelope.length; cur = client->envelope.data; while (*cur) { line = strchr(cur, 0x0A); if (line) { line++; } else { line = cur + strlen(cur); } if (cur[0] != QUEUE_FLAGS) { cur = line; continue; } count = cur - client->envelope.data; memcpy(envelope, client->envelope.data, count); count += sprintf(envelope + count, QUEUES_FLAGS"%lu\r\n", client->entry.flags); length -= (line - client->envelope.data); memcpy(envelope + count, line, length); count += length; break; } if (!count) { count = sprintf(envelope, QUEUES_FLAGS"%lu\r\n", client->entry.flags); memcpy(envelope + count, client->envelope.data, client->envelope.length); count += client->envelope.length; } MemFree(client->envelope.data); client->envelope.data = envelope; client->envelope.length = count; envelope[count] = '\0'; if (client->entry.queue == Q_FIVE) { if (client->recipients.local) { client->flags |= PLUSPACK_CLIENT_FLAG_COPIED; client->recipients.local++; if (PlusPack.copy.inbox[0]) { count = sprintf(envelope + client->envelope.length, QUEUES_RECIP_MBOX_LOCAL"%s %s 0 %s %d\r\n", PlusPack.copy.user, PlusPack.copy.user, PlusPack.copy.inbox, NO_PLUSPACK); } else { count = sprintf(envelope + client->envelope.length, QUEUES_RECIP_LOCAL"%s %s %d\r\n", PlusPack.copy.user, PlusPack.copy.user, NO_PLUSPACK); } client->envelope.length += count; } } else if (client->recipients.remote) { client->flags |= PLUSPACK_CLIENT_FLAG_COPIED; client->recipients.local++; if (PlusPack.copy.outbox[0]) { count = sprintf(envelope + client->envelope.length, QUEUES_RECIP_MBOX_LOCAL"%s %s 0 %s %d\r\n", PlusPack.copy.user, PlusPack.copy.user, PlusPack.copy.outbox, NO_PLUSPACK); } else { count = sprintf(envelope + client->envelope.length, QUEUES_RECIP_LOCAL"%s %s %d\r\n", PlusPack.copy.user, PlusPack.copy.user, NO_PLUSPACK); } client->envelope.length += count; } } else { LoggerEvent(PlusPack.handle.directory, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_OUT_OF_MEMORY, LOG_ERROR, 0, __FILE__, NULL, sizeof(MDBValueStruct), __LINE__, NULL, 0); count = 0; } } else { count = 0; } return(count); } static int ProcessMime(PlusPackClient *client) { int ccode; int count; unsigned long size; unsigned long position; unsigned char *ptr; unsigned char *type = NULL; unsigned char *subtype = NULL; unsigned char *charset = NULL; unsigned char *encoding = NULL; count = 0; ccode = NMAPSendCommandF(client->conn, "QMIME %s\r\n", client->entry.name); while ((ccode != -1) && (ccode != NMAP_OK)) { ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE); switch (ccode) { case NMAP_OK: { continue; } case 2002: { ptr = NULL; type = client->line; subtype = strchr(client->line, ' '); if (subtype) { *subtype++ = '\0'; charset = strchr(subtype, ' '); if (charset) { *charset++ = '\0'; encoding = strchr(charset, ' '); if (encoding) { *encoding++ = '\0'; ptr = strchr(encoding, ' '); if (ptr) { *ptr++ = '\0'; ptr = strrchr(ptr, '"'); if (ptr) { ptr += 2; } } } } } if (type && subtype && charset && encoding && ptr) { if (sscanf(ptr, "%lu %lu", &position, &size) == 2) { if (!count) { if (XplStrCaseCmp(type, "multipart") == 0) { if (XplStrCaseCmp(subtype, "alternative") == 0) { count++; } else if (XplStrCaseCmp(subtype, "mixed") == 0) { count++; client->mime.attachments = TRUE; } } } if (count < 2) { if (XplStrCaseCmp(type, "text") == 0) { if (XplStrCaseCmp(subtype, "plain") == 0) { client->flags |= PLUSPACK_CLIENT_FLAG_SIGNATURE; client->mime.plain.position = position; client->mime.plain.size = size; } else if (XplStrCaseCmp(subtype, "html") == 0) { client->flags |= PLUSPACK_CLIENT_FLAG_SIGNATURE_HTML; client->mime.html.position = position; client->mime.html.size = size; } else { client->mime.attachments = TRUE; } } else if ((XplStrCaseCmp(type, "multipart") != 0) && (XplStrCaseCmp(type, "message") != 0)) { client->mime.attachments = TRUE; } } } } continue; } case 2003: case 2004: { count--; continue; } default: { ccode = -1; continue; } } } if ((client->flags & PLUSPACK_CLIENT_FLAG_SIGNATURE) && (client->flags & PLUSPACK_CLIENT_FLAG_SIGNATURE_HTML)) { if (client->mime.html.position < client->mime.plain.position) { client->mime.signature[0].html = TRUE; client->mime.signature[0].position = client->mime.html.position; client->mime.signature[0].size = client->mime.html.size; client->mime.signature[1].html = FALSE; client->mime.signature[1].position = client->mime.plain.position; client->mime.signature[1].size = client->mime.plain.size; } else { client->mime.signature[0].html = FALSE; client->mime.signature[0].position = client->mime.plain.position; client->mime.signature[0].size = client->mime.plain.size; client->mime.signature[1].html = TRUE; client->mime.signature[1].position = client->mime.html.position; client->mime.signature[1].size = client->mime.html.size; } } else if (client->flags & PLUSPACK_CLIENT_FLAG_SIGNATURE) { client->mime.signature[0].html = FALSE; client->mime.signature[0].position = client->mime.plain.position; client->mime.signature[0].size = client->mime.plain.size; client->mime.signature[1].position = 0; } else if (client->flags & PLUSPACK_CLIENT_FLAG_SIGNATURE_HTML) { client->mime.signature[0].html = TRUE; client->mime.signature[0].position = client->mime.html.position; client->mime.signature[0].size = client->mime.html.size; client->mime.signature[1].position = 0; } if (((ccode = NMAPSendCommandF(client->conn, "QINFO %s\r\n", client->entry.name)) != -1) && ((ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE)) == 2001) && (sscanf(client->line, "%*s %lu %lu", &client->mime.size, &client->mime.header) == 2)) { return(0); } return(-1); } static int ProcessAttachments(PlusPackClient *client) { int ccode = 0; unsigned char preserve; unsigned char *cur; unsigned char *eol; unsigned char *line; preserve = '\0'; if ((client->entry.queue == Q_DELIVER) && client->mime.attachments) { client->flags &= ~(PLUSPACK_FLAG_SIGNATURE_HTML | PLUSPACK_FLAG_SIGNATURE); eol = NULL; cur = client->envelope.data; while (*cur) { if (eol) { *eol = preserve; } line = strchr(cur, 0x0A); if (line) { if (line[-1] == 0x0D) { eol = line - 1; } else { eol = line; } preserve = *eol; *eol = '\0'; line++; } else { eol = NULL; line = cur + strlen(cur); } switch (cur[0]) { case QUEUE_CALENDAR_LOCAL: case QUEUE_RECIP_LOCAL: case QUEUE_RECIP_MBOX_LOCAL: case QUEUE_RECIP_REMOTE: { /* If the COPIED bit has been set; then the last recipient in the envelope is the copied user and we need to preserve it. Otherwise; consume all recipients. */ if (!(client->flags & PLUSPACK_CLIENT_FLAG_COPIED) || *line) { break; } ccode = NMAPSendCommandF(client->conn, "QMOD RAW %s\r\n", cur); break; } case QUEUE_FLAGS: { ccode = NMAPSendCommandF(client->conn, "QMOD RAW "QUEUES_FLAGS"%d\r\n", client->entry.flags | MSG_FLAG_PLUSPACK_PROCESSED); break; } case QUEUE_ADDRESS: case QUEUE_BOUNCE: case QUEUE_DATE: case QUEUE_FROM: case QUEUE_ID: case QUEUE_THIRD_PARTY: default: { ccode = NMAPSendCommandF(client->conn, "QMOD RAW %s\r\n", cur); break; } } cur = line; } if (eol) { *eol = preserve; } client->bounce = "You are not allowed to send attatchments."; } return(ccode); } static int ProcessAllowed(PlusPackClient *client) { int ccode = 0; unsigned char preserve; unsigned char *cur; unsigned char *eol; unsigned char *line; preserve = '\0'; if ((client->entry.queue == Q_DELIVER) && client->recipients.remote && !(client->flags & PLUSPACK_CLIENT_FLAG_ALLOWED)) { client->flags &= ~(PLUSPACK_FLAG_SIGNATURE_HTML | PLUSPACK_FLAG_SIGNATURE); if (!client->bounce) { eol = NULL; cur = client->envelope.data; while (*cur) { if (eol) { *eol = preserve; } line = strchr(cur, 0x0A); if (line) { if (line[-1] == 0x0D) { eol = line - 1; } else { eol = line; } preserve = *eol; *eol = '\0'; line++; } else { eol = NULL; line = cur + strlen(cur); } switch (cur[0]) { case QUEUE_CALENDAR_LOCAL: case QUEUE_RECIP_LOCAL: case QUEUE_RECIP_MBOX_LOCAL: { ccode = NMAPSendCommandF(client->conn, "QMOD RAW %s\r\n", cur); break; } case QUEUE_RECIP_REMOTE: { break; } case QUEUE_ADDRESS: case QUEUE_BOUNCE: case QUEUE_DATE: case QUEUE_FROM: case QUEUE_ID: case QUEUE_THIRD_PARTY: case QUEUE_FLAGS: default: { ccode = NMAPSendCommandF(client->conn, "QMOD RAW %s\r\n", cur); break; } } cur = line; } if (eol) { *eol = preserve; } client->bounce = "You are not allowed to send external mail."; } else { client->bounce = "You are not allowed to send external mail; or attachments."; } } return(ccode); } static int ProcessEnvelope(PlusPackClient *client) { int ccode = 0; unsigned char preserve; unsigned char *cur; unsigned char *eol; unsigned char *line; preserve = '\0'; if (client->flags & PLUSPACK_CLIENT_FLAG_COPIED) { eol = NULL; cur = client->envelope.data; while ((ccode != -1) && *cur) { if (eol) { *eol = preserve; } line = strchr(cur, 0x0A); if (line) { if (line[-1] == 0x0D) { eol = line - 1; } else { eol = line; } preserve = *eol; *eol = '\0'; line++; } else { eol = NULL; line = cur + strlen(cur); } ccode = NMAPSendCommandF(client->conn, "QMOD RAW %s\r\n", cur); cur = line; } if (eol) { *eol = preserve; } } return(ccode); } static int ProcessSignatures(PlusPackClient *client) { int ccode; int count; unsigned char preserve; unsigned char *ptr; unsigned char *cur; unsigned char *eol; unsigned char *line; preserve = '\0'; if ((client->entry.queue == Q_DELIVER) && client->recipients.remote) { ccode = NMAPSendCommand(client->conn, "QCREA\r\n", 7); } else { ccode = ProcessEnvelope(client); return(ccode); } if ((ccode != -1) && ((ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE)) == NMAP_OK)) { client->flags |= PLUSPACK_CLIENT_FLAG_SPLIT; if (((ccode = NMAPSendCommandF(client->conn, "QSTOR FLAGS %d\r\n", client->entry.flags | MSG_FLAG_PLUSPACK_PROCESSED)) != -1) && ((ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE)) == NMAP_OK) && ((ccode = NMAPSendCommandF(client->conn, "QSTOR FROM %s %s\r\n", client->sender.claim, client->sender.auth)) != -1) && ((ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE)) == NMAP_OK) && ((ccode = NMAPSendCommandF(client->conn, "QADDQ %s 0 %lu\r\n", client->entry.name, client->mime.header)) != -1) && ((ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE)) == NMAP_OK) && ((ccode = NMAPSendCommandF(client->conn, "QSTOR MESSAGE\r\nX-AutoSignature-Version: Bongo Signature Agent 0.1\r\n.\r\n")) != -1) && ((ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE)) == NMAP_OK)) { if ((client->flags & PLUSPACK_CLIENT_FLAG_SIGNATURE) && (client->flags & PLUSPACK_CLIENT_FLAG_SIGNATURE_HTML)) { if (((ccode = NMAPSendCommandF(client->conn, "QADDQ %s %lu %lu\r\n", client->entry.name, client->mime.header, client->mime.signature[0].position + client->mime.signature[0].size)) != -1) && ((ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE)) == NMAP_OK)) { if (client->mime.signature[0].html) { ptr = PlusPack.signature.html; } else { ptr = PlusPack.signature.plain; } count = strlen(ptr); if ((ccode = NMAPSendCommandF(client->conn, "QSTOR MESSAGE %d\r\n", count)) != -1) { ccode = NMAPSendCommand(client->conn, ptr, count); } } else { ccode = -1; } if ((ccode != -1) && ((ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE)) == NMAP_OK) && ((ccode = NMAPSendCommand(client->conn, "QSTOR MESSAGE 2\r\n\r\n", 19)) != -1) && ((ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE)) == NMAP_OK) && ((ccode = NMAPSendCommandF(client->conn, "QADDQ %s %lu %lu\r\n", client->entry.name, client->mime.header + client->mime.signature[0].position + client->mime.signature[0].size, (client->mime.signature[1].position - client->mime.signature[0].position - client->mime.signature[0].size) + client->mime.signature[1].size)) != -1) && ((ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE)) == NMAP_OK)) { if (client->mime.signature[1].html) { ptr = PlusPack.signature.html; } else { ptr = PlusPack.signature.plain; } count = strlen(ptr); if ((ccode = NMAPSendCommandF(client->conn, "QSTOR MESSAGE %d\r\n", count)) != -1) { ccode = NMAPSendCommand(client->conn, ptr, count); } } else { ccode = -1; } if ((ccode != -1) && ((ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE)) == NMAP_OK) && ((ccode = NMAPSendCommand(client->conn, "QSTOR MESSAGE 2\r\n\r\n", 19)) != -1) && ((ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE)) == NMAP_OK)) { ccode = NMAPSendCommandF(client->conn, "QADDQ %s %lu %lu\r\n", client->entry.name, client->mime.header + client->mime.signature[1].position + client->mime.signature[1].size, client->mime.size - client->mime.header - client->mime.signature[1].position - client->mime.signature[1].size); } else { ccode = -1; } } else if (client->flags & (PLUSPACK_CLIENT_FLAG_SIGNATURE | PLUSPACK_CLIENT_FLAG_SIGNATURE_HTML)) { if (((ccode = NMAPSendCommandF(client->conn, "QADDQ %s %lu %lu\r\n", client->entry.name, client->mime.header, client->mime.signature[0].position + client->mime.signature[0].size)) != -1) && ((ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE)) == NMAP_OK)) { if (client->mime.signature[0].html) { ptr = PlusPack.signature.html; } else { ptr = PlusPack.signature.plain; } count = strlen(ptr); if ((ccode = NMAPSendCommandF(client->conn, "QSTOR MESSAGE %d\r\n", count)) != -1) { ccode = NMAPSendCommand(client->conn, ptr, count); } } else { ccode = -1; } if ((ccode != -1) && ((ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE)) == NMAP_OK) && ((ccode = NMAPSendCommand(client->conn, "QSTOR MESSAGE 2\r\n\r\n", 19)) != -1) && ((ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE)) == NMAP_OK)) { ccode = NMAPSendCommandF(client->conn, "QADDQ %s %lu %lu\r\n", client->entry.name, client->mime.header + client->mime.signature[0].position + client->mime.signature[0].size, client->mime.size - client->mime.header - client->mime.signature[0].position - client->mime.signature[0].size); } else { ccode = -1; } } else { ccode = NMAPSendCommandF(client->conn, "QADDQ %s %lu %lu\r\n", client->entry.name, client->mime.header, client->mime.size - client->mime.header); } if (ccode != -1) { ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE); eol = NULL; cur = client->envelope.data; while ((ccode != -1) && *cur) { if (eol) { *eol = preserve; } line = strchr(cur, 0x0A); if (line) { if (line[-1] == 0x0D) { eol = line - 1; } else { eol = line; } preserve = *eol; *eol = '\0'; line++; } else { eol = NULL; line = cur + strlen(cur); } switch (cur[0]) { case QUEUE_CALENDAR_LOCAL: case QUEUE_RECIP_LOCAL: case QUEUE_RECIP_MBOX_LOCAL: { ccode = NMAPSendCommandF(client->conn, "QMOD RAW %s\r\n", cur); break; } case QUEUE_RECIP_REMOTE: { if ((client->flags & PLUSPACK_CLIENT_FLAG_ALLOWED) && ((ccode = NMAPSendCommandF(client->conn, "QSTOR RAW %s\r\n", cur)) != -1)) { ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE); } break; } case QUEUE_FROM: case QUEUE_DATE: case QUEUE_FLAGS: { ccode = NMAPSendCommandF(client->conn, "QMOD RAW %s\r\n", cur); break; } case QUEUE_ADDRESS: case QUEUE_BOUNCE: case QUEUE_ID: case QUEUE_THIRD_PARTY: default: { if (((ccode = NMAPSendCommandF(client->conn, "QMOD RAW %s\r\n", cur)) != -1) && ((ccode = NMAPSendCommandF(client->conn, "QSTOR RAW %s\r\n", cur)) != -1)) { ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE); } break; } } cur = line; } if (eol) { *eol = preserve; } } } if (ccode == -1) { client->flags &= ~PLUSPACK_CLIENT_FLAG_SPLIT; NMAPSendCommand(client->conn, "QABRT\r\n", 7); NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, FALSE); } } else { ccode = -1; } return(ccode); } static void HandleConnection(void *param) { int ccode; long threadNumber = (long)param; time_t sleep = time(NULL); time_t wokeup; PlusPackClient *client; if ((client = PlusPackClientAlloc()) == NULL) { XplConsolePrintf("bongopluspack: New worker failed to startup; out of memory.\r\n"); NMAPSendCommand(client->conn, "QDONE\r\n", 7); XplSafeDecrement(PlusPack.nmap.queue.active); return; } do { XplRenameThread(XplGetThreadID(), "PlusPack Worker"); XplSafeIncrement(PlusPack.nmap.queue.idle); XplWaitOnLocalSemaphore(PlusPack.nmap.queue.todo); XplSafeDecrement(PlusPack.nmap.queue.idle); wokeup = time(NULL); XplWaitOnLocalSemaphore(PlusPack.nmap.semaphore); client->conn = PlusPack.nmap.queue.tail; if (client->conn) { PlusPack.nmap.queue.tail = client->conn->queue.previous; if (PlusPack.nmap.queue.tail) { PlusPack.nmap.queue.tail->queue.next = NULL; } else { PlusPack.nmap.queue.head = NULL; } } XplSignalLocalSemaphore(PlusPack.nmap.semaphore); if (client->conn) { if (((client->vs = MDBCreateValueStruct(PlusPack.handle.directory, NULL)) != NULL) && ConnNegotiate(client->conn, PlusPack.nmap.ssl.context)) { ccode = ProcessConnection(client); if ((ccode != -1) && !(client->entry.flags & MSG_FLAG_PLUSPACK_PROCESSED)) { if (PlusPack.flags & PLUSPACK_FLAG_ACL_ENABLED) { ProcessACL(client); } else { client->flags |= (PLUSPACK_CLIENT_FLAG_FOUND | PLUSPACK_CLIENT_FLAG_ALLOWED); } if (PlusPack.flags & PLUSPACK_FLAG_BIGBROTHER_ENABLED) { ccode = ProcessCopy(client); } if ((ccode != -1) && (PlusPack.flags & (PLUSPACK_FLAG_SIGNATURE_HTML | PLUSPACK_FLAG_SIGNATURE | PLUSPACK_FLAG_NO_ATTACHMENTS))) { ccode = ProcessMime(client); } if ((ccode != -1) && (PlusPack.flags & PLUSPACK_FLAG_NO_ATTACHMENTS)) { ccode = ProcessAttachments(client); } if ((ccode != -1) && (PlusPack.flags & PLUSPACK_FLAG_ACL_ENABLED)) { ccode = ProcessAllowed(client); } if (ccode != -1) { if (!client->bounce) { if (PlusPack.flags & (PLUSPACK_FLAG_SIGNATURE_HTML | PLUSPACK_FLAG_SIGNATURE)) { ccode = ProcessSignatures(client); } else { ccode = ProcessEnvelope(client); } } else { ccode = NMAPSendCommandF(client->conn, "QRTS %s %s %d %d %s\r\n", client->sender.claim, client->sender.claim, DSN_HEADER | DSN_FAILURE, DELIVER_BLOCKED, client->bounce); } } if (client->flags & PLUSPACK_CLIENT_FLAG_SPLIT) { if ((ccode = NMAPSendCommand(client->conn, "QRUN\r\n", 6)) != -1) { ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, FALSE); } } } if ((ccode != -1) && ((ccode = NMAPSendCommand(client->conn, "QDONE\r\n", 7)) != -1)) { ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, FALSE); } } else { if (!client->vs) { LoggerEvent(PlusPack.handle.directory, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_OUT_OF_MEMORY, LOG_ERROR, 0, __FILE__, NULL, sizeof(MDBValueStruct), __LINE__, NULL, 0); } NMAPSendCommand(client->conn, "QDONE\r\n", 7); NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, FALSE); } } if (client->conn) { ConnFlush(client->conn); } FreeClientData(client); /* Live or die? */ if (threadNumber == XplSafeRead(PlusPack.nmap.queue.active)) { if ((wokeup - sleep) > PlusPack.nmap.sleepTime) { break; } } sleep = time(NULL); PlusPackClientAllocCB(client, NULL); } while (PlusPack.state == PLUSPACK_STATE_RUNNING); FreeClientData(client); PlusPackClientFree(client); XplSafeDecrement(PlusPack.nmap.queue.active); XplExitThread(TSR_THREAD, 0); return; } static void PlusPackQueueServer5(void *ignored) { int ccode; XplThreadID id; Connection *conn; XplSafeIncrement(PlusPack.server.active); XplRenameThread(XplGetThreadID(), "PlusPack Queue 6 Server"); while (PlusPack.state < PLUSPACK_STATE_STOPPING) { if (ConnAccept(PlusPack.nmap.conn.queue6, &conn) != -1) { if (PlusPack.state < PLUSPACK_STATE_STOPPING) { conn->ssl.enable = FALSE; QUEUE_WORK_TO_DO(conn, id, ccode); if (!ccode) { XplSignalLocalSemaphore(PlusPack.nmap.queue.todo); continue; } } ConnWrite(conn, "QDONE\r\n", 7); ConnClose(conn, 0); ConnFree(conn); conn = NULL; continue; } switch (errno) { case ECONNABORTED: #ifdef EPROTO case EPROTO: #endif case EINTR: { if (PlusPack.state < PLUSPACK_STATE_STOPPING) { LoggerEvent(PlusPack.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_ACCEPT_FAILURE, LOG_ERROR, 0, "Server", NULL, errno, 0, NULL, 0); } continue; } default: { if (PlusPack.state < PLUSPACK_STATE_STOPPING) { XplConsolePrintf("bongopluspack: Exiting after an accept() failure; error %d\r\n", errno); LoggerEvent(PlusPack.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_ACCEPT_FAILURE, LOG_ERROR, 0, "Server", NULL, errno, 0, NULL, 0); PlusPack.state = PLUSPACK_STATE_STOPPING; } break; } } break; } /* Shutting down */ PlusPack.state = PLUSPACK_STATE_UNLOADING; XplConsolePrintf("bongopluspack: Remote recipient handler shutting down.\r\n"); XplSafeDecrement(PlusPack.server.active); XplSetThreadGroupID(id); return; } static void PlusPackQueueServer6(void *ignored) { int i; int ccode; XplThreadID id; Connection *conn; XplSafeIncrement(PlusPack.server.active); XplRenameThread(XplGetThreadID(), "PlusPack Queue 5 Server"); while (PlusPack.state < PLUSPACK_STATE_STOPPING) { if (ConnAccept(PlusPack.nmap.conn.queue5, &conn) != -1) { if (PlusPack.state < PLUSPACK_STATE_STOPPING) { conn->ssl.enable = FALSE; QUEUE_WORK_TO_DO(conn, id, ccode); if (!ccode) { XplSignalLocalSemaphore(PlusPack.nmap.queue.todo); continue; } } ConnWrite(conn, "QDONE\r\n", 7); ConnClose(conn, 0); ConnFree(conn); conn = NULL; continue; } switch (errno) { case ECONNABORTED: #ifdef EPROTO case EPROTO: #endif case EINTR: { if (PlusPack.state < PLUSPACK_STATE_STOPPING) { LoggerEvent(PlusPack.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_ACCEPT_FAILURE, LOG_ERROR, 0, "Server", NULL, errno, 0, NULL, 0); } continue; } default: { if (PlusPack.state < PLUSPACK_STATE_STOPPING) { XplConsolePrintf("bongopluspack: Exiting after an accept() failure; error %d\r\n", errno); LoggerEvent(PlusPack.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_ACCEPT_FAILURE, LOG_ERROR, 0, "Server", NULL, errno, 0, NULL, 0); PlusPack.state = PLUSPACK_STATE_STOPPING; } break; } } break; } /* Shutting down */ PlusPack.state = PLUSPACK_STATE_UNLOADING; XplConsolePrintf("bongopluspack: Shutting down.\r\n"); id = XplSetThreadGroupID(PlusPack.id.group); if (PlusPack.nmap.conn.queue5) { ConnClose(PlusPack.nmap.conn.queue5, 1); PlusPack.nmap.conn.queue5 = NULL; } if (PlusPack.nmap.conn.queue6) { ConnClose(PlusPack.nmap.conn.queue6, 1); PlusPack.nmap.conn.queue6 = NULL; } if (PlusPack.nmap.ssl.enable) { PlusPack.nmap.ssl.enable = FALSE; if (PlusPack.nmap.ssl.conn) { ConnClose(PlusPack.nmap.ssl.conn, 1); PlusPack.nmap.ssl.conn = NULL; } if (PlusPack.nmap.ssl.context) { ConnSSLContextFree(PlusPack.nmap.ssl.context); PlusPack.nmap.ssl.context = NULL; } } ConnCloseAll(1); for (i = 0; (XplSafeRead(PlusPack.server.active) > 1) && (i < 60); i++) { XplDelay(1000); } XplConsolePrintf("bongopluspack: Shutting down %d queue threads\r\n", XplSafeRead(PlusPack.nmap.queue.active)); XplWaitOnLocalSemaphore(PlusPack.nmap.semaphore); ccode = XplSafeRead(PlusPack.nmap.queue.idle); while (ccode--) { XplSignalLocalSemaphore(PlusPack.nmap.queue.todo); } XplSignalLocalSemaphore(PlusPack.nmap.semaphore); for (i = 0; XplSafeRead(PlusPack.nmap.queue.active) && (i < 60); i++) { XplDelay(1000); } if (XplSafeRead(PlusPack.server.active) > 1) { XplConsolePrintf("bongopluspack: %d server threads outstanding; attempting forceful unload.\r\n", XplSafeRead(PlusPack.server.active) - 1); } if (XplSafeRead(PlusPack.nmap.queue.active)) { XplConsolePrintf("bongopluspack: %d threads outstanding; attempting forceful unload.\r\n", XplSafeRead(PlusPack.nmap.queue.active)); } LoggerClose(PlusPack.handle.logging); PlusPack.handle.logging = NULL; XplCloseLocalSemaphore(PlusPack.nmap.queue.todo); XplCloseLocalSemaphore(PlusPack.nmap.semaphore); MsgShutdown(); CONN_TRACE_SHUTDOWN(); ConnShutdown(); if (PlusPack.signature.plain) { MemFree(PlusPack.signature.plain); } if (PlusPack.signature.html) { MemFree(PlusPack.signature.html); } if (PlusPack.allowedGroup) { MemFree(PlusPack.allowedGroup); } MemPrivatePoolFree(PlusPack.nmap.pool); MemoryManagerClose(PLUSPACK_AGENT); XplConsolePrintf("bongopluspack: Shutdown complete\r\n"); XplSignalLocalSemaphore(PlusPack.sem.main); XplWaitOnLocalSemaphore(PlusPack.sem.shutdown); XplCloseLocalSemaphore(PlusPack.sem.shutdown); XplCloseLocalSemaphore(PlusPack.sem.main); XplSetThreadGroupID(id); return; } static BOOL ReadConfiguration(void) { unsigned char *ptr; MDBValueStruct *vs; vs = MDBCreateValueStruct(PlusPack.handle.directory, MsgGetServerDN(NULL)); if (vs) { if (MDBRead(MDB_CURRENT_CONTEXT, MSGSRV_A_OFFICIAL_NAME, vs)) { strcpy(PlusPack.officialName, vs->Value[0]); MDBFreeValues(vs); } else { PlusPack.officialName[0] = '\0'; } if (MDBRead(PLUSPACK_AGENT, MSGSRV_A_CONFIGURATION, vs)) { PlusPack.flags = atol(vs->Value[0]); MDBFreeValues(vs); } if (MDBRead(PLUSPACK_AGENT, MSGSRV_A_LIST_SIGNATURE, vs)) { if (vs->Value[0][0] && ((PlusPack.signature.plain = MemStrdup(vs->Value[0])) != NULL)) { PlusPack.flags |= PLUSPACK_FLAG_SIGNATURE; } else { PlusPack.flags &= ~PLUSPACK_FLAG_SIGNATURE; } MDBFreeValues(vs); } if (MDBRead(PLUSPACK_AGENT, MSGSRV_A_LIST_SIGNATURE_HTML, vs)) { if (vs->Value[0][0] && ((PlusPack.signature.html = MemStrdup(vs->Value[0])) != NULL)) { PlusPack.flags |= PLUSPACK_FLAG_SIGNATURE_HTML; } else { PlusPack.flags &= ~PLUSPACK_FLAG_SIGNATURE_HTML; } MDBFreeValues(vs); } if (MDBReadDN(PLUSPACK_AGENT, PLUSPACK_A_COPY_USER, vs)) { if (vs->Value[0][0] && (strlen(vs->Value[0]) < sizeof(PlusPack.copy.user))) { if (!(ptr = strrchr(vs->Value[0], '\\'))) { strcpy(PlusPack.copy.user, vs->Value[0]); } else { strcpy(PlusPack.copy.user, ptr + 1); } PlusPack.flags |= PLUSPACK_FLAG_BIGBROTHER_ENABLED; } else { PlusPack.flags &= ~PLUSPACK_FLAG_BIGBROTHER_ENABLED; } MDBFreeValues(vs); } PlusPack.copy.inbox[0] = '\0'; PlusPack.copy.outbox[0] = '\0'; if (MDBRead(PLUSPACK_AGENT, PLUSPACK_A_COPY_MBOX, vs)) { if (vs->Value[0][0] && (strlen(vs->Value[0]) < sizeof(PlusPack.copy.inbox))) { strcpy(PlusPack.copy.inbox, vs->Value[0]); } if ((vs->Used == 2) && vs->Value[1][0] && (strlen(vs->Value[1]) < sizeof(PlusPack.copy.outbox))) { strcpy(PlusPack.copy.outbox, vs->Value[1]); } else { strcpy(PlusPack.copy.outbox, PlusPack.copy.inbox); } MDBFreeValues(vs); } if (MDBReadDN(PLUSPACK_AGENT, PLUSPACK_A_ACL_GROUP, vs)) { if (vs->Value[0][0]) { PlusPack.allowedGroup = vs->Value[0]; vs->Used = 0; PlusPack.flags |= PLUSPACK_FLAG_ACL_ENABLED; } else { PlusPack.flags &= ~PLUSPACK_FLAG_ACL_ENABLED; } MDBFreeValues(vs); } MDBDestroyValueStruct(vs); return(TRUE); } return(FALSE); } #if defined(NETWARE) || defined(LIBC) || defined(WIN32) static int _NonAppCheckUnload(void) { static BOOL checked = FALSE; XplThreadID id; if (!checked) { checked = TRUE; PlusPack.state = PLUSPACK_STATE_UNLOADING; XplWaitOnLocalSemaphore(PlusPack.sem.shutdown); id = XplSetThreadGroupID(PlusPack.id.group); ConnClose(PlusPack.nmap.conn.queue5, 1); XplSetThreadGroupID(id); id = XplSetThreadGroupID(PlusPack.id.group); ConnClose(PlusPack.nmap.conn.queue6, 1); XplSetThreadGroupID(id); XplWaitOnLocalSemaphore(PlusPack.sem.main); } return(0); } #endif static void SignalHandler(int sigtype) { switch(sigtype) { case SIGHUP: { if (PlusPack.state < PLUSPACK_STATE_UNLOADING) { PlusPack.state = PLUSPACK_STATE_UNLOADING; } break; } case SIGINT: case SIGTERM: { if (PlusPack.state == PLUSPACK_STATE_STOPPING) { XplUnloadApp(getpid()); } else if (PlusPack.state < PLUSPACK_STATE_STOPPING) { PlusPack.state = PLUSPACK_STATE_STOPPING; } break; } default: { break; } } return; } static int QueueSocketInit(void) { if (PlusPack.flags & PLUSPACK_FLAG_BIGBROTHER_ENABLED) { PlusPack.nmap.conn.queue5 = ConnAlloc(FALSE); } PlusPack.nmap.conn.queue6 = ConnAlloc(FALSE); if (PlusPack.nmap.conn.queue6 && (!(PlusPack.flags & PLUSPACK_FLAG_BIGBROTHER_ENABLED) || PlusPack.nmap.conn.queue5)) { memset(&(PlusPack.nmap.conn.queue6->socketAddress), 0, sizeof(PlusPack.nmap.conn.queue6->socketAddress)); PlusPack.nmap.conn.queue6->socketAddress.sin_family = AF_INET; PlusPack.nmap.conn.queue6->socketAddress.sin_addr.s_addr = MsgGetAgentBindIPAddress(); if (PlusPack.flags & PLUSPACK_FLAG_BIGBROTHER_ENABLED) { memset(&(PlusPack.nmap.conn.queue5->socketAddress), 0, sizeof(PlusPack.nmap.conn.queue5->socketAddress)); PlusPack.nmap.conn.queue5->socketAddress.sin_family = AF_INET; PlusPack.nmap.conn.queue5->socketAddress.sin_addr.s_addr = MsgGetAgentBindIPAddress(); } /* Get root privs back for the bind. It's ok if this fails - the user might not need to be root to bind to the port */ XplSetEffectiveUserId(0); if (PlusPack.flags & PLUSPACK_FLAG_BIGBROTHER_ENABLED) { PlusPack.nmap.conn.queue5->socket = ConnServerSocket(PlusPack.nmap.conn.queue5, 2048); } PlusPack.nmap.conn.queue6->socket = ConnServerSocket(PlusPack.nmap.conn.queue6, 2048); if (XplSetEffectiveUser(MsgGetUnprivilegedUser()) < 0) { XplConsolePrintf("bongopluspack: Could not drop to unprivileged user '%s'\r\n", MsgGetUnprivilegedUser()); if (PlusPack.nmap.conn.queue5) { ConnFree(PlusPack.nmap.conn.queue5); PlusPack.nmap.conn.queue5 = NULL; } ConnFree(PlusPack.nmap.conn.queue6); PlusPack.nmap.conn.queue6 = NULL; return(-1); } if ((PlusPack.nmap.conn.queue5->socket == -1) || (PlusPack.nmap.conn.queue6->socket == -1)) { XplConsolePrintf("bongopluspack: Could not bind to dynamic port\r\n"); if (PlusPack.nmap.conn.queue5) { ConnFree(PlusPack.nmap.conn.queue5); PlusPack.nmap.conn.queue5 = NULL; } ConnFree(PlusPack.nmap.conn.queue6); PlusPack.nmap.conn.queue6 = NULL; return(-1); } if ((QueueRegister(PLUSPACK_AGENT, Q_FIVE, PlusPack.nmap.conn.queue5->socketAddress.sin_port) != REGISTRATION_COMPLETED) || (QueueRegister(PLUSPACK_AGENT, Q_DELIVER, PlusPack.nmap.conn.queue6->socketAddress.sin_port) != REGISTRATION_COMPLETED)) { XplConsolePrintf("bongopluspack: Could not register with bongonmap\r\n"); if (PlusPack.nmap.conn.queue5) { ConnFree(PlusPack.nmap.conn.queue5); PlusPack.nmap.conn.queue5 = NULL; } ConnFree(PlusPack.nmap.conn.queue6); PlusPack.nmap.conn.queue6 = NULL; return(-1); } } else { if (PlusPack.nmap.conn.queue5) { ConnFree(PlusPack.nmap.conn.queue5); PlusPack.nmap.conn.queue5 = NULL; } XplConsolePrintf("bongopluspack: Could not allocate connection.\r\n"); return(-1); } return(0); } XplServiceCode(SignalHandler) int XplServiceMain(int argc, char *argv[]) { int ccode; XplThreadID id; if (XplSetEffectiveUser(MsgGetUnprivilegedUser()) < 0) { XplConsolePrintf("bongopluspack: Could not drop to unprivileged user '%s', exiting.\n", MsgGetUnprivilegedUser()); return(1); } XplInit(); XplSignalHandler(SignalHandler); PlusPack.id.main = XplGetThreadID(); PlusPack.id.group = XplGetThreadGroupID(); PlusPack.state = PLUSPACK_STATE_INITIALIZING; PlusPack.nmap.conn.queue5 = NULL; PlusPack.nmap.conn.queue6 = NULL; PlusPack.nmap.pool = NULL; PlusPack.nmap.sleepTime = (5 * 60); PlusPack.nmap.ssl.conn = NULL; PlusPack.nmap.ssl.enable = FALSE; PlusPack.nmap.ssl.context = NULL; PlusPack.nmap.ssl.config.options = 0; PlusPack.handle.directory = NULL; PlusPack.handle.logging = NULL; strcpy(PlusPack.nmap.address, "127.0.0.1"); XplSafeWrite(PlusPack.server.active, 0); XplSafeWrite(PlusPack.nmap.queue.idle, 0); XplSafeWrite(PlusPack.nmap.queue.active, 0); XplSafeWrite(PlusPack.nmap.queue.maximum, 100000); if (MemoryManagerOpen(PLUSPACK_AGENT) == TRUE) { PlusPack.nmap.pool = MemPrivatePoolAlloc("PlusPack Connections", sizeof(PlusPackClient), 0, 3072, TRUE, FALSE, PlusPackClientAllocCB, NULL, NULL); if (PlusPack.nmap.pool != NULL) { XplOpenLocalSemaphore(PlusPack.sem.main, 0); XplOpenLocalSemaphore(PlusPack.sem.shutdown, 1); XplOpenLocalSemaphore(PlusPack.nmap.semaphore, 1); XplOpenLocalSemaphore(PlusPack.nmap.queue.todo, 1); } else { MemoryManagerClose(PLUSPACK_AGENT); XplConsolePrintf("bongopluspack: Unable to create connection pool; shutting down.\r\n"); return(-1); } } else { XplConsolePrintf("bongopluspack: Unable to initialize memory manager; shutting down.\r\n"); return(-1); } ConnStartup(CONNECTION_TIMEOUT, TRUE); MDBInit(); PlusPack.handle.directory = (MDBHandle)MsgInit(); if (PlusPack.handle.directory == NULL) { XplBell(); XplConsolePrintf("bongopluspack: Invalid directory credentials; exiting!\r\n"); XplBell(); MemoryManagerClose(PLUSPACK_AGENT); return(-1); } /* We need to delay the startup of the plus-pack agent to allow SMTP to register with NMAP first. fixme - when enhanced nmap registration is available; remove this delay! */ #if 0 XplDelay(20 * 1000); #endif NMAPInitialize(); SetCurrentNameSpace(NWOS2_NAME_SPACE); SetTargetNameSpace(NWOS2_NAME_SPACE); PlusPack.handle.logging = LoggerOpen("bongopluspack"); if (!PlusPack.handle.logging) { XplConsolePrintf("bongopluspack: Unable to initialize logging; disabled.\r\n"); } ReadConfiguration(); CONN_TRACE_INIT((char *)MsgGetWorkDir(NULL), "pluspack"); // CONN_TRACE_SET_FLAGS(CONN_TRACE_ALL); /* uncomment this line and pass '--enable-conntrace' to autogen to get the agent to trace all connections */ if (PlusPack.flags) { if (QueueSocketInit() < 0) { XplConsolePrintf("bongopluspack: Exiting.\r\n"); MemoryManagerClose(PLUSPACK_AGENT); return -1; } if (XplSetRealUser(MsgGetUnprivilegedUser()) < 0) { XplConsolePrintf("bongopluspack: Could not drop to unprivileged user '%s', exiting.\r\n", MsgGetUnprivilegedUser()); MemoryManagerClose(PLUSPACK_AGENT); return 1; } PlusPack.nmap.ssl.enable = FALSE; PlusPack.nmap.ssl.config.certificate.file = MsgGetTLSCertPath(NULL); PlusPack.nmap.ssl.config.key.type = GNUTLS_X509_FMT_PEM; PlusPack.nmap.ssl.config.key.file = MsgGetTLSKeyPath(NULL); PlusPack.nmap.ssl.context = ConnSSLContextAlloc(&(PlusPack.nmap.ssl.config)); if (PlusPack.nmap.ssl.context) { PlusPack.nmap.ssl.enable = TRUE; } NMAPSetEncryption(PlusPack.nmap.ssl.context); PlusPack.state = PLUSPACK_STATE_RUNNING; if (PlusPack.flags & PLUSPACK_FLAG_BIGBROTHER_ENABLED) { XplBeginThread(&id, PlusPackQueueServer5, 8192, NULL, ccode); } else { ccode = 0; } if (!ccode) { XplStartMainThread(PRODUCT_SHORT_NAME, &id, PlusPackQueueServer6, 8192, NULL, ccode); } else { XplConsolePrintf("bongopluspack: Unable to startup an NMAP queue server thread.\r\n"); } } else { XplConsolePrintf("bongopluspack: Not configured; unloading.\r\n"); } XplUnloadApp(XplGetThreadID()); return(0); }