Line data Source code
1 : #ifndef DDEBUG
2 : #define DDEBUG 0
3 : #endif
4 : #include "ddebug.h"
5 :
6 :
7 : #include <ndk.h>
8 :
9 : #include "ngx_http_set_base32.h"
10 : #include "ngx_http_set_misc_module.h"
11 :
12 :
13 : #define base32_encoded_length(len) ((((len)+4)/5)*8)
14 : #define base32_decoded_length(len) ((((len)+7)/8)*5)
15 :
16 :
17 : static void encode_base32(size_t slen, u_char *src, size_t *dlen, u_char *dst,
18 : ngx_flag_t padding, ngx_str_t *alphabet);
19 : static int decode_base32(size_t slen, u_char *src, size_t *dlen, u_char *dst,
20 : u_char *basis32);
21 :
22 :
23 : ngx_int_t
24 0 : ngx_http_set_misc_encode_base32(ngx_http_request_t *r, ngx_str_t *res,
25 : ngx_http_variable_value_t *v)
26 : {
27 : size_t len;
28 : u_char *p;
29 : u_char *src, *dst;
30 :
31 : ngx_http_set_misc_loc_conf_t *conf;
32 :
33 0 : conf = ngx_http_get_module_loc_conf(r, ngx_http_set_misc_module);
34 :
35 0 : len = base32_encoded_length(v->len);
36 :
37 : dd("estimated dst len: %d", (int) len);
38 :
39 0 : p = ngx_palloc(r->pool, len);
40 0 : if (p == NULL) {
41 0 : return NGX_ERROR;
42 : }
43 :
44 0 : src = v->data; dst = p;
45 :
46 0 : encode_base32(v->len, src, &len, dst, conf->base32_padding,
47 : &conf->base32_alphabet);
48 :
49 0 : res->data = p;
50 0 : res->len = len;
51 :
52 : dd("res (len %d): %.*s", (int) res->len, (int) res->len, res->data);
53 :
54 0 : return NGX_OK;
55 : }
56 :
57 :
58 : ngx_int_t
59 0 : ngx_http_set_misc_decode_base32(ngx_http_request_t *r, ngx_str_t *res,
60 : ngx_http_variable_value_t *v)
61 : {
62 : size_t len;
63 : u_char *p;
64 : u_char *src, *dst;
65 : int ret;
66 :
67 : ngx_http_set_misc_loc_conf_t *conf;
68 :
69 0 : conf = ngx_http_get_module_loc_conf(r, ngx_http_set_misc_module);
70 :
71 0 : len = base32_decoded_length(v->len);
72 :
73 : dd("estimated dst len: %d", (int) len);
74 :
75 0 : p = ngx_palloc(r->pool, len);
76 0 : if (p == NULL) {
77 0 : return NGX_ERROR;
78 : }
79 :
80 0 : src = v->data; dst = p;
81 :
82 0 : ret = decode_base32(v->len, src, &len, dst, conf->basis32);
83 :
84 0 : if (ret == 0 /* OK */) {
85 0 : res->data = p;
86 0 : res->len = len;
87 :
88 0 : return NGX_OK;
89 : }
90 :
91 : /* failed to decode */
92 :
93 0 : res->data = NULL;
94 0 : res->len = 0;
95 :
96 0 : return NGX_OK;
97 : }
98 :
99 :
100 : /* See the implementation in src/core/ngx_string.c's
101 : * ngx_(encode|decode)_base64() for details. */
102 :
103 : static void
104 0 : encode_base32(size_t slen, u_char *src, size_t *dlen, u_char *dst,
105 : ngx_flag_t padding, ngx_str_t *alphabet)
106 : {
107 0 : unsigned char *basis32 = alphabet->data;
108 :
109 : size_t len;
110 : u_char *s;
111 : u_char *d;
112 :
113 0 : len = slen;
114 0 : s = src;
115 0 : d = dst;
116 :
117 0 : while (len > 4) {
118 0 : *d++ = basis32[s[0] >> 3];
119 0 : *d++ = basis32[((s[0] & 0x07) << 2) | (s[1] >> 6)];
120 0 : *d++ = basis32[(s[1] >> 1) & 0x1f];
121 0 : *d++ = basis32[((s[1] & 1) << 4) | (s[2] >> 4)];
122 0 : *d++ = basis32[((s[2] & 0x0f) << 1) | (s[3] >> 7)];
123 0 : *d++ = basis32[(s[3] >> 2) & 0x1f];
124 0 : *d++ = basis32[((s[3] & 0x03) << 3) | (s[4] >> 5)];
125 0 : *d++ = basis32[s[4] & 0x1f];
126 :
127 0 : s += 5;
128 0 : len -= 5;
129 : }
130 :
131 0 : if (len) {
132 0 : *d++ = basis32[s[0] >> 3];
133 :
134 0 : if (len == 1) {
135 : /* 1 byte left */
136 0 : *d++ = basis32[(s[0] & 0x07) << 2];
137 :
138 : /* pad six '='s to the end */
139 0 : if (padding) {
140 0 : *d++ = '=';
141 0 : *d++ = '=';
142 0 : *d++ = '=';
143 0 : *d++ = '=';
144 0 : *d++ = '=';
145 : }
146 :
147 : } else {
148 0 : *d++ = basis32[((s[0] & 0x07) << 2) | (s[1] >> 6)];
149 0 : *d++ = basis32[(s[1] >> 1) & 0x1f];
150 :
151 0 : if (len == 2) {
152 : /* 2 bytes left */
153 0 : *d++ = basis32[(s[1] & 1) << 4];
154 :
155 : /* pad four '='s to the end */
156 0 : if (padding) {
157 0 : *d++ = '=';
158 0 : *d++ = '=';
159 0 : *d++ = '=';
160 : }
161 :
162 : } else {
163 0 : *d++ = basis32[((s[1] & 1) << 4) | (s[2] >> 4)];
164 :
165 0 : if (len == 3) {
166 : /* 3 bytes left */
167 0 : *d++ = basis32[(s[2] & 0x0f) << 1];
168 :
169 0 : if (padding) {
170 : /* pad three '='s to the end */
171 0 : *d++ = '=';
172 0 : *d++ = '=';
173 : }
174 :
175 : } else {
176 : /* 4 bytes left */
177 0 : *d++ = basis32[((s[2] & 0x0f) << 1) | (s[3] >> 7)];
178 0 : *d++ = basis32[(s[3] >> 2) & 0x1f];
179 0 : *d++ = basis32[(s[3] & 0x03) << 3];
180 :
181 : /* pad one '=' to the end */
182 : }
183 : }
184 : }
185 :
186 0 : if (padding) {
187 0 : *d++ = '=';
188 : }
189 : }
190 :
191 0 : *dlen = (size_t) (d - dst);
192 0 : }
193 :
194 :
195 : static int
196 0 : decode_base32(size_t slen, u_char *src, size_t *dlen, u_char *dst,
197 : u_char *basis32)
198 : {
199 : size_t len, mod;
200 0 : u_char *s = src;
201 0 : u_char *d = dst;
202 :
203 0 : for (len = 0; len < slen; len++) {
204 0 : if (s[len] == '=') {
205 0 : break;
206 : }
207 :
208 0 : if (basis32[s[len]] == 77) {
209 0 : return -1;
210 : }
211 : }
212 :
213 0 : mod = len % 8;
214 :
215 0 : if (mod == 1 || mod == 3 || mod == 6) {
216 : /* bad Base32 digest length */
217 0 : return -1;
218 : }
219 :
220 0 : while (len > 7) {
221 0 : *d++ = (basis32[s[0]] << 3) | ((basis32[s[1]] >> 2) & 0x07);
222 :
223 0 : *d++ = ((basis32[s[1]] & 0x03) << 6) | (basis32[s[2]] << 1) |
224 0 : ((basis32[s[3]] >> 4) & 1);
225 :
226 0 : *d++ = ((basis32[s[3]] & 0x0f) << 4) | ((basis32[s[4]] >> 1) & 0x0f);
227 :
228 0 : *d++ = ((basis32[s[4]] & 1) << 7) | ((basis32[s[5]] & 0x1f) << 2) |
229 0 : ((basis32[s[6]] >> 3) & 0x03);
230 0 : *d++ = ((basis32[s[6]] & 0x07) << 5) | (basis32[s[7]] & 0x1f);
231 :
232 0 : s += 8;
233 0 : len -= 8;
234 : }
235 :
236 0 : if (len) {
237 : /* 2 bytes left */
238 0 : *d++ = (basis32[s[0]] << 3) | ((basis32[s[1]] >> 2) & 0x07);
239 :
240 0 : if (len > 2) {
241 : /* 4 bytes left */
242 0 : *d++ = ((basis32[s[1]] & 0x03) << 6) | ((basis32[s[2]] & 0x1f) << 1)
243 0 : | ((basis32[s[3]] >> 4) & 1);
244 :
245 0 : if (len > 4) {
246 : /* 5 bytes left */
247 0 : *d++ = ((basis32[s[3]] & 0x0f) << 4) |
248 0 : ((basis32[s[4]] >> 1) & 0x0f);
249 :
250 0 : if (len > 5) {
251 : /* 7 bytes left */
252 0 : *d++ = ((basis32[s[4]] & 1) << 7) |
253 0 : ((basis32[s[5]] & 0x1f) << 2) |
254 0 : ((basis32[s[6]] >> 3) & 0x03);
255 : }
256 : }
257 : }
258 : }
259 :
260 0 : *dlen = (size_t) (d - dst);
261 :
262 0 : return 0;
263 : }
|