int STREAMWriteLine(const char *Buffer, STREAM *S) { int result; if (StrLen(Buffer) < 1) return(FALSE); result=STREAMWriteBytes(S,Buffer,strlen(Buffer)); if (result < 0) return(result); if (S->Flags & FLUSH_LINE) result=STREAMFlush(S); return(result); }
int ConnectHopHTTPSProxy(STREAM *S, const char *Proxy, const char *Destination) { char *Tempstr=NULL, *Token=NULL; char *Proto=NULL, *Host=NULL, *User=NULL, *Pass=NULL; const char *ptr=NULL; int result=FALSE, Port; ParseConnectDetails(Proxy, &Token, &Host, &Token, &User, &Pass, NULL); Port=atoi(Token); if (! (S->State & SS_INITIAL_CONNECT_DONE)) { if (Port==0) Port=443; S->in_fd=TCPConnect(Host,Port,0); S->out_fd=S->in_fd; if (S->in_fd == -1) { RaiseError(0, "ConnectHopHTTPSProxy", "failed to connect to proxy at %s:%d", Host, Port); return(FALSE); } } ptr=Destination; if (strncmp(ptr,"tcp:",4)==0) ptr+=4; Tempstr=FormatStr(Tempstr,"CONNECT %s HTTP/1.1\r\n\r\n",ptr); STREAMWriteLine(Tempstr,S); STREAMFlush(S); Tempstr=STREAMReadLine(Tempstr,S); if (Tempstr) { StripTrailingWhitespace(Tempstr); ptr=GetToken(Tempstr," ",&Token,0); ptr=GetToken(ptr," ",&Token,0); if (*Token=='2') result=TRUE; else RaiseError(0, "ConnectHopHTTPSProxy", "proxy request to %s:%d failed. %s", Host, Port, Tempstr); while (StrLen(Tempstr)) { Tempstr=STREAMReadLine(Tempstr,S); StripTrailingWhitespace(Tempstr); } } else RaiseError(0, "ConnectHopHTTPSProxy", "proxy request to %s:%d failed. Server Disconnectd.", Host, Port); DestroyString(Tempstr); DestroyString(Token); DestroyString(Host); DestroyString(User); DestroyString(Pass); return(result); }
int STREAMDisassociateFromFD(STREAM *Stream) { int fd; if (! Stream) return(-1); fd=Stream->in_fd; STREAMFlush(Stream); DestroyString(Stream->InputBuff); DestroyString(Stream->OutputBuff); DestroyString(Stream->Path); free(Stream); return(fd); }
int HTTPServerExecCGI(STREAM *ClientCon, HTTPSession *Session, const char *ScriptPath) { char *Tempstr=NULL; int i; if (StrLen(Session->Group) && (! SwitchGroup(Session->Group))) { LogToFile(Settings.LogPath,"WARN: Failed to switch to group '%s' to execute script: %s",Session->Group, ScriptPath); } //Switch user. ALAYA WILL NOT RUN SCRIPTS AS ROOT! if ((geteuid()==0) && (! SwitchUser(Session->RealUser))) { LogToFile(Settings.LogPath,"ERROR: Failed to switch to user '%s' to execute script: %s",Session->RealUser, ScriptPath); return(FALSE); } if (geteuid()==0) { HTTPServerSendHTML(ClientCon, NULL, "403 Forbidden","Alaya will not run .cgi programs as 'root'.<br>\r\nTry setting 'Default User' in config file or command line."); LogToFile(Settings.LogPath, "Failed to switch user to '%s' for running a .cgi program. Will not run programs as 'root'. Set 'DefaultUser' in config file or command line.",Session->RealUser); } else { Session->ResponseCode=CopyStr(Session->ResponseCode,"200 OK"); HTTPServerSendHeaders(ClientCon, Session, HEADERS_CGI); STREAMFlush(ClientCon); SetupEnvironment(Session, ScriptPath); Tempstr=FindScriptHandlerForScript(Tempstr,ScriptPath); if (Tempstr) LogToFile(Settings.LogPath,"Execute script: %s using handler '%s'",ScriptPath,Tempstr); else LogToFile(Settings.LogPath,"Execute script: %s QUERY_STRING= '%s'",ScriptPath,getenv("QUERY_STRING")); //Only do this late! Otherwise logging won't work. for (i=3; i < 1000; i++) close(i); if (StrLen(Tempstr)) execl(Tempstr, Tempstr, ScriptPath,NULL); else execl(ScriptPath,ScriptPath,NULL); /*If this code gets executed, then 'execl' failed*/ HTTPServerSendHTML(ClientCon, Session, "403 Forbidden","You don't have permission for that."); //Logging won't work after we've closed all the file descriptors! LogToFile(Settings.LogPath,"Cannot execute script: %s",ScriptPath); } //if we get there then, for whatever reason, our script didn't run DestroyString(Tempstr); return(FALSE); }
pid_t HandleChildRegisterRequest(STREAM *S, char *Data) { char *Tempstr=NULL, *Host=NULL, *ptr; int Flags=0; time_t LastTime; ptr=GetToken(Data,":",&Host,0); if (*ptr=='A') Flags |= LOGIN_CHECK_ALLOWED; if (*ptr=='I') Flags |= LOGGED_IN; if (*ptr=='F') Flags |= LOGIN_FAIL; if (*ptr=='C') Flags |= LOGIN_CHANGE; ptr=GetVar(Settings.HostConnections,Host); LastTime=time(NULL); if (Flags & LOGIN_CHECK_ALLOWED) { if (ptr && (strcmp(ptr,"logout")==0)) { SetVar(Settings.HostConnections,Host,""); STREAMWriteLine("logout\n",S); } else { STREAMWriteLine("okay\n",S); } } else if (Flags & LOGIN_CHANGE) { Tempstr=CopyStr(Tempstr,"logout"); SetVar(Settings.HostConnections,Host,Tempstr); STREAMWriteLine("okay\n",S); } else { if (Flags & LOGGED_IN) LastTime=0; Tempstr=FormatStr(Tempstr,"%ld",LastTime); SetVar(Settings.HostConnections,Host,Tempstr); STREAMWriteLine("okay\n",S); } STREAMFlush(S); DestroyString(Tempstr); DestroyString(Host); return(0); }
int ConnectHopSocks(STREAM *S, int Type, const char *Host, int Port, const char *User, const char *Pass, const char *Path) { char *Tempstr=NULL; uint8_t *ptr; char *Token=NULL; const char *tptr; int result, RetVal=FALSE; S->in_fd=ConnectToHost(Host,Port,0); S->out_fd=S->in_fd; if (S->in_fd == -1) return(FALSE); //Horrid binary protocol. Tempstr=SetStrLen(Tempstr, StrLen(User) +20); ptr=Tempstr; *ptr=4; //version number ptr++; *ptr=1; //outward connection (2 binds a port for incoming) ptr++; tptr=Path; if (strncmp(tptr,"tcp:",4)==0) tptr+=4; tptr=GetToken(tptr,":",&Token,0); //destination port *((uint16_t *) ptr) =htons(atoi(tptr)); ptr+=2; //destination host *((uint32_t *) ptr) =StrtoIP(Token); ptr+=4; strcpy(ptr,User); ptr+=StrLen(User); ptr++; STREAMWriteBytes(S,Tempstr,(char *)ptr-Tempstr); STREAMFlush(S); result=STREAMReadBytes(S,Tempstr,8); //Positive response will be 0x00 0x5a 0x00 0x00 0x00 0x00 0x00 0x00 //although only the leading two bytes (0x00 0x5a, or \0Z) matters if ((result==8) && (Tempstr[0]=='\0') && (Tempstr[1]=='Z')) RetVal=TRUE; DestroyString(Tempstr); DestroyString(Token); return(RetVal); }
int IDriveCloseFileWrite(TFileStore *FS, STREAM *S) { char *Tempstr=NULL, *Error=NULL, *ptr; ListNode *Vars=NULL; HTTPInfoStruct *Info; int result=FALSE, val; Info=(HTTPInfoStruct *) FS->Extra; if (Info) { Tempstr=MCopyStr(Tempstr,"\r\n--",STREAMGetValue(S,"Boundary"),"--\r\n",NULL); STREAMWriteLine(Tempstr,S); STREAMFlush(S); HTTPTransact(Info); /* <?xml version="1.0" encoding="UTF-8"?> <tree message="SUCCESS"> <item filename="autoget.c" filesize="27620" lmd="1969/12/31 16:00:00" message="SUCCESS"/> </tree> */ val=HTTPReadDocument(S, &Tempstr); if (Settings.Flags & FLAG_VERBOSE) printf("\n%s\n",Tempstr); Vars=ListCreate(); IDriveParseResponse(Tempstr, Vars); Tempstr=CopyStr(Tempstr,GetVar(Vars,"message")); if (strcmp(Tempstr,"SUCCESS")==0) { val=atoi(STREAMGetValue(S,"Transfer-Size")); if (val==atoi(GetVar(Vars,"filesize"))) result=TRUE; else result=ERR_INTERRUPTED; } else { SetVar(FS->Vars,"Error",GetVar(Vars,"desc")); result=ERR_CUSTOM; } } DestroyString(Tempstr); return(result); }
double STREAMTell(STREAM *S) { double pos; if (S->OutEnd > 0) STREAMFlush(S); #ifdef _LARGEFILE64_SOURCE pos=(double) lseek64(S->in_fd,0,SEEK_CUR); #else pos=(double) lseek(S->in_fd,0,SEEK_CUR); #endif pos-=(S->InEnd-S->InStart); return(pos); }
int STREAMDeleteDataProcessor(STREAM *S, char *Class, char *Name) { ListNode *Curr; char *Tempstr=NULL; int len; STREAMFlush(S); Tempstr=MCopyStr(Tempstr,Class,":",Name,NULL); Curr=ListFindNamedItem(S->ProcessingModules,Tempstr); ListDeleteNode(Curr); DestroyString(Tempstr); return(TRUE); }
void AlayaLog(char *Msg) { char *Tempstr=NULL; if (ParentProcessPipe) { Tempstr=MCopyStr(Tempstr,"LOG ",Msg, "'\n",NULL); STREAMWriteLine(Tempstr,ParentProcessPipe); STREAMFlush(ParentProcessPipe); } else LogToFile(Settings.LogPath,Msg); DestroyString(Tempstr); }
char *TerminalReadText(char *RetStr, int Flags, STREAM *S) { int inchar, len=0; char outchar; inchar=STREAMReadChar(S); while (inchar != EOF) { if (Flags & TERM_SHOWTEXT) outchar=inchar & 0xFF; if (Flags & TERM_SHOWSTARS) { if ((outchar & 0xFF) =='\n') outchar=inchar & 0xFF; else if ((outchar & 0xFF) =='\b') outchar=inchar & 0xFF; else outchar='*'; } if (Flags & TERM_SHOWTEXTSTARS) { switch (inchar) { case '\n': case '\r': case 0x08: break; default: if (len > 0) STREAMWriteString("\x08*",S); break; } outchar=inchar & 0xFF; } STREAMWriteBytes(S, &outchar,1); STREAMFlush(S); if (inchar == '\n') break; if (inchar == '\r') break; RetStr=AddCharToBuffer(RetStr,len++, inchar & 0xFF); inchar=STREAMReadChar(S); } return(RetStr); }
off_t STREAMSendFile(STREAM *In, STREAM *Out, off_t Max) { char *Buffer=NULL; int BuffSize=BUFSIZ; off_t val, result=SENDFILE_FAILED; #ifdef USE_SENDFILE //if we are not using ssl and not using processor modules, we can use //kernel-level copy! #include <sys/sendfile.h> val=In->Flags | Out->Flags; if ((! (val & SF_SSL)) && (ListSize(In->ProcessingModules)==0) && (ListSize(Out->ProcessingModules)==0)) { val=0; STREAMFlush(Out); result=sendfile(Out->out_fd, In->in_fd,0,BUFSIZ); while (result > 0) { val+=result; if ((Max > 0) && (val >= Max)) break; result=sendfile(Out->out_fd, In->in_fd,0,BUFSIZ); } } #endif if (result==SENDFILE_FAILED) { val=0; Buffer=SetStrLen(Buffer,BuffSize); result=STREAMReadBytes(In,Buffer,BuffSize); while (result >=0) { val+=STREAMWriteBytes(Out,Buffer,result); if ((Max > 0) && (val >= Max)) break; result=STREAMReadBytes(In,Buffer,BuffSize); } } DestroyString(Buffer); return(val); }
int ProxyControlConnect(TSession *Session, char *Host, int Port) { char *Tempstr=NULL; int fd, result=FALSE; if (StrLen(Host)==0) { SendLoggedLine(Session,"421 ERROR: Proxy cannot connect. No destination host."); } else { Tempstr=IPCRequest(Tempstr, Session, "GetIP", Host); if (strcmp(Tempstr,"DENIED")==0) { Tempstr=FormatStr(Tempstr,"421 ERROR: Proxy connection denied for host %s:%d",Host,Port); SendLoggedLine(Session,Tempstr); } else { fd=ConnectToHost(Tempstr,Port,FALSE); if (fd==-1) { Tempstr=FormatStr(Tempstr,"421 ERROR: Proxy cannot connect to host %s:%d",Host,Port); SendLoggedLine(Session,Tempstr); } else { Session->ProxySock=STREAMFromFD(fd); result=TRUE; do { Tempstr=STREAMReadLine(Tempstr,Session->ProxySock); STREAMWriteLine(Tempstr,Session->ClientSock); } while ( (Tempstr[3]=='-') || (isspace(Tempstr[0])) ); STREAMFlush(Session->ClientSock); } } } DestroyString(Tempstr); return(result); }
pid_t HandlePostFileRequest(STREAM *ClientCon, char *Data) { HTTPSession *Response; STREAM *S; char *Tempstr=NULL; pid_t pid; pid=fork(); if (pid==0) { Response=ParseSessionInfo(Data); Tempstr=FindFileInPath(Tempstr,Response->Path,Response->SearchPath); Response->Path=CopyStr(Response->Path, Tempstr); if (! SwitchGroup(Response->Group)) { LogToFile(Settings.LogPath,"WARN: Failed to switch to group '%s' when posting '%s'", Response->RealUser, Tempstr); } if (! SwitchUser(Response->RealUser)) { LogToFile(Settings.LogPath,"ERROR: Failed to switch to user '%s' when posting to document '%s'", Tempstr); LogFileFlushAll(TRUE); _exit(0); } LogToFile(Settings.LogPath,"SWITCH USER: '******' posting document '%s'", Response->RealUser, Response->Group, Tempstr); STREAMWriteLine("READY\n",ClientCon); STREAMFlush(ClientCon); HTTPServerHandlePost(ClientCon, Response); //exit 1 means that we can keep connection alive for re-use LogFileFlushAll(TRUE); if (Response->Flags & SESSION_KEEPALIVE) _exit(1); _exit(0); } else ClientCon->State |= SS_EMBARGOED; DestroyString(Tempstr); return(pid); }
int PipeCommandProcessorWrite(TProcessingModule *ProcMod, const char *InData, int InLen, char **OutData, int *OutLen, int Flush) { STREAM *S; S=(STREAM *) ProcMod->Data; if (InLen > 0) { STREAMWriteBytes(S,InData,InLen); STREAMFlush(S); } if (Flush) { if (S->out_fd > -1) close(S->out_fd); S->out_fd=-1; } else if (! STREAMCheckForBytes(S)) return(0); return(STREAMReadBytes(S,*OutData,*OutLen)); }
STREAM *STREAMSelect(ListNode *Streams, struct timeval *tv) { fd_set SelectSet; STREAM *S; ListNode *Curr; int highfd=0, result; FD_ZERO(&SelectSet); Curr=ListGetNext(Streams); while (Curr) { S=(STREAM *) Curr->Item; if (! (S->State & SS_EMBARGOED)) { //Pump any data in the stream STREAMFlush(S); if (S->InEnd > S->InStart) return(S); FD_SET(S->in_fd,&SelectSet); if (S->in_fd > highfd) highfd=S->in_fd; } Curr=ListGetNext(Curr); } result=select(highfd+1,&SelectSet,NULL,NULL,tv); if (result > 0) { Curr=ListGetNext(Streams); while (Curr) { S=(STREAM *) Curr->Item; if (FD_ISSET(S->in_fd,&SelectSet)) return(S); Curr=ListGetNext(Curr); } } return(NULL); }
int SMTPInteract(const char *Line, STREAM *S) { char *Tempstr=NULL; int result=FALSE; if (StrValid(Line)) STREAMWriteLine(Line, S); STREAMFlush(S); Tempstr=SMTPRead(Tempstr, S); /* syslog(LOG_DEBUG,"mail >> %s",Line); syslog(LOG_DEBUG,"mail << %s",Tempstr); */ if ( StrValid(Tempstr) && ( (*Tempstr=='2') || (*Tempstr=='3') ) ) result=TRUE; DestroyString(Tempstr); return(result); }
pid_t HandleGetFileRequest(STREAM *ClientCon, char *Data) { HTTPSession *Response; char *Tempstr=NULL; pid_t pid; pid=fork(); if (pid==0) { Response=ParseSessionInfo(Data); Tempstr=FindFileInPath(Tempstr,Response->Path,Response->SearchPath); if (! SwitchGroup(Response->Group)) { LogToFile(Settings.LogPath,"WARN: Failed to switch to group '%s' when getting document '%s'", Response->RealUser, Tempstr); } if (! SwitchUser(Response->RealUser)) { LogToFile(Settings.LogPath,"ERROR: Failed to switch to user '%s' when getting document '%s'", Tempstr); LogFileFlushAll(TRUE); _exit(0); } STREAMWriteLine("READY\n",ClientCon); STREAMFlush(ClientCon); HTTPServerSendDocument(ClientCon, Response, Tempstr, HEADERS_SENDFILE|HEADERS_USECACHE|HEADERS_KEEPALIVE); //exit 1 means that we can keep connection alive for re-use LogFileFlushAll(TRUE); if (Response->Flags & SESSION_KEEPALIVE) _exit(1); _exit(0); } DestroyString(Tempstr); return(pid); }
int HTTPServerHandleRegister(HTTPSession *Session, int Flags) { char *Tempstr=NULL, *Name=NULL, *Value=NULL, *ptr; char *FlagChar=""; int result=FALSE; if (Flags & LOGGED_IN) FlagChar="I"; if (Flags & LOGIN_FAIL) FlagChar="F"; Tempstr=MCopyStr(Tempstr,"REG ",Session->ClientIP,":",FlagChar,"\n",NULL); //Override above tempstr if Logout value found if (Flags & LOGIN_CHANGE) Tempstr=MCopyStr(Tempstr,"REG ",Session->Path,":C\n",NULL); if (Flags & LOGIN_CHECK_ALLOWED) { FlagChar="A"; ptr=GetNameValuePair(Session->Arguments,"&","=",&Name,&Value); while (ptr) { if (Name && (strcmp(Name,"Logout")==0)) Tempstr=MCopyStr(Tempstr,"REG ",Value,":",FlagChar,"\n",NULL); ptr=GetNameValuePair(ptr,"&","=",&Name,&Value); } } STREAMWriteLine(Tempstr,ParentProcessPipe); STREAMFlush(ParentProcessPipe); Tempstr=STREAMReadLine(Tempstr,ParentProcessPipe); if (strcmp(Tempstr,"okay\n")==0) result=TRUE; DestroyString(Tempstr); DestroyString(Name); DestroyString(Value); return(result); }
pid_t HandleChildProcessRequest(STREAM *S) { char *Tempstr=NULL, *Token=NULL, *ptr; pid_t Pid=0; Tempstr=STREAMReadLine(Tempstr,S); if (! Tempstr) return(FALSE); StripTrailingWhitespace(Tempstr); if (Settings.Flags & FLAG_LOG_MORE_VERBOSE) LogToFile(Settings.LogPath, "HANDLE CHROOT REQUEST: %s",Tempstr); ptr=GetToken(Tempstr,"\\S",&Token,0); if (strcmp(Token,"EXEC")==0) Pid=HandleCGIExecRequest(S,ptr); else if (strcmp(Token,"WEBSOCKET")==0) Pid=HandleWebsocketExecRequest(S,ptr); else if (strcmp(Token,"LOG")==0) { LogToFile(Settings.LogPath,ptr); Pid=0; } else if (strcmp(Token,"GETF")==0) Pid=HandleGetFileRequest(S,ptr); else if (strcmp(Token,"POST")==0) Pid=HandlePostFileRequest(S,ptr); else if (strcmp(Token,"GETIP")==0) Pid=HandleResolveIPRequest(S,ptr); else if (strcmp(Token,"REG")==0) Pid=HandleChildRegisterRequest(S,ptr); else if (strcmp(Token,"PROXY")==0) Pid=HandleProxyRequest(S,ptr); else if (strcmp(Token,"MIMEICON")==0) Pid=HandleIconRequest(S, ptr); else if (strcmp(Token,"EVENT")==0) Pid=RunEventScript(S, ptr); STREAMSetValue(S,"HelperType", Token); STREAMFlush(S); DestroyString(Tempstr); DestroyString(Token); return(Pid); }
STREAM *STREAMClose(STREAM *S) { ListNode *Curr; int len; if (! S) return(NULL); len=S->OutEnd; STREAMReadThroughProcessors(S, NULL, 0); STREAMFlush(S); if ( (StrLen(S->Path)==0) || (strcmp(S->Path,"-") !=0) ) { if ((S->out_fd != -1) && (S->out_fd != S->in_fd)) close(S->out_fd); if (S->in_fd != -1) close(S->in_fd); } Curr=ListGetNext(S->Values); while (Curr) { if (strncmp(Curr->Tag,"HelperPID",9)==0) kill(atoi(Curr->Item),SIGKILL); Curr=ListGetNext(Curr); } ListDestroy(S->Values,(LIST_ITEM_DESTROY_FUNC)DestroyString); ListDestroy(S->ProcessingModules,DataProcessorDestroy); DestroyString(S->InputBuff); DestroyString(S->OutputBuff); DestroyString(S->Path); free(S); return(NULL); }
int InternalCopyFile(TTransferContext *Ctx, TFileInfo *iSrcFI) { STREAM *Src=NULL, *Dest=NULL; TFileInfo *SrcFI=NULL, *DestFI=NULL; char *Buffer=NULL, *Tempstr=NULL, *ptr; int BuffSize=4096; int result, bytes=0, towrite=0; unsigned int TotalBytes=0, BytesSent=0, percent=0, secs=0, val; double bigval; //TFileInfo *FI; int RetVal=TRANSFER_OKAY; struct timeval StartTime, Now; TProcessingModule *CompressionMod=NULL; if (! Ctx->SrcFS->ReadBytes) return(ERR_READ_NOTSUPPORTED); if (Ctx->DestFS && (! Ctx->DestFS->WriteBytes)) return(ERR_WRITE_NOTSUPPORTED); gettimeofday(&StartTime,NULL); if (Ctx->DestFS && Ctx->DestFS->BuffSize) BuffSize=Ctx->DestFS->BuffSize; Buffer=SetStrLen(Buffer,BuffSize*2+1); SrcFI=FileInfoClone(iSrcFI); DestFI=FileInfoClone(iSrcFI); DestFI->Path=FileStoreFormatPath(DestFI->Path, Ctx->DestFS, iSrcFI->Name); //if a PreCopyHook script is specified, then run it if (StrLen(Ctx->PreCopyHook)) { Tempstr=FormatStr(Tempstr,"%s '%s' '%s' '%s'",Ctx->PreCopyHook,DestFI->Name,DestFI->Path,""); system(Tempstr); } Src=InternalCopyOpenSource(Ctx, SrcFI); TotalBytes=SrcFI->Size; if (Ctx->CmdFlags & FLAG_CMD_RESUME) BytesSent=SrcFI->ResumePoint; if (Src) { if (Ctx->SrcFS->Settings & FS_COMPRESSION) CompressionMod=ActivateCompression(Ctx->DestFS,Ctx->SrcFS); if (Ctx->DestFS) Dest=InternalCopyOpenDest(Ctx, SrcFI, DestFI); else Dest=STREAMFromFD(1); if (Dest) { result=Ctx->SrcFS->ReadBytes(Ctx->SrcFS,Src,Buffer,BuffSize*2); while ((bytes > 0) || (result != EOF)) { if (CompressionMod) result=HandleCompression(CompressionMod,Buffer,result); if (result > 0) bytes+=result; if (bytes > BuffSize) towrite=BuffSize; else towrite=bytes; if (Ctx->DestFS) result=Ctx->DestFS->WriteBytes(Ctx->DestFS,Dest,Buffer,towrite); else result=STREAMWriteBytes(Dest,Buffer,towrite); if (result==-1) { RetVal=ERR_INTERRUPTED; break; } if (Settings.Flags & FLAG_INTERRUPT) { Settings.Flags &= ~FLAG_INTERRUPT; RetVal=ERR_CANCEL; break; } BytesSent+=result; bytes-=result; if (bytes > 0) memmove(Buffer,Buffer+result,bytes); gettimeofday(&Now,NULL); val=Now.tv_sec - StartTime.tv_sec; if (val > secs) { secs=val; if (secs > 0) DisplayTransferStatus(SrcFI->Name,BytesSent,TotalBytes,&percent,secs,Ctx->CmdFlags,Ctx->Throttle); } result=Ctx->SrcFS->ReadBytes(Ctx->SrcFS,Src,Buffer+bytes,BuffSize*2 -bytes); } if (Ctx->SrcFS->CloseFile) Ctx->SrcFS->CloseFile(Ctx->SrcFS,Src); if (Ctx->DestFS && Ctx->DestFS->CloseFile) { result=Ctx->DestFS->CloseFile(Ctx->DestFS,Dest); if (result !=TRUE) { //Handle Errors returned by Close file if (RetVal >= FALSE) RetVal=result; SetVar(Ctx->Vars,"Error",GetVar(Ctx->DestFS->Vars,"Error")); SetVar(Ctx->DestFS->Vars,"Error",""); } else ListAddNamedItem(Ctx->DestFS->DirListing,DestFI->Name,FileInfoClone(DestFI)); } else STREAMFlush(Dest); if ((TotalBytes > 0) && (BytesSent < TotalBytes)) RetVal=ERR_INTERRUPTED; } else RetVal=ERR_DESTFILE; secs=Now.tv_sec - StartTime.tv_sec; if (secs < 1) secs=1; DisplayTransferStatus(SrcFI->Name,BytesSent,TotalBytes,&percent,secs,0,0); //if (! (CmdFlags & FLAG_QUIET)) printf("\n"); } else RetVal=ERR_SOURCEFILE; Ctx->TotalBytes+=BytesSent; FileInfoDestroy(DestFI); FileInfoDestroy(SrcFI); DestroyString(Buffer); DestroyString(Tempstr); return(RetVal); }
void HTTPSendHeaders(STREAM *S, HTTPInfoStruct *Info) { char *SendStr=NULL, *Tempstr=NULL, *ptr; ListNode *Curr; int count; int i; static int AuthCounter=0; STREAMClearDataProcessors(S); SendStr=CopyStr(SendStr,Info->Method); SendStr=CatStr(SendStr," "); if (Info->Flags & HTTP_PROXY) Tempstr=HTTPInfoToURL(Tempstr, Info); else Tempstr=HTTPQuoteChars(Tempstr,Info->Doc," "); SendStr=CatStr(SendStr,Tempstr); if (Info->Flags & HTTP_VER1_0) SendStr=CatStr(SendStr," HTTP/1.0\r\n"); else SendStr=MCatStr(SendStr," HTTP/1.1\r\n","Host: ",Info->Host,"\r\n",NULL); if (StrLen(Info->PostContentType) >0) { Tempstr=FormatStr(Tempstr,"Content-type: %s\r\n",Info->PostContentType); SendStr=CatStr(SendStr,Tempstr); } if (Info->PostContentLength > 0) { Tempstr=FormatStr(Tempstr,"Content-Length: %d\r\n",Info->PostContentLength); SendStr=CatStr(SendStr,Tempstr); } if (StrLen(Info->Destination)) { Tempstr=FormatStr(Tempstr,"Destination: %s\r\n",Info->Destination); SendStr=CatStr(SendStr,Tempstr); } /* If we have authorisation details then send them */ if (Info->Authorization) SendStr=HTTPHeadersAppendAuth(SendStr, "Authorization", Info, Info->Authorization); if (Info->ProxyAuthorization) SendStr=HTTPHeadersAppendAuth(SendStr, "Proxy-Authorization", Info, Info->ProxyAuthorization); if (Info->Flags & HTTP_NOCACHE) SendStr=CatStr(SendStr,"Pragma: no-cache\r\nCache-control: no-cache\r\n"); if (Info->Depth > 0) { Tempstr=FormatStr(Tempstr,"Depth: %d\r\n",Info->Depth); SendStr=CatStr(SendStr,Tempstr); } /* if ((PathData->Options.Restart) && (PathData->offset >0)) { snprintf(Buffer,sizeof(Buffer),"Range: bytes=%d-\r\n",PathData->offset); SendStr=CatStr(SendStr,Buffer); } */ if (Info->IfModifiedSince > 0) { Tempstr=CopyStr(Tempstr,GetDateStrFromSecs("%a, %d %b %Y %H:%M:%S GMT",Info->IfModifiedSince,NULL)); SendStr=MCatStr(SendStr,"If-Modified-Since: ",Tempstr, "\r\n",NULL); } if ( (strcasecmp(Info->Method,"DELETE") !=0) && (strcasecmp(Info->Method,"HEAD") !=0) && (strcasecmp(Info->Method,"PUT") !=0) ) { Tempstr=CopyStr(Tempstr,""); if (! (Info->Flags & HTTP_NOCOMPRESS)) { if (DataProcessorAvailable("Compression","gzip")) Tempstr=CatStr(Tempstr,"gzip"); if (DataProcessorAvailable("Compression","zlib")) { if (StrLen(Tempstr)) Tempstr=CatStr(Tempstr,", deflate"); else Tempstr=CatStr(Tempstr,"deflate"); } } if (StrLen(Tempstr)) SendStr=MCatStr(SendStr,"Accept-Encoding: ",Tempstr,"\r\n",NULL); else SendStr=CatStr(SendStr,"Accept-Encoding:\r\n"); } if (Info->Flags & HTTP_KEEPALIVE) { //if (Info->Flags & HTTP_VER1_0) SendStr=CatStr(SendStr,"Connection: Keep-Alive\r\n"); //SendStr=CatStr(SendStr,"Content-Length: 0\r\n"); } else { SendStr=CatStr(SendStr,"Connection: Close\r\n"); } ptr=LibUsefulGetValue("HTTP:User-Agent"); if (StrLen(ptr)) SendStr=MCatStr(SendStr,"User-Agent: ",ptr, "\r\n",NULL); Curr=ListGetNext(Info->CustomSendHeaders); while (Curr) { SendStr=MCatStr(SendStr,Curr->Tag, ": ", (char *) Curr->Item, "\r\n",NULL); Curr=ListGetNext(Curr); } if (! (Info->Flags & HTTP_NOCOOKIES)) { SendStr=AppendCookies(SendStr,Cookies); } SendStr=CatStr(SendStr,"\r\n"); Info->State |= HTTP_HEADERS_SENT; if (Info->Flags & HTTP_DEBUG) fprintf(stderr,"HTTPSEND: ------\n%s------\n\n",SendStr); STREAMWriteLine(SendStr,S); STREAMFlush(S); DestroyString(Tempstr); DestroyString(SendStr); }
int STREAMProcessConnectHop(STREAM *S, char *HopURL, int LastHop) { int val, result=FALSE; char *Token=NULL, *Token2=NULL; char *Tempstr=NULL; char *User=NULL, *Host=NULL,*Pass=NULL, *KeyFile=NULL; int Port=0; ParseConnectDetails(HopURL, &Token, &Host, &Token2, &User, &Pass, NULL); Port=atoi(Token2); val=MatchTokenFromList(Token,HopTypes,0); switch (val) { case CONNECT_HOP_TCP: if (S->in_fd==-1) { S->in_fd=ConnectToHost(Host,Port,0); S->out_fd=S->in_fd; if (S->in_fd > -1) result=TRUE; } break; case CONNECT_HOP_HTTPTUNNEL: result=DoHTTPProxyTunnel(S, Host, Port, S->Path, 0); break; case CONNECT_HOP_SSH: case CONNECT_HOP_SSHTUNNEL: result=ConnectHopSSH(S, val, Host, Port, User, Pass, S->Path); break; case CONNECT_HOP_SOCKS4: result=ConnectHopSocks(S, val, Host, Port, User, Pass, S->Path); break; case CONNECT_HOP_SHELL_CMD: break; case CONNECT_HOP_TELNET: if (Port > 0) { Tempstr=FormatStr(Tempstr,"telnet -8 %s %d ",Host, Port); } else Tempstr=FormatStr(Tempstr,"telnet -8 %s ",Host); if (S->in_fd==-1) { PseudoTTYSpawn(& S->in_fd,Tempstr,0); S->out_fd=S->in_fd; if (S->in_fd > -1) { result=TRUE; STREAMSetFlushType(S,FLUSH_LINE,0,0); } } else { Tempstr=CatStr(Tempstr,";exit\n"); STREAMWriteLine(Tempstr,S); result=TRUE; } if (StrLen(User) > 0) { Tempstr=MCopyStr(Tempstr,User,"\n",NULL); STREAMExpectAndReply(S,"ogin:",Tempstr); } if (StrLen(Pass) > 0) { Tempstr=MCopyStr(Tempstr,Pass,"\n",NULL); STREAMExpectAndReply(S,"assword:",Tempstr); } STREAMExpectSilence(S,2); break; } DestroyString(Tempstr); DestroyString(Token); DestroyString(KeyFile); DestroyString(Host); DestroyString(User); DestroyString(Pass); STREAMFlush(S); return(result); }
int ChrootProcessRequest(STREAM *S, HTTPSession *Session, const char *Type, const char *Path, const char *SearchPath) { char *Tempstr=NULL; char *ResponseLine=NULL, *Headers=NULL, *ptr; off_t ContentLength=0; int KeepAlive=FALSE, RetVal=FALSE; LogFileFlushAll(TRUE); if (! ChrootSendRequest(Session, Type, Path, SearchPath)) return(FALSE); //Wait till process outside of chroot responds to our request, while (STREAMCheckForBytes(ParentProcessPipe)==0) usleep(10000); //Read 'OKAY' line Tempstr=STREAMReadLine(Tempstr, ParentProcessPipe); //then send it the post data if there is any. if (strcmp(Session->Method,"POST") ==0) { if (Session->ContentSize > 0) { LogToFile(Settings.LogPath,"PUSH POST: [%d]",Session->ContentSize); STREAMSendFile(S, ParentProcessPipe, Session->ContentSize, SENDFILE_KERNEL|SENDFILE_LOOP); LogToFile(Settings.LogPath,"PUSH POST:DONE [%d]",Session->ContentSize); } //we shouldn't need this CR-LF, as we've sent 'Content-Length' characters //but some CGI implementations seem to expect it, and it does no harm to //provide it anyway STREAMWriteLine("\r\n",ParentProcessPipe); STREAMFlush(ParentProcessPipe); } //Handle Headers from CGI script Headers=CopyStr(Headers,""); ResponseLine=STREAMReadLine(ResponseLine,ParentProcessPipe); StripTrailingWhitespace(ResponseLine); if (StrLen(ResponseLine)) RetVal=TRUE; Tempstr=STREAMReadLine(Tempstr,ParentProcessPipe); while (Tempstr) { StripTrailingWhitespace(Tempstr); if (StrLen(Tempstr)==0) break; //Handle 'Status' header that changes the 1st Response line if (strncasecmp(Tempstr,"Status:",7)==0) { ptr=Tempstr+7; while (isspace(*ptr) && (*ptr != '\0')) ptr++; ResponseLine=MCopyStr(ResponseLine, Session->Protocol, " ", ptr, NULL); } else if (strncasecmp(Tempstr,"Content-Length:",15)==0) { ptr=Tempstr+15; while (isspace(*ptr)) ptr++; ContentLength=(off_t) strtoull(ptr,NULL,10); Headers=MCatStr(Headers,Tempstr,"\r\n",NULL); } else if (strncasecmp(Tempstr,"Connection:",11)==0) { ptr=Tempstr+11; while (isspace(*ptr)) ptr++; if (strncasecmp(ptr,"Keep-Alive",10)==0) KeepAlive=TRUE; Headers=MCatStr(Headers,Tempstr,"\r\n",NULL); } else Headers=MCatStr(Headers,Tempstr,"\r\n",NULL); Tempstr=STREAMReadLine(Tempstr,ParentProcessPipe); } //The second "\r\n" here will provide the blank line that marks the end //of the headers Tempstr=MCopyStr(Tempstr, ResponseLine,"\r\n",Headers,"\r\n",NULL); STREAMWriteLine(Tempstr,S); if (Settings.Flags & FLAG_LOG_MORE_VERBOSE) LogToFile(Settings.LogPath,"CGI HEADERS: [%s]",Tempstr); //Read remaining data from CGI STREAMSendFile(ParentProcessPipe, S, ContentLength,SENDFILE_KERNEL|SENDFILE_LOOP); STREAMFlush(S); //if we're running a cgi program, then it will close the session when done, so //turn off the 'reuse session' flag if (KeepAlive) Session->Flags |= SESSION_KEEPALIVE | SESSION_REUSE; else Session->Flags &= ~(SESSION_KEEPALIVE | SESSION_REUSE); DestroyString(Tempstr); DestroyString(Headers); DestroyString(ResponseLine); return(RetVal); }
STREAM *ChrootSendRequest(HTTPSession *Session, const char *Type, const char *Path, const char *SearchPath) { char *Tempstr=NULL, *ContentLengthStr=NULL; char *Quoted=NULL; if (! ParentProcessPipe) return(NULL); ContentLengthStr=FormatStr(ContentLengthStr,"%d",Session->ContentSize); //Trying to do this all as one string causes a problem! Tempstr=MCopyStr(Tempstr,Type," Host='",Session->Host, "' ClientIP='",Session->ClientIP, "' ClientMAC='",Session->ClientMAC,"'",NULL); Quoted=QuoteCharsInStr(Quoted,Session->URL,"'&"); Tempstr=MCatStr(Tempstr, " URL='",Quoted,"'",NULL); Quoted=QuoteCharsInStr(Quoted,Path,"'&"); Tempstr=MCatStr(Tempstr, " Path='",Quoted,"'",NULL); Quoted=QuoteCharsInStr(Quoted,SearchPath,"'&"); Tempstr=MCatStr(Tempstr, " SearchPath='",Quoted,"'",NULL); Tempstr=MCatStr(Tempstr," Method=",Session->Method," UserAgent='",Session->UserAgent,"' ContentLength='",ContentLengthStr,"'",NULL); if (StrLen(Session->ContentBoundary)) Tempstr=MCatStr(Tempstr, " ContentType='",Session->ContentType, "; boundary=",Session->ContentBoundary, "'",NULL); else Tempstr=MCatStr(Tempstr, " ContentType='",Session->ContentType,"'", NULL); Quoted=FormatStr(Quoted,"%d",Session->ServerPort); Tempstr=MCatStr(Tempstr," ServerName=",Session->ServerName," ServerPort=",Quoted,NULL); if (StrLen(Session->Cipher)) Tempstr=MCatStr(Tempstr," Cipher='",Session->Cipher,"'",NULL); if (StrLen(Session->Cookies)) Tempstr=MCatStr(Tempstr," Cookies='",Session->Cookies,"'",NULL); Quoted=QuoteCharsInStr(Quoted,Session->StartDir,"'&"); Tempstr=MCatStr(Tempstr," StartDir='",Quoted,"'",NULL); Quoted=QuoteCharsInStr(Quoted,Session->ClientReferrer,"'&"); Tempstr=MCatStr(Tempstr, " ClientReferrer='",Quoted,"'",NULL); if (Session->Flags & SESSION_KEEPALIVE) Tempstr=CatStr(Tempstr," KeepAlive=Y"); if (Session->Flags & SESSION_UPLOAD) Tempstr=CatStr(Tempstr," Upload=Y"); if (Session->AuthFlags & FLAG_AUTH_HASCOOKIE) Tempstr=CatStr(Tempstr," AuthCookie=Y"); if (Session->CacheTime > 0) { Quoted=FormatStr(Quoted," Cache=%d",Session->CacheTime); Tempstr=CatStr(Tempstr,Quoted); } if (StrLen(Session->UserName)) Tempstr=MCatStr(Tempstr," User='******'",NULL); if (StrLen(Session->RealUser)) Tempstr=MCatStr(Tempstr," RealUser='******'",NULL); if (StrLen(Session->Group)) Tempstr=MCatStr(Tempstr," Group='",Session->Group,"'",NULL); if (StrLen(Session->RemoteAuthenticate)) Tempstr=MCatStr(Tempstr," RemoteAuthenticate='",Session->RemoteAuthenticate,"'",NULL); Quoted=QuoteCharsInStr(Quoted,Session->Arguments,"'&"); Tempstr=MCatStr(Tempstr, " Arguments='",Quoted,"'", NULL); Tempstr=CatStr(Tempstr,"\n"); if (Settings.Flags & FLAG_LOG_MORE_VERBOSE) LogToFile(Settings.LogPath,"REQUESTING DATA FROM OUTSIDE CHROOT: [%s]",Tempstr); STREAMWriteLine(Tempstr,ParentProcessPipe); STREAMFlush(ParentProcessPipe); DestroyString(Tempstr); DestroyString(Quoted); DestroyString(ContentLengthStr); return(ParentProcessPipe); }
void STREAMClear(STREAM *S) { STREAMFlush(S); S->InStart=0; }
pid_t HandleIconRequest(STREAM *ClientCon, char *Data) { HTTPSession *Response; char *Name=NULL, *Value=NULL, *ptr, *tptr; char *Tempstr=NULL; ListNode *Vars; pid_t pid; pid=fork(); if (pid==0) { Response=ParseSessionInfo(Data); Vars=ListCreate(); ptr=GetNameValuePair(Response->Arguments,"&","=",&Name,&Tempstr); while (ptr) { Value=HTTPUnQuote(Value,Tempstr); SetVar(Vars,Name,Value); if (strcasecmp(Name,"MimeType")==0) { tptr=GetToken(Value,"/",&Tempstr,0); SetVar(Vars,"MimeClass",Tempstr); SetVar(Vars,"MimeSub",tptr); } ptr=GetNameValuePair(ptr,"&","=",&Name,&Tempstr); } if (! SwitchGroup(Response->Group)) { LogToFile(Settings.LogPath,"WARN: Failed to switch to group '%s' for mimeicons '%s'", Response->RealUser, Tempstr); } if (! SwitchUser(Response->RealUser)) { LogToFile(Settings.LogPath,"ERROR: Failed to switch to user '%s' when getting icons from '%s'", Response->SearchPath); LogFileFlushAll(TRUE); _exit(0); } STREAMWriteLine("READY\n",ClientCon); STREAMFlush(ClientCon); ptr=GetToken(Response->SearchPath,":",&Value,0); while (ptr) { Tempstr=SubstituteVarsInString(Tempstr,Value,Vars,0); if (access(Tempstr,R_OK)==0) break; ptr=GetToken(ptr,":",&Value,0); } //HTTPServerSendDocument(ClientCon, Response, Tempstr, HEADERS_SENDFILE|HEADERS_USECACHE|HEADERS_KEEPALIVE); HTTPServerSendDocument(ClientCon, Response, Tempstr, HEADERS_SENDFILE|HEADERS_USECACHE); //exit 1 means we can keep connection alive for reuse LogFileFlushAll(TRUE); _exit(1); } DestroyString(Name); DestroyString(Value); DestroyString(Tempstr); return(pid); }
pid_t HandleCGIExecRequest(STREAM *ClientCon, char *Data) { char *Tempstr=NULL, *Name=NULL, *Value=NULL; char *ScriptPath=NULL; int result, i; HTTPSession *Response; //We will never read from this stream again. Any further data will be read //by the process we spawn off ClientCon->State |= SS_EMBARGOED; Response=ParseSessionInfo(Data); CleanStr(Response->Path); CleanStr(Response->SearchPath); CleanStr(Response->StartDir); ScriptPath=FindFileInPath(ScriptPath,Response->Path,Response->SearchPath); if (access(ScriptPath,F_OK) !=0) { HTTPServerSendHTML(ClientCon, Response, "404 Not Found","Couldn't find that script."); LogToFile(Settings.LogPath,"No such script: %s in path %s = %s",Response->Path,Response->SearchPath,ScriptPath); } else if ( (access(ScriptPath,X_OK) !=0) || (! CheckScriptIntegrity(ScriptPath)) ) { HTTPServerSendHTML(ClientCon, Response, "403 Forbidden","You don't have permission for that."); LogToFile(Settings.LogPath,"Cannot execute script: %s",ScriptPath); } else { STREAMFlush(ClientCon); LogFileFlushAll(TRUE); result=fork(); if (result==0) { //do this so that when we exec the script, anything output goes to the client close(0); dup(ClientCon->in_fd); close(1); dup(ClientCon->out_fd); //must use write because stream is embargoed write(1,"READY\n",6); HTTPServerExecCGI(ClientCon, Response, ScriptPath); //exit whether script ran or not! _exit(0); } } HTTPSessionDestroy(Response); DestroyString(ScriptPath); DestroyString(Tempstr); DestroyString(Name); DestroyString(Value); //Always return STREAM_CLOSED, so that pipe gets closed regardless of exit status of //forked helper process return(STREAM_CLOSED); }
pid_t HandleWebsocketExecRequest(STREAM *ClientCon, char *Data) { char *Tempstr=NULL, *Name=NULL, *Value=NULL; char *ScriptPath=NULL; int result, i; HTTPSession *Response; //We will never read from this stream again. Any further data will be read //by the process we spawn off ClientCon->State |= SS_EMBARGOED; Response=ParseSessionInfo(Data); CleanStr(Response->Path); CleanStr(Response->SearchPath); CleanStr(Response->StartDir); ScriptPath=FindFileInPath(ScriptPath, Response->Path, Response->SearchPath); LogToFile(Settings.LogPath,"Script: Found=[%s] SearchPath=[%s] ScriptName=[%s] Arguments=[%s]", ScriptPath, Response->SearchPath, Response->Path, Response->Arguments); if (access(ScriptPath,F_OK) !=0) { LogToFile(Settings.LogPath,"No such script: %s in path %s = %s",Response->Path, Response->SearchPath, ScriptPath); } else if ( (access(ScriptPath,X_OK) !=0) || (! CheckScriptIntegrity(ScriptPath)) ) { LogToFile(Settings.LogPath,"Cannot execute script: %s", ScriptPath); } else { STREAMFlush(ClientCon); result=fork(); if (result==0) { //do this so that when we exec the script, anything output goes to the client close(0); dup(ClientCon->in_fd); close(1); dup(ClientCon->out_fd); if (! SwitchGroup(Response->Group)) { LogToFile(Settings.LogPath,"WARN: Failed to switch to group '%s' to execute script: %s using handler '%s'", Response->RealUser, ScriptPath, Tempstr); } //Switch user. ALAYA WILL NOT RUN SCRIPTS AS ROOT! if (! SwitchUser(Response->RealUser)) { LogToFile(Settings.LogPath,"ERROR: Failed to switch to user '%s' to execute script: %s using handler '%s'", Response->RealUser, ScriptPath, Tempstr); LogFileFlushAll(TRUE); _exit(0); } if (geteuid()==0) { LogToFile(Settings.LogPath, "Failed to switch user to '%s' for running a .cgi program. Will not run programs as 'root'. Set 'DefaultUser' in config file or command line.", Response->RealUser); } else { SetupEnvironment(Response, ScriptPath); Tempstr=FindScriptHandlerForScript(Tempstr,ScriptPath); if (Tempstr) LogToFile(Settings.LogPath,"Execute script: %s using handler '%s'",ScriptPath,Tempstr); else LogToFile(Settings.LogPath,"Execute script: %s QUERY_STRING= '%s'",ScriptPath,getenv("QUERY_STRING")); //Only do this late! Otherwise logging won't work. for (i=3; i < 1000; i++) close(i); if (StrLen(Tempstr)) execl(Tempstr, Tempstr, ScriptPath,NULL); else execl(ScriptPath,ScriptPath,NULL); //Logging won't work after we've closed all the file descriptors! LogToFile(Settings.LogPath,"Cannot execute script: %s",ScriptPath); } LogFileFlushAll(TRUE); _exit(0); } else { } } HTTPSessionDestroy(Response); DestroyString(ScriptPath); DestroyString(Tempstr); DestroyString(Name); DestroyString(Value); //Always return STREAM_CLOSED, so that pipe gets closed regardless of exit status of //forked helper process return(STREAM_CLOSED); }