diff options
Diffstat (limited to 'support/dktools/dk3appr.c')
-rw-r--r-- | support/dktools/dk3appr.c | 857 |
1 files changed, 857 insertions, 0 deletions
diff --git a/support/dktools/dk3appr.c b/support/dktools/dk3appr.c new file mode 100644 index 0000000000..ae661e85c4 --- /dev/null +++ b/support/dktools/dk3appr.c @@ -0,0 +1,857 @@ +/* + 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: dk3appr.ctr +*/ + +/* +Copyright (C) 2011-2017, 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 dk3appr.c The dk3appr module. +*/ + + +#line 10 "dk3appr.ctr" + +#include "dk3all.h" + +#if DK3_HAVE_OPENSSL_RAND_H +#include <openssl/rand.h> +#endif + +#if DK3_ON_WINDOWS +#include <wincrypt.h> +#endif + + + + +#line 22 "dk3appr.ctr" + + + +/** Names for the PRNG types. +*/ +static dkChar const * const dk3app_prng_type_names[] = { +/* 0 */ dkT("openssl"), /* OpenSSL PRNG. */ +/* 1 */ dkT("random"), /* initstate()/setstate()/random() */ +/* 2 */ dkT("rand48"), /* lrand48(). */ +/* 3 */ dkT("simple"), /* srand()/rand(). */ +NULL +}; + +int +dk3app_get_allowed_prng_types(dk3_app_t *app, dkChar const *il) +{ + int back = 0; + dkChar buffer[256]; + dkChar *p1 = NULL; + dkChar *p2 = NULL; + int i = 0; + + +#line 44 "dk3appr.ctr" + if((app) && (il)) { + if(dk3str_len(il) < DK3_SIZEOF(buffer,dkChar)) { + dk3str_cpy_not_overlapped(buffer, il); + p1 = dk3str_start(buffer, NULL); + while(p1) { + p2 = dk3str_chr(p1, dkT(',')); + if(p2) { + *(p2++) = dkT('\0'); p2 = dk3str_start(p2, NULL); + } + i = dk3str_array_index(dk3app_prng_type_names, p1, 0); + switch(i) { + case 0: { +#if DK3_HAVE_OPENSSL_RAND_H + back |= DK3_PRNG_OPENSSL; +#else + /* ERROR: Openssl PRNG not available! */ + dk3app_log_i1(app, DK3_LL_ERROR, 192); +#endif + } break; + case 1: { +#if DK3_HAVE_INITSTATE && DK3_HAVE_SETSTATE && DK3_HAVE_RANDOM + back |= DK3_PRNG_STATE; +#else + /* ERROR: initstate()/setstate()/random() not available. */ + dk3app_log_i1(app, DK3_LL_ERROR, 191); +#endif + } break; + case 2: { +#if DK3_HAVE_NRAND48 && DK3_HAVE_LRAND48 + back |= DK3_PRNG_RAND48; +#else + /* ERROR: lrand48()/lrand48() not available. */ + dk3app_log_i1(app, DK3_LL_ERROR, 190); +#endif + } break; + case 3: { +#if DK3_HAVE_RAND && DK3_HAVE_SRAND + back |= DK3_PRNG_SIMPLE; +#else + /* ERROR: srand()/rand() not available! */ + dk3app_log_i1(app, DK3_LL_ERROR, 189); +#endif + } break; + default: { + /* Unknown PRNG type name! */ + dk3app_log_i3(app, DK3_LL_ERROR, 187, 188, p1); + } break; + } + p1 = p2; + } + } else { + /* ERROR: Line too long for buffer! */ + dk3app_log_i1(app, DK3_LL_ERROR, 38); + } + } + +#line 99 "dk3appr.ctr" + return back; +} + + + +/** Find allowed PRNG types using preferences. + @param app Application structure. + @return Or-combination of DK3_PRNG_xxx. +*/ +static +int +dk3app_rand_find_allowed_types(dk3_app_t *app) +{ + int back = DK3_PRNG_ALL; + dkChar buffer[256]; + + +#line 115 "dk3appr.ctr" + if(dk3app_get_pref( + app,dk3app_not_localized(37),buffer,DK3_SIZEOF(buffer,dkChar)) + ) + { + +#line 119 "dk3appr.ctr" + back = dk3app_get_allowed_prng_types(app, buffer); + } + +#line 121 "dk3appr.ctr" + return back; +} + + + +/** Get bytes to seed random number generator. + @param app Application structure. + @param dp Destination buffer pointer. + @param sz Number of bytes required. + @param fn File name for seed file. + @return Number of bytes found. +*/ +static +size_t +dk3app_read_bytes_from_file( + dk3_app_t *app, + void *dp, + size_t sz, + dkChar const *fn +) +{ + size_t back = 0; + FILE *fipo; + + +#line 145 "dk3appr.ctr" + fipo = dk3sf_fopen_app(fn, dk3app_not_localized(36), app); + if(fipo) { + back = dk3sf_fread_app(dp, 1, sz, fipo, app); + fclose(fipo); + } + +#line 150 "dk3appr.ctr" + return back; +} + + + + +/** Get bytes to seed random number generator. + @param app Application structure. + @param dp Destination buffer pointer. + @param sz Number of bytes required. + @param fn File name for seed file. + @return Number of bytes found. +*/ +static +size_t +dk3app_get_seed_from_source(dk3_app_t *app,void *dp,size_t sz,dkChar const *fn) +{ + size_t back = 0; + dk3_stat_t stb; + int can_use_file = 1; + int mode_denied; + + +#line 172 "dk3appr.ctr" + /* DEBUG: Attempting to get seed data from ... */ + dk3app_log_i3(app, DK3_LL_DEBUG, 196, 197, fn); + if(dk3sf_stat_app(&stb, fn, NULL)) { + +#line 175 "dk3appr.ctr" + switch((stb.ft) & (~(DK3_FT_SYMLINK))) { + case DK3_FT_DIRECTORY: { + /* Ignore it. */ + } break; + case DK3_FT_REGULAR: { + /* Security checks before using the file. */ + mode_denied = DK3_FPERM_G_READ + | DK3_FPERM_G_WRITE + | DK3_FPERM_O_READ + | DK3_FPERM_O_WRITE; + if((stb.ft) & DK3_FT_SYMLINK) { + if((stb.ai) & DK3_STAT_AI_USER_DIFFERS) { + can_use_file = 0; + /* WARNING: Symlink owner is not file owner. */ + dk3app_log_i3(app, DK3_LL_ERROR, 185, 186, fn); + } + if((stb.perm) & mode_denied) { + can_use_file = 0; + /* WARNING: File not used (permissions). */ + dk3app_log_i3(app, DK3_LL_ERROR, 183, 184, fn); + } else { + if((stb.lperm) & mode_denied) { + can_use_file = 0; + /* WARNING: File not used (permissions). */ + dk3app_log_i3(app, DK3_LL_ERROR, 183, 184, fn); + } + } + } else { + if((stb.perm) & mode_denied) { + can_use_file = 0; + /* WARNING: File not used (permissions). */ + dk3app_log_i3(app, DK3_LL_ERROR, 183, 184, fn); + } + } + if(can_use_file) { + back = dk3app_read_bytes_from_file(app, dp, sz, fn); + } + } break; + default: { + /* Use file. */ + back = dk3app_read_bytes_from_file(app, dp, sz, fn); + } break; + } + } + +#line 219 "dk3appr.ctr" + /* DEBUG: Seed data: ... bytes. */ + { + char b1[64]; + dkChar b2[64]; + sprintf(b1, "%lu", (unsigned long)back); + if(dk3str_cnv_c8_to_str_app(b2, DK3_SIZEOF(b2,dkChar), b1, app)) { + dk3app_log_i3(app, DK3_LL_DEBUG, 198, 199, b2); + } + } + return back; +} + + + +/** Get bytes to seed random number generator. + @param app Application structure. + @param dp Destination buffer pointer. + @param sz Number of bytes required. + @param fn File name for seed file. + @param passno Pass number (only 0 uses files). + @return Number of bytes found. +*/ +static +size_t +dk3app_get_seed_bytes( + dk3_app_t *app, + void *dp, + size_t sz, + dkChar const *fn, + int passno +) +{ + size_t back = 0; + dkChar const *p1; + dkChar const *p2; + dkChar const *p3; + dkChar const *p4; + dkChar const *p5; + dkChar *p6; + size_t s; + dkChar fnb[DK3_MAX_PATH]; /* File name buffer. */ + if((app) && (dp) && (sz)) { + /* $HOME/.rnd-xxx-application */ + if(passno == 0) { + if(dk3app_get_pref_bool(app, dk3app_not_localized(46), 1)) { + p1 = dk3app_get_homedir(app); + p2 = dk3app_not_localized(20); + p3 = fn; + p4 = dk3app_not_localized(5); + p5 = dk3app_get_appname(app); + if((p1) && (p2) && (p3) && (p4) && (p5)) { + s = dk3str_len(p1); + s += dk3str_len(p2); + s += dk3str_len(p3); + s += dk3str_len(p4); + s += dk3str_len(p5); + if(s < DK3_SIZEOF(fnb,dkChar)) { + dk3str_cpy_not_overlapped(fnb, p1); + dk3str_cat(fnb, p2); + dk3str_cat(fnb, p3); + dk3str_cat(fnb, p4); + dk3str_cat(fnb, p5); + back = dk3app_get_seed_from_source(app, dp, sz, fnb); + } + } + } + } + /* EGD socket from environment. */ + if(back == 0) { + p1 = dk3sf_getenv(dk3app_not_localized(43)); + if(p1) { + back = dk3app_get_seed_from_source(app, dp, sz, p1); + } + } + /* EGD socket from preferences. */ + if(back == 0) { + if(dk3app_get_pref( + app, dk3app_not_localized(42), fnb, DK3_SIZEOF(fnb,dkChar)) + ) + { + p6 = dk3str_start(fnb, NULL); + if(p6) { + dk3str_chomp(p6, NULL); + back = dk3app_get_seed_from_source(app, dp, sz, p6); + } + } + } +#if !DK3_ON_WINDOWS + /* /dev/urandom */ + if(back == 0) { + back = dk3app_get_seed_from_source(app, dp, sz, dk3app_not_localized(44)); + } + /* /dev/random */ + if(back == 0) { + back = dk3app_get_seed_from_source(app, dp, sz, dk3app_not_localized(45)); + } +#endif + } + return back; +} + + + +#if DK3_HAVE_OPENSSL_RAND_H +/** Initialize OpenSSL PRNG. + @param app Application structure. + @return 1 on success, 0 on error. +*/ +static +int +dk3app_init_prng_openssl(dk3_app_t *app) +{ + int back = 0; + int cc = 0; + int passno = 0; + size_t sz; + char seedval[DK3_SEED_OPENSSL_BYTES]; +#if DK3_ON_WINDOWS + BYTE sv[DK3_SEED_OPENSSL_BYTES]; + HCRYPTPROV hcp; + BOOL res; + DWORD dwLgt; +#endif + + +#line 343 "dk3appr.ctr" + do { + cc = 0; + sz = + dk3app_get_seed_bytes( + app,seedval,sizeof(seedval),dk3app_not_localized(41),passno + ); + +#line 349 "dk3appr.ctr" + if(sz > 0) { + cc = 1; + RAND_seed(seedval, (int)sz); + if(RAND_status() == 1) { + cc = 0; back = 1; + } + } +#if DK3_ON_WINDOWS + if(back == 0) { + +#line 358 "dk3appr.ctr" + dk3app_log_i1(app, DK3_LL_DEBUG, 227); + res = CryptAcquireContext( + &hcp, /* Pointer to result variable. */ + NULL, /* Default container (user name). */ + NULL, /* Users default cryptographic provider. */ + PROV_RSA_FULL, /* Provider type. */ + CRYPT_VERIFYCONTEXT + ); + if(res) { + +#line 367 "dk3appr.ctr" + dwLgt = sizeof(sv); + res = CryptGenRandom(hcp, dwLgt, sv); + if(res) { + +#line 370 "dk3appr.ctr" + cc = 1; + RAND_seed(sv, sizeof(sv)); + if(RAND_status() == 1) { + cc = 0; back = 1; + +#line 374 "dk3appr.ctr" + } + } else { + +#line 376 "dk3appr.ctr" + } + CryptReleaseContext(hcp, (DWORD)0L); + } else { + +#line 379 "dk3appr.ctr" + } + } + if(back == 0) { + +#line 382 "dk3appr.ctr" + dk3app_log_i1(app, DK3_LL_DEBUG, 228); + RAND_screen(); + if(RAND_status() == 1) { + cc = 0; back = 1; + +#line 386 "dk3appr.ctr" + } + } +#endif + passno++; + } while(cc); + if(back) { + dk3app_log_i1(app, DK3_LL_DEBUG, 229); + } else { + /* Warning: Failed to seed OpenSSL PRNG! */ + dk3app_log_i1(app, DK3_LL_ERROR, 182); + } + +#line 397 "dk3appr.ctr" + return back; +} +#endif + +#if DK3_HAVE_INITSTATE && DK3_HAVE_SETSTATE && DK3_HAVE_RANDOM +/** Initialize state PRNG. + @param app Application structure. + @return 1 on success, 0 on error. +*/ +static +int +dk3app_init_prng_state(dk3_app_t *app) +{ + int back = 0; + unsigned int seedval = 0; + if(dk3app_get_seed_bytes( + app, (void *)(&seedval), sizeof(unsigned int), dk3app_not_localized(40), 0 + ) + ) + { + srandom(seedval); + back = 1; + } + if(!back) { + /* Warning: Failed to seed random() PRNG! */ + dk3app_log_i1(app, DK3_LL_ERROR, 181); + } + return back; +} +#endif + +#if DK3_HAVE_NRAND48 && DK3_HAVE_LRAND48 +/** Initialize lrand48() PRNG. + @param app Application structure. + @return 1 on success, 0 on error. +*/ +static +int +dk3app_init_prng_rand48(dk3_app_t *app) +{ + int back = 0; + long int seedval = 0L; + if(dk3app_get_seed_bytes( + app, (void *)(&seedval), sizeof(long int), dk3app_not_localized(39), 0 + ) + ) + { + srand48(seedval); + back = 1; + } + if(!back) { + /*Warning: Failed to seed lrand48() PRNG! */ + dk3app_log_i1(app, DK3_LL_ERROR, 180); + } + return back; +} +#endif + +#if DK3_HAVE_RAND && DK3_HAVE_SRAND +/** Initialize simple rand() PRNG. + @param app Application structure. + @return 1 on success, 0 on error. +*/ +static +int +dk3app_init_prng_simple(dk3_app_t *app) +{ + int back = 0; + unsigned int ui; + if( + dk3app_get_seed_bytes( + app, (void *)(&ui), sizeof(unsigned int), dk3app_not_localized(38), 0 + ) + ) + { + srand(ui); + back = 1; + } + if(!back) { + /* Warning: Failed to seed simple PRNG! */ + dk3app_log_i1(app, DK3_LL_ERROR, 179); + } + return back; +} +#endif + + + +/** Attempt to initialize a PRNG. + @param app Application structure. + @param il Input line listing allowed PRNGs comma-separated. + @return 1 on success (at least one PRNG usable), 0 on error. +*/ +int +dk3app_rand_init(dk3_app_t *app, dkChar const *il) +{ + int back = 0; + int allowed_types; + + +#line 496 "dk3appr.ctr" + if(app) { + if(app->f_rand_initialized) { + back = app->f_rand_success; + } else { + app->f_rand_initialized = 1; + if(il) { + allowed_types = dk3app_get_allowed_prng_types(app, il); + } else { + allowed_types = dk3app_rand_find_allowed_types(app); + } + if(!back) { + if(allowed_types & DK3_PRNG_OPENSSL) { + +#line 508 "dk3appr.ctr" +#if DK3_HAVE_OPENSSL_RAND_H + + +#line 510 "dk3appr.ctr" + back = dk3app_init_prng_openssl(app); + if(back) { + +#line 512 "dk3appr.ctr" + app->rand_type = DK3_PRNG_OPENSSL; + } +#else + + +#line 516 "dk3appr.ctr" +#endif + } + } + if(!back) { + if(allowed_types & DK3_PRNG_STATE) { +#if DK3_HAVE_INITSTATE && DK3_HAVE_SETSTATE && DK3_HAVE_RANDOM + back = dk3app_init_prng_state(app); + if(back) { + app->rand_type = DK3_PRNG_STATE; + } +#endif + } + } + if(!back) { + if(allowed_types & DK3_PRNG_RAND48) { +#if DK3_HAVE_NRAND48 && DK3_HAVE_LRAND48 + back = dk3app_init_prng_rand48(app); + if(back) { + app->rand_type = DK3_PRNG_RAND48; + } +#endif + } + } + if(!back) { + if(allowed_types & DK3_PRNG_SIMPLE) { +#if DK3_HAVE_RAND && DK3_HAVE_SRAND + back = dk3app_init_prng_simple(app); + if(back) { + app->rand_type = DK3_PRNG_SIMPLE; + } +#endif + } + } + if(back) { + app->f_rand_success = 1; + } + } + } + if(!back) { + /* ERROR: No PRNG usable! */ + dk3app_log_i1(app, DK3_LL_ERROR, 178); + } + +#line 558 "dk3appr.ctr" + return back; +} + + + +/** Get random bytes. + @param app Application structure. + @param db Destination buffer. + @param sz Size of \a db (number of bytes). + @param f_crypto Flag: For cryptographic purposes. + @return Number of bytes written to \a db. +*/ +static +size_t +dk3app_rand_bytes_internal(dk3_app_t *app, void *db, size_t sz, int f_crypto) +{ + size_t back = 0; + unsigned char *ucptr = NULL; + size_t i = 0; + unsigned u = 0; + if((app) && (db) && (sz)) { + ucptr = (unsigned char *)db; + if(!(app->f_rand_initialized)) { + dk3app_rand_init(app, NULL); + } + if(app->f_rand_success) { + switch(app->rand_type) { + case DK3_PRNG_OPENSSL: { +#if DK3_HAVE_OPENSSL_RAND_H + if(f_crypto) { + if(RAND_bytes(ucptr, (int)sz) == 1) { + back = sz; + } + } else { + if(RAND_pseudo_bytes(ucptr, (int)sz) > -1) { + back = sz; + } + } +#else + /* BUG: Not available! */ +#endif + } break; + case DK3_PRNG_STATE: { +#if DK3_HAVE_INITSTATE && DK3_HAVE_SETSTATE && DK3_HAVE_RANDOM + long lval; + size_t position; + + lval = random() >> 8; + position = 0; + for(i = 0; i < sz; i++) { + *(ucptr++) = (unsigned char)(lval & 0x000000FFL); + position++; + lval = lval >> 8; + if(position >= (sizeof(long) - 1)) { + lval = random() >> 8; + position = 0; + } + } + back = sz; +#else + /* BUG: Not available! */ +#endif + } break; + case DK3_PRNG_RAND48: { +#if DK3_HAVE_NRAND48 && DK3_HAVE_LRAND48 + long lval; + size_t position; + + lval = lrand48() >> 8; + position = 0; + for(i = 0; i < sz; i++) { + *(ucptr++) = (unsigned char)(lval & 0x000000FFL); + position++; + lval = lval >> 8; + if(position >= (sizeof(long) - 1)) { + lval = lrand48() >> 8; + position = 0; + } + } + back = sz; +#else + /* BUG: Not available! */ +#endif + } break; + default: { +#if DK3_HAVE_RAND && DK3_HAVE_SRAND + for(i = 0; i < sz; i++) { + u = rand(); +#if DK3_SIZEOF_INT > 2 +#if DK3_SIZEOF_INT > 4 + u = u >> 28; +#else + u = u >> 12; +#endif +#else + u = u >> 4; +#endif + u &= 0x00FFU; + *(ucptr++) = (unsigned char)u; + } + back = sz; +#else + /* BUG: Not available! */ +#endif + } break; + } + } + } + if(back < sz) { + /* ERROR: Failed to obtain enough random bytes! */ + dk3app_log_i1(app, DK3_LL_ERROR, 177); + } + return back; +} + + +size_t +dk3app_rand_bytes(dk3_app_t *app, void *db, size_t sz) +{ + size_t back; + back = dk3app_rand_bytes_internal(app, db, sz, 1); + return back; +} + + +size_t +dk3app_rand_bytes_non_crypto(dk3_app_t *app, void *db, size_t sz) +{ + size_t back; + back = dk3app_rand_bytes_internal(app, db, sz, 0); + return back; +} + + + +void +dk3app_rand_end(dk3_app_t *app) +{ +#if DK3_HAVE_OPENSSL_RAND_H +#if DK3_CHAR_SIZE == 1 + dkChar const *p1 = NULL; + dkChar const *p2 = NULL; + dkChar const *p3 = NULL; + dkChar const *p4 = NULL; + dkChar const *p5 = NULL; + size_t sz = 0; + FILE *fipo = NULL; + dkChar fnb[DK3_MAX_PATH]; +#endif +#endif + + +#line 709 "dk3appr.ctr" + if((app->f_rand_initialized) && (app->f_rand_success)) { + +#line 710 "dk3appr.ctr" + switch(app->rand_type) { + case DK3_PRNG_OPENSSL: { +#if DK3_HAVE_OPENSSL_RAND_H +#if DK3_CHAR_SIZE == 1 + p1 = dk3app_get_homedir(app); + p2 = dk3app_not_localized(20); + p3 = dk3app_not_localized(41); + p4 = dk3app_not_localized(5); + p5 = dk3app_get_appname(app); + if((p1) && (p2) && (p3) && (p4) && (p5)) { + sz = dk3str_len(p1); + sz += dk3str_len(p2); + sz += dk3str_len(p3); + sz += dk3str_len(p4); + sz += dk3str_len(p5); + if(sz < DK3_SIZEOF(fnb,dkChar)) { + dk3str_cpy_not_overlapped(fnb, p1); + dk3str_cat(fnb, p2); + dk3str_cat(fnb, p3); + dk3str_cat(fnb, p4); + dk3str_cat(fnb, p5); + +#line 731 "dk3appr.ctr" + fipo = dk3sf_fopen_app(fnb, dk3app_not_localized(24), app); + if(fipo) { + fclose(fipo); fipo = NULL; +#if DK3_ON_WINDOWS + /* chmod(fnb, 0600); */ +#else +#if DK3_HAVE_CHMOD + chmod(fnb, 0600); +#endif +#endif + if(RAND_write_file(fnb) <= 0) { + /* Warning: Failed to save random seed. */ + dk3app_log_i1(app, DK3_LL_ERROR, 193); + } + } + } + } +#endif +#endif + } break; + } + } else { + +#line 753 "dk3appr.ctr" + } + +#line 754 "dk3appr.ctr" +} + + + +/* vim: set ai sw=2 : */ + |