How to Fake a process to be the child of another - linux

Program A (ReportHandler) calls program B (Specific Report). In order for me to get my "specific report" I need to go through program A, which then calls program B and gets me my report. My problem here is that Program B has a "security" measure that checks for program B to be a child process of program A. (This is because program A makes sure no-one else is running this program B, makes sure it gets run between x and y hour of the day, or other programs that may interfere with the running of program B, etc.)
Program A & B are C based, but I cannot (must not) change them. I checked the code and I cannot pass parameters to program A to run B from console.. SOOO, the only idea I have left, is to try and "trick" the system so that program B shows up as a child of program A so that I can run it from console.
The reason for me to try and automate this, is that I need to dial into a dozen servers each day to get this report... I want to centralize this script so that I can remotely ssh this script to each server and be done with it. would save me an hour of my day. or more.
Check being made
if ( TRUE != child_of_Program_A() )
{
epause( win[MAIN], 1,
_("This Program Must Be Run From Program A"));
return( FAILURE );
}
STATIC BOOL child_of_Program_A()
{
FILE *fp;
char statname[32];
pid_t ppid;
char proc_name[32];
char buffer[128];
char *ptr;
ppid = getppid();
while(ppid != 1)
{
snprintf(statname, sizeof(statname), "/proc/%d/status", ppid);
if (NULL == (fp = fopen(statname, "r")))
{
return(FALSE);
}
proc_name[0] = '\0';
ppid = -1;
while (NULL != fgets(buffer, sizeof(buffer), fp))
{
if (NULL != (ptr = strtok(buffer, STAT_SEP)))
{
if (strcasecmp(ptr, "name") == 0)
{
if (NULL != (ptr = strtok(NULL, STAT_SEP)))
{
if (strcmp(ptr, "Program_A") == 0)
{
fclose(fp);
return(TRUE);
}
strncpy(proc_name, ptr, sizeof(proc_name));
}
}
else if (strcasecmp(ptr, "ppid") == 0)
{
if (NULL != (ptr = strtok(NULL, STAT_SEP)))
{
ppid = atoi(ptr);
}
}
}
if (ppid != -1 && proc_name[0] != '\0')
break;
}
fclose(fp);
}
return(FALSE);

If I understand - you are making this harder than it needs to be. Automate navigating the menu maze.
Unless you really want to try the very unusual thing you asked about - consider this alternative.
Going into program A in a non-interactive way will solve the problem. scp a shell script to each of the servers, in your account. The shell script can be a here document. stdin becomes the script, in place of the keyboard.
Pretend that you have a transcript of a correct interactive session with Program A and it looks like this:
cd /foo
./programA username
password
A
/deviceA/catalog.txt
B
A
13 cows
now
The script using a here doc looks like this
#!/bin/ksh
cd /foo
./programA username<<EOF
password
A
/deviceA/catalog.txt
B
A
13 cows
now
EOF
You may have answers that are unique to each remote server, incorporate them. scp the correct file to each remote server.
ssh remote_server 'cd /foo && chmod +x ./myscript.sh
This sets execute permissions.
On your local desktop create a simple script.sh
ssh remote1 './foo/myscript.sh'
ssh remote2 './foo/myscript.sh'
ssh remote3 './foo/myscript.sh'
This script.sh now runs your report with no intervention from you. I am also guessing you may not have set up ssh keys on the remote servers - this allows passwordless access like the script above would want to have.
http://rcsg-gsir.imsb-dsgi.nrc-cnrc.gc.ca/documents/internet/node31.html

Related

How a interactive program knows the shell/terminal from which it is launched

I have a client program that can be executed in a linux terminal. The client sends this message to the server, and immediately dies once it receives the ack from the server:
struct Msg {
char my_id[16];
};
The server just appends this my_id to a log file.
The thing is, I want Msg::my_id to be the same across the terminal/shell the client is executed from. How would I do this?
Say, I am a Linux user, and open two terminals: terminals X and Y.
I ran my client from X three times, and from Y twice. In that case, what should I add to the client in order for me to see three Xs and two Ys in the server side log file?
One thing I can think of is to take the ppid and send it. Would this always work? If not, what'd be better alternatives?
#Author,
Proceed based on comment from Barmar.
I thought of sharing:
    #include <unistd.h>
    #include <string.h>
    #if defined( CYGWIN_NT ) || defined( LINUX )
            #include <iostream>
            using namespace std;
    #else
            #include <iostream.h>
    #endif
    int main()
    {
            // SAMPLE PROGRAM.
            struct Msg
            {
                    char my_id[16];
            };
            Msg obj;
            // I am not handling fork/... other related enhancements/updates at code.
            sprintf( obj.my_id, "%llu", getppid() );
            cout << obj.my_id << "\n";
            sprintf( obj.my_id, "%s", ttyname(STDIN_FILENO) );
            cout << obj.my_id << "\n";
            return 0;
    }
    $ g++ -DCYGWIN_NT getmy_id.cpp -o ./a.out
    $ ./a.out
    47130
    /dev/pty0
    $ echo $$ current terminal pid
    47130 current terminal pid
We can also achieve the same using:
user's last login:
    How to get user's last login including the year in C

Interprocess Communication with pipe and file

i'm using linux as operating system and trying to communicate three processes with pipe and file. It should work with any file put on STDIN.
And pipe works just fine, but second process is unavailable to write one char into file properly or third to read.
Firstly of course i initialize function as semlock and semunlock and opening pipe is also there. I appreciate any help cause i have no clue.
if (!(PID[1] = fork ())) {
int BUF_SIZE = 4096;
char d[BUF_SIZE];
while (fgets (d, BUF_SIZE, stdin) != NULL) {
write (mypipe[1], &d, BUF_SIZE);
}
}
if (!(PID[2] = fork ())) {
int reading_size = 0;
char r;
close (mypipe[1]);
semlock (semid1);
while (reading_size = read (mypipe[0], &r, 1)) {
if ((file = fopen ("proces2.txt", "w")) == NULL) {
warn ("error !!!");
exit (1);
}
fputc (r, file);
fclose (file);
semunlock (semid2);
}
}
if (!(PID[3] = fork ())) {
char x;
semlock (semid2);
do {
if ((plikProces3 = fopen ("proces2.txt", "r")) == NULL) {
warn ("Blad przy otwarciu pliku do odczytu !!!");
exit (1);
}
i = getc (plikProces3);
o = fprintf (stdout, "%c", i);
fclose (plikProces3);
semunlock (semid1);
} while (i != EOF);
}
What makes you think the child runs first? You haven't waited for the child process to finish so can hit EOF reading the file, before the previous child has written. Shouldn't the last fork() call be a wait, so you know the file was written? As it stands you have 4 processes, NOT 3!!
Then you are closing the mypipe[1] in the 2nd child process which as it is a forked copy, does not close the pipe inthe first child. You also are trying to write BUFSIZ characters, so you appear to be trying to write out more characters than were written, try "write (mypipe[1], &d, strlen(d));".
It looks very odd, to have the fopen() & fclose() within the character read/write loop. You really want to re-open & re-write 1 character into the file over and over?
Similarly the process2 file seems to be re-opened so the first character within would be written again and again, if it's non-empty.
There are bound to be other bugs, but that should help you for now.

rapidly writing to a temp file and renaming it... is that a good idea?

I have a daemon / service on a linux box (Debian 6) that reads from a hardware device, does some calculations and then updates a file with some relevant values. This happens about 5 times per second.
Any process that is reading the file always sees nicely structured and recent values in the file.
Here is the relevant daemon code:
while(1)
{
int rename_ret;
char tmpname[] = "/var/something/readout.tmp";
char txtname[] = "/var/something/readout.txt";
FILE *f = fopen(tmpname, "w");
if (f == NULL)
{
printf("Error opening file!\n");
exit(1);
}
# ... reading from hardware, some calculation ...
# then print to the tmp file:
fprintf(f, "%12.4f\n", CntVal1);
fprintf(f, "%12.4f\n", CntVal2);
fclose(f);
rename_ret = rename(tmpname, txtname);
if(rename_ret != 0)
{
printf("Error: unable to rename the file");
exit(1);
}
nanosleep((struct timespec[]){{0, 200000000}}, NULL); // 0.2 sec
}
This works fine, but it feels kind of... wronggg?
Note that this is not the device driver, but instead it reads from the driver and processes the values for other processes to read.
So my question is:
is this a bad idea?
what's the proper way to go about it? I like the idea to be able to "just read a file" and get fairly recent values...

Linux Terminal Problem with Non-Canonical Terminal I/O app

I have a small app written in C designed to run on Linux. Part of the app accepts user-input from the keyboard, and it uses non-canonical terminal mode so that it can respond to each keystroke.
The section of code that accepts input is a simple function which is called repeatedly in a loop:
char get_input()
{
char c = 0;
int res = read(input_terminal, &c, 1);
if (res == 0) return 0;
if (res == -1) { /* snip error handling */ }
return c;
}
This reads a single character from the terminal. If no input is received within a certain timeframe, (specified by the c_cc[VTIME] value in the termios struct), read() returns 0, and get_input() is called again.
This all works great, except I recently discovered that if you run this app in a terminal window, and then close the terminal window without terminating the app, the app does not exit but launches into a CPU intensive infinite loop, where read() continuously returns 0 without waiting.
So how can I have the app exit gracefully if it is run from a terminal window, and then the terminal window is closed? The problem is that read() never returns -1, so the error condition is indistinguishable from a normal case where read() returns 0. So the only solution I see is to put in a timer, and assume there is an error condition if read returns 0 faster than the time specified in c_cc[V_TIME]. But that solution seems hacky at best, and I was hoping there is some better way to handle this situation.
Any ideas or suggestions?
Are you catching signals and resetting things before your program exits? I think SIGHUP is the one you need to focus on. Possibly set a switch in the signal handler, if switch is on when returning from read() clean up and exit.
You should handle timeout with select rather than with terminal settings. If the terminal is configured without timeout, then it will never return 0 on a read except on EOF.
Select gives you the timeout, and read gives you the 0 on close.
rc = select(...);
if(rc > 0) {
char c = 0;
int res = read(input_terminal, &c, 1);
if (res == 0) {/* EOF detected, close your app ?*/}
if (res == -1) { /* snip error handling */ }
return c;
} else if (rc == 0) {
/* timeout */
return 0;
} else {
/* handle select error */
}
Read should return 0 on EOF. I.e. it will read nothing successfully.
Your function will return 0 in that case!
What you should do is compare value returned from read with 1 and process exception.
I.e. you asked for one, but did you get one?
You will probably want to handle errno==EINTR if -1 is returned.
char get_input()
{
char c = 0;
int res = read(input_terminal, &c, 1);
switch(res) {
case 1:
return c;
case 0:
/* EOF */
case -1:
/* error */
}
}

Tools to reduce risk regarding password security and HDD slack space

Down at the bottom of this essay is a comment about a spooky way to beat passwords. Scan the entire HDD of a user including dead space, swap space etc, and just try everything that looks like it might be a password.
The question: part 1, are there any tools around (A live CD for instance) that will scan an unmounted file system and zero everything that can be? (Note I'm not trying to find passwords)
This would include:
Slack space that is not part of any file
Unused parts of the last block used by a file
Swap space
Hibernation files
Dead space inside of some types of binary files (like .DOC)
The tool (aside from the last case) would not modify anything that can be detected via the file system API. I'm not looking for a block device find/replace but rather something that just scrubs everything that isn't part of a file.
part 2, How practical would such a program be? How hard would it be to write? How common is it for file formats to contain uninitialized data?
One (risky and costly) way to do this would be to use a file system aware backup tool (one that only copies the actual data) to back up the whole disk, wipe it clean and then restore it.
I don't understand your first question (do you want to modify the file system? Why? Isn't this dead space exactly where you want to look?)
Anyway, here's an example of such a tool:
#include <stdio.h>
#include <alloca.h>
#include <string.h>
#include <ctype.h>
/* Number of bytes we read at once, >2*maxlen */
#define BUFSIZE (1024*1024)
/* Replace this with a function that tests the passwort consisting of the first len bytes of pw */
int testPassword(const char* pw, int len) {
/*char* buf = alloca(len+1);
memcpy(buf, pw,len);
buf[len] = '\0';
printf("Testing %s\n", buf);*/
int rightLen = strlen("secret");
return len == rightLen && memcmp(pw, "secret", len) == 0;
}
int main(int argc, char* argv[]) {
int minlen = 5; /* We know the password is at least 5 characters long */
int maxlen = 7; /* ... and at most 7. Modify to find longer ones */
int avlen = 0; /* available length - The number of bytes we already tested and think could belong to a password */
int i;
char* curstart;
char* curp;
FILE* f;
size_t bytes_read;
char* buf = alloca(BUFSIZE+maxlen);
if (argc != 2) {
printf ("Usage: %s disk-file\n", argv[0]);
return 1;
}
f = fopen(argv[1], "rb");
if (f == NULL) {
printf("Couldn't open %s\n", argv[1]);
return 2;
}
for(;;) {
/* Copy the rest of the buffer to the front */
memcpy(buf, buf+BUFSIZE, maxlen);
bytes_read = fread(buf+maxlen, 1, BUFSIZE, f);
if (bytes_read == 0) {
/* Read the whole file */
break;
}
for (curstart = buf;curstart < buf+bytes_read;) {
for (curp = curstart+avlen;curp < curstart + maxlen;curp++) {
/* Let's assume the password just contains letters and digits. Use isprint() otherwise. */
if (!isalnum(*curp)) {
curstart = curp + 1;
break;
}
}
avlen = curp - curstart;
if (avlen < minlen) {
/* Nothing to test here, move along */
curstart = curp+1;
avlen = 0;
continue;
}
for (i = minlen;i <= avlen;i++) {
if (testPassword(curstart, i)) {
char* found = alloca(i+1);
memcpy(found, curstart, i);
found[i] = '\0';
printf("Found password: %s\n", found);
}
}
avlen--;
curstart++;
}
}
fclose(f);
return 0;
}
Installation:
Start a Linux Live CD
Copy the program to the file hddpass.c in your home directory
Open a terminal and type the following
su || sudo -s # Makes you root so that you can access the HDD
apt-get install -y gcc # Install gcc
This works only on Debian/Ubuntu et al, check your system documentation for others
gcc -o hddpass hddpass.c # Compile.
./hddpass /dev/YOURDISK # The disk is usually sda, hda on older systems
Look at the output
Test (copy to console, as root):
gcc -o hddpass hddpass.c
</dev/zero head -c 10000000 >testdisk # Create an empty 10MB file
mkfs.ext2 -F testdisk # Create a file system
rm -rf mountpoint; mkdir -p mountpoint
mount -o loop testdisk mountpoint # needs root rights
</dev/urandom head -c 5000000 >mountpoint/f # Write stuff to the disk
echo asddsasecretads >> mountpoint/f # Write password in our pagefile
# On some file systems, you could even remove the file.
umount testdisk
./hdpass testdisk # prints secret
Test it yourself on an Ubuntu Live CD:
# Start a console and type:
wget http://phihag.de/2009/so/hddpass-testscript.sh
sh hddpass-testscript.sh
Therefore, it's relatively easy. As I found out myself, ext2 (the file system I used) overwrites deleted files. However, I'm pretty sure some file systems don't. Same goes for the pagefile.
How common is it for file formats to contain uninitialized data?
Less and less common, I would've thought. The classic "offender" is older versions of MS office applications that (essentially) did a memory dump to disk as its "quicksave" format. No serialisation, no selection of what to dump and a memory allocator that doesn't zero newly allocated memory pages. That lead to not only juicy things from previous versions of the document (so the user could use undo), but also juicy snippets from other applications.
How hard would it be to write?
Something that clears out unallocated disk blocks shouldn't be that hard. It'd need to run either off-line or as a kernel module, so as to not interfer with normal file-system operations, but most file systems have an "allocated"/"not allocated" structure that is fairly straight-forward to parse. Swap is harder, but as long as you're OK with having it cleared on boot (or shutdown), it's not too tricky. Clearing out the tail block is trickier, definitely not something I'd want to try to do on-line, but it shouldn't be TOO hard to make it work for off-line cleaning.
How practical would such a program be?
Depends on your threat model, really. I'd say that on one end, it'd not give you much at all, but on the other end, it's a definite help to keep information out of the wrong hands. But I can't give a hard and fast answer,
Well, if I was going to code it for a boot CD, I'd do something like this:
File is 101 bytes but takes up a 4096-byte cluster.
Copy the file "A" to "B" which has nulls added to the end.
Delete "A" and overwrite it's (now unused) cluster.
Create "A" again and use the contents of "B" without the tail (remember the length).
Delete "B" and overwrite it.
Not very efficient, and would need a tweak to make sure you don't try to copy the first (and therefor full) clusters in a file. Otherwise, you'll run into slowness and failure if there's not enough free space.
There's tools that do this efficiently that are open source?

Resources