"Fossies" - the Fresh Open Source Software Archive

Member "passgen-1.2.0/src/passgen.c" (18 Jun 2011, 12645 Bytes) of package /linux/privat/old/passgen-1.2.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "passgen.c" see the Fossies "Dox" file reference documentation.

    1 /*  Author:     V. Alex Brennen (vab@mit.edu)   */
    2 /*  Copyright:      None                */
    3 /*  License:        Public Domain           */
    4 /*  Created:        2006.09.15          */
    5 /*  Last Updated:   2011.06.18          */
    6 
    7 #include "passgen.h"
    8 
    9 
   10 /* This is a simple program to read some data from /dev/random or
   11  * /dev/urandom and map it to a set of ASCII characters. That group
   12  * of pseudorandom characters can then be used as a password.
   13  */
   14 
   15 int main(int argc,char *argv[])
   16 {
   17     const char version[] = "1.2.0";
   18 
   19     int rslt = 0;
   20     int arg = 0;
   21     int n = 0;
   22 
   23 
   24     /* Init the config, then read config file */
   25     struct passgen_config *config = (struct passgen_config *)malloc(sizeof(struct passgen_config));
   26     if(config == NULL)
   27     {
   28         fprintf(stderr,"Failed to malloc config struct.\n");
   29         fprintf(stderr,"Perhaps, the system is out of memory?\n");
   30         fprintf(stderr,"Exiting...\n\n");
   31 
   32         return -1;
   33     }
   34     rslt = init_passgen_config(&config);
   35     if(rslt != 0)
   36     {
   37         fprintf(stderr,"Warning!  Failed to initialize passgen config.\n");
   38         fprintf(stderr,"Perhaps, the system is experiencing memory problems?\n");
   39         fprintf(stderr,"Exiting...\n\n");
   40 
   41         return -1;
   42     }
   43     if(argc > 1)
   44     {
   45         for(arg = 1; arg < argc; arg++)
   46         {
   47             if(argv[arg][0] == '-')
   48             {
   49                 if(argv[arg][1] == 'C')
   50                 {
   51                     config->suppress_config_warning = 1;
   52                     
   53                     break;
   54                 }
   55                 else if(argv[arg][1] == 'h')
   56                 {
   57                     print_help();
   58                     if(config != NULL)
   59                         free(config);
   60 
   61                     return 0;
   62                 }
   63                 else if(argv[arg][1] == 'v')
   64                 {
   65                     printf("CryptNET Password Generator Version %s\n", version);
   66                     if(config != NULL)
   67                         free(config);
   68 
   69                     return 0;
   70                 }
   71                 else if(argv[arg][1] == '-')
   72                 {
   73                     if(strstr(argv[arg],"help") != NULL)
   74                     {
   75                         print_help();
   76                         if(config != NULL)
   77                             free(config);
   78 
   79                         return 0;
   80                     }
   81                     else if(strstr(argv[arg],"version") != NULL)
   82                     {
   83                         printf("CryptNET Password Generator Version %s\n", version);
   84                         if(config != NULL)
   85                             free(config);
   86 
   87                         return 0;
   88                     }
   89                 }
   90             }
   91         }
   92     }
   93     rslt = read_passgen_config(&config);
   94     if((rslt != 0) && (config->suppress_config_warning == 0))
   95     {
   96         fprintf(stderr,"Password candidates may not match desired criteria.\n");
   97         fprintf(stderr,"Continuing...\n\n");
   98     }
   99 
  100     if(argc > 1)
  101     {
  102         int conf_lowercase_set = 0;
  103         int conf_uppercase_set = 0;
  104         int conf_urandom_set = 0;
  105         int conf_random_set = 0;
  106 
  107 
  108         for(arg = 1; arg < argc; arg++)
  109         {
  110             if(argv[arg][0] == '-')
  111             {
  112                 if(argv[arg][1] == 'a')
  113                 {
  114                     config->passwd_type = D_ALPHA_NUMERIC;
  115                 }
  116                 else if(argv[arg][1] == 'A')
  117                 {
  118                     config->passwd_type = D_ALPHA_ONLY;
  119                 }
  120                 else if(argv[arg][1] == 'C')
  121                 {
  122                     continue;
  123                 }
  124                 else if(argv[arg][1] == 'H')
  125                 {
  126                     n = arg;
  127                     n++;
  128                     if(((argv[n] != NULL) && isdigit(argv[n][0])))              
  129                     {
  130                         config->homoglyph_suppression_level = atoi(argv[n]);
  131                         if((config->homoglyph_suppression_level > 2) ||
  132                             (config->homoglyph_suppression_level < 0))
  133                         {
  134                             invalid_argument();
  135                             fprintf(stderr,"Configuration Error: Homoglyph suppression levels must be between 0 and 2.\n");
  136                             if(config != NULL)
  137                                 free(config);
  138 
  139                             return 0;
  140                         }
  141                     }
  142                     else
  143                     {
  144                         invalid_argument();
  145                         fprintf(stderr,"Configuration Error: Proper format is -n x, where x in an integer.\n");
  146                         if(config != NULL)
  147                             free(config);
  148 
  149                         return 0;
  150                     }
  151                 }
  152                 else if(argv[arg][1] == 'l')
  153                 {
  154                     /* Read in info on how many chars are wanted */
  155                     n = arg;
  156                     n++;
  157                     if((argv[n] != NULL) && (isdigit(argv[n][0])))
  158                     {
  159                         config->num_chars = atoi(argv[n]);
  160                     }
  161                     else
  162                     {
  163                         invalid_argument();
  164                         fprintf(stderr,"Configuration Error: Proper format is -l x, where x in an integer.\n");
  165                         if(config != NULL)
  166                             free(config);
  167 
  168                         return 0;
  169                     }
  170                 }
  171                 else if(argv[arg][1] == 'L')
  172                 {
  173                     conf_lowercase_set = 1;
  174                     if(conf_uppercase_set == 1)
  175                     {
  176                         invalid_argument();
  177                         fprintf(stderr,"Configuration Error: Lowercase only and uppercase only options are mutually exclusive.\n");
  178                         if(config != NULL)
  179                             free(config);
  180         
  181                         return 0;
  182                     }
  183                     config->lowercase_only = 1;
  184                 }
  185                 else if(argv[arg][1] == 'n')
  186                 {
  187                     /* Read in info on how many chars are wanted */
  188                     n = arg;
  189                     n++;
  190                     if(((argv[n] != NULL) && isdigit(argv[n][0])))              
  191                     {
  192                         config->num_passwds = atoi(argv[n]);
  193                     }
  194                     else
  195                     {
  196                         invalid_argument();
  197                         fprintf(stderr, "Configuration Error: Proper format is -n x, where x in an integer.\n");
  198                         if(config != NULL)
  199                             free(config);
  200 
  201                         return 0;
  202                     }
  203                 }
  204                 else if(argv[arg][1] == 'N')
  205                 {
  206                     config->passwd_type = D_NUMERIC_ONLY;
  207                 }
  208                 else if(argv[arg][1] == 'r')
  209                 {
  210                     conf_random_set = 1;
  211                     if(conf_urandom_set == 1)
  212                     {
  213                         invalid_argument();
  214                         fprintf(stderr,"Configuration Error: Options to use /dev/random and /dev/urandom are mutually exclusive.\n");
  215                         if(config != NULL)
  216                             free(config);
  217 
  218                         return 0;
  219                     }
  220                     config->use_urandom = 0;
  221                 }
  222                 else if(argv[arg][1] == 's')
  223                 {
  224                     config->no_space = 1;
  225                 }
  226                 else if(argv[arg][1] == 'u')
  227                 {
  228                     conf_urandom_set = 1;
  229                     if(conf_random_set == 1)
  230                     {
  231                         invalid_argument();
  232                         fprintf(stderr,"Configuration Error: Options to use /dev/random and /dev/urandom are mutually exclusive.\n");
  233                         if(config != NULL)
  234                             free(config);
  235 
  236                         return 0;
  237                     }
  238                     config->use_urandom = 1;
  239                 }
  240                 else if(argv[arg][1] == 'U')
  241                 {
  242                     conf_uppercase_set = 1;
  243                     if(conf_lowercase_set == 1)
  244                     {
  245                         invalid_argument();
  246                         fprintf(stderr,"Configuration Error: Lowercase only and uppercase only options are mutually exclusive.\n");
  247                         if(config != NULL)
  248                             free(config);
  249 
  250                         return 0;
  251                     }
  252                     config->uppercase_only = 1;
  253                 }
  254                 else if(isdigit(argv[arg][0]))
  255                 {
  256                     continue;
  257                 }
  258                 else
  259                 {
  260                     invalid_argument();
  261                     if(config != NULL)
  262                         free(config);
  263 
  264                     return 0;
  265                 }
  266             }
  267         }
  268     }
  269     rslt = map_data_to_chars(config);
  270     if(rslt != 0)
  271     {
  272         fprintf(stderr,"ERROR:  The char mapping function returned an error.\n");
  273         fprintf(stderr,"Password generation failed.\n");
  274         fprintf(stderr,"Exiting.\n\n");
  275         if(config != NULL)
  276             free(config);
  277 
  278         return -1;
  279     }
  280 
  281     if(config != NULL)
  282         free(config);
  283 
  284 
  285     return 0;
  286 }
  287 
  288 
  289 int map_data_to_chars(struct passgen_config *config)
  290 {
  291     int lcv = 0;
  292     int i = 0;
  293     int rslt = 0;
  294     int size = 0;
  295     int array_size = 0;
  296     unsigned int tmp = 0;
  297     char c = 0x00;
  298 
  299     FILE    *pseudorandom = NULL;
  300 
  301     /* There are four different arrays here because having different mapping arrays for the 
  302        different major types of passwords will prevent the generator from discarding
  303        pseudorandomness with excessive generated character rejections. This matters primarily
  304        if we're pulling the pseudorandomness from /dev/random.  But, since /dev/urandom is 
  305        also seeded a very small decrease in randomness is possible with excessive discards. */
  306     static char array[95] = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q',
  307              'R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h',
  308              'i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y',
  309              'z','0','1','2','3','4','5','6','7','8','9','~','`','!','@','#','$',
  310              '%','^','&','*','(',')','[',']','{','}','/','?','=','+','-','_','|',
  311              '\\',';',':','"','\'',',','<','.','>',' '};
  312 
  313     char alpha_numeric_array[62] = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q',
  314              'R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h',
  315              'i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y',
  316              'z','0','1','2','3','4','5','6','7','8','9'};
  317 
  318     char alpha_array[52] = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q',
  319              'R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h',
  320              'i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y',
  321              'z'};
  322 
  323     char numeric_array[10] = {'0','1','2','3','4','5','6','7','8','9'};
  324 
  325     char homoglyph_lvl1_suppress[4] = {'0','O','1','l'};
  326 
  327     char homoglyph_lvl2_suppress[9] = {'0','O','1','l','\'','`','"',' ','_'};
  328 
  329     char buff = 0x00;
  330     char *passwd = NULL;
  331 
  332 
  333     size = config->num_chars;
  334 
  335     /* Here array_size is array *address size*.  Arrays size is one more than array address size
  336        since addresses start at zero in the C language.
  337     */
  338     if(config->passwd_type == D_DEFAULT)
  339     {
  340         array_size = 94;
  341     }
  342     else if(config->passwd_type == D_ALPHA_NUMERIC)
  343     {
  344         array_size = 61;
  345     }
  346     else if(config->passwd_type == D_ALPHA_ONLY)
  347     {
  348         array_size = 51;
  349     }
  350     else if(config->passwd_type == D_NUMERIC_ONLY)
  351     {
  352         array_size = 9;
  353     }
  354     else
  355     {
  356         fprintf(stderr,"passgen:  Error unknown password type requested: %d.\n", config->passwd_type);
  357 
  358         return -1;
  359     }
  360     
  361     if(config->use_urandom == 0)
  362     {
  363         if(NULL == (pseudorandom = fopen("/dev/random","r")))
  364         {
  365             fprintf(stderr,"ERROR:  Failed to open /dev/random!\n");
  366             fprintf(stderr,"Exiting...\n\n");
  367 
  368             return 0;
  369         }
  370     }
  371     else
  372     {
  373         if(NULL == (pseudorandom = fopen("/dev/urandom","r")))
  374         {
  375             fprintf(stderr,"ERROR:  Failed to open /dev/urandom!\n");
  376             fprintf(stderr,"Exiting...\n\n");
  377 
  378             return 0;
  379         }
  380     }
  381 
  382     passwd = malloc(size+1);
  383     if(passwd == NULL)
  384     {
  385         printf("Failed to allocate memory.\n");
  386         fclose(pseudorandom);
  387 
  388         return -1;
  389     }
  390 
  391     for(i = 0;i < config->num_passwds; i++)
  392     {
  393         lcv = 0;
  394         memset(passwd,0x00,size+1);
  395         
  396         while(lcv < size)
  397         {
  398             buff = 0x00;
  399     
  400             rslt = fread(&buff,1,1,pseudorandom);
  401             if(rslt < 0)
  402             {
  403                 fprintf(stderr,"ERROR:  Read of data from specified device failed.\n");
  404                 fclose(pseudorandom);
  405                 free(passwd);
  406 
  407                 return -1;
  408             }
  409 
  410             tmp = buff;
  411             if(tmp > array_size)
  412             {
  413                 tmp = tmp % array_size;
  414             }
  415 
  416             if((config->passwd_type == D_DEFAULT))
  417             {
  418                 c = array[tmp];
  419             }
  420             if(config->passwd_type == D_ALPHA_NUMERIC)
  421             {
  422                 c = alpha_numeric_array[tmp];
  423             }
  424             else if(config->passwd_type == D_ALPHA_ONLY)
  425             {
  426                 c = alpha_array[tmp];
  427             }
  428             else if(config->passwd_type == D_NUMERIC_ONLY)
  429             {
  430                 c = numeric_array[tmp];
  431             }
  432             else
  433             {
  434                 c = array[tmp];
  435             }
  436             
  437             /* If we're excluding spaces and the generated password character is space generate another character */
  438             if((config->no_space == 1) && (c == ' '))
  439             {
  440                 continue;
  441             }
  442 
  443             /* If we're suppressing homoglyphs and one comes up, read another byte of randomness
  444              * and map it to the array */
  445             if(config->homoglyph_suppression_level > 0)
  446             {
  447                 if(config->homoglyph_suppression_level == 1)
  448                 {
  449                     if((memchr(homoglyph_lvl1_suppress,array[tmp],4)) != NULL)
  450                     {
  451                         continue;
  452                     }
  453                 }
  454                 else if(config->homoglyph_suppression_level == 2)
  455                 {
  456                     if((memchr(homoglyph_lvl2_suppress,array[tmp],9)) != NULL)
  457                     {
  458                         continue;
  459                     }
  460                 }
  461                 else
  462                 {
  463                     fprintf(stderr,"There appears to be an error with the homoglyph suppression configuration.\n");
  464                     fclose(pseudorandom);
  465                     free(passwd);
  466     
  467                     return -1;
  468                 }
  469             }
  470 
  471             if(config->uppercase_only == 1)
  472             {
  473                 c = toupper(c);
  474             }
  475             else if(config->lowercase_only == 1)
  476             {
  477                 c = tolower(c); 
  478             }
  479 
  480             /* This shouldn't be possible, but it is caught just in case. */
  481             if(c == '\0')
  482             {
  483                 fclose(pseudorandom);
  484                 free(passwd);
  485 
  486                 return -1;
  487             }
  488             passwd[lcv] = c;
  489 
  490             lcv++;
  491         }
  492         passwd[lcv] = '\0';
  493         printf("%s\n", passwd);
  494     }
  495     fclose(pseudorandom);
  496     free(passwd);
  497 
  498 
  499     return 0;
  500 }
  501 
  502 
  503 int print_help(void)
  504 {
  505     printf("Usage: passgen\n");
  506     printf("\t-a\t\tAlpha numeric characters only.\n");
  507     printf("\t-A\t\tAlphabetic characters only.\n");
  508     printf("\t-C\t\tSuppress config file not found messages.\n");
  509     printf("\t-h\t\tThis help text.\n");
  510     printf("\t-H\t\tHomoglyph suppression level (0-2).\n");
  511     printf("\t-l\t\tThe length of the password.\n");
  512     printf("\t-L\t\tFor any letters, use lowercase only.\n");
  513     printf("\t-n\t\tNumber of passwords to provide.\n");
  514     printf("\t-N\t\tNumeric characters only.\n");
  515     printf("\t-r\t\tUse /dev/random for password generation.\n");
  516     printf("\t-s\t\tExclude the space character.\n");
  517     printf("\t-u\t\tUse /dev/urandom rather than /dev/random.\n");
  518     printf("\t\t\t(Will speed password generation)\n");
  519     printf("\t-U\t\tFor any letters, user uppercase only.\n");
  520     printf("\t-v\t\tDisplay version information.\n");
  521     printf("\t--help\t\tThis help text.\n");
  522     printf("\t--version\tDisplay version information.\n");
  523     printf("\n");
  524     printf("Persisting alternate default configuration values may be set in passgen.conf.\n");
  525     printf("For for information: `man passgen.conf`\n");
  526     printf("\n");
  527 
  528 
  529     return 0;
  530 }
  531 
  532 
  533 int invalid_argument(void)
  534 {
  535     fprintf(stderr,"passgen: Invalid arument given\n\n");
  536 
  537     print_help();
  538 
  539 
  540     return 0;
  541 }