/src/suricata7/libhtp/htp/htp_base64.c
Line | Count | Source (jump to first uncovered line) |
1 | | /*************************************************************************** |
2 | | * Copyright (c) 2009-2010 Open Information Security Foundation |
3 | | * Copyright (c) 2010-2013 Qualys, Inc. |
4 | | * All rights reserved. |
5 | | * |
6 | | * Redistribution and use in source and binary forms, with or without |
7 | | * modification, are permitted provided that the following conditions are |
8 | | * met: |
9 | | * |
10 | | * - Redistributions of source code must retain the above copyright |
11 | | * notice, this list of conditions and the following disclaimer. |
12 | | |
13 | | * - Redistributions in binary form must reproduce the above copyright |
14 | | * notice, this list of conditions and the following disclaimer in the |
15 | | * documentation and/or other materials provided with the distribution. |
16 | | |
17 | | * - Neither the name of the Qualys, Inc. nor the names of its |
18 | | * contributors may be used to endorse or promote products derived from |
19 | | * this software without specific prior written permission. |
20 | | * |
21 | | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
22 | | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
23 | | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
24 | | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
25 | | * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
26 | | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
27 | | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
28 | | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
29 | | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
30 | | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
31 | | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
32 | | ***************************************************************************/ |
33 | | |
34 | | /** |
35 | | * @file |
36 | | * @author Ivan Ristic <ivanr@webkreator.com> |
37 | | */ |
38 | | |
39 | | /* Adapted from the libb64 project (http://sourceforge.net/projects/libb64), which is in public domain. */ |
40 | | |
41 | | #include "bstr.h" |
42 | | #include "htp_base64.h" |
43 | | |
44 | | /** |
45 | | * Decode single base64-encoded character. |
46 | | * |
47 | | * @param[in] value_in |
48 | | * @return decoded character |
49 | | */ |
50 | 0 | int htp_base64_decode_single(signed char value_in) { |
51 | 0 | static const signed char decoding[] = {62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, |
52 | 0 | -1, -1, -1, -2, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, |
53 | 0 | 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, |
54 | 0 | 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51}; |
55 | 0 | static const signed char decoding_size = sizeof (decoding); |
56 | |
|
57 | 0 | value_in -= 43; |
58 | |
|
59 | 0 | if ((value_in < 0) || (value_in > decoding_size - 1)) return -1; |
60 | | |
61 | 0 | return decoding[(int) value_in]; |
62 | 0 | } |
63 | | |
64 | | /** |
65 | | * Initialize base64 decoder. |
66 | | * |
67 | | * @param[in] decoder |
68 | | */ |
69 | 0 | void htp_base64_decoder_init(htp_base64_decoder *decoder) { |
70 | 0 | decoder->step = step_a; |
71 | 0 | decoder->plainchar = 0; |
72 | 0 | } |
73 | | |
74 | | /** |
75 | | * Feed the supplied memory range to the decoder. |
76 | | * |
77 | | * @param[in] decoder |
78 | | * @param[in] _code_in |
79 | | * @param[in] length_in |
80 | | * @param[in] _plaintext_out |
81 | | * @param[in] length_out |
82 | | * @return how many bytes were placed into plaintext output |
83 | | */ |
84 | 0 | int htp_base64_decode(htp_base64_decoder *decoder, const void *_code_in, int length_in, void *_plaintext_out, int length_out) { |
85 | 0 | const unsigned char *code_in = (const unsigned char *)_code_in; |
86 | 0 | unsigned char *plaintext_out = (unsigned char *)_plaintext_out; |
87 | 0 | const unsigned char *codechar = code_in; |
88 | 0 | unsigned char *plainchar = plaintext_out; |
89 | 0 | signed char fragment; |
90 | |
|
91 | 0 | if (length_out <= 0) return 0; |
92 | | |
93 | 0 | *plainchar = decoder->plainchar; |
94 | |
|
95 | 0 | switch (decoder->step) { |
96 | 0 | while (1) { |
97 | 0 | case step_a: |
98 | 0 | do { |
99 | 0 | if (codechar == code_in + length_in) { |
100 | 0 | decoder->step = step_a; |
101 | 0 | decoder->plainchar = *plainchar; |
102 | 0 | return (int) (plainchar - plaintext_out); |
103 | 0 | } |
104 | 0 | fragment = (char) htp_base64_decode_single(*codechar++); |
105 | 0 | } while (fragment < 0); |
106 | 0 | *plainchar = (unsigned char) ((fragment & 0x03f) << 2); |
107 | | /* fall through */ |
108 | |
|
109 | 0 | case step_b: |
110 | 0 | do { |
111 | 0 | if (codechar == code_in + length_in) { |
112 | 0 | decoder->step = step_b; |
113 | 0 | decoder->plainchar = *plainchar; |
114 | 0 | return (int) (plainchar - plaintext_out); |
115 | 0 | } |
116 | 0 | fragment = (char) htp_base64_decode_single(*codechar++); |
117 | 0 | } while (fragment < 0); |
118 | 0 | *plainchar++ |= (fragment & 0x030) >> 4; |
119 | 0 | *plainchar = (unsigned char) ((fragment & 0x00f) << 4); |
120 | 0 | if (--length_out == 0) { |
121 | 0 | return (int) (plainchar - plaintext_out); |
122 | 0 | } |
123 | | /* fall through */ |
124 | | |
125 | 0 | case step_c: |
126 | 0 | do { |
127 | 0 | if (codechar == code_in + length_in) { |
128 | 0 | decoder->step = step_c; |
129 | 0 | decoder->plainchar = *plainchar; |
130 | 0 | return (int) (plainchar - plaintext_out); |
131 | 0 | } |
132 | 0 | fragment = (char) htp_base64_decode_single(*codechar++); |
133 | 0 | } while (fragment < 0); |
134 | 0 | *plainchar++ |= (fragment & 0x03c) >> 2; |
135 | 0 | *plainchar = (unsigned char) ((fragment & 0x003) << 6); |
136 | 0 | if (--length_out == 0) { |
137 | 0 | return (int) (plainchar - plaintext_out); |
138 | 0 | } |
139 | | /* fall through */ |
140 | | |
141 | 0 | case step_d: |
142 | 0 | do { |
143 | 0 | if (codechar == code_in + length_in) { |
144 | 0 | decoder->step = step_d; |
145 | 0 | decoder->plainchar = *plainchar; |
146 | 0 | return (int) (plainchar - plaintext_out); |
147 | 0 | } |
148 | 0 | fragment = (char) htp_base64_decode_single(*codechar++); |
149 | 0 | } while (fragment < 0); |
150 | 0 | *plainchar++ |= (fragment & 0x03f); |
151 | 0 | if (--length_out == 0) { |
152 | 0 | return (int) (plainchar - plaintext_out); |
153 | 0 | } |
154 | | /* fall through */ |
155 | 0 | } |
156 | 0 | } |
157 | | |
158 | | /* control should not reach here */ |
159 | 0 | return plainchar - plaintext_out; |
160 | 0 | } |
161 | | |
162 | | /** |
163 | | * Base64-decode input, given as bstring. |
164 | | * |
165 | | * @param[in] input |
166 | | * @return new base64-decoded bstring |
167 | | */ |
168 | 0 | bstr *htp_base64_decode_bstr(bstr *input) { |
169 | 0 | return htp_base64_decode_mem(bstr_ptr(input), bstr_len(input)); |
170 | 0 | } |
171 | | |
172 | | /** |
173 | | * Base64-decode input, given as memory range. |
174 | | * |
175 | | * @param[in] data |
176 | | * @param[in] len |
177 | | * @return new base64-decoded bstring |
178 | | */ |
179 | 0 | bstr *htp_base64_decode_mem(const void *data, size_t len) { |
180 | 0 | htp_base64_decoder decoder; |
181 | 0 | bstr *r = NULL; |
182 | |
|
183 | 0 | htp_base64_decoder_init(&decoder); |
184 | |
|
185 | 0 | unsigned char *tmpstr = malloc(len); |
186 | 0 | if (tmpstr == NULL) return NULL; |
187 | | |
188 | 0 | int resulting_len = htp_base64_decode(&decoder, data, (int) len, tmpstr, (int) len); |
189 | 0 | if (resulting_len > 0) { |
190 | 0 | r = bstr_dup_mem(tmpstr, resulting_len); |
191 | 0 | } |
192 | |
|
193 | 0 | free(tmpstr); |
194 | |
|
195 | 0 | return r; |
196 | 0 | } |