wxFTP - permission errors on inputstream

Talk here about issues with one of the components hosted at wxCode, or suggest features for it.
Post Reply
cobralasers
Earned a small fee
Earned a small fee
Posts: 10
Joined: Tue Mar 01, 2022 8:53 pm

wxFTP - permission errors on inputstream

Post by cobralasers »

Hello, new to this forum. I'm using an old version, wxWidgets-2.8.11 & no, unfortunately I cannot update it. Much of my current woes are part of being in a locked down environment. The C++ code is also compiling with VS 2008 :(, shoot me.

Anywho, I have an embedded Linux system running OE-Yocto project Rocko-2.4.2, with the ftpd package built into Busybox-1.24.1. I have used Busybox's menuconfig to enable the FTP feature (ftpd, Enable upload commands, Enable workaround for RFC-violating clients (though I'm not entirely sure what this does...), Enable authentication.)
The ftp server is launched on startup from a systemd service script as follows:

Code: Select all

ExecStart=/usr/bin/tcpsvd -vE 0.0.0.0 21 /usr/sbin/ftpd -wS /home/root
I wanted to keep the user there in the home directory, but they need access to the systems logs. So, in /etc/fstab I added this:

Code: Select all

/var/log    /home/root/var/log    none    bind    0    0
This works, kinda. Using a file transfer program like FileZilla I connect as root and am placed in root's home directory. There as root I can access the bound /var/log and get the system logs.

When I try using wxFTP to fetch the logs programmatically, for what ever reason, the wxFTP client doesn't seem to have permissions? I get the ftp error 550, which could be a few things but based on the behavior I observe I guessing permissions. wxFTP code looks like this:

Code: Select all

void CouchView::OnRetrieveCouchLogs(wxCommandEvent& event)
{
    // Prompt the user for a file name
    wxFileDialog saveFileDialog(this, wxEmptyString, wxEmptyString,
        "CouchLogs.zip", "Supported Files (*.zip)|*.zip", wxFD_SAVE | wxFD_OVERWRITE_PROMPT);

    if (saveFileDialog.ShowModal() == wxID_OK)
    {
        wxString FileName = saveFileDialog.GetFilename();
        wxString FullPath = saveFileDialog.GetPath();
        wxString FolderPath = FullPath.BeforeLast(wxFileName::GetPathSeparator());


        // Create a progress dialog for retrieval
        wxProgressDialog progressDialog(wxTheApp->GetAppName(),
            "Retrieving logs. Please wait...", 0, wxTheApp->GetTopWindow(), wxPD_APP_MODAL);
        
        // connect to FTP server
        wxFTP ftp;
        ftp.SetUser("root");
        ftp.SetPassword("password");
        ftp.SetDefaultTimeout(3);
        if ( !ftp.Connect("192.168.10.7") )
        {
            wxMessageBox("Failed to connect to FTP server to retrieve files.", 
                "Retrieval Error", wxOK | wxICON_EXCLAMATION);
            return;
        }

		ftp.SetBinary();
		ftp.ChDir("/home/root/var/log/");
		ftp.GetFilesList(files);
		if(files.size() <= 0)
		{
			return;
		}

        // create zip archive
        wxFFileOutputStream out(FullPath);
        if(!out.IsOk())
        {
            wxMessageBox("wxFFileOutputStream is not valid", 
                        "Retrieval Error", wxOK | wxICON_EXCLAMATION);
                    return;
        }
       
        wxZipOutputStream zip(out, -1, wxConvUTF8);
        if(!zip.IsOk())
        {
            wxMessageBox("wxZipOutputStream is not valid", 
                        "Retrieval Error", wxOK | wxICON_EXCLAMATION);
                    return;
        }
        // retrieve each file and store it in the zip archive
        for (size_t i = 0; i < files.size(); i++)
        {
            wxInputStream* in = ftp.GetInputStream(files[i]);

            // make sure we've got good data
            if (in)
            {
                // Write the downloaded file to the zip archive
                if(zip.PutNextEntry(files[i]))
                {
                    zip.Write(*in);    
                    wxString msg = wxString::Format( wxT(" bytes written = '%d' "), zip.LastWrite() );
                    wxMessageBox(msg.mb_str(), "Attempting write", wxOK | wxICON_EXCLAMATION);
                    msg = wxString::Format( wxT(" Last Error = '%d' "), zip.GetLastError() );
                    wxMessageBox(msg.mb_str(), "DEBUG ", wxOK | wxICON_EXCLAMATION);  
                }
                else
                {
                    wxMessageBox("Failed to add file to zip", 
                        "Retrieval Error", wxOK | wxICON_EXCLAMATION);
                    return;
                }

                // delete the file download stream
                delete in;
            }
            else
            {
                    wxMessageBox("Failed to get wxInputStream", 
                        "Retrieval Error", wxOK | wxICON_EXCLAMATION);
                    return;
            }
        }
    }
}
It fails to get open the inputstream: wxInputStream* in = ftp.GetInputStream(files); How is it that FileZilla with the same credentials, same server & location, same transfer mode (passive - binary) works and wxFTP does not?

Any ideas?
Last edited by cobralasers on Wed Mar 02, 2022 8:12 pm, edited 1 time in total.
User avatar
doublemax
Moderator
Moderator
Posts: 19159
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxFTP - permission errors on inputstream

Post by doublemax »

I can only guess that Filezilla sends some commands to the ftp server that wxFTP doesn't. Check the ftpd log file, it should contain all the commands that are exchanged between server and client.

Alternatively, use libcurl instead of wxFTP.
Use the source, Luke!
cobralasers
Earned a small fee
Earned a small fee
Posts: 10
Joined: Tue Mar 01, 2022 8:53 pm

Re: wxFTP - permission errors on inputstream

Post by cobralasers »

doublemax wrote: Tue Mar 01, 2022 10:28 pm I can only guess that Filezilla sends some commands to the ftp server that wxFTP doesn't. Check the ftpd log file, it should contain all the commands that are exchanged between server and client.

Alternatively, use libcurl instead of wxFTP.
That is a good idea. I didn't realize there was yet one more level of verbosity I could add to the ftpd server logging. With that I can now see the commands showing up on the target. I have attached the respective logs files. After reviewing them, nothing is really standing out to me though.

Aside from FIleZIlla is issue the raw command:

Mar 1 22:53:15 CCA ftpd[966]: RETR file.txt

I am going to try this out instead of the current method of opening input/outputstreams & creating a zip file, but I am not sure at the moment how to use the wxFTP::SendCommand feature.
Attachments
syslog_prog.txt
ftpd syslogs from program
(3.39 KiB) Downloaded 157 times
syslog_FileZilla.txt
ftpd syslogs from FileZilla
(3.96 KiB) Downloaded 137 times
User avatar
doublemax
Moderator
Moderator
Posts: 19159
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxFTP - permission errors on inputstream

Post by doublemax »

Code: Select all

Mar  1 22:55:22 CCA ftpd[1027]: PASV 
Mar  1 22:55:22 CCA ftpd[1027]: 227 PASV ok (192,168,10,7,166,205) 
Mar  1 22:55:22 CCA ftpd[1027]: RETR .bash_history 
Mar  1 22:55:22 CCA ftpd[1027]: 150 Opening BINARY connection for .bash_history (2150 bytes) 
Mar  1 22:55:22 CCA ftpd[1027]: 226 Operation successful 
This looks like you could successfully download this particular file?


Code: Select all

Mar  1 22:55:24 CCA ftpd[1027]: PASV 
Mar  1 22:55:24 CCA ftpd[1027]: 227 PASV ok (192,168,10,7,173,17) 
Mar  1 22:55:24 CCA ftpd[1027]: RETR .config 
Mar  1 22:55:24 CCA ftpd[1027]: 550 Error 
I didn't see you downloading the same file with Filezilla. Maybe the ftp daemon just has no rights to read it?


Code: Select all

Mar  1 22:55:13 CCA ftpd[1027]: RNTO /home/root/CouchLogs 
Mar  1 22:55:13 CCA ftpd[1027]: 550 Error 
Do you actively try to rename files in your code?
Use the source, Luke!
cobralasers
Earned a small fee
Earned a small fee
Posts: 10
Joined: Tue Mar 01, 2022 8:53 pm

Re: wxFTP - permission errors on inputstream

Post by cobralasers »

Sorry about that, you are correct. syslog_prog.txt must have been from a run where I was trying something else; like trying to copy the files into a different directory. I just modified the code to only execute the RETR commands for the files I want, looks like this:

Code: Select all

for (size_t i = 0; i < files.size(); i++)
            {
                std::string file_in_list;
                file_in_list = std::string(files[i]);
                if(file_in_list.empty())
                {
                    LogCalibration("+++DEBUG Message - 4.25 wxString to std::string failed - ");
                    return;
                }
                if (file_in_list.find("Log_I_want") != std::string::npos) 
                {
                    wxString msg = wxString::Format( wxT("RETR '%s' "), files[i]);
                    ftp.SendCommand(msg);
                } 
            }
with this run, I see this in the ftp logs on the target:

Code: Select all

Mar  2 18:15:29 CCA ftpd[567]: 226 Operation successful
Mar  2 18:15:29 CCA ftpd[567]: TYPE I
Mar  2 18:15:29 CCA ftpd[567]: 200 Operation successful
Mar  2 18:15:29 CCA ftpd[567]: CWD /home/root/var/log/
Mar  2 18:15:29 CCA ftpd[567]: 250 Operation successful
Mar  2 18:15:29 CCA ftpd[567]: PASV
Mar  2 18:15:29 CCA ftpd[567]: 227 PASV ok (192,168,10,7,173,241)
Mar  2 18:15:29 CCA ftpd[567]: NLST
Mar  2 18:15:29 CCA ftpd[567]: 150 Directory listing
Mar  2 18:15:29 CCA ftpd[567]: 226 Operation successful
Mar  2 18:15:29 CCA ftpd[567]: RETR 'Log_I_want.csv'
Mar  2 18:15:29 CCA ftpd[567]: 425 Use PORT/PASV first
Mar  2 18:15:29 CCA ftpd[567]: RETR '_Log_I_want00Num.txt'
Mar  2 18:15:29 CCA ftpd[567]: 425 Use PORT/PASV first
Mar  2 18:15:29 CCA ftpd[567]: RETR '_Log_I_want01.txt'
Mar  2 18:15:29 CCA ftpd[567]: 425 Use PORT/PASV first
Mar  2 18:15:29 CCA ftpd[567]: RETR '_Log_I_want02.txt'
Mar  2 18:15:29 CCA ftpd[567]: 425 Use PORT/PASV first
Mar  2 18:16:02 CCA ftpd[567]: PASV
Mar  2 18:16:02 CCA ftpd[567]: 227 PASV ok (192,168,10,7,143,151)
None of them say Operation successful....so unless I am not using the SendCommand correctly, I may just start looking into libcurl.
User avatar
doublemax
Moderator
Moderator
Posts: 19159
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxFTP - permission errors on inputstream

Post by doublemax »

I'm not too familiar with the ftp protocol, maybe you have to send PASV before any command that receives data? That's what it looks like in the Filezilla log.
I may just start looking into libcurl.
That's a good idea in any case.
Use the source, Luke!
cobralasers
Earned a small fee
Earned a small fee
Posts: 10
Joined: Tue Mar 01, 2022 8:53 pm

Re: wxFTP - permission errors on inputstream

Post by cobralasers »

oft. just read this:
http://proton-ce.sourceforge.net/rc/wxw ... wxftp.html
...To use a commands which doesn't involve file transfer (i.e. directory oriented commands) you just need to call a corresponding member function or use the generic SendCommand method. However to actually transfer files you just get or give a stream to or from...
so, I guess that's not going to work.
Post Reply