diff --git a/README b/README index 3dbcca5..2caf15c 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -Written by omen23 -- David Schuster in 2012 (david [dot] schuster [at] kdemail [dot] net) +Written by omen23 -- David Schuster © in 2012-2016 (david [dot] schuster [at] kdemail [dot] net) Open and free! (but please give me some credit =) This is an interface to a sqlite3 database which stores its keys hashed or in plain @@ -6,6 +6,16 @@ text. So it is designed for a login-procedure and was thought to be useful for CGI login handling. The hashing capabilities can be turnt off in case you are lazy enough to check your passwords or keys plain-text. + Friday, 14.10.2016 - COMPLETE REWRITE OF MODULAR HASHING SYSTEM + - ongoing rewrite of static functions that are only needed for one reason, made the login function easier (no more self supplied sql) + - this is a login interface, thats what it does - no more cost for database calls than needed (rewrite of callback code) + - future hopes: cgi interface to get this running on a web-server (reading the book atm) + +This software now produces the right digests. Sorry there is no test database but everything should be working now. +Thanks, David + +p.s.: maybe try "user" as first program parameter and "test" as second - it should work (= + OK enough -- this is what this package provides: login.c - login routine and sqlite3 callback (with an example main function) hash.c - the hashing function which is used in the login program @@ -13,7 +23,7 @@ hash.c - the hashing function which is used in the login program hashit.c - a small utility that can generate digests of all implemented gcrypt hashing algorithms (e.g. for generation of your keys) ftm.c - feature test macros -login.h - a header file where all the fun is defined :) +login.h - a header file where all crossover fun is defined :) There is a Makefile for convenience - just type "make" and if you have a debian based system with "libgcrypt-dev" and "libsqlite3-dev" installed everything should work OOB. @@ -35,7 +45,4 @@ all this is fixed now If you have problems setting this up - contact me! I cannot promise that I will answer because my inbox is always really full. The string macros supplied use GNU extensions or BSD versions of the standard implementation. (strlen, strcat, strcpy) - --Wno-pointer-sign -funsigned-char were used tho compile this with gcc before version -4.5 I guess - the code was fixed or the compiler or both. -(This code is under development since quite a while) + diff --git a/build/debug/ex1.db b/build/debug/ex1.sql similarity index 89% rename from build/debug/ex1.db rename to build/debug/ex1.sql index 156d4e2..2c12f2f 100644 Binary files a/build/debug/ex1.db and b/build/debug/ex1.sql differ diff --git a/c-app.rls.tar.gz b/c-app.rls.tar.gz deleted file mode 100644 index ceef027..0000000 Binary files a/c-app.rls.tar.gz and /dev/null differ diff --git a/ex1.db b/ex1.db deleted file mode 100644 index 156d4e2..0000000 Binary files a/ex1.db and /dev/null differ diff --git a/build/release/ex1.db b/ex1.sql similarity index 89% rename from build/release/ex1.db rename to ex1.sql index 156d4e2..2c12f2f 100644 Binary files a/build/release/ex1.db and b/ex1.sql differ diff --git a/ex2.db b/ex2.db deleted file mode 100644 index d303d3e..0000000 Binary files a/ex2.db and /dev/null differ diff --git a/ftm.c b/ftm.c index 61c8a26..19a917b 100644 --- a/ftm.c +++ b/ftm.c @@ -1,7 +1,20 @@ -#include -#include -#include +/* + * feature testing software + * _POSIX_SOURCE defined + * _POSIX_C_SOURCE defined: 200809L + * _ISOC99_SOURCE defined + * _ISOC11_SOURCE defined + * _XOPEN_SOURCE defined: 700 + * _XOPEN_SOURCE_EXTENDED defined + * _LARGEFILE64_SOURCE defined + * _DEFAULT_SOURCE defined + * _ATFILE_SOURCE defined + * _GNU_SOURCE defined + * _FORTIFY_SOURCE defined + */ +#define _GNU_SOURCE +#include "login.h" int main(int argc, char *argv[]) @@ -18,6 +31,10 @@ main(int argc, char *argv[]) printf("_ISOC99_SOURCE defined\n"); #endif +#ifdef _ISOC11_SOURCE + printf("_ISOC11_SOURCE defined\n"); +#endif + #ifdef _XOPEN_SOURCE printf("_XOPEN_SOURCE defined: %d\n", _XOPEN_SOURCE); #endif @@ -41,6 +58,10 @@ main(int argc, char *argv[]) #ifdef _SVID_SOURCE printf("_SVID_SOURCE defined\n"); #endif + +#ifdef _DEFAULT_SOURCE + printf("_DEFAULT_SOURCE defined\n"); +#endif #ifdef _ATFILE_SOURCE printf("_ATFILE_SOURCE defined\n"); @@ -57,9 +78,10 @@ main(int argc, char *argv[]) #ifdef _THREAD_SAFE printf("_THREAD_SAFE defined\n"); #endif + #ifdef _FORTIFY_SOURCE printf("_FORTIFY_SOURCE defined\n"); #endif - exit(EXIT_SUCCESS); } + diff --git a/hash.c b/hash.c index 5cb37da..a99318e 100644 --- a/hash.c +++ b/hash.c @@ -1,113 +1,26 @@ -/* C to sqlite DB interface (for logins) - * with hashing mechanisms using gcrypt - * written by oMeN23 in 2011-2012 - * If you think this is useful, use it! - * copyleft, open and free! - * file: hash.c (hashing) +/* + * new modular hash function for the sqlite3 interface + * by David Schuster © 2016 */ -#include -#include -#include -#include -#include -#include -#include -#include + +#define _GNU_SOURCE #include "login.h" -/* this function calculates a hex-string which represents - * the hash of the user's password or any value - * arg1 = the value - * arg2 = the destination (caller has to allocate dynamic or automatic memory and free it eventually after) - min. (gcry_md_get_algo_dlen(algo)*4) for hex notation - * arg3 = the algorithm (see libgcrypt docs) - * arg4 = some flags (see below) - * 0 = none, - * GCRY_MGCRY_MD_FLAG_SECURE = 1, Allocate all buffers in "secure" memory. - * GCRY_MD_FLAG_HMAC = 2, Make an HMAC out of this algorithm. - */ -void hash_func(const char* value, char* dest, int algo, unsigned int flags) { +void hash_func(int algo, char* digest, const void* value, size_t len) +{ + size_t algolen = gcry_md_get_algo_dlen(algo); + char* rawResult = gcry_malloc_secure(algolen); - gcrypt_init(); - gcry_md_hd_t Crypto_handle; /* crypto context handle */ - gcry_error_t Crypto_error = 0; - - /* determine pw length + 1 (macro handles it), max USERBUF , not overflowable MACRO USED */ - size_t text_length = stringlength(value) + 1; /* terminating null, shouldnt make a diff, sys dependend, this is correct */ - /* check if the library is working as it should .. */ - Crypto_error = gcry_md_open(&Crypto_handle, algo, flags); - if (Crypto_error || Crypto_handle == NULL) - fprintf(stderr, "Failure: %s\t/\t%s\n", - gcry_strsource(Crypto_error), - gcry_strerror(Crypto_error) - ); - Crypto_error = gcry_md_enable(Crypto_handle, algo); - if (Crypto_error) - fprintf(stderr, "Failure: %s\t/\t%s\n", - gcry_strsource(Crypto_error), - gcry_strerror(Crypto_error) - ); - if (Crypto_error || !gcry_md_is_enabled(Crypto_handle, algo)) { - fprintf(stderr, "Failure: %s\t/\t%s\n", - gcry_strsource(Crypto_error), - gcry_strerror(Crypto_error) - ); - abort(); - } - /* if algo works start the hashing */ - if (gcry_md_test_algo(algo) == GPG_ERR_NO_ERROR) { - - /* pass pw into hash function bytewise (unsigned char) */ - for (int x = 0 ; x < text_length; x++) { - gcry_md_putc(Crypto_handle, (unsigned char)value[x]); - } - /* finalize calculation */ - gcry_md_final(Crypto_handle); - /* allocate (secure) heap memory for the hash */ - unsigned char* byte_result = gcry_malloc_secure(gcry_md_get_algo_dlen(algo)*4); // NOTE: we actually ran out of space here once - /* helpers to make them human readable and comparable */ - unsigned char* helper = gcry_malloc_secure(16); /* actually only need 1 char */ - - if ( !gcry_is_secure(helper)|| !gcry_is_secure(byte_result)) { - fprintf(stderr, "Could not allocate in secure memory!\n"); - abort(); - } - // NOTE: 10.6.2012 fixed a strcpy issue - where digests with a value of zer0 [00] in the middle would be - // cut off - using memcpy instead - /* copy hash into a RAW string */ - memcpy(byte_result, gcry_md_read(Crypto_handle, algo), gcry_md_get_algo_dlen(algo)*2); /* read in the raw byte string - size times two for hex notation */ - - if (dest == NULL) { /* the caller has to allocate the destination memory */ - fprintf(stderr, "\t Hashing-Function: destination memory adress is not valid!\n\ - The caller of this function is responsible for allocating a destination buffer that is large enough\n\ - for holding the digest value\n"); - abort(); - } - memset((void*)dest, 0, sizeof(dest)); /* clear memory where hash is to be written */ - - - /* format the raw string to hex notation and - * pass it piece by piece into our char *dest - * and concatenate */ - for (int i = 0; i < gcry_md_get_algo_dlen(algo); i++) { - sprintf((char*)helper, "%02x", (unsigned char)byte_result[i]); - stringconcat(dest, (const char*)helper); - } - dest[ strlen( dest ) ] = '\0'; - /* generally clean up after ourselves ... */ - gcry_md_close(Crypto_handle); /* releases all security relevant information */ - gcry_free(Crypto_handle); - gcry_free(byte_result); - gcry_free(helper); - Crypto_error = 0; - Crypto_handle = NULL; - byte_result = NULL; - helper = NULL; - - } else /* if the hash mechanism isnt working abort */ - abort(); + gcry_md_hash_buffer(algo, rawResult, value, len); + + for (int i = 0; i < algolen; i++) { + sprintf(digest+(i*2), "%02x", (unsigned char)rawResult[i]); /* pointer magic */ + } + gcry_free(rawResult); } -void gcrypt_init() { +void gcrypt_init() +{ static bool initialized = false; if (gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P) || initialized) return; @@ -119,8 +32,8 @@ void gcrypt_init() { /* this is the actual library initialization * with a sec mem starting pool of 64k */ gcry_control(GCRYCTL_SUSPEND_SECMEM_WARN), - gcry_control(GCRYCTL_INIT_SECMEM, 16384*4, 0), + gcry_control(GCRYCTL_INIT_SECMEM, 65536, 0), gcry_control(GCRYCTL_RESUME_SECMEM_WARN), - gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); + gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0), initialized = true; } diff --git a/hashit.c b/hashit.c index 75d5e41..5511ee1 100644 --- a/hashit.c +++ b/hashit.c @@ -1,66 +1,63 @@ -#include -#include -#include -#include - -#include -#include -#include -#include +/* C to sqlite DB interface (for logins) + * with hashing mechanisms using gcrypt + * written by oMeN23 in 2011-2016 + * If you think this is useful, use it! + * copyleft, open and free! + * file: hashit.c (hashing-utility) + */ +#define _GNU_SOURCE #include "login.h" -int main(int argc, char** argv) +int main(int argc, char* argv[]) { time_t thetime = time(NULL); - printf("hashit v0.1 - %s", ctime(&thetime)); - clock_t start, end; - start = clock(); - int algo; - char buffer[1<<12]; - char final[1<<12]; + + printf("hashit v0.25 - %s", ctime(&thetime)); gcrypt_init(); + int algo; + +start: printf("These are the available algorithms: \n\ - GCRY_MD_MD5 = 1,\n\ - GCRY_MD_SHA1 = 2,\n\ - GCRY_MD_RMD160 = 3,\n\ - GCRY_MD_TIGER = 6, /* TIGER/192 as used by gpg <= 1.3.2. */\n\ - GCRY_MD_SHA256 = 8,\n\ - GCRY_MD_SHA384 = 9,\n\ - GCRY_MD_SHA512 = 10,\n\ - GCRY_MD_SHA224 = 11,\n\ - GCRY_MD_MD4 = 301,\n\ - GCRY_MD_CRC32 = 302,\n\ - GCRY_MD_CRC32_RFC1510 = 303,\n\ - GCRY_MD_CRC24_RFC2440 = 304,\n\ - GCRY_MD_WHIRLPOOL = 305,\n\ - GCRY_MD_TIGER1 = 306, /* TIGER fixed. */\n\ - GCRY_MD_TIGER2 = 307 /* TIGER2 variant. */\n"); + GCRY_MD_MD5 = 1,\n\ + GCRY_MD_SHA1 = 2,\n\ + GCRY_MD_RMD160 = 3,\n\ + GCRY_MD_TIGER = 6, /* TIGER/192 as used by gpg <= 1.3.2. */\n\ + GCRY_MD_SHA256 = 8,\n\ + GCRY_MD_SHA384 = 9,\n\ + GCRY_MD_SHA512 = 10,\n\ + GCRY_MD_SHA224 = 11,\n\ + GCRY_MD_MD4 = 301,\n\ + GCRY_MD_CRC32 = 302,\n\ + GCRY_MD_CRC32_RFC1510 = 303,\n\ + GCRY_MD_CRC24_RFC2440 = 304,\n\ + GCRY_MD_WHIRLPOOL = 305,\n\ + GCRY_MD_TIGER1 = 306, /* TIGER fixed. */\n\ + GCRY_MD_TIGER2 = 307 /* TIGER2 variant. */\n"); printf("Please enter the number of the desired algorithm: "); - scanf("%i", &algo); + scanf("%i", &algo), + getchar(); // fall thru without this call bool rangeOk = false; if ((algo > 0 && algo < 12 && (algo != 4 && algo != 5 && algo != 7)) || (algo > 300 && algo < 308)) rangeOk = true; if (!rangeOk) { - printf("Select a valid algorithm please\n"); - abort(); + printf("Select a valid algorithm please.\n"); + goto start; } + char* final = gcry_malloc_secure((gcry_md_get_algo_dlen(algo)*2)+1); + char* ptr = gcry_malloc_secure(4096); - char* ptr = buffer; - getchar(); // fall thru without this call printf("What value do you want to hash? "); - fgets(ptr, sizeof buffer, stdin); - ptr[strlen(ptr)-1] = '\0'; // remove '\n' of fgets - - char* hash = final; - hash_func(ptr, hash, algo, GCRY_MD_FLAG_SECURE); - printf("\"%s\" hashed is:\n%s\n", ptr, hash); - end = clock(); - double execution_time = (double) ((end - start) / CLOCKS_PER_SEC); - printf("Execution of the program took %.12lf secs\n",execution_time); //(double) ((end - start) / CLOCKS_PER_SEC) ); - - return 0; + fgets(ptr, 4096, stdin); + ptr[ strlen(ptr) - 1 ] = '\0'; // remove '\n' of fgets -} \ No newline at end of file + hash_func(algo, final, ptr, strlen(ptr)); + printf("%s\n", final); + + gcry_free(final); + gcry_free(ptr); + + return 0; +} diff --git a/login.c b/login.c index 4a8b2ee..9f6c457 100644 --- a/login.c +++ b/login.c @@ -1,20 +1,22 @@ -/* C to sqlite DB interface (for logins) +/* + * C to sqlite DB interface (for logins) * with hashing mechanisms using gcrypt - * written by oMeN23 in 2011 + * written by oMeN23 © in 2011-2016 * If you think this is useful, use it! * copyleft, open and free! * file: login.c (main) */ -#include -#include -#include -#include -#include -#include -#include -#include -#include + +#define _GNU_SOURCE #include "login.h" +/* small function to build the matching + * sql string for our purposes + * arg1 is the destination memory + * arg2 is the username */ +static inline void build_sql_string(char* dest, const char* username) +{ + sprintf(dest, "select * from users where username = '%s';", username); +} /* does the user exist in the db */ bool isRegistered = false; @@ -29,194 +31,121 @@ static int callback (void* logindata, /* sql_exec passes its forth argument in h char** Db_entries, /* array of strings which represent the indiviual entries of this row ![REMEMBER the callback gets called for every ROW] */ char** azColName) /* the matching row name for the above strings eg.: azColname[0] = "username", Db_entries[0] = "man" in the last call */ { - bool usr1 = false; - bool pw1 = false; - login_data_t userdata = (login_data_t)logindata; - /* basically iterate over the data we get - check for match - * thats why we gotta return 0 if we have no match - * the callback wouldnt get called again for the next row - */ - for (int i = 0 ; i < numArgs; i++) { - if (Db_entries[i] != NULL) { - if (strcmp(Db_entries[i], userdata->username) == 0) { - usr1 = true; - isRegistered = true; /* username found in db (as we got a callback) -> search for matching pw */ - } - if (strcmp(Db_entries[i], userdata->hash) == 0) - pw1 = true; - } - } - if (usr1 && pw1) { /* successfully logged in */ - isLoggedOn = true; - return 0; /* ABORT match found */ - } else { - fprintf(stderr, "No match found!\n"); - return 0; /* no match found */ - } + login_data_t userdata = (login_data_t)logindata; + /* basically iterate over the data we get - check for match + * thats why we gotta return 0 if we have no match + * the callback wouldnt get called again for the next row + */ + for (int i = 0; i < numArgs; i++) { + if (!stringcompare(Db_entries[0], userdata->username)) { + isRegistered = true; /* username found in db (if check) -> search for matching pw */ + + if (isRegistered && !stringcompare(Db_entries[1], userdata->hash)) { + isLoggedOn = true; + return 0; + } + } + } + return 0; } /* in this function im trying to handle the login event and interface with sqlite * this will result in return values true as ok and false otherwise */ bool login(const char* username, /* username */ - char* password, /* password -> gets deleted for security reasons */ - bool own_sql, /* indicates if you want your own sql statement executed against the DB */ - const char* sql_statement) /* the sql statement to be executed against the Database or NULL */ + char* password) /* password -> gets deleted for security reasons */ { - /* check for user overflow attempts */ - if (stringlength(username) > USERBUF - 6 || stringlength(password) > USERBUF - 6) { - fprintf(stderr, "Username and/or password too long! Max. %d characters.\n", USERBUF - 6); - fprintf(stderr, "Make a different choice, please.\n"); - abort(); - } - else if (stringlength(username) < 2 || stringlength(password) < 4) { - fprintf(stderr, "Username min. 3 characters and password min. 4 characters.\n"); /* TODO ADJUST THIS IS FOR THE FINAL */ - abort(); - } - - /* PREREQUESITES AND MEM ALLOC */ - sqlite3* Db_object = NULL; - char* errormsg; - gcrypt_init(); /* initialize mem manager and stuff so lib doesnt complain */ - - login_data_t container = gcry_malloc_secure(sizeof *container); - - if (container == NULL) { - fprintf(stderr, "Could not allocate memory!\n"); - abort(); - } - container->username = gcry_malloc_secure(USERBUF); - container->password = gcry_malloc_secure(USERBUF); - container->hash = gcry_malloc_secure(USERBUF * 2); - - if (!gcry_is_secure(container->hash) || !gcry_is_secure(container) || !gcry_is_secure(container->password)) { - fprintf(stderr, "Could not allocate in secure memory!\n"); - abort(); - } - - strcpy(container->username, username); /* copy userdata in secure mem */ - strcpy(container->password, password); + /* check for user overflow attempts */ + if (stringlength(username) > USERBUF - 6 || stringlength(password) > USERBUF - 6) { + fprintf(stderr, "Username and/or password too long! Max. %d characters.\n", USERBUF - 6); + fprintf(stderr, "Make a different choice, please.\n"); + exit(1); + } + else if (stringlength(username) < 2 || stringlength(password) < 4) { + fprintf(stderr, "Username min. 3 characters and password min. 4 characters.\n"); /* TODO ADJUST THIS IS FOR THE FINAL */ + exit(1); + } + + /* PREREQUESITES AND MEM ALLOC */ + sqlite3* Db_object = NULL; + char* errormsg; + gcrypt_init(); /* initialize mem manager and stuff so lib doesnt complain */ + + login_data_t container = gcry_malloc_secure(sizeof *container); + + if (container == NULL) { + fprintf(stderr, "Could not allocate memory!\n"); + abort(); + } + container->username = gcry_malloc_secure(USERBUF); + container->hash = gcry_malloc_secure(USERBUF); + + if (!gcry_is_secure(container->hash) || !gcry_is_secure(container) || !gcry_is_secure(container->username)) { + fprintf(stderr, "Could not allocate in secure memory!\n"); + exit(2); + } + stringcopy(container->username, username); /* copy userdata in secure mem */ #ifndef HASH - strcpy(container->hash, password); /* SO IF SOMEBODY TURNS OFF HASHING IT WILL STILL WORK */ + stringcopy(container->hash, password); /* SO IF SOMEBODY TURNS OFF HASHING IT WILL STILL WORK */ #endif - memset((void*)password, 0, stringlength(password)); /* fill the parameter with zeroes - its not secure - then it is */ - int err = sqlite3_open(DATABASE, /* const char *filename - Database filename (UTF-8), defined in the header MACRO USED */ - &Db_object); /* sqlite3 **ppDb - OUT: SQLite db handle */ - - if (err != SQLITE_OK) { - fprintf(stderr, "Database connection failed, something went wrong.\n"); - abort(); - } - -#ifdef HASH /* call of the hashing function -> hash.c */ - hash_func(container->password, container->hash, GCRY_MD_TIGER, GCRY_MD_FLAG_SECURE); // TODO XXX change 6 with 306 - fprintf(stderr, "Trying to log in as \n'%s' \nwith hashed-pw \n'%s'\n", container->username, container->hash); + int err = sqlite3_open(DATABASE, /* const char *filename - Database filename (UTF-8), defined in the header MACRO USED */ + &Db_object); /* sqlite3 **ppDb - OUT: SQLite db handle */ + + if (err != SQLITE_OK) { + fprintf(stderr, "Database connection failed, something went wrong.\n"); + exit(3); + } + +#ifdef HASH /* call of the hashing function -> hash.c .. change to GCRY_MD_TIGER1 */ + hash_func(GCRY_MD_TIGER, container->hash, password, stringlength(password)); // TODO XXX change 6 with 306 see above for enum decl + fprintf(stderr, "Trying to log in as \n'%s' \nwith hashed-pw \n'%s'\n", container->username, container->hash); + memset(password, 0, stringlength(password)); #else - fprintf(stderr, "Trying to log in as '%s'\n", container->username); + fprintf(stderr, "Trying to log in as '%s'\n", container->username); #endif - /* turn off self-supplied SQL if a null ptr or empty string is supplied */ - - /* SQL STUFF AND BUILDER */ - char sql[LARGEBUF]; - if (own_sql) { - if (longstringlength(sql_statement) >= LARGEBUF) { /* FUNC MACRO USED */ - fprintf(stderr, "SQL statement too long. Max. %d characters.\n", LARGEBUF); - abort(); - } - if (sql_statement == NULL || strcmp(sql_statement, "") == 0) { - own_sql = false; - fprintf(stderr, "login(...) called with wrong args - arg3 is true and arg4 is NULL or empty!\n"); - } - - /*if (sql_statement == NULL) { - fprintf(stderr, "Cannot pass NULL Pointer as SQL statement!\n"); - abort(); not possible as for convenience, this is turned off if a null ptr is supplied - }*/ - if (stringlength(sql_statement) < 6) { /* FUNC MACRO USED */ - fprintf(stderr, "Cannot pass empty or nonsensical string as SQL statement!\n"); - abort(); - } - /* SQL OK copy it into our string - dest array should be clean so string isnt garbage */ - memset((void*)sql, 0, sizeof(sql)); - strcpy(sql, sql_statement); - } - else /* use default sql string builder mechanism (fast and convenient and safe) 1 call per login/username */ - build_sql_string((const char*)container->username, sql); - - /* DATABASE CALL */ - err = sqlite3_exec(Db_object, /* An open database ![IMPORTANT -> callback is called for every ROW]! */ - sql, /* SQL to be evaluated */ - callback, /* Callback function */ - /* int (*callback)(void* freeSlot, int numDbEntries, char** DBEntries, char** ColumnName) - - * arg1 is a free pointer specified by the sqlite3 calling convention interface - - * I put the data to compare against in here (could be unused too) - * arg2 NumDbEntries retrieves the count of entries in that row, - * arg3 DBEntries is an array of strings of the data in that row and - * arg4 ColumnName is an array of strings representing the column. */ - (void*)container, /* 1st argument to callback */ - &errormsg); /* Error msg written here */ - - if (err != SQLITE_OK) { - // ^^ er == 4 ? callback returned 1 (or any nonzero value) - // fprintf(stderr, "SQL notice: callback requested query abort because a match was found.\n"); old logic part - fprintf(stderr, "SQL error: %s\n", errormsg ); // sqlite3_errmsg(Db_object) - sqlite3_free(errormsg); - } - /* clean up the DB connection */ - sqlite3_close(Db_object); - - /* BUFFER FLUSH */ - memset(container->hash, 0, USERBUF * 2); - memset(container->password, 0, USERBUF); - memset(container->username, 0, USERBUF); - /* fprintf(stderr, "VAR TEST usr1: %s %s %s %s %s\n", username, password, container->username, - * container->password, container->hash); // MEM TEST FUNC to see if mem was overwritten */ - - /* release the memory - no data left in RAM */ - gcry_free(container->hash); - gcry_free(container->password); - gcry_free(container->username); - gcry_free(container); - container->password = NULL; - container->hash = NULL; - container->username = NULL; - container = NULL; - /* set ptrs null, username is the only variable left intact -> see above - * the whole login_data_t container is now overwritten - also the passed password argument (around line 104) */ - - /* print messages concerning status */ - if (!isRegistered) - fprintf(stderr, "Username '%s' not found in DB.\n", username); - /* if someone is found in the DB, but not logged in he can only have supplied a wrong password */ - if (isRegistered && !isLoggedOn) - fprintf(stderr, "Wrong password for user '%s'.\n", username); - /* msg for logon for logfile and display, watch the supplied stream args */ - if (isLoggedOn) { - fprintf(stderr, "User '%s' logged on succesful!\n", username); - fprintf(stdout, "Welcome %s!\n", username); - fprintf(stdout, "Have a nice stay.\n"); - } - - /* magic global indicating our successful login (gets set in the callback) */ - return isLoggedOn; -} - -/* small function to build the matching - * sql string for our purposes - * arg1 is the username - * arg2 is to where to write the string - * already in auto use of the login function if third param is false (of the login func) - */ -void build_sql_string(const char* username, char* dest) -{ - char sql_string[LARGEBUF] = ""; - strcpy(sql_string, "select * from users where username = '"); /* users is the name of the SQL table */ - stringconcat(sql_string, username); /* FUNC MACRO USED */ - stringconcat(sql_string, "';"); - memset((void*)dest, 0, sizeof(dest)); /* clear mem where sql string is to be written - so theres no garbage */ - strcpy(dest, sql_string); + char sql[USERBUF]; + build_sql_string(sql, container->username); + /* DATABASE CALL */ + err = sqlite3_exec(Db_object, /* An open database ![IMPORTANT -> callback is called for every ROW]! */ + sql, /* SQL to be evaluated */ + callback, /* Callback function */ + container, /* 1st argument to callback */ + &errormsg); /* Error msg written here */ + + if (err != SQLITE_OK) { + fprintf(stderr, "SQL error: %s\n", errormsg); /* sqlite3_errmsg(Db_object) */ + sqlite3_free(errormsg); + } + /* clean up the DB connection */ + sqlite3_close(Db_object); + memset(container->hash, 0, USERBUF); + memset(container->username, 0, USERBUF); + + /* release the memory - no data left in RAM */ + gcry_free(container->hash); + gcry_free(container->username); + gcry_free(container); + memset(container, 0, sizeof *container); + /* set ptrs null, username is the only variable left intact -> see above + * the whole login_data_t container is now overwritten - also the passed password argument (around line 104) */ + + /* print messages concerning status */ + if (!isRegistered) + fprintf(stderr, "Username '%s' not found in DB.\n", username); + /* if someone is found in the DB, but not logged in he can only have supplied a wrong password */ + if (isRegistered && !isLoggedOn) + fprintf(stderr, "Wrong password for user '%s'.\n", username); + /* msg for logon for logfile and display, watch the supplied stream args */ + if (isLoggedOn) { + fprintf(stderr, "User '%s' logged on succesful!\n", username); + fprintf(stdout, "Welcome %s!\n", username); + fprintf(stdout, "Have a nice stay.\n"); + } + + /* magic global indicating our successful login (gets set in the callback) */ + return isLoggedOn; } /* Example main ... this is intented to be a "library" - only a glue code @@ -225,27 +154,24 @@ void build_sql_string(const char* username, char* dest) int main(int argc, char* argv[]) { - /* get user data - change this so it suits your needs - try to use secure storage */ - if (!argv[1] || !argv[2]) { printf("please supply two args\n"); abort(); } - char* user = argv[1]; - char* pass = argv[2]; - - /* login -> returns a bool indicating success */ - bool logged_on = login(user, /* self expl this variable will come back unchanged */ - pass, /* this variable will be garbage after the login */ - false, /* own sql statement suppplied as arg4(true) or default func(false), I'd go with this setting */ - NULL); /* sql string like "select * from users;" or NULL pointer for default func */ - - if (logged_on) - { - /* log-in succeeded - do what you like here */ - return 0; - } - else - { - /* log-in didnt succeed, handle it how you like ... (call main again whatever) */ - return 1; - - } + /* get user data - change this so it suits your needs - try to use secure storage */ + if (!argv[1] || !argv[2]) { printf("please supply two args\n"); exit(-1); } + char* user = argv[1]; + char* pass = argv[2]; + + /* login -> returns a bool indicating success */ + bool logged_on = login(user, /* self expl this variable will come back unchanged */ + pass); /* this variable will be garbage after the login */ + + if (logged_on) + { + /* log-in succeeded - do what you like here */ + return 0; + } + else + { + /* log-in didnt succeed, handle it how you like ... (call main again whatever) */ + return 1; + } } diff --git a/login.h b/login.h index c0d7ebd..96686f4 100644 --- a/login.h +++ b/login.h @@ -1,71 +1,77 @@ -/* C to sqlite DB interface (for logins) +/* + * C to sqlite DB interface (for logins) * with hashing mechanisms using gcrypt - * written by oMeN23 in 2011 + * written by oMeN23 in 2011-2016 © * If you think this is useful, use it! * copyleft, open and free! * file: login.h (headerfile) */ -#ifndef _LOGIN_H_ -#define _LOGIN_H_ + #pragma once // NOTE: does this work on our compiler (gcc) ? (back of my mind tells me only msvc supports this) /* This code conforms to the ISO C99 standard and makes heavy use of GNU extensions */ -#define _ISOC99_SOURCE #define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include + #ifndef _GNU_SOURCE #warning "Using GNU EXTENSIONS highly improves security \ of this program, the other features are deprecated! \ Tried to define GNU extensions, if this fails \ change login.h." -#endif // ifndef _GNU_SOURCE +#endif /* !_GNU_SOURCE */ #define GCRYPT_NO_DEPRECATED // we dont want to use old library routines #define HASH /* IF THIS TOKEN IS UNDEF'D YOU HAVE A SQLITE INTERFACE PROGRAM WITHOUT HASHING CAPABILITIES (pass match is done plain-text - so dont undef this) */ -#define DATABASE "ex1.db" /* path to a sqlite3 database - specify full db path if db is not in binary's folder or launch binary from db's folder */ +#define DATABASE "ex1.sql" /* path to a sqlite3 database - specify full db path if db is not in binary's folder or launch binary from db's folder */ /* multi-platform string routines */ -#if defined _GNU_SOURCE +#ifdef _GNU_SOURCE size_t strnlen(const char* string, size_t maxlen); - #define stringlength(x) strnlen(x, USERBUF) - #define longstringlength(x) strnlen(x, LARGEBUF + 40) - #define stringconcat(s1, s2) strncat(s1, s2, USERBUF) + #define stringlength(x) strnlen(x, USERBUF) + #define longstringlength(x) strnlen(x, LARGEBUF) + #define stringconcat(s1, s2) strncat(s1, s2, USERBUF) + #define stringcompare(s1, s2) strncmp(s1, s2, USERBUF) + #define stringcopy(s1, s2) strncpy(s1, s2, USERBUF) #elif _BSD_SOURCE - #define stringconcat(s1, s2) strncat(s1, s2, USERBUF) - #define longstringlength(x) strlen(x) - #define stringlength(x) strlen(x) + #define stringconcat(s1, s2) strncat(s1, s2, USERBUF) + #define longstringlength(x) strlen(x) + #define stringlength(x) strlen(x) + #define stringcompare(s1, s2) strncmp(s1, s2, USERBUF) + #define stringcopy(s1, s2) strncpy(s1, s2, USERBUF) #else /* !_GNU_SOURCE && !_BSD_SOURCE */ - #define longstringlength(x) strlen(x) - #define stringlength(x) strlen(x) - #define stringconcat(s1, s2) strcat(s1, s2) + #define longstringlength(x) strlen(x) + #define stringlength(x) strlen(x) + #define stringconcat(s1, s2) strcat(s1, s2) + #define stringcompare(s1, s2) strcmp(s1, s2) + #define stringcopy(s1, s2) strcpy(s1, s2) #endif /* buffers */ -#define LARGEBUF (1 << 12) // 4096 -#define USERBUF (1 << 8) // 256 +#define LARGEBUF (1 << 12) +#define USERBUF (1 << 9) /* user data definitions - mostly hidden - only in use in the interior of the login func */ -typedef struct { - char* username; - char* password; +typedef struct login_data { + char* username; char* hash; -} login_data; -typedef login_data* login_data_t; +} *login_data_t; + /* function prototypes */ -/* in this function im trying to handle the login event and interface with sqlite - * this will result in return values true as ok and false otherwise - * arg 1 and 2 are self explanatory (arg2 gets zero'd out in the process) - * arg3 is a bool asking if you want to supply your own SQL - * if arg3 is true supply your SQL statement as arg4 else NULL */ -bool login(const char* username, char* password, bool own_sql_statement_on, const char* sql_statement); -/* small function to build the matching - * sql string for our purposes - * arg1 is the username - * arg2 is to where to write the string */ -void build_sql_string(const char* username, char* destination); + /* this function calculates a string which represents - * the hash of the user's password */ -void hash_func(const char* value, char* destination, int algo, unsigned int flags); -void gcrypt_init( void ); -#endif // _LOGIN_H_ + * the hash of the user's password + * digest has to be min. gcry_md_get_algo_dlen(algo)*2 + */ +void hash_func(int algo, char* digest, const void* value, size_t len); +void gcrypt_init(void); + diff --git a/optimizers.txt b/optimizers.txt index d0177da..85f420c 100644 --- a/optimizers.txt +++ b/optimizers.txt @@ -1,166 +1,222 @@ The following options control optimizations: - -O - -Os - -falign-functions [enabled] - -falign-jumps [enabled] - -falign-labels [enabled] - -falign-loops [disabled] - -fargument-alias [enabled] - -fargument-noalias [disabled] - -fargument-noalias-anything [disabled] - -fargument-noalias-global [disabled] - -fasynchronous-unwind-tables [enabled] - -fbranch-count-reg [enabled] - -fbranch-probabilities [disabled] - -fbranch-target-load-optimize [disabled] - -fbranch-target-load-optimize2 [disabled] - -fbtr-bb-exclusive [disabled] - -fcaller-saves [enabled] - -fcommon [enabled] - -fconserve-stack [disabled] - -fcprop-registers [enabled] - -fcrossjumping [enabled] - -fcse-follow-jumps [enabled] - -fcse-skip-blocks [disabled] - -fcx-fortran-rules [disabled] - -fcx-limited-range [disabled] - -fdata-sections [disabled] - -fdce [enabled] - -fdefer-pop [enabled] - -fdelayed-branch [disabled] - -fdelete-null-pointer-checks [enabled] - -fdse [enabled] - -fearly-inlining [enabled] - -fexceptions [disabled] - -fexpensive-optimizations [enabled] - -ffinite-math-only [disabled] - -ffloat-store [disabled] - -fforward-propagate [enabled] - -fgcse [enabled] - -fgcse-after-reload [enabled] - -fgcse-las [disabled] - -fgcse-lm [enabled] - -fgcse-sm [disabled] - -fgraphite-identity [disabled] - -fguess-branch-probability [enabled] - -fhandle-exceptions - -fif-conversion [enabled] - -fif-conversion2 [enabled] - -finline-functions [enabled] - -finline-functions-called-once [enabled] - -finline-small-functions [enabled] - -fipa-cp [enabled] - -fipa-cp-clone [enabled] - -fipa-matrix-reorg [disabled] - -fipa-pta [disabled] - -fipa-pure-const [enabled] - -fipa-reference [enabled] - -fipa-type-escape [disabled] - -fivopts [enabled] - -fjump-tables [enabled] - -floop-block [disabled] - -floop-interchange [disabled] - -floop-strip-mine [disabled] - -fmath-errno [enabled] - -fmerge-all-constants [disabled] - -fmerge-constants [enabled] - -fmodulo-sched [disabled] - -fmove-loop-invariants [enabled] - -fnon-call-exceptions [disabled] - -fomit-frame-pointer [enabled] - -foptimize-register-move [enabled] - -foptimize-sibling-calls [enabled] - -fpack-struct [disabled] - -fpack-struct= - -fpeel-loops [disabled] - -fpeephole [enabled] - -fpeephole2 [enabled] - -fpredictive-commoning [enabled] - -fprefetch-loop-arrays [disabled] - -fpromote-loop-indices [disabled] - -freg-struct-return [disabled] - -fregmove [enabled] - -fremove-local-statics [disabled] - -frename-registers [enabled] - -freorder-blocks [enabled] - -freorder-blocks-and-partition [disabled] - -freorder-functions [enabled] - -frerun-cse-after-loop [enabled] - -freschedule-modulo-scheduled-loops [disabled] - -frounding-math [disabled] - -frtl-abstract-sequences [disabled] - -frtti - -fsched-interblock [enabled] - -fsched-spec [enabled] - -fsched-spec-load [disabled] - -fsched-spec-load-dangerous [disabled] - -fsched-stalled-insns [disabled] - -fsched-stalled-insns-dep [enabled] - -fsched2-use-superblocks [disabled] - -fsched2-use-traces [disabled] - -fschedule-insns [disabled] - -fschedule-insns2 [enabled] - -fsection-anchors [disabled] - -fsel-sched-pipelining [disabled] - -fsel-sched-pipelining-outer-loops [disabled] - -fsel-sched-reschedule-pipelined [disabled] - -fselective-scheduling [disabled] - -fselective-scheduling2 [disabled] - -fshort-double - -fshort-enums - -fshort-wchar - -fsignaling-nans [disabled] - -fsigned-zeros [enabled] - -fsingle-precision-constant [disabled] - -fsplit-ivs-in-unroller [enabled] - -fsplit-wide-types [enabled] - -fstrict-aliasing [enabled] - -fthread-jumps [enabled] - -fno-threadsafe-statics - -ftoplevel-reorder [enabled] - -ftrapping-math [enabled] - -ftrapv [disabled] - -ftree-builtin-call-dce [enabled] - -ftree-ccp [enabled] - -ftree-ch [enabled] - -ftree-copy-prop [enabled] - -ftree-copyrename [enabled] - -ftree-cselim [enabled] - -ftree-dce [enabled] - -ftree-dominator-opts [enabled] - -ftree-dse [enabled] - -ftree-fre [enabled] - -ftree-loop-distribution [disabled] - -ftree-loop-im [enabled] - -ftree-loop-ivcanon [enabled] - -ftree-loop-linear [disabled] - -ftree-loop-optimize [enabled] - -ftree-lrs [disabled] - -ftree-pre [enabled] - -ftree-pre-partial-partial [enabled] - -ftree-pre-partial-partial-obliviously [disabled] - -ftree-reassoc [enabled] - -ftree-scev-cprop [enabled] - -ftree-sink [enabled] - -ftree-sra [enabled] - -ftree-switch-conversion [enabled] - -ftree-ter [enabled] - -ftree-vect-loop-version [enabled] - -ftree-vectorize [enabled] - -ftree-vrp [enabled] - -funit-at-a-time [enabled] - -funroll-all-loops [disabled] - -funroll-loops [disabled] - -funsafe-loop-optimizations [disabled] - -funsafe-math-optimizations [disabled] - -funswitch-loops [enabled] - -funwind-tables [disabled] - -fvar-tracking [enabled] - -fvar-tracking-uninit [disabled] - -fvariable-expansion-in-unroller [disabled] - -fvect-cost-model [enabled] - -fvpt [disabled] - -fweb [enabled] - -fwhole-program [disabled] - -fwrapv [disabled] + -O + -Ofast + -Og + -Os + -faggressive-loop-optimizations [enabled] + -falign-functions [disabled] + -falign-jumps [disabled] + -falign-labels [disabled] + -falign-loops [disabled] + -fassociative-math [disabled] + -fasynchronous-unwind-tables [enabled] + -fauto-inc-dec [enabled] + -fbranch-count-reg [disabled] + -fbranch-probabilities [disabled] + -fbranch-target-load-optimize [disabled] + -fbranch-target-load-optimize2 [disabled] + -fbtr-bb-exclusive [disabled] + -fcaller-saves [disabled] + -fcombine-stack-adjustments [disabled] + -fcompare-elim [disabled] + -fconserve-stack [disabled] + -fcprop-registers [disabled] + -fcrossjumping [disabled] + -fcse-follow-jumps [disabled] + -fcx-fortran-rules [disabled] + -fcx-limited-range [disabled] + -fdce [enabled] + -fdefer-pop [disabled] + -fdelayed-branch [disabled] + -fdelete-dead-exceptions [disabled] + -fdelete-null-pointer-checks [enabled] + -fdevirtualize [disabled] + -fdevirtualize-speculatively [disabled] + -fdse [enabled] + -fearly-inlining [enabled] + -fexceptions [disabled] + -fexpensive-optimizations [disabled] + -ffinite-math-only [disabled] + -ffloat-store [disabled] + -fforward-propagate [disabled] + -ffp-contract= fast + -ffunction-cse [enabled] + -fgcse [disabled] + -fgcse-after-reload [disabled] + -fgcse-las [disabled] + -fgcse-lm [enabled] + -fgcse-sm [disabled] + -fgraphite [disabled] + -fgraphite-identity [disabled] + -fguess-branch-probability [disabled] + -fhandle-exceptions + -fhoist-adjacent-loads [disabled] + -fif-conversion [disabled] + -fif-conversion2 [disabled] + -findirect-inlining [disabled] + -finline [enabled] + -finline-atomics [enabled] + -finline-functions [disabled] + -finline-functions-called-once [disabled] + -finline-small-functions [disabled] + -fipa-cp [disabled] + -fipa-cp-alignment [disabled] + -fipa-cp-clone [disabled] + -fipa-icf [disabled] + -fipa-icf-functions [disabled] + -fipa-profile [disabled] + -fipa-pta [disabled] + -fipa-pure-const [disabled] + -fipa-ra [disabled] + -fipa-reference [disabled] + -fipa-sra [disabled] + -fira-algorithm= CB + -fira-hoist-pressure [enabled] + -fira-loop-pressure [disabled] + -fira-region= [default] + -fira-share-save-slots [enabled] + -fira-share-spill-slots [enabled] + -fisolate-erroneous-paths-attribute [disabled] + -fisolate-erroneous-paths-dereference [disabled] + -fivopts [enabled] + -fjump-tables [enabled] + -flifetime-dse [enabled] + -flive-range-shrinkage [disabled] + -floop-block [disabled] + -floop-interchange [disabled] + -floop-nest-optimize [disabled] + -floop-parallelize-all [disabled] + -floop-strip-mine [disabled] + -floop-unroll-and-jam [disabled] + -flra-remat [disabled] + -fmath-errno [enabled] + -fmodulo-sched [disabled] + -fmodulo-sched-allow-regmoves [disabled] + -fmove-loop-invariants [disabled] + -fnon-call-exceptions [disabled] + -fnothrow-opt [disabled] + -fomit-frame-pointer [disabled] + -fopt-info [disabled] + -foptimize-sibling-calls [disabled] + -foptimize-strlen [disabled] + -fpack-struct [disabled] + -fpack-struct= + -fpartial-inlining [disabled] + -fpeel-loops [disabled] + -fpeephole [enabled] + -fpeephole2 [disabled] + -fpredictive-commoning [disabled] + -fprefetch-loop-arrays [enabled] + -freciprocal-math [disabled] + -freg-struct-return [disabled] + -frename-registers [enabled] + -freorder-blocks [disabled] + -freorder-blocks-and-partition [disabled] + -freorder-functions [disabled] + -frerun-cse-after-loop [disabled] + -freschedule-modulo-scheduled-loops [disabled] + -frounding-math [disabled] + -frtti [enabled] + -fsched-critical-path-heuristic [enabled] + -fsched-dep-count-heuristic [enabled] + -fsched-group-heuristic [enabled] + -fsched-interblock [enabled] + -fsched-last-insn-heuristic [enabled] + -fsched-pressure [disabled] + -fsched-rank-heuristic [enabled] + -fsched-spec [enabled] + -fsched-spec-insn-heuristic [enabled] + -fsched-spec-load [disabled] + -fsched-spec-load-dangerous [disabled] + -fsched-stalled-insns [disabled] + -fsched-stalled-insns-dep [enabled] + -fsched-stalled-insns-dep= + -fsched-stalled-insns= + -fsched2-use-superblocks [disabled] + -fschedule-fusion [enabled] + -fschedule-insns [disabled] + -fschedule-insns2 [disabled] + -fsection-anchors [disabled] + -fsel-sched-pipelining [disabled] + -fsel-sched-pipelining-outer-loops [disabled] + -fsel-sched-reschedule-pipelined [disabled] + -fselective-scheduling [disabled] + -fselective-scheduling2 [disabled] + -fshort-double [disabled] + -fshort-enums [enabled] + -fshort-wchar [disabled] + -fshrink-wrap [disabled] + -fsignaling-nans [disabled] + -fsigned-zeros [enabled] + -fsimd-cost-model= unlimited + -fsingle-precision-constant [disabled] + -fsplit-ivs-in-unroller [enabled] + -fsplit-wide-types [disabled] + -fssa-phiopt [disabled] + -fstack-reuse= all + -fstdarg-opt [enabled] + -fstrict-aliasing [disabled] + -fstrict-enums [disabled] + -fstrict-overflow [disabled] + -fstrict-volatile-bitfields [enabled] + -fthread-jumps [disabled] + -fno-threadsafe-statics [enabled] + -ftracer [disabled] + -ftrapping-math [enabled] + -ftrapv [disabled] + -ftree-bit-ccp [disabled] + -ftree-builtin-call-dce [disabled] + -ftree-ccp [disabled] + -ftree-ch [disabled] + -ftree-coalesce-inlined-vars [disabled] + -ftree-coalesce-vars [enabled] + -ftree-copy-prop [disabled] + -ftree-copyrename [disabled] + -ftree-cselim [enabled] + -ftree-dce [disabled] + -ftree-dominator-opts [disabled] + -ftree-dse [disabled] + -ftree-forwprop [enabled] + -ftree-fre [disabled] + -ftree-loop-distribute-patterns [disabled] + -ftree-loop-distribution [disabled] + -ftree-loop-if-convert [enabled] + -ftree-loop-if-convert-stores [disabled] + -ftree-loop-im [enabled] + -ftree-loop-ivcanon [enabled] + -ftree-loop-optimize [enabled] + -ftree-loop-vectorize [disabled] + -ftree-lrs [disabled] + -ftree-parallelize-loops= 0x1 + -ftree-partial-pre [disabled] + -ftree-phiprop [enabled] + -ftree-pre [disabled] + -ftree-pta [disabled] + -ftree-reassoc [enabled] + -ftree-scev-cprop [enabled] + -ftree-sink [disabled] + -ftree-slp-vectorize [disabled] + -ftree-slsr [disabled] + -ftree-sra [disabled] + -ftree-switch-conversion [disabled] + -ftree-tail-merge [disabled] + -ftree-ter [disabled] + -ftree-vectorize [disabled] + -ftree-vrp [disabled] + -funroll-all-loops [disabled] + -funroll-loops [disabled] + -funsafe-loop-optimizations [disabled] + -funsafe-math-optimizations [disabled] + -funswitch-loops [disabled] + -funwind-tables [disabled] + -fvar-tracking [enabled] + -fvar-tracking-assignments [enabled] + -fvar-tracking-assignments-toggle [disabled] + -fvar-tracking-uninit [disabled] + -fvariable-expansion-in-unroller [disabled] + -fvect-cost-model= [default] + -fvpt [disabled] + -fweb [enabled] + -fwrapv [disabled] +