Coverage Report

Created: 2024-02-25 06:34

/src/kamailio/src/core/parser/parse_privacy.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2006 Juha Heinanen
3
 *
4
 * This file is part of Kamailio, a free SIP server.
5
 *
6
 * Kamailio is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version
10
 *
11
 * Kamailio is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19
 *
20
 */
21
22
/*!
23
 * \file
24
 * \brief Privacy value parser
25
 * \ingroup parser
26
 * Copyright (c) 2006 Juha Heinanen
27
 */
28
29
#include <stdlib.h>
30
#include <string.h>
31
#include "../dprint.h"
32
#include "../trim.h"
33
#include "parse_privacy.h"
34
#include "msg_parser.h"
35
36
37
/*!
38
 * Parse a privacy value pointed by start that can be at most max_len long.
39
 * \return length of matched privacy value on success or NULL otherwise
40
 */
41
unsigned int parse_priv_value(
42
    char *start, unsigned int max_len, unsigned int *value)
43
3.45k
{
44
3.45k
  unsigned int len;
45
46
3.45k
  if(!start || !value) {
47
0
    LM_ERR("invalid parameter value\n");
48
0
    return 0;
49
0
  }
50
51
3.45k
  switch(start[0]) {
52
53
288
    case 'c':
54
334
    case 'C':
55
334
      if(max_len < 8)
56
14
        return 0;
57
320
      if(strncasecmp(start, "critical", 8) == 0) {
58
244
        *value = PRIVACY_CRITICAL;
59
244
        len = 8;
60
244
        break;
61
244
      } else {
62
76
        return 0;
63
76
      }
64
65
222
    case 'h':
66
608
    case 'H':
67
608
      if(max_len < 6)
68
10
        return 0;
69
598
      if(strncasecmp(start, "header", 6) == 0) {
70
374
        *value = PRIVACY_HEADER;
71
374
        len = 6;
72
374
        break;
73
374
      }
74
224
      if(max_len < 7)
75
37
        return 0;
76
187
      if(strncasecmp(start, "history", 7) == 0) {
77
99
        *value = PRIVACY_HISTORY;
78
99
        len = 7;
79
99
        break;
80
99
      } else {
81
88
        return 0;
82
88
      }
83
84
759
    case 'i':
85
1.15k
    case 'I':
86
1.15k
      if(max_len < 2)
87
10
        return 0;
88
1.14k
      if(start[1] == 'd' || start[1] == 'D') {
89
1.12k
        *value = PRIVACY_ID;
90
1.12k
        len = 2;
91
1.12k
        break;
92
1.12k
      } else {
93
18
        return 0;
94
18
      }
95
96
126
    case 'n':
97
386
    case 'N':
98
386
      if(max_len < 4)
99
14
        return 0;
100
372
      if(strncasecmp(start, "none", 4) == 0) {
101
328
        *value = PRIVACY_NONE;
102
328
        len = 4;
103
328
        break;
104
328
      } else {
105
44
        return 0;
106
44
      }
107
108
568
    case 's':
109
603
    case 'S':
110
603
      if(max_len < 7)
111
13
        return 0;
112
590
      if(strncasecmp(start, "session", 7) == 0) {
113
526
        *value = PRIVACY_SESSION;
114
526
        len = 7;
115
526
        break;
116
526
      } else {
117
64
        return 0;
118
64
      }
119
120
73
    case 'u':
121
316
    case 'U':
122
316
      if(max_len < 4)
123
10
        return 0;
124
306
      if(strncasecmp(start, "user", 4) == 0) {
125
265
        *value = PRIVACY_USER;
126
265
        len = 4;
127
265
        break;
128
265
      } else {
129
41
        return 0;
130
41
      }
131
132
53
    default:
133
53
      return 0;
134
3.45k
  }
135
136
2.95k
  if(len < max_len) {
137
2.92k
    if(start[len] != '\0' && start[len] != ';' && start[len] != ' '
138
2.92k
        && start[len] != '\t' && start[len] != '\r'
139
2.92k
        && start[len] != '\n')
140
28
      return 0;
141
2.92k
  }
142
143
2.93k
  return len;
144
2.95k
}
145
146
147
/*!
148
 * This method is used to parse Privacy HF body, which consist of
149
 * comma separated list of priv-values.  After parsing, msg->privacy->parsed
150
 * contains enum bits of privacy values defined in parse_privacy.h.
151
 * \return 0 on success and -1 on failure.
152
 */
153
int parse_privacy(struct sip_msg *msg)
154
14.2k
{
155
14.2k
  unsigned int val_len, value, values, len;
156
14.2k
  str next;
157
14.2k
  char *p, *beyond;
158
159
  /* maybe the header is already parsed! */
160
14.2k
  if(msg->privacy && msg->privacy->parsed)
161
0
    return 0;
162
163
  /* parse Privacy HF (there should be only one) */
164
14.2k
  if(!msg->privacy
165
14.2k
      && (parse_headers(msg, HDR_PRIVACY_F, 0) == -1 || !msg->privacy)) {
166
13.2k
    return -1;
167
13.2k
  }
168
169
993
  next.len = msg->privacy->body.len;
170
993
  next.s = msg->privacy->body.s;
171
172
993
  trim_leading(&next);
173
174
993
  if(next.len == 0) {
175
333
    LM_ERR("no values\n");
176
333
    return -1;
177
333
  }
178
179
660
  values = 0;
180
660
  p = next.s;
181
660
  beyond = next.s + next.len;
182
183
3.45k
  while(p < beyond) {
184
3.45k
    len = beyond - p;
185
3.45k
    if((val_len = parse_priv_value(p, len, &value)) != 0) {
186
2.93k
      values |= value;
187
2.93k
      p = p + val_len;
188
2.93k
    } else {
189
520
      LM_ERR("invalid privacy value\n");
190
520
      return -1;
191
520
    }
192
193
4.85k
    while(p < beyond
194
4.85k
        && (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n'))
195
1.92k
      p++;
196
197
2.93k
    if(p >= beyond)
198
70
      break;
199
200
2.86k
    if(*p == ';') {
201
2.82k
      p++;
202
3.85k
      while(p < beyond
203
3.85k
          && (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n'))
204
1.03k
        p++;
205
2.82k
      if(p >= beyond) {
206
30
        LM_ERR("no privacy value after comma\n");
207
30
        return -1;
208
30
      }
209
2.82k
    } else {
210
40
      LM_ERR("semicolon expected\n");
211
40
      return -1;
212
40
    }
213
2.86k
  }
214
215
70
  if((values & PRIVACY_NONE) && (values ^ PRIVACY_NONE)) {
216
1
    LM_ERR("no other privacy values allowed with 'none'\n");
217
1
    return -1;
218
1
  }
219
220
69
  msg->privacy->parsed = (void *)(long)values;
221
222
69
  return 0;
223
70
}