1 /*------------------------------------------------------------------------------
2  *
3  * Copyright (c) 2011-2021, EURid vzw. All rights reserved.
4  * The YADIFA TM software product is provided under the BSD 3-clause license:
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  *        * Redistributions of source code must retain the above copyright
11  *          notice, this list of conditions and the following disclaimer.
12  *        * Redistributions in binary form must reproduce the above copyright
13  *          notice, this list of conditions and the following disclaimer in the
14  *          documentation and/or other materials provided with the distribution.
15  *        * Neither the name of EURid nor the names of its contributors may be
16  *          used to endorse or promote products derived from this software
17  *          without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  *------------------------------------------------------------------------------
32  *
33  */
34 
35 /** @defgroup streaming Streams
36  *  @ingroup dnscore
37  *  @brief
38  *
39  *
40  *
41  * @{
42  *
43  *----------------------------------------------------------------------------*/
44 #include "dnscore/dnscore-config.h"
45 #include <stdio.h>
46 #include <stdlib.h>
47 
48 #include <arpa/inet.h>  /* or netinet/in.h */
49 
50 #include "dnscore/input_stream.h"
51 #include "dnscore/rfc.h"
52 #include "dnscore/logger.h"
53 
54 #include "dnscore/dnscore.h"
55 
56 #define MODULE_MSG_HANDLE g_system_logger
57 
58 ya_result
input_stream_read_fully(input_stream * stream,void * buffer_start,u32 len_start)59 input_stream_read_fully(input_stream *stream, void* buffer_start, u32 len_start)
60 {
61     input_stream_read_method* readfunc = stream->vtbl->read;
62     u32 len = len_start;
63     u8* buffer = (u8*)buffer_start;
64     ya_result ret;
65 
66     while(len > 0)
67     {
68         if(FAIL(ret = readfunc(stream, buffer, len)))
69         {
70             return ret;
71         }
72 
73         if(ret == 0) /* eof */
74         {
75             break;
76         }
77 
78         buffer += ret;
79         len -= ret; // cppcheck: false positive
80     }
81 
82     /* If we only read a partial it's wrong.
83      * If we were aked to read nothing it's ok.
84      * If we read nothing at all we were on EOF and its still ok
85      */
86 
87     if(len > 0)
88     {
89         return UNABLE_TO_COMPLETE_FULL_READ;
90     }
91 
92     return (ya_result)(buffer - (u8*)buffer_start);
93 }
94 
95 ya_result
input_stream_skip_fully(input_stream * stream,u32 len_start)96 input_stream_skip_fully(input_stream *stream, u32 len_start)
97 {
98     input_stream_skip_method* skipfunc = stream->vtbl->skip;
99     u32 len = len_start;
100     ya_result ret;
101 
102     while(len > 0)
103     {
104         if(FAIL(ret = skipfunc(stream, len)))
105         {
106             return ret;
107         }
108 
109         if(ret == 0) /* eof */
110         {
111             break;
112         }
113 
114         len -= ret; // cppcheck: false positive
115     }
116 
117     /* If we only read a partial it's wrong.
118      * If we were aked to read nothing it's ok.
119      * If we read nothing at all we were on EOF and its still ok
120      */
121 
122     if(len > 0)
123     {
124         return UNABLE_TO_COMPLETE_FULL_READ;
125     }
126 
127     return len_start;
128 }
129 
130 ya_result
input_stream_read_nu32(input_stream * stream,u32 * output)131 input_stream_read_nu32(input_stream *stream, u32 *output)
132 {
133     u32 data;
134     ya_result err;
135 
136     if(ISOK(err = input_stream_read_fully(stream, &data, 4)))
137     {
138         *output = ntohl(data);
139     }
140 
141     return err;
142 }
143 
144 ya_result
input_stream_read_nu16(input_stream * stream,u16 * output)145 input_stream_read_nu16(input_stream *stream, u16 *output)
146 {
147     u16 data;
148     ya_result err;
149 
150     if(ISOK(err = input_stream_read_fully(stream, &data, 2)))
151     {
152         *output = ntohs(data);
153     }
154 
155     return err;
156 }
157 
158 ya_result
input_stream_read_u32(input_stream * stream,u32 * output)159 input_stream_read_u32(input_stream *stream, u32 *output)
160 {
161     u32 data;
162     ya_result err;
163 
164     if(ISOK(err = input_stream_read_fully(stream, &data, 4)))
165     {
166         *output = data;
167     }
168 
169     return err;
170 }
171 
172 ya_result
input_stream_read_s32(input_stream * stream,s32 * output)173 input_stream_read_s32(input_stream *stream, s32 *output)
174 {
175     u32 data;
176     ya_result err;
177 
178     if(ISOK(err = input_stream_read_fully(stream, &data, 4)))
179     {
180         *output = data;
181     }
182 
183     return err;
184 }
185 
186 ya_result
input_stream_read_u16(input_stream * stream,u16 * output)187 input_stream_read_u16(input_stream *stream, u16 *output)
188 {
189     u16 data;
190     ya_result err;
191 
192     if(ISOK(err = input_stream_read_fully(stream, &data, 2)))
193     {
194         *output = data;
195     }
196 
197     return err;
198 }
199 
200 union t32
201 {
202     u8 bytes[4];
203     u32 value;
204 };
205 
206 ya_result
input_stream_read_pu32(input_stream * is,u32 * output)207 input_stream_read_pu32(input_stream* is, u32 *output)
208 {
209     ya_result ret;
210     u32 value = 0;
211     union t32 buffer;
212     buffer.value = 0;
213     ya_result n = 0;
214     u8 s = 0;
215 
216     for(;;)
217     {
218 #if WORDS_BIGENDIAN
219         if(FAIL(ret = input_stream_read(is, &buffer.bytes[3], 1)))
220         {
221             return ret;
222         }
223 #else
224         if(FAIL(ret = input_stream_read(is, &buffer.bytes[0], 1)))
225         {
226             return ret;
227         }
228 #endif
229 
230         value |= (buffer.value & 127) << s;
231 
232         ++n;
233 
234         if(buffer.value < 128)
235         {
236             *output = value;
237             return n;
238         }
239 
240         s += 7;
241     }
242 }
243 
244 union t64
245 {
246     u8 bytes[8];
247     u64 value;
248 };
249 
250 ya_result
input_stream_read_pu64(input_stream * is,u64 * output)251 input_stream_read_pu64(input_stream* is, u64 *output)
252 {
253     ya_result ret;
254     u64 value = 0;
255     union t64 buffer;
256     buffer.value = 0;
257     ya_result n = 0;
258     u8 s = 0;
259 
260     for(;;)
261     {
262 #if WORDS_BIGENDIAN
263         if(FAIL(ret = input_stream_read(is, &buffer.bytes[7], 1)))
264         {
265             return ret;
266         }
267 #else
268         if(FAIL(ret = input_stream_read(is, &buffer.bytes[0], 1)))
269         {
270             return ret;
271         }
272 #endif
273 
274         value |= (buffer.value & 127) << s;
275 
276         ++n;
277 
278         if(buffer.value < 128)
279         {
280             *output = value;
281             return n;
282         }
283 
284         s += 7;
285     }
286 }
287 
288 ya_result
input_stream_read_dnsname(input_stream * stream,u8 * output_buffer)289 input_stream_read_dnsname(input_stream *stream, u8 *output_buffer)
290 {
291     u8 *output = output_buffer;
292     const u8 * const limit = &output_buffer[MAX_DOMAIN_LENGTH - 1];  /* -1 because the limit is computed after the terminator */
293 
294     for(;;)
295     {
296         int n;
297 
298         if(FAIL(n = input_stream_read_fully(stream, output, 1)))
299         {
300             return (output == output_buffer) ? 0 /* eof*/ : n;
301         }
302 
303         if((n = *output++) == 0)
304         {
305             break;
306         }
307 
308         if(n > MAX_LABEL_LENGTH)
309         {
310             return LABEL_TOO_LONG;
311         }
312 
313         u8* tmp = output;
314 
315         output += n;
316 
317         if(output >= limit)
318         {
319             return DOMAIN_TOO_LONG;
320         }
321 
322         if(FAIL(n = input_stream_read_fully(stream, tmp, n)))
323         {
324             return n;
325         }
326 
327         /* 0x012a = 01 '*' = wildcard */
328 
329         /*if(GET_U16_AT(tmp[-1]) != NU16(0x012a))*/
330         {
331             if(!dnslabel_locase_verify_charspace(&tmp[-1]))
332             {
333                 return INVALID_CHARSET;
334             }
335         }
336     }
337 
338     return (ya_result)(output - output_buffer);
339 }
340 
341 ya_result
input_stream_read_rname(input_stream * stream,u8 * output_buffer)342 input_stream_read_rname(input_stream *stream, u8 *output_buffer)
343 {
344     u8 *output = output_buffer;
345     const u8 * const limit = &output_buffer[MAX_DOMAIN_LENGTH - 1];  /* -1 because the limit is computed after the terminator */
346 
347     for(;;)
348     {
349         int n;
350 
351         if(FAIL(n = input_stream_read_fully(stream, output, 1)))
352         {
353             return (output == output_buffer) ? 0 /* eof*/ : n;
354         }
355 
356         if((n = *output++) == 0)
357         {
358             break;
359         }
360 
361         if(n > MAX_LABEL_LENGTH)
362         {
363             return LABEL_TOO_LONG;
364         }
365 
366         u8* tmp = output;
367 
368         output += n;
369 
370         if(output >= limit)
371         {
372             return DOMAIN_TOO_LONG;
373         }
374 
375         if(FAIL(n = input_stream_read_fully(stream, tmp, n)))
376         {
377             return n;
378         }
379     }
380 
381     return (ya_result)(output - output_buffer);
382 }
383 
384 ya_result
input_stream_read_line(input_stream * stream,char * output_,int max_len)385 input_stream_read_line(input_stream *stream, char *output_, int max_len)
386 {
387     const char * const limit = &output_[max_len];
388     char *output = output_;
389 
390     /*
391      * Cache the method
392      */
393 
394     input_stream_read_method *read_method = stream->vtbl->read;
395 
396     while(output < limit)
397     {
398         ya_result n = read_method(stream, (u8*)output, 1);
399 
400         if(n <= 0)
401         {
402             if(n == 0)
403             {
404                 n = ((ya_result)(output - output_));
405             }
406 
407             return n;
408         }
409 
410         if(*output++ == '\n')
411         {
412             return ((ya_result)(output - output_));
413         }
414     }
415 
416     return max_len;
417 }
418 
input_stream_void_read(input_stream * stream,void * in_buffer,u32 in_len)419 static ya_result input_stream_void_read(input_stream *stream, void* in_buffer,u32 in_len)
420 {
421     (void)stream;
422     (void)in_buffer;
423     (void)in_len;
424 
425     log_err("tried to read a closed stream");
426     return INVALID_STATE_ERROR;
427 }
428 
input_stream_void_skip(input_stream * stream,u32 byte_count)429 static ya_result input_stream_void_skip(input_stream *stream, u32 byte_count)
430 {
431     (void)stream;
432     (void)byte_count;
433 
434     log_err("tried to skip a closed stream");
435     return INVALID_STATE_ERROR;
436 }
437 
input_stream_void_close(input_stream * stream)438 static void input_stream_void_close(input_stream *stream)
439 {
440     (void)stream;
441 
442     log_err("tried to close a closed stream");
443 #if DEBUG
444     logger_flush();
445     abort();
446 #endif
447 }
448 
449 static const input_stream_vtbl void_input_stream_vtbl ={
450     input_stream_void_read,
451     input_stream_void_skip,
452     input_stream_void_close,
453     "void_input_stream",
454 };
455 
456 /**
457  * This tools allows a safer misuse (and detection) of closed streams
458  * It sets the stream to a sink that warns abouts its usage and for which every call that can fail fails.
459  */
460 
input_stream_set_void(input_stream * is)461 void input_stream_set_void(input_stream* is)
462 {
463     yassert(is != NULL);
464     is->data = NULL;
465     is->vtbl = &void_input_stream_vtbl;
466 }
467 
input_stream_sink_read(input_stream * stream,void * in_buffer,u32 in_len)468 static ya_result input_stream_sink_read(input_stream *stream, void* in_buffer,u32 in_len)
469 {
470     (void)stream;
471     (void)in_buffer;
472     (void)in_len;
473     return -1;
474 }
475 
input_stream_sink_skip(input_stream * stream,u32 byte_count)476 static ya_result input_stream_sink_skip(input_stream *stream, u32 byte_count)
477 {
478     (void)stream;
479     return byte_count;
480 }
481 
input_stream_sink_close(input_stream * stream)482 static void input_stream_sink_close(input_stream *stream)
483 {
484     (void)stream;
485 }
486 
487 static const input_stream_vtbl sink_input_stream_vtbl ={
488     input_stream_sink_read,
489     input_stream_sink_skip,
490     input_stream_sink_close,
491     "sink_input_stream",
492 };
493 
494 /**
495  * Used to temporarily initialise a stream with a sink that can be closed safely.
496  * Typically used as pre-init so the stream can be closed even if the function
497  * setup failed before reaching stream initialisation.
498  *
499  * @param is
500  */
501 
input_stream_set_sink(input_stream * is)502 void input_stream_set_sink(input_stream* is)
503 {
504     yassert(is != NULL);
505     is->data = NULL;
506     is->vtbl = &sink_input_stream_vtbl;
507 }
508 
509 /** @} */
510