Guest User

MikelSV TFTP Daemon

a guest
Nov 24th, 2012
273
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // MSV TFTP Daemon 1.0 - 21.11.2012 22:24
  2. // 1.1 - 24.11.2012 2:40
  3.  
  4. // Used MSVLibrsry code, Brain, Reverse engineering.
  5. // Not used: FAQ, RFC.
  6.  
  7. // DEL: OS: +(available) Windows, -(unavailable, temporarily) Linux, ?(oh my god. maybe) Android.
  8. // NEW: OS: +(available) Windows, (available) Linux, (oh noo, i'm next) Android.
  9.  
  10. // I want:
  11. // test, test, test...
  12. // Add config.
  13. // Add logs.
  14. // Add tftp extensions.
  15. // Read Only. Add Write file.
  16. // Create tftp client.
  17. // Make packages: rpm, ebuild, deb.
  18. // Send packages to repositary.
  19. // Android, i see you.
  20.  
  21. // DEL: Problem: send last block. Close file or wait? <Yes>. Last block lose. -> Fail.
  22.  
  23. // Main(): go to far far down.
  24.  
  25. #ifdef WIN32
  26. #include <WinSock2.h>
  27. #include <io.h>
  28. #include <direct.h>
  29.  
  30. #define lseek64 _lseeki64
  31.  
  32. typedef __int64 int64;
  33. typedef int socklen_t;
  34.  
  35. #pragma comment(lib,"Ws2_32.lib")
  36. #else // linux way
  37. #include <unistd.h>
  38. #include <arpa/inet.h>
  39. #include <sys/socket.h>
  40.  
  41. #define SOCKADDR SOCKADDR_IN
  42. #define SOCKADDR sockaddr
  43. #define SOCKADDR_IN sockaddr_in
  44. #define O_BINARY 0
  45.  
  46. #define FILE_BEGIN 0
  47. #define FILE_CUR 1
  48. #define FILE_END 2
  49.  
  50. typedef long long int64;
  51. typedef int SOCKET;
  52.  
  53. #define memcpy memmove
  54. #define closesocket(sock) close(sock)
  55. void Sleep(unsigned int i){ usleep((int64)i*1000); return ; }
  56. #endif
  57.  
  58.  
  59. #ifdef WIN32
  60. #ifndef WINCE
  61. HANDLE _std_input_handle = GetStdHandle(STD_INPUT_HANDLE);
  62. HANDLE _std_output_handle = GetStdHandle(STD_OUTPUT_HANDLE);
  63. #endif
  64. #endif
  65.  
  66.  
  67. // all systems
  68. #include <stdio.h>
  69. #include <time.h>
  70. #include <fcntl.h>
  71. #include <string.h>
  72. #include <stdlib.h>
  73. #include <sys/stat.h>
  74.  
  75. ///////////////////////////////////////////////////////////////////////////////////// For Me
  76. #define _del(v){ if(v) free(v); }
  77. #define _deln(v){ if(v){ free(v); v=0; } }
  78. #define _newn(sz) (unsigned char*)malloc(sz)
  79.  
  80. ///////////////////////////////////////////////////////////////////////////////////// Strings
  81. class VString{
  82. public:
  83.     unsigned char *data;
  84.     unsigned int sz;
  85.  
  86.     void Init(){ data=0; sz=0; }
  87.  
  88.     VString(){ Init(); }
  89.     VString(const VString &line){ data=line; sz=line.sz;  }
  90.     VString(const char *line){ data=(unsigned char*)line; sz=strlen((const char*)line); }
  91.     VString(const unsigned char *line){ data=(unsigned char*)line; sz=strlen((const char*)line); }
  92.     VString(const char *line, const unsigned int s){ data=(unsigned char*)line; sz=s; }
  93.     VString(const unsigned char *line, const unsigned int s){ data=(unsigned char *)line; sz=s; }
  94.    
  95.     VString& operator=(VString line){ data=line; sz=line; return *this; }
  96.     VString& operator=(unsigned char* line){ data=line; sz=strlen((const char*)line); return *this; }
  97.     VString& operator=(char* line){ data=(unsigned char*)line; sz=strlen((const char*)line); return *this; }
  98.    
  99.     VString& set(VString line){ return setu(line.data, line.sz); return *this; }
  100.     VString& set(char* line, const unsigned int size){ sz=size; data=(unsigned char*)line; return *this; }
  101.     VString& setu(unsigned char* line, const unsigned int size){ sz=size; data=(unsigned char*)line; return *this; }
  102.  
  103.     VString str(const int p){
  104.         if(sz<=p) return VString();
  105.         return VString(data+p, sz-p);
  106.     }
  107.    
  108.     operator void*()const { return data; }
  109.     operator char*()const { return (char*)data; }
  110.     operator unsigned char*()const { return data; }
  111.     operator unsigned int()const { return sz; }
  112. //  operator VString(){ return *this; }
  113.  
  114.     char *rchar()const { return (char*)data; }
  115.     unsigned char *uchar()const { return data; }
  116.     char *end()const { return (char*)data+sz; }
  117.     unsigned char *endu()const { return data+sz; }
  118.  
  119.     void Clean(){ Init(); }
  120. };
  121.  
  122. class MString: public VString{
  123. //  unsigned char *data;
  124. //  unsigned int sz;
  125.  
  126. public:
  127.     void Init(){ _deln(data); sz=0; }
  128.     MString(){ data=0; sz=0; }
  129.    
  130. protected:
  131.     void MStringNew(const void*line){ // optimize
  132.         if(!sz){ data=0; return ; }
  133.         data=_newn(sz+1);
  134.         if(line) memcpy(data, line, sz);
  135.         data[sz]=0;
  136.         return ;
  137.     }
  138.  
  139. public:
  140.     MString(const VString line){ sz=line.sz; MStringNew(line); }
  141.     MString(const unsigned char *line, const unsigned int s){ sz=s; MStringNew(line); }
  142.        
  143.     MString& operator=(const VString line){ sz=line; unsigned char *odata=data; MStringNew(line); _deln(odata); return *this; }
  144.     MString& operator=(const unsigned char* line){ unsigned char *odata=data; sz=strlen((const char*)line); MStringNew(line); _deln(odata); return *this; }
  145.     MString& operator=(const char* line){ unsigned char *odata=data; sz=strlen((const char*)line); MStringNew(line); _deln(odata); return *this; }
  146.  
  147.     ~MString(){ Init(); }
  148.  
  149.     MString& set(VString line){ sz=line; unsigned char *odata=data; MStringNew(line); _deln(odata); return *this; }
  150.     MString& set(char* line, const unsigned int size){ sz=size; unsigned char *odata=data; MStringNew(line); _deln(odata); return *this; }
  151.     MString& setu(unsigned char* line, const unsigned int size){ sz=size; unsigned char *odata=data; MStringNew(line); _deln(odata); return *this; }
  152.  
  153.     MString str(const int p){
  154.         if(sz<=p) return MString();
  155.         return MString(data+p, sz-p);
  156.     }
  157.  
  158.     void Clean(){ Init(); }
  159. };
  160.  
  161. int compare(unsigned char *l1, unsigned int s1, unsigned char *l2, unsigned int s2){
  162.     if(s1!=s2) return 0;
  163.     for(int i=0; i<s1; i++){ if(*l1++!=*l2++) return 0; }
  164.     return 1;
  165. }
  166.  
  167. int operator==(const VString &l1, const VString &l2){ return compare(l1, l1, l2, l2); }
  168. int operator==(const unsigned char *l1, const VString &l2){ return compare((unsigned char*)l1, strlen((char*)l1), l2, l2); }
  169. int operator==(const VString &l1, const unsigned char *l2){ return compare(l1, l1, (unsigned char*)l2, strlen((char*)l2)); }
  170. int operator==(const char *l1, const VString &l2){ return compare((unsigned char*)l1, strlen((char*)l1), l2, l2); }
  171. int operator==(const VString &l1, const char *l2){ return compare(l1, l1, (unsigned char*)l2, strlen((char*)l2)); }
  172.  
  173.  
  174. ///////////////////////////////////////////////////////////////////////////////////// String Operations
  175.  
  176. int rtms(unsigned char *to, unsigned char *fr, unsigned int frs, unsigned char *&line){ //read to symbol
  177.     if(!line || !fr || !frs) return 0;
  178.     unsigned char *lfr, *tfr, *ln;
  179.     to-=frs-1;
  180.  
  181.     for(line; line<to; line++){
  182.         if(*line==*fr){
  183.             lfr=fr+1; tfr=fr+frs; ln=line+1;
  184.             for(lfr; lfr<tfr; lfr++){ if(*ln++!=*lfr){ break; } }
  185.             if(lfr==tfr){ return 1; }
  186.         }
  187.     } line=to+(frs-1); return 0;
  188. }
  189.  
  190. VString PartLine(VString line, VString &two, VString el){
  191.     unsigned char *pos=line;
  192.     if(!rtms(line.endu(), el, el, pos)){ two.Clean(); return line; }
  193.     two.setu(pos+el.sz, line.endu()-pos-el.sz);
  194.     return VString(line.uchar(), pos-line.uchar());
  195. }
  196.  
  197.  
  198. ///////////////////////////////////////////////////////////////////////////////////// Print
  199. inline int print(const VString &line){ if(!line) return 0;
  200. #ifdef WIN32
  201.     DWORD wr;
  202.     return WriteFile(_std_output_handle, line, line, &wr, 0); //printf(line);
  203. #else
  204.     return write(1, line, line);
  205. #endif
  206. }
  207.  
  208. // multiprint
  209. inline int print(const VString &l1, const VString &l2){
  210.     int r=print(l1); r=print(l2) && r; return r;
  211. }
  212. inline int print(const VString &l1, const VString &l2, const VString &l3){
  213.     int r=print(l1); r=print(l2) && r; r=print(l3) && r; return r;
  214. }
  215.  
  216. ///////////////////////////////////////////////////////////////////////////////////// Socket Options
  217. int OpenUDPPort(unsigned short port, const char*ip=0){
  218. SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if(sock==-1) return 0;
  219.  
  220. SOCKADDR_IN sin;
  221.     sin.sin_family = AF_INET;
  222.     sin.sin_port = htons(port);
  223.     if (ip) sin.sin_addr.s_addr = inet_addr(ip);
  224.     else sin.sin_addr.s_addr = INADDR_ANY;
  225.  
  226. //int i=1;
  227. //if(setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char*)&i, 4)) print("SOCKOPT ERROR\r\n");
  228. //if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&i, sizeof(i))) print("SOCKOPT ERROR\r\n");
  229. //  KeepAlive(sock);
  230.     int err = bind(sock, (SOCKADDR*)&sin, sizeof(sin) ); if(err<0){ closesocket(sock); return 0; }
  231. //err = listen( sock, SOMAXCONN); if(err<0) { closesocket(sock); return 0; }
  232.     return (int)sock;
  233. }
  234.  
  235. ///////////////////////////////////////////////////////////////////////////////////// Defines
  236. #define S1K 1024
  237. #define S8K (1024*8)
  238.  
  239. ///////////////////////////////////////////////////////////////////////////////////// File IO
  240. #ifdef WIN32
  241. #define O_CREAT     _O_CREAT
  242. #define O_RDONLY    _O_RDONLY
  243. #define S_IREAD     _S_IREAD
  244. #define S_IWRITE    _S_IWRITE
  245. #endif
  246.  
  247. int CreateFile(char* file, int op, int pm){ return open(file, op|O_BINARY, pm); }
  248. int ReadFile(int fl, unsigned char* buf, unsigned int sz){ return read(fl, buf, sz); }
  249. int WriteFile(int fl, unsigned char* buf, unsigned int sz){ return write(fl, buf, sz); }
  250. int64 SetFilePointer(int fl, int64 pos, int origin=FILE_BEGIN){ return lseek64(fl, pos, origin); }
  251. int CloseHandle(int fl){ return close(fl); }
  252.  
  253. #define IsHandle(h) ((h) && ((int)h)!=-1)
  254. #define ishandle(h) ((h) && ((int)h)!=-1)
  255.  
  256. bool IsFile(VString file){
  257.     int fl; fl=CreateFile(file, O_RDONLY, S_IREAD| S_IWRITE);
  258.     if(!ishandle(fl)) return 0;
  259.     CloseHandle(fl); return 1;
  260. }
  261.  
  262. ///////////////////////////////////////////////////////////////////////////////////// Special
  263. unsigned int time(){ return time(0); }
  264.  
  265. ///////////////////////////////////////////////////////////////////////////////////// Hmm. Class for open files
  266. class tftp_data{
  267. public:
  268.     unsigned int ip; unsigned short port; unsigned int time, fl;
  269.     MString file;
  270. };
  271.  
  272. class tftp_d{
  273.     tftp_data tdata[128]; int tdatai; // may create: elenents list
  274.  
  275. public:
  276.     tftp_d(){ tdatai=0; memset(tdata, 0, sizeof(tdata)); } // may use: for .. tdata[i].time=0;
  277.  
  278.     tftp_data* Get(unsigned int ip, unsigned short port){
  279.         for(int k=0; k<sizeof(tdata)/sizeof(tftp_data); k++){
  280.             if(tdata[k].ip==ip && tdata[k].port==port) return &tdata[k];
  281.         }
  282.         return 0;
  283.     }
  284.  
  285.     tftp_data* Add(unsigned int ip, unsigned short port, VString file){
  286.         int i=-1;
  287.  
  288.         for(int k=0; k<sizeof(tdata)/sizeof(tftp_data); k++){
  289.             if(!tdata[k].time){ i=k; break; } // don't dublicate tdata=...
  290.         }
  291.  
  292.         if(i==-1) i=DelOld(1); else DelOld(); // hmm. no free. kill one?
  293.        
  294.         tdata[i].ip=ip; tdata[i].port=port; tdata[i].file=file; tdata[i].time=time();
  295.         return &tdata[i];
  296.     }
  297.  
  298.     int DelOld(int r=0){
  299.         int d=0; unsigned int tm=time(); // del more 1 hour? 3600 sec.
  300.         for(int k=0; k<sizeof(tdata)/sizeof(tftp_data); k++){
  301.             if(tdata[d].time+3600<tm){
  302.                 tdata[k].time=0; tdata[k].ip=0; tdata[k].port=0; tdata[k].file.Clean();
  303.                 if(tdata[k].fl){ CloseHandle(tdata[k].fl); tdata[k].fl=0; }            
  304.             }
  305.             if(tdata[d].time>tdata[k].time) d=k;
  306.         }
  307.        
  308.         return d;
  309.     }
  310.  
  311.     int Del(tftp_data* data){
  312.         if(!data) return 0;
  313.         //int pos=data-&tdata;
  314.         if(data->fl){ CloseHandle(data->fl); tdata->fl=0; }
  315.         data->time=0; data->ip=0; data->port=0; data->file.Clean();
  316.         return 1;
  317.     }
  318.    
  319. }tftp_d;
  320.  
  321. ///////////////////////////////////////////////////////////////////////////////////// TFTP
  322. #define TFTP_RRQ    1
  323. #define TFTP_WRQ    2
  324. #define TFTP_DATA   3
  325. #define TFTP_ACK    4
  326. #define TFTP_ERR    5
  327.  
  328. int TFTPError(int err, VString text, unsigned char *buf, unsigned int bufs){
  329.     if(bufs<5) return 0;
  330.  
  331.     if(text=="-"){
  332.         switch(err){
  333.             case 0: text="Not defined, see error message (if any)."; break;
  334.             case 1: text="File not found."; break;
  335.             case 2: text="Access violation."; break;
  336.             case 3: text="Disk full or allocation exceeded."; break;
  337.             case 4: text="Illegal TFTP operation."; break;
  338.             case 5: text="Unknown transfer ID."; break;
  339.             case 6: text="File already exists."; break;
  340.             case 7: text="No such user."; break;
  341.         }
  342.     }
  343.  
  344.     int bufi=5;
  345.     buf[0]=0; buf[1]=TFTP_ERR; *(unsigned short*)(buf+2)=ntohs(err);
  346.     if(bufs<5+text.sz) text.sz=bufs-5;
  347.     memcpy(buf+4, text, text); bufi+=text.sz;
  348.     buf[bufi-1]=0;
  349.     return bufi;
  350. }
  351.  
  352. int TFTPSend(SOCKET sock, unsigned int cip, unsigned int cport, unsigned char *buf, int bufi){
  353.     // send
  354.     sockaddr_in from; int fromlen=sizeof(from);
  355.     from.sin_family = AF_INET;
  356.     from.sin_addr.s_addr=ntohl(cip);
  357.     from.sin_port=htons(cport);
  358.  
  359.     return sendto(sock, (char*)buf, bufi, 0, (struct sockaddr*)&from, fromlen);
  360. }
  361.  
  362. int RecvUDP(SOCKET sock, unsigned int cip, unsigned int cport, unsigned char* rcvbuf, int rcvi){
  363.     if(rcvi<2) return 0;
  364.  
  365.     unsigned char buf[S1K]; int bufi=0;
  366.     unsigned short op=ntohs(*(unsigned short*)rcvbuf);
  367.  
  368.     if(op==TFTP_RRQ){
  369.         VString fl=VString(rcvbuf+2, rcvi-2), type, o, t;
  370.         fl=PartLine(fl, t, VString("\x00", 1));
  371.         type=PartLine(t, t, VString("\x00", 1));
  372.  
  373.         MString file=fl; //file.Add("./", fl);
  374.         if(!IsFile(file)){ print("Request file: ", file, ". Not found.\r\n");
  375.             bufi=TFTPError(1, "-", buf, sizeof(buf));
  376.             TFTPSend(sock, cip, cport, buf, bufi);
  377.             return 0;
  378.         }
  379.  
  380.         t=file; o=PartLine(t, t, "..");
  381.         if(!o || t){
  382.             print("Hacher found! Get file: '", file, "'. Get out!\r\n");
  383.             bufi=TFTPError(2, "-", buf, sizeof(buf));
  384.             TFTPSend(sock, cip, cport, buf, bufi);
  385.             return 0;
  386.         }
  387.  
  388.         tftp_data* tdata=tftp_d.Add(cip, cport, file);
  389.  
  390.         tdata->fl=CreateFile(file, O_RDONLY, 0);
  391.  
  392.         buf[0]=0; buf[1]=TFTP_DATA; *(unsigned short*)(buf+2)=ntohs(1);
  393.         ReadFile(tdata->fl, buf+4, 512);
  394.  
  395.         TFTPSend(sock, cip, cport, buf, 516); print("Request file: '", file, ". Send first block. \r\n");
  396.         return 1;
  397.     }
  398.     else if(op==TFTP_ACK){
  399.         unsigned short bl=ntohs(*(unsigned short*)(rcvbuf+2));
  400.         buf[0]=0; buf[1]=TFTP_DATA; *(unsigned short*)(buf+2)=ntohs(bl+1);
  401.  
  402.         tftp_data* tdata=tftp_d.Get(cip, cport);
  403.         if(!tdata){ print("No pervous request!\r\n");
  404.             bufi=TFTPError(5, "-", buf, sizeof(buf));
  405.             TFTPSend(sock, cip, cport, buf, bufi);
  406.             return 0;
  407.         }
  408.  
  409.         //print("block: ", itos(bl), "\r\n");
  410.         printf("ACK: %d. Send next block.\r\n", bl);
  411.  
  412.         unsigned int p=SetFilePointer(tdata->fl, bl*512, FILE_BEGIN);
  413.         int rd=ReadFile(tdata->fl, buf+4, 512);
  414.         TFTPSend(sock, cip, cport, buf, 4+rd);
  415.         if(!rd){
  416.             printf("End Of File. Close.\r\n", bl);
  417.             tftp_d.Del(tdata);
  418.         }
  419.         return 1;
  420.     }else{
  421.         int z=0;
  422.     }
  423.  
  424.     return 1;
  425. }
  426.  
  427. ///////////////////////////////////////////////////////////////////////////////////// Main
  428. int main(int args, char* arg[]){
  429. #ifdef WIN32
  430.     WSADATA WsaData; WSAStartup (MAKEWORD( 2, 2 ), &WsaData);
  431. #endif
  432.  
  433. // server configurations
  434.     int openport=69;
  435.     chdir("./"); // set directory
  436.  
  437. //openport
  438.     SOCKET osock=OpenUDPPort(openport);
  439.     if(!osock){ printf("Ooops. UDP port not opened. Exit."); return 1; }
  440.  
  441. // recv
  442.     sockaddr_in from, local; int fromlen=sizeof(from);
  443.     unsigned char rcvbuf[S8K], *rcv=(unsigned char*)&rcvbuf; int rcvi=0;
  444.  
  445.     while(1){
  446.         rcvi=recvfrom(osock, (char*)rcv, S8K, 0, (struct sockaddr*)&from, (socklen_t*)&fromlen);
  447.         if(rcvi==0){ Sleep(1); continue; }
  448.         else if(rcvi<0){ break; }
  449.  
  450.         RecvUDP(osock, ntohl(from.sin_addr.s_addr), htons(from.sin_port), rcvbuf, rcvi);
  451.     }
  452.  
  453.     printf("Exit.\r\n");
  454.  
  455.     return 0;
  456. }
RAW Paste Data