Coverage Report

Created: 2024-06-12 06:06

/src/opensips/parser/parse_body.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * Copyright (C) 2009 Voice Sistem SRL
3
 * Copyright (C) 2016 OpenSIPS Solutions
4
 *
5
 * This file is part of opensips, a free SIP server.
6
 *
7
 * opensips is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 2 of the License, or
10
 * (at your option) any later version
11
 *
12
 * opensips is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
20
 *
21
 */
22
23
#include "../mem/mem.h"
24
#include "../ut.h"
25
#include "parse_body.h"
26
#include "parse_content.h"
27
#include "parse_hname2.h"
28
#include "parser_f.h"
29
#include "sdp/sdp_helpr_funcs.h"
30
31
0
#define parse_hname(_b,_e,_h) parse_hname2((_b),(_e),(_h))
32
33
static struct body_part * new_part(void)
34
0
{
35
0
  struct body_part * temp;
36
37
0
  temp = pkg_malloc(sizeof (struct body_part));
38
39
0
  if (temp == 0)
40
0
  {
41
0
    LM_ERR("Unable to allocate memory\n");
42
0
    return 0;
43
0
  }
44
0
  memset(temp, 0, sizeof (struct body_part));
45
46
0
  return temp;
47
0
};
48
49
50
static char* get_hdr_field_unparsed(char* buf, char* end,struct hdr_field* hdr)
51
0
{
52
53
0
  char* tmp;
54
0
  char *match;
55
56
0
  if ((*buf) == '\n' || (*buf) == '\r')
57
0
  {
58
    /* double crlf or lflf or crcr */
59
0
    LM_DBG("found end of header\n");
60
0
    hdr->type = HDR_EOH_T;
61
0
    return buf;
62
0
  }
63
64
0
  LM_DBG("getting hdr from [%.*s...]\n",
65
0
    (int)((end-buf)<25?end-buf:25), buf);
66
67
0
  tmp = parse_hname(buf, end, hdr);
68
0
  if (hdr->type == HDR_ERROR_T)
69
0
  {
70
0
    LM_ERR("bad header\n");
71
0
    goto error_bad_hdr;
72
0
  }
73
74
  /* eliminate leading whitespace */
75
0
  tmp = eat_lws_end(tmp, end);
76
0
  if (tmp >= end)
77
0
  {
78
0
    LM_ERR("hf empty\n");
79
0
    goto error_bad_hdr;
80
0
  }
81
82
  /* just skip over it */
83
0
  hdr->body.s = tmp;
84
  /* find end of header */
85
  /* find lf */
86
0
  do
87
0
  {
88
0
    match = q_memchr(tmp, '\n', end - tmp);
89
0
    if (match)
90
0
    {
91
0
      match++;
92
0
    } else
93
0
    {
94
0
      LM_ERR("bad body for <%s>(%d)\n", hdr->name.s, hdr->type);
95
0
      tmp = end;
96
0
      goto error_bad_hdr;
97
0
    }
98
0
    tmp = match;
99
0
  } while (match < end && ((*match == ' ') || (*match == '\t')));
100
0
  tmp = match;
101
0
  hdr->body.len = match - hdr->body.s;
102
103
104
  /* jku: if \r covered by current length, shrink it */
105
0
  trim_r(hdr->body);
106
0
  hdr->len = tmp - hdr->name.s;
107
0
  return tmp;
108
109
0
error_bad_hdr:
110
0
  LM_ERR("Unable to parse headers\n");
111
112
0
  hdr->type = HDR_ERROR_T;
113
0
  hdr->len = tmp - hdr->name.s;
114
0
  return tmp;
115
0
}
116
117
118
static char *find_line_delimiter(char* p, char* plimit, str delimiter)
119
0
{
120
0
  static char delimiterhead[3] = "--";
121
0
  char *cp, *cp1;
122
123
  /* Iterate through body */
124
0
  cp = p;
125
0
  for (;;) {
126
0
    if (cp >= plimit)
127
0
      return NULL;
128
0
    for(;;) {
129
0
      cp1 = l_memmem(cp, delimiterhead, plimit-cp, 2);
130
0
      if (cp1 == NULL)
131
0
        return NULL;
132
      /* We matched '--',
133
       * now let's match the boundary delimiter */
134
0
      if (strncmp(cp1+2, delimiter.s, delimiter.len) == 0)
135
0
        break;
136
0
      else
137
0
        cp = cp1 + 2 + delimiter.len;
138
0
      if (cp >= plimit)
139
0
        return NULL;
140
0
    }
141
0
    if (cp1[-1] == '\n' || cp1[-1] == '\r')
142
0
      return cp1;
143
0
    if (plimit - cp1 < 2 + delimiter.len)
144
0
      return NULL;
145
0
    cp = cp1 + 2 + delimiter.len;
146
0
  }
147
0
}
148
149
150
static int parse_single_part(struct body_part *part, char * start, char * end)
151
0
{
152
0
  char * tmp, *body_end, * mime_end;
153
0
  unsigned int mime;
154
155
0
  part->mime = -1;
156
157
0
  if (*start=='\r') {
158
0
    start++;
159
0
    if (*start=='\n') start++;
160
0
  } else if (*start=='\n') {
161
0
    start++;
162
0
  } else {
163
0
    LM_ERR("invalid separator between boundry and body [%x/%x]\n",
164
0
      *start,*(start+1));
165
0
    return -1;
166
0
  }
167
168
0
  if (*(end-1)=='\n') {
169
0
    end--;
170
0
    if (*(end-1)=='\r') end--;
171
0
  } else if (*(end-1)=='\r') {
172
0
    end--;
173
0
  } else {
174
0
    LM_ERR("invalid separator between body and boundry [%x/%x]\n",
175
0
      *(end-2),*(end-1));
176
0
    return -1;
177
0
  }
178
179
0
  LM_DBG("parsing part [%.*s...]\n",
180
0
    (int)((end-start)<25?end-start:25), start);
181
182
0
  tmp = start;
183
0
  while (1)
184
0
  {
185
0
    struct hdr_field hd;
186
0
    memset(&hd, 0, sizeof (struct hdr_field));
187
188
0
    tmp = get_hdr_field_unparsed(tmp, end, &hd);
189
0
    if (tmp == NULL || hd.type == HDR_ERROR_T)
190
0
    {
191
0
      LM_ERR("Error parsing body part header\n");
192
0
      return -1;
193
0
    }
194
195
0
    if (hd.type == HDR_CONTENTTYPE_T)
196
0
    {
197
0
      body_end = hd.body.s + hd.body.len;
198
0
      mime_end = decode_mime_type(hd.body.s, body_end, &mime, NULL);
199
200
0
      if (mime_end == NULL)
201
0
      {
202
0
        LM_ERR("Error parsing MIME\n");
203
0
        return -1;
204
0
      }
205
0
      part->mime = mime;
206
0
      part->mime_s = hd.body;
207
0
    }
208
209
0
    if (hd.type == HDR_EOH_T)
210
0
    {
211
      /* remove the last \n\r from the body */
212
0
      tmp += 2;
213
0
      break;
214
0
    }
215
0
  }
216
217
0
  part->headers.s = start;
218
0
  part->headers.len = (tmp-2) - start;
219
220
0
  if (part->mime < 0)
221
0
    part->mime = ((TYPE_TEXT) << 16) + SUBTYPE_PLAIN;
222
223
0
  part->body.s = tmp;
224
0
  part->body.len = end - part->body.s;
225
226
0
  return 0;
227
0
};
228
229
230
int parse_sip_body(struct sip_msg * msg)
231
0
{
232
0
  char *start, *end;
233
0
  int type = 0;
234
0
  struct body_part *part, *last;
235
0
  str delimiter, body;
236
237
  /* is body already parsed ? */
238
0
  if (msg->body)
239
0
    return 0;
240
241
0
  if ( get_body(msg,&body)!=0 || body.len==0)
242
0
    return 0;
243
244
0
  type = parse_content_type_hdr(msg);
245
0
  if (type <= 0)
246
0
    return 0;
247
248
0
  msg->body = pkg_malloc(sizeof (struct sip_msg_body));
249
0
  if (msg->body == 0)
250
0
  {
251
0
    LM_ERR("Unable to allocate memory\n");
252
0
    return -1;
253
0
  }
254
0
  memset(msg->body, 0, sizeof (struct sip_msg_body));
255
256
0
  msg->body->body = body;
257
258
0
  msg->body->boundary = ((content_t *) msg->content_type->parsed)->boundary;
259
260
0
  if ((type >> 16) == TYPE_MULTIPART)
261
0
  {
262
0
    msg->body->flags |= SIP_BODY_RCV_MULTIPART;
263
0
    delimiter = ((content_t*) msg->content_type->parsed)->boundary;
264
265
0
    LM_DBG("Starting parsing with boundary = [%.*s]\n",
266
0
      delimiter.len, delimiter.s);
267
268
0
    start = find_line_delimiter( body.s, body.s + body.len, delimiter);
269
0
    if (start == NULL) {
270
0
      LM_ERR("Unable to parse multipart type:"
271
0
        " malformed - missing start delimiters\n");
272
0
      return 0;
273
0
    }
274
275
    /* mark as first part (no previous one) */
276
0
    last = NULL;
277
278
0
    while (1)
279
0
    {
280
0
      end = find_line_delimiter(start + 1, body.s + body.len,
281
0
        delimiter);
282
0
      if (end == NULL)
283
0
        break;
284
285
      /* is it the first part ? */
286
0
      if (last==NULL) {
287
0
        part = &msg->body->first;
288
0
      } else {
289
0
        if ( (part=new_part()) == NULL )
290
0
          return 0;
291
0
      }
292
293
      /* add 4 to delimiter 2 for "--"*/
294
0
      if (parse_single_part(part, start + delimiter.len + 2, end)!=0) {
295
0
        LM_ERR("Unable to parse part:[%.*s]\n",(int)(end-start),start);
296
0
        return -1;
297
0
      }
298
299
      /* set the parsing for the next cycle */
300
0
      start = end;
301
302
      /* link the new part; note that the first part is part of 
303
       * the body structure, no need to be linked */
304
0
      if (last)
305
0
        last->next = part;
306
0
      last = part;
307
0
      msg->body->part_count++;
308
309
0
    }
310
311
0
  } else {
312
313
    /* only one part in the body */
314
0
    part = &msg->body->first;
315
316
0
    part->mime = type;
317
0
    part->mime_s = msg->content_type->body;
318
0
    part->body = body;
319
0
    part->headers.s = NULL;
320
0
    part->headers.len = 0;
321
0
    msg->body->part_count++;
322
0
  }
323
324
0
  msg->body->updated_part_count = msg->body->part_count;
325
326
0
  return 0;
327
328
0
};
329
330
331
struct body_part* add_body_part(struct sip_msg *msg, str *mime_s,
332
                            str * hdrs, str *body)
333
0
{
334
0
  struct body_part *part, *last;
335
0
  char *m;
336
337
0
  if ( parse_sip_body(msg)<0) {
338
0
    LM_ERR("failed to parse existing SIP body\n");
339
0
    return NULL;
340
0
  }
341
342
0
  LM_DBG("adding mime <%.*s>, hdrs <%.*s>, body=<%.*s>\n",
343
0
    mime_s->len, mime_s->s, hdrs?hdrs->len:0 , hdrs?hdrs->s:NULL,
344
0
    body?body->len:0, body?body->s:NULL );
345
346
0
  if (msg->body==NULL) {
347
348
    /* the message has no body so far */
349
0
    msg->body = (struct sip_msg_body*)pkg_malloc(
350
0
      sizeof(struct sip_msg_body) + (body?body->len:0) +
351
0
      (hdrs?hdrs->len:0) + mime_s->len );
352
0
    if (!msg->body) {
353
0
      LM_ERR("No more pkg memory!\n");
354
0
      return NULL;
355
0
    }
356
0
    memset(msg->body, 0, sizeof(struct sip_msg_body));
357
358
0
    msg->body->part_count = 0;
359
0
    msg->body->updated_part_count = 1;
360
0
    msg->body->flags = SIP_BODY_FLAG_NEW;
361
0
    msg->body->boundary.s = NULL;
362
0
    msg->body->boundary.len = 0;
363
364
0
    part = &msg->body->first;
365
0
    m = (char*)(msg->body+1); /* pointer to mime */
366
367
0
  } else {
368
369
    /* allocate a new body part */
370
0
    part = (struct body_part*)pkg_malloc(
371
0
      sizeof(struct body_part) + (body?body->len:0) +
372
0
      (hdrs?hdrs->len:0) + mime_s->len );
373
0
    if (part==NULL) {
374
0
      LM_ERR("failed to allocated pkg mem\n");
375
0
      return NULL;
376
0
    }
377
378
0
    m = (char*)(part+1); /* pointer to mime */
379
380
    /* link new part at the end of the parts list */
381
0
    for (last=&msg->body->first; last->next ; last=last->next);
382
0
    last->next = part;
383
384
0
    msg->body->updated_part_count++;
385
0
  }
386
387
0
  memset( part, 0, sizeof(struct body_part) );
388
389
0
  part->flags = SIP_BODY_PART_FLAG_NEW;
390
391
  /* mime follows right after the part, in the same mem chunk */
392
0
  memcpy( m, mime_s->s, mime_s->len);
393
0
  part->mime_s.s = m;
394
0
  part->mime_s.len = mime_s->len;
395
396
0
  if (hdrs) {
397
    /* SIP hdrs follow right after mime, in the same mem chunk */
398
0
    part->headers.s = m + mime_s->len;
399
0
    memcpy( part->headers.s, hdrs->s, hdrs->len);
400
0
    part->headers.len = hdrs->len;
401
0
  }
402
403
0
  if (body) {
404
    /* body follows right after headers, in the same mem chunk */
405
0
    part->body.s = m + mime_s->len + (hdrs?hdrs->len:0);
406
0
    memcpy( part->body.s, body->s, body->len);
407
0
    part->body.len = body->len;
408
0
  }
409
410
0
  return part;
411
0
}
412
413
414
int delete_body_part(struct sip_msg *msg, struct body_part *part)
415
0
{
416
0
  if (msg->body==NULL) {
417
0
    LM_BUG("deleting a body part, but body not found/parsed :-/\n");
418
0
    return -1;
419
0
  }
420
421
  /* mark the part as deleted */
422
0
  part->flags |= SIP_BODY_PART_FLAG_DELETED;
423
424
0
  msg->body->updated_part_count--;
425
426
0
  return 0;
427
0
}
428
429
430
void free_sip_body(struct sip_msg_body *body)
431
0
{
432
0
  struct body_part * p, *tmp;
433
0
  osips_free_f my_free;
434
435
0
  if (body) {
436
0
    my_free = (body->flags&SIP_BODY_FLAG_SHM) ? shm_free_func : pkg_free_func;
437
    /* the first part does not need to be freed */
438
0
    p = &body->first;
439
0
    if (p->parsed && p->free_parsed_f)
440
0
      p->free_parsed_f( p->parsed, my_free );
441
    /* following parts need to be also freed */
442
0
    p = p->next;
443
0
    while(p) {
444
0
      tmp =  p;
445
0
      p = p->next;
446
      /* any need to free some parsed format of the part ? */
447
0
      if (tmp->parsed && tmp->free_parsed_f)
448
0
        tmp->free_parsed_f( tmp->parsed, my_free );
449
0
      func_free(my_free, tmp);
450
0
    }
451
0
    func_free(my_free, body);
452
0
  }
453
0
}
454
455
456
/* Clones the sip_msg_body structure attached to a sip msg into shm or pkg
457
 * memory.
458
 * Parameters:
459
 *    * src_msg - the original sip_msg containing the sip_msg_body to be cloned
460
 *                It can be in shm or pkg and it is mandatory.
461
 *    * dst_msg - the destination sip_msg - this is need only when cloning into
462
 *                shm, as we need to translate to this new sip msg all the 
463
 *                pointers (from our structure) into inside the buffer of the
464
 *                sip msg; must be provided if cloning to shm;
465
 *    * p_dst   - the holder where the clone will be returned if success.
466
 *    * shared  - 1 if to SHM or 0 if to PKG
467
 */
468
int clone_sip_msg_body(struct sip_msg *src_msg, struct sip_msg *dst_msg,
469
                  struct sip_msg_body **p_dst, int shared)
470
0
{
471
0
  struct sip_msg_body *dst, *src;
472
0
  struct body_part *p, *np;
473
0
  osips_malloc_f my_malloc;
474
0
  int extra_len;
475
476
0
  if (src_msg==NULL || src_msg->body==NULL) {
477
0
    *p_dst = NULL;
478
0
    return 0;
479
0
  }
480
481
0
  my_malloc = shared ? shm_malloc_func : pkg_malloc_func;
482
0
  src = src_msg->body;
483
484
  /* clone the SIP MSG BODY */
485
0
  extra_len = (src->flags&SIP_BODY_FLAG_NEW) ?
486
0
    src->first.mime_s.len+src->first.body.len : 0 ;
487
0
  if ( (dst=func_malloc(my_malloc, sizeof(struct sip_msg_body)+extra_len))==NULL ) {
488
0
    LM_ERR("failed to allocate new sip_msg_body clone (shared=%d)\n",
489
0
      shared);
490
0
    goto err;
491
0
  }
492
0
  memcpy( dst, src, sizeof(struct sip_msg_body)+extra_len);
493
0
  if (shared)
494
0
    dst->flags |= SIP_BODY_FLAG_SHM;
495
0
  else
496
0
    dst->flags &= ~SIP_BODY_FLAG_SHM;
497
  /* update the links inside it */
498
0
  if (dst_msg) { \
499
0
    dst->body.s = translate_pointer(dst_msg->buf ,src_msg->buf,
500
0
      src->body.s );
501
0
    dst->boundary.s = translate_pointer(dst_msg->buf ,src_msg->buf,
502
0
      src->boundary.s );
503
0
  }
504
  /* clone the body parts */
505
0
  for( p=&src->first,np=NULL ; p ; p=p->next) {
506
0
    if (np==NULL) { \
507
      /* first body part */
508
0
      np = &dst->first;
509
0
      extra_len = 0;
510
0
    } else {
511
0
      extra_len = (p->flags&SIP_BODY_PART_FLAG_NEW) ?
512
0
        p->mime_s.len+p->body.len+p->headers.len : 0 ;
513
0
      if((np->next=func_malloc(my_malloc, sizeof(struct body_part)+extra_len))==NULL){
514
0
        LM_ERR("failed to allocate new body_part clone (shared=%d)\n",
515
0
          shared);
516
0
        goto err;
517
0
      } \
518
0
      np = np->next;
519
0
    } \
520
0
    memcpy( np, p, sizeof(struct body_part)+extra_len);
521
    /* update the links inside it */
522
0
    if (p->flags&SIP_BODY_PART_FLAG_NEW) {
523
      /* links are pointing inside the body_part structure */
524
0
      if (p==&src->first) {
525
0
        np->body.s = translate_pointer((char*)dst ,(char*)src,
526
0
          p->body.s);
527
0
        np->mime_s.s = translate_pointer((char*)dst, (char*)src,
528
0
          p->mime_s.s);
529
0
        np->headers.s = translate_pointer((char*)dst, (char*)src,
530
0
          p->headers.s);
531
0
      } else {
532
0
        np->body.s = translate_pointer((char*)np ,(char*)p,
533
0
          p->body.s);
534
0
        np->mime_s.s = translate_pointer((char*)np, (char*)p,
535
0
          p->mime_s.s);
536
0
        np->headers.s = translate_pointer((char*)np, (char*)p,
537
0
          p->headers.s);
538
0
      }
539
0
    } else {
540
      /* links are pointing inside the sip msg body, so update only
541
       * a new sip msg was provided */ \
542
0
      if (dst_msg) { \
543
0
        np->body.s = translate_pointer( dst_msg->buf,
544
0
          src_msg->buf, p->body.s );
545
0
        np->mime_s.s = translate_pointer( dst_msg->buf,
546
0
          src_msg->buf, p->mime_s.s );
547
0
        np->headers.s = translate_pointer( dst_msg->buf,
548
0
            src_msg->buf, p->headers.s );
549
0
      }
550
0
    }
551
0
    if (p->parsed && p->clone_parsed_f)
552
0
      np->parsed = p->clone_parsed_f(p, np, src_msg, dst_msg, my_malloc);
553
0
    else
554
0
      np->parsed = NULL;
555
0
  }
556
557
0
  *p_dst = dst;
558
0
  return 0;
559
0
err:
560
0
  if (dst) free_sip_body(dst);
561
0
  return -1;
562
0
}
563
564
565
566
int should_update_sip_body(struct sip_msg *msg)
567
0
{
568
0
  struct body_part *part;
569
570
0
  if (!msg->body)
571
0
    return 0;
572
573
  /* body changed using lumps */
574
0
  if (msg->body_lumps)
575
0
    return 1;
576
577
0
  for(part = &msg->body->first; part; part = part->next) {
578
    /* body removed or added */
579
0
    if (part->flags & (SIP_BODY_PART_FLAG_NEW|SIP_BODY_PART_FLAG_DELETED))
580
0
      return 1;
581
582
    /* binary body */
583
0
    if (part->dump_f)
584
0
      return 1;
585
0
  }
586
  /* no changes on the body - should not be updated */
587
0
  return 0;
588
0
}
589
590
str *get_body_part(struct sip_msg *msg, unsigned int type, unsigned int subtype)
591
0
{
592
0
  struct body_part *p;
593
594
0
  if (parse_sip_body(msg)<0 || msg->body==NULL) {
595
0
    LM_DBG("cannot parse body\n");
596
0
    return NULL;
597
0
  }
598
0
  if (type == 0 && subtype == 0)
599
0
    return &msg->body->first.body; /* not interested in a particular type */
600
601
0
  for (p = &msg->body->first; p; p = p->next) {
602
0
    if (is_body_part_received(p) &&
603
0
        (p->mime & (type << 16) &&
604
0
        (subtype == 0 || p->mime == (type << 16) + subtype)))
605
0
      return &p->body;
606
0
  }
607
608
0
  return NULL;
609
0
}
610
611
int has_body_part(struct sip_msg *msg, unsigned int type, unsigned int subtype)
612
0
{
613
0
  return (get_body_part(msg, type, subtype) == NULL?0:1);
614
0
}