/* 
#  This is version 0.3 of absent
#
#               Copyright (c) 1999 by AT&T.
#  Permission to use, copy, and modify this software without fee is
#  hereby granted, provided that this entire notice is included in all
#  copies of any software which is or includes a copy or modification
#  of this software and in all copies of the supporting documentation
#  for such software.
#
#  SOME PARTS OF ABSENT MAY BE RESTRICTED UNDER UNITED STATES EXPORT
#  REGULATIONS.
#
#  THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
#  IMPLIED WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE
#  ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
#  MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
#  PURPOSE.
*/
#include "user_table.h"


int otp_register_user(name, phrase, n)
char *name;
char *phrase;
int n;
{
  /* emulate the opiepasswd command.  brute force, no security. */
  char seed[OPIE_SEED_MAX +1];

  if(opienewseed(seed) < 0)
    return -1;
  if(opiepasscheck(phrase) < 0)
    return -2;
  if(opiepasswd(NULL, 1|OPIEPASSWD_FORCE, name, n>0 ? n : 499, seed, phrase))
    return -3;
  return 1;
}


/* Returns the challenge string populated from a call to opiechallenge
   and stores the opie struct in the file named by the user. */

void otp_make_challenge(name,challenge)
char *name;
char *challenge;
{
        struct opie _oc;
        user_entry entry;
        int wrote_bytes;
        int nread;
        int result;

	result = opiechallenge(&_oc, name, challenge);

        if (result != 0) {
            challenge[0] = 0;
            return;
        }

        /* read in the whole entry */
        nread = read_user_entry(name, &entry);

        /* read_user_entry does malloc, but we don't need that stuff */
        if (nread > 0) {
          free(entry.opie_entry.opie_seed);
          free(entry.opie_entry.opie_principal);
          free(entry.opie_entry.opie_val);
        }

        /* overwrite the challenge in the entry */
        bcopy(&_oc, &entry.opie_entry, sizeof(struct opie));
        entry.state = CHALLENGED;
        wrote_bytes = write_user(name, &entry);

}



/* returns 1 if the response is correct, 0 otherwise */

int otp_check_response(name,response)
char *name;
char *response;
{
        int result;
        user_entry entry;
	struct opie _ov;
        int bytes_read;

        bytes_read = read_user_entry(name, &entry);
    
        if (bytes_read == -1) {
           return(-1);
        }        

	bcopy(&entry.opie_entry, &_ov, sizeof(struct opie));
        /* TODO, perhaps check if entry.state is CHALLENGED? */

        result = opieverify(&_ov, response);
        /* Now I need to free up some memory that got allocated
           when reading this in from disk */

        if (bytes_read > 0) {
           free(entry.opie_entry.opie_principal);
           free(entry.opie_entry.opie_seed);
           free(entry.opie_entry.opie_val);
        }


        if (result == 0) {
           entry.state = AUTHENTICATED;
           return(1);
        } else {
           return(0);
        }

}


/*
   This routine takes in a user name, and creates an entry for
   them with a null opie struct, a new key, and a timeout
*/

void otp_login_user(name)
char *name;
{

   C_Block master_key;
   user_entry entry;
   int nread;
   long counter=1;
   int result;

   nread = read_user_entry(name, &entry);
   
   if (nread <= 0) {
      printf("No record of authentication for %s.\n",name);
      return;
   }


   result = read_key(&counter, master_key, MASTER_KEY);

   if (result == -1) {
      printf("Error reading in master key\n");
      return;
   }
       
   /* sets the users MAC key */
   gen_key(counter, master_key, entry.MACKey);
   entry.key_creation_time = time(NULL);
   entry.state = NONE;

   write_user(name, &entry);

   /* Now I need to free up some memory that got allocated
            when reading this in from disk */
 
       if (nread > 0) {
            free(entry.opie_entry.opie_principal);
            free(entry.opie_entry.opie_seed);
            free(entry.opie_entry.opie_val);
       }


}

