wrapper.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. /*
  2. * Written by Solar Designer and placed in the public domain.
  3. * See crypt_blowfish.c for more information.
  4. */
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <errno.h>
  8. #ifndef __set_errno
  9. #define __set_errno(val) errno = (val)
  10. #endif
  11. #ifdef TEST
  12. #include <stdio.h>
  13. #include <unistd.h>
  14. #include <signal.h>
  15. #include <time.h>
  16. #include <sys/time.h>
  17. #include <sys/times.h>
  18. #ifdef TEST_THREADS
  19. #include <pthread.h>
  20. #endif
  21. #endif
  22. #include <ruby.h>
  23. #include <util.h>
  24. #define CRYPT_OUTPUT_SIZE (7 + 22 + 31 + 1)
  25. #define CRYPT_GENSALT_OUTPUT_SIZE (7 + 22 + 1)
  26. #if defined(__GLIBC__) && defined(_LIBC)
  27. #define __SKIP_GNU
  28. #endif
  29. #include "ow-crypt.h"
  30. extern char *_crypt_blowfish_rn(__CONST char *key, __CONST char *setting,
  31. char *output, int size);
  32. extern char *_crypt_gensalt_blowfish_rn(unsigned long count,
  33. __CONST char *input, int size, char *output, int output_size);
  34. extern unsigned char _crypt_itoa64[];
  35. extern char *_crypt_gensalt_traditional_rn(unsigned long count,
  36. __CONST char *input, int size, char *output, int output_size);
  37. extern char *_crypt_gensalt_extended_rn(unsigned long count,
  38. __CONST char *input, int size, char *output, int output_size);
  39. extern char *_crypt_gensalt_md5_rn(unsigned long count,
  40. __CONST char *input, int size, char *output, int output_size);
  41. #if defined(__GLIBC__) && defined(_LIBC)
  42. /* crypt.h from glibc-crypt-2.1 will define struct crypt_data for us */
  43. #include "crypt.h"
  44. extern char *__md5_crypt_r(const char *key, const char *salt,
  45. char *buffer, int buflen);
  46. /* crypt-entry.c needs to be patched to define __des_crypt_r rather than
  47. * __crypt_r, and not define crypt_r and crypt at all */
  48. extern char *__des_crypt_r(const char *key, const char *salt,
  49. struct crypt_data *data);
  50. extern struct crypt_data _ufc_foobar;
  51. #endif
  52. static int _crypt_data_alloc(void **data, int *size, int need)
  53. {
  54. void *updated;
  55. if (*data && *size >= need) return 0;
  56. updated = realloc(*data, need);
  57. if (!updated) {
  58. #ifndef __GLIBC__
  59. /* realloc(3) on glibc sets errno, so we don't need to bother */
  60. __set_errno(ENOMEM);
  61. #endif
  62. return -1;
  63. }
  64. #if defined(__GLIBC__) && defined(_LIBC)
  65. if (need >= sizeof(struct crypt_data))
  66. ((struct crypt_data *)updated)->initialized = 0;
  67. #endif
  68. *data = updated;
  69. *size = need;
  70. return 0;
  71. }
  72. static char *_crypt_retval_magic(char *retval, __CONST char *setting,
  73. char *output)
  74. {
  75. if (retval) return retval;
  76. output[0] = '*';
  77. output[1] = '0';
  78. output[2] = '\0';
  79. if (setting[0] == '*' && setting[1] == '0')
  80. output[1] = '1';
  81. return output;
  82. }
  83. #if defined(__GLIBC__) && defined(_LIBC)
  84. /*
  85. * Applications may re-use the same instance of struct crypt_data without
  86. * resetting the initialized field in order to let crypt_r() skip some of
  87. * its initialization code. Thus, it is important that our multiple hashing
  88. * algorithms either don't conflict with each other in their use of the
  89. * data area or reset the initialized field themselves whenever required.
  90. * Currently, the hashing algorithms simply have no conflicts: the first
  91. * field of struct crypt_data is the 128-byte large DES key schedule which
  92. * __des_crypt_r() calculates each time it is called while the two other
  93. * hashing algorithms use less than 128 bytes of the data area.
  94. */
  95. char *__crypt_rn(__const char *key, __const char *setting,
  96. void *data, int size)
  97. {
  98. if (setting[0] == '$' && setting[1] == '2')
  99. return _crypt_blowfish_rn(key, setting, (char *)data, size);
  100. if (setting[0] == '$' && setting[1] == '1')
  101. return __md5_crypt_r(key, setting, (char *)data, size);
  102. if (setting[0] == '$' || setting[0] == '_') {
  103. __set_errno(EINVAL);
  104. return NULL;
  105. }
  106. if (size >= sizeof(struct crypt_data))
  107. return __des_crypt_r(key, setting, (struct crypt_data *)data);
  108. __set_errno(ERANGE);
  109. return NULL;
  110. }
  111. char *__crypt_ra(__const char *key, __const char *setting,
  112. void **data, int *size)
  113. {
  114. if (setting[0] == '$' && setting[1] == '2') {
  115. if (_crypt_data_alloc(data, size, CRYPT_OUTPUT_SIZE))
  116. return NULL;
  117. return _crypt_blowfish_rn(key, setting, (char *)*data, *size);
  118. }
  119. if (setting[0] == '$' && setting[1] == '1') {
  120. if (_crypt_data_alloc(data, size, CRYPT_OUTPUT_SIZE))
  121. return NULL;
  122. return __md5_crypt_r(key, setting, (char *)*data, *size);
  123. }
  124. if (setting[0] == '$' || setting[0] == '_') {
  125. __set_errno(EINVAL);
  126. return NULL;
  127. }
  128. if (_crypt_data_alloc(data, size, sizeof(struct crypt_data)))
  129. return NULL;
  130. return __des_crypt_r(key, setting, (struct crypt_data *)*data);
  131. }
  132. char *__crypt_r(__const char *key, __const char *setting,
  133. struct crypt_data *data)
  134. {
  135. return _crypt_retval_magic(
  136. __crypt_rn(key, setting, data, sizeof(*data)),
  137. setting, (char *)data);
  138. }
  139. char *__crypt(__const char *key, __const char *setting)
  140. {
  141. return _crypt_retval_magic(
  142. __crypt_rn(key, setting, &_ufc_foobar, sizeof(_ufc_foobar)),
  143. setting, (char *)&_ufc_foobar);
  144. }
  145. #else
  146. char *crypt_rn(__CONST char *key, __CONST char *setting, void *data, int size)
  147. {
  148. return _crypt_blowfish_rn(key, setting, (char *)data, size);
  149. }
  150. char *crypt_ra(__CONST char *key, __CONST char *setting,
  151. void **data, int *size)
  152. {
  153. if (_crypt_data_alloc(data, size, CRYPT_OUTPUT_SIZE))
  154. return NULL;
  155. return _crypt_blowfish_rn(key, setting, (char *)*data, *size);
  156. }
  157. char *crypt_r(__CONST char *key, __CONST char *setting, void *data)
  158. {
  159. return _crypt_retval_magic(
  160. crypt_rn(key, setting, data, CRYPT_OUTPUT_SIZE),
  161. setting, (char *)data);
  162. }
  163. #define __crypt_gensalt_rn crypt_gensalt_rn
  164. #define __crypt_gensalt_ra crypt_gensalt_ra
  165. #define __crypt_gensalt crypt_gensalt
  166. #endif
  167. char *__crypt_gensalt_rn(__CONST char *prefix, unsigned long count,
  168. __CONST char *input, int size, char *output, int output_size)
  169. {
  170. char *(*use)(unsigned long count,
  171. __CONST char *input, int size, char *output, int output_size);
  172. /* This may be supported on some platforms in the future */
  173. if (!input) {
  174. __set_errno(EINVAL);
  175. return NULL;
  176. }
  177. if (!strncmp(prefix, "$2a$", 4))
  178. use = _crypt_gensalt_blowfish_rn;
  179. else
  180. if (!strncmp(prefix, "$1$", 3))
  181. use = _crypt_gensalt_md5_rn;
  182. else
  183. if (prefix[0] == '_')
  184. use = _crypt_gensalt_extended_rn;
  185. else
  186. if (!prefix[0] ||
  187. (prefix[0] && prefix[1] &&
  188. memchr(_crypt_itoa64, prefix[0], 64) &&
  189. memchr(_crypt_itoa64, prefix[1], 64)))
  190. use = _crypt_gensalt_traditional_rn;
  191. else {
  192. __set_errno(EINVAL);
  193. return NULL;
  194. }
  195. return use(count, input, size, output, output_size);
  196. }
  197. char *__crypt_gensalt_ra(__CONST char *prefix, unsigned long count,
  198. __CONST char *input, int size)
  199. {
  200. char output[CRYPT_GENSALT_OUTPUT_SIZE];
  201. char *retval;
  202. retval = __crypt_gensalt_rn(prefix, count,
  203. input, size, output, sizeof(output));
  204. if (retval) {
  205. retval = ruby_strdup(retval);
  206. #ifndef __GLIBC__
  207. /* strdup(3) on glibc sets errno, so we don't need to bother */
  208. if (!retval)
  209. __set_errno(ENOMEM);
  210. #endif
  211. }
  212. return retval;
  213. }
  214. char *__crypt_gensalt(__CONST char *prefix, unsigned long count,
  215. __CONST char *input, int size)
  216. {
  217. static char output[CRYPT_GENSALT_OUTPUT_SIZE];
  218. return __crypt_gensalt_rn(prefix, count,
  219. input, size, output, sizeof(output));
  220. }