

sfrazor
Members-
Content Count
62 -
Joined
-
Last visited
Everything posted by sfrazor
-
Thank you. I'll look at that example. Working strictly with self signed keys in a closed environment, I need to specifically validate (compare) a compiled in public key in the client to the public Key sent by the server and accept or reject based on that compare.
-
Commented out exceptions in OverbyteIcsHttpPort
sfrazor posted a topic in ICS - Internet Component Suite
Commented out exception handling around line 3996. {* if FStatusCode > 401 then Dec 14, 2004 *} // if NOT FResponseNoException then begin { V8.54 should error exceptions be skipped? } // if FRequestDoneError <> httperrNoError then { V7.23 } // raise EHttpException.Create(FReasonPhrase, FRequestDoneError) { V7.23 } // else if (FStatusCode >= 400) and (FStatusCode <> 401) and (FStatusCode <> 407) then // raise EHttpException.Create(FReasonPhrase, FStatusCode); // end; Why? I'm using Fr0sT-Brutal's memorymodule to load a DLL plugin. When a parent DLL, loaded with loadlibrary, loads a child DLL via memorymodule, the exception handlers do not fire and a raise will kill the child (plugin) DLL when a connection failure happens. Seems as though the try/except never fires correctly. In original development I was using the exception handler to rotate dest IP's from Host1 to Host2. Using rundll32 to test the plugin DLL and building the DLL as an EXE everything works as expected. SO its a combination of a DLL loading DLL via memorymodule. Some background: We have a DOS app that is a small loader. It loads the main DLL via a normal loadlibrary which is the application itself. The main app runs fine and all exceptions fire correctly. However using memorymodule to load a child (plugin) DLL the try/excepts no longer work like I would expect. I'd like to understand why. After reading, I see that raising exceptions and something about DLL boundries will cause this problem? I don't pretend to understand. I originally hit this roadblock when using TNETHTTPClient and a raise in System.Net.HTTPClient.Win line 1538. Thiis was the original component used. Using that component I was attemping to use the exception handler ot switch between Host1 and Host2 should a comms failure happen. Before I can trap any errors or validate any http results, that raise kills the Child and cascades to the parent. Again, this is with memorymodule loading the child. So, on to ICS. Hoping I can use the above idea to switch Hosts on connectoin failure events I ran in to a similar problem and decided to comment out the above section of Exceptions as a trial. Exceptoins no longer kill the DLL. I don't know ICS very well so capturing the failure and rotating Hosts is still something I'm working on. Any suggestions would help. I'm fairly certain there is no easy way to fix this considering I'm stuck using memorymodule. Will the above lines commented out hurt? I'm concerned that some event handler, someplace, relies on them and I just caused my self problems. Or is there a better way to switch/rotate hosts upon failure that won't trip exceptions? Also, the child DLL mentioned is nothing more than a HTTPS client using GET to check for updates from a rest server. In the past it never had to rotate hosts. Thanks for taking the time read all of this. example.7z -
Commented out exceptions in OverbyteIcsHttpPort
sfrazor replied to sfrazor's topic in ICS - Internet Component Suite
Thanks Frost, I'm using TNETHTTPClient - which is just a WINHttp wrapper it seems. It seems pretty fast and fairly lightweight that handles HTTPS get and post and allows for cert verification and doesn't generate callbacks based on raising exceptions. With the added bonus of cross platform and no openssl dlls needed. memorymodule works pretty well. Not sure what's wrong that exceptions won't percolate to the top. The C version works because callbacks are pointers set intentionally and of coarse there are no exceptions to muck thing up. Its all result codes. If there were a lightweight HTTPS put and get (preferably that don't need openssl... I use YuOpenSSL when I can) that don't use exception handlers to manage traffic memorymodule would work. As I mentioned to Angus, I don't see any good options for loading DLL's from resource or streams. I set the code aside and am looking at ICS today and tomorrow. WAY more features than I need. I really appreciate everyone here taking the time to try and help. -
Commented out exceptions in OverbyteIcsHttpPort
sfrazor replied to sfrazor's topic in ICS - Internet Component Suite
Thanks Angus, Never heard of memorymodule, not sure what relevance it has here. Correct, Memorymodule has no relevance her except to expose all that I was trying to attempt and bring attention to what it was I was trying to do, and it wasn't a simple loadmodule call. The exacting issue is TNHTTPClient.Post and TNETHTTP.Get use exceptions to flag callbacks such as ValidateServerCertificate. TNETHTTPCLient.Post generates an exception and then call back to ValidateServerCerrtivicate. Normal loadmodule handles the exception and the validation callback happens fine. All exceptions percolate to the top and the finally handles it. That very same exception using memorymodule fails to call the validation callback and the raise kills the DLL. Hence I was looking at ICS and you mentioned ResponseNoException property. This is what I'm experimenting with now. There seems to be no other components/libraries etc available to load a DLL from a resource file or stream. In C, the public available memorymodule that Fr0sT.Brutal ported works perfectly in C and in Delphi (as long as no execptions are raised). Now that I'm aware of the property for ResponseNoException (I feel stupid for missing that). no commented line changes are needed 🙂 Thank you for that hint. So to sum it up, I need to load DLL's from a resource file or memorystrream and manage HTTP Get and HTTP Put (HTTPS) talking to a REST API . Something light-weight is preferred. I'm still looking for that. -
Spending time on a function to ping continuously I noticed that I can't seem to kill the proccess I started. I googled around a bit and copied this peice of code to learn with and noticed that if a command ends properly all is well. I thought I knew how and I've tried a few things. You'll notice the lines commented out of the various things I tried. The end goal is to collect the ping results until a time expires. But I never got that far. In task manager, after each of he attempts to terminate the ping, it shows to be still running. What am I doing wrong? procedure GetDosOutput; var SA: TSecurityAttributes; SI: TStartupInfo; PI: TProcessInformation; StdOutPipeRead, StdOutPipeWrite: THandle; WasOK: Boolean; Buffer: PAnsiChar; BytesRead: Cardinal; WorkDir: string; Handle: Boolean; CommandLine: string; Output: String; taskkill: string; begin CommandLine:='c:\windows\system32\cmd.exe /c ping -t 127.0.0.1'; Buffer:=AllocMem(128000); Output := ''; with SA do begin nLength := SizeOf(SA); bInheritHandle := True; lpSecurityDescriptor := nil; end; CreatePipe(StdOutPipeRead, StdOutPipeWrite, @SA, 0); try with SI do begin FillChar(SI, SizeOf(SI), 0); cb := SizeOf(SI); dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; wShowWindow := SW_HIDE; hStdInput := GetStdHandle(STD_INPUT_HANDLE); hStdOutput := StdOutPipeWrite; hStdError := StdOutPipeWrite; end; PI:= Default(TProcessInformation); UniqueString(CommandLine); Handle := CreateProcess(nil, PWIdeChar(CommandLine), nil, nil, True, 0, nil, nil, SI, PI); CloseHandle(StdOutPipeWrite); if Handle then try repeat WasOK := ReadFile(StdOutPipeRead, Buffer, 128000, BytesRead, nil); if BytesRead > 0 then begin Buffer[BytesRead] := #0; Output := Output + Buffer; end; until not WasOK or (BytesRead = 0); WaitForSingleObject(PI.hProcess, 5000); finally //TerminateProcess(PI.hProcess,0); //CloseHandle(PI.hThread); //CloseHandle(PI.hProcess); end; finally CloseHandle(StdOutPipeRead); end; // taskkill:= '/C taskkill /f /t /PID = '+ INtToStr(PI.dwProcessId); // ShellExecute(0, nil, 'cmd.exe',pWideChar(taskkill), nil, SW_HIDE); // taskkill:= '/C taskkill /f /t /PID = '+ INtToStr(PI.hProcess); // ShellExecute(0, nil, 'cmd.exe',pWideChar(taskkill), nil, SW_HIDE); FreeMem(Buffer); end;
-
Thanks FPiette. I do use the ICS and Indy components. Ping -t is just a simple example. The end goal would be to kill a stuck process that I started after x seconds/minutes and capture the output until that time. There is a couple of good DOS components that are overkill, but I don't learn that way. 🙂 The WaitForSIngleObject is set for 5 seconds. When it expires it falls through like I would expect and the taskkill, closehandle etc get executed as I would think. But still the ping -t doesn't die. I'm using ping -t as an example but other continuous commands suffer the same. What I don't understand is, even when the taskkill or closehandle get executed the procerss doesn't die. I don't directly have the PID of ping so I'm missign something. From what I can tell, the dwProcessID is the PID of the cmd.exe that is created but when that is killed, the ping keeps going even though the parent is gone. Maybe there is a better way to careate a process, monitor it and kill it after a time, if its still running.
-
I'm wanting to extend a Windows app via plugins. I'm sure this has come up before but I'm not quite sure what to search for. I have a standard windows Form app that has a menu across the top and side. I'd like to add plugins (new menu options) to the menu on the side. I'd like for the plugin to be scripted so any dev can add them. I down want be stuck producing a dll that has to be put in place but prefer a script (not picky about the scripting language) Add the plugin script to a folder and when the app starts/restarts the new menu item shows up and is interactive with the main app. Simplicity is key.... I'm sure I can do it but it sounds more difficult than it probably is. This is something I'm toying with after seeing a python app that allows plugins via very small and simple python scripts and am curious if I can accomplish something similar. Can someone point me to an example perhaps? Or ideas?
-
Thanks Frost, for me, this whole exercise is learning. I've never tried to dynamically extend an app other than dll's. I'd think including a script engine would be a good way to go. What would really be good is to be able to create the plugin from within the app. So a script editor perhaps available in an admin area. Sort of a mini Delphi editor maybe. I've read a bit about some of the scripting tools in Delphi having access to the main app by exposing certain classes/objects. That's also interesting but I'm not confident on how to tie it all together. Sorry if I sounds like I'm rambling. This weekend I'll dive in a bit. My bet is that someone has been down this road already, and solved it. All of this came from a python app I was working on. Its easy to include a plugin because the entire language is scripting and the groundwork for pulling in plugins was already in place. It was prone to lots of debugging, so I was thinking maybe I could do it in Delphi easier once I got it straight.
-
It looks like TNetHTTPClient trusts all CA's by default. Then leaves it up to the developer to verify the public key. But, is there a way to only allow or validate against a specific CA? I've done some searching and reading and Indy comes up with some examples but I don't see anything on TNetHTTPClient and how to accomplish this.
-
Thanks for the response. I really like ICS. Last visit to the site there was some info on the use of YuOpenSSL. I'm going to go search when I'm done here. Specifically is there a how-to to add YuOpenSSL as an alternative? Last look it was a bit cryptic for me to understand.
-
Thanks, and yes. I'm using the callback for validating (cert pinning). So I was confused. The components utilize native cert validation unless the callback is in place. I was confused what the pubkey was and I found out it is the modulus. My lack of understanding of the validating the cert. Or overall lack of understanding. But I'm learning!
-
Right, what I'm saying is our requirements doc produced by our Project Manager dictates what's wanted for a specific dev task. In this case (and not always) he asked for a single dll deliverable. The dll is obviously including https comms. Makes my job interesting to say the least.
-
Hey Frost, Sorry for the late reply. I can make suggestions for projects when things just don't make sense. This forum is good at pointing those things out. Like why no SSL dll's. But the short of it is, the requirement of packaging a single deliverable executable or DLL which the PM describes as no openssl DLL's if at all possible. This leaves me with Indy and ICS for comms components using YuOpenSSL.
-
I've done some searching and see very minimal information about running Delphi in a CI/CD pipeline on gitlab. I wish it was CMAKE driven but MSBUILD is OK I suppose, I have a successful CI/CD pipeline running with MSBuild. Finally. My question is specific to gitlab and what files need to be committed to the repo for proper collaboration. In my environment all changes are peer reviewed and accepted for merge. However, the commit changes are littered with .dproj, .local, .grpproj and cache XML files. Obviously the .cache files can be added to the .gitignore. What exactly is required to commit to gitlab for proper collaboration? The catch is, if I make changes to my local environment, it gets pushed which is not needed If I add a project to the group It gets pushed via the grpproj file, which is needed so the next person checking out the project has the new project in the group, The .grpproj seems to get pushed every time by the fact that its touched. Maybe I'm wrong. All of t his seems very messy. Is there a proper way to accomplish all of this in git that will eliminate all of the change cruft from being pushed?
-
Yes, I saw that ICS also has the ability to build against YUOpenSSL. I may have to hit up Remy for some hand holding if I decide to use Indy and YUOpenSSL. If we work it out, I'll post the details here.
-
I made mods to my .gitignore based on your example. Thanks! I'll see how that does. Also pulled down the projectmagician to give that a try....
-
Thanks Frost. I did end up using the windows API like you mentioned. Not what I would have liked. I would have used Indy if they had a way to eliminate the openssl distribution requirement. On that note, I see there is an option for YUOpenSSL (or whatever its called) that interests me. But no step-by-step for dummies (that I find) on how to implement it. Add the compiler options, add the YUOpenSSL library and install the new alternate Indy in to Delphi. But its promising. Indy has all of the above Cert details surfaced which is what I really need.
-
At the moment I'm playing with TNetHTTPClient.UseDefaultCreedentials:= False to turn off the default credential validation then TNetHTTPClient.CredentialStorage.AddCredentials(MyCreds); Trying to turn off the accept ALL CA's and insert my own. I have no idea if I'm heading in the right direction. I don't see any good examples of how to add my own CA cert and validate a server CA against it.
-
When building a DLL, I have a series of arrays that I want compiled together in the binary. Perhaps like a packed record. I'm not sure I'm asking this question correctly.... For example item1: array [0..64] of ansichar item2: array [0..64] of ansichar item3: array [0..64] of ansichar I want the compiler/linker to keep them together in the binary so I can open the DLL and do a replace on 192 contiguous bytes. The compiler seems to move these around and not contiguous. Is there a way, or a better way to achieve this without using a packed record? I've searched the compiler and linker flags but I don't see anything that looks obvious. The Align flag doesn't seem to be what I'm looking for.
-
Sorry for the late reply. That was a wow moment! I honestly didn't even think of that. That's a MUCH easier refactor than I was getting ready to do. Thanks Remy. I'll give it a try. I'll have to figure out how to add a search marker so I can scan the binary for the beginning of the array.
-
Thank you. I was afraid that was the answer. I have some refactoring to do of some rather ugly code.
-
I have a common.pas file that contains a procedure dbgWriteLn. It would seem I would have to get a valid Handle for the current cmd.exe process and write to that. The procedure looks like this: Atach Console is defined thus: function AttachConsole(dwProdessID: Integer): boolean; stdcall external 'kernel32.dll'; function FreeConsole(): Boolean; stedall; external 'kernel32.dll' procedure DbgWriteLn(const outstr: string); begin {$IFDEF DEBUG} AttachConsole(-1); WriteLn(outstr); FreeConsloe; {$ENDIF} end; Using a simple exe that loads the dll via LoadLIbrary and GetProcAddress, I call the entry point and all is fine. Except I need to have debug output on the cmd.exe console when the loader loads and runs the dll. The loader works fine. There is no output from the dbdWriteLn within the dll. After a bit of searching I don't find anything definitive. I read that WriteLn is not a typical replacement for something like printf. Writeln output is given special handling within the compiler if I understand it properly. The dll gets passed to a tester for review and the release and debug version are included. He needs to see the debug outpout from the dll. In C printf works regardless. I need something similar in delphi. Or is there a better way to achieve the output to the console (stdout) from within a dll that is run via a cmd.exe console?
-
Update: After some reading and trying to understand why WriteLn is not working in the above code, I tried to this with some success: Still not sure if this is the best way to accomplish this. procedure DbgWriteLn(const outstr: string); var WinHandle: THandle; written: cardinal; begin if outstr.length = 0 then Exit; {$IFDEF DEBUG} WinHandle:= GetStdHandle(std_Output_Handle); if (WinHandle <> Invalid_Handle_Value) then begin WriteConsole(WinHandle,Pointer(outstr),outstr.length,written,nil); end; {$ENDIF} end;
-
In the past I've used easy curl/libcurl in C to accomplish some tasks. I am novice when it comes to this so forgive me if I construct my questions incorrectly. I'm trying to understand how to accomplish the following in native Delphi using the TNetHTTPClient/NetHTTPRequest component. Rather than post a bunch of embarrassing code, I'll post some C Code best I can recall that I've worked through in the past and see if I can accomplish it in Delphi. I don't mind reading but I didn't see anything that addressed this on a simple level I can understand. If I'm understanding, there is nothing CURL is doing here that a HTTP Client can't accomplish. In 'C' //first some curl basic setup.... then: curl_mimepart *part; curl_addpart(mime); curl_mime_name(part, "data"); curl_mime_filename(part, "filename"); //there is no filename but curl is odd and needs it to send as if binary data if I remember correctly. curl_mime_data(part, databuf, data_len); curl_mime_type((part, "application/octet-stream"); // NetHTTPClient1.ContentType:= 'application/octet-stream' ?? curl_easy_setopt(curol, CURLOPT_MIMEPOST, mime); // NetHTTPRequest1.MethodString:= 'POST' ?? curl_easy_perform(curl); What am I trying to accomplish? Sending a simple binary data buffer as if it were a file.
-
Remy, Thanks for the details. It helps. This should go a bit further in clarifying my process..... PostData: TMultipartFormData; ms: TMemoryStream; ResultString: TStringStream; URL: string CompressedWithBytes: string;; CompressedLen: Cardinal; //unsigned is required by the server .... URL := 'https://10.1.1.1:8443/' ms := TMemoryStream.create ResultString := TStringStream.create; PostDat := TMultipartFormData.create; CompressedWithBytes := ZipAddJSON(JSONDATA); // Returns string with 4 bytes added to header (27 02 00 00 <GZIP-JSON data>) CompressedLen := Length(CompressedWithBytes); ms.write(CompressedWithBytes, CompressedLen); Postdata.AddStream('data', ms, 'filename', 'application/octet-stream); NetHttpRequest.Post(URL,PostData); Server Side Python3 Receives HTTP(S) POST ... filedata = request.files.get('data'); // verifies data keyword is there prints error if missing // verifies application/octet-stream is there prints error if missing data = file.stream.read() file.close() size = int.from_bytes(data[:4], 'little) <- this should be the 4 byte size of the uncompressed data print(f"First four bytes: {size}") First four bytes: 88434780 <--should be 27020000 which is the first 4 bytes added to the data before sending data = zlib.decompress(data[4:], buffsize=int.from_bytes(data[:4], "little")) <---------- fails excep zlib.error as e: raise HTTPError(400, f"Failed to decompress data: {e}") //Exception Prints: //Error in app: Failed to decompress data: Error -3 while decompressing data: incorrect header check I'll see if I can provide the curl raw data... Its actually production code that send periodic updates to a server. I also don't know how to do that with TNETHTTPCLient or TNETHTTPRequest 😞