You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

578 lines
12 KiB

3 years ago
3 years ago
3 years ago
7 years ago
6 years ago
7 years ago
3 years ago
7 years ago
6 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. /** @file */
  2. /** @brief File description for doxygen missing. FIXME */
  3. // This file is under GNU General Public License 3.0
  4. // see LICENSE.txt
  5. #define _POSIX_C_SOURCE 200809L
  6. #ifdef ANDROID
  7. #ifndef __LP64__
  8. #include <time64.h>
  9. #endif
  10. #endif
  11. #include <stdbool.h>
  12. #include <time.h>
  13. #include <string.h>
  14. #include <stdlib.h>
  15. #include <assert.h>
  16. #include <stdio.h>
  17. #include <glob.h>
  18. #include <errno.h>
  19. #include <sys/stat.h>
  20. #include <sys/types.h>
  21. #include <fcntl.h>
  22. #include <regex.h>
  23. #include "platform_unix.h"
  24. #include "dynamic_api.h"
  25. #define MAX_PATH 1024
  26. #ifndef LOCAL_DB_FILENAME
  27. #define OLD_LOCAL_DB_FILENAME ".pEp_management.db"
  28. #define OLD_KEYS_DB_FILENAME ".pEp_keys.db"
  29. #define LOCAL_DB_FILENAME "management.db"
  30. #define KEYS_DB_FILENAME "keys.db"
  31. #endif
  32. #define SYSTEM_DB_FILENAME "system.db"
  33. #ifdef ANDROID
  34. #include <uuid.h>
  35. /* FIXME : timegm will miss when linking for x86_64 on android, when supported */
  36. #ifndef __LP64__
  37. time_t timegm(struct tm* const t) {
  38. static const time_t kTimeMax = ~(1L << (sizeof(time_t) * CHAR_BIT - 1));
  39. static const time_t kTimeMin = (1L << (sizeof(time_t) * CHAR_BIT - 1));
  40. time64_t result = timegm64(t);
  41. if (result < kTimeMin || result > kTimeMax)
  42. return -1;
  43. return result;
  44. }
  45. #endif
  46. char *stpncpy(char *dst, const char *src, size_t n)
  47. {
  48. if (n != 0) {
  49. char *d = dst;
  50. const char *s = src;
  51. dst = &dst[n];
  52. do {
  53. if ((*d++ = *s++) == 0) {
  54. dst = d - 1;
  55. /* NUL pad the remaining n-1 bytes */
  56. while (--n != 0)
  57. *d++ = 0;
  58. break;
  59. }
  60. } while (--n != 0);
  61. }
  62. return (dst);
  63. }
  64. char *stpcpy(char *dst, const char *src)
  65. {
  66. for (;; ++dst, ++src) {
  67. *dst = *src;
  68. if (*dst == 0)
  69. break;
  70. }
  71. return dst;
  72. }
  73. /*
  74. long int random(void)
  75. {
  76. static bool seeded = false;
  77. static unsigned short xsubi[3];
  78. if(!seeded)
  79. {
  80. const long long t = (long long)time(NULL);
  81. xsubi[0] = (unsigned short)t;
  82. xsubi[1] = (unsigned short)(t>>16);
  83. xsubi[2] = (unsigned short)(t>>32);
  84. seeded = true;
  85. }
  86. return nrand48(xsubi);
  87. } */
  88. const char *android_system_db(void)
  89. {
  90. static char buffer[MAX_PATH];
  91. static bool done = false;
  92. if (!done) {
  93. char *tw_env;
  94. if(tw_env = getenv("TRUSTWORDS")){
  95. char *p = stpncpy(buffer, tw_env, MAX_PATH);
  96. ssize_t len = MAX_PATH - (p - buffer) - 2;
  97. if (len < strlen(SYSTEM_DB_FILENAME)) {
  98. assert(0);
  99. return NULL;
  100. }
  101. *p++ = '/';
  102. strncpy(p, SYSTEM_DB_FILENAME, len);
  103. done = true;
  104. }else{
  105. return NULL;
  106. }
  107. }
  108. return buffer;
  109. }
  110. void uuid_generate_random(pEpUUID out)
  111. {
  112. uuid_t *uuid;
  113. uuid_rc_t rc_create;
  114. size_t size = sizeof(uuid_string_t);
  115. void *_out = out;
  116. if ((rc_create = uuid_create(&uuid)) != UUID_RC_OK ||
  117. uuid_make(uuid, UUID_MAKE_V1) != UUID_RC_OK ||
  118. uuid_export(uuid, UUID_FMT_BIN, &_out, &size) != UUID_RC_OK)
  119. {
  120. memset(out, 0, sizeof(pEpUUID));
  121. }
  122. if (rc_create == UUID_RC_OK)
  123. {
  124. uuid_destroy(uuid);
  125. }
  126. }
  127. void uuid_unparse_upper(pEpUUID uu, uuid_string_t out)
  128. {
  129. uuid_t *uuid;
  130. uuid_rc_t rc_create;
  131. size_t size = sizeof(uuid_string_t);
  132. void *_out = out;
  133. if ((rc_create = uuid_create(&uuid)) != UUID_RC_OK ||
  134. uuid_import(uuid, UUID_FMT_BIN, uu, sizeof(pEpUUID)) != UUID_RC_OK ||
  135. uuid_export(uuid, UUID_FMT_STR, &_out, &size) != UUID_RC_OK)
  136. {
  137. memset(out, 0, sizeof(uuid_string_t));
  138. }
  139. else
  140. {
  141. out[sizeof(uuid_string_t) - 1] = 0;
  142. }
  143. if (rc_create == UUID_RC_OK)
  144. {
  145. uuid_destroy(uuid);
  146. }
  147. }
  148. #endif
  149. #if !defined(BSD) && !defined(__APPLE__)
  150. size_t strlcpy(char* dst, const char* src, size_t size) {
  151. size_t retval = strlen(src);
  152. size_t size_to_copy = (retval < size ? retval : size - 1);
  153. // strlcpy doc says src and dst not allowed to overlap, as
  154. // it's undefined. So this is acceptable:
  155. memcpy((void*)dst, (void*)src, size_to_copy); // no defined error return, but strcpy doesn't either
  156. dst[size_to_copy] = '\0';
  157. return retval;
  158. }
  159. size_t strlcat(char* dst, const char* src, size_t size) {
  160. size_t start_len = strnlen(dst, size);
  161. if (start_len == size)
  162. return size; // no copy, no null termination in size bytes, according to spec
  163. size_t add_len = strlen(src);
  164. size_t retval = start_len + add_len;
  165. size_t size_to_copy = (retval < size ? add_len : (size - start_len) - 1);
  166. // strlcat doc says src and dst not allowed to overlap, as
  167. // it's undefined. So this is acceptable:
  168. memcpy((void*)(dst + start_len), (void*)src, size_to_copy); // no defined error return, but strcpy doesn't either
  169. dst[start_len + size_to_copy] = '\0';
  170. return retval;
  171. }
  172. char *strnstr(const char *big, const char *little, size_t len) {
  173. if (big == NULL || little == NULL)
  174. return NULL;
  175. if (*little == '\0')
  176. return (char*)big;
  177. const char* curr_big = big;
  178. size_t little_len = strlen(little);
  179. size_t remaining = len;
  180. const char* retval = NULL;
  181. for (remaining = len; remaining >= little_len && *curr_big != '\0'; remaining--, curr_big++) {
  182. // find first-char match
  183. if (*curr_big != *little) {
  184. continue;
  185. }
  186. retval = curr_big;
  187. const char* inner_big = retval + 1;
  188. const char* curr_little = little + 1;
  189. int j;
  190. for (j = 1; j < little_len; j++, inner_big++, curr_little++) {
  191. if (*inner_big != *curr_little) {
  192. retval = NULL;
  193. break;
  194. }
  195. }
  196. if (retval)
  197. break;
  198. }
  199. return (char*)retval;
  200. }
  201. // #ifdef USE_NETPGP
  202. // // FIXME: This may cause problems - this is a quick compatibility fix for netpgp code
  203. // int regnexec(const regex_t* preg, const char* string,
  204. // size_t len, size_t nmatch, regmatch_t pmatch[], int eflags) {
  205. // return regexec(preg, string, nmatch, pmatch, eflags);
  206. // }
  207. // #endif
  208. #endif
  209. /**
  210. * @internal
  211. *
  212. * <!-- _stradd() -->
  213. *
  214. * @brief TODO
  215. *
  216. * @param[in] **first char
  217. * @param[in] *second constchar
  218. *
  219. */
  220. static char *_stradd(char **first, const char *second)
  221. {
  222. assert(first && *first && second);
  223. if (!(first && *first && second))
  224. return NULL;
  225. size_t len1 = strlen(*first);
  226. size_t len2 = strlen(second);
  227. size_t size = len1 + len2 + 1;
  228. char *_first = realloc(*first, size);
  229. assert(_first);
  230. if (!_first)
  231. return NULL;
  232. *first = _first;
  233. strlcat(*first, second, size);
  234. return *first;
  235. }
  236. /**
  237. * @internal
  238. *
  239. * <!-- _empty() -->
  240. *
  241. * @brief TODO
  242. *
  243. * @param[in] **p char
  244. *
  245. */
  246. static void _empty(char **p)
  247. {
  248. free(*p);
  249. *p = NULL;
  250. }
  251. /**
  252. * @internal
  253. *
  254. * <!-- _move() -->
  255. *
  256. * @brief TODO
  257. *
  258. * @param[in] *o constchar
  259. * @param[in] *ext constchar
  260. * @param[in] *n constchar
  261. *
  262. */
  263. static void _move(const char *o, const char *ext, const char *n)
  264. {
  265. assert(o && ext && n);
  266. if (!(o && ext && n))
  267. return;
  268. char *_old = strdup(o);
  269. assert(_old);
  270. if (!_old)
  271. return;
  272. char *r = _stradd(&_old, ext);
  273. if (!r) {
  274. free(_old);
  275. return;
  276. }
  277. char *_new = strdup(n);
  278. assert(_new);
  279. if (!_new) {
  280. free(_old);
  281. return;
  282. }
  283. r = _stradd(&_new, ext);
  284. if (r)
  285. rename(_old, _new);
  286. free(_old);
  287. free(_new);
  288. }
  289. #ifndef NDEBUG
  290. /**
  291. * @internal
  292. *
  293. * <!-- _per_user_directory() -->
  294. *
  295. * @brief TODO
  296. *
  297. * @param[in] reset int
  298. *
  299. */
  300. static const char *_per_user_directory(int reset)
  301. #else
  302. static const char *_per_user_directory(void)
  303. #endif
  304. {
  305. static char *path = NULL;
  306. #ifdef NDEBUG
  307. if (path)
  308. return path;
  309. #else
  310. if (path && !reset)
  311. return path;
  312. else if (path) {
  313. free(path);
  314. path = NULL;
  315. }
  316. #endif
  317. const char *home = NULL;
  318. #ifndef NDEBUG
  319. home = getenv("PEP_HOME");
  320. if (!home)
  321. #endif
  322. home = getenv("HOME");
  323. assert(home);
  324. if (!home)
  325. return NULL;
  326. path = strdup(home);
  327. assert(path);
  328. if (!path)
  329. return NULL;
  330. char *_path = _stradd(&path, "/");
  331. if (!_path)
  332. goto error;
  333. _path = _stradd(&path, PER_USER_DIRECTORY);
  334. if (!_path)
  335. goto error;
  336. return path;
  337. error:
  338. _empty(&path);
  339. return NULL;
  340. }
  341. #ifdef NDEBUG
  342. const char *unix_local_db(void)
  343. #else
  344. const char *unix_local_db(int reset)
  345. #endif
  346. {
  347. static char *path = NULL;
  348. #ifdef NDEBUG
  349. if (path)
  350. #else
  351. if (path && !reset)
  352. #endif
  353. return path;
  354. const char* pathret = NULL;
  355. #ifndef NDEBUG
  356. pathret = _per_user_directory(reset);
  357. #else
  358. pathret = _per_user_directory();
  359. #endif
  360. if (!pathret)
  361. return NULL;
  362. path = strdup(pathret);
  363. assert(path);
  364. if (!path)
  365. return NULL;
  366. char *path_c = NULL;
  367. char *old_path = NULL;
  368. char *old_path_c = NULL;
  369. struct stat dir;
  370. int r = stat(path, &dir);
  371. if (r) {
  372. if (errno == ENOENT) {
  373. // directory does not yet exist
  374. r = mkdir(path, 0700);
  375. if (r)
  376. goto error;
  377. }
  378. else {
  379. goto error;
  380. }
  381. }
  382. char *_path = _stradd(&path, "/");
  383. if (!_path)
  384. goto error;
  385. // make a copy of this path in case we need to move files
  386. path_c = strdup(path);
  387. assert(path_c);
  388. if (!path_c)
  389. goto error;
  390. _path = _stradd(&path, LOCAL_DB_FILENAME);
  391. if (!_path)
  392. goto error;
  393. struct stat file;
  394. r = stat(path, &file);
  395. if (r) {
  396. if (errno == ENOENT) {
  397. // we do not have management.db yet, let's test if we need to move
  398. // one with the old name
  399. const char *home = NULL;
  400. #ifndef NDEBUG
  401. home = getenv("PEP_HOME");
  402. if (!home)
  403. #endif
  404. home = getenv("HOME");
  405. // we were already checking for HOME existing, so this is only a
  406. // safeguard
  407. assert(home);
  408. old_path = strdup(home);
  409. assert(old_path);
  410. if (!old_path)
  411. goto error;
  412. char *_old_path = _stradd(&old_path, "/");
  413. if (!_old_path)
  414. goto error;
  415. old_path_c = strdup(old_path);
  416. assert(old_path_c);
  417. if (!old_path_c)
  418. goto error;
  419. _old_path = _stradd(&old_path, OLD_LOCAL_DB_FILENAME);
  420. if (!_old_path)
  421. goto error;
  422. struct stat old;
  423. r = stat(old_path, &old);
  424. if (r == 0) {
  425. // old file existing, new file not yet existing, move
  426. rename(old_path, path);
  427. // if required move associated files, too
  428. _move(old_path, "-shm", path);
  429. _move(old_path, "-wal", path);
  430. // move keys database
  431. _old_path = _stradd(&old_path_c, OLD_KEYS_DB_FILENAME);
  432. if (!_old_path)
  433. goto error;
  434. _path = _stradd(&path_c, KEYS_DB_FILENAME);
  435. if (!_path)
  436. goto error;
  437. rename(old_path_c, path_c);
  438. // if required move associated files, too
  439. _move(old_path_c, "-shm", path_c);
  440. _move(old_path_c, "-wal", path_c);
  441. }
  442. }
  443. else {
  444. goto error;
  445. }
  446. }
  447. goto the_end;
  448. error:
  449. _empty(&path);
  450. the_end:
  451. free(path_c);
  452. free(old_path);
  453. free(old_path_c);
  454. return path;
  455. }
  456. DYNAMIC_API const char *per_user_directory(void) {
  457. #ifdef NDEBUG
  458. return _per_user_directory();
  459. #else
  460. return _per_user_directory(false);
  461. #endif
  462. }
  463. DYNAMIC_API const char *per_machine_directory(void)
  464. {
  465. return PER_MACHINE_DIRECTORY;
  466. }
  467. const char *unix_system_db(void)
  468. {
  469. static char *path = NULL;
  470. if (path)
  471. return path;
  472. path = strdup(per_machine_directory());
  473. assert(path);
  474. if (!path)
  475. return NULL;
  476. char *_path = _stradd(&path, "/");
  477. if (!_path)
  478. goto error;
  479. _path = _stradd(&path, SYSTEM_DB_FILENAME);
  480. if (!_path)
  481. goto error;
  482. return path;
  483. error:
  484. _empty(&path);
  485. return NULL;
  486. }