diff --git a/c/rexec/Makefile b/c/rexec/Makefile new file mode 100644 index 0000000..2a6f5db --- /dev/null +++ b/c/rexec/Makefile @@ -0,0 +1,7 @@ + +all: rexec rexecd + +rexec: rexec.c rexec.h + $(CC) $(CFLAGS) $^ -o rexec +rexecd: rexecd.c rexec.h + $(CC) $(CFLAGS) $^ -o rexecd diff --git a/c/rexec/rexec.c b/c/rexec/rexec.c new file mode 100644 index 0000000..913b76a --- /dev/null +++ b/c/rexec/rexec.c @@ -0,0 +1,171 @@ +/* + * rexec: remote exec + */ + +/* + * Copyright (c) 2006 Andreas Jaggi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "rexec.h" + +const char usagemsg[] = + "usage: rexec -i [IP] -c [command] \n" + "\n" + "options:\n" + " -i IP connect to host with address IP\n" + " -c command execute command on host\n" + " also: rexec -v show version\n" + " rexec -h display this help\n" + " rexec -l display (BSD) license\n" + ; + +const char versionmsg[] = "rexec 0.2\n"; + +void usage(void); +void version(void); +void license(void); + +int main ( int argc, char* argv[] ) { + int localargsparsed = 0; + int i; + int sock; + int tmp; + int child; + char buff; + char *command = NULL; + in_addr_t remote_addr = 0; + struct sockaddr_in *remote_host_addr = NULL; + + while ( !localargsparsed && (tmp = getopt(argc, argv, "i:c:hlv")) != -1 ) { + switch ( tmp ) { + case 'h': + usage(); + exit(0); + case 'l': + license(); + exit(0); + case 'v': + version(); + exit(0); + case 'i': + remote_addr = inet_addr(optarg); + if ( command != NULL ) { + localargsparsed = 1; + } + break; + case 'c': + command = optarg; + if ( remote_addr != 0 ) { + localargsparsed = 1; + } + break; + } + } + + if ( (remote_addr == 0) || (command == NULL) ) { + usage(); + exit(-1); + } + + remote_host_addr = malloc(sizeof(struct sockaddr_in)); + remote_host_addr->sin_family = AF_INET; + remote_host_addr->sin_addr.s_addr = remote_addr; + remote_host_addr->sin_port = REXEC_PORT; + + sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if ( sock < 0 ) { + printf("error: %s\n", strerror(errno)); + exit(-1); + } + + tmp = connect(sock, (struct sockaddr*)remote_host_addr, sizeof(struct sockaddr_in)); + free(remote_host_addr); + if ( tmp < 0 ) { + printf("error: %s\n", strerror(errno)); + exit(-1); + } + + /* send command with args and a final \n */ + write(sock, command, strlen(command)+1); + for ( i = optind; i < argc; i++ ) { + write(sock, argv[i], strlen(argv[i])+1); + } + write(sock, "\n", 1); + + if ( (child = fork()) == 0 ) { + while ( tmp > -1 ) { + if ( (tmp = read(sock, &buff, 1)) == 1 ) { + printf("%c", buff); + } else { + usleep(200000); + } + } + } else { + while ( feof(stdin) == 0 ) { + if ( buff = (char)getchar() ) { + write(sock, &buff, 1); + } else { + usleep(200000); + } + } + } + + tmp = shutdown(sock, SHUT_RDWR); + if ( tmp < 0 ) { + printf("error: %s\n", strerror(errno)); + exit(-1); + } + + tmp = close(sock); + if ( tmp < 0 ) { + printf("error: %s\n", strerror(errno)); + exit(-1); + } + + while ( wait(&tmp) > 0 ) { } + + exit(0); +} + +void usage(void) { + fprintf(stdout, "%s", usagemsg); +} + +void version(void) { + fprintf(stdout, "%s", versionmsg); +} + +void license(void) { + fprintf(stdout, "%s", licensemsg); +} diff --git a/c/rexec/rexec.h b/c/rexec/rexec.h new file mode 100644 index 0000000..961cc81 --- /dev/null +++ b/c/rexec/rexec.h @@ -0,0 +1,35 @@ +#ifndef _REXEC_H +#define _REXEC_H + +#define REXEC_PORT 1234 +#define REXEC_MAX_LENGTH 1024 +#define REXEC_MAX_ARGS 256 + +const char licensemsg[] = + "rexec/rexecd is copyright (c) 2006 Andreas Jaggi \n" + "All rights reserved.\n" + "\n" + "Redistribution and use in source and binary forms, with or without\n" + "modification, are permitted provided that the following conditions\n" + "are met:\n" + "1. Redistributions of source code must retain the above copyright\n" + " notice, this list of conditions and the following disclaimer.\n" + "2. Redistributions in binary form must reproduce the above copyright\n" + " notice, this list of conditions and the following disclaimer in the\n" + " documentation and/or other materials provided with the distribution.\n" + "3. The name of the author may not be used to endorse or promote products\n" + " derived from this software without specific prior written permission.\n" + "\n" + "THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n" + "IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n" + "OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n" + "IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n" + "INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n" + "NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n" + "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n" + "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n" + "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n" + "THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" + ; + +#endif diff --git a/c/rexec/rexecd.c b/c/rexec/rexecd.c new file mode 100644 index 0000000..3d7d57a --- /dev/null +++ b/c/rexec/rexecd.c @@ -0,0 +1,206 @@ +/* + * rexecd: remote exec daemon + */ + +/* + * Copyright (c) 2006 Andreas Jaggi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +#include "rexec.h" + +const char usagemsg[] = + "usage: rexecd\n" + " rexecd -v show version\n" + " rexecd -h display this help\n" + " rexecd -l display (BSD) license\n" + ; + +const char versionmsg[] = "rexecd 0.2\n"; + +void usage(void); +void version(void); +void license(void); + +int main ( int argc, char * argv[] ) { + int sock; + int child; + int tmp; + int i,j,k; + int sock2; + int lineend; + int *remote_host_addr_len; + char buff; + struct sockaddr *remote_host_addr = NULL; + struct sockaddr_in *local_addr = NULL; + char cmdline[REXEC_MAX_LENGTH+1]; + char* cmdargs[REXEC_MAX_ARGS]; + + while ( (tmp = getopt(argc, argv, "hlv")) != -1 ) { + switch ( tmp ) { + case 'h': + usage(); + exit(0); + case 'l': + license(); + exit(0); + case 'v': + version(); + exit(0); + default: + usage(); + exit(-1); + } + } + + local_addr = malloc(sizeof(struct sockaddr_in)); + local_addr->sin_family = AF_INET; + local_addr->sin_addr.s_addr = INADDR_ANY; + local_addr->sin_port = REXEC_PORT; + + sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if ( sock < 0 ) { + printf("error: %s\n", strerror(errno)); + exit(-1); + } + + tmp = bind(sock, (struct sockaddr*)local_addr, sizeof(struct sockaddr_in)); + free(local_addr); + if ( tmp < 0 ) { + printf("error: %s\n", strerror(errno)); + exit(-1); + } + + tmp = listen(sock, 4); + if ( tmp < 0 ) { + printf("error: %s\n", strerror(errno)); + exit(-1); + } + + while ( (sock2 = accept(sock, remote_host_addr, remote_host_addr_len)) > -1 ) { + if ( (child = fork()) == 0 ) { + + if ( (child = fork()) == 0 ) { + i = 0; + do { + tmp = read(sock2, &buff, 1); + if ( tmp < 0 ) { + printf("error: %s\n", strerror(errno)); + exit(-1); + } + cmdline[i] = buff; + + i++; + } while ( buff != '\n' && i < REXEC_MAX_LENGTH ); + + lineend = i; + + cmdline[lineend] = '\n'; + + for ( i = 0, j = 0; i < lineend-1 && j < REXEC_MAX_ARGS; j++ ) { + while ( cmdline[i] == '\0' ) { + i++; + } + if ( i < lineend-1 ) { + cmdargs[j] = &(cmdline[i]); + + while ( cmdline[i] != '\0' ) { + i++; + } + } + } + + dup2(sock2, 0); + dup2(sock2, 1); + dup2(sock2, 2); + + tmp = execvp(cmdargs[0], cmdargs); + if ( tmp < 0 ) { + printf("error: %s\n", strerror(errno)); + exit(-1); + } + exit(0); + } else { + wait(); + } + + tmp = shutdown(sock2, SHUT_RDWR); + if ( tmp < 0 ) { + printf("error: %s\n", strerror(errno)); + exit(-1); + } + + tmp = close(sock2); + if ( tmp < 0 ) { + printf("error: %s\n", strerror(errno)); + exit(-1); + } + + exit(0); + } else { + usleep(200000); + } + } + + if ( sock2 < 0 ) { + printf("error: %s\n", strerror(errno)); + exit(-1); + } + + tmp = shutdown(sock, SHUT_RDWR); + if ( tmp < 0 ) { + printf("error: %s\n", strerror(errno)); + exit(-1); + } + + tmp = close(sock); + if ( tmp < 0 ) { + printf("error: %s\n", strerror(errno)); + exit(-1); + } + + while ( wait(&tmp) > 0 ) { } + + exit(0); +} + +void usage(void) { + fprintf(stdout, "%s", usagemsg); +} + +void version(void) { + fprintf(stdout, "%s", versionmsg); +} + +void license(void) { + fprintf(stdout, "%s", licensemsg); +}