/* (c) 2008 Jan Dlabal <dlabaljan@gmail.com> */
/* */
/* This file is part of the bfg. */
/* */
/* bfgen is free software: you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation, either version 3 of the License, or */
/* any later version. */
/* */
/* bfgen is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with bfgen. If not, see <http://gnu.org/licenses>. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include "bfg.h"
bf_option bf_options;
#ifdef HAVE_MATH_H
void bf_recurse(unsigned int len, unsigned int pos, char *string);
int bf_add(char *string);
char *ptr = NULL;
/* return values : 0 on success, 1 on error */
int bf_init(char *arg) {
int i = 0;
int crs_len = 1;
char flags = 0;
char *tmp = strchr(arg, ':');
// printf("%s %s, [%s] (c) Jan Dlabal, %s\n", BF_NAME, BF_VERSION, BF_WEBSITE, BF_YEAR);
if (!tmp) {
fprintf(stderr, "Error: Invalid option format for -x\n");
return 1;
} else {
tmp[0] = '\0';
}
bf_options.crt = atoi(arg);
arg = tmp + 1;
tmp++;
if (!arg[0]) {
fprintf(stderr, "Error: no maximum length specified for -x min:max:types!\n");
return 1;
}
tmp = strchr(arg, ':');
if (!tmp) {
fprintf(stderr, "Error: Invalid option format for -x\n");
return 1;
} else {
tmp[0] = '\0';
}
bf_options.max = atoi(arg);
bf_options.end = 0;
tmp++;
if (bf_options.crt > bf_options.max) {
fprintf(stderr, "Error: you specified a minimum length higher than the maximum length!\n");
return 1;
}
if (!tmp[0]) {
fprintf(stderr, "Error: charset not specified!\n");
return 1;
}
bf_options.crs = malloc(sizeof(char) * BF_CHARSMAX);
if (bf_options.crs == NULL) {
fprintf(stderr, "Error: can't allocate enough memory!\n");
return 1;
}
bf_options.crs[0] = 0;
for (; tmp[i]; i++) {
switch (tmp[i]) {
case 'a':
crs_len += 26;
if (BF_CHARSMAX - crs_len < 0) {
free(bf_options.crs);
fprintf(stderr, "Error: charset specification exceeds %d characters.\n", BF_CHARSMAX);
return 1;
} else if (flags & BF_LOWER) {
free(bf_options.crs);
fprintf(stderr, "Error: 'a' specified more than once in charset!\n");
return 1;
} else {
strcat(bf_options.crs, "abcdefghijklmnopqrstuvwxyz");
flags |= BF_LOWER;
}
break;
case 'A':
crs_len += 26;
if (BF_CHARSMAX - crs_len < 0) {
free(bf_options.crs);
fprintf(stderr, "Error: charset specification exceeds %d characters.\n", BF_CHARSMAX);
return 1;
} else if (flags & BF_UPPER) {
free(bf_options.crs);
fprintf(stderr, "Error: 'A' specified more than once in charset!\n");
return 1;
} else {
strcat(bf_options.crs, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
flags |= BF_UPPER;
}
break;
case '1':
crs_len += 10;
if (BF_CHARSMAX - crs_len < 0) {
free(bf_options.crs);
fprintf(stderr, "Error: charset specification exceeds %d characters.\n", BF_CHARSMAX);
return 1;
} else if (flags & BF_NUMS) {
free(bf_options.crs);
fprintf(stderr, "Error: '1' specified more than once in charset!\n");
return 1;
} else {
strcat(bf_options.crs, "0123456789");
flags |= BF_NUMS;
}
break;
default:
crs_len += 1;
if (BF_CHARSMAX - crs_len < 0) {
free(bf_options.crs);
fprintf(stderr, "Error: charset specification exceeds %d characters.\n", BF_CHARSMAX);
return 1;
} else {
bf_options.crs[crs_len - 1] = '\0';
bf_options.crs[crs_len - 2] = tmp[i];
}
break;
}
}
ptr = bf_options.ptr;
return 0;
}
/* returns 0 on success, 1 on error */
int bf_generate() {
static char *tmp1 = NULL;
if (tmp1 == NULL) {
if ((tmp1 = malloc(BF_BUFLEN)) == NULL)
return 1;
}
bf_options.end = 0;
while (bf_options.end == 0)
bf_recurse(bf_options.crt, 0, tmp1);
free(tmp1);
tmp1 = NULL;
return 0;
}
void bf_recurse(unsigned int len, unsigned int pos, char *string) {
// len is the length of the currently tested password,
// pos is the position of the char that this function has to modify
// string is the string to test
int i;
char last = 0;
if (bf_options.save[pos] >= strlen(bf_options.crs)) {
bf_options.save[pos] = 0;
bf_options.save[pos - 1]++;
return;
}
if (bf_options.last || pos == 0) {
last = 1;
bf_options.last = 0;
}
for (i = bf_options.save[pos]; ((i < strlen(bf_options.crs)) && (bf_options.end == 0)); i++) {
if (last && (i + 1 == strlen(bf_options.crs)))
bf_options.last = 1;
if (pos < (len - 1)) {
string[pos] = bf_options.crs[i];
bf_recurse(len, pos + 1, string);
} else {
string[pos] = bf_options.crs[i];
string[pos + 1] = '\0';
bf_add(string);
bf_options.end = 1;
if (bf_options.last) {
bf_options.crt++;
bf_options.last = 0;
}
}
}
if ((bf_options.end == 1) && (bf_options.last == 0)) {
if (pos == (len - 1)) {
bf_options.save[pos] = i;
} else {
bf_options.save[pos] = i - 1;
}
} else {
bf_options.save[pos] = 0;
}
}
// returns 0 when no error is detected, and 1 when the buffer is filled
int bf_add(char *tmp) {
unsigned int len;
if (tmp[0] != 0) {
if ((len = strlen(tmp)) > 0) {
tmp[len] = 0; /* ensure null byte at the end of the string */
bf_options.ptr = tmp;
return 1;
}
}
return 0;
}
unsigned long int bf_get_pcount() {
int i;
unsigned long int count = 0;
for (i = bf_options.crt; i <= bf_options.max; i++)
count += (unsigned long int) (pow((float) strlen(bf_options.crs), (float) i));
return count;
}
char *bf_next() {
char *tmp2 = malloc(BF_BUFLEN); // we don't care for freeing - this is handled by others
if (tmp2 == NULL) {
fprintf(stderr, "Error: Can not allocate memory for -x data!\n");
return NULL;
}
bf_generate();
strcpy(tmp2, bf_options.ptr);
return tmp2;
}
#endif