linux expect command - regex

I am using the linux 'expect' to automate passwords.
#!/usr/bin/expect
set password passwd
spawn scp * root#ip_address:.
expect "password:"
send "$password\r"
expect eof
output :
spawn scp * root#ip_address:.
root#ip_address's password: *: No such file or directory
Looks like the regular expression '*' is not recognized. I know of the ssh-key gen method to set up keys but 'expect' command is more suitable for my specific case.

* is not a valid regular expression, and in the context you're using it, it would be a wildcard. The spawn will interpret it literally and pass it as an argument to the program you're starting.
If you want the asterisk globbed, you'll have to get a shell to do it for you:
spawn sh -c "scp * root#foo"

Related

Qt5 QProcess handling arguments with "special" characters

I'm maintaining a Qt5 program that uses QProcess to execute ncftpget on Linux.
The command that I'm attempting to execute is:
ncftpget -E -Z -u username -p 'a#$b1379' 1.1.1.1 /x/y/temp/ update/file
Which simply transfers a file from a server into a local directory. If I execute the above command on the bash command line it works properly.
However, when my Qt5 application executes the same command using QProcess the ftp server replies saying the username/password is not correct. When the password doesn't contain any "special" characters it works properly.
As mentioned by S.M. QProcess isn't executing the command in a shell. So I'm assuming fork() and some version of the exec() call is made. How do I make QProcess do the correct thing here?
I'm assuming that the problem has do to with the special character(s) in the password. When I build my QProcess argument list I specifically make sure the password is surrounded by ' so that the special characters are escaped.
Code snippet:
processFTP.setParent(this->parent());
processFTP.setProcessChannelMode(QProcess::MergedChannels);
// ncftpArgs is a QStringList
// snippet doesn't show complete argument list
ncftpArgs->push_back("-Z");
ncftpArgs->push_back("-u");//username
ncftpArgs->push_back(QString((*phashSettings)[FTPUSERNAME]));
ncftpArgs->push_back("-p");//pw
// password can have special characters when shell executes command.
QString password((*phashSettings)[FTPPASSWORD]);
password.prepend("'");
password.append("'");
ncftpArgs->push_back(password);
ncftpArgs->push_back(QString((*phashSettings)[FTPSERVERIP]));
ncftpArgs->push_back(QString((*phashSettings)[FTPTEMPDIR]));
//beging the ncftpget session
QString sExe = "ncftpget"; //process name
// processFTP is a QProcess object
processFTP.start(sExe, (*ncftpArgs));
bSuccess = processFTP.waitForStarted();
// .... more code to monitor process etc...
The code logs the command and arguments that will passed to processFTP and everything looks correct.
How do I properly set up the arguments and start the QProcess object so that the password argument containing the special characters are properly passed to the executable ncftpget?
And/or how do I go about debugging the problem?
When I build my QProcess argument list I specifically make sure the password is surrounded by ' so that the special characters are escaped.
Do not append or prepend the password with ', remove these lines
password.prepend("'");
password.append("'");
QProcess::start is responsible for proper way of program arguments passing. Besides bash interpreter is not run by this call in your code.

Ssh command from Qt

I have a problem with ssh in my Qt application. I need to run a command which removes a file on a remote server. I tried to use a QProcess class to achieve it. So I pass "ssh" as a name of command and necessary args. In common it looks like this:
QStringList params;
params.append(" user#" + ::host +
" \"rm /tmp/" + ::fileName + "\"");
d->impDelProcess->start("ssh", params);
But after all it keeps asking a password, though I generated ssh keys and copied a public key to the remote server. Moreover, when I run the command above in the terminal like this:
ssh user#host "rm /path/fileName"
it works perfect. The file is deleted and no password is asked. So, the problem is somwhere in QProcess. Is any way to get rid of asking a password? Thank you!
Those are separate arguments, when you use string list. Try this:
params.append("user#" + ::host");
params.append("rm /tmp/" + ::fileName);
That will make Qt pass two arguments for ssh, the login string and the command to execute at remote host.
Important note! Above assumes ::filename does not contain spaces or anything else nasty!. You can get around spaces with this:
params.append("rm '/tmp/" + ::fileName + "'");
But it won't help against wild cards or .. in path... Imagine if file name was ../home/user/* for example... So that is better be trusted input, or you need to sanitize it (but that is beyond scope of this answer).
What you do in the question code is to construct a single argument, equivalent to this shell command line:
ssh 'user#host "rm /path/filename"'

Why I cannot send more than one parameter to PHP from C++?

I want to save data from C++ to PHP and here is what I have
string cmd = "wget localhost/tem1.php?t=1&date=1&time=1";
system((const char*) cmd.c_str());
as you can see I want to send parameter t, date and time, but it just sends t without the two others parameters, here is the output :
--2016-11-21 20:56:45-- http://localhost/tem1.php?t=1
Resolving localhost (localhost)... ::1, 127.0.0.1
Connecting to localhost (localhost)|::1|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 5 [text/html]
Saving to: 'tem1.php?t=1'
Why it only takes t ? please help me to solve this problem
* Notice :
When I write it in the link bar it will insert the data successfully
Thank you
If this is on a Unix/Linux system, the reason is the ampersand &. system executes your command by executing a shell
The system() library function uses fork(2) to create a child process that executes the shell command specified in command using execl(3) as follows:
execl("/bin/sh", "sh", "-c", command, (char *) 0);
system() returns after the command has been completed.
The shell interprets & as putting the command into the background. To prevent this, you must wrap the argument with quotes
string cmd = "wget \"localhost/tem1.php?t=" + to_string(temperature) + "&date=" + date + "&time=" + time + "\"";
This tells the shell to leave the ampersand alone.

Permissions issue calling bash script from c++ code that apache is running

The goal of this code is to create a stack trace whenever a sigterm/sigint/sigsegv/etc is caught. In order to not rely on memory management inside of the C++ code in the case of a sigsegv, I have decided to write a bash script that will receive the PID and memory addresses in the trace array.
The Sig events are being caught.
Below is where I generate the call to the bash script
trace_size = backtrace(trace, 16);
trace[1] = (void *)ctx->rsi;
messages = backtrace_symbols(trace, trace_size);
char syscom[356] = {0};
sprintf(syscom,"bash_crash_supp.sh %d", getpid());
for (i=1; i<(trace_size-1) && i < 10; ++i)
{
sprintf(syscom,"%s %p",syscom,trace[i]);
}
Below is where my issue arises. The command in syscom is generating correctly. I can stop the code before the following popen, run the command in a terminal, and it functions correctly.
However running the script directly from the c++ code does not seem to work.
setuid(0);
FILE *bashCommand = popen(syscom,"r");
char buf[256] = {0};
while(fgets(buf,sizeof(buf),bashCommand) != 0) {
LogMessage(LOG_WARNING, "%s\n", buf);
}
pclose(bashCommand);
exit(sig);
The purpose of the bash script is to get the offset from /proc/pid/maps, and then use that to run addr2line to get the file name/line number.
strResult=$(sudo cat /proc/"$1"/maps | grep "target_file" | grep -m 1 '[0-9a-fA-F]')
offset=$( cut -d '-' -f 1 <<< "$strResult");
However offset is getting 0 when I run from the c++ code, but when I run the exact same command (that is stored in syscom in the c++ code) in a terminal, I get the expected output.
I have been trying to fix this for a while. Permissions are most likely the issue, but I've tried to work around these with every way I know of/have seen via google. The user trying to run the script (currently running the c++ code) is apache.
The fix does not need to worry about the security of the box. If something as simple as "chmod 777 /proc -r" worked, that would have been the solution (sadly the OS doesn't let me mess do such commands with /proc).
Things I've already tried:
Adding `` around the command that's stored in syscom from the c++ code
chown the script to apache
chmod 4755 on the bash_crash_supp.sh script, allowing it to always fire as root.
I have added apache to sudoers (visudo), allowing them to run sudo without using a password
I have added a sub file to sudoers.d (just in case) that does the same as above
I have looked into objdump, however it does not give me either the offset or the file/line num for an addr (from what I can see)
I have setuid(0) in the c++ code to set the current user to root
Command generated in C++
bash_crash_supp.sh 25817 0x7f4bfe600ec8 0x7f4bf28f7400 0x7f4bf28f83c6 0x7f4bf2904f02 0x7f4bfdf0fbb0 0x7f4bfdf1346e 0x7f4bfdf1eb30 0x7f4bfdf1b9a8 0x7f4bfdf176b8
Params in bash:
25817 0x7f4bfe600ec8 0x7f4bf28f7400 0x7f4bf28f83c6 0x7f4bf2904f02 0x7f4bfdf0fbb0 0x7f4bfdf1346e 0x7f4bfdf1eb30 0x7f4bfdf1b9a8 0x7f4bfdf176b8
Can anyone think of any other ways to solve this?
Long story short, almost all Unix-based systems ignore setuid on any interpreted script (anything with a shebang #!) as a security precaution.
You may use setuid on actual executables, but not the shell scripts themselves. If you're willing to take a massive security risk, you can make a wrapper executable to run the shell script and give the executable setuid.
For more information, see this question on the Unix StackExchange: https://unix.stackexchange.com/a/2910

Mkdir over SSH with Python does not work

I'm trying to create a new dir via SSH with a python script. When i try my commands by using the Python command line it just works. But when I try to do the same by a script it does not create the new 'test' folder (I even copy/paste the commands in the script into the Python cmd to verify they are right and there they work). So any ideas why it does not work by script?
The used code:
child = pexpect.spawn('ssh 192.168.56.101 -oStrictHostKeyChecking=no')
child.expect=('password:')
child.sendline('MyPwd')
child.sendline('mkdir /home/myUser/Desktop/test')
Seems to work when I just add another line
for example
child.sendline('\n')
so the entire script is
child = pexpect.spawn('ssh 192.168.56.101 -oStrictHostKeyChecking=no')
child.expect=('password:')
child.sendline('MyPwd')
child.sendline('mkdir /home/myUser/Desktop/test')
child.sendline('\n')
What I usually do to solve this issue is sync-ing with host machine. After I send something to the machine, I expect an answer, which usually translates in the machine's prompt. So, in your case, I would go for something like this:
child = pexpect.spawn('ssh 192.168.56.101 -oStrictHostKeyChecking=no')
child.expect('password:')
child.sendline('MyPwd')
child.expect('YourPromptHere')
child.sendline('mkdir /home/myUser/Desktop/test')
child.expect('YourPromptHere')
You can just replace YourPromptHere with the prompt of the machine, if you are running the script on a single target, or with a regular expression (eg. "(\$ )|(# )|(> )").
tl;dr : To summarize what I said, you need to wait until the previous action was finished until sending a new one.