From a3c62230162f44891ec4ced3a8937cc775acb0bf Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 25 Mar 2010 21:33:21 +0800 Subject: remove code duplication between telnet-client / telnet-client-ipa We now simply use the original telnet-client.c with one small callback into the ipaccess authentication layer --- util/Makefile.am | 3 +- util/ipaccess-auth.c | 80 ++++++++++++ util/telnet-client-ipa.c | 327 ----------------------------------------------- util/telnet-client.c | 6 + 4 files changed, 88 insertions(+), 328 deletions(-) create mode 100644 util/ipaccess-auth.c delete mode 100644 util/telnet-client-ipa.c diff --git a/util/Makefile.am b/util/Makefile.am index 7134d68..5cee32b 100644 --- a/util/Makefile.am +++ b/util/Makefile.am @@ -1,8 +1,9 @@ AM_CFLAGS = -I.. AM_LDFLAGS = -L.. -ipaccess_telnet_SOURCES = telnet-client-ipa.c ../libtelnet.h +ipaccess_telnet_SOURCES = telnet-client.c ../libtelnet.h ipaccess-auth.c ipaccess_telnet_LDADD = ../libtelnet.la -lssl +ipaccess_telnet_CFLAGS = -DNANO_BTS_CLI_CLIENT telnet_client_SOURCES = telnet-client.c ../libtelnet.h telnet_client_LDADD = ../libtelnet.la diff --git a/util/ipaccess-auth.c b/util/ipaccess-auth.c new file mode 100644 index 0000000..e550f4a --- /dev/null +++ b/util/ipaccess-auth.c @@ -0,0 +1,80 @@ +/* ipaccess nanoBTS proprietary telnet authentication, + * written by Dieter Spaar */ + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#define CLI_USER "CLICLIENT\n" +#define KEY "Sh1n30nY0uCra2yD1am0nd" + +static void compute_response(unsigned char *ubChallenge, unsigned char *ubResponse) +{ + MD5_CTX md5; + int i; + + MD5_Init(&md5); + + for(i = 0; i < 4; i++) { + MD5_Update(&md5, (unsigned char *)KEY, strlen(KEY)); + MD5_Update(&md5, ubChallenge, 16); + } + MD5_Final(ubResponse, &md5); +} + +// nanoBTS Challenge/Response +int ipaccess_telnet_auth(int sock) +{ + char buffer[512]; + int rs; + unsigned char ubResponse[18]; + + // send client name + + if ((rs = send(sock, CLI_USER, strlen(CLI_USER), 0)) == -1) { + fprintf(stderr, "send() failed: %s\n", strerror(errno)); + exit(1); + } else if (rs == 0) { + fprintf(stderr, "send() unexpectedly returned 0\n"); + exit(1); + } + + // receive challenge + + if ((rs = recv(sock, buffer, sizeof(buffer), 0)) > 0) { + if(rs != 18 || buffer[0] != '<' || buffer[17] != '>') { + fprintf(stderr, "unexpected response\n"); + exit(1); + } + } else if (rs == 0) { + fprintf(stderr, "recv(client) unexpectedly returned 0\n"); + exit(1); + } else { + fprintf(stderr, "recv(client) failed: %s\n", + strerror(errno)); + exit(1); + } + + // calculate response + + memset(&ubResponse, 0, sizeof(ubResponse)); + compute_response(buffer + 1, ubResponse + 1); + ubResponse[0] = '<'; + ubResponse[17] = '>'; + + // send response + if ((rs = send(sock, ubResponse, sizeof(ubResponse), 0)) == -1) { + fprintf(stderr, "send() failed: %s\n", strerror(errno)); + exit(1); + } else if (rs == 0) { + fprintf(stderr, "send() unexpectedly returned 0\n"); + exit(1); + } +} diff --git a/util/telnet-client-ipa.c b/util/telnet-client-ipa.c deleted file mode 100644 index 4e22e20..0000000 --- a/util/telnet-client-ipa.c +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Sean Middleditch - * sean@sourcemud.org - * - * The author or authors of this code dedicate any and all copyright interest - * in this code to the public domain. We make this dedication for the benefit - * of the public at large and to the detriment of our heirs and successors. We - * intend this dedication to be an overt act of relinquishment in perpetuity of - * all present and future rights to this code under copyright law. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_ZLIB -#include "zlib.h" -#endif - -#include "libtelnet.h" - -#define NANO_BTS_CLI_CLIENT 1 - -#if NANO_BTS_CLI_CLIENT - #include -#endif - -static struct termios orig_tios; -static telnet_t *telnet; -static int do_echo; - -static const telnet_telopt_t telopts[] = { - { TELNET_TELOPT_ECHO, TELNET_WONT, TELNET_DO }, - { TELNET_TELOPT_TTYPE, TELNET_WILL, TELNET_DONT }, - { TELNET_TELOPT_COMPRESS2, TELNET_WONT, TELNET_DO }, - { TELNET_TELOPT_MSSP, TELNET_WONT, TELNET_DO }, - { -1, 0, 0 } -}; - -static void _cleanup(void) { - tcsetattr(STDOUT_FILENO, TCSADRAIN, &orig_tios); -} - -static void _input(char *buffer, int size) { - static char crlf[] = { '\r', '\n' }; - int i; - - for (i = 0; i != size; ++i) { - /* if we got a CR or LF, replace with CRLF - * NOTE that usually you'd get a CR in UNIX, but in raw - * mode we get LF instead (not sure why) - */ - if (buffer[i] == '\r' || buffer[i] == '\n') { - if (do_echo) - printf("\r\n"); - telnet_send(telnet, crlf, 2); - } else { - if (do_echo) - putchar(buffer[i]); - telnet_send(telnet, buffer + i, 1); - } - } - fflush(stdout); -} - -static void _send(int sock, const char *buffer, size_t size) { - int rs; - - /* send data */ - while (size > 0) { - if ((rs = send(sock, buffer, size, 0)) == -1) { - fprintf(stderr, "send() failed: %s\n", strerror(errno)); - exit(1); - } else if (rs == 0) { - fprintf(stderr, "send() unexpectedly returned 0\n"); - exit(1); - } - - /* update pointer and size to see if we've got more to send */ - buffer += rs; - size -= rs; - } -} - -static void _event_handler(telnet_t *telnet, telnet_event_t *ev, - void *user_data) { - int sock = *(int*)user_data; - - switch (ev->type) { - /* data received */ - case TELNET_EV_DATA: - printf("%.*s", (int)ev->size, ev->buffer); - break; - /* data must be sent */ - case TELNET_EV_SEND: - _send(sock, ev->buffer, ev->size); - break; - /* request to enable remote feature (or receipt) */ - case TELNET_EV_WILL: - /* we'll agree to turn off our echo if server wants us to stop */ - if (ev->telopt == TELNET_TELOPT_ECHO) - do_echo = 0; - break; - /* notification of disabling remote feature (or receipt) */ - case TELNET_EV_WONT: - if (ev->telopt == TELNET_TELOPT_ECHO) - do_echo = 1; - break; - /* request to enable local feature (or receipt) */ - case TELNET_EV_DO: - break; - /* demand to disable local feature (or receipt) */ - case TELNET_EV_DONT: - break; - /* respond to particular subnegotiations */ - case TELNET_EV_SUBNEGOTIATION: - /* if they just asked for our terminal type, response with it */ - /* respond with our terminal type */ - if (ev->telopt == TELNET_TELOPT_TTYPE && - ev->argc >= 1 && ev->argv[0][0] == TELNET_TTYPE_SEND) { - telnet_format_sb(telnet, TELNET_TELOPT_TTYPE, 1, - TELNET_TTYPE_IS, getenv("TERM")); - } - break; - /* error */ - case TELNET_EV_ERROR: - fprintf(stderr, "ERROR: %s\n", ev->buffer); - exit(1); - default: - /* ignore */ - break; - } -} - -#if NANO_BTS_CLI_CLIENT - -#define KEY "Sh1n30nY0uCra2yD1am0nd" - -void compute_response(unsigned char *ubChallenge, unsigned char *ubResponse) -{ - MD5_CTX md5; - int i; - - MD5_Init(&md5); - - for(i = 0; i < 4; i++) - { - MD5_Update(&md5, (unsigned char *)KEY, strlen(KEY)); - MD5_Update(&md5, ubChallenge, 16); - } - - MD5_Final(ubResponse, &md5); -} - -#endif - -int main(int argc, char **argv) { - char buffer[512]; - int rs; - int sock; - struct sockaddr_in addr; - struct pollfd pfd[2]; - struct addrinfo *ai; - struct addrinfo hints; - struct termios tios; - - /* check usage */ - if (argc != 3) { - fprintf(stderr, "Usage:\n ./telnet-client \n"); - return 1; - } - - /* look up server host */ - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - if ((rs = getaddrinfo(argv[1], argv[2], &hints, &ai)) != 0) { - fprintf(stderr, "getaddrinfo() failed for %s: %s\n", argv[1], - gai_strerror(rs)); - return 1; - } - - /* create server socket */ - if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { - fprintf(stderr, "socket() failed: %s\n", strerror(errno)); - return 1; - } - - /* bind server socket */ - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) { - fprintf(stderr, "bind() failed: %s\n", strerror(errno)); - return 1; - } - - /* connect */ - if (connect(sock, ai->ai_addr, ai->ai_addrlen) == -1) { - fprintf(stderr, "server() failed: %s\n", strerror(errno)); - return 1; - } - - /* free address lookup info */ - freeaddrinfo(ai); - -#if NANO_BTS_CLI_CLIENT - - { - // nanoBTS Challenge/Response - - unsigned char ubResponse[18]; - - #define CLI_USER "CLICLIENT\n" - - // send client name - - if ((rs = send(sock, CLI_USER, strlen(CLI_USER), 0)) == -1) { - fprintf(stderr, "send() failed: %s\n", strerror(errno)); - exit(1); - } else if (rs == 0) { - fprintf(stderr, "send() unexpectedly returned 0\n"); - exit(1); - } - - // receive challenge - - if ((rs = recv(sock, buffer, sizeof(buffer), 0)) > 0) { - if(rs != 18 || buffer[0] != '<' || buffer[17] != '>') { - fprintf(stderr, "unexpected response\n"); - exit(1); - } - } else if (rs == 0) { - fprintf(stderr, "recv(client) unexpectedly returned 0\n"); - exit(1); - } else { - fprintf(stderr, "recv(client) failed: %s\n", - strerror(errno)); - exit(1); - } - - // calculate response - - memset(&ubResponse, 0, sizeof(ubResponse)); - compute_response(buffer + 1, ubResponse + 1); - ubResponse[0] = '<'; - ubResponse[17] = '>'; - - // send response - - if ((rs = send(sock, ubResponse, sizeof(ubResponse), 0)) == -1) { - fprintf(stderr, "send() failed: %s\n", strerror(errno)); - exit(1); - } else if (rs == 0) { - fprintf(stderr, "send() unexpectedly returned 0\n"); - exit(1); - } - } - -#endif - - /* get current terminal settings, set raw mode, make sure we - * register atexit handler to restore terminal settings - */ - - tcgetattr(STDOUT_FILENO, &orig_tios); - atexit(_cleanup); - tios = orig_tios; - cfmakeraw(&tios); - tcsetattr(STDOUT_FILENO, TCSADRAIN, &tios); - - /* set input echoing on by default */ - do_echo = 1; - - /* initialize telnet box */ - telnet = telnet_init(telopts, _event_handler, 0, &sock); - - /* initialize poll descriptors */ - memset(pfd, 0, sizeof(pfd)); - pfd[0].fd = STDIN_FILENO; - pfd[0].events = POLLIN; - pfd[1].fd = sock; - pfd[1].events = POLLIN; - /* loop while both connections are open */ - while (poll(pfd, 2, -1) != -1) { - /* read from stdin */ - if (pfd[0].revents & POLLIN) { - if ((rs = read(STDIN_FILENO, buffer, sizeof(buffer))) > 0) { - _input(buffer, rs); - } else if (rs == 0) { - break; - } else { - fprintf(stderr, "recv(server) failed: %s\n", - strerror(errno)); - exit(1); - } - } - - /* read from client */ - if (pfd[1].revents & POLLIN) { - if ((rs = recv(sock, buffer, sizeof(buffer), 0)) > 0) { - telnet_recv(telnet, buffer, rs); - } else if (rs == 0) { - break; - } else { - fprintf(stderr, "recv(client) failed: %s\n", - strerror(errno)); - exit(1); - } - } - } - - /* clean up */ - telnet_free(telnet); - close(sock); - - return 0; -} - diff --git a/util/telnet-client.c b/util/telnet-client.c index 5565656..f2fcedb 100644 --- a/util/telnet-client.c +++ b/util/telnet-client.c @@ -135,6 +135,8 @@ static void _event_handler(telnet_t *telnet, telnet_event_t *ev, } } +extern int ipaccess_telnet_auth(int sock); + int main(int argc, char **argv) { char buffer[512]; int rs; @@ -184,6 +186,10 @@ int main(int argc, char **argv) { /* free address lookup info */ freeaddrinfo(ai); +#if NANO_BTS_CLI_CLIENT + ipaccess_telnet_auth(sock); +#endif + /* get current terminal settings, set raw mode, make sure we * register atexit handler to restore terminal settings */ -- cgit v1.2.3