Is it possible to create a proper interactive shell over http? - linux

I want to have a shell access over http to interact with a program running on my server (as opposed to SSH and other protocol). I have done some research and found two main ways, the php way such as http://sourceforge.net/projects/phpterm/ and the CGI way. Although these result in shell-like terminals over http, I can't interact with programs with standard input/output without passing paramaters at run: ./prog -options etc..
With a standard shell over netcat for example ./prog would provide full interaction so that it could prompt for input etc..
The test program I am running is:
#include<stdio.h>
#include<sys/types.h>
include<stdlib.h>
int main ()
{
// set up keyword(passcode)
char this[14];
char that[128];
// check the password and exit if it doesn't match;
fgets(this, 14, stdin);
if (strncmp(this, "passwd\n", 14)) {
exit(0);
}
printf("shell interaction success! \n");
fgets(that, 128, stdin);
system(that);
exit(0);
}
If run from netcat this would occur:
./prog
passwd
Shell interaction success
If run from other shell like solutions over http I have come accrss:
./prog
then nothing.
Fingers crossed someone knows how!

You could do this, but since HTTP is a connectionless request-response protocol, it wouldn't use just one HTTP connection.
A browser would make a request to start a shell on the remote server
A backend service would be started that creates the desired process and captures the stdin/stdout pipes
Javascript on the browser would send (POST perhaps) a request to the server to say "this user typed some character"
Some kind of AJAX request polling loop would get new output from the backend process and display it on the browser
Or, this could be considerably simplified using WebSockets which is a stream protocol (and is implemented by some browsers but is not HTTP).

Related

Telnet using JMeter 3.3

I am using Jmeter 3.2 and I need to do a telnet connection and parse the response.
Is it possible using Jmeter 3.2 or adding any plugin?
What I need to achieve is what I would do using this command line
telnet
open [IP] [PORT]
and understand if the connection is established or not.
Also I wonder what is the effective difference if I simply use a TCP Sampler.
Thanks
Given you have groovy tag here's how you can test the connectivity using Socket class, the example code would be something like:
def sock = new Socket()
sock.setSoTimeout(1000)
sock.connect(new InetSocketAddress("example.com",80))
if (sock.isConnected()) {
log.info('Connection established')
}
else {
log.info('Server is not listening')
}
Also be aware that you can invoke telnet command directly using String.execute() method like:
"telnet example.com 80".execute().text
And last but not the least, you can run an arbitrary command or program using JMeter's OS Process Sampler.

NodeJS. Child_process.spawn. Handle process' input prompt

I'm currently working on my web interface for git. Accessing git itself by child_process.spawn. Everything is fine while there is simple "command -> response" mechanism, but I cannot understand what should I do with command prompts (git fetch asks for password for example). Hypothetically there is some event fired, but I don't know what to listen to. All I see is "git_user#myserver's password: _" in command line where node.js process itself is running.
It would be great to redirect this request into my web application, but is it even possible?
I've tried to listen on message, data, pipe, end, close, readable at all streams (stdout, stdin, stderr), but no one fires on password prompt.
Here is my working solution (without mentioned experiments):
var out="";
var err="";
var proc=spawn(exe,cmd);
proc.on("exit",function(exitCode){
});
proc.stdout.on("data",function(data){
out+=data;
});
proc.stderr.on("data",function(data){
err+=data;
});
proc.on("close",function(code){
if(!code)func(out);
else return errHandler(err);
});
Can you please help me with my investigations?
UPDATE
Current situation: on my GIT web interface there is a button "FETCH" (as an example, for simple "git fetch"). When I press it, http request is generated and being sent to node.js server created by http.createServer(callback).listen(8080). callback function receives my request and creates child_process.spawn('git',['-C','path/to/local/repo','fetch']). All this time I see only loading screen on my web interface, but if I switch to command line window where node script is running I will see a password prompt. Now let's pretend that I can't switch window to console, because I work remotely.
I want to see password prompt on my web interface. It would be very easy to achieve if, for instance, child_process would emit some event on child.stdin (or somewhere else) when prompting for user input. In that case I would send string "Come on, dude, git wants to know your password! Enter it here: _______" back to web client (by response.end(str)), and will keep on waiting for the next http connection with client response, containing desired password. Then simply child.stdin.write(pass) it to git process.
Is this solution possible? Or something NOT involving command line with parent process.
UPDATE2
Just tried to attach listeners to all possible events described in official documentation: stdout and stderr (readable, data, end, close, error), stdin (drain, finish, pipe, unpipe, error), child (message, exit, close, disconnect, message).
Tried the same listeners on process.stdout, process.stderr after piping git streams to it.
Nothing fires on password request...
The main reason why your code wont work is because you only find out what happened with your Git process after is what executed.
The major reason to use spawn is beacause the spawned process can be configured, and stdout and stderr are Readable streams in the parent process.
I just tried this code out and it worked pretty good. Here is an example of spawning a process to perform a git push. However, as you may know git will ask you for username and password.
var spawn = require('child_process').spawn;
var git = spawn('git', ['push', 'origin', 'master']);
git.stderr.on('data', function(data) {
// do something with it
});
git.stderr.pipe(process.stderr);
git.stdout.pipe(process.stdout);
Make a local git repo and setup things so that you can do the above push command. However, you can really do any git command.
Copy this into a file called git_process.js.
Run with node git_process.js
Don't know if this would help but I found the only way to intercept the prompts from child processes was to set the detached option to true when you spawn a new child process.
Like you I couldn't find any info on prompts from child process in node on the interwebs. One would suspect it should go to stdout and then you would have to write to stdin. If I remember correctly you may find the prompt being sent to stderr.
Its a bit amazing to me that others haven't had this problem. Maybe we just doing it wrong.

Kernel as client, User application as server using netlink

I want to establish connection between kernel module and user application with the kernel as a client. In other words, kernel will send message to the user app, wait for reply, receive reply, and then continue execution.
For example, inside kernel I will send message and then wait for reply.
// inside kernel
nlmsg_unicast();
wait_until_user_reply();
/* process reply */
/* continue execution.. */
while inside user,
while (1) {
// inside user
recvmsg();
/* assembly reply.. */
sendmsg();
}
however, what netlink protocol does is invoking a callback function every time user sends message. What I want is to make kernel wait for a reply from user, then continue the execution. Is waiting in a busy loop on a global variable which is updated inside callback function feasible? I tried but I think that's not a very good solution.
Can I do something like "sleep until a reply come". Can I put the kernel to sleep?
I have resolved this problem using wait_for_completion. It turns out that it wasn't that hard.

Send command to running node process, get back data from inside the app

I start a node.js app per commandline in linux.
I see the app running, e.g. by entering "top".
Is there a way to send some command to the running app (maybe to the pid?) and get back info from inside it (maybe listen for some input and return requested info)?
Use repl module. There are examples in the doco doing exactly what you need: run JS in the context of your application and return output.
One simple solution is to use process signals. You can define a handler for a signal in your program to output some data to the console (or write to a file or to a database, if your application is running as a service not attached to a terminal you can see):
process.on('SIGUSR1', function() {
console.log('hello. you called?');
});
and then send a signal to it from your shell:
kill --signal USR1 <pid of node app.js>
This will invoke the signal handler you have defined in your node.js application.

Linux: How to make a daemon/service usable with xinetd?

Anybody knows what changes are necessary for a server to work with xinetd ?
The server being a .NET mailserver that runs on Linux.
See the bottom of this post for reference:
Lumisoft Mailserver Forum Post
Note: xinetd, not mono-service. [x]inetd is an internet superserver.
A superserver starts a server service on demand.
(As opposed to the server service running continuously, which is what mono-service does)
An inetd service runs differently from a standalone server. inetd services read stdin and write to stdout, letting inetd handle the gory details of TCP/IP, rather than keeping track of their own sockets. If you want to make a server run under inetd, it'll have to do the same.
The following program runs just fine under xinetd on my machine:
#include <iostream>
#include <string>
using namespace std; // yeah, i'm lazy.
int main()
{
string name;
cout << "What's your name? " << flush;
cin >> name;
cout << "Hi, " << name << "!" << endl;
}
Note i'm not at all worried about sockets -- xinetd arranges things so that the service can read standard input and write to standard output. You just write your app like you'd be running it on the console, for the most part. The socket details are specified in the config file for the service. (Note, you might be able to get/set details about the socket using stdin/stdout, which may be the actual socket -- i'm not sure -- but you really should leave that stuff up to inetd.)
An inetd services are really great for one off apps that need to take in data and act with some degree of interaction with the user. IT works over tcp/udp by piping the data viva a socket from (x)inetd to std{in,out,err}. inetd apps also works well with tcpwrappers to inhance security though system policy files and ACL.
So yes you would write your app like its a console app since in reality it is a console app. Just think of inetd as a transparent reverse proxy from the network to your app's inputs.
A Word of advice, write your code to handle the process signals correctly and if you need to interact with another process on the system use unix sockets/fifo for that.
Also, don't try to write an app that streams a lot of data all at once or needs a lot of connections. Scalability is an issue as inetd becomes a bottle neck, this is why Apache and Sendmail dropped support for inetd and sit as mono apps instead. HTTP fits this role better and a fastcgi (or insert favorite framework) script with nginx works best for that use case.
A good example for an inetd would be:
lock = Mutex.new
trap :HUP { #log the connection and cleanup }
trap :USR1 { lock.synchronize do #stuff; end }
trap :TERM { #clean up }
trap :KILL { #clean up and die with error codes }
puts "App name - version"
loop do
('%s> ' % Console.prompt).display
input = gets.chomp
command, *params = input.split /\s/
case command
when /\Ahelp\z/i
puts App.help_text
when /\Ado\z/i
Action.perform *params
when /\Aquit\z/i
exit
else
puts 'Invalid command'
end
end
exit
Edit your /etc/services to include your app like this:
myapp port#/proto
and add your app to /etc/inetd.conf (or xinetd.d) like this:
myapp stream tcp6 nowait myappuser /path/to/myapp myapp -arg_flags

Resources