/*
* Copyright (c) 2000, 2004 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/un.h>
#include <netdb.h>
#include "config.h"
#include <sys/time.h>
#include <err.h>
#include <errno.h>
#ifdef HAVE_LIBEDIT
#include <histedit.h>
#endif
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#ifdef HAVE_LIBREADLINE
#include <readline/readline.h>
#include <readline/history.h>
#endif
#if !defined(HAVE_LIBEDIT) && !defined(HAVE_LIBREADLINE)
#error "Need either libedit or libreadline"
#endif
#define LINELEN 2048
char Buffer[LINELEN];
#define CTLNAME "honeydctl"
#define HONEYD_SOCK "/var/run/honeyd.sock"
int
usage()
{
fprintf(stderr,
"usage: %s [-v] [-t n] [LocalSock]\n"
"\t -v tells %s to output all conversation\n"
"\t -t n specifies a timeout of n seconds when connecting\n",
CTLNAME, CTLNAME);
exit(1);
}
int TimedOut = 0;
void
Timeout(int Sig)
{
TimedOut = 1;
}
#define REC_SHOW (2)
#define REC_VERBOSE (4)
char *passwd;
char *prompt;
#ifdef HAVE_LIBEDIT
char *
getprompt(EditLine *e)
{
if (prompt == NULL)
prompt = "";
return prompt;
}
#endif
int
receive(int fd, int display)
{
int Result;
int len;
char *last;
prompt = Buffer;
len = 0;
while (Result = read(fd, Buffer+len, sizeof(Buffer)-len-1), Result != -1) {
if (Result == 0 && errno != EINTR) {
Result = -1;
break;
}
len += Result;
Buffer[len] = '\0';
if (len > 2 && !strcmp(Buffer+len-2, "> ")) {
prompt = strrchr(Buffer, '\n');
if (display & (REC_SHOW|REC_VERBOSE)) {
if (display & REC_VERBOSE)
last = Buffer+len-1;
else
last = prompt;
if (last) {
last++;
write(1, Buffer, last-Buffer);
}
}
prompt = prompt == NULL ? Buffer : prompt+1;
for (last = Buffer+len-2; last > Buffer && *last != ' '; last--)
;
if (last > Buffer+3 && !strncmp(last-3, " on", 3)) {
/* a password is required ! */
Result = 1;
} else
Result = 0;
break;
}
if (len == sizeof (Buffer) - 1) {
int flush;
if ((last = strrchr(Buffer, '\n')) == NULL)
/* Yeuch - this is one mother of a line ! */
flush = sizeof (Buffer) / 2;
else
flush = last - Buffer + 1;
write(1, Buffer, flush);
strlcpy(Buffer, Buffer + flush, sizeof(Buffer));
len -= flush;
}
}
return Result;
}
int data = -1;
jmp_buf pppdead;
void
check_fd(int sig)
{
if (data != -1) {
struct timeval t;
fd_set f;
static char buf[LINELEN];
int len;
FD_ZERO(&f);
FD_SET(data, &f);
t.tv_sec = t.tv_usec = 0;
if (select(data+1, &f, NULL, NULL, &t) > 0) {
len = read(data, buf, sizeof (buf));
if (len > 0)
write(fileno(stdout), buf, len);
else
longjmp(pppdead, -1);
}
}
}
const char *
#ifdef HAVE_LIBEDIT
smartgets(EditLine *e, int *count, int fd)
#else
smartgets(int *count, int fd)
#endif
{
const char *result;
data = fd;
signal(SIGALRM, check_fd);
ualarm(500000, 500000);
result = setjmp(pppdead) ? NULL :
#ifdef HAVE_LIBEDIT
el_gets(e, count);
#else
readline(prompt);
if (result != NULL)
*count = strlen(result);
#endif
ualarm(0,0);
signal(SIGALRM, SIG_DFL);
data = -1;
return result;
}
int
main(int argc, char **argv)
{
struct sockaddr *sock;
struct sockaddr_un ifsun;
int fd, len, verbose, save_errno;
unsigned TimeoutVal;
struct sigaction act, oact;
char *sockname = HONEYD_SOCK;
#ifdef HAVE_LIBEDIT
EditLine *edit;
History *hist;
HistEvent hev = { 0, "" };
#endif
const char *l;
int ch;
verbose = 0;
TimeoutVal = 2;
while ((ch = getopt(argc, argv, "t:v")) != -1) {
switch (ch) {
case 't':
TimeoutVal = (unsigned)atoi(optarg);
break;
case 'v':
verbose = REC_VERBOSE;
break;
default:
usage();
}
}
argc -= optind;
argv += optind;
if (argc > 0)
sockname = argv[0];
sock = (struct sockaddr *)&ifsun;
memset(&ifsun, '\0', sizeof (ifsun));
#ifdef HAVE_SUN_LEN
ifsun.sun_len = strlen(sockname);
if (ifsun.sun_len > sizeof (ifsun.sun_path) - 1)
errx(1, "%s: path too long", sockname);
#endif /* HAVE_SUN_LEN */
ifsun.sun_family = AF_UNIX;
strlcpy(ifsun.sun_path, sockname, sizeof(ifsun.sun_path));
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
errx(2, "cannot create local domain socket");
TimedOut = 0;
if (TimeoutVal) {
act.sa_handler = Timeout;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGALRM, &act, &oact);
alarm(TimeoutVal);
}
if (connect(fd, sock, sizeof (ifsun)) == -1) {
if (TimeoutVal) {
save_errno = errno;
alarm(0);
sigaction(SIGALRM, &oact, 0);
errno = save_errno;
}
if (TimedOut)
warnx("timeout: cannot connect to socket %s",
sockname);
else
warn("cannot connect to socket %s", sockname);
close(fd);
return 3;
}
if (TimeoutVal) {
alarm(0);
sigaction(SIGALRM, &oact, 0);
}
/* Get Prompt ? */
receive(fd, REC_SHOW);
#ifdef HAVE_LIBEDIT
hist = history_init();
# ifdef H_SETSIZE
history(hist, &hev, H_SETSIZE, 20);
edit = el_init("honeydctl", stdin, stdout, stderr);
# else /* !H_SETSIZE */
history(hist, H_EVENT, 20);
edit = el_init("honeydctl", stdin, stdout);
# endif
el_source(edit, NULL);
el_set(edit, EL_PROMPT, getprompt);
el_set(edit, EL_EDITOR, "emacs");
el_set(edit, EL_SIGNAL, 1);
el_set(edit, EL_HIST, history, (const char *)hist);
#endif
#ifdef HAVE_LIBEDIT
while ((l = smartgets(edit, &len, fd))) {
if (len > 1)
# ifdef H_SETSIZE
history(hist, &hev, H_ENTER, l);
# else
history(hist, H_ENTER, l);
# endif /* H_SETSIZE */
#else /* !HAVE_LIBEDIT */
while ((l = smartgets(&len, fd))) {
char line[128];
if (len > 0) {
add_history((char *)l);
snprintf(line, sizeof(line), "%s\n", l);
l = line;
len++;
}
#endif
write(fd, l, len);
if (receive(fd, REC_SHOW) != 0)
break;
}
fprintf(stderr, "Connection closed\n");
#ifdef HAVE_LIBEDIT
el_end(edit);
history_end(hist);
#endif
close(fd);
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1