chatchat stuff from gpk@onramp.net
authorPaul Mackerras <paulus@samba.org>
Wed, 12 May 1999 06:12:08 +0000 (06:12 +0000)
committerPaul Mackerras <paulus@samba.org>
Wed, 12 May 1999 06:12:08 +0000 (06:12 +0000)
scripts/chatchat/README [new file with mode: 0644]
scripts/chatchat/chatchat.c [new file with mode: 0644]

diff --git a/scripts/chatchat/README b/scripts/chatchat/README
new file mode 100644 (file)
index 0000000..88a4c69
--- /dev/null
@@ -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 (file)
index 0000000..4534fb9
--- /dev/null
@@ -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 <filename>
+*
+*   where <filename> 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 <sys/time.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+/* 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);
+}