/*
** Copyright (c) 1999, 2000, 2001, 2002, 2003
** Adel I. Mirzazhanov. All rights reserved
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
**     1.Redistributions of source code must retain the above copyright notice,
**       this list of conditions and the following disclaimer.
**     2.Redistributions in binary form must reproduce the above copyright
**       notice, this list of conditions and the following disclaimer in the
**       documentation and/or other materials provided with the distribution.
**     3.The name of the author may not be used to endorse or promote products
**       derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR  ``AS IS'' AND ANY EXPRESS
** OR IMPLIED WARRANTIES, INCLUDING,  BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
** ARE DISCLAIMED.  IN  NO  EVENT  SHALL THE AUTHOR BE LIABLE FOR ANY
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
** DAMAGES (INCLUDING, BUT NOT LIMITED TO,  PROCUREMENT OF SUBSTITUTE
** GOODS OR SERVICES;  LOSS OF USE,  DATA,  OR  PROFITS;  OR BUSINESS
** INTERRUPTION)  HOWEVER  CAUSED  AND  ON  ANY  THEORY OF LIABILITY,
** WHETHER  IN  CONTRACT,   STRICT   LIABILITY,  OR  TORT  (INCLUDING
** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/*
** randpass.c - Random password generation module of PWGEN program
*/

#if defined (HAVE_CONFIG_H)
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#if defined (HAVE_PWD_H)
#include <pwd.h>
#endif /* HAVE_PWD_H */
#include <unistd.h>
#include "randpass.h"

#include "owntypes.h"
#include "smbl.h"

/*
** gen_rand_pass - generates random password of specified type
** INPUT:
**   char * - password string.
**   int    - minimum password length.
**   int    - maximum password length.
**   unsigned int - password generation mode.
** OUTPUT:
**   int - password length or -1 on error.
** NOTES:
**   none.
*/
int
gen_rand_pass (char *password_string, int minl, int maxl, unsigned int pass_mode)
{
  int length = 0;
  char *str_pointer;
  int random_weight[94];
  int max_weight = 0;
  int max_weight_element_number = 0;

  if (minl > APG_MAX_PASSWORD_LENGTH || maxl > APG_MAX_PASSWORD_LENGTH ||
      minl < 1 || maxl < 1 || minl > maxl)
      return (-1);
  for (int i = 0; i <= 93; i++) random_weight[i] = 0;
  length = minl + randint(maxl-minl+1);
  str_pointer = password_string;

  for (int i = 0; i < length; i++)
    {
/* Asign random weight in weight array if mode is present*/
      for (int j = 0; j <= 93 ; j++)
         if ( ( (pass_mode & smbl[j].type) > 0) &&
             !( (S_RS & smbl[j].type) > 0))
            random_weight[j] = 1 + randint(20000);

/* Find an element with maximum weight */
      for (int j = 0; j <= 93; j++)
        if (random_weight[j] > max_weight)
          {
            max_weight = random_weight[j];
            max_weight_element_number = j;
          }
/* Get password symbol */
      *str_pointer = smbl[max_weight_element_number].ch;
      str_pointer++;
      max_weight = 0;
      max_weight_element_number = 0;
      for (int j = 0; j <= 93; j++) random_weight[j] = 0;
    }
  *str_pointer = 0;
  return (length);
}

/*
** gen_rand_symbol - generates random password of specified type
** INPUT:
**   char * - symbol.
**   unsigned int - symbol type.
** OUTPUT:
**   int - password length or -1 on error.
** NOTES:
**   none.
*/
int
gen_rand_symbol (char *symbol, unsigned int mode)
{
  char *str_pointer;
  int random_weight[94];
  int max_weight = 0;
  int max_weight_element_number = 0;

  for (int j = 0; j <= 93; j++) random_weight[j] = 0;
  str_pointer = symbol;

/* Asign random weight in weight array if mode is present*/
  for (int j = 0; j <= 93 ; j++)
     if ( ( (mode & smbl[j].type) > 0) &&
         !( (S_RS & smbl[j].type) > 0))
           random_weight[j] = 1 + randint(20000);

/* Find an element with maximum weight */
  for (int j = 0; j <= 93; j++)
     if (random_weight[j] > max_weight)
       {
        max_weight = random_weight[j];
        max_weight_element_number = j;
       }
/* Get password symbol */
  *str_pointer = smbl[max_weight_element_number].ch;

  return (0);
}

/*
** is_restricted_symbol - detcts if symbol is restricted rigt now
** INPUT:
**   char - symbol.
** OUTPUT:
**   int - 0 - not restricted
**         1 - restricted
** NOTES:
**   none.
*/
int
is_restricted_symbol (char symbol)
{
  int j = 0;
  for (j = 0; j <= 93 ; j++)
    if (symbol == smbl[j].ch)
      if ((S_RS & smbl[j].type) > 0)
        return(1);
  return(0);
}
