git ssb

0+

dangerousbeans / %aPBe2k3ugtjBr4rrsU1…



Tree: cbe335aadd1e8c3ec57ebf0943ddccaf77af0f37

Files: cbe335aadd1e8c3ec57ebf0943ddccaf77af0f37 / ext / mri / wrapper.c

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

Built with git-ssb-web