Archive

Archive for December, 2006

Using PTYs to fool getpass()

26 December, 2006 2 comments

This is an article that I had posted in my livejournal on 4th-May-2006 03:08 pm. I’m trying to migrate the most valuable stuff to wordpress.

Today we’ll discuss the getpass() library function and the hurdles it presents for a system administrator for system automation. The usual bash pipe (‘|’) wont help us in providing password for tools like ssh, ftp, su, etc. The main reason is the way in which getpass works to get the password from the terminal. Unlike other library routines like getchar() or scanf() which read from stdin, this one opens the /dev/tty to read the user input.

The only solution been provided to overcome this is to create pseudo terminals(pty) and run your application in that. One of the most useful of the various functions used for this is forkpty(). Yes, here I’m talking about writing your own program to create a new pty, fork and run its child in that pty, and exec the application(like ssh, ftp,…) in the child. You will get a file descriptor which can be used to read or write data to the pty(ie, the application i/o). Below is given a program that tries to make a connection between you and your application.

// ptymagic.c
#include <pty.h>
#include <utmp.h>

#include <stdio.h>
#include <stdlib.h>

#include <unistd.h>
#include <pthread.h>

int readtunnel(int pty) // thread for reading from appl
{

char ch;
while(read(pty,&ch,1) != -1)
write(1,&ch,1);

}

int writetunnel(int pty) // thread for writing to appl
{

char ch;
while(read(0,&ch,1))
write(pty,&ch,1);

}

main(int argc, char **argv)
{

int pty,child;
int ret;
pthread_t pread,pwrite;

if(argc < 2)
{

exit(-1);

}

child = forkpty(&pty,0,0,0);

if(!child)
{

struct termios tios;tcgetattr(0, &tios);
tios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
tios.c_oflag &= ~(ONLCR);
tcsetattr(0, TCSANOW, &tios);

execv(argv[1],&argv[1]);

exit(-1);

}

if(child == -1)

exit(-1);

read(pty,&ret,1); // wait till the child has outputted atleast one character
write(1,&ret,1);

pthread_create(&pread,0,readtunnel,pty);
pthread_create(&pwrite,0, writetunnel,pty);

pthread_join(pread,0);

wait(&ret);

if(ret >= 0 && ret <= 255)

exit(ret);

exit(-1);

}

Compile the program as:

gcc -l pthread -l util -o ptymagic ptymagic.c

And try to run as:

echo “Your_Root_Password” | ./ptymagic su -c “cat /etc/shadow”

and see the magic.

Here, the defect is that we have to write a c program for every different kind of application which is going to be a tedious task. A better alternative is also there about which I’ll explain later.

Till then,

BYE.

Categories: System Administration

Using CVS pserver over an SSH tunnel through an intermediate server

23 December, 2006 Leave a comment

This is an article that I had posted in my livejournal on 27th-Apr-2006 12:11 pm. I’m trying to migrate the most valuable stuff to wordpress.

Today I had to access a public cvs repository from my computer in the office. Unfortunately it seemed that the company firewall disallows any cvs :pserver: connections due to security reasons. I had to find a way to checkout a module from the repository. Then I noticed an article about ssh tunnelling in the internet and quickly found my solution. I’m describing it below:

There are presently two computers in our picture. One is my system (localhost) and the other is ecos.sourceware.org. I wanted to access the repository in /cvs/ecos of the sourceware.org server. The proper way of doing it is:

cvs -z3 -d :pserver:anoncvs@ecos.sourceware.org:/cvs/ecos checkout ecos

But, it seemed that my company firewall won’t allow it to proceed since its trying to use the pserver protocol. Then, I thought of making an ssh tunnel to the sourceware.org server as a work around. But, for that I need to have an ssh account on the server itself.

Now, its here that my sourceforge.net shell account helped me. I created an ssh tunnel from my system to the sourceforge.net system and forwarded all packets at port 2401 to it. The command to create the tunnel and port forwarding looked like this:

ssh -L localhost:2401:ecos.sourceware.org:2401 jineshkj@shell.sf.net

It says that, ssh should login to shell.sf.net with as jineshkj while forwarding the localhost:2401 to ecos.sourceware.org:2401 through it. So, now I’ve added another computer to the picture, which is the shell.sf.net.

Now, in order to access the ecos.sourceware.org:2401, I only need to connect to localhost:2401. The cvs command should thus be modified as given below:

cvs -z3 -d :pserver:anoncvs@localhost:/cvs/ecos checkout ecos

What happens now is that, I’ll try to access the localhost:2401 using the pserver protocol, which actually gets forwarded to ecos.sourceware.org:2401 through the ssh tunnel. In the local system you can use custom port number other than the standard one as shown below:

ssh -L localhost:8000:ecos.sourceware.org:2401 jineshkj@shell.sf.net

cvs -z3 -d :pserver:anoncvs@localhost:8000:/cvs/ecos checkout ecos

Note that the cvs command has to be executed in your local shell and not in the ssh shell.

Best of luck.

Categories: System Administration

How to capture stdin, stdout and stderr of child program!

22 December, 2006 10 comments

This is an article that I had posted in my livejournal on 21st-Apr-2006 05:28 pm. I’m trying to migrate the most valuable stuff to wordpress.

Hi everyone,

I have been asking this particular question to everyone for some time, the solution of which I found just now. What I wanted was to capture the standard file streams of a child process. Also that, I wanted not to use any named pipes for this purpose. One of the many ways I found was using a popen() system call. But, it seem to give to the parent either of stdin or stdout, but not both, and most importantly never stderr.

I used to wonder how various IDE’s used to execute compilers and debuggers in the background providing them with proper input and interpret their output. Anyway, I could find a solution to my problem. The basic fact is that “the child process always inherits the parent’s file descriptors”. ie, if a child can be made to inherit the file descriptors 0, 1 and 2, which actually points to some pipes with their other end in the parent process, the the parent effectively captures the child’s standard file descriptors.

So, what should be done is that, before fork(), the parent has to create the required number of pipes(one pipe for each stream) and make its own standard descriptors point to the file descriptors of the child end(supposed) of the pipes. After doing the fork(), the child will have its standard descriptors as what the parent had till the fork is called(ie, one of the ends of pipes).

Suppose you have to write something to the stdin of a child program. The steps to follow are as given below:

1. Create a pipe – use pipe() – the pipe will have a read end and a write end – two descriptors
2. Duplicate parent’s stdin – use oldstream=dup(). this is just like to save our original stream
3. Close stdin – So that we can assign the read end(child’s stdin) of the pipe to file descriptor 0
4. Make read end of pipe as stdin – use dup2() to duplicate the read end fd as 0
5. do the fork() – From now on whatever the parent and child reads from stdin will come from the read end of pipe.
6. Close unnecessary fds – Close the read and write end file descriptors from the child – it’ll use only stdin from now on. You may also close read end from parent since the parent is only going to write to the pipe.
7. Restore parent’s stdin – close the fd 0, use dup2() to use the saved(oldstream) copy of the parent’s stdin.
8. Start writing to child – Now start writing to the write end of the pipe to write to the stdin of child.

The above steps may be confusing. But if spent little time to think, you’ll surely get the idea. For more help see the code given below which captures both stdin and stdout of the child which is here the ‘bc’ calculator:

#include <unistd.h>
#include <stdio.h>

main()
{

int outfd[2];
int infd[2];

int oldstdin, oldstdout;

pipe(outfd); // Where the parent is going to write to
pipe(infd); // From where parent is going to read

oldstdin = dup(0); // Save current stdin
oldstdout = dup(1); // Save stdout

close(0);
close(1);

dup2(outfd[0], 0); // Make the read end of outfd pipe as stdin
dup2(infd[1],1); // Make the write end of infd as stdout

if(!fork())
{

char *argv[]={“/usr/bin/bc”,
“-q”,
0};close(outfd[0]); // Not required for the child
close(outfd[1]);
close(infd[0]);
close(infd[1]);

execv(argv[0],argv);

}
else
{

char input[100];close(0); // Restore the original std fds of parent
close(1);
dup2(oldstdin, 0);
dup2(oldstdout, 1);

close(outfd[0]); // These are being used by the child
close(infd[1]);

write(outfd[1],”2^32\n”,5); // Write to child’s stdin

input[read(infd[0],input,100)] = 0; // Read from child’s stdout

printf(“%s”,input);

}

}

I apologise for such a lengthy post.

bye for now.

Categories: Programming

crosstool a valuable tool for embedded development

15 December, 2006 Leave a comment

Hi all,

So, this time I’m here to talk about the crosstool, a must have tool for anyone starting out to develop applications for embedded targets. The tool can automatically configure and build the complete cross development tool chain for most of the embedded platforms. This time I was trying to build the compiler for sh4 target. The procedure was simple:

  1. Get the crosstool from the website (I had used 0.43)
  2. Modify the variables TARBALLS_DIR, RESULT_TOP,GCC_LANGUAGES in demo-sh4.sh according to where you want the package source code to be downloaded, the place where the resulting binaries to be installed and the list of languages the GCC need to build respectively.
  3. If you don’t have internet(or if ur internet has any firewall blocking FTP), you may download the packages(*.tar.bz2) manually into TARBALLS_DIR directory. By inspecting the demo-sh4.sh file, I understood that the it is using gcc-4.1.0-glibc-2.3.6.dat to get the details of the package versions to obtain.
  4. Run demo-sh4.dat.

Its very nice to observe how the crosstool has cleanly built the cross compilation tool chain. The problem that I faced next was with the compilation of linux kernel(crosstool-0.43 uses linux-2.6.15.4) that was lacking adequate support for sh4 arch. Then I manually downloaded linux-2.6.19(the latest as of today) and compiled with the newly built development tools. The steps I had followed are the following:

  1. Download and untar linux-2.6.19 kernel source package and cd into it.
  2. Run make ARCH=sh CROSS_COMPILE=/opt/crosstool/gcc-4.1.0-glibc-2.3.6/sh4-unknown-linux-gnu/bin/sh4-unknown-linux-gnu- xconfig
  3. Do the necessary configuration for the kernel. By running make ARCH=sh CROSS_COMPILE=/opt/crosstool/gcc-4.1.0-glibc-2.3.6/sh4-unknown-linux-gnu/bin/sh4-unknown-linux-gnu- help you may get the list of default configurations available for various Architecture specific targets (sh). For example, the one that I used was systemh_defconfig. Running make ARCH=sh CROSS_COMPILE=/opt/crosstool/gcc-4.1.0-glibc-2.3.6/sh4-unknown-linux-gnu/bin/sh4-unknown-linux-gnu- systemh_defconfig you can generate the configuration default for the systemh board following which you may do manual configuration using the menuconfig, xconfig, gconfig, etc.
  4. Just run make.

Voila :-) Our kernel and the modules are ready to be deployed on the target board. So, now that the kernel compilation was successful, its time to do it the crosstool way. For making crosstool to use this kernel version(mind you, the only use of linux kernel for crosstool is to install the kernel headers for userland apps), I modified the LINUX_DIR variable in gcc-4.1.0-glibc-2.3.6.dat to linux-2.6.19 and copied linux-2.6.19.tar.bz2 to the TARBALLS_DIR. That’s it. Running demo-sh4.sh again is the only step required to make the tool chain use our new kernel headers.

Note that, by default the crosstool extracts the packages and build them relative to the current directory where we run the demo-sh4.sh. Inorder to have a different build directory we may modify the variable BUILD_DIR inside the all.sh script file.

Categories: Programming

Linux as router

14 December, 2006 Leave a comment

This is an article that I had posted in my livejournal on 22nd-Aug-2006 01:51 pm. I’m trying to migrate the most valuable stuff to wordpress.

Hi all,

Few weeks back I moved to a new apartment with my friends and the best part of it is the broadband connection we already have there. But the sad part is that we had to share the internet amonst us. One of many ways to do it is obviously the proxy. Proxying is fine to start with, but in long run it really gives us headache.

Few days back we started our experiments with iptables, but with a little or no success. It was then that I found the Masquerading Made Simple HOWTO . That’s it. Just two commands and my linux laptop became a router. Those commands are:

iptables -t nat -A POSTROUTING -o eth2 -j SNAT --to X.X.X.X
echo 1 > /proc/sys/net/ipv4/ip_forward

where eth2 is connected to internet through an ADSL modem with IP X.X.X.X. Now everything works fine with a few optimizations left to be done.

My next job is to configure my wireless card and run a home wifi network. The main concern here is obviously the security. I’m right now refering the Wireless Howto .

Categories: System Administration

Counting 1′s in a binary number

13 December, 2006 Leave a comment

This is an article that I had posted in my livejournal on 17th-May-2006 04:23 pm. I’m trying to migrate the most valuable stuff to wordpress.

Hi everyone,

I just wanted to find the number of ones in a binary number. In the course of finding it, I met with a few ones who claimed they are the best. But through a few tests things became clear. Of course, there could be better one tomorrow… but till the sun rises the next day, let me hope this entry of mine will hold true… The best one that I have found till now is shown below:


main()
{

unsigned int number;
while(1)
{

int cnt = 0;
scanf("%u", &number);
if(number == 0)

break;

while(number)
{

cnt++;
number = number & (number-1);

}
printf("%d\n", cnt);

}

}

The counting loop can be in many other ways as given below in the order of their ranking in performance:


while(number)
{

cnt ++;
number = number & (number ^ (-number));

}

while(number)
{

cnt += number & 1;
number >>= 1;

}

and ultimately the worst one I ever found:


power = 9999999;
while ( number > 0 && power > 0)
{

cnt++;
power = (int)(log(number)/log(2));
number = number - ( 1 << power );

}

I don’t understand why one would write such a code. May be if the log() is optimized for base 2, things could change. Right now I’m doing more rigorous tests on the above algorithms. Note that, the difference in these algorithms can be noticed only when large numbers are given as input. ie, log2() of the number should be as large as possible.

Enjoy.

Categories: Programming

jingle a headache, but not for windows

13 December, 2006 3 comments

I have been trying to use jingle with many of the jabber clients like, psi, jabbin, kopete, tapioca. the source code compilation of both psi and kopete with –enable-jingle was pretty hectic, not to mention how much a disaster was the efforts that I had put into it. All the way during their compilation, I got stuck at one message: undefined reference to `speex_wb’ and undefined reference to `pcmu8000′.

Surprisingly though, the psi compiled perfectly in my LFS system with the jingle enabled. But, since I could not find any option to compile the binary statically, I had to copy the executable with its shared library dependencies along with. To my great happiness, the psi worked with jingle and I could talk between two systems running my psi client. I’m still trying to figure out why the compilation had failed in my FC6.

It should be a happy news for windows users since the jabbin.exe works okay in windows, though it will crash if you try to do something really nasty with it. BTW, compiling libjingle with gcc gives you some simple errors which you can easily correct by modifying the source files appropriately. That’s it for now…

Categories: System Administration
Follow

Get every new post delivered to your Inbox.