diff options
Diffstat (limited to 'src/encryption.c')
| -rw-r--r-- | src/encryption.c | 544 |
1 files changed, 295 insertions, 249 deletions
diff --git a/src/encryption.c b/src/encryption.c index 65b8843..382f6d5 100644 --- a/src/encryption.c +++ b/src/encryption.c | |||
| @@ -1,12 +1,12 @@ | |||
| 1 | /** | 1 | /** |
| 2 | * @file encryption.c | 2 | * @file encryption.c |
| 3 | * @author syxhe (https://t.me/syxhe) | 3 | * @author syxhe (https://t.me/syxhe) |
| 4 | * @brief *Implementing `encryption.h`* | 4 | * @brief A collection of all encryption related functions |
| 5 | * @version 0.1 | 5 | * @version 0.1 |
| 6 | * @date 2025-06-09 | 6 | * @date 2025-06-09 |
| 7 | * | 7 | * |
| 8 | * @copyright Copyright (c) 2025 | 8 | * @copyright Copyright (c) 2025 |
| 9 | * | 9 | * |
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | // TODO: Go back and make sure every function has proper error handling | 12 | // TODO: Go back and make sure every function has proper error handling |
| @@ -14,11 +14,16 @@ | |||
| 14 | // I need to make sure every single function in this file returns with an indicated error instead of nuking the whole program with | 14 | // I need to make sure every single function in this file returns with an indicated error instead of nuking the whole program with |
| 15 | // error() | 15 | // error() |
| 16 | 16 | ||
| 17 | #ifndef __VXGG_REWRITE___ENCRYPTION_C___1481879318188___ | ||
| 18 | #define __VXGG_REWRITE___ENCRYPTION_C___1481879318188___ | ||
| 19 | |||
| 20 | |||
| 17 | #define _GNU_SOURCE | 21 | #define _GNU_SOURCE |
| 18 | 22 | ||
| 19 | #include "shared.h" | 23 | #define TPSIZE (1<<13) |
| 20 | #include "encryption.h" | 24 | |
| 21 | #include "threadpool.h" | 25 | #include "shared.c" |
| 26 | #include "threadpool.c" | ||
| 22 | 27 | ||
| 23 | #include <sodium.h> | 28 | #include <sodium.h> |
| 24 | 29 | ||
| @@ -33,16 +38,91 @@ | |||
| 33 | #include <fcntl.h> | 38 | #include <fcntl.h> |
| 34 | #include <stdio.h> | 39 | #include <stdio.h> |
| 35 | 40 | ||
| 41 | /// Determines whether any function that calls libsodium functions also checks to make sure libsodium is actually initialized. May | ||
| 42 | /// cause unexpected issues with early exiting due to libsodium failing to initialize properly. It's recommended that you just | ||
| 43 | /// manually run `sodium_init()` in some main or init function of your own so that you can deal with a potential error yourself | ||
| 44 | #define ___VXGG___ALWAYS_CHECK_LIBSODIUM___ 1 | ||
| 45 | |||
| 46 | /// Grants access to the `vxgg_setsodiumfailcb` function, which can be used to set a custom callback for what to do when libsodium | ||
| 47 | /// fails upon initialization | ||
| 48 | #define ___VXGG___USE_CLS_CALLBACK___ 1 | ||
| 49 | |||
| 50 | /// Chunk size for en/decryption. I originally wanted to use st_blksize from stat(), but given that those chunks may be of different | ||
| 51 | /// sizes between computers / filesystems / architectures / files, it's easier to just have this be a consistent macro | ||
| 52 | #define CHUNKSIZE (1 << 9) | ||
| 53 | |||
| 54 | // Fuck reading from a file. Even if someone ran strings on the binary and got this they wouldn't be able to regenerate the key | ||
| 55 | //! A list of possible words for password creation | ||
| 56 | #define PASSWORD_WORDS (\ | ||
| 57 | (const char * const []){\ | ||
| 58 | "the", "of", "to", "and", "for", "our", "their", "has", "in", "he", "a", "them", "that", "these", "by", "have", "we", \ | ||
| 59 | "us", "people", "which", "all", "is", "with", "laws", "be", "are", "his", "states", "on", "they", "right", "it", "from", \ | ||
| 60 | "government", "such", "among", "powers", "most", "an", "time", "should", "new", "as", "been", "colonies", "assent", \ | ||
| 61 | "large", "at", "independent", "free", "united", "when", "mankind", "hold", "rights", "governments", "consent", "its", \ | ||
| 62 | "long", "themselves", "abolishing", "usurpations", "absolute", "repeated", "this", "world", "refused", "pass", "other", \ | ||
| 63 | "others", "without", "justice", "peace", "power", "seas", "war", "do", "declaration", "america", "becomes", "necessary", \ | ||
| 64 | "political", "equal", "declare", "causes", "separation", "men", "happiness", "any", "form", "alter", "or", "will", \ | ||
| 65 | "forms", "same", "object", "off", "necessity", "history", "great", "britain", "tyranny", "over", "public", "good", \ | ||
| 66 | "unless", "suspended", "so", "would", "legislature", "only", "legislative", "bodies", "purpose", "into", "dissolved", \ | ||
| 67 | "state", "endeavoured", "refusing", "hither", "conditions", "establishing", "offices", "out", "armies", "legislatures", \ | ||
| 68 | "render", "jurisdiction", "foreign", "acts", "pretended", "trial", "inhabitants", "cases", "transporting", "rule", \ | ||
| 69 | "declaring", "here", "protection", "against", "lives", "circumstances", "ages", "totally", "friends", "brethren", "whose", \ | ||
| 70 | "every", "may", "therefore", "ought", "unanimous", "thirteen", "course", "human", "events", "one", "dissolve", "bands", \ | ||
| 71 | "connected", "another", "assume", "earth", "separate", "station", "nature", "natures", "god", "entitle", "decent", \ | ||
| 72 | "respect", "opinions", "requires", "impel", "truths", "self", "evident", "created", "endowed", "creator", "certain", \ | ||
| 73 | "unalienable", "life", "liberty", "pursuit", "secure", "instituted", "deriving", "just", "governed", "whenever", \ | ||
| 74 | "destructive", "ends", "abolish", "institute", "laying", "foundation", "principles", "organizing", "shall", "seem", \ | ||
| 75 | "likely", "effect", "safety", "prudence", "indeed", "dictate", "established", "not", "changed", "light", "transient", \ | ||
| 76 | "accordingly", "experience", "hath", "shewn", "more", "disposed", "suffer", "while", "evils", "sufferable", "than", \ | ||
| 77 | "accustomed", "but", "train", "abuses", "pursuing", "invariably", "evinces", "design", "reduce", "under", "despotism", \ | ||
| 78 | "duty", "throw", "provide", "guards", "future", "security", "patient", "sufferance", "now", "constrains", "former", \ | ||
| 79 | "systems", "present", "king", "injuries", "having", "direct", "establishment", "prove", "let", "facts", "submitted", \ | ||
| 80 | "candid", "wholesome", "forbidden", "governors", "immediate", "pressing", "importance", "operation", "till", "obtained", \ | ||
| 81 | "utterly", "neglected", "attend", "accommodation", "districts", "those", "relinquish", "representation", "inestimable", \ | ||
| 82 | "formidable", "tyrants", "called", "together", "places", "unusual", "uncomfortable", "distant", "depository", "records", \ | ||
| 83 | "sole", "fatiguing", "compliance", "measures", "representative", "houses", "repeatedly", "opposing", "manly", "firmness", \ | ||
| 84 | "invasions", "after", "dissolutions", "cause", "elected", "whereby", "incapable", "annihilation", "returned", "exercise", \ | ||
| 85 | "remaining", "mean", "exposed", "dangers", "invasion", "convulsions", "within", "prevent", "population", "obstructing", \ | ||
| 86 | "naturalization", "foreigners", "encourage", "migrations", "raising", "appropriations", "lands", "obstructed", \ | ||
| 87 | "administration", "judiciary", "made", "judges", "dependent", "alone", "tenure", "amount", "payment", "salaries", \ | ||
| 88 | "erected", "multitude", "sent", "swarms", "officers", "harrass", "eat", "substance", "kept", "times", "standing", \ | ||
| 89 | "affected", "military", "superior", "civil", "combined", "subject", "constitution", "unacknowledged", "giving", \ | ||
| 90 | "legislation", "quartering", "armed", "troops", "protecting", "mock", "punishment", "murders", "commit", "cutting", \ | ||
| 91 | "trade", "parts", "imposing", "taxes", "depriving", "many", "benefits", "jury", "beyond", "tried", "offences", "system", \ | ||
| 92 | "english", "neighbouring", "province", "therein", "arbitrary", "enlarging", "boundaries", "once", "example", "fit", \ | ||
| 93 | "instrument", "introducing", "taking", "away", "charters", "valuable", "altering", "fundamentally", "suspending", "own", \ | ||
| 94 | "invested", "legislate", "whatsoever", "abdicated", "waging", "plundered", "ravaged", "coasts", "burnt", "towns", \ | ||
| 95 | "destroyed", "mercenaries", "compleat", "works", "death", "desolation", "already", "begun", "cruelty", "perfidy", \ | ||
| 96 | "scarcely", "paralleled", "barbarous", "unworthy", "head", "civilized", "nation", "constrained", "fellow", "citizens", \ | ||
| 97 | "taken", "captive", "high", "bear", "arms", "country", "become", "executioners", "fall", "hands", "excited", "domestic", \ | ||
| 98 | "insurrections", "amongst", "bring", "frontiers", "merciless", "indian", "savages", "known", "warfare", "undistinguished", \ | ||
| 99 | "destruction", "sexes", "stage", "oppressions", "petitioned", "redress", "humble", "terms", "petitions", "answered", \ | ||
| 100 | "injury", "prince", "character", "thus", "marked", "act", "define", "tyrant", "unfit", "ruler", "nor", "wanting", \ | ||
| 101 | "attentions", "brittish", "warned", "attempts", "extend", "unwarrantable", "reminded", "emigration", "settlement", \ | ||
| 102 | "appealed", "native", "magnanimity", "conjured", "ties", "common", "kindred", "disavow", "inevitably", "interrupt", \ | ||
| 103 | "connections", "correspondence", "too", "deaf", "voice", "consanguinity", "must", "acquiesce", "denounces", "rest", \ | ||
| 104 | "enemies", "representatives", "general", "congress", "assembled", "appealing", "supreme", "judge", "rectitude", \ | ||
| 105 | "intentions", "name", "authority", "solemnly", "publish", "absolved", "allegiance", "british", "crown", "connection", \ | ||
| 106 | "between", "full", "levy", "conclude", "contract", "alliances", "establish", "commerce", "things", "support", "firm", \ | ||
| 107 | "reliance", "divine", "providence", "mutually", "pledge", "each", "fortunes", "sacred", "honor"\ | ||
| 108 | }\ | ||
| 109 | ) | ||
| 110 | //! Short macro for getting the `PASSWORD_WORDS` array size | ||
| 111 | #define PASSWORD_WORDS_LEN (STATIC_ARRAY_LEN(PASSWORD_WORDS)) | ||
| 112 | |||
| 36 | #if ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 | 113 | #if ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 |
| 37 | #if ___VXGG___USE_CLS_CALLBACK___ > 0 | 114 | #if ___VXGG___USE_CLS_CALLBACK___ > 0 |
| 38 | 115 | ||
| 116 | //! Definition for the callback function that fires when a call to checksodium fails | ||
| 117 | typedef void (*vxgg_naclfailcb)(void*); | ||
| 118 | |||
| 39 | /** | 119 | /** |
| 40 | * @brief Default sodium init fail callback for use in `checksodiumcb()` | 120 | * @brief Default sodium init fail callback for use in `checksodiumcb()` |
| 41 | * | 121 | * |
| 42 | * @param none Unused param to fit callback spec | 122 | * @param none Unused param to fit callback spec |
| 43 | */ | 123 | */ |
| 44 | static void naclfaildefault(void *none) { | 124 | static void naclfaildefault(void *none) { |
| 45 | none = none; // Makes gcc happy | 125 | none = none; // Makes gcc happy |
| 46 | if(___VXGG___VERBOSE_ERRORS___) | 126 | if(___VXGG___VERBOSE_ERRORS___) |
| 47 | error(1, ENOTSUP, "<naclfaildefault> Couldn't initialize sodium for some reason. Quitting..."); | 127 | error(1, ENOTSUP, "<naclfaildefault> Couldn't initialize sodium for some reason. Quitting..."); |
| 48 | exit(EXIT_FAILURE); | 128 | exit(EXIT_FAILURE); |
| @@ -50,7 +130,7 @@ static void naclfaildefault(void *none) { | |||
| 50 | 130 | ||
| 51 | /** | 131 | /** |
| 52 | * @brief Internal function to deal with the `___VXGG___USE_CLS_CALLBACK___` macro | 132 | * @brief Internal function to deal with the `___VXGG___USE_CLS_CALLBACK___` macro |
| 53 | * | 133 | * |
| 54 | * `checksodiumcb()` runs the sodium function `sodium_init()` and on error calls the provided callback with the provided data. The | 134 | * `checksodiumcb()` runs the sodium function `sodium_init()` and on error calls the provided callback with the provided data. The |
| 55 | * callback and data default to `naclfaildefault` and `NULL`, but can be changed when the `set` parameter is non-zero. When `set` | 135 | * callback and data default to `naclfaildefault` and `NULL`, but can be changed when the `set` parameter is non-zero. When `set` |
| 56 | * is zero, the sodium init check is preformed | 136 | * is zero, the sodium init check is preformed |
| @@ -59,11 +139,11 @@ static void naclfaildefault(void *none) { | |||
| 59 | * macros are both greater than 0 when compiling, and 2: a function in `encryption.c` calls a function originating from sodium. This | 139 | * macros are both greater than 0 when compiling, and 2: a function in `encryption.c` calls a function originating from sodium. This |
| 60 | * function exists as a way to deal with sodium failing yourself, instead of instantly calling `exit()`. If you don't care to handle | 140 | * function exists as a way to deal with sodium failing yourself, instead of instantly calling `exit()`. If you don't care to handle |
| 61 | * it, or are initializing sodium yourself, this is unnecessary | 141 | * it, or are initializing sodium yourself, this is unnecessary |
| 62 | * | 142 | * |
| 63 | * @param callback A callback to be ran when sodium fails to initialize itself. Ignored if `set` is zero. Must be non-null when `set` is non-zero | 143 | * @param callback A callback to be ran when sodium fails to initialize itself. Ignored if `set` is zero. Must be non-null when `set` is non-zero |
| 64 | * @param data Data to be passed to the callback when it is fired. Ignored if `set` is zero. May be null | 144 | * @param data Data to be passed to the callback when it is fired. Ignored if `set` is zero. May be null |
| 65 | * @param set Flag on whether to check sodium or to set a new callback and data pair. Checks sodium when zero, sets callback & data when non-zero | 145 | * @param set Flag on whether to check sodium or to set a new callback and data pair. Checks sodium when zero, sets callback & data when non-zero |
| 66 | * @retval int | 146 | * @retval int |
| 67 | */ | 147 | */ |
| 68 | static int checksodiumcb(vxgg_naclfailcb const callback, void *data, unsigned char set) { | 148 | static int checksodiumcb(vxgg_naclfailcb const callback, void *data, unsigned char set) { |
| 69 | static vxgg_naclfailcb cb = naclfaildefault; | 149 | static vxgg_naclfailcb cb = naclfaildefault; |
| @@ -97,9 +177,9 @@ void vxgg_setsodiumfailcb(vxgg_naclfailcb cb, void *data) { | |||
| 97 | * @brief Simple function to check if sodium has been properly initialized | 177 | * @brief Simple function to check if sodium has been properly initialized |
| 98 | * | 178 | * |
| 99 | * `checksodium()` will run in functions located in `encryption.h` only when the macro `___VXGG___ALWAYS_CHECK_LIBSODIUM___` is greater | 179 | * `checksodium()` will run in functions located in `encryption.h` only when the macro `___VXGG___ALWAYS_CHECK_LIBSODIUM___` is greater |
| 100 | * than zero when compiling. It will call the `checksodiumcb()` function if compiled with the `___VXGG___USE_CLS_CALLBACK___` macro. | 180 | * than zero when compiling. It will call the `checksodiumcb()` function if compiled with the `___VXGG___USE_CLS_CALLBACK___` macro. |
| 101 | * When called, checksodium will run `sodium_init()`, and will either run the user-defined callback or `XALLOC_EXIT`. | 181 | * When called, checksodium will run `sodium_init()`, and will either run the user-defined callback or `XALLOC_EXIT`. |
| 102 | * | 182 | * |
| 103 | */ | 183 | */ |
| 104 | static void checksodium(void) { | 184 | static void checksodium(void) { |
| 105 | #if ___VXGG___USE_CLS_CALLBACK___ > 0 | 185 | #if ___VXGG___USE_CLS_CALLBACK___ > 0 |
| @@ -112,17 +192,30 @@ static void checksodium(void) { | |||
| 112 | } | 192 | } |
| 113 | 193 | ||
| 114 | #endif | 194 | #endif |
| 115 | 195 | ||
| 116 | return; | 196 | return; |
| 117 | } | 197 | } |
| 118 | 198 | ||
| 119 | #endif | 199 | #endif |
| 120 | 200 | ||
| 201 | /** | ||
| 202 | * @brief open() with the flags O_TMPFILE, O_WRONLY, O_CLOEXEC, and O_SYNC. Opened with mode S_IRUSR, S_IWUSR | ||
| 203 | * | ||
| 204 | * @param dest The filename the new descriptor should have. Must be non-null | ||
| 205 | * @retval (int)[-1,int] A new file descriptor. -1 on error | ||
| 206 | */ | ||
| 121 | int maketmp(const char * const dest) { | 207 | int maketmp(const char * const dest) { |
| 122 | if(!dest) ERRRET(EINVAL, -1); | 208 | if(!dest) ERRRET(EINVAL, -1); |
| 123 | return open(dest, (O_TMPFILE | O_WRONLY | O_CLOEXEC | O_SYNC), (S_IRUSR | S_IWUSR)); | 209 | return open(dest, (O_TMPFILE | O_WRONLY | O_CLOEXEC | O_SYNC), (S_IRUSR | S_IWUSR)); |
| 124 | } | 210 | } |
| 125 | 211 | ||
| 212 | /** | ||
| 213 | * @brief Link a file descriptor into the filesystem | ||
| 214 | * | ||
| 215 | * @param target New filename the descriptor should have | ||
| 216 | * @param tgfd The file descriptor to link | ||
| 217 | * @retval (int)[-1, 0] 0 on success, -1 on error | ||
| 218 | */ | ||
| 126 | int linkto(const char * const target, int tgfd) { | 219 | int linkto(const char * const target, int tgfd) { |
| 127 | if(!target) ERRRET(EINVAL, -1); | 220 | if(!target) ERRRET(EINVAL, -1); |
| 128 | 221 | ||
| @@ -131,6 +224,9 @@ int linkto(const char * const target, int tgfd) { | |||
| 131 | if(!path) | 224 | if(!path) |
| 132 | ERROR(1, errno, "<linkto> Couldn't get path to move file into system",); | 225 | ERROR(1, errno, "<linkto> Couldn't get path to move file into system",); |
| 133 | remove(target); // Make sure an old version isn't sticking around (it's not catastrophic if this fails, but it should be noted or logged somewhere) | 226 | remove(target); // Make sure an old version isn't sticking around (it's not catastrophic if this fails, but it should be noted or logged somewhere) |
| 227 | // TODO: This is bad. If a file gets deleted and the program crashes before the new one can get linked into the fs, the data is lost. | ||
| 228 | // I really should write a function entirely dedicated to dealing with linking | ||
| 229 | |||
| 134 | int res = linkat(AT_FDCWD, path, AT_FDCWD, target, AT_SYMLINK_FOLLOW); | 230 | int res = linkat(AT_FDCWD, path, AT_FDCWD, target, AT_SYMLINK_FOLLOW); |
| 135 | free(path); | 231 | free(path); |
| 136 | return res; | 232 | return res; |
| @@ -150,6 +246,132 @@ static void __ucl_fclose(void *file) { | |||
| 150 | return; | 246 | return; |
| 151 | } | 247 | } |
| 152 | 248 | ||
| 249 | /** | ||
| 250 | * @brief Encrypt src to dst using libsodium's xchacha encryption suite | ||
| 251 | * | ||
| 252 | * @param src File to encrypt | ||
| 253 | * @param dst Destination to write encrypted file | ||
| 254 | * @param key Key for encryption | ||
| 255 | * @retval (int)[-1, 0] Returns 0 on success, sets errno and returns -1 on error | ||
| 256 | */ | ||
| 257 | int encrypttofile(FILE *src, FILE *dst, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]) { | ||
| 258 | if(!src || !dst || !key) ERRRET(EINVAL, -1); | ||
| 259 | #if ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 | ||
| 260 | checksodium(); | ||
| 261 | #endif | ||
| 262 | |||
| 263 | unsigned char buf[CHUNKSIZE], cbuf[CHUNKSIZE + crypto_secretstream_xchacha20poly1305_ABYTES]; | ||
| 264 | unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES]; | ||
| 265 | crypto_secretstream_xchacha20poly1305_state state; | ||
| 266 | unsigned long long cbuflen; | ||
| 267 | unsigned char tag; | ||
| 268 | size_t bytesread; | ||
| 269 | int eof; | ||
| 270 | |||
| 271 | // Write the header | ||
| 272 | crypto_secretstream_xchacha20poly1305_init_push(&state, header, key); | ||
| 273 | if(fwrite(header, 1, sizeof(header), dst) < sizeof(header)) { | ||
| 274 | if(ferror(dst)) { | ||
| 275 | WARN(errno, "<encrypttofile> Could not write header",); | ||
| 276 | return -1; | ||
| 277 | } | ||
| 278 | } | ||
| 279 | |||
| 280 | // Encrypt each chunk | ||
| 281 | do { | ||
| 282 | if((bytesread = fread(buf, 1, sizeof(buf), src)) < sizeof(buf)) | ||
| 283 | if(ferror(src)) { | ||
| 284 | WARN(errno, "<encrypttofile> Could not read from source",); | ||
| 285 | return -1; | ||
| 286 | } | ||
| 287 | eof = feof(src); | ||
| 288 | tag = eof ? crypto_secretstream_xchacha20poly1305_TAG_FINAL : 0; | ||
| 289 | |||
| 290 | crypto_secretstream_xchacha20poly1305_push(&state, cbuf, &cbuflen, buf, bytesread, NULL, 0, tag); | ||
| 291 | if(fwrite(cbuf, 1, (size_t)cbuflen, dst) < (size_t)cbuflen) | ||
| 292 | if(ferror(dst)) { | ||
| 293 | WARN(errno, "<encrypttofile> Could not write to target",); | ||
| 294 | return -1; | ||
| 295 | } | ||
| 296 | } while (!eof); | ||
| 297 | |||
| 298 | return 0; | ||
| 299 | } | ||
| 300 | |||
| 301 | /** | ||
| 302 | * @brief Decrypt src to dst using libsodium's xchacha encryption suite | ||
| 303 | * | ||
| 304 | * @param src File to decrypt | ||
| 305 | * @param dst Destination to write decrypted file | ||
| 306 | * @param key Key used to encrypt | ||
| 307 | * @retval (int)[-1, 0] Returns 0 on success, sets errno and returns -1 on error | ||
| 308 | */ | ||
| 309 | int decrypttofile(FILE *src, FILE *dst, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]) { | ||
| 310 | if(!src || !dst || !key) ERRRET(EINVAL, -1); | ||
| 311 | #if ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 | ||
| 312 | checksodium(); | ||
| 313 | #endif | ||
| 314 | |||
| 315 | unsigned char cbuf[CHUNKSIZE + crypto_secretstream_xchacha20poly1305_ABYTES], buf[CHUNKSIZE]; | ||
| 316 | unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES]; | ||
| 317 | crypto_secretstream_xchacha20poly1305_state state; | ||
| 318 | unsigned long long buflen; | ||
| 319 | unsigned char tag; | ||
| 320 | size_t bytesread; | ||
| 321 | int eof; | ||
| 322 | |||
| 323 | // Read the header | ||
| 324 | if(fread(header, 1, sizeof(header), src) < sizeof(header)) { | ||
| 325 | if(ferror(src)) { | ||
| 326 | WARN(errno, "<decrypttofile> Couldn't read header", ); | ||
| 327 | return -1; | ||
| 328 | } | ||
| 329 | } | ||
| 330 | |||
| 331 | // Make sure the header isn't fuckey | ||
| 332 | if(crypto_secretstream_xchacha20poly1305_init_pull(&state, header, key) != 0) { | ||
| 333 | WARN(errno, "<decrypttofile> Incomplete header", ); | ||
| 334 | return -1; | ||
| 335 | } | ||
| 336 | |||
| 337 | // Decrypt each chunk | ||
| 338 | do { | ||
| 339 | if((bytesread = fread(cbuf, 1, sizeof(cbuf), src)) < sizeof(cbuf)) { | ||
| 340 | if(ferror(src)) { | ||
| 341 | WARN(errno, "<decrypttofile> Ran into problem reading for decryption", ); | ||
| 342 | return -1; | ||
| 343 | } | ||
| 344 | } | ||
| 345 | eof = feof(src); | ||
| 346 | |||
| 347 | if (crypto_secretstream_xchacha20poly1305_pull(&state, buf, &buflen, &tag, cbuf, bytesread, NULL, 0) != 0) { | ||
| 348 | WARN(errno, "<decrypttofile> Corrupted chunk", ); | ||
| 349 | return -1; | ||
| 350 | } | ||
| 351 | |||
| 352 | if(tag == crypto_secretstream_xchacha20poly1305_TAG_FINAL && !eof) { | ||
| 353 | WARN(errno, "<decrypttofile> End of stream before end of file", ); | ||
| 354 | return -1; | ||
| 355 | } | ||
| 356 | if(eof && tag != crypto_secretstream_xchacha20poly1305_TAG_FINAL) { | ||
| 357 | WARN(errno, "<decrypttofile> End of file before end of stream", ); | ||
| 358 | return -1; | ||
| 359 | } | ||
| 360 | |||
| 361 | fwrite(buf, 1, (size_t)buflen, dst); | ||
| 362 | } while(! eof); | ||
| 363 | |||
| 364 | return 0; | ||
| 365 | } | ||
| 366 | |||
| 367 | /** | ||
| 368 | * @brief Encrypt file at `target` to `output` using Linux's named temp file system to do it in the background | ||
| 369 | * | ||
| 370 | * @param target | ||
| 371 | * @param output | ||
| 372 | * @param key | ||
| 373 | * @retval (int)[,] | ||
| 374 | */ | ||
| 153 | int encryptviatmp(const char * const target, const char * const output, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]) { | 375 | int encryptviatmp(const char * const target, const char * const output, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]) { |
| 154 | #if ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 | 376 | #if ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 |
| 155 | checksodium(); | 377 | checksodium(); |
| @@ -203,7 +425,7 @@ int encryptviatmp(const char * const target, const char * const output, const un | |||
| 203 | // Not going to bother changing this, it probably is catastrophic if an error happens when it shouldn't | 425 | // Not going to bother changing this, it probably is catastrophic if an error happens when it shouldn't |
| 204 | if(encrypttofile(src, dst, key) < 0) | 426 | if(encrypttofile(src, dst, key) < 0) |
| 205 | ERROR(1, ENOTRECOVERABLE, "<encryptviatmp> I don't even have a way to cause an error here. How did you do it?",); | 427 | ERROR(1, ENOTRECOVERABLE, "<encryptviatmp> I don't even have a way to cause an error here. How did you do it?",); |
| 206 | 428 | ||
| 207 | // Link the temp file into the system | 429 | // Link the temp file into the system |
| 208 | if(linkto(output, tfd) < 0) | 430 | if(linkto(output, tfd) < 0) |
| 209 | WARN(errno, "<encryptviatmp> Could not link \"%s\" into system after encryption", , output); | 431 | WARN(errno, "<encryptviatmp> Could not link \"%s\" into system after encryption", , output); |
| @@ -213,21 +435,29 @@ int encryptviatmp(const char * const target, const char * const output, const un | |||
| 213 | fclose(src); | 435 | fclose(src); |
| 214 | // fclose alco closes fd and tfd, as fdopen does not dup the file descriptors | 436 | // fclose alco closes fd and tfd, as fdopen does not dup the file descriptors |
| 215 | ); | 437 | ); |
| 216 | 438 | ||
| 217 | 439 | ||
| 218 | cleanup_CNDFIRE(); | 440 | cleanup_CNDFIRE(); |
| 219 | if(cleanup_ERRORFLAGGED) | 441 | if(cleanup_ERRORFLAGGED) |
| 220 | return -1; | 442 | return -1; |
| 221 | 443 | ||
| 222 | return 0; | 444 | return 0; |
| 223 | } | 445 | } |
| 224 | 446 | ||
| 447 | /** | ||
| 448 | * @brief Decrypt the file at `encrypted` to `target` | ||
| 449 | * | ||
| 450 | * @param encrypted | ||
| 451 | * @param target | ||
| 452 | * @param key | ||
| 453 | * @retval (int)[,] | ||
| 454 | */ | ||
| 225 | int decryptto(const char * const target, const char * const output, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]) { | 455 | int decryptto(const char * const target, const char * const output, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]) { |
| 226 | if(!target || !output || !key) ERRRET(EINVAL, -1); | 456 | if(!target || !output || !key) ERRRET(EINVAL, -1); |
| 227 | #if ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 | 457 | #if ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 |
| 228 | checksodium(); | 458 | checksodium(); |
| 229 | #endif | 459 | #endif |
| 230 | 460 | ||
| 231 | cleanup_CREATE(10); | 461 | cleanup_CREATE(10); |
| 232 | FILE *src, *dst; | 462 | FILE *src, *dst; |
| 233 | int fdst; | 463 | int fdst; |
| @@ -276,7 +506,7 @@ int decryptto(const char * const target, const char * const output, const unsign | |||
| 276 | if(cleanup_ERRORFLAGGED) | 506 | if(cleanup_ERRORFLAGGED) |
| 277 | return -1; | 507 | return -1; |
| 278 | 508 | ||
| 279 | // Note: If an error were to theoretically occur, which shouldn't be possible but I'm covering my bases here, after the | 509 | // Note: If an error were to theoretically occur, which shouldn't be possible but I'm covering my bases here, after the |
| 280 | // `dst = fdopen` line, a double close on the temp file descriptor would occur. I've been told that this is not catastrophic, | 510 | // `dst = fdopen` line, a double close on the temp file descriptor would occur. I've been told that this is not catastrophic, |
| 281 | // and considering how my multithreading works it *should* be fine, but it very well could cause problems. The easy solution is | 511 | // and considering how my multithreading works it *should* be fine, but it very well could cause problems. The easy solution is |
| 282 | // to man up and just write another cleanup function to pop the last thing off the stack, but again this is an error I can't | 512 | // to man up and just write another cleanup function to pop the last thing off the stack, but again this is an error I can't |
| @@ -285,108 +515,13 @@ int decryptto(const char * const target, const char * const output, const unsign | |||
| 285 | return 0; | 515 | return 0; |
| 286 | } | 516 | } |
| 287 | 517 | ||
| 288 | int encrypttofile(FILE *src, FILE *dst, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]) { | 518 | /** |
| 289 | if(!src || !dst || !key) ERRRET(EINVAL, -1); | 519 | * @brief Generate a password viable for use in the derivation of a key |
| 290 | #if ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 | 520 | * |
| 291 | checksodium(); | 521 | * @param str Pointer to a string. This will be filled by a malloc'ed string of words (the password). Must be non-null |
| 292 | #endif | 522 | * @param words The number of words to include in the password. A password of at least 20 words and probably not more than 40 is recommended |
| 293 | 523 | * @retval (int)[-1, words] On success, returns the number of words requested. On error, returns -1 and sets errno | |
| 294 | unsigned char buf[CHUNKSIZE], cbuf[CHUNKSIZE + crypto_secretstream_xchacha20poly1305_ABYTES]; | 524 | */ |
| 295 | unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES]; | ||
| 296 | crypto_secretstream_xchacha20poly1305_state state; | ||
| 297 | unsigned long long cbuflen; | ||
| 298 | unsigned char tag; | ||
| 299 | size_t bytesread; | ||
| 300 | int eof; | ||
| 301 | |||
| 302 | // Write the header | ||
| 303 | crypto_secretstream_xchacha20poly1305_init_push(&state, header, key); | ||
| 304 | if(fwrite(header, 1, sizeof(header), dst) < sizeof(header)) { | ||
| 305 | if(ferror(dst)) { | ||
| 306 | WARN(errno, "<encrypttofile> Could not write header",); | ||
| 307 | return -1; | ||
| 308 | } | ||
| 309 | } | ||
| 310 | |||
| 311 | // Encrypt each chunk | ||
| 312 | do { | ||
| 313 | if((bytesread = fread(buf, 1, sizeof(buf), src)) < sizeof(buf)) | ||
| 314 | if(ferror(src)) { | ||
| 315 | WARN(errno, "<encrypttofile> Could not read from source",); | ||
| 316 | return -1; | ||
| 317 | } | ||
| 318 | eof = feof(src); | ||
| 319 | tag = eof ? crypto_secretstream_xchacha20poly1305_TAG_FINAL : 0; | ||
| 320 | |||
| 321 | crypto_secretstream_xchacha20poly1305_push(&state, cbuf, &cbuflen, buf, bytesread, NULL, 0, tag); | ||
| 322 | if(fwrite(cbuf, 1, (size_t)cbuflen, dst) < (size_t)cbuflen) | ||
| 323 | if(ferror(dst)) { | ||
| 324 | WARN(errno, "<encrypttofile> Could not write to target",); | ||
| 325 | return -1; | ||
| 326 | } | ||
| 327 | } while (!eof); | ||
| 328 | |||
| 329 | return 0; | ||
| 330 | } | ||
| 331 | |||
| 332 | int decrypttofile(FILE *src, FILE *dst, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]) { | ||
| 333 | if(!src || !dst || !key) ERRRET(EINVAL, -1); | ||
| 334 | #if ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 | ||
| 335 | checksodium(); | ||
| 336 | #endif | ||
| 337 | |||
| 338 | unsigned char cbuf[CHUNKSIZE + crypto_secretstream_xchacha20poly1305_ABYTES], buf[CHUNKSIZE]; | ||
| 339 | unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES]; | ||
| 340 | crypto_secretstream_xchacha20poly1305_state state; | ||
| 341 | unsigned long long buflen; | ||
| 342 | unsigned char tag; | ||
| 343 | size_t bytesread; | ||
| 344 | int eof; | ||
| 345 | |||
| 346 | // Read the header | ||
| 347 | if(fread(header, 1, sizeof(header), src) < sizeof(header)) { | ||
| 348 | if(ferror(src)) { | ||
| 349 | WARN(errno, "<decrypttofile> Couldn't read header", ); | ||
| 350 | return -1; | ||
| 351 | } | ||
| 352 | } | ||
| 353 | |||
| 354 | // Make sure the header isn't fuckey | ||
| 355 | if(crypto_secretstream_xchacha20poly1305_init_pull(&state, header, key) != 0) { | ||
| 356 | WARN(errno, "<decrypttofile> Incomplete header", ); | ||
| 357 | return -1; | ||
| 358 | } | ||
| 359 | |||
| 360 | // Decrypt each chunk | ||
| 361 | do { | ||
| 362 | if((bytesread = fread(cbuf, 1, sizeof(cbuf), src)) < sizeof(cbuf)) { | ||
| 363 | if(ferror(src)) { | ||
| 364 | WARN(errno, "<decrypttofile> Ran into problem reading for decryption", ); | ||
| 365 | return -1; | ||
| 366 | } | ||
| 367 | } | ||
| 368 | eof = feof(src); | ||
| 369 | |||
| 370 | if (crypto_secretstream_xchacha20poly1305_pull(&state, buf, &buflen, &tag, cbuf, bytesread, NULL, 0) != 0) { | ||
| 371 | WARN(errno, "<decrypttofile> Corrupted chunk", ); | ||
| 372 | return -1; | ||
| 373 | } | ||
| 374 | |||
| 375 | if(tag == crypto_secretstream_xchacha20poly1305_TAG_FINAL && !eof) { | ||
| 376 | WARN(errno, "<decrypttofile> End of stream before end of file", ); | ||
| 377 | return -1; | ||
| 378 | } | ||
| 379 | if(eof && tag != crypto_secretstream_xchacha20poly1305_TAG_FINAL) { | ||
| 380 | WARN(errno, "<decrypttofile> End of file before end of stream", ); | ||
| 381 | return -1; | ||
| 382 | } | ||
| 383 | |||
| 384 | fwrite(buf, 1, (size_t)buflen, dst); | ||
| 385 | } while(! eof); | ||
| 386 | |||
| 387 | return 0; | ||
| 388 | } | ||
| 389 | |||
| 390 | int genpassword(char **str, unsigned int words) { | 525 | int genpassword(char **str, unsigned int words) { |
| 391 | // Early returns | 526 | // Early returns |
| 392 | if(words < 1) return 0; | 527 | if(words < 1) return 0; |
| @@ -402,7 +537,7 @@ int genpassword(char **str, unsigned int words) { | |||
| 402 | 537 | ||
| 403 | // Concat the rest of the words into the password (without leaking memory) | 538 | // Concat the rest of the words into the password (without leaking memory) |
| 404 | int ret; | 539 | int ret; |
| 405 | for(unsigned int i = 1; i < words; i++) { | 540 | for(unsigned int i = 1; i < words; i++) { |
| 406 | ret = asprintf(&tmp, "%s %s", lstr, PASSWORD_WORDS[randombytes_uniform(PASSWORD_WORDS_LEN)]); | 541 | ret = asprintf(&tmp, "%s %s", lstr, PASSWORD_WORDS[randombytes_uniform(PASSWORD_WORDS_LEN)]); |
| 407 | sodium_memzero(lstr, strlen(lstr) + 1); | 542 | sodium_memzero(lstr, strlen(lstr) + 1); |
| 408 | free(lstr); | 543 | free(lstr); |
| @@ -416,6 +551,14 @@ int genpassword(char **str, unsigned int words) { | |||
| 416 | return words; | 551 | return words; |
| 417 | } | 552 | } |
| 418 | 553 | ||
| 554 | /** | ||
| 555 | * @brief sodium_malloc wrapper. | ||
| 556 | * | ||
| 557 | * Calls `error()` or `abort()` depnding on the value of `___VXGG___XALLOC_EXIT_ON_ERROR___`. Will make sure libsodium is initialized if `___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0` | ||
| 558 | * | ||
| 559 | * @param size | ||
| 560 | * @retval (void*) A pointer to some data allocated via `sodium_malloc()` | ||
| 561 | */ | ||
| 419 | void* xsodium_malloc(size_t size) { | 562 | void* xsodium_malloc(size_t size) { |
| 420 | #if ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 | 563 | #if ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 |
| 421 | checksodium(); | 564 | checksodium(); |
| @@ -436,7 +579,7 @@ void* xsodium_malloc(size_t size) { | |||
| 436 | 579 | ||
| 437 | // dlinkedlist * scandirlist(const char * const dir, int (*selector)(const struct dirent *), int (*cmp)(const struct dirent **, const struct dirent **)) { | 580 | // dlinkedlist * scandirlist(const char * const dir, int (*selector)(const struct dirent *), int (*cmp)(const struct dirent **, const struct dirent **)) { |
| 438 | // if(!dir || selector == NULL || cmp == NULL) ERRRET(EINVAL, NULL); | 581 | // if(!dir || selector == NULL || cmp == NULL) ERRRET(EINVAL, NULL); |
| 439 | 582 | ||
| 440 | // struct dirent **namelist = NULL; | 583 | // struct dirent **namelist = NULL; |
| 441 | // dlinkedlist *list = NULL; | 584 | // dlinkedlist *list = NULL; |
| 442 | // int numentries = -1; | 585 | // int numentries = -1; |
| @@ -459,137 +602,38 @@ void* xsodium_malloc(size_t size) { | |||
| 459 | // return list; | 602 | // return list; |
| 460 | // } | 603 | // } |
| 461 | 604 | ||
| 605 | // Above implementation is flawed and would not actually scan the entire system. The process must be recursive: | ||
| 606 | // Step 1 - Create directory list | ||
| 607 | // Step 2 - Create --cryption ctq | ||
| 608 | // Step 3 - Scan initial starting dir. This will be /home/ | ||
| 609 | // Step 4 - Iterate over scan results | ||
| 610 | // Step 4.1 - For all directory dirent objects, add them to the directory list | ||
| 611 | // Step 4.2 - For all file dirent objects, add them to the --cryption ctq | ||
| 612 | // Step 5 - Scan next entry in the dirlist, removing it once done. Repeat Step 4 | ||
| 613 | // Step 6 - Free dirlist once empty, return newly populated --cryption ctq | ||
| 462 | 614 | ||
| 615 | // Idea: Create 2 ctqs. Use one for the actual scanning, and the other as the return result. That way, not only will scanning be | ||
| 616 | // fast, but I can also just reuse code I've already written and not make some absolute spaghetti mess trying to do everything | ||
| 617 | // linearly | ||
| 463 | 618 | ||
| 464 | struct __FLC_FKP { | 619 | int __cscan_worker(void *data) { |
| 465 | char *target; | 620 | if(!data) return -1; |
| 466 | char *output; | ||
| 467 | const unsigned char *key; | ||
| 468 | }; | ||
| 469 | |||
| 470 | struct __FLC_FKP * fkp_init(char * const target, char * const output, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]) { | ||
| 471 | if(!target || !output || !key) ERRRET(EINVAL, NULL); | ||
| 472 | struct __FLC_FKP *fkp = calloc(1, sizeof(*fkp)); | ||
| 473 | if(!fkp) | ||
| 474 | return NULL; | ||
| 475 | |||
| 476 | fkp->key = key; | ||
| 477 | fkp->output = output; | ||
| 478 | fkp->target = target; | ||
| 479 | |||
| 480 | return fkp; | ||
| 481 | } | ||
| 482 | |||
| 483 | void fkp_free(void *fkp) { | ||
| 484 | if(!fkp) return; | ||
| 485 | struct __FLC_FKP *real = (struct __FLC_FKP *)fkp; | ||
| 486 | |||
| 487 | free(real->output); | ||
| 488 | free(real->target); | ||
| 489 | free(real); | ||
| 490 | |||
| 491 | return; | ||
| 492 | } | ||
| 493 | |||
| 494 | static int __FLC_TASK_ENCRYPT(void *fkp) { | ||
| 495 | if(!fkp) | ||
| 496 | return -1; | ||
| 497 | struct __FLC_FKP *real = (struct __FLC_FKP *)fkp; | ||
| 498 | return encryptviatmp(real->target, real->output, real->key); | ||
| 499 | } | ||
| 500 | static int __FLC_TASK_DECRYPT(void *fkp) { | ||
| 501 | if(!fkp) | ||
| 502 | return -1; | ||
| 503 | struct __FLC_FKP *real = (struct __FLC_FKP *)fkp; | ||
| 504 | return decryptto(real->target, real->output, real->key); | ||
| 505 | } | ||
| 506 | 621 | ||
| 507 | enum VXGG_FLC { | 622 | return 0; |
| 508 | VXGG_FLC__INVALID, | ||
| 509 | VXGG_FLC__ENCRYPT, | ||
| 510 | VXGG_FLC__DECRYPT, | ||
| 511 | VXGG_FLC__TOOBIG | ||
| 512 | }; | ||
| 513 | |||
| 514 | struct __ucl_namelist_vals { | ||
| 515 | struct dirent **namelist; | ||
| 516 | int entries; | ||
| 517 | }; | ||
| 518 | |||
| 519 | static void __ucl_namelist(void *namelist) { | ||
| 520 | if(!namelist) return; | ||
| 521 | struct __ucl_namelist_vals *real = namelist; | ||
| 522 | for(int i = 0; i > real->entries; i++) | ||
| 523 | free(real->namelist[i]); | ||
| 524 | free(real->namelist); | ||
| 525 | return; | ||
| 526 | } | 623 | } |
| 527 | 624 | ||
| 528 | // TODO: Write these | 625 | ctqueue * cryptscan() { |
| 529 | static int encryption_filter(const struct dirent *de) { | 626 | ctqueue *res = ctqueue_init(TPSIZE), *working = ctqueue_init(TPSIZE); |
| 627 | if(!res || !working) ERRRET(errno, NULL); | ||
| 530 | 628 | ||
| 531 | } | 629 | task *start = task_init(__cscan_worker, free, void *data); |
| 532 | static int decryption_filter(const struct dirent *de) { | 630 | if(!start) ERRRET(errno, NULL); |
| 631 | ctqueue_waitpush(working, start); | ||
| 533 | 632 | ||
| 534 | } | ||
| 535 | 633 | ||
| 536 | ctqueue * getfilelist(enum VXGG_FLC mode, const char * const dir, int threads, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]) { | 634 | return res; |
| 537 | if(mode <= VXGG_FLC__INVALID || mode >= VXGG_FLC__TOOBIG || !dir || threads <= 0 || !key) ERRRET(EINVAL, NULL); | ||
| 538 | |||
| 539 | cleanup_CREATE(10); | ||
| 540 | ctqueue *ctq = NULL; | ||
| 541 | int files = -1; | ||
| 542 | |||
| 543 | // Create the ctqueue for later | ||
| 544 | ctq = ctqueue_init(threads); | ||
| 545 | if(!ctq) | ||
| 546 | return NULL; | ||
| 547 | cleanup_REGISTER(ctqueue_free, ctq); | ||
| 548 | |||
| 549 | // Get the scandir list | ||
| 550 | struct dirent **namelist; | ||
| 551 | if((files = scandir(dir, &namelist, ((mode == VXGG_FLC__ENCRYPT) ? encryption_filter : decryption_filter), alphasort)) < 0) | ||
| 552 | cleanup_MARK(); | ||
| 553 | cleanup_CNDREGISTER(__ucl_namelist, (void*)(&(struct __ucl_namelist_vals){.namelist = namelist, .entries = files})); | ||
| 554 | |||
| 555 | // Push everything onto the ctqueue | ||
| 556 | // TODO: Write task* compatible callbacks for encryption and decryption, then populate the ctqueue based on the specified mode | ||
| 557 | cleanup_CNDEXEC( | ||
| 558 | for(int i = 0; i < files; i++) { | ||
| 559 | |||
| 560 | // Target is either "filename" or "filename.vxggr" | ||
| 561 | // Output is either "filename.vxggr" or "filename" | ||
| 562 | |||
| 563 | struct __FLC_FKP *fkp = fkp_init(target, output, key); | ||
| 564 | if(!fkp) { | ||
| 565 | WARN(errno, "<getfilelist> Could not create file-key pair for \"%s\"'s %scryption task, skipping...",, namelist[i]->d_name, ((mode == VXGG_FLC__ENCRYPT) ? "en" : "de")); | ||
| 566 | free(target); | ||
| 567 | free(output); | ||
| 568 | } | ||
| 569 | task *ctask = task_init((mode == VXGG_FLC__ENCRYPT) ? __FLC_TASK_ENCRYPT : __FLC_TASK_DECRYPT, fkp_free, fkp); | ||
| 570 | if(!ctask) { | ||
| 571 | WARN(errno, "<getfilelist> Could not push \"%s\"'s %scryption task, skipping...",, namelist[i]->d_name, ((mode == VXGG_FLC__ENCRYPT) ? "en" : "de")); | ||
| 572 | free(namelist[i]); | ||
| 573 | continue; | ||
| 574 | } | ||
| 575 | ctqueue_waitpush(ctq, ctask); | ||
| 576 | } | ||
| 577 | |||
| 578 | free(namelist); | ||
| 579 | // namelist is the array that holds each pointer to each dirent, so it needs to be free'd separately from the other elements | ||
| 580 | ); | ||
| 581 | |||
| 582 | cleanup_CNDFIRE(); | ||
| 583 | if(cleanup_ERRORFLAGGED) | ||
| 584 | return NULL; | ||
| 585 | |||
| 586 | return ctq; | ||
| 587 | } | 635 | } |
| 588 | 636 | ||
| 589 | |||
| 590 | |||
| 591 | |||
| 592 | |||
| 593 | /* | 637 | /* |
| 594 | int main(void) { | 638 | int main(void) { |
| 595 | // Example code for creating a temp file, writing to it, then linking it back into the fs | 639 | // Example code for creating a temp file, writing to it, then linking it back into the fs |
| @@ -602,7 +646,7 @@ int main(void) { | |||
| 602 | 646 | ||
| 603 | if(write(fd, testmsg, strlen(testmsg)) < 0) | 647 | if(write(fd, testmsg, strlen(testmsg)) < 0) |
| 604 | error(1, errno, "write broke"); | 648 | error(1, errno, "write broke"); |
| 605 | 649 | ||
| 606 | asprintf(&path, "/proc/self/fd/%d", fd); | 650 | asprintf(&path, "/proc/self/fd/%d", fd); |
| 607 | linkat(AT_FDCWD, path, AT_FDCWD, "./test", AT_SYMLINK_FOLLOW); | 651 | linkat(AT_FDCWD, path, AT_FDCWD, "./test", AT_SYMLINK_FOLLOW); |
| 608 | free(path); | 652 | free(path); |
| @@ -623,7 +667,7 @@ int main(void) { | |||
| 623 | //*/// | 667 | //*/// |
| 624 | 668 | ||
| 625 | /*// Example code for generating a password, derriving a secret key from it, and storing things properly | 669 | /*// Example code for generating a password, derriving a secret key from it, and storing things properly |
| 626 | 670 | ||
| 627 | // Initialization | 671 | // Initialization |
| 628 | checksodium(); | 672 | checksodium(); |
| 629 | char *pass = NULL, hpass[crypto_pwhash_STRBYTES]; | 673 | char *pass = NULL, hpass[crypto_pwhash_STRBYTES]; |
| @@ -638,7 +682,7 @@ int main(void) { | |||
| 638 | // Store the password | 682 | // Store the password |
| 639 | if(crypto_pwhash_str(hpass, pass, strlen(pass) + 1, crypto_pwhash_OPSLIMIT_MODERATE, crypto_pwhash_MEMLIMIT_MODERATE) != 0) | 683 | if(crypto_pwhash_str(hpass, pass, strlen(pass) + 1, crypto_pwhash_OPSLIMIT_MODERATE, crypto_pwhash_MEMLIMIT_MODERATE) != 0) |
| 640 | error(1, errno, "Couldn't generate password, quitting..."); | 684 | error(1, errno, "Couldn't generate password, quitting..."); |
| 641 | // Don't know if I want to use MODERATE or SENSITIVE for this. SENSITIVE takes a little bit on my laptop, which honestly | 685 | // Don't know if I want to use MODERATE or SENSITIVE for this. SENSITIVE takes a little bit on my laptop, which honestly |
| 642 | // shouldn't be a problem, but it annoys me. MODERATE is quick and snappy, or at least quick enough that the slowdown is | 686 | // shouldn't be a problem, but it annoys me. MODERATE is quick and snappy, or at least quick enough that the slowdown is |
| 643 | // barely noticable. I might do MODERATE for testing and SENSITIVE for release | 687 | // barely noticable. I might do MODERATE for testing and SENSITIVE for release |
| 644 | 688 | ||
| @@ -661,4 +705,6 @@ int main(void) { | |||
| 661 | 705 | ||
| 662 | return 0; | 706 | return 0; |
| 663 | } | 707 | } |
| 664 | */ \ No newline at end of file | 708 | */ |
| 709 | |||
| 710 | #endif \ No newline at end of file | ||
