abyss_bool ConnWriteFromFile(TConn * const connectionP, TFile * const fileP, uint64_t const start, uint64_t const last, void * const buffer, uint32_t const buffersize, uint32_t const rate) { /*---------------------------------------------------------------------------- Write the contents of the file stream *fileP, from offset 'start' up through 'last', to the HTTP connection *connectionP. Meter the reading so as not to read more than 'rate' bytes per second. Use the 'bufferSize' bytes at 'buffer' as an internal buffer for this. -----------------------------------------------------------------------------*/ abyss_bool retval; uint32_t waittime; abyss_bool success; uint32_t readChunkSize; if (rate > 0) { readChunkSize = MIN(buffersize, rate); /* One second's worth */ waittime = (1000 * buffersize) / rate; } else { readChunkSize = buffersize; waittime = 0; } success = FileSeek(fileP, start, SEEK_SET); if (!success) retval = FALSE; else { uint64_t const totalBytesToRead = last - start + 1; uint64_t bytesread; bytesread = 0; /* initial value */ while (bytesread < totalBytesToRead) { uint64_t const bytesLeft = totalBytesToRead - bytesread; uint64_t const bytesToRead = MIN(readChunkSize, bytesLeft); uint64_t bytesReadThisTime; bytesReadThisTime = FileRead(fileP, buffer, bytesToRead); bytesread += bytesReadThisTime; if (bytesReadThisTime > 0) ConnWrite(connectionP, buffer, bytesReadThisTime); else break; if (waittime > 0) xmlrpc_millisecond_sleep(waittime); } retval = (bytesread >= totalBytesToRead); } return retval; }
bool HTTPWriteContinue(TSession * const sessionP) { char const continueStatus[] = "HTTP/1.1 100 continue\r\n\r\n"; /* This is a status line plus an end-of-header empty line */ return ConnWrite(sessionP->connP, continueStatus, strlen(continueStatus)); }
static void sendBody(TSession * const sessionP, TFile * const fileP, uint64_t const filesize, const char * const mediatype, uint64_t const start0, uint64_t const end0, char * const z) { if (sessionP->ranges.size == 0) ConnWriteFromFile(sessionP->conn, fileP, 0, filesize - 1, z, 4096, 0); else if (sessionP->ranges.size == 1) ConnWriteFromFile(sessionP->conn, fileP, start0, end0, z, 4096, 0); else { uint64_t i; for (i = 0; i <= sessionP->ranges.size; ++i) { ConnWrite(sessionP->conn,"--", 2); ConnWrite(sessionP->conn, BOUNDARY, strlen(BOUNDARY)); ConnWrite(sessionP->conn, CRLF, 2); if (i < sessionP->ranges.size) { uint64_t start; uint64_t end; abyss_bool decoded; decoded = RangeDecode((char *)(sessionP->ranges.item[i]), filesize, &start, &end); if (decoded) { /* Entity header, not response header */ sprintf(z, "Content-type: %s" CRLF "Content-range: bytes %llu-%llu/%llu" CRLF "Content-length: %llu" CRLF CRLF, mediatype, start, end, filesize, end-start+1); ConnWrite(sessionP->conn, z, strlen(z)); ConnWriteFromFile(sessionP->conn, fileP, start, end, z, 4096, 0); } } } } }
int HandleCommand(QueueClient *client) { int ccode = 0; while (Agent.agent.state < BONGO_AGENT_STATE_STOPPING && client && client->conn && !client->done) { client->buffer[0] = '\0'; ccode = ConnReadAnswer(client->conn, client->buffer, CONN_BUFSIZE); if ((ccode != -1) && (ccode < CONN_BUFSIZE)) { ProtocolCommand *command; if (client->authorized) { command = ProtocolCommandTreeSearch(&Agent.commands, client->buffer); } else { command = ProtocolCommandTreeSearch(&Agent.authCommands, client->buffer); } if (command) { ccode = command->handler(client); } else { if (client->authorized) { ccode = ConnWrite(client->conn, MSG3000UNKNOWN, sizeof(MSG3000UNKNOWN) - 1); } else { ccode = ConnWrite(client->conn, MSG3240NOAUTH, sizeof(MSG3240NOAUTH) - 1); } Log(LOG_DEBUG, "Handled command from %s", LOGIP(client->conn->socketAddress)); } } else if (ccode == -1) { break; } if ((ccode = ConnFlush(client->conn)) == -1) { break; } } return(ccode); }
bool HTTPWriteEndChunk(TSession * const sessionP) { bool retval; if (sessionP->chunkedwrite && sessionP->chunkedwritemode) { /* May be one day trailer dumping will be added */ sessionP->chunkedwritemode = false; retval = ConnWrite(sessionP->connP, "0\r\n\r\n", 5); } else retval = true; return retval; }
static abyss_bool HTTPWriteEnd(TSession * s) { if (!s->chunkedwritemode) return TRUE; if (s->chunkedwrite) { /* May be one day trailer dumping will be added */ s->chunkedwritemode = FALSE; return ConnWrite(s->connP, "0" CRLF CRLF, 5); } s->requestInfo.keepalive = FALSE; return TRUE; }
int ConnWriteFromFile(TConn *c,TFile *file,uint64 start,uint64 end, void *buffer,uint32 buffersize,uint32 rate) { uint64 y = 0; uint64 bytesread=0; uint32 waittime = 0; /* sanity */ if (!c || !buffer) { return FALSE; } if( c->out_bufferpos ) ConnWriteFlush( c ); if (rate>0) { if (buffersize>rate) buffersize=rate; waittime=(1000*buffersize)/rate; } else waittime=0; if (!FileSeek(file,start,SEEK_SET)) return FALSE; while (bytesread<=end-start) { y=(end-start+1)-bytesread; if (y>buffersize) y=buffersize; y=FileRead(file,buffer,y); bytesread+=y; if (y>0) ConnWrite(c,buffer,y); else break; if (waittime) ThreadSleep(waittime); }; return (bytesread>end-start); }
bool HTTPWriteBodyChunk(TSession * const sessionP, const char * const buffer, uint32_t const len) { bool succeeded; if (sessionP->chunkedwrite && sessionP->chunkedwritemode) { char chunkHeader[16]; sprintf(chunkHeader, "%x\r\n", len); succeeded = ConnWrite(sessionP->connP, chunkHeader, strlen(chunkHeader)); if (succeeded) { succeeded = ConnWrite(sessionP->connP, buffer, len); if (succeeded) succeeded = ConnWrite(sessionP->connP, "\r\n", 2); } } else succeeded = ConnWrite(sessionP->connP, buffer, len); return succeeded; }
void ResponseError2(TSession * const sessionP, const char * const explanation) { const char * errorDocument; ResponseAddField(sessionP, "Content-type", "text/html"); ResponseWriteStart(sessionP); xmlrpc_asprintf(&errorDocument, "<HTML><HEAD><TITLE>Error %d</TITLE></HEAD>" "<BODY>" "<H1>Error %d</H1>" "<P>%s</P>" SERVER_HTML_INFO "</BODY>" "</HTML>", sessionP->status, sessionP->status, explanation); ConnWrite(sessionP->connP, errorDocument, strlen(errorDocument)); xmlrpc_strfree(errorDocument); }
static BOOL SaveCalendarInvitation(ItipAgentClient *client, Connection *nmap, char *invitation) { char buffer[CONN_BUFSIZE]; int ccode; int size; size = strlen(invitation); ccode = NMAPCreateCollection(nmap, "/invitations/calendar", NULL); if (ccode != 4226 && ccode != 1000) { return ccode; } ccode = NMAPRunCommandF(nmap, buffer, CONN_BUFSIZE, "WRITE /invitations/calendar %d %d\r\n", STORE_DOCTYPE_CALENDAR, size); if (ccode != 2002) { return ccode; } ccode = ConnWrite(nmap, invitation, size); ConnFlush(nmap); if (ccode < 0) { return ccode; } ccode = NMAPReadAnswer(nmap, buffer, CONN_BUFSIZE, TRUE); return ccode; }
static int CommandHelp(void *param) { int ccode; unsigned char *ptr; QueueClient *client = (QueueClient *)param; ptr = client->buffer + 4; if (*ptr == '\0') { ccode = ConnWrite(client->conn, MSG2001HELP, sizeof(MSG2001HELP) - 1); } else if (*ptr++ == ' ') { ProtocolCommand *command; if (client->authorized) { command = ProtocolCommandTreeSearch(&Agent.commands, ptr); } else { command = ProtocolCommandTreeSearch(&Agent.authCommands, ptr); } if (command) { if (command->help) { ccode = ConnWrite(client->conn, command->help, strlen(command->help)); } else { ccode = ConnWrite(client->conn, NMAP_HELP_NOT_DEFINED, sizeof(NMAP_HELP_NOT_DEFINED) - 1); } } else { return(ConnWrite(client->conn, MSG3000UNKNOWN, sizeof(MSG3000UNKNOWN) - 1)); } } else { return(ConnWrite(client->conn, MSG3010BADARGC, sizeof(MSG3010BADARGC) - 1)); } if (ccode != -1) { ccode = ConnWrite(client->conn, MSG1000OK, sizeof(MSG1000OK) - 1); } return(ccode); }
ConnThread(void *arg) { PRInt32 num; nsresult rv = NS_OK; ipcConnectionState *s = (ipcConnectionState *) arg; // we monitor two file descriptors in this thread. the first (at index 0) is // the socket connection with the IPC daemon. the second (at index 1) is the // pollable event we monitor in order to know when to send messages to the // IPC daemon. s->fds[SOCK].in_flags = PR_POLL_READ; s->fds[POLL].in_flags = PR_POLL_READ; while (NS_SUCCEEDED(rv)) { s->fds[SOCK].out_flags = 0; s->fds[POLL].out_flags = 0; // // poll on the IPC socket and NSPR pollable event // num = PR_Poll(s->fds, 2, PR_INTERVAL_NO_TIMEOUT); if (num > 0) { ipcCallbackQ cbs_to_run; // check if something has been added to the send queue. if so, then // acknowledge pollable event (wait should not block), and configure // poll flags to find out when we can write. if (s->fds[POLL].out_flags & PR_POLL_READ) { PR_WaitForPollableEvent(s->fds[POLL].fd); PR_Lock(s->lock); if (!s->send_queue.IsEmpty()) s->fds[SOCK].in_flags |= PR_POLL_WRITE; if (!s->callback_queue.IsEmpty()) s->callback_queue.MoveTo(cbs_to_run); PR_Unlock(s->lock); } // check if we can read... if (s->fds[SOCK].out_flags & PR_POLL_READ) rv = ConnRead(s); // check if we can write... if (s->fds[SOCK].out_flags & PR_POLL_WRITE) rv = ConnWrite(s); // check if we have callbacks to run while (!cbs_to_run.IsEmpty()) { ipcCallback *cb = cbs_to_run.First(); (cb->func)(cb->arg); cbs_to_run.DeleteFirst(); } // check if we should exit this thread. delay processing a shutdown // request until after all queued up messages have been sent and until // after all queued up callbacks have been run. PR_Lock(s->lock); if (s->shutdown && s->send_queue.IsEmpty() && s->callback_queue.IsEmpty()) rv = NS_ERROR_ABORT; PR_Unlock(s->lock); } else { LOG(("PR_Poll returned error %d (%s), os error %d\n", PR_GetError(), PR_ErrorToName(PR_GetError()), PR_GetOSError())); rv = NS_ERROR_UNEXPECTED; } } // notify termination of the IPC connection if (rv == NS_ERROR_ABORT) rv = NS_OK; IPC_OnConnectionEnd(rv); LOG(("IPC thread exiting\n")); }
int CommandPass(void *param) { unsigned char *ptr; unsigned char *pass; int result; struct sockaddr_in nmap; QueueClient *client = (QueueClient *)param; ptr = client->buffer + 4; if (*ptr++ == ' ') { if ( (toupper(ptr[0]) == 'U') && (toupper(ptr[1]) == 'S') && (toupper(ptr[2]) == 'E') && (toupper(ptr[3]) == 'R') && (ptr[4] == ' ') && (ptr[5] != '\0') && (!isspace(ptr[5])) && ((pass = strchr(ptr + 5, ' ')) != NULL)) { ptr += 5; *pass++ = '\0'; result = MsgAuthVerifyPassword(ptr, pass); if ((result==0) && (nmap.sin_addr.s_addr == MsgGetHostIPAddress())) { return(ConnWrite(client->conn, MSG1000OK, sizeof(MSG1000OK) - 1)); } else { return(ConnWrite(client->conn, MSG4120USERLOCKED, sizeof(MSG4120USERLOCKED) - 1)); } Log(LOG_NOTICE, "PASS USER failed for user from host %s", LOGIP(client->conn->socketAddress)); } else if ( (toupper(ptr[0]) == 'S') && (toupper(ptr[1]) == 'Y') && (toupper(ptr[2]) == 'S') && (toupper(ptr[3]) == 'T') && (toupper(ptr[4]) == 'E') && (toupper(ptr[5]) == 'M') && (ptr[6] == ' ')) { ptr += 7; #if defined(DEBUG) if (strcmp(Conf.serverHash, ptr) == 0) { client->authorized = TRUE; return(ConnWrite(client->conn, MSG1000OK, sizeof(MSG1000OK) - 1)); } #endif Log(LOG_NOTICE, "PASS SYSTEM failed from host %s", LOGIP(client->conn->socketAddress)); } } XplDelay(2000); ConnWrite(client->conn, MSG3010BADARGC, sizeof(MSG3010BADARGC) - 1); client->done = TRUE; return(-1); }
unsigned long ProxyPOP3Account(MailProxyClient *client, ProxyAccount *proxy) { long i; long j; long len; long ccode; long id; long first; long total; long mCount; long mSize; unsigned char *ptr; unsigned char *uid; XplDnsRecord *dns = NULL; proxy->flags |= MAILPROXY_FLAG_STORE_UID; strcpy(client->lastUID, proxy->uid); len = strlen(proxy->host) - 1; if (proxy->host[len] == '.') { proxy->host[len] = '\0'; } if ((client->conn = ConnAlloc(TRUE)) != NULL) { client->conn->socketAddress.sin_addr.s_addr = inet_addr(proxy->host); if (client->conn->socketAddress.sin_addr.s_addr == INADDR_NONE) { ptr = strchr(proxy->host, '@'); if (ptr) { ptr++; } else { ptr = proxy->host; } ccode = XplDnsResolve(ptr, &dns, XPL_RR_A); switch (ccode) { case XPL_DNS_SUCCESS: { client->conn->socketAddress.sin_addr = dns->A.addr; MemFree(dns); break; } case XPL_DNS_BADHOSTNAME: case XPL_DNS_NORECORDS: { LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_BAD_HOSTNAME, LOG_DEBUG, 0, ptr, client->q->user, 0, 0, NULL, 0); proxy->flags |= MAILPROXY_FLAG_BAD_HOST; MemFree(dns); return(-1); } default: case XPL_DNS_FAIL: case XPL_DNS_TIMEOUT: { MemFree(dns); LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_OUT_OF_MEMORY, LOG_ERROR, 0, __FILE__, client->q->user, sizeof(Connection), __LINE__, NULL, 0); return(-1); } } } client->conn->socketAddress.sin_family = AF_INET; client->conn->socketAddress.sin_port = htons(proxy->port); } else { LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_OUT_OF_MEMORY, LOG_ERROR, 0, __FILE__, client->q->user, sizeof(Connection), __LINE__, NULL, 0); proxy->flags &= ~MAILPROXY_FLAG_STORE_UID; return(-1); } /* fixme - this check only works on single server solutions */ if (MsgGetHostIPAddress() != client->conn->socketAddress.sin_addr.s_addr) { if (!(proxy->flags & MAILPROXY_FLAG_SSL)) { ccode = ConnConnect(client->conn, NULL, 0, NULL); } else if (MailProxy.client.ssl.enable) { if (proxy->port == PORT_POP3) { ccode = ConnConnect(client->conn, NULL, 0, NULL); } else { ccode = ConnConnect(client->conn, NULL, 0, MailProxy.client.ssl.context); } } else { ccode = -1; } } else { /* We don't want to proxy ourselves... */ LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_OUT_OF_MEMORY, LOG_ERROR, 0, client->q->user, NULL, XplHostToLittle(client->conn->socketAddress.sin_addr.s_addr), 0, NULL, 0); proxy->flags |= MAILPROXY_FLAG_BAD_HOST; return(-1); } /* POP3 greeting */ if (ccode != -1) { if (proxy->flags & MAILPROXY_FLAG_SSL) { if (proxy->port == PORT_POP3) { if (((ccode = ConnReadAnswer(client->conn, client->line, CONN_BUFSIZE)) != -1) && (client->line[0] == '+') && ((ccode = ConnWrite(client->conn, "CAPA\r\n", 6)) != -1) && ((ccode = ConnFlush(client->conn)) != -1) && ((ccode = ConnReadAnswer(client->conn, client->line, CONN_BUFSIZE)) != -1) && (client->line[0] == '+')) { proxy->flags &= ~MAILPROXY_FLAG_SSL; while ((ccode != -1) && (client->line[0] != POP_OK)) { ccode = ConnReadAnswer(client->conn, client->line, CONN_BUFSIZE); if (ccode != -1) { CHOP_NEWLINE(client->line); if (XplStrCaseCmp(client->line, "STLS") != 0) { continue; } proxy->flags |= MAILPROXY_FLAG_SSL; } } if ((ccode != -1) && (client->line[0] == '+') && (proxy->flags & MAILPROXY_FLAG_SSL) && ((ccode = ConnWrite(client->conn, "STLS\r\n", 6)) != -1) && ((ccode = ConnFlush(client->conn)) != -1) && ((ccode = ConnReadAnswer(client->conn, client->line, CONN_BUFSIZE)) != -1)) { client->conn->ssl.enable = TRUE; ccode = ConnEncrypt(client->conn, MailProxy.client.ssl.context); } else { ccode = -1; } } else { ccode = -1; } } else { client->conn->ssl.enable = TRUE; if (((ccode = ConnReadAnswer(client->conn, client->line, CONN_BUFSIZE)) != -1) && (client->line[0] != POP_OK)) { ccode = -1; } } } else if (((ccode = ConnReadAnswer(client->conn, client->line, CONN_BUFSIZE)) != -1) && (client->line[0] != POP_OK)) { ccode = -1; } } else { proxy->flags |= MAILPROXY_FLAG_BAD_HANDSHAKE; LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_IP_CONNECT_FAILURE, LOG_ERROR, 0, proxy->host, client->q->user, XplHostToLittle(client->conn->socketAddress.sin_addr.s_addr), 0, NULL, 0); return(-1); } if ((ccode != -1) && ((ccode = ConnWriteF(client->conn, "USER %s\r\n", proxy->user)) != -1) && ((ccode = ConnFlush(client->conn)) != -1) && ((ccode = ConnReadLine(client->conn, client->line, CONN_BUFSIZE)) != -1) && (client->line[0] == POP_OK) && ((ccode = ConnWriteF(client->conn, "PASS %s\r\n", proxy->password)) != -1) && ((ccode = ConnFlush(client->conn)) != -1) && ((ccode = ConnReadLine(client->conn, client->line, CONN_BUFSIZE)) != -1) && (client->line[0] == POP_OK) && ((ccode = ConnWrite(client->conn, "UIDL\r\n", 6)) != -1) && ((ccode = ConnFlush(client->conn)) != -1) && ((ccode = ConnReadLine(client->conn, client->line, CONN_BUFSIZE)) != -1) && (client->line[0] == POP_OK)) { first = 1; total = 0; while (((ccode = ConnReadAnswer(client->conn, client->line, CONN_BUFSIZE)) != -1) && (client->line[0] != POP_EOD)) { total++; id = atol(client->line); uid = strchr(client->line, ' '); if (uid) { while (*uid && isspace(*uid)) { uid++; } if (strcmp(uid, proxy->uid) == 0) { first = id + 1; } } else { LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_NEGOTIATION_FAILED, LOG_ERROR, 0, proxy->host, client->q->user, XplHostToLittle(client->conn->socketAddress.sin_addr.s_addr), 0, NULL, 0); return(-1); } } } else { if (ccode != -1) { XplSafeIncrement(MailProxy.stats.wrongPassword); proxy->flags |= MAILPROXY_FLAG_BAD_PASSWORD; LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_WRONG_PASSWORD, LOG_ERROR, 0, client->q->user, proxy->password, XplHostToLittle(client->conn->socketAddress.sin_addr.s_addr), 0, NULL, 0); } else { proxy->flags |= MAILPROXY_FLAG_BAD_HANDSHAKE; LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_NETWORK_IO_FAILURE, LOG_ERROR, 0, proxy->host, client->q->user, XplHostToLittle(client->conn->socketAddress.sin_addr.s_addr), __LINE__, NULL, 0); } return(-1); } if (ccode != -1) { if (first <= total) { client->nmap = NMAPConnectEx(MailProxy.nmap.address, NULL, client->conn->trace.destination); } else { /* We've already got all the messages, or there are none */ LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_PROXY_USER, LOG_WARNING, 0, client->q->user, proxy->host, 0, 0, NULL, 0); return(0); } } else { proxy->flags |= MAILPROXY_FLAG_BAD_PROXY; LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_NEGOTIATION_FAILED, LOG_ERROR, 0, proxy->host, client->q->user, XplHostToLittle(client->conn->socketAddress.sin_addr.s_addr), 0, NULL, 0); return(-1); } if ((client->nmap) && (NMAPAuthenticate(client->nmap, client->line, CONN_BUFSIZE) == TRUE)) { mCount = 0; mSize = 0; } else { if (client->nmap) { NMAPSendCommand(client->nmap, "QUIT\r\n", 6); NMAPReadAnswer(client->nmap, client->line, CONN_BUFSIZE, FALSE); LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_NMAP_UNAVAILABLE, LOG_ERROR, 0, NULL, NULL, XplHostToLittle(client->conn->socketAddress.sin_addr.s_addr), 0, NULL, 0); } else { LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_OUT_OF_MEMORY, LOG_ERROR, 0, __FILE__, client->q->user, sizeof(Connection), __LINE__, NULL, 0); } proxy->flags |= MAILPROXY_FLAG_BAD_PROXY; return(-1); } if (client->nmap) { for (i = first; (ccode != -1) && (i <= total); i++) { ccode = NMAPSendCommandF(client->nmap, "QCREA\r\nQSTOR FLAGS 128\r\nQSTOR FROM %s %s -\r\nQSTOR LOCAL %s %s %d\r\nQSTOR MESSAGE\r\n", MailProxy.postmaster, MailProxy.postmaster, client->q->user, client->q->user, NO_FORWARD); for (j = 0; (ccode != -1) && (j < 4); j++) { /* QSTOR does not have an immediate result [it comes once the . makes it to the other side] */ if ((ccode = NMAPReadAnswer(client->nmap, client->line, CONN_BUFSIZE, FALSE)) != -1) { continue; } LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_OUT_OF_MEMORY, LOG_ERROR, 0, client->q->user, "Create queue entry", ccode, 0, NULL, 0); XplConsolePrintf("bongomailprox: Could not create queue entry, NMAP error %lu, user %s", ccode, client->q->user); return(mCount); } if (((ccode = ConnWriteF(client->conn, "RETR %lu\r\n", i)) != -1) && ((ccode = ConnFlush(client->conn)) != -1) && ((ccode = ConnReadLine(client->conn, client->line, CONN_BUFSIZE)) != -1) && (client->line[0] == POP_OK)) { ccode = ConnReadToConnUntilEOS(client->conn, client->nmap); } else { LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_NEGOTIATION_FAILED, LOG_ERROR, 0, proxy->host, client->q->user, XplHostToLittle(client->conn->socketAddress.sin_addr.s_addr), 0, NULL, 0); return(mCount); } if (ccode != -1) { if (((ccode = NMAPReadAnswer(client->nmap, client->line, CONN_BUFSIZE, TRUE)) == NMAP_OK) /* QSTOR MESSAGE */ && ((ccode = NMAPSendCommand(client->nmap, "QRUN\r\n", 6)) != -1) && ((ccode = NMAPReadAnswer(client->nmap, client->line, CONN_BUFSIZE, TRUE)) == NMAP_ENTRY_CREATED)) { if (((ccode = ConnWriteF(client->conn, "UIDL %lu\r\n", i)) != -1) && ((ccode = ConnFlush(client->conn)) != -1) && ((ccode = ConnReadAnswer(client->conn, client->line, CONN_BUFSIZE)) != -1) && (client->line[0] == POP_OK)) { uid = strchr(client->line+4, ' '); while (*uid && isspace(*uid)) { uid++; } /* Save the UID because this message is now in Bongo */ strcpy(client->lastUID, uid); mCount++; mSize += ccode; if (proxy->flags & MAILPROXY_FLAG_LEAVE_MAIL) { continue; } if (((ccode = ConnWriteF(client->conn, "DELE %lu\r\n", i)) != -1) && ((ccode = ConnFlush(client->conn)) != -1) && ((ccode = ConnReadLine(client->conn, client->line, CONN_BUFSIZE)) != -1) && (client->line[0] == POP_OK)) { continue; } } } } return(mCount); } mSize = (mSize + 1023) / 1024; LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_PROXY_USER, LOG_WARNING, 0, client->q->user, proxy->host, mCount, mSize, NULL, 0); XplSafeAdd(MailProxy.stats.messages, mCount); XplSafeAdd(MailProxy.stats.kiloBytes, mSize); return(mCount); } LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_OUT_OF_MEMORY, LOG_ERROR, 0, __FILE__, client->q->user, sizeof(Connection), __LINE__, NULL, 0); return(-1); }
abyss_bool handler_hook(TSession * r) { //char *mime = "text/html"; char buf[80] = "HTTP/1.1 200 OK\n"; switch_stream_handle_t stream = { 0 }; char *command; int i; TTableItem *ti; char *fs_user = NULL, *fs_domain = NULL; char *path_info = NULL; abyss_bool ret = TRUE; int html = 0, text = 0, xml = 0; const char *api_str; stream.data = r; stream.write_function = http_stream_write; stream.raw_write_function = http_stream_raw_write; if (!r || !r->requestInfo.uri) { return FALSE; } if ((command = strstr(r->requestInfo.uri, "/api/"))) { command += 5; } else if ((command = strstr(r->requestInfo.uri, "/webapi/"))) { command += 8; html++; } else if ((command = strstr(r->requestInfo.uri, "/txtapi/"))) { command += 8; text++; } else if ((command = strstr(r->requestInfo.uri, "/xmlapi/"))) { command += 8; xml++; } else { return FALSE; } if ((path_info = strchr(command, '/'))) { *path_info++ = '\0'; } for (i = 0; i < r->response_headers.size; i++) { ti = &r->response_headers.item[i]; if (!strcasecmp(ti->name, "freeswitch-user")) { fs_user = ti->value; } else if (!strcasecmp(ti->name, "freeswitch-domain")) { fs_domain = ti->value; } } if (is_authorized(r, command)) { goto auth; } ret = TRUE; goto end; auth: if (switch_event_create(&stream.param_event, SWITCH_EVENT_API) == SWITCH_STATUS_SUCCESS) { const char *const content_length = RequestHeaderValue(r, "content-length"); if (html) switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "Content-type", "text/html"); else if (text) switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "Content-type", "text/plain"); else if (xml) switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "Content-type", "text/xml"); if (fs_user) switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "FreeSWITCH-User", fs_user); if (fs_domain) switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "FreeSWITCH-Domain", fs_domain); if (path_info) switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-Path-Info", path_info); switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-URI", r->requestInfo.uri); if (r->requestInfo.query) switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-QUERY", r->requestInfo.query); if (r->requestInfo.host) switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-HOST", r->requestInfo.host); if (r->requestInfo.from) switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-FROM", r->requestInfo.from); if (r->requestInfo.useragent) switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-USER-AGENT", r->requestInfo.useragent); if (r->requestInfo.referer) switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-REFERER", r->requestInfo.referer); if (r->requestInfo.requestline) switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-REQUESTLINE", r->requestInfo.requestline); if (r->requestInfo.user) switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-USER", r->requestInfo.user); if (r->requestInfo.port) switch_event_add_header(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-PORT", "%u", r->requestInfo.port); if (r->requestInfo.query || content_length) { char *q, *qd; char *next; char *query = (char *) r->requestInfo.query; char *name, *val; char qbuf[8192] = ""; if (r->requestInfo.method == m_post && content_length) { int len = atoi(content_length); int qlen = 0; if (len > 0) { int succeeded; char *qp = qbuf; do { int blen = r->conn->buffersize - r->conn->bufferpos; if ((qlen + blen) > len) { blen = len - qlen; } qlen += blen; if (qlen > sizeof(qbuf)) { break; } memcpy(qp, r->conn->buffer + r->conn->bufferpos, blen); qp += blen; if (qlen >= len) { break; } } while ((succeeded = ConnRead(r->conn, 2000))); query = qbuf; } } if (query) { switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-QUERY", query); qd = strdup(query); switch_assert(qd != NULL); q = qd; next = q; do { char *p; if ((next = strchr(next, '&'))) { *next++ = '\0'; } for (p = q; p && *p; p++) { if (*p == '+') { *p = ' '; } } switch_url_decode(q); name = q; if ((val = strchr(name, '='))) { *val++ = '\0'; switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, name, val); } q = next; } while (q != NULL); free(qd); } } } //ResponseChunked(r); //ResponseContentType(r, mime); //ResponseWrite(r); HTTPWrite(r, buf, (uint32_t) strlen(buf)); //HTTPWrite(r, "<pre>\n\n", 7); /* generation of the date field */ { const char *dateValue; DateToString(r->date, &dateValue); if (dateValue) { ResponseAddField(r, "Date", dateValue); } } /* Generation of the server field */ ResponseAddField(r, "Server", "FreeSWITCH-" SWITCH_VERSION_FULL "-mod_xml_rpc"); if (html) { ResponseAddField(r, "Content-Type", "text/html"); } else if (text) { ResponseAddField(r, "Content-Type", "text/plain"); } else if (xml) { ResponseAddField(r, "Content-Type", "text/xml"); } for (i = 0; i < r->response_headers.size; i++) { ti = &r->response_headers.item[i]; ConnWrite(r->conn, ti->name, (uint32_t) strlen(ti->name)); ConnWrite(r->conn, ": ", 2); ConnWrite(r->conn, ti->value, (uint32_t) strlen(ti->value)); ConnWrite(r->conn, CRLF, 2); } switch_snprintf(buf, sizeof(buf), "Connection: close\r\n"); ConnWrite(r->conn, buf, (uint32_t) strlen(buf)); if (html || text || xml) { ConnWrite(r->conn, "\r\n", 2); } if (switch_stristr("unload", command) && switch_stristr("mod_xml_rpc", r->requestInfo.query)) { command = "bgapi"; api_str = "unload mod_xml_rpc"; } else if (switch_stristr("reload", command) && switch_stristr("mod_xml_rpc", r->requestInfo.query)) { command = "bgapi"; api_str = "reload mod_xml_rpc"; } else { api_str = r->requestInfo.query; } if (switch_api_execute(command, api_str, NULL, &stream) == SWITCH_STATUS_SUCCESS) { ResponseStatus(r, 200); r->responseStarted = TRUE; //r->done = TRUE; } else { ResponseStatus(r, 404); ResponseError(r); } //SocketClose(&(r->conn->socket)); HTTPWriteEnd(r); //if (r->conn->channelP) //ConnKill(r->conn); //ChannelInterrupt(r->conn->channelP); //ConnClose(r->conn); //ChannelDestroy(r->conn->channelP); r->requestInfo.keepalive = 0; end: return ret; }
BOOL VirusCheck(AVirusClient *client, const char *queueID, BOOL hasFlags, unsigned long msgFlags, unsigned long senderIp, char *senderUserName) { int ccode; long size; BOOL infected = FALSE; Connection *conn; conn = ConnAddressPoolConnect(&(AVirus.clamd.hosts), AVirus.clamd.connectionTimeout); if (conn) { Connection *data; unsigned short port; ConnWrite(conn, "STREAM\r\n", strlen("STREAM\r\n")); ConnFlush(conn); ccode = ConnReadAnswer(conn, client->line, CONN_BUFSIZE); if (!ccode || strncmp(client->line, "PORT ", strlen("PORT ")) != 0 || (port = atoi(client->line + strlen("PORT "))) == 0) { ConnFree(conn); return -1; } data = ConnAlloc(TRUE); if (!data) { ConnFree(conn); return -1; } memcpy(&data->socketAddress, &conn->socketAddress, sizeof(struct sockaddr_in)); data->socketAddress.sin_port = htons(port); if (ConnConnectEx(data, NULL, 0, NULL, client->conn->trace.destination) < 0) { ConnFree(conn); ConnFree(data); return -1; } size = 0; if (((ccode = NMAPSendCommandF(client->conn, "QRETR %s MESSAGE\r\n", queueID)) != -1) && ((ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE)) != -1) && ccode == 2023) { char *ptr; ptr = strchr (client->line, ' '); if (ptr) { *ptr = '\0'; } size = atol(client->line); } if (size == 0) { ConnFree(conn); ConnFree(data); return -1; } ccode = ConnReadToConn(client->conn, data, size); ConnFree(data); if ((ccode == -1) || ((ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE)) != 1000)) { Log(LOG_DEBUG, "result: %d", ccode); ConnFree(conn); return -1; } while ((ccode = ConnReadAnswer(conn, client->line, CONN_BUFSIZE)) != -1) { char *ptr; ptr = strrchr(client->line, ' '); if (XplStrCaseCmp(ptr + 1, "FOUND") == 0) { *ptr = '\0'; ptr = client->line + strlen("stream: "); #if 0 if(client->foundViruses.used == client->foundViruses.allocated) { client->foundViruses.names = MemRealloc(client->foundViruses.names, sizeof(char*) * (client->foundViruses.allocated + MIME_REALLOC_SIZE)); } client->foundViruses.names[client->foundViruses.used++] = MemStrdup(ptr); XplSafeIncrement(AVirus.stats.viruses); #endif infected = TRUE; } } ConnFree(conn); } return infected; }
abyss_bool handler_hook(TSession * r) { switch_stream_handle_t stream = { 0 }; char *command; int i; char *fs_user = NULL, *fs_domain = NULL; char *path_info = NULL; abyss_bool ret = TRUE; int html = 0, text = 0, xml = 0, api = 0; const char *api_str; const char *uri = 0; TRequestInfo *info = 0; switch_event_t *evnt = 0; /* shortcut to stream.param_event */ if (!r || !(info = &r->requestInfo) || !(uri = info->uri)) { return FALSE; } stream.data = r; stream.write_function = http_stream_write; stream.raw_write_function = http_stream_raw_write; if ((command = strstr(uri, "/api/"))) { command += 5; api++; } else if ((command = strstr(uri, "/webapi/"))) { command += 8; html++; } else if ((command = strstr(uri, "/txtapi/"))) { command += 8; text++; } else if ((command = strstr(uri, "/xmlapi/"))) { command += 8; xml++; } else { return FALSE; /* 404 */ } if ((path_info = strchr(command, '/'))) { *path_info++ = '\0'; } for (i = 0; i < r->responseHeaderFields.size; i++) { TTableItem *ti = &r->responseHeaderFields.item[i]; if (!strcasecmp(ti->name, "freeswitch-user")) { fs_user = ti->value; } else if (!strcasecmp(ti->name, "freeswitch-domain")) { fs_domain = ti->value; } } if (!is_authorized(r, command)) { ret = TRUE; goto end; } /* auth: */ if (switch_event_create(&stream.param_event, SWITCH_EVENT_API) == SWITCH_STATUS_SUCCESS) { const char *const content_length = RequestHeaderValue(r, "content-length"); evnt = stream.param_event; if (html) { switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "Content-Type", "text/html"); } else if (text) { switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "Content-Type", "text/plain"); } else if (xml) { switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "Content-Type", "text/xml"); } if (api) { switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-API", "api"); } if (fs_user) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "FreeSWITCH-User", fs_user); if (fs_domain) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "FreeSWITCH-Domain", fs_domain); if (path_info) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-Path-Info", path_info); if (info->host) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-HOST", info->host); if (info->from) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-FROM", info->from); if (info->useragent) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-USER-AGENT", info->useragent); if (info->referer) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-REFERER", info->referer); if (info->requestline) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-REQUESTLINE", info->requestline); if (info->user) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-USER", info->user); if (info->port) switch_event_add_header(evnt, SWITCH_STACK_BOTTOM, "HTTP-PORT", "%u", info->port); { char *q, *qd; char *next; char *query = (char *) info->query; char *name, *val; char qbuf[8192] = ""; /* first finish reading from the socket if post method was used*/ if (info->method == m_post && content_length) { int len = atoi(content_length); int qlen = 0; if (len > 0) { int succeeded = TRUE; char *qp = qbuf; char *readError; do { int blen = r->connP->buffersize - r->connP->bufferpos; if ((qlen + blen) > len) { blen = len - qlen; } qlen += blen; if (qlen > sizeof(qbuf)) { break; } memcpy(qp, r->connP->buffer.b + r->connP->bufferpos, blen); qp += blen; if (qlen >= len) { break; } ConnRead(r->connP, 2000, NULL, NULL, &readError); if (readError) { succeeded = FALSE; free(readError); } } while (succeeded); query = qbuf; } } /* parse query and add kv-pairs as event headers */ /* a kv pair starts with '&', '+' or \0 mark the end */ if (query) { switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-QUERY", query); qd = strdup(query); } else { qd = strdup(uri); } switch_assert(qd != NULL); q = qd; next = q; do { char *p; if (next = strchr(next, '&')) { if (!query) { /* pass kv pairs from uri to query */ /* "?" is absent in url so parse uri */ *((char *)uri + (next - q - 1)) = '\0'; query = next; switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-QUERY", next); /* and strip uri */ /* the start of first kv pair marks the end of uri */ /* to prevent kv-pairs confusing fs api commands */ /* that have arguments separated by space */ } *next++ = '\0'; } for (p = q; p && *p; p++) { if (*p == '+') { *p = ' '; } } /* hmmm, get method requests are already decoded ... */ switch_url_decode(q); name = q; if ((val = strchr(name, '='))) { *val++ = '\0'; switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, name, val); } q = next; } while (q != NULL); free(qd); } } switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-URI", uri); /* We made it this far, always OK */ if (!HTTPWrite(r, "HTTP/1.1 200 OK\r\n", (uint32_t) strlen("HTTP/1.1 200 OK\r\n"))) { return TRUE; } ResponseAddField(r, "Connection", "close"); /* generation of the date field */ if (evnt) { ResponseAddField(r, "Date", switch_event_get_header(evnt, "Event-Date-GMT")); } else { const char *dateValue; DateToString(r->date, &dateValue); if (dateValue) { ResponseAddField(r, "Date", dateValue); free((void *)dateValue); } } /* Generation of the server field */ ResponseAddField(r, "Server", "FreeSWITCH-" SWITCH_VERSION_FULL "-mod_xml_rpc"); if (html) { ResponseAddField(r, "Content-Type", "text/html"); } else if (text) { ResponseAddField(r, "Content-Type", "text/plain"); } else if (xml) { ResponseAddField(r, "Content-Type", "text/xml"); } for (i = 0; i < r->responseHeaderFields.size; i++) { TTableItem *ti = &r->responseHeaderFields.item[i]; char *header = switch_mprintf("%s: %s\r\n", ti->name, ti->value); if (!ConnWrite(r->connP, header, (uint32_t) strlen(header))) { switch_safe_free(header); return TRUE; } switch_safe_free(header); } /* send end http header */ if (html||text||xml) { if (!ConnWrite(r->connP, CRLF, 2)) { return TRUE; } } else { /* content-type and end of http header will be streamed by fs api or http_stream_write */ } if (switch_stristr("unload", command) && switch_stristr("mod_xml_rpc", info->query)) { command = "bgapi"; api_str = "unload mod_xml_rpc"; } else if (switch_stristr("reload", command) && switch_stristr("mod_xml_rpc", info->query)) { command = "bgapi"; api_str = "reload mod_xml_rpc"; } else { api_str = info->query; } /* TODO (maybe): take "refresh=xxx" out of query as to not confuse fs api commands */ /* execute actual fs api command */ /* fs api command will write to stream, calling http_stream_write / http_stream_raw_write */ /* switch_api_execute will stream INVALID COMMAND before it fails */ switch_api_execute(command, api_str, NULL, &stream); r->responseStarted = TRUE; ResponseStatus(r, 200); /* we don't want an assertion failure */ r->requestInfo.keepalive = 0; end: return ret; }
bool ConnWriteFromFile(TConn * const connectionP, const TFile * const fileP, uint64_t const start, uint64_t const last, void * const buffer, uint32_t const buffersize, uint32_t const rate) { /*---------------------------------------------------------------------------- Write the contents of the file stream *fileP, from offset 'start' up through 'last', to the HTTP connection *connectionP. Meter the reading so as not to read more than 'rate' bytes per second. Use the 'bufferSize' bytes at 'buffer' as an internal buffer for this. -----------------------------------------------------------------------------*/ bool retval; uint32_t waittime; bool success; uint32_t readChunkSize; uint32_t ChunkSize = 4096 * 2; /* read buffer size */ if (rate > 0) { readChunkSize = MIN(buffersize, rate); /* One second's worth */ waittime = (1000 * buffersize) / rate; } else { readChunkSize = ChunkSize; waittime = 0; } success = FileSeek(fileP, start, SEEK_SET); if (!success) retval = FALSE; else { uint64_t const totalBytesToRead = last - start + 1; uint64_t bytesread = 0; int32_t bytesReadThisTime = 0; char * chunk = (char *) buffer; /* the beginning */ do { if ((bytesReadThisTime = FileRead(fileP, chunk, readChunkSize)) <= 0 ) break; bytesread += bytesReadThisTime; chunk += bytesReadThisTime; /* fix bug in ms ie as it doesn't render text/plain properly */ /* if CRLFs are split between reassembled tcp packets, */ /* ie "might" undeterministically render extra empty lines */ /* if it ends in CR or LF, read an extra chunk until the buffer is full */ /* or end of file is reached. You may still have bad luck, complaints go to MS) */ /* if (bytesReadThisTime == readChunkSize && chunk - (char *) buffer + readChunkSize < buffersize) { * char * end = chunk - 1; * if (*end == CR || *end == LF) { * continue; * } * } */ if (!bytesReadThisTime || !ConnWrite(connectionP, buffer, chunk - (char *) buffer)) { break; } chunk = (char *) buffer; /* a new beginning */ if (waittime > 0) xmlrpc_millisecond_sleep(waittime); } while (bytesReadThisTime == readChunkSize); retval = (bytesread >= totalBytesToRead); } return retval; }