From 49638dd3efa6c3455f5e621c4281b461d5a0eb74 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 12 May 1999 06:12:08 +0000 Subject: [PATCH 1/1] chatchat stuff from gpk@onramp.net --- scripts/chatchat/README | 134 ++++++++++++ scripts/chatchat/chatchat.c | 409 ++++++++++++++++++++++++++++++++++++ 2 files changed, 543 insertions(+) create mode 100644 scripts/chatchat/README create mode 100644 scripts/chatchat/chatchat.c diff --git a/scripts/chatchat/README b/scripts/chatchat/README new file mode 100644 index 0000000..88a4c69 --- /dev/null +++ b/scripts/chatchat/README @@ -0,0 +1,134 @@ +v 0.1 gpk@onramp.net 3/27/99 + +I Intro + + This document covers the use of the modified "chat" program and its +adjunct "chatchat" to login using the Security Dynamics SecurID card +on a linux system. + + This set of files comprises a modified version of the chat program +(the one distributed with ppp-2.3.5) and a new program called chatchat +that allows you to supply data from the keyboard to the chat program. + + The SecurID card generates passwords that have a lifetime of one +minute and are used as a first layer in dial up security. The only +software I know of for this card is for windows, so I wrote my own. +This software allows you to type in the time-sensitive password right +when your chat script is asked to supply the passcode by the remote +system. + + +II How It Works + + This version of chat his an additional command that can be put into +its options that says "Don't reply with this string. Open this pipe, +read the contents, and reply with that instead." Chatchat creates a +pipe and lets you type your passcode into it, then chat picks that up +and sends it out just as though the passcode was hardcoded into the +options. + + +III Installation + + I've provided intel binaries and source code the the modified chat +program and the chatchat program. I'll recommend that you copy the +chat.c program into your ppp-2.3.5/chat directory (save your original +chat.c program first!) and re-make it using the Makefile that comes +with chat. Copy the new chat somewhere into your path. (On my system +chat lives in /usr/sbin/chat, so I've copied the modified one into +/usr/sbin/chat.new and changed my dial in script to call chat.new +instead of chat. + + Second, compile chatchat.c and install it somewhere in your path: + + gcc -g -o chatchat chatchat.c + cp chatchat /usr/sbin + + Third, modify your chat script to use the chatchat program. Mine +looks something like this: + + + -------------------- + +#!/bin/sh +# +# This is part 2 of the ppp-on script. It will perform the connection +# protocol for the desired connection. +# use atm0 to turn down the speaker volume on my sportster x2 voice modem +# gpk 11/2/97 + +exec /usr/sbin/chat.new -V -v \ + ABORT "BUSY" \ + ABORT "NO DIAL TONE" \ + ABORT "NO ANSWER" \ + TIMEOUT 50 \ + "" "atm0" \ + OK ATDT$TELEPHONE \ + CONNECT '' \ + name: \\da0xxxxxx \ + word: @/var/tmp/p \ + compress. '' + + + ----------------------- + + This is a standard chat script: + +* abort if the modem is busy, you don't get a dial tone, no one + answers, or 50 seconds elapses. + +* use atm0 to mute the modem + +* dial the modem, when it connects, wait to be asked for account name + +* when we see "name:" prompt, delay briefly then respond with your + account name (fill in your account name) + +Now we get to the new stuff: + +* when we see "word:" in the password prompt, instead of responding + with "@/var/tmp/p", the modified chat program will open the pipe + /var/tmp/p, read the passcode out of there, and send it + +* when we see "compress." (the last word before ppp starts), reply + with nothing. The script ends and we start ppp. + +Note: + +* Make sure there is some whitespace between the filename and the \. + + +IV Usage + + To use this install the modified chat and chatchat programs, and +modify your chat script similar to the above. Before you dial in, +start that chatchat program giving it the same pipe as in your config +file. In the above case: + +chatchat /var/tmp/p + + Wait until you have one or two tick marks left on your card's +current number, then start your dial up process that eventually calls +chat. When chat goes to open and read the pipe, chatchat will prompt: + + +type PIN into SecurID card and + enter resulting passcode: + + At that point, type your PIN number into your Securid card, press +the diamond, and type the resulting numbers in as your passcode. If +you've left the -V -v options on your chat command you'll see +everything so out, otherwise it works silently. + + If you type the number wrong or run out of time, the server will +respond with an authentication failure. In that case you will have to +hang up and start again. I don't know how to build a conditional script +that says either expect "compress" next, but if you see "name:" again, +do this instead. + + +V Additional Information + + You can obtain additional information about chat and ppp from the +man pages for chat and pppd, as well as the PPP-HOWTO. + diff --git a/scripts/chatchat/chatchat.c b/scripts/chatchat/chatchat.c new file mode 100644 index 0000000..4534fb9 --- /dev/null +++ b/scripts/chatchat/chatchat.c @@ -0,0 +1,409 @@ +/* ************************************************************************* +* NAME: chatchat.c +* +* DESCRIPTION: +* +* This program creates a pipe for the chat process to read. The user +* can supply information (like a password) that will be picked up +* by chat and sent just like the regular contents of a chat script. +* +* Usage is: +* +* chatchat +* +* where matches the option given in the chat script. +* +* for instance the chat script fragment: +* +* ... +* name: \\dmyname \ +* word: @/var/tmp/p \ +* ... +* ^ +* (note: leave some whitespace after the filename) +* +* expect "name:", reply with a delay followed by "myname" +* expect "word:", reply with the data read from the pipe /var/tmp/p +* +* the matching usage of chatchat would be: +* +* chatchat /var/tmp/p +* +* eg: +* +* $chatchat /var/tmp/p +* ... +* some other process eventually starts: +* chat ... +* chat parses the "@/var/tmp/p" option and opens +* /var/tmp/p +* (chatchat prompts:) +* +* type PIN into SecurID card +* enter resulting passcode: [user inputs something] +* +* chat reads /var/tmp/p & gets what the +* user typed at chatchat's "enter string" prompt +* chat removes the pipe file +* chat sends the user's input as a response in +* place of "@/var/tmp/p" +* +* PROCESS: +* +* gcc -g -o chatchat chatchat.c +* +* +* GLOBALS: none +* +* REFERENCES: +* +* see the man pages and documentation that come with the 'chat' program +* (part of the ppp package). you will need to use the modified chat +* program that accepts the '@' operator. +* +* LIMITATIONS: +* +* REVISION HISTORY: +* +* STR Description Author +* +* 23-Mar-99 initial coding gpk +* 12-May-99 unlink the pipe after closing paulus +* +* TARGET: ANSI C +* This program is in the public domain. +* +* +* ************************************************************************* */ + + + + +#include +#include +#include +#include +#include +#include +#include + +/* MAXINPUT - the data typed into chatchat must be fewer */ +/* characters than this. */ + +#define MAXINPUT 80 + + + + + + +/* ************************************************************************* + + + NAME: main + + + USAGE: + + int argc; + char * argv[]; + + main(argc, argv[]); + + returns: int + + DESCRIPTION: + if the pipe file name is given on the command line, + create the pipe, prompt the user and put whatever + is typed into the pipe. + + returns -1 on error + else # characters entered + REFERENCES: + + LIMITATIONS: + + GLOBAL VARIABLES: + + accessed: none + + modified: none + + FUNCTIONS CALLED: + + REVISION HISTORY: + + STR Description of Revision Author + + 25-Mar-99 initial coding gpk + + ************************************************************************* */ + +int main(int argc, char * argv[]) +{ + int retval; + + int create_and_write_pipe(char * pipename); + + if (argc != 2) + { + fprintf(stderr, "usage: %s pipename\n", argv[0]); + retval = -1; + } + else + { + retval = create_and_write_pipe(argv[1]); + } + return (retval); +} + + + + +/* ************************************************************************* + + + NAME: create_and_write_pipe + + + USAGE: + + int some_int; + char * pipename; + + some_int = create_and_write_pipe(pipename); + + returns: int + + DESCRIPTION: + given the pipename, create the pipe, open it, + prompt the user for a string to put into the + pipe, write the string, and close the pipe + + on error, print out an error message and return -1 + + returns -1 on error + else #bytes written into the pipe + REFERENCES: + + LIMITATIONS: + + GLOBAL VARIABLES: + + accessed: none + + modified: none + + FUNCTIONS CALLED: + + REVISION HISTORY: + + STR Description of Revision Author + + 25-Mar-99 initial coding gpk + 12-May-99 remove pipe after closing paulus + + ************************************************************************* */ + +int create_and_write_pipe(char * pipename) +{ + int retval, created, pipefd, nread, nwritten; + char input[MAXINPUT]; + char errstring[180]; + + int create_pipe(char * pipename); + int write_to_pipe(int pipefd, char * input, int nchar); + + created = create_pipe(pipename); + + if (-1 == created) + { + sprintf(errstring, "unable to create pipe '%s'", pipename); + perror(errstring); + retval = -1; + } + else + { + + /* note: this open won't succeed until chat has the pipe */ + /* open and ready to read. this makes for nice timing. */ + + pipefd = open(pipename, O_WRONLY); + + if (-1 == pipefd) + { + sprintf(errstring, "unable to open pipe '%s'", pipename); + perror(errstring); + retval = -1; + } + else + { + fprintf(stderr, "%s \n %s", + "type PIN into SecurID card and", + "enter resulting passcode:"); + nread = read(STDIN_FILENO, (void *)input, MAXINPUT); + + + if (0 >= nread) + { + perror("unable to read from stdin"); + retval = -1; + } + else + { + /* munch off the newline character, chat supplies */ + /* a return when it sends the string out. */ + input[nread -1] = 0; + nread--; + nwritten = write_to_pipe(pipefd, input, nread); + /* printf("wrote [%d]: '%s'\n", nwritten, input); */ + retval = nwritten; + } + close(pipefd); + + /* Now make the pipe go away. It won't actually go away + completely until chat closes it. */ + if (unlink(pipename) < 0) + perror("Warning: couldn't remove pipe"); + } + } + return(retval); +} + + + + + + + +/* ************************************************************************* + + + NAME: create_pipe + + + USAGE: + + int some_int; + char * pipename; + + some_int = create_pipe(pipename); + + returns: int + + DESCRIPTION: + create a pipe of the given name + + if there is an error (like the pipe already exists) + print an error message and return + + return -1 on failure else success + + REFERENCES: + + LIMITATIONS: + + GLOBAL VARIABLES: + + accessed: none + + modified: none + + FUNCTIONS CALLED: + + REVISION HISTORY: + + STR Description of Revision Author + + 25-Mar-99 initial coding gpk + + ************************************************************************* */ + +int create_pipe(char * pipename) +{ + mode_t old_umask; + int created; + + /* hijack the umask temporarily to get the mode I want */ + /* on the pipe. */ + + old_umask = umask(000); + + created = mknod(pipename, S_IFIFO | S_IRWXU | S_IWGRP | S_IWOTH, + (dev_t)NULL); + + /* now restore umask. */ + + (void)umask(old_umask); + + if (-1 == created) + { + perror("unable to create pipe"); + } + + return(created); +} + + + + + + +/* ************************************************************************* + + + NAME: write_to_pipe + + + USAGE: + + int some_int; + int pipefd; + char * input; + int nchar; + + some_int = write_to_pipe(pipefd, input, nchar); + + returns: int + + DESCRIPTION: + write nchars of data from input to pipefd + + on error print a message to stderr + + return -1 on error, else # bytes written + REFERENCES: + + LIMITATIONS: + + GLOBAL VARIABLES: + + accessed: none + + modified: none + + FUNCTIONS CALLED: + + REVISION HISTORY: + + STR Description of Revision Author + + 25-Mar-99 initial coding gpk + 12-May-99 don't write count word first paulus + + ************************************************************************* */ + +int write_to_pipe(int pipefd, char * input, int nchar) +{ + int nwritten; + + /* nwritten = write(pipefd, (void *)&nchar, sizeof(nchar)); */ + nwritten = write(pipefd, (void *)input, nchar); + + if (-1 == nwritten) + { + perror("unable to write to pipe"); + } + + return(nwritten); +} -- 2.39.2