/* * Copyright (c) 2019 Clementine Computing LLC. * * This file is part of PopuFare. * * PopuFare is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * PopuFare 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with PopuFare. If not, see . * */ #include "passdb_slim.h" // SHALLOW COPY // passdb_slim_config is a shallow container. All memory management // should be done from ctx. // void passdb_slim_copy_config( passdb_slim_config *cfg, passdb_slim_context *ctx ) { cfg->hash_modulus = ctx->hash_modulus; cfg->n_one_cred_bank = ctx->n_one_cred_bank; cfg->n_two_cred_bank = ctx->n_two_cred_bank; cfg->n_spillover_bank = ctx->n_spillover_bank; cfg->n_one_cred_bank_size = ctx->n_one_cred_bank_size; cfg->n_two_cred_bank_size = ctx->n_two_cred_bank_size; cfg->n_spillover_bank_size = ctx->n_spillover_bank_size; cfg->n_one_cred_max_bank = ctx->n_one_cred_max_bank; cfg->n_two_cred_max_bank = ctx->n_two_cred_max_bank; cfg->n_spillover_max_bank = ctx->n_spillover_max_bank; cfg->one_cred_db_base_fn = ctx->one_cred_db_base_fn; cfg->two_cred_db_base_fn = ctx->two_cred_db_base_fn; cfg->spillover_db_base_fn = ctx->spillover_db_base_fn; cfg->db_fn_suffix = ctx->db_fn_suffix; cfg->ruleparam_db_fn = ctx->ruleparam_db_fn; cfg->high_watermark_threshold = ctx->high_watermark_threshold; cfg->low_watermark_threshold = ctx->low_watermark_threshold; } #define DEFAULT_HASH_MODULUS 131101 #define DEFAULT_ONE_CRED_MAX_BANK 25 #define DEFAULT_TWO_CRED_MAX_BANK 25 #define DEFAULT_SPILLOVER_MAX_BANK 25 #define DEFAULT_ONE_CRED_BANK_SIZE 10012 #define DEFAULT_TWO_CRED_BANK_SIZE 10012 #define DEFAULT_SPILLOVER_BANK_SIZE 32 #define DEFAULT_ONE_CRED_BANK 1 #define DEFAULT_TWO_CRED_BANK 1 #define DEFAULT_SPILLOVER_BANK 1 #define DEFAULT_ONE_CRED_DB_BASE DATABASE_FILE_PATH "passes_one_bank" #define DEFAULT_TWO_CRED_DB_BASE DATABASE_FILE_PATH "passes_two_bank" #define DEFAULT_SPILLOVER_DB_BASE DATABASE_FILE_PATH "passes_spillover_bank" #define DEFAULT_DB_SUFFIX ".mem" #define DEFAULT_RULEPARAM_DB DATABASE_FILE_PATH "ruleparam.db" #define DEFAULT_HIGH_WATERMARK 0.95 //unused // #define DEFAULT_LOW_WATERMARK 0.25 int make_default_config( char *config_fn ) { FILE *fp; struct tm tm_tim; struct timeval timval; char str_tim[FN_SZ]; gettimeofday(&timval, NULL); localtime_r(&(timval.tv_sec), &tm_tim); asctime_r(&tm_tim, str_tim); fp = fopen(config_fn, "w"); if (!fp) return -1; fprintf(fp, "# %s", str_tim ); fprintf(fp, "#\n"); fprintf(fp, "#\n"); fprintf(fp, "hash_modulus %i\n", DEFAULT_HASH_MODULUS); fprintf(fp, "\n"); fprintf(fp, "n_one_cred_max_bank %i\n", DEFAULT_ONE_CRED_MAX_BANK ); fprintf(fp, "n_two_cred_max_bank %i\n", DEFAULT_TWO_CRED_MAX_BANK ); fprintf(fp, "n_spillover_max_bank %i\n", DEFAULT_SPILLOVER_MAX_BANK ); fprintf(fp, "\n"); fprintf(fp, "n_one_cred_bank_size %i\n", DEFAULT_ONE_CRED_BANK_SIZE ); fprintf(fp, "n_two_cred_bank_size %i\n", DEFAULT_TWO_CRED_BANK_SIZE ); fprintf(fp, "n_spillover_bank_size %i\n", DEFAULT_SPILLOVER_BANK_SIZE ); fprintf(fp, "\n"); fprintf(fp, "n_one_cred_bank %i\n", DEFAULT_ONE_CRED_BANK ); fprintf(fp, "n_two_cred_bank %i\n", DEFAULT_TWO_CRED_BANK ); fprintf(fp, "n_spillover_bank %i\n", DEFAULT_SPILLOVER_BANK ); fprintf(fp, "\n"); fprintf(fp, "one_cred_db_base %s\n", DEFAULT_ONE_CRED_DB_BASE ); fprintf(fp, "two_cred_db_base %s\n", DEFAULT_TWO_CRED_DB_BASE ); fprintf(fp, "spillover_db_base %s\n", DEFAULT_SPILLOVER_DB_BASE ); fprintf(fp, "\n"); fprintf(fp, "db_suffix %s\n", DEFAULT_DB_SUFFIX ); fprintf(fp, "\n"); fprintf(fp, "ruleparam_db %s\n", DEFAULT_RULEPARAM_DB ); fprintf(fp, "\n"); fprintf(fp, "high_watermark_threshold %f\n", DEFAULT_HIGH_WATERMARK ); fprintf(fp, "low_watermark_threshold %f\n", DEFAULT_LOW_WATERMARK ); fprintf(fp, "\n"); fclose(fp); return 0; } int save_config( passdb_slim_config *cfg, char *config_fn ) { FILE *fp; struct tm tm_tim; struct timeval timval; char str_tim[FN_SZ]; gettimeofday(&timval, NULL); localtime_r(&(timval.tv_sec), &tm_tim); asctime_r(&tm_tim, str_tim); fp = fopen( config_fn, "w" ); if (!fp) { //DEBUG //fprintf(stderr, "ERROR: passdb.save_config: could not open file %s\n", config_fn); //exit(1); perror(config_fn); return -1; } fprintf(fp, "# %s", str_tim ); fprintf(fp, "#\n"); fprintf(fp, "#\n"); fprintf(fp, "hash_modulus %i\n", cfg->hash_modulus); fprintf(fp, "\n"); fprintf(fp, "n_one_cred_max_bank %i\n", cfg->n_one_cred_max_bank); fprintf(fp, "n_two_cred_max_bank %i\n", cfg->n_two_cred_max_bank); fprintf(fp, "n_spillover_max_bank %i\n", cfg->n_spillover_max_bank); fprintf(fp, "\n"); fprintf(fp, "n_one_cred_bank_size %i\n", cfg->n_one_cred_bank_size); fprintf(fp, "n_two_cred_bank_size %i\n", cfg->n_two_cred_bank_size); fprintf(fp, "n_spillover_bank_size %i\n", cfg->n_spillover_bank_size); fprintf(fp, "\n"); fprintf(fp, "n_one_cred_bank %i\n", cfg->n_one_cred_bank); fprintf(fp, "n_two_cred_bank %i\n", cfg->n_two_cred_bank); fprintf(fp, "n_spillover_bank %i\n", cfg->n_spillover_bank); fprintf(fp, "\n"); fprintf(fp, "one_cred_db_base %s\n", cfg->one_cred_db_base_fn); fprintf(fp, "two_cred_db_base %s\n", cfg->two_cred_db_base_fn); fprintf(fp, "spillover_db_base %s\n", cfg->spillover_db_base_fn); fprintf(fp, "\n"); fprintf(fp, "db_suffix %s\n", cfg->db_fn_suffix); fprintf(fp, "\n"); fprintf(fp, "ruleparam_db %s\n", cfg->ruleparam_db_fn); fprintf(fp, "\n"); fprintf(fp, "high_watermark_threshold %f\n", (double)cfg->high_watermark_threshold ); fprintf(fp, "low_watermark_threshold %f\n", (double)cfg->low_watermark_threshold ); fprintf(fp, "\n"); fclose(fp); return 0; } int read_config( passdb_slim_config *cfg, char *config_fn ) { FILE *fp; char buf[FN_SZ]; char keyword[FN_SZ], rvalue[FN_SZ]; int r; cfg->hash_modulus = -1; cfg->n_one_cred_bank_size = -1; cfg->n_two_cred_bank_size = -1; cfg->n_spillover_bank_size = -1; cfg->n_one_cred_bank = -1; cfg->n_two_cred_bank = -1; cfg->n_spillover_bank = -1; cfg->one_cred_db_base_fn = NULL; cfg->two_cred_db_base_fn = NULL; cfg->spillover_db_base_fn = NULL; cfg->db_fn_suffix = NULL; cfg->high_watermark_threshold = 0.99; cfg->low_watermark_threshold = 0.1; cfg->ruleparam_db_fn = NULL; fp = fopen(config_fn, "r"); if (!fp) return -1; while ( fgets(buf, FN_SZ-1, fp) ) { if (buf[0] == '#') continue; r = sscanf(buf, "%s %s", keyword, rvalue); if (keyword[0] == '#') continue; if (r!=2) continue; if ( strncmp(keyword, "hash_modulus", FN_SZ-1) == 0 ) { cfg->hash_modulus = atoi(rvalue); } else if (strncmp(keyword, "n_one_cred_bank_size", FN_SZ-1) == 0 ) { cfg->n_one_cred_bank_size = atoi(rvalue); } else if (strncmp(keyword, "n_two_cred_bank_size", FN_SZ-1) == 0 ) { cfg->n_two_cred_bank_size = atoi(rvalue); } else if (strncmp(keyword, "n_spillover_bank_size", FN_SZ-1) == 0 ) { cfg->n_spillover_bank_size = atoi(rvalue); } else if (strncmp(keyword, "n_one_cred_bank", FN_SZ-1) == 0 ) { cfg->n_one_cred_bank = atoi(rvalue); } else if (strncmp(keyword, "n_two_cred_bank", FN_SZ-1) == 0 ) { cfg->n_two_cred_bank = atoi(rvalue); } else if (strncmp(keyword, "n_spillover_bank", FN_SZ-1) == 0 ) { cfg->n_spillover_bank = atoi(rvalue); } else if (strncmp(keyword, "n_one_cred_max_bank", FN_SZ-1) == 0 ) { cfg->n_one_cred_max_bank = atoi(rvalue); } else if (strncmp(keyword, "n_two_cred_max_bank", FN_SZ-1) == 0 ) { cfg->n_two_cred_max_bank = atoi(rvalue); } else if (strncmp(keyword, "n_spillover_max_bank", FN_SZ-1) == 0 ) { cfg->n_spillover_max_bank = atoi(rvalue); } else if (strncmp(keyword, "one_cred_db_base", FN_SZ-1) == 0) { cfg->one_cred_db_base_fn = strdup(rvalue); } else if (strncmp(keyword, "two_cred_db_base", FN_SZ-1) == 0) { cfg->two_cred_db_base_fn = strdup(rvalue); } else if (strncmp(keyword, "spillover_db_base", FN_SZ-1) == 0) { cfg->spillover_db_base_fn = strdup(rvalue); } else if (strncmp(keyword, "db_suffix", FN_SZ-1) == 0) { cfg->db_fn_suffix = strdup(rvalue); } else if (strncmp(keyword, "ruleparam_db", FN_SZ-1) == 0) { cfg->ruleparam_db_fn = strdup(rvalue); } else if (strncmp(keyword, "high_watermark_threshold", FN_SZ-1) == 0) { cfg->high_watermark_threshold = atof(rvalue); } else if (strncmp(keyword, "low_watermark_threshold", FN_SZ-1) == 0) { cfg->low_watermark_threshold = atof(rvalue); } } fclose(fp); if (!cfg->ruleparam_db_fn) cfg->ruleparam_db_fn = strdup( RULEPARAM_DB_FILE ); // If there were any errors, bail out // if ( (cfg->hash_modulus <= 0) || (cfg->n_one_cred_max_bank <= 0) || (cfg->n_two_cred_max_bank <= 0) || (cfg->n_spillover_max_bank <= 0) || (cfg->n_one_cred_bank_size <= 0) || (cfg->n_two_cred_bank_size <= 0) || (cfg->n_spillover_bank_size <= 0) || (cfg->n_one_cred_bank <= 0) || (cfg->n_two_cred_bank <= 0) || (cfg->n_spillover_bank <= 0) || (cfg->high_watermark_threshold <= 0.0) || (cfg->high_watermark_threshold >= 1.0) || (cfg->low_watermark_threshold <= 0.0) || (cfg->low_watermark_threshold >= cfg->high_watermark_threshold) || (!cfg->one_cred_db_base_fn) || (!cfg->two_cred_db_base_fn) || (!cfg->spillover_db_base_fn) || (!cfg->db_fn_suffix) || (!cfg->ruleparam_db_fn) ) { if (cfg->one_cred_db_base_fn) free(cfg->one_cred_db_base_fn); if (cfg->two_cred_db_base_fn) free(cfg->two_cred_db_base_fn); if (cfg->spillover_db_base_fn) free(cfg->spillover_db_base_fn); if (cfg->db_fn_suffix) free(cfg->db_fn_suffix); if (cfg->ruleparam_db_fn) free(cfg->ruleparam_db_fn); return -1; } return 0; } // Dead simple config file parsing // int init_context_from_config( passdb_slim_context *ctx, char *config_fn ) { int i, r; // Don't copy new values over until we're sure config file read // was successful. Store in local variables and copy over // afterwards. // passdb_slim_config cfg; r = read_config(&cfg, config_fn); if (r<0) return r; ctx->n_one_cred_bank = cfg.n_one_cred_bank; ctx->n_two_cred_bank = cfg.n_two_cred_bank; ctx->n_spillover_bank = cfg.n_spillover_bank; ctx->n_one_cred_max_bank = cfg.n_one_cred_max_bank; ctx->n_two_cred_max_bank = cfg.n_two_cred_max_bank; ctx->n_spillover_max_bank = cfg.n_spillover_max_bank; ctx->n_one_cred_bank_size = cfg.n_one_cred_bank_size; ctx->n_two_cred_bank_size = cfg.n_two_cred_bank_size; ctx->n_spillover_bank_size = cfg.n_spillover_bank_size; ctx->hash_modulus = cfg.hash_modulus; // Get rid of stale filenames // if (ctx->one_cred_db_bank_fn) { for (i=0; in_one_cred_max_bank; i++) if (ctx->one_cred_db_bank_fn[i]) free(ctx->one_cred_db_bank_fn[i]); free(ctx->one_cred_db_bank_fn); } if (ctx->two_cred_db_bank_fn) { for (i=0; in_two_cred_max_bank; i++) if (ctx->two_cred_db_bank_fn[i]) free(ctx->two_cred_db_bank_fn[i]); free(ctx->two_cred_db_bank_fn); } if (ctx->spillover_db_bank_fn) { for (i=0; in_spillover_max_bank; i++) if (ctx->spillover_db_bank_fn[i]) free(ctx->spillover_db_bank_fn[i]); free(ctx->spillover_db_bank_fn); } if (ctx->one_cred_db_base_fn) free(ctx->one_cred_db_base_fn); if (ctx->two_cred_db_base_fn) free(ctx->two_cred_db_base_fn); if (ctx->spillover_db_base_fn) free(ctx->spillover_db_base_fn); if (ctx->db_fn_suffix) free(ctx->db_fn_suffix); if (ctx->ruleparam_db_fn) free(ctx->ruleparam_db_fn); if (ctx->logical_card_id_hash) free(ctx->logical_card_id_hash); if (ctx->rider_mag_hash) free(ctx->rider_mag_hash); if (ctx->rider_rf_hash) free(ctx->rider_rf_hash); ctx->one_cred_db_base_fn = cfg.one_cred_db_base_fn; ctx->two_cred_db_base_fn = cfg.two_cred_db_base_fn; ctx->spillover_db_base_fn = cfg.spillover_db_base_fn; ctx->db_fn_suffix = cfg.db_fn_suffix; ctx->ruleparam_db_fn = cfg.ruleparam_db_fn; ctx->high_watermark_threshold = cfg.high_watermark_threshold; ctx->low_watermark_threshold = cfg.low_watermark_threshold; //--------------------------------------- // ONE CREDENTIAL bank // - filenames // - file descriptors // - bank (memory) // // allocate all filenames, even if we don't create the actual DB files // ctx->one_cred_db_bank_fn = (char **)malloc(sizeof(char *) * (ctx->n_one_cred_max_bank)); CHECK_ALLOC_FAIL( (ctx->one_cred_db_bank_fn) ); for (i=0; in_one_cred_max_bank; i++) { ctx->one_cred_db_bank_fn[i] = (char *)malloc(sizeof(char)*FN_SZ); CHECK_ALLOC_FAIL( (ctx->one_cred_db_bank_fn[i]) ); snprintf(ctx->one_cred_db_bank_fn[i], FN_SZ, "%s%i%s", ctx->one_cred_db_base_fn, i, ctx->db_fn_suffix ); } ctx->passes_one_cred_bank_fd = (int *)malloc(sizeof(int) * ctx->n_one_cred_max_bank ); CHECK_ALLOC_FAIL( (ctx->passes_one_cred_bank_fd) ); for (i=0; in_one_cred_max_bank; i++) ctx->passes_one_cred_bank_fd[i] = -1; ctx->rider_one_cred_bank = (void **)malloc(sizeof(void *) * ctx->n_one_cred_max_bank ); CHECK_ALLOC_FAIL( (ctx->rider_one_cred_bank) ); for (i=0; in_one_cred_max_bank; i++) ctx->rider_one_cred_bank[i] = NULL; //--------------------------------------- // TWO CREDENTIAL bank // - filenames // - file descriptors // - bank (memory) // // allocate all filenames, even if we don't create the actual DB files // ctx->two_cred_db_bank_fn = (char **)malloc(sizeof(char *) * (ctx->n_two_cred_max_bank)); CHECK_ALLOC_FAIL( (ctx->two_cred_db_bank_fn) ); for (i=0; in_two_cred_max_bank; i++) { ctx->two_cred_db_bank_fn[i] = (char *)malloc(sizeof(char)*FN_SZ); CHECK_ALLOC_FAIL( (ctx->two_cred_db_bank_fn[i]) ); snprintf(ctx->two_cred_db_bank_fn[i], FN_SZ, "%s%i%s", ctx->two_cred_db_base_fn, i, ctx->db_fn_suffix ); } ctx->passes_two_cred_bank_fd = (int *)malloc(sizeof(int) * ctx->n_two_cred_max_bank ); CHECK_ALLOC_FAIL( (ctx->passes_two_cred_bank_fd) ); for (i=0; in_two_cred_max_bank; i++) ctx->passes_two_cred_bank_fd[i] = -1; ctx->rider_two_cred_bank = (void **)malloc(sizeof(void *) * ctx->n_two_cred_max_bank ); CHECK_ALLOC_FAIL( (ctx->rider_two_cred_bank) ); for (i=0; in_two_cred_max_bank; i++) ctx->rider_two_cred_bank[i] = NULL; //--------------------------------------- // SPILLOVER // - filenames // - file descriptors // - bank (memory) // // allocate all filenames, even if we don't create the actual DB files // ctx->spillover_db_bank_fn = (char **)malloc(sizeof(char *) * (ctx->n_spillover_max_bank)); CHECK_ALLOC_FAIL( (ctx->spillover_db_bank_fn) ); for (i=0; in_spillover_max_bank; i++) { ctx->spillover_db_bank_fn[i] = (char *)malloc(sizeof(char)*FN_SZ); CHECK_ALLOC_FAIL( (ctx->spillover_db_bank_fn[i]) ); snprintf(ctx->spillover_db_bank_fn[i], FN_SZ, "%s%i%s", ctx->spillover_db_base_fn, i, ctx->db_fn_suffix ); } ctx->passes_spillover_bank_fd = (int *)malloc(sizeof(int) * ctx->n_spillover_max_bank ); CHECK_ALLOC_FAIL( (ctx->passes_spillover_bank_fd) ); for (i=0; in_spillover_max_bank; i++) ctx->passes_spillover_bank_fd[i] = -1; ctx->rider_spillover_bank = (void **)malloc(sizeof(void *) * ctx->n_spillover_max_bank ); CHECK_ALLOC_FAIL( (ctx->rider_spillover_bank) ); for (i=0; in_spillover_max_bank; i++) ctx->rider_spillover_bank[i] = NULL; ctx->logical_card_id_hash = (rider_node **)malloc(sizeof(rider_node *) * ctx->hash_modulus ); CHECK_ALLOC_FAIL( (ctx->logical_card_id_hash) ); ctx->rider_mag_hash = (rider_node **)malloc(sizeof(rider_node *) * ctx->hash_modulus ); CHECK_ALLOC_FAIL( (ctx->rider_mag_hash) ); ctx->rider_rf_hash = (rider_node **)malloc(sizeof(rider_node *) * ctx->hash_modulus ); CHECK_ALLOC_FAIL( (ctx->rider_rf_hash) ); for (i=0; ihash_modulus; i++) { ctx->logical_card_id_hash[i] = NULL; ctx->rider_mag_hash[i] = NULL; ctx->rider_rf_hash[i] = NULL; } return 0; }