text: /*
   * This program is copyright Alec Muffett 1993. The author disclaims all
   * responsibility or liability with respect to it's usage or its effect
   * upon hardware or computer systems, and maintains copyright as set out
   * in the "LICENCE" document which accompanies distributions of Crack v4.0
   * and upwards.
   */
  /*
   * Modifications made by Clyde Hoover
   *	Academic Computing & Instructional Technologies Services
   *	University of Texas at Austin
   *
   * Title to copyright to original version of this software shall at all times
   * remain with Alec Muffett.
   *
   * Title to copyright to U. T. Austin modificiations to this software and 
   * its associated documentation shall at all times remain with U. T. Austin.
   *
   * U. T. Austin hereby grants USER permission to use, copy, modify, and
   * distribute this software and its documentation for any purpose and
   * without fee, provided that:
   *
   * 1. the above copyright notice appears in all copies of the software
   *    and its documentation, or portions thereof, and 
   * 2. a full copy of this notice is included with the software and its
   *    documentation, or portions thereof, and 
   * 3. neither the software nor its documentation, nor portions thereof,
   *    is sold for profit. Any commercial sale or license of this software,
   *    copies of the software, its associated documentation and/or
   *    modifications of either is strictly prohibited without the prior
   *    consent of U. T. Austin. 
   * 
   * No right is granted to use in advertising, publicity
   * or otherwise any trademark, service mark, or the name of U. T. Austin.
   * 
   * This software and any associated documentation are provided "as is,"
   * and U. T. AUSTIN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESSED OR
   * IMPLIED, INCLUDING THOSE OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR
   * PURPOSE, OR THAT USE OF THE SOFTWARE, MODIFICATIONS, OR ASSOCIATED
   * DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS OR
   * OTHER INTELLECTUAL PROPERTY RIGHTS OF A THIRD PARTY. U. T. Austin, The
   * University of Texas System, its Regents, officers, and employees shall
   * not be liable under any circumstances for any direct, indirect, special,
   * incidental, or consequential damages with respect to any claim by USER
   * or any third party on account of or arising from the use, or inability
   * to use, this software or its associated documentation, even if U. T.
   * Austin has been advised of the possibility of those damages.
   * 
   * Submit commercialization requests to: Office of the Executive Vice
   * President and Provost, U. T. Austin, 201 Main Bldg., Austin, Texas,
   * 78712, ATTN: Technology Licensing Specialist.
   */
  
  #ifndef	lint
  static char ut_id[] = "@(#)fascist.c	2.14 10/21/03 (cc.utexas.edu)";
  static char vers_id[] = "fascist.c : v2.3p3 Alec Muffett 14 dec 1997";
  #endif
  
  #include <sys/types.h>
  #include <pwd.h>
  #include "packer.h"
  
  #define ISSKIP(x) (isspace(x) || ispunct(x))
  
  #define MINDIFF 5		/* How many different chars required */
  #define MINLEN 6		/* Minimum password length */
  #define MAXSTEP 4		/* How far apart replicated chars must be */
  
  /*
   * Look in rules.c to find out how these rules work
   */
  static char *r_destructors[] = {
      ":",                        /* noop - must do this to test raw word. */
  
  #ifdef CRACKLIB_DEBUG2
      (char *) 0,
  #endif
  /*
   * Disable these deconstructors if you think too many passwords are
   * being rejected.
   */
  #define	CRACKLIB_ANAL
  #ifdef	CRACKLIB_ANAL
      "[",                        /* trimming leading/trailing junk */
      "]",
      "[[",
      "]]",
      "[[[",
      "]]]",
  #endif
  
      "/?p@?p",                   /* purging out punctuation/symbols/junk */
      "/?s@?s",
      "/?X@?X",
  
      /* attempt reverse engineering of password strings */
      /* These rules are taken from Crack */
  
      "/$s$s",
      "/$s$s/0s0o",
      "/$s$s/0s0o/2s2a",
      "/$s$s/0s0o/2s2a/3s3e",
      "/$s$s/0s0o/2s2a/3s3e/5s5s",
      "/$s$s/0s0o/2s2a/3s3e/5s5s/1s1i",
      "/$s$s/0s0o/2s2a/3s3e/5s5s/1s1l",
      "/$s$s/0s0o/2s2a/3s3e/5s5s/1s1i/4s4a",
      "/$s$s/0s0o/2s2a/3s3e/5s5s/1s1i/4s4h",
      "/$s$s/0s0o/2s2a/3s3e/5s5s/1s1l/4s4a",
      "/$s$s/0s0o/2s2a/3s3e/5s5s/1s1l/4s4h",
      "/$s$s/0s0o/2s2a/3s3e/5s5s/4s4a",
      "/$s$s/0s0o/2s2a/3s3e/5s5s/4s4h",
      "/$s$s/0s0o/2s2a/3s3e/5s5s/4s4a",
      "/$s$s/0s0o/2s2a/3s3e/5s5s/4s4h",
      "/$s$s/0s0o/2s2a/3s3e/1s1i",
      "/$s$s/0s0o/2s2a/3s3e/1s1l",
      "/$s$s/0s0o/2s2a/3s3e/1s1i/4s4a",
      "/$s$s/0s0o/2s2a/3s3e/1s1i/4s4h",
      "/$s$s/0s0o/2s2a/3s3e/1s1l/4s4a",
      "/$s$s/0s0o/2s2a/3s3e/1s1l/4s4h",
      "/$s$s/0s0o/2s2a/3s3e/4s4a",
      "/$s$s/0s0o/2s2a/3s3e/4s4h",
      "/$s$s/0s0o/2s2a/3s3e/4s4a",
      "/$s$s/0s0o/2s2a/3s3e/4s4h",
      "/$s$s/0s0o/2s2a/5s5s",
      "/$s$s/0s0o/2s2a/5s5s/1s1i",
      "/$s$s/0s0o/2s2a/5s5s/1s1l",
      "/$s$s/0s0o/2s2a/5s5s/1s1i/4s4a",
      "/$s$s/0s0o/2s2a/5s5s/1s1i/4s4h",
      "/$s$s/0s0o/2s2a/5s5s/1s1l/4s4a",
      "/$s$s/0s0o/2s2a/5s5s/1s1l/4s4h",
      "/$s$s/0s0o/2s2a/5s5s/4s4a",
      "/$s$s/0s0o/2s2a/5s5s/4s4h",
      "/$s$s/0s0o/2s2a/5s5s/4s4a",
      "/$s$s/0s0o/2s2a/5s5s/4s4h",
      "/$s$s/0s0o/2s2a/1s1i",
      "/$s$s/0s0o/2s2a/1s1l",
      "/$s$s/0s0o/2s2a/1s1i/4s4a",
      "/$s$s/0s0o/2s2a/1s1i/4s4h",
      "/$s$s/0s0o/2s2a/1s1l/4s4a",
      "/$s$s/0s0o/2s2a/1s1l/4s4h",
      "/$s$s/0s0o/2s2a/4s4a",
      "/$s$s/0s0o/2s2a/4s4h",
      "/$s$s/0s0o/2s2a/4s4a",
      "/$s$s/0s0o/2s2a/4s4h",
      "/$s$s/0s0o/3s3e",
      "/$s$s/0s0o/3s3e/5s5s",
      "/$s$s/0s0o/3s3e/5s5s/1s1i",
      "/$s$s/0s0o/3s3e/5s5s/1s1l",
      "/$s$s/0s0o/3s3e/5s5s/1s1i/4s4a",
      "/$s$s/0s0o/3s3e/5s5s/1s1i/4s4h",
      "/$s$s/0s0o/3s3e/5s5s/1s1l/4s4a",
      "/$s$s/0s0o/3s3e/5s5s/1s1l/4s4h",
      "/$s$s/0s0o/3s3e/5s5s/4s4a",
      "/$s$s/0s0o/3s3e/5s5s/4s4h",
      "/$s$s/0s0o/3s3e/5s5s/4s4a",
      "/$s$s/0s0o/3s3e/5s5s/4s4h",
      "/$s$s/0s0o/3s3e/1s1i",
      "/$s$s/0s0o/3s3e/1s1l",
      "/$s$s/0s0o/3s3e/1s1i/4s4a",
      "/$s$s/0s0o/3s3e/1s1i/4s4h",
      "/$s$s/0s0o/3s3e/1s1l/4s4a",
      "/$s$s/0s0o/3s3e/1s1l/4s4h",
      "/$s$s/0s0o/3s3e/4s4a",
      "/$s$s/0s0o/3s3e/4s4h",
      "/$s$s/0s0o/3s3e/4s4a",
      "/$s$s/0s0o/3s3e/4s4h",
      "/$s$s/0s0o/5s5s",
      "/$s$s/0s0o/5s5s/1s1i",
      "/$s$s/0s0o/5s5s/1s1l",
      "/$s$s/0s0o/5s5s/1s1i/4s4a",
      "/$s$s/0s0o/5s5s/1s1i/4s4h",
      "/$s$s/0s0o/5s5s/1s1l/4s4a",
      "/$s$s/0s0o/5s5s/1s1l/4s4h",
      "/$s$s/0s0o/5s5s/4s4a",
      "/$s$s/0s0o/5s5s/4s4h",
      "/$s$s/0s0o/5s5s/4s4a",
      "/$s$s/0s0o/5s5s/4s4h",
      "/$s$s/0s0o/1s1i",
      "/$s$s/0s0o/1s1l",
      "/$s$s/0s0o/1s1i/4s4a",
      "/$s$s/0s0o/1s1i/4s4h",
      "/$s$s/0s0o/1s1l/4s4a",
      "/$s$s/0s0o/1s1l/4s4h",
      "/$s$s/0s0o/4s4a",
      "/$s$s/0s0o/4s4h",
      "/$s$s/0s0o/4s4a",
      "/$s$s/0s0o/4s4h",
      "/$s$s/2s2a",
      "/$s$s/2s2a/3s3e",
      "/$s$s/2s2a/3s3e/5s5s",
      "/$s$s/2s2a/3s3e/5s5s/1s1i",
      "/$s$s/2s2a/3s3e/5s5s/1s1l",
      "/$s$s/2s2a/3s3e/5s5s/1s1i/4s4a",
      "/$s$s/2s2a/3s3e/5s5s/1s1i/4s4h",
      "/$s$s/2s2a/3s3e/5s5s/1s1l/4s4a",
      "/$s$s/2s2a/3s3e/5s5s/1s1l/4s4h",
      "/$s$s/2s2a/3s3e/5s5s/4s4a",
      "/$s$s/2s2a/3s3e/5s5s/4s4h",
      "/$s$s/2s2a/3s3e/5s5s/4s4a",
      "/$s$s/2s2a/3s3e/5s5s/4s4h",
      "/$s$s/2s2a/3s3e/1s1i",
      "/$s$s/2s2a/3s3e/1s1l",
      "/$s$s/2s2a/3s3e/1s1i/4s4a",
      "/$s$s/2s2a/3s3e/1s1i/4s4h",
      "/$s$s/2s2a/3s3e/1s1l/4s4a",
      "/$s$s/2s2a/3s3e/1s1l/4s4h",
      "/$s$s/2s2a/3s3e/4s4a",
      "/$s$s/2s2a/3s3e/4s4h",
      "/$s$s/2s2a/3s3e/4s4a",
      "/$s$s/2s2a/3s3e/4s4h",
      "/$s$s/2s2a/5s5s",
      "/$s$s/2s2a/5s5s/1s1i",
      "/$s$s/2s2a/5s5s/1s1l",
      "/$s$s/2s2a/5s5s/1s1i/4s4a",
      "/$s$s/2s2a/5s5s/1s1i/4s4h",
      "/$s$s/2s2a/5s5s/1s1l/4s4a",
      "/$s$s/2s2a/5s5s/1s1l/4s4h",
      "/$s$s/2s2a/5s5s/4s4a",
      "/$s$s/2s2a/5s5s/4s4h",
      "/$s$s/2s2a/5s5s/4s4a",
      "/$s$s/2s2a/5s5s/4s4h",
      "/$s$s/2s2a/1s1i",
      "/$s$s/2s2a/1s1l",
      "/$s$s/2s2a/1s1i/4s4a",
      "/$s$s/2s2a/1s1i/4s4h",
      "/$s$s/2s2a/1s1l/4s4a",
      "/$s$s/2s2a/1s1l/4s4h",
      "/$s$s/2s2a/4s4a",
      "/$s$s/2s2a/4s4h",
      "/$s$s/2s2a/4s4a",
      "/$s$s/2s2a/4s4h",
      "/$s$s/3s3e",
      "/$s$s/3s3e/5s5s",
      "/$s$s/3s3e/5s5s/1s1i",
      "/$s$s/3s3e/5s5s/1s1l",
      "/$s$s/3s3e/5s5s/1s1i/4s4a",
      "/$s$s/3s3e/5s5s/1s1i/4s4h",
      "/$s$s/3s3e/5s5s/1s1l/4s4a",
      "/$s$s/3s3e/5s5s/1s1l/4s4h",
      "/$s$s/3s3e/5s5s/4s4a",
      "/$s$s/3s3e/5s5s/4s4h",
      "/$s$s/3s3e/5s5s/4s4a",
      "/$s$s/3s3e/5s5s/4s4h",
      "/$s$s/3s3e/1s1i",
      "/$s$s/3s3e/1s1l",
      "/$s$s/3s3e/1s1i/4s4a",
      "/$s$s/3s3e/1s1i/4s4h",
      "/$s$s/3s3e/1s1l/4s4a",
      "/$s$s/3s3e/1s1l/4s4h",
      "/$s$s/3s3e/4s4a",
      "/$s$s/3s3e/4s4h",
      "/$s$s/3s3e/4s4a",
      "/$s$s/3s3e/4s4h",
      "/$s$s/5s5s",
      "/$s$s/5s5s/1s1i",
      "/$s$s/5s5s/1s1l",
      "/$s$s/5s5s/1s1i/4s4a",
      "/$s$s/5s5s/1s1i/4s4h",
      "/$s$s/5s5s/1s1l/4s4a",
      "/$s$s/5s5s/1s1l/4s4h",
      "/$s$s/5s5s/4s4a",
      "/$s$s/5s5s/4s4h",
      "/$s$s/5s5s/4s4a",
      "/$s$s/5s5s/4s4h",
      "/$s$s/1s1i",
      "/$s$s/1s1l",
      "/$s$s/1s1i/4s4a",
      "/$s$s/1s1i/4s4h",
      "/$s$s/1s1l/4s4a",
      "/$s$s/1s1l/4s4h",
      "/$s$s/4s4a",
      "/$s$s/4s4h",
      "/$s$s/4s4a",
      "/$s$s/4s4h",
      "/0s0o",
      "/0s0o/2s2a",
      "/0s0o/2s2a/3s3e",
      "/0s0o/2s2a/3s3e/5s5s",
      "/0s0o/2s2a/3s3e/5s5s/1s1i",
      "/0s0o/2s2a/3s3e/5s5s/1s1l",
      "/0s0o/2s2a/3s3e/5s5s/1s1i/4s4a",
      "/0s0o/2s2a/3s3e/5s5s/1s1i/4s4h",
      "/0s0o/2s2a/3s3e/5s5s/1s1l/4s4a",
      "/0s0o/2s2a/3s3e/5s5s/1s1l/4s4h",
      "/0s0o/2s2a/3s3e/5s5s/4s4a",
      "/0s0o/2s2a/3s3e/5s5s/4s4h",
      "/0s0o/2s2a/3s3e/5s5s/4s4a",
      "/0s0o/2s2a/3s3e/5s5s/4s4h",
      "/0s0o/2s2a/3s3e/1s1i",
      "/0s0o/2s2a/3s3e/1s1l",
      "/0s0o/2s2a/3s3e/1s1i/4s4a",
      "/0s0o/2s2a/3s3e/1s1i/4s4h",
      "/0s0o/2s2a/3s3e/1s1l/4s4a",
      "/0s0o/2s2a/3s3e/1s1l/4s4h",
      "/0s0o/2s2a/3s3e/4s4a",
      "/0s0o/2s2a/3s3e/4s4h",
      "/0s0o/2s2a/3s3e/4s4a",
      "/0s0o/2s2a/3s3e/4s4h",
      "/0s0o/2s2a/5s5s",
      "/0s0o/2s2a/5s5s/1s1i",
      "/0s0o/2s2a/5s5s/1s1l",
      "/0s0o/2s2a/5s5s/1s1i/4s4a",
      "/0s0o/2s2a/5s5s/1s1i/4s4h",
      "/0s0o/2s2a/5s5s/1s1l/4s4a",
      "/0s0o/2s2a/5s5s/1s1l/4s4h",
      "/0s0o/2s2a/5s5s/4s4a",
      "/0s0o/2s2a/5s5s/4s4h",
      "/0s0o/2s2a/5s5s/4s4a",
      "/0s0o/2s2a/5s5s/4s4h",
      "/0s0o/2s2a/1s1i",
      "/0s0o/2s2a/1s1l",
      "/0s0o/2s2a/1s1i/4s4a",
      "/0s0o/2s2a/1s1i/4s4h",
      "/0s0o/2s2a/1s1l/4s4a",
      "/0s0o/2s2a/1s1l/4s4h",
      "/0s0o/2s2a/4s4a",
      "/0s0o/2s2a/4s4h",
      "/0s0o/2s2a/4s4a",
      "/0s0o/2s2a/4s4h",
      "/0s0o/3s3e",
      "/0s0o/3s3e/5s5s",
      "/0s0o/3s3e/5s5s/1s1i",
      "/0s0o/3s3e/5s5s/1s1l",
      "/0s0o/3s3e/5s5s/1s1i/4s4a",
      "/0s0o/3s3e/5s5s/1s1i/4s4h",
      "/0s0o/3s3e/5s5s/1s1l/4s4a",
      "/0s0o/3s3e/5s5s/1s1l/4s4h",
      "/0s0o/3s3e/5s5s/4s4a",
      "/0s0o/3s3e/5s5s/4s4h",
      "/0s0o/3s3e/5s5s/4s4a",
      "/0s0o/3s3e/5s5s/4s4h",
      "/0s0o/3s3e/1s1i",
      "/0s0o/3s3e/1s1l",
      "/0s0o/3s3e/1s1i/4s4a",
      "/0s0o/3s3e/1s1i/4s4h",
      "/0s0o/3s3e/1s1l/4s4a",
      "/0s0o/3s3e/1s1l/4s4h",
      "/0s0o/3s3e/4s4a",
      "/0s0o/3s3e/4s4h",
      "/0s0o/3s3e/4s4a",
      "/0s0o/3s3e/4s4h",
      "/0s0o/5s5s",
      "/0s0o/5s5s/1s1i",
      "/0s0o/5s5s/1s1l",
      "/0s0o/5s5s/1s1i/4s4a",
      "/0s0o/5s5s/1s1i/4s4h",
      "/0s0o/5s5s/1s1l/4s4a",
      "/0s0o/5s5s/1s1l/4s4h",
      "/0s0o/5s5s/4s4a",
      "/0s0o/5s5s/4s4h",
      "/0s0o/5s5s/4s4a",
      "/0s0o/5s5s/4s4h",
      "/0s0o/1s1i",
      "/0s0o/1s1l",
      "/0s0o/1s1i/4s4a",
      "/0s0o/1s1i/4s4h",
      "/0s0o/1s1l/4s4a",
      "/0s0o/1s1l/4s4h",
      "/0s0o/4s4a",
      "/0s0o/4s4h",
      "/0s0o/4s4a",
      "/0s0o/4s4h",
      "/2s2a",
      "/2s2a/3s3e",
      "/2s2a/3s3e/5s5s",
      "/2s2a/3s3e/5s5s/1s1i",
      "/2s2a/3s3e/5s5s/1s1l",
      "/2s2a/3s3e/5s5s/1s1i/4s4a",
      "/2s2a/3s3e/5s5s/1s1i/4s4h",
      "/2s2a/3s3e/5s5s/1s1l/4s4a",
      "/2s2a/3s3e/5s5s/1s1l/4s4h",
      "/2s2a/3s3e/5s5s/4s4a",
      "/2s2a/3s3e/5s5s/4s4h",
      "/2s2a/3s3e/5s5s/4s4a",
      "/2s2a/3s3e/5s5s/4s4h",
      "/2s2a/3s3e/1s1i",
      "/2s2a/3s3e/1s1l",
      "/2s2a/3s3e/1s1i/4s4a",
      "/2s2a/3s3e/1s1i/4s4h",
      "/2s2a/3s3e/1s1l/4s4a",
      "/2s2a/3s3e/1s1l/4s4h",
      "/2s2a/3s3e/4s4a",
      "/2s2a/3s3e/4s4h",
      "/2s2a/3s3e/4s4a",
      "/2s2a/3s3e/4s4h",
      "/2s2a/5s5s",
      "/2s2a/5s5s/1s1i",
      "/2s2a/5s5s/1s1l",
      "/2s2a/5s5s/1s1i/4s4a",
      "/2s2a/5s5s/1s1i/4s4h",
      "/2s2a/5s5s/1s1l/4s4a",
      "/2s2a/5s5s/1s1l/4s4h",
      "/2s2a/5s5s/4s4a",
      "/2s2a/5s5s/4s4h",
      "/2s2a/5s5s/4s4a",
      "/2s2a/5s5s/4s4h",
      "/2s2a/1s1i",
      "/2s2a/1s1l",
      "/2s2a/1s1i/4s4a",
      "/2s2a/1s1i/4s4h",
      "/2s2a/1s1l/4s4a",
      "/2s2a/1s1l/4s4h",
      "/2s2a/4s4a",
      "/2s2a/4s4h",
      "/2s2a/4s4a",
      "/2s2a/4s4h",
      "/3s3e",
      "/3s3e/5s5s",
      "/3s3e/5s5s/1s1i",
      "/3s3e/5s5s/1s1l",
      "/3s3e/5s5s/1s1i/4s4a",
      "/3s3e/5s5s/1s1i/4s4h",
      "/3s3e/5s5s/1s1l/4s4a",
      "/3s3e/5s5s/1s1l/4s4h",
      "/3s3e/5s5s/4s4a",
      "/3s3e/5s5s/4s4h",
      "/3s3e/5s5s/4s4a",
      "/3s3e/5s5s/4s4h",
      "/3s3e/1s1i",
      "/3s3e/1s1l",
      "/3s3e/1s1i/4s4a",
      "/3s3e/1s1i/4s4h",
      "/3s3e/1s1l/4s4a",
      "/3s3e/1s1l/4s4h",
      "/3s3e/4s4a",
      "/3s3e/4s4h",
      "/3s3e/4s4a",
      "/3s3e/4s4h",
      "/5s5s",
      "/5s5s/1s1i",
      "/5s5s/1s1l",
      "/5s5s/1s1i/4s4a",
      "/5s5s/1s1i/4s4h",
      "/5s5s/1s1l/4s4a",
      "/5s5s/1s1l/4s4h",
      "/5s5s/4s4a",
      "/5s5s/4s4h",
      "/5s5s/4s4a",
      "/5s5s/4s4h",
      "/1s1i",
      "/1s1l",
      "/1s1i/4s4a",
      "/1s1i/4s4h",
      "/1s1l/4s4a",
      "/1s1l/4s4h",
      "/4s4a",
      "/4s4h",
      "/4s4a",
      "/4s4h",
  
      /* done */
      (char *) 0
  };
  
  static char *r_constructors[] = {
      ":",
  #ifdef CRACKLIB_DEBUG2
      (char *) 0,
  #endif
      "r",
      "d",
      "f",
      "dr",
      "fr",
      "rf",
      "c",
      "rc",
      (char *) 0
  };
  
  /*
   * GTry - check if <password> is a permutation of <rawtext>
   */
  int
  GTry(rawtext, password)
      char *rawtext;
      char *password;
  {
      int i;
      int len;
      char *mp;
  
      /* use destructors to turn password into rawtext */
      /* note use of Reverse() to save duplicating all rules */
  
      len = strlen(password);
  
      for (i = 0; r_destructors[i]; i++)
      {
  	if (!(mp = Mangle(password, r_destructors[i])))
  	{
  	    continue;
  	}
  
  #ifdef CRACKLIB_DEBUG
  	printf("Gtry: '%s' = '%s' (destruct %s)\n", mp,
  		rawtext, r_destructors[i]);
  #endif
  
  	if (!strncmp(mp, rawtext, len))
  	{
  	    return (1);
  	}
  
  #ifdef CRACKLIB_DEBUG
  	printf("Gtry: '%s' = '%s' (destruct %s reversed)\n", Reverse(mp),
  		rawtext, r_destructors[i]);
  #endif
  
  	if (!strncmp(Reverse(mp), rawtext, len))
  	{
  	    return (1);
  	}
      }
  
      /*
       * Use constructors to turn rawtext into password
       */
      for (i = 0; r_constructors[i]; i++)
      {
  	if (!(mp = Mangle(rawtext, r_constructors[i])))
  	{
  	    continue;
  	}
  
  #ifdef CRACKLIB_DEBUG
  	printf("Gtry: '%s' = '%s' (construct %s)\n", mp,
  		password, r_constructors[i]);
  #endif
  
  	if (!strncmp(mp, password, len))
  	{
  	    return (1);
  	}
      }
  
      return (0);
  }
  
  /*
   * FascistGecos - check if <password> is a permutation of the user's GECOS field
   */
  char *
  FascistGecos(password, uid, pwin)
      char *password;
      int uid;
      struct passwd *pwin;		/* Optional */
  {
      int i;
      int j;
      int wc;
      char *ptr;
      int gwords;
      struct passwd *pwp;
      char gbuffer[STRINGSIZE];
      char tbuffer[STRINGSIZE];
      char *uwords[STRINGSIZE];
      char longbuffer[STRINGSIZE * 2];
  
      if (!pwin)
      {
  	if (!(pwp = getpwuid(uid)))
  	{
  		return ("you cannot be found in the password file");
  	}
      } else
      {
  	pwp = pwin;
      }
  
      /*
       * It never used to be that you got passwd strings > 1024 chars,
       * but now...
       */
      (void) strncpy(tbuffer, pwp->pw_name, STRINGSIZE);
      tbuffer[STRINGSIZE-1] = '\0';
  #ifdef CRACKLIB_DEBUG
      printf("FascistGecos: username check\n");
  #endif
      if (GTry(tbuffer, password))
      {
  	return ("it is based on your username");
      }
  
      /*
       * See if they use something of their home directory path
       */
      (void) strncpy(tbuffer, pwp->pw_dir, STRINGSIZE);
      tbuffer[STRINGSIZE-1] = '\0';
  #ifdef CRACKLIB_DEBUG
      printf("FascistGecos: directory check\n");
  #endif
      if (GTry(tbuffer, password))
      {
  	return ("it is derived from your home directory path");
      }
  
      /*
       * Let's get really paranoid and assume a dangerously long gecos entry
       */
      (void) strncpy(tbuffer, pwp->pw_gecos, STRINGSIZE);
      tbuffer[STRINGSIZE-1] = '\0';
      (void) strcpy(gbuffer, Lowercase(tbuffer));
  
      wc = 0;
      ptr = gbuffer;
      gwords = 0;
      uwords[0] = (char *)0;
  
      while (*ptr)
      {
  	while (*ptr && ISSKIP(*ptr))
  	{
  	    ptr++;
  	}
  
  	if (ptr != gbuffer)
  	{
  	    ptr[-1] = '\0';
  	}
  
  	gwords++;
  	uwords[wc++] = ptr;
  
  	if (wc == STRINGSIZE)
  	{
  	    uwords[--wc] = (char *) 0;  /* to hell with it */
  	    break;
  	} else
  	{
  	    uwords[wc] = (char *) 0;
  	}
  
  	while (*ptr && !ISSKIP(*ptr))
  	{
  	    ptr++;
  	}
  
  	if (*ptr)
  	{
  	    *(ptr++) = '\0';
  	}
      }
  
      for (i = 0; uwords[i]; i++)
      {
  #ifdef CRACKLIB_DEBUG
  	printf("FascistGecos: gecosword %s\n", uwords[i]);
  #endif
  	if (GTry(uwords[i], password))
  	{
  	    return ("it is based upon your user information");
  	}
      }
  
      /* since uwords are taken from gbuffer,
  	no uword can be longer than gbuffer */
  
      for (j = 1; (j < gwords) && uwords[j]; j++)
      {
  	for (i = 0; i < j; i++)
  	{
  	    (void) strcpy(longbuffer, uwords[i]);
  	    (void) strcat(longbuffer, uwords[j]);
  
  	    if (GTry(longbuffer, password))
  	    {
  		return ("it is derived from your user information");
  	    }
  
  	    (void) strcpy(longbuffer, uwords[j]);
  	    (void) strcat(longbuffer, uwords[i]);
  
  	    if (GTry(longbuffer, password))
  	    {
  		return ("it is derived from your user information");
  	    }
  
  	    longbuffer[0] = uwords[i][0];
  	    longbuffer[1] = '\0';
  	    (void) strcat(longbuffer, uwords[j]);
  
  	    if (GTry(longbuffer, password))
  	    {
  		return ("it is deriveable from your user information");
  	    }
  
  	    longbuffer[0] = uwords[j][0];
  	    longbuffer[1] = '\0';
  	    (void) strcat(longbuffer, uwords[i]);
  
  	    if (GTry(longbuffer, password))
  	    {
  		return ("it is derivable from your user information");
  	    }
  	}
      }
      return ((char *) 0);
  }
  
  /*
   * FascistLook - search for <instring> in dictionary <pwp>
   */
  char *
  FascistLook(pwp, instring)
      PWDICT *pwp;
      char *instring;
  {
      int i;
      char *ptr;
      char *jptr;
      char junk[STRINGSIZE];
      char *password;
      char rpassword[STRINGSIZE];
      c_int32 notfound;
  
      notfound = PW_WORDS(pwp);
      /* already truncated if from FascistCheck() */
      /* but pretend it wasn't ... */
      (void) strncpy(rpassword, instring, TRUNCSTRINGSIZE);
      rpassword[TRUNCSTRINGSIZE - 1] = '\0';
      password = rpassword;
  
      if (strlen(password) < 4)
      {
  	return ("it is WAY too short");
      }
  
      if (strlen(password) < MINLEN)
      {
  	return ("it is too short");
      }
  
      jptr = junk;
      *jptr = '\0';
  
      for (i = 0; i < STRINGSIZE && password[i]; i++)
      {
  	if (!strchr(junk, password[i]))
  	{
  	    *(jptr++) = password[i];
  	    *jptr = '\0';
  	}
      }
  
      if (strlen(junk) < MINDIFF)
      {
  	return ("it does not contain enough DIFFERENT characters");
      }
  
      (void) strcpy(password, Lowercase(password));
  
      Trim(password);
  
      while (*password && isspace(*password))
      {
  	password++;
      }
  
      if (!*password)
      {
  	return ("it is all whitespace");
      }
  
      i = 0;
      ptr = password;
      while (ptr[0] && ptr[1])
      {
  	if ((ptr[1] == (ptr[0] + 1)) || (ptr[1] == (ptr[0] - 1)))
  	{
  	    i++;
  	}
  	ptr++;
      }
  
      if (i > MAXSTEP)
      {
  	return ("it is too simplistic/systematic");
      }
  
      if (PMatch("aadddddda", password, 0))  /* smirk */
      {
  	return ("it looks like a National Insurance number");
      }
  
      if (ptr = FascistGecos(password, getuid(), (struct passwd *)0))
      {
  	return (ptr);
      }
  
      /* it should be safe to use Mangle with its reliance on STRINGSIZE
         since password cannot be longer than TRUNCSTRINGSIZE;
         nonetheless this is not an elegant solution */
  
      for (i = 0; r_destructors[i]; i++)
      {
  	char *a;
  
  	if (!(a = Mangle(password, r_destructors[i])))
  	{
  	    continue;
  	}
  
  #ifdef CRACKLIB_DEBUG
  	printf("FascistLook: '%s' (dict)\n", a);
  #endif
  
  	if (FindPW(pwp, a) != notfound)
  	{
  	    return ("it is based on a dictionary word");
  	}
      }
  
      (void) strcpy(password, Reverse(password));
  
      for (i = 0; r_destructors[i]; i++)
      {
  	char *a;
  
  	if (!(a = Mangle(password, r_destructors[i])))
  	{
  	    continue;
  	}
  #ifdef CRACKLIB_DEBUG
  	printf("FascistLook: '%s' (reversed dict)\n", a);
  #endif
  	if (FindPW(pwp, a) != notfound)
  	{
  	    return ("it is based on a (reversed) dictionary word");
  	}
      }
      return ((char *) 0);
  }
  
  /*
   * FascistCheck - look for <password> in dictionary <path>
   */
  char *
  FascistCheck(password, path)
      char *password;
      char *path;
  {
      PWDICT *pwp;
      char pwtrunced[STRINGSIZE];
  
      /* security problem: assume we may have been given a really long
         password (buffer attack) and so truncate it to a workable size;
         try to define workable size as something from which we cannot
         extend a buffer beyond its limits in the rest of the code */
  
      (void) strncpy(pwtrunced, password, TRUNCSTRINGSIZE);
      pwtrunced[TRUNCSTRINGSIZE - 1] = '\0'; /* enforce */
  
      /* perhaps someone should put something here to check if password
         is really long and syslog() a message denoting buffer attacks?  */
  
      if (pwp)
      {
  	(void) PWClose(pwp);
  	pwp = (PWDICT *)0;
      }
  
      if (!pwp)
      {
  	if (!(pwp = PWOpen(path, "r")))
  	{
  	    (void) fprintf(stderr, "%s: PWOpen error %s\n", path, PWioError);
  	    exit(-1);
  	}
      }
      return (FascistLook(pwp, pwtrunced));
  }
  
  /*
   * FascistNpasswd - Cracklib stuff that npasswd needs
   */
  char *
  FascistNpasswd(pwl, instring, verbose)
      char **pwl;		/* List of dictionaries to look in */
      char *instring;	/* Password string */
      int verbose;	/* Verbose flag */
  {
      char **decon;			/* Mangle deconstructor */
      char *password;			/* Pointer to stuff in rpassword */
      char rpassword[STRINGSIZE];		/* Cleaned copy of <instring> */
      char revpassword[STRINGSIZE];	/* Reversed copy of <rpassword> */
      int  ndicts = 0;			/* How many dictionaries looked in */
  
      /*
       * Copy input string and truncate
       */
      (void) strncpy(rpassword, instring, TRUNCSTRINGSIZE);
      rpassword[TRUNCSTRINGSIZE - 1] = '\0';
      password = rpassword;
  
      (void) strcpy(password, Lowercase(password));	/* Make lower case */
      (void) Trim(password);			/* Trim trailing whitespace */
  
      while (*password && isspace(*password))	/* Trim leading whitespace */
      {
  	password++;
      }
  
      if (!*password)
      {
  	return ("it is all whitespace");
      }
  
      /* 
       * It should be safe to use Mangle with its reliance on STRINGSIZE
       * since password cannot be longer than TRUNCSTRINGSIZE
       */
      (void) strcpy(revpassword, Reverse(password));
  
      /* 
       * Iterate through the mangle deconstructors
       */
      for (decon = r_destructors; *decon; decon++)
      {
  	static char msgbuf[STRINGSIZE];
  	char mangled[STRINGSIZE];
          char **pwx;
  	char *a;
  
  	mangled[0] = 0;
  	if (a = Mangle(password, *decon))	/* Forward password */
  	{
  		(void) strcpy(mangled, a);
  		if (verbose)
  			printf("FascistNpasswd: '%s' (dict) decon '%s'\n",
  				mangled, *decon);
  	}
  	if (a = Mangle(revpassword, *decon))	/* Reversed password */
  	{
  		if (verbose)
  			printf("FascistNpasswd: '%s' (rev dict) decon '%s'\n",
  				a, *decon);
  	}
  	for (pwx = pwl; *pwx; pwx++) {	/* Iterate dictionaries */
  		PWDICT	*pw = PWOpen(*pwx, "r");
  		c_int32	found;
  
  		if (pw == 0)
  		{
  		    (void) sprintf (msgbuf,
  			"Lookup error (%s) in dictionary \"%s\"",
  				PWioError, *pwx);
  		    return (msgbuf);
  		}
  		if (verbose)
  			printf("FascistNpasswd: dict '%s'\n", *pwx);
  		if (mangled[0] && (found = FindPW(pw, mangled)) != PW_WORDS(pw))
  		{
  		    (void) sprintf (msgbuf,
  			"it can be derived from the word '%s'",
  				GetPW(pw, found));
  		    (void) PWClose (pw);
  		    return (msgbuf);
  		}
  		if (a && (found = FindPW(pw, a)) != PW_WORDS(pw))
  		{
  		    (void) sprintf (msgbuf,
  			"it can be derived from the word '%s'",
  				GetPW(pw, found));
  		    (void) PWClose (pw);
  		    return (msgbuf);
  		}
  		(void) PWClose (pw);
  		ndicts++;
  	}
      }
      if (ndicts)
  	    return ((char *) 0);
      else
  	    return ("no dictionaries were found");
  }
  
  /* End fascist.c */
  