/* WARNING: This file was generated by dkct. Changes you make here will be lost if dkct is run again! You should modify the original source and run dkct on it. Original source: dkt-crp.ctr */ /* Copyright (C) 2011-2013, Dirk Krause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above opyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 COPYRIGHT OWNER OR CONTRIBUTORS 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. */ /** @file dkt-crp.c The dkt-crp module. */ #line 10 "dkt-crp.ctr" #include "dk3all.h" #include "dkt.h" #line 17 "dkt-crp.ctr" /** Range (used for length, number of digits, number of special characters and number of upper-case characters. */ typedef struct { size_t min; /**< Minimum value. */ size_t max; /**< Maximum value. */ } DKT_PW_RANGE; /** Password class definition. */ typedef struct { dkChar const *name; /**< Password class name. */ int type; /**< Password type (DKT_PWCLASS_xxx). */ DKT_PW_RANGE lgt; /**< Length. */ DKT_PW_RANGE dig; /**< Number of digits. */ DKT_PW_RANGE spc; /**< Number of special characters. */ DKT_PW_RANGE upp; /**< Number of upper-case characters. */ } DKT_PW_CL; /** Job structure for dkt createp. */ typedef struct { dk3_app_t *app; /**< Application. */ dk3_option_set_t *opt; /**< Option set. */ dkChar const * const *msg; /**< Localized messages. */ dkChar const * const *kwnl; /**< Keywords, not localized. */ int exval; /**< Exit status code. */ dk3_sto_t *s_cl; /**< Password classes storage. */ dk3_sto_it_t *i_cl; /**< Password classes iterator. */ DKT_PW_CL pwcl; /**< Password class. */ } DKT_CRP_J; /** Options. */ static dk3_option_t const dkt_crp_options[] = { { dkT('R'), dkT("reset"), 0 }, { dkT('t'), dkT("type"), 1 }, { dkT('l'), dkT("length"), 1 }, { dkT('d'), dkT("digits"), 1 }, { dkT('s'), dkT("specials"), 1 }, { dkT('u'), dkT("upper-case"), 1 }, { dkT('c'), dkT("class"), 1 } }; /** Number of options in the dkt_crp_options array. */ static size_t const dkt_crp_szoptions = sizeof(dkt_crp_options)/sizeof(dk3_option_t); /** Long options for dkt createp. */ static dkChar const * const dkt_crp_long_options[] = { dkT("reset"), dkT("class"), NULL }; /** Keywords in a class configuration. */ static dkChar const * const dkt_crp_class_kw[] = { dkT("type"), /* 0 */ dkT("length"), /* 1 */ dkT("digits"), /* 2 */ dkT("specials"), /* 3 */ dkT("upper-case"), /* 4 */ NULL }; /** Password types. */ static dkChar const * const dkt_crp_password_types[] = { dkT("simple"), dkT("hex"), dkT("ascii-85"), dkT("h"), dkT("a85"), dkT("ascii85"), NULL }; /** Character pools for characters, digits, specials and upper-case. */ static char const * const dkt_crp_char_pools[] = { /* 0 */ "abcdefghijklmnopqrstuvwxyz", /* 1 */ "01234567890", /* 2 */ "^!\"$%&()[]{}=?\\+-*/#~_.,:;<>|", /* 3 */ "ABCDEFGHIJKLMNOPQRSTUVWXYZ", NULL }; /** Compare two class entries. @param l Left entry. @param r Right entry. @param cr Comparison criteria (0=class/class, 1=class/name). @return Comparison result. */ static int dkt_crp_class_compare(void *l, void *r, int cr) { int back = 0; DKT_PW_CL *pl = NULL; DKT_PW_CL *pr = NULL; pl = (DKT_PW_CL *)l; pr = (DKT_PW_CL *)r; if(l) { if(r) { switch(cr) { case 1: { if(pl->name) { back = dk3str_cmp(pl->name, (dkChar const *)r); } else { back = -1; } } break; default: { if(pl->name) { if(pr->name) { back = dk3str_cmp(pl->name, pr->name); } else { back = 1; } } else { if(pr->name) { back = -1; } } } break; } } else { back = 1;} } else { if(r) { back = -1; } } if(back < -1) { back = -1; } if(back > 1) { back = 1; } return back; } /** Delete class entry, release memory. @param cl Class entry to delete. */ static void dkt_crp_class_delete(DKT_PW_CL *cl) { if(cl) { #line 178 "dkt-crp.ctr" dk3_release(cl->name) dk3_delete(cl); } } /** Initialize class entry. @param cl Entry to initialize. */ static void dkt_crp_class_init_empty(DKT_PW_CL *cl) { cl->name = NULL; cl->type = DKT_PWCLASS_SIMPLE; (cl->lgt).min = 6; (cl->lgt).max = 8; (cl->dig).min = 1; (cl->dig).max = 2; (cl->spc).min = 1; (cl->spc).max = 2; (cl->upp).min = 1; (cl->upp).max = 2; #line 198 "dkt-crp.ctr" } /** Create new class entry, allocate memory. @param cn Class name. @param app Application structure for diagnostics. @return Pointer to new entry on success, NULL on error. */ static DKT_PW_CL * dkt_crp_class_new(dkChar *cn, dk3_app_t *app) { DKT_PW_CL *back = NULL; #line 213 "dkt-crp.ctr" if(cn) { back = dk3_new_app(DKT_PW_CL,1,app); if(back) { dkt_crp_class_init_empty(back); back->name = dk3str_dup_app(cn, app); if(!(back->name)) { dkt_crp_class_delete(back); back = NULL; } } } #line 223 "dkt-crp.ctr" return back; } /** Set a range. @param j Job structure. @param ra Range to set up. @param v Text containing the values for range. @param verb Flag: Verbose. @return 1 on success, 0 on error. */ static int dkt_crp_set_range(DKT_CRP_J *j, DKT_PW_RANGE *ra, dkChar *v, int verb) { int back = 0; dkChar *p1 = NULL; /* Start of text. */ dkChar *p2 = NULL; /* End of range. */ unsigned u = 0; /* Used by sscanf(). */ #line 244 "dkt-crp.ctr" p1 = dk3str_start(v, NULL); if(p1) { p2 = dk3str_chr(p1, dkT('-')); if(p2) { *(p2++) = dkT('\0'); p2 = dk3str_start(p2, NULL); } dk3str_chomp(p1, NULL); if(dk3sf_sscanf3(p1, dkT("%u"), &u) == 1) { back = 1; ra->min = (size_t)u; ra->max = ra->min; if(p2) { back = 0; if(dk3sf_sscanf3(p2, dkT("%u"), &u) == 1) { back = 1; ra->max = (size_t)u; } else { if(verb) { /* ERROR: Not numeric! */ dk3app_log_i3(j->app, DK3_LL_ERROR, 141, 142, p2); } } } } else { if(verb) { /* ERROR: Not numeric! */ dk3app_log_i3(j->app, DK3_LL_ERROR, 141, 142, p1); } } } else { if(verb) { /* ERROR: Empty interval */ dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 40); } } #line 280 "dkt-crp.ctr" return back; } /** Set type for a password class. @param j job structure. @param cl Class to modify. @param v Text containing the type. @param verb Flag: Verbose. @return 1 on success, 0 on error. */ static int dkt_crp_set_type(DKT_CRP_J *j, DKT_PW_CL *cl, dkChar const *v, int verb) { int back = 0; #line 298 "dkt-crp.ctr" switch(dk3str_array_index(dkt_crp_password_types, v, 0)) { case 0: { cl->type = DKT_PWCLASS_SIMPLE; back = 1; } break; case 1: case 3: { cl->type = DKT_PWCLASS_HEX; back = 1; } break; case 2: case 4: case 5: { cl->type = DKT_PWCLASS_A85; back = 1; } break; default: { if(verb) { /* ERROR: Unknown type! */ dk3app_log_3(j->app, DK3_LL_ERROR, j->msg, 41, 42, v); } } break; } #line 318 "dkt-crp.ctr" return back; } /** Apply a key/value pair to a class entry. @param j Job structure. @param cl Class to modify. @param k Key. @param v Value. @return 1 on success, 0 on error. */ static int dkt_crp_class_apply_kv(DKT_CRP_J *j, DKT_PW_CL *cl, dkChar *k, dkChar *v) { int back = 0; #line 336 "dkt-crp.ctr" switch(dk3str_array_index(dkt_crp_class_kw, k, 0)) { case 0: { back = dkt_crp_set_type(j, cl, v, 0); } break; case 1: { back = dkt_crp_set_range(j, &(cl->lgt), v, 0); } break; case 2: { back = dkt_crp_set_range(j, &(cl->dig), v, 0); } break; case 3: { back = dkt_crp_set_range(j, &(cl->spc), v, 0); } break; case 4: { back = dkt_crp_set_range(j, &(cl->upp), v, 0); } break; } #line 353 "dkt-crp.ctr" return back; } /** Configure a class. @param j Job structure. @param cl Class to modify. @param il Input line, contains comma-separated key/value pairs. @return 1 on success, 0 on error. */ static int dkt_crp_class_configure(DKT_CRP_J *j, DKT_PW_CL *cl, dkChar *il) { int back = 1; dkChar *p1 = NULL; /* Current key/value pair. */ dkChar *p2 = NULL; /* Next key/value pair (if any). */ dkChar *p3 = NULL; /* Value pointer. */ #line 373 "dkt-crp.ctr" p1 = il; while(p1) { p2 = dk3str_chr(p1, dkT(',')); if(p2) { *(p2++) = dkT('\0'); p2 = dk3str_start(p2, NULL); } dk3str_chomp(p1, NULL); p3 = dk3str_chr(p1, dkT('=')); if(p3) { *(p3++) = dkT('\0'); p3 = dk3str_start(p3, NULL); if(p3) { p1 = dk3str_start(p1, NULL); if(p1) { dk3str_chomp(p1, NULL); dk3str_chomp(p3, NULL); if(!dkt_crp_class_apply_kv(j, cl, p1, p3)) { back = 0; } } else { /* ERROR: Syntax! */ back = 0; } } else { /* ERROR: Syntax! */ back = 0; } } else { /* ERROR: Syntax! */ back = 0; } p1 = p2; } #line 407 "dkt-crp.ctr" return back; } /** Process one line describing a class. @param j Job structure. @param il Input line to process. @return 1 on success, 0 on error. */ static int dkt_crp_class_data(DKT_CRP_J *j, dkChar const *il) { int back = 0; dkChar bu[1024]; /* Private copy. */ dkChar *p1 = NULL; /* Class name. */ dkChar *p2 = NULL; /* Start of configuration. */ DKT_PW_CL *cl = NULL; /* New class. */ #line 427 "dkt-crp.ctr" if(dk3str_len(il) < DK3_SIZEOF(bu,dkChar)) { dk3str_cpy(bu, il); p1 = dk3str_start(bu, NULL); if(p1) { p2 = dk3str_chr(p1, dkT(',')); if(p2) { *(p2++) = dkT('\0'); p1 = dk3str_start(p1, NULL); if(p1) { dk3str_chomp(p1, NULL); cl = (DKT_PW_CL *)dk3sto_it_find_like(j->i_cl, p1, 1); if(cl) { /* Warning: Overwriting existing class. */ } else { cl = dkt_crp_class_new(p1, j->app); if(cl) { if(!dk3sto_add(j->s_cl, (void *)cl)) { dkt_crp_class_delete(cl); cl = NULL; } } } if(cl) { back = dkt_crp_class_configure(j, cl, p2); } } else { /* ERROR: Empty name! */ dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 43); } } else { /* ERROR: No detail information! */ dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 44); } } else { /* ERROR: No text! */ dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 45); } } else { /* ERROR: Line too long! */ dk3app_log_3(j->app, DK3_LL_ERROR, j->msg, 46, 47, il); } #line 467 "dkt-crp.ctr" return back; } /** Reset job structure on -R or --reset. @param j Job structure. */ static void dkt_crp_job_reset(DKT_CRP_J *j) { int i = 0; for(i = 11; i <= 13; i++) { dkt_crp_class_data(j, (j->kwnl)[i]); } } /** Initialize job structure. @param j Job structure. @param app Application structure. */ static void dkt_crp_job_init(DKT_CRP_J *j, dk3_app_t *app) { j->app = NULL; j->msg = NULL; j->kwnl = NULL; j->opt = NULL; j->exval = DKT_RESULT_ERR_UNSPECIFIC; j->s_cl = NULL; j->i_cl = NULL; j->s_cl = dk3sto_open_app(app); dkt_crp_class_init_empty(&(j->pwcl)); if(j->s_cl) { dk3sto_set_comp(j->s_cl, dkt_crp_class_compare, 0); j->i_cl = dk3sto_it_open(j->s_cl); } #line 504 "dkt-crp.ctr" } /** Clean up job structure. @param j Job structure to clean up. */ static void dkt_crp_job_cleanup(DKT_CRP_J *j) { DKT_PW_CL *cl = NULL; if(j->opt) { dk3opt_close(j->opt); } j->opt = NULL; if(j->s_cl) { if(j->i_cl) { dk3sto_it_reset(j->i_cl); while((cl = (DKT_PW_CL *)dk3sto_it_next(j->i_cl)) != NULL) { dkt_crp_class_delete(cl); } dk3sto_it_close(j->i_cl); } j->i_cl = NULL; dk3sto_close(j->s_cl); } j->s_cl = NULL; #line 530 "dkt-crp.ctr" } /** Process one key/value pair. @param jv Pointer to job structure casted to void *. @param k Key. @param v Value. @return 1 to indicate success. */ static int dkt_crp_conf_line(void *jv, dkChar const *k, dkChar const *v) { int back = 0; #line 546 "dkt-crp.ctr" switch(dk3str_array_index(dkt_crp_long_options, v, 0)) { case 0: { /* reset */ dkt_crp_job_reset((DKT_CRP_J *)jv); back = 1; } break; case 1: { /* class */ if(v) { back = dkt_crp_class_data((DKT_CRP_J *)jv, v); } } break; } #line 557 "dkt-crp.ctr" return back; } /** Fill a range from command line options. @param j Job structure. @param r Range to set up. @param c Command line option char. @return 1 on success, 0 on error. */ static int dkt_crp_set_range_from_arg(DKT_CRP_J *j, DKT_PW_RANGE *r, dkChar c) { int back = 1; dkChar bu[1024]; /* Private copy of command line argument. */ dkChar const *arg = NULL; /* Command line argument. */ #line 576 "dkt-crp.ctr" if(dk3opt_is_set(j->opt, c)) { arg = dk3opt_get_short_arg(j->opt, c); if(arg) { if(dk3str_len(arg) < DK3_SIZEOF(bu,dkChar)) { dk3str_cpy(bu, arg); back = dkt_crp_set_range(j, r, bu, 1); if(!back) { #line 583 "dkt-crp.ctr" back = 0; j->exval = DKT_RESULT_ERR_OPTION; } } else { #line 586 "dkt-crp.ctr" back = 0; j->exval = DKT_RESULT_ERR_OPTION; /* ERROR: Option too long! */ dk3app_log_i3(j->app, DK3_LL_ERROR, 135, 136, arg); } } else { #line 591 "dkt-crp.ctr" back = 0; j->exval = DKT_RESULT_ERR_OPTION; } } #line 594 "dkt-crp.ctr" return back; } /** Process command line arguments and options. @param j Job structure. @return 1 on success, 0 on error. */ static int dkt_crp_process_arguments(DKT_CRP_J *j) { int back = 0; int xargc = 0; /* Number of command line arguments. */ dkChar const *arg = NULL; /* Argument. */ dkChar const * const *xargv = NULL; /* Command line arguments array. */ DKT_PW_CL *cl = NULL; /* Class. */ size_t sz = 0; /* Variable to check ranges. */ xargc = dk3app_get_argc(j->app); xargv = dk3app_get_argv(j->app); xargv++; xargv++; xargc--; xargc--; #line 617 "dkt-crp.ctr" j->opt = dk3opt_open_app( dkt_crp_options, dkt_crp_szoptions, dkT('\0'), NULL, xargc, xargv, j->app ); if(j->opt) { if(0 == dk3opt_get_error_code(j->opt)) { back = 1; if(dk3opt_is_set(j->opt, dkT('R'))) { dkt_crp_job_reset(j); } if(dk3opt_is_set(j->opt, dkT('c'))) { arg = dk3opt_get_short_arg(j->opt, dkT('c')); if(arg) { cl = (DKT_PW_CL *)dk3sto_it_find_like(j->i_cl, (void *)arg, 1); if(cl) { dk3mem_cpy((void *)(&(j->pwcl)), (void *)cl, sizeof(DKT_PW_CL)); } else { #line 639 "dkt-crp.ctr" back = 0; j->exval = DKT_RESULT_ERR_OPTION; /* ERROR: No such class! */ dk3app_log_3(j->app, DK3_LL_ERROR, j->msg, 48, 49, arg); } } else { #line 644 "dkt-crp.ctr" back = 0; j->exval = DKT_RESULT_ERR_OPTION; } } else { cl = (DKT_PW_CL *)dk3sto_it_find_like( j->i_cl, (void *)((j->kwnl)[14]), 1 ); if(cl) { dk3mem_cpy((void *)(&(j->pwcl)), (void *)cl, sizeof(DKT_PW_CL)); } else { #line 653 "dkt-crp.ctr" back = 0; j->exval = DKT_RESULT_ERR_OPTION; /* ERROR: No such class! */ dk3app_log_3(j->app, DK3_LL_ERROR, j->msg, 48, 49, (j->kwnl)[14]); } } if(dk3opt_is_set(j->opt, dkT('t'))) { arg = dk3opt_get_short_arg(j->opt, dkT('t')); if(arg) { if(!dkt_crp_set_type(j, &(j->pwcl), arg, 1)) { back = 0; j->exval = DKT_RESULT_ERR_OPTION; #line 663 "dkt-crp.ctr" } } else { #line 665 "dkt-crp.ctr" back = 0; j->exval = DKT_RESULT_ERR_OPTION; } } if(!dkt_crp_set_range_from_arg(j, &((j->pwcl).lgt), dkT('l'))) { back = 0; #line 670 "dkt-crp.ctr" } if(!dkt_crp_set_range_from_arg(j, &((j->pwcl).dig), dkT('d'))) { back = 0; #line 673 "dkt-crp.ctr" } if(!dkt_crp_set_range_from_arg(j, &((j->pwcl).spc), dkT('s'))) { back = 0; #line 676 "dkt-crp.ctr" } if(!dkt_crp_set_range_from_arg(j, &((j->pwcl).upp), dkT('u'))) { back = 0; #line 679 "dkt-crp.ctr" } #line 681 "dkt-crp.ctr" #line 682 "dkt-crp.ctr" #line 683 "dkt-crp.ctr" #line 684 "dkt-crp.ctr" #line 685 "dkt-crp.ctr" if((j->pwcl).lgt.max >= (j->pwcl).lgt.min) { if((j->pwcl).lgt.max < DKT_PASSWORD_MAXLENGTH) { if((j->pwcl).type == DKT_PWCLASS_SIMPLE) { if((j->pwcl).dig.max >= (j->pwcl).dig.min) { if((j->pwcl).spc.max >= (j->pwcl).spc.min) { if((j->pwcl).upp.max >= (j->pwcl).upp.min) { sz = (j->pwcl).upp.max + (j->pwcl).spc.max + (j->pwcl).dig.max; #line 693 "dkt-crp.ctr" if(sz > (j->pwcl).lgt.min) { #line 694 "dkt-crp.ctr" /* ERROR: Inconsistency! */ back = 0; j->exval = DKT_RESULT_ERR_OPTION; dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 50); } } else { #line 699 "dkt-crp.ctr" /* ERROR: Bad uppercase range! */ back = 0; j->exval = DKT_RESULT_ERR_OPTION; dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 51); } } else { #line 704 "dkt-crp.ctr" /* ERROR: Bad specials range! */ back = 0; j->exval = DKT_RESULT_ERR_OPTION; dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 52); } } else { #line 709 "dkt-crp.ctr" /* ERROR: Bad digits range! */ back = 0; j->exval = DKT_RESULT_ERR_OPTION; dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 53); } } } else { #line 715 "dkt-crp.ctr" /* ERROR: Password length too large! */ back = 0; j->exval = DKT_RESULT_ERR_OPTION; dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 55); } } else { #line 720 "dkt-crp.ctr" /* ERROR: Bad length range! */ dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 54); back = 0; j->exval = DKT_RESULT_ERR_OPTION; } } else { j->exval = DKT_RESULT_ERR_OPTION; } } else { j->exval = DKT_RESULT_ERR_OPTION; } #line 731 "dkt-crp.ctr" return back; } /** Produce ASCII-85 password. @param j Job structure. */ static void dkt_crp_run_a85(DKT_CRP_J *j) { char tb[DKT_PASSWORD_MAXLENGTH + 20]; char bb[((4 * DKT_PASSWORD_MAXLENGTH) / 5) + 6]; size_t st = 0; /* Text size for output. */ size_t sz = 0; /* Difference between min and max of range. */ size_t rb = 0; /* Number of binary random bytes to read. */ int ok = 1; /* Flag: No errors yet. */ st = (j->pwcl).lgt.min; if((j->pwcl).lgt.max > (j->pwcl).lgt.min) { sz = (j->pwcl).lgt.max - (j->pwcl).lgt.min; if(dk3app_rand_bytes(j->app, (void *)(&rb), sizeof(size_t)) == sizeof(size_t) ) { st = st + (rb % sz); } else { ok = 0; j->exval = DKT_RESULT_ERR_PRNG; } } if(ok) { sz = ((4 * st) / 5) + 1; if(dk3app_rand_bytes(j->app, (void *)bb, sz) == sz) { if(dk3enc_bin_to_ra85_app( tb, sizeof(tb), bb, sz, j->app)) { tb[st] = '\0'; dk3sf_initialize_stdout(); #if DK3_CHAR_SIZE > 1 for(rb = 0; rb < st; rb++) { dk3sf_fputc((((dkChar)(tb[rb])) & 0x00FFU), stdout); } dk3sf_fputc(dkT('\n'), stdout); #else fputs(tb, stdout); fputc('\n', stdout); #endif } else { j->exval = DKT_RESULT_ERR_UNSPECIFIC; } } else { j->exval = DKT_RESULT_ERR_PRNG; } } } /** Produce hex password. @param j Job structure. */ static void dkt_crp_run_hex(DKT_CRP_J *j) { char tb[DKT_PASSWORD_MAXLENGTH + 20]; char bb[(DKT_PASSWORD_MAXLENGTH / 2) + 5]; size_t st = 0; /* Text size for output. */ size_t sz = 0; /* Size for binary data. */ size_t rb = 0; /* Loop through result. */ int ok = 1; /* Flag: Everything ok. */ st = (j->pwcl).lgt.min; if((j->pwcl).lgt.max > (j->pwcl).lgt.min) { sz = (j->pwcl).lgt.max - (j->pwcl).lgt.min; if(dk3app_rand_bytes(j->app, (void *)(&rb), sizeof(size_t)) == sizeof(size_t) ) { st = st + (rb % sz); } else { ok = 0; j->exval = DKT_RESULT_ERR_PRNG; } } if(ok) { sz = (st / 2) + 1; if(dk3app_rand_bytes(j->app, (void *)bb, sz) == sz) { if(dk3enc_bin_to_hex_app(tb, sizeof(tb), bb, sz, j->app)) { tb[st] = '\0'; dk3sf_initialize_stdout(); #if DK3_CHAR_SIZE > 1 for(rb = 0; rb < st; rb++) { dk3sf_fputc((((dkChar)(tb[rb])) & 0x00FFU), stdout); } dk3sf_fputc(dkT('\n'), stdout); #else fputs(tb, stdout); fputc('\n', stdout); #endif } else { j->exval = DKT_RESULT_ERR_UNSPECIFIC; } } else { j->exval = DKT_RESULT_ERR_PRNG; } } } /** Choose a random value from a range. @param j Job structure. @param r Range. @param ok Pointer to OK-flag variable. @return Value from range. */ static size_t dkt_crp_get_value_from_range(DKT_CRP_J *j, DKT_PW_RANGE *r, int *ok) { size_t back = 0; size_t val = 0; back = r->min; if((r->max) > (r->min)) { if(dk3app_rand_bytes(j->app, (void *)(&val), sizeof(size_t)) == sizeof(size_t) ) { back = back + (val % ((r->max) - (r->min))); } else { *ok = 0; /* ERROR: Failed to obtain random bytes! */ j->exval = DKT_RESULT_ERR_PRNG; } } return back; } /** Set entries in the type character array. @param j Job structure. @param ty Type character array. @param in Index array. @param kc Key character to set. @param np Number of positions to set. @param pa Positions available. @param ok Pointer to ok-flag variable. */ static void dkt_crp_ct( DKT_CRP_J *j, char *ty, size_t *in, char kc, size_t np, size_t *pa, int *ok ) { size_t ri = 0; /* Random index into the in[0...*pa] array. */ size_t i = 0; /* Pass number, 0 ... (np-1). */ size_t k = 0; /* Index of current index to copy. */ size_t numcopy = 0; /* Number of indexes to copy. */ #line 899 "dkt-crp.ctr" for(i = 0; ((i < np) && ((*pa) > 0) && (*ok)); i++) { #line 901 "dkt-crp.ctr" if(dk3app_rand_bytes(j->app,(void *)(&ri),sizeof(size_t)) == sizeof(size_t)) { ri = (ri % (*pa)); #line 904 "dkt-crp.ctr" ty[ in[ri] ] = kc; #line 905 "dkt-crp.ctr" numcopy = (*pa) - ri - 1; #line 906 "dkt-crp.ctr" if(numcopy > 0) { for(k = 0; k < numcopy; k++) { in[ri + k] = in[ri + k + 1]; } } *pa = *pa - 1; #line 912 "dkt-crp.ctr" } else { *ok = 0; j->exval = DKT_RESULT_ERR_PRNG; } } #line 919 "dkt-crp.ctr" } /** Find one character of a given type. @param j Job structure. @param bu Buffer to fill. @param ty Buffer of type indicators already filled. @param i Index of character in bu to fill. @param ok Pointer to OK-flag variable. */ static void dkt_crp_find_char(DKT_CRP_J *j, char *bu, char *ty, size_t i, int *ok) { char const *poolptr = NULL; /* Pointer to character pool string. */ size_t poollgt = 0; /* Length of the pool string. */ size_t ri = 0; /* Random index into pool string. */ #line 938 "dkt-crp.ctr" poolptr = dkt_crp_char_pools[0]; #line 939 "dkt-crp.ctr" switch(ty[i]) { case 0x01: { poolptr = dkt_crp_char_pools[1]; } break; case 0x02: { poolptr = dkt_crp_char_pools[2]; } break; case 0x03: { poolptr = dkt_crp_char_pools[3]; } break; } poollgt = dk3str_c8_len(poolptr); if(dk3app_rand_bytes(j->app, (void *)(&ri), sizeof(size_t)) == sizeof(size_t)) { ri = (ri % poollgt); bu[i] = poolptr[ri]; #line 949 "dkt-crp.ctr" } else { *ok = 0; j->exval = DKT_RESULT_ERR_PRNG; } #line 955 "dkt-crp.ctr" } /** Produce a simple password. @param j Job structure. */ static void dkt_crp_run_simple(DKT_CRP_J *j) { size_t st = 0; /* Text size for output. */ size_t sd = 0; /* Number of digits. */ size_t ss = 0; /* Number of special characters. */ size_t su = 0; /* Number of upper-case characters. */ size_t posav = 0; /* Number of positions available. */ int ok = 1; /* Flag: Everything ok. */ char bu[DKT_PASSWORD_MAXLENGTH]; char ty[DKT_PASSWORD_MAXLENGTH]; size_t in[DKT_PASSWORD_MAXLENGTH]; size_t i = 0; /* Index of current output character. */ /* Find length values. */ st = dkt_crp_get_value_from_range(j, &((j->pwcl).lgt), &ok); sd = dkt_crp_get_value_from_range(j, &((j->pwcl).dig), &ok); ss = dkt_crp_get_value_from_range(j, &((j->pwcl).spc), &ok); su = dkt_crp_get_value_from_range(j, &((j->pwcl).upp), &ok); posav = st; if(ok) { /* Initialize buffers. */ for(i = 0; i < DKT_PASSWORD_MAXLENGTH; i++) { bu[i] = '\0'; ty[i] = '\0'; in[i] = i; } /* Find character types. */ dkt_crp_ct(j, ty, in, 0x01, sd, &posav, &ok); dkt_crp_ct(j, ty, in, 0x02, ss, &posav, &ok); dkt_crp_ct(j, ty, in, 0x03, su, &posav, &ok); if(ok) { /* Get the random characters. */ for(i = 0; i < st; i++) { dkt_crp_find_char(j, bu, ty, i, &ok); } bu[st] = '\0'; if(ok) { /* Write output. */ dk3sf_initialize_stdout(); #if DK3_CHAR_SIZE > 1 for(i = 0; i < st; i++) { dk3sf_fputc((dkChar)(bu[i]), stdout); } dk3sf_fputc(dkT('\n'), stdout); #else fputs(bu, stdout); fputc('\n', stdout); #endif } } else { } } else { } } /** Create password. @param j Job structure. */ static void dkt_crp_run(DKT_CRP_J *j) { #line 1036 "dkt-crp.ctr" if(dk3app_rand_init(j->app, NULL)) { switch((j->pwcl).type) { case DKT_PWCLASS_A85: { dkt_crp_run_a85(j); } break; case DKT_PWCLASS_HEX: { dkt_crp_run_hex(j); } break; default: { dkt_crp_run_simple(j); } break; } dk3app_rand_end(j->app); } else { j->exval = DKT_RESULT_ERR_PRNG; } #line 1053 "dkt-crp.ctr" } int dkt_crp( dk3_app_t *app, dkChar const *sn, dkChar const * const *msg, dkChar const * const *kwnl ) { int back = DKT_RESULT_ERR_UNSPECIFIC; int ok = 1; int i; DKT_CRP_J j; #line 1070 "dkt-crp.ctr" dkt_crp_job_init(&j, app); j.app = app; j.msg = msg; j.kwnl = kwnl; if((j.s_cl) && (j.i_cl)) { for(i = 11; i <= 13; i++) { if(!dkt_crp_class_data(&j, kwnl[i])) { ok = 0; } } if(ok) { dkt_tool_read_conf(app, sn, (void *)(&j), dkt_crp_conf_line); if(dkt_crp_process_arguments(&j)) { j.exval = DKT_RESULT_OK; dkt_crp_run(&j); } } } back = j.exval; dkt_crp_job_cleanup(&j); #line 1089 "dkt-crp.ctr" return back; } /* vim: set ai sw=2 : */