int DisplayAvailableFormats(ListNode *Vars, char *Formats, int ShowSize) { char *URL=NULL, *Token=NULL, *TokenID=NULL, *Tempstr=NULL, *ptr; STREAM *S; int result=TRUE; fprintf(stderr, "\nFormats available for this Movie: "); ptr=GetToken(Formats," ",&Token,0); while (ptr) { if (StrLen(Token)) TokenID=MCopyStr(TokenID,"item:",Token,NULL); URL=CopyStr(URL,GetVar(Vars,TokenID)); if (strcmp(Token,"reference") !=0) { fprintf(stderr,"%s",Token); if (ShowSize) { S=HTTPMethod("HEAD",URL,NULL,NULL); if (S) { Tempstr=CopyStr(Tempstr,STREAMGetValue(S,"HTTP:ResponseCode")); if (strcmp(Tempstr,"403") ==0) { printf("\nERROR: %s response for %s\n",Tempstr,URL); result=FALSE; break; } else if (strcmp(Tempstr,"200")==0) { Tempstr=CopyStr(Tempstr,STREAMGetValue(S,"HTTP:Content-length")); fprintf(stderr, " (%s)",GetHumanReadableDataQty(strtod(Tempstr,NULL),FALSE)); STREAMClose(S); } } } } fprintf(stderr,", "); ptr=GetToken(ptr," ",&Token,0); } fprintf(stderr,"\n\n",Tempstr); DestroyString(Token); DestroyString(TokenID); DestroyString(Tempstr); DestroyString(URL); return(result); }
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); }
STREAM *InternalCopyOpenSource(TTransferContext *Ctx, TFileInfo *SrcFI) { STREAM *S; char *ptr; int val=0; //Specify the DESTINATION size in the source, for use in 'resume' transfers if (Ctx->DestFS->GetFileSize) SrcFI->ResumePoint=Ctx->DestFS->GetFileSize(Ctx->DestFS, SrcFI->Name); //Set version info if getting a particular version of file ptr=GetVar(Ctx->Vars,"Version"); SetVar(SrcFI->Vars,"Version,",ptr); if ( (Ctx->CmdFlags & FLAG_CMD_RESUME) && (Ctx->SrcFS->Features & FS_RESUME_TRANSFERS) && (Ctx->DestFS->Features & FS_RESUME_TRANSFERS) ) val |= OPEN_RESUME; S=Ctx->SrcFS->OpenFile(Ctx->SrcFS,SrcFI, val); //OPEN SOURCE DONE //Construct 'write' args. THESE ARE ARGS TO OPEN THE DEST FILE if (S) { ptr=STREAMGetValue(S,"filesize"); if (StrLen(ptr)) SrcFI->Size=atoi(ptr); else if (Ctx->SrcFS->GetFileSize) SrcFI->Size=Ctx->SrcFS->GetFileSize(Ctx->SrcFS, SrcFI->Path); } return(S); }
const char *OpenSSLQueryCipher(STREAM *S) { void *ptr; if (! S) return(NULL); ptr=STREAMGetItem(S,"LIBUSEFUL-SSL-CTX"); if (! ptr) return(NULL); #ifdef HAVE_LIBSSL const SSL_CIPHER *Cipher; char *Tempstr=NULL; Cipher=SSL_get_current_cipher((const SSL *) ptr); if (Cipher) { Tempstr=FormatStr(Tempstr,"%d bit %s",SSL_CIPHER_get_bits(Cipher,NULL), SSL_CIPHER_get_name(Cipher)); STREAMSetValue(S,"SSL-Cipher",Tempstr); Tempstr=SetStrLen(Tempstr,1024); Tempstr=SSL_CIPHER_description(Cipher, Tempstr, 1024); STREAMSetValue(S,"SSL-Cipher-Details",Tempstr); } DestroyString(Tempstr); return(STREAMGetValue(S,"SSL-Cipher")); #else return(NULL); #endif }
//Will only return false if FLAG_SSL_CERT_REQUIRED is set int HTTPServerCheckCertificate(HTTPSession *Session, STREAM *S) { char *ptr; int result=TRUE; ptr=STREAMGetValue(S,"SSL-Certificate-Verify"); if (StrLen(ptr) && (strcmp(ptr,"no certificate") !=0) ) { LogToFile(Settings.LogPath,"AUTH SSL Certificate Provided by '%s@%s'. Subject=%s Issuer=%s",Session->UserName,Session->ClientIP,STREAMGetValue(S,"SSL-Certificate-Subject"), STREAMGetValue(S,"SSL-Certificate-Issuer")); if (strcmp(ptr,"OK")!=0) { if (Settings.AuthFlags & FLAG_AUTH_CERT_REQUIRED) { LogToFile(Settings.LogPath,"AUTH: ERROR: SSL Certificate REQUIRED from client '%s@%s'. Invalid Certificate. Error was: %s",Session->UserName,Session->ClientIP, ptr); result=FALSE; } else LogToFile(Settings.LogPath,"AUTH: SSL Certificate Optional for client '%s@%s'. Invalid Certificate. Error was: %s",Session->UserName,Session->ClientIP, ptr); LogFileFlushAll(TRUE); } } else if (Settings.AuthFlags & FLAG_AUTH_CERT_REQUIRED) LogToFile(Settings.LogPath,"AUTH: ERROR: SSL Certificate REQUIRED from client '%s@%s'. Missing Certificate.",Session->UserName,Session->ClientIP); return(result); }
int CheckSSLAuthentication(HTTPSession *Session, char *UserName) { char *ptr; if (! Session->S) return(FALSE); if (Settings.AuthFlags & FLAG_AUTH_CERT_SUFFICIENT) { ptr=STREAMGetValue(Session->S,"SSL-Certificate-Verify"); if (StrLen(ptr) && (strcmp(ptr,"OK")==0)) { ptr=STREAMGetValue(Session->S,"SSL-Certificate-CommonName"); if (StrLen(ptr) && (strcmp(ptr,UserName)==0)) { LogToFile(Settings.LogPath,"AUTH: SSL-Certificate Authentication sufficient for User '%s'",UserName); return(TRUE); } } } return(FALSE); }
int DownloadStream(char *URL, char *Title, ListNode *Items, int Flags) { STREAM *Con=NULL, *S=NULL; ListNode *Curr; char *Tempstr=NULL, *ptr; char *Token=NULL; int Port; double len=0, ApproxDocSize=0, BytesRead=0; Curr=ListGetNext(Items); if (Flags & (FLAG_TEST | FLAG_TEST_SITES) ) { if (Flags & FLAG_TEST) fprintf(stderr,"TEST MODE: would have downloaded '%s' url=%s\n",Title,Curr->Item); if (Curr) return(TRUE); return(FALSE); } OpenOutputFiles(Title,URL,&BytesRead); while (Curr) { if (strncmp((char *) Curr->Item,"http:",5)==0) Tempstr=CopyStr(Tempstr,(char *) Curr->Item); else { Tempstr=CopyStr(Tempstr,URL); ptr=strrchr(Tempstr,'/'); if (ptr) *ptr='\0'; Tempstr=MCatStr(Tempstr,"/",(char *) Curr->Item,NULL); } Con=ConnectAndRetryUntilDownload(Tempstr, 0, 0); if (Con) { ptr=STREAMGetValue(Con,"HTTP:content-length"); if (ptr) len=atof(ptr); if (ApproxDocSize==0) ApproxDocSize=ListSize(Items) * len; TransferItem(Con, Title, Curr->Item, "", len, ApproxDocSize, &BytesRead, BytesRead==0); STREAMClose(Con); } Curr=ListGetNext(Curr); } CloseOutputFiles(); DestroyString(Tempstr); DestroyString(Token); return(TRUE); }
char *LogFileInternalGetRotateDestinationPath(char *RetStr, TLogFile *LogFile) { char *Tempstr=NULL; Tempstr=CopyStr(Tempstr, STREAMGetValue(LogFile->S,"RotatePath")); if (StrLen(Tempstr) && strchr(Tempstr,'$')) { STREAMSetValue(LogFile->S, "Date",GetDateStr("%Y_%m_%d",NULL)); STREAMSetValue(LogFile->S, "Time",GetDateStr("%H:%M:%S",NULL)); RetStr=SubstituteVarsInString(RetStr,Tempstr,LogFile->S->Values,0); } else RetStr=CopyStr(RetStr,LogFile->Path); DestroyString(Tempstr); return(RetStr); }
int SMTPHelo(STREAM *S) { int RetVal=0; char *Tempstr=NULL, *Token=NULL; const char *ptr; ptr=LibUsefulGetValue("SMTP:HELO"); if (! StrValid(ptr)) ptr=STREAMGetValue(S,"SMTP:HELO"); if (! StrValid(ptr)) { Token=GetExternalIP(Token); ptr=Token; } Tempstr=MCopyStr(Tempstr, "EHLO ", ptr, "\r\n", NULL); STREAMWriteLine(Tempstr,S); Tempstr=SMTPRead(Tempstr, S); if (*Tempstr == '2') { RetVal |= CAP_EHLO; ptr=GetToken(Tempstr,"\n",&Token,0); while (ptr) { StripTrailingWhitespace(Token); RetVal |= SMTPParseCapabilities(Token); ptr=GetToken(ptr,"\n",&Token,0); } } //Some old server that doesn't support EHLO, switch to HELO else { Tempstr=MCopyStr(Tempstr, "HELO ", ptr, "\r\n", NULL); STREAMWriteLine(Tempstr,S); if (SMTPInteract(Tempstr, S)) RetVal |= CAP_HELO; } DestroyString(Tempstr); DestroyString(Token); return(RetVal); }
//curl -X POST -d "client_id=CLIENT_ID_HERE&client_secret=CLIENT_SECRET_HERE&grant_type=password&username=YOUR_EMAIL&password=YOUR_PASSWORD" -Ss https://mastodon.social/oauth/token int OAuthGrant(OAUTH *Ctx, const char *URL, const char *PostArgs) { STREAM *S; char *Tempstr=NULL; int len, result=FALSE; Tempstr=MCopyStr(Tempstr,URL,"?",PostArgs,NULL); S=HTTPMethod("POST",URL,"application/x-www-form-urlencoded; charset=UTF-8",PostArgs,StrLen(PostArgs)); if (S) { sleep(1); Tempstr=STREAMReadDocument(Tempstr, S); result=OAuthParseReply(Ctx, STREAMGetValue(S, "HTTP:Content-Type"), Tempstr); STREAMClose(S); } DestroyString(Tempstr); return(result); }
int IDriveCloseFile(TFileStore *FS, STREAM *S) { char *Tempstr=NULL, *Error=NULL, *ptr; ListNode *Vars=NULL; int result=FALSE, val; if (S) { //if there's a boundary we must be doing a WriteFile ptr=STREAMGetValue(S,"Boundary"); if (StrLen(ptr)) result=IDriveCloseFileWrite(FS, S); else result=TRUE; STREAMClose(S); FS->S=NULL; } DestroyString(Tempstr); DestroyString(Error); return(result); }
int ConnectHopSSH(STREAM *S,int Type, char *Host, int Port, char *User, char *Pass, char *NextHop) { char *Tempstr=NULL, *KeyFile=NULL, *Token=NULL, *Token2=NULL; STREAM *AuthS; int result=FALSE, val; unsigned int TunnelPort=0; if (Type==CONNECT_HOP_SSHTUNNEL) { TunnelPort=(rand() % (0xFFFF - 9000)) +9000; //Host will be Token, and port Token2 ParseConnectDetails(NextHop, NULL, &Token, &Token2, NULL, NULL, NULL); Tempstr=FormatStr(Tempstr,"ssh -2 -N %s@%s -L %d:%s:%s ",User,Host,TunnelPort,Token,Token2); } else Tempstr=MCopyStr(Tempstr,"ssh -2 -T ",User,"@",Host, " ", NULL ); if (strncmp(Pass,"keyfile:",8)==0) { if (S->in_fd != -1) { Token=FormatStr(Token,".%d-%d",getpid(),time(NULL)); SendPublicKeyToRemote(S,Token,Pass+8); KeyFile=CopyStr(KeyFile,Token); } Tempstr=MCatStr(Tempstr,"-i ",KeyFile," ",NULL); } if (Port > 0) { Token=FormatStr(Token," -p %d ",Port); Tempstr=CatStr(Tempstr,Token); } if (Type==CONNECT_HOP_SSHTUNNEL) { Tempstr=CatStr(Tempstr, " 2> /dev/null"); AuthS=STREAMSpawnCommand(Tempstr,COMMS_BY_PTY); STREAMSetValue(S,"HelperPID:SSH",STREAMGetValue(AuthS,"PeerPID")); } else if (S->in_fd==-1) { Tempstr=CatStr(Tempstr, " 2> /dev/null"); 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); } AuthS=S; } else { if (StrLen(KeyFile)) Tempstr=MCatStr(Tempstr," ; rm -f ",KeyFile,NULL); Tempstr=CatStr(Tempstr,"; exit\n"); STREAMWriteLine(Tempstr,S); result=TRUE; AuthS=S; } if ((StrLen(KeyFile)==0) && (StrLen(Pass) > 0)) { Token=MCopyStr(Token,Pass,"\n",NULL); for (val=0; val < 3; val++) { if (STREAMExpectAndReply(AuthS,"assword:",Token)) break; } } STREAMSetTimeout(AuthS,100); //STREAMExpectSilence(AuthS); sleep(3); if (Type==CONNECT_HOP_SSHTUNNEL) { S->in_fd=ConnectToHost("127.0.0.1",TunnelPort,0); S->out_fd=S->in_fd; if (S->in_fd > -1) result=TRUE; } DestroyString(Tempstr); DestroyString(KeyFile); DestroyString(Token2); DestroyString(Token); return(result); }
//This function reads the first line of an HTTP Request, including the Method, URL, and cgi arguments void HTTPServerParseCommand(HTTPSession *Session, STREAM *S, char *Command) { char *Token=NULL, *ptr, *tmp_ptr; int val; GetSockDetails(S->in_fd,&Session->ServerName,&Session->ServerPort,&Session->ClientIP,&val); GetHostARP(Session->ClientIP, &Token, &Session->ClientMAC); if ((Settings.Flags & FLAG_LOOKUP_CLIENT) && StrLen(Session->ClientIP)) Session->ClientHost=CopyStr(Session->ClientHost,IPStrToHostName(Session->ClientIP)); LogToFile(Settings.LogPath,""); //Log first line of the response Token=MCopyStr(Token, "NEW REQUEST: ",Session->ClientHost," (",Session->ClientIP,") ", Command, NULL); if (Settings.Flags & FLAG_SSL) { Session->Cipher=CopyStr(Session->Cipher,STREAMGetValue(S,"SSL-Cipher")); Token=MCatStr(Token," SSL-CIPHER=", Session->Cipher, NULL); if (! HTTPServerCheckCertificate(Session,S)) exit(1); //Set the Username to be the common name signed in the certificate. If it doesn't //authenticate against a user then we can query for a username later Session->UserName=CopyStr(Session->UserName,STREAMGetValue(Session->S,"SSL-Certificate-CommonName")); if (Settings.AuthFlags & FLAG_AUTH_CERT_SUFFICIENT) { if (StrLen(Session->UserName)) Session->AuthFlags |= FLAG_AUTH_PRESENT; } } LogToFile(Settings.LogPath, "%s", Token); //Read Method (GET, POST, etc) ptr=GetToken(Command,"\\S",&Session->Method,0); Session->MethodID=MatchTokenFromList(Session->Method,HTTPMethods,0); //Read URL ptr=GetToken(ptr,"\\S",&Token,0); //Read Protocol (HTTP1.0, HTTP1.1, etc) ptr=GetToken(ptr,"\\S",&Session->Protocol,0); if (! StrLen(Session->Protocol)) Session->Protocol=CopyStr(Session->Protocol,"HTTP/1.0"); tmp_ptr=Token; //Clip out arguments from URL tmp_ptr=strchr(Token,'?'); if (tmp_ptr) { *tmp_ptr='\0'; tmp_ptr++; // Session->Arguments=HTTPUnQuote(Session->Arguments,tmp_ptr); //Don't unquote arguments here, one of them might contain '&' Session->Arguments=CopyStr(Session->Arguments,tmp_ptr); } //URL with arguments removed is the 'true' URL Session->OriginalURL=CopyStr(Session->OriginalURL,Token); if (StrLen(Session->OriginalURL)==0) Session->OriginalURL=CopyStr(Session->OriginalURL,"/"); if ( (strncasecmp(Session->OriginalURL,"http:",5)==0) || (strncasecmp(Session->OriginalURL,"https:",6)==0) ) { if (Session->MethodID==METHOD_GET) { Session->Method=CopyStr(Session->Method,"RGET"); Session->MethodID=METHOD_RGET; } if (Session->MethodID==METHOD_POST) { Session->Method=CopyStr(Session->Method,"RPOST"); Session->MethodID=METHOD_RPOST; } } DestroyString(Token); }
int HTTPServerActivateSSL(HTTPSession *Session,ListNode *Keys) { ListNode *Curr; int Flags=0; Curr=ListGetNext(Keys); while (Curr) { STREAMSetValue(Session->S,Curr->Tag,(char *) Curr->Item); Curr=ListGetNext(Curr); } Flags |= LU_SSL_PFS; if (Settings.AuthFlags & (FLAG_AUTH_CERT_REQUIRED | FLAG_AUTH_CERT_SUFFICIENT | FLAG_AUTH_CERT_ASK)) Flags |= LU_SSL_VERIFY_PEER; if (DoSSLServerNegotiation(Session->S,Flags)) { Session->Flags |= HTTP_SSL; return(TRUE); } LogToFile(Settings.LogPath,"ERROR: SSL negotiation failed with %s %s. Error was %s",Session->ClientHost,Session->ClientIP,STREAMGetValue(Session->S,"SSL-Error")); return(FALSE); }