📄 tftpserver.cpp
字号:
/*************************************************************************** Copyright (C) 2005 by Achal Dhir ** achaldhir@gmail.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** 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, write to the ** Free Software Foundation, Inc., ** 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ****************************************************************************/// tftpserver.cpp#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <net/if.h>#include <netdb.h>#include <unistd.h>#include <signal.h>#include <stdio.h>#include <fcntl.h>#include <errno.h>#include <sys/time.h>#include <sys/ioctl.h>#include <time.h>#include <stdlib.h>#include <limits.h>#include <memory.h>#include <sys/stat.h>#include <stdio.h>#include <stdlib.h>#include <syslog.h>#include <string>#include <pthread.h>#include "tftpserver.h"//Functionsvoid runProg();void *ProcessRequest(void *lpParam);char *cleanstr(char* buff, bool next);void init();bool getSection(char *sectionName, char *buffer, int sizeofbuffer, char *fileName);char *myLower(char *string);char *myUpper(char *string);char* IP2String(DWORD);void clean(request*);void getServ();BYTE isIP(char*);void logMess(request*, BYTE);void logMess(BYTE);DWORD my_inet_addr(char*);//Global Variablesbool verbatim = false;char iniFile[]="/etc/tftpserver.ini";DWORD blksize = USHRT_MAX - 4;WORD interval = 3;data2 cfig;char tempbuff[256];char logBuff[512];int main(int argc, char **argv){ verbatim = (argc > 1); if (verbatim) { init(); timeval tv; fd_set readfds; if (cfig.tftpConn[0].server) { printf("\nAccepting requests..\n"); do { FD_ZERO(&readfds); tv.tv_sec = 20; tv.tv_usec = 0; for (int i = 0; i < MAX_SERVERS && cfig.tftpConn[i].server; i++) FD_SET(cfig.tftpConn[i].sock, &readfds); errno=0; int fdsReady = select(cfig.maxFD, &readfds, NULL, NULL, &tv); //if (errno) // printf("%s\n", strerror(errno)); for (int i = 0; fdsReady > 0 && i < MAX_SERVERS && cfig.tftpConn[i].server; i++) { if (FD_ISSET(cfig.tftpConn[i].sock, &readfds)) { fdsReady--; request *req = (request*)malloc(sizeof(request)); memset(req, 0, sizeof(request)); req->clientsize = sizeof(req->client); errno = 0; req->bytesRecd = recvfrom(cfig.tftpConn[i].sock, (char*) & req->datain, sizeof(ack), 0, (sockaddr*) & req->client, &req->clientsize); req->knock = cfig.tftpConn[i].sock; req->sockInd = i; if (!errno) { if (cfig.hostRanges[0].rangeStart) { DWORD iip = ntohl(req->client.sin_addr.s_addr); BYTE allowed = 0; for (int j = 0; j <= 32 && cfig.hostRanges[j].rangeStart; j++) { if (iip >= cfig.hostRanges[j].rangeStart && iip <= cfig.hostRanges[j].rangeEnd) { allowed = 1; break; } } if (!allowed) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(2); strcpy(req->serverError.errormessage, "Access Denied"); logMess(req, 1); req->bytesSent = sendto(cfig.tftpConn[i].sock, (const char*) & req->serverError, strlen(req->serverError.errormessage) + 5, 0, (sockaddr*) & req->client, req->clientsize); free(req); continue; } } if (req->bytesRecd > 0 && (ntohs(req->datain.opcode) == 1 || ntohs(req->datain.opcode) == 2)) { pthread_create(&req->threadId, 0, ProcessRequest, (void*)req); if (!req->threadId) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(0); strcpy(req->serverError.errormessage, "Thread Creation Error"); logMess(req, 2); req->bytesSent = sendto(cfig.tftpConn[i].sock, (const char*) & req->serverError, strlen(req->serverError.errormessage) + 5, 0, (sockaddr*) & req->client, req->clientsize); free(req); } } else if (req->bytesRecd > 0 && (htons(req->datain.opcode) == 5)) { sprintf(req->serverError.errormessage, "Error Code %i at Client, %s", ntohs(req->clientError.errorcode), req->clientError.errormessage); logMess(req, 2); free(req); } else { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(0); sprintf(req->serverError.errormessage, "Invalid Option Code %i", ntohs(req->datain.opcode)); logMess(req, 2); req->bytesSent = sendto(cfig.tftpConn[i].sock, (const char*) & req->serverError, strlen(req->serverError.errormessage) + 5, 0, (sockaddr*) & req->client, req->clientsize); free(req); } } else { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(0); sprintf(req->serverError.errormessage, "Communication Error"); logMess(req, 1); free(req); } } } } while (true); } for (int i = 0; i < MAX_SERVERS && cfig.tftpConn[i].server; i++) close(cfig.tftpConn[i].sock); } else { /* Our process ID and Session ID */ pid_t pid, sid; /* Fork off the parent process */ pid = fork(); if (pid < 0) { exit(EXIT_FAILURE); } /* If we got a good PID, then we can exit the parent process. */ if (pid > 0) { exit(EXIT_SUCCESS); } /* Change the file mode mask */ umask(0); /* Open any logs here */ /* Create a new SID for the child process */ sid = setsid(); if (sid < 0) { /* Log the failure */ exit(EXIT_FAILURE); } /* Close out the standard file descriptors */ close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); /* Daemon-specific initialization goes here */ init(); timeval tv; fd_set readfds; if (cfig.tftpConn[0].server) { do { FD_ZERO(&readfds); tv.tv_sec = 20; tv.tv_usec = 0; for (int i = 0; i < MAX_SERVERS && cfig.tftpConn[i].server; i++) FD_SET(cfig.tftpConn[i].sock, &readfds); errno=0; int fdsReady = select(cfig.maxFD, &readfds, NULL, NULL, &tv); //if (errno) // printf("%s\n", strerror(errno)); for (int i = 0; fdsReady > 0 && i < MAX_SERVERS && cfig.tftpConn[i].server; i++) { if (FD_ISSET(cfig.tftpConn[i].sock, &readfds)) { fdsReady--; request *req = (request*)malloc(sizeof(request)); memset(req, 0, sizeof(request)); req->clientsize = sizeof(req->client); errno = 0; req->bytesRecd = recvfrom(cfig.tftpConn[i].sock, (char*) & req->datain, sizeof(ack), 0, (sockaddr*) & req->client, &req->clientsize); req->knock = cfig.tftpConn[i].sock; req->sockInd = i; if (!errno) { if (cfig.hostRanges[0].rangeStart) { DWORD iip = ntohl(req->client.sin_addr.s_addr); BYTE allowed = 0; for (int j = 0; j <= 32 && cfig.hostRanges[j].rangeStart; j++) { if (iip >= cfig.hostRanges[j].rangeStart && iip <= cfig.hostRanges[j].rangeEnd) { allowed = 1; break; } } if (!allowed) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(0); strcpy(req->serverError.errormessage, "Access Denied"); logMess(req, 1); req->bytesSent = sendto(cfig.tftpConn[i].sock, (const char*) & req->serverError, strlen(req->serverError.errormessage) + 5, 0, (sockaddr*) & req->client, req->clientsize); free(req); continue; } } if (req->bytesRecd > 0 && (ntohs(req->datain.opcode) == 1 || ntohs(req->datain.opcode) == 2)) { pthread_create(&req->threadId, 0, ProcessRequest, (void*)req); if (!req->threadId) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(0); strcpy(req->serverError.errormessage, "Thread Creation Error"); logMess(req, 1); req->bytesSent = sendto(cfig.tftpConn[i].sock, (const char*) & req->serverError, strlen(req->serverError.errormessage) + 5, 0, (sockaddr*) & req->client, req->clientsize); free(req); } } else if (req->bytesRecd > 0 && (htons(req->datain.opcode) == 5)) { sprintf(req->serverError.errormessage, "Error Code %i at Client, %s", ntohs(req->clientError.errorcode), req->clientError.errormessage); logMess(req, 1); free(req); } else { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(0); sprintf(req->serverError.errormessage, "Invalid Option Code %i", ntohs(req->datain.opcode)); logMess(req, 1); req->bytesSent = sendto(cfig.tftpConn[i].sock, (const char*) & req->serverError, strlen(req->serverError.errormessage) + 5, 0, (sockaddr*) & req->client, req->clientsize); free(req); } } else { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(0); sprintf(req->serverError.errormessage, "Communication Error"); logMess(req, 1); free(req); } } } } while (true); } for (int i = 0; i < MAX_SERVERS && cfig.tftpConn[i].server; i++) close(cfig.tftpConn[i].sock); }}void *ProcessRequest(void *lpParam){ //printf("here\n"); request *req = (request*)lpParam; req->blksize = 512; req->interval = interval - (interval/2); bool fetchAck = false; req->m_socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); if (req->m_socket == -1) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(0); strcpy(req->serverError.errormessage, "Thread Socket Creation Error"); req->bytesSent = sendto(req->knock, (const char*) & req->serverError, strlen(req->serverError.errormessage) + 5, 0, (sockaddr*) & req->client, req->clientsize); logMess(req, 1); free(req); pthread_exit(NULL); } WORD comport; sockaddr_in service; for (comport = cfig.minport;;comport++) { service.sin_family = AF_INET; service.sin_addr.s_addr = cfig.tftpConn[req->sockInd].server; service.sin_port = htons(comport); if (comport > cfig.maxport) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(0); strcpy(req->serverError.errormessage, "No port is free"); req->bytesSent = sendto(req->knock, (const char*) & req->serverError, strlen(req->serverError.errormessage) + 5, 0, (sockaddr*) & req->client, req->clientsize); logMess(req, 1); clean(req); pthread_exit(NULL); } else if (bind(req->m_socket, (sockaddr*) &service, sizeof(service) ) == -1) continue; else break; } if (connect(req->m_socket, (sockaddr*)&req->client, req->clientsize) == -1) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(0); strcpy(req->serverError.errormessage, "Connect Failed"); req->bytesSent = sendto(req->knock, (const char*) & req->serverError, strlen(req->serverError.errormessage) + 5, 0, (sockaddr*) & req->client, req->clientsize); logMess(req, 1); clean(req); pthread_exit(NULL); } char *temp = (char*) & req->datain; temp += 2; req->filename = temp; temp += strlen(temp) + 1; req->mode = temp; temp += strlen(temp) + 1; req->alias = req->filename; for (int i = 0; i < strlen(req->alias); i++) if (req->alias[i] == '\\') req->alias[i] = '/'; if (strstr(req->alias, "../")) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(2); strcpy(req->serverError.errormessage, "Access violation"); req->bytesSent = send(req->m_socket, (const char*) & req->serverError, strlen(req->serverError.errormessage) + 5, 0); logMess(req, 1); clean(req); pthread_exit(NULL); } if (req->alias[0] == '/') req->alias++; if (!cfig.homes[0].alias[0]) { strcpy(req->path, cfig.homes[0].target); strcat(req->path, req->alias); } else { char *ptr = strchr(req->alias, '/'); if (ptr) { *ptr = 0; ptr++; } else { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(2); sprintf(req->serverError.errormessage, "Missing directory/alias"); req->bytesSent = send(req->m_socket, (const char*) & req->serverError, strlen(req->serverError.errormessage) + 5, 0); logMess(req, 1); clean(req); pthread_exit(NULL); } for (int i = 0; i < 8; i++) { //printf("%s=%i\n", req->alias, cfig.homes[i].alias[0]); if (cfig.homes[i].alias[0] && !strcasecmp(req->alias, cfig.homes[i].alias)) { strcpy(req->path, cfig.homes[i].target); strcat(req->path, ptr); break; } else if (i == 7 || !cfig.homes[i].alias[0]) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(2); sprintf(req->serverError.errormessage, "No such directory/alias"); req->bytesSent = send(req->m_socket, (const char*) & req->serverError, strlen(req->serverError.errormessage) + 5, 0); logMess(req, 1); clean(req); pthread_exit(NULL); } } } if (ntohs(req->datain.opcode) == 1) { errno = 0; if (!strcasecmp(req->mode, "netascii") || !strcasecmp(req->mode, "ascii")) req->file = fopen(req->path, "rt"); else req->file = fopen(req->path, "rb"); if (errno || !req->file) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(1); strcpy(req->serverError.errormessage, "File Not Found"); logMess(req, 1); req->bytesSent = send(req->m_socket, (const char*) & req->serverError, strlen(req->serverError.errormessage) + 5, 0); clean(req); pthread_exit(NULL); } } else { if (!cfig.overwrite) { req->file = fopen(req->path, "rb"); if (req->file) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(6); strcpy(req->serverError.errormessage, "File already exists"); logMess(req, 1); req->bytesSent = send(req->m_socket, (const char*) & req->serverError, strlen(req->serverError.errormessage) + 5, 0); clean(req); pthread_exit(NULL); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -