utils.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /*
  2. * This program is free software; you can redistribute it and/or
  3. * modify it under the terms of the GNU General Public License
  4. * as published by the Free Software Foundation; either version 2
  5. * of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. * Author: g0tsu
  12. * Email: g0tsu at dnmx.0rg
  13. */
  14. #include <global.h>
  15. #include <libcaptcha.h>
  16. #include <stdint.h>
  17. #include <string.h>
  18. #include <stdlib.h>
  19. #include <ctype.h>
  20. #include <unistd.h>
  21. #include <fcntl.h>
  22. #include <sys/types.h>
  23. #include <sys/stat.h>
  24. #include <sys/syscall.h>
  25. #include <errno.h>
  26. #include <assert.h>
  27. int lc_random_bytes(void *bytes, size_t size) {
  28. size_t read_bytes = 0;
  29. ssize_t n;
  30. /* Linux getrandom(2) syscall or FreeBSD getrandom(2) function*/
  31. /* Keep reading until we get enough entropy */
  32. while (read_bytes < size) {
  33. /* Below, (bytes + read_bytes) is pointer arithmetic.
  34. bytes read_bytes size
  35. | | |
  36. [#######=============] (we're going to write over the = region)
  37. \\\\\\\\\\\\\
  38. amount_to_read
  39. */
  40. size_t amount_to_read = size - read_bytes;
  41. n = syscall(SYS_getrandom, bytes + read_bytes, amount_to_read, 0);
  42. if (n == -1) {
  43. if (errno == ENOSYS) {
  44. /* This can happen if PHP was compiled against a newer kernel where getrandom()
  45. * is available, but then runs on an older kernel without getrandom(). If this
  46. * happens we simply fall back to reading from /dev/urandom. */
  47. assert(read_bytes == 0);
  48. break;
  49. } else if (errno == EINTR || errno == EAGAIN) {
  50. /* Try again */
  51. continue;
  52. } else {
  53. /* If the syscall fails, fall back to reading from /dev/urandom */
  54. break;
  55. }
  56. }
  57. read_bytes += (size_t) n;
  58. }
  59. if (read_bytes < size) {
  60. int fd;
  61. struct stat st;
  62. if (fd < 0) {
  63. #if HAVE_DEV_URANDOM
  64. fd = open("/dev/urandom", O_RDONLY);
  65. #else
  66. fd = open("/dev/random", O_RDONLY);
  67. #endif
  68. if (fd < 0) {
  69. return 1;
  70. }
  71. /* Does the file exist and is it a character device? */
  72. if (fstat(fd, &st) != 0 ||
  73. # ifdef S_ISNAM
  74. !(S_ISNAM(st.st_mode) || S_ISCHR(st.st_mode))
  75. # else
  76. !S_ISCHR(st.st_mode)
  77. # endif
  78. ) {
  79. close(fd);
  80. return 1;
  81. }
  82. }
  83. for (read_bytes = 0; read_bytes < size; read_bytes += (size_t) n) {
  84. n = read(fd, bytes + read_bytes, size - read_bytes);
  85. if (n <= 0) {
  86. break;
  87. }
  88. }
  89. if (read_bytes < size) {
  90. return 1;
  91. }
  92. }
  93. return 0;
  94. }
  95. const char lc_cval[16] = "0123456789abcdef";
  96. static int lc_val_pos(const char c) {
  97. for (int i = 0; i < 16; i++) {
  98. if (lc_cval[i] == c)
  99. return i;
  100. }
  101. return 0;
  102. }
  103. lc_rgb *lc_rgb_from_text(const char *str) {
  104. char *cp = (char *)str;
  105. char c;
  106. lc_rgb *rgb;
  107. if (strlen(str) < 7)
  108. return NULL;
  109. cp++; // skip #
  110. rgb = (lc_rgb *)malloc(sizeof(*rgb));
  111. for (int i = 0; i < 6; i++, cp++) {
  112. c = tolower(*cp);
  113. switch (i) {
  114. case 0:
  115. rgb->r = lc_val_pos(c) * 16;
  116. break;
  117. case 1:
  118. rgb->r += lc_val_pos(c);
  119. case 2:
  120. rgb->g = lc_val_pos(c) * 16;
  121. break;
  122. case 3:
  123. rgb->g += lc_val_pos(c);
  124. case 4:
  125. rgb->b = lc_val_pos(c) * 16;
  126. break;
  127. case 5:
  128. rgb->b += lc_val_pos(c);
  129. default:
  130. break;
  131. }
  132. }
  133. return rgb;
  134. }