/* charon.c -- This source is for the program "charon", a client of the
 * charon initialization.  This is a stream buffer that assumes that
 * given no arguments it will get charon input from the server on stdin
 * and output charon protocol on stdout.  The User's password is obtained
 * from /dev/tty.
 *
 * Created by:	Derek Atkins <warlord@MIT.EDU>
 *
 * $Source: /afs/net.mit.edu/user/warlord/Thesis/src/charon/RCS/charon.c,v $
 * $Author: warlord $
 *
 */

#include <warlord-copyright.h>

#if !defined(lint) && !defined(SABER)
static char charon_c[] = "$Id: charon.c,v 1.3 94/03/22 01:04:39 warlord Exp $";
#endif

#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <setjmp.h>
#include <fcntl.h>
#include <sys/types.h>
#include <krb.h>
#include <charon_prot.h>
#include <charon.h>

static void *tty_state = NULL;

/* If we get a signal, we should do this, so that we can exit
 * cleanly.
 */
int
error_exit()
{
  crn_revert_echo(tty_state);
  exit(1);
}

static int
charon_key_proc(char *user, char *instance, char *realm, char *arg, 
	     des_cblock key)
{
    charon_t *charon = (charon_t *)arg;
    char password[BUFSIZ];
    int ok = 0;
    void *tty_state;
    int	fd = -1;
    static jmp_buf env;

    BCLEAR(password);

    fd = open("/dev/tty", O_RDONLY);
    if (fd < 0) {
	    perror("/dev/tty");
	    return -1;
    }

    /* 
     * If the username does not match the aname in the ticket, 
     * we will print that too.  Otherwise, we won't.
     */
    
    fprintf(stderr, "Charon initialization (%s)", charon->hostinst);
    
    fprintf(stderr, "\nPassword for %s%s%s@%s: ", user,
	    (instance[0]) ? "." : "", instance, realm);

    fflush(stderr);

    if (setjmp(env)) {
	ok = -1;
	goto lose;
    }
    
    tty_state = crn_kill_echo(fd);

    if (read(fd, password, sizeof(password)) == -1) {
	perror("read");
	ok = -1;
	goto lose;
    }

    if (password[strlen(password)-1] == '\n')
	password[strlen(password)-1] = 0;

     /* Generate the key from the password and destroy the password */

    des_string_to_key(password, key);

lose:
    BCLEAR(password);

    crn_revert_echo(tty_state);

    close(fd);

    fprintf(stderr, "\n");

    return(ok);
}

main(int argc, char *argv[])
{
    int retval;

    /* Turn off echoing */
    tty_state = crn_kill_echo(0);

    /* trap a lot of signals */
    signal(SIGHUP, error_exit);
    signal(SIGINT, error_exit);
    signal(SIGQUIT, error_exit);
    signal(SIGKILL, error_exit);
    signal(SIGTERM, error_exit);

    /* Initiate the protocol */
    if ((retval = crn_cli_get_tickets(0, charon_key_proc, 0, 0)) != CRN_OK)
	fprintf(stderr, "%s\n", crn_err_msg(retval));

    /* Turn on echoing */
    crn_revert_echo(tty_state);

    return(0);
}
