1 
2 /*-------------------------------------------------------------*/
3 /***************************************************************
4  * A netwib_buf is the standard memory storage used in netwib. *
5  *                                                             *
6  * A netwib_buf points to an array (static or malloced) which  *
7  * starts at 'first' and finishes at 'last'.                   *
8  * The memory contains user data between 'begin' and 'end'.    *
9  *    ---------------------------------------------------      *
10  *    |       |               data              |       |      *
11  *    |F|     |B|                               |E|     |L     *
12  *    ---------------------------------------------------      *
13  *   First   Begin                              End    Last    *
14  *     0       x                                 y   totalsize *
15  *                                                             *
16  * Data between 'first and begin', and data between 'end and   *
17  * last' may be corrupted when working on the buffer. To avoid *
18  * this, use netwib_buf_init_ext_buf and work on the new buffer*
19  ***************************************************************/
20 
21 /*-------------------------------------------------------------*/
22 typedef struct {
23   netwib_uint32 flags;       /* see below */
24   netwib_data totalptr;      /* ptr to first */
25   netwib_uint32 totalsize;   /* last - first */
26   netwib_uint32 beginoffset; /* begin - first */
27   netwib_uint32 endoffset;   /* end - first */
28 } netwib_buf;
29 typedef const netwib_buf netwib_constbuf;
30 
31 /*-------------------------------------------------------------*/
32 /***************************************************************
33  * Field "flags" is a bit field indicating some information    *
34  * about a netwib_buf.                                         *
35  ***************************************************************/
36 
37 /* If totalptr points :
38      0x0001 : to an allocated memory
39     ~0x0001 : to an external array (stack array or array which
40               does not need to be freed)
41    Those two modes corresponds to the two ways to initialize a
42    netwib_buf :
43      - netwib_buf_init_malloc : it internally allocates memory
44        and eventually reallocate it if more is needed. At the
45        end, function netwib_buf_close must be called to free
46        memory.
47      - netwib_buf_init_ext_xyz : buffer does not contain memory,
48        but points on an external array. At the end, function
49        netwib_buf_close does not need to be called to free
50        memory (no closing function is needed).
51    This flag should not be directly modified by user.
52  */
53 #define NETWIB_BUF_FLAGS_ALLOC 0x00000001u
54 
55 /* In the following case :
56      - flag NETWIB_BUF_FLAGS_ALLOC is unset, and
57      - there is no sufficient space in the array
58    we can :
59      0x0002 : allocate memory and store array content in it
60               (the array is no more used)
61     ~0x0002 : return a space limitation error
62    This flag is very useful to optimize code. When we know in
63    most cases our code will need 80 bytes, we use an array
64    of 80 bytes. In the rare cases where it is not sufficient,
65    an allocated pointer is created. Like this for most
66    frequently encountered cases, there is no need to allocate.
67    Once allocated, it works like if it was allocated from beginning.
68    Once allocated, the external array is no more used.
69    Once allocated, flag NETWIB_BUF_FLAGS_ALLOC is automatically
70    set.
71    If array size is greater than 2k, it's not really advantageous
72    to use this flag, because copying 2k needs almost the same time
73    as a malloc and free.
74    This is generally used with netwib_buf_init_ext_arrayempty.
75    This flag defaults to false. It has to be explicitly set
76    by user.
77  */
78 #define NETWIB_BUF_FLAGS_CANALLOC 0x00000002u
79 
80 /* If functions are :
81      0x0004 : allowed to slide data (shrunk space between First
82               and Begin), when there is no sufficient space
83               between End and Last for appending
84     ~0x0004 : not allowed to slide
85    This flag defaults to false. It has to be explicitly set
86    by user.
87 */
88 #define NETWIB_BUF_FLAGS_CANSLIDE 0x00000004u
89 
90 /* Sometimes, a buffer contains sensitive data such as a password,
91    so we want to do a memset on this data when it is no more needed.
92    This flags says that buffer contains sensitive data. Buffer will
93    be wiped with memset(.0.) during:
94      netwib_buf_close(),
95      netwib__buf_reinit(),
96      netwib__buf_erase(),
97      netwib_bufpool_buf_close(),
98      netwib_bufpool_close(),
99      and all functions using above ones.
100    It is developer's task to set this flag each time a buffer may
101    contain sensitive data.
102    Netwib supports a feature to transfer this flag (also known as
103    tainting in other languages). For example, when a sensitive
104    buffer is copied to another buffer, this one also becomes
105    sensitive.
106    Once buffer is closed, the flag is unset, so user has to set
107    it each time sensitive data is initialized. The closing
108    functions are:
109      netwib_buf_close(),
110      netwib_bufpool_buf_close(),
111      netwib_bufpool_close().
112    WARNING:
113    This feature was conceived for PASSWORDS or cryptographic KEYS
114    stored in a netwib_buf. It cannot help for other types such
115    as a netwib_string, a netwib_ring or a netwib_ip.
116    This feature was conceived for buffer manipulation functions,
117    such as netwib_buf_append_buf, and not in functions unrelated
118    to passwords or keys, such as netwib_pkt_... or
119    netwib_sniff_... When a function supports this feature, it is
120    indicated in its help comment before the prototype (.h file).
121    Perhaps one day, I will expand this feature to erase other kind
122    of data, but this is not the case currently.
123    To sum up, don't expect this feature to be the Solution for
124    your sensitive data management, but only a small step towards it.
125    END OF WARNING.
126    This flag defaults to false. It has to be explicitly set
127    by user.
128 */
129 #define NETWIB_BUF_FLAGS_SENSITIVE 0x00000008u
130 /* data is sensitive, but readonly (such as a password stored
131    in a static string which cannot be wiped, but can be
132    transfered when buffer is copied)
133 */
134 #define NETWIB_BUF_FLAGS_SENSITIVE_READONLY 0x00000010u
135 /* to transfer the sensitive flag to the second buffer */
136 #define netwib__buf_transfersensitive(pbuf1,pbuf2) { if ((pbuf1) != NULL && (pbuf2) != NULL) { if ((pbuf1)->flags & NETWIB_BUF_FLAGS_SENSITIVE) { (pbuf2)->flags |= NETWIB_BUF_FLAGS_SENSITIVE; } } }
137 /* to wipe a local array used in parallel of a buffer */
138 #define netwib__localarray_wipe(arr) netwib_c_memset((arr),0,sizeof(arr))
139 #define netwib__localarray_ifbuf_wipe(pbuf,arr) { if ((pbuf) != NULL && ((pbuf)->flags & NETWIB_BUF_FLAGS_SENSITIVE)) netwib__localarray_wipe(arr); }
140 
141 /* number of used bits */
142 #define NETWIB_BUF_FLAGS_USEDBITS 5
143 
144 /*-------------------------------------------------------------*/
145 /***************************************************************
146  * Type netwib_bufext is exactly the same as netwib_buf. It    *
147  * permits to easily determine which kind of buffer is needed  *
148  * by a function :                                             *
149  *  - Functions having an output parameter of type netwib_buf  *
150  *    must be called with the buffer previously initialized :  *
151  *    they will append data to it                              *
152  *  - Functions having an output parameter of type             *
153  *    netwib_bufext will initialize it.                        *
154  * Example :                                                   *
155  *  An IP4 packet might contain an IP4 option. There is no     *
156  *  need to allocate/copy data for this option, because it is  *
157  *  simply contained in the input packet (at offset            *
158  *  20==sizeof(ip4hdr)). So in this case a netwib_bufext is    *
159  *  used.                                                      *
160  ***************************************************************/
161 typedef netwib_buf netwib_bufext;
162 
163 /*-------------------------------------------------------------*/
164 /* Name : netwib_buf_init_malloc
165    Description :
166      Initialize a buf. Its memory dynamically grows.
167    Input parameter(s) :
168      allocsize : allocated size. If 0, a
169                  default value is used.
170    Input/output parameter(s) :
171    Output parameter(s) :
172      *pbuf : netwib_buf initialized
173    Normal return values :
174      NETWIB_ERR_OK : ok
175 */
176 netwib_err netwib_buf_init_malloc(netwib_uint32 allocs,
177                                   netwib_buf *pbuf);
178 #define netwib_buf_init_mallocdefault(pbuf) netwib_buf_init_malloc(1024,pbuf)
179 
180 /*-------------------------------------------------------------*/
181 /* Name : netwib_buf_init_ext_array
182    Description :
183      Initialize a buf. Its memory corresponds to an external
184      fixed size array.
185    Input parameter(s) :
186      array : external array
187      arraysize : external array size
188      beginoffset : offset of begin in this array
189      endoffset : offset of end in this array
190    Input/output parameter(s) :
191    Output parameter(s) :
192      *pbuf : netwib_bufext initialized
193    Normal return values :
194      NETWIB_ERR_OK : ok
195 */
196 netwib_err netwib_buf_init_ext_array(netwib_constptr array,
197                                      netwib_uint32 arraysize,
198                                      netwib_uint32 beginoffset,
199                                      netwib_uint32 endoffset,
200                                      netwib_bufext *pbuf);
201 #define netwib_buf_init_ext_arrayempty(array,arraysize,pbuf) netwib_buf_init_ext_array(array,arraysize,0,0,pbuf)
202 #define netwib_buf_init_ext_arrayfilled(array,arraysize,pbuf) netwib_buf_init_ext_array(array,arraysize,0,arraysize,pbuf)
203 #define netwib_buf_init_ext_arraysizeofempty(array,pbuf) netwib_buf_init_ext_arrayempty(array,sizeof(array),pbuf)
204 #define netwib_buf_init_ext_arraysizeoffilled(array,pbuf) netwib_buf_init_ext_arrayfilled(array,sizeof(array),pbuf)
205 /* A buffer containing no data */
206 #define netwib_buf_init_ext_empty(pbuf) netwib_buf_init_ext_array(NULL,0,0,0,pbuf)
207 
208 /*-------------------------------------------------------------*/
209 /* Name : netwib_buf_init_ext_storagearray
210    Description :
211      Initialize a buf. Its memory corresponds to an external
212      fixed size array or to nothing. When data is added, it may
213      be allocated. A call to netwib_buf_close() will have to be done.
214    Input parameter(s) :
215      array : external array
216      arraysize : external array size
217      beginoffset : offset of begin in this array
218      endoffset : offset of end in this array
219    Input/output parameter(s) :
220    Output parameter(s) :
221      *pbuf : netwib_bufext initialized
222    Normal return values :
223      NETWIB_ERR_OK : ok
224 */
225 netwib_err netwib_buf_init_ext_storagearray(netwib_constptr array,
226                                             netwib_uint32 arraysize,
227                                             netwib_bufext *pbuf);
228 /* An empty buffer, allocated on first append */
229 #define netwib_buf_init_ext_storage(pbuf) netwib_buf_init_ext_storagearray(NULL,0,pbuf)
230 /* An empty array, allocated if not sufficiently big */
231 #define netwib_buf_init_ext_storagearraysizeof(array,pbuf) netwib_buf_init_ext_storagearray(array,sizeof(array),pbuf)
232 
233 /*-------------------------------------------------------------*/
234 /* Name : netwib_buf_init_ext_buf
235    Description :
236      Initialize a buf. Its memory corresponds to an external
237      buffer.
238    Input parameter(s) :
239      *pbuf : netwib_buf containing data
240    Input/output parameter(s) :
241    Output parameter(s) :
242      *pbuf : netwib_bufext initialized
243    Normal return values :
244      NETWIB_ERR_OK : ok
245    This function supports NETWIB_BUF_FLAGS_SENSITIVE.
246 */
247 netwib_err netwib_buf_init_ext_buf(netwib_constbuf *pbufin,
248                                    netwib_bufext *pbuf);
249 
250 /*-------------------------------------------------------------*/
251 /* Name : netwib_buf_init_ext_string
252    Description :
253      Initialize a buf. Its memory corresponds to an external
254      preset string.
255    Input parameter(s) :
256      str : external string
257    Input/output parameter(s) :
258    Output parameter(s) :
259      *pbuf : netwib_bufext initialized
260    Normal return values :
261      NETWIB_ERR_OK : ok
262 */
263 netwib_err netwib_buf_init_ext_string(netwib_conststring str,
264                                       netwib_bufext *pbuf);
265 
266 /*-------------------------------------------------------------*/
267 /* Name : netwib_buf_append_xyz
268    Description :
269      Add data to a buf.
270    Input parameter(s) :
271      data : data to add
272      datasize : size of data to add
273      str : string to add
274      c : character to add
275    Input/output parameter(s) :
276      *pbuf : netwib_buf updated
277    Output parameter(s) :
278    Normal return values :
279      NETWIB_ERR_OK : ok
280    The netwib_buf_append_buf function supports NETWIB_BUF_FLAGS_SENSITIVE.
281 */
282 netwib_err netwib_buf_append_data(netwib_constdata data,
283                                   netwib_uint32 datasize,
284                                   netwib_buf *pbuf);
285 netwib_err netwib_buf_append_string(netwib_conststring str,
286                                     netwib_buf *pbuf);
287 netwib_err netwib_buf_append_buf(netwib_constbuf *pbuftoappend,
288                                  netwib_buf *pbuf);
289 netwib_err netwib_buf_append_byte(netwib_byte b,
290                                   netwib_buf *pbuf);
291 
292 /*-------------------------------------------------------------*/
293 /* Name : netwib_buf_prepend_buf
294    Description :
295      Prepend data to a buf.
296    Input parameter(s) :
297    Input/output parameter(s) :
298      *pbuf : netwib_buf updated
299    Output parameter(s) :
300    Normal return values :
301      NETWIB_ERR_OK : ok
302    Note :
303      Parameter canslide has no effect on this function (this is
304      logical).
305    This function supports NETWIB_BUF_FLAGS_SENSITIVE.
306 */
307 netwib_err netwib_buf_prepend_buf(netwib_constbuf *pbuftoprepend,
308                                   netwib_buf *pbuf);
309 
310 /*-------------------------------------------------------------*/
311 /* Name : netwib_buf_ref_string
312    Description :
313      Get pointers to data stored in buf (between begin and end).
314      If buffer internal storage does not end with '\0',
315      a new one is added. So, we can have NETWIB_ERR_DATANOSPACE
316      if there is no room for the '\0'.
317    Input parameter(s) :
318      *pbuf : buffer
319    Input/output parameter(s) :
320    Output parameter(s) :
321      *pstr : pointer to start of string
322    Normal return values :
323      NETWIB_ERR_OK : ok
324      NETWIB_ERR_DATANOSPACE : no room for the '\0'
325 */
326 netwib_err netwib_buf_ref_string(netwib_buf *pbuf,
327                                  netwib_string *pstr);
328 
329 /*-------------------------------------------------------------*/
330 /* Name : netwib_constbuf_ref_string
331    Description :
332      Some as netwib_buf_ref_string except it does not modify
333      the buffer to add the '\0'.
334    Input parameter(s) :
335      *pbuf : buffer
336    Input/output parameter(s) :
337    Output parameter(s) :
338      *pstr : pointer to start of string
339    Normal return values :
340      NETWIB_ERR_OK : ok
341      NETWIB_ERR_DATANOSPACE : the char after endoffset is not a '\0'
342 */
343 netwib_err netwib_constbuf_ref_string(netwib_constbuf *pbuf,
344                                       netwib_string *pstr);
345 /* to use at begin of a function to manage a local buffer */
346 #define netwib__constbuf_ref_string(pbuf, str, bufstorage, func) { netwib_err bufstorageret; bufstorageret = netwib_constbuf_ref_string(pbuf, &str); if (bufstorageret != NETWIB_ERR_OK) { if (bufstorageret == NETWIB_ERR_DATANOSPACE) { netwib_data bufstoragearray[512]; netwib_buf bufstorage; netwib_er(netwib_buf_init_ext_storagearraysizeof(bufstoragearray, &bufstorage)); netwib_er(netwib_buf_append_buf(pbuf, &bufstorage)); netwib_er(netwib_buf_append_byte(0, &bufstorage)); bufstorage.endoffset--; bufstorageret = func; netwib_er(netwib_buf_close(&bufstorage)); } return(bufstorageret); } }
347 
348 /*-------------------------------------------------------------*/
349 /* Name : netwib_buf_wantspace
350    Description :
351      Request space in a buffer (from end to last).
352      When buffer is initialized as malloced memory, it is
353      possible to obtain unlimited space. Otherwise, we cannot
354      obtain more space than array size (unless flag
355      NETWIB_BUF_FLAGS_CANALLOC is set).
356    Input parameter(s) :
357      wantedspace : wanted space
358    Input/output parameter(s) :
359      *pbuf : buffer
360    Output parameter(s) :
361      *pdata : pointer to end (endoffset)
362    Normal return values :
363      NETWIB_ERR_OK : ok
364      NETWIB_ERR_DATANOSPACE : there is less than wantedspace
365 */
366 netwib_err netwib_buf_wantspace(netwib_buf *pbuf,
367                                 netwib_uint32 wantedspace,
368                                 netwib_data *pdata);
369 
370 /*-------------------------------------------------------------*/
371 /* Name : netwib_buf_wishspace
372    Description :
373      Request space in a buffer (from end to last).
374      When buffer is initialized as malloced memory, it is
375      possible to obtain unlimited space. Otherwise, we cannot
376      obtain more space than array size (unless flag
377      NETWIB_BUF_FLAGS_CANALLOC is set).
378    Input parameter(s) :
379      wantedspace : wanted space
380    Input/output parameter(s) :
381      *pbuf : buffer
382    Output parameter(s) :
383      *pdata : pointer to end (endoffset)
384      *pobtainedspace : obtained space (from end to last)
385    Normal return values :
386      NETWIB_ERR_OK : ok
387 */
388 netwib_err netwib_buf_wishspace(netwib_buf *pbuf,
389                                 netwib_uint32 wantedspace,
390                                 netwib_data *pdata,
391                                 netwib_uint32 *pobtainedspace);
392 
393 /*-------------------------------------------------------------*/
394 /* Name : netwib_buf_cmp
395    Description :
396      Compare two netwib_buf.
397    Input parameter(s) :
398      *pbuf1 : netwib_buf to compare with buf2
399      *pbuf2 : netwib_buf to compare with buf1
400    Input/output parameter(s) :
401    Output parameter(s) :
402      *pcmp :
403        NETWIB_CMP_LT : buf1<buf2
404        NETWIB_CMP_EQ : if buf1 and buf2 are equal
405        NETWIB_CMP_GT : buf1>buf2
406    Normal return values :
407      NETWIB_ERR_OK : ok
408 */
409 netwib_err netwib_buf_cmp(netwib_constbuf *pbuf1,
410                           netwib_constbuf *pbuf2,
411                           netwib_cmp *pcmp);
412 /* ignore case */
413 netwib_err netwib_buf_casecmp(netwib_constbuf *pbuf1,
414                               netwib_constbuf *pbuf2,
415                               netwib_cmp *pcmp);
416 /* compare to a string */
417 netwib_err netwib_buf_cmp_string(netwib_constbuf *pbuf1,
418                                  netwib_conststring string2,
419                                  netwib_cmp *pcmp);
420 netwib_err netwib_buf_casecmp_string(netwib_constbuf *pbuf1,
421                                      netwib_conststring string2,
422                                      netwib_cmp *pcmp);
423 
424 /*-------------------------------------------------------------*/
425 /* Name : netwib_buf_shift
426    Description :
427      Shift data in a buf.
428    Input parameter(s) :
429      offset : offset
430      truncbegend : truncate on begin/end edges (otherwise,
431                    truncate only on first/last edges)
432    Input/output parameter(s) :
433      *pbuf : netwib_buf updated
434    Output parameter(s) :
435    Normal return values :
436      NETWIB_ERR_OK : ok
437    Examples :
438      buf contains         "   data  "
439      shift(buf,-1,0) =>   "  data   "
440      shift(buf,-1,1) =>   "   ata   " (d is truncated)
441      shift(buf,+1,0) =>   "    data "
442      shift(buf,+4,0) =>   "       data" (if buffer is malloced)
443      shift(buf,+4,0) =>   "       da" (if buffer is external)
444      shift(buf,+1,1) =>   "    dat  " (a is truncated)
445    Note :
446      Flag NETWIB_BUF_FLAGS_CANSLIDE has no effect on this
447      function (this is logical).
448 */
449 netwib_err netwib_buf_shift(netwib_buf *pbuf,
450                             netwib_int32 offset,
451                             netwib_bool truncbegend);
452 
453 /*-------------------------------------------------------------*/
454 /* Name : netwib_buf_close
455    Description :
456      Close buf, eventually freeing data it contains.
457    Input parameter(s) :
458    Input/output parameter(s) :
459      *pbuf : buffer closed
460    Output parameter(s) :
461    Normal return values :
462      NETWIB_ERR_OK : ok
463    Note :
464      This function is only needed for a buffer initialized
465      with netwib_buf_init_malloc, or if flag
466      NETWIB_BUF_FLAGS_CANALLOC is set.
467 */
468 netwib_err netwib_buf_close(netwib_buf *pbuf);
469 
470 /*-------------------------------------------------------------*/
471 /* Frequently needed defines */
472 #define netwib__buf_reinit(pbuf) { (pbuf)->beginoffset = 0; (pbuf)->endoffset = 0; if (((pbuf)->flags & NETWIB_BUF_FLAGS_SENSITIVE) && !((pbuf)->flags & NETWIB_BUF_FLAGS_SENSITIVE_READONLY)) { netwib_c_memset((pbuf)->totalptr, 0, (pbuf)->totalsize); } }
473 #define netwib__buf_erase(pbuf) { if (((pbuf)->flags & NETWIB_BUF_FLAGS_SENSITIVE) && !((pbuf)->flags & NETWIB_BUF_FLAGS_SENSITIVE_READONLY)) { netwib_c_memset((pbuf)->totalptr+(pbuf)->beginoffset, 0, (pbuf)->endoffset-(pbuf)->beginoffset); } (pbuf)->endoffset = (pbuf)->beginoffset; }
474 #define netwib__buf_ref_data_ptr(pbuf) ((pbuf)->totalptr + (pbuf)->beginoffset)
475 #define netwib__buf_ref_data_size(pbuf) ((pbuf)->endoffset -(pbuf)->beginoffset)
476 #define netwib__buf_ref_data_sizenull(pbuf) ((pbuf)!=NULL?netwib__buf_ref_data_size(pbuf):0)
477 
478